Список LPPROC_THREAD_ATTRIBUTE_LIST требует двух этапов при создании и двух действий при разрушении: сначала инициализируются внутренние атрибуты, затем освобождается выделенный буфер. Удобно связать этот порядок с временем жизни C++-объекта.
Двухфазная инициализация
Первый вызов InitializeProcThreadAttributeList с nullptr используется, чтобы получить требуемый размер буфера; он ожидаемо возвращает ошибку и в out-параметре bytes указывает необходимый объём. После выделения буфера нужно повторно вызвать InitializeProcThreadAttributeList. Если второй вызов не удался, освобождается только память: удалять ещё не инициализированный список нельзя.
#include <windows.h>
#include <new>
#include <system_error>
struct Attributes final {
LPPROC_THREAD_ATTRIBUTE_LIST value = nullptr;
explicit Attributes(DWORD capacity) {
SIZE_T bytes = 0;
InitializeProcThreadAttributeList(nullptr, capacity, 0, &bytes);
if (!bytes)
throw std::system_error(GetLastError(), std::system_category());
void* storage = HeapAlloc(GetProcessHeap(), 0, bytes);
if (!storage) throw std::bad_alloc();
auto candidate = static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(storage);
if (!InitializeProcThreadAttributeList(candidate, capacity, 0, &bytes)) {
DWORD error = GetLastError();
HeapFree(GetProcessHeap(), 0, storage);
throw std::system_error(error, std::system_category());
}
value = candidate;
}
~Attributes() {
if (value) {
DeleteProcThreadAttributeList(value);
HeapFree(GetProcessHeap(), 0, value);
}
}
Attributes(const Attributes&) = delete;
Attributes& operator=(const Attributes&) = delete;
};
Это минимальный пример владения для Windows SDK без дополнительных оболочек. Копирование запрещено, чтобы два объекта не попытались освободить один указатель. Для добавления каждого атрибута следует вызывать UpdateProcThreadAttribute и проверять результат; память, на которую ссылаются значения атрибутов, должна оставаться действительной до вызова DeleteProcThreadAttributeList. Для создания процесса с расширённой информацией необходима структура STARTUPINFOEX и флаг EXTENDED_STARTUPINFO_PRESENT при вызове CreateProcess.
Перед использованием примера проверьте его сборку и обработку ошибок в целевой конфигурации Windows SDK.