Can not create a file in Windows using the createFile API

advertisements

I am failing to create a file in windows using the CreateFile API, GetLastError returns the error code 80 which means the file exists, but actually the file was not existing.

hFile = CreateFile((LPCTSTR) FILEPATH,  // name of the write
    GENERIC_READ|GENERIC_WRITE,         // open for writing
    0,                                  // do not share
    NULL,                               // default security
    CREATE_ALWAYS,                      // create new file only
    FILE_ATTRIBUTE_NORMAL,              // normal file
    NULL);                              // no attr. template
printf("GET LAST ERROR VALUE IS: %d\n", GetLastError());

What am I doing wrong?


Your error checking is wrong. The documentation says:

Return value

If the function succeeds, the return value is an open handle to the specified file, device, named pipe, or mail slot.

If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.

In other words, failure is determined by the return value. You cannot use GetLastError to determine failure. You must check the return value and compare against INVALID_HANDLE_VALUE. When you do so I predict that you will find that the return value is not equal to INVALID_HANDLE_VALUE.


In fact, this API uses the last error value to convey extra information even when the function succeeds.

From the documentation of CREATE_ALWAYS:

If the specified file exists and is writable, the function overwrites the file, the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS (183).

And from the documentation of CREATE_NEW:

Creates a new file, only if it does not already exist. If the specified file exists, the function fails and the last-error code is set to ERROR_FILE_EXISTS (80).

And so on.

The golden rule, one that you must burn into your memory, is that error checking varies from function to function and that you must read the documentation from top to tail.


Note that I am rather sceptical of your (LPCTSTR) cast. That's just asking for trouble. If the path is the wrong type, the compiler will save you from yourself, unless you use that cast. That cast just tells the compiler to shut up. But here it knows better. That cast will allow you to pass ANSI text to a wide API and vice versa. You really should remove it.