Roddy
Roddy

Reputation: 68053

Alternative to GetProcessID for Windows 2000

I've accidentally removed Win2K compatibility from an application by using GetProcessID.

I use it like this, to get the main HWND for the launched application.

ShellExecuteEx(&info); // Launch application
HANDLE han = info.hProcess; // Get process

cbinfo.han = han;

//Call EnumWindows to enumerate windows....
//with this as the callback

static BOOL CALLBACK enumproc(HWND hwnd, LPARAM lParam)
{
  DWORD id;
  GetWIndowThreadProcessID(hwnd, &id);
  if (id == GetProcessID(cbinfo.han))
    setResult(hwnd)
 ...
}

Any ideas how the same function could be acheived on Win2K?

Upvotes: 4

Views: 4009

Answers (4)

Roddy
Roddy

Reputation: 68053

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;
    }
}

Upvotes: 3

Larry Osterman
Larry Osterman

Reputation: 16142

DavidK's right. Please see the comment in the ZwQueryInformationProcess documentation:

[ZwQueryInformationProcess may be altered or unavailable in future versions of Windows. Applications should use the alternate functions listed in this topic.]

That means that Microsoft can choose to remove this at any time in the future, thus breaking your application. I strongly consider you follow DavidK's advice and use ZwQueryInformationProcess on OS's that don't support GetProcessID and use GetProcessID on OS's that support it (XP SP1 and above).

Upvotes: 4

kilo
kilo

Reputation:

No, it's not ZwQueryInformationProcess() It's NtQIP and of course it works for all versions since NT 3.5 and you don't need to test OS at all

Upvotes: -1

user31394
user31394

Reputation:

There is an 'sort-of-unsupported' function: ZwQueryInformationProcess(): see

http://msdn.microsoft.com/en-us/library/ms687420.aspx

This will give you the process id (amongst other things), given the handle. This isn't guaranteed to work with future Windows versions, so I'd suggest having a helper function that tests the OS version and then uses GetProcAddress() to call either GetProcessId() for XP and above, and ZwQueryInformationProcess() for Win2K only.

Upvotes: 6

Related Questions