Thanks to DavidK and Larry - Here's my final solution. Full error handling is left as an exercise for the reader.
Note that rather than specifically checking the OS version, I attempt to dynamically link to the functions. Static linking would mean that the application would simply fail to load if the procedure wasn't available.
This has been tried successfully on Win2K and 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;
}
}