/*
 * Windows Service related function definitions
 * By Raju Krishnappa(raju_krishnappa@yahoo.com)
 *
 */

#ifdef WIN32

#include <net-snmp/net-snmp-config.h>

#include <windows.h>
#include <tchar.h>

#include <stdio.h>		/* sprintf */
#include <process.h>		/* beginthreadex  */

#include <net-snmp/library/winservice.h>

#ifdef mingw32 /* MinGW doesn't fully support exception handling. */

#define TRY if(1)
#define LEAVE goto labelFIN
#define FINALLY do { \
labelFIN: \
	; \
} while(0); if(1)

#else

#define TRY __try
#define LEAVE __leave
#define FINALLY __finally

#endif /* mingw32 */


#define CountOf(arr) ( sizeof(arr) / sizeof(arr[0]) )


#if defined(WIN32) && defined(HAVE_WIN32_PLATFORM_SDK) && !defined(mingw32)
#pragma comment(lib, "iphlpapi.lib")
#endif
#if defined(WIN32) && !defined(mingw32)
#ifdef USING_WINEXTDLL_MODULE
#pragma comment(lib, "snmpapi.lib")
#pragma comment(lib, "mgmtapi.lib")
#endif
#endif

 
    /*
     * External global variables used here
     */

    /*
     * Application Name 
     * This should be declared by the application, which wants to register as
     * windows service
     */
extern LPTSTR app_name_long;

    /*
     * Declare global variable
     */

    /*
     * Flag to indicate whether process is running as Service 
     */
BOOL g_fRunningAsService = FALSE;

    /*
     * Variable to maintain Current Service status 
     */
static SERVICE_STATUS ServiceStatus;

    /*
     * Service Handle 
     */
static SERVICE_STATUS_HANDLE hServiceStatus = 0L;

    /*
     * Service Table Entry 
     */
SERVICE_TABLE_ENTRY ServiceTableEntry[] = {
  {NULL, ServiceMain},		/* Service Main function */
  {NULL, NULL}
};

    /*
     * Handle to Thread, to implement Pause, Resume and Stop functions
     */
static HANDLE hServiceThread = NULL;	/* Thread Handle */

    /*
     * Holds calling partys Function Entry point, that should start
     * when entering service mode
     */
static INT (*ServiceEntryPoint) (INT Argc, LPTSTR Argv[]) = 0L;

    /*
     * To hold Stop Function address, to be called when STOP request
     * received from the SCM
     */
static VOID (*StopFunction) (VOID) = 0L;


    /*
     * To update windows service status to SCM 
     */
static BOOL UpdateServiceStatus (DWORD dwStatus, DWORD dwErrorCode,
				 DWORD dwWaitHint);

    /*
     * To Report current service status to SCM 
     */
static BOOL ReportCurrentServiceStatus (VOID);

VOID
ProcessError (WORD eventLogType, LPCTSTR pszMessage, int useGetLastError, int quiet);

    /*
     * To register as Windows Service with SCM(Service Control Manager)
     * Input - Service Name, Service Display Name,Service Description and
     * Service startup arguments
     */
int
RegisterService (LPCTSTR lpszServiceName, LPCTSTR lpszServiceDisplayName,
		 LPCTSTR lpszServiceDescription,
		 InputParams * StartUpArg, int quiet) /* Startup argument to the service */
{
  TCHAR szServicePath[MAX_PATH];	/* To hold module File name */
  TCHAR MsgErrorString[MAX_STR_SIZE];	/* Message or Error string */
  TCHAR szServiceCommand[MAX_PATH + 9];	/* Command to execute */
  SC_HANDLE hSCManager = NULL;
  SC_HANDLE hService = NULL;
  TCHAR szRegAppLogKey[] =
    _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
  TCHAR szRegKey[512];
  HKEY hKey = NULL;		/* Key to registry entry */
  HKEY hParamKey = NULL;	/* To store startup parameters */
  DWORD dwData;			/* Type of logging supported */
  DWORD i, j;			/* Loop variables */
  int exitStatus = 0;
  GetModuleFileName (NULL, szServicePath, MAX_PATH);
  TRY
  {

    /*
     * Open Service Control Manager handle 
     */
    hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (hSCManager == NULL)
      {
        ProcessError (EVENTLOG_ERROR_TYPE, _T ("Can't open SCM (Service Control Manager)"), 1, quiet);
        exitStatus = SERVICE_ERROR_SCM_OPEN;
	LEAVE;
      }

    /*
     * Generate the command to be executed by the SCM 
     */
    _sntprintf (szServiceCommand, CountOf(szServiceCommand), _T("%s %s"), szServicePath, _T ("-service"));

    /*
     * Create the desired service 
     */
    hService = CreateService (hSCManager, lpszServiceName, lpszServiceDisplayName,
			SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
			SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szServiceCommand,
			      NULL,	/* load-order group */
			      NULL,	/* group member tag */
			      NULL,	/* dependencies */
			      NULL,	/* account */
			      NULL);	/* password */
    if (hService == NULL)
      {
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
		   _T ("Can't create service"), lpszServiceDisplayName);
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);

        exitStatus = SERVICE_ERROR_CREATE_SERVICE;
	LEAVE;
      }

    /*
     * Create registry entries for the event log 
     */
    /*
     * Create registry Application event log key 
     */
    _tcscpy (szRegKey, szRegAppLogKey);
    _tcscat (szRegKey, lpszServiceName);

    /*
     * Create registry key 
     */
    if (RegCreateKey (HKEY_LOCAL_MACHINE, szRegKey, &hKey) != ERROR_SUCCESS)
      {
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
		   _T ("is unable to create registry entries"), lpszServiceDisplayName);
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
        exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
	LEAVE;
      }

    /*
     * Add Event ID message file name to the 'EventMessageFile' subkey 
     */
    RegSetValueEx (hKey, _T("EventMessageFile"), 0, REG_EXPAND_SZ,
		   (CONST BYTE *) szServicePath,
		   _tcslen (szServicePath) + sizeof (TCHAR));

    /*
     * Set the supported types flags. 
     */
    dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
    RegSetValueEx (hKey, _T("TypesSupported"), 0, REG_DWORD,
		   (CONST BYTE *) & dwData, sizeof (DWORD));

    /*
     * Close Registry key 
     */
    RegCloseKey (hKey);

    /*
     * Set Service Description String  and save startup parameters if present
     */
    if (lpszServiceDescription != NULL || StartUpArg->Argc > 2)
      {
	/*
	 * Create Registry Key path 
	 */
	_tcscpy (szRegKey, _T ("SYSTEM\\CurrentControlSet\\Services\\"));
	_tcscat (szRegKey, app_name_long);
	hKey = NULL;

	/*
	 * Open Registry key using Create and Set access. 
	 */
	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_WRITE,
			  &hKey) != ERROR_SUCCESS)
	  {
	    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
		       _T ("is unable to create registry entries"),
		       lpszServiceDisplayName);
            ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
            exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
	    LEAVE;
	  }

	/*
	 * Create description subkey and the set value 
	 */
	if (lpszServiceDescription != NULL)
	  {
	    if (RegSetValueEx (hKey, _T("Description"), 0, REG_SZ,
			       (CONST BYTE *) lpszServiceDescription,
			       _tcslen (lpszServiceDescription) +
			       sizeof (TCHAR)) != ERROR_SUCCESS)
	      {
		_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
			   _T ("is unable to create registry entries"),
			   lpszServiceDisplayName);
                ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
                exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
		LEAVE;
	      };
	  }

	/*
	 * Save startup arguments if they are present 
	 */
	if (StartUpArg->Argc > 2)
	  {
	    /*
	     * Create Subkey parameters 
	     */
	    if (RegCreateKeyEx
		(hKey, _T("Parameters"), 0, NULL,
		 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
		 &hParamKey, NULL) != ERROR_SUCCESS)
	      {
		_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
			   _T ("is unable to create registry entries"),
			   lpszServiceDisplayName);
                ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
                exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
                LEAVE;
	      }

	    /*
	     * Save parameters 
	     */

	    /*
	     * Loop through arguments 
	     */
            if (quiet) /* Make sure we don't store -quiet arg */
              i = 3;
            else
              i = 2;

	    for (j = 1; i < StartUpArg->Argc; i++, j++)
	      {
		_sntprintf (szRegKey, CountOf(szRegKey), _T("%s%d"), _T ("Param"), j);

		/*
		 * Create registry key 
		 */
		if (RegSetValueEx
		    (hParamKey, szRegKey, 0, REG_SZ,
		     (CONST BYTE *) StartUpArg->Argv[i],
		     _tcslen (StartUpArg->Argv[i]) +
		     sizeof (TCHAR)) != ERROR_SUCCESS)
		  {
		    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"),
			       _T ("is unable to create registry entries"),
			       lpszServiceDisplayName);
                    ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
                    exitStatus = SERVICE_ERROR_CREATE_REGISTRY_ENTRIES;
		    LEAVE;
		  };
	      }
	  }

	/*
	 * Everything is set, delete hKey 
	 */
	RegCloseKey (hParamKey);
	RegCloseKey (hKey);
      }

    /*
     * Ready to log messages 
     */

    /*
     * Successfully registered as service 
     */
    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), lpszServiceName,
	       _T ("successfully registered as a service"));

    /*
     * Log message to eventlog 
     */
    ProcessError (EVENTLOG_INFORMATION_TYPE, MsgErrorString, 0, quiet);
  }

  FINALLY
  {
    if (hSCManager)
      CloseServiceHandle (hSCManager);
    if (hService)
      CloseServiceHandle (hService);
    if (hKey)
      RegCloseKey (hKey);
    if (hParamKey)
      RegCloseKey (hParamKey);
  }
  return (exitStatus);
}

    /*
     * Unregister the service with the  Windows SCM 
     * Input - ServiceName
     */
int
UnregisterService (LPCTSTR lpszServiceName, int quiet)
{
  TCHAR MsgErrorString[MAX_STR_SIZE];	/* Message or Error string */
  SC_HANDLE hSCManager = NULL;	/* SCM handle */
  SC_HANDLE hService = NULL;	/* Service Handle */
  SERVICE_STATUS sStatus;
  TCHAR szRegAppLogKey[] =
    _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
  TCHAR szRegKey[512];
  int exitStatus = 0;
/*  HKEY hKey = NULL;		?* Key to registry entry */
  TRY
  {
    /*
     * Open Service Control Manager 
     */
    hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (hSCManager == NULL)
      {
        ProcessError (EVENTLOG_ERROR_TYPE, _T ("Can't open SCM (Service Control Manager)"), 1, quiet);
        exitStatus = SERVICE_ERROR_SCM_OPEN;       
	LEAVE;
      }

    /*
     * Open registered service 
     */
    hService = OpenService (hSCManager, lpszServiceName, SERVICE_ALL_ACCESS);
    if (hService == NULL)
      {
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), _T ("Can't open service"),
		   lpszServiceName);
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 1, quiet);
        exitStatus = SERVICE_ERROR_OPEN_SERVICE;       
	LEAVE;
      }

    /*
     * Query service status 
     * If running stop before deleting 
     */
    if (QueryServiceStatus (hService, &sStatus))
      {
	if (sStatus.dwCurrentState == SERVICE_RUNNING
	    || sStatus.dwCurrentState == SERVICE_PAUSED)
	  {
	    ControlService (hService, SERVICE_CONTROL_STOP, &sStatus);
	  }
      };

    /*
     * Delete the service  
     */
    if (DeleteService (hService) == FALSE)
      {
	_sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), _T ("Can't delete service"),
		   lpszServiceName);

	/*
	 * Log message to eventlog 
	 */
        ProcessError (EVENTLOG_ERROR_TYPE, MsgErrorString, 0, quiet);
	LEAVE;
      }

    /*
     * Log "Service deleted successfully " message to eventlog
     */
    _sntprintf (MsgErrorString, CountOf(MsgErrorString), _T("%s %s"), lpszServiceName, _T ("service deleted"));
    ProcessError (EVENTLOG_INFORMATION_TYPE, MsgErrorString, 0, quiet);

    /*
     * Delete registry entries for EventLog 
     */
    _tcscpy (szRegKey, szRegAppLogKey);
    _tcscat (szRegKey, lpszServiceName);
    RegDeleteKey (HKEY_LOCAL_MACHINE, szRegKey);
  }

  /*
   * Delete the handles 
   */
  FINALLY
  {
    if (hService)
      CloseServiceHandle (hService);
    if (hSCManager)
      CloseServiceHandle (hSCManager);
  }
  return (exitStatus);
}

    /*
     * Write a message to the Windows event log.
     */
VOID
WriteToEventLog (WORD wType, LPCTSTR pszFormat, ...)
{
  TCHAR szMessage[512];
  LPCTSTR LogStr[1];
  va_list ArgList;
  HANDLE hEventSource = NULL;

  va_start (ArgList, pszFormat);
  _vsntprintf (szMessage, CountOf(szMessage), pszFormat, ArgList);
  va_end (ArgList);
  LogStr[0] = szMessage;
  hEventSource = RegisterEventSource (NULL, app_name_long);
  if (hEventSource == NULL)
    return;
  ReportEvent (hEventSource, wType, 0,
	       DISPLAY_MSG,
	       NULL, 1, 0, LogStr, NULL);
  DeregisterEventSource (hEventSource);
}

    /*
     * Pre-process the second command-line argument from the user. 
     *     Service related options are:
     *     -register       - registers the service
     *     -unregister     - unregisters the service
     *     -service        - run as service
     *     other command-line arguments are ignored here.
     *
     * Return: Type indicating the option specified
     */
INT
ParseCmdLineForServiceOption (int argc, TCHAR * argv[], int *quiet)
{
  int nReturn = RUN_AS_CONSOLE;	/* default is to run as a console application */

  if (argc >= 2)
    {

      /*
       * second argument present 
       */
      if (lstrcmpi (_T ("-register"), argv[1]) == 0)
	{
	  nReturn = REGISTER_SERVICE;
	}

      else if (lstrcmpi (_T ("-unregister"), argv[1]) == 0)
	{
	  nReturn = UN_REGISTER_SERVICE;
	}

      else if (lstrcmpi (_T ("-service"), argv[1]) == 0)
	{
	  nReturn = RUN_AS_SERVICE;
	}
    }

  if (argc >= 3)
  {
    /*
     * third argument present 
     */
    if (lstrcmpi (_T ("-quiet"), argv[2]) == 0)
    {
      *quiet = 1;	
    }
  }
  
  return nReturn;
}

    /*
     * Write error message to event log, console or pop-up window.
     *
     * If useGetLastError is 1, the last error returned from GetLastError()
     * is appended to pszMessage, separated by a ": ".
     *
     * eventLogType:                 MessageBox equivalent:
     * 
     * EVENTLOG_INFORMATION_TYPE     MB_ICONASTERISK
     * EVENTLOG_WARNING_TYPE         MB_ICONEXCLAMATION
     * EVENTLOG_ERROR_TYPE           MB_ICONSTOP
     * 
     */
VOID
ProcessError (WORD eventLogType, LPCTSTR pszMessage, int useGetLastError, int quiet)
{
  HANDLE hEventSource = NULL;
  TCHAR pszMessageFull[MAX_STR_SIZE]; /* Combined pszMessage and GetLastError */

  /*
   * If useGetLastError enabled, generate text from GetLastError() and append to
   * pszMessageFull
   */
  if (useGetLastError) {
  LPTSTR pErrorMsgTemp = NULL;
  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
		 FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (),
		 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) & pErrorMsgTemp, 0, NULL);

    _sntprintf (pszMessageFull, CountOf(pszMessageFull), _T("%s: %s"), pszMessage, pErrorMsgTemp);
    if (pErrorMsgTemp) {
      LocalFree (pErrorMsgTemp);
      pErrorMsgTemp = NULL;
    }
  }
  else {
    _sntprintf (pszMessageFull, CountOf(pszMessageFull), _T("%s"), pszMessage);
  }
  
  hEventSource = RegisterEventSource (NULL, app_name_long);
  if (hEventSource != NULL) {
    LPCTSTR LogStr[1];
    LogStr[0] = pszMessageFull;
    
    if (ReportEvent (hEventSource, 
          eventLogType, 
          0,
          DISPLAY_MSG,	/* just output the text to the event log */
          NULL, 
          1, 
          0, 
          LogStr, 
          NULL)) {
    }
    else {
      LPTSTR pErrorMsgTemp = NULL;
      FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
          FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (),
          MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
          (LPTSTR) & pErrorMsgTemp, 0, NULL);
      _ftprintf(stderr,_T("Could NOT lot to Event Log.  Error returned from ReportEvent(): %s\n"),pErrorMsgTemp);
      if (pErrorMsgTemp) {
        LocalFree (pErrorMsgTemp);
        pErrorMsgTemp = NULL;
      }
    }
    DeregisterEventSource (hEventSource);
    }

      if (quiet) {
    _ftprintf(stderr,_T("%s\n"),pszMessageFull);
      }
      else {
    switch (eventLogType) {
      case EVENTLOG_INFORMATION_TYPE:
        MessageBox (NULL, pszMessageFull, app_name_long, MB_ICONASTERISK);
        break;
      case EVENTLOG_WARNING_TYPE:
        MessageBox (NULL, pszMessageFull, app_name_long, MB_ICONEXCLAMATION);
        break;
      case EVENTLOG_ERROR_TYPE:
        MessageBox (NULL, pszMessageFull, app_name_long, MB_ICONSTOP);
        break;
      default:
        MessageBox (NULL, pszMessageFull, app_name_long, EVENTLOG_WARNING_TYPE);
        break;
      }
    }
}

    /*
     * Update current service status.
     * Sends the current service status to the SCM. Also updates
     * the global service status structure.
     */
static BOOL
UpdateServiceStatus (DWORD dwStatus, DWORD dwErrorCode, DWORD dwWaitHint)
{
  DWORD static dwCheckpoint = 1;
  DWORD dwControls = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
  if (g_fRunningAsService == FALSE)
    return FALSE;
  ZeroMemory (&ServiceStatus, sizeof (ServiceStatus));
  ServiceStatus.dwServiceType = SERVICE_WIN32;
  ServiceStatus.dwCurrentState = dwStatus;
  ServiceStatus.dwWaitHint = dwWaitHint;
  if (dwErrorCode)
    {
      ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
      ServiceStatus.dwServiceSpecificExitCode = dwErrorCode;
    }

  /*
   * special cases that depend on the new state 
   */
  switch (dwStatus)
    {
    case SERVICE_START_PENDING:
      dwControls = 0;
      break;
    case SERVICE_RUNNING:
    case SERVICE_STOPPED:
      dwCheckpoint = 0;
      break;
    }
  ServiceStatus.dwCheckPoint = dwCheckpoint++;
  ServiceStatus.dwControlsAccepted = dwControls;
  return ReportCurrentServiceStatus ();
}

    /*
     * Reports current service status to SCM
     */
static BOOL
ReportCurrentServiceStatus ()
{
  return SetServiceStatus (hServiceStatus, &ServiceStatus);
}

    /*
     * ServiceMain function.
     */
VOID WINAPI
ServiceMain (DWORD argc, LPTSTR argv[])
{
  SECURITY_ATTRIBUTES SecurityAttributes;
  unsigned threadId;

  /*
   * Input arguments
   */
  DWORD ArgCount = 0;
  LPTSTR *ArgArray = NULL;
  TCHAR szRegKey[512];
  HKEY hParamKey = NULL;
  DWORD TotalParams = 0;
  DWORD i;
  InputParams ThreadInputParams;

  /*
   * Build the Input parameters to pass to worker thread 
   */

  /*
   * SCM sends Service Name as first arg, increment to point
   * arguments user specified while starting control agent
   */

  /*
   * Read registry parameter 
   */
  ArgCount = 1;

  /*
   * Create registry key path 
   */
  _sntprintf (szRegKey, CountOf(szRegKey), _T("%s%s\\%s"),
	     _T ("SYSTEM\\CurrentControlSet\\Services\\"), app_name_long,
	     _T("Parameters"));
  if (RegOpenKeyEx
      (HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_ALL_ACCESS, &hParamKey) == ERROR_SUCCESS)
    {

      /*
       * Read startup configuration information 
       */
      /*
       * Find number of subkeys inside parameters 
       */
      if (RegQueryInfoKey (hParamKey, NULL, NULL, 0,
	   NULL, NULL, NULL, &TotalParams,
	   NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
	{
	  if (TotalParams != 0)
	    {
	      ArgCount += TotalParams;

	      /*
	       * Allocate memory to hold strings 
	       */
	      ArgArray = calloc(ArgCount, sizeof(ArgArray[0]));
              if (ArgArray == 0)
                {
                  WriteToEventLog (EVENTLOG_ERROR_TYPE,
		       _T ("Resource failure"));
                  return;
                }

	      /*
	       * Copy first argument 
	       */
	      ArgArray[0] = _tcsdup (argv[0]);
	      for (i = 1; i <= TotalParams; i++)
		{
                  DWORD dwErrorcode;
                  DWORD nSize;
                  DWORD nRegkeyType;
                  TCHAR *szValue;

		  /*
		   * Create Subkey value name 
		   */
		  _sntprintf (szRegKey, CountOf(szRegKey), _T("%s%d"), _T("Param"), i);

		  /*
		   * Query subkey.
		   */
		  nSize = 0;
		  dwErrorcode = RegQueryValueEx(hParamKey, szRegKey, NULL,
                                                &nRegkeyType, NULL, &nSize);
                  if (dwErrorcode == ERROR_SUCCESS) {
                    if (nRegkeyType == REG_SZ || nRegkeyType == REG_EXPAND_SZ) {
                      szValue = malloc(nSize + sizeof(szValue[0]));
                      if (szValue) {
		        dwErrorcode = RegQueryValueEx(hParamKey, szRegKey, NULL,
                                                      &nRegkeyType, (LPBYTE)szValue, &nSize);
                        if (dwErrorcode == ERROR_SUCCESS) {
                          szValue[nSize] = 0;
                          ArgArray[i] = szValue;
                        } else {
                          free(szValue);
                          WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: error code %ld"), szRegKey, dwErrorcode);
                        }
                      } else
                        WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: out of memory"), szRegKey);
                    } else
                      WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Type %ld of registry key %s is incorrect"), nRegkeyType, szRegKey);
                  } else
                    WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: error code %ld"), szRegKey, dwErrorcode);

                  if (!ArgArray[i]) {
                    TotalParams = ArgCount = i;
                    break;
                  }
		}
	    }
	}
      RegCloseKey (hParamKey);
    }
  if (ArgCount == 1)
    {

      /*
       * No startup args are given 
       */
      ThreadInputParams.Argc = argc;
      ThreadInputParams.Argv = argv;
    }

  else
    {
      ThreadInputParams.Argc = ArgCount;
      ThreadInputParams.Argv = ArgArray;
    }

  /*
   * Register Service Control Handler 
   */
  hServiceStatus = RegisterServiceCtrlHandler (app_name_long, ControlHandler);
  if (hServiceStatus == 0)
    {
      WriteToEventLog (EVENTLOG_ERROR_TYPE,
		       _T ("RegisterServiceCtrlHandler failed"));
      return;
    }

  /*
   * Update the service status to START_PENDING.
   */
  UpdateServiceStatus (SERVICE_START_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);

  /*
   * Start the worker thread, which does the majority of the work .
   */
  TRY
  {
    if (SetSimpleSecurityAttributes (&SecurityAttributes) == FALSE)
      {
	WriteToEventLog (EVENTLOG_ERROR_TYPE,
			 _T ("Couldn't init security attributes"));
	LEAVE;
      }
    hServiceThread =
      (void *) _beginthreadex (&SecurityAttributes, 0,
			       ThreadFunction,
			       (void *) &ThreadInputParams, 0, &threadId);
    if (hServiceThread == NULL)
      {
	WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("Couldn't start worker thread"));
	LEAVE;
      }

    /*
     * Set service status to SERVICE_RUNNING.
     */
    UpdateServiceStatus (SERVICE_RUNNING, NO_ERROR, SCM_WAIT_INTERVAL);

    /*
     * Wait until the worker thread finishes.
     */
    WaitForSingleObject (hServiceThread, INFINITE);
  }
  FINALLY
  {
    /*
     * Release resources 
     */
    UpdateServiceStatus (SERVICE_STOPPED, NO_ERROR, SCM_WAIT_INTERVAL);
    if (hServiceThread)
      CloseHandle (hServiceThread);
    FreeSecurityAttributes (&SecurityAttributes);

    /*
     * Free allocated argument list 
     */
    if (ArgCount > 1 && ArgArray != NULL)
      {
	/*
	 * Free all strings 
	 */
	for (i = 0; i < ArgCount; i++)
	  {
	    free (ArgArray[i]);
	  }
	free (ArgArray);
      }
  }
}

    /*
     * Function to start as Windows service
     * The calling party should specify their entry point as input parameter
     * Returns TRUE if the Service is started successfully
     */
BOOL
RunAsService (INT (*ServiceFunction) (INT, LPTSTR *))
{

  /*
   * Set the ServiceEntryPoint 
   */
  ServiceEntryPoint = ServiceFunction;

  /*
   * By default, mark as Running as a service 
   */
  g_fRunningAsService = TRUE;

  /*
   * Initialize ServiceTableEntry table 
   */
  ServiceTableEntry[0].lpServiceName = app_name_long;	/* Application Name */

  /*
   * Call SCM via StartServiceCtrlDispatcher to run as Service 
   * * If the function returns TRUE we are running as Service, 
   */
  if (StartServiceCtrlDispatcher (ServiceTableEntry) == FALSE)
    {
      g_fRunningAsService = FALSE;

      /*
       * Some other error has occurred. 
       */
      WriteToEventLog (EVENTLOG_ERROR_TYPE,
		       _T ("Couldn't start service - %s"), app_name_long);
    }
  return g_fRunningAsService;
}

    /*
     * Service control handler function
     * Responds to SCM commands/requests
     * This service handles 4 commands
     * - interrogate, pause, continue and stop.
     */
VOID WINAPI
ControlHandler (DWORD dwControl)
{
  switch (dwControl)
    {
    case SERVICE_CONTROL_INTERROGATE:
      ProcessServiceInterrogate ();
      break;

    case SERVICE_CONTROL_PAUSE:
      ProcessServicePause ();
      break;

    case SERVICE_CONTROL_CONTINUE:
      ProcessServiceContinue ();
      break;

    case SERVICE_CONTROL_STOP:
      ProcessServiceStop ();
      break;
    }
}

    /*
     * To stop the service.
     * If a stop function was registered, invoke it,
     * otherwise terminate the worker thread.
     * After stopping, Service status is set to STOP in 
     * main loop
     */
VOID
ProcessServiceStop (VOID)
{
  UpdateServiceStatus (SERVICE_STOP_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);

  if (StopFunction != NULL)
    {
      (*StopFunction) ();
    }

  else
    {
      TerminateThread (hServiceThread, 0);
    }
}

    /*
     * Returns the current state of the service to the SCM.
     */
VOID
ProcessServiceInterrogate (VOID)
{
  ReportCurrentServiceStatus ();
}

    /*
     * To Create a security descriptor with a NULL ACL, which
     * allows unlimited access. Returns a SECURITY_ATTRIBUTES
     * structure that contains the security descriptor.
     * The structure contains a dynamically allocated security
     * descriptor that must be freed either manually, or by
     * calling FreeSecurityAttributes 
     */
BOOL
SetSimpleSecurityAttributes (SECURITY_ATTRIBUTES * pSecurityAttr)
{
  BOOL fReturn = FALSE;
  SECURITY_DESCRIPTOR *pSecurityDesc = NULL;

  /*
   * If an invalid address is passed as a parameter, return
   * FALSE right away. 
   */
  if (!pSecurityAttr)
    return FALSE;
  pSecurityDesc =
    (SECURITY_DESCRIPTOR *) LocalAlloc (LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  if (!pSecurityDesc)
    return FALSE;
  fReturn =
    InitializeSecurityDescriptor (pSecurityDesc, SECURITY_DESCRIPTOR_REVISION);
  if (fReturn != FALSE)
    {
      fReturn = SetSecurityDescriptorDacl (pSecurityDesc, TRUE, NULL, FALSE);
    }
  if (fReturn != FALSE)
    {
      pSecurityAttr->nLength = sizeof (SECURITY_ATTRIBUTES);
      pSecurityAttr->lpSecurityDescriptor = pSecurityDesc;
      pSecurityAttr->bInheritHandle = TRUE;
    }

  else
    {
      /*
       * Couldn't initialize or set security descriptor. 
       */
      LocalFree (pSecurityDesc);
    }
  return fReturn;
}

    /*
     * This function Frees the security descriptor, if any was created.
     */
VOID
FreeSecurityAttributes (SECURITY_ATTRIBUTES * pSecurityAttr)
{
  if (pSecurityAttr && pSecurityAttr->lpSecurityDescriptor)
    LocalFree (pSecurityAttr->lpSecurityDescriptor);
}

    /*
     * This function runs in the worker thread
     * until an exit is forced, or until the SCM issues the STOP command.
     * Invokes registered service function
     * Returns when called registered function returns
     *
     * Input:
     *   lpParam contains argc and argv, pass to service main function 
     */
unsigned WINAPI
ThreadFunction (LPVOID lpParam)
{
  InputParams * pInputArg = (InputParams *) lpParam;
  return (*ServiceEntryPoint) (pInputArg->Argc, pInputArg->Argv);
}

    /*
     * This function is called to register an application-specific function
     *   which is invoked when the SCM stops the worker thread.
     */
VOID
RegisterStopFunction (VOID (*StopFunc) (VOID))
{
  StopFunction = StopFunc;
}

    /*
     * SCM pause command invokes this function
     * If the service is not running, this function does nothing.
     * Otherwise, suspend the worker thread and update the status.
     */
VOID
ProcessServicePause (VOID)
{
  if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
    {
      UpdateServiceStatus (SERVICE_PAUSE_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);

      if (SuspendThread (hServiceThread) != -1)
	{
	  UpdateServiceStatus (SERVICE_PAUSED, NO_ERROR, SCM_WAIT_INTERVAL);
	}
    }
}

    /*
     * SCM resume command invokes this function
     * If the service is not paused, this function does nothing.
     * Otherwise, resume the worker thread and update the status.
     */
VOID
ProcessServiceContinue (VOID)
{
  if (ServiceStatus.dwCurrentState == SERVICE_PAUSED)
    {
      UpdateServiceStatus (SERVICE_CONTINUE_PENDING, NO_ERROR, SCM_WAIT_INTERVAL);

      if (ResumeThread (hServiceThread) != -1)
	{
	  UpdateServiceStatus (SERVICE_RUNNING, NO_ERROR, SCM_WAIT_INTERVAL);
	}
    }
}

#endif /* WIN32 */


