2010-02-06 66 views
3

我正在使用VC++使用CreateProcessAsUser從Vista上的服務創建進程。當我通過本地機器上的登錄執行此代碼時,進程創建成功。當我使用遠程桌面(mstsc)從另一臺計算機登錄到我的機器並啓動我的應用程序時,相同的代碼失敗。從Vista上的服務使用CreateProcessAsUser的桌面問題

我可以理解,當我進行遠程登錄時,活動桌面被視爲遠程桌面。有人能幫助我獲得當前登錄用戶桌面的桌面名稱,而不是遠程桌面的桌面名稱。

這裏是我的代碼

ACTIVECONSOLESESSIONIDFUNC lpfnProc; // WTSGetActiveConsoleSessionId function pointer 
HMODULE hModule = NULL;   // Instance for kernel32.dll library 
DWORD dwSessionId = 0;   // Session ID 
HANDLE hToken = NULL;   // Active session token 
HANDLE hDupToken = NULL;  // Duplicate session token 
WCHAR szErr[1024] = {0}; 

LPVOID lpEnvironment = NULL;   // Environtment block 

// Get the active session ID 
hModule = LoadLibrary(KERNEL32LIB); 
if(!hModule) 
{ 
    //wsprintf(szErr, L"LoadLibrary Error: %d", GetLastError()); 
    return; 
} 

lpfnProc = (ACTIVECONSOLESESSIONIDFUNC)GetProcAddress(hModule,"WTSGetActiveConsoleSessionId"); 

dwSessionId = lpfnProc(); 

// Get token of the logged in user by the active session ID 
BOOL bRet = WTSQueryUserToken(dwSessionId, &hToken); 

if (!bRet) 
{  
    //wsprintf(szErr, L"WTSQueryUserToken Error: %d", GetLastError()); 
    return; 
} 

// Get duplicate token from the active logged in user's token 
bRet = DuplicateTokenEx(hToken,  // Active session token 
       MAXIMUM_ALLOWED,   // Desired access 
         NULL,      // Token attributes           
         SecurityIdentification, // Impersonation level 
         TokenPrimary,    // Token type 
         &hDupToken);    // New/Duplicate token 
    if (!bRet) 
    { 
     //wsprintf(szErr, L"DuplicateTokenEx Error: %d", GetLastError()); 
     return; 
    } 

    // Get all necessary environment variables of logged in user 
    // to pass them to the process 

    bRet = CreateEnvironmentBlock(&lpEnvironment, // Environment block 
           hDupToken,  // New token 
           FALSE);   // Inheritence 
    if(!bRet) 
    { 
     //wsprintf(szErr, L"CreateEnvironmentBlock Error: %d", GetLastError()); 
     return; 
    } 

    HDESK hdeskInput=OpenInputDesktop(0, FALSE, 0); // does not set GetLastError(), so GetLastError() is arbitrary if NULL is returned 
    if(hdeskInput==NULL) { 
     TRACE("hdeskInput==NULL"); 
     return false; 
    } 

    // Initialize Startup and Process info 
    startupInfo->cb = sizeof(STARTUPINFO); 
    startupInfo->lpDesktop = TEXT("winsta0\\default"); 



    // Start the process on behalf of the current user 

    BOOL returnCode = CreateProcessAsUser(hDupToken, 
           applicationName, 
           commandLine, 
           NULL, 
           NULL, 
           FALSE, 
           NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, 
           lpEnvironment, 
           NULL, 
           startupInfo, 
           &processInformation); 

感謝, ˚F

回答

1

大量的谷歌搜索後,我能找到我的問題的解決方案。

這裏是我找到解決方案的鏈接。 http://www.codeproject.com/KB/vista-security/interaction-in-vista.aspx

感謝每一位試圖幫助我的人。

+0

當然,我希望你是那臺機器上唯一的一臺,否則你仍然可以在另一臺桌面上隨機創建一個進程:) – tyranid 2010-02-09 18:28:32

+0

所以,如果我需要在這種情況下解決問題。我需要做什麼? – coolcake 2010-02-10 04:58:25

1

什麼是啓動服務來創建一個新的工藝中具有承載在一個合適的答案是什麼? WTSGetActiveConsoleSessionId獲取當前物理控制檯會話的會話標識,而不是您的意義上的「活動」會話標識。通過終端服務,可能會有許多不同的用戶連接到不同的會話,因此您不能只選擇一個並希望,但實際上可能有或沒有實際登錄的用戶。

一種方法是使用WTSEnumerateSessions列出所有活動的會話,並嘗試找到您實際需要的會話,您可以使用類似WTSQuerySessionInformation之類的名稱獲取該會話的用戶名。

如果您的服務正在響應您的用戶帳戶的某些請求(而不是處理某些自動事件),那麼如果您使用的是類似RPC /命名管道/ DCOM等的東西,則可以始終模擬用戶假設安全性設置爲允許非匿名/識別模擬)並將該線程的令牌複製到主令牌中並使用該令牌。

+0

謝謝蟲族什麼。我上面粘貼的代碼是通過瀏覽網絡獲得的代碼。我對桌面或會話沒有任何知識。我希望你能理解我的問題。我的問題是我將從我的機器登錄到我的桌面,然後應用程序正常運行,即。我能夠從服務創建進程,但是當我從另一臺機器(mstsc)登錄到我的桌面時,我的服務無法創建進程。因爲它在調用WtsQueryUserToken時失敗,錯誤1008 ERROR_NO_TOKEN;會議ID我越來越是3,而我的實際是1.請幫助。 – coolcake 2010-02-08 10:56:55

+0

正如所說的那樣,實際上是在創建過程,就像上面的代碼如何被調用以及在什麼情況下一樣。 – tyranid 2010-02-08 17:46:03

+0

我的應用程序有一個在系統帳戶下運行的服務創建過程。我想創建一個單獨的進程來處理服務的GUI相關任務。當我的服務收到來自App的管道消息時,會嘗試創建該進程。 – coolcake 2010-02-09 03:56:45

4

下面是完整的工作代碼,做你想做

//Function to run a process as active user from windows service 
void ImpersonateActiveUserAndRun(WCHAR* path, WCHAR* args) 
{ 
    DWORD session_id = -1; 
    DWORD session_count = 0; 

    WTS_SESSION_INFOA *pSession = NULL; 


    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count)) 
    { 
     //log success 
    } 
    else 
    { 
     //log error 
     return; 
    } 

    for (int i = 0; i < session_count; i++) 
    { 
     session_id = pSession[i].SessionId; 

     WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected; 
     WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL; 

     DWORD bytes_returned = 0; 
     if (::WTSQuerySessionInformation(
      WTS_CURRENT_SERVER_HANDLE, 
      session_id, 
      WTSConnectState, 
      reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state), 
      &bytes_returned)) 
     { 
      wts_connect_state = *ptr_wts_connect_state; 
      ::WTSFreeMemory(ptr_wts_connect_state); 
      if (wts_connect_state != WTSActive) continue; 
     } 
     else 
     { 
      //log error 
      continue; 
     } 

     HANDLE hImpersonationToken; 

     if (!WTSQueryUserToken(session_id, &hImpersonationToken)) 
     { 
      //log error 
      continue; 
     } 


     //Get real token from impersonation token 
     DWORD neededSize1 = 0; 
     HANDLE *realToken = new HANDLE; 
     if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1)) 
     { 
      CloseHandle(hImpersonationToken); 
      hImpersonationToken = *realToken; 
     } 
     else 
     { 
      //log error 
      continue; 
     } 


     HANDLE hUserToken; 

     if (!DuplicateTokenEx(hImpersonationToken, 
      //0, 
      //MAXIMUM_ALLOWED, 
      TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED, 
      NULL, 
      SecurityImpersonation, 
      TokenPrimary, 
      &hUserToken)) 
     { 
      //log error 
      continue; 
     } 

     // Get user name of this process 
     //LPTSTR pUserName = NULL; 
     WCHAR* pUserName; 
     DWORD user_name_len = 0; 

     if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len)) 
     { 
      //log username contained in pUserName WCHAR string 
     } 

     //Free memory       
     if (pUserName) WTSFreeMemory(pUserName); 

     ImpersonateLoggedOnUser(hUserToken); 

     STARTUPINFOW StartupInfo; 
     GetStartupInfoW(&StartupInfo); 
     StartupInfo.cb = sizeof(STARTUPINFOW); 
     //StartupInfo.lpDesktop = "winsta0\\default"; 

     PROCESS_INFORMATION processInfo; 

     SECURITY_ATTRIBUTES Security1; 
     Security1.nLength = sizeof SECURITY_ATTRIBUTES; 

     SECURITY_ATTRIBUTES Security2; 
     Security2.nLength = sizeof SECURITY_ATTRIBUTES; 

     void* lpEnvironment = NULL; 

     // Get all necessary environment variables of logged in user 
     // to pass them to the new process 
     BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE); 
     if (!resultEnv) 
     { 
      //log error 
      continue; 
     } 

     WCHAR PP[1024]; //path and parameters 
     ZeroMemory(PP, 1024 * sizeof WCHAR); 
     wcscpy(PP, path); 
     wcscat(PP, L" "); 
     wcscat(PP, args); 

     // Start the process on behalf of the current user 
     BOOL result = CreateProcessAsUserW(hUserToken, 
      NULL, 
      PP, 
      //&Security1, 
      //&Security2, 
      NULL, 
      NULL, 
      FALSE, 
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, 
      //lpEnvironment, 
      NULL, 
      //"C:\\ProgramData\\some_dir", 
      NULL, 
      &StartupInfo, 
      &processInfo); 

     if (!result) 
     { 
      //log error 
     } 
     else 
     { 
      //log success 
     } 

     DestroyEnvironmentBlock(lpEnvironment); 

     CloseHandle(hImpersonationToken); 
     CloseHandle(hUserToken); 
     CloseHandle(realToken); 

     RevertToSelf(); 
    } 

    WTSFreeMemory(pSession); 
} 
+1

很好放,榮譽! – 2017-01-22 02:00:44