Windows API之DuplicateHandle

  在进程之间共享内核对象句柄的一种方法:DuplicateHandle
  简单地说,该函数取得某个进程句柄表中的一个表项,然后把它拷贝到另一个进程的句柄表中。    

  BOOL WINAPI DuplicateHandle(
    __in          HANDLE hSourceProcessHandle,
    __in          HANDLE hSourceHandle,
    __in          HANDLE hTargetProcessHandle,
    __out         LPHANDLE lpTargetHandle,
    __in          DWORD dwDesiredAccess,
    __in          BOOL bInheritHandle,
    __in          DWORD dwOptions
  );

  hSourceProcessHandle:源进程内核句柄(即负责传递内核对象句柄的进程句柄)
  hSourceHandle:要传递的内核对象句柄
  hTargetProcessHandle:目标进程内核句柄
  lpTargetHandle:接收内核对象句柄的地址(先随便声明一个HANDLE)
  dwDesiredAccess:TargetHandle句柄使用何种访问掩码(这个掩码是在句柄表中的一项)
  bInheritHandle:是否拥有继承
  dwOptions:当设DUPLICATE_SAME_ACCESS时,表示于源的内核对象所有标志一样,此时wDesiredAccess可标志为0 当设DUPLICATE_CLOSE_SOURCE时,传输完后,关闭源中的内核对象句柄
  此函数能否成功调用还要看你是否有足够的权限去操作目标进程
  通常目标进程的内核句柄是利用OpenProcess()得到的

  注意:不要试图在源进程中利用CloseHandle()关闭TargetHandle,因为这个TargetHandle句柄值并不属于源进程的句柄表中的,若错误关闭了,会产生不可预料的结果!
 

   不知道为何要用复制句柄函数,我利用进程间通信把句柄传给目标进程不就行了吗?
    这样的想法就大错特错了,我们表面上是在复制句柄值,实际上是把该句柄在源进程句柄表中的所有项复制到目标进程的句柄表中,而且使该内核对象的计数器+1了,如果只是简单的只传句柄值,目标进程的句柄表中是不会有所增加的。

  下面例子演示在ApiDuplicateHandleSource.exe中创建一个线程,将该线程句柄复制到ApiDuplicateHandle.exe中去,在进程ApiDuplicateHandle.exe中结束该线程。

// ApiDuplicateHandleSource.cpp
#include <iostream> #include <Windows.h> #include <process.h> #include <tchar.h> #include <TlHelp32.h> using namespace std; unsigned __stdcall thread (void * lpPragma); HANDLE GetProcessHandle(LPCTSTR szName); int main (void) { HANDLE hThread = NULL; hThread = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL); cout << "My thread handle is " << hThread << endl; HANDLE hTarget = NULL; BOOL bSucc = FALSE; //你是不是想说这里的hThread与调用DuplicateHandle相关? bSucc = DuplicateHandle (GetCurrentProcess(), //当前进程的源进程句柄 hThread, //当前进程中存在的线程资源句柄(内核对象) GetProcessHandle(_T("ApiDuplicateHandle.exe")), //目标进程的句柄 &hTarget, //要得到的目的句柄(Out) 0, //访问的方式 FALSE, //得到的句柄能不能被得到的其的进程的子进程继承 DUPLICATE_SAME_ACCESS ); //访问选项 if (bSucc) { cout << "句柄复制成功, 其句柄值为:" << hTarget << endl; } cin.get(); return 0; } unsigned __stdcall thread (void * lpPragma) { while (1) { Sleep (1000); cout << "Please terminal me!" << endl; } return 0; } HANDLE GetProcessHandle(LPCTSTR szName) { HANDLE hSanpshot = NULL; hSanpshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if ( INVALID_HANDLE_VALUE == hSanpshot ) { return NULL; } PROCESSENTRY32 pe; BOOL bOk = FALSE; pe.dwSize = sizeof(pe); bOk = Process32First (hSanpshot, &pe); if (!bOk) return NULL; do { if ( !_tcscmp (pe.szExeFile, szName) ) { return OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID); } bOk = Process32Next (hSanpshot, &pe); } while (bOk); return NULL; }
// ApiDuplicateHandle.cpp
#include <iostream> #include <Windows.h> #include <stdlib.h> #include <process.h> using namespace std; int main (void) { HANDLE hRecv = NULL; cout << "请输入复制过来的句柄 : " << endl; cin >> hRecv; TerminateThread(hRecv, 0); cin.get(); return 0; }

   参考

  http://www.cnblogs.com/staring-hxs/p/3576927.html

  http://blog.sina.com.cn/s/blog_4cfc933d0100rsrv.html

原文地址:https://www.cnblogs.com/MakeView660/p/7753516.html