서비스를 동작시키기 위해서는 아래의 3가지 형태의 프로그램이 필요하다.
1. 서비스 프로그램
- 실제 작업을 처리하는 서비스 프로그램이다.
2. 서비스 설정 프로그램
- 서비스의 목록을 레지스트리(HKEY_LOCAL_MACHINE\System\CurrentControlSet\Service)에 DB형태로 저장해서 관리하는데 서비스 프로그램을 설치 및 제거하는데 사용된다.
3. 서비스 제어 프로그램
- 서비스 프로그램은 백그라운드에서 동작하기 때문에 사용자가 제어할 수 없다. 따라서 서비스 제어 프로그램을 이용해서 서비스 프로그램을 제어(중지, 시작 등)한다.
[ 서비스 DB ]
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Service 레지스트리 (service.msc와 동일)]
1. 서비스 프로그램
[동작 Logic]
(Main_1) SCM에 서비스를 등록한다. - StartServiceCtrlDispatcher에서 Dispatcher Thread(서비스 함수)를 실행시킨다.
(ServiceMain_1) main에서 등록한 서비스 함수가 실행된다.
(ServiceMain_2) RegisterServiceCtrlHandler로 SCM에 핸들러를 등록한다.
(ServiceMain_3) 자신의 상태를 SCM에 전송한다.
(Handler) SCM에서 오는 제어는 핸들러 함수에서 처리한다.
(ServiceMain_4) 서비스에서 원하는 작업을 수행한다.
(Main_2) Dispatcher Thread(서비스 함수)가 모두 종료되면 StartServiceCtrlDispatcher가 리턴된다.
= 서비스 프로그램 C++ 코드 기본 틀 =
#include "Windows.h" SERVICE_STATUS_HANDLE g_hSrv; DWORD g_NowState; BOOL g_bPause; HANDLE Exit_Event; void ServiceMain1(DWORD argc, LPTSTR *argv); void ServiceHandler (DWORD fdwControl); void SetStatus ( DWORD dwState, DWORD dwAccept); // 메인 함수 int main(int argc, char* argv[]) { SERVICE_TABLE_ENTRY ste[] = { {L"TestService",(LPSERVICE_MAIN_FUNCTION)ServiceMain1}, {NULL, NULL} }; //SCM에 서비스를 등록한다. StartServiceCtrlDispatcher(ste); return 0; } // 서비스 메인함수 void ServiceMain1(DWORD argc, LPTSTR *argv) { //SCM의 제어를 처리할 핸들러 등록한다. g_hSrv = RegisterServiceCtrlHandler(L"TestService", (LPHANDLER_FUNCTION)ServiceHandler); if ( g_hSrv == 0) { return ; } //SCM에 작업이 시작됨을 알린다. SetStatus(SERVICE_START_PENDING, 3); // --- 필요한 초기화 작업 수행 SetStatus (SERVICE_RUNNING, 3); // --- 원하는 작업 수행 } // 핸들러 함수 void ServiceHandler (DWORD fdwControl) { if(fdwControl == g_NowState) return ; switch(fdwControl){ case SERVICE_CONTROL_PAUSE: SetStatus (SERVICE_PAUSE_PENDING,0); g_bPause=TRUE; SetStatus (SERVICE_PAUSED, 3); break; case SERVICE_CONTROL_CONTINUE: SetStatus (SERVICE_CONTINUE_PENDING,0); g_bPause=FALSE; SetStatus (SERVICE_RUNNING, 3); break; case SERVICE_CONTROL_STOP: SetStatus (SERVICE_STOP_PENDING,0); SetStatus (SERVICE_STOPPED,0); break; case SERVICE_CONTROL_INTERROGATE: default: SetStatus(g_NowState, 3); break; } } void SetStatus ( DWORD dwState, DWORD dwAccept) { SERVICE_STATUS ss; ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwCurrentState = dwState; ss.dwControlsAccepted = dwAccept; ss.dwWin32ExitCode = 0; ss.dwServiceSpecificExitCode = 0; ss.dwCheckPoint=0; ss.dwWaitHint =0; g_NowState = dwState; SetServiceStatus (g_hSrv, &ss); }
[REF]
http://blog.naver.com/shin5341?Redirect=Log&logNo=80035810083
'Programming > Win_API' 카테고리의 다른 글
Windows 버전 구별 - GetVerion() (0) | 2014.01.21 |
---|---|
Windows API - 서비스 제어 (0) | 2014.01.21 |
ANSI, WIDE, TCHAR 함수들 (0) | 2014.01.08 |
실행 중인 Class, Caption, Process 이름 구하기 (0) | 2014.01.08 |
API Hooking - [3] DLL Injection + Trampoline Code Hooking (0) | 2013.12.07 |