Win32 Error Handling

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

CodeNameDescription
0ERROR_SUCCESSThe operation completed successfully.
2ERROR_FILE_NOT_FOUNDThe system cannot find the file specified.
5ERROR_ACCESS_DENIEDAccess is denied.
6ERROR_INVALID_HANDLEThe handle is invalid.
87ERROR_INVALID_PARAMETERThe parameter is incorrect.
123ERROR_INVALID_NAMEThe filename, directory name, or volume label syntax is incorrect.
995ERROR_OPERATION_ABORTEDThe 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;
}