WinapiZone.net




Tutorials > WinAPI > Process

Process "translation"

Here are some neat things to do with processes handles, process ids and window handles.

From process id to process handle

This is quite easy: through the OpenProcess API we can obtain a local copy of the handle to the process. Just remember to close it using CloseHandle:
//With PROCESS_ALL_ACCESS you get all the rights you need.
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
CloseHandle(processHandle);

From window handle to process id

Also this is easy, the GetWindowThreadProcessId API is what we need here:
DWORD processId = 0;
GetWindowThreadProcessId(windowHandle, &processId);

From process handle to process id

This can be done easily through the GetProcessId function:
HANDLE processHandle = //processHandle must have the PROCESS_QUERY_INFORMATION access right
DWORD processId = GetProcessId(processHandle);
Unfortunately, this function is available only under Windows XP.
There's another way that only requires Windows 2000 and superior, using GetCurrentProcessId (requires Windows 95) and CreateRemoteThread (requires Windows 2000):
HANDLE processHandle = //processHandle must have the PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ access rights

//Start the remote thread with GetCurrentProcessId as thread routine
HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, GetCurrentProcessId, 0, NULL);

//Wait till the thread exits
WaitForSingleObject(remoteThread, INFINITE);

//Get the exit code of the remote thread, that is the process id
DWORD processId = 0;
GetExitCodeThread(remoteThread, &processId);

CloseHandle(remoteThread);
Basically, we inject a call to the GetCurrentProcessId function in the process space though CreateRemoteThread, and get the thread's exit code, that is the exit code of the thread routine, which is GetCurrentProcessId(). Got it? :)

From process id to process executable path

There's an API that can make this procedure easy: GetModuleFileNameEx:
//As from "From process id to process handle"
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);

TCHAR exePath[MAX_PATH] = _T("");
GetModuleFileNameEx(processHandle, NULL, exePath, MAX_PATH);

CloseHandle(processHandle);
To use GetModuleFileNameEx, you must link against psapi.lib / libpsapi.a.
But again, this function is available only under Windows XP.

Using the toolhelp library there's a solution for all Windows' version. But, the procedure to get the window handle from the process id is different between Windows XP and older versions of Windows.

Windows XP
// Take a snapshot of the modules of this process
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID);

//Get the first module
MODULEENTRY32 me = {0};
me.dwSize = sizeof(MODULEENTRY32);
Module32First(moduleSnapshot, &me);

//The path is in me.szExePath!

CloseHandle(moduleSnapshot);
The obviously thing to do would be enumerate all the processes and compare them to our process id until we find it. But, under Windows XP, the PROCESSENTRY32 structure doesn't set the full path of the executable of the process, just the executable's file name. Instead, the first module of each process has it. So we
  1. Enumerate all the modules in the process using CreateToolhelp32Snapshot and TH32CS_SNAPMODULE.
  2. Get the info of the first module using Module32First and the MODULEENTRY32 structure
  3. The function will copy in the MODULEENTRY32 structure's member variable szExePath the full path of the executable

Windows versions inferior to XP
// Take a snapshot of all the processes HANDLE processSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //Find the process that has the same id of the window PROCESSENTRY32 pe = {0}; pe.dwSize = sizeof(PROCESSENTRY32); if (Process32First(processSnapshot, &pe)) { do { if (pe.th32ProcessID == processID) { //We found our process //The path is in pe.szExeFile! break; } } while(Process32Next(processSnapshot, &pe)); } CloseHandle(processSnapshot);
Under windows 9x/ME, the PROCESSENTRY32 has already the full path to the executable (which is stored in the PROCESSENTRY32 structure's member variable szExeFile). I only need to loop through the open processes to find the right process.

To use the toolhelp library, remember to include the header tlhelp32.h.

From process id to window handle

Using EnumWindows we can enumerate all top windows and use GetWindowThreadProcessId on each of them, until we find the correct window:
typedef struct { DWORD processId; HANDLE windowHandle; } PIDTOHWND; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { PIDTOHWND pth = (PIDTOHWND)lParam; DWORD windowProcessId = 0; GetWindowThreadProcessId(hwnd, windowProcessId); if (pth->processId == windowProcessId) { pth->windowHandle = hwnd; return FALSE; } return TRUE; } PIDTOHWND pth = {processId, NULL}; EnumWindows(EnumWindowsProc, pth); //pth->windowHandle now contains the window handle

Comments

Paul Sanders wrote:

This is truly terrific. Thans very much for posting.

Regards,

Paul Sanders
http://www.alpinesoft.co.uk
(06.09.2008, 22:11)

NickM wrote:

Great information, many thanks :-)
(29.07.2008, 21:57)

Your comment:

Name:
E-mail or homepage:
Captcha:
captcha

Script by Alex



This page was last modified 34 months, 4 weeks and 21 hours ago