参考:
1. http://www.cnblogs.com/Kernone/archive/2009/08/18/1549286.html
2. http://blog.sina.com.cn/s/blog_4b226b9201011bu6.html
在使用很多函数的时候,我们都需要获得一个对象的句柄,而某些函数,如GetCurrentProcess() / GetCurrentThread() 返回的是伪句柄 pseudohandle。
所谓伪句柄,即指向当前线程或者进程的句柄,并不是真正意义上的句柄。它并不创建句柄,同时也不增加引用计数,因次调用CloseHandle()不作任何处理。
它本身就只指向调用它的主调进程或线程。会因为调用者的不同而改变,比如:调用者A使用一个伪句柄,这个句柄指向调用者A,而调用者A将该句柄传递给调用者X,则这个句柄就指向调用者X。
进程的伪句柄总是0xffffffff,而线程的伪句柄总是0xfffffffe。
通过使用DuplicateHandle这个强大的函数,可以将伪句柄转换为真正的句柄。
函数原型:
BOOL DuplicateHandle( HANDLE hSourceProcessHandle, // handle to source process HANDLE hSourceHandle, // handle to duplicate HANDLE hTargetProcessHandle, // handle to target process LPHANDLE lpTargetHandle, // duplicate handle DWORD dwDesiredAccess, // requested access BOOL bInheritHandle, // handle inheritance option DWORD dwOptions // optional actions );参数:
1> hSourceProcessHandle:拥有待复制HANDLE的进程句柄;
2> hSourceHandle:待复制的HANDLE;
3> hTargetProcessHandle:接收复制后HANDLE的进程句柄;
4> lpTargetHandle:指向 存储复制后HANDLE的 地址;如果取值为NULL,函数复制句柄,但不会返回复制后的句柄
5> dwDesiredAccess:指明对新HANDLE的访问权限;
6> bInheritHandle:指明新HANDLE是否可被继承;
7> dwOptions:指明可选的行为;可以取值为0,也可以取如下值的任意结合:
DUPLICATE_CLOSE_SOURCE:关闭掉原HANDLE;
DUPLICATE_SAME_ACCESS:忽略dwDesiredAccess指明的对新HANDLE的访问权限;新句柄具有同原句柄相同的访问权限;
返回值:
如果成功,返回非零值,即TRUE;
如果失败,返回0,即FALSE;(可以调用GetLastError()获取详细错误信息)
注意:
1. 原句柄和复制后的句柄是类似引用的关系,两者指向同一内核对象,对原句柄或复制后的句柄,其中任何一个的改变,都会导致另外一个的改变;
2. DuplicateHandle()会递增特定对象的使用计数,因此当完成对复制对象句柄的使用时,应该调用CloseHandle()关闭句柄,从而递减对象的使用计数;
3. lpTargetHandle所指向的句柄跟CreateThread()时创建的句柄不一定相同;
示例:
HANDLE hPseudoThread=GetCurrentThread();
HANDLE hProcess=GetCurrentProcess();
HANDLE hRealThread=NULL;
DuplicateHandle(hProcess, hPseudoThread, hProcess, &hRealThread, 0, false, 0);
调试内容:
hPseudoThread 0xfffffffe void *
hProcess 0xffffffff void *
hRealThread 0x00000ed8 void *