Сервисы (службы) в Delphi на чистом API

Часть 1 Основные понятия

Вот так получилось нужно было по работе написать сервис но не хотелось пользоваться классами Delphi, так как код написанный с применением оных большой, а хотелось чего-нибудь поменьше, то есть на API, но к сожелению видно этим никто не занимался в Delphi (примеров на Си более чем достаточно), вот и родилась идея этого обзора. Что же это сервис(еще их называют службами)??? Попробую рассказать как умею...

В любой операционной системе, нужны программы которые работают в фоновом режиме (это нужно например для различных серверов СУБД, сетевые приложения, программ мониторинга следящих за чем то и т.д. и т.п), в Unix-системах такие программы называются демонами, в DOS они назывались TSR (Terminate and Stay Resident). В NT и 2000(далее я буду называть их только для NT, что подразумевает под сообой и 2000) Windows такие программы называются сервисами (или службами).Сервис NT (Windows NT service) - процесс, обладающий специальным интерфейсом для взаимодействия с операционной системой Windows NT. Сервисы бывают двух типов - сервисы Win32, взаимодействующие с операционной системой посредством диспетчера управления сервисами (Service Control Manager - SCM), и драйвера, работающие по протоколу драйвера устройства Windows NT. Я буду рассказывать только про сервисы Win32. Сервисы доступны в панели управления. Запустив Service Applet, вы увидите список доступных сервисов. Вы можете запускать, останавливать, ставить сервисы на паузу. Нажав кнопку Startup, Вы можете изменить поведение сервиса при запуске. Сервисы могут запускаться автоматически при старте компьютера, быть абсолютно выключеными или иметь возможность запуска вручную. Если сервис запускается вручную, то пользователь может указать параметры запуска. Для управления сервисами Вам нужны права администратора или права power user. ОС использует много сервисов и информацию о каждом из них пишет в реестр в ключ "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services".Там содержатся следующие сведения:
Тип службы.
Указывает на то, реализован ли в данной программе только один сервис (эксклюзивный) или же их несколько. Эксклюзивный сервис может работать в любом контексте безопасности. Несколько сервисов внутри одного приложения могут работать только в контексте LocalSystem.
Способ запуска.
Автоматический - сервис запускается при старте системы. По требованию - сервис запускается пользователем вручную. Деактивированный - сервис не может быть запущен.
Имя исполняемого EXE-файла.
Порядок запуска по отношению к другим сервисам.
В некоторых случаях для корректной работы сервиса требуется, чтобы был запущен один или несколько других сервисов. В этом случае в реестре содержится информация о сервисах, запускаемых перед данным сервисом.
Контекст безопасности
Здесь хранится сетевое имя и пароль. По умолчанию контекст безопасности соответствует LocalSystem.

Любая программа, имеющее соответствующие права, может взаимодействовать с сервисом. Это подразумевает изменение состояния сервиса (Вы можете изменить состояния сервиса используя Service Applet), то есть перевод его в одно из трех состояний - активный (сервис работает), приостоновленный (работа сервиса приостановлена), полная остановка и осуществляется при помощи посылки запросов SCM.
Запросы бывают трех типов:
Сообщения от сервисов (фиксация их состояний).
Запросы, связанные с изменением конфигурации сервиса или получением информации о нем.
Запросы приложений на изменение состояния сервиса.

Для управления сервисом необходимо в первую очередь получить дескриптор с помощью функции OpenService. Функция StartService запускает сервис. Изменение состояния сервиса производится вызовом функции ControlService.
С помощью определенных функций вы можете изменить информацию о сервисе, тем самым и в реестре.
OpenSCManager, CreateService, OpenService, CloseServiceHandle - для создания (открытия) сервиса.
QueryServiceConfig, QueryServiceObjectSecurity, EnumDependentServices, EnumServicesStatus - для получения информации о сервисе.
ChangeServiceConfig, SetServiceObjectSecurity, LockServiceDatabase, UnlockServiceDatabase, QueryServiceLockStatus - для изменения конфигурационной информации сервиса.

В принципе как было сказано сервис - это в принципе обычный exe-файл поддерживающий интерфейс SCM, только имеющий определенное строение. Для того чтобы стать сервисом программа должна быть построена соответствующим образом(т.е. иметь набор определенных функций). В следующей части я подробно расскажу об этом.

Описание функций для работы с сервисами (постепенно будут добавлены описания для всех функций), большая часть из них объявлена в WinSvc.Pas.

ChangeServiceConfig
Изменяет параметры конфигурации сервиса
ChangeServiceConfig2
Изменяет необязательные параметры конфигурации сервиса
CloseServiceHandle
Закрывает указанный дескриптор к сервисному объекту
ControlService
Посылает сервису управляющий код
CreateService
Создает сервисный объект
DeleteService Удаляет сервис из базы данных диспетчеров сервисов
EnumDependentServices Перечисляет зависимые сервисы
EnumServicesStatus Перечисляет сервисы
EnumServicesStatusEx Перечисляет сервисы
GetServiceDisplayName Возвращает отображаемое имя сервиса
GetServiceKeyName Возвращает имя сервиса
Handler Функция обработки управляющих кодов
HandlerEx Функция обработки управляющих кодов
LockServiceDatabase Блокирует базу данных сервисов
NotifyBootConfigStatus Уведомляет о приеме загрузочной информации
OpenSCManager Подключает приложение к менеджеру сервисов
OpenService Открывает сервис
QueryServiceConfig Запрашивает параметры конфигурации
QueryServiceConfig2 Запрашивает необязательные параметры конфигурации
QueryServiceLockStatus Запрашивает статус блокировки
QueryServiceObjectSecurity Запрашивает дескриптор безопасности
QueryServiceStatus Запрашивает статус сервиса
QueryServiceStatusEx Запрашивает статус сервиса
RegisterServiceCtrlHandler Регистрирует обработчик запросов
RegisterServiceCtrlHandlerEx Регистрирует обработчик запросов
ServiceMain Главная функция сервиса
SetServiceBits Обноволяет статус сервиса для диспетчера сервисов
SetServiceObjectSecurity Изменяет дескриптор безопасности сервисного объекта
SetServiceStatus Устанавливает статус сервиса
StartService Запускает сервис
StartServiceCtrlDispatcher Запускает поток
UnlockServiceDatabase Разблокирование базы данных

Также при написание сервиса используются такие структуры(описания их то же постепенно будут добавлятся).

ENUM_SERVICE_STATUS
ENUM_SERVICE_STATUS_PROCESS
QUERY_SERVICE_CONFIG
QUERY_SERVICE_LOCK_STATUS
SC_ACTION
SERVICE_DESCRIPTION
SERVICE_FAILURE_ACTIONS
SERVICE_STATUS
SERVICE_STATUS_PROCESS
SERVICE_TABLE_ENTRY

Но вот и все для основных понятий...Вообще сервисы довольно сильно облегчают жизнь программисту, и понимание их работы (даже не используя) полезны, не только программистам, но и системным администраторам и пользователям.

В статье использованы материалы из Microsoft SDK(Эта статья входит в рамки проекта DSDN).

С удовольствием выслушаю все комментария и замечания по поводу данной статьи. Сразу хочу предупредить, я не отвечаю на письма где меня просят выслать что либо или будет ли продолжение(и подобные письма не несущие какой-то содержательной части), я их читаю, но отвечать на них у меня времени нет. Также , если кто обнаружит неточности, да и просто грамматические ошибки в статье, за это прошу заранее извинение.

Желаю удачи в темных делах.
С уважением Алексей.