1
This commit is contained in:
181
utils/vmpi/vmpi_service/service_helpers.cpp
Normal file
181
utils/vmpi/vmpi_service/service_helpers.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "service_helpers.h"
|
||||
|
||||
|
||||
static CRITICAL_SECTION g_CtrlHandlerMutex;
|
||||
|
||||
static void (*g_pInternalServiceFn)( void *pParam ) = NULL;
|
||||
static void *g_pInternalServiceParam = NULL;
|
||||
|
||||
static volatile bool g_bShouldExit = false;
|
||||
|
||||
|
||||
SERVICE_STATUS MyServiceStatus;
|
||||
SERVICE_STATUS_HANDLE MyServiceStatusHandle = NULL;
|
||||
|
||||
|
||||
void WINAPI MyServiceCtrlHandler( DWORD Opcode )
|
||||
{
|
||||
DWORD status;
|
||||
|
||||
switch(Opcode)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP:
|
||||
// Do whatever it takes to stop here.
|
||||
ServiceHelpers_ExitEarly();
|
||||
|
||||
MyServiceStatus.dwWin32ExitCode = 0;
|
||||
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
|
||||
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus) )
|
||||
{
|
||||
status = GetLastError();
|
||||
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
|
||||
}
|
||||
|
||||
Msg( "[MY_SERVICE] Leaving MyService \n" );
|
||||
return;
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
// Fall through to send current status.
|
||||
break;
|
||||
|
||||
default:
|
||||
Msg("[MY_SERVICE] Unrecognized opcode %ld\n", Opcode );
|
||||
}
|
||||
|
||||
// Send current status.
|
||||
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
|
||||
{
|
||||
status = GetLastError();
|
||||
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WINAPI MyServiceStart( DWORD argc, LPTSTR *argv )
|
||||
{
|
||||
DWORD status;
|
||||
|
||||
MyServiceStatus.dwServiceType = SERVICE_WIN32;
|
||||
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
MyServiceStatus.dwWin32ExitCode = 0;
|
||||
MyServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
MyServiceStatus.dwCheckPoint = 0;
|
||||
MyServiceStatus.dwWaitHint = 0;
|
||||
|
||||
MyServiceStatusHandle = RegisterServiceCtrlHandler( "MyService", MyServiceCtrlHandler );
|
||||
if ( MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 )
|
||||
{
|
||||
Msg("[MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialization complete - report running status.
|
||||
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
|
||||
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
|
||||
{
|
||||
status = GetLastError();
|
||||
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
|
||||
}
|
||||
|
||||
|
||||
// Run the app's main in-thread loop.
|
||||
g_pInternalServiceFn( g_pInternalServiceParam );
|
||||
|
||||
|
||||
// Tell the SCM that we're stopped.
|
||||
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
MyServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||||
MyServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus );
|
||||
|
||||
|
||||
// This is where the service does its work.
|
||||
Msg( "[MY_SERVICE] Returning the Main Thread \n" );
|
||||
}
|
||||
|
||||
|
||||
void ServiceHelpers_Init()
|
||||
{
|
||||
InitializeCriticalSection( &g_CtrlHandlerMutex );
|
||||
}
|
||||
|
||||
|
||||
bool ServiceHelpers_StartService( const char *pServiceName, void (*pFn)( void *pParam ), void *pParam )
|
||||
{
|
||||
// Ok, just run the service.
|
||||
const SERVICE_TABLE_ENTRY DispatchTable[2] =
|
||||
{
|
||||
{ (char*)pServiceName, MyServiceStart },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
g_pInternalServiceFn = pFn;
|
||||
g_pInternalServiceParam = pParam;
|
||||
|
||||
if ( StartServiceCtrlDispatcher( DispatchTable ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "StartServiceCtrlDispatcher error = '%s'\n", GetLastErrorString() );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ServiceHelpers_ExitEarly()
|
||||
{
|
||||
EnterCriticalSection( &g_CtrlHandlerMutex );
|
||||
g_bShouldExit = true;
|
||||
LeaveCriticalSection( &g_CtrlHandlerMutex );
|
||||
}
|
||||
|
||||
|
||||
bool ServiceHelpers_ShouldExit()
|
||||
{
|
||||
EnterCriticalSection( &g_CtrlHandlerMutex );
|
||||
bool bRet = g_bShouldExit;
|
||||
LeaveCriticalSection( &g_CtrlHandlerMutex );
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
char* GetLastErrorString()
|
||||
{
|
||||
static char err[2048];
|
||||
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
strncpy( err, (char*)lpMsgBuf, sizeof( err ) );
|
||||
LocalFree( lpMsgBuf );
|
||||
|
||||
err[ sizeof( err ) - 1 ] = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user