如何将程序的句柄赋予它创建的进程?

时间:2018-09-06 23:58:29

标签: c++ windows winapi

我有两个程序,ParentKid

我希望孩子在父母使用CreateProcess创建孩子之后得到孩子的父母的帮助。传递此句柄的最简单方法似乎是将Handle放在CreateProcess的命令行参数中,但是我看不到将Parent的Handle放入Parent的方法。 GetCurrentProcess返回一个奇怪的非值,并且DuplicateHandle在没有孩子的句柄的情况下不起作用(不可能,因为我需要创建孩子来获得它的句柄,但是CreateProcess也是将“父母之手”发送给孩子的唯一机会。

有什么办法可以使Kid容易处理吗?{p}?

3 个答案:

答案 0 :(得分:2)

  

传递此句柄的最简单方法似乎是将句柄放在CreateProcess的命令行参数中

这是一种方法,但这不是 only 方法。

另一种简单的方法是让Parent将其进程ID从GetCurrentProcessId()发送到Kid,然后Kid可以使用OpenProcess()来获取句柄Parent

  

我无法看到将“家长的句柄”放入“家长”内部。

GetCurrentProcess(),它返回代表调用过程的伪句柄。在调用进程的上下文中使用时,所有接受进程句柄的API都将接受此伪句柄。

但是,为了将调用进程的句柄传递到另一个进程,Parent必须使用DuplicateHandle()将伪句柄转换为真实句柄(将Parent设置为两个源和目标过程)。这是记录的行为。

  

GetCurrentProcess返回一个奇怪的非值,并且DuplicateHandle在没有儿童手柄的情况下不起作用

Parent将伪句柄从GetProcessHandle()复制到真实句柄之后,然后可以在命令行上将复制的副本传递给Kid。只要确保副本是可继承的,然后在bInheritHandles=TRUE调用中使用CreateProcess(),或将STARTUPINFOEX传递到包含CreateProcess()的{​​{1}}(请参阅{{ 3}})。

  

不可能,因为我需要创建一个Kid来处理它

如果您不想使用可继承的句柄,那么PROC_THREAD_ATTRIBUTE_HANDLE_LIST可以创建Parent而不在命令行上传递任何句柄,然后将Kid伪句柄复制为{ {1}}作为目标进程,然后使用您选择的IPC机制在副本已运行后将其发送到GetCurrentProcess()

  

但是Kid也是将父母的把柄传给孩子的唯一机会

不,这不是 only 方式。 IPC是另一种方式。

答案 1 :(得分:1)

尝试从其自己的进程句柄获取父PID:

DWORD pid = GetProcessId(Parent);

然后在给定pid的孩子中,取回手柄:

OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);

PID可以带数字,因此很容易传递。

有关更多详细信息,请参见以下内容:

答案 2 :(得分:0)

首先,我们需要获取Kid中父进程的进程ID。这可以通过与ProcessBasicInformation一起调用NtQueryInformationProcess来完成。在PROCESS_BASIC_INFORMATION内部(在 ntddk.h 中声明的此结构)内部存在InheritedFromUniqueProcessId成员。严格说来,如果您在创建Kid时使用PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,这可能不是父进程ID,但是如果您在调用CreateProcess-InheritedFromUniqueProcessId时不使用此属性,它将是您的父级进程ID。

我们需要理解的是,父级可以终止,并且在此新进程之后以相同的ID开始。因此,在使用InheritedFromUniqueProcessId打开进程之后,我们需要检查它是否确实是父进程,而不是在父进程退出并重新使用此ID之后创建的新进程。这可以通过查询进程的开始时间来完成-显然,如果不是父进程,它是在父退出后(无法重用此ID之前)已经启动的,并且在他启动Kid之后退出了。因此InheritedFromUniqueProcessId只能在创建时间> =孩子创建时间的情况下才能成为父项。我们可以使用ProcessTimes通过NtQueryInformationProcess查询流程创建时间。因此最终代码可以是:

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;
}