How to write to a specific offset, using a file handle

0

I'm injecting a DLL into a process, retrieve a file handle.

Then I try to write using the WriteFile Winapi function. This works great, but if I want to write to a specific offset (adding the offset arg, instead of NULL),

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

then I get:

ERROR_ALREADY_EXISTS 183 Cannot create a file when that file already exists.

Which makes me think I can't because the HANDLE has been created WITHOUT the FILE_FLAG_OVERLAPPED. Could this be coming from something else ?

If this is indeed the cause of the error, is there a hacky workaround ?

c++
winapi
asked on Stack Overflow Mar 11, 2019 by Bonjour123

1 Answer

2

for write to a specific offset via WriteFile we need set this offset inside OVERLAPPED:

This offset is specified by setting the Offset and OffsetHigh members of the OVERLAPPED structure.

this is very common mistake assume that we can use OVERLAPPED only with asynchronous file handle (If hFile is opened with FILE_FLAG_OVERLAPPED). but this not true. we can always use pointer to OVERLAPPED in WriteFile as parameter. different only in next - in case asynchronous file handle this is mandatory parameter, otherwise optional

OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED, otherwise this parameter can be NULL.

can be but not must be.

another way for set file position - use SetFilePointer[Ex] - is absolete, not efficient and pointer to raise contditional - all what do this api - set CurrentByteOffset inside FILE_OBJECT structure. then in WriteFile if we not provide explicit offset via OVERLAPPED - implicit offset FILE_OBJECT.CurrentByteOffset used. do this (several additional calls to kernel which not need really) - very not efficient compare explicit file offset on OVERLAPPED (and when sombody else use file in concurrent - this offset can be changed between SetFilePointer[Ex] and WriteFile or ReadFile calls) also The old DOS SetFilePointer API is an anachronism. One should specify the file offset in the overlapped structure even for synchronous I/O.

but when we use OVERLAPPED structure - we must initialize it hEvent member to 0 or to valid event handle with SYNCHRONIZE|EVENT_MODIFY_STATE access rigths(and this event must be unique per I/O request - not used in concurrent in another I/O request, until this not finished).

so your current code, when you not intialize hEvent inside _OVERLAPPED offset; by fact is UB. some time it can work ok, if hEvent will be random 0. otherwice you can got next status errors: STATUS_INVALID_HANDLE (the random value inside hEvent not valid handle at all), STATUS_OBJECT_TYPE_MISMATCH (handle is valid but not event), STATUS_ACCESS_DENIED (handle not have EVENT_MODIFY_STATE)

but i sure that WriteFile not return to you error ERROR_ALREADY_EXISTS. only STATUS_OBJECT_NAME_COLLISION is converted to this error and i not view any place where, how NtWriteFile can return such status. i absolute sure that you not got this error, but another. and always good call RtlGetLastNtStatus(); instead (or with) GetLastError() for better diagnostic in this case

answered on Stack Overflow Mar 11, 2019 by RbMm

User contributions licensed under CC BY-SA 3.0