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);