Как записать в конкретное смещение, используя дескриптор файла - PullRequest
0 голосов
/ 11 марта 2019

Я внедряю DLL в процесс, получаю дескриптор файла.

Затем я пытаюсь писать, используя функцию WriteFile Winapi. Это прекрасно работает, но если я хочу записать в конкретное смещение (добавив аргумент смещения вместо NULL),

_OVERLAPPED offset;
offset.Offset = 0xFFFFFFFF;
offset.OffsetHigh = 0xFFFFFFFF;
if (!WriteFile(hFile, &buffer, 9, &written,&offset)) {
    Debug(GetLastErrorStdStr());
}

тогда я получаю:

ERROR_ALREADY_EXISTS 183 Невозможно создать файл, если этот файл уже существует.

Что заставляет меня думать, что я не могу, потому что РУЧКА была создана БЕЗ FILE_FLAG_OVERLAPPED. Может ли это быть из-за чего-то другого?

Если это действительно является причиной ошибки, есть ли хакерский обходной путь?

1 Ответ

2 голосов
/ 11 марта 2019

для записи в определенное смещение через 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() для лучшей диагностики в этом случае

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...