伪句柄转换为真正的句柄
HANDLE GetCurrentProcess(); 返回值 0XFFFFFFFF -1
HANDLE GetCurrentThread(); 返回值 0XFFFFFFFE -2
这两个函数都返回到主调线程的进程或线程内核对象的一个伪句柄(pseudohandle )。GetCurrentProcess得到得到的只是伪句柄,一个标识,可以发现,其实就是返回$FFFFFFFF(-1),每个进程得句柄都是一样的,只是适用于进程内部使用。同样道理,GetCurrentThread也是伪句柄,其返回值永远是$FFFFFFFE(-2),只是适用于线程内部使用。而"伪句柄"的存在,就是使用简单,不用CloseHandle关闭,不会造成内存泄漏。它们不会在主调进程的句柄表中新建句柄。而且,调用这两个函数,不会影响进程或线程内核对象的使用计数。如果调用closehandle,将一个伪句柄作为参数传入,closehandle只是简单地忽略此调 用,并返回false。在这种情况下,getlasterror将返回error_invalid_handle。
如果想得到实际得句柄,在进程间进行通讯,必需要进行转化,DuplicateHandle函数就可以执行这个转换。
WINBASEAPI
BOOL
WINAPI
DuplicateHandle(
_In_ HANDLE hSourceProcessHandle,
_In_ HANDLE hSourceHandle,
_In_ HANDLE hTargetProcessHandle,
_Outptr_ LPHANDLE lpTargetHandle,
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwOptions
);
现在,想要通过父进程的句柄,在子进程当中操作父进程,或者获取父进程的相关消息,当父线程执行时,它会把标识父线程的有歧义的伪句柄转换为一个新的、真正的句柄,后者明确、无歧义地标识了父线程。然后,它将这个真正的句柄传给createthread。当子线程开始执行时,其pvparam参数就会包含这个真正的线程句柄。在调用任何函数时,只要传入这个句 柄,影响的就将是父线程,而非子线程。 因为duplicatehandle递增了指定内核对象的使用计数,所以在用完复制的对象句柄后,有必要 把目标句柄传给closehandle,以递减对象的使用计数。
父进程:
// #include "stdafx.h" #include <windows.h> #include <iostream> using namespace std; int main() { HANDLE RealProcessHandle = NULL; HANDLE PseudoProcessHandle = GetCurrentProcess(); //获得一个伪句柄 DuplicateHandle( GetCurrentProcess(), //源进程内核句柄(即负责传递内核对象句柄的进程句柄) PseudoProcessHandle, //进程伪句柄 GetCurrentProcess() GetCurrentProcess(), //目标进程内核句柄 &RealProcessHandle, //接受新的,真实句柄! 0, //TargetHandle句柄使用何种访问掩码,这个参数将被忽略,因为DUPLICATE_SAME_ACCESS FALSE, //新的句柄不可继承 DUPLICATE_SAME_ACCESS);//新句柄拥有与原始句柄相同的安全访问特征 //通过上面的函数就可以将一个进程中的一个线程的伪句柄转换成正真的句柄 //DuplicateHandle 递增了内核对象的句柄数最好要调用CloseHandle(); //改变句柄能够被继承 if (SetHandleInformation( RealProcessHandle, //句柄 HANDLE_FLAG_INHERIT, //更改继承标志 HANDLE_FLAG_INHERIT)==FALSE)//将标志修改为可继承 { int LastError = GetLastError(); } ULONG_PTR* v1 = (ULONG_PTR*)PseudoProcessHandle; ULONG_PTR* v2 = (ULONG_PTR*)RealProcessHandle; printf("父进程句柄值:%d %d\r\n", v1,v2); //将存有句柄值的BufferData作为命令行传给子进程 WCHAR BufferData[20] = { 0 }; swprintf_s(BufferData, L"%d %d", v1,v2); STARTUPINFO StartupInfo = { 0 }; StartupInfo.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION ProcessInfo = { 0 }; ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); BOOL IsOk = CreateProcess(L"ChildProcess.exe", (LPWSTR)BufferData,NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo); if (IsOk == FALSE) { printf("CreateProcess\r\n失败"); goto Exit; } CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); printf("Input AnyKey To Exit\r\n"); getchar(); Exit: if (RealProcessHandle!=NULL) { CloseHandle(RealProcessHandle); RealProcessHandle = NULL; } return 0; }
子进程:
// ChildProcess.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> //定义参数 int main(int argc, char* argv[]) { ULONG_PTR v1 = 0; //接收CommandLine的数据实际上是单字的 sscanf_s((CHAR*)argv[0], "%d", &v1); HANDLE PseudoProcessHandle = (HANDLE)v1; sscanf_s((CHAR*)argv[1], "%d", &v1); HANDLE RealProcessHandle = (HANDLE)v1; printf("继承的父进程句柄值:PseudoProcessHandle: %d RealProcessHandle: %d\r\n", PseudoProcessHandle,RealProcessHandle); Sleep(3000); //TerminateProcess(PseudoProcessHandle,0); //把自己杀死了 CloseHandle(RealProcessHandle); //减少引用计数 if (TerminateProcess(RealProcessHandle, 0)==FALSE) { int LastError = GetLastError(); printf("LastError:%d", LastError); } printf("Input AnyKey To Exit\r\n"); getchar(); ExitProcess(0); return 0; }