
/**
 * @file: scmDrivers.c
 *
 * Tento modul implementuje funkce, ktere dovoluji snadneji pracovat
 * s ovladaci jadra pres rozhrani spravce sluzeb (Service Control Manager).
 */

#include <stdio.h>
#include <windows.h>
#include <winsvc.h>
#include "..\..\shared\common.h"
#include "scmDrivers.h"


// Handle k databazi sluzeb s pravem "ziskat handle k libovolne sluzbe"
static SC_HANDLE hmanager_connect = NULL;

// Handle k databazi sluzeb s pravem "vytvaret nove sluzby"
static SC_HANDLE hmanager_inst = NULL;



/** Nainstaluje ovladac do systemu.
 *
 * Rutina vytvori sluzbu, ktera bude ovladac reprezentovat pri dalsich
 * operacich.
 *
 * @param DriverName Interni nazev nove sluzby.
 * @param FileName Plny nazev souboru ovladace.
 *
 * @return Funkce vraci TRUE v pripade uspechu a FALSE v pripade neuspechu.
 */
BOOL scmInstallDriver(IN PWCHAR DriverName, IN PWCHAR FileName)
{
  BOOL ret = FALSE;
  SC_HANDLE hservice = NULL;
  DebugMsg(("scmDrivers.c: scmInstallDriver(DriverName=%S; FileName=%S)\n", DriverName, FileName));

  hservice = CreateServiceW(hmanager_inst, DriverName, NULL, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, FileName, NULL, NULL, NULL, NULL, NULL);
  ret = hservice != NULL;
  if (ret)
    CloseServiceHandle(hservice);
  else DebugMsg(("scmDrivers.c: scmInstallDriver(): CreateServiceW failed. Error %u\n", GetLastError()));
	
  DebugMsg(("scmDrivers.c: scmInstallDriver(-):%u\n", ret));
  return ret;
}


/** Nacte ovladac do jadra pomoci rozhrani spravce sluzeb.
 *
 *  @param DriverName Interni jmeno sluzby ovladace.
 *
 *  @return Funkce vrati TRUE v pripade uspechu a FALSE v 
 *  pripade neuspechu.
 */
BOOL scmLoadDriver(IN PWCHAR DriverName)
{
  SC_HANDLE hservice = NULL;
  BOOL ret = FALSE;
  DebugMsg(("scmDrivers.c: scmLoadDriver(DriverName=%S)\n", DriverName));

  hservice = OpenServiceW(hmanager_connect, DriverName, SERVICE_START);
  ret = hservice != NULL;
  if (ret) {
    ret = StartService(hservice, 0, NULL);
    if (!ret)
      DebugMsg(("scmDrivers.c: scmLoadDriver(): StartService failed. Error %u\n", GetLastError()));
	
    CloseServiceHandle(hservice);
  } else DebugMsg(("scmDrivers.c: scmLoadDriver(): OpenServiceW failed. Error %u\n", GetLastError()));

  DebugMsg(("scmDrivers.c: scmLoadDriver(-):%u\n", ret));
  return ret;
}


/** Uvolni ovladac z jadra pomoci rozhrani psravce sluzeb.
 *
 * @param DriverName Interni nazev sluzby ovladace.
 *
 * @return Funkce vrati TRUE v pripade uspechu a FALSE v 
 * pripade neuspechu.
 */
BOOL scmUnloadDriver (IN PWCHAR DriverName)
{
  SERVICE_STATUS ss;
  SC_HANDLE hservice = NULL;
  BOOL ret = FALSE;
  DebugMsg(("scmDrivers.c: scmUnloadDriver(DriverName=%S)\n", DriverName));

  hservice = OpenServiceW(hmanager_connect, DriverName, SERVICE_STOP);
  ret = hservice != NULL;
  if (ret) {
    ret = ControlService(hservice, SERVICE_CONTROL_STOP, &ss);
    if (!ret)
      DebugMsg(("scmDrivers.c: scmUnloadDriver(): ControlService failed. Error %u\n", GetLastError()));

    CloseServiceHandle(hservice);
  } else DebugMsg(("scmDrivers.c: scmUnloadDriver(): OpenServiceW failed. Error %u\n", GetLastError()));

  DebugMsg(("scmDrivers.c: scmUnloadDriver(-):%u\n", ret));
  return ret;
}


/** Odinstaluje ovladac pomoci rozhrani spravce sluzeb.
 *
 * Efektem uspesneho volani teto rutiny je odstraneni podklice sluzby
 * ovladace z registru.
 *
 * @param DriverName Interni nazev sluzby ovladace.
 *
 * @return Funkce vraci TRUE v pripade uspechu a FALSE 
 * v pripade neuspechu.
 */
BOOL scmUninstallDriver (IN PWCHAR DriverName)
{
  SC_HANDLE hservice = NULL;
  BOOL ret = FALSE;
  DebugMsg(("scmDrivers.c: scmUninstallDriver(DriverName=%S)\n", DriverName));

  hservice = OpenServiceW(hmanager_connect, DriverName, DELETE);
  ret = hservice != NULL;
  if (ret) {
    ret = DeleteService(hservice);
    if (!ret)
      DebugMsg(("scmDrivers.c: scmUninstallDriver(): DeleteService failed. Error %u\n", GetLastError()));

    CloseServiceHandle(hservice);
  } else DebugMsg(("scmDrivers.c: scmUninstallDriver(): OpenServiceW failed. Error %u\n", GetLastError()));

  DebugMsg(("scmDrivers.c: scmUninstallDriver(-):%u\n", ret));
  return ret;
}



/** Zjisti, zda sluzba zadaneho jmena existuje.
 *
 *  @param ServiceName Interni jmeno sluzby.
 *
 *  @return Funkce vrati TRUE, pokud sluzba existuje a FALSE v ostatnich
 *  pripadech.
 */
BOOL scmServiceExists(IN PWCHAR ServiceName)
{
  SC_HANDLE hmanager = NULL;
  SC_HANDLE hservice = NULL;
  BOOL ret = FALSE;
  DebugMsg(("scmDrivers.c: scmServiceExists(ServiceName=%S)\n", ServiceName));

  hservice = OpenServiceW(hmanager_connect, ServiceName, SERVICE_QUERY_STATUS);
  ret = hservice != NULL;
  if (ret)
    CloseServiceHandle(hservice);

  DebugMsg(("scmDrivers.c: scmServiceExists(-):%u\n", ret));
  return ret;
}



/** Inicializuje modul pro praci s ovladaci pres rozhrani spravce sluzeb.
 *
 *  Rutina ziska handle k databazi sluzeb s opravnenim pro instalaci
 *  novych sluzeb a ziskani libovolneho opravneni k jiz existujicim sluzbam.
 */
BOOL scmInit(VOID)
{
  BOOL ret = FALSE;
  DebugMsg(("scmDrivers.c: scmInit()\n"));

  hmanager_connect = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
  ret = hmanager_connect != NULL;
  if (ret) {
    hmanager_inst = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
    ret = hmanager_inst != NULL;
    if (!ret) {
	  DebugMsg(("scmDrivers.c: scmInit(): OpenSCManagerW(SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE) failed. Error %u\n", GetLastError()));
      CloseServiceHandle(hmanager_connect);
    }
  } else DebugMsg(("scmDrivers.c: scmInit(): OpenSCManager(SC_MANAGER_CONNECT) failed. Error %u\n", GetLastError()));

  DebugMsg(("scmDrivers.c: scmInit(-):%u\n", ret));
  return ret;
}


/** Provede uklid po modulu pracujicim s ovladaci pres rozhrani
 *  spravce sluzeb.
 *
 * Rutina zrusi obe handle k databazi sluzeb vytvorena pri inicializaci
 * modulu.
 */
VOID scmFinit(VOID)
{
  DebugMsg(("scmDrivers.c: scmFinit()\n"));

  if (hmanager_inst != NULL)
    CloseServiceHandle(hmanager_inst);
  
  if (hmanager_connect != NULL)
    CloseServiceHandle(hmanager_connect);

  DebugMsg(("scmDrivers.c: scmFinit(-)\n"));
  return;
}
