Source code of Windows XP (NT5)
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.

362 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. bootvrfy.c
  5. Abstract:
  6. This is a small service that simply calls NotifyBootConfigStatus to
  7. indicate that the boot is acceptable. This service is to go at the
  8. end of the service dependency list.
  9. The assumption is that if we got far enough to start this service, the
  10. the boot must be ok.
  11. Author:
  12. Dan Lafferty (danl) 06 May-1991
  13. Environment:
  14. User Mode -Win32
  15. Revision History:
  16. --*/
  17. //
  18. // Includes
  19. //
  20. #include <nt.h> // DbgPrint prototype
  21. #include <ntrtl.h> // DbgPrint prototype
  22. #include <windef.h>
  23. #include <nturtl.h> // needed for winbase.h
  24. #include <winbase.h>
  25. #include <winsvc.h>
  26. #include <tstr.h> // Unicode string macros
  27. //
  28. // Defines
  29. //
  30. #define SERVICE_WAIT_TIME 0xffffffff // infinite
  31. #define BV_SERVICE_NAME L"BootVerification"
  32. //
  33. // DEBUG MACROS
  34. //
  35. //
  36. // The following allow debug print syntax to look like:
  37. //
  38. // BV_LOG(DEBUG_TRACE, "An error occured %x\n",status)
  39. //
  40. #if DBG
  41. #define STATIC
  42. #define BV_LOG0(level, string) \
  43. KdPrintEx((DPFLTR_BOOTVRFY_ID, \
  44. DEBUG_##level, \
  45. "[BootVrfy]" string))
  46. #define BV_LOG1(level, string, var1) \
  47. KdPrintEx((DPFLTR_BOOTVRFY_ID, \
  48. DEBUG_##level, \
  49. "[BootVrfy]" string, \
  50. var1))
  51. #define BV_LOG2(level, string, var1, var2) \
  52. KdPrintEx((DPFLTR_BOOTVRFY_ID, \
  53. DEBUG_##level, \
  54. "[BootVrfy]" string, \
  55. var1, \
  56. var2))
  57. #else
  58. #define STATIC static
  59. #define BV_LOG0(level, string)
  60. #define BV_LOG1(level, string, var)
  61. #define BV_LOG2(level, string, var1, var2)
  62. #endif
  63. //
  64. // Debug output is filtered at two levels: A global level and a component
  65. // specific level.
  66. //
  67. // Each debug output request specifies a component id and a filter level
  68. // or mask. These variables are used to access the debug print filter
  69. // database maintained by the system. The component id selects a 32-bit
  70. // mask value and the level either specified a bit within that mask or is
  71. // as mask value itself.
  72. //
  73. // If any of the bits specified by the level or mask are set in either the
  74. // component mask or the global mask, then the debug output is permitted.
  75. // Otherwise, the debug output is filtered and not printed.
  76. //
  77. // The component mask for filtering the debug output of this component is
  78. // Kd_BOOTVRFY_Mask and may be set via the registry or the kernel debugger.
  79. //
  80. // The global mask for filtering the debug output of all components is
  81. // Kd_WIN2000_Mask and may be set via the registry or the kernel debugger.
  82. //
  83. // The registry key for setting the mask value for this component is:
  84. //
  85. // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\
  86. // Session Manager\Debug Print Filter\BOOTVRFY
  87. //
  88. // The key "Debug Print Filter" may have to be created in order to create
  89. // the component key.
  90. //
  91. // The following levels are used to filter debug output.
  92. //
  93. #define DEBUG_ERROR (0x00000001 | DPFLTR_MASK)
  94. #define DEBUG_TRACE (0x00000004 | DPFLTR_MASK)
  95. #define DEBUG_ALL (0xffffffff | DPFLTR_MASK)
  96. //
  97. // Globals
  98. //
  99. SERVICE_STATUS BootVerificationStatus;
  100. HANDLE BootVerificationDoneEvent;
  101. SERVICE_STATUS_HANDLE BootVerificationStatusHandle;
  102. //
  103. // Function Prototypes
  104. //
  105. STATIC VOID
  106. BootVerificationStart (
  107. DWORD argc,
  108. LPWSTR *argv
  109. );
  110. STATIC VOID
  111. BootVerificationCtrlHandler (
  112. IN DWORD opcode
  113. );
  114. /****************************************************************************/
  115. VOID __cdecl
  116. main(void)
  117. {
  118. DWORD status;
  119. SERVICE_TABLE_ENTRYW DispatchTable[] = {
  120. { BV_SERVICE_NAME, BootVerificationStart },
  121. { NULL, NULL }
  122. };
  123. status = StartServiceCtrlDispatcherW( DispatchTable);
  124. BV_LOG0(TRACE,"The Service Process is Terminating....\n");
  125. ExitProcess(0);
  126. }
  127. /****************************************************************************/
  128. //
  129. // BootVerification will take a long time to respond to pause
  130. //
  131. //
  132. VOID
  133. BootVerificationStart (
  134. DWORD argc,
  135. LPWSTR *argv
  136. )
  137. {
  138. DWORD status;
  139. SC_HANDLE hScManager;
  140. SC_HANDLE hService;
  141. SERVICE_STATUS ServiceStatus;
  142. BV_LOG0(TRACE,"Inside the BootVerification Service Thread\n");
  143. BootVerificationDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  144. //
  145. // Fill in this services status structure
  146. //
  147. BootVerificationStatus.dwServiceType = SERVICE_WIN32;
  148. BootVerificationStatus.dwCurrentState = SERVICE_RUNNING;
  149. BootVerificationStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  150. BootVerificationStatus.dwWin32ExitCode = 0;
  151. BootVerificationStatus.dwServiceSpecificExitCode = 0;
  152. BootVerificationStatus.dwCheckPoint = 0;
  153. BootVerificationStatus.dwWaitHint = 0;
  154. //
  155. // Register the Control Handler routine.
  156. //
  157. BV_LOG0(TRACE,"Getting Ready to call RegisterServiceCtrlHandler\n");
  158. BootVerificationStatusHandle = RegisterServiceCtrlHandlerW(
  159. BV_SERVICE_NAME,
  160. BootVerificationCtrlHandler);
  161. if (BootVerificationStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  162. BV_LOG1(ERROR,"RegisterServiceCtrlHandlerW failed %d\n", GetLastError());
  163. }
  164. //
  165. // Return the status
  166. //
  167. if (!SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus)) {
  168. status = GetLastError();
  169. BV_LOG1(ERROR,"SetServiceStatus error %ld\n",status);
  170. }
  171. //
  172. // Tell Service Controller that the Boot is OK.
  173. //
  174. BV_LOG0(TRACE,"Tell Service Controller that the boot is ok\n");
  175. if (!NotifyBootConfigStatus(TRUE)) {
  176. BV_LOG0(ERROR,"NotifyBootConfigStatus Failed\n");
  177. }
  178. ////////////////////////////////////////////////////////////////////////
  179. //
  180. // Tell the Service Controller that we want to shut down now.
  181. //
  182. // If anything fails along the way, just exit process, and allow
  183. // the service controller to clean up.
  184. //
  185. BV_LOG0(TRACE,"Send Control to Service Controller to shut down BOOTVFY\n");
  186. hScManager = OpenSCManagerW(
  187. NULL,
  188. NULL,
  189. SC_MANAGER_CONNECT);
  190. if (hScManager == NULL) {
  191. status = GetLastError();
  192. BV_LOG1(ERROR,"OpenSCManager failed %d\n",status);
  193. BootVerificationStatus.dwWin32ExitCode = status;
  194. SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus);
  195. ExitProcess(0);
  196. }
  197. hService = OpenServiceW(
  198. hScManager,
  199. BV_SERVICE_NAME,
  200. SERVICE_STOP);
  201. if (hService == NULL) {
  202. status = GetLastError();
  203. BV_LOG1(ERROR,"OpenService failed %d\n",status);
  204. BootVerificationStatus.dwWin32ExitCode = status;
  205. SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus);
  206. ExitProcess(0);
  207. }
  208. if (!ControlService (hService,SERVICE_CONTROL_STOP,&ServiceStatus)) {
  209. status = GetLastError();
  210. BV_LOG1(ERROR,"OpenService failed %d\n",status);
  211. BootVerificationStatus.dwWin32ExitCode = status;
  212. SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus);
  213. ExitProcess(0);
  214. }
  215. ////////////////////////////////////////////////////////////////////////
  216. //
  217. // Wait forever until we are told to terminate.
  218. //
  219. status = WaitForSingleObject (
  220. BootVerificationDoneEvent,
  221. SERVICE_WAIT_TIME);
  222. BV_LOG0(TRACE,"Leaving the BootVerification service\n");
  223. BootVerificationStatus.dwWin32ExitCode = 0;
  224. BootVerificationStatus.dwCurrentState = SERVICE_STOPPED;
  225. if (!SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus)) {
  226. status = GetLastError();
  227. BV_LOG1(ERROR,"SetServiceStatus error %ld\n",status);
  228. }
  229. ExitThread(NO_ERROR);
  230. return;
  231. }
  232. /****************************************************************************/
  233. VOID
  234. BootVerificationCtrlHandler (
  235. IN DWORD Opcode
  236. )
  237. {
  238. DWORD status;
  239. BV_LOG1(TRACE,"opcode = %ld\n", Opcode);
  240. //
  241. // Find and operate on the request.
  242. //
  243. switch(Opcode) {
  244. case SERVICE_CONTROL_PAUSE:
  245. break;
  246. case SERVICE_CONTROL_CONTINUE:
  247. break;
  248. case SERVICE_CONTROL_STOP:
  249. BootVerificationStatus.dwWin32ExitCode = 0;
  250. BootVerificationStatus.dwCurrentState = SERVICE_STOP_PENDING;
  251. SetEvent(BootVerificationDoneEvent);
  252. break;
  253. case SERVICE_CONTROL_INTERROGATE:
  254. break;
  255. default:
  256. BV_LOG1(ERROR,"Unrecognized opcode %ld\n", Opcode);
  257. }
  258. //
  259. // Send a status response.
  260. //
  261. if (!SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus)) {
  262. status = GetLastError();
  263. BV_LOG1(ERROR,"SetServiceStatus error %ld\n",status);
  264. }
  265. return;
  266. }