Шпаргалка по 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);
}
Частые ошибки и как их избежать (кратко)
- Забыли закрыть дескриптор — всегда используйте CloseHandle или RegCloseKey в паре с открытием.
- Проверка на NULL вместо INVALID_HANDLE_VALUE — для CreateFile проверяйте именно на INVALID_HANDLE_VALUE.
- Игнорирование кодов ошибок — вызывайте GetLastError() сразу после неудачного вызова.
- Смешивание ANSI и Unicode — используйте W-версии функций и определите UNICODE.
- Неправильный размер буфера — всегда передавайте актуальный размер и проверяйте, сколько байт записано.
Часто задаваемые вопросы (FAQ)
Что такое Windows API (Win32)?
Windows API (Win32) — это набор системных функций, с помощью которых приложения взаимодействуют с операционной системой Windows. Он предоставляет доступ к работе с файлами, памятью, процессами, потоками, реестром, окнами и другими возможностями ОС.
Когда стоит использовать Win32 API вместо готовых библиотек?
Win32 API используют, когда требуется прямой доступ к возможностям операционной системы, высокая производительность или реализация функций, которые недоступны через высокоуровневые библиотеки. Такой подход особенно востребован при разработке системных утилит, драйверов, средств администрирования и специализированного программного обеспечения.
Почему важно закрывать дескрипторы после работы?
Каждый открытый дескриптор занимает системные ресурсы. Если не закрывать их после завершения работы, приложение постепенно начнет потреблять всё больше памяти и ресурсов операционной системы, что может привести к утечкам памяти и нестабильной работе программы.
В чем разница между ANSI- и Unicode-функциями Win32?
Большинство функций Win32 существуют в двух версиях: ANSI (A) и Unicode (W). Современные приложения рекомендуется разрабатывать с использованием Unicode-версий, поскольку Windows внутренне работает с кодировкой UTF-16, что обеспечивает корректную обработку символов любых языков.
Как правильно обрабатывать ошибки функций Win32?
После неудачного вызова функции необходимо сразу проверить её возвращаемое значение и получить код ошибки с помощью GetLastError(). Это позволяет определить точную причину сбоя и корректно обработать исключительную ситуацию в приложении.
Для каких задач чаще всего используют Win32 API?
Win32 API применяется для работы с файловой системой, запуска и управления процессами, выделения памяти, взаимодействия с реестром Windows, синхронизации потоков, создания системных утилит, служб Windows и других приложений, которым необходим прямой доступ к возможностям операционной системы.
Заключение
Этот справочник покрывает основные функции Win32, которые понадобятся в большинстве прикладных задач. Освоив чтение файлов, запуск процессов, работу с реестром и базовую синхронизацию, вы сможете создавать надёжные системные утилиты и тонко настраивать поведение приложений. Для углублённого изучения обращайтесь к официальной документации Microsoft Learn — там вы найдёте полные списки параметров и дополнительные примеры.
Если вы тестируете Win32-приложения, которые требуют изолированного окружения, удобно использовать выделенный сервер — например, VPS от Serverspace. На нём можно развернуть чистую Windows, проводить эксперименты с дескрипторами и памятью, не боясь нарушить стабильность основной рабочей станции.