2011-11-29 2 views
4

이 문제는 한 번 발생했지만 여전히 해결 방법을 모릅니다. Windows 서비스가 있는데 서비스가 실행되면 로그인 된 사용자 (활성 사용자)를 가장하여 사용자의 응용 프로그램 데이터 폴더에 저장된 일부 경로와 설정을로드해야합니다. 새로운 사용자가 창에 로그온 할 때마다 내가 사용하고있는 코드가 완벽하게 작동합니다. 단, 서비스가 가장을 잘못 처리하여 액티비티 대신 시스템 세션을 가장 한 경우는 예외입니다. 내가 말했듯이, 이것은 한 번만 일어 났지만, 왜 그런지 말할 수는 없습니다.시스템 세션을 반환하는 WTSGetActiveConsoleSessionId

이 뭐죠 활성 세션과 가장을 수행하는 방법을 확인하고 방법입니다

서비스가 다음 검사를

WTSGetActiveConsoleSessionId(); 

를 호출하여 쿼리 활성 세션 ID의 로그온 이벤트를 감지 할 때 처음 세션이 WTSQuerySessionInformation를 호출하여 활성 상태 (접속)되어있는 경우에는 다음과 같이

SESSION_ID를 WTSG하여 세션 ID를 반환
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)) 
{ 
     ASSERT(bytes_returned == sizeof(*ptr_wts_connect_state)); 
     wts_connect_state = *ptr_wts_connect_state; 
     ::WTSFreeMemory(ptr_wts_connect_state); 
     return (WTSActive == wts_connect_state); 
} 

etActiveConsoleSessionId(). 그런 다음

내가 사용하여 사용자 토큰 쿼리 WTSQueryUserToken

그런 다음 다음과 같이 서비스가 GetTokenInformation를 호출 성공하면 : hImpersonationToken가 GetTokenInformation

그리고 모든 경우에서 검색 한 토큰

DWORD neededSize = 0; 
    HANDLE *realToken = new HANDLE; 
    if(GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize)) 
    { 
     CloseHandle(hImpersonationToken); 
     hImpersonationToken = *realToken; 
    } 

을 위의 성공 후 그것을 호출

DuplicateTokenEx(hImpersonationToken, 
           0, 
           NULL, 
           SecurityImpersonation, 
           TokenPrimary, 
           phUserToken); 

     CloseHandle(hImpersonationToken); 

하고 다음 성공하면이 검색된 토큰

ImpersonateLoggedOnUser(phUserToken); 

내 서비스를 가장하여 로그 파일에 기록하고 성공적인 아직 가장 후 서비스가 대신 시스템 프로파일을로드 로그인 이전의 모든 통화에 따라 사용자의

이제이 문제는 컴퓨터를 다시 시작할 때 한 번 발생했지만 다시 복제하지는 못했지만 몇 주 동안 계속 노력했습니다.

시스템 프로필 세션이 활성 세션 인 방법이 확실하지 않습니다. 난 단지 내가 뭔가 잘못된 일을하고 있는지, 내가 세션 정보 나 뭔가를 질의 할 때 잘못된 정보 클래스를 사용하는지 잘 모르겠다.

반환 된 토큰으로 가장하기 전에 쿼리 한 세션이 실제로 시스템 세션인지 여부를 판단 할 수 있는지 알고 싶습니다. 그러면 다시 가장을 다시 시도 할 수 있습니까?

앞에서 언급 한 모든 호출에는 다음 단계로 이동하기 전에 반환 객체와 코드가 확인되므로 호출에서 오류가 발생하지 않았으므로 가장으로 계속해서 실행해서는 안되었습니다. 그러나 (

감사 ... 어떤 가능한 도움 감사하겠습니다.

답변

4

WTSGetActiveConsoleSessionId을() 서비스에서 실행 및 Windows 버전에 따라이 실행되는 경우 실제로 세션 0을 반환 할 수 있습니다.

원하는 작업을 수행하는 방법은 모든 세션이 연결되어있는 세션 (세션 0이 연결되어 있지 않음)을 찾은 다음 해당 세션의 사용자를 가장하는 것을 열거합니다. 아래 코드는 내 상자에서 잘 작동합니다.

//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); 
} 
관련 문제