Программирование для Windows NT (том 2)

       

Исходный текст сервиса


Исходный текст сервиса представлен в листинге 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);


Содержание раздела