Learn how to a build a cloud-first strategyRegister Now


Get process/thread ID from handle...

Posted on 1998-08-19
Medium Priority
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.

Question by:Madshi
  • 5
  • 4
  • 2
  • +1

Expert Comment

ID: 1413638
LVL 20

Author Comment

ID: 1413639

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.

Expert Comment

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

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.


Accepted Solution

cessi0g earned 680 total points
ID: 1413641

What do you mean with a Process Handle and Process ID.
Is the numberyou obtain with GetCurrentProcess() and GetCurrentProcessId()?

I don't know what you wanna do with this numbers.
If you let me know, I surely can help you.

Meanwhile, here you are some info that can help you.

At ring 3 Level (that is a normal Win32 App):
- A Process Handle is a pseudohandle that you can use in those funtcions that require it, like OpenProcess() an so on. This value isn't almost insteresting.
- A Process ID is a wrapping value of the real Process ID the system work with. This real value is maintained at Ring 0 Level (that is from system VxD's). This is really interesting because it points to an internal structure describing all information about the process.

To obtain this Ring 0 value, you must use the magic number and or'ed with the Ring 3 value.

The Thread related values are of the same kind but there's another value, the ring 0 thread handle, which point to another structure.

So, let me know exactly what you want to do, and I'll explain how all this values are related with a piece of source code.

One more thing, to work with all this values you not necesary need to write any VxD. Almost all the work can be done with a simple Win32 app.


LVL 20

Author Comment

ID: 1413642

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)
LVL 20

Author Comment

ID: 1413643
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.

Expert Comment

ID: 1413644
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

LVL 20

Author Comment

ID: 1413645

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

Thanx a lot, Madshi.

Expert Comment

ID: 1413646
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


LVL 11

Expert Comment

ID: 1413647
>> 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!
LVL 20

Author Comment

ID: 1413648
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.
LVL 11

Expert Comment

ID: 1413649
Thanx!  Will look...

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question