23.07.2026

Шпаргалка по Windows API: основные функции Win32, команды и сценарии

Windows API (Win32) — это фундамент, на котором строятся все приложения для Windows. Если вы пишете код, который взаимодействует с системой на низком уровне, вам нужен быстрый доступ к ключевым функциям: работа с файлами, процессами, памятью и реестром. Эта статья — не общий обзор, а компактный справочник с конкретными сигнатурами, примерами и типичными сценариями использования. Здесь нет лишней теории — только то, что пригодится в ежедневной разработке.

Базовые понятия, которые нужно знать перед стартом

Прежде чем переходить к функциям, разберём четыре важных механизма, без которых невозможно правильно работать с Win32.

Дескрипторы (HANDLE) и их закрытие

Большинство функций Win32, открывающих ресурсы (файлы, процессы, ключи реестра), возвращают значение типа HANDLE — это целочисленный дескриптор (непрозрачный идентификатор), который ядро использует для ссылки на объект. Он не является указателем на память и не должен интерпретироваться как адрес. Дескриптор нужно обязательно закрывать с помощью CloseHandle (или специализированной функции, например RegCloseKey), иначе произойдёт утечка ресурсов. Каждый открытый дескриптор потребляет память и может привести к нестабильности системы при долгой работе.

INVALID_HANDLE_VALUE

При ошибке функция CreateFile возвращает не NULL, а специальное значение INVALID_HANDLE_VALUE (определено как (HANDLE)-1). Это важно помнить: проверяйте именно на это значение, а не на NULL.

Коды ошибок и GetLastError

Каждая функция Win32 возвращает своё специальное значение ошибки: это может быть FALSE (0) для функций с типом BOOL, NULL для функций, возвращающих указатели (например, VirtualAlloc, OpenProcess), INVALID_HANDLE_VALUE для CreateFile, или код, отличный от ERROR_SUCCESS для функций реестра. Чтобы получить детальную причину, сразу после неудачного вызова используйте GetLastError(). Код ошибки можно сопоставить с константами из winerror.h (например, ERROR_FILE_NOT_FOUND).

Версии функций: A и W

Многие строковые функции существуют в двух вариантах: с суффиксом A (ANSI, однобайтовая кодировка) и W (широкие символы, UTF-16). В современных проектах рекомендуется использовать W-версии, так как Windows внутренне работает с UTF-16. При использовании A-версий происходит преобразование в кодовую страницу системы (например, Windows-1251), что может исказить нелатинские символы. Убедитесь, что в проекте определены макросы UNICODE и _UNICODE, чтобы по умолчанию вызывались широкие версии.

Ключевые функции Win32: сводная таблица

Ниже приведены наиболее востребованные функции, сгруппированные по категориям. Для каждой указаны: назначение, основные параметры, возвращаемое значение и типичный сценарий использования.

Работа с файлами и каталогами

Функция Детали
CreateFile
Назначение: Открывает или создаёт файл, устройство, канал
Параметры:
lpFileName
dwDesiredAccess
dwShareMode
lpSecurityAttributes
dwCreationDisposition
dwFlagsAndAttributes
hTemplateFile
Возвращает: HANDLE или INVALID_HANDLE_VALUE
Сценарий: Открыть файл для чтения/записи
ReadFile
Назначение: Читает данные из файла или устройства
Параметры:
hFile
lpBuffer
nNumberOfBytesToRead
lpNumberOfBytesRead
lpOverlapped
Возвращает: BOOL (ненулевое при успехе)
Сценарий: Прочитать содержимое файла в буфер
WriteFile
Назначение: Записывает данные в файл или устройство
Параметры:
hFile
lpBuffer
nNumberOfBytesToWrite
lpNumberOfBytesWritten
lpOverlapped
Возвращает: BOOL
Сценарий: Сохранить данные в файл
CloseHandle
Назначение: Закрывает любой дескриптор
Параметры:
hObject
Возвращает: BOOL
Сценарий: Освободить ресурс после работы

Управление процессами

Функция Детали
CreateProcess
Назначение: Запускает новый процесс
Параметры:
lpApplicationName
lpCommandLine
lpProcessAttributes
lpThreadAttributes
bInheritHandles
dwCreationFlags
lpEnvironment
lpCurrentDirectory
lpStartupInfo
lpProcessInformation
Возвращает: BOOL
Сценарий: Запустить внешнее приложение (например, калькулятор)
OpenProcess
Назначение: Открывает существующий процесс по PID
Параметры:
dwDesiredAccess
bInheritHandle
dwProcessId
Возвращает: HANDLE или NULL
Сценарий: Получить доступ к памяти другого процесса
TerminateProcess
Назначение: Принудительно завершает процесс
Параметры:
hProcess
uExitCode
Возвращает: BOOL
Сценарий: Аварийно остановить процесс (используйте с осторожностью)

Управление памятью

Функция Детали
VirtualAlloc
Назначение: Резервирует или фиксирует память в виртуальном адресном пространстве
Параметры:
lpAddress
dwSize
flAllocationType
flProtect
Возвращает: LPVOID или NULL
Сценарий: Выделить буфер для чтения больших файлов
VirtualFree
Назначение: Освобождает память
Параметры:
lpAddress
dwSize
dwFreeType
Возвращает: BOOL
Сценарий: Освободить выделенный участок
ReadProcessMemory
Назначение: Читает память другого процесса
Параметры:
hProcess
lpBaseAddress
lpBuffer
nSize
lpNumberOfBytesRead
Возвращает: BOOL
Сценарий: Отладка или мониторинг

Работа с реестром

Функция Детали
RegOpenKeyEx
Назначение: Открывает существующий раздел реестра
Параметры:
hKey
lpSubKey
ulOptions
samDesired
phkResult
Возвращает: LONG (ERROR_SUCCESS при успехе)
Сценарий: Открыть ключ для чтения настроек
RegQueryValueEx
Назначение: Получает значение из открытого раздела
Параметры:
hKey
lpValueName
lpReserved
lpType
lpData
lpcbData
Возвращает: LONG
Сценарий: Прочитать строковое или DWORD-значение
RegSetValueEx
Назначение: Записывает значение в раздел
Параметры:
hKey
lpValueName
Reserved
dwType
lpData
cbData
Возвращает: LONG
Сценарий: Сохранить настройки приложения
RegCloseKey
Назначение: Закрывает дескриптор раздела
Параметры:
hKey
Возвращает: LONG
Сценарий: Закрыть ключ после работы

Примитивы синхронизации

Функция Детали
CreateMutex
Назначение: Создаёт или открывает именованный мьютекс
Параметры:
lpMutexAttributes
bInitialOwner
lpName
Возвращает: HANDLE или NULL
Сценарий: Обеспечить одиночный запуск приложения
WaitForSingleObject
Назначение: Ожидает сигнального состояния объекта
Параметры:
hHandle
dwMilliseconds
Возвращает: DWORD (WAIT_OBJECT_0 и др.)
Сценарий: Ожидать завершения потока или освобождения мьютекса

Практические примеры кода

Чтение файла с обработкой ошибок

#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("Не удалось открыть файл, ошибка: %lu\n", err);
        return 1;
    }

    char buffer[1024];
    DWORD bytesRead;
    if (!ReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {
        DWORD err = GetLastError();
        printf("Ошибка чтения: %lu\n", err);
        CloseHandle(hFile);
        return 1;
    }

    buffer[bytesRead] = '\0';
    printf("Содержимое: %s\n", buffer);

    CloseHandle(hFile);
    return 0;
}

Запуск процесса (калькулятор) и ожидание его завершения

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("Ошибка запуска: %lu\n", GetLastError());
}

Чтение значения из реестра

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];
    // Внимание: размер буфера передаётся в байтах, а не в символах.
    // Для WCHAR-массива sizeof(buffer) даёт общий размер в байтах,
    // что корректно для RegQueryValueExW.
    DWORD bufferSize = sizeof(buffer);
    DWORD type;
    if (RegQueryValueExW(hKey, L"ProductName", NULL, &type,
                         (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS) {
        wprintf(L"Имя продукта: %s\n", buffer);
    }
    RegCloseKey(hKey);
} else {
    printf("Не удалось открыть ключ, код: %ld\n", result);
}

Частые ошибки и как их избежать (кратко)

Часто задаваемые вопросы (FAQ)

Что такое INVALID_HANDLE_VALUE и когда его проверять?
Это константа, равная -1. Её возвращает CreateFile и некоторые другие функции (например, CreateNamedPipe). Однако функции OpenProcess, CreateMutex, CreateThread при ошибке возвращают NULL. Всегда сверяйтесь с документацией конкретной функции, чтобы знать, какое значение ошибки ожидать.
В чём разница между CloseHandle и RegCloseKey?
CloseHandle закрывает общие дескрипторы (файлы, процессы, мьютексы). Для ключей реестра используйте RegCloseKey — она делает то же самое, но специально для реестра.
Какую версию функций выбирать: A или W?
Рекомендуется W (Unicode), так как это родной формат Windows. Использование A может привести к проблемам с кодировкой для неанглийских символов.
Почему GetLastError возвращает 0, хотя функция вернула ошибку?
Возможно, вы вызвали другую функцию до GetLastError. Код ошибки сохраняется только до следующего вызова Win32 API. Вызывайте GetLastError сразу после неудачной функции.

Заключение

Этот справочник покрывает основные функции Win32, которые понадобятся в большинстве прикладных задач. Освоив чтение файлов, запуск процессов, работу с реестром и базовую синхронизацию, вы сможете создавать надёжные системные утилиты и тонко настраивать поведение приложений. Для углублённого изучения обращайтесь к официальной документации Microsoft Learn — там вы найдёте полные списки параметров и дополнительные примеры.

Если вы тестируете Win32-приложения, которые требуют изолированного окружения, удобно использовать выделенный сервер — например, VPS от Serverspace. На нём можно развернуть чистую Windows, проводить эксперименты с дескрипторами и памятью, не боясь нарушить стабильность основной рабочей станции.