Windows API Cheat Sheet: Key Win32 Functions, Commands, and Use Cases
Windows API (Win32) is the foundation on which all Windows applications are built. If you write code that interacts with the system at a low level, you need quick access to key functions: file operations, processes, memory, and the registry. This article is not a general overview, but a compact reference with concrete signatures, examples, and typical usage scenarios. There is no superfluous theory here — only what you will use in day-to-day development.
Basic concepts you need to know before starting
Before diving into the functions, let's go over four important mechanisms without which you cannot properly work with Win32.
Handles (HANDLE) and closing them
Most Win32 functions that open resources (files, processes, registry keys) return a value of type HANDLE — this is an integer handle (an opaque identifier) that the kernel uses to reference an object. It is not a pointer to memory and should not be interpreted as an address. The handle must be closed with CloseHandle (or a specialised function such as RegCloseKey), otherwise a resource leak will occur. Each open handle consumes memory and can lead to system instability over time.
INVALID_HANDLE_VALUE
On error, the CreateFile function returns not NULL but a special value INVALID_HANDLE_VALUE (defined as (HANDLE)-1). It is important to remember: check specifically for this value, not for NULL.
Error codes and GetLastError
Each Win32 function returns its own special error value: it may be FALSE (0) for functions with BOOL return type, NULL for functions returning pointers (e.g., VirtualAlloc, OpenProcess), INVALID_HANDLE_VALUE for CreateFile, or a code other than ERROR_SUCCESS for registry functions. To get the detailed reason, immediately after a failed call use GetLastError(). The error code can be matched with constants from winerror.h (e.g., ERROR_FILE_NOT_FOUND).
Function versions: A and W
Many string functions exist in two variants: with the suffix A (ANSI, single-byte encoding) and W (wide characters, UTF-16). In modern projects, it is recommended to use the W versions, because Windows works internally with UTF-16. Using the A versions involves conversion to the system code page (e.g., Windows-1251), which can distort non-Latin characters. Make sure that the UNICODE and _UNICODE macros are defined in your project so that the wide versions are called by default.
Key Win32 functions: summary table
The following tables list the most commonly used functions, grouped by category. For each, we give the purpose, main parameters, return value, and a typical usage scenario.
File and directory operations
| Function | Purpose and typical use | Parameters and return value |
|---|---|---|
| CreateFile | Opens or creates a file, device, pipe, or another I/O object.
Typical use: Open a file for reading or writing.
|
Parameters:
lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile
Returns: HANDLE or INVALID_HANDLE_VALUE
|
| ReadFile | Reads data from a file or device.
Typical use: Read file contents into a buffer.
|
Parameters:
hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped
Returns: BOOL
|
| WriteFile | Writes data to a file or device.
Typical use: Save data to a file.
|
Parameters:
hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped
Returns: BOOL
|
| CloseHandle | Closes an open kernel object handle.
Typical use: Release a file, process, thread, mutex, or another handle after use.
|
Parameters:
hObject
Returns: BOOL
|
Process management
| Function | Purpose and typical use | Parameters and return value |
|---|---|---|
| CreateProcess | Creates a new process and its primary thread.
Typical use: Launch an external application and obtain handles to its process and primary thread.
|
Parameters:
lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation
Returns: BOOL
|
| OpenProcess | Opens an existing process by its process ID.
Typical use: Inspect, monitor, or interact with another process when permissions allow it.
|
Parameters:
dwDesiredAccess, bInheritHandle, dwProcessId
Returns: HANDLE or NULL
|
| TerminateProcess | Forcibly terminates a process.
Typical use: Stop an unresponsive process. Use only when graceful shutdown is not possible.
|
Parameters:
hProcess, uExitCode
Returns: BOOL
|
Memory management
| Function | Purpose and typical use | Parameters and return value |
|---|---|---|
| VirtualAlloc | Reserves or commits pages in the virtual address space of the calling process.
Typical use: Allocate a memory region for buffers, data structures, or executable code.
|
Parameters:
lpAddress, dwSize, flAllocationType, flProtect
Returns: LPVOID or NULL
|
| VirtualFree | Releases or decommits pages allocated with VirtualAlloc.
Typical use: Release an allocated memory region.
|
Parameters:
lpAddress, dwSize, dwFreeType
Returns: BOOL
|
| ReadProcessMemory | Copies data from the address space of another process.
Typical use: Use in debuggers, diagnostic tools, and authorised process monitoring.
|
Parameters:
hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead
Returns: BOOL
|
Registry operations
| Function | Purpose and typical use | Parameters and return value |
|---|---|---|
| RegOpenKeyEx | Opens an existing registry key.
Typical use: Open a key before reading or changing application settings.
|
Parameters:
hKey, lpSubKey, ulOptions, samDesired, phkResult
Returns: LONG; ERROR_SUCCESS on success
|
| RegQueryValueEx | Retrieves the type and data of a value in an open registry key.
Typical use: Read a string, DWORD, binary value, or another registry data type.
|
Parameters:
hKey, lpValueName, lpReserved, lpType, lpData, lpcbData
Returns: LONG
|
| RegSetValueEx | Stores data in a value under an open registry key.
Typical use: Save application configuration in the registry.
|
Parameters:
hKey, lpValueName, Reserved, dwType, lpData, cbData
Returns: LONG
|
| RegCloseKey | Closes a handle to an open registry key.
Typical use: Release the registry key handle after use.
|
Parameters:
hKey
Returns: LONG
|
Synchronisation primitives
| Function | Purpose and typical use | Parameters and return value |
|---|---|---|
| CreateMutex | Creates a mutex object or opens an existing named mutex.
Typical use: Coordinate access to a shared resource or enforce a single application instance.
|
Parameters:
lpMutexAttributes, bInitialOwner, lpName
Returns: HANDLE or NULL
|
| WaitForSingleObject | Waits until one kernel object is signalled or the timeout expires.
Typical use: Wait for a process or thread to finish, or for a mutex or event to become available.
|
Parameters:
hHandle, dwMilliseconds
Returns: DWORD
|
Code examples
Reading a file with error handling
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE hFile = CreateFileW(
L"example.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
printf("Failed to open file, error: %lu\n", err);
return 1;
}
char buffer[1024];
DWORD bytesRead;
if (!ReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {
DWORD err = GetLastError();
printf("Read error: %lu\n", err);
CloseHandle(hFile);
return 1;
}
buffer[bytesRead] = '\0';
printf("Content: %s\n", buffer);
CloseHandle(hFile);
return 0;
}
Launching a process (Calculator) and waiting for it to finish
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi;
if (CreateProcessW(
L"C:\\Windows\\System32\\calc.exe",
NULL, NULL, NULL, FALSE,
0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else {
printf("Launch error: %lu\n", GetLastError());
}
Reading a value from the registry
HKEY hKey;
LONG result = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
0, KEY_READ, &hKey);
if (result == ERROR_SUCCESS) {
WCHAR buffer[256];
// Note: the buffer size is passed in bytes, not characters.
// For a WCHAR array, sizeof(buffer) gives the total size in bytes,
// which is correct for RegQueryValueExW.
DWORD bufferSize = sizeof(buffer);
DWORD type;
if (RegQueryValueExW(hKey, L"ProductName", NULL, &type,
(LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS) {
wprintf(L"Product name: %s\n", buffer);
}
RegCloseKey(hKey);
} else {
printf("Failed to open key, code: %ld\n", result);
}
Common mistakes and how to avoid them (brief)
- Forgetting to close a handle — always pair opening with CloseHandle or RegCloseKey.
- Checking for NULL instead of INVALID_HANDLE_VALUE — for CreateFile, always check for INVALID_HANDLE_VALUE.
- Ignoring error codes — call GetLastError() immediately after a failed call.
- Mixing ANSI and Unicode — use W versions and define UNICODE.
- Incorrect buffer size — always pass the actual size and check how many bytes were written.
Frequently Asked Questions (FAQ)
What is the Windows API (Win32)?
The Windows API (Win32) is a collection of system functions that allow applications to interact directly with the Windows operating system. It provides access to files, processes, memory, the Windows Registry, threads, synchronization objects, and many other low-level system features.
When should I use the Win32 API instead of high-level libraries?
Win32 API is the right choice when you need direct access to operating system functionality, maximum performance, or features that are not exposed through higher-level frameworks. It is commonly used for system utilities, administration tools, desktop applications, debugging software, and performance-critical programs.
Why is it important to close handles in Win32?
Every open handle consumes operating system resources. If handles are not closed after use, applications may leak resources over time, leading to increased memory usage, reduced system stability, and eventually application failures. Always release handles using CloseHandle or the appropriate Win32 function for the specific object type.
Should I use ANSI or Unicode versions of Win32 functions?
For modern Windows development, the Unicode (W) versions are strongly recommended. Windows internally uses UTF-16, making Unicode functions more reliable for international applications and preventing character encoding issues that can occur with ANSI (A) functions.
How should Win32 errors be handled?
Always check the return value of a Win32 function. If the call fails, immediately call GetLastError() to retrieve the system error code before executing any other Win32 API function. The returned code can then be used to identify the exact reason for the failure.
What are the most commonly used Win32 API functions?
Some of the most frequently used Win32 functions include CreateFile for file operations, ReadFile and WriteFile for reading and writing data, CreateProcess for launching applications, VirtualAlloc for memory allocation, OpenProcess for accessing other processes, RegOpenKeyEx for Registry operations, and WaitForSingleObject for thread and process synchronization.
Conclusion
This reference covers the main Win32 functions you will need in most application tasks. By mastering file reading, process launching, registry operations, and basic synchronisation, you will be able to create robust system utilities and fine‑tune application behaviour. For deeper study, refer to the official Microsoft Learn documentation, where you will find complete parameter lists and additional examples.
If you are testing Win32 applications that require an isolated environment, consider using a dedicated server — for example, VPS from Serverspace. You can deploy a clean Windows instance there, run experiments with handles and memory, without risking the stability of your main workstation.