BOOL DuplicateHandle( HANDLE hSourceProcessHandle, // handle to the source process HANDLE hSourceHandle, // handle to duplicate HANDLE hTargetProcessHandle, // handle to process to duplicate to LPHANDLE lpTargetHandle, // pointer to duplicate handle DWORD dwDesiredAccess, // access for duplicate handle
BOOL bInheritHandle, // handle inheritance flag
DWORD dwOptions // optional actions );
在系统中,对象分两类:核心对象和用户对象.如进程对象,线程对象,文件映射对象等就是核心对象;而向窗口,菜单等都是用户对象. 两者是有差别的,用于标示用户对象的句柄是系统唯一的,也就是说,一个进程完全可以对另外一个进程中的用户对象进行操作,比如两个进程间通信的方法之一, 就是发送消息.正是由于窗口是用户对象,所以句柄是系统唯一,通过FindWindow(), 得到另外一个进程的窗口句柄,然后用SendMessage(),让hWnd的窗口过程来处理消息,实现了进程间的通信.因此,对于用户对象,你根本不用DuplicateHandle(),直接把句柄拿来用就行了. 而核心对象则不一样.核心对象是为了加强系统的稳定性,因此,核心对象句柄是进程相关的,在每一个进程中都有一个核心对象表,每一个对象的索引(不完全是)作为内和对象的句柄,从而实现进程相关.同一个对象在不同的进程中可能有不同的索引,即句柄.对核心对象进行操作时,系统还要进行安全检验,看一下你是否有权来操作这个对象.因此你不能同用户对象一样,直接把句柄拿过来用.比方说,你想操作另一个进程中的文件映射对象,这个文件映射对象句柄在那个进程中假设是0x000001,但在你的进程中,很有可能0x00000001时表示另一个核心对象,此时的操作就永远不会成功,甚至会产生灾难性的后果.此时,就有必要用DuplicateHandle(). DuplicateHandle(),要涉及到三个进程,(一般很少有这种情况,最多的是两个进程). 第一个是你调用DuplicateHandle()函数的线程.第二个是你的源进程,第三个是目的进程. hSourceHandle,是你要复制的核心对象句柄.调用这个函数后,系统将检索对象名空间, 找到内核对象,增加计数,然后在你的目的进程中的核心对象表中,为这个对象分配一个索引,这个索引作为目的进程中该内核对象的句柄.然后你还要通知(发消息)目的进程说 "喂,你现在可以用这个核心对象了",目的进程才可以操作该对象.
一句话,用于复制进程或线程句柄
dwDesiredAccess:TargetHandle句柄使用何种访问掩码(这个掩码是在句柄表中的一项)
bInheritHandle:是否拥有继承
dwOptions:当设DUPLICATE_SAME_ACCESS时,表示于源的内核对象所有标志一样,此时wDesiredAccess可标志为0 当设DUPLICATE_CLOSE_SOURCE时,传输完后,关闭源中的内核对象句柄 此函数能否成功调用还要看你是否有足够的权限去操作目标进程
通常目标进程的内核句柄是利用OpenProcess()得到的
HANDLE WINAPI OpenProcess( __in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in DWORD dwProcessId );
dwDesiredAccess:决定你拥有该进程的操作权限,如果要成功用到则要填PROCESS_ALL_ACCESS或PROCESS_DUP_HANDLE
bInheritHandle:是否可继承
dwProcessId:这个ID可在资源管理器中找到, 若DuplicateHandle()能成功执行,则利用进程通信把句柄值TargetHandle传给目标进程,让他知道利用该句柄使用内核对象 注意:不要试图在源进程中利用CloseHandle()关闭TargetHandle,因为这个TargetHandle句柄值并不属于源进程的句柄表中的,若错误关闭了,会产生不可预料的结果 好了,只要依照上面的做法,基本是可以正确用到DuplicateHandle()函数的 但很多人都不知道为何要用复制句柄函数,我利用进程间通信把句柄传给目标进程不就行了吗? 这样的想法就大错特错了,我们表面上是在复制句柄值,实际上是把该句柄在源进程句柄表中的所有项复制到目标进程的句柄表中,而且使该内核对象的计数器+1了,如果只是简单的只传句柄值,目标进程的句柄表中是不会有所增加的 顺便一提,句柄表是各进程用来记录该进程的内核对象的.