Спасибо DavidK и Larry - вот мое окончательное решение. Полная обработка ошибок оставлена читателю в качестве упражнения.
Обратите внимание, что вместо того, чтобы специально проверять версию ОС, я пытаюсь динамически связываться с функциями. Статическое связывание будет означать, что приложение просто не сможет загрузиться, если процедура недоступна.
Это было успешно опробовано в Windows 2000 и Vista:
#include "Winternl.h"
typedef DWORD (WINAPI* pfnGetProcID)(HANDLE h);
typedef NTSTATUS (WINAPI* pfnQueryInformationProcess)(
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength);
DWORD MyGetProcessId(HANDLE h)
{
static pfnQueryInformationProcess ntQIP = (pfnQueryInformationProcess) GetProcAddress(GetModuleHandle("NTDLL.DLL"),"NtQueryInformationProcess");
static pfnGetProcID getPId = (pfnGetProcID) GetProcAddress(GetModuleHandle("KERNEL32.DLL"),"GetProcessId");
if ((ntQIP == NULL) && (getPId == NULL))
throw Exception("Can't retrieve process ID : GetProcessID not supported");
if (getPId != NULL)
return getPId(h);
else
{
PROCESS_BASIC_INFORMATION info;
ULONG returnSize;
ntQIP(h, ProcessBasicInformation, &info, sizeof(info), &returnSize); // Get basic information.
return info.UniqueProcessId;
}
}