在Windows7中,服務在一個叫做Session 0 的特殊Session中承載。由於應用程序運行在用戶登錄到系統後所創建的Session 0 之後的Session中,所以應用程序和服務也就隔離開來:第一個登錄的用戶在Session 1中,第二個在Session 2中,以此類推。事實上運行在不同的Session中,如果沒有特別將其放入全局命名空間(並且設置了相應的訪問控制配置),是不能互相傳遞窗體消息,共享UI元素或者共享kernel對象。
利用CreateProcessAsUser,我們可以在Session 0中創建用戶進程,下面提供兩種創建方式:
typedef BOOL (*FUNCTypeA)( LPVOID*, HANDLE, BOOL) ;
typedef BOOL (*FUNCTypeB)( LPVOID );
typedef DWORD (WINAPI* PWTSActiveSessionID)();
DWORD GetActiveConsoleSessionId()
{
PWTSActiveSessionID pWTSActiveSessionID;
DWORD dwResult = 0;
HINSTANCE hKernal32 = NULL;
do {
OSVERSIONINFO os = {sizeof(OSVERSIONINFO)};
GetVersionEx(&os);
if(os.dwMajorVersion == 5 && os.dwMinorVersion==0)
{
break;
}
else
{
hKernal32 = LoadLibrary(_T("kernel32.dll"));
if(hKernal32 == NULL)
{
break;
}
pWTSActiveSessionID = (PWTSActiveSessionID)GetProcAddress(hKernal32, "WTSGetActiveConsoleSessionId" );
if(pWTSActiveSessionID == NULL)
{
break;
}
dwResult = pWTSActiveSessionID();
}
} while(FALSE);
if(hKernal32 != NULL)
FreeLibrary(hKernal32);
return dwResult;
}
BOOL CreateUserProcess1(LPTSTR szMonName)
{
DWORD dwSessionId;
BOOL bResult;
HANDLE hTokenThis = NULL;
HANDLE hTokenDup = NULL;
HANDLE hThisProcess;
STARTUPINFO starinfo;
PROCESS_INFORMATION processinfo;
HMODULE hModule;
FUNCTypeA CreateEnvironmentBlock;
FUNCTypeB DestroyEnvironmentBlock;
hThisProcess = GetCurrentProcess();
DWORD ddd = GetLastError();
bResult = OpenProcessToken(hThisProcess,TOKEN_ALL_ACCESS, &hTokenThis);
ddd = GetLastError();
bResult = DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
dwSessionId = GetActiveConsoleSessionId();
bResult = SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));
hModule =LoadLibrary(_T("userenv.dll"));
if (hModule)
{
CreateEnvironmentBlock = (FUNCTypeA) GetProcAddress(hModule,"CreateEnvironmentBlock");
DestroyEnvironmentBlock= (FUNCTypeB)GetProcAddress(hModule,"DestroyEnvironmentBlock");
}
ZeroMemory( &starinfo, sizeof(STARTUPINFO) );
ZeroMemory( &processinfo, sizeof(PROCESS_INFORMATION) );
starinfo.cb = sizeof(starinfo);
starinfo.wShowWindow = SW_SHOWNORMAL;
starinfo.dwFlags |= STARTF_USESTDHANDLES;
starinfo.lpDesktop = L"WinSta0\\Default";
FreeLibrary(hModule);
TCHAR zsAppName[MAX_PATH];
_tcscpy(zsAppName,szMonName);
bResult = CreateProcessAsUser( hTokenDup,
zsAppName,
NULL,
NULL,
NULL,
TRUE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&starinfo,
&processinfo);
CloseHandle(hTokenDup);
if(bResult)
{
CloseHandle(processinfo.hThread);
CloseHandle(processinfo.hProcess);
return TRUE;
}
return 0;
}
typedef DWORD (*WTSGETACTIVECONSOLESESSIONID)(void);
typedef BOOL (WINAPI *WTSQUERYUSERTOKEN)(ULONG,PHANDLE);
WTSQUERYUSERTOKEN WTSProc=NULL;
HMODULE hModWTS=NULL;
BOOL CreateUserProcess2(TCHAR *filename)
{
PROCESS_INFORMATION pInfo;
STARTUPINFO sInfo;
BOOL bRet = FALSE;
ZeroMemory(&sInfo,sizeof(sInfo));
ZeroMemory(&pInfo,sizeof(pInfo));
sInfo.cb=sizeof(STARTUPINFO);
sInfo.cbReserved2=0;
sInfo.dwFillAttribute=0;
sInfo.dwFlags=STARTF_USESHOWWINDOW;
sInfo.wShowWindow=SW_SHOW;
sInfo.lpDesktop = L"winsta0\\default";
HANDLE hToken=NULL;
HMODULE hmod = LoadLibrary( L"kernel32.dll");
if(hmod == NULL)
{
return bRet;
}
WTSGETACTIVECONSOLESESSIONID lpfnWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress(hmod, "WTSGetActiveConsoleSessionId");
DWORD dwSessionId=-1;
dwSessionId = lpfnWTSGetActiveConsoleSessionId();
FreeLibrary(hmod);
hModWTS = LoadLibrary( L"wtsapi32.dll");
if(hModWTS !=NULL)
{
WTSProc = (WTSQUERYUSERTOKEN) GetProcAddress(hModWTS, "WTSQueryUserToken");
TCHAR zsAppName[MAX_PATH];
_tcscpy(zsAppName,filename);
if(WTSProc!=NULL)
{
if(WTSProc(dwSessionId,&hToken)!=0)
{
if(CreateProcessAsUser(hToken,NULL,zsAppName,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS ,NULL,NULL,&sInfo,&pInfo))
{
CloseHandle(pInfo.hThread);
CloseHandle(pInfo.hProcess);
bRet = TRUE;
}
CloseHandle(hToken);
}
}
FreeLibrary(hModWTS);
hModWTS = NULL;
}
return bRet;
}