Исходный текст сервиса
Исходный текст сервиса представлен в листинге 5.1. Так как ранее мы уже подробно описывали структуру этого сервиса, то мы оставим вам этот листинг и листинг приложения SRVCTRL на самостоятельное изучение.
Листинг 5.1. Файл service/small/small.c
// ==================================================
// Сервис "Sample of simple service"
// Шаблон простейшего сервиса Windows NT
//
// (С) Фролов А.В., 1996
// Email: frolov@glas.apc.org
// ==================================================
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include "small.h"
// -----------------------------------------------------
// Глобальные переменные
// -----------------------------------------------------
// Код ошибки
DWORD dwErrCode;
// Текущее состояние сервиса
SERVICE_STATUS ss;
// Идентификатор сервиса
SERVICE_STATUS_HANDLE ssHandle;
// -----------------------------------------------------
// Функция main
// Точка входа процесса
// -----------------------------------------------------
void main(int agrc, char *argv[])
{
// Таблица точек входа
SERVICE_TABLE_ENTRY DispatcherTable[] =
{
{
// Имя сервиса
MYServiceName,
// Функция main сервиса
(LPSERVICE_MAIN_FUNCTION)ServiceMain
},
{
NULL,
NULL
}
};
printf("Sample of simple service\n"
"(C) A. Frolov, 1996, Email: frolov@glas.apc.org\n");
// Запуск диспетчера
if(!StartServiceCtrlDispatcher(DispatcherTable))
{
fprintf(stdout,
"StartServiceCtrlDispatcher: Error %ld\n",
GetLastError());
getch();
return;
}
}
// -----------------------------------------------------
// Функция ServiceMain
// Точка входа сервиса
// -----------------------------------------------------
void WINAPI ServiceMain(DWORD argc, LPSTR *argv)
{
// Регистрируем управляющую функцию сервиса
ssHandle =
RegisterServiceCtrlHandler(MYServiceName, ServiceControl);
if(!ssHandle)
return;
// Устанавливаем состояние сервиса
// Сервис работает как отдельный процесс
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
// Код ошибки при инициализации и завершения сервиса
// не используется
ss.dwServiceSpecificExitCode = 0;
// Начинаем запуск сервиса.
// Прежде всего устанавливаем состояние ожидания
// запуска сервиса
ReportStatus(SERVICE_START_PENDING, NO_ERROR, 4000);
// Вызываем функцию, которая выполняет все
// необходимые инициализирующие действия
// ServiceStart(argc, argv);
// После завершения инициализации устанавливаем
// состояние работающего сервиса
ReportStatus(SERVICE_RUNNING, NOERROR, 0);
return;
}
// -----------------------------------------------------
// Функция ServiceControl
// Точка входа функции обработки команд
// -----------------------------------------------------
void WINAPI ServiceControl(DWORD dwControlCode)
{
// Анализируем код команды и выполняем эту команду
switch(dwControlCode)
{
// Команда остановки сервиса
case SERVICE_CONTROL_STOP:
{
// Устанавливаем состояние ожидания остановки
ss.dwCurrentState = SERVICE_STOP_PENDING;
ReportStatus(ss.dwCurrentState, NOERROR, 0);
// Выполняем остановку сервиса, вызывая функцию,
// которая выполняет все необходимые для этого действия
// ServiceStop();
// Отмечаем состояние как остановленный сервис
ReportStatus(SERVICE_STOPPED, NOERROR, 0);
break;
}
// Определение текущего состояния сервиса
case SERVICE_CONTROL_INTERROGATE:
{
// Возвращаем текущее состояние сервиса
ReportStatus(ss.dwCurrentState, NOERROR, 0);
break;
}
// В ответ на другие команды просто возвращаем
// текущее состояние сервиса
default:
{
ReportStatus(ss.dwCurrentState, NOERROR, 0);
break;
}
}
}
// -----------------------------------------------------
// Функция ReportStatus
// Посылка состояния сервиса системе управления сервисами
// -----------------------------------------------------
void ReportStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
// Счетчик шагов длительных операций
static DWORD dwCheckPoint = 1;
// Если сервис не находится в процессе запуска,
// его можно остановить
if(dwCurrentState == SERVICE_START_PENDING)
ss.dwControlsAccepted = 0;
else
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
// Сохраняем состояние, переданное через
// параметры функции
ss.dwCurrentState = dwCurrentState;
ss.dwWin32ExitCode = dwWin32ExitCode;
ss.dwWaitHint = dwWaitHint;
// Если сервис не работает и не остановлен,
// увеличиваем значение счетчика шагов
// длительных операций
if((dwCurrentState == SERVICE_RUNNING)
(dwCurrentState == SERVICE_STOPPED))
ss.dwCheckPoint = 0;
else
ss.dwCheckPoint = dwCheckPoint++;
// Вызываем функцию установки состояния
SetServiceStatus(ssHandle, &ss);
}
В файле small.h (листинг 5.2) определено имя сервиса MYServiceName и прототипы функций.
Листинг 5.2. Файл service/small/small.h
#define MYServiceName "Sample of simple service"
void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArv);
void WINAPI ServiceControl(DWORD dwControlCode);
void ReportStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode, DWORD dwWaitHint);