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.

388 lines
8.8 KiB

  1. #include "stdafx.h"
  2. #if !defined(BITS_V12_ON_NT4)
  3. #include "init.tmh"
  4. #endif
  5. EVENT_LOG * g_EventLogger;
  6. BOOL
  7. CreateAndWaitForThread(
  8. LPTHREAD_START_ROUTINE fn,
  9. HANDLE * pThreadHandle,
  10. DWORD * pThreadId
  11. );
  12. //
  13. // The whole block of code is an attempt to work
  14. // around the C++ termination handler. The idea is to
  15. // intercept the C++ exception code and map it to
  16. // a bogus code which probably won't be handled.
  17. // This should give us the Dr. Watson.
  18. //
  19. // The NT exception # used by C runtime
  20. #define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000)
  21. DWORD BackgroundThreadProcFilter(
  22. LPEXCEPTION_POINTERS ExceptionPointers )
  23. {
  24. // Values are 32 bit values layed out as follows:
  25. //
  26. // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  27. // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  28. // +---+-+-+-----------------------+-------------------------------+
  29. // |Sev|C|R| Facility | Code |
  30. // +---+-+-+-----------------------+-------------------------------+
  31. // pick a random code that probably won't be handled.
  32. if ( EH_EXCEPTION_NUMBER == ExceptionPointers->ExceptionRecord->ExceptionCode )
  33. ExceptionPointers->ExceptionRecord->ExceptionCode = 0xE0000001;
  34. return EXCEPTION_CONTINUE_SEARCH;
  35. }
  36. DWORD BackgroundThreadProc( void *lp );
  37. DWORD WINAPI BackgroundThreadProcWrap( void *lp )
  38. {
  39. __try
  40. {
  41. return BackgroundThreadProc( lp );
  42. }
  43. __except( BackgroundThreadProcFilter(
  44. GetExceptionInformation() ) )
  45. {
  46. ASSERT( 0 );
  47. }
  48. ASSERT( 0 );
  49. return 0;
  50. }
  51. DWORD BackgroundThreadProc( void *lp )
  52. //
  53. // 5-18-2001: I'm avoiding LogInfo calls before g_Manager is initialized,
  54. // in order to catch a bug where init and Uninit seem to overlap.
  55. //
  56. {
  57. MSG msg;
  58. HRESULT hr = S_OK;
  59. DWORD dwRegCONew = 0;
  60. DWORD dwRegCOOld = 0;
  61. DWORD instance = g_ServiceInstance;
  62. HANDLE hEvent = (HANDLE) lp;
  63. //CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); //not on Win95!
  64. //hr = CoInitialize(NULL);
  65. hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  66. if (FAILED(hr))
  67. {
  68. LogInfo( "background thread failed CoInit, instance %d, hr %x", instance, hr );
  69. return hr;
  70. }
  71. //force it to create a msg queue
  72. PeekMessage(&msg, NULL, WM_APP, WM_APP, PM_NOREMOVE);
  73. try
  74. {
  75. ASSERT( g_Manager == NULL );
  76. g_EventLogger = new EVENT_LOG;
  77. g_Manager = new CJobManager;
  78. LogInfo( "background thread starting, instance %d, manager %p", instance, g_Manager );
  79. THROW_HRESULT( g_Manager->Unserialize() );
  80. //
  81. // List currently active users as logged in.
  82. // List the Big Three service accounts as logged in.
  83. //
  84. THROW_HRESULT( g_Manager->m_Users.AddActiveUsers() );
  85. THROW_HRESULT( g_Manager->m_Users.AddServiceAccounts() );
  86. g_Manager->m_Users.Dump();
  87. //
  88. // If any networks are active, begin processing jobs.
  89. //
  90. g_Manager->OnNetworkChange();
  91. //
  92. // Allow client calls.
  93. //
  94. THROW_HRESULT( g_Manager->RegisterClassObjects() );
  95. LogInfo( "Background thread initialized.");
  96. //
  97. // The thread has set up completely.
  98. //
  99. SetEvent( hEvent );
  100. }
  101. catch (ComError exception)
  102. {
  103. hr = exception.Error();
  104. LogInfo( "background thread failed, instance %d, hr %x", instance, hr );
  105. goto exit;
  106. }
  107. catch (HRESULT exception )
  108. {
  109. LogError( "init : caught unhandled HRESULT %x", exception);
  110. #ifdef DBG
  111. DbgBreakPoint();
  112. #endif
  113. hr = exception;
  114. goto exit;
  115. }
  116. catch (DWORD exception )
  117. {
  118. LogError( "init : caught unhandled error %d", exception);
  119. #ifdef DBG
  120. DbgBreakPoint();
  121. #endif
  122. hr = exception;
  123. goto exit;
  124. }
  125. //
  126. // Message & task pump: returns only when the object shuts down.
  127. // Intentionally, call this function outside of a try/catch
  128. // since any unhandled exception in this function should
  129. // be an AV.
  130. g_Manager->TaskThread();
  131. exit:
  132. LogInfo("task thread exiting, hr %x", hr);
  133. if (g_Manager)
  134. {
  135. ASSERT( instance == g_ServiceInstance );
  136. g_Manager->Shutdown();
  137. delete g_Manager;
  138. g_Manager = NULL;
  139. }
  140. delete g_EventLogger; g_EventLogger = NULL;
  141. CoUninitialize();
  142. return hr;
  143. }
  144. HANDLE g_hBackgroundThread;
  145. DWORD g_dwBackgroundThreadId;
  146. // void TestImpersonationObjects();
  147. HRESULT WINAPI
  148. InitQmgr()
  149. {
  150. ++g_ServiceInstance;
  151. if (!CreateAndWaitForThread( BackgroundThreadProcWrap,
  152. &g_hBackgroundThread,
  153. &g_dwBackgroundThreadId
  154. ))
  155. {
  156. return HRESULT_FROM_WIN32( GetLastError() );
  157. }
  158. LogInfo( "Finishing InitQmgr()" );
  159. return S_OK;
  160. }
  161. HRESULT WINAPI
  162. UninitQmgr()
  163. {
  164. DWORD s;
  165. HANDLE hThread = g_hBackgroundThread;
  166. if (hThread == NULL)
  167. {
  168. // never set up
  169. LogInfo("Uninit Qmgr: nothing to do");
  170. return S_OK;
  171. }
  172. LogInfo("Uninit Qmgr: beginning");
  173. //
  174. // Tell the thread to terminate.
  175. //
  176. // 3.5 interrupt the downloader.
  177. g_Manager->LockWriter();
  178. // Hold the writer lock while killing the downloader.
  179. g_Manager->InterruptDownload();
  180. g_Manager->UnlockWriter();
  181. PostThreadMessage(g_dwBackgroundThreadId, WM_QUIT, 0, 0);
  182. g_dwBackgroundThreadId = 0;
  183. g_hBackgroundThread = NULL;
  184. //
  185. // Wait until the thread actually terminates.
  186. //
  187. s = WaitForSingleObject( hThread, INFINITE );
  188. LogInfo("Uninit Qmgr: wait finished with %d", s);
  189. CloseHandle(hThread);
  190. if (s != WAIT_OBJECT_0)
  191. {
  192. return HRESULT_FROM_WIN32( s );
  193. }
  194. return S_OK;
  195. }
  196. HRESULT
  197. CheckServerInstance(
  198. long ObjectServiceInstance
  199. )
  200. {
  201. IncrementCallCount();
  202. if (g_ServiceInstance != ObjectServiceInstance ||
  203. g_ServiceState != MANAGER_ACTIVE)
  204. {
  205. LogWarning("call blocked: mgr state %d, instance %d vs. %d",
  206. g_ServiceState, g_ServiceInstance, ObjectServiceInstance);
  207. DecrementCallCount();
  208. return CO_E_SERVER_STOPPING;
  209. }
  210. return S_OK;
  211. }
  212. BOOL
  213. CreateAndWaitForThread(
  214. LPTHREAD_START_ROUTINE fn,
  215. HANDLE * pThreadHandle,
  216. DWORD * pThreadId
  217. )
  218. {
  219. HANDLE hThread = NULL;
  220. HANDLE hEvent = NULL;
  221. HANDLE Handles[2];
  222. DWORD dwThreadID;
  223. DWORD s = 0;
  224. *pThreadHandle = NULL;
  225. *pThreadId = 0;
  226. //
  227. // Create the message-pump thread, then wait for the thread to exit or to signal success.
  228. //
  229. hEvent = CreateEvent( NULL, // no security
  230. FALSE, // not manual reset
  231. FALSE, // initially not set
  232. NULL
  233. );
  234. if (!hEvent)
  235. {
  236. goto Cleanup;
  237. }
  238. hThread = CreateThread(NULL, 0, fn, PVOID(hEvent), 0, &dwThreadID);
  239. if (hThread == NULL)
  240. {
  241. goto Cleanup;
  242. }
  243. enum
  244. {
  245. THREAD_INDEX = 0,
  246. EVENT_INDEX = 1
  247. };
  248. Handles[ THREAD_INDEX ] = hThread;
  249. Handles[ EVENT_INDEX ] = hEvent;
  250. s = WaitForMultipleObjects( 2, // 2 handles
  251. Handles,
  252. FALSE, // don't wait for all
  253. INFINITE
  254. );
  255. switch (s)
  256. {
  257. case WAIT_OBJECT_0 + THREAD_INDEX:
  258. {
  259. // the thread exited.
  260. if (GetExitCodeThread( hThread, &s))
  261. {
  262. SetLastError( s );
  263. }
  264. goto Cleanup;
  265. }
  266. case WAIT_OBJECT_0 + EVENT_INDEX:
  267. {
  268. // success
  269. break;
  270. }
  271. default:
  272. {
  273. // some random error. We are really toasted if
  274. // WaitForMultipleObjects is failing.
  275. ASSERT(0);
  276. goto Cleanup;
  277. }
  278. }
  279. CloseHandle( hEvent );
  280. hEvent = NULL;
  281. *pThreadHandle = hThread;
  282. *pThreadId = dwThreadID;
  283. return TRUE;
  284. Cleanup:
  285. if (hThread)
  286. {
  287. CloseHandle( hThread );
  288. }
  289. if (hEvent)
  290. {
  291. CloseHandle( hEvent );
  292. }
  293. return FALSE;
  294. }