我有两个程序,Parent
和Kid
在父母使用CreateProcess
创建Kid之后,我希望Kid获得Parent的Handle。传递这个句柄的最简单方法似乎是将Handle放在CreateProcess
的命令行参数中,但是我无法看到在Parent中获取Parent的句柄。 GetCurrentProcess
返回一个奇怪的非价值,DuplicateHandle
没有孩子的手柄不能工作(不可能,因为我需要创建孩子来得到它的句柄,但CreateProcess
也是唯一的机会将父母的句柄发送到儿童)。
有什么方法我可以给Kid
它的Parent's
容易处理?
传递此句柄的最简单方法似乎是将Handle放在
CreateProcess
的命令行参数中
这是一种方法,但它不是唯一的方法。
另一个简单的方法是让Parent
将其进程ID从GetCurrentProcessId()
发送到Kid
,然后Kid
可以使用OpenProcess()
来获取Parent
的句柄。
我无法看到在父母内部获得父母的句柄。
GetCurrentProcess()
,返回表示调用进程的伪句柄。当在调用进程的上下文中使用时,所有接受进程句柄的API都将接受此伪句柄。
但是,为了将调用进程的句柄传递给另一个进程,Parent
必须使用DuplicateHandle()
将伪句柄转换为真正的句柄(将Parent
设置为源和目标进程)。这是记录在案的行为。
GetCurrentProcess
返回一个奇怪的非值,并且DuplicateHandle
在没有Kid's Handle的情况下不起作用
在Parent
将伪句柄从GetProcessHandle()
复制到真实句柄之后,它可以在命令行上将该副本传递给Kid
。只要确保副本是可继承的,然后在bInheritHandles=TRUE
调用中使用CreateProcess()
,或者将STARTUPINFOEX
传递给包含CreateProcess()
的PROC_THREAD_ATTRIBUTE_HANDLE_LIST
(请参阅Programmatically controlling which handles are inherited by new processes in Win32)。
不可能,因为我需要创建Kid来获得它的句柄
如果你不想使用可继承的句柄,那么Parent
也可以创建Kid
而不在命令行上传递任何句柄,然后用GetCurrentProcess()
作为目标进程复制Kid
伪句柄,然后使用你选择的IPC机制发送Kid
已经运行后的副本。
但
CreateProcess
也是将父母的手柄送给孩子的唯一机会
不,这不是唯一的方法。 IPC是另一种方式。
尝试从自己的进程句柄获取父PID:
DWORD pid = GetProcessId(Parent);
然后在孩子中,给予pid,拿回手柄:
OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
PID可以很容易地传递,因为它的数字。
有关详细信息,请参阅以下内容
首先,我们需要在Kid中获取父进程的进程ID。这可以通过与NtQueryInformationProcess
调用ProcessBasicInformation
来完成。在PROCESS_BASIC_INFORMATION
内部(这个结构在ntddk.h中声明)存在InheritedFromUniqueProcessId
成员。严格说这可能不是父进程id,以防你在创建Kid时使用PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
,但如果你在调用CreateProcess
时没有使用这个属性 - InheritedFromUniqueProcessId
- 这将是你的父进程id。
比我们需要了解的那样,父母可以终止并且在这个新进程之后以相同的id开始。所以在我们使用InheritedFromUniqueProcessId
打开进程之后,我们需要检查这是否真的是父进程,而不是新进程,在父进程后创建并重用此id。这可以通过查询进程开始时间来完成 - 显然如果这不是父进程,它在父进程之后已经启动(在此id之前无法重用),并且在他启动之后父进程退出。所以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;
}