📄 winservice.c
字号:
{
ThreadInputParams.Argc = ArgCount;
ThreadInputParams.Argv = ArgArray;
}
/* * Register Serivce Control Handler */
hServiceStatus = RegisterServiceCtrlHandler(g_szAppName,
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);
/* * Spin of worker thread, which does 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,
&dwThreadId);
if (hServiceThread == NULL)
{
WriteToEventLog(EVENTLOG_ERROR_TYPE,
_T("Couldn't start worker thread"));
__leave;
}
/* * Set Service Status to Running */
UpdateServiceStatus(SERVICE_RUNNING,
NO_ERROR,
SCM_WAIT_INTERVAL);
/* * Wait for termination event and worker thread to
* * spin down.
*/
WaitForSingleObject(hServiceThread, INFINITE);
}
__finally
{
/* * Release resources */
UpdateServiceStatus(SERVICE_STOPPED,
NO_ERROR,
SCM_WAIT_INTERVAL);
if (hServiceThread)
CloseHandle(hServiceThread);
FreeSecurityAttributes(&SecurityAttributes);
/* * Delete allocated argument list */
if (ArgCount > 1 && ArgArray != NULL)
{
/* * Delete 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 = g_szAppName; /* 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"), g_szAppName);
}
return g_fRunningAsService;
}
/* *
* * Service control handler function
* * Responds to SCM commands/requests
* * The service handles 4 commands
* * commands - interrogate,pause, continue and stop.
*/
VOID WINAPI ControlHandler(DWORD dwControl)
{
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
ProcessServiceStop(); /* To stop the service */
break;
case SERVICE_CONTROL_INTERROGATE:
ProcessServiceInterrogate(); /* Report Current state of the Service */
break;
case SERVICE_CONTROL_PAUSE:
ProcessServicePause(); /* To puase service */
break;
case SERVICE_CONTROL_CONTINUE:
ProcessServiceContinue(); /* To continue Service */
break;
}
}
/* *
* * To stop the service. This invokes registered
* * stop function to stop the service(gracefull exit)
* * After stopping, Service status is set to STOP in
* * main loop
*/
VOID ProcessServiceStop(VOID)
{
UpdateServiceStatus(SERVICE_STOP_PENDING,
NO_ERROR,
SCM_WAIT_INTERVAL);
/* * Invoke registered Stop funciton */
if (StopFunction != NULL)
{
(*StopFunction) ();
}
else
{
/* * There is no registered stop function, so terminate the thread */
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 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 funciton Frees the security descriptor owned by a SECURITY_ATTRIBUTES
* * structure.
*/
VOID FreeSecurityAttributes(SECURITY_ATTRIBUTES * pSecurityAttr)
{
if (pSecurityAttr && pSecurityAttr->lpSecurityDescriptor)
LocalFree(pSecurityAttr->lpSecurityDescriptor);
}
/* * TheadFunction
* * This function is spawn as thread.
* * Invokes registered service function
* * Returns when called registered function returns
*/
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
/* * lpParam contains argc and argv, pass to service main function */
/* * Declare pointer to InputParams */
InputParams * pInputArg;
pInputArg = (InputParams *) lpParam;
return (*ServiceEntryPoint) (pInputArg->Argc, pInputArg->Argv);
}
/* *
* * To register STOP function with the framework
* * This function will be inovked when SCM sends
* * STOP command
*/
VOID RegisterStopFunction(void (*StopFunc) ())
{
StopFunction = StopFunc;
}
/* *
* * To Pause the service whec SCM sends pause command
* * Invokes PauseThread on worker Thread handle, only
* * when Service status is Running
*/
VOID ProcessServicePause(VOID)
{
if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
UpdateServiceStatus(SERVICE_PAUSE_PENDING,
NO_ERROR,
SCM_WAIT_INTERVAL);
/* * Invoke Thread pause on ThreadHandle */
if (SuspendThread(hServiceThread) != -1)
{
UpdateServiceStatus(SERVICE_PAUSED,
NO_ERROR,
SCM_WAIT_INTERVAL);
}
}
}
/* *
* * To Continue paused service
* * Invoke ResumeThread, if thread is paused
*/
VOID ProcessServiceContinue(VOID)
{
if (ServiceStatus.dwCurrentState == SERVICE_PAUSED)
{
UpdateServiceStatus(SERVICE_CONTINUE_PENDING,
NO_ERROR,
SCM_WAIT_INTERVAL);
/* * Invoke Thread pause on ThreadHandle */
if (ResumeThread(hServiceThread) != -1)
{
UpdateServiceStatus(SERVICE_RUNNING,
NO_ERROR,
SCM_WAIT_INTERVAL);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -