0

I have a win32 app opening a log file on a network share using CreateFile and WriteFile (non overlapped) to write records. What I am seeing when the network share is lost, WriteFile reports an error (59 or 53), but an empty record (zero bytes) of the correct size is written to the file. When the share comes back online, I can see the valid data previously written and the empty records for the time that the share was lost. At the same time as the share disconnect, GetFileSize and SetFilePointer can't see any errors, but instead report the changed files as new records get added.

How does WriteFile fail when a shared file is offline ?

Happens on server 2012 ,2019, mapped drive.

Opening of the file:

hFile=CreateFile(filename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
    if (hFile==INVALID_HANDLE_VALUE && GetLastError()==ERROR_FILE_NOT_FOUND)
        hFile=CreateFile(filename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_NEW,0,NULL);

Writing data:

if (!WriteFile(hFile,(LPCVOID)&data,sizeof(data),&bytes,NULL) || bytes==0)
{
    lasterror=GetLastError();

The file is kept open all the time.

1
  • 1
    I don't have an answer for you, just an observation - your double-call of CreateFile() introduces a TOCTOU race condition. You don't need 2 calls, just 1 call will suffice using OPEN_ALWAYS instead of OPEN_EXISTING+CREATE_NEW separately. Commented Nov 18 at 20:37

1 Answer 1

1

The empty records happen because Windows caches network writes. When the share goes offline, WriteFile fails but space is already reserved, creating zeroed records.

Fixes:

  1. Use FILE_FLAG_WRITE_THROUGH to bypass cache:
hFile = CreateFile(filename, GENERIC_READ|GENERIC_WRITE,
                   FILE_SHARE_READ|FILE_SHARE_WRITE,
                   NULL, OPEN_EXISTING,
                   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
  1. Flush after each write:
WriteFile(hFile, &data, sizeof(data), &bytes, NULL);
FlushFileBuffers(hFile);
  1. Handle errors and retry or queue locally.
Sign up to request clarification or add additional context in comments.

2 Comments

After the share is lost, WriteFile & SetFilePointer correctly work (WriteFile returns the same error & SetFilePointer(...FILE_END) gets advanced, this is good, so I need to keep this going with the same FileHandle. How then do I detect that the network share is reconnected again, Close the old handle and start saving data that was needed when the share was disconnected ? Use a 2nd CreateFile as a test ?
The original handle won’t recover. You can try a second CreateFile; once it succeeds, close the old handle and write any data buffered while the share was disconnected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.