Unsure about PsLookupProcessByProcessId

Hello everybody,

I have two questions, one about the way process Ids are declared in windows and the other is about the PsLookupProcessByProcessId function doing something that I don’t expect.

About process IDs, it confuses me that sometimes a process ID is declared as a DWORD(like in the EPROCESS structure) and other times it is declared as a HANDLE(e.g. when passing it to the PsLookupProcessByProcessId function). Maybe this is a silly question but why is this mixed? We can just cast the HANDLE to a DWORD to obtain the numeric value of the ID, so actually my question comes down to:
If I want to store the process ID of some process that I opened, what is the most logical way to declare it, as DWORD or as HANDLE.

Secondly, the PsLookupProcessByProcessId function. I’ve defined it as following:
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId( IN HANDLE ProcessId, OUT PEPROCESS *Process );

And I call it:

if( ! NT_SUCCESS( PsLookupProcessByProcessId( gClientInfo.hProcessId, &pEProcess ) ) )
DbgPrint( “PsLookupProcessByProcessId unsuccessful” );

With:
PEPROCESS pEProcess = NULL;
HANDLE hProcessId; // (In a structure)

If after the function call I print hProcessId and pEProcess->UniqueProcessId I get two different numeric values.

I am guessing that something in the PsLookupProcessByProcessId goes wrong so the EPROCESS is filled with garbage data, that I am casting to a DWORD when printing.
If this is the case, how can I check if the EPROCESS structure is filled correctly?

While writing this I actually got two another questions:

  • What is the ‘standard’ way to check a buffer before accessing it.
    For example before I call RtlCopyMemory I should check if the address is valid, if I have access to perform the operation on it(check if page_fault will occur). I’ve read about a function that could check if a page fault will occur on a given address, I actually forgot the function name because I read it shouldn’t be used.
    There will be a difference for UM or KM buffers I suppose, is ‘probeforread / write’ in a try/catch sufficient for UM buffers?

  • When I read on OSR some information about certain bugchecks I noted a line saying: “This cannot be protected by try/catch it must be protected by Probe” (not an exact quote). I’ve tried to google for Probe in the contect of driver development but it’s quite a general word, could someone point me in the direction where to find more information about this?

Thank you all in advance for any help.

xxxxx@gmail.com wrote:

About process IDs, it confuses me that sometimes a process ID is declared as a DWORD(like in the EPROCESS structure) and other times it is declared as a HANDLE(e.g. when passing it to the PsLookupProcessByProcessId function). Maybe this is a silly question but why is this mixed? We can just cast the HANDLE to a DWORD to obtain the numeric value of the ID, so actually my question comes down to:
If I want to store the process ID of some process that I opened, what is the most logical way to declare it, as DWORD or as HANDLE.

This is largely a user/kernel distinction. In user mode, the process
HANDLE is local to a process, and can be used to take action on the
process. A process can have several handles. A process ID is an
integer, unique system-wide (although not unique in time). Basically,
all you can do with a process ID is fetch a handle from it (using
OpenProcess).

In kernel mode, the system-wide process ID is typed as a HANDLE. The
information that the user-mode HANDLE points to is basically a pointer
to the EPROCESS structure for the process.

So, in user mode, define your process IDs as DWORD. In kernel mode,
define them as HANDLE.

If after the function call I print hProcessId and pEProcess->UniqueProcessId I get two different numeric values.

Process IDs are multiples of 8. Are both of your numbers multiples of 8?

  • What is the ‘standard’ way to check a buffer before accessing it.
    For example before I call RtlCopyMemory I should check if the address is valid, if I have access to perform the operation on it(check if page_fault will occur). I’ve read about a function that could check if a page fault will occur on a given address, I actually forgot the function name because I read it shouldn’t be used.
    There will be a difference for UM or KM buffers I suppose, is ‘probeforread / write’ in a try/catch sufficient for UM buffers?

Kernel code is trusted code. For the most part, any addresses you get
from another kernel component are assumed to be valid. If they should
happen to be bad, you get a blue screen.

For user mode buffers, you shouldn’t find yourself in a situation where
you need to do that validation. By using buffered or direct I/O, the
I/O system will do this validation for you. When you need to do so,
yes, the ProbeFor* interfaces are the right way.

  • When I read on OSR some information about certain bugchecks I noted a line saying: “This cannot be protected by try/catch it must be protected by Probe” (not an exact quote). I’ve tried to google for Probe in the contect of driver development but it’s quite a general word, could someone point me in the direction where to find more information about this?

You already said it: ProbeForRead, ProbeForWrite.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Two corrections/additions:

  1. The OP is, I believe, referring to how most of NT refers to client IDs as HANDLE and not ULONG/DWORD while Win32 refers to these as DWORD. They’re the same value under the hood. I’d prototype these as HANDLE in kernel mode code as my belief is that that’s closer to the real intent, although with Win32 code assuming just 32 significant bits this is in practical terms probably going to be difficult to change.

  2. Process IDs provide no guarantees that they’ll be multiples of 4 (not 8!) as they are in today’s implementation. This is not an interface contract and you shouldn’t treat it as one. It just happens this way as the CID table of today uses the EXHANDLE package for its internal implementation.

This was not always the case (wasn’t so on nt4 IIRC) and unless it becomes documented to remain that way, you can’t rely on it from a coding standpoint (beyond debugging).

  • S

-----Original Message-----
From: Tim Roberts
Sent: Thursday, July 23, 2009 14:16
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Unsure about PsLookupProcessByProcessId

xxxxx@gmail.com wrote:
> About process IDs, it confuses me that sometimes a process ID is declared as a DWORD(like in the EPROCESS structure) and other times it is declared as a HANDLE(e.g. when passing it to the PsLookupProcessByProcessId function). Maybe this is a silly question but why is this mixed? We can just cast the HANDLE to a DWORD to obtain the numeric value of the ID, so actually my question comes down to:
> If I want to store the process ID of some process that I opened, what is the most logical way to declare it, as DWORD or as HANDLE.
>

This is largely a user/kernel distinction. In user mode, the process
HANDLE is local to a process, and can be used to take action on the
process. A process can have several handles. A process ID is an
integer, unique system-wide (although not unique in time). Basically,
all you can do with a process ID is fetch a handle from it (using
OpenProcess).

In kernel mode, the system-wide process ID is typed as a HANDLE. The
information that the user-mode HANDLE points to is basically a pointer
to the EPROCESS structure for the process.

So, in user mode, define your process IDs as DWORD. In kernel mode,
define them as HANDLE.

> If after the function call I print hProcessId and pEProcess->UniqueProcessId I get two different numeric values.
>

Process IDs are multiples of 8. Are both of your numbers multiples of 8?

> - What is the ‘standard’ way to check a buffer before accessing it.
> For example before I call RtlCopyMemory I should check if the address is valid, if I have access to perform the operation on it(check if page_fault will occur). I’ve read about a function that could check if a page fault will occur on a given address, I actually forgot the function name because I read it shouldn’t be used.
> There will be a difference for UM or KM buffers I suppose, is ‘probeforread / write’ in a try/catch sufficient for UM buffers?
>

Kernel code is trusted code. For the most part, any addresses you get
from another kernel component are assumed to be valid. If they should
happen to be bad, you get a blue screen.

For user mode buffers, you shouldn’t find yourself in a situation where
you need to do that validation. By using buffered or direct I/O, the
I/O system will do this validation for you. When you need to do so,
yes, the ProbeFor* interfaces are the right way.

> - When I read on OSR some information about certain bugchecks I noted a line saying: “This cannot be protected by try/catch it must be protected by Probe” (not an exact quote). I’ve tried to google for Probe in the contect of driver development but it’s quite a general word, could someone point me in the direction where to find more information about this?
>

You already said it: ProbeForRead, ProbeForWrite.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Email secured by Check Point at OSR.COM

> About process IDs, it confuses me that sometimes a process ID is declared as a DWORD(like in the

EPROCESS structure) and other times it is declared as a HANDLE(e.g. when passing it to the
PsLookupProcessByProcessId function). Maybe this is a silly question but why is this mixed?

Just truncate the lower 32 bits of HANDLE.

Secondly, the PsLookupProcessByProcessId function.

How great. WDK docs now document this function. It was not so some time ago.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com