We help IT Professionals succeed at work.

Get process/thread ID from handle...

Madshi asked
Last Modified: 2013-12-03
Is there an easy way to get the process ID from a process handle (and the thread ID from a thread handle)?
(In the moment I use the toolhelp functions (win95) respectively enumProcesses (winNT) to do this task. But it's quite fussy...)

Thanx for your help.

Watch Question



wow, that's complicated...
But - sorry - for me there remain some questions.   :-)

First, some basic questions:
(1) I don't write vxds. So I deal only with Ring3 identifiers?
(2) What is the magic value?
(3) You enumerated all identifiers the system works with (pid3,tid3,pid0,tid0,th0).
    What is with the other identifiers (ph3,th3,ph0)?
(4) You mentioned something like "pid0=ph0". Is that really right?
    (You wrote: "This process Id is from the same type than the ones you obtain when
     you call VWin32_GetCurrentProcessHandle().)
(5) You wrote that the 50h offset conversations work only when the th0 is owned by the System VM.
    Does that mean, I can't use this conversation on my "normal" thread handles?

The conversations I understand:
(1) pid3 xor magic => pid0
(2) tid3 xor magic => tid0
(3) tid0 offset 8h => pid0
(4) th0  offset 8h => ph0
(5) th0  offset TCB offset 50h           => tid0
(6) th0  offset TCB offset 50h offset 4h => pid0
Are they right? (I hope you understand my shortcuts.)

Now the conversations you didn't describe yet (very important for me):
(1) ph3 => ph0
(2) th3 => th0
(3) ph0 => pid0

Thank you for your answer.

Regards, Madshi.

For calculating the magic number you should get a hold of the book by Matt Pietrek:  Win95 rogramming secrets.  

Unlock this solution and get a sample of our free trial.
(No credit card required)



calling "CreateProcess" you get pid3,ph3,tid3 and th3. This would be all I need. Unfortunately I want to use "ShellExecuteEx", and that API returns only ph3.
But for several reasons I need the pid3 (e.g. enumerating all windows and test with "GetWindowThreadProcessID" if they belong to the process).
So how can I get the pid3 when I have only the ph3?
This is my main question.
By the way I would like to know how I can get the tid3 from the th3, too. But that is not so important.

However, I would be very happy if you would send me some sources about all this relationships... (Please send me vmm.h, too. Thanks!)

Thanx a lot, Madshi.    (eMail: Mathias.Rauen@gmx.de)


Thanks duneram, found some links on the site you mentioned. So now I have "magic" sources without that book. Nevertheless, that book looks interesting...

Regards, Madshi.

Below there's some code that solves your problem.
The module does the follow:

- First, call ShellExecuteEx() to execute CALC.EXE.
- This call returns the process handle on the hProcess member of SHELLEXECUTEINFO structure.
- This is a handle like you obtain when you open a file for read. It is an index to the Handle Table created by the system for the PH2PID process.
- Calling GetCurrentProcessId() obtains a ring3 process handle for PH2PID process. This isn't interesting.
- So, Applying the value to the magic number obtains the ring0
process handle, which is a pointer to an internal structure representing the process in the system.
- At offset 0x44 of this structure is the pointer to ring0 Handle Table belonging to the process.
- The hProcess member of the SHELLEXECUTEINFO structure is an index to the corresponding entry. The member pObject of this entry, is the ring0 handle, so we need to apply again the magic number to obtain the ring3 handle. Like this handle is a process, this is the same value tha would obtain if you could call GetCurrentProcessId() inside CALC.EXE.

Is a bit complicated, but is the only way I know to do what you want to do.

I hope this will help you.


//PH2PID  Ring3 process handle to Ring3 Process Id
#include <windows.h>
#include <shellapi.h>

typedef struct _HANDLE_TABLE_ENTRY
    DWORD   flags;
    DWORD   pObject;

typedef struct _HANDLE_TABLE
    DWORD   cEntries;
    HANDLE_TABLE_ENTRY array[1];

void InitMagic( void );

DWORD Magic = 0;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow )
HANDLE     hProcess;
DWORD      ProcessID;
char       Calculator[] = "CALC.EXE";
DWORD                          dw;       
PDWORD                pdw;
PHANDLE_TABLE         phTable;


      StInfo.cbSize = sizeof( SHELLEXECUTEINFO );
      StInfo.hwnd = 0;
      StInfo.lpVerb = 0;
      StInfo.lpFile = Calculator;
      StInfo.lpParameters = 0;
      StInfo.lpDirectory = 0;
      StInfo.nShow = SW_NORMAL;
      StInfo.lpIDList = 0;
      StInfo.lpClass = 0;
      StInfo.hkeyClass = 0;
      StInfo.dwHotKey = 0;
      StInfo.hIcon = NULL;
      StInfo.hProcess = NULL;
      if( ShellExecuteEx( &StInfo ) ) hProcess = StInfo.hProcess;
      else return -1;

/* Now StInfo.hProcess contains the index to the Handle Table
Array that belongs to the process (usually 0x00000002)*/

      ProcessID = GetCurrentProcessId(); /* Process Id of the calling process */

      dw = (DWORD)( ProcessID ^ Magic );
        pdw = (PDWORD)( dw + 0x44 ); /* Offset to the handle table that belongs to the calling process */
      phTable = (PHANDLE_TABLE)*pdw;
      hEntry = phTable->array;
      hEntry += (DWORD)hProcess; /* Index into the handle table /*
      ProcessID = ( (DWORD)hEntry->pObject ^ Magic );

/* Now ProceesID contains the ProccessId of CALC.EXE */

      return 0;

void InitMagic()
DWORD tid;

      tid = GetCurrentThreadId();

           push ax
           push es
           push fs
           mov  ax, fs
           mov  es, ax
           mov  eax, 18h
           mov  eax, es:[eax]
           sub  eax, 10h
           xor  eax, [tid]
           mov  [Magic], eax
           pop  fs
           pop  es
           pop  ax



it really works!   :-)
(I'm just wondering: Why is there no API for that?)

Thanx a lot, Madshi.

I think this one of the misterys about Microsoft.
I don't really understand why Microsoft doesn't provide an API to do that and many other things.

If you have any question about "under the hood" things, just write me to jmarcosf@cajamadrid.es


>> Thanks duneram, found some links on the site you mentioned. So now I have "magic" sources without that book.

Madshi, could you provide URLs for the info?  Thanx!


thanx for your email address. It's always great to have a competent "eMail friend".   :-))

look at "ftp://ftp.ora.com/pub/examples/windows/win95.update/dirty.html". It's an excerpt from the book duneram mentioned with two links to little source examples.

Regards, Madshi.

Thanx!  Will look...
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.