Failed to create a file in windows using createFile API - windows

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.

GetLastError can cause trouble.
Note the docs say
"If the function fails, the return value is INVALID_HANDLE_VALUE. To
get extended error information, call GetLastError."
So, first, only call GetLastError if you get and INVALID_HANDLE_VALUE handle back from CreateFile.
Second, the last error code can be the , well, liertally, last error code - i.e. the most recent call may be OK, but something previously failed: again from the docs
"If the function is not documented to set the last-error code, the value returned by
this function is simply the most recent last-error
code to have been set; some functions set the last-error code to 0 on
success and others do not."

Related

CreateDIBSection: Return value vs error

The documentation of CreateDIBSection states:
If the function succeeds, the return value is a handle to the newly
created DIB, and *ppvBits points to the bitmap bit values.
If the function fails, the return value is NULL, and *ppvBits is NULL.
However, directly after that it states:
This function can return the following value [...] ERROR_INVALID_PARAMETER
So, what is meant by this last sentence? I can hardly imagine that it really returns that value (possibly it actually calls SetLastError). Is this somewhere thoroughly documented?
This is simply an error in the current version of the documentation!
The CreateDIBSection always returns an HBITMAP. If the function fails, then it will return 0 (NULL), and you can call GetLastError. GetLastError will return ERROR_INVALID_PARAMETER.
This is the standard way that all GDI functions work, not to mention the fact that it is impossible for a function return both NULL and an error code. I was also able to dig up an old version of the MSDN documentation for this function (circa 2008), and it confirms that the current version of the online documentation is indeed erroneous:

SetProcessDpiAwareness error code

I'm adding a call to the SetProcessDpiAwareness windows function as the first thing in my Delphi XE7 application (after dynamically loading the shcore DLL). I know it is preferable to use a manifest to set the DPIAware value and I've got that working separately and will use it eventually. However during development I want to use a command line parameter to set DPIAwareness value, otherwise I have to rebuild the app to change this status.
The problem is that SetProcessDpiAwareness returns the error code $800700A0.
That is not documented in the function description, what does the code mean?
Ah I've found it, thanks to the answer to look at the parameter, I had declared the function type wrong, I had:
TSetDPIFunc = function (const PROCESS_DPI_AWARENESS) : HRESULT; stdcall;
but PROCESS_DPI_AWARENESS was not defined as an enum.
Changed to the following and it now works fine:
TSetDPIFunc = function (const x: Integer) : HRESULT; stdcall;
0x8007XXXX is a Win32 error code encapsulated in a COM HRESULT using HRESULT_FROM_WIN32(). WIN32_FROM_HRESULT(0x800700A0) gives 0xA0, i.e. error code 160, which is ERROR_BAD_ARGUMENTS ("One or more of the input parameters are not correct").
It makes no sense for me though that you get this error, since this function doesn't even take any arguments!
So the only thing I can think of would be that it has something to with the issue described here, assuming you changed the DPI settings yourself for testing and it failed then:
So it seems that in order for SetProcessDPIAware (and the related approaches: SetProcessDpiAwareness() and manifest with true) to work correctly, one has to log out and login again after changing the DPI setting and before running the program.
By the way, in case this is helpful: For testing manifests without totally rebuilding, you could use mt.exe to attach a manifest to your application from the command line.

CopyFileEx returns ERROR_INVALID_PARAMETER even if the copy is successful on Win2012R2

CopyFileEx with a following call to GetLastError returns ERROR_INVALID_PARAMETER even if the copy is successful on Win2012R2 since around 2 months back (maybe from December 2015). On Windows XP till Windows 7 and Win 2k3 till Win2k8R2 this does not happen and GetLastError always returns 0 (ERROR_SUCCESS).
Is this expected behavior of this kind of Win32 API?
Do you have to add both result and GetLastError code be sure of the result?
This KB seems related to the problem but applying this patch does not alter the API behavior. There was probably another KB that caused the problem to appear but I have been unable to find it
https://support.microsoft.com/en-us/kb/2963918
Documentation for GetLastError:
Return value
The return value is the calling thread's last-error code.
The Return Value section of the documentation for each function that
sets the last-error code notes the conditions under which the function
sets the last-error code. Most functions that set the thread's
last-error code set it when they fail. However, some functions also
set the last-error code when they succeed. If the function is not
documented to set the last-error code, the value returned by this
function is simply the most recent last-error code to have been set;
some functions set the last-error code to 0 on success and others do
not.
From the documentation:
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error
information call GetLastError.
In other words, if the function succeeds, you are not expected to call GetLastError, and no promise is made about what will be returned if you do.
So, you are ascribing meaning to the value returned by GetLastError where no meaning should be ascribed.
This is a common pattern in Win32. A great many functions are similar. The value returned by GetLastError is only meaningful in the event that the return value of the function indicates failure. That is not a universal rule though, so you do need to check the documentation on a function by function basis.
The typical form of a call to such a Win32 function looks like this:
if (CopyFileEx(...))
{
// function call succeeded, continue
}
else
{
DWORD err = GetLastError();
// do something with err
}
Note that GetLastError is only called if the function indicates failure through its return value.

How to determine if a write operation is successful using NSFileHandle?

The method -writeData: of NSFileHandle class returns nothing. Is there any way for us to determine whether the operation is successful or not? Or I should use other way to save my data?
According to writeData method Reference, this method raises an exception if the file descriptor is closed or is not valid, if the receiver represents an unconnected pipe or socket endpoint, if no free space is left on the file system, or if any other writing error occurs.
You can write any standard cocoa object to a file pretty simple. This returns a BOOL value if it is sucessful or not
BOOL result = [YOUR_OBJECT writeToFile:#"absolute/file/path" atomically:YES]];
if (result)
NSLog(#"All went well");
else
NSLog(#"File was not saved");

How to Initialize Win32 HANDLE appropriately?

Is it OK to initialize the Win32 HANDLE to NULL? Or are there any better or recommended way to initialize HANDLEs?
For example,
void foo()
{
HANDLE hFile;
hFile = CreateFile(/* necessary arguments*/);
}
What shall i initialize the hFile with?
In your example code you don't need to initialise hFile to anything since it is initialised by the CreateFile function.
The Windows API is not completely consistent on what it considers a "null" handle. Some APIs (like CreateFile) return INVALID_HANDLE_VALUE on failure, whereas others return NULL on failure. So the way you test if a HANDLE is valid or not depends on the function you are getting it from - check the actual documentation for the function and see what it says is the return value on failure.

Resources