Retrieving the parent of a process (WinNT)

Did you ever have to find out parent of a process? Well, if so, you'll already have found out that there is no documented relation between processes in Win32 (like there is on UN*X). But, fortunately, the emphasis is on 'documented', as the NT Native API offers LOTS of undocumented APIs that can be useful in a variety of situations. Prototypes and parameter information for about 25 NT API functions can be found in the header files of the NT DDK. The function that serves the basic purpose of this article is 'NtQueryInformationProcess()' and is declared as follows:

NTSYSAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
    IN HANDLE ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN ULONG ProcessInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );
When specifying 'ProcessBasicInformation' as the 'ProcessInformationClass' parameter and a valid process handle, 'NtQueryInformationProcess()' fills in a 'PROCESS_BASIC_INFORMATION' structure whose adress has been passed in as the 'ProcessInformation' parameter. The structure member 'InheritedFromUniqueProcessId' holds the process ID of the process that created process specified in 'ProcessHandle'. So, all that has to be done is obtaining a pointer to this function and calling it, supplying the appropriate parameters:


DWORD   GetParentProcessID  (   DWORD   dwPID)
{
    NTSTATUS                        ntStatus;
    DWORD                           dwParentPID =   0xffffffff;

    HANDLE                          hProcess;
    PROCESS_BASIC_INFORMATION       pbi;
    ULONG                           ulRetLen;

    //  create entry point for 'NtQueryInformationProcess()'
    CREATE_DYNFUNC_5    (   NtQueryInformationProcess,
                            NtQueryInformationProcess,
                            ntdll,
                            NTSTATUS,
                            __stdcall,
                            HANDLE,
                            PROCESSINFOCLASS,
                            PVOID,
                            ULONG,
                            PULONG
                        );

    //  get process handle
    hProcess    =   OpenProcess (   PROCESS_QUERY_INFORMATION,
                                    FALSE,
                                    dwPID
                                );

    //  could fail due to invalid PID or insufficiant privileges
    if  (   !hProcess)
            return  (   0xffffffff);

    //  gather information
    ntStatus    =   NtQueryInformationProcess   (   hProcess,
                                                    ProcessBasicInformation,
                                                    ( void*) &pbi,
                                                    sizeof  (   PROCESS_BASIC_INFORMATION),
                                                    &ulRetLen
                                                );

    //  copy PID on success
    if  (   !ntStatus)
            dwParentPID =   pbi.InheritedFromUniqueProcessId;

    CloseHandle (   hProcess);

    return  (   dwParentPID);
}


The only 'fancy' thing in the above code is the 'CREATE_DYNFUNC_5()' convenience macro, which just simplifies the method of typedef'ing a function pointer and loading it by serving as a 'wrapper' ('5' indicates that a pointer to a function taking 5 parameters is created):

#define DYNLOADED_FPTR( ptrname, procname, dllname)\
FPTR_##procname ptrname = \
( FPTR_##procname ) GetProcAddress ( GetModuleHandle (  _TEXT( #dllname)), #procname);

#define CREATE_DYNFUNC_5( ptrname, procname, dllname, rettype, callconv, a1, a2, a3, a4, a5)\
typedef  rettype (callconv *FPTR_##procname) ( a1, a2, a3, a4, a5);\
DYNLOADED_FPTR( ptrname, procname, dllname);
which (in our example) expands to

typedef NTSTATUS (__stdcall *FPTR_NtQueryInformationProcess) ( HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
FPTR_NtQueryInformationProcess NtQueryInformationProcess = ( FPTR_NtQueryInformationProcess ) GetProcAddress ( GetModuleHandleA ( "ntdll"), "NtQueryInformationProcess");
NOTE that this may fail if the DLL isn't loaded when the above code is executed! ('ntdll.dll' is loaded for every process running on NT, so this isn't checked here)

Download demo executable - 12.6 KB

Download source - 2.03 KB



Comments

  • Command line tool -> getpids

    Posted by xca1019 on 08/12/2007 06:25pm

    Hi, if you are happen write batch files or similar, you can use the getpids tool [1] for retrieving those process ID, parent process ID etc. information. It's output very easy to parse too. [1] http://www.scheibli.com/projects/getpids/index.html

    Reply
  • To get Parent PID?

    Posted by Legacy on 02/07/2004 12:00am

    Originally posted by: ScratXP

    You do not need to go as far as Nt* APIs to get something as trivial as the Parent PID. While these APIs could be used to find more advanced features, this article does not go into any details and simply shows a useless function of the API.
    Please look at the following APIs:

    CreateToolhelp32Snapshot()
    Process32First()

    These are supported on all platforms.

    Reply
  • Unsupported

    Posted by Legacy on 09/14/2000 12:00am

    Originally posted by: Michael Quinn

    This is really cool stuff, but it's important to be aware of the following (snipped from the MSDN online help)

    >>>
    Before I proceed, I’m obligated to point out that NtQueryInformationProcess isn’t part of the Win32 API. Microsoft could change or remove this API in the future. Likewise, this API isn’t available on Windows 95, so be aware of what you’re getting into if you want to use it.
    <<<

    Reply
  • Parent Process Info -> stdout

    Posted by Legacy on 07/06/1999 12:00am

    Originally posted by: Hakan Erduman

    ( Cool, if MS does not change these undefined structures 
    
    and procedures )


    But: Can one possibly use these structs to get
    the parents's standard output / input handles
    (these are not inherited if a console app starts
    a GUI app)

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Hybrid cloud platforms need to think in terms of sweet spots when it comes to application platform interface (API) integration. Cloud Velocity has taken a unique approach to tight integration with the API sweet spot; enough to support the agility of physical and virtual apps, including multi-tier environments and databases, while reducing capital and operating costs. Read this case study to learn how a global-level Fortune 1000 company was able to deploy an entire 6+ TB Oracle eCommerce stack in Amazon Web …

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today makes data protection a must-have, as we live in a data-driven society -- the digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join Seagate Cloud …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds