Leaked source code of windows server 2003
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.

272 lines
6.0 KiB

  1. #include "stdinc.h"
  2. #pragma hdrstop
  3. #include <svcs.h>
  4. #include "sxsserviceserver.h"
  5. EXTERN_C RPC_IF_HANDLE SxsStoreManager_ServerIfHandle;
  6. BOOL
  7. CServiceStatus::Initialize(
  8. PCWSTR pcwszServiceName,
  9. LPHANDLER_FUNCTION pHandler,
  10. DWORD dwServiceType,
  11. DWORD dwControlsAccepted,
  12. DWORD dwInitialState
  13. )
  14. {
  15. NTSTATUS status = STATUS_SUCCESS;
  16. BOOL fSuccess = FALSE;
  17. //
  18. // Double-initialization isn't a bad thing, but it's frowned on.
  19. //
  20. ASSERT(m_StatusHandle == NULL);
  21. if (m_StatusHandle != NULL)
  22. return TRUE;
  23. InitializeCriticalSection(&m_CSection);
  24. //
  25. // Register this service as owning the service status
  26. //
  27. m_StatusHandle = RegisterServiceCtrlHandler(pcwszServiceName, pHandler);
  28. if (m_StatusHandle == NULL) {
  29. goto Failure;
  30. }
  31. //
  32. // Set the initial state of the world
  33. //
  34. ZeroMemory(static_cast<SERVICE_STATUS*>(this), sizeof(SERVICE_STATUS));
  35. this->dwServiceType = dwServiceType;
  36. this->dwCurrentState = dwInitialState;
  37. this->dwControlsAccepted = dwControlsAccepted;
  38. if (!SetServiceStatus(m_StatusHandle, this)) {
  39. goto Failure;
  40. }
  41. return TRUE;
  42. Failure:
  43. {
  44. const DWORD dwLastError = ::GetLastError();
  45. DeleteCriticalSection(&m_CSection);
  46. m_StatusHandle = NULL;
  47. SetLastError(dwLastError);
  48. }
  49. return FALSE;
  50. }
  51. BOOL
  52. CServiceStatus::SetServiceState(
  53. DWORD dwStatus,
  54. DWORD dwCheckpoint
  55. )
  56. {
  57. BOOL fSuccess = FALSE;
  58. EnterCriticalSection(&m_CSection);
  59. __try {
  60. if (m_StatusHandle != NULL) {
  61. this->dwCurrentState = dwStatus;
  62. if (dwCheckpoint != 0xFFFFFFFF) {
  63. this->dwCheckPoint = dwCheckpoint;
  64. }
  65. fSuccess = SetServiceStatus(m_StatusHandle, this);
  66. }
  67. }
  68. __finally {
  69. LeaveCriticalSection(&m_CSection);
  70. }
  71. return fSuccess;
  72. }
  73. //
  74. // In-place construction
  75. //
  76. bool
  77. CServiceStatus::Construct(
  78. CServiceStatus *&pServiceStatusTarget
  79. )
  80. {
  81. ASSERT(pServiceStatusTarget == NULL);
  82. return (pServiceStatusTarget = new CServiceStatus) != NULL;
  83. }
  84. EXTERN_C HANDLE g_hFakeServiceControllerThread = INVALID_HANDLE_VALUE;
  85. EXTERN_C DWORD g_dwFakeServiceControllerThreadId = 0;
  86. EXTERN_C PSVCHOST_GLOBAL_DATA g_pGlobalServiceData = NULL;
  87. BYTE g_rgbServiceStatusStorage[sizeof(CServiceStatus)];
  88. EXTERN_C CServiceStatus *g_pServiceStatus = NULL;
  89. //
  90. // The service host will call this to send in API callbacks
  91. //
  92. VOID
  93. SvchostPushServiceGlobals(
  94. PSVCHOST_GLOBAL_DATA pGlobals
  95. )
  96. {
  97. ASSERT(g_pGlobalServiceData == NULL);
  98. g_pGlobalServiceData = pGlobals;
  99. }
  100. PVOID operator new(size_t cb, PVOID pv) {
  101. return pv;
  102. }
  103. //
  104. // Control handler for service notifications
  105. //
  106. VOID
  107. ServiceHandler(
  108. DWORD dwControlCode
  109. )
  110. {
  111. return;
  112. }
  113. #define CHECKPOINT_ZERO (0)
  114. #define CHECKPOINT_RPC_STARTED (1)
  115. //
  116. // Stop the service with an error code, ERROR_SUCCESS for a successful stoppage
  117. //
  118. VOID
  119. ShutdownService(
  120. DWORD dwLastError
  121. )
  122. {
  123. return;
  124. }
  125. //
  126. // Where the fun starts
  127. //
  128. VOID WINAPI
  129. ServiceMain(
  130. DWORD dwServiceArgs,
  131. LPWSTR lpServiceArgList[]
  132. )
  133. {
  134. NTSTATUS status = STATUS_SUCCESS;
  135. //
  136. // svchost must have given us some global data before we got to this point.
  137. //
  138. ASSERT(g_pGlobalServiceData != NULL);
  139. ASSERT(g_pServiceStatus == NULL);
  140. g_pServiceStatus = new (g_rgbServiceStatusStorage) CServiceStatus;
  141. if (!g_pServiceStatus->Initialize(
  142. SXS_STORE_SERVICE_NAME, ServiceHandler,
  143. SERVICE_WIN32,
  144. SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE,
  145. SERVICE_START_PENDING))
  146. {
  147. DebugPrint(DBGPRINT_LVL_ERROR, "Can't start service status handler, error 0x%08lx\n", ::GetLastError());
  148. }
  149. //
  150. // Go initialize RPC, and register our interface. If this fails, we shut down.
  151. //
  152. status = g_pGlobalServiceData->StartRpcServer(
  153. SXS_STORE_SERVICE_NAME,
  154. SxsStoreManager_ServerIfHandle);
  155. if (!NT_SUCCESS(status)) {
  156. ShutdownService(status);
  157. return;
  158. }
  159. //
  160. // Tell the world that we're off and running
  161. //
  162. g_pServiceStatus->SetServiceState(SERVICE_RUNNING);
  163. return;
  164. }
  165. DWORD WINAPI FakeServiceController(PVOID pvCookie);
  166. //
  167. // This stub will start a dispatch thread, and then call into the
  168. // service main function
  169. //
  170. BOOL
  171. FakeRunningAsService()
  172. {
  173. //
  174. // Create a thread running the service dispatch function, and then call
  175. // the service main function to get things rolling
  176. //
  177. g_hFakeServiceControllerThread = CreateThread(
  178. NULL,
  179. 0,
  180. FakeServiceController,
  181. 0,
  182. 0,
  183. &g_dwFakeServiceControllerThreadId);
  184. if (g_hFakeServiceControllerThread == NULL) {
  185. return FALSE;
  186. }
  187. ServiceMain(0, NULL);
  188. return TRUE;
  189. }
  190. VOID __cdecl wmain(INT argc, WCHAR** argv)
  191. {
  192. SERVICE_TABLE_ENTRYW SxsGacServiceEntries[] = {
  193. { SXS_STORE_SERVICE_NAME, ServiceMain },
  194. { NULL, NULL }
  195. };
  196. BOOL RunningAsService = TRUE;
  197. BOOL fSuccess = FALSE;
  198. if (argc > 1 && (lstrcmpiW(argv[1], L"notservice") == 0)) {
  199. RunningAsService = FALSE;
  200. }
  201. if (RunningAsService) {
  202. fSuccess = StartServiceCtrlDispatcherW(SxsGacServiceEntries);
  203. if (!fSuccess) {
  204. const DWORD dwError = ::GetLastError();
  205. DebugPrint(DBGPRINT_LVL_ERROR, "Failed starting service dispatch, error %ld\n", dwError);
  206. }
  207. }
  208. else {
  209. fSuccess = FakeRunningAsService();
  210. if (!fSuccess) {
  211. const DWORD dwError = ::GetLastError();
  212. DebugPrint(DBGPRINT_LVL_ERROR, "Failed faking service startup, error %ld\n", dwError);
  213. }
  214. }
  215. return;
  216. }