Blame snmplib/winservice.c

Packit fcad23
/*
Packit fcad23
 * Windows Service related function definitions
Packit fcad23
 * By Raju Krishnappa(raju_krishnappa@yahoo.com)
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
Packit fcad23
#ifdef WIN32
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
Packit fcad23
#include <windows.h>
Packit fcad23
#include <tchar.h>
Packit fcad23
Packit fcad23
#include <stdio.h>		/* sprintf */
Packit fcad23
#include <process.h>		/* beginthreadex  */
Packit fcad23
Packit fcad23
#include <net-snmp/library/winservice.h>
Packit fcad23
Packit fcad23
#ifdef mingw32 /* MinGW doesn't fully support exception handling. */
Packit fcad23
Packit fcad23
#define TRY if(1)
Packit fcad23
#define LEAVE goto labelFIN
Packit fcad23
#define FINALLY do { \
Packit fcad23
labelFIN: \
Packit fcad23
	; \
Packit fcad23
} while(0); if(1)
Packit fcad23
Packit fcad23
#else
Packit fcad23
Packit fcad23
#define TRY __try
Packit fcad23
#define LEAVE __leave
Packit fcad23
#define FINALLY __finally
Packit fcad23
Packit fcad23
#endif /* mingw32 */
Packit fcad23
Packit fcad23
Packit fcad23
#define CountOf(arr) ( sizeof(arr) / sizeof(arr[0]) )
Packit fcad23
Packit fcad23
Packit fcad23
#if defined(WIN32) && defined(HAVE_WIN32_PLATFORM_SDK) && !defined(mingw32)
Packit fcad23
#pragma comment(lib, "iphlpapi.lib")
Packit fcad23
#endif
Packit fcad23
#if defined(WIN32) && !defined(mingw32)
Packit fcad23
#ifdef USING_WINEXTDLL_MODULE
Packit fcad23
#pragma comment(lib, "snmpapi.lib")
Packit fcad23
#pragma comment(lib, "mgmtapi.lib")
Packit fcad23
#endif
Packit fcad23
#endif
Packit fcad23
Packit fcad23
 
Packit fcad23
    /*
Packit fcad23
     * External global variables used here
Packit fcad23
     */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Application Name 
Packit fcad23
     * This should be declared by the application, which wants to register as
Packit fcad23
     * windows service
Packit fcad23
     */
Packit fcad23
extern LPTSTR app_name_long;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Declare global variable
Packit fcad23
     */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Flag to indicate whether process is running as Service 
Packit fcad23
     */
Packit fcad23
BOOL g_fRunningAsService = FALSE;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Variable to maintain Current Service status 
Packit fcad23
     */
Packit fcad23
static SERVICE_STATUS ServiceStatus;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Service Handle 
Packit fcad23
     */
Packit fcad23
static SERVICE_STATUS_HANDLE hServiceStatus = 0L;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Service Table Entry 
Packit fcad23
     */
Packit fcad23
SERVICE_TABLE_ENTRY ServiceTableEntry[] = {
Packit fcad23
  {NULL, ServiceMain},		/* Service Main function */
Packit fcad23
  {NULL, NULL}
Packit fcad23
};
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Handle to Thread, to implement Pause, Resume and Stop functions
Packit fcad23
     */
Packit fcad23
static HANDLE hServiceThread = NULL;	/* Thread Handle */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Holds calling partys Function Entry point, that should start
Packit fcad23
     * when entering service mode
Packit fcad23
     */
Packit fcad23
static INT (*ServiceEntryPoint) (INT Argc, LPTSTR Argv[]) = 0L;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * To hold Stop Function address, to be called when STOP request
Packit fcad23
     * received from the SCM
Packit fcad23
     */
Packit fcad23
static VOID (*StopFunction) (VOID) = 0L;
Packit fcad23
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * To update windows service status to SCM 
Packit fcad23
     */
Packit fcad23
static BOOL UpdateServiceStatus (DWORD dwStatus, DWORD dwErrorCode,
Packit fcad23
				 DWORD dwWaitHint);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * To Report current service status to SCM 
Packit fcad23
     */
Packit fcad23
static BOOL ReportCurrentServiceStatus (VOID);
Packit fcad23
Packit fcad23
VOID
Packit fcad23
ProcessError (WORD eventLogType, LPCTSTR pszMessage, int useGetLastError, int quiet);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * To register as Windows Service with SCM(Service Control Manager)
Packit fcad23
     * Input - Service Name, Service Display Name,Service Description and
Packit fcad23
     * Service startup arguments
Packit fcad23
     */
Packit fcad23
int
Packit fcad23
RegisterService (LPCTSTR lpszServiceName, LPCTSTR lpszServiceDisplayName,
Packit fcad23
		 LPCTSTR lpszServiceDescription,
Packit fcad23
		 InputParams * StartUpArg, int quiet) /* Startup argument to the service */
Packit fcad23
{
Packit fcad23
  TCHAR szServicePath[MAX_PATH];	/* To hold module File name */
Packit fcad23
  TCHAR MsgErrorString[MAX_STR_SIZE];	/* Message or Error string */
Packit fcad23
  TCHAR szServiceCommand[MAX_PATH + 9];	/* Command to execute */
Packit fcad23
  SC_HANDLE hSCManager = NULL;
Packit fcad23
  SC_HANDLE hService = NULL;
Packit fcad23
  TCHAR szRegAppLogKey[] =
Packit fcad23
    _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
Packit fcad23
  TCHAR szRegKey[512];
Packit fcad23
  HKEY hKey = NULL;		/* Key to registry entry */
Packit fcad23
  HKEY hParamKey = NULL;	/* To store startup parameters */
Packit fcad23
  DWORD dwData;			/* Type of logging supported */
Packit fcad23
  DWORD i, j;			/* Loop variables */
Packit fcad23
  int exitStatus = 0;
Packit fcad23
  GetModuleFileName (NULL, szServicePath, MAX_PATH);
Packit fcad23
  TRY
Packit fcad23
  {
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Open Service Control Manager handle 
Packit fcad23
     */
Packit fcad23
    hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
Packit fcad23
    if (hSCManager == NULL)
Packit fcad23
      {
Packit fcad23
        ProcessError (EVENTLOG_ERROR_TYPE, _T ("Can't open SCM (Service Control Manager)"), 1, quiet);
Packit fcad23
        exitStatus = SERVICE_ERROR_SCM_OPEN;
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Generate the command to be executed by the SCM 
Packit fcad23
     */
Packit fcad23
    _sntprintf(szServiceCommand, CountOf(szServiceCommand), _T("\"%s\" %s"),
Packit fcad23
               szServicePath, _T("-service"));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Create the desired service 
Packit fcad23
     */
Packit fcad23
    hService = CreateService (hSCManager, lpszServiceName, lpszServiceDisplayName,
Packit fcad23
			SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
Packit fcad23
			SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szServiceCommand,
Packit fcad23
			      NULL,	/* load-order group */
Packit fcad23
			      NULL,	/* group member tag */
Packit fcad23
			      NULL,	/* dependencies */
Packit fcad23
			      NULL,	/* account */
Packit fcad23
			      NULL);	/* password */
Packit fcad23
    if (hService == NULL)
Packit fcad23
      {
Packit fcad23
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
Packit fcad23
		   _T ("Can't create service"), lpszServiceDisplayName);
Packit fcad23
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
Packit fcad23
        exitStatus = SERVICE_ERROR_CREATE_SERVICE;
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Create registry entries for the event log 
Packit fcad23
     */
Packit fcad23
    /*
Packit fcad23
     * Create registry Application event log key 
Packit fcad23
     */
Packit fcad23
    _tcscpy (szRegKey, szRegAppLogKey);
Packit fcad23
    _tcscat (szRegKey, lpszServiceName);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Create registry key 
Packit fcad23
     */
Packit fcad23
    if (RegCreateKey (HKEY_LOCAL_MACHINE, szRegKey, &hKey) != ERROR_SUCCESS)
Packit fcad23
      {
Packit fcad23
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
Packit fcad23
		   _T ("is unable to create registry entries"), lpszServiceDisplayName);
Packit fcad23
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
        exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Add Event ID message file name to the 'EventMessageFile' subkey 
Packit fcad23
     */
Packit fcad23
    RegSetValueEx (hKey, _T("EventMessageFile"), 0, REG_EXPAND_SZ,
Packit fcad23
		   (CONST BYTE *) szServicePath,
Packit fcad23
		   _tcslen (szServicePath) + sizeof (TCHAR));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Set the supported types flags. 
Packit fcad23
     */
Packit fcad23
    dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
Packit fcad23
    RegSetValueEx (hKey, _T("TypesSupported"), 0, REG_DWORD,
Packit fcad23
		   (CONST BYTE *) & dwData, sizeof (DWORD));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Close Registry key 
Packit fcad23
     */
Packit fcad23
    RegCloseKey (hKey);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Set Service Description String  and save startup parameters if present
Packit fcad23
     */
Packit fcad23
    if (lpszServiceDescription != NULL || StartUpArg->Argc > 2)
Packit fcad23
      {
Packit fcad23
	/*
Packit fcad23
	 * Create Registry Key path 
Packit fcad23
	 */
Packit fcad23
	_tcscpy (szRegKey, _T ("SYSTEM\\CurrentControlSet\\Services\\"));
Packit fcad23
	_tcscat (szRegKey, app_name_long);
Packit fcad23
	hKey = NULL;
Packit fcad23
Packit fcad23
	/*
Packit fcad23
	 * Open Registry key using Create and Set access. 
Packit fcad23
	 */
Packit fcad23
	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_WRITE,
Packit fcad23
			  &hKey) != ERROR_SUCCESS)
Packit fcad23
	  {
Packit fcad23
	    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
Packit fcad23
		       _T ("is unable to create registry entries"),
Packit fcad23
		       lpszServiceDisplayName);
Packit fcad23
            ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
            exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
Packit fcad23
	    LEAVE;
Packit fcad23
	  }
Packit fcad23
Packit fcad23
	/*
Packit fcad23
	 * Create description subkey and the set value 
Packit fcad23
	 */
Packit fcad23
	if (lpszServiceDescription != NULL)
Packit fcad23
	  {
Packit fcad23
	    if (RegSetValueEx (hKey, _T("Description"), 0, REG_SZ,
Packit fcad23
			       (CONST BYTE *) lpszServiceDescription,
Packit fcad23
			       _tcslen (lpszServiceDescription) +
Packit fcad23
			       sizeof (TCHAR)) != ERROR_SUCCESS)
Packit fcad23
	      {
Packit fcad23
		_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
Packit fcad23
			   _T ("is unable to create registry entries"),
Packit fcad23
			   lpszServiceDisplayName);
Packit fcad23
                ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
                exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
Packit fcad23
		LEAVE;
Packit fcad23
	      };
Packit fcad23
	  }
Packit fcad23
Packit fcad23
	/*
Packit fcad23
	 * Save startup arguments if they are present 
Packit fcad23
	 */
Packit fcad23
	if (StartUpArg->Argc > 2)
Packit fcad23
	  {
Packit fcad23
	    /*
Packit fcad23
	     * Create Subkey parameters 
Packit fcad23
	     */
Packit fcad23
	    if (RegCreateKeyEx
Packit fcad23
		(hKey, _T("Parameters"), 0, NULL,
Packit fcad23
		 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
Packit fcad23
		 &hParamKey, NULL) != ERROR_SUCCESS)
Packit fcad23
	      {
Packit fcad23
		_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
Packit fcad23
			   _T ("is unable to create registry entries"),
Packit fcad23
			   lpszServiceDisplayName);
Packit fcad23
                ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
                exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
Packit fcad23
                LEAVE;
Packit fcad23
	      }
Packit fcad23
Packit fcad23
	    /*
Packit fcad23
	     * Save parameters 
Packit fcad23
	     */
Packit fcad23
Packit fcad23
	    /*
Packit fcad23
	     * Loop through arguments 
Packit fcad23
	     */
Packit fcad23
            if (quiet) /* Make sure we don't store -quiet arg */
Packit fcad23
              i = 3;
Packit fcad23
            else
Packit fcad23
              i = 2;
Packit fcad23
Packit fcad23
	    for (j = 1; i < StartUpArg->Argc; i++, j++)
Packit fcad23
	      {
Packit fcad23
		_sntprintf (szRegKey, CountOf(szRegKey), _T("%s%d"), _T ("Param"), j);
Packit fcad23
Packit fcad23
		/*
Packit fcad23
		 * Create registry key 
Packit fcad23
		 */
Packit fcad23
		if (RegSetValueEx
Packit fcad23
		    (hParamKey, szRegKey, 0, REG_SZ,
Packit fcad23
		     (CONST BYTE *) StartUpArg->Argv[i],
Packit fcad23
		     _tcslen (StartUpArg->Argv[i]) +
Packit fcad23
		     sizeof (TCHAR)) != ERROR_SUCCESS)
Packit fcad23
		  {
Packit fcad23
		    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
Packit fcad23
			       _T ("is unable to create registry entries"),
Packit fcad23
			       lpszServiceDisplayName);
Packit fcad23
                    ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
                    exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
Packit fcad23
		    LEAVE;
Packit fcad23
		  };
Packit fcad23
	      }
Packit fcad23
	  }
Packit fcad23
Packit fcad23
	/*
Packit fcad23
	 * Everything is set, delete hKey 
Packit fcad23
	 */
Packit fcad23
	RegCloseKey (hParamKey);
Packit fcad23
	RegCloseKey (hKey);
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Ready to log messages 
Packit fcad23
     */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Successfully registered as service 
Packit fcad23
     */
Packit fcad23
    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), lpszServiceName,
Packit fcad23
	       _T ("successfully registered as a service"));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Log message to eventlog 
Packit fcad23
     */
Packit fcad23
    ProcessError (EVENTLOG_INFORMATION_TYPE, MsgErrorString, 0, quiet);
Packit fcad23
  }
Packit fcad23
Packit fcad23
  FINALLY
Packit fcad23
  {
Packit fcad23
    if (hSCManager)
Packit fcad23
      CloseServiceHandle (hSCManager);
Packit fcad23
    if (hService)
Packit fcad23
      CloseServiceHandle (hService);
Packit fcad23
    if (hKey)
Packit fcad23
      RegCloseKey (hKey);
Packit fcad23
    if (hParamKey)
Packit fcad23
      RegCloseKey (hParamKey);
Packit fcad23
  }
Packit fcad23
  return (exitStatus);
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Unregister the service with the  Windows SCM 
Packit fcad23
     * Input - ServiceName
Packit fcad23
     */
Packit fcad23
int
Packit fcad23
UnregisterService (LPCTSTR lpszServiceName, int quiet)
Packit fcad23
{
Packit fcad23
  TCHAR MsgErrorString[MAX_STR_SIZE];	/* Message or Error string */
Packit fcad23
  SC_HANDLE hSCManager = NULL;	/* SCM handle */
Packit fcad23
  SC_HANDLE hService = NULL;	/* Service Handle */
Packit fcad23
  SERVICE_STATUS sStatus;
Packit fcad23
  TCHAR szRegAppLogKey[] =
Packit fcad23
    _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
Packit fcad23
  TCHAR szRegKey[512];
Packit fcad23
  int exitStatus = 0;
Packit fcad23
/*  HKEY hKey = NULL;		?* Key to registry entry */
Packit fcad23
  TRY
Packit fcad23
  {
Packit fcad23
    /*
Packit fcad23
     * Open Service Control Manager 
Packit fcad23
     */
Packit fcad23
    hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
Packit fcad23
    if (hSCManager == NULL)
Packit fcad23
      {
Packit fcad23
        ProcessError (EVENTLOG_ERROR_TYPE, _T ("Can't open SCM (Service Control Manager)"), 1, quiet);
Packit fcad23
        exitStatus = SERVICE_ERROR_SCM_OPEN;       
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Open registered service 
Packit fcad23
     */
Packit fcad23
    hService = OpenService (hSCManager, lpszServiceName, SERVICE_ALL_ACCESS);
Packit fcad23
    if (hService == NULL)
Packit fcad23
      {
Packit fcad23
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), _T ("Can't open service"),
Packit fcad23
		   lpszServiceName);
Packit fcad23
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
Packit fcad23
        exitStatus = SERVICE_ERROR_OPEN_SERVICE;       
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Query service status 
Packit fcad23
     * If running stop before deleting 
Packit fcad23
     */
Packit fcad23
    if (QueryServiceStatus (hService, &sStatus))
Packit fcad23
      {
Packit fcad23
	if (sStatus.dwCurrentState == SERVICE_RUNNING
Packit fcad23
	    || sStatus.dwCurrentState == SERVICE_PAUSED)
Packit fcad23
	  {
Packit fcad23
	    ControlService (hService, SERVICE_CONTROL_STOP, &sStatus);
Packit fcad23
	  }
Packit fcad23
      };
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Delete the service  
Packit fcad23
     */
Packit fcad23
    if (DeleteService (hService) == FALSE)
Packit fcad23
      {
Packit fcad23
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), _T ("Can't delete service"),
Packit fcad23
		   lpszServiceName);
Packit fcad23
Packit fcad23
	/*
Packit fcad23
	 * Log message to eventlog 
Packit fcad23
	 */
Packit fcad23
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 0, quiet);
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Log "Service deleted successfully " message to eventlog
Packit fcad23
     */
Packit fcad23
    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), lpszServiceName, _T ("service deleted"));
Packit fcad23
    ProcessError (EVENTLOG_INFORMATION_TYPE, MsgErrorString, 0, quiet);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Delete registry entries for EventLog 
Packit fcad23
     */
Packit fcad23
    _tcscpy (szRegKey, szRegAppLogKey);
Packit fcad23
    _tcscat (szRegKey, lpszServiceName);
Packit fcad23
    RegDeleteKey (HKEY_LOCAL_MACHINE, szRegKey);
Packit fcad23
  }
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Delete the handles 
Packit fcad23
   */
Packit fcad23
  FINALLY
Packit fcad23
  {
Packit fcad23
    if (hService)
Packit fcad23
      CloseServiceHandle (hService);
Packit fcad23
    if (hSCManager)
Packit fcad23
      CloseServiceHandle (hSCManager);
Packit fcad23
  }
Packit fcad23
  return (exitStatus);
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Write a message to the Windows event log.
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
WriteToEventLog (WORD wType, LPCTSTR pszFormat, ...)
Packit fcad23
{
Packit fcad23
  TCHAR szMessage[512];
Packit fcad23
  LPCTSTR LogStr[1];
Packit fcad23
  va_list ArgList;
Packit fcad23
  HANDLE hEventSource = NULL;
Packit fcad23
Packit fcad23
  va_start (ArgList, pszFormat);
Packit fcad23
  _vsntprintf (szMessage, CountOf(szMessage), pszFormat, ArgList);
Packit fcad23
  va_end (ArgList);
Packit fcad23
  LogStr[0] = szMessage;
Packit fcad23
  hEventSource = RegisterEventSource (NULL, app_name_long);
Packit fcad23
  if (hEventSource == NULL)
Packit fcad23
    return;
Packit fcad23
  ReportEvent (hEventSource, wType, 0,
Packit fcad23
	       DISPLAY_MSG,
Packit fcad23
	       NULL, 1, 0, LogStr, NULL);
Packit fcad23
  DeregisterEventSource (hEventSource);
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Pre-process the second command-line argument from the user. 
Packit fcad23
     *     Service related options are:
Packit fcad23
     *     -register       - registers the service
Packit fcad23
     *     -unregister     - unregisters the service
Packit fcad23
     *     -service        - run as service
Packit fcad23
     *     other command-line arguments are ignored here.
Packit fcad23
     *
Packit fcad23
     * Return: Type indicating the option specified
Packit fcad23
     */
Packit fcad23
INT
Packit fcad23
ParseCmdLineForServiceOption (int argc, TCHAR * argv[], int *quiet)
Packit fcad23
{
Packit fcad23
  int nReturn = RUN_AS_CONSOLE;	/* default is to run as a console application */
Packit fcad23
Packit fcad23
  if (argc >= 2)
Packit fcad23
    {
Packit fcad23
Packit fcad23
      /*
Packit fcad23
       * second argument present 
Packit fcad23
       */
Packit fcad23
      if (lstrcmpi (_T ("-register"), argv[1]) == 0)
Packit fcad23
	{
Packit fcad23
	  nReturn = REGISTER_SERVICE;
Packit fcad23
	}
Packit fcad23
Packit fcad23
      else if (lstrcmpi (_T ("-unregister"), argv[1]) == 0)
Packit fcad23
	{
Packit fcad23
	  nReturn = UN_REGISTER_SERVICE;
Packit fcad23
	}
Packit fcad23
Packit fcad23
      else if (lstrcmpi (_T ("-service"), argv[1]) == 0)
Packit fcad23
	{
Packit fcad23
	  nReturn = RUN_AS_SERVICE;
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
Packit fcad23
  if (argc >= 3)
Packit fcad23
  {
Packit fcad23
    /*
Packit fcad23
     * third argument present 
Packit fcad23
     */
Packit fcad23
    if (lstrcmpi (_T ("-quiet"), argv[2]) == 0)
Packit fcad23
    {
Packit fcad23
      *quiet = 1;	
Packit fcad23
    }
Packit fcad23
  }
Packit fcad23
  
Packit fcad23
  return nReturn;
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Write error message to event log, console or pop-up window.
Packit fcad23
     *
Packit fcad23
     * If useGetLastError is 1, the last error returned from GetLastError()
Packit fcad23
     * is appended to pszMessage, separated by a ": ".
Packit fcad23
     *
Packit fcad23
     * eventLogType:                 MessageBox equivalent:
Packit fcad23
     * 
Packit fcad23
     * EVENTLOG_INFORMATION_TYPE     MB_ICONASTERISK
Packit fcad23
     * EVENTLOG_WARNING_TYPE         MB_ICONEXCLAMATION
Packit fcad23
     * EVENTLOG_ERROR_TYPE           MB_ICONSTOP
Packit fcad23
     * 
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
ProcessError (WORD eventLogType, LPCTSTR pszMessage, int useGetLastError, int quiet)
Packit fcad23
{
Packit fcad23
  HANDLE hEventSource = NULL;
Packit fcad23
  TCHAR pszMessageFull[MAX_STR_SIZE]; /* Combined pszMessage and GetLastError */
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * If useGetLastError enabled, generate text from GetLastError() and append to
Packit fcad23
   * pszMessageFull
Packit fcad23
   */
Packit fcad23
  if (useGetLastError) {
Packit fcad23
  LPTSTR pErrorMsgTemp = NULL;
Packit fcad23
  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
Packit fcad23
		 FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (),
Packit fcad23
		 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
Packit fcad23
        (LPTSTR) & pErrorMsgTemp, 0, NULL);
Packit fcad23
Packit fcad23
    _sntprintf (pszMessageFull, CountOf(pszMessageFull), _T("%s: %s"), pszMessage, pErrorMsgTemp);
Packit fcad23
    if (pErrorMsgTemp) {
Packit fcad23
      LocalFree (pErrorMsgTemp);
Packit fcad23
      pErrorMsgTemp = NULL;
Packit fcad23
    }
Packit fcad23
  }
Packit fcad23
  else {
Packit fcad23
    _sntprintf (pszMessageFull, CountOf(pszMessageFull), _T("%s"), pszMessage);
Packit fcad23
  }
Packit fcad23
  
Packit fcad23
  hEventSource = RegisterEventSource (NULL, app_name_long);
Packit fcad23
  if (hEventSource != NULL) {
Packit fcad23
    LPCTSTR LogStr[1];
Packit fcad23
    LogStr[0] = pszMessageFull;
Packit fcad23
    
Packit fcad23
    if (ReportEvent (hEventSource, 
Packit fcad23
          eventLogType, 
Packit fcad23
          0,
Packit fcad23
          DISPLAY_MSG,	/* just output the text to the event log */
Packit fcad23
          NULL, 
Packit fcad23
          1, 
Packit fcad23
          0, 
Packit fcad23
          LogStr, 
Packit fcad23
          NULL)) {
Packit fcad23
    }
Packit fcad23
    else {
Packit fcad23
      LPTSTR pErrorMsgTemp = NULL;
Packit fcad23
      FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
Packit fcad23
          FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (),
Packit fcad23
          MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
Packit fcad23
          (LPTSTR) & pErrorMsgTemp, 0, NULL);
Packit fcad23
      _ftprintf(stderr,_T("Could NOT lot to Event Log.  Error returned from ReportEvent(): %s\n"),pErrorMsgTemp);
Packit fcad23
      if (pErrorMsgTemp) {
Packit fcad23
        LocalFree (pErrorMsgTemp);
Packit fcad23
        pErrorMsgTemp = NULL;
Packit fcad23
      }
Packit fcad23
    }
Packit fcad23
    DeregisterEventSource (hEventSource);
Packit fcad23
    }
Packit fcad23
Packit fcad23
      if (quiet) {
Packit fcad23
    _ftprintf(stderr,_T("%s\n"),pszMessageFull);
Packit fcad23
      }
Packit fcad23
      else {
Packit fcad23
    switch (eventLogType) {
Packit fcad23
      case EVENTLOG_INFORMATION_TYPE:
Packit fcad23
        MessageBox (NULL, pszMessageFull, app_name_long, MB_ICONASTERISK);
Packit fcad23
        break;
Packit fcad23
      case EVENTLOG_WARNING_TYPE:
Packit fcad23
        MessageBox (NULL, pszMessageFull, app_name_long, MB_ICONEXCLAMATION);
Packit fcad23
        break;
Packit fcad23
      case EVENTLOG_ERROR_TYPE:
Packit fcad23
        MessageBox (NULL, pszMessageFull, app_name_long, MB_ICONSTOP);
Packit fcad23
        break;
Packit fcad23
      default:
Packit fcad23
        MessageBox (NULL, pszMessageFull, app_name_long, EVENTLOG_WARNING_TYPE);
Packit fcad23
        break;
Packit fcad23
      }
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Update current service status.
Packit fcad23
     * Sends the current service status to the SCM. Also updates
Packit fcad23
     * the global service status structure.
Packit fcad23
     */
Packit fcad23
static BOOL
Packit fcad23
UpdateServiceStatus (DWORD dwStatus, DWORD dwErrorCode, DWORD dwWaitHint)
Packit fcad23
{
Packit fcad23
  static DWORD dwCheckpoint = 1;
Packit fcad23
  DWORD dwControls = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
Packit fcad23
  if (g_fRunningAsService == FALSE)
Packit fcad23
    return FALSE;
Packit fcad23
  ZeroMemory (&ServiceStatus, sizeof (ServiceStatus));
Packit fcad23
  ServiceStatus.dwServiceType = SERVICE_WIN32;
Packit fcad23
  ServiceStatus.dwCurrentState = dwStatus;
Packit fcad23
  ServiceStatus.dwWaitHint = dwWaitHint;
Packit fcad23
  if (dwErrorCode)
Packit fcad23
    {
Packit fcad23
      ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
Packit fcad23
      ServiceStatus.dwServiceSpecificExitCode = dwErrorCode;
Packit fcad23
    }
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * special cases that depend on the new state 
Packit fcad23
   */
Packit fcad23
  switch (dwStatus)
Packit fcad23
    {
Packit fcad23
    case SERVICE_START_PENDING:
Packit fcad23
      dwControls = 0;
Packit fcad23
      break;
Packit fcad23
    case SERVICE_RUNNING:
Packit fcad23
    case SERVICE_STOPPED:
Packit fcad23
      dwCheckpoint = 0;
Packit fcad23
      break;
Packit fcad23
    }
Packit fcad23
  ServiceStatus.dwCheckPoint = dwCheckpoint++;
Packit fcad23
  ServiceStatus.dwControlsAccepted = dwControls;
Packit fcad23
  return ReportCurrentServiceStatus ();
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Reports current service status to SCM
Packit fcad23
     */
Packit fcad23
static BOOL
Packit fcad23
ReportCurrentServiceStatus ()
Packit fcad23
{
Packit fcad23
  return SetServiceStatus (hServiceStatus, &ServiceStatus);
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * ServiceMain function.
Packit fcad23
     */
Packit fcad23
VOID WINAPI
Packit fcad23
ServiceMain (DWORD argc, LPTSTR argv[])
Packit fcad23
{
Packit fcad23
  SECURITY_ATTRIBUTES SecurityAttributes;
Packit fcad23
  unsigned threadId;
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Input arguments
Packit fcad23
   */
Packit fcad23
  DWORD ArgCount = 0;
Packit fcad23
  LPTSTR *ArgArray = NULL;
Packit fcad23
  TCHAR szRegKey[512];
Packit fcad23
  HKEY hParamKey = NULL;
Packit fcad23
  DWORD TotalParams = 0;
Packit fcad23
  DWORD i;
Packit fcad23
  InputParams ThreadInputParams;
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Build the Input parameters to pass to worker thread 
Packit fcad23
   */
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * SCM sends Service Name as first arg, increment to point
Packit fcad23
   * arguments user specified while starting control agent
Packit fcad23
   */
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Read registry parameter 
Packit fcad23
   */
Packit fcad23
  ArgCount = 1;
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Create registry key path 
Packit fcad23
   */
Packit fcad23
  _sntprintf (szRegKey, CountOf(szRegKey), _T("%s%s\\%s"),
Packit fcad23
	     _T ("SYSTEM\\CurrentControlSet\\Services\\"), app_name_long,
Packit fcad23
	     _T("Parameters"));
Packit fcad23
  if (RegOpenKeyEx
Packit fcad23
      (HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_ALL_ACCESS, &hParamKey) == ERROR_SUCCESS)
Packit fcad23
    {
Packit fcad23
Packit fcad23
      /*
Packit fcad23
       * Read startup configuration information 
Packit fcad23
       */
Packit fcad23
      /*
Packit fcad23
       * Find number of subkeys inside parameters 
Packit fcad23
       */
Packit fcad23
      if (RegQueryInfoKey (hParamKey, NULL, NULL, 0,
Packit fcad23
	   NULL, NULL, NULL, &TotalParams,
Packit fcad23
	   NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
Packit fcad23
	{
Packit fcad23
	  if (TotalParams != 0)
Packit fcad23
	    {
Packit fcad23
	      ArgCount += TotalParams;
Packit fcad23
Packit fcad23
	      /*
Packit fcad23
	       * Allocate memory to hold strings 
Packit fcad23
	       */
Packit fcad23
	      ArgArray = calloc(ArgCount, sizeof(ArgArray[0]));
Packit fcad23
              if (ArgArray == 0)
Packit fcad23
                {
Packit fcad23
                  WriteToEventLog (EVENTLOG_ERROR_TYPE,
Packit fcad23
		       _T ("Resource failure"));
Packit fcad23
                  return;
Packit fcad23
                }
Packit fcad23
Packit fcad23
	      /*
Packit fcad23
	       * Copy first argument 
Packit fcad23
	       */
Packit fcad23
	      ArgArray[0] = _tcsdup (argv[0]);
Packit fcad23
	      for (i = 1; i <= TotalParams; i++)
Packit fcad23
		{
Packit fcad23
                  DWORD dwErrorcode;
Packit fcad23
                  DWORD nSize;
Packit fcad23
                  DWORD nRegkeyType;
Packit fcad23
                  TCHAR *szValue;
Packit fcad23
Packit fcad23
		  /*
Packit fcad23
		   * Create Subkey value name 
Packit fcad23
		   */
Packit fcad23
		  _sntprintf (szRegKey, CountOf(szRegKey), _T("%s%d"), _T("Param"), i);
Packit fcad23
Packit fcad23
		  /*
Packit fcad23
		   * Query subkey.
Packit fcad23
		   */
Packit fcad23
		  nSize = 0;
Packit fcad23
		  dwErrorcode = RegQueryValueEx(hParamKey, szRegKey, NULL,
Packit fcad23
                                                &nRegkeyType, NULL, &nSize);
Packit fcad23
                  if (dwErrorcode == ERROR_SUCCESS) {
Packit fcad23
                    if (nRegkeyType == REG_SZ || nRegkeyType == REG_EXPAND_SZ) {
Packit fcad23
                      szValue = malloc(nSize + sizeof(szValue[0]));
Packit fcad23
                      if (szValue) {
Packit fcad23
		        dwErrorcode = RegQueryValueEx(hParamKey, szRegKey, NULL,
Packit fcad23
                                                      &nRegkeyType, (LPBYTE)szValue, &nSize);
Packit fcad23
                        if (dwErrorcode == ERROR_SUCCESS) {
Packit fcad23
                          szValue[nSize] = 0;
Packit fcad23
                          ArgArray[i] = szValue;
Packit fcad23
                        } else {
Packit fcad23
                          free(szValue);
Packit fcad23
                          WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: error code %ld"), szRegKey, dwErrorcode);
Packit fcad23
                        }
Packit fcad23
                      } else
Packit fcad23
                        WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: out of memory"), szRegKey);
Packit fcad23
                    } else
Packit fcad23
                      WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Type %ld of registry key %s is incorrect"), nRegkeyType, szRegKey);
Packit fcad23
                  } else
Packit fcad23
                    WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: error code %ld"), szRegKey, dwErrorcode);
Packit fcad23
Packit fcad23
                  if (!ArgArray[i]) {
Packit fcad23
                    TotalParams = ArgCount = i;
Packit fcad23
                    break;
Packit fcad23
                  }
Packit fcad23
		}
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
      RegCloseKey (hParamKey);
Packit fcad23
    }
Packit fcad23
  if (ArgCount == 1)
Packit fcad23
    {
Packit fcad23
Packit fcad23
      /*
Packit fcad23
       * No startup args are given 
Packit fcad23
       */
Packit fcad23
      ThreadInputParams.Argc = argc;
Packit fcad23
      ThreadInputParams.Argv = argv;
Packit fcad23
    }
Packit fcad23
Packit fcad23
  else
Packit fcad23
    {
Packit fcad23
      ThreadInputParams.Argc = ArgCount;
Packit fcad23
      ThreadInputParams.Argv = ArgArray;
Packit fcad23
    }
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Register Service Control Handler 
Packit fcad23
   */
Packit fcad23
  hServiceStatus = RegisterServiceCtrlHandler (app_name_long, ControlHandler);
Packit fcad23
  if (hServiceStatus == 0)
Packit fcad23
    {
Packit fcad23
      WriteToEventLog (EVENTLOG_ERROR_TYPE,
Packit fcad23
		       _T ("RegisterServiceCtrlHandler failed"));
Packit fcad23
      return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Update the service status to START_PENDING.
Packit fcad23
   */
Packit fcad23
  UpdateServiceStatus (SERVICE_START_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Start the worker thread, which does the majority of the work .
Packit fcad23
   */
Packit fcad23
  TRY
Packit fcad23
  {
Packit fcad23
    if (SetSimpleSecurityAttributes (&SecurityAttributes) == FALSE)
Packit fcad23
      {
Packit fcad23
	WriteToEventLog (EVENTLOG_ERROR_TYPE,
Packit fcad23
			 _T ("Couldn't init security attributes"));
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
    hServiceThread =
Packit fcad23
      (void *) _beginthreadex (&SecurityAttributes, 0,
Packit fcad23
			       ThreadFunction,
Packit fcad23
			       (void *) &ThreadInputParams, 0, &threadId);
Packit fcad23
    if (hServiceThread == NULL)
Packit fcad23
      {
Packit fcad23
	WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("Couldn't start worker thread"));
Packit fcad23
	LEAVE;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Set service status to SERVICE_RUNNING.
Packit fcad23
     */
Packit fcad23
    UpdateServiceStatus (SERVICE_RUNNING, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Wait until the worker thread finishes.
Packit fcad23
     */
Packit fcad23
    WaitForSingleObject (hServiceThread, INFINITE);
Packit fcad23
  }
Packit fcad23
  FINALLY
Packit fcad23
  {
Packit fcad23
    /*
Packit fcad23
     * Release resources 
Packit fcad23
     */
Packit fcad23
    UpdateServiceStatus (SERVICE_STOPPED, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
    if (hServiceThread)
Packit fcad23
      CloseHandle (hServiceThread);
Packit fcad23
    FreeSecurityAttributes (&SecurityAttributes);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Free allocated argument list 
Packit fcad23
     */
Packit fcad23
    if (ArgCount > 1 && ArgArray != NULL)
Packit fcad23
      {
Packit fcad23
	/*
Packit fcad23
	 * Free all strings 
Packit fcad23
	 */
Packit fcad23
	for (i = 0; i < ArgCount; i++)
Packit fcad23
	  {
Packit fcad23
	    free (ArgArray[i]);
Packit fcad23
	  }
Packit fcad23
	free (ArgArray);
Packit fcad23
      }
Packit fcad23
  }
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Function to start as Windows service
Packit fcad23
     * The calling party should specify their entry point as input parameter
Packit fcad23
     * Returns TRUE if the Service is started successfully
Packit fcad23
     */
Packit fcad23
BOOL
Packit fcad23
RunAsService (INT (*ServiceFunction) (INT, LPTSTR *))
Packit fcad23
{
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Set the ServiceEntryPoint 
Packit fcad23
   */
Packit fcad23
  ServiceEntryPoint = ServiceFunction;
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * By default, mark as Running as a service 
Packit fcad23
   */
Packit fcad23
  g_fRunningAsService = TRUE;
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Initialize ServiceTableEntry table 
Packit fcad23
   */
Packit fcad23
  ServiceTableEntry[0].lpServiceName = app_name_long;	/* Application Name */
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * Call SCM via StartServiceCtrlDispatcher to run as Service 
Packit fcad23
   * * If the function returns TRUE we are running as Service, 
Packit fcad23
   */
Packit fcad23
  if (StartServiceCtrlDispatcher (ServiceTableEntry) == FALSE)
Packit fcad23
    {
Packit fcad23
      g_fRunningAsService = FALSE;
Packit fcad23
Packit fcad23
      /*
Packit fcad23
       * Some other error has occurred. 
Packit fcad23
       */
Packit fcad23
      WriteToEventLog (EVENTLOG_ERROR_TYPE,
Packit fcad23
		       _T ("Couldn't start service - %s"), app_name_long);
Packit fcad23
    }
Packit fcad23
  return g_fRunningAsService;
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Service control handler function
Packit fcad23
     * Responds to SCM commands/requests
Packit fcad23
     * This service handles 4 commands
Packit fcad23
     * - interrogate, pause, continue and stop.
Packit fcad23
     */
Packit fcad23
VOID WINAPI
Packit fcad23
ControlHandler (DWORD dwControl)
Packit fcad23
{
Packit fcad23
  switch (dwControl)
Packit fcad23
    {
Packit fcad23
    case SERVICE_CONTROL_INTERROGATE:
Packit fcad23
      ProcessServiceInterrogate ();
Packit fcad23
      break;
Packit fcad23
Packit fcad23
    case SERVICE_CONTROL_PAUSE:
Packit fcad23
      ProcessServicePause ();
Packit fcad23
      break;
Packit fcad23
Packit fcad23
    case SERVICE_CONTROL_CONTINUE:
Packit fcad23
      ProcessServiceContinue ();
Packit fcad23
      break;
Packit fcad23
Packit fcad23
    case SERVICE_CONTROL_STOP:
Packit fcad23
      ProcessServiceStop ();
Packit fcad23
      break;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * To stop the service.
Packit fcad23
     * If a stop function was registered, invoke it,
Packit fcad23
     * otherwise terminate the worker thread.
Packit fcad23
     * After stopping, Service status is set to STOP in 
Packit fcad23
     * main loop
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
ProcessServiceStop (VOID)
Packit fcad23
{
Packit fcad23
  UpdateServiceStatus (SERVICE_STOP_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
Packit fcad23
  if (StopFunction != NULL)
Packit fcad23
    {
Packit fcad23
      (*StopFunction) ();
Packit fcad23
    }
Packit fcad23
Packit fcad23
  else
Packit fcad23
    {
Packit fcad23
      TerminateThread (hServiceThread, 0);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Returns the current state of the service to the SCM.
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
ProcessServiceInterrogate (VOID)
Packit fcad23
{
Packit fcad23
  ReportCurrentServiceStatus ();
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * To Create a security descriptor with a NULL ACL, which
Packit fcad23
     * allows unlimited access. Returns a SECURITY_ATTRIBUTES
Packit fcad23
     * structure that contains the security descriptor.
Packit fcad23
     * The structure contains a dynamically allocated security
Packit fcad23
     * descriptor that must be freed either manually, or by
Packit fcad23
     * calling FreeSecurityAttributes 
Packit fcad23
     */
Packit fcad23
BOOL
Packit fcad23
SetSimpleSecurityAttributes (SECURITY_ATTRIBUTES * pSecurityAttr)
Packit fcad23
{
Packit fcad23
  BOOL fReturn = FALSE;
Packit fcad23
  SECURITY_DESCRIPTOR *pSecurityDesc = NULL;
Packit fcad23
Packit fcad23
  /*
Packit fcad23
   * If an invalid address is passed as a parameter, return
Packit fcad23
   * FALSE right away. 
Packit fcad23
   */
Packit fcad23
  if (!pSecurityAttr)
Packit fcad23
    return FALSE;
Packit fcad23
  pSecurityDesc =
Packit fcad23
    (SECURITY_DESCRIPTOR *) LocalAlloc (LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
Packit fcad23
  if (!pSecurityDesc)
Packit fcad23
    return FALSE;
Packit fcad23
  fReturn =
Packit fcad23
    InitializeSecurityDescriptor (pSecurityDesc, SECURITY_DESCRIPTOR_REVISION);
Packit fcad23
  if (fReturn != FALSE)
Packit fcad23
    {
Packit fcad23
      fReturn = SetSecurityDescriptorDacl (pSecurityDesc, TRUE, NULL, FALSE);
Packit fcad23
    }
Packit fcad23
  if (fReturn != FALSE)
Packit fcad23
    {
Packit fcad23
      pSecurityAttr->nLength = sizeof (SECURITY_ATTRIBUTES);
Packit fcad23
      pSecurityAttr->lpSecurityDescriptor = pSecurityDesc;
Packit fcad23
      pSecurityAttr->bInheritHandle = TRUE;
Packit fcad23
    }
Packit fcad23
Packit fcad23
  else
Packit fcad23
    {
Packit fcad23
      /*
Packit fcad23
       * Couldn't initialize or set security descriptor. 
Packit fcad23
       */
Packit fcad23
      LocalFree (pSecurityDesc);
Packit fcad23
    }
Packit fcad23
  return fReturn;
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * This function Frees the security descriptor, if any was created.
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
FreeSecurityAttributes (SECURITY_ATTRIBUTES * pSecurityAttr)
Packit fcad23
{
Packit fcad23
  if (pSecurityAttr && pSecurityAttr->lpSecurityDescriptor)
Packit fcad23
    LocalFree (pSecurityAttr->lpSecurityDescriptor);
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * This function runs in the worker thread
Packit fcad23
     * until an exit is forced, or until the SCM issues the STOP command.
Packit fcad23
     * Invokes registered service function
Packit fcad23
     * Returns when called registered function returns
Packit fcad23
     *
Packit fcad23
     * Input:
Packit fcad23
     *   lpParam contains argc and argv, pass to service main function 
Packit fcad23
     */
Packit fcad23
unsigned WINAPI
Packit fcad23
ThreadFunction (LPVOID lpParam)
Packit fcad23
{
Packit fcad23
  InputParams * pInputArg = (InputParams *) lpParam;
Packit fcad23
  return (*ServiceEntryPoint) (pInputArg->Argc, pInputArg->Argv);
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * This function is called to register an application-specific function
Packit fcad23
     *   which is invoked when the SCM stops the worker thread.
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
RegisterStopFunction (VOID (*StopFunc) (VOID))
Packit fcad23
{
Packit fcad23
  StopFunction = StopFunc;
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * SCM pause command invokes this function
Packit fcad23
     * If the service is not running, this function does nothing.
Packit fcad23
     * Otherwise, suspend the worker thread and update the status.
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
ProcessServicePause (VOID)
Packit fcad23
{
Packit fcad23
  if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
Packit fcad23
    {
Packit fcad23
      UpdateServiceStatus (SERVICE_PAUSE_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
Packit fcad23
      if (SuspendThread (hServiceThread) != -1)
Packit fcad23
	{
Packit fcad23
	  UpdateServiceStatus (SERVICE_PAUSED, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * SCM resume command invokes this function
Packit fcad23
     * If the service is not paused, this function does nothing.
Packit fcad23
     * Otherwise, resume the worker thread and update the status.
Packit fcad23
     */
Packit fcad23
VOID
Packit fcad23
ProcessServiceContinue (VOID)
Packit fcad23
{
Packit fcad23
  if (ServiceStatus.dwCurrentState == SERVICE_PAUSED)
Packit fcad23
    {
Packit fcad23
      UpdateServiceStatus (SERVICE_CONTINUE_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
Packit fcad23
      if (ResumeThread (hServiceThread) != -1)
Packit fcad23
	{
Packit fcad23
	  UpdateServiceStatus (SERVICE_RUNNING, NO_ERROR, SCM_WAIT_INTERVAL);
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
#endif /* WIN32 */
Packit fcad23
Packit fcad23