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.

4807 lines
157 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. WmiFinalizer2
  5. Abstract:
  6. History:
  7. paulall 27-Mar-2000 Created.
  8. marioh 20-Oct-2000 Major updates completed
  9. --*/
  10. #include "precomp.h"
  11. #include <stdio.h>
  12. #include "wbemint.h"
  13. #include "wbemcli.h"
  14. #include "WmiFinalizer.h"
  15. #include "coresvc.h"
  16. #include "coreq.h"
  17. #include <wbemcore.h>
  18. #include <wmiarbitrator.h>
  19. #include <autoptr.h>
  20. #include <initguid.h>
  21. #ifndef INITGUID
  22. #define INITGUID
  23. #endif
  24. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. // Batching related registry data
  26. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27. #define REGKEY_CIMOM "Software\\Microsoft\\Wbem\\CIMOM"
  28. #define REGVALUE_BATCHSIZE "FinalizerBatchSize"
  29. ULONG g_ulMaxBatchSize = 0;
  30. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  31. // Client callback related registry data
  32. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33. #define REGVALUE_CLIENTCALLBACKTIMEOUT "ClientCallbackTimeout"
  34. ULONG g_ulClientCallbackTimeout = 0;
  35. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36. // Queue threshold related registry data
  37. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  38. #define REGVALUE_QUEUETHRESHOLD "FinalizerQueueThreshold"
  39. #define DEFAULT_QUEUETHRESHOLD 2
  40. ULONG g_ulFinalizerQueueThreshold = 0;
  41. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  42. // Static declarations and initialization
  43. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  44. LONG s_Finalizer_ObjectCount = 0 ; // Global finalizer count
  45. LONG s_FinalizerCallResult_ObjectCount = 0 ; // Global CallbackEesult count
  46. LONG s_FinalizerEnum_ObjectCount = 0 ; // Global Enumerator count
  47. LONG s_FinalizerEnumSink_ObjectCount = 0 ; // Global Enumerator sink count
  48. LONG s_FinalizerInBoundSink_ObjectCount = 0 ; // Global InboundSink count
  49. #define RET_FNLZR_ASSERT(msg, hres) return hres
  50. #define FNLZR_ASSERT(msg, hres)
  51. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  52. // CWMIFINALIZER
  53. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  54. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  55. // CWmiFinalizer::CWmiFinalizer()
  56. //
  57. // Peforms initialization of the finalizer.
  58. //
  59. // Exceptions thrown:
  60. //
  61. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  62. CWmiFinalizer::CWmiFinalizer(CCoreServices *pSrvs)
  63. : m_lRefCount(0),
  64. m_lInternalRefCount(0),
  65. m_phTask(NULL),
  66. m_pArbitrator(NULL),
  67. m_pDestSink(NULL),
  68. m_uForwardingType(forwarding_type_none),
  69. m_hresFinalResult(-1),
  70. m_bRestartable(false),
  71. m_uCurObjectPosition(0),
  72. m_bSetStatusCalled(false),
  73. m_bSetStatusConsumed(false),
  74. m_ulQueueSize (0),
  75. m_bCancelledCall (FALSE),
  76. m_bNaughtyClient (FALSE),
  77. m_ulStatus (WMI_FNLZR_STATE_NO_INPUT),
  78. m_hCancelEvent (NULL),
  79. m_hStatus (NoError),
  80. m_ulOperationType (0),
  81. m_ulSemisyncWakeupCall (0),
  82. m_ulAsyncDeliveryCount (0),
  83. m_apAsyncDeliveryBuffer (NULL),
  84. m_lCurrentlyDelivering (FALSE),
  85. m_lCurrentlyCancelling (FALSE),
  86. m_enumBatchStatus (FinalizerBatch_NoError),
  87. m_bSetStatusEnqueued ( FALSE ),
  88. m_bSetStatusWithError ( FALSE ),
  89. m_lMemoryConsumption ( 0 ),
  90. m_bTaskInitialized ( FALSE ) ,
  91. m_bClonedFinalizer ( FALSE ) ,
  92. m_hWaitForSetStatus ( NULL ) ,
  93. m_bSetStatusDelivered ( FALSE ),
  94. m_LineCancelCall(0)
  95. {
  96. // validate CoreServices pointer
  97. if (NULL == pSrvs) throw CX_MemoryException();
  98. // Create m_hResultReceived handle
  99. HANDLE hTmpResRecved = CreateEvent(NULL, TRUE, FALSE, NULL);
  100. if ( NULL == hTmpResRecved ) throw CX_MemoryException();
  101. OnDeleteIf<HANDLE,BOOL(*)(HANDLE),CloseHandle> cmResRecved(hTmpResRecved );
  102. // Create m_hCancelEvent handle
  103. HANDLE hTmpCancelEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  104. if (NULL == hTmpCancelEvent) throw CX_MemoryException();
  105. OnDeleteIf<HANDLE,BOOL(*)(HANDLE),CloseHandle> cmCancelEvent (hTmpCancelEvent);
  106. // Create new callresult
  107. m_pCallResult = new CWmiFinalizerCallResult(this);
  108. if (NULL == m_pCallResult) throw CX_MemoryException();
  109. m_pCallResult->InternalAddRef();
  110. cmResRecved.dismiss();
  111. m_hResultReceived = hTmpResRecved;
  112. cmCancelEvent.dismiss();
  113. m_hCancelEvent = hTmpCancelEvent;
  114. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  115. // Get arbitrator
  116. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  117. m_pArbitrator = CWmiArbitrator::GetRefedArbitrator();
  118. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  119. // Check what the batch size is supposed to be through registry.
  120. // If not found, use default size defined in DEFAULT_BATCH_TRANSMIT_BYTES
  121. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  122. if ( !g_ulMaxBatchSize )
  123. {
  124. g_ulMaxBatchSize = DEFAULT_BATCH_TRANSMIT_BYTES;
  125. Registry batchSize (HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE, TEXT(REGKEY_CIMOM));
  126. if ( batchSize.GetLastError() == ERROR_SUCCESS )
  127. {
  128. DWORD dwTmp;
  129. batchSize.GetDWORD ( TEXT(REGVALUE_BATCHSIZE), &dwTmp );
  130. if ( batchSize.GetLastError() == ERROR_SUCCESS )
  131. g_ulMaxBatchSize = (LONG) dwTmp;
  132. }
  133. }
  134. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  135. // Check what the timeout for client callbacks is supposed to be through registry.
  136. // If not found, use default size defined in ABANDON_PROXY_THRESHOLD
  137. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  138. if ( !g_ulClientCallbackTimeout )
  139. {
  140. g_ulClientCallbackTimeout = ABANDON_PROXY_THRESHOLD;
  141. Registry batchSize (HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE, TEXT(REGKEY_CIMOM));
  142. if ( batchSize.GetLastError() == ERROR_SUCCESS )
  143. {
  144. DWORD dwTmp;
  145. batchSize.GetDWORD ( TEXT(REGVALUE_CLIENTCALLBACKTIMEOUT), &dwTmp );
  146. if ( batchSize.GetLastError() == ERROR_SUCCESS )
  147. g_ulClientCallbackTimeout = (LONG) dwTmp;
  148. }
  149. }
  150. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  151. // Check what the timeout for client callbacks is supposed to be through registry.
  152. // If not found, use default size defined in ABANDON_PROXY_THRESHOLD
  153. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  154. if ( !g_ulFinalizerQueueThreshold )
  155. {
  156. g_ulFinalizerQueueThreshold = DEFAULT_QUEUETHRESHOLD;
  157. Registry batchSize (HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE, TEXT(REGKEY_CIMOM));
  158. if ( batchSize.GetLastError() == ERROR_SUCCESS )
  159. {
  160. DWORD dwTmp;
  161. batchSize.GetDWORD ( TEXT(REGVALUE_QUEUETHRESHOLD), &dwTmp );
  162. if ( batchSize.GetLastError() == ERROR_SUCCESS )
  163. g_ulFinalizerQueueThreshold = (LONG) dwTmp;
  164. }
  165. }
  166. InterlockedIncrement ( & s_Finalizer_ObjectCount ) ;
  167. }
  168. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  169. // CWmiFinalizer::~CWmiFinalizer()
  170. //
  171. // Destructor. Decrements global finalizer object count
  172. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  173. CWmiFinalizer::~CWmiFinalizer()
  174. {
  175. InterlockedDecrement ( & s_Finalizer_ObjectCount ) ;
  176. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  177. // Unregister with arbitrator
  178. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  179. if (m_pArbitrator)
  180. {
  181. m_pArbitrator->UnRegisterArbitratee (0, m_phTask, this);
  182. }
  183. if ( m_phTask )
  184. {
  185. m_phTask->Release ( );
  186. m_phTask = NULL ;
  187. }
  188. if (m_pArbitrator)
  189. {
  190. m_pArbitrator->Release();
  191. m_pArbitrator = NULL ;
  192. }
  193. }
  194. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  195. // CWmiFinalizer::CallBackRelease ()
  196. //
  197. // Called when the external ref count (client ref count) goes to zero.
  198. // Performs following clean up tasks
  199. //
  200. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  201. void CWmiFinalizer::CallBackRelease ()
  202. {
  203. {
  204. CInCritSec cs(&m_cs);
  205. // Release the arbitrator and all inbound sinks
  206. for (LONG i = 0; i < m_objects.Size(); i++)
  207. {
  208. CWmiFinalizerObj *pObj = (CWmiFinalizerObj*)m_objects[i];
  209. delete pObj;
  210. }
  211. m_objects.Empty ( ) ;
  212. }
  213. for (int i = 0; i < m_inboundSinks.Size(); i++)
  214. {
  215. ((CWmiFinalizerInboundSink*)m_inboundSinks[i])->InternalRelease();
  216. }
  217. m_inboundSinks.Empty();
  218. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  219. // Release the destination sink
  220. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  221. ReleaseDestinationSink();
  222. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  223. // If the call hasnt been cancelled already, go ahead and
  224. // do so now
  225. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  226. if (!m_bCancelledCall)
  227. CancelTaskInternal();
  228. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  229. // Close all handles
  230. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  231. if ( m_hResultReceived )
  232. {
  233. SetEvent ( m_hResultReceived ) ;
  234. CloseHandle ( m_hResultReceived);
  235. m_hResultReceived = NULL ;
  236. }
  237. if ( m_hCancelEvent )
  238. {
  239. SetEvent ( m_hCancelEvent );
  240. CloseHandle ( m_hCancelEvent );
  241. m_hCancelEvent = NULL ;
  242. }
  243. // Release callresult and enumerator
  244. m_pCallResult->InternalRelease();
  245. m_pCallResult = NULL ;
  246. //
  247. // Release all enumerators associated with this finalizer
  248. //
  249. {
  250. CInCritSec cs ( &m_cs ) ; // SEC:REVIEWED 2002-03-22 : Assumes entry
  251. for ( i = 0; i < m_enumerators.Size(); i++ )
  252. {
  253. ((CWmiFinalizerEnumerator*)m_enumerators[i])->InternalRelease ( ) ;
  254. }
  255. m_enumerators.Empty ( ) ;
  256. }
  257. NotifyClientOfCancelledCall ( ) ;
  258. }
  259. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  260. // CWmiFinalizer::CancelTaskInternal()
  261. //
  262. // Calls the arbitrator and unregisters the task
  263. //
  264. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  265. HRESULT CWmiFinalizer::CancelTaskInternal ( )
  266. {
  267. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  268. HRESULT hRes = WBEM_E_FAILED;
  269. if (m_phTask && m_pArbitrator)
  270. {
  271. hRes = m_pArbitrator->UnregisterTask(m_phTask);
  272. }
  273. return hRes;
  274. }
  275. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  276. // CWmiFinalizer::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  277. //
  278. // Std implementation of QI
  279. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  280. STDMETHODIMP CWmiFinalizer::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  281. {
  282. if (ppvObj == 0)
  283. return ERROR_INVALID_PARAMETER;
  284. // SEC:REVIEWED 2002-03-22 : Ideally, we should have EH around all
  285. // derefs of ppvObj, in case the memory is invalid.
  286. if (IID_IUnknown==riid )
  287. {
  288. *ppvObj = (_IWmiFinalizer*)this;
  289. }
  290. else if (IID__IWmiFinalizer == riid)
  291. {
  292. *ppvObj = (_IWmiFinalizer*)this;
  293. }
  294. else if (IID__IWmiArbitratee == riid)
  295. {
  296. *ppvObj = (_IWmiArbitratee*)this;
  297. }
  298. else if (IID_IWbemShutdown == riid)
  299. {
  300. *ppvObj = (IWbemShutdown*)this;
  301. }
  302. else
  303. {
  304. *ppvObj = 0;
  305. return E_NOINTERFACE;
  306. }
  307. ((IUnknown *)(* ppvObj))->AddRef(); // SEC:REVIEWED 2002-03-22 : Needs EH
  308. return NOERROR;
  309. }
  310. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  311. // CWmiFinalizer::AddRef()
  312. //
  313. // Std implementation of AddRef.
  314. // Also does internal addref
  315. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  316. ULONG CWmiFinalizer::AddRef()
  317. {
  318. ULONG uNewCount = InterlockedIncrement(&m_lRefCount);
  319. if ( uNewCount == 1 )
  320. {
  321. InternalAddRef () ;
  322. }
  323. return uNewCount;
  324. }
  325. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  326. // CWmiFinalizer::Release()
  327. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  328. ULONG CWmiFinalizer::Release()
  329. {
  330. ULONG uNewCount = InterlockedDecrement(&m_lRefCount);
  331. if (0 == uNewCount)
  332. {
  333. CallBackRelease () ;
  334. InternalRelease () ;
  335. }
  336. return uNewCount;
  337. }
  338. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  339. // CWmiFinalizer::InternalAddRef()
  340. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  341. ULONG CWmiFinalizer::InternalAddRef()
  342. {
  343. ULONG uNewCount = InterlockedIncrement(&m_lInternalRefCount);
  344. return uNewCount;
  345. }
  346. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  347. // ULONG CWmiFinalizer::InternalRelease()
  348. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  349. ULONG CWmiFinalizer::InternalRelease()
  350. {
  351. ULONG uNewCount = InterlockedDecrement(&m_lInternalRefCount);
  352. if (0 == uNewCount)
  353. {
  354. delete this ;
  355. }
  356. return uNewCount;
  357. }
  358. /*
  359. * =====================================================================================================
  360. |
  361. | HRESULT CWmiFinalizer::ReportMemoryUsage ( ULONG lFlags, LONG lDelta )
  362. | ----------------------------------------------------------------------
  363. |
  364. | Common point to report memory consumption to the arbitrator.
  365. |
  366. | Uses m_phTask when calling arbitrator.
  367. |
  368. |
  369. |
  370. * =====================================================================================================
  371. */
  372. HRESULT CWmiFinalizer::ReleaseDestinationSink ( )
  373. {
  374. HRESULT hRes = WBEM_S_NO_ERROR ;
  375. {
  376. CInCritSec lock(&m_destCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  377. if (m_pDestSink)
  378. {
  379. m_pDestSink->Release(); // SEC:REVIEWED 2002-03-22 : Needs EH in case user sink is garbage
  380. m_pDestSink = 0;
  381. }
  382. }
  383. NotifyClientOfCancelledCall ( ) ;
  384. return hRes ;
  385. }
  386. /*
  387. * =====================================================================================================
  388. |
  389. | HRESULT CWmiFinalizer::ReportMemoryUsage ( ULONG lFlags, LONG lDelta )
  390. | ----------------------------------------------------------------------
  391. |
  392. | Common point to report memory consumption to the arbitrator.
  393. |
  394. | Uses m_phTask when calling arbitrator.
  395. |
  396. |
  397. |
  398. * =====================================================================================================
  399. */
  400. HRESULT CWmiFinalizer::ReportMemoryUsage ( ULONG lFlags, LONG lDelta )
  401. {
  402. HRESULT hRes = WBEM_S_NO_ERROR ;
  403. if (m_pArbitrator)
  404. hRes = m_pArbitrator->ReportMemoryUsage ( lFlags, lDelta, m_phTask ) ;
  405. //
  406. // Atomic update of MemoryConsumption
  407. //
  408. InterlockedExchangeAdd ( &m_lMemoryConsumption, lDelta ) ;
  409. return hRes ;
  410. }
  411. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  412. //
  413. // CWmiFinalizer::Configure
  414. // ------------------------
  415. //
  416. // Allows decoupled & fast-track configuration with no thread switches.
  417. // Also will be used to configure cache operations and the likes.
  418. //
  419. // Parameters
  420. // ----------
  421. // uConfigID - One of the values defined in WMI_FNLZR_CFG_TYPE
  422. // pConfigVal - Additional information needed
  423. // Return codes
  424. // ------------
  425. // WBEM_E_INVALID_OPERATION - try to do the same thing more than once, or
  426. // trying to change something already set up
  427. // WBEM_E_INVALID_PARAMETER - Configuration parameter we do not know about
  428. // was passed in
  429. // WBEM_NO_ERROR - Everything went well
  430. //
  431. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  432. STDMETHODIMP CWmiFinalizer::Configure(
  433. /*[in]*/ ULONG uConfigID,
  434. /*[in]*/ ULONG uValue
  435. )
  436. {
  437. switch (uConfigID)
  438. {
  439. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  440. // Do they want us to fast track?
  441. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  442. case WMI_FNLZR_FLAG_FAST_TRACK:
  443. {
  444. if (m_uForwardingType != forwarding_type_none)
  445. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::Configure called more than once!"), WBEM_E_INVALID_OPERATION);
  446. m_uForwardingType = forwarding_type_fast;
  447. break;
  448. }
  449. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  450. // Do they want us to decouple?
  451. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  452. case WMI_FNLZR_FLAG_DECOUPLED:
  453. {
  454. if (m_uForwardingType != forwarding_type_none)
  455. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::Configure called more than once!"), WBEM_E_INVALID_OPERATION);
  456. m_uForwardingType = forwarding_type_decoupled;
  457. DWORD dwThreadId = 0;
  458. break;
  459. }
  460. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  461. // Do they want us to do anything else? If so, assert
  462. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  463. default:
  464. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::Configure - invalid parameter uConfigID"), WBEM_E_INVALID_PARAMETER);
  465. }
  466. return WBEM_NO_ERROR;
  467. }
  468. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  469. //
  470. // CWmiFinalizer::SetTaskHandle
  471. // ----------------------------
  472. //
  473. // Task handle has user-specific stuff. Finalizer just
  474. // passes this through to _IWmiArbitrator::CheckTask. It should only ever
  475. // be called once
  476. //
  477. // Parameters
  478. // ----------
  479. // phTask - Pointer to the task handle
  480. // Return codes
  481. // ------------
  482. // WBEM_E_INVALID_OPERATION - try to do the same call more than once
  483. // WBEM_E_INVALID_PARAMETER - Passed in parameter is invalid
  484. // WBEM_NO_ERROR - Everything went well
  485. //
  486. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  487. STDMETHODIMP CWmiFinalizer::SetTaskHandle(
  488. _IWmiCoreHandle *phTask
  489. )
  490. {
  491. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  492. // Parameter validation
  493. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  494. if (m_phTask != NULL)
  495. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetTaskHandle - already have m_phTask"), WBEM_E_INVALID_OPERATION);
  496. if (phTask == NULL)
  497. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetTaskHandle - phTask == NULL"), WBEM_E_INVALID_PARAMETER);
  498. m_bTaskInitialized = TRUE ;
  499. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  500. // Assign the task and AddRef it
  501. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  502. {
  503. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  504. m_phTask = phTask;
  505. m_phTask->AddRef();
  506. }
  507. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  508. // Register the finalizer with the arbitrator
  509. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  510. {
  511. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  512. if (m_pArbitrator)
  513. {
  514. m_pArbitrator->RegisterArbitratee(0, m_phTask, this);
  515. }
  516. }
  517. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  518. // From the task, we can now see exactly what type of operation we are doing.
  519. // Get the operation type (SYNC/SEMISYNC/ASYNC) to avoid having to get it every time
  520. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  521. CWmiTask *pTsk = (CWmiTask *) m_phTask;
  522. ULONG ulTaskType = pTsk->GetTaskType();
  523. if ( (ulTaskType & WMICORE_TASK_TYPE_SYNC) )
  524. {
  525. m_ulOperationType = Operation_Type_Sync;
  526. }
  527. else if ( (ulTaskType & WMICORE_TASK_TYPE_SEMISYNC) )
  528. {
  529. m_ulOperationType = Operation_Type_Semisync;
  530. }
  531. else if ( (ulTaskType & WMICORE_TASK_TYPE_ASYNC) )
  532. {
  533. m_ulOperationType = Operation_Type_Async;
  534. }
  535. else
  536. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetTaskHandle - Invalid operation type"), WBEM_E_FAILED );
  537. return WBEM_NO_ERROR;
  538. }
  539. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  540. //
  541. // CWmiFinalizer::SetDestinationSink
  542. // ---------------------------------
  543. //
  544. // For async operations, therefore if the forwarding type is not set to
  545. // decoupled, this will fail. If there are any items outstanding,
  546. // this will also trigger them to be started
  547. //
  548. // Parameters
  549. // ----------
  550. // uFlags - unused
  551. //
  552. // pSink - pointer to the created destination sink
  553. //
  554. // Return codes
  555. // ------------
  556. // WBEM_E_INVALID_OPERATION - try to do the same call more than once
  557. // WBEM_E_INVALID_PARAMETER - Passed in parameter is invalid
  558. // WBEM_NO_ERROR - Everything went well
  559. //
  560. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  561. STDMETHODIMP CWmiFinalizer::SetDestinationSink(
  562. /*[in]*/ ULONG uFlags,
  563. /*[in]*/ REFIID riid,
  564. /*[in], iid_is(riid)]*/ LPVOID pVoid
  565. )
  566. {
  567. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  568. // Parameter validation
  569. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  570. if (m_pDestSink != NULL)
  571. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetDestinationSink - m_pDestSink != NULL"), WBEM_E_INVALID_OPERATION);
  572. if ((pVoid == NULL) || (uFlags != 0))
  573. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetDestinationSink - ((pSink == NULL) || (uFlags != 0))"), WBEM_E_INVALID_PARAMETER);
  574. if (m_uForwardingType == forwarding_type_none)
  575. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetDestinationSink - m_uForwardingType == forwarding_type_none"), WBEM_E_INVALID_OPERATION);
  576. if ((riid != IID_IWbemObjectSink) )
  577. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetDestinationSink - iid must be IID_IWbemObjectSink"), WBEM_E_INVALID_PARAMETER);
  578. HRESULT hr;
  579. IWbemObjectSink * pSink = (IWbemObjectSink *)pVoid;
  580. IWbemObjectSink * pSinkToStore = NULL;
  581. m_iidDestSink = IID_IWbemObjectSink;
  582. pSinkToStore = pSink;
  583. // Set the destination sink, AddRef it and set the impersonation level
  584. // to identity
  585. {
  586. CInCritSec lock(&m_destCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  587. m_pDestSink = pSinkToStore;
  588. m_pDestSink->AddRef(); // SEC:REVIEWED 2002-03-22 : Needs EH in case sink is garbage
  589. SetSinkToIdentity (m_pDestSink);
  590. }
  591. return WBEM_NO_ERROR;
  592. }
  593. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  594. // The callback called during final Release(); Set() is called with the
  595. // task handle, followed by SetStatus()
  596. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  597. STDMETHODIMP CWmiFinalizer::SetSelfDestructCallback(
  598. /*[in]*/ ULONG uFlags,
  599. /*[in]*/ IWbemObjectSink *pSink
  600. )
  601. {
  602. return E_NOTIMPL;
  603. }
  604. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  605. // STDMETHODIMP CWmiFinalizer::GetStatus(
  606. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  607. STDMETHODIMP CWmiFinalizer::GetStatus(
  608. ULONG *pFlags
  609. )
  610. {
  611. *pFlags = m_ulStatus;
  612. return WBEM_NO_ERROR;
  613. }
  614. //***************************************************************************
  615. //
  616. // CWmiFinalizer::NewInboundSink
  617. // -----------------------------
  618. //
  619. // Returns a sink to the caller. This sink is used to indicate result sets
  620. // back to the client.
  621. //
  622. // Parameters
  623. // ----------
  624. // uFlags - Additional flags. Currently 0 is only valid value.
  625. // pSink - Pointer to variable which will get the returned inbound sink.
  626. // It is this sink that allows the caller to send result sets.
  627. //
  628. // Return codes
  629. // ------------
  630. // WBEM_E_OUT_OF_MEMORY - Failed to create the finaliser sink because of an
  631. // out of memory situation
  632. // WBEM_E_INVALID_PARAMETER - Invalid parameters passed to method
  633. // WBEM_NO_ERROR - Everything completed successfully
  634. //***************************************************************************
  635. STDMETHODIMP CWmiFinalizer::NewInboundSink(
  636. /*[in]*/ ULONG uFlags,
  637. /*[out]*/ IWbemObjectSink **pSink
  638. )
  639. {
  640. if ((pSink == NULL) || (uFlags != 0))
  641. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::NewInboundSink - ((pSink == NULL) || (uFlags != 0))!"), WBEM_E_INVALID_PARAMETER);
  642. if (m_inboundSinks.Size())
  643. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::NewInboundSink - Multiple inbound sinks not yet implemented!!"), E_NOTIMPL);
  644. CWmiFinalizerInboundSink *pNewSink = new CWmiFinalizerInboundSink(this);
  645. if (pNewSink == NULL)
  646. return WBEM_E_OUT_OF_MEMORY;
  647. pNewSink->AddRef(); // Required to return a positive ref count on a new object // SEC:REVIEWED 2002-03-22 : OK
  648. CInCritSec autoLock(&m_cs); // SEC:REVIEWED 2002-03-22 : Assumes entry
  649. int nRet = m_inboundSinks.Add(pNewSink);
  650. if (nRet != CFlexArray::no_error)
  651. {
  652. pNewSink->Release();
  653. return WBEM_E_OUT_OF_MEMORY;
  654. }
  655. else
  656. {
  657. pNewSink->InternalAddRef();
  658. }
  659. *pSink = pNewSink; // SEC:REVIEWED 2002-03-22 : Should be in EH if case memory is not valid
  660. return WBEM_NO_ERROR;
  661. }
  662. //***************************************************************************
  663. //
  664. // Allows merging another Finalizer, _IWmiCache, etc.
  665. // For sorting, we will create a sorted _IWmiCache and merge it in later when
  666. // the sort is completed.
  667. //
  668. //***************************************************************************
  669. STDMETHODIMP CWmiFinalizer::Merge(
  670. /*[in]*/ ULONG uFlags,
  671. /*[in]*/ REFIID riid,
  672. /*[in]*/ LPVOID pObj
  673. )
  674. {
  675. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::Merge - Not implemented!"), E_NOTIMPL);
  676. }
  677. // For setting, getting objects
  678. //***************************************************************************
  679. //
  680. //***************************************************************************
  681. STDMETHODIMP CWmiFinalizer::SetResultObject(
  682. /*[in]*/ ULONG uFlags,
  683. /*[in]*/ REFIID riid,
  684. /*[in]*/ LPVOID pObj
  685. )
  686. {
  687. //No one is calling this! All objects are getting in through a call to Indicate,
  688. //or Set, which are both just forwards from the InboundSink we pass out.
  689. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::Merge - Not implemented!"), E_NOTIMPL);
  690. }
  691. //***************************************************************************
  692. //
  693. // Support _IWmiObject, IWbemClassObject, etc.
  694. // IEnumWbemClassObject
  695. // _IWmiCache
  696. //
  697. //***************************************************************************
  698. STDMETHODIMP CWmiFinalizer::GetResultObject(
  699. /*[in]*/ ULONG uFlags,
  700. /*[in]*/ REFIID riid,
  701. /*[out, iid_is(riid)]*/ LPVOID *ppObj
  702. )
  703. {
  704. // uFlags can be non-zero iff the requested interface is an enumerator
  705. if (uFlags != 0 && riid != IID_IEnumWbemClassObject)
  706. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::GetResultObject - uFlags != 0, non enum interface!"), WBEM_E_INVALID_PARAMETER);
  707. if (riid == IID_IEnumWbemClassObject)
  708. {
  709. //If forward-only is set we should not let the result set be restartable.
  710. if (!(uFlags & WBEM_FLAG_FORWARD_ONLY))
  711. m_bRestartable = true;
  712. //m_uDeliveryType = delivery_type_pull;
  713. CWmiFinalizerEnumerator* pEnum = NULL ;
  714. try
  715. {
  716. //
  717. // I'm using the uFlags as a means of passing the current object position
  718. //
  719. pEnum = new CWmiFinalizerEnumerator(this);
  720. }
  721. catch (...) // status_no_memory
  722. {
  723. ExceptionCounter c;
  724. }
  725. if (pEnum == NULL)
  726. return WBEM_E_OUT_OF_MEMORY;
  727. else
  728. pEnum->InternalAddRef();
  729. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  730. // Make sure nasty client does not crash us
  731. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  732. try
  733. {
  734. *ppObj = pEnum;
  735. }
  736. catch (...) // ppObj is an untrusted param
  737. {
  738. ExceptionCounter c;
  739. pEnum->InternalRelease();
  740. return WBEM_E_INVALID_PARAMETER;
  741. }
  742. {
  743. CInCritSec lock( &m_cs ) ; // SEC:REVIEWED 2002-03-22 : Assumes entry
  744. //
  745. // Lets add the enumerator to the list of enumerators
  746. // associated with this finalizer.
  747. //
  748. int nRet = m_enumerators.Add ( pEnum ) ;
  749. if ( nRet != CFlexArray::no_error )
  750. {
  751. pEnum->InternalRelease ( ) ;
  752. return WBEM_E_OUT_OF_MEMORY;
  753. }
  754. }
  755. pEnum->AddRef();
  756. return WBEM_NO_ERROR;
  757. }
  758. //Get the next object we have cached.
  759. if ((riid == IID_IWbemClassObject) || (riid == IID__IWmiObject))
  760. {
  761. if (m_pDestSink != NULL)
  762. {
  763. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::GetResultObject - Cannot get an object when there is a destination sink!"), WBEM_E_INVALID_OPERATION);
  764. }
  765. if (m_bSetStatusConsumed)
  766. return WBEM_E_NOT_FOUND;
  767. CWmiFinalizerObj *pFinalizerObj = NULL;
  768. bool bFinished = false;
  769. HRESULT hRes = WBEM_E_NOT_FOUND;
  770. while (!bFinished)
  771. {
  772. hRes = GetNextObject(&pFinalizerObj);
  773. if (FAILED(hRes))
  774. return hRes;
  775. else if (hRes == WBEM_S_FALSE)
  776. return WBEM_E_NOT_FOUND;
  777. if (pFinalizerObj->m_objectType == CWmiFinalizerObj::object)
  778. {
  779. if (ppObj)
  780. {
  781. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  782. // Make sure nasty client does not crash us
  783. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  784. try
  785. {
  786. *ppObj = pFinalizerObj->m_pObj;
  787. }
  788. catch (...) // untrusted param
  789. {
  790. ExceptionCounter c;
  791. return WBEM_E_INVALID_PARAMETER;
  792. }
  793. if (pFinalizerObj->m_pObj)
  794. pFinalizerObj->m_pObj->AddRef();
  795. }
  796. bFinished = true;
  797. }
  798. else if ((pFinalizerObj->m_objectType == CWmiFinalizerObj::status) && (pFinalizerObj->m_lFlags == WBEM_STATUS_COMPLETE))
  799. {
  800. m_bSetStatusConsumed = true;
  801. hRes = WBEM_E_NOT_FOUND;
  802. bFinished = true;
  803. }
  804. else if (pFinalizerObj->m_objectType == CWmiFinalizerObj::status)
  805. {
  806. //This is a non-completion status message! We most certainly have not finished yet!
  807. }
  808. delete pFinalizerObj;
  809. }
  810. return hRes;
  811. }
  812. if ((riid == IID_IWbemCallResult) )
  813. {
  814. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  815. // Make sure nasty client does not crash us
  816. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  817. try
  818. {
  819. m_pCallResult->AddRef();
  820. *ppObj = m_pCallResult;
  821. }
  822. catch (...) // untrusted param
  823. {
  824. ExceptionCounter c;
  825. m_pCallResult->Release ();
  826. return WBEM_E_INVALID_PARAMETER;
  827. }
  828. return WBEM_S_NO_ERROR;
  829. }
  830. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::GetResultObject - Unknown object IID requested!"), WBEM_E_INVALID_PARAMETER);
  831. }
  832. // For status-only operations
  833. //***************************************************************************
  834. //
  835. //***************************************************************************
  836. STDMETHODIMP CWmiFinalizer::SetOperationResult(
  837. /*[in]*/ ULONG uFlags,
  838. /*[in]*/ HRESULT hRes
  839. )
  840. {
  841. if (uFlags != 0)
  842. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::SetOperationResult - uFlags != 0!"), WBEM_E_INVALID_PARAMETER);
  843. if ( m_hresFinalResult != -1 )
  844. {
  845. if ( hRes != WBEM_E_CALL_CANCELLED )
  846. {
  847. return WBEM_S_NO_ERROR ;
  848. }
  849. }
  850. if ( hRes == WBEM_E_CALL_CANCELLED_CLIENT )
  851. {
  852. m_hresFinalResult = hRes = WBEM_E_CALL_CANCELLED ;
  853. }
  854. else if ( hRes != WBEM_E_CALL_CANCELLED )
  855. {
  856. m_hresFinalResult = hRes ;
  857. }
  858. HRESULT hResCancel = WBEM_NO_ERROR ;
  859. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  860. // Special case for cancellations. Iff its an async operation. Otherwise,
  861. // we might mess up for sync/semi sync
  862. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  863. if ( ( hRes == WBEM_E_CALL_CANCELLED ) && ( m_ulOperationType == Operation_Type_Async ) )
  864. {
  865. hResCancel = CancelCall(__LINE__);
  866. }
  867. SetEvent(m_hResultReceived);
  868. return hResCancel ;
  869. }
  870. //***************************************************************************
  871. //
  872. //***************************************************************************
  873. STDMETHODIMP CWmiFinalizer::GetOperationResult(
  874. /*[in]*/ ULONG uFlags,
  875. /*[in]*/ ULONG uTimeout,
  876. /*[out]*/ HRESULT *phRes
  877. )
  878. {
  879. if (uFlags != 0)
  880. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::GetOperationResult - uFlags != 0!"), WBEM_E_INVALID_PARAMETER);
  881. HRESULT hr = WaitForCompletion(uTimeout);
  882. if (hr == WBEM_S_NO_ERROR)
  883. {
  884. *phRes = m_hresFinalResult; // SEC:REVIEWED 2002-03-22 : Needs EH
  885. if ( FAILED ( m_hresFinalResult ) )
  886. {
  887. m_pCallResult->SetErrorInfo ( ); // SEC:REVIEWED 2002-03-22 : Needs EH
  888. }
  889. CancelTaskInternal();
  890. m_hStatus = NoError;
  891. }
  892. return hr;
  893. }
  894. //***************************************************************************
  895. // STDMETHODIMP CWmiFinalizer::CancelTask(
  896. //***************************************************************************
  897. STDMETHODIMP CWmiFinalizer::CancelTask(
  898. /*[in]*/ ULONG uFlags
  899. )
  900. {
  901. if (uFlags != 0)
  902. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::CancelTask - uFlags != 0!"), WBEM_E_INVALID_PARAMETER);
  903. return CancelTaskInternal ( );
  904. }
  905. //***************************************************************************
  906. //
  907. //***************************************************************************
  908. HRESULT CWmiFinalizer::WaitForCompletion(ULONG uTimeout)
  909. {
  910. DWORD dwRet = CCoreQueue :: QueueWaitForSingleObject(m_hResultReceived, uTimeout);
  911. if (dwRet == WAIT_OBJECT_0)
  912. {
  913. return WBEM_S_NO_ERROR;
  914. }
  915. else if ((dwRet == WAIT_FAILED) ||
  916. (dwRet == WAIT_ABANDONED))
  917. {
  918. return WBEM_E_FAILED;
  919. }
  920. else
  921. {
  922. return WBEM_S_TIMEDOUT;
  923. }
  924. }
  925. //***************************************************************************
  926. //
  927. //***************************************************************************
  928. HRESULT CWmiFinalizer::Reset(
  929. )
  930. {
  931. if (m_bRestartable)
  932. {
  933. /*m_uCurObjectPosition = 0;
  934. m_bSetStatusConsumed = false;*/
  935. return WBEM_NO_ERROR;
  936. }
  937. else
  938. return WBEM_E_INVALID_OPERATION;
  939. }
  940. //***************************************************************************
  941. //
  942. //***************************************************************************
  943. IWbemObjectSink* CWmiFinalizer::ReturnProtectedDestinationSink ( )
  944. {
  945. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  946. // Do we have a valid object sink?
  947. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  948. IWbemObjectSink* pTmp = NULL;
  949. {
  950. CInCritSec lock(&m_destCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  951. if ( m_pDestSink==NULL )
  952. {
  953. return NULL;
  954. }
  955. else
  956. {
  957. pTmp = m_pDestSink;
  958. pTmp->AddRef(); // SEC:REVIEWED 2002-03-22 : Needs EH in case sink is garbage
  959. }
  960. }
  961. return pTmp;
  962. }
  963. //***************************************************************************
  964. //
  965. //***************************************************************************
  966. DWORD WINAPI CWmiFinalizer::ThreadBootstrap( PVOID pParam )
  967. {
  968. // char buff[100];
  969. // sprintf(buff, "thread this pointer = 0x%p\n", pParam);
  970. // OutputDebugString(buff);
  971. return ((CWmiFinalizer*)pParam)->AsyncDeliveryProcessor();
  972. }
  973. //***************************************************************************
  974. //
  975. //***************************************************************************
  976. HRESULT CWmiFinalizer::BootstrapDeliveryThread ( )
  977. {
  978. BOOL bRes;
  979. HRESULT hRes = WBEM_S_NO_ERROR;
  980. AddRef(); // Need to AddRef Finalizer for the delivery thread
  981. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  982. // Native Win2k thread dispatching
  983. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  984. bRes = QueueUserWorkItem ( ThreadBootstrap, this, WT_EXECUTEDEFAULT );
  985. if ( !bRes )
  986. {
  987. Release ();
  988. hRes = WBEM_E_FAILED;
  989. }
  990. return hRes;
  991. }
  992. //***************************************************************************
  993. //
  994. //***************************************************************************
  995. ULONG CWmiFinalizer::AsyncDeliveryProcessor()
  996. {
  997. HRESULT hRes = WBEM_S_NO_ERROR;
  998. BOOL bKeepDelivering = TRUE;
  999. m_enumBatchStatus = FinalizerBatch_NoError;
  1000. RevertToSelf ( ); // SEC:REVIEWED 2002-03-22 : Needs check
  1001. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1002. // First we tell the arbitrator about the delivery thread
  1003. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1004. {
  1005. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1006. if (m_pArbitrator)
  1007. {
  1008. hRes = m_pArbitrator->RegisterThreadForTask(m_phTask);
  1009. if (hRes == WBEM_E_QUOTA_VIOLATION)
  1010. {
  1011. //TODO: WHAT HAPPENS HERE?
  1012. }
  1013. }
  1014. }
  1015. while ( bKeepDelivering )
  1016. {
  1017. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1018. // First off, have we been cancelled?
  1019. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1020. if ( m_bCancelledCall )
  1021. {
  1022. DeliverSingleObjFromQueue ( );
  1023. bKeepDelivering = FALSE;
  1024. continue;
  1025. }
  1026. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1027. // Next, we build the transmit buffer
  1028. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1029. hRes = BuildTransmitBuffer ( );
  1030. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1031. // BuildTransmitBuffer will return WBEM_S_FALSE if the batch immediately hit a
  1032. // status message.
  1033. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1034. if ( hRes != WBEM_E_FAILED )
  1035. {
  1036. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1037. // Next, deliver the batch of objects
  1038. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1039. DeliverBatch ( );
  1040. }
  1041. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1042. // If we have a status message to deliver do so now
  1043. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1044. if ( m_enumBatchStatus == FinalizerBatch_StatusMsg )
  1045. {
  1046. DeliverSingleObjFromQueue ( );
  1047. }
  1048. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1049. // If we have a status complete message we should keep building the batch and
  1050. // delivering until done
  1051. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1052. if ( m_bSetStatusEnqueued && m_objects.Size() )
  1053. continue;
  1054. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1055. // We could have another batch to deliver by now. Check
  1056. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1057. else if ( m_ulQueueSize < g_ulMaxBatchSize )
  1058. bKeepDelivering = FALSE;
  1059. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1060. // Make sure we're properly synchronized with the inbound threads
  1061. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1062. CInCritSec cs(&m_cs); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1063. {
  1064. if ( !m_bSetStatusEnqueued )
  1065. {
  1066. bKeepDelivering = FALSE;
  1067. m_lCurrentlyDelivering = FALSE;
  1068. }
  1069. else
  1070. {
  1071. bKeepDelivering = TRUE;
  1072. }
  1073. }
  1074. }
  1075. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1076. // Tell the arbitrator that the thread is done
  1077. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1078. {
  1079. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1080. if (m_pArbitrator)
  1081. {
  1082. m_pArbitrator->UnregisterThreadForTask(m_phTask); // Since thread is going away, tell arbitrator about this
  1083. }
  1084. }
  1085. Release();
  1086. return 0;
  1087. }
  1088. //***************************************************************************
  1089. //
  1090. //***************************************************************************
  1091. HRESULT CWmiFinalizer::GetNextObject(CWmiFinalizerObj **ppObj)
  1092. {
  1093. if (m_uCurObjectPosition >= (ULONG)m_objects.Size())
  1094. return WBEM_S_FALSE;
  1095. CInCritSec cs(&m_cs); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1096. CWmiFinalizerObj *pStorageObject = (CWmiFinalizerObj*)m_objects[m_uCurObjectPosition];
  1097. if (m_bRestartable)
  1098. {
  1099. //We have to hold on to results, so increment cursor position...
  1100. m_uCurObjectPosition++;
  1101. *ppObj = new CWmiFinalizerObj(*pStorageObject); // SEC:REVIEWED 2002-03-22 : Needs EH and NULL test
  1102. if (*ppObj == NULL)
  1103. return WBEM_E_OUT_OF_MEMORY;
  1104. //ReportMemoryUsage ( 0, (*ppObj)->m_uSize ) ;
  1105. }
  1106. else
  1107. {
  1108. //We are not restartable, therefore we need to release everything...
  1109. m_objects.RemoveAt(0);
  1110. *ppObj = pStorageObject; // SEC:REVIEWED 2002-03-22 : Needs EH and NULL test
  1111. //ADDBACK: ReportMemoryUsage ( 0, -((*ppObj)->m_uSize) ) ;
  1112. // printf("Returning object 0x%p from object list\n", pStorageObject);
  1113. }
  1114. return WBEM_NO_ERROR;
  1115. }
  1116. //***************************************************************************
  1117. //
  1118. //***************************************************************************
  1119. HRESULT CWmiFinalizer::UnregisterInboundSink(CWmiFinalizerInboundSink *pSink)
  1120. {
  1121. // Use m_cs lock for this
  1122. CInCritSec lock(&m_cs); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1123. for (int i = 0; i != m_inboundSinks.Size(); i++)
  1124. {
  1125. if (m_inboundSinks[i] == pSink)
  1126. {
  1127. pSink->InternalRelease () ; // SEC:REVIEWED 2002-03-22 : Could use an EH for safety
  1128. m_inboundSinks.RemoveAt(i);
  1129. if (m_inboundSinks.Size() == 0)
  1130. TriggerShutdown();
  1131. return WBEM_NO_ERROR;
  1132. }
  1133. }
  1134. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::UnregisterInboundSink - Unregistering Inbound Sink that we could not find!"), WBEM_E_NOT_FOUND);
  1135. }
  1136. //***************************************************************************
  1137. //
  1138. //***************************************************************************
  1139. HRESULT CWmiFinalizer::Indicate(
  1140. /*[in]*/ long lObjectCount,
  1141. /*[in, size_is(lObjectCount)]*/
  1142. IWbemClassObject** apObjArray
  1143. )
  1144. {
  1145. HRESULT hRes = WBEM_S_NO_ERROR;
  1146. if ( m_bCancelledCall )
  1147. {
  1148. return WBEM_E_CALL_CANCELLED;
  1149. }
  1150. {
  1151. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1152. if ( m_bSetStatusCalled )
  1153. {
  1154. return WBEM_E_INVALID_OPERATION;
  1155. }
  1156. }
  1157. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1158. // First check the array for NULL objects. Return INVALID_OBJECT if
  1159. // array contains a NULL object
  1160. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1161. for (long x = 0; x != lObjectCount; x++)
  1162. {
  1163. if ( apObjArray[x] == NULL ) // SEC:REVIEWED 2002-03-22 : Needs EH
  1164. return WBEM_E_INVALID_OBJECT;
  1165. }
  1166. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1167. // Are we fast tracking and async request?
  1168. // ESS brutally tells us to deliver on the
  1169. // same thread and do no batching
  1170. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1171. if ( (m_uForwardingType == forwarding_type_fast) && (m_ulOperationType == Operation_Type_Async))
  1172. {
  1173. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink ( );
  1174. if ( !pTmp )
  1175. {
  1176. return WBEM_E_FAILED;
  1177. }
  1178. CReleaseMe myReleaseMe(pTmp);
  1179. hRes = DoIndicate ( pTmp, lObjectCount, apObjArray ); // SEC:REVIEWED 2002-03-22 : Needs EH in case <apObjArray> is garbage
  1180. // Client can also tell us to cancel a call by returning WBEM_E_CALL_CANCELLED from Indicate
  1181. // We also want to cancel the call if the client is taking way too long to return
  1182. if ( FAILED (hRes) || m_bCancelledCall == TRUE || m_bNaughtyClient == TRUE )
  1183. {
  1184. if ( hRes == WBEM_E_CALL_CANCELLED || m_bCancelledCall )
  1185. {
  1186. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_CALL_CANCELLED, 0, 0 );
  1187. }
  1188. else
  1189. {
  1190. DoSetStatusCancel ( pTmp, hRes );
  1191. }
  1192. hRes = WBEM_E_CALL_CANCELLED;
  1193. myReleaseMe.release ( ) ;
  1194. ReleaseDestinationSink ( ) ;
  1195. CancelCall(__LINE__);
  1196. }
  1197. }
  1198. else
  1199. {
  1200. for (long lIndex = 0; lIndex != lObjectCount; lIndex++)
  1201. {
  1202. if ( apObjArray[lIndex] ) // SEC:REVIEWED 2002-03-22 : Needs EH
  1203. {
  1204. CWmiFinalizerObj *pFinalizerObj = new CWmiFinalizerObj(apObjArray[lIndex], this); // SEC:REVIEWED 2002-03-22 : Needs EH
  1205. if (pFinalizerObj == NULL) return WBEM_E_OUT_OF_MEMORY;
  1206. HRESULT hr = QueueOperation(pFinalizerObj);
  1207. if (FAILED(hr)) return hr; // queue will always destroy pFinalizerObj
  1208. }
  1209. }
  1210. }
  1211. return hRes;
  1212. }
  1213. //***************************************************************************
  1214. //
  1215. //***************************************************************************
  1216. HRESULT CWmiFinalizer::Set(
  1217. /*[in]*/ long lFlags,
  1218. /*[in]*/ REFIID riid,
  1219. /*[in, iid_is(riid)]*/ void *pComObject
  1220. )
  1221. {
  1222. CWmiFinalizerObj *pFinalizerObj = new CWmiFinalizerObj(lFlags, riid, pComObject); // SEC:REVIEWED 2002-03-22 : Needs EH
  1223. if (pFinalizerObj == NULL) return WBEM_E_OUT_OF_MEMORY;
  1224. return QueueOperation(pFinalizerObj);
  1225. }
  1226. //***************************************************************************
  1227. //
  1228. //***************************************************************************
  1229. HRESULT CWmiFinalizer::SetStatus(
  1230. /*[in]*/ long lFlags,
  1231. /*[in]*/ HRESULT hResult,
  1232. /*[in]*/ BSTR strParam,
  1233. /*[in]*/ IWbemClassObject* pObjParam
  1234. )
  1235. {
  1236. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1237. // If the operation has been cancelled, we should not accept another call
  1238. // WBEM_E_CALL_CANCELLED
  1239. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1240. if ( m_bCancelledCall )
  1241. {
  1242. return WBEM_E_CALL_CANCELLED;
  1243. }
  1244. {
  1245. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1246. if ( m_bSetStatusCalled && ( lFlags == WBEM_STATUS_COMPLETE ) )
  1247. {
  1248. return WBEM_E_INVALID_OPERATION;
  1249. }
  1250. else if ( lFlags == WBEM_STATUS_COMPLETE )
  1251. {
  1252. m_bSetStatusCalled = true ;
  1253. }
  1254. }
  1255. //If this is a final call, we need to record it.
  1256. if (lFlags == WBEM_STATUS_COMPLETE )
  1257. {
  1258. m_pCallResult->SetStatus(lFlags, hResult, strParam, pObjParam);
  1259. }
  1260. // Special case for cancellations
  1261. if ( hResult == WBEM_E_CALL_CANCELLED )
  1262. {
  1263. HRESULT hr = CancelCall(__LINE__);
  1264. SetEvent(m_hResultReceived);
  1265. return hr;
  1266. }
  1267. HRESULT ourhres = WBEM_E_FAILED;
  1268. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1269. // Once again, we have to special case ESS
  1270. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1271. if ( (m_uForwardingType == forwarding_type_fast) &&
  1272. (m_ulOperationType == Operation_Type_Async) )
  1273. {
  1274. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1275. // Do we have a valid object sink?
  1276. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1277. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink();
  1278. CReleaseMe myReleaseMe(pTmp);
  1279. if ( pTmp )
  1280. {
  1281. ourhres = DoSetStatus ( pTmp, lFlags, hResult, strParam, pObjParam );
  1282. if (lFlags == WBEM_STATUS_COMPLETE ||
  1283. FAILED ( ourhres ) ||
  1284. m_bCancelledCall == TRUE ||
  1285. m_bNaughtyClient == TRUE )
  1286. {
  1287. NotifyAllEnumeratorsOfCompletion ( ) ;
  1288. SetOperationResult(0, hResult);
  1289. {
  1290. CInCritSec lock(&m_destCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1291. if ( m_pDestSink )
  1292. {
  1293. ReleaseDestinationSink ( ) ;
  1294. m_bSetStatusConsumed = true;
  1295. UpdateStatus ( WMI_FNLZR_STATE_CLIENT_COMPLETE );
  1296. }
  1297. }
  1298. CancelTaskInternal ( );
  1299. if ( FAILED ( ourhres ) || m_bCancelledCall == TRUE || m_bNaughtyClient == TRUE )
  1300. {
  1301. ourhres = WBEM_E_CALL_CANCELLED ;
  1302. }
  1303. }
  1304. }
  1305. }
  1306. else
  1307. {
  1308. //Send the request to the user...
  1309. // ObjectType::status
  1310. CWmiFinalizerObj *pObj = new CWmiFinalizerObj(lFlags, hResult, strParam, pObjParam); // SEC:REVIEWED 2002-03-22 : Needs EH
  1311. if (pObj == NULL)
  1312. {
  1313. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink();
  1314. CReleaseMe myReleaseMe(pTmp);
  1315. if ( pTmp )
  1316. {
  1317. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_OUT_OF_MEMORY, 0, 0 ) ;
  1318. }
  1319. SetOperationResult(0,WBEM_E_OUT_OF_MEMORY);
  1320. m_hStatus = QueueFailure;
  1321. NotifyAllEnumeratorsOfCompletion();
  1322. return WBEM_E_OUT_OF_MEMORY;
  1323. }
  1324. ourhres = QueueOperation(pObj);
  1325. if (lFlags == WBEM_STATUS_COMPLETE)
  1326. {
  1327. SetOperationResult(0, hResult);
  1328. //QueueFailure is set internally in the QueueOperation
  1329. NotifyAllEnumeratorsOfCompletion ( ) ;
  1330. //
  1331. // Lock the task
  1332. //
  1333. CWmiTask* pTask = NULL ;
  1334. {
  1335. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1336. if ( m_phTask )
  1337. {
  1338. pTask = (CWmiTask*) m_phTask ;
  1339. pTask->AddRef ( ) ;
  1340. }
  1341. }
  1342. CReleaseMe _r ( pTask ) ;
  1343. if ( pTask )
  1344. {
  1345. pTask->SetTaskResult ( hResult ) ;
  1346. }
  1347. ((CWmiArbitrator*) m_pArbitrator)->UnregisterTaskForEntryThrottling ( (CWmiTask*) m_phTask ) ;
  1348. }
  1349. }
  1350. return ourhres;
  1351. }
  1352. //***************************************************************************
  1353. //
  1354. //***************************************************************************
  1355. HRESULT CWmiFinalizer::QueueOperation(CWmiFinalizerObj *pObj)
  1356. {
  1357. LONG lDelta = 0;
  1358. HRESULT hRes = WBEM_S_NO_ERROR;
  1359. CCheckedInCritSec cs ( &m_cs ) ; // SEC:REVIEWED 2002-03-22 : Assumes entry
  1360. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1361. // Update total object size
  1362. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1363. if (pObj->m_objectType == CWmiFinalizerObj::object)
  1364. {
  1365. CWbemObject* pObjTmp = (CWbemObject*) pObj -> m_pObj;
  1366. m_ulQueueSize += pObjTmp -> GetBlockLength();
  1367. }
  1368. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1369. // If we get a WBEM_E_CALL_CANCELLED status message, prioritize
  1370. // the handling of this. Needed for fast shutdown.
  1371. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1372. if ( (pObj->m_objectType == CWmiFinalizerObj::status) && FAILED (pObj->m_hRes) )
  1373. {
  1374. m_bSetStatusWithError = TRUE ;
  1375. if (CFlexArray::no_error != m_objects.InsertAt ( 0, pObj ))
  1376. {
  1377. delete pObj;
  1378. m_hStatus = QueueFailure;
  1379. return WBEM_E_OUT_OF_MEMORY;
  1380. }
  1381. }
  1382. else
  1383. {
  1384. // Normal Add object to queue
  1385. if (CFlexArray::no_error != m_objects.Add(pObj))
  1386. {
  1387. delete pObj;
  1388. m_hStatus = QueueFailure;
  1389. return WBEM_E_OUT_OF_MEMORY;
  1390. }
  1391. }
  1392. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1393. // First we check with the arbitrator what it tells us about
  1394. // current limits. Make sure we call ReportMemoryUsage since
  1395. // we're only interested in what it would potentially have done.
  1396. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1397. HRESULT hArb = WBEM_S_ARB_NOTHROTTLING;
  1398. lDelta = pObj->m_uSize;
  1399. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1400. // Are we decoupled, if so we need to analyze the current batch
  1401. // and make decisions on delivery. Need to once again special case ESS.
  1402. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1403. if ( m_uForwardingType == forwarding_type_decoupled ||
  1404. ( m_uForwardingType == forwarding_type_fast &&
  1405. m_ulOperationType == Operation_Type_Async ) )
  1406. {
  1407. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1408. // What did the arbitrator tell us about our situation?
  1409. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1410. if ( pObj->m_hArb != WBEM_S_ARB_NOTHROTTLING )
  1411. {
  1412. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1413. // Arbitrator told us that we either were about to be
  1414. // cancelled or throttled. Flush our delivery buffers
  1415. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1416. if ( m_lCurrentlyDelivering == FALSE || m_lCurrentlyCancelling == TRUE )
  1417. {
  1418. m_lCurrentlyDelivering = TRUE;
  1419. BootstrapDeliveryThread( ); // Kick of the delivery thread since we're decoupled
  1420. }
  1421. cs.Leave ( ) ;
  1422. hArb = m_pArbitrator->Throttle ( 0, m_phTask );
  1423. if ( hArb == WBEM_E_ARB_CANCEL )
  1424. {
  1425. CancelCall( __LINE__);
  1426. }
  1427. }
  1428. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1429. // If we are decoupled and get a Status message we should deliver
  1430. // the batch and set the status
  1431. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1432. else if ( (pObj->m_objectType == CWmiFinalizerObj::status) )
  1433. {
  1434. if ( pObj->m_lFlags == WBEM_STATUS_COMPLETE )
  1435. {
  1436. m_bSetStatusEnqueued = TRUE;
  1437. }
  1438. if ( m_lCurrentlyDelivering == FALSE || m_lCurrentlyCancelling == TRUE )
  1439. {
  1440. m_lCurrentlyDelivering = TRUE;
  1441. BootstrapDeliveryThread ( ); // Kick of the delivery thread since we're decoupled
  1442. }
  1443. }
  1444. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1445. // Delivery needs to be decoupled
  1446. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1447. else if ( (m_ulQueueSize > g_ulMaxBatchSize) )
  1448. {
  1449. if ( m_lCurrentlyDelivering == FALSE )
  1450. {
  1451. m_lCurrentlyDelivering = TRUE;
  1452. BootstrapDeliveryThread ( ); // Kick of the delivery thread since we're decoupled
  1453. }
  1454. }
  1455. }
  1456. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1457. // Otherwise, we wake up any potential clients waiting in
  1458. // PullObjects
  1459. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1460. else if ( m_uForwardingType == forwarding_type_fast )
  1461. {
  1462. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1463. // We dont want to wake up the client unless we have the
  1464. // number of objects he/she requested OR a setstatus has
  1465. // come through [CWmiFinalizer::SetStatus]
  1466. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1467. if ( (pObj->m_objectType == CWmiFinalizerObj::object) )
  1468. {
  1469. for ( int i = 0; i < m_enumerators.Size ( ); i++ )
  1470. {
  1471. CWmiFinalizerEnumerator* pEnum = (CWmiFinalizerEnumerator*) m_enumerators[i] ;
  1472. if ( ( pEnum->m_ulSemisyncWakeupCall != 0 ) && ( m_objects.Size() >= ( pEnum->m_ulSemisyncWakeupCall + pEnum->m_uCurObjectPosition ) ) )
  1473. {
  1474. SetEvent ( pEnum->m_hWaitOnResultSet );
  1475. pEnum->m_ulSemisyncWakeupCall = 0;
  1476. }
  1477. }
  1478. }
  1479. else if ( (pObj->m_objectType == CWmiFinalizerObj::status) )
  1480. {
  1481. NotifyAllEnumeratorsOfCompletion ( ) ;
  1482. }
  1483. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1484. // Now, lets throttle this thread since we have no control
  1485. // of outbound flow
  1486. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1487. cs.Leave ( ) ;
  1488. HRESULT hArb = m_pArbitrator->Throttle ( 0, m_phTask );
  1489. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1490. // If the arbitrator returned CANCEL, we operation has been
  1491. // cancelled and we need to stop:
  1492. // 1. Threads potentially waiting in the enumerator
  1493. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1494. if ( hArb == WBEM_E_ARB_CANCEL )
  1495. {
  1496. cs.Leave ( ) ;
  1497. CancelTaskInternal ( );
  1498. cs.Enter ( ) ;
  1499. m_hStatus = QuotaViolation;
  1500. NotifyAllEnumeratorsOfCompletion ( ) ;
  1501. hRes = WBEM_E_QUOTA_VIOLATION;
  1502. }
  1503. }
  1504. return hRes;
  1505. }
  1506. //***************************************************************************
  1507. //
  1508. //***************************************************************************
  1509. HRESULT CWmiFinalizer::TriggerShutdown()
  1510. {
  1511. if (m_uForwardingType == forwarding_type_decoupled)
  1512. {
  1513. //We need to queue up a shutdown request to the thread...
  1514. CWmiFinalizerObj *pObj = new CWmiFinalizerObj(CWmiFinalizerObj::shutdown); // SEC:REVIEWED 2002-03-22 : Needs EH
  1515. if (pObj == NULL) return WBEM_E_OUT_OF_MEMORY;
  1516. return QueueOperation(pObj);
  1517. }
  1518. else
  1519. ShutdownFinalizer();
  1520. return WBEM_NO_ERROR;
  1521. }
  1522. //***************************************************************************
  1523. //
  1524. //***************************************************************************
  1525. HRESULT CWmiFinalizer::ShutdownFinalizer()
  1526. {
  1527. return WBEM_NO_ERROR;
  1528. }
  1529. //****************************************************************************
  1530. // BuildTransmitBuffer ( )
  1531. // ~~~~~~~~~~~~~~~~~~~~~~~
  1532. //
  1533. // Works in two phases.
  1534. //
  1535. // 1. Quickly scans the object queue to get a count of the number of objects
  1536. // 2. Actually dequeueus the objects and builds the buffer
  1537. //
  1538. //****************************************************************************
  1539. HRESULT CWmiFinalizer::BuildTransmitBuffer ( )
  1540. {
  1541. HRESULT hRes = WBEM_NO_ERROR;
  1542. ULONG nBatchSize = 0;
  1543. ULONG nBatchBytes = 0;
  1544. ULONG nTempAdd = 0;
  1545. m_ulAsyncDeliveryCount = 0;
  1546. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1547. // Lock the object queue while building the transmit buffer
  1548. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1549. CInCritSec cs(&m_cs); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1550. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1551. // PHASE 1
  1552. // -------
  1553. // Quickly scan through the object queue to get an object count
  1554. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1555. bool bBuildingBuffer = true;
  1556. while ( bBuildingBuffer && nTempAdd < m_objects.Size() )
  1557. {
  1558. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1559. // First, we peek at the object. Dont want to dequeue anything that is not
  1560. // deliverable in this batch
  1561. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1562. CWmiFinalizerObj *pFinObj;
  1563. pFinObj = (CWmiFinalizerObj*) m_objects[m_uCurObjectPosition + nTempAdd];
  1564. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1565. // If we get a NULL pointer back we should stop the batch count
  1566. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1567. if ( pFinObj == NULL )
  1568. {
  1569. bBuildingBuffer = false;
  1570. m_enumBatchStatus = FinalizerBatch_NoError;
  1571. break;
  1572. }
  1573. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1574. // Anything else BUT an object will break the batch count
  1575. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1576. if ( pFinObj->m_objectType != CWmiFinalizerObj::object )
  1577. {
  1578. m_enumBatchStatus = FinalizerBatch_StatusMsg;
  1579. break;
  1580. }
  1581. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1582. // If we have a NULL IWbemClassObject we should stop the batch count.
  1583. // Actaully we should yell very loudly!
  1584. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1585. CWbemObject* pObj = (CWbemObject*) pFinObj->m_pObj;
  1586. if ( pObj==NULL )
  1587. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::BuildTransmitBuffer: Queue contains NULL object!"), WBEM_E_INVALID_OPERATION);
  1588. ULONG ulLen = pFinObj->m_uSize;
  1589. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1590. // Check to see if we have reached the max batch size yet.
  1591. // If so, we should break otherwise, update totals and continue
  1592. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1593. // paulall - added check in case there is no object in queue and the current object
  1594. // is greater than the max size...
  1595. if ((nBatchBytes != 0) && ((nBatchBytes+ulLen) > g_ulMaxBatchSize ))
  1596. {
  1597. m_enumBatchStatus = FinalizerBatch_BufferOverFlow;
  1598. bBuildingBuffer = false;
  1599. break;
  1600. }
  1601. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1602. // No overflow, update the object count
  1603. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1604. nBatchSize++;
  1605. nBatchBytes+=ulLen;
  1606. nTempAdd++;
  1607. }
  1608. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1609. // PHASE 2
  1610. // -------
  1611. // Build the actual transmit buffer
  1612. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1613. ULONG OldSize = m_ulAsyncDeliverySize;
  1614. ULONG OldCount = m_ulAsyncDeliveryCount;
  1615. m_ulQueueSize -= nBatchBytes;
  1616. m_ulAsyncDeliverySize = nBatchBytes;
  1617. m_ulAsyncDeliveryCount = nBatchSize;
  1618. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1619. // If we have a batch to build, lets do it
  1620. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1621. if ( m_ulAsyncDeliveryCount > 0 )
  1622. {
  1623. m_apAsyncDeliveryBuffer = new IWbemClassObject* [ m_ulAsyncDeliveryCount ];
  1624. if ( m_apAsyncDeliveryBuffer )
  1625. {
  1626. memset(m_apAsyncDeliveryBuffer,0,sizeof(IWbemClassObject*)*m_ulAsyncDeliveryCount);
  1627. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1628. // Now, loop through the object queue and store the IWbemClassObject ptr
  1629. // in the batch
  1630. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1631. for ( ULONG x = 0; x < m_ulAsyncDeliveryCount; x++ )
  1632. {
  1633. CWmiFinalizerObj *pObjTmp = 0;
  1634. hRes = DequeueObject(&pObjTmp, NULL);
  1635. if (FAILED(hRes) )
  1636. {
  1637. RET_FNLZR_ASSERT(__TEXT("CWmiFinalizer::BuildTransmitBuffer, failed to dequeue object [heap corruption]!"), WBEM_E_FAILED);
  1638. }
  1639. m_apAsyncDeliveryBuffer [ x ] = pObjTmp->m_pObj;
  1640. m_apAsyncDeliveryBuffer [ x ] -> AddRef();
  1641. delete pObjTmp;
  1642. }
  1643. }
  1644. else
  1645. {
  1646. m_ulQueueSize += nBatchBytes;
  1647. m_ulAsyncDeliverySize = OldSize;
  1648. m_ulAsyncDeliveryCount = OldCount;
  1649. hRes = WBEM_E_OUT_OF_MEMORY;
  1650. }
  1651. }
  1652. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1653. // Otherwise, we only got a status message.
  1654. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1655. else
  1656. hRes = WBEM_E_FAILED;
  1657. return hRes;
  1658. }
  1659. //***************************************************************************
  1660. //
  1661. //***************************************************************************
  1662. HRESULT CWmiFinalizer::DeliverSingleObjFromQueue ( )
  1663. {
  1664. HRESULT hRes = WBEM_S_NO_ERROR;
  1665. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1666. // Ensure destination sink is protected [stress bug]
  1667. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1668. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink();
  1669. if ( !pTmp )
  1670. {
  1671. CancelCall (__LINE__);
  1672. return WBEM_E_CALL_CANCELLED;
  1673. }
  1674. CReleaseMe myReleaseMe(pTmp);
  1675. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1676. // Retrieve the object from the object queue
  1677. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1678. CWmiFinalizerObj* pObj = NULL;
  1679. hRes = DequeueObject ( &pObj, NULL );
  1680. if ( FAILED(hRes) || !pObj )
  1681. hRes = WBEM_E_FAILED;
  1682. else
  1683. {
  1684. if (pObj->m_objectType == CWmiFinalizerObj::object)
  1685. {
  1686. HANDLE hTimer;
  1687. BOOL bStatus = CreateTimerQueueTimer ( &hTimer, NULL, ProxyThreshold, (PVOID) this, g_ulClientCallbackTimeout, 0, WT_EXECUTEONLYONCE|WT_EXECUTEINTIMERTHREAD );
  1688. if ( !bStatus )
  1689. {
  1690. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_OUT_OF_MEMORY, 0, 0 );
  1691. delete pObj;
  1692. return CancelCall(__LINE__);
  1693. }
  1694. if ( HasWriteOnlyProps (pObj->m_pObj) )
  1695. ZapWriteOnlyProps (pObj->m_pObj);
  1696. CWbemObject* pWbemObj = (CWbemObject*) pObj->m_pObj;
  1697. m_ulQueueSize-=pWbemObj->GetBlockLength();
  1698. IWbemClassObject * pObj_ = pObj->m_pObj;
  1699. hRes = DoIndicate(pTmp, 1, &pObj_);
  1700. // Client can also tell us to cancel a call by returning WBEM_E_CALL_CANCELLED from Indicate
  1701. // We also want to cancel the call if the client is taking way too long to return
  1702. if ( FAILED (hRes) || m_bCancelledCall == TRUE )
  1703. {
  1704. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_CALL_CANCELLED, 0, 0 );
  1705. DeleteTimerQueueTimer (NULL, hTimer, INVALID_HANDLE_VALUE );
  1706. delete pObj;
  1707. return CancelCall(__LINE__);
  1708. }
  1709. else
  1710. DeleteTimerQueueTimer (NULL, hTimer, INVALID_HANDLE_VALUE );
  1711. }
  1712. else if (pObj->m_objectType == CWmiFinalizerObj::status)
  1713. {
  1714. // ATTGORA: What about the handle? When do we close it?
  1715. HANDLE hTimer;
  1716. BOOL bStatus = CreateTimerQueueTimer ( &hTimer, NULL, ProxyThreshold, (PVOID) this, g_ulClientCallbackTimeout, 0, WT_EXECUTEONLYONCE|WT_EXECUTEINTIMERTHREAD );
  1717. if ( !bStatus )
  1718. {
  1719. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_OUT_OF_MEMORY, 0, 0 );
  1720. delete pObj;
  1721. return CancelCall(__LINE__);
  1722. }
  1723. hRes = DoSetStatus(pTmp, pObj->m_lFlags, pObj->m_hRes, pObj->m_bStr, pObj->m_pObj);
  1724. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1725. // Client can also tell us to cancel a call by returning WBEM_E_CALL_CANCELLED
  1726. // from Indicate We also want to cancel the call if the client is taking way
  1727. // too long to return
  1728. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1729. if ( FAILED (hRes) || m_bCancelledCall == TRUE )
  1730. {
  1731. hRes = CancelCall(__LINE__);
  1732. }
  1733. DeleteTimerQueueTimer (NULL, hTimer, INVALID_HANDLE_VALUE );
  1734. if (pObj->m_lFlags == WBEM_STATUS_COMPLETE)
  1735. {
  1736. {
  1737. CInCritSec lock(&m_destCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1738. if (m_pDestSink)
  1739. {
  1740. ReleaseDestinationSink ( ) ;
  1741. m_bSetStatusConsumed = true;
  1742. UpdateStatus ( WMI_FNLZR_STATE_CLIENT_COMPLETE );
  1743. }
  1744. }
  1745. CancelTaskInternal();
  1746. }
  1747. }
  1748. delete pObj;
  1749. }
  1750. return hRes;
  1751. }
  1752. //***************************************************************************
  1753. //
  1754. //***************************************************************************
  1755. HRESULT CWmiFinalizer::DeliverBatch ( )
  1756. {
  1757. HRESULT hRes = WBEM_NO_ERROR;
  1758. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1759. // Ensure destination sink is protected [stress bug]
  1760. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1761. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink ( );
  1762. if ( !pTmp )
  1763. {
  1764. ZeroAsyncDeliveryBuffer ( );
  1765. CancelCall(__LINE__);
  1766. return WBEM_E_CALL_CANCELLED;
  1767. }
  1768. CReleaseMe myReleaseMe(pTmp);
  1769. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1770. // Create a timer queue in case we need to time out the call to the client
  1771. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1772. HANDLE hTimer;
  1773. BOOL bStatus = CreateTimerQueueTimer ( &hTimer, NULL, ProxyThreshold, (PVOID) this, g_ulClientCallbackTimeout, 0, WT_EXECUTEONLYONCE|WT_EXECUTEINTIMERTHREAD );
  1774. if ( !bStatus )
  1775. {
  1776. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_OUT_OF_MEMORY, 0, 0 );
  1777. ZeroAsyncDeliveryBuffer ( );
  1778. return CancelCall(__LINE__);
  1779. }
  1780. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1781. // If we have sensitive data, zap it.
  1782. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1783. for (int i = 0; i < m_ulAsyncDeliveryCount; i++)
  1784. {
  1785. if ( HasWriteOnlyProps (m_apAsyncDeliveryBuffer[i]) )
  1786. ZapWriteOnlyProps (m_apAsyncDeliveryBuffer[i]);
  1787. }
  1788. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1789. // DoIndicate to the client
  1790. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1791. hRes = DoIndicate ( pTmp, m_ulAsyncDeliveryCount, m_apAsyncDeliveryBuffer );
  1792. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1793. // Client can also tell us to cancel a call by returning WBEM_E_CALL_CANCELLED
  1794. // from Indicate We also want to cancel the call if the client is taking way
  1795. // too long to return
  1796. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1797. if ( FAILED (hRes) || m_bCancelledCall == TRUE )
  1798. {
  1799. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_CALL_CANCELLED, 0, 0 );
  1800. hRes = CancelCall(__LINE__);
  1801. InterlockedCompareExchange ( &m_lCurrentlyCancelling, TRUE, m_lCurrentlyCancelling);
  1802. }
  1803. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1804. // Make sure timer queue is deleted
  1805. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1806. DeleteTimerQueueTimer (NULL, hTimer, INVALID_HANDLE_VALUE );
  1807. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1808. // Clean up the async delivery buffer
  1809. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1810. ZeroAsyncDeliveryBuffer ( );
  1811. return hRes;
  1812. }
  1813. /*
  1814. * =====================================================================================================
  1815. |
  1816. | BOOL CWmiFinalizer::IsValidDestinationSink ( )
  1817. | -----------------------------------------------
  1818. |
  1819. | Returns TRUE if we have a valid destination sink, FALSE otherwise.
  1820. |
  1821. |
  1822. * =====================================================================================================
  1823. */
  1824. BOOL CWmiFinalizer::IsValidDestinationSink ( )
  1825. {
  1826. BOOL bIsValidDestinationSink = FALSE ;
  1827. CInCritSec lock(&m_destCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1828. if ( m_pDestSink != NULL )
  1829. {
  1830. bIsValidDestinationSink = TRUE ;
  1831. }
  1832. return bIsValidDestinationSink ;
  1833. }
  1834. /*
  1835. * =====================================================================================================
  1836. |
  1837. | HRESULT CWmiFinalizer::NotifyClientOfCancelledCall ( )
  1838. | ------------------------------------------------------
  1839. |
  1840. | If Client issued a CancelAsync call he/she is potentially waiting to be woken up once the delivery
  1841. | of WBEM_E_CALL_CANCELLED is completed.
  1842. |
  1843. |
  1844. * =====================================================================================================
  1845. */
  1846. HRESULT CWmiFinalizer::NotifyClientOfCancelledCall ( )
  1847. {
  1848. HRESULT hRes = WBEM_S_NO_ERROR ;
  1849. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1850. if ( m_hWaitForSetStatus )
  1851. {
  1852. SetEvent ( m_hWaitForSetStatus ) ;
  1853. m_hWaitForSetStatus = NULL ;
  1854. }
  1855. return hRes ;
  1856. }
  1857. /*
  1858. * =====================================================================================================
  1859. |
  1860. | HRESULT CWmiFinalizer::CancelWaitHandle ( )
  1861. | -------------------------------------------
  1862. |
  1863. | Cancels the handle the client may be waiting for in a CancelAsynCall. Clients _will_ wait for a final
  1864. | SetStatus to be called before waking up.
  1865. |
  1866. |
  1867. * =====================================================================================================
  1868. */
  1869. HRESULT CWmiFinalizer::CancelWaitHandle ( )
  1870. {
  1871. HRESULT hRes = WBEM_S_NO_ERROR ;
  1872. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1873. if ( m_hWaitForSetStatus )
  1874. {
  1875. m_hWaitForSetStatus = NULL ;
  1876. }
  1877. return hRes ;
  1878. }
  1879. /*
  1880. * =====================================================================================================
  1881. |
  1882. | HRESULT CWmiFinalizer::SetClientCancellationHandle ( HANDLE hCancelEvent )
  1883. | --------------------------------------------------------------------------
  1884. |
  1885. | Sets the handle that the client is waiting for in case of a CancelAsyncCall.
  1886. |
  1887. * =====================================================================================================
  1888. */
  1889. HRESULT CWmiFinalizer::SetClientCancellationHandle ( HANDLE hCancelEvent )
  1890. {
  1891. HRESULT hRes = WBEM_S_NO_ERROR ;
  1892. CInCritSec lock(&m_arbitratorCS); // SEC:REVIEWED 2002-03-22 : Assumes entry
  1893. if ( m_hWaitForSetStatus == NULL )
  1894. {
  1895. m_hWaitForSetStatus = hCancelEvent ;
  1896. }
  1897. return hRes ;
  1898. }
  1899. //***************************************************************************
  1900. // ATTGORA: Do we really need to tell a client that 'setstatus' or 'indicates'
  1901. // us for cancellation that we are cancelling?
  1902. //***************************************************************************
  1903. HRESULT CWmiFinalizer::CancelCall()
  1904. {
  1905. CAutoSignal CancelCallSignal (m_hCancelEvent);
  1906. HRESULT hRes;
  1907. if ( InterlockedCompareExchange ( &m_bCancelledCall, 1, 0 ) == 0 )
  1908. {
  1909. hRes = WBEM_NO_ERROR;
  1910. m_bCancelledCall = TRUE;
  1911. //
  1912. // Indicate the cancellation to the client, iff we are not cancelling
  1913. // due to a naughty client (i.e a client that didnt return from
  1914. // the indicate or setstatus call in a reasonable amount of time
  1915. //
  1916. if ( !m_bNaughtyClient )
  1917. {
  1918. //
  1919. // Ensure destination sink is protected [stress bug]
  1920. //
  1921. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink ( );
  1922. if ( !pTmp )
  1923. {
  1924. m_hStatus = CallCancelled;
  1925. NotifyAllEnumeratorsOfCompletion ( ) ;
  1926. CancelTaskInternal ( ) ;
  1927. return WBEM_NO_ERROR;
  1928. }
  1929. CReleaseMe myReleaseMe(pTmp);
  1930. //
  1931. // This is an async operation. Need to call setstatus on delivery thread
  1932. // Hack: What we do is forcfully insert the setstatus message at the beginning
  1933. // of the object queue. Two scenarios:
  1934. // 1. If the async delivery thread is waiting, it will be woken up
  1935. // 2. If the async delivery thread is delivering, the next object delivered
  1936. // will be the status msg.
  1937. //
  1938. CWmiFinalizerObj *pObj = new CWmiFinalizerObj(0, WBEM_E_CALL_CANCELLED, NULL, NULL); // SEC:REVIEWED 2002-03-22 : Needs EH
  1939. if (pObj == NULL)
  1940. {
  1941. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_OUT_OF_MEMORY,0,0);
  1942. SetOperationResult(0,WBEM_E_OUT_OF_MEMORY);
  1943. m_hStatus = QueueFailure;
  1944. NotifyAllEnumeratorsOfCompletion();
  1945. return WBEM_E_OUT_OF_MEMORY;
  1946. }
  1947. QueueOperation ( pObj );
  1948. m_bSetStatusCalled = true;
  1949. }
  1950. else
  1951. {
  1952. //
  1953. // We have a client that is not being cooperative (not returning within 60s). BAD
  1954. // BAD CLIENT!
  1955. //
  1956. // Try to push a SetStatus (WBEM_E_CALL_CANCELLED) through. Maybe they're not intentially
  1957. // trying to be bad, perhaps they're just incompentent and not reading the docs !
  1958. //
  1959. IWbemObjectSink* pTmp = ReturnProtectedDestinationSink ( );
  1960. if ( !pTmp )
  1961. {
  1962. m_hStatus = CallCancelled;
  1963. NotifyAllEnumeratorsOfCompletion ( ) ;
  1964. return WBEM_NO_ERROR;
  1965. }
  1966. CReleaseMe myReleaseMe(pTmp);
  1967. //
  1968. // This is the absolutely last attempt to notify the client that something
  1969. // is going wrong. We dont care about the result of this operation since
  1970. // we cant do anything about a failure anyway! More than likey, if this call
  1971. // doesnt return the client has messed up again and we're done.
  1972. //
  1973. DoSetStatus ( pTmp, WBEM_STATUS_COMPLETE, WBEM_E_CALL_CANCELLED, 0, 0 ) ;
  1974. }
  1975. //
  1976. // If we dont have a destination sink, who cares? Do some cleanup.
  1977. // Tell the arbitrator to do some system wide clean up. This HAS TO
  1978. // finish before we continue cleaning up, otherwise we could be destroying
  1979. // sinks that are still considered active
  1980. //
  1981. hRes = CancelTaskInternal();
  1982. }
  1983. else
  1984. hRes = WBEM_E_CALL_CANCELLED;
  1985. m_hStatus = CallCancelled;
  1986. NotifyAllEnumeratorsOfCompletion ( ) ;
  1987. return hRes;
  1988. }
  1989. //***************************************************************************
  1990. //
  1991. //***************************************************************************
  1992. VOID WINAPI CWmiFinalizer::ProxyThreshold ( PVOID pvContext, BOOLEAN bTimerOrWait )
  1993. {
  1994. ((CWmiFinalizer*)pvContext)->ProxyThresholdImp();
  1995. }
  1996. //***************************************************************************
  1997. //
  1998. //***************************************************************************
  1999. VOID CWmiFinalizer::ProxyThresholdImp ( )
  2000. {
  2001. RevertToSelf ( ) ; // SEC:REVIEWED 2002-03-22 : Needs check
  2002. UpdateStatus ( WMI_FNLZR_STATE_CLIENT_DEAD );
  2003. ERRORTRACE((LOG_WBEMCORE, "Client did not return from a SetStatus or Indicate call within %d ms\n",g_ulClientCallbackTimeout));
  2004. m_bNaughtyClient = TRUE;
  2005. CancelCall(__LINE__);
  2006. }
  2007. //***************************************************************************
  2008. //
  2009. //***************************************************************************
  2010. HRESULT CWmiFinalizer::PullObjects(
  2011. long lTimeout,
  2012. ULONG uCount,
  2013. IWbemClassObject** apObjects,
  2014. ULONG* puReturned,
  2015. CWmiFinalizerEnumerator* pEnum,
  2016. BOOL bAddToObjQueue,
  2017. BOOL bSetErrorObj
  2018. )
  2019. {
  2020. HRESULT hr = WBEM_NO_ERROR;
  2021. BOOL bTimeOutExpired = FALSE;
  2022. if (pEnum == 0)
  2023. return WBEM_E_INVALID_PARAMETER;
  2024. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2025. // Has SetStatus already been consumed?
  2026. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2027. if (pEnum->m_bSetStatusConsumed)
  2028. {
  2029. try
  2030. {
  2031. *puReturned = 0;
  2032. }
  2033. catch (...) // untrusted param
  2034. {
  2035. ExceptionCounter c;
  2036. return WBEM_E_INVALID_PARAMETER;
  2037. }
  2038. return WBEM_S_FALSE;
  2039. }
  2040. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2041. // Now we want to loop until we recieved the number of
  2042. // objects requested
  2043. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2044. ULONG index = 0;
  2045. while (index != uCount)
  2046. {
  2047. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2048. // Dequeue the object
  2049. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2050. CWmiFinalizerObj *pObj = NULL;
  2051. hr = DequeueObject(&pObj, pEnum);
  2052. if (hr == WBEM_S_FALSE )
  2053. {
  2054. if ( !bTimeOutExpired )
  2055. {
  2056. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2057. // If Dequeue returned FALSE it means
  2058. // that there are no objects. We should
  2059. // wait for them, unless we have been
  2060. // told to cancel or we have been
  2061. // released
  2062. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2063. if ( m_hStatus == CallCancelled )
  2064. {
  2065. hr = WBEM_E_CALL_CANCELLED;
  2066. break ;
  2067. }
  2068. else if ( m_hStatus == RequestReleased )
  2069. {
  2070. hr = WBEM_E_FAILED;
  2071. break;
  2072. }
  2073. else if ( m_hStatus == QuotaViolation )
  2074. {
  2075. hr = WBEM_E_QUOTA_VIOLATION;
  2076. break;
  2077. }
  2078. else if (QueueFailure == m_hStatus)
  2079. {
  2080. hr = WBEM_E_OUT_OF_MEMORY;
  2081. break;
  2082. }
  2083. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2084. //Wait for another object to come in...
  2085. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2086. DWORD dwRet = CCoreQueue::QueueWaitForSingleObject(pEnum->m_hWaitOnResultSet, lTimeout);
  2087. if (dwRet == WAIT_TIMEOUT)
  2088. {
  2089. bTimeOutExpired = TRUE;
  2090. continue;
  2091. }
  2092. else if ( m_hStatus == CallCancelled )
  2093. {
  2094. hr = WBEM_E_CALL_CANCELLED;
  2095. break ;
  2096. }
  2097. else if ( m_hStatus == RequestReleased )
  2098. {
  2099. hr = WBEM_E_FAILED;
  2100. break;
  2101. }
  2102. else if ( m_hStatus == QuotaViolation )
  2103. {
  2104. hr = WBEM_E_QUOTA_VIOLATION;
  2105. break;
  2106. }
  2107. else if (QueueFailure == m_hStatus)
  2108. {
  2109. hr = WBEM_E_OUT_OF_MEMORY;
  2110. break;
  2111. }
  2112. else
  2113. continue;
  2114. }
  2115. else
  2116. {
  2117. hr = WBEM_S_TIMEDOUT;
  2118. break;
  2119. }
  2120. }
  2121. if (FAILED(hr))
  2122. break;
  2123. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2124. // If we recieved a status complete message, simply break out of
  2125. // the loop
  2126. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2127. if ((pObj->m_objectType == CWmiFinalizerObj::status) && (pObj->m_lFlags == WBEM_STATUS_COMPLETE))
  2128. {
  2129. // Fix for: 175856, 143550
  2130. if ( bSetErrorObj && FAILED (pObj->m_hRes) && pObj->m_pObj )
  2131. {
  2132. m_pCallResult->SetErrorInfo ( ); // SEC:REVIEWED 2002-03-22 : Needs EH
  2133. }
  2134. hr = pObj->m_hRes;
  2135. if (SUCCEEDED ( hr ) )
  2136. hr = WBEM_S_FALSE;
  2137. pEnum->m_bSetStatusConsumed = true;
  2138. delete pObj;
  2139. break;
  2140. }
  2141. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2142. // If its a status message
  2143. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2144. else if (pObj->m_objectType == CWmiFinalizerObj::status )
  2145. {
  2146. delete pObj;
  2147. continue;
  2148. }
  2149. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2150. // If its an object we enqueue it if requested
  2151. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2152. else if (pObj->m_objectType == CWmiFinalizerObj::object)
  2153. {
  2154. if ( bAddToObjQueue )
  2155. {
  2156. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2157. // Make sure we dont trip on nasty client supplied buffers
  2158. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2159. try
  2160. {
  2161. apObjects[index] = pObj->m_pObj;
  2162. if (apObjects[index])
  2163. {
  2164. pObj->m_pObj->AddRef();
  2165. }
  2166. }
  2167. catch (...) // untrusted args
  2168. {
  2169. ExceptionCounter c;
  2170. hr = WBEM_E_INVALID_PARAMETER;
  2171. delete pObj;
  2172. break;
  2173. }
  2174. }
  2175. delete pObj;
  2176. }
  2177. else
  2178. {
  2179. if ( pObj )
  2180. {
  2181. delete pObj;
  2182. }
  2183. }
  2184. index ++;
  2185. }
  2186. if (SUCCEEDED(hr))
  2187. {
  2188. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2189. // Make sure we dont trip on nasty client supplied buffers
  2190. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2191. try
  2192. {
  2193. *puReturned = index;
  2194. }
  2195. catch (...) // untrusted args
  2196. {
  2197. ExceptionCounter c;
  2198. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2199. // need to release all the objects already in the array otherwise they will be leaked...
  2200. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2201. if ( bAddToObjQueue )
  2202. {
  2203. for (DWORD i = 0; i != index; i++)
  2204. {
  2205. if (apObjects[i])
  2206. apObjects[i]->Release();
  2207. }
  2208. }
  2209. return WBEM_E_INVALID_PARAMETER;
  2210. }
  2211. }
  2212. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2213. // If we fail, clean up the obj array
  2214. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2215. else
  2216. {
  2217. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2218. // need to release all the objects already in the array otherwise they will be leaked...
  2219. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2220. if ( bAddToObjQueue )
  2221. {
  2222. for (DWORD i = 0; i != index; i++)
  2223. {
  2224. if (apObjects[i])
  2225. apObjects[i]->Release(); // SEC:REVIEWED 2002-03-22 : Needs EH
  2226. }
  2227. }
  2228. }
  2229. return hr;
  2230. }
  2231. //***************************************************************************
  2232. //
  2233. //***************************************************************************
  2234. HRESULT CWmiFinalizer::DequeueObject( CWmiFinalizerObj **ppObj, CWmiFinalizerEnumerator* pEnum )
  2235. {
  2236. CInCritSec cs(&m_cs); // SEC:REVIEWED 2002-03-22 : Assumes entry
  2237. if ( pEnum != NULL )
  2238. {
  2239. if (pEnum->m_uCurObjectPosition >= (ULONG)m_objects.Size())
  2240. return WBEM_S_FALSE;
  2241. ULONG lIndex = pEnum->m_uCurObjectPosition ;
  2242. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2243. // If this is a semisync call we should decrement the wake up call
  2244. // flag
  2245. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2246. if ( m_ulOperationType == Operation_Type_Semisync && pEnum->m_ulSemisyncWakeupCall != 0 )
  2247. {
  2248. pEnum->m_ulSemisyncWakeupCall--;
  2249. }
  2250. if ( m_bSetStatusWithError && m_bRestartable )
  2251. {
  2252. lIndex = 0 ;
  2253. }
  2254. CWmiFinalizerObj *pStorageObject = (CWmiFinalizerObj*)m_objects[lIndex];
  2255. if (m_bRestartable)
  2256. {
  2257. //We have to hold on to results, so increment cursor position...
  2258. pEnum->m_uCurObjectPosition++;
  2259. *ppObj = new CWmiFinalizerObj(*pStorageObject); // SEC:REVIEWED 2002-03-22 : Needs EH
  2260. if (*ppObj == NULL) // SEC:REVIEWED 2002-03-22 : Needs EH
  2261. return WBEM_E_OUT_OF_MEMORY;
  2262. }
  2263. else
  2264. {
  2265. //We are not restartable, therefore we need to release everything...
  2266. CWmiFinalizerObj *pStorageObject = (CWmiFinalizerObj*)m_objects[0];
  2267. m_objects.RemoveAt(0);
  2268. *ppObj = pStorageObject;
  2269. }
  2270. }
  2271. else
  2272. {
  2273. if ( m_uCurObjectPosition >= (ULONG)m_objects.Size() )
  2274. return WBEM_S_FALSE;
  2275. CWmiFinalizerObj *pStorageObject = (CWmiFinalizerObj*)m_objects[0];
  2276. m_objects.RemoveAt(0);
  2277. *ppObj = pStorageObject; // SEC:REVIEWED 2002-03-22 : Needs EH
  2278. }
  2279. return WBEM_NO_ERROR;
  2280. }
  2281. //***************************************************************************
  2282. //
  2283. //***************************************************************************
  2284. HRESULT CWmiFinalizer::Skip(
  2285. /*[in]*/ long lTimeout,
  2286. /*[in]*/ ULONG nCount,
  2287. /*[in]*/ CWmiFinalizerEnumerator* pEnum
  2288. )
  2289. {
  2290. ULONG uReturned = 0;
  2291. return PullObjects(lTimeout, nCount, NULL, &uReturned, pEnum, FALSE);
  2292. }
  2293. //***************************************************************************
  2294. //
  2295. //***************************************************************************
  2296. HRESULT CWmiFinalizer::NextAsync ( CWmiFinalizerEnumerator* pEnum )
  2297. {
  2298. BOOL bRes;
  2299. if (pEnum == 0)
  2300. return WBEM_E_FAILED;
  2301. wmilib::auto_ptr<InsertableEvent> pInsert( new InsertableEvent);
  2302. if (NULL == pInsert.get()) return WBEM_E_OUT_OF_MEMORY;
  2303. pInsert->pEnum = pEnum;
  2304. pInsert->ThreadId = 0;
  2305. pEnum->Add_NextAsync(pInsert.get());
  2306. bRes = QueueUserWorkItem ( pEnum->ThreadBootstrapNextAsync, pInsert.get(), WT_EXECUTEDEFAULT );
  2307. if ( !bRes )
  2308. {
  2309. pEnum->Remove_NextAsync(pInsert.release()); // let the Remove function to delete the LIST_ENTRY
  2310. pEnum->SetCompletionSignalEvent();
  2311. return WBEM_E_FAILED;
  2312. }
  2313. pInsert.release(); // the WorkItem took possession at this point
  2314. return WBEM_S_NO_ERROR;
  2315. }
  2316. //***************************************************************************
  2317. //
  2318. //***************************************************************************
  2319. HRESULT CWmiFinalizer::SetSinkToIdentity ( IWbemObjectSink* pSink )
  2320. {
  2321. HRESULT sc;
  2322. // SEC:REVIEWED 2002-03-22 : Assumes valid pSink. Needs EH in case it is garbage.
  2323. IClientSecurity * pFromSec = NULL;
  2324. sc = pSink->QueryInterface(IID_IClientSecurity, (void **) &pFromSec);
  2325. if(sc == S_OK)
  2326. {
  2327. OLECHAR * pPrincipal = NULL;
  2328. DWORD dwAuthnSvc, dwAuthzSvc, dwAuthnLevel, dwImpLevel, dwCapabilities;
  2329. sc = pFromSec->QueryBlanket(pSink, &dwAuthnSvc, &dwAuthzSvc,
  2330. &pPrincipal,
  2331. &dwAuthnLevel, &dwImpLevel,
  2332. NULL, &dwCapabilities);
  2333. if ( sc==S_OK )
  2334. {
  2335. sc = pFromSec->SetBlanket(pSink, dwAuthnSvc, dwAuthzSvc,
  2336. pPrincipal,
  2337. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2338. RPC_C_IMP_LEVEL_IDENTIFY, // We always call back on System and IDENTITY IMP LEVEL!!!
  2339. NULL, dwCapabilities);
  2340. if(pPrincipal)
  2341. CoTaskMemFree(pPrincipal);
  2342. }
  2343. pFromSec->Release();
  2344. }
  2345. return sc;
  2346. }
  2347. //***************************************************************************
  2348. //
  2349. // ZapWriteOnlyProps
  2350. //
  2351. // Removes write-only properties from an object.
  2352. // Precondition: Object has been tested for presence of "HasWriteOnlyProps"
  2353. // on the object itself.
  2354. //
  2355. //***************************************************************************
  2356. HRESULT CWmiFinalizer::ZapWriteOnlyProps(IWbemClassObject *pObj)
  2357. {
  2358. if (pObj == 0)
  2359. return WBEM_E_INVALID_PARAMETER;
  2360. VARIANT v;
  2361. VariantInit(&v);
  2362. V_VT(&v) = VT_NULL;
  2363. SAFEARRAY *pNames = 0;
  2364. pObj->GetNames(L"WriteOnly", WBEM_FLAG_ONLY_IF_TRUE, 0, &pNames); // SEC:REVIEWED 2002-03-22 : Assumes success
  2365. LONG lUpper;
  2366. SafeArrayGetUBound(pNames, 1, &lUpper);
  2367. for (long i = 0; i <= lUpper; i++)
  2368. {
  2369. BSTR strName = 0;
  2370. SafeArrayGetElement(pNames, &i, &strName);
  2371. pObj->Put(strName, 0, &v, 0);
  2372. SysFreeString (strName);
  2373. }
  2374. SafeArrayDestroy(pNames);
  2375. VariantClear (&v);
  2376. return WBEM_S_NO_ERROR;
  2377. }
  2378. //***************************************************************************
  2379. //
  2380. // HasWriteOnlyProps
  2381. //
  2382. // Returns TRUE if object contains any Write only props, otherwise FALSE
  2383. //
  2384. //***************************************************************************
  2385. BOOL CWmiFinalizer::HasWriteOnlyProps ( IWbemClassObject* pObj )
  2386. {
  2387. BOOL bRes;
  2388. if (pObj == 0) return FALSE;
  2389. IWbemQualifierSet *pQSet = 0;
  2390. HRESULT hRes = pObj->GetQualifierSet(&pQSet);
  2391. if (FAILED(hRes))
  2392. return FALSE;
  2393. hRes = pQSet->Get(L"HasWriteOnlyProps", 0, 0, 0);
  2394. if (SUCCEEDED(hRes))
  2395. bRes = TRUE;
  2396. else
  2397. bRes = FALSE;
  2398. pQSet->Release();
  2399. return bRes;
  2400. }
  2401. //***************************************************************************
  2402. //
  2403. // DoSetStatus
  2404. //
  2405. // Using LowerAuthLevel
  2406. //
  2407. //***************************************************************************
  2408. HRESULT CWmiFinalizer::DoSetStatusCancel(IWbemObjectSink * pSink, HRESULT realError )
  2409. {
  2410. IWbemClassObject * objParam;
  2411. try
  2412. {
  2413. CErrorObject Error(0);
  2414. Error.SetStatusCode(realError);
  2415. objParam = Error.GetObject();
  2416. }
  2417. catch ( CX_Exception & )
  2418. {
  2419. }
  2420. HRESULT hr = DoSetStatus(pSink, WBEM_STATUS_COMPLETE, WBEM_E_CALL_CANCELLED, 0, objParam);
  2421. if (objParam) objParam->Release();
  2422. return hr;
  2423. }
  2424. //***************************************************************************
  2425. //
  2426. // DoSetStatus
  2427. //
  2428. // Using LowerAuthLevel
  2429. //
  2430. //***************************************************************************
  2431. HRESULT CWmiFinalizer::DoSetStatus(IWbemObjectSink * psink, long lFlags, HRESULT lParam, BSTR strParam,
  2432. IWbemClassObject* pObjParam, BOOL bAllowMultipleCalls )
  2433. {
  2434. HRESULT hres = WBEM_E_FAILED;
  2435. //
  2436. // In the case of NextAsync we will in fact allow multiple calls to DoSetStatus
  2437. //
  2438. if ( ( bAllowMultipleCalls == FALSE ) && ( lFlags == WBEM_STATUS_COMPLETE ) )
  2439. {
  2440. //
  2441. // If a setstatus has already been delivered, fail this operation
  2442. // This is a must since we support the CancelAsynCall in which case
  2443. // there is potential for 2 setstatus msg to be enqueued.
  2444. //
  2445. {
  2446. CCheckedInCritSec cs ( &m_cs ) ; // SEC:REVIEWED 2002-03-22 : Assumes entry
  2447. if ( m_bSetStatusDelivered == TRUE )
  2448. {
  2449. //
  2450. // If a SetStatus has already been delivered (in non-error cases, i.e. not via client cancellation)
  2451. // we still may want to try and wake up the client since they may have tried to enter a cancellation
  2452. // wait state.
  2453. //
  2454. cs.Leave ( ) ;
  2455. NotifyClientOfCancelledCall ( ) ;
  2456. return hres ;
  2457. }
  2458. else
  2459. {
  2460. //
  2461. // We assume that the delivery will be successfull. If its not, we dont
  2462. // want to try again anyway.
  2463. //
  2464. m_bSetStatusDelivered = TRUE ;
  2465. }
  2466. }
  2467. }
  2468. DWORD dwLastAuthnLevel = LOWER_AUTH_LEVEL_NOTSET;
  2469. // put this a loop, but use the counter to make sure there is always an exit.
  2470. for(int i = 0; i < 10; i ++)
  2471. {
  2472. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2473. // Make sure bad client sink does not trip us
  2474. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2475. try
  2476. {
  2477. hres = psink->SetStatus(lFlags, lParam, strParam, pObjParam);
  2478. }
  2479. catch (...) // untrusted sink
  2480. {
  2481. ExceptionCounter c;
  2482. hres = WBEM_E_INVALID_PARAMETER;
  2483. break;
  2484. }
  2485. if(!FAILED(hres))
  2486. {
  2487. break ; // all done, normal exit
  2488. }
  2489. if ( hres != E_ACCESSDENIED &&
  2490. HRESULT_CODE(hres) != RPC_S_SERVER_TOO_BUSY && // When the target is Win9x and
  2491. HRESULT_CODE(hres) != RPC_S_UNKNOWN_AUTHN_SERVICE) // the level is above connect
  2492. // DFS patch not applied
  2493. break;
  2494. hres = FinalizerLowerAuthLevel(psink, &dwLastAuthnLevel);
  2495. if(FAILED(hres))
  2496. break;
  2497. }
  2498. if ( FAILED (hres) )
  2499. {
  2500. ERRORTRACE((LOG_WBEMCORE, "Could not SetStatus to remote client, hres =%X\n",hres));
  2501. }
  2502. if ( lParam == WBEM_E_CALL_CANCELLED )
  2503. {
  2504. NotifyClientOfCancelledCall ( ) ;
  2505. }
  2506. if ( lFlags == WBEM_STATUS_COMPLETE && bAllowMultipleCalls == FALSE )
  2507. {
  2508. NotifyClientOfCancelledCall ( ) ;
  2509. CancelTaskInternal ( ) ;
  2510. }
  2511. return hres;
  2512. }
  2513. //***************************************************************************
  2514. //
  2515. // DoSetIndicate
  2516. //
  2517. // Using LowerAuthLevel
  2518. //
  2519. //***************************************************************************
  2520. HRESULT CWmiFinalizer::DoIndicate(IWbemObjectSink * psink, int nBatchSize, IWbemClassObject **pBatch)
  2521. {
  2522. HRESULT hres = WBEM_E_FAILED;
  2523. DWORD dwLastAuthnLevel = LOWER_AUTH_LEVEL_NOTSET;
  2524. // put this a loop, but use the counter to make sure there is always an exit.
  2525. for(int i = 0; i < 10; i ++)
  2526. {
  2527. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2528. // Make sure bad client sink does not trip us
  2529. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2530. try
  2531. {
  2532. hres = psink->Indicate(nBatchSize, pBatch);
  2533. }
  2534. catch (...) // untrusted sink
  2535. {
  2536. ExceptionCounter c;
  2537. hres = WBEM_E_INVALID_PARAMETER;
  2538. break;
  2539. }
  2540. if(!FAILED(hres))
  2541. {
  2542. return hres; // all done, normal exit
  2543. }
  2544. if ( hres != E_ACCESSDENIED &&
  2545. HRESULT_CODE(hres) != RPC_S_SERVER_TOO_BUSY && // When the target is Win9x and
  2546. HRESULT_CODE(hres) != RPC_S_UNKNOWN_AUTHN_SERVICE) // the level is above connect
  2547. break;
  2548. hres = FinalizerLowerAuthLevel(psink, &dwLastAuthnLevel);
  2549. if(FAILED(hres))
  2550. break;
  2551. }
  2552. ERRORTRACE((LOG_WBEMCORE, "Could not Indicate to remote client, hres %X\n",hres));
  2553. return hres;
  2554. }
  2555. //***************************************************************************
  2556. //
  2557. // LowerAuth.
  2558. //
  2559. // Using LowerAuthLevel
  2560. //
  2561. //***************************************************************************
  2562. HRESULT CWmiFinalizer::FinalizerLowerAuthLevel(IWbemObjectSink * psink, DWORD* pdwLastAuthnLevel )
  2563. {
  2564. IClientSecurity * pFromSec = NULL;
  2565. SCODE sc;
  2566. try
  2567. {
  2568. sc = psink->QueryInterface(IID_IClientSecurity, (void **) &pFromSec); // SEC:REVIEWED 2002-03-22 : Assumes entry
  2569. }
  2570. catch(...)
  2571. {
  2572. sc = WBEM_E_INVALID_PARAMETER;
  2573. }
  2574. if(sc == S_OK)
  2575. {
  2576. OLECHAR * pPrincipal = NULL;
  2577. DWORD dwAuthnSvc, dwAuthzSvc, dwAuthnLevel, dwImpLevel, dwCapabilities;
  2578. sc = pFromSec->QueryBlanket(psink, &dwAuthnSvc, &dwAuthzSvc,
  2579. &pPrincipal,
  2580. &dwAuthnLevel, &dwImpLevel,
  2581. NULL, &dwCapabilities);
  2582. // If we have never retrieved the authentication level before, then we
  2583. // should record what it currently is
  2584. if ( LOWER_AUTH_LEVEL_NOTSET == *pdwLastAuthnLevel )
  2585. {
  2586. *pdwLastAuthnLevel = dwAuthnLevel;
  2587. }
  2588. if (FAILED(sc))
  2589. return sc;
  2590. if(*pdwLastAuthnLevel == RPC_C_AUTHN_LEVEL_NONE)
  2591. return WBEM_E_FAILED;
  2592. (*pdwLastAuthnLevel)--; // normal case is to try one lower
  2593. sc = pFromSec->SetBlanket(psink, dwAuthnSvc, dwAuthzSvc,
  2594. pPrincipal,
  2595. *pdwLastAuthnLevel, RPC_C_IMP_LEVEL_IDENTIFY, // We always call back on System and IDENTITY IMP LEVEL!!!
  2596. NULL, dwCapabilities);
  2597. if(pPrincipal)
  2598. CoTaskMemFree(pPrincipal);
  2599. pFromSec->Release();
  2600. }
  2601. return sc;
  2602. }
  2603. //***************************************************************************
  2604. //
  2605. // ZeroAsyncDeliveryBuffer
  2606. //
  2607. // Clears out the async delivery buffer
  2608. //
  2609. //***************************************************************************
  2610. VOID CWmiFinalizer::ZeroAsyncDeliveryBuffer ( )
  2611. {
  2612. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2613. // Delete the object array
  2614. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2615. for ( ULONG i = 0; i < m_ulAsyncDeliveryCount; i++ )
  2616. {
  2617. m_apAsyncDeliveryBuffer[i]->Release(); // SEC:REVIEWED 2002-03-22 : Needs check for NULLness or EH
  2618. }
  2619. delete [] m_apAsyncDeliveryBuffer;
  2620. m_ulAsyncDeliveryCount = 0;
  2621. m_ulAsyncDeliverySize = 0;
  2622. }
  2623. //***************************************************************************
  2624. //
  2625. //***************************************************************************
  2626. HRESULT CWmiFinalizer::DumpDebugInfo (
  2627. /*[in]*/ ULONG uFlags,
  2628. /*[in]*/ const BSTR strFile
  2629. )
  2630. {
  2631. HRESULT hRes = WBEM_S_NO_ERROR;
  2632. return hRes;
  2633. }
  2634. //***************************************************************************
  2635. //
  2636. //***************************************************************************
  2637. HRESULT CWmiFinalizer::Shutdown(
  2638. /*[in]*/ LONG uReason,
  2639. /*[in]*/ ULONG uMaxMilliseconds,
  2640. /*[in]*/ IWbemContext *pCtx)
  2641. {
  2642. wmilib::auto_buffer<IUnknown *> ppEnums;
  2643. DWORD Len;
  2644. {
  2645. CInCritSec lock( &m_cs ) ; // SEC:REVIEWED 2002-03-22 : Assumes entry
  2646. Len = m_enumerators.Size();
  2647. ppEnums.reset(new IUnknown * [Len]);
  2648. if (NULL == ppEnums.get()) return WBEM_E_OUT_OF_MEMORY;
  2649. for (DWORD i = 0;i<Len;i++)
  2650. {
  2651. ppEnums[i] = (IUnknown *)m_enumerators[i];
  2652. ppEnums[i]->AddRef();
  2653. }
  2654. }
  2655. for (DWORD i = 0;i<Len;i++)
  2656. {
  2657. IUnknown * p = ppEnums[i];
  2658. IWbemWCOSmartEnum * pSmartEnum = NULL;
  2659. if (SUCCEEDED(p->QueryInterface(IID_IWbemWCOSmartEnum,(void **)&pSmartEnum)))
  2660. {
  2661. CoDisconnectObject(pSmartEnum,0);
  2662. pSmartEnum->Release();
  2663. }
  2664. IWbemFetchSmartEnum * pFetch = NULL;
  2665. if (SUCCEEDED(p->QueryInterface(IID_IWbemFetchSmartEnum,(void **)&pFetch)))
  2666. {
  2667. CWmiFinalizerEnumerator * pEnum = (CWmiFinalizerEnumerator *)(void *)p;
  2668. if (pEnum->HasSmartEnum() && SUCCEEDED(pFetch->GetSmartEnum(&pSmartEnum)))
  2669. {
  2670. CoDisconnectObject(pSmartEnum,0);
  2671. pSmartEnum->Release();
  2672. }
  2673. pFetch->Release();
  2674. }
  2675. CoDisconnectObject(p,0);
  2676. p->Release();
  2677. }
  2678. return S_OK;
  2679. }
  2680. /*
  2681. * ==================================================================================================
  2682. |
  2683. | HRESULT CWmiFinalizer::NotifyAllEnumeratorsOfCompletion ( )
  2684. | -----------------------------------------------------------
  2685. |
  2686. |
  2687. |
  2688. * ==================================================================================================
  2689. */
  2690. HRESULT CWmiFinalizer::NotifyAllEnumeratorsOfCompletion ( )
  2691. {
  2692. //
  2693. // Cocked, Locked, and ready to Rock
  2694. //
  2695. CInCritSec _cs ( &m_cs ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  2696. HRESULT hRes = WBEM_S_NO_ERROR ;
  2697. for ( int i = 0; i < m_enumerators.Size ( ); i++ )
  2698. {
  2699. CWmiFinalizerEnumerator* pEnum = (CWmiFinalizerEnumerator*) m_enumerators[i] ;
  2700. if ( pEnum )
  2701. {
  2702. SetEvent ( pEnum->m_hWaitOnResultSet );
  2703. }
  2704. }
  2705. return hRes ;
  2706. }
  2707. /*
  2708. * ==================================================================================================
  2709. |
  2710. | HRESULT CWmiFinalizer::UnregisterEnumerator ( CWmiFinalizerEnumerator* pEnum )
  2711. | ------------------------------------------------------------------------------
  2712. |
  2713. |
  2714. |
  2715. * ==================================================================================================
  2716. */
  2717. HRESULT CWmiFinalizer::UnregisterEnumerator ( CWmiFinalizerEnumerator* pEnum )
  2718. {
  2719. //
  2720. // Cocked, Locked, and ready to Rock
  2721. //
  2722. CInCritSec _cs ( &m_cs ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  2723. HRESULT hRes = WBEM_S_NO_ERROR ;
  2724. for ( int i = 0; i < m_enumerators.Size ( ); i++ )
  2725. {
  2726. CWmiFinalizerEnumerator* pEnumerator = (CWmiFinalizerEnumerator*) m_enumerators[i] ;
  2727. if ( pEnum == pEnumerator )
  2728. {
  2729. pEnumerator->InternalRelease ( ) ;
  2730. m_enumerators.RemoveAt ( i ) ;
  2731. break ;
  2732. }
  2733. }
  2734. return hRes ;
  2735. }
  2736. //***************************************************************************
  2737. //
  2738. //***************************************************************************
  2739. void CWmiFinalizer::Dump(FILE* f)
  2740. {
  2741. fprintf(f, "--Finalizer Stats---\n"); // SEC:REVIEWED 2002-03-22 : OK
  2742. fprintf(f, " s_Finalizer_ObjectCount = %d\n", s_Finalizer_ObjectCount); // SEC:REVIEWED 2002-03-22 : OK
  2743. fprintf(f, " s_FinalizerCallResult_ObjectCount = %d\n", s_FinalizerCallResult_ObjectCount); // SEC:REVIEWED 2002-03-22 : OK
  2744. fprintf(f, " s_FinalizerEnum_ObjectCount = %d\n", s_FinalizerEnum_ObjectCount); // SEC:REVIEWED 2002-03-22 : OK
  2745. fprintf(f, " s_FinalizerEnumSink_ObjectCount = %d\n", s_FinalizerEnumSink_ObjectCount); // SEC:REVIEWED 2002-03-22 : OK
  2746. fprintf(f, " s_FinalizerInBoundSink_ObjectCount = %d\n\n", s_FinalizerInBoundSink_ObjectCount); // SEC:REVIEWED 2002-03-22 : OK
  2747. }
  2748. // ==========================================================================
  2749. // ==========================================================================
  2750. // CWmiFinalizerInboundSink
  2751. // ==========================================================================
  2752. // ==========================================================================
  2753. //***************************************************************************
  2754. //
  2755. //***************************************************************************
  2756. CWmiFinalizerInboundSink::CWmiFinalizerInboundSink(CWmiFinalizer *pFinalizer)
  2757. : m_lRefCount(0), m_lInternalRefCount (0),m_pFinalizer(pFinalizer), m_bSetStatusCalled(false)
  2758. {
  2759. InterlockedIncrement ( & s_FinalizerInBoundSink_ObjectCount ) ;
  2760. m_pFinalizer->AddRef();
  2761. gClientCounter.AddClientPtr(&m_Entry);
  2762. }
  2763. //***************************************************************************
  2764. //
  2765. //***************************************************************************
  2766. CWmiFinalizerInboundSink::~CWmiFinalizerInboundSink()
  2767. {
  2768. InterlockedDecrement ( & s_FinalizerInBoundSink_ObjectCount ) ;
  2769. gClientCounter.RemoveClientPtr(&m_Entry);
  2770. }
  2771. //***************************************************************************
  2772. //
  2773. //***************************************************************************
  2774. void CWmiFinalizerInboundSink::CallBackRelease ()
  2775. {
  2776. if (!m_bSetStatusCalled)
  2777. {
  2778. //FNLZR_ASSERT(__TEXT("CWmiFinalizerInboundSink::~CWmiFinalizerInboundSink - Released sink without calling SetStatus! Sending WBEM_E_FAILED to client!"), WBEM_E_INVALID_OPERATION);
  2779. m_pFinalizer->SetStatus(0, WBEM_E_UNEXPECTED, NULL, NULL);
  2780. ERRORTRACE((LOG_WBEMCORE, "Finalizer: Sink released without SetStatus being called\n"));
  2781. }
  2782. m_pFinalizer->UnregisterInboundSink(this);
  2783. m_pFinalizer->Release();
  2784. }
  2785. //***************************************************************************
  2786. //
  2787. //***************************************************************************
  2788. STDMETHODIMP CWmiFinalizerInboundSink::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  2789. {
  2790. // SEC:REVIEWED 2002-03-22 : Should we wrap this in EH? <ppvObj> may point to garbage or be NULL
  2791. *ppvObj = 0;
  2792. if ((IID_IUnknown==riid) || (IID_IWbemObjectSink == riid))
  2793. {
  2794. *ppvObj = this;
  2795. AddRef();
  2796. return NOERROR;
  2797. }
  2798. return E_NOINTERFACE;
  2799. }
  2800. //***************************************************************************
  2801. //
  2802. //***************************************************************************
  2803. ULONG CWmiFinalizerInboundSink::AddRef()
  2804. {
  2805. ULONG uNewCount = InterlockedIncrement(&m_lRefCount);
  2806. if ( uNewCount == 1 )
  2807. {
  2808. InternalAddRef () ;
  2809. }
  2810. // printf("CWmiFinalizerInboundSink::Release: 0x%p", this);
  2811. return uNewCount;
  2812. }
  2813. //***************************************************************************
  2814. //
  2815. //***************************************************************************
  2816. ULONG CWmiFinalizerInboundSink::Release()
  2817. {
  2818. ULONG uNewCount = InterlockedDecrement(&m_lRefCount);
  2819. // printf("CWmiFinalizerInboundSink::Release: 0x%p", this);
  2820. if (0 == uNewCount)
  2821. {
  2822. CallBackRelease () ;
  2823. InternalRelease () ;
  2824. }
  2825. return uNewCount;
  2826. }
  2827. //***************************************************************************
  2828. //
  2829. //***************************************************************************
  2830. ULONG CWmiFinalizerInboundSink::InternalAddRef()
  2831. {
  2832. ULONG uNewCount = InterlockedIncrement(&m_lInternalRefCount);
  2833. // printf("CWmiFinalizerInboundSink::Release: 0x%p", this);
  2834. return uNewCount;
  2835. }
  2836. //***************************************************************************
  2837. //
  2838. //***************************************************************************
  2839. ULONG CWmiFinalizerInboundSink::InternalRelease()
  2840. {
  2841. ULONG uNewCount = InterlockedDecrement(&m_lInternalRefCount);
  2842. // printf("CWmiFinalizerInboundSink::Release: 0x%p", this);
  2843. if (0 == uNewCount)
  2844. {
  2845. delete this ;
  2846. }
  2847. return uNewCount;
  2848. }
  2849. //***************************************************************************
  2850. //
  2851. //***************************************************************************
  2852. STDMETHODIMP CWmiFinalizerInboundSink::Indicate(
  2853. /*[in]*/ long lObjectCount,
  2854. /*[in, size_is(lObjectCount)]*/
  2855. IWbemClassObject** apObjArray
  2856. )
  2857. {
  2858. // If someone is trying to indicate NULL objects, reject and return WBEM_E_INVALID_PARAMETER
  2859. if ( apObjArray == NULL )
  2860. return WBEM_E_INVALID_PARAMETER;
  2861. // Update status variable to show that indicate has been called at least once
  2862. m_pFinalizer->UpdateStatus ( WMI_FNLZR_STATE_ACTIVE );
  2863. // Special case: Call has been cancelled.
  2864. if ( m_pFinalizer->IsCallCancelled() )
  2865. return WBEM_E_CALL_CANCELLED;
  2866. return m_pFinalizer->Indicate(lObjectCount, apObjArray);
  2867. }
  2868. //***************************************************************************
  2869. //
  2870. //***************************************************************************
  2871. STDMETHODIMP CWmiFinalizerInboundSink::SetStatus(
  2872. /*[in]*/ long lFlags,
  2873. /*[in]*/ HRESULT hResult,
  2874. /*[in]*/ BSTR strParam,
  2875. /*[in]*/ IWbemClassObject* pObjParam
  2876. )
  2877. {
  2878. // Update status variable to show that SetStatus has been called but not yet delivered
  2879. // to client
  2880. m_pFinalizer->UpdateStatus ( WMI_FNLZR_STATE_CORE_COMPLETE );
  2881. // Special case: Call has been cancelled.
  2882. if ( m_pFinalizer->IsCallCancelled() )
  2883. return WBEM_E_CALL_CANCELLED;
  2884. if (lFlags == WBEM_STATUS_COMPLETE)
  2885. {
  2886. m_bSetStatusCalled = true;
  2887. }
  2888. return m_pFinalizer->SetStatus(lFlags, hResult, strParam, pObjParam);
  2889. }
  2890. //***************************************************************************
  2891. //
  2892. //***************************************************************************
  2893. STDMETHODIMP CWmiFinalizerInboundSink::Set(
  2894. /*[in]*/ long lFlags,
  2895. /*[in]*/ REFIID riid,
  2896. /*[in, iid_is(riid)]*/ void *pComObject
  2897. )
  2898. {
  2899. #ifdef DBG
  2900. DebugBreak();
  2901. #endif
  2902. return WBEM_E_NOT_SUPPORTED;
  2903. }
  2904. //***************************************************************************
  2905. //
  2906. //***************************************************************************
  2907. CWmiFinalizerEnumerator::CWmiFinalizerEnumerator(CWmiFinalizer *pFinalizer )
  2908. :
  2909. m_lRefCount(0),
  2910. m_lInternalRefCount(0),
  2911. m_pFinalizer(pFinalizer),
  2912. m_ulCount(0),
  2913. m_pDestSink (NULL),
  2914. m_hSignalCompletion (NULL),
  2915. m_pSec (NULL),
  2916. m_XSmartEnum( this ),
  2917. m_pEnumMarshal (NULL)
  2918. {
  2919. //
  2920. // Cloning fix. We need to keep the state of the enumerator.
  2921. // This means keeping individual wait event as well as object
  2922. // position
  2923. //
  2924. m_hWaitOnResultSet = CreateEvent(NULL, FALSE, FALSE, NULL);
  2925. if (NULL == m_hWaitOnResultSet) throw CX_MemoryException();
  2926. m_uCurObjectPosition = 0 ;
  2927. m_ulSemisyncWakeupCall = 0 ;
  2928. m_bSetStatusConsumed = FALSE ;
  2929. InterlockedIncrement ( &s_FinalizerEnum_ObjectCount ) ;
  2930. m_pFinalizer->AddRef();
  2931. InitializeListHead(&m_HeadNextAsync);
  2932. gClientCounter.AddClientPtr(&m_Entry);
  2933. }
  2934. //***************************************************************************
  2935. //
  2936. //***************************************************************************
  2937. CWmiFinalizerEnumerator::~CWmiFinalizerEnumerator()
  2938. {
  2939. InterlockedDecrement ( & s_FinalizerEnum_ObjectCount ) ;
  2940. if ( m_hSignalCompletion )
  2941. {
  2942. CloseHandle (m_hSignalCompletion);
  2943. m_hSignalCompletion = NULL;
  2944. }
  2945. CloseHandle ( m_hWaitOnResultSet ) ;
  2946. m_hWaitOnResultSet = NULL ;
  2947. IUnknown * pUnk = (IUnknown *)InterlockedCompareExchangePointer((PVOID *)&m_pEnumMarshal,0,m_pEnumMarshal);
  2948. if (pUnk) pUnk->Release();
  2949. gClientCounter.RemoveClientPtr(&m_Entry);
  2950. }
  2951. void CWmiFinalizerEnumerator::CallBackRelease ()
  2952. {
  2953. m_pFinalizer->SetInternalStatus ( CWmiFinalizer::QueueStatus::RequestReleased );
  2954. m_pFinalizer->CancelTaskInternal();
  2955. m_pFinalizer->UnregisterEnumerator ( this ) ;
  2956. SetEvent ( m_hWaitOnResultSet ); // in case Cancel did not do it
  2957. m_clientLock.Enter();
  2958. while (!IsListEmpty(&m_HeadNextAsync))
  2959. {
  2960. m_clientLock.Leave();
  2961. Sleep(100);
  2962. m_clientLock.Enter();
  2963. }
  2964. m_clientLock.Leave();
  2965. m_pFinalizer->Release();
  2966. m_pFinalizer = NULL;
  2967. }
  2968. //***************************************************************************
  2969. //
  2970. //***************************************************************************
  2971. ULONG CWmiFinalizerEnumerator::AddRef()
  2972. {
  2973. ULONG uNewCount = InterlockedIncrement(&m_lRefCount);
  2974. if ( uNewCount == 1 )
  2975. {
  2976. InternalAddRef () ;
  2977. }
  2978. // printf("CWmiFinalizerCallResult::Release: 0x%p", this);
  2979. return uNewCount;
  2980. }
  2981. //***************************************************************************
  2982. //
  2983. //***************************************************************************
  2984. ULONG CWmiFinalizerEnumerator::Release()
  2985. {
  2986. ULONG uNewCount = InterlockedDecrement(&m_lRefCount);
  2987. // printf("CWmiFinalizerCallResult::Release: 0x%p", this);
  2988. if (0 == uNewCount)
  2989. {
  2990. _DBG_ASSERT(2 == m_lInternalRefCount);
  2991. CallBackRelease () ;
  2992. InternalRelease () ;
  2993. }
  2994. return uNewCount;
  2995. }
  2996. //***************************************************************************
  2997. //
  2998. //***************************************************************************
  2999. ULONG CWmiFinalizerEnumerator::InternalAddRef()
  3000. {
  3001. ULONG uNewCount = InterlockedIncrement(&m_lInternalRefCount);
  3002. // printf("CWmiFinalizerCallResult::Release: 0x%p", this);
  3003. return uNewCount;
  3004. }
  3005. //***************************************************************************
  3006. //
  3007. //***************************************************************************
  3008. ULONG CWmiFinalizerEnumerator::InternalRelease()
  3009. {
  3010. ULONG uNewCount = InterlockedDecrement(&m_lInternalRefCount);
  3011. // printf("CWmiFinalizerCallResult::Release: 0x%p", this);
  3012. if (0 == uNewCount)
  3013. {
  3014. delete this ;
  3015. }
  3016. return uNewCount;
  3017. }
  3018. //***************************************************************************
  3019. //
  3020. //***************************************************************************
  3021. STDMETHODIMP CWmiFinalizerEnumerator::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  3022. {
  3023. if (NULL == ppvObj) return E_POINTER;
  3024. // Added support for IID_IWbemFetchSmartEnum
  3025. if ((IID_IUnknown==riid) || (IID_IEnumWbemClassObject==riid) )
  3026. {
  3027. *ppvObj = this;
  3028. AddRef();
  3029. return NOERROR;
  3030. }
  3031. else if ( IID_IWbemFetchSmartEnum == riid )
  3032. {
  3033. *ppvObj = (IWbemFetchSmartEnum*) this;
  3034. AddRef();
  3035. return NOERROR;
  3036. }
  3037. {
  3038. *ppvObj = 0;
  3039. return E_NOINTERFACE;
  3040. }
  3041. }
  3042. void CWmiFinalizerEnumerator::Add_NextAsync(InsertableEvent * pInsert)
  3043. {
  3044. CInCritSec ics(&m_clientLock);
  3045. InsertTailList(&m_HeadNextAsync,&pInsert->m_Entry);
  3046. }
  3047. void CWmiFinalizerEnumerator::Remove_NextAsync(InsertableEvent * pInsert)
  3048. {
  3049. CInCritSec ics(&m_clientLock);
  3050. RemoveEntryList(&pInsert->m_Entry);
  3051. delete pInsert;
  3052. }
  3053. //***************************************************************************
  3054. //
  3055. //***************************************************************************
  3056. STDMETHODIMP CWmiFinalizerEnumerator::Reset()
  3057. {
  3058. if(!m_Security.AccessCheck())
  3059. return WBEM_E_ACCESS_DENIED;
  3060. BOOL bDidIWait = FALSE;
  3061. if (InterlockedCompareExchangePointer(&m_hSignalCompletion,m_hSignalCompletion,0))
  3062. {
  3063. CCoreQueue::QueueWaitForSingleObject(m_hSignalCompletion, INFINITE);
  3064. bDidIWait = TRUE;
  3065. }
  3066. CInCritSec cs(&m_clientLock); // SEC:REVIEWED 2002-03-22 : Assumes entry
  3067. if ( m_pFinalizer->IsRestartable ( ) )
  3068. {
  3069. m_uCurObjectPosition = 0;
  3070. m_bSetStatusConsumed = false;
  3071. if (bDidIWait) SetCompletionSignalEvent();
  3072. return WBEM_NO_ERROR;
  3073. }
  3074. else
  3075. {
  3076. if (bDidIWait) SetCompletionSignalEvent();
  3077. return WBEM_E_INVALID_OPERATION;
  3078. }
  3079. }
  3080. //***************************************************************************
  3081. //
  3082. //***************************************************************************
  3083. STDMETHODIMP CWmiFinalizerEnumerator::Next(
  3084. /*[in]*/ long lTimeout,
  3085. /*[in]*/ ULONG uCount,
  3086. /*[out, size_is(uCount), length_is(*puReturned)]*/ IWbemClassObject** apObjects,
  3087. /*[out]*/ ULONG* puReturned
  3088. )
  3089. {
  3090. if(!m_Security.AccessCheck())
  3091. return WBEM_E_ACCESS_DENIED;
  3092. CInCritSec cs(&m_clientLock); // SEC:REVIEWED 2002-03-22 : Assumes entry
  3093. if ( ( puReturned == NULL ) || ( apObjects == NULL ) || (lTimeout < 0 && lTimeout != WBEM_INFINITE) )
  3094. {
  3095. return WBEM_E_INVALID_PARAMETER ;
  3096. }
  3097. if ( uCount == 0 )
  3098. {
  3099. return WBEM_S_NO_ERROR;
  3100. }
  3101. *puReturned = 0 ;
  3102. m_ulSemisyncWakeupCall = uCount ;
  3103. return m_pFinalizer->PullObjects(lTimeout, uCount, apObjects, puReturned, this );
  3104. }
  3105. //***************************************************************************
  3106. //
  3107. //***************************************************************************
  3108. STDMETHODIMP CWmiFinalizerEnumerator::NextAsync(
  3109. /*[in]*/ ULONG uCount,
  3110. /*[in]*/ IWbemObjectSink* pSink
  3111. )
  3112. {
  3113. if(!m_Security.AccessCheck())
  3114. return WBEM_E_ACCESS_DENIED;
  3115. // If delivery sink is NULL
  3116. if ( pSink == NULL )
  3117. {
  3118. return WBEM_E_INVALID_PARAMETER ;
  3119. }
  3120. // If requested count is 0
  3121. if ( uCount == 0 )
  3122. {
  3123. return WBEM_S_FALSE;
  3124. }
  3125. HRESULT hRes;
  3126. if ( m_hSignalCompletion == NULL )
  3127. {
  3128. HANDLE hTmpEvent = CreateEvent ( NULL, FALSE, TRUE, NULL );
  3129. if (NULL == hTmpEvent) return WBEM_E_FAILED;
  3130. if (InterlockedCompareExchangePointer(&m_hSignalCompletion,hTmpEvent,NULL))
  3131. {
  3132. CloseHandle(hTmpEvent);
  3133. }
  3134. }
  3135. if ( m_pFinalizer->GetInternalStatus() != m_pFinalizer->NoError )
  3136. return WBEM_E_FAILED;
  3137. CCoreQueue::QueueWaitForSingleObject(m_hSignalCompletion, INFINITE);
  3138. if ( m_pFinalizer->GetInternalStatus() != m_pFinalizer->NoError )
  3139. {
  3140. // Dont forget to wake up any other threads waiting!
  3141. SetCompletionSignalEvent();
  3142. return WBEM_E_FAILED;
  3143. }
  3144. if ( m_bSetStatusConsumed )
  3145. {
  3146. m_pFinalizer->SetSinkToIdentity ( pSink );
  3147. m_pFinalizer->DoSetStatus ( pSink, WBEM_STATUS_COMPLETE, m_pFinalizer->GetFinalResult ( ), 0, 0 );
  3148. SetCompletionSignalEvent();
  3149. return WBEM_S_FALSE ;
  3150. }
  3151. // If we are already done.
  3152. m_pDestSink = pSink;
  3153. m_pDestSink->AddRef(); // SEC:REVIEWED 2002-03-22 : Needs EH in case sink is garbage
  3154. m_ulCount = uCount;
  3155. m_pFinalizer->SetSinkToIdentity ( m_pDestSink );
  3156. return m_pFinalizer->NextAsync (this);
  3157. }
  3158. //***************************************************************************
  3159. //
  3160. //***************************************************************************
  3161. HRESULT CWmiFinalizerEnumerator::_NextAsync ( )
  3162. {
  3163. HRESULT hRes = WBEM_S_NO_ERROR;
  3164. DWORD dwRet;
  3165. RevertToSelf ( ); // SEC:REVIEWED 2002-03-22 : Needs check
  3166. // Grab the client lock. All remainding ::NextAsync calls will be queued up
  3167. CInCritSec cs(&m_clientLock); // SEC:REVIEWED 2002-03-22 : Assumes entry
  3168. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3169. // Is the operation complete? If so, we should notify the sink
  3170. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3171. if ( m_bSetStatusConsumed )
  3172. {
  3173. HRESULT hFinalRes;
  3174. m_pFinalizer->GetOperationResult ( 0, INFINITE, &hFinalRes );
  3175. m_pFinalizer->DoSetStatus ( m_pDestSink, WBEM_STATUS_COMPLETE, hFinalRes, 0, 0 );
  3176. hRes = WBEM_S_FALSE;
  3177. }
  3178. else
  3179. {
  3180. // NOTE [marioh] : This is no longer needed since we've decided to go with the Win2k solution
  3181. // for the time being.
  3182. // If we fail to impersonate, we dont continue!!!!
  3183. //CAutoRevert AutoRevert (m_pFinalizer);
  3184. //if ( AutoRevert.IsImpersonated() == FALSE )
  3185. // return WBEM_E_CRITICAL_ERROR;
  3186. IWbemClassObject **pArray = new IWbemClassObject *[m_ulCount];
  3187. if (pArray == NULL)
  3188. {
  3189. m_pFinalizer->DoSetStatus ( m_pDestSink, WBEM_STATUS_COMPLETE, WBEM_E_OUT_OF_MEMORY, 0, 0 );
  3190. }
  3191. else
  3192. {
  3193. ULONG uReturned = 0;
  3194. m_pFinalizer->SetSemisyncWakeupCall (m_ulCount);
  3195. HRESULT hr = m_pFinalizer->PullObjects(INFINITE, m_ulCount, pArray, &uReturned, this, TRUE, FALSE );
  3196. if ( FAILED (hr) )
  3197. {
  3198. if ( hr == WBEM_E_CALL_CANCELLED )
  3199. {
  3200. m_pFinalizer->DoSetStatus (m_pDestSink, WBEM_STATUS_COMPLETE, WBEM_E_CALL_CANCELLED, 0, 0);
  3201. }
  3202. }
  3203. if (SUCCEEDED(hr) && uReturned)
  3204. {
  3205. for (int i=0; i!=uReturned; i++)
  3206. {
  3207. if ( m_pFinalizer->HasWriteOnlyProps (pArray[i]) )
  3208. m_pFinalizer->ZapWriteOnlyProps (pArray[i]);
  3209. }
  3210. hr = m_pFinalizer->DoIndicate(m_pDestSink, uReturned, pArray);
  3211. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3212. // Cleanup the array
  3213. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3214. for (ULONG i = 0; i != uReturned; i++)
  3215. {
  3216. pArray[i]->Release();
  3217. }
  3218. }
  3219. delete [] pArray;
  3220. if ( SUCCEEDED (hr) )
  3221. {
  3222. // If number of requested objects == number of objects delivered, SetStatus (WBEM_S_NO_ERROR)
  3223. if ( uReturned == m_ulCount )
  3224. {
  3225. m_pFinalizer->DoSetStatus (m_pDestSink, WBEM_STATUS_COMPLETE, WBEM_S_NO_ERROR, 0, 0, TRUE );
  3226. }
  3227. // If less objects are delivered, SetStatus (WBEM_S_FALSE)
  3228. else
  3229. {
  3230. m_pFinalizer->DoSetStatus (m_pDestSink, WBEM_STATUS_COMPLETE, WBEM_S_FALSE, 0, 0, TRUE );
  3231. }
  3232. }
  3233. else
  3234. {
  3235. m_pFinalizer->DoSetStatusCancel (m_pDestSink, hr );
  3236. }
  3237. }
  3238. }
  3239. return hRes;
  3240. }
  3241. //***************************************************************************
  3242. //
  3243. //***************************************************************************
  3244. DWORD WINAPI CWmiFinalizerEnumerator::ThreadBootstrapNextAsync ( PVOID pParam )
  3245. {
  3246. HRESULT hRes;
  3247. InsertableEvent * pInsert;
  3248. CWmiFinalizerEnumerator* pEnum;
  3249. pInsert = (InsertableEvent *)pParam;
  3250. pInsert->ThreadId = GetCurrentThreadId();
  3251. pEnum = pInsert->pEnum;
  3252. try
  3253. {
  3254. hRes = pEnum->_NextAsync();
  3255. }
  3256. catch (...)
  3257. {
  3258. ExceptionCounter c;
  3259. };
  3260. pEnum->GetDestSink()->Release();
  3261. pEnum->NULLDestSink();
  3262. pEnum->SetCompletionSignalEvent ();
  3263. pEnum->Remove_NextAsync(pInsert);
  3264. return hRes;
  3265. }
  3266. //***************************************************************************
  3267. //
  3268. //***************************************************************************
  3269. STDMETHODIMP CWmiFinalizerEnumerator::Clone(
  3270. /*[out]*/ IEnumWbemClassObject** ppEnum
  3271. )
  3272. {
  3273. if(!m_Security.AccessCheck())
  3274. return WBEM_E_ACCESS_DENIED;
  3275. CInCritSec cs(&m_clientLock); // SEC:REVIEWED 2002-03-22 : Assumes entry
  3276. if ( ppEnum == NULL )
  3277. {
  3278. return WBEM_E_INVALID_PARAMETER ;
  3279. }
  3280. // If the enumerator is not restartable, it is forward only, and hence cannot
  3281. // be cloned.
  3282. if ( !m_pFinalizer->IsRestartable() )
  3283. {
  3284. return WBEM_E_INVALID_OPERATION;
  3285. }
  3286. HRESULT hRes = S_OK ;
  3287. //
  3288. // Get the enumerator
  3289. //
  3290. hRes = m_pFinalizer->GetResultObject ( m_uCurObjectPosition, IID_IEnumWbemClassObject, (void**)ppEnum ) ;
  3291. //
  3292. // Keep state information
  3293. //
  3294. if ( SUCCEEDED ( hRes ) )
  3295. {
  3296. ((CWmiFinalizerEnumerator*)(*ppEnum))->m_uCurObjectPosition = m_uCurObjectPosition ;
  3297. ((CWmiFinalizerEnumerator*)(*ppEnum))->m_bSetStatusConsumed = m_bSetStatusConsumed ;
  3298. }
  3299. return hRes;
  3300. }
  3301. //***************************************************************************
  3302. //
  3303. //***************************************************************************
  3304. STDMETHODIMP CWmiFinalizerEnumerator::Skip(
  3305. /*[in]*/ long lTimeout,
  3306. /*[in]*/ ULONG nCount
  3307. )
  3308. {
  3309. if(!m_Security.AccessCheck())
  3310. return WBEM_E_ACCESS_DENIED;
  3311. if ( (lTimeout < 0 && lTimeout != WBEM_INFINITE) )
  3312. {
  3313. return WBEM_E_INVALID_PARAMETER;
  3314. }
  3315. CInCritSec cs(&m_clientLock); // SEC:REVIEWED 2002-03-22 : Assumes entry
  3316. m_ulSemisyncWakeupCall = nCount ;
  3317. return m_pFinalizer->Skip(lTimeout, nCount, this ) ;
  3318. }
  3319. //***************************************************************************
  3320. // IWbemFetchSmartEnum
  3321. // GetSmartEnum
  3322. //***************************************************************************
  3323. STDMETHODIMP CWmiFinalizerEnumerator::GetSmartEnum ( IWbemWCOSmartEnum** ppSmartEnum )
  3324. {
  3325. if(!m_Security.AccessCheck())
  3326. return WBEM_E_ACCESS_DENIED;
  3327. HRESULT hRes;
  3328. if (NULL == m_pEnumMarshal)
  3329. {
  3330. _IWbemEnumMarshaling * pEnum = NULL;
  3331. if (FAILED(hRes = CoCreateInstance ( CLSID__WbemEnumMarshaling,
  3332. NULL, CLSCTX_INPROC_SERVER, IID__IWbemEnumMarshaling,
  3333. (void**) &pEnum )))
  3334. {
  3335. return hRes;
  3336. }
  3337. if (InterlockedCompareExchangePointer((PVOID *)&m_pEnumMarshal,pEnum,0))
  3338. {
  3339. pEnum->Release(); // we've been beaten
  3340. }
  3341. }
  3342. return m_XSmartEnum.QueryInterface( IID_IWbemWCOSmartEnum, (void**) ppSmartEnum );
  3343. }
  3344. //***************************************************************************
  3345. // SmartEnum
  3346. // QI
  3347. //***************************************************************************
  3348. STDMETHODIMP CWmiFinalizerEnumerator::XSmartEnum::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  3349. {
  3350. *ppvObj = 0;
  3351. if ( IID_IUnknown==riid || IID_IWbemWCOSmartEnum == riid)
  3352. {
  3353. *ppvObj = (IWbemWCOSmartEnum*)this;
  3354. AddRef();
  3355. return NOERROR;
  3356. }
  3357. else
  3358. {
  3359. return m_pOuter->QueryInterface( riid, ppvObj );
  3360. }
  3361. }
  3362. //***************************************************************************
  3363. // SmartEnum
  3364. // Addref
  3365. //***************************************************************************
  3366. ULONG CWmiFinalizerEnumerator::XSmartEnum::AddRef( void )
  3367. {
  3368. return m_pOuter->AddRef();
  3369. }
  3370. //***************************************************************************
  3371. // SmartEnum
  3372. // Release
  3373. //***************************************************************************
  3374. ULONG CWmiFinalizerEnumerator::XSmartEnum::Release( void )
  3375. {
  3376. return m_pOuter->Release();
  3377. }
  3378. //***************************************************************************
  3379. // SmartEnum
  3380. // Release
  3381. //***************************************************************************
  3382. STDMETHODIMP CWmiFinalizerEnumerator::XSmartEnum:: Next( REFGUID proxyGUID, long lTimeout, ULONG uCount,
  3383. ULONG* puReturned, ULONG* pdwBuffSize, BYTE** pBuffer)
  3384. {
  3385. if(!m_pOuter->m_Security.AccessCheck())
  3386. return WBEM_E_ACCESS_DENIED;
  3387. HRESULT hRes = WBEM_S_NO_ERROR;
  3388. IWbemClassObject** apObj = new IWbemClassObject* [uCount];
  3389. if ( !apObj )
  3390. hRes = WBEM_E_OUT_OF_MEMORY;
  3391. else
  3392. {
  3393. // Call next on real enumerator
  3394. hRes = m_pOuter->Next ( lTimeout, uCount, apObj, puReturned );
  3395. if ( SUCCEEDED (hRes) )
  3396. {
  3397. if ( *puReturned > 0 )
  3398. {
  3399. HRESULT hResMarshal = m_pOuter->m_pEnumMarshal->GetMarshalPacket ( proxyGUID, *puReturned, apObj, pdwBuffSize, pBuffer );
  3400. if ( FAILED (hResMarshal) )
  3401. hRes = hResMarshal;
  3402. }
  3403. else
  3404. {
  3405. *pdwBuffSize = 0;
  3406. *pBuffer = NULL;
  3407. }
  3408. for ( ULONG ulIn=0; ulIn < *puReturned; ulIn++ )
  3409. {
  3410. try
  3411. {
  3412. apObj[ulIn]->Release();
  3413. }
  3414. catch(...)
  3415. {
  3416. }
  3417. }
  3418. }
  3419. delete [] apObj;
  3420. }
  3421. return hRes;
  3422. }
  3423. // ===================================================================================================================================================
  3424. // ===================================================================================================================================================
  3425. //***************************************************************************
  3426. //
  3427. //***************************************************************************
  3428. CWmiFinalizerCallResult::CWmiFinalizerCallResult (
  3429. CWmiFinalizer *pFinalizer
  3430. ) : m_lInternalRefCount(0),
  3431. m_pFinalizer(pFinalizer),
  3432. m_lFlags(-1),
  3433. m_hResult(0),
  3434. m_strParam(0),
  3435. m_pObj(0),
  3436. m_pServices(0),
  3437. m_bGotObject(false),
  3438. m_bGotServices(false),
  3439. m_pErrorObj(NULL),
  3440. m_lRefCount(0)
  3441. {
  3442. InterlockedIncrement ( & s_FinalizerCallResult_ObjectCount );
  3443. gClientCounter.AddClientPtr(&m_Entry);
  3444. }
  3445. //***************************************************************************
  3446. //
  3447. //***************************************************************************
  3448. CWmiFinalizerCallResult::~CWmiFinalizerCallResult()
  3449. {
  3450. InterlockedDecrement ( & s_FinalizerCallResult_ObjectCount ) ;
  3451. if (m_pObj)
  3452. m_pObj->Release();
  3453. SysFreeString(m_strParam);
  3454. if (m_pServices)
  3455. m_pServices->Release();
  3456. if (m_pErrorObj)
  3457. m_pErrorObj->Release();
  3458. gClientCounter.RemoveClientPtr(&m_Entry);
  3459. }
  3460. //***************************************************************************
  3461. //
  3462. //***************************************************************************
  3463. STDMETHODIMP CWmiFinalizerCallResult::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  3464. {
  3465. *ppvObj = 0;
  3466. if ((IID_IUnknown==riid) || (IID_IWbemCallResult == riid))
  3467. {
  3468. *ppvObj = this;
  3469. AddRef();
  3470. return NOERROR;
  3471. }
  3472. return E_NOINTERFACE;
  3473. }
  3474. //***************************************************************************
  3475. //
  3476. //***************************************************************************
  3477. ULONG CWmiFinalizerCallResult::AddRef()
  3478. {
  3479. ULONG uNewCount = InterlockedIncrement(&m_lRefCount);
  3480. if (uNewCount == 1)
  3481. m_pFinalizer->AddRef () ;
  3482. return uNewCount;
  3483. }
  3484. //***************************************************************************
  3485. //
  3486. //***************************************************************************
  3487. ULONG CWmiFinalizerCallResult::Release()
  3488. {
  3489. ULONG uNewCount = InterlockedDecrement(&m_lRefCount);
  3490. if (uNewCount == 0)
  3491. {
  3492. m_pFinalizer->CancelTaskInternal();
  3493. m_pFinalizer->Release () ;
  3494. }
  3495. return uNewCount;
  3496. }
  3497. //***************************************************************************
  3498. //
  3499. //***************************************************************************
  3500. ULONG CWmiFinalizerCallResult::InternalAddRef()
  3501. {
  3502. ULONG uNewCount = InterlockedIncrement(&m_lInternalRefCount);
  3503. return uNewCount;
  3504. }
  3505. //***************************************************************************
  3506. //
  3507. //***************************************************************************
  3508. ULONG CWmiFinalizerCallResult::InternalRelease()
  3509. {
  3510. ULONG uNewCount = InterlockedDecrement(&m_lInternalRefCount);
  3511. if (0 == uNewCount)
  3512. {
  3513. delete this ;
  3514. }
  3515. return uNewCount;
  3516. }
  3517. //***************************************************************************
  3518. //
  3519. //***************************************************************************
  3520. HRESULT CWmiFinalizerCallResult::GetResultObject(
  3521. /*[in]*/ long lTimeout,
  3522. /*[out]*/ IWbemClassObject** ppResultObject
  3523. )
  3524. {
  3525. if(!m_Security.AccessCheck())
  3526. return WBEM_E_ACCESS_DENIED;
  3527. if ( ( ppResultObject==NULL ) || (lTimeout < 0 && lTimeout != WBEM_INFINITE) )
  3528. {
  3529. return WBEM_E_INVALID_PARAMETER ;
  3530. }
  3531. if (!m_bGotObject)
  3532. {
  3533. HRESULT hrResult = WBEM_S_NO_ERROR ;
  3534. HRESULT hr = m_pFinalizer->GetOperationResult(0, lTimeout, &hrResult);
  3535. if (FAILED(hr))
  3536. {
  3537. return WBEM_E_FAILED ;
  3538. }
  3539. else if (hr == WBEM_S_TIMEDOUT)
  3540. {
  3541. return WBEM_S_TIMEDOUT;
  3542. }
  3543. else if ( FAILED ( hrResult ) )
  3544. {
  3545. return hrResult ;
  3546. }
  3547. if (FAILED(hrResult))
  3548. SetErrorInfo();
  3549. {
  3550. CWmiFinalizerObj *pFinalizerObj=NULL;
  3551. bool bFinished = false;
  3552. HRESULT hRes = WBEM_E_NOT_FOUND;
  3553. while (!bFinished)
  3554. {
  3555. hRes = m_pFinalizer->GetNextObject(&pFinalizerObj);
  3556. if (FAILED(hRes))
  3557. {
  3558. return WBEM_E_FAILED ;
  3559. }
  3560. else if (hRes == WBEM_S_FALSE)
  3561. {
  3562. return WBEM_S_TIMEDOUT;
  3563. }
  3564. if (pFinalizerObj->m_objectType == CWmiFinalizerObj::object)
  3565. {
  3566. m_bGotObject = true;
  3567. m_pObj = pFinalizerObj->m_pObj;
  3568. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3569. // Catch any nasty attempts to crash WinMgmt through bad
  3570. // pointers.
  3571. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3572. try
  3573. {
  3574. *ppResultObject = pFinalizerObj->m_pObj;
  3575. }
  3576. catch (...)
  3577. {
  3578. ExceptionCounter c;
  3579. delete pFinalizerObj;
  3580. return WBEM_E_INVALID_PARAMETER;
  3581. }
  3582. if ( pFinalizerObj->m_pObj )
  3583. {
  3584. //Need 2 add-refs, one because we hold on to it, the other because we pass it back to the user!
  3585. pFinalizerObj->m_pObj->AddRef();
  3586. pFinalizerObj->m_pObj->AddRef();
  3587. }
  3588. bFinished = true;
  3589. hrResult = WBEM_S_NO_ERROR ;
  3590. }
  3591. else if ((pFinalizerObj->m_objectType == CWmiFinalizerObj::status) && (pFinalizerObj->m_lFlags == WBEM_STATUS_COMPLETE))
  3592. {
  3593. hrResult = pFinalizerObj->m_hRes;
  3594. bFinished = true;
  3595. }
  3596. else if (pFinalizerObj->m_objectType == CWmiFinalizerObj::status)
  3597. {
  3598. //We have a non-completion status object...
  3599. }
  3600. delete pFinalizerObj;
  3601. }
  3602. }
  3603. return hrResult;
  3604. }
  3605. else
  3606. {
  3607. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3608. // Catch any nasty attempts to crash WinMgmt through bad
  3609. // pointers.
  3610. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3611. try
  3612. {
  3613. m_pObj->AddRef();
  3614. *ppResultObject = m_pObj;
  3615. }
  3616. catch (...)
  3617. {
  3618. ExceptionCounter c;
  3619. m_pObj->Release ();
  3620. return WBEM_E_INVALID_PARAMETER;
  3621. }
  3622. return WBEM_S_NO_ERROR;
  3623. }
  3624. }
  3625. //***************************************************************************
  3626. //
  3627. //***************************************************************************
  3628. HRESULT CWmiFinalizerCallResult::GetResultString(
  3629. /*[in]*/ long lTimeout,
  3630. /*[out]*/ BSTR* pstrResultString
  3631. )
  3632. {
  3633. if(!m_Security.AccessCheck())
  3634. return WBEM_E_ACCESS_DENIED;
  3635. if ( ( pstrResultString==NULL ) || (lTimeout < 0 && lTimeout != WBEM_INFINITE) )
  3636. {
  3637. return WBEM_E_INVALID_PARAMETER ;
  3638. }
  3639. HRESULT hrResult;
  3640. HRESULT hr = m_pFinalizer->GetOperationResult(0, lTimeout, &hrResult);
  3641. if (hr != WBEM_S_NO_ERROR)
  3642. return hr;
  3643. if (FAILED(hrResult))
  3644. SetErrorInfo();
  3645. //
  3646. // BUGBUG duplicated code SysAllocString takes NULL
  3647. //
  3648. if(m_strParam)
  3649. {
  3650. try
  3651. {
  3652. *pstrResultString = SysAllocString(m_strParam);
  3653. }
  3654. catch (...)
  3655. {
  3656. ExceptionCounter c;
  3657. return WBEM_E_INVALID_PARAMETER;
  3658. }
  3659. hr = WBEM_S_NO_ERROR;
  3660. }
  3661. else
  3662. {
  3663. try
  3664. {
  3665. *pstrResultString = NULL;
  3666. }
  3667. catch (...)
  3668. {
  3669. ExceptionCounter c;
  3670. return WBEM_E_INVALID_PARAMETER;
  3671. }
  3672. if ( SUCCEEDED (hrResult) )
  3673. {
  3674. hr = WBEM_E_INVALID_OPERATION;
  3675. }
  3676. else
  3677. {
  3678. hr = hrResult;
  3679. }
  3680. }
  3681. return hr;
  3682. }
  3683. //***************************************************************************
  3684. //
  3685. //***************************************************************************
  3686. HRESULT CWmiFinalizerCallResult::GetResultServices(
  3687. /*[in]*/ long lTimeout,
  3688. /*[out]*/ IWbemServices** ppServices
  3689. )
  3690. {
  3691. if(!m_Security.AccessCheck())
  3692. return WBEM_E_ACCESS_DENIED;
  3693. if ( ( ppServices==NULL ) || (lTimeout < 0 && lTimeout != WBEM_INFINITE) )
  3694. {
  3695. return WBEM_E_INVALID_PARAMETER ;
  3696. }
  3697. if (!m_bGotServices)
  3698. {
  3699. HRESULT hrResult;
  3700. HRESULT hr = m_pFinalizer->GetOperationResult(0, lTimeout, &hrResult);
  3701. if (hr != WBEM_S_NO_ERROR)
  3702. return hr;
  3703. if (FAILED(hrResult))
  3704. SetErrorInfo();
  3705. if (SUCCEEDED(hrResult))
  3706. {
  3707. CWmiFinalizerObj *pFinalizerObj=NULL;
  3708. HRESULT hRes = m_pFinalizer->GetNextObject(&pFinalizerObj);
  3709. if (FAILED(hRes))
  3710. return hRes;
  3711. if ( hRes==WBEM_S_FALSE )
  3712. return WBEM_E_NOT_FOUND;
  3713. m_bGotServices = true;
  3714. m_pServices = (IWbemServices*)pFinalizerObj->m_pvObj;
  3715. if (ppServices)
  3716. {
  3717. try
  3718. {
  3719. *ppServices = (IWbemServices*)pFinalizerObj->m_pvObj;
  3720. }
  3721. catch (...)
  3722. {
  3723. ExceptionCounter c;
  3724. delete pFinalizerObj;
  3725. return WBEM_E_INVALID_PARAMETER;
  3726. }
  3727. if ( pFinalizerObj->m_pvObj )
  3728. {
  3729. //Need 2 add-refs, one because we hold on to it, the other because we pass it back to the user!
  3730. ((IWbemServices*)pFinalizerObj->m_pvObj)->AddRef();
  3731. ((IWbemServices*)pFinalizerObj->m_pvObj)->AddRef();
  3732. }
  3733. }
  3734. delete pFinalizerObj;
  3735. }
  3736. return hrResult;
  3737. }
  3738. else
  3739. {
  3740. try
  3741. {
  3742. *ppServices = m_pServices;
  3743. }
  3744. catch (...)
  3745. {
  3746. ExceptionCounter c;
  3747. return WBEM_E_INVALID_PARAMETER;
  3748. }
  3749. return WBEM_NO_ERROR;
  3750. }
  3751. }
  3752. //***************************************************************************
  3753. //
  3754. //***************************************************************************
  3755. HRESULT CWmiFinalizerCallResult::GetCallStatus(
  3756. /*[in]*/ long lTimeout,
  3757. /*[out]*/ long* plStatus
  3758. )
  3759. {
  3760. if(!m_Security.AccessCheck())
  3761. return WBEM_E_ACCESS_DENIED;
  3762. if ( (plStatus == NULL) || (lTimeout < 0 && lTimeout != WBEM_INFINITE) )
  3763. return WBEM_E_INVALID_PARAMETER;
  3764. HRESULT hrResult;
  3765. HRESULT hr = m_pFinalizer->GetOperationResult(0, lTimeout, &hrResult);
  3766. if (hr != WBEM_S_NO_ERROR)
  3767. {
  3768. return hr;
  3769. }
  3770. try
  3771. {
  3772. *plStatus = hrResult;
  3773. }
  3774. catch (...)
  3775. {
  3776. ExceptionCounter c;
  3777. return WBEM_E_INVALID_PARAMETER;
  3778. }
  3779. if(FAILED(hrResult))
  3780. {
  3781. SetErrorInfo();
  3782. }
  3783. return WBEM_S_NO_ERROR;
  3784. }
  3785. //***************************************************************************
  3786. //
  3787. //***************************************************************************
  3788. HRESULT CWmiFinalizerCallResult::GetResult(
  3789. /*[in]*/ long lTimeout,
  3790. /*[in]*/ long lFlags,
  3791. /*[in]*/ REFIID riid,
  3792. /*[out, iid_is(riid)]*/ void **ppvResult
  3793. )
  3794. {
  3795. #ifdef DBG
  3796. DebugBreak();
  3797. #endif
  3798. return WBEM_E_NOT_SUPPORTED;
  3799. }
  3800. //***************************************************************************
  3801. //
  3802. //***************************************************************************
  3803. HRESULT CWmiFinalizerCallResult::SetStatus(
  3804. /*[in]*/ long lFlags,
  3805. /*[in]*/ HRESULT hResult,
  3806. /*[in]*/ BSTR strParam,
  3807. /*[in]*/ IWbemClassObject* pObjParam
  3808. )
  3809. {
  3810. if (m_lFlags != -1)
  3811. {
  3812. SysFreeString(m_strParam);
  3813. m_strParam = 0;
  3814. }
  3815. if (strParam)
  3816. {
  3817. m_strParam = SysAllocString(strParam);
  3818. if (m_strParam == NULL)
  3819. return WBEM_E_OUT_OF_MEMORY;
  3820. }
  3821. m_lFlags = lFlags;
  3822. m_hResult = hResult;
  3823. if ( m_pErrorObj )
  3824. {
  3825. m_pErrorObj->Release ( );
  3826. }
  3827. m_pErrorObj = pObjParam;
  3828. if (m_pErrorObj)
  3829. {
  3830. m_pErrorObj->AddRef();
  3831. }
  3832. return WBEM_S_NO_ERROR;
  3833. }
  3834. //***************************************************************************
  3835. //
  3836. //***************************************************************************
  3837. void CWmiFinalizerCallResult::SetErrorInfo()
  3838. {
  3839. if(m_pErrorObj)
  3840. {
  3841. IErrorInfo* pInfo = NULL;
  3842. m_pErrorObj->QueryInterface(IID_IErrorInfo, (void**)&pInfo);
  3843. ::SetErrorInfo(0, pInfo);
  3844. pInfo->Release();
  3845. }
  3846. }
  3847. //***************************************************************************
  3848. // CWmiFinalizerObj Methods
  3849. //***************************************************************************
  3850. /*
  3851. * ==================================================================================================
  3852. |
  3853. | CWmiFinalizerObj::CWmiFinalizerObj(IWbemClassObject *pObj, _IWmiFinalizer* pFin )
  3854. | ---------------------------------------------------------------------------------
  3855. |
  3856. |
  3857. |
  3858. |
  3859. * ==================================================================================================
  3860. */
  3861. CWmiFinalizerObj::CWmiFinalizerObj(IWbemClassObject *pObj, _IWmiFinalizer* pFin ) : m_pObj(pObj),
  3862. m_objectType(object),
  3863. m_lFlags(0),
  3864. m_bStr(0),
  3865. m_hRes(0) ,
  3866. m_pvObj(0),
  3867. m_pFin ( pFin ),
  3868. m_hArb ( WBEM_S_ARB_NOTHROTTLING )
  3869. {
  3870. if (m_pObj)
  3871. {
  3872. m_pObj->AddRef();
  3873. CWbemObject* pObjTmp = (CWbemObject*) pObj;
  3874. if ( pObjTmp )
  3875. {
  3876. m_uSize = pObjTmp -> GetBlockLength();
  3877. if ( m_pFin )
  3878. {
  3879. m_hArb = ((CWmiFinalizer*)m_pFin)->ReportMemoryUsage ( 0, m_uSize ) ;
  3880. }
  3881. }
  3882. else
  3883. {
  3884. m_uSize = 0;
  3885. }
  3886. }
  3887. }
  3888. /*
  3889. * ==================================================================================================
  3890. |
  3891. | CWmiFinalizerObj::CWmiFinalizerObj (CWmiFinalizerObj& obj)
  3892. | ----------------------------------------------------------
  3893. |
  3894. | Copyconstructor for CWmiFinalizerObj. This is ONLY used on restartable enumerators.
  3895. | Since we keep the objects in the queue when someone grabs an object on a restartable
  3896. | enumerator we dont account for this memory to avoid misreporting memory due to
  3897. | destruction of finalizer.
  3898. |
  3899. |
  3900. * ==================================================================================================
  3901. */
  3902. CWmiFinalizerObj::CWmiFinalizerObj (CWmiFinalizerObj& obj)
  3903. {
  3904. m_pvObj = obj.m_pvObj;
  3905. m_iid = obj.m_iid;
  3906. m_uSize = obj.m_uSize;
  3907. m_pFin = NULL ;
  3908. m_hArb = obj.m_hArb ;
  3909. if (m_pvObj)
  3910. {
  3911. if (m_iid == IID_IUnknown)
  3912. {
  3913. ((IUnknown*)m_pvObj)->AddRef();
  3914. }
  3915. else if (m_iid == IID_IWbemClassObject)
  3916. {
  3917. ((IWbemClassObject*)m_pvObj)->AddRef();
  3918. }
  3919. else if (m_iid == IID__IWmiObject)
  3920. {
  3921. ((_IWmiObject*)m_pvObj)->AddRef();
  3922. }
  3923. else if (m_iid == IID_IWbemServices)
  3924. {
  3925. ((IWbemServices*)m_pvObj)->AddRef();
  3926. }
  3927. /*
  3928. else if (m_iid == IID_IWbemServicesEx)
  3929. {
  3930. ((IWbemServicesEx*)m_pvObj)->AddRef();
  3931. }
  3932. */
  3933. }
  3934. m_pObj = obj.m_pObj;
  3935. m_objectType = obj.m_objectType;
  3936. m_lFlags = obj.m_lFlags;
  3937. if (obj.m_bStr)
  3938. m_bStr = SysAllocString(obj.m_bStr);
  3939. else
  3940. m_bStr = NULL;
  3941. m_hRes = obj.m_hRes;
  3942. if (m_pObj)
  3943. m_pObj->AddRef();
  3944. }
  3945. /*
  3946. * ==================================================================================================
  3947. |
  3948. | CWmiFinalizerObj(ULONG lFlags, REFIID riid, void *pvObj)
  3949. | --------------------------------------------------------
  3950. |
  3951. |
  3952. |
  3953. * ==================================================================================================
  3954. */
  3955. CWmiFinalizerObj::CWmiFinalizerObj(ULONG lFlags, REFIID riid, void *pvObj) : m_pObj(0),
  3956. m_objectType(set),
  3957. m_lFlags(lFlags),
  3958. m_bStr(0),
  3959. m_hRes(0),
  3960. m_pvObj(pvObj),
  3961. m_iid(riid),
  3962. m_pFin ( NULL ),
  3963. m_hArb ( WBEM_S_ARB_NOTHROTTLING )
  3964. {
  3965. m_uSize = 0;
  3966. if (m_iid == IID_IUnknown)
  3967. {
  3968. ((IUnknown*)m_pvObj)->AddRef();
  3969. }
  3970. else if (m_iid == IID_IWbemClassObject)
  3971. {
  3972. ((IWbemClassObject*)m_pvObj)->AddRef();
  3973. }
  3974. else if (m_iid == IID__IWmiObject)
  3975. {
  3976. ((_IWmiObject*)m_pvObj)->AddRef();
  3977. }
  3978. else if (m_iid == IID_IWbemServices)
  3979. {
  3980. ((IWbemServices*)m_pvObj)->AddRef();
  3981. }
  3982. /*
  3983. else if (m_iid == IID_IWbemServicesEx)
  3984. {
  3985. ((IWbemServicesEx*)m_pvObj)->AddRef();
  3986. }
  3987. */
  3988. else
  3989. {
  3990. memset(&m_iid, 0, sizeof(IID)); // SEC:REVIEWED 2002-03-22 : OK
  3991. m_pvObj = 0;
  3992. m_objectType = unknown;
  3993. }
  3994. }
  3995. /*
  3996. * ==================================================================================================
  3997. |
  3998. | CWmiFinalizerObj(ULONG lFlags, HRESULT hRes, BSTR bStr, IWbemClassObject *pObj)
  3999. | -------------------------------------------------------------------------------
  4000. |
  4001. |
  4002. |
  4003. * ==================================================================================================
  4004. */
  4005. CWmiFinalizerObj::CWmiFinalizerObj(ULONG lFlags,
  4006. HRESULT hRes,
  4007. BSTR bStr,
  4008. IWbemClassObject *pObj):
  4009. m_pObj(pObj),
  4010. m_objectType(status),
  4011. m_lFlags(lFlags),
  4012. m_hRes(hRes),
  4013. m_pvObj(0),
  4014. m_pFin ( NULL ) ,
  4015. m_hArb ( WBEM_S_ARB_NOTHROTTLING )
  4016. {
  4017. m_uSize = 0;
  4018. if (bStr)
  4019. m_bStr = SysAllocString(bStr);
  4020. else
  4021. m_bStr = NULL;
  4022. if (m_pObj)
  4023. m_pObj->AddRef();
  4024. }
  4025. /*
  4026. * ==================================================================================================
  4027. |
  4028. | CWmiFinalizerObj::~CWmiFinalizerObj ( )
  4029. | ---------------------------------------
  4030. |
  4031. |
  4032. * ==================================================================================================
  4033. */
  4034. CWmiFinalizerObj::~CWmiFinalizerObj ( )
  4035. {
  4036. if (m_bStr)
  4037. {
  4038. SysFreeString(m_bStr);
  4039. }
  4040. if (m_pObj)
  4041. {
  4042. m_pObj->Release();
  4043. m_pObj = NULL ;
  4044. }
  4045. if (m_pvObj)
  4046. {
  4047. if (m_iid == IID_IUnknown)
  4048. {
  4049. ((IUnknown*)m_pvObj)->Release();
  4050. }
  4051. else if (m_iid == IID_IWbemClassObject)
  4052. {
  4053. ((IWbemClassObject*)m_pvObj)->Release();
  4054. }
  4055. else if (m_iid == IID__IWmiObject)
  4056. {
  4057. ((_IWmiObject*)m_pvObj)->Release();
  4058. }
  4059. else if (m_iid == IID_IWbemServices)
  4060. {
  4061. ((IWbemServices*)m_pvObj)->Release();
  4062. }
  4063. m_pvObj = NULL ;
  4064. }
  4065. if ( m_pFin )
  4066. {
  4067. ((CWmiFinalizer*)m_pFin)->ReportMemoryUsage ( 0, -m_uSize ) ;
  4068. m_pFin = NULL ;
  4069. }
  4070. }