Jenter Алекс
Шрифт:
sStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
sStatus.dwServiceSpecificExitCode = 0;
sStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
sStatus.dwWaitHint = 0;
sStatus.dwWin32ExitCode = NOERROR;
// Для инициализации службы вызывается функция InitService;
// Для того, чтобы в процессе инициализации система не
// выгрузила службу, запускается поток, который раз в
// секунду сообщает, что служба в процессе инициализации.
// Для синхронизации потока создаётся событие.
// После этого запускается рабочий поток, для
// синхронизации которого также
// создаётся событие.
hSendStartPending = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE hSendStartThread;
DWORD dwThreadId;
hSendStartThread = CreateThread(NULL, 0, SendStartPending, NULL, 0, &dwThreadId);
//Здесь производится вся инициализация службы.
InitService;
SetEvent(hSendStartPending);
if (WaitForSingleObject(hSendStartThread, 2000) != WAIT_OBJECT_0) {
TerminateThread(hSendStartThread, 0);
}
CloseHandle(hSendStartPending);
CloseHandle(hSendStartThread);
hWork = CreateEvent(NULL, TRUE, FALSE, NULL);
hServiceThread = CreateThread(NULL, 0, ServiceFunc, 0, 0, &dwThreadId);
sStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hSS, &sStatus);
}
// Функция потока, каждую секунду посылающая уведомления SCM
// о том, что процесс инициализации идёт. Работа функции
// завершается, когда устанавливается
// событие hSendStartPending.
DWORD WINAPI SendStartPending(LPVOID) {
sStatus.dwCheckPoint = 0;
sStatus.dwCurrentState = SERVICE_START_PENDING;
sStatus.dwWaitHint = 2000;
// "Засыпаем" на 1 секунду. Если через 1 секунду
// событие hSendStartPending не перешло
// в сигнальное состояние (инициализация службы не
// закончилась), посылаем очередное уведомление,
// установив максимальный интервал времени
// в 2 секунды, для того, чтобы был запас времени до
// следующего уведомления.
while (true) {
SetServiceStatus(hSS, &sStatus);
sStatus.dwCheckPoint++;
if (WaitForSingleObject(hSendStartPending, 1000) != WAIT_TIMEOUT) break;
}
sStatus.dwCheckPoint = 0;
return 0;
}
// Функция, инициализирующая службу. Чтение данных,
// распределение памяти и т.п.
void InitService {
...
}
// Функция, содержащая «полезный» код службы.
DWORD WINAPI ServiceFunc(LPVOID) {
while (true) {
if (!bPause) {
// Здесь содержится код, который как правило
// выполняет какие-либо циклические операции...
}
if (WaitForSingleObject(hWork, 1000) != WAIT_TIMEOUT) break;
sStatus.dwCheckPoint = 0;
return 0;
}
}
Функция Handler
А вот код функции Handler и вспомогательных потоков:
// Обработчик запросов от SCM
void WINAPI ServiceHandler(DWORD dwCode) {
switch (dwCode) {
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0, 1000);