서비스 UI에서 동작시키는법
[문제발생]
서비스에서 UI가 있는 A.exe 프로그램을 CreateProcess() API를 사용하여 실행을 시켰다. 실행은 되었지만 UI가 있는 프로그램임에도 불구하고 UI가 나타나지 않는다. 그 이유는 SYSTEM권한으로 실행되어서 UI가 발생되지 않았던 것이다.
[문제분석]
윈도우는 기본적으로 User Interface, GDI, 커널 메인 객체를 제공한다. 커널은 안전하지만, UI, GDI는 그렇지 않기 때문에 추가적인 보안성을 제공하기 위해 윈도우는 Stations와 desktops을 사용한다.
각 윈도우 데스크탑은 세션과 윈도우 스테이션에 속하며, 각 세션에서 오직 한번에 하나의 테스크탑만이 활성되 될 수 있다. 그리고 그것은 반드시 WinSta0에 속해야 한다.
Station - Clipborad, destop 등을 포함하는 프로세스와 관련이 있는 보안 객체
Desktop - Station내에 존재하며 논리화면, 윈도우, 메뉴, 훅과 같은 User Interface를 포함하는 보안 객체
- 평상시 윈도우 화면을 보여주는 interactive desktop
- 로그온 화면을 관리하는 winlogon desktop,
- 화면 보호기를 담당하는 screen saver desktop,
총 3가지로 나뉘어진다.
WinSta0은 3개의 로드된 데스크탑을 가진다.
- WinSta0\Default 사용자의 작업이 수행되는 쉘 환경( 사용자 테스크탑 )
- WinSta0\Winlogon 로그온 테스크탑 (로그온화면)
- WinSta0\Screen-Saver 화면 보호기가 실행되는 순간 사용되는 Desktop
( 액티브 데스크탑의 핸들을 가져오기 위해서는 OpenInputDesktop() 함수를 사용하면된다. )
사용자가 로그온을 하게 되면 WinSta0\Winlogon 에서 smss.exe(세션메니져), winlogon.exe msgina.dl 를 통해 일련의 logon 작업을 거쳐 최종적으로 Winst0\default 라는 interactive window station을 생성한다.
그러므로 사용자는 Winsta0의 station에서만이 UI 및 키 입력을 받을 수 있다. (즉 서비스의 경우는 Service-0x0-3e7$\default 로 생성됨)
Winlogon과 default desktop은 서로 메시지나 대화상자를 공유할 수 없다. 자신의 desktop(winlogon, default)에서만 사용이 가능하다. 하지만 클립 보드는 Station에서 관리하기 때문에 다른 desktop에서 사용이 가능하다.
Service의 경우 LocalSystem 계정(administrator 보다 상위)으로 실행되어 Service-0x0-3e7$\default 와 같은 station을 생성하므로 UI및 키 입력을 받을 수 없다. 그래서 서비스 내에서 UI를 가진 프로그램을 실행시키기 위해서는 STARTUPINFO구조체를 si.lpDesktop = "WinSta0\\Default"; 와 같이 설정하여 실행시켜야 한다.
typedef struct _STARTUPINFOA {
DWORD cb;
LPSTR lpReserved;
LPSTR lpDesktop;
LPSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;
서비스 프로그램중에서 mtask.exe와 같은 프로그램은 WinSta0을 사용한다. 반면 서비스 프로그램을 UI 또는 키 입력을 받기 위해서는 CreateService로 실행시 SERVICE_INTERATIVE_PROCESS 옵션을 사용하거나 서비스 등록정보에서 로그인정보에 "데스크와 상호 작용"을 설정하면 서비스도 UI 및 키입력을 받을 수 있다.
Session -> WindowStation -> Desktop와 같은 구조를 이루는데 다른 Session에서는 같은 winsta0\default를 가졌더라도 메시지 및 UI가 공유 될 수 없다. 즉 Session 1에 logon한 사용자가 실행시킨 프로그램에서 표시된 대화상자는 Session 2로 logon 사용자의 화면에는 나타나지 않는다는 말이다.
서비스 프로그램에서 UI있는 프로그램을 수행시키기 위해서는 CreateProcess()로는 안되고 CreateProcessAsUser()를 사용해야된다.
참조 : https://duzi077.tistory.com/25
'훈, IT 공부 > C,C++,MFC' 카테고리의 다른 글
Library, DetourCreateProcessWithDll() 함수 (6) | 2019.09.17 |
---|---|
Visual Studio 2008 - fatal error C1859 미리 컴파일된 헤더에서 예기치 않은 오류가 발생했습니다. 컴파일러를 다시 실행하면 이 문제를 해결할 수 있습니다. (6) | 2019.06.17 |
C++, Gdiplus 사용하여 png 생성하기 (0) | 2018.09.09 |
[MFC]CreateFont (0) | 2018.08.31 |
[MFC]트레이아이콘(Tray)과 풍선(Balloon) 알림 사용 (2) | 2018.08.12 |
댓글