Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes WriteFile to return ERROR_ACCESS_DENIED?

We currently face the problem of a call to WriteFile (or, rather CFile::Write - but that just calls WriteFile internally) causing the Win32 error 5 ERROR_ACCESS_DENIED.

(EDIT: Note that we can't repro the behavior. All we have at the moment is a logfile indicating the source line where the CFile::Write was and containing as error ERROR_ACCESS_DENIED!)

(EDIT: The file is on a local drive and it is in fact a file and not a directory.)

Now, WriteFiles's documentation doesn't really help, and experimenting with a simple test-app yields the following results:

  1. WriteFile will cause ERROR_ACCESS_DENIED if it is called for a file handle that is not opened for writing (i.e. is opened for reading only).
  2. It will not cause ERROR_ACCESS_DENIED if
    • The handle is not valid or the file isn't open at all
    • The access rights, or the write protected flag for the file are modified after the file has been opened by the process. (If these are modified before the file is opened, then we never get to WriteFile because opening the file will fail.)
    • The file is somehow locked by another process/handle (This will at best result in error 32 ERROR_SHARING_VIOLATION).

That leaves us with the situation, that apparently the only possibility for this call to fail if the file was actually opened with the read flag instead of the write flag. However, looking at our code, this seems extremely unlikely. (Due to our tracing, we can be sure that WriteFile failed and we can be sure that the error is ERROR_ACCESS_DENIED, we cannot be 100.1% sure of the opening flags, because these are not traced out.)

Are there any other known circumstances where WriteFile (CFile::Write) would cause an ERROR_ACCESS_DENIED?

Note: To additionally clarify the context of this question:

  • The file was open, therefore it can't be a directory or somesuch
  • All tests I performed indicate that while the file is open it cannot be deleted, so the file should still have been there on the call to WriteFile
  • The file is located on a local drive and not on a network drive.

I should add that we're running on WIndows XP sp3 and the app is compiled with Visual Studio 2005.

like image 612
Martin Ba Avatar asked Nov 30 '10 10:11

Martin Ba


2 Answers

The question was

What causes WriteFile to return ERROR_ACCESS_DENIED?

and I stated in the question

  1. WriteFile will cause ERROR_ACCESS_DENIED if it is called for a file handle that is not opened for writing (i.e. is opened for reading only).

After adding further logging for the open flags and another incident, it turns out this was correct. The logging for the open flags shows that at the point of error, the file object was opened with CFile::modeRead and therefore we got ERROR_ACCESS_DENIED.

Haven't found out yet which weird code path leads to this, but this just goes to show: Never trust your own code. :-)

(Oh, and btw. It wasn't ::WriteFile that failed, but the ::FlushFileBuffers API, but apparently that returns the same error.)

like image 141
Martin Ba Avatar answered Nov 08 '22 16:11

Martin Ba


There is about a dozen different situations that might result in ERROR_ACCESS_DENIED. Internally, all WriteFile does is call NtWriteFile and map its (somewhat meaningful) NTSTATUS error code into a less meaningful HRESULT.

Among other things, ERROR_ACCESS_DENIED could indicate that the file is on a network volume and something went wrong with write permissions, or that the file is really not a file but a directory.

like image 33
Eugene Smith Avatar answered Nov 08 '22 16:11

Eugene Smith