// ==================================================
// Приложение SRVCTRL
// Работа с сервисом "Sample of simple service"
//
// (С) Фролов А.В., 1996
// Email: frolov@glas.apc.org
// ==================================================

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include "resource.h"
#include "afxres.h"

#include "srvctrl.h"

HINSTANCE hInst;
char szAppName[]  = "ServiceCtlApp";
char szAppTitle[] = "Simple Service Control";

// Состояние сервиса
SERVICE_STATUS ss;

// -----------------------------------------------------
// Функция WinMain
// -----------------------------------------------------
int APIENTRY 
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
{
  WNDCLASSEX wc;
  HWND hWnd;
  MSG msg;
  
  // Сохраняем идентификатор приложения
  hInst = hInstance;

  // Преверяем, не было ли это приложение запущено ранее
  hWnd = FindWindow(szAppName, NULL);
  if(hWnd)
  {
    // Если было, выдвигаем окно приложения на
    // передний план
    if(IsIconic(hWnd))
	    ShowWindow(hWnd, SW_RESTORE);
	  SetForegroundWindow(hWnd);
    return FALSE;
  }

  // Регистрируем класс окна
  memset(&wc, 0, sizeof(wc));
  wc.cbSize = sizeof(WNDCLASSEX);
  wc.hIconSm = LoadImage(hInst,
    MAKEINTRESOURCE(IDI_APPICONSM), 
    IMAGE_ICON, 16, 16, 0);
  wc.style = 0;
  wc.lpfnWndProc = (WNDPROC)WndProc;
  wc.cbClsExtra  = 0;
  wc.cbWndExtra  = 0;
  wc.hInstance = hInst;
  wc.hIcon = LoadImage(hInst,
    MAKEINTRESOURCE(IDI_APPICON), 
    IMAGE_ICON, 32, 32, 0);
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = MAKEINTRESOURCE(IDR_APPMENU);
  wc.lpszClassName = szAppName;
  if(!RegisterClassEx(&wc))
    if(!RegisterClass((LPWNDCLASS)&wc.style))
	  return FALSE;
    
  // Создаем главное окно приложения
  hWnd = CreateWindow(szAppName, szAppTitle, 
     WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 
     NULL, NULL, hInst, NULL);
  if(!hWnd) return(FALSE);

  // Отображаем окно и запускаем цикл 
  // обработки сообщений
  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  while(GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return msg.wParam;
}

// -----------------------------------------------------
// Функция WndProc
// -----------------------------------------------------
LRESULT WINAPI
WndProc(HWND hWnd, UINT msg, WPARAM wParam, 
        LPARAM lParam)
{
  switch(msg)
  {
    HANDLE_MSG(hWnd, WM_COMMAND, WndProc_OnCommand);
    HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy);

	  default:
      return(DefWindowProc(hWnd, msg, wParam, lParam));
  }
}

// -----------------------------------------------------
// Функция WndProc_OnDestroy
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnDestroy(HWND hWnd)
{
  PostQuitMessage(0);
  return 0L;
}

// -----------------------------------------------------
// Функция WndProc_OnCommand
// -----------------------------------------------------
#pragma warning(disable: 4098)
void WndProc_OnCommand(HWND hWnd, int id, 
  HWND hwndCtl, UINT codeNotify)
{
  // Идентификатор сервиса
  SC_HANDLE schService;

  // Идентификатор системы управления сервисами
  SC_HANDLE schSCManager;

  LPQUERY_SERVICE_CONFIG  lpBuf;
  DWORD dwBytesNeeded;
  char szBuf[1024];
  
  switch (id)
  {
    case ID_FILE_EXIT:  
    {
	    // Завершаем работу приложения
      PostQuitMessage(0);
	    return 0L;
	    break;
    }
	  
    // Установка сервиса в систему
    case ID_SERVICE_INSTALL:
    {
      // Открываем систему управления сервисами
      schSCManager = OpenSCManager(NULL, NULL, 
        SC_MANAGER_ALL_ACCESS);

      if(!schSCManager)
        break;

      // Создаем сервис с именем MYServiceName
      schService = CreateService(
        schSCManager,
        MYServiceName,
        MYServiceName,
        SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START,
        SERVICE_ERROR_NORMAL,
        "c:\\ntbk2\\src\\service\\small\\debug\\small.exe",
        NULL,
        NULL,
        "",
        NULL,
        NULL);

      // Закрываем идентификатор системы управления
      // сервисами
      CloseServiceHandle(schSCManager);
	    break;
    }

    // Удаление сервиса из системы
    case ID_SERVICE_REMOVE:
    {
      // Открываем систему управления сервисами
      schSCManager = OpenSCManager(NULL, NULL, 
        SC_MANAGER_ALL_ACCESS);

      if(!schSCManager)
        break;

      // Открываем сервис с именем MYServiceName
      schService = OpenService(
        schSCManager, MYServiceName,
        SERVICE_ALL_ACCESS);

      if(!schService)
        break;

      // Останавливаем сервис
      ControlService(schService, 
        SERVICE_CONTROL_STOP, &ss);
      
      // Вызываем функцию удаления сервиса из системы
      DeleteService(schService);

      // Закрываем идентификатор системы управления
      // сервисами
      CloseServiceHandle(schSCManager);
	    break;
    }

    case ID_SERVICE_START:
    {
      // Открываем систему управления сервисами
      schSCManager = OpenSCManager(NULL, NULL, 
        SC_MANAGER_ALL_ACCESS);

      if(!schSCManager)
        break;

      // Открываем сервис с именем MYServiceName
      schService = OpenService(
        schSCManager, MYServiceName,
        SERVICE_ALL_ACCESS);

      if(!schService)
        break;

      // Запускаем сервис
      StartService(schService, 0, NULL);
      
      // Закрываем идентификатор системы управления
      // сервисами
      CloseServiceHandle(schSCManager);
      break;
    }

    case ID_SERVICE_STOP:
    {
      // Открываем систему управления сервисами
      schSCManager = OpenSCManager(NULL, NULL, 
        SC_MANAGER_ALL_ACCESS);

      if(!schSCManager)
        break;

      // Открываем сервис с именем MYServiceName
      schService = OpenService(
        schSCManager, MYServiceName,
        SERVICE_ALL_ACCESS);

      // Останавливаем сервис
      ControlService(schService, 
        SERVICE_CONTROL_STOP, &ss);
      
      // Закрываем идентификатор системы управления
      // сервисами
      CloseServiceHandle(schSCManager);
      break;
    }
    
    case ID_SERVICE_GETCONFIGURATION:
    {
      // Открываем систему управления сервисами
      schSCManager = OpenSCManager(NULL, NULL, 
        SC_MANAGER_ALL_ACCESS);

      if(!schSCManager)
        break;

      // Открываем сервис с именем MYServiceName
      schService = OpenService(
        schSCManager, MYServiceName,
        SERVICE_ALL_ACCESS);

      if(!schService)
        break;
      
      // Получаем буфер для сохранения конфигурации
      lpBuf = (LPQUERY_SERVICE_CONFIG)malloc(4096);
      
      if(lpBuf != NULL)
      {
        // Сохраняем конфигурацию в буфере
        QueryServiceConfig(schService, 
           lpBuf, 4096, &dwBytesNeeded);
        
        // Отображаем некоторые поля конфигурации
        wsprintf(szBuf, "Binary path: %s\n"
          "Start Name: %s\n"
          "Display Name: %s\n",
          lpBuf->lpBinaryPathName,
          lpBuf->lpServiceStartName,
          lpBuf->lpDisplayName);

        MessageBox(hWnd, szBuf, szAppTitle, 
          MB_OK | MB_ICONINFORMATION);

        // Освобождаем буфер
        free(lpBuf);
      }

      // Закрываем идентификатор системы управления
      // сервисами
      CloseServiceHandle(schSCManager);
      break;
    }
    
    case ID_HELP_ABOUT:
    {
      MessageBox(hWnd, 
        "Simple Service Control\n"
        "(C) Alexandr Frolov, 1996\n"
        "Email: frolov@glas.apc.org",
        szAppTitle, MB_OK | MB_ICONINFORMATION);
	     return 0L;
	     break;
    }

  	default:
	    break;
  }
  return FORWARD_WM_COMMAND(hWnd, id, hwndCtl, codeNotify,
    DefWindowProc);
}


