для записи в определенное смещение через WriteFile
нам нужно установить это смещение внутри OVERLAPPED
:
Это смещение задается настройкой Offset и OffsetHigh члены структуры OVERLAPPED
.
это очень распространенная ошибка, если предположить, что мы можем использовать OVERLAPPED
только с асинхронным дескриптором файла (если hFile
открывается с FILE_FLAG_OVERLAPPED
).но это не правда.мы можем всегда использовать указатель на OVERLAPPED
в WriteFile
в качестве параметра.отличается только в следующем - в случае дескриптора асинхронного файла это обязательный параметр, в противном случае необязательный
OVERLAPPED
структура обязательнаесли параметр hFile был открыт с помощью FILE_FLAG_OVERLAPPED
, в противном случае этот параметр может быть NULL
.
может быть, ноне должно быть.
другой способ задать положение файла - используйте SetFilePointer[Ex]
- устарел, неэффективен и указатель для поднятия условно - все, что делает этот API - установить CurrentByteOffset
внутри FILE_OBJECT
структура.затем в WriteFile
, если мы не предоставляем явное смещение через OVERLAPPED
- используется неявное смещение FILE_OBJECT.CurrentByteOffset
.сделать это (несколько дополнительных обращений к ядру, которые на самом деле не нужны) - очень неэффективно сравнивать явное смещение файла на OVERLAPPED
(а когда кто-то еще использует файл одновременно - это смещение может быть изменено между SetFilePointer[Ex]
и WriteFile
или ReadFile
звонки) также Старый API DOS SetFilePointer является анахронизмом.Следует указать смещение файла в перекрывающейся структуре даже для синхронного ввода-вывода.
, но когда мы используем структуру OVERLAPPED
- мы должны инициализировать его hEvent
для элемента 0 или для допустимого дескриптора события с SYNCHRONIZE|EVENT_MODIFY_STATE
правами доступа (и это событие должно быть уникальным на запрос ввода-вывода - не используется одновременно в другом запросе ввода-выводаДо тех пор, пока это не закончено).
поэтому ваш текущий код, когда вы не инициализируете hEvent
внутри _OVERLAPPED offset;
, фактически равен UB .Некоторое время это может работать нормально, если hEvent
будет случайным 0. В противном случае вы можете получить следующие ошибки статуса: STATUS_INVALID_HANDLE
(случайное значение внутри hEvent
вообще не является допустимым дескриптором), STATUS_OBJECT_TYPE_MISMATCH
(дескриптор допустим, ноне событие), STATUS_ACCESS_DENIED
(дескриптор не имеет EVENT_MODIFY_STATE
)
, но я уверен, что WriteFile
не вернет вам ошибку ERROR_ALREADY_EXISTS
.только STATUS_OBJECT_NAME_COLLISION
преобразуется в эту ошибку, и я не вижу места, где NtWriteFile
может вернуть такой статус.Я абсолютно уверен, что вы получили не эту ошибку, а другую.и всегда хороший вызов RtlGetLastNtStatus();
вместо (или с) GetLastError()
для лучшей диагностики в этом случае