进程/线程的身份识别(《WINDOWS核心编程》笔记一)
一般来说,我们都会使用GetCurrentProcess()或GetCurrentThread()函数来获取一个进程句柄或是线程句柄。但是值得注意的是函数返回的只是其内核对象的一个伪句柄。而在使用这个伪句柄的时候,有些情况会无法得到我们想要的效果。例如:
父线程传递自己的句柄给子线程,子线程在线程处理函数中获取父线程的CPU使用时间。但是这个意图不能实现,原因就在于,传递的是一个父线程的伪句柄,导致获得是子线程自己的CPU使用时间。Code
伪句柄的定义:一个指向当前线程/进程的句柄。
上面的例子中,当前的线程是子线程,所以传递的伪句柄便是子线程的句柄。解决的方法,需要灵活使用DuplicateHandle函数,将一个伪句柄转换为真正的句柄。
1BOOL DuplicateHandle(
2 HANDLE hSourceProcess,
3 HANDLE hSource,
4 HANDLE hTargetProcess,
5 PHANDLE phTarget,
6 DWORD dwDesiredAccess,
7 BOOL bInheritHandle,
8 DWORD dwOptions);
DuplicateHandle函数本意是跨进程边界共享内核对象,复制对象的句柄。它的第一个与第三个参数必须是进程内核对象句柄;第二个参数可以是任意类型的内核对象句柄,但是不能与此函数的主调进程句柄相关;第四个参数就是复制得到的句柄地址,从类型上可以看出他是指向内核对象句柄的句柄;最后三个参数这里不赘述,对这个问题影响不大。2 HANDLE hSourceProcess,
3 HANDLE hSource,
4 HANDLE hTargetProcess,
5 PHANDLE phTarget,
6 DWORD dwDesiredAccess,
7 BOOL bInheritHandle,
8 DWORD dwOptions);
Code
因为DuplicateHandle递增了内核对象的使用计数,所以在复制的对象句柄用完后必须调用CloseHandle()函数,递减内核对象的使用技术。这里补充的是,CloseHandle()接受的句柄参数也必须是真正的句柄,如果传递的是伪句柄,则返回FALSE同时GetLastError()将返回ERROR_INVALID_HANDLE。