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.

383 lines
8.3 KiB

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