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.

549 lines
12 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TaskManager.cpp
  7. //
  8. // Description:
  9. // Task Manager implementation.
  10. //
  11. // Documentation:
  12. // Yes.
  13. //
  14. // Maintained By:
  15. // Galen Barbee (GalenB) 22-NOV-1999
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "Pch.h"
  19. #include "TaskManager.h"
  20. DEFINE_THISCLASS( "CTaskManager" )
  21. #define THISCLASS CTaskManager
  22. #define LPTHISCLASS CTaskManager *
  23. //
  24. // Define this to cause the Task Manager to do all tasks synchonously.
  25. //
  26. //#define SYNCHRONOUS_TASKING
  27. //****************************************************************************
  28. //
  29. // Constructor / Destructor
  30. //
  31. //****************************************************************************
  32. //////////////////////////////////////////////////////////////////////////////
  33. //++
  34. //
  35. // HRESULT
  36. // CTaskManager::S_HrCreateInstance(
  37. // IUnknown ** ppunkOut
  38. // )
  39. //
  40. //--
  41. //////////////////////////////////////////////////////////////////////////////
  42. HRESULT
  43. CTaskManager::S_HrCreateInstance(
  44. IUnknown ** ppunkOut
  45. )
  46. {
  47. TraceFunc( "" );
  48. HRESULT hr = S_OK;
  49. IServiceProvider * psp = NULL;
  50. CTaskManager * ptm = NULL;
  51. Assert( ppunkOut != NULL );
  52. if ( ppunkOut == NULL )
  53. {
  54. hr = THR( E_POINTER );
  55. goto Cleanup;
  56. }
  57. // Don't wrap - this can fail with E_POINTER.
  58. hr = CServiceManager::S_HrGetManagerPointer( &psp );
  59. if ( hr == E_POINTER )
  60. {
  61. ptm = new CTaskManager();
  62. if ( ptm == NULL )
  63. {
  64. hr = THR( E_OUTOFMEMORY );
  65. goto Cleanup;
  66. }
  67. hr = THR( ptm->HrInit() );
  68. if ( FAILED( hr ) )
  69. {
  70. goto Cleanup;
  71. }
  72. hr = THR( ptm->TypeSafeQI( IUnknown, ppunkOut ) );
  73. if ( FAILED( hr ) )
  74. {
  75. goto Cleanup;
  76. }
  77. TraceMoveToMemoryList( *ppunkOut, IUnknown );
  78. } // if: service manager doesn't exist
  79. else if ( FAILED( hr ) )
  80. {
  81. THR( hr );
  82. goto Cleanup;
  83. }
  84. else
  85. {
  86. hr = THR( psp->TypeSafeQS( CLSID_TaskManager, IUnknown, ppunkOut ) );
  87. psp->Release();
  88. } // else: service manager exists
  89. Cleanup:
  90. if ( ptm != NULL )
  91. {
  92. ptm->Release();
  93. }
  94. HRETURN( hr );
  95. } //*** CTaskManager::S_HrCreateInstance
  96. //////////////////////////////////////////////////////////////////////////////
  97. //++
  98. //
  99. // CTaskManager::CTaskManager
  100. //
  101. // Description:
  102. // Default constructor.
  103. //
  104. // Arguments:
  105. // None.
  106. //
  107. // Return Values:
  108. // None.
  109. //
  110. //--
  111. //////////////////////////////////////////////////////////////////////////////
  112. CTaskManager::CTaskManager( void )
  113. : m_cRef( 1 )
  114. {
  115. TraceFunc( "" );
  116. InterlockedIncrement( &g_cObjects );
  117. TraceFuncExit();
  118. } //*** CTaskManager::CTaskManager
  119. //////////////////////////////////////////////////////////////////////////////
  120. //++
  121. //
  122. // CTaskManager::HrInit
  123. //
  124. // Description:
  125. // Initialize the instance.
  126. //
  127. // Arguments:
  128. // None.
  129. //
  130. // Return Values:
  131. // S_OK - Successful.
  132. //
  133. //--
  134. //////////////////////////////////////////////////////////////////////////////
  135. STDMETHODIMP
  136. CTaskManager::HrInit( void )
  137. {
  138. TraceFunc( "" );
  139. // IUnknown
  140. Assert( m_cRef == 1 );
  141. HRETURN( S_OK );
  142. } //*** CTaskManager::HrInit
  143. //////////////////////////////////////////////////////////////////////////////
  144. //++
  145. //
  146. // CTaskManager::~CTaskManager
  147. //
  148. // Description:
  149. // Destructor.
  150. //
  151. // Arguments:
  152. // None.
  153. //
  154. // Return Values:
  155. // None.
  156. //
  157. //--
  158. //////////////////////////////////////////////////////////////////////////////
  159. CTaskManager::~CTaskManager( void )
  160. {
  161. TraceFunc( "" );
  162. InterlockedDecrement( &g_cObjects );
  163. TraceFuncExit();
  164. } //*** CTaskManager::~CTaskManager
  165. //****************************************************************************
  166. //
  167. // IUnknown
  168. //
  169. //****************************************************************************
  170. //////////////////////////////////////////////////////////////////////////////
  171. //++
  172. //
  173. // CTaskManager::QueryInterface
  174. //
  175. // Description:
  176. // Query this object for the passed in interface.
  177. //
  178. // Arguments:
  179. // riidIn
  180. // Id of interface requested.
  181. //
  182. // ppvOut
  183. // Pointer to the requested interface.
  184. //
  185. // Return Value:
  186. // S_OK
  187. // If the interface is available on this object.
  188. //
  189. // E_NOINTERFACE
  190. // If the interface is not available.
  191. //
  192. // E_POINTER
  193. // ppvOut was NULL.
  194. //
  195. // Remarks:
  196. // None.
  197. //
  198. //--
  199. //////////////////////////////////////////////////////////////////////////////
  200. STDMETHODIMP
  201. CTaskManager::QueryInterface(
  202. REFIID riidIn
  203. , LPVOID * ppvOut
  204. )
  205. {
  206. TraceQIFunc( riidIn, ppvOut );
  207. HRESULT hr = S_OK;
  208. //
  209. // Validate arguments.
  210. //
  211. Assert( ppvOut != NULL );
  212. if ( ppvOut == NULL )
  213. {
  214. hr = THR( E_POINTER );
  215. goto Cleanup;
  216. }
  217. //
  218. // Handle known interfaces.
  219. //
  220. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  221. {
  222. *ppvOut = static_cast< ITaskManager * >( this );
  223. } // if: IUnknown
  224. else if ( IsEqualIID( riidIn, IID_ITaskManager ) )
  225. {
  226. *ppvOut = TraceInterface( __THISCLASS__, ITaskManager, this , 0 );
  227. } // else if: ITaskManager
  228. else
  229. {
  230. *ppvOut = NULL;
  231. hr = E_NOINTERFACE;
  232. }
  233. //
  234. // Add a reference to the interface if successful.
  235. //
  236. if ( SUCCEEDED( hr ) )
  237. {
  238. ((IUnknown *) *ppvOut)->AddRef();
  239. } // if: success
  240. Cleanup:
  241. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  242. } //*** CTaskManager::QueryInterface
  243. //////////////////////////////////////////////////////////////////////////////
  244. //++
  245. //
  246. // CTaskManager::AddRef
  247. //
  248. // Description:
  249. // Add a reference to the object.
  250. //
  251. // Arguments:
  252. // None.
  253. //
  254. // Return Values:
  255. // Count of references.
  256. //
  257. //--
  258. //////////////////////////////////////////////////////////////////////////////
  259. STDMETHODIMP_( ULONG )
  260. CTaskManager::AddRef( void )
  261. {
  262. TraceFunc( "[IUnknown]" );
  263. InterlockedIncrement( &m_cRef );
  264. CRETURN( m_cRef );
  265. } //*** CTaskManager::AddRef
  266. //////////////////////////////////////////////////////////////////////////////
  267. //++
  268. //
  269. // CTaskManager::Release
  270. //
  271. // Description:
  272. // Decrement the reference count on the object.
  273. //
  274. // Arguments:
  275. // None.
  276. //
  277. // Returns:
  278. // New reference count.
  279. //
  280. //--
  281. //////////////////////////////////////////////////////////////////////////////
  282. STDMETHODIMP_( ULONG )
  283. CTaskManager::Release( void )
  284. {
  285. TraceFunc( "[IUnknown]" );
  286. LONG cRef;
  287. cRef = InterlockedDecrement( &m_cRef );
  288. if ( cRef == 0 )
  289. {
  290. TraceDo( delete this );
  291. }
  292. CRETURN( cRef );
  293. } //*** CTaskManager::Release
  294. //****************************************************************************
  295. //
  296. // ITaskManager
  297. //
  298. //****************************************************************************
  299. //////////////////////////////////////////////////////////////////////////////
  300. //++
  301. //
  302. // CTaskManager::SubmitTask
  303. //
  304. // Description:
  305. // Execute a task.
  306. //
  307. // Arguments:
  308. // pTask - The task to execute.
  309. //
  310. // Return Values:
  311. // S_OK - Successful.
  312. // Other HRESULTs.
  313. //
  314. //--
  315. //////////////////////////////////////////////////////////////////////////////
  316. STDMETHODIMP
  317. CTaskManager::SubmitTask(
  318. IDoTask * pTask
  319. )
  320. {
  321. TraceFunc1( "[ITaskManager] pTask = %#x", pTask );
  322. BOOL fResult;
  323. HRESULT hr;
  324. TraceFlow1( "[MT] CTaskManager::SubmitTask() Thread id %d", GetCurrentThreadId() );
  325. #if defined( SYNCHRONOUS_TASKING )
  326. //
  327. // Don't wrap. The "return value" is meaningless since it normally
  328. // would not make it back here. The "return value" of doing the task
  329. // should have been submitted thru the Notification Manager.
  330. //
  331. pTask->BeginTask();
  332. //
  333. // Fake it as if the task was submitted successfully.
  334. //
  335. hr = S_OK;
  336. goto Cleanup;
  337. #else
  338. IStream * pstm; // don't free! (unless QueueUserWorkItem fails)
  339. TraceMemoryDelete( pTask, FALSE ); // About to be handed to another thread.
  340. hr = THR( CoMarshalInterThreadInterfaceInStream( IID_IDoTask, pTask, &pstm ) );
  341. if ( FAILED( hr ) )
  342. goto Cleanup;
  343. fResult = QueueUserWorkItem( S_BeginTask, pstm, WT_EXECUTELONGFUNCTION );
  344. if ( fResult != FALSE )
  345. {
  346. hr = S_OK;
  347. } // if: success
  348. else
  349. {
  350. hr = THR( HRESULT_FROM_WIN32( GetLastError() ) );
  351. pstm->Release();
  352. } // else:
  353. //
  354. // Don't free the stream. It will be freed by S_BeginTask.
  355. //
  356. #endif
  357. Cleanup:
  358. HRETURN( hr );
  359. } //*** CTaskManager::SubmitTask
  360. //////////////////////////////////////////////////////////////////////////////
  361. //++
  362. //
  363. // CTaskManager::CreateTask
  364. //
  365. // Description:
  366. // The purpose of this is to create the task in our process and/or our
  367. // apartment.
  368. //
  369. // Arguments:
  370. // clsidTaskIn - CLSID of the task to create.
  371. // ppUnkOut - IUnknown interface.
  372. //
  373. // Return Values:
  374. //
  375. //
  376. //--
  377. //////////////////////////////////////////////////////////////////////////////
  378. STDMETHODIMP
  379. CTaskManager::CreateTask(
  380. REFIID clsidTaskIn, // CLSID of the task to create
  381. IUnknown ** ppUnkOut // IUnknown interface
  382. )
  383. {
  384. TraceFunc( "[ITaskManager] clsidTaskIn, ppvOut" );
  385. HRESULT hr;
  386. //
  387. // TODO: gpease 27-NOV-1999
  388. // Maybe implement a list of "spent" tasks in order to
  389. // reuse tasks that have been completed and reduce heap
  390. // thrashing.(????)
  391. //
  392. hr = THR( HrCoCreateInternalInstance(
  393. clsidTaskIn
  394. , NULL
  395. , CLSCTX_INPROC_SERVER, IID_IUnknown
  396. , reinterpret_cast< void ** >( ppUnkOut )
  397. ) );
  398. HRETURN( hr );
  399. } //*** CTaskManager::CreateTask
  400. //****************************************************************************
  401. //
  402. // Private Methods
  403. //
  404. //****************************************************************************
  405. //////////////////////////////////////////////////////////////////////////////
  406. //++
  407. //
  408. // static
  409. // CTaskManager::S_BeginTask
  410. //
  411. // Description:
  412. // Thread task to begin the task.
  413. //
  414. // Arguments:
  415. // pParam - Parameter for the task.
  416. //
  417. // Return Values:
  418. // Ignored.
  419. //
  420. //--
  421. //////////////////////////////////////////////////////////////////////////////
  422. DWORD
  423. WINAPI
  424. CTaskManager::S_BeginTask(
  425. LPVOID pParam
  426. )
  427. {
  428. TraceFunc1( "pParam = %#x", pParam );
  429. Assert( pParam != NULL );
  430. HRESULT hr;
  431. IDoTask * pTask = NULL;
  432. IStream * pstm = reinterpret_cast< IStream * >( pParam );
  433. TraceMemoryAddPunk( pTask );
  434. hr = STHR( CoInitializeEx( NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE ) );
  435. if ( FAILED( hr ) )
  436. goto Bail;
  437. hr = THR( CoUnmarshalInterface( pstm, TypeSafeParams( IDoTask, &pTask ) ) );
  438. if ( FAILED( hr ) )
  439. goto Cleanup;
  440. pTask->BeginTask();
  441. Cleanup:
  442. if ( pTask != NULL )
  443. {
  444. pTask->Release(); // AddRef'ed in SubmitTask
  445. }
  446. if ( pstm != NULL )
  447. {
  448. pstm->Release();
  449. }
  450. CoUninitialize();
  451. Bail:
  452. FRETURN( hr );
  453. return hr;
  454. } //*** CTaskManager::S_BeginTask