Overview
Win32 error handling provides a set of functions and conventions for reporting and interpreting errors in Windows applications. The core mechanism revolves around GetLastError and SetLastError, which store an error code in thread‑local storage.
Most Windows API functions indicate failure by returning a boolean FALSE, a NULL handle, or a special value such as INVALID_HANDLE_VALUE. When a function fails, you can retrieve the extended error information by calling GetLastError.
Key Functions
GetLastError
#include <windows.h>
DWORD GetLastError(void);
Retrieves the calling thread's last-error code value. The last-error code is maintained on a per‑thread basis.
SetLastError
#include <windows.h>
void SetLastError(DWORD dwErrCode);
Sets the last-error code for the calling thread. Most applications should not call this directly; it is used when implementing custom wrappers around Windows APIs.
FormatMessage
#include <windows.h>
DWORD FormatMessage(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPTSTR lpBuffer,
DWORD nSize,
va_list *Arguments);
Formats a message string. Commonly used to translate an error code returned by GetLastError into a readable string.
Common Win32 Error Codes
| Code | Name | Description |
|---|---|---|
| 0 | ERROR_SUCCESS | The operation completed successfully. |
| 2 | ERROR_FILE_NOT_FOUND | The system cannot find the file specified. |
| 5 | ERROR_ACCESS_DENIED | Access is denied. |
| 6 | ERROR_INVALID_HANDLE | The handle is invalid. |
| 87 | ERROR_INVALID_PARAMETER | The parameter is incorrect. |
| 123 | ERROR_INVALID_NAME | The filename, directory name, or volume label syntax is incorrect. |
| 995 | ERROR_OPERATION_ABORTED | The I/O operation has been aborted because of either a thread exit or an application request. |
Example: Using GetLastError and FormatMessage
#include <windows.h>
#include <stdio.h>
int main(void) {
HANDLE hFile = CreateFileA(
"nonexistent.txt",
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
char msg[256];
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
0,
msg,
sizeof(msg),
NULL);
printf("Failed to open file: %s\\n", msg);
} else {
CloseHandle(hFile);
}
return 0;
}