서비스를 동작시키기 위해서는 아래의 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 |