windows是通过句柄对进程中的各种内核对象进行引用。实际上windows句柄就是一个索引,索引对应对象的地址,拿到地址就可以获取对象本身了
句柄表存放的三个值
1句柄是否有继承权限 2句柄(索引) 3对象的地址
1 1 0x11111111
跨进程使用句柄
1)子进程继承父进程句柄的方式
将父进程的句柄放到子进程的句柄表里
1- 句柄本身可以被继承(有继承权限),SECURITY_ATTRIBUTES 结构体中的bInheritHandle 成员设置为TRUE标识句柄可以被继承
2- Createprocess的参数bInheritHandles为TRUE,子进程继续父进程的句柄,只会拷贝有继承权限的句柄
3- 继承已经打开的句柄,OpenProcess这个API返回的句柄第二个参数为TRUE,表示指定返回的句柄是否可以由当前进程创建的新进程继承。 如果为TRUE,则句柄是可继承的,相当于第一种把打开的句柄继承权限改为1
TCHAR szBuff[] = { _T("创建的子进程名") };
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE; //用CreateProcess创建的进程返回的进程句柄是否可以被继承(也就是子进程自己的单个句柄),也就是pi.dwProcessId进程句柄是否可以被继承
if (!CreateProcess(NULL,
szBuff,
&sa, // 新建的进程的中的句柄可以被继承
NULL,
TRUE, // 是否继承本进程的句柄
0,
NULL,
NULL,
&si,
&pi)
)
{
AfxMessageBox(_T("CreateProcess failed."));
}
2) 非父子进程使用句柄
1打开句柄,A进程打开B进程,A进程中的句柄表中添加了一个新句柄,新句柄值不一定相同,但是这个句柄索引的内核对象是同一个
HANDLE OpenProcess(
DWORD dwDesiredAccess, //渴望得到的访问权限(标志)
BOOL bInheritHandle, // 是否继承句柄,指定返回的句柄是否可以由当前进程创建的新进程继承。 如果为TRUE,则句柄是可继承的
DWORD dwProcessId// 进程标示符
);
2复制句柄 -- DuplicateHandle 也是将源进程的句柄传给目标进程,使得目标进程的句柄表中有源进程的句柄
//1. 查找窗口
HWND hWnd = ::FindWindow(NULL, _T("源进程"));
//2. 拿到进程id
DWORD dwProcessId;
::GetWindowThreadProcessId(hWnd, &dwProcessId);
//3. 打开进程
HANDLE hProcess = ::OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
dwProcessId);
HWND hWndDst = ::FindWindow(NULL, _T("目标进程"));
::GetWindowThreadProcessId(hWndDst, &dwProcessId);
HANDLE hProcessDst = ::OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
dwProcessId);
//复制句柄,从当前进程拷贝hProcess句柄给目标进程
HANDLE hTargetHandle;
DuplicateHandle(
GetCurrentProcess(),//源进程的进程句柄,getcurrent获取的是本进程的句柄
hProcess, //拷贝的句柄
hProcessDst, //目标进程的进程句柄
&hTargetHandle, //给目标进程使用的值
0, //忽略
FALSE, //句柄是否可以被hProcessDst的子进程继承
DUPLICATE_SAME_ACCESS); //目标进程的句柄和源进程的句柄有相同的权限
SetDlgItemInt(EDT_DUPLICATEHANDLE, (UINT)hTargetHandle);
3) 窗口句柄可以直接跨进程使用
//1. 查找窗口
HWND hWnd = ::FindWindow(NULL, _T("查找的窗口标题"));
//2. 拿到进程id
DWORD dwProcessId;
::GetWindowThreadProcessId(hWnd, &dwProcessId);
//3. 打开进程
HANDLE hProcess = ::OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
dwProcessId);
SetDlgItemInt(EDT_HANDLE, (UINT)hProcess);