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 ?
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 withFILE_FLAG_OVERLAPPED
, otherwise this parameter can beNULL
.
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
User contributions licensed under CC BY-SA 3.0