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.

514 lines
11 KiB

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