原文鏈接:http://www.cnblogs.com/lifeengines/archive/2008/08/26/1277054.html
本來在Vista之前服務(wù)與桌面互交是一件很容易的事情,自從Vista把服務(wù)都挪到Session 0
中運(yùn)行去而且不可以跨Session之后,問題就復(fù)雜了許多,有時(shí)候我就在想這些問題是否真的不得不解決而且似乎對于安全并未帶來多大提升的更改總是讓人
頭疼,Google了一些文檔,抄襲了不少代碼我是如下實(shí)現(xiàn)的
這個(gè)函數(shù)抄自winehq網(wǎng)站,順便不得不說一下winehq的代碼是很值得參考的
1 BOOL WINAPI EnablePrivilege(LPSTR lpPrivilegeName, BOOL bEnable)
2 {
3 TOKEN_PRIVILEGES Privileges;
4 HANDLE hToken;
5 BOOL bResult;
6 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
7 return FALSE;
8
9 Privileges.PrivilegeCount = 1;
10 Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
11
12 if (!LookupPrivilegeValue(NULL, lpPrivilegeName,
13 &Privileges.Privileges[0].Luid))
14 {
15 CloseHandle(hToken);
16 return FALSE;
17 }
18
19 bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
20
21 CloseHandle(hToken);
22
23 return bResult;
24 }
EnablePrivilege用來提升本進(jìn)程權(quán)限,因?yàn)槲覀兊暮诵乃悸肥怯肅reateProcessAsUser創(chuàng)建進(jìn)程到需要互交的Session,
//保證擁有權(quán)限
EnablePrivilege(SE_TCB_NAME, TRUE);
EnablePrivilege(SE_CHANGE_NOTIFY_NAME, TRUE);
EnablePrivilege(SE_INCREASE_QUOTA_NAME, TRUE);
EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME, TRUE);
//獲取當(dāng)前進(jìn)程的靈牌
HANDLE hTokenThis = NULL;
HANDLE hTokenDup = NULL;
HANDLE hThisProcess = GetCurrentProcess();
OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);
//復(fù)制令牌
DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
//枚舉所有Session,本來還有一個(gè)WTSGetActiveConsoleSessionId,不過這個(gè)函數(shù)在win2000下只有Server版本安裝WTS才可以
PWTS_SESSION_INFO pSInfo;
DWORD pCInfo = 0;
WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,0,1,&pSInfo,&pCInfo);
DWORD dwSessionId = 0;
for (int i=0;i<pCInfo;i++)
{
if (pSInfo[i].State == WTSActive)
{
dwSessionId = pSInfo[i].SessionId;
break;
}
}
//DWORD dwSessionId = WTSGetActiveConsoleSessionId();
//替換令牌,關(guān)鍵地方,我們并不需要以Session用戶創(chuàng)建進(jìn)程,只需要替換令牌就可以了
SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);
si.lpDesktop = "WinSta0\\Default";
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
char pPath[MAX_PATH*2];
GetModuleFileName(NULL,pPath,sizeof(pPath));
strcat(pPath," -work");
LPVOID pEnv;
CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE);
if (!CreateProcessAsUser(hTokenDup,NULL,pPath,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))
{
//
// int p = GetLastError();
// p = 0;
}
WaitForSingleObject(pi.hProcess,INFINITE);
CloseHandle(hTokenDup);
CloseHandle(hTokenThis);
這樣我們的程序就可以和桌面互交了,這只是核心,其余牽涉多用戶切換這些還需要另外考慮