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.

3134 lines
60 KiB

  1. #ifndef __THREAD_CPP
  2. #define __THREAD_CPP
  3. /*++
  4. Copyright (C) 1996-2001 Microsoft Corporation
  5. Module Name:
  6. Thread.cpp
  7. Abstract:
  8. Enhancements to current functionality:
  9. Timeout mechanism should track across waits.
  10. AddRef/Release on task when scheduling.
  11. Enhancement Ticker logic.
  12. History:
  13. --*/
  14. #include <HelperFuncs.h>
  15. #include <tchar.h>
  16. /******************************************************************************
  17. *
  18. * Name:
  19. *
  20. *
  21. * Description:
  22. *
  23. *
  24. *****************************************************************************/
  25. template <class WmiKey>
  26. WmiThread <WmiKey> :: ThreadContainer *WmiThread <WmiKey> :: s_ThreadContainer = NULL ;
  27. template <class WmiKey>
  28. WmiThread <WmiKey> :: TaskContainer *WmiThread <WmiKey> :: s_TaskContainer = NULL ;
  29. template <class WmiKey>
  30. CriticalSection WmiThread <WmiKey> :: s_CriticalSection(FALSE) ;
  31. template <class WmiKey>
  32. LONG WmiThread <WmiKey> :: s_InitializeReferenceCount = 0 ;
  33. /******************************************************************************
  34. *
  35. * Name:
  36. *
  37. *
  38. * Description:
  39. *
  40. *
  41. *****************************************************************************/
  42. template <class WmiKey>
  43. WmiStatusCode WmiThread <WmiKey> :: Static_Initialize ( WmiAllocator &a_Allocator )
  44. {
  45. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  46. if ( InterlockedIncrement ( & s_InitializeReferenceCount ) == 1 )
  47. {
  48. t_StatusCode = WmiHelper :: InitializeCriticalSection ( & s_CriticalSection ) ;
  49. if ( t_StatusCode == e_StatusCode_Success )
  50. {
  51. if ( s_ThreadContainer == NULL )
  52. {
  53. t_StatusCode = a_Allocator.New (
  54. ( void ** ) & s_ThreadContainer ,
  55. sizeof ( ThreadContainer )
  56. ) ;
  57. if ( t_StatusCode == e_StatusCode_Success )
  58. {
  59. :: new ( ( void * ) s_ThreadContainer ) WmiThread <WmiKey> :: ThreadContainer ( a_Allocator ) ;
  60. }
  61. }
  62. else
  63. {
  64. }
  65. if ( s_TaskContainer == NULL )
  66. {
  67. t_StatusCode = a_Allocator.New (
  68. ( void ** ) & s_TaskContainer ,
  69. sizeof ( TaskContainer )
  70. ) ;
  71. if ( t_StatusCode == e_StatusCode_Success )
  72. {
  73. :: new ( ( void * ) s_TaskContainer ) WmiThread <WmiKey> :: TaskContainer ( a_Allocator ) ;
  74. }
  75. }
  76. else
  77. {
  78. }
  79. }
  80. }
  81. return t_StatusCode ;
  82. }
  83. /******************************************************************************
  84. *
  85. * Name:
  86. *
  87. *
  88. * Description:
  89. *
  90. *
  91. *****************************************************************************/
  92. template <class WmiKey>
  93. WmiStatusCode WmiThread <WmiKey> :: Static_UnInitialize ( WmiAllocator &a_Allocator )
  94. {
  95. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  96. if ( InterlockedDecrement ( & s_InitializeReferenceCount ) == 0 )
  97. {
  98. if ( s_ThreadContainer )
  99. {
  100. s_ThreadContainer->~WmiBasicTree () ;
  101. t_StatusCode = a_Allocator.Delete (
  102. ( void * ) s_ThreadContainer
  103. ) ;
  104. s_ThreadContainer = NULL ;
  105. }
  106. if ( s_TaskContainer )
  107. {
  108. s_TaskContainer->~WmiBasicTree () ;
  109. t_StatusCode = a_Allocator.Delete (
  110. ( void * ) s_TaskContainer
  111. ) ;
  112. s_TaskContainer = NULL ;
  113. }
  114. WmiHelper :: DeleteCriticalSection ( & s_CriticalSection );
  115. }
  116. return t_StatusCode ;
  117. }
  118. /******************************************************************************
  119. *
  120. * Name:
  121. *
  122. *
  123. * Description:
  124. *
  125. *
  126. *****************************************************************************/
  127. template <class WmiKey>
  128. ULONG WmiTask <WmiKey> :: AddRef ()
  129. {
  130. return InterlockedIncrement ( & m_ReferenceCount ) ;
  131. }
  132. /******************************************************************************
  133. *
  134. * Name:
  135. *
  136. *
  137. * Description:
  138. *
  139. *
  140. *****************************************************************************/
  141. template <class WmiKey>
  142. ULONG WmiTask <WmiKey> :: Release ()
  143. {
  144. ULONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
  145. if ( t_ReferenceCount == 0 )
  146. {
  147. delete this ;
  148. }
  149. return t_ReferenceCount ;
  150. }
  151. /******************************************************************************
  152. *
  153. * Name:
  154. *
  155. *
  156. * Description:
  157. *
  158. *
  159. *****************************************************************************/
  160. template <class WmiKey>
  161. WmiTask <WmiKey> :: WmiTask (
  162. WmiAllocator &a_Allocator ,
  163. const wchar_t *a_Name ,
  164. const wchar_t *a_CompletionName
  165. ) : m_Allocator ( a_Allocator ) ,
  166. m_ReferenceCount ( 0 ) ,
  167. m_Event ( NULL ) ,
  168. m_CompletionEvent ( NULL ) ,
  169. m_Name ( NULL ) ,
  170. m_CompletionName ( NULL ) ,
  171. m_InitializationStatusCode ( e_StatusCode_Success ) ,
  172. m_TaskState ( e_WmiTask_UnInitialized )
  173. {
  174. if ( a_Name )
  175. {
  176. m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_Name , m_Name ) ;
  177. }
  178. if ( m_InitializationStatusCode == e_StatusCode_Success )
  179. {
  180. if ( a_CompletionName )
  181. {
  182. m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_CompletionName , m_CompletionName ) ;
  183. }
  184. }
  185. if ( m_InitializationStatusCode == e_StatusCode_Success )
  186. {
  187. m_InitializationStatusCode = WmiHelper :: CreateNamedEvent ( m_Name , m_Event ) ;
  188. }
  189. if ( m_InitializationStatusCode == e_StatusCode_Success )
  190. {
  191. m_InitializationStatusCode = WmiHelper :: CreateNamedEvent ( m_CompletionName , m_CompletionEvent ) ;
  192. }
  193. }
  194. /******************************************************************************
  195. *
  196. * Name:
  197. *
  198. *
  199. * Description:
  200. *
  201. *
  202. *****************************************************************************/
  203. template <class WmiKey>
  204. WmiTask <WmiKey> :: WmiTask (
  205. WmiAllocator &a_Allocator ,
  206. HANDLE a_Event ,
  207. HANDLE a_CompletionEvent ,
  208. const wchar_t *a_Name ,
  209. const wchar_t *a_CompletionName
  210. ) : m_Allocator ( a_Allocator ) ,
  211. m_ReferenceCount ( 0 ) ,
  212. m_Event ( NULL ) ,
  213. m_CompletionEvent ( NULL ) ,
  214. m_Name ( NULL ) ,
  215. m_CompletionName ( NULL ) ,
  216. m_InitializationStatusCode ( e_StatusCode_Success ) ,
  217. m_TaskState ( e_WmiTask_UnInitialized )
  218. {
  219. if ( a_Name )
  220. {
  221. m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_Name , m_Name ) ;
  222. }
  223. if ( m_InitializationStatusCode == e_StatusCode_Success )
  224. {
  225. if ( a_CompletionName )
  226. {
  227. m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_CompletionName , m_CompletionName ) ;
  228. }
  229. }
  230. if ( m_InitializationStatusCode == e_StatusCode_Success )
  231. {
  232. if ( a_Event )
  233. {
  234. m_InitializationStatusCode = WmiHelper :: DuplicateHandle ( a_Event , m_Event ) ;
  235. }
  236. }
  237. if ( m_InitializationStatusCode == e_StatusCode_Success )
  238. {
  239. if ( a_CompletionEvent )
  240. {
  241. m_InitializationStatusCode = WmiHelper :: DuplicateHandle ( a_CompletionEvent , m_CompletionEvent ) ;
  242. }
  243. }
  244. }
  245. /******************************************************************************
  246. *
  247. * Name:
  248. *
  249. *
  250. * Description:
  251. *
  252. *
  253. *****************************************************************************/
  254. template <class WmiKey>
  255. WmiTask <WmiKey> :: ~WmiTask ()
  256. {
  257. if ( m_Name )
  258. {
  259. m_Allocator.Delete ( ( void * ) m_Name ) ;
  260. }
  261. if ( m_CompletionName )
  262. {
  263. m_Allocator.Delete ( ( void * ) m_CompletionName ) ;
  264. }
  265. if ( m_Event )
  266. {
  267. CloseHandle ( m_Event ) ;
  268. }
  269. if ( m_CompletionEvent )
  270. {
  271. CloseHandle ( m_CompletionEvent ) ;
  272. }
  273. }
  274. /******************************************************************************
  275. *
  276. * Name:
  277. *
  278. *
  279. * Description:
  280. *
  281. *
  282. *****************************************************************************/
  283. template <class WmiKey>
  284. WmiStatusCode WmiTask <WmiKey> :: Initialize ()
  285. {
  286. m_TaskState = e_WmiTask_Initialized ;
  287. return m_InitializationStatusCode ;
  288. }
  289. /******************************************************************************
  290. *
  291. * Name:
  292. *
  293. *
  294. * Description:
  295. *
  296. *
  297. *****************************************************************************/
  298. template <class WmiKey>
  299. WmiStatusCode WmiTask <WmiKey> :: UnInitialize ()
  300. {
  301. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  302. return t_StatusCode ;
  303. }
  304. /******************************************************************************
  305. *
  306. * Name:
  307. *
  308. *
  309. * Description:
  310. *
  311. *
  312. *****************************************************************************/
  313. template <class WmiKey>
  314. WmiStatusCode WmiTask <WmiKey> :: Process ( WmiThread <WmiKey> &a_Thread )
  315. {
  316. if ( m_InitializationStatusCode == e_StatusCode_Success )
  317. {
  318. return Complete () ;
  319. }
  320. return e_StatusCode_NotInitialized ;
  321. }
  322. /******************************************************************************
  323. *
  324. * Name:
  325. *
  326. *
  327. * Description:
  328. *
  329. *
  330. *****************************************************************************/
  331. template <class WmiKey>
  332. WmiStatusCode WmiTask <WmiKey> :: Exec ()
  333. {
  334. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  335. if ( m_InitializationStatusCode == e_StatusCode_Success )
  336. {
  337. if ( m_Event )
  338. {
  339. BOOL t_Status = SetEvent ( m_Event ) ;
  340. if ( ! t_Status )
  341. {
  342. t_StatusCode = e_StatusCode_Unknown ;
  343. }
  344. }
  345. }
  346. else
  347. {
  348. t_StatusCode = e_StatusCode_NotInitialized ;
  349. }
  350. return t_StatusCode ;
  351. }
  352. /******************************************************************************
  353. *
  354. * Name:
  355. *
  356. *
  357. * Description:
  358. *
  359. *
  360. *****************************************************************************/
  361. template <class WmiKey>
  362. WmiStatusCode WmiTask <WmiKey> :: Complete ()
  363. {
  364. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  365. if ( m_InitializationStatusCode == e_StatusCode_Success )
  366. {
  367. BOOL t_Status = SetEvent ( m_CompletionEvent ) ;
  368. if ( ! t_Status )
  369. {
  370. t_StatusCode = e_StatusCode_Unknown ;
  371. }
  372. }
  373. else
  374. {
  375. t_StatusCode = e_StatusCode_NotInitialized ;
  376. }
  377. return t_StatusCode ;
  378. }
  379. /******************************************************************************
  380. *
  381. * Name:
  382. *
  383. *
  384. * Description:
  385. *
  386. *
  387. *****************************************************************************/
  388. template <class WmiKey>
  389. WmiStatusCode WmiTask <WmiKey> :: Wait ( const ULONG &a_Timeout )
  390. {
  391. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  392. if ( m_InitializationStatusCode == e_StatusCode_Success )
  393. {
  394. t_StatusCode = WmiThread <WmiKey> :: Static_Dispatch (
  395. *this ,
  396. a_Timeout
  397. ) ;
  398. }
  399. else
  400. {
  401. t_StatusCode = e_StatusCode_NotInitialized ;
  402. }
  403. return t_StatusCode ;
  404. }
  405. /******************************************************************************
  406. *
  407. * Name:
  408. *
  409. *
  410. * Description:
  411. *
  412. *
  413. *****************************************************************************/
  414. // call static GetEvents on WmiThread to determine list of tasks to execute.
  415. template <class WmiKey>
  416. WmiStatusCode WmiTask <WmiKey> :: WaitAlertable ( const ULONG &a_Timeout )
  417. {
  418. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  419. if ( m_InitializationStatusCode == e_StatusCode_Success )
  420. {
  421. t_StatusCode = WmiThread <WmiKey> :: Static_AlertableDispatch (
  422. *this ,
  423. a_Timeout
  424. ) ;
  425. }
  426. else
  427. {
  428. t_StatusCode = e_StatusCode_NotInitialized ;
  429. }
  430. return t_StatusCode ;
  431. }
  432. /******************************************************************************
  433. *
  434. * Name:
  435. *
  436. *
  437. * Description:
  438. *
  439. *
  440. *****************************************************************************/
  441. template <class WmiKey>
  442. WmiStatusCode WmiTask <WmiKey> :: WaitInterruptable ( const ULONG &a_Timeout )
  443. {
  444. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  445. if ( m_InitializationStatusCode == e_StatusCode_Success )
  446. {
  447. t_StatusCode = WmiThread <WmiKey> :: Static_InterruptableDispatch (
  448. *this ,
  449. a_Timeout
  450. ) ;
  451. }
  452. else
  453. {
  454. t_StatusCode = e_StatusCode_NotInitialized ;
  455. }
  456. return t_StatusCode ;
  457. }
  458. /******************************************************************************
  459. *
  460. * Name:
  461. *
  462. *
  463. * Description:
  464. *
  465. *
  466. *****************************************************************************/
  467. template <class WmiKey>
  468. LONG operator == ( const WmiThread <WmiKey> :: QueueKey &a_Arg1 , const WmiThread <WmiKey> :: QueueKey &a_Arg2 )
  469. {
  470. LONG t_Compare ;
  471. if ( ( t_Compare = CompareElement ( a_Arg1.m_Key , a_Arg2.m_Key ) ) == 0 )
  472. {
  473. t_Compare = CompareElement ( a_Arg1.m_Tick , a_Arg2.m_Tick ) ;
  474. }
  475. return t_Compare == 0 ? true : false ;
  476. }
  477. template <class WmiKey>
  478. bool operator < ( const WmiThread <WmiKey> :: QueueKey &a_Arg1 , const WmiThread <WmiKey> :: QueueKey &a_Arg2 )
  479. {
  480. LONG t_Compare ;
  481. if ( ( t_Compare = CompareElement ( a_Arg1.m_Key , a_Arg2.m_Key ) ) == 0 )
  482. {
  483. t_Compare = CompareElement ( a_Arg1.m_Tick , a_Arg2.m_Tick ) ;
  484. }
  485. return t_Compare < 0 ? true : false ;
  486. }
  487. /******************************************************************************
  488. *
  489. * Name:
  490. *
  491. *
  492. * Description:
  493. *
  494. *
  495. *****************************************************************************/
  496. template <class WmiKey>
  497. WmiStatusCode WmiThread <WmiKey> :: PostShutdown ()
  498. {
  499. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  500. SetEvent ( m_Terminate ) ;
  501. return t_StatusCode ;
  502. }
  503. /******************************************************************************
  504. *
  505. * Name:
  506. *
  507. *
  508. * Description:
  509. *
  510. *
  511. *****************************************************************************/
  512. template <class WmiKey>
  513. ULONG WmiThread <WmiKey> :: ThreadProc ( void *a_Thread )
  514. {
  515. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  516. WmiThread *t_Thread = ( WmiThread * ) a_Thread ;
  517. if ( t_Thread )
  518. {
  519. t_StatusCode = t_Thread->Initialize_Callback () ;
  520. if ( t_StatusCode == e_StatusCode_Success )
  521. {
  522. SetEvent ( t_Thread->m_Initialized ) ;
  523. t_StatusCode = t_Thread->ThreadDispatch () ;
  524. }
  525. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  526. t_StatusCode = t_Thread->UnInitialize_Callback () ;
  527. t_Thread->InternalRelease () ;
  528. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  529. }
  530. return ( ULONG ) t_StatusCode ;
  531. }
  532. /******************************************************************************
  533. *
  534. * Name:
  535. *
  536. *
  537. * Description:
  538. *
  539. *
  540. *****************************************************************************/
  541. template <class WmiKey>
  542. ULONG WmiThread <WmiKey> :: AddRef ()
  543. {
  544. ULONG t_ReferenceCount = InterlockedIncrement ( & m_ReferenceCount ) ;
  545. if ( t_ReferenceCount == 1 )
  546. {
  547. InternalAddRef () ;
  548. }
  549. return t_ReferenceCount ;
  550. }
  551. /******************************************************************************
  552. *
  553. * Name:
  554. *
  555. *
  556. * Description:
  557. *
  558. *
  559. *****************************************************************************/
  560. template <class WmiKey>
  561. ULONG WmiThread <WmiKey> :: Release ()
  562. {
  563. ULONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
  564. if ( t_ReferenceCount == 0 )
  565. {
  566. CallBackRelease () ;
  567. PostShutdown () ;
  568. return InternalRelease () ;
  569. }
  570. else
  571. {
  572. return t_ReferenceCount ;
  573. }
  574. }
  575. /******************************************************************************
  576. *
  577. * Name:
  578. *
  579. *
  580. * Description:
  581. *
  582. *
  583. *****************************************************************************/
  584. template <class WmiKey>
  585. ULONG WmiThread <WmiKey> :: InternalAddRef ()
  586. {
  587. return InterlockedIncrement ( & m_InternalReferenceCount ) ;
  588. }
  589. /******************************************************************************
  590. *
  591. * Name:
  592. *
  593. *
  594. * Description:
  595. *
  596. *
  597. *****************************************************************************/
  598. template <class WmiKey>
  599. ULONG WmiThread <WmiKey> :: InternalRelease ()
  600. {
  601. ULONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
  602. if ( t_ReferenceCount == 0 )
  603. {
  604. WmiStatusCode t_StatusCode = s_ThreadContainer->Delete ( m_Identifier ) ;
  605. delete this ;
  606. return 0 ;
  607. }
  608. else
  609. {
  610. return t_ReferenceCount ;
  611. }
  612. }
  613. /******************************************************************************
  614. *
  615. * Name:
  616. *
  617. *
  618. * Description:
  619. *
  620. *
  621. *****************************************************************************/
  622. template <class WmiKey>
  623. WmiStatusCode WmiThread <WmiKey> :: CreateThread ()
  624. {
  625. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  626. InternalAddRef () ;
  627. m_Thread = :: CreateThread (
  628. NULL ,
  629. m_StackSize ,
  630. ( LPTHREAD_START_ROUTINE ) ThreadProc ,
  631. ( void * ) this ,
  632. 0 ,
  633. & m_Identifier
  634. ) ;
  635. if ( m_Thread )
  636. {
  637. ThreadContainerIterator t_Iterator ;
  638. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  639. if ( ( t_StatusCode = s_ThreadContainer->Insert ( m_Identifier , this , t_Iterator ) ) == e_StatusCode_Success )
  640. {
  641. }
  642. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  643. }
  644. else
  645. {
  646. InternalRelease () ;
  647. t_StatusCode = e_StatusCode_OutOfResources ;
  648. }
  649. return t_StatusCode ;
  650. }
  651. /******************************************************************************
  652. *
  653. * Name:
  654. *
  655. *
  656. * Description:
  657. *
  658. *
  659. *****************************************************************************/
  660. template <class WmiKey>
  661. WmiThread <WmiKey> :: WmiThread (
  662. WmiAllocator &a_Allocator ,
  663. const wchar_t *a_Name ,
  664. ULONG a_Timeout ,
  665. DWORD a_StackSize
  666. ) : m_Allocator ( a_Allocator ) ,
  667. m_TaskQueue ( a_Allocator ) ,
  668. m_AlertableTaskQueue ( a_Allocator ) ,
  669. m_InterruptableTaskQueue ( a_Allocator ) ,
  670. m_Thread ( NULL ) ,
  671. m_Initialized ( NULL ) ,
  672. m_Terminate ( NULL ) ,
  673. m_QueueChange ( NULL ) ,
  674. m_Identifier ( 0 ) ,
  675. m_Name ( NULL ) ,
  676. m_Timeout ( a_Timeout ) ,
  677. m_StackSize ( a_StackSize ) ,
  678. m_ReferenceCount ( 0 ) ,
  679. m_InternalReferenceCount ( 0 ) ,
  680. m_InitializationStatusCode ( e_StatusCode_Success ),
  681. m_CriticalSection(NOTHROW_LOCK)
  682. {
  683. m_InitializationStatusCode = WmiHelper :: InitializeCriticalSection ( & m_CriticalSection ) ;
  684. if ( m_InitializationStatusCode == e_StatusCode_Success )
  685. {
  686. m_InitializationStatusCode = m_TaskQueue.Initialize () ;
  687. }
  688. if ( m_InitializationStatusCode == e_StatusCode_Success )
  689. {
  690. m_InitializationStatusCode = m_InterruptableTaskQueue.Initialize () ;
  691. }
  692. if ( m_InitializationStatusCode == e_StatusCode_Success )
  693. {
  694. m_InitializationStatusCode = m_AlertableTaskQueue.Initialize () ;
  695. }
  696. if ( a_Name )
  697. {
  698. m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_Name , m_Name ) ;
  699. }
  700. if ( m_InitializationStatusCode == e_StatusCode_Success )
  701. {
  702. m_InitializationStatusCode = WmiHelper :: CreateUnNamedEvent ( m_Terminate ) ;
  703. }
  704. if ( m_InitializationStatusCode == e_StatusCode_Success )
  705. {
  706. m_InitializationStatusCode = WmiHelper :: CreateUnNamedEvent ( m_Initialized ) ;
  707. }
  708. if ( m_InitializationStatusCode == e_StatusCode_Success )
  709. {
  710. m_InitializationStatusCode = WmiHelper :: CreateUnNamedEvent ( m_QueueChange ) ;
  711. }
  712. }
  713. /******************************************************************************
  714. *
  715. * Name:
  716. *
  717. *
  718. * Description:
  719. *
  720. *
  721. *****************************************************************************/
  722. template <class WmiKey>
  723. WmiThread <WmiKey> :: ~WmiThread ()
  724. {
  725. if ( m_Name )
  726. {
  727. m_Allocator.Delete ( ( void * ) m_Name ) ;
  728. }
  729. if ( m_Initialized )
  730. {
  731. CloseHandle ( m_Initialized ) ;
  732. }
  733. if ( m_Terminate )
  734. {
  735. CloseHandle ( m_Terminate ) ;
  736. }
  737. if ( m_QueueChange )
  738. {
  739. CloseHandle ( m_QueueChange ) ;
  740. }
  741. if ( m_Thread )
  742. {
  743. CloseHandle ( m_Thread ) ;
  744. }
  745. WmiHelper :: DeleteCriticalSection ( & m_CriticalSection ) ;
  746. }
  747. /******************************************************************************
  748. *
  749. * Name:
  750. *
  751. *
  752. * Description:
  753. *
  754. *
  755. *****************************************************************************/
  756. template <class WmiKey>
  757. WmiStatusCode WmiThread <WmiKey> :: Initialize ( const ULONG &a_Timeout )
  758. {
  759. if ( m_InitializationStatusCode == e_StatusCode_Success )
  760. {
  761. m_InitializationStatusCode = CreateThread () ;
  762. }
  763. if ( m_InitializationStatusCode == e_StatusCode_Success )
  764. {
  765. ULONG t_Status = WaitForSingleObject ( m_Initialized , a_Timeout ) ;
  766. switch ( t_Status )
  767. {
  768. case WAIT_TIMEOUT:
  769. {
  770. m_InitializationStatusCode = e_StatusCode_Success_Timeout ;
  771. }
  772. break ;
  773. case WAIT_OBJECT_0:
  774. {
  775. m_InitializationStatusCode = e_StatusCode_Success ;
  776. }
  777. break ;
  778. default :
  779. {
  780. m_InitializationStatusCode = e_StatusCode_Unknown ;
  781. }
  782. break ;
  783. }
  784. }
  785. return m_InitializationStatusCode ;
  786. }
  787. /******************************************************************************
  788. *
  789. * Name:
  790. *
  791. *
  792. * Description:
  793. *
  794. *
  795. *****************************************************************************/
  796. template <class WmiKey>
  797. WmiStatusCode WmiThread <WmiKey> :: UnInitialize ()
  798. {
  799. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  800. t_StatusCode = m_TaskQueue.UnInitialize () ;
  801. if ( t_StatusCode == e_StatusCode_Success )
  802. {
  803. t_StatusCode = m_InterruptableTaskQueue.UnInitialize () ;
  804. }
  805. if ( t_StatusCode == e_StatusCode_Success )
  806. {
  807. t_StatusCode = m_AlertableTaskQueue.UnInitialize () ;
  808. }
  809. return t_StatusCode ;
  810. }
  811. /******************************************************************************
  812. *
  813. * Name:
  814. *
  815. *
  816. * Description:
  817. *
  818. *
  819. *****************************************************************************/
  820. template <class WmiKey>
  821. WmiStatusCode WmiThread <WmiKey> :: TimedOut ()
  822. {
  823. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  824. return t_StatusCode ;
  825. }
  826. /******************************************************************************
  827. *
  828. * Name:
  829. *
  830. *
  831. * Description:
  832. *
  833. *
  834. *****************************************************************************/
  835. // Queue a task to be executed immediately, a thread that calls a task procedure that
  836. // executes a Wait or MsgWait will receive an indication in Queue status will not execute
  837. // newly queued tasks.
  838. template <class WmiKey>
  839. WmiStatusCode WmiThread <WmiKey> :: EnQueue (
  840. const WmiKey &a_Key ,
  841. WmiTask <WmiKey> &a_Task
  842. )
  843. {
  844. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  845. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  846. TaskContainerIterator t_Iterator ;
  847. if ( ( t_StatusCode = s_TaskContainer->Insert ( &a_Task , this , t_Iterator ) ) == e_StatusCode_Success )
  848. {
  849. a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_EnQueued ) ;
  850. a_Task.AddRef () ;
  851. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  852. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  853. QueueKey t_QueueKey ( m_Key++ , a_Key ) ;
  854. t_StatusCode = m_TaskQueue.EnQueue ( t_QueueKey , & a_Task ) ;
  855. if ( t_StatusCode == e_StatusCode_Success )
  856. {
  857. a_Task.EnqueueAs ( WmiTask <WmiKey> :: e_WmiTask_Enqueue ) ;
  858. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  859. BOOL t_Status = SetEvent ( m_QueueChange ) ;
  860. if ( ! t_Status )
  861. {
  862. t_StatusCode = e_StatusCode_Failed ;
  863. }
  864. }
  865. else
  866. {
  867. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  868. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  869. t_StatusCode = s_TaskContainer->Delete ( &a_Task ) ;
  870. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  871. a_Task.Release () ;
  872. }
  873. }
  874. else
  875. {
  876. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  877. }
  878. return t_StatusCode ;
  879. }
  880. /******************************************************************************
  881. *
  882. * Name:
  883. *
  884. *
  885. * Description:
  886. *
  887. *
  888. *****************************************************************************/
  889. template <class WmiKey>
  890. WmiStatusCode WmiThread <WmiKey> :: EnQueueAlertable (
  891. const WmiKey &a_Key ,
  892. WmiTask <WmiKey> &a_Task
  893. )
  894. {
  895. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  896. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  897. TaskContainerIterator t_Iterator ;
  898. if ( ( t_StatusCode = s_TaskContainer->Insert ( &a_Task , this , t_Iterator ) ) == e_StatusCode_Success )
  899. {
  900. a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_EnQueued ) ;
  901. a_Task.AddRef () ;
  902. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  903. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  904. QueueKey t_QueueKey ( m_Key++ , a_Key ) ;
  905. t_StatusCode = m_AlertableTaskQueue.EnQueue ( t_QueueKey , & a_Task ) ;
  906. if ( t_StatusCode == e_StatusCode_Success )
  907. {
  908. a_Task.EnqueueAs ( WmiTask <WmiKey> :: e_WmiTask_EnqueueAlertable ) ;
  909. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  910. BOOL t_Status = SetEvent ( m_QueueChange ) ;
  911. if ( ! t_Status )
  912. {
  913. t_StatusCode = e_StatusCode_Failed ;
  914. }
  915. }
  916. else
  917. {
  918. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  919. WmiHelper :: EnterCriticalSection ( & s_CriticalSection , TRUE ) ;
  920. t_StatusCode = s_TaskContainer->Delete ( &a_Task ) ;
  921. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  922. a_Task.Release () ;
  923. }
  924. }
  925. else
  926. {
  927. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  928. }
  929. return t_StatusCode ;
  930. }
  931. /******************************************************************************
  932. *
  933. * Name:
  934. *
  935. *
  936. * Description:
  937. *
  938. *
  939. *****************************************************************************/
  940. // Queue a task to be executed immediately, a thread that calls a task procedure that
  941. // executes a Wait or MsgWait will receive an indication of Queue status change will execute
  942. // newly queued tasks. This is used for STA based execution where we need to interrupt the wait
  943. // to execute a dependant request.
  944. //
  945. template <class WmiKey>
  946. WmiStatusCode WmiThread <WmiKey> :: EnQueueInterruptable (
  947. const WmiKey &a_Key ,
  948. WmiTask <WmiKey> &a_Task
  949. )
  950. {
  951. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  952. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  953. TaskContainerIterator t_Iterator ;
  954. if ( ( t_StatusCode = s_TaskContainer->Insert ( &a_Task , this , t_Iterator ) ) == e_StatusCode_Success )
  955. {
  956. a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_EnQueued ) ;
  957. a_Task.AddRef () ;
  958. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  959. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  960. QueueKey t_QueueKey ( m_Key++ , a_Key ) ;
  961. t_StatusCode = m_InterruptableTaskQueue.EnQueue ( t_QueueKey , & a_Task ) ;
  962. if ( t_StatusCode == e_StatusCode_Success )
  963. {
  964. a_Task.EnqueueAs ( WmiTask <WmiKey> :: e_WmiTask_EnqueueInterruptable ) ;
  965. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  966. BOOL t_Status = SetEvent ( m_QueueChange ) ;
  967. if ( ! t_Status )
  968. {
  969. t_StatusCode = e_StatusCode_Failed ;
  970. }
  971. }
  972. else
  973. {
  974. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  975. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  976. t_StatusCode = s_TaskContainer->Delete ( &a_Task ) ;
  977. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  978. a_Task.Release () ;
  979. }
  980. }
  981. else
  982. {
  983. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  984. }
  985. return t_StatusCode ;
  986. }
  987. /******************************************************************************
  988. *
  989. * Name:
  990. *
  991. *
  992. * Description:
  993. *
  994. *
  995. *****************************************************************************/
  996. template <class WmiKey>
  997. WmiStatusCode WmiThread <WmiKey> :: DeQueue (
  998. const WmiKey &a_Key ,
  999. WmiTask <WmiKey> &a_Task
  1000. )
  1001. {
  1002. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1003. a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_DeQueued ) ;
  1004. return t_StatusCode ;
  1005. }
  1006. /******************************************************************************
  1007. *
  1008. * Name:
  1009. *
  1010. *
  1011. * Description:
  1012. *
  1013. *
  1014. *****************************************************************************/
  1015. template <class WmiKey>
  1016. WmiStatusCode WmiThread <WmiKey> :: DeQueueAlertable (
  1017. const WmiKey &a_Key ,
  1018. WmiTask <WmiKey> &a_Task
  1019. )
  1020. {
  1021. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1022. a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_DeQueued ) ;
  1023. return t_StatusCode ;
  1024. }
  1025. /******************************************************************************
  1026. *
  1027. * Name:
  1028. *
  1029. *
  1030. * Description:
  1031. *
  1032. *
  1033. *****************************************************************************/
  1034. template <class WmiKey>
  1035. WmiStatusCode WmiThread <WmiKey> :: DeQueueInterruptable (
  1036. const WmiKey &a_Key ,
  1037. WmiTask <WmiKey> &a_Task
  1038. )
  1039. {
  1040. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1041. a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_DeQueued ) ;
  1042. return t_StatusCode ;
  1043. }
  1044. /******************************************************************************
  1045. *
  1046. * Name:
  1047. *
  1048. *
  1049. * Description:
  1050. *
  1051. *
  1052. *****************************************************************************/
  1053. template <class WmiKey>
  1054. WmiThread <WmiKey> *WmiThread <WmiKey> :: GetThread ()
  1055. {
  1056. WmiThread *t_Thread = NULL ;
  1057. ULONG t_CurrentThreadId = GetCurrentThreadId () ;
  1058. ThreadContainerIterator t_Iterator ;
  1059. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  1060. WmiStatusCode t_StatusCode = s_ThreadContainer->Find ( t_CurrentThreadId , t_Iterator ) ;
  1061. if ( t_StatusCode == e_StatusCode_Success )
  1062. {
  1063. t_Thread = t_Iterator.GetElement () ;
  1064. }
  1065. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  1066. return t_Thread ;
  1067. }
  1068. /******************************************************************************
  1069. *
  1070. * Name:
  1071. *
  1072. *
  1073. * Description:
  1074. *
  1075. *
  1076. *****************************************************************************/
  1077. template <class WmiKey>
  1078. WmiThread <WmiKey> *WmiThread <WmiKey> :: GetServicingThread ( WmiTask <WmiKey> &a_Task )
  1079. {
  1080. WmiThread *t_Thread = NULL ;
  1081. TaskContainerIterator t_Iterator ;
  1082. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  1083. WmiStatusCode t_StatusCode = s_TaskContainer->Find ( &a_Task, t_Iterator ) ;
  1084. if ( t_StatusCode == e_StatusCode_Success )
  1085. {
  1086. t_Thread = t_Iterator.GetElement () ;
  1087. }
  1088. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  1089. return t_Thread ;
  1090. }
  1091. /*
  1092. Scheduling Action
  1093. Task None
  1094. Dispatch nothing
  1095. On Thread
  1096. Wait on Completion
  1097. Wait on Thread Termination
  1098. Wait on Servicing Thread Termination
  1099. Off Thread
  1100. Wait on Completion
  1101. Wait on Servicing Thread Termination
  1102. Task Altertable
  1103. Dispatch Alertable Queue
  1104. On Thread
  1105. MsgWait on Completion
  1106. MsgWait on Thread Termination
  1107. MsgWait on Servicing Thread Termination
  1108. Off Thread
  1109. MsgWait on Completion
  1110. MsgWait on Servicing Thread Termination
  1111. Task Interruptable
  1112. Dispatch Alertable Queue
  1113. Dispatch Normal Queue
  1114. On Thread
  1115. MsgWait on Completion
  1116. MsgWait on Thread Termination
  1117. MsgWait on Servicing Thread Termination
  1118. MsgWait on Alertables
  1119. Off Thread
  1120. MsgWait on Completion
  1121. MsgWait on Servicing Thread Termination
  1122. Thread Alertable
  1123. Dispatch Alertable Queue
  1124. Dispatch Normal Queue
  1125. MsgWait on Thread Termination
  1126. MsgWait on Alertables
  1127. */
  1128. /******************************************************************************
  1129. *
  1130. * Name:
  1131. *
  1132. *
  1133. * Description:
  1134. *
  1135. *
  1136. *****************************************************************************/
  1137. template <class WmiKey>
  1138. WmiStatusCode WmiThread <WmiKey> :: Static_Dispatch (
  1139. WmiTask <WmiKey> &a_Task ,
  1140. WmiThread <WmiKey> &a_Thread ,
  1141. const ULONG &a_Timeout
  1142. )
  1143. {
  1144. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1145. HANDLE t_Handles [ 3 ] ;
  1146. t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
  1147. t_Handles [ 1 ] = a_Thread.GetHandle () ;
  1148. t_Handles [ 2 ] = a_Thread.GetTerminationEvent () ;
  1149. ULONG t_Event = WaitForMultipleObjects (
  1150. 3 ,
  1151. t_Handles ,
  1152. FALSE ,
  1153. a_Timeout
  1154. ) ;
  1155. switch ( t_Event )
  1156. {
  1157. case WAIT_TIMEOUT:
  1158. {
  1159. t_StatusCode = e_StatusCode_Success_Timeout ;
  1160. }
  1161. break ;
  1162. case WAIT_OBJECT_0:
  1163. {
  1164. t_StatusCode = e_StatusCode_Success ;
  1165. }
  1166. break ;
  1167. case WAIT_OBJECT_0+1:
  1168. case WAIT_OBJECT_0+2:
  1169. {
  1170. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1171. #if DBG
  1172. #ifdef _X86_
  1173. __asm
  1174. {
  1175. int 3 ;
  1176. }
  1177. #endif
  1178. #endif
  1179. }
  1180. break ;
  1181. default:
  1182. {
  1183. t_StatusCode = e_StatusCode_Unknown ;
  1184. #if DBG
  1185. #ifdef _X86_
  1186. __asm
  1187. {
  1188. int 3 ;
  1189. }
  1190. #endif
  1191. #endif
  1192. }
  1193. break ;
  1194. }
  1195. return t_StatusCode ;
  1196. }
  1197. /******************************************************************************
  1198. *
  1199. * Name:
  1200. *
  1201. *
  1202. * Description:
  1203. *
  1204. *
  1205. *****************************************************************************/
  1206. template <class WmiKey>
  1207. WmiStatusCode WmiThread <WmiKey> :: Static_Dispatch (
  1208. WmiTask <WmiKey> &a_Task ,
  1209. const ULONG &a_Timeout
  1210. )
  1211. {
  1212. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1213. WmiThread *t_Thread = GetThread () ;
  1214. if ( t_Thread )
  1215. {
  1216. t_StatusCode = t_Thread->Dispatch ( a_Task , a_Timeout ) ;
  1217. }
  1218. else
  1219. {
  1220. WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
  1221. if ( t_ServicingThread )
  1222. {
  1223. t_StatusCode = Static_Dispatch ( a_Task , *t_ServicingThread , a_Timeout ) ;
  1224. }
  1225. else
  1226. {
  1227. t_StatusCode = e_StatusCode_Success ;
  1228. }
  1229. }
  1230. return t_StatusCode ;
  1231. }
  1232. /******************************************************************************
  1233. *
  1234. * Name:
  1235. *
  1236. *
  1237. * Description:
  1238. *
  1239. *
  1240. *****************************************************************************/
  1241. template <class WmiKey>
  1242. WmiStatusCode WmiThread <WmiKey> :: Dispatch (
  1243. WmiTask <WmiKey> &a_Task ,
  1244. const ULONG &a_Timeout
  1245. )
  1246. {
  1247. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1248. do
  1249. {
  1250. }
  1251. while ( ( t_StatusCode = Wait ( a_Task , a_Timeout ) ) == e_StatusCode_Success ) ;
  1252. return t_StatusCode ;
  1253. }
  1254. /******************************************************************************
  1255. *
  1256. * Name:
  1257. *
  1258. *
  1259. * Description:
  1260. *
  1261. *
  1262. *****************************************************************************/
  1263. template <class WmiKey>
  1264. WmiStatusCode WmiThread <WmiKey> :: Wait (
  1265. WmiTask <WmiKey> &a_Task ,
  1266. const ULONG &a_Timeout
  1267. )
  1268. {
  1269. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1270. WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
  1271. if ( t_ServicingThread )
  1272. {
  1273. HANDLE t_Handles [ 4 ] ;
  1274. t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
  1275. t_Handles [ 1 ] = GetTerminationEvent () ;
  1276. t_Handles [ 2 ] = t_ServicingThread->GetHandle () ;
  1277. t_Handles [ 3 ] = t_ServicingThread->GetTerminationEvent () ;
  1278. ULONG t_Event = WaitForMultipleObjects (
  1279. 4 ,
  1280. t_Handles ,
  1281. FALSE ,
  1282. a_Timeout
  1283. ) ;
  1284. switch ( t_Event )
  1285. {
  1286. case WAIT_TIMEOUT:
  1287. {
  1288. t_StatusCode = e_StatusCode_Success_Timeout ;
  1289. }
  1290. break ;
  1291. case WAIT_OBJECT_0:
  1292. {
  1293. t_StatusCode = e_StatusCode_Success ;
  1294. }
  1295. break ;
  1296. case WAIT_OBJECT_0+1:
  1297. {
  1298. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  1299. #if DBG
  1300. #ifdef _X86_
  1301. __asm
  1302. {
  1303. int 3 ;
  1304. }
  1305. #endif
  1306. #endif
  1307. }
  1308. break ;
  1309. case WAIT_OBJECT_0+2:
  1310. case WAIT_OBJECT_0+3:
  1311. {
  1312. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1313. #if DBG
  1314. #ifdef _X86_
  1315. __asm
  1316. {
  1317. int 3 ;
  1318. }
  1319. #endif
  1320. #endif
  1321. }
  1322. break ;
  1323. default:
  1324. {
  1325. t_StatusCode = e_StatusCode_Unknown ;
  1326. #if DBG
  1327. #ifdef _X86_
  1328. __asm
  1329. {
  1330. int 3 ;
  1331. }
  1332. #endif
  1333. #endif
  1334. }
  1335. break ;
  1336. }
  1337. }
  1338. else
  1339. {
  1340. t_StatusCode = e_StatusCode_Success ;
  1341. }
  1342. return t_StatusCode ;
  1343. }
  1344. /******************************************************************************
  1345. *
  1346. * Name:
  1347. *
  1348. *
  1349. * Description:
  1350. *
  1351. *
  1352. *****************************************************************************/
  1353. template <class WmiKey>
  1354. WmiStatusCode WmiThread <WmiKey> :: Static_InterruptableDispatch (
  1355. WmiTask <WmiKey> &a_Task ,
  1356. WmiThread <WmiKey> &a_Thread ,
  1357. const ULONG &a_Timeout
  1358. )
  1359. {
  1360. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1361. HANDLE t_Handles [ 3 ] ;
  1362. t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
  1363. t_Handles [ 1 ] = a_Thread.GetHandle () ;
  1364. t_Handles [ 2 ] = a_Thread.GetTerminationEvent () ;
  1365. bool t_Continuing = true ;
  1366. while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
  1367. {
  1368. ULONG t_Event = MsgWaitForMultipleObjects (
  1369. 3 ,
  1370. t_Handles ,
  1371. FALSE ,
  1372. a_Timeout ,
  1373. QS_ALLINPUT
  1374. ) ;
  1375. switch ( t_Event )
  1376. {
  1377. case WAIT_TIMEOUT:
  1378. {
  1379. t_StatusCode = e_StatusCode_Success_Timeout ;
  1380. }
  1381. break ;
  1382. case WAIT_OBJECT_0:
  1383. {
  1384. t_StatusCode = e_StatusCode_Success ;
  1385. t_Continuing = false ;
  1386. }
  1387. break ;
  1388. case WAIT_OBJECT_0+1:
  1389. case WAIT_OBJECT_0+2:
  1390. {
  1391. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1392. #if DBG
  1393. #ifdef _X86_
  1394. __asm
  1395. {
  1396. int 3 ;
  1397. }
  1398. #endif
  1399. #endif
  1400. }
  1401. break ;
  1402. case WAIT_OBJECT_0+3:
  1403. {
  1404. BOOL t_DispatchStatus ;
  1405. MSG t_Msg ;
  1406. while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
  1407. {
  1408. if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
  1409. {
  1410. TranslateMessage ( & t_Msg ) ;
  1411. DispatchMessage ( & t_Msg ) ;
  1412. }
  1413. }
  1414. ULONG t_Event = WaitForMultipleObjects (
  1415. 3 ,
  1416. t_Handles ,
  1417. FALSE ,
  1418. 0
  1419. ) ;
  1420. switch ( t_Event )
  1421. {
  1422. case WAIT_TIMEOUT:
  1423. {
  1424. t_StatusCode = e_StatusCode_Success_Timeout ;
  1425. }
  1426. break ;
  1427. case WAIT_OBJECT_0:
  1428. {
  1429. t_StatusCode = e_StatusCode_Success ;
  1430. t_Continuing = true ;
  1431. }
  1432. break ;
  1433. case WAIT_OBJECT_0+1:
  1434. case WAIT_OBJECT_0+2:
  1435. {
  1436. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1437. #if DBG
  1438. #ifdef _X86_
  1439. __asm
  1440. {
  1441. int 3 ;
  1442. }
  1443. #endif
  1444. #endif
  1445. }
  1446. break ;
  1447. default:
  1448. {
  1449. t_StatusCode = e_StatusCode_Unknown ;
  1450. #if DBG
  1451. #ifdef _X86_
  1452. __asm
  1453. {
  1454. int 3 ;
  1455. }
  1456. #endif
  1457. #endif
  1458. }
  1459. break ;
  1460. }
  1461. }
  1462. break ;
  1463. default:
  1464. {
  1465. t_StatusCode = e_StatusCode_Unknown ;
  1466. #if DBG
  1467. #ifdef _X86_
  1468. __asm
  1469. {
  1470. int 3 ;
  1471. }
  1472. #endif
  1473. #endif
  1474. }
  1475. break ;
  1476. }
  1477. }
  1478. return t_StatusCode ;
  1479. }
  1480. /******************************************************************************
  1481. *
  1482. * Name:
  1483. *
  1484. *
  1485. * Description:
  1486. *
  1487. *
  1488. *****************************************************************************/
  1489. template <class WmiKey>
  1490. WmiStatusCode WmiThread <WmiKey> :: Static_InterruptableDispatch (
  1491. WmiTask <WmiKey> &a_Task ,
  1492. const ULONG &a_Timeout
  1493. )
  1494. {
  1495. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1496. WmiThread *t_Thread = GetThread () ;
  1497. if ( t_Thread )
  1498. {
  1499. t_StatusCode = t_Thread->InterruptableDispatch ( a_Task , a_Timeout ) ;
  1500. }
  1501. else
  1502. {
  1503. WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
  1504. if ( t_ServicingThread )
  1505. {
  1506. t_StatusCode = Static_InterruptableDispatch ( a_Task , *t_ServicingThread , a_Timeout ) ;
  1507. }
  1508. else
  1509. {
  1510. t_StatusCode = e_StatusCode_Success ;
  1511. }
  1512. }
  1513. return t_StatusCode ;
  1514. }
  1515. /******************************************************************************
  1516. *
  1517. * Name:
  1518. *
  1519. *
  1520. * Description:
  1521. *
  1522. *
  1523. *****************************************************************************/
  1524. template <class WmiKey>
  1525. WmiStatusCode WmiThread <WmiKey> :: InterruptableDispatch (
  1526. WmiTask <WmiKey> &a_Task ,
  1527. const ULONG &a_Timeout
  1528. )
  1529. {
  1530. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1531. QueueContainer t_EnQueue ( m_Allocator ) ;
  1532. t_StatusCode = t_EnQueue.Initialize () ;
  1533. if ( t_StatusCode == e_StatusCode_Success )
  1534. {
  1535. do
  1536. {
  1537. do
  1538. {
  1539. t_StatusCode = Execute ( m_InterruptableTaskQueue , t_EnQueue ) ;
  1540. } while ( t_StatusCode == e_StatusCode_Success ) ;
  1541. if ( t_StatusCode == e_StatusCode_NotInitialized )
  1542. {
  1543. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  1544. t_StatusCode = m_InterruptableTaskQueue.Merge ( t_EnQueue ) ;
  1545. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  1546. if ( t_StatusCode == e_StatusCode_Success )
  1547. {
  1548. t_StatusCode = InterruptableWait ( a_Task , a_Timeout ) ;
  1549. }
  1550. }
  1551. }
  1552. while ( t_StatusCode == e_StatusCode_Success || t_StatusCode == e_StatusCode_Change ) ;
  1553. }
  1554. return t_StatusCode ;
  1555. }
  1556. /******************************************************************************
  1557. *
  1558. * Name:
  1559. *
  1560. *
  1561. * Description:
  1562. *
  1563. *
  1564. *****************************************************************************/
  1565. template <class WmiKey>
  1566. WmiStatusCode WmiThread <WmiKey> :: InterruptableWait (
  1567. WmiTask <WmiKey> &a_Task ,
  1568. const ULONG &a_Timeout
  1569. )
  1570. {
  1571. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1572. WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
  1573. if ( t_ServicingThread )
  1574. {
  1575. HANDLE t_Handles [ 5 ] ;
  1576. t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
  1577. t_Handles [ 1 ] = GetTerminationEvent () ;
  1578. t_Handles [ 2 ] = t_ServicingThread->GetHandle () ;
  1579. t_Handles [ 3 ] = t_ServicingThread->GetTerminationEvent () ;
  1580. t_Handles [ 4 ] = t_ServicingThread->GetQueueChangeEvent () ;
  1581. bool t_Continuing = true ;
  1582. while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
  1583. {
  1584. ULONG t_Event = MsgWaitForMultipleObjects (
  1585. 5 ,
  1586. t_Handles ,
  1587. FALSE ,
  1588. a_Timeout ,
  1589. QS_ALLINPUT
  1590. ) ;
  1591. switch ( t_Event )
  1592. {
  1593. case WAIT_TIMEOUT:
  1594. {
  1595. t_StatusCode = e_StatusCode_Success_Timeout ;
  1596. }
  1597. break ;
  1598. case WAIT_OBJECT_0:
  1599. {
  1600. t_StatusCode = e_StatusCode_Success ;
  1601. t_Continuing = false ;
  1602. }
  1603. break ;
  1604. case WAIT_OBJECT_0+1:
  1605. {
  1606. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  1607. #if DBG
  1608. #ifdef _X86_
  1609. __asm
  1610. {
  1611. int 3 ;
  1612. }
  1613. #endif
  1614. #endif
  1615. }
  1616. break ;
  1617. case WAIT_OBJECT_0+2:
  1618. case WAIT_OBJECT_0+3:
  1619. {
  1620. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1621. #if DBG
  1622. #ifdef _X86_
  1623. __asm
  1624. {
  1625. int 3 ;
  1626. }
  1627. #endif
  1628. #endif
  1629. }
  1630. break ;
  1631. case WAIT_OBJECT_0+4:
  1632. {
  1633. t_StatusCode = e_StatusCode_Change ;
  1634. }
  1635. break ;
  1636. case WAIT_OBJECT_0+5:
  1637. {
  1638. BOOL t_DispatchStatus ;
  1639. MSG t_Msg ;
  1640. while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
  1641. {
  1642. if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
  1643. {
  1644. TranslateMessage ( & t_Msg ) ;
  1645. DispatchMessage ( & t_Msg ) ;
  1646. }
  1647. }
  1648. ULONG t_Event = WaitForMultipleObjects (
  1649. 5 ,
  1650. t_Handles ,
  1651. FALSE ,
  1652. 0
  1653. ) ;
  1654. switch ( t_Event )
  1655. {
  1656. case WAIT_TIMEOUT:
  1657. {
  1658. t_StatusCode = e_StatusCode_Success_Timeout ;
  1659. }
  1660. break ;
  1661. case WAIT_OBJECT_0:
  1662. {
  1663. t_StatusCode = e_StatusCode_Success ;
  1664. t_Continuing = false ;
  1665. }
  1666. break ;
  1667. case WAIT_OBJECT_0+1:
  1668. {
  1669. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  1670. #if DBG
  1671. #ifdef _X86_
  1672. __asm
  1673. {
  1674. int 3 ;
  1675. }
  1676. #endif
  1677. #endif
  1678. }
  1679. break ;
  1680. case WAIT_OBJECT_0+2:
  1681. case WAIT_OBJECT_0+3:
  1682. {
  1683. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1684. #if DBG
  1685. #ifdef _X86_
  1686. __asm
  1687. {
  1688. int 3 ;
  1689. }
  1690. #endif
  1691. #endif
  1692. }
  1693. break ;
  1694. case WAIT_OBJECT_0+4:
  1695. {
  1696. t_StatusCode = e_StatusCode_Change ;
  1697. }
  1698. break ;
  1699. default:
  1700. {
  1701. t_StatusCode = e_StatusCode_Unknown ;
  1702. #if DBG
  1703. #ifdef _X86_
  1704. __asm
  1705. {
  1706. int 3 ;
  1707. }
  1708. #endif
  1709. #endif
  1710. }
  1711. break ;
  1712. }
  1713. }
  1714. break ;
  1715. default:
  1716. {
  1717. t_StatusCode = e_StatusCode_Unknown ;
  1718. #if DBG
  1719. #ifdef _X86_
  1720. __asm
  1721. {
  1722. int 3 ;
  1723. }
  1724. #endif
  1725. #endif
  1726. }
  1727. break ;
  1728. }
  1729. }
  1730. }
  1731. else
  1732. {
  1733. t_StatusCode = e_StatusCode_Success ;
  1734. }
  1735. return t_StatusCode ;
  1736. }
  1737. /******************************************************************************
  1738. *
  1739. * Name:
  1740. *
  1741. *
  1742. * Description:
  1743. *
  1744. *
  1745. *****************************************************************************/
  1746. template <class WmiKey>
  1747. WmiStatusCode WmiThread <WmiKey> :: Static_AlertableDispatch (
  1748. WmiTask <WmiKey> &a_Task ,
  1749. WmiThread <WmiKey> &a_Thread ,
  1750. const ULONG &a_Timeout
  1751. )
  1752. {
  1753. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1754. HANDLE t_Handles [ 3 ] ;
  1755. t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
  1756. t_Handles [ 1 ] = a_Thread.GetHandle () ;
  1757. t_Handles [ 2 ] = a_Thread.GetTerminationEvent () ;
  1758. bool t_Continuing = true ;
  1759. while ( t_StatusCode == e_StatusCode_Success && t_Continuing )
  1760. {
  1761. ULONG t_Event = MsgWaitForMultipleObjects (
  1762. 3 ,
  1763. t_Handles ,
  1764. FALSE ,
  1765. a_Timeout ,
  1766. QS_ALLINPUT
  1767. ) ;
  1768. switch ( t_Event )
  1769. {
  1770. case WAIT_TIMEOUT:
  1771. {
  1772. t_StatusCode = e_StatusCode_Success_Timeout ;
  1773. }
  1774. break ;
  1775. case WAIT_OBJECT_0:
  1776. {
  1777. t_StatusCode = e_StatusCode_Success ;
  1778. t_Continuing = false ;
  1779. }
  1780. break ;
  1781. case WAIT_OBJECT_0+1:
  1782. case WAIT_OBJECT_0+2:
  1783. {
  1784. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  1785. #if DBG
  1786. #ifdef _X86_
  1787. __asm
  1788. {
  1789. int 3 ;
  1790. }
  1791. #endif
  1792. #endif
  1793. }
  1794. break ;
  1795. case WAIT_OBJECT_0+3:
  1796. {
  1797. BOOL t_DispatchStatus ;
  1798. MSG t_Msg ;
  1799. while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
  1800. {
  1801. if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
  1802. {
  1803. TranslateMessage ( & t_Msg ) ;
  1804. DispatchMessage ( & t_Msg ) ;
  1805. }
  1806. }
  1807. ULONG t_Event = WaitForMultipleObjects (
  1808. 3 ,
  1809. t_Handles ,
  1810. FALSE ,
  1811. 0
  1812. ) ;
  1813. switch ( t_Event )
  1814. {
  1815. case WAIT_TIMEOUT:
  1816. {
  1817. t_StatusCode = e_StatusCode_Success_Timeout ;
  1818. }
  1819. break ;
  1820. case WAIT_OBJECT_0:
  1821. {
  1822. t_StatusCode = e_StatusCode_Success ;
  1823. t_Continuing = false ;
  1824. }
  1825. break ;
  1826. case WAIT_OBJECT_0+1:
  1827. case WAIT_OBJECT_0+2:
  1828. {
  1829. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  1830. }
  1831. break ;
  1832. default:
  1833. {
  1834. t_StatusCode = e_StatusCode_Unknown ;
  1835. #if DBG
  1836. #ifdef _X86_
  1837. __asm
  1838. {
  1839. int 3 ;
  1840. }
  1841. #endif
  1842. #endif
  1843. }
  1844. break ;
  1845. }
  1846. }
  1847. break ;
  1848. default:
  1849. {
  1850. t_StatusCode = e_StatusCode_Unknown ;
  1851. #if DBG
  1852. #ifdef _X86_
  1853. __asm
  1854. {
  1855. int 3 ;
  1856. }
  1857. #endif
  1858. #endif
  1859. }
  1860. break ;
  1861. }
  1862. }
  1863. return t_StatusCode ;
  1864. }
  1865. /******************************************************************************
  1866. *
  1867. * Name:
  1868. *
  1869. *
  1870. * Description:
  1871. *
  1872. *
  1873. *****************************************************************************/
  1874. template <class WmiKey>
  1875. WmiStatusCode WmiThread <WmiKey> :: Static_AlertableDispatch (
  1876. WmiTask <WmiKey> &a_Task ,
  1877. const ULONG &a_Timeout
  1878. )
  1879. {
  1880. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1881. WmiThread *t_Thread = GetThread () ;
  1882. if ( t_Thread )
  1883. {
  1884. t_StatusCode = t_Thread->AlertableDispatch ( a_Task , a_Timeout ) ;
  1885. }
  1886. else
  1887. {
  1888. WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
  1889. if ( t_ServicingThread )
  1890. {
  1891. t_StatusCode = Static_AlertableDispatch ( a_Task , *t_ServicingThread , a_Timeout ) ;
  1892. }
  1893. else
  1894. {
  1895. t_StatusCode = e_StatusCode_Success ;
  1896. }
  1897. }
  1898. return t_StatusCode ;
  1899. }
  1900. /******************************************************************************
  1901. *
  1902. * Name:
  1903. *
  1904. *
  1905. * Description:
  1906. *
  1907. *
  1908. *****************************************************************************/
  1909. template <class WmiKey>
  1910. WmiStatusCode WmiThread <WmiKey> :: AlertableDispatch (
  1911. WmiTask <WmiKey> &a_Task ,
  1912. const ULONG &a_Timeout
  1913. )
  1914. {
  1915. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  1916. QueueContainer t_EnQueue ( m_Allocator ) ;
  1917. t_StatusCode = t_EnQueue.Initialize () ;
  1918. if ( t_StatusCode == e_StatusCode_Success )
  1919. {
  1920. do
  1921. {
  1922. do
  1923. {
  1924. t_StatusCode = Execute ( m_InterruptableTaskQueue , t_EnQueue ) ;
  1925. } while ( t_StatusCode == e_StatusCode_Success ) ;
  1926. if ( t_StatusCode == e_StatusCode_NotInitialized )
  1927. {
  1928. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  1929. t_StatusCode = m_InterruptableTaskQueue.Merge ( t_EnQueue ) ;
  1930. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  1931. if ( t_StatusCode == e_StatusCode_Success )
  1932. {
  1933. do
  1934. {
  1935. t_StatusCode = Execute ( m_TaskQueue , t_EnQueue ) ;
  1936. } while ( t_StatusCode == e_StatusCode_Success ) ;
  1937. }
  1938. }
  1939. if ( t_StatusCode == e_StatusCode_NotInitialized )
  1940. {
  1941. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  1942. t_StatusCode = m_TaskQueue.Merge ( t_EnQueue ) ;
  1943. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  1944. if ( t_StatusCode == e_StatusCode_Success )
  1945. {
  1946. t_StatusCode = AlertableWait ( a_Task , a_Timeout ) ;
  1947. }
  1948. }
  1949. }
  1950. while ( t_StatusCode == e_StatusCode_Success || t_StatusCode == e_StatusCode_Change ) ;
  1951. }
  1952. return t_StatusCode ;
  1953. }
  1954. /******************************************************************************
  1955. *
  1956. * Name:
  1957. *
  1958. *
  1959. * Description:
  1960. *
  1961. *
  1962. *****************************************************************************/
  1963. template <class WmiKey>
  1964. WmiStatusCode WmiThread <WmiKey> :: Execute ( QueueContainer &a_Queue , QueueContainer &a_EnQueue )
  1965. {
  1966. QueueKey t_TopKey ;
  1967. WmiTask < WmiKey > *t_TopTask ;
  1968. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  1969. WmiStatusCode t_StatusCode = a_Queue.Top ( t_TopKey , t_TopTask ) ;
  1970. if ( t_StatusCode == e_StatusCode_Success )
  1971. {
  1972. t_StatusCode = a_Queue.DeQueue () ;
  1973. if ( t_StatusCode == e_StatusCode_Success )
  1974. {
  1975. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  1976. if ( t_TopTask->TaskState () == WmiTask < WmiKey > :: e_WmiTask_EnQueued )
  1977. {
  1978. t_StatusCode = t_TopTask->Process ( *this ) ;
  1979. if ( t_StatusCode != e_StatusCode_EnQueue )
  1980. {
  1981. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  1982. if ( ( t_StatusCode = s_TaskContainer->Delete ( t_TopTask ) ) == e_StatusCode_NotFound )
  1983. {
  1984. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  1985. t_StatusCode = e_StatusCode_Success ;
  1986. }
  1987. else
  1988. {
  1989. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  1990. t_TopTask->Release () ;
  1991. }
  1992. }
  1993. else
  1994. {
  1995. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  1996. switch ( t_TopTask->EnqueuedAs () )
  1997. {
  1998. case WmiTask <WmiKey> :: e_WmiTask_Enqueue:
  1999. {
  2000. t_StatusCode = a_EnQueue.EnQueue ( t_TopKey , t_TopTask ) ;
  2001. }
  2002. break ;
  2003. case WmiTask <WmiKey> :: e_WmiTask_EnqueueAlertable:
  2004. {
  2005. t_StatusCode = m_AlertableTaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
  2006. }
  2007. break ;
  2008. case WmiTask <WmiKey> :: e_WmiTask_EnqueueInterruptable:
  2009. {
  2010. t_StatusCode = m_InterruptableTaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
  2011. }
  2012. break ;
  2013. default:
  2014. {
  2015. }
  2016. break ;
  2017. }
  2018. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2019. SetEvent ( m_QueueChange ) ;
  2020. }
  2021. }
  2022. else
  2023. {
  2024. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  2025. if ( ( t_StatusCode = s_TaskContainer->Delete ( t_TopTask ) ) == e_StatusCode_NotFound )
  2026. {
  2027. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  2028. t_StatusCode = e_StatusCode_Success ;
  2029. }
  2030. else
  2031. {
  2032. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  2033. }
  2034. t_TopTask->Complete () ;
  2035. t_TopTask->Release () ;
  2036. }
  2037. }
  2038. else
  2039. {
  2040. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2041. }
  2042. }
  2043. else
  2044. {
  2045. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2046. }
  2047. return t_StatusCode ;
  2048. }
  2049. /******************************************************************************
  2050. *
  2051. * Name:
  2052. *
  2053. *
  2054. * Description:
  2055. *
  2056. *
  2057. *****************************************************************************/
  2058. template <class WmiKey>
  2059. WmiStatusCode WmiThread <WmiKey> :: ShuffleTask (
  2060. const HANDLE &a_Event
  2061. )
  2062. {
  2063. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  2064. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  2065. ULONG t_Index = m_AlertableTaskQueue.Size () ;
  2066. while ( ( t_StatusCode == e_StatusCode_Success ) && ( t_Index ) )
  2067. {
  2068. QueueKey t_TopKey ;
  2069. WmiTask < WmiKey > *t_TopTask ;
  2070. t_StatusCode = m_AlertableTaskQueue.Top ( t_TopKey , t_TopTask ) ;
  2071. if ( t_StatusCode == e_StatusCode_Success )
  2072. {
  2073. t_StatusCode = m_AlertableTaskQueue.DeQueue () ;
  2074. if ( t_StatusCode == e_StatusCode_Success )
  2075. {
  2076. if ( t_TopTask->GetEvent () == a_Event )
  2077. {
  2078. if ( t_TopTask->TaskState () == WmiTask < WmiKey > :: e_WmiTask_EnQueued )
  2079. {
  2080. t_StatusCode = m_TaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
  2081. if ( t_StatusCode == e_StatusCode_Success )
  2082. {
  2083. SetEvent ( m_QueueChange ) ;
  2084. break ;
  2085. }
  2086. }
  2087. else
  2088. {
  2089. WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
  2090. if ( ( t_StatusCode = s_TaskContainer->Delete ( t_TopTask ) ) == e_StatusCode_NotFound )
  2091. {
  2092. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  2093. t_StatusCode = e_StatusCode_Success ;
  2094. }
  2095. else
  2096. {
  2097. WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
  2098. }
  2099. t_TopTask->Complete () ;
  2100. t_TopTask->Release () ;
  2101. }
  2102. }
  2103. else
  2104. {
  2105. t_TopKey.SetTick ( m_Key++ ) ;
  2106. t_StatusCode = m_AlertableTaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
  2107. if ( t_StatusCode == e_StatusCode_Success )
  2108. {
  2109. }
  2110. }
  2111. }
  2112. }
  2113. t_Index -- ;
  2114. }
  2115. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2116. return t_StatusCode ;
  2117. }
  2118. /******************************************************************************
  2119. *
  2120. * Name:
  2121. *
  2122. *
  2123. * Description:
  2124. *
  2125. *
  2126. *****************************************************************************/
  2127. template <class WmiKey>
  2128. WmiStatusCode WmiThread <WmiKey> :: FillHandleTable (
  2129. HANDLE *a_HandleTable ,
  2130. ULONG &a_Capacity
  2131. )
  2132. {
  2133. ULONG t_Index = 0 ;
  2134. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  2135. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  2136. QueueContainerIterator t_Iterator ;
  2137. t_Iterator = m_AlertableTaskQueue.End () ;
  2138. while ( ( t_StatusCode == e_StatusCode_Success ) && ( t_Index < a_Capacity ) && ! t_Iterator.Null () )
  2139. {
  2140. if ( t_Iterator.GetElement ()->GetEvent () )
  2141. {
  2142. a_HandleTable [ t_Index ] = t_Iterator.GetElement ()->GetEvent () ;
  2143. }
  2144. else
  2145. {
  2146. t_StatusCode = e_StatusCode_InvalidArgs ;
  2147. }
  2148. t_Iterator.Decrement () ;
  2149. t_Index ++ ;
  2150. }
  2151. if ( t_StatusCode == e_StatusCode_NotInitialized )
  2152. {
  2153. t_StatusCode = e_StatusCode_Success ;
  2154. }
  2155. a_Capacity = t_Index ;
  2156. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2157. return t_StatusCode ;
  2158. }
  2159. /******************************************************************************
  2160. *
  2161. * Name:
  2162. *
  2163. *
  2164. * Description:
  2165. *
  2166. *
  2167. *****************************************************************************/
  2168. template <class WmiKey>
  2169. WmiStatusCode WmiThread <WmiKey> :: AlertableWait (
  2170. WmiTask <WmiKey> &a_Task ,
  2171. const ULONG &a_Timeout
  2172. )
  2173. {
  2174. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  2175. WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
  2176. if ( t_ServicingThread )
  2177. {
  2178. HANDLE t_Handles [ MAXIMUM_WAIT_OBJECTS - 1 ] ;
  2179. t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
  2180. t_Handles [ 1 ] = GetTerminationEvent () ;
  2181. t_Handles [ 2 ] = t_ServicingThread->GetHandle () ;
  2182. t_Handles [ 3 ] = t_ServicingThread->GetTerminationEvent () ;
  2183. t_Handles [ 4 ] = t_ServicingThread->GetQueueChangeEvent () ;
  2184. ULONG t_Capacity = MAXIMUM_WAIT_OBJECTS - 6 ;
  2185. t_StatusCode = FillHandleTable ( & t_Handles [ 5 ] , t_Capacity ) ;
  2186. bool t_Continuing = true ;
  2187. while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
  2188. {
  2189. ULONG t_Event = MsgWaitForMultipleObjects (
  2190. 5 + t_Capacity ,
  2191. t_Handles ,
  2192. FALSE ,
  2193. a_Timeout ,
  2194. QS_ALLINPUT
  2195. ) ;
  2196. switch ( t_Event )
  2197. {
  2198. case WAIT_TIMEOUT:
  2199. {
  2200. t_StatusCode = e_StatusCode_Success_Timeout ;
  2201. }
  2202. break ;
  2203. case WAIT_OBJECT_0:
  2204. {
  2205. t_StatusCode = e_StatusCode_Success ;
  2206. t_Continuing = false ;
  2207. }
  2208. break ;
  2209. case WAIT_OBJECT_0+1:
  2210. {
  2211. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  2212. #if DBG
  2213. #ifdef _X86_
  2214. __asm
  2215. {
  2216. int 3 ;
  2217. }
  2218. #endif
  2219. #endif
  2220. }
  2221. break ;
  2222. case WAIT_OBJECT_0+2:
  2223. case WAIT_OBJECT_0+3:
  2224. {
  2225. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  2226. #if DBG
  2227. #ifdef _X86_
  2228. __asm
  2229. {
  2230. int 3 ;
  2231. }
  2232. #endif
  2233. #endif
  2234. }
  2235. break ;
  2236. case WAIT_OBJECT_0+4:
  2237. {
  2238. t_StatusCode = e_StatusCode_Change ;
  2239. }
  2240. break ;
  2241. default:
  2242. {
  2243. if ( t_Event == t_Capacity + 5 )
  2244. {
  2245. BOOL t_DispatchStatus ;
  2246. MSG t_Msg ;
  2247. while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
  2248. {
  2249. if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
  2250. {
  2251. TranslateMessage ( & t_Msg ) ;
  2252. DispatchMessage ( & t_Msg ) ;
  2253. }
  2254. }
  2255. ULONG t_Event = WaitForMultipleObjects (
  2256. 5 + t_Capacity ,
  2257. t_Handles ,
  2258. FALSE ,
  2259. 0
  2260. ) ;
  2261. switch ( t_Event )
  2262. {
  2263. case WAIT_TIMEOUT:
  2264. {
  2265. t_StatusCode = e_StatusCode_Success_Timeout ;
  2266. }
  2267. break ;
  2268. case WAIT_OBJECT_0:
  2269. {
  2270. t_StatusCode = e_StatusCode_Success ;
  2271. t_Continuing = false ;
  2272. }
  2273. break ;
  2274. case WAIT_OBJECT_0+1:
  2275. {
  2276. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  2277. #if DBG
  2278. #ifdef _X86_
  2279. __asm
  2280. {
  2281. int 3 ;
  2282. }
  2283. #endif
  2284. #endif
  2285. }
  2286. break ;
  2287. case WAIT_OBJECT_0+2:
  2288. case WAIT_OBJECT_0+3:
  2289. {
  2290. t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
  2291. #if DBG
  2292. #ifdef _X86_
  2293. __asm
  2294. {
  2295. int 3 ;
  2296. }
  2297. #endif
  2298. #endif
  2299. }
  2300. break ;
  2301. case WAIT_OBJECT_0+4:
  2302. {
  2303. t_StatusCode = e_StatusCode_Change ;
  2304. }
  2305. break ;
  2306. default:
  2307. {
  2308. if ( t_Event < t_Capacity + 5 )
  2309. {
  2310. t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
  2311. }
  2312. else
  2313. {
  2314. t_StatusCode = e_StatusCode_InvalidArgs ;
  2315. #if DBG
  2316. #ifdef _X86_
  2317. __asm
  2318. {
  2319. int 3 ;
  2320. }
  2321. #endif
  2322. #endif
  2323. }
  2324. }
  2325. }
  2326. }
  2327. else if ( t_Event < t_Capacity + 5 )
  2328. {
  2329. t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
  2330. }
  2331. else
  2332. {
  2333. t_StatusCode = e_StatusCode_InvalidArgs ;
  2334. #if DBG
  2335. #ifdef _X86_
  2336. __asm
  2337. {
  2338. int 3 ;
  2339. }
  2340. #endif
  2341. #endif
  2342. }
  2343. }
  2344. break ;
  2345. }
  2346. }
  2347. }
  2348. else
  2349. {
  2350. t_StatusCode = e_StatusCode_Success ;
  2351. }
  2352. return t_StatusCode ;
  2353. }
  2354. /******************************************************************************
  2355. *
  2356. * Name:
  2357. *
  2358. *
  2359. * Description:
  2360. *
  2361. *
  2362. *****************************************************************************/
  2363. template <class WmiKey>
  2364. WmiStatusCode WmiThread <WmiKey> :: ThreadDispatch ()
  2365. {
  2366. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  2367. QueueContainer t_EnQueue ( m_Allocator ) ;
  2368. t_StatusCode = t_EnQueue.Initialize () ;
  2369. if ( t_StatusCode == e_StatusCode_Success )
  2370. {
  2371. do
  2372. {
  2373. do
  2374. {
  2375. t_StatusCode = Execute ( m_InterruptableTaskQueue , t_EnQueue ) ;
  2376. } while ( t_StatusCode == e_StatusCode_Success ) ;
  2377. if ( t_StatusCode == e_StatusCode_NotInitialized )
  2378. {
  2379. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  2380. t_StatusCode = m_InterruptableTaskQueue.Merge ( t_EnQueue ) ;
  2381. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2382. if ( t_StatusCode == e_StatusCode_Success )
  2383. {
  2384. do
  2385. {
  2386. t_StatusCode = Execute ( m_TaskQueue , t_EnQueue ) ;
  2387. } while ( t_StatusCode == e_StatusCode_Success ) ;
  2388. }
  2389. }
  2390. if ( t_StatusCode == e_StatusCode_NotInitialized )
  2391. {
  2392. WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
  2393. t_StatusCode = m_TaskQueue.Merge ( t_EnQueue ) ;
  2394. WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
  2395. if ( t_StatusCode == e_StatusCode_Success )
  2396. {
  2397. t_StatusCode = ThreadWait () ;
  2398. }
  2399. }
  2400. }
  2401. while ( t_StatusCode == e_StatusCode_Success || t_StatusCode == e_StatusCode_Change ) ;
  2402. }
  2403. return t_StatusCode ;
  2404. }
  2405. /******************************************************************************
  2406. *
  2407. * Name:
  2408. *
  2409. *
  2410. * Description:
  2411. *
  2412. *
  2413. *****************************************************************************/
  2414. template <class WmiKey>
  2415. WmiStatusCode WmiThread <WmiKey> :: ThreadWait ()
  2416. {
  2417. int sleep_duration = 0;
  2418. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  2419. HANDLE t_Handles [ MAXIMUM_WAIT_OBJECTS - 1 ] ;
  2420. t_Handles [ 0 ] = GetTerminationEvent () ;
  2421. t_Handles [ 1 ] = GetQueueChangeEvent () ;
  2422. ULONG t_Capacity = MAXIMUM_WAIT_OBJECTS - 3 ;
  2423. t_StatusCode = FillHandleTable ( & t_Handles [ 2 ] , t_Capacity ) ;
  2424. bool t_Continuing = true ;
  2425. while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
  2426. {
  2427. ULONG t_Event = MsgWaitForMultipleObjectsEx (
  2428. 2 + t_Capacity ,
  2429. t_Handles ,
  2430. m_Timeout ,
  2431. QS_ALLINPUT ,
  2432. MWMO_ALERTABLE
  2433. ) ;
  2434. switch ( t_Event )
  2435. {
  2436. case WAIT_TIMEOUT:
  2437. {
  2438. t_StatusCode = TimedOut () ;
  2439. }
  2440. break ;
  2441. case WAIT_OBJECT_0:
  2442. {
  2443. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  2444. #if DBG
  2445. OutputDebugString ( _T("\nWmiThread - Thread Terminating") ) ;
  2446. #endif
  2447. }
  2448. break ;
  2449. case WAIT_OBJECT_0+1:
  2450. {
  2451. t_StatusCode = e_StatusCode_Change ;
  2452. }
  2453. break ;
  2454. case WAIT_IO_COMPLETION:
  2455. {
  2456. t_StatusCode = e_StatusCode_Success;
  2457. }
  2458. break ;
  2459. default:
  2460. {
  2461. if ( t_Event == t_Capacity + 2 )
  2462. {
  2463. BOOL t_DispatchStatus ;
  2464. MSG t_Msg ;
  2465. while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
  2466. {
  2467. if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
  2468. {
  2469. TranslateMessage ( & t_Msg ) ;
  2470. DispatchMessage ( & t_Msg ) ;
  2471. }
  2472. }
  2473. ULONG t_Event = WaitForMultipleObjects (
  2474. 2 + t_Capacity ,
  2475. t_Handles ,
  2476. FALSE ,
  2477. 0
  2478. ) ;
  2479. switch ( t_Event )
  2480. {
  2481. case WAIT_TIMEOUT:
  2482. {
  2483. t_StatusCode = TimedOut () ;
  2484. }
  2485. break ;
  2486. case WAIT_OBJECT_0:
  2487. {
  2488. t_StatusCode = e_StatusCode_HostingThreadTerminated ;
  2489. #if DBG
  2490. OutputDebugString ( _T("\nWmiThread - Thread Terminating")) ;
  2491. #endif
  2492. }
  2493. break ;
  2494. case WAIT_OBJECT_0+1:
  2495. {
  2496. t_StatusCode = e_StatusCode_Change ;
  2497. }
  2498. break ;
  2499. default:
  2500. {
  2501. if ( t_Event < t_Capacity + 2 )
  2502. {
  2503. t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
  2504. }
  2505. else if (t_Event == WAIT_FAILED && GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
  2506. {
  2507. Sleep(sleep_duration?10:0);
  2508. sleep_duration^=1;
  2509. continue;
  2510. }
  2511. else
  2512. {
  2513. t_StatusCode = e_StatusCode_InvalidArgs ;
  2514. #if DBG
  2515. #ifdef _X86_
  2516. __asm
  2517. {
  2518. int 3 ;
  2519. }
  2520. #endif
  2521. #endif
  2522. }
  2523. }
  2524. }
  2525. }
  2526. else if ( t_Event < t_Capacity + 2 )
  2527. {
  2528. t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
  2529. }
  2530. else if (t_Event == WAIT_FAILED && GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
  2531. {
  2532. Sleep(sleep_duration?10:0);
  2533. sleep_duration^=1;
  2534. continue;
  2535. }
  2536. else
  2537. {
  2538. t_StatusCode = e_StatusCode_InvalidArgs ;
  2539. #if DBG
  2540. #ifdef _X86_
  2541. __asm
  2542. {
  2543. int 3 ;
  2544. }
  2545. #endif
  2546. #endif
  2547. }
  2548. }
  2549. break ;
  2550. }
  2551. }
  2552. return t_StatusCode ;
  2553. }
  2554. #endif __THREAD_CPP