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.

322 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. splinit.c
  5. Abstract:
  6. Spooler Service Initialization Routines.
  7. The following is a list of functions in this file:
  8. SpoolerInitializeSpooler
  9. Author:
  10. Krishna Ganugapati (KrishnaG) 17-Oct-1993
  11. Environment:
  12. User Mode - Win32
  13. Notes:
  14. optional-notes
  15. Revision History:
  16. 4-Jan-1999 Khaleds
  17. Added Code for optimiziting the load time of the spooler by decoupling
  18. the startup dependency between spoolsv and spoolss
  19. 17-October-1993 KrishnaG
  20. Created.
  21. --*/
  22. #include "precomp.h"
  23. #include "server.h"
  24. #include "client.h"
  25. #include "splsvr.h"
  26. #include "kmspool.h"
  27. DWORD MessageThreadId; // message thread ID
  28. extern DWORD GetSpoolMessages(VOID);
  29. HANDLE hPhase2Init = NULL;
  30. //
  31. // Following is to make sure only one spooler process runs at a time.
  32. // When spooler is asked to stop it will tell SCM SERVICE_STOPPED but it may
  33. // be some more time before the spoolsv process dies.
  34. // In the meantime if a SCM starts another spooler process it will not
  35. // initialize. This is because GDI assumes one spooler process at a time.
  36. //
  37. // To fix when spooler is asked to stop it creates a named event Spooler_exiting
  38. // The handle to which will be closed when the process dies.
  39. //
  40. // On spooler startup we will look for this event and wait for it to go away.
  41. // A named event goes away when the last handle is closed.
  42. //
  43. //
  44. WCHAR szSpoolerExitingEvent[] = L"Spooler_exiting";
  45. const PrintSpoolerServerExports gServerExports =
  46. {
  47. ServerAllowRemoteCalls,
  48. ServerGetPolicy
  49. };
  50. #define WAITFOR_SPOOLEREXIT_TIMEOUT 3*1000
  51. BOOL
  52. PreInitializeRouter(
  53. SERVICE_STATUS_HANDLE SpoolerStatusHandle
  54. );
  55. DWORD
  56. SpoolerInitializeSpooler(
  57. DWORD argc,
  58. LPTSTR *argv
  59. )
  60. /*++
  61. Routine Description:
  62. Registers the control handler with the dispatcher thread. Then it
  63. performs all initialization including the starting of the RPC server.
  64. If any of the initialization fails, SpoolerStatusUpdate is called so that the
  65. status is updated and the thread is terminated.
  66. Arguments:
  67. Return Value:
  68. --*/
  69. {
  70. RPC_STATUS rpcStatus;
  71. DWORD Win32status;
  72. HANDLE hThread, hEvent;
  73. DWORD ThreadId;
  74. ULONG HeapFragValue = 2;
  75. //
  76. // Initialize the ThreadCritical Section which serializes access to
  77. // the Status database.
  78. //
  79. if (!InitializeCriticalSectionAndSpinCount(&ThreadCriticalSection, 0x80000000))
  80. {
  81. return GetLastError();
  82. }
  83. //
  84. // Initialize the status structure
  85. //
  86. SpoolerStatusInit();
  87. //
  88. // NTRAID#NTBUG9-751157-2002/12/13 : Disable HKCU to prevent driver HKCU leak which
  89. // cause roaming profile loading error.
  90. //
  91. RegDisablePredefinedCache();
  92. //
  93. // Activate LFH (low fragmentation) for the process heap. We ignore the return value.
  94. // LHF cannot be activated if certain gflags are set.
  95. //
  96. HeapSetInformation(GetProcessHeap(),
  97. HeapCompatibilityInformation,
  98. &HeapFragValue,
  99. sizeof(HeapFragValue));
  100. //
  101. // Register this service with the ControlHandler.
  102. // Now we can accept control requests and be requested to UNINSTALL.
  103. //
  104. DBGMSG(DBG_TRACE, ("Calling RegisterServiceCtrlHandler\n"));
  105. if ((SpoolerStatusHandle = RegisterServiceCtrlHandlerEx(
  106. SERVICE_SPOOLER,
  107. SpoolerCtrlHandler,
  108. NULL
  109. )) == (SERVICE_STATUS_HANDLE)ERROR_SUCCESS) {
  110. Win32status = GetLastError();
  111. DBGMSG(DBG_ERROR,
  112. ("FAILURE: RegisterServiceCtrlHandler status = %d\n", Win32status));
  113. return( SpoolerBeginForcedShutdown (
  114. IMMEDIATE,
  115. Win32status,
  116. (DWORD)0
  117. ));
  118. }
  119. //
  120. // Notify that installation is pending
  121. //
  122. SpoolerState = SpoolerStatusUpdate(STARTING);
  123. if (SpoolerState != STARTING) {
  124. //
  125. // An UNINSTALL control request must have been received
  126. //
  127. return(SpoolerState);
  128. }
  129. //
  130. // If there is another spooler process exiting wait for it to die
  131. // Look at comments in splctrlh.c
  132. //
  133. for ( ; ; ) {
  134. hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, szSpoolerExitingEvent);
  135. if ( hEvent == NULL )
  136. break;
  137. DBGMSG(DBG_WARNING, ("Waiting for previous spooler to exit\n"));
  138. CloseHandle(hEvent);
  139. SpoolerState = SpoolerStatusUpdate(STARTING);
  140. if (SpoolerState != STARTING) {
  141. //
  142. // An UNINSTALL control request must have been received
  143. //
  144. return(SpoolerState);
  145. }
  146. Sleep(WAITFOR_SPOOLEREXIT_TIMEOUT);
  147. }
  148. hPhase2Init = CreateEvent( NULL, TRUE, FALSE, L"RouterPreInitEvent" );
  149. if (hPhase2Init == NULL)
  150. {
  151. //
  152. // Fail if the event is not created
  153. //
  154. DBGMSG(DBG_ERROR, ("Failed to create Phase2Init Event, error %d\n", GetLastError()));
  155. ExitProcess(0);
  156. }
  157. DBGMSG(DBG_TRACE,
  158. ("SpoolerInitializeSpooler:getting ready to start RPC server\n"));
  159. rpcStatus = SpoolerStartRpcServer();
  160. if (rpcStatus != RPC_S_OK) {
  161. DBGMSG(DBG_WARN, ("RPC Initialization Failed %d\n", rpcStatus));
  162. return (SpoolerBeginForcedShutdown(
  163. PENDING,
  164. rpcStatus,
  165. (DWORD)0
  166. ));
  167. }
  168. SpoolerStatusUpdate(STARTING);
  169. DBGMSG(DBG_TRACE,
  170. ("SpoolerInitializeSpooler:Getting ready to kick off the Router\n"));
  171. hThread = CreateThread(NULL,
  172. LARGE_INITIAL_STACK_COMMIT,
  173. (LPTHREAD_START_ROUTINE)PreInitializeRouter,
  174. (LPVOID)SpoolerStatusHandle,
  175. 0,
  176. &ThreadId);
  177. if( hThread ){
  178. CloseHandle(hThread);
  179. //
  180. // Create Kernel Spooler Message Thread
  181. //
  182. Win32status=GetSpoolMessages();
  183. } else {
  184. Win32status = GetLastError();
  185. }
  186. if (Win32status != ERROR_SUCCESS) {
  187. DBGMSG(DBG_WARNING, ("Kernel Spooler Messaging Initialization Failed %d\n", Win32status));
  188. return SpoolerBeginForcedShutdown(PENDING, Win32status, (DWORD) 0);
  189. }
  190. //
  191. // Update the status to indicate that installation is complete.
  192. // Get the current state back in case the ControlHandling thread has
  193. // told us to shutdown.
  194. //
  195. DBGMSG(DBG_TRACE, ("Exiting SpoolerInitializeSpooler - Init Done!\n"));
  196. return (SpoolerStatusUpdate(RUNNING));
  197. }
  198. BOOL
  199. PreInitializeRouter(
  200. SERVICE_STATUS_HANDLE SpoolerStatusHandle
  201. )
  202. {
  203. HANDLE hThread = NULL;
  204. BOOL bRet = FALSE;
  205. RouterInitializationParams *pRouterParams = NULL;
  206. DWORD ThreadId;
  207. pRouterParams = AllocSplMem(sizeof(*pRouterParams));
  208. bRet = pRouterParams != NULL;
  209. if (bRet)
  210. {
  211. pRouterParams->SpoolerStatusHandle = SpoolerStatusHandle;
  212. pRouterParams->pExports = &gServerExports;
  213. //
  214. // Wait on hPhase2Init
  215. //
  216. WaitForSingleObject( hPhase2Init, SPOOLER_START_PHASE_TWO_INIT );
  217. hThread = CreateThread(NULL,
  218. LARGE_INITIAL_STACK_COMMIT,
  219. (LPTHREAD_START_ROUTINE) InitializeRouter,
  220. (LPVOID)pRouterParams,
  221. 0,
  222. &ThreadId);
  223. if (hThread)
  224. {
  225. CloseHandle(hThread);
  226. }
  227. else
  228. {
  229. bRet = FALSE;
  230. FreeSplMem(pRouterParams);
  231. }
  232. }
  233. return bRet;
  234. }