헬마입니다.

스프링노트에서 보내기 해봤는데 별로 깔끔하지 않네요.
깔끔하게 보시려면 이쪽으로~~
http://jgh0721.springnote.com/pages/911438


----------------

주로 서비스에서 UI 있는 프로그램을 서비스 세션이 아닌 대화형 데스크탑이 있는 세션에서 실행시킴으로써 정상적으로 작동시키기 위한 것.

부가적으로 이 함수로 실행시키면 비스타의 UAC 를 띄우지 않고 관리자 권한으로 실행시킬 수 있다.

서비스가 SYSTEM 계정으로 실행중이라면 실행시킨 프로그램도 SYSTEM 계정을 받아서 실행됨.


코드 프로젝트의 기사의 소스코드를 기반으로 2000 ~ Vista 에서 작동하도록 수정함.

http://www.codeproject.com/KB/vista-security/VistaSessions.aspx


  1. #ifdef _UNICODE
     #define tstring wstring
    #else
     #define tstring string
    #endif

  2.  // Winlogon.exe 실행파일의 세션을 검색하여 같은 세션에서 실행시킴, 2000 ~ Vista
    BOOL LaunchAppIntoDifferentSessionAll(tstring strPath)
    {
     if( strPath.empty() )
      return FALSE;
     
     tstring strSearch;
     OSVERSIONINFO osi;
     ZeroMemory(&osi,sizeof(OSVERSIONINFO));
     osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
     GetVersionEx(&osi);
  3.  // 변수 선언
     BOOL bResult = FALSE;
     DWORD dwSessionId = 0; // 세션 ID
     DWORD dwWinlogonPID = 0; // Winlogon PID
  4.  typedef DWORD (*pfnWTSGetActiveConsoleSessionId)(void);
     HMODULE hModule = NULL;
     pfnWTSGetActiveConsoleSessionId fnWTSGetActiveConsoleSessionId = NULL;
  5.  if( osi.dwMajorVersion == 6 )
     {
      OutputDebugString(_T("Vista, 라이브러리 로딩 시도"));
      hModule = ::LoadLibrary(_T("Kernel32.dll"));
      if( hModule != NULL )
      {
       OutputDebugString(_T("Vista, 함수 로딩 시도"));
       fnWTSGetActiveConsoleSessionId = (pfnWTSGetActiveConsoleSessionId) GetProcAddress(hModule, "WTSGetActiveConsoleSessionId");
       if( fnWTSGetActiveConsoleSessionId == NULL )
        OutputDebugString(_T("WTSGetActiveConsoleSessionId 함수 로딩 실패"));
  6.    dwSessionId = fnWTSGetActiveConsoleSessionId();
      }
     }
     
     // 같은 세션으로 실행할 프로세스 찾기(Winlogon.exe)
     BOOL IsExistsWinlogon = FALSE;
     PROCESSENTRY32 pe32;
     pe32.dwSize = sizeof(PROCESSENTRY32);
     
     HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     if( hSnap == INVALID_HANDLE_VALUE )
     {
      bResult = FALSE;
      goto CleanUP;
     }
  7.  if( !Process32First(hSnap, &pe32) )
     {
      bResult = FALSE;
      goto CleanUP;
     }
  8.  if( osi.dwMajorVersion == 6 )
      strSearch = _T("winlogon.exe");
     else if( osi.dwMajorVersion == 5 )
      strSearch = _T("explorer.exe");
  9.  do
     {
      if( lstrcmpi(pe32.szExeFile, strSearch.c_str()) == 0 )
      {
       OutputDebugString(_T("WinLogon 프로세스 검색"));
       DWORD dwWLSessionID = 0;
       BOOL bRet = ProcessIdToSessionId(pe32.th32ProcessID, &dwWLSessionID);
  10.    if(  bRet && (osi.dwMajorVersion == 6) && (dwSessionId == dwWLSessionID) )
       {
        // 비스타
        OutputDebugString(_T("Vista"));
        dwWinlogonPID = pe32.th32ProcessID;
        IsExistsWinlogon = TRUE;
        break;
       }
       else if( bRet && (osi.dwMajorVersion == 5) )
       {
        // 2000 ~ XP
        OutputDebugString(_T("2000/XP"));
        dwSessionId = dwWLSessionID;
        dwWinlogonPID = pe32.th32ProcessID;
        IsExistsWinlogon = TRUE;
        break;
       }
      }
     } while ( Process32Next(hSnap, &pe32) );
  11.  if( IsExistsWinlogon == FALSE )
     {
      OutputDebugString(_T("Winlogon.exe 검색 실패"));
      bResult = FALSE;
      goto CleanUP;
     }
  12.  // WINLOGON 프로세스 열고 토큰 복사하여 특정 세션 지정
     HANDLE hProcess = ::OpenProcess(MAXIMUM_ALLOWED, FALSE, dwWinlogonPID);
     HANDLE hToken = NULL;
     HANDLE hTokenDup = NULL;
     if( hProcess == NULL )
      goto CleanUP;
     if( !::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID|TOKEN_READ|TOKEN_WRITE, &hToken))
     {
      OutputDebugString(_T("OpenProcessToken Failed"));
      bResult = FALSE;
      goto CleanUP;
     }
     LUID luid;
     if( !LookupPrivilegeValue(NULL,SE_DEBUG_NAME, &luid) )
     {
      OutputDebugString(_T("LookupPrivilegeValue Failed"));
      bResult = FALSE;
      goto CleanUP;
     }
     TOKEN_PRIVILEGES tp;
     tp.PrivilegeCount = 1;
     tp.Privileges[0].Luid = luid;
     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     if( !DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup) )
     {
      OutputDebugString(_T("DuplicateTokenEx Failed"));
      bResult = FALSE;
      goto CleanUP;
     }
     SetTokenInformation(hTokenDup, TokenSessionId, (LPVOID)&dwSessionId, sizeof(DWORD));
     if( !AdjustTokenPrivileges(hTokenDup, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL,NULL) )
     {
      OutputDebugString(_T("AdjustTokenPrivileges Failed"));
      bResult = FALSE;
      goto CleanUP;
     }
     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
     {
      OutputDebugString(_T("AdjustTokenPrivileges Assign Failed"));
      bResult = FALSE;
      goto CleanUP;
     }
  13.  // CreateProcessAsUser 준비
     STARTUPINFO si;
     ZeroMemory(&si, sizeof(STARTUPINFO));
     si.cb = sizeof(STARTUPINFO);
     si.lpDesktop = _T("winsta0\\default");
     PROCESS_INFORMATION pi;
     ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
     DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
     LPVOID pEnv = NULL;
     if( CreateEnvironmentBlock(&pEnv, hTokenDup, TRUE) )
      dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
     else
      pEnv = NULL;
  14.  LPTSTR lpszPath = _tcsdup(strPath.c_str());
     if( lpszPath == NULL )
     {
      OutputDebugString(_T("Path String Assign Failed"));
      bResult = FALSE;
      goto CleanUP;
     }
  15.  OutputDebugString(lpszPath);
  16.  bResult = ::CreateProcessAsUser(
        hTokenDup,
        NULL,
        lpszPath,
        NULL,
        NULL,
        FALSE,
        dwCreationFlags,
        pEnv,
        NULL,
        &si,
        &pi);
  17.  free(lpszPath);
  18.  if( !bResult )
      OutputDebugString(_T("CreateProcessAsUser Failed"));
     
     if( (bResult) && (pi.hProcess != INVALID_HANDLE_VALUE) )
      CloseHandle(pi.hProcess);
     if( (bResult) && (pi.hThread != INVALID_HANDLE_VALUE) )
      CloseHandle(pi.hThread);
  19. CleanUP:
     if( hModule )
      FreeLibrary(hModule);
     if( hSnap != INVALID_HANDLE_VALUE )
      CloseHandle(hSnap);
     if( hProcess != NULL )
      CloseHandle(hProcess);
     if( hToken )
      CloseHandle(hToken);
     if( hTokenDup )
      CloseHandle(hTokenDup);
  20.  return bResult;
    }
  21. BOOL EnablePrivilege(LPCTSTR szPrivilege)
    {
     BOOL bResult = FALSE;
     HANDLE hToken = NULL;
     TOKEN_PRIVILEGES tpOld, tpCurrent;
  22.  if( !OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken) )
      return bResult;
  23.  tpCurrent.PrivilegeCount = 1;
     tpCurrent.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  24.  if( ::LookupPrivilegeValue(NULL, szPrivilege, &tpCurrent.Privileges[0].Luid) )
     {
      DWORD dwOld = sizeof(TOKEN_PRIVILEGES);
      if( ::AdjustTokenPrivileges(hToken, FALSE, &tpCurrent, dwOld, &tpOld, &dwOld) )
       bResult = TRUE;
      else
       bResult = FALSE;
     }
     else
      bResult = FALSE;
  25.  CloseHandle(hToken);
     return bResult;
    }

이 글은 스프링노트에서 작성되었습니다.

댓글을 달아 주세요