Q: How to correctly use GetLastError to get the error code for a WinAPI function failure?

A:
  • First of all, take a look in the documentation to see if the given WinAPI function sets thread's last-error code value. Usually, you can find a reference to GetLastError in the "Return Values" section.
  • See what is the value returned in case of failure: it may be zero, a NULL handle, or some other particular value like INVALID_HANDLE_VALUE.
  • Finally, test the returned value in your code and, in case of failure, call GetLastError.

Examples
Code:
   BOOL bRet = ::DeleteFile(pszFileName);
   if(! bRet) // DeleteFile function has failed
   {
      DWORD dwError = ::GetLastError();
      // ...
   }
Code:
   HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
   if(NULL == hProcess) // OpenProcess function has failed
   {
      DWORD dwError = ::GetLastError();
      // ...
   }
Code:
   HANDLE hFind = ::FindFirstFile(pszFileName, &findData);
   if(INVALID_HANDLE_VALUE == hFind) // FindFirstFile function has failed
   {
      DWORD dwError = ::GetLastError();
      // ...
   }
Notes
  1. There is not guaranteed that a WinAPI function sets thread's last-error code to zero in case of success. One mistake often made by programmers is to call GetLastError without previously check for the function failure. In the next example, GetLastError returns a value of 8 (ERROR_NOT_ENOUGH_MEMORY) even when LoadImage succeeds.
    Code:
       HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, pszFileName,
          IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    
       DWORD dwError = ::GetLastError(); 
       // This is wrong! You have to call GetLastError only if hBitmap is NULL.
  2. Some WinAPI functions (e.g. RegQueryValueEx) directly return an error code so a further call of GetLastError has no sense.
    In any case you have to pay attention to the WinAPI function's documentation to see if it sets last-error or not.


See also