|
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 |
|