Anne Quinn
Anne Quinn

Reputation: 12992

How to give a program's Handle to a process it created?

I have two programs, Parent and Kid

I want Kid to get the Handle of Parent after Parent creates Kid using CreateProcess. The easiest way to transmit this handle seems to be by putting the Handle in the commandline arguments of CreateProcess, but there is no way I can see to get the Parent's Handle inside Parent. GetCurrentProcess returns a weird non-value, and DuplicateHandle doesn't work without having the Kid's Handle (Impossible, since I need to create the Kid to get a Handle to it, but CreateProcess is also the only chance to send the Parent's Handle to the Kid).

Is there any way I can give Kid it's Parent's Handle easily?

Upvotes: 1

Views: 1502

Answers (3)

ash
ash

Reputation: 5155

Try getting the parent PID from its own process handle:

DWORD pid = GetProcessId(Parent);

Then in the child, given the pid, get the handle back:

OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);

The PID can easily be passed around since its a number.

See the following for more details:

Upvotes: 1

RbMm
RbMm

Reputation: 33706

first of all we need get process id of parent process in Kid. this can be done by call NtQueryInformationProcess with ProcessBasicInformation. and inside PROCESS_BASIC_INFORMATION (this structure declared in ntddk.h ) exist InheritedFromUniqueProcessId member. strictly say this is can be not parent process id in case you use PROC_THREAD_ATTRIBUTE_PARENT_PROCESS when create Kid, but if you not use this attribute when call CreateProcess - the InheritedFromUniqueProcessId - this will be your parent process id.

than we need understand, that parent can terminated and after this new process start with the same id. so after we open process with InheritedFromUniqueProcessId we need check that this is really parent, but not new process, created after parent exit and reusing this id. this can be done by query process start time - obviously if this not parent process it started already after parent exit (before this id can not be reused), and parent exit after he start kid. so InheritedFromUniqueProcessId can be not parent only in case it create time >= kid create time. we can query process create time by ProcessTimes with NtQueryInformationProcess. so final code can be:

NTSTATUS OpenParent(PHANDLE phProcess, ULONG DesiredAccess)
{
    HANDLE hProcess;
    KERNEL_USER_TIMES kut, _kut;
    PROCESS_BASIC_INFORMATION pbi;

    NTSTATUS status;

    if (0 <= (status = NtQueryInformationProcess(
        NtCurrentProcess(), ProcessBasicInformation, 
        &pbi, sizeof(pbi), 0)) && 
        0 <= (status = NtQueryInformationProcess(
        NtCurrentProcess(), ProcessTimes, 
        &kut, sizeof(kut), 0)))
    {

        static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
        CLIENT_ID cid = { (HANDLE)pbi.InheritedFromUniqueProcessId };
        if (0 <= (status = NtOpenProcess(&hProcess, DesiredAccess|
            PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &cid)))
        {

            if (0 > (status = NtQueryInformationProcess(
                hProcess, ProcessTimes, &_kut, sizeof(_kut), 0)) || 
                kut.CreateTime.QuadPart <= _kut.CreateTime.QuadPart)
            {
                NtClose(hProcess);
                return STATUS_PROCESS_IS_TERMINATING;
            }

            *phProcess = hProcess;
        }
    }

    return status;
}

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 595392

The easiest way to transmit this handle seems to be by putting the Handle in the commandline arguments of CreateProcess

That is one way to do it, but it is not the only way.

Another simple way is to have Parent send its process ID from GetCurrentProcessId() to Kid, and then Kid can use OpenProcess() to get a handle to Parent.

there is no way I can see to get the Parent's Handle inside Parent.

GetCurrentProcess(), which returns a pseudo-handle representing the calling process. All APIs that accept a process handle will accept this pseudo-handle when used in the context of the calling process.

But, for purposes of passing the calling process's handle to another process, Parent would have to use DuplicateHandle() to convert the pseudo-handle into a real handle (set Parent as both source and target process). This is documented behavior.

GetCurrentProcess returns a weird non-value, and DuplicateHandle doesn't work without having the Kid's Handle

After Parent has duplicated the pseudo-handle from GetProcessHandle() into a real handle, it can then pass that duplicate to Kid on the command line. Just make sure the duplicate is inheritable, and then use bInheritHandles=TRUE in the CreateProcess() call, or pass a STARTUPINFOEX to CreateProcess() containing a PROC_THREAD_ATTRIBUTE_HANDLE_LIST (see Programmatically controlling which handles are inherited by new processes in Win32).

Impossible, since I need to create the Kid to get a Handle to it

If you don't want to use inheritable handles, then Parent can alternatively create Kid without passing any handle on the command line, then duplicate the GetCurrentProcess() pseudo-handle with Kid as the target process, then use an IPC mechanism of your choosing to send the duplicate to Kid after it is already running.

but CreateProcess is also the only chance to send the Parent's Handle to the Kid

No, it is not the only way. IPC is another way.

Upvotes: 3

Related Questions