Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "service_helpers.h"
  9. static CRITICAL_SECTION g_CtrlHandlerMutex;
  10. static void (*g_pInternalServiceFn)( void *pParam ) = NULL;
  11. static void *g_pInternalServiceParam = NULL;
  12. static volatile bool g_bShouldExit = false;
  13. SERVICE_STATUS MyServiceStatus;
  14. SERVICE_STATUS_HANDLE MyServiceStatusHandle = NULL;
  15. void WINAPI MyServiceCtrlHandler( DWORD Opcode )
  16. {
  17. DWORD status;
  18. switch(Opcode)
  19. {
  20. case SERVICE_CONTROL_STOP:
  21. // Do whatever it takes to stop here.
  22. ServiceHelpers_ExitEarly();
  23. MyServiceStatus.dwWin32ExitCode = 0;
  24. MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
  25. if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus) )
  26. {
  27. status = GetLastError();
  28. Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
  29. }
  30. Msg( "[MY_SERVICE] Leaving MyService \n" );
  31. return;
  32. case SERVICE_CONTROL_INTERROGATE:
  33. // Fall through to send current status.
  34. break;
  35. default:
  36. Msg("[MY_SERVICE] Unrecognized opcode %ld\n", Opcode );
  37. }
  38. // Send current status.
  39. if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
  40. {
  41. status = GetLastError();
  42. Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
  43. }
  44. }
  45. void WINAPI MyServiceStart( DWORD argc, LPTSTR *argv )
  46. {
  47. DWORD status;
  48. MyServiceStatus.dwServiceType = SERVICE_WIN32;
  49. MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  50. MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  51. MyServiceStatus.dwWin32ExitCode = 0;
  52. MyServiceStatus.dwServiceSpecificExitCode = 0;
  53. MyServiceStatus.dwCheckPoint = 0;
  54. MyServiceStatus.dwWaitHint = 0;
  55. MyServiceStatusHandle = RegisterServiceCtrlHandler( "MyService", MyServiceCtrlHandler );
  56. if ( MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 )
  57. {
  58. Msg("[MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError() );
  59. return;
  60. }
  61. // Initialization complete - report running status.
  62. MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
  63. if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
  64. {
  65. status = GetLastError();
  66. Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
  67. }
  68. // Run the app's main in-thread loop.
  69. g_pInternalServiceFn( g_pInternalServiceParam );
  70. // Tell the SCM that we're stopped.
  71. MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
  72. MyServiceStatus.dwWin32ExitCode = NO_ERROR;
  73. MyServiceStatus.dwServiceSpecificExitCode = 0;
  74. SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus );
  75. // This is where the service does its work.
  76. Msg( "[MY_SERVICE] Returning the Main Thread \n" );
  77. }
  78. void ServiceHelpers_Init()
  79. {
  80. InitializeCriticalSection( &g_CtrlHandlerMutex );
  81. }
  82. bool ServiceHelpers_StartService( const char *pServiceName, void (*pFn)( void *pParam ), void *pParam )
  83. {
  84. // Ok, just run the service.
  85. const SERVICE_TABLE_ENTRY DispatchTable[2] =
  86. {
  87. { (char*)pServiceName, MyServiceStart },
  88. { NULL, NULL }
  89. };
  90. g_pInternalServiceFn = pFn;
  91. g_pInternalServiceParam = pParam;
  92. if ( StartServiceCtrlDispatcher( DispatchTable ) )
  93. {
  94. return true;
  95. }
  96. else
  97. {
  98. Msg( "StartServiceCtrlDispatcher error = '%s'\n", GetLastErrorString() );
  99. return false;
  100. }
  101. }
  102. void ServiceHelpers_ExitEarly()
  103. {
  104. EnterCriticalSection( &g_CtrlHandlerMutex );
  105. g_bShouldExit = true;
  106. LeaveCriticalSection( &g_CtrlHandlerMutex );
  107. }
  108. bool ServiceHelpers_ShouldExit()
  109. {
  110. EnterCriticalSection( &g_CtrlHandlerMutex );
  111. bool bRet = g_bShouldExit;
  112. LeaveCriticalSection( &g_CtrlHandlerMutex );
  113. return bRet;
  114. }
  115. char* GetLastErrorString()
  116. {
  117. static char err[2048];
  118. LPVOID lpMsgBuf;
  119. FormatMessage(
  120. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  121. FORMAT_MESSAGE_FROM_SYSTEM |
  122. FORMAT_MESSAGE_IGNORE_INSERTS,
  123. NULL,
  124. GetLastError(),
  125. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  126. (LPTSTR) &lpMsgBuf,
  127. 0,
  128. NULL
  129. );
  130. strncpy( err, (char*)lpMsgBuf, sizeof( err ) );
  131. LocalFree( lpMsgBuf );
  132. err[ sizeof( err ) - 1 ] = 0;
  133. return err;
  134. }