Thought that it may be helpful to someone because it was a kind of surprise for me.
WriteFile function tries to write into its 4th (optional) parameter, and if it is NULL it causes Access Violation exception... But not on Windows 8(.1).
This is the function definition from msdn:
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten, // Optional
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
lpNumberOfBytesWritten [out, optional] ... This parameter can be NULL only when the lpOverlapped parameter is not NULL.
I created short example that reproduces the error. The code is Win32 console application created in Visual Studio 2008 SP1:
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = CreateFile(L"N:\\Test\\Test.tmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
if (INVALID_HANDLE_VALUE == hFile) {
return -1;
}
unsigned int testValue = 32;
//-----------------------------------------------
// Next line generates AV exception on Windows 7,
// On Windows 8 it works fine:
//-----------------------------------------------
WriteFile(hFile, &testValue, sizeof(unsigned int), NULL, NULL);
CloseHandle(hFile);
return 0;
}
And, finally, if I change the call to WriteFile() by the following two lines, this solves the problem and works on all platforms:
// Now it does not generate AV:
DWORD written = 0;
WriteFile(hFile, &testValue, sizeof(unsigned int), &written, NULL);
The code generates Access Violation on Windows 7 and on Windows XP SP3 (did not test it on Vista). On Windows 8(.1) it works, even when I pass NULL in 4th parameter (lpNumberOfBytesWritten).
The actual problem was that I developed a module that writes into a temporary file, but I ignored the 4th parameter (I read "optional" but misread the rest and thought that it may be ignored). I developed and tested it on Windows 8.1, so the code worked fine, but the client machine was on Windows 7 and code failed.
The lessons I learned: I should be more attentive (to details) and don't be smug (and test carefully).
The documentation for lpNumberOfBytesWritten
says:
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
In other words, the lpNumberOfBytesWritten
parameter is only optional when you are using overlapped IO. You are passing NULL
for lpOverlapped
, and therefore not using overlapped IO, the lpNumberOfBytesWritten
is not optional and cannot be NULL
.