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.

882 lines
23 KiB

  1. //=============================================================================
  2. //
  3. // Copyright (c) 1996-1999, Microsoft Corporation, All rights reserved
  4. //
  5. // STDCONS.CPP
  6. //
  7. // This file implements the class for standard event consumer.
  8. //
  9. // History:
  10. //
  11. // 11/27/96 a-levn Compiles.
  12. //
  13. //=============================================================================
  14. #include "precomp.h"
  15. #include <stdio.h>
  16. #include "pragmas.h"
  17. #include "permcons.h"
  18. #include "ess.h"
  19. #include <wbemidl.h>
  20. #include "wbemutil.h"
  21. #include <cominit.h>
  22. #include <genutils.h>
  23. #include "NCEvents.h"
  24. #define HRESULT_ERROR_MASK (0x0000FFFF)
  25. #define HRESULT_ERROR_FUNC(X) (X&HRESULT_ERROR_MASK)
  26. #define HRESULT_ERROR_SERVER_UNAVAILABLE 1722L
  27. #define HRESULT_ERROR_CALL_FAILED_DNE 1727L
  28. long CPermanentConsumer::mstatic_lMaxQueueSizeHandle = 0;
  29. long CPermanentConsumer::mstatic_lSidHandle = 0;
  30. bool CPermanentConsumer::mstatic_bHandlesInitialized = false;
  31. // static
  32. HRESULT CPermanentConsumer::InitializeHandles( _IWmiObject* pObject)
  33. {
  34. if(mstatic_bHandlesInitialized)
  35. return S_FALSE;
  36. CIMTYPE ct;
  37. pObject->GetPropertyHandle(CONSUMER_MAXQUEUESIZE_PROPNAME, &ct,
  38. &mstatic_lMaxQueueSizeHandle);
  39. pObject->GetPropertyHandleEx(OWNER_SID_PROPNAME, 0, &ct,
  40. &mstatic_lSidHandle);
  41. mstatic_bHandlesInitialized = true;
  42. return S_OK;
  43. }
  44. //******************************************************************************
  45. // public
  46. //
  47. // See stdcons.h for documentation
  48. //
  49. //******************************************************************************
  50. CPermanentConsumer::CPermanentConsumer(CEssNamespace* pNamespace)
  51. : CEventConsumer(pNamespace), m_pCachedSink(NULL), m_pLogicalConsumer(NULL),
  52. m_dwLastDelivery(GetTickCount())
  53. {
  54. pNamespace->IncrementObjectCount();
  55. }
  56. HRESULT CPermanentConsumer::Initialize(IWbemClassObject* pObj)
  57. {
  58. HRESULT hres;
  59. CWbemPtr<_IWmiObject> pActualConsumer;
  60. hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pActualConsumer );
  61. if ( FAILED(hres) )
  62. {
  63. return WBEM_E_CRITICAL_ERROR;
  64. }
  65. InitializeHandles(pActualConsumer);
  66. // Get the "database key" --- unique identifier
  67. // ============================================
  68. BSTR strStandardPath;
  69. hres = pActualConsumer->GetNormalizedPath( 0, &strStandardPath );
  70. if(FAILED(hres))
  71. return hres;
  72. CSysFreeMe sfm1(strStandardPath);
  73. if(!(m_isKey = strStandardPath))
  74. return WBEM_E_OUT_OF_MEMORY;
  75. //
  76. // set the queueing sink name to the consumer name.
  77. // TODO : this is temporary and will go away when the consumer no longer
  78. // inherits from queueing sink.
  79. //
  80. hres = SetName( strStandardPath );
  81. if ( FAILED(hres) )
  82. {
  83. return hres;
  84. }
  85. // Get the maximum queue size, if specified
  86. // ========================================
  87. DWORD dwMaxQueueSize;
  88. hres = pActualConsumer->ReadDWORD(mstatic_lMaxQueueSizeHandle,
  89. &dwMaxQueueSize);
  90. if(hres == S_OK)
  91. SetMaxQueueSize(dwMaxQueueSize);
  92. // Get the SID
  93. // ===========
  94. if(IsNT())
  95. {
  96. PSID pSid;
  97. ULONG ulNumElements;
  98. hres = pActualConsumer->GetArrayPropAddrByHandle( mstatic_lSidHandle,
  99. 0,
  100. &ulNumElements,
  101. &pSid );
  102. if ( hres != S_OK )
  103. {
  104. return WBEM_E_INVALID_OBJECT;
  105. }
  106. m_pOwnerSid = new BYTE[ulNumElements];
  107. if ( m_pOwnerSid == NULL )
  108. {
  109. return WBEM_E_OUT_OF_MEMORY;
  110. }
  111. memcpy( m_pOwnerSid, pSid, ulNumElements );
  112. }
  113. return WBEM_S_NO_ERROR;
  114. }
  115. //******************************************************************************
  116. // public
  117. //
  118. // See stdcons.h for documentation
  119. //
  120. //******************************************************************************
  121. CPermanentConsumer::~CPermanentConsumer()
  122. {
  123. if(m_pCachedSink)
  124. {
  125. FireSinkUnloadedEvent();
  126. m_pCachedSink->Release();
  127. }
  128. if(m_pNamespace)
  129. m_pNamespace->DecrementObjectCount();
  130. if(m_pLogicalConsumer)
  131. m_pLogicalConsumer->Release();
  132. }
  133. HRESULT CPermanentConsumer::RetrieveProviderRecord(
  134. RELEASE_ME CConsumerProviderRecord** ppRecord,
  135. RELEASE_ME IWbemClassObject** ppLogicalConsumer)
  136. {
  137. HRESULT hres;
  138. // Retrieve our logical consumer instance
  139. // ======================================
  140. _IWmiObject* pLogicalConsumer = NULL;
  141. WString wsKey = m_isKey;
  142. hres = m_pNamespace->GetDbInstance((LPCWSTR)wsKey, &pLogicalConsumer);
  143. if(FAILED(hres))
  144. return hres;
  145. CReleaseMe rm1(pLogicalConsumer);
  146. *ppRecord = m_pNamespace->GetConsumerProviderCache().GetRecord(
  147. pLogicalConsumer);
  148. if(*ppRecord == NULL)
  149. {
  150. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  151. }
  152. else
  153. {
  154. if(pLogicalConsumer && ppLogicalConsumer)
  155. {
  156. *ppLogicalConsumer = pLogicalConsumer;
  157. (*ppLogicalConsumer)->AddRef();
  158. }
  159. }
  160. return WBEM_S_NO_ERROR;
  161. }
  162. //******************************************************************************
  163. //
  164. // RetrieveConsumer
  165. //
  166. // Have consumer provider produce a sink for this logical consumer
  167. //
  168. //******************************************************************************
  169. HRESULT CPermanentConsumer::RetrieveSink(
  170. RELEASE_ME IWbemUnboundObjectSink** ppSink,
  171. RELEASE_ME IWbemClassObject** ppLogicalConsumer)
  172. {
  173. // Check if one is cached
  174. // ======================
  175. {
  176. CInCritSec ics(&m_cs);
  177. if(m_pCachedSink)
  178. {
  179. *ppSink = m_pCachedSink;
  180. (*ppSink)->AddRef();
  181. *ppLogicalConsumer = m_pLogicalConsumer;
  182. if(*ppLogicalConsumer)
  183. (*ppLogicalConsumer)->AddRef();
  184. return WBEM_S_NO_ERROR;
  185. }
  186. }
  187. // Not cached. Retrieve one
  188. // ========================
  189. HRESULT hres = ObtainSink(ppSink, ppLogicalConsumer);
  190. if(FAILED(hres))
  191. return hres;
  192. m_pNamespace->EnsureConsumerWatchInstruction();
  193. // Cache it, if needed
  194. // ===================
  195. {
  196. CInCritSec ics(&m_cs);
  197. if(m_pCachedSink)
  198. {
  199. if(m_pCachedSink != (*ppSink))
  200. {
  201. // Drop ours, and use the one that's there
  202. // =======================================
  203. (*ppSink)->Release();
  204. *ppSink = m_pCachedSink;
  205. (*ppSink)->AddRef();
  206. }
  207. if(m_pLogicalConsumer != *ppLogicalConsumer)
  208. {
  209. if(*ppLogicalConsumer)
  210. (*ppLogicalConsumer)->Release();
  211. *ppLogicalConsumer = m_pLogicalConsumer;
  212. if(*ppLogicalConsumer)
  213. (*ppLogicalConsumer)->AddRef();
  214. }
  215. return WBEM_S_NO_ERROR;
  216. }
  217. else
  218. {
  219. // Cache it
  220. // ========
  221. m_pCachedSink = *ppSink;
  222. m_pCachedSink->AddRef();
  223. m_pLogicalConsumer = *ppLogicalConsumer;
  224. if(m_pLogicalConsumer)
  225. m_pLogicalConsumer->AddRef();
  226. }
  227. }
  228. return WBEM_S_NO_ERROR;
  229. }
  230. HRESULT CPermanentConsumer::ObtainSink(
  231. RELEASE_ME IWbemUnboundObjectSink** ppSink,
  232. RELEASE_ME IWbemClassObject** ppLogicalConsumer)
  233. {
  234. *ppSink = NULL;
  235. CConsumerProviderRecord* pRecord = NULL;
  236. IWbemClassObject* pLogicalConsumer = NULL;
  237. HRESULT hres = RetrieveProviderRecord(&pRecord, &pLogicalConsumer);
  238. if(FAILED(hres))
  239. return hres;
  240. CTemplateReleaseMe<CConsumerProviderRecord> rm1(pRecord);
  241. CReleaseMe rm2(pLogicalConsumer);
  242. // Check for global sink shortcut
  243. // ==============================
  244. hres = pRecord->GetGlobalObjectSink(ppSink, pLogicalConsumer);
  245. if(FAILED(hres)) return hres;
  246. if(*ppSink != NULL)
  247. {
  248. // That's it --- this consumer provider provides itself!
  249. // =====================================================
  250. *ppLogicalConsumer = pLogicalConsumer;
  251. if(pLogicalConsumer)
  252. pLogicalConsumer->AddRef();
  253. return S_OK;
  254. }
  255. hres = pRecord->FindConsumer(pLogicalConsumer, ppSink);
  256. if(FAILED(hres))
  257. {
  258. ERRORTRACE((LOG_ESS, "Event consumer provider is unable to instantiate "
  259. "event consumer %S: error code 0x%X\n",
  260. (LPCWSTR)(WString)m_isKey, hres));
  261. return hres;
  262. }
  263. else
  264. {
  265. if(hres == WBEM_S_FALSE)
  266. {
  267. // Consumer provider says: don't need logical consumer!
  268. // ====================================================
  269. *ppLogicalConsumer = NULL;
  270. }
  271. else
  272. {
  273. *ppLogicalConsumer = pLogicalConsumer;
  274. (*ppLogicalConsumer)->AddRef();
  275. }
  276. }
  277. return hres;
  278. }
  279. //******************************************************************************
  280. //
  281. // ClearCache
  282. //
  283. // Releases cached event consumer pointers.
  284. //
  285. //******************************************************************************
  286. HRESULT CPermanentConsumer::ClearCache()
  287. {
  288. //
  289. // First, clear consumer provider record
  290. //
  291. CConsumerProviderRecord* pRecord = NULL;
  292. IWbemClassObject* pLogicalConsumer = NULL;
  293. HRESULT hres = RetrieveProviderRecord(&pRecord, &pLogicalConsumer);
  294. if(SUCCEEDED(hres))
  295. {
  296. pLogicalConsumer->Release();
  297. pRecord->Invalidate();
  298. pRecord->Release();
  299. }
  300. //
  301. // Need to PostponeRelease outside of the critical section, since
  302. // it will not actually postpone if done on a delivery thread
  303. //
  304. IWbemUnboundObjectSink* pSink = NULL;
  305. {
  306. CInCritSec ics(&m_cs);
  307. if(m_pCachedSink)
  308. {
  309. FireSinkUnloadedEvent();
  310. pSink = m_pCachedSink;
  311. m_pCachedSink = NULL;
  312. }
  313. if(m_pLogicalConsumer)
  314. {
  315. m_pLogicalConsumer->Release();
  316. m_pLogicalConsumer = NULL;
  317. }
  318. }
  319. _DBG_ASSERT( m_pNamespace != NULL );
  320. if(pSink)
  321. m_pNamespace->PostponeRelease(pSink);
  322. return S_OK;
  323. }
  324. HRESULT CPermanentConsumer::Indicate(IWbemUnboundObjectSink* pSink,
  325. IWbemClassObject* pLogicalConsumer,
  326. long lNumEvents, IWbemEvent** apEvents,
  327. BOOL bSecure)
  328. {
  329. HRESULT hres;
  330. try
  331. {
  332. hres = pSink->IndicateToConsumer(pLogicalConsumer, lNumEvents,
  333. apEvents);
  334. }
  335. catch(...)
  336. {
  337. ERRORTRACE((LOG_ESS, "Event consumer threw an exception!\n"));
  338. hres = WBEM_E_PROVIDER_FAILURE;
  339. }
  340. return hres;
  341. }
  342. //******************************************************************************
  343. // public
  344. //
  345. // See stdcons.h for documentation
  346. //
  347. //******************************************************************************
  348. HRESULT CPermanentConsumer::ActuallyDeliver(long lNumEvents,
  349. IWbemEvent** apEvents, BOOL bSecure,
  350. CEventContext* pContext)
  351. {
  352. HRESULT hres;
  353. // Mark "last-delivery" time
  354. // =========================
  355. m_dwLastDelivery = GetTickCount();
  356. // Retrieve the sink to deliver the event into
  357. // ===========================================
  358. IWbemUnboundObjectSink* pSink = NULL;
  359. IWbemClassObject* pLogicalConsumer = NULL;
  360. hres = RetrieveSink(&pSink, &pLogicalConsumer);
  361. if(FAILED(hres))
  362. {
  363. ERRORTRACE((LOG_ESS, "Failed the first attempt to retrieve the sink to "
  364. "deliver an event to event consumer %S with error code %X.\n"
  365. "WMI will reload and retry.\n",
  366. (LPCWSTR)(WString)m_isKey, hres));
  367. return Redeliver(lNumEvents, apEvents, bSecure);
  368. }
  369. CReleaseMe rm1(pSink);
  370. CReleaseMe rm2(pLogicalConsumer);
  371. // Try to deliver (m_pLogicalConsumer is immutable, so no cs is needed)
  372. // ====================================================================
  373. hres = Indicate(pSink, pLogicalConsumer, lNumEvents, apEvents, bSecure);
  374. if(FAILED(hres))
  375. {
  376. // decide whether it's an RPC error code
  377. DWORD shiftedRPCFacCode = FACILITY_RPC << 16;
  378. if ( ( ( hres & 0x7FF0000 ) == shiftedRPCFacCode ) ||
  379. ( HRESULT_ERROR_FUNC(hres) == HRESULT_ERROR_SERVER_UNAVAILABLE ) ||
  380. ( HRESULT_ERROR_FUNC(hres) == HRESULT_ERROR_CALL_FAILED_DNE ) ||
  381. ( hres == RPC_E_DISCONNECTED ) )
  382. {
  383. ERRORTRACE((LOG_ESS, "Failed the first attempt to deliver an event to "
  384. "event consumer %S with error code 0x%X.\n"
  385. "WMI will reload and retry.\n",
  386. (LPCWSTR)(WString)m_isKey, hres));
  387. return Redeliver(lNumEvents, apEvents, bSecure);
  388. }
  389. else
  390. {
  391. ReportConsumerFailure(lNumEvents, apEvents, hres);
  392. ERRORTRACE((LOG_ESS, "Failed to deliver an event to "
  393. "event consumer %S with error code 0x%X. Dropping event.\n",
  394. (LPCWSTR)(WString)m_isKey, hres));
  395. return hres;
  396. }
  397. }
  398. return hres;
  399. }
  400. HRESULT CPermanentConsumer::Redeliver(long lNumEvents,
  401. IWbemEvent** apEvents, BOOL bSecure)
  402. {
  403. HRESULT hres;
  404. // Clear everything
  405. // ================
  406. ClearCache();
  407. // Re-retrieve the sink
  408. // ====================
  409. IWbemUnboundObjectSink* pSink = NULL;
  410. IWbemClassObject* pLogicalConsumer = NULL;
  411. hres = RetrieveSink(&pSink, &pLogicalConsumer);
  412. if(SUCCEEDED(hres))
  413. {
  414. CReleaseMe rm1(pSink);
  415. CReleaseMe rm2(pLogicalConsumer);
  416. // Re-deliver
  417. // ==========
  418. hres = Indicate(pSink, pLogicalConsumer, lNumEvents, apEvents, bSecure);
  419. }
  420. if(FAILED(hres))
  421. {
  422. ERRORTRACE((LOG_ESS,
  423. "Failed the second attempt to deliver an event to "
  424. "event consumer %S with error code %X.\n"
  425. "This event is dropped for this consumer.\n",
  426. (LPCWSTR)(WString)m_isKey, hres));
  427. ReportConsumerFailure(lNumEvents, apEvents, hres);
  428. }
  429. return hres;
  430. }
  431. BOOL CPermanentConsumer::IsFullyUnloaded()
  432. {
  433. return (m_pCachedSink == NULL);
  434. }
  435. HRESULT CPermanentConsumer::Validate(IWbemClassObject* pLogicalConsumer)
  436. {
  437. HRESULT hres;
  438. //
  439. // Retrieve our consumer provider record
  440. //
  441. CConsumerProviderRecord* pRecord = NULL;
  442. hres = RetrieveProviderRecord(&pRecord);
  443. if(FAILED(hres))
  444. return hres;
  445. CTemplateReleaseMe<CConsumerProviderRecord> rm1(pRecord);
  446. //
  447. // Get it to validate our logical consumer
  448. //
  449. hres = pRecord->ValidateConsumer(pLogicalConsumer);
  450. return hres;
  451. }
  452. BOOL CPermanentConsumer::UnloadIfUnusedFor(CWbemInterval Interval)
  453. {
  454. CInCritSec ics(&m_cs);
  455. if(m_pCachedSink &&
  456. GetTickCount() - m_dwLastDelivery > Interval.GetMilliseconds())
  457. {
  458. FireSinkUnloadedEvent();
  459. _DBG_ASSERT( m_pNamespace != NULL );
  460. m_pNamespace->PostponeRelease(m_pCachedSink);
  461. m_pCachedSink = NULL;
  462. if(m_pLogicalConsumer)
  463. m_pLogicalConsumer->Release();
  464. m_pLogicalConsumer = NULL;
  465. DEBUGTRACE((LOG_ESS, "Unloading event consumer sink %S\n",
  466. (LPCWSTR)(WString)m_isKey));
  467. return TRUE;
  468. }
  469. else
  470. {
  471. return FALSE;
  472. }
  473. }
  474. HRESULT CPermanentConsumer::ResetProviderRecord(LPCWSTR wszProviderRef)
  475. {
  476. HRESULT hres;
  477. // Check if anything is even cached
  478. // ================================
  479. {
  480. CInCritSec ics(&m_cs);
  481. if(m_pCachedSink == NULL)
  482. return WBEM_S_FALSE;
  483. }
  484. // Locate our consumer provider record
  485. // ===================================
  486. CConsumerProviderRecord* pRecord = NULL;
  487. hres = RetrieveProviderRecord(&pRecord);
  488. if(FAILED(hres))
  489. return hres;
  490. CTemplateReleaseMe<CConsumerProviderRecord> rm1(pRecord);
  491. if(!wbem_wcsicmp(pRecord->GetProviderRef(), wszProviderRef))
  492. {
  493. ClearCache();
  494. return WBEM_S_NO_ERROR;
  495. }
  496. else
  497. {
  498. return WBEM_S_FALSE;
  499. }
  500. }
  501. SYSFREE_ME BSTR CPermanentConsumer::ComputeKeyFromObj(
  502. CEssNamespace* pNamespace,
  503. IWbemClassObject* pObj)
  504. {
  505. HRESULT hres;
  506. CWbemPtr<_IWmiObject> pConsumerObj;
  507. hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pConsumerObj );
  508. if ( FAILED(hres) )
  509. {
  510. return NULL;
  511. }
  512. BSTR strStandardPath = NULL;
  513. hres = pConsumerObj->GetNormalizedPath( 0, &strStandardPath );
  514. if(FAILED(hres))
  515. return NULL;
  516. return strStandardPath;
  517. }
  518. HRESULT CPermanentConsumer::ReportQueueOverflow(IWbemEvent* pEvent,
  519. DWORD dwQueueSize)
  520. {
  521. HRESULT hres;
  522. if(CEventConsumer::ReportEventDrop(pEvent) != S_OK)
  523. return S_FALSE;
  524. // Construct event instance
  525. // ========================
  526. IWbemEvent* pErrorEvent = NULL;
  527. hres = ConstructErrorEvent(QUEUE_OVERFLOW_CLASS, pEvent, &pErrorEvent);
  528. if(FAILED(hres))
  529. return hres;
  530. CReleaseMe rm1(pErrorEvent);
  531. // Fill in the queue size
  532. // ======================
  533. VARIANT v;
  534. V_VT(&v) = VT_I4;
  535. V_I4(&v) = dwQueueSize;
  536. hres = pErrorEvent->Put(QUEUE_OVERFLOW_SIZE_PROPNAME, 0, &v, 0);
  537. if(FAILED(hres))
  538. return hres;
  539. // Raise it
  540. // ========
  541. hres = m_pNamespace->RaiseErrorEvent(pErrorEvent,TRUE);
  542. return hres;
  543. }
  544. HRESULT CPermanentConsumer::ReportConsumerFailure(long lNumEvents,
  545. IWbemEvent** apEvents, HRESULT hresError)
  546. {
  547. HRESULT hres;
  548. //
  549. // Compute the error object to use
  550. //
  551. _IWmiObject* pErrorObj = NULL;
  552. //
  553. // Get it from the thread
  554. //
  555. IErrorInfo* pErrorInfo = NULL;
  556. hres = GetErrorInfo(0, &pErrorInfo);
  557. if(hres != S_OK)
  558. {
  559. pErrorInfo = NULL;
  560. }
  561. else
  562. {
  563. hres = pErrorInfo->QueryInterface(IID__IWmiObject, (void**)&pErrorObj);
  564. if(FAILED(hres))
  565. {
  566. ERRORTRACE((LOG_ESS, "Non-WMI error object found returned by event "
  567. "consumer. Error object ignored\n"));
  568. pErrorObj = NULL;
  569. }
  570. }
  571. CReleaseMe rm1(pErrorObj);
  572. for(long l = 0; l < lNumEvents; l++)
  573. {
  574. ReportConsumerFailure(apEvents[l], hresError, pErrorObj);
  575. }
  576. return S_OK;
  577. }
  578. HRESULT CPermanentConsumer::ReportConsumerFailure(IWbemEvent* pEvent,
  579. HRESULT hresError,
  580. _IWmiObject* pErrorObj)
  581. {
  582. HRESULT hres;
  583. if(CEventConsumer::ReportEventDrop(pEvent) != S_OK)
  584. return S_FALSE;
  585. //
  586. // Construct event instance
  587. //
  588. IWbemEvent* pErrorEvent = NULL;
  589. hres = ConstructErrorEvent(CONSUMER_FAILURE_CLASS, pEvent, &pErrorEvent);
  590. if(FAILED(hres))
  591. return hres;
  592. CReleaseMe rm1(pErrorEvent);
  593. //
  594. // Fill in the error code
  595. //
  596. VARIANT v;
  597. V_VT(&v) = VT_I4;
  598. V_I4(&v) = hresError;
  599. hres = pErrorEvent->Put(CONSUMER_FAILURE_ERROR_PROPNAME, 0, &v, 0);
  600. if(FAILED(hres))
  601. return hres;
  602. if(pErrorObj)
  603. {
  604. //
  605. // Fill in the error object
  606. //
  607. V_VT(&v) = VT_UNKNOWN;
  608. V_UNKNOWN(&v) = pErrorObj;
  609. hres = pErrorEvent->Put(CONSUMER_FAILURE_ERROROBJ_PROPNAME, 0, &v, 0);
  610. if(FAILED(hres))
  611. {
  612. //
  613. // That's OK, sometimes error objects are not supported
  614. //
  615. }
  616. }
  617. // Raise it
  618. // ========
  619. hres = m_pNamespace->RaiseErrorEvent(pErrorEvent,TRUE);
  620. return hres;
  621. }
  622. HRESULT CPermanentConsumer::ReportQosFailure( IWbemEvent* pEvent,
  623. HRESULT hresError )
  624. {
  625. HRESULT hres;
  626. if(CEventConsumer::ReportEventDrop(pEvent) != S_OK)
  627. return S_FALSE;
  628. // Construct event instance
  629. // ========================
  630. IWbemEvent* pErrorEvent = NULL;
  631. hres = ConstructErrorEvent(QOS_FAILURE_CLASS, pEvent, &pErrorEvent);
  632. if(FAILED(hres))
  633. return hres;
  634. CReleaseMe rm1(pErrorEvent);
  635. // Fill in the error code
  636. // ======================
  637. VARIANT v;
  638. V_VT(&v) = VT_I4;
  639. V_I4(&v) = hresError;
  640. hres = pErrorEvent->Put(QOS_FAILURE_ERROR_PROPNAME, 0, &v, 0);
  641. if(FAILED(hres))
  642. return hres;
  643. // Raise it
  644. // ========
  645. hres = m_pNamespace->RaiseErrorEvent(pErrorEvent,TRUE);
  646. return hres;
  647. }
  648. HRESULT CPermanentConsumer::ConstructErrorEvent(LPCWSTR wszEventClass,
  649. IWbemEvent* pEvent, IWbemEvent** ppErrorEvent)
  650. {
  651. HRESULT hres;
  652. _IWmiObject* pClass = NULL;
  653. hres = m_pNamespace->GetClass(wszEventClass, &pClass);
  654. if(FAILED(hres))
  655. return hres;
  656. CReleaseMe rm2(pClass);
  657. IWbemClassObject* pErrorEvent = NULL;
  658. hres = pClass->SpawnInstance(0, &pErrorEvent);
  659. if(FAILED(hres))
  660. return hres;
  661. CReleaseMe rm3(pErrorEvent);
  662. VARIANT v;
  663. VariantInit(&v);
  664. V_VT(&v) = VT_UNKNOWN;
  665. V_UNKNOWN(&v) = pEvent;
  666. hres = pErrorEvent->Put(EVENT_DROP_EVENT_PROPNAME, 0, &v, 0);
  667. if(FAILED(hres))
  668. return hres;
  669. BSTR strTemp = SysAllocString((WString)m_isKey);
  670. if ( NULL == strTemp )
  671. {
  672. return WBEM_E_OUT_OF_MEMORY;
  673. }
  674. V_VT(&v) = VT_BSTR;
  675. V_BSTR(&v) = strTemp;
  676. hres = pErrorEvent->Put(EVENT_DROP_CONSUMER_PROPNAME, 0, &v, 0);
  677. VariantClear(&v);
  678. if(FAILED(hres))
  679. return hres;
  680. *ppErrorEvent = pErrorEvent;
  681. pErrorEvent->AddRef();
  682. return S_OK;
  683. }
  684. void CPermanentConsumer::FireSinkUnloadedEvent()
  685. {
  686. CConsumerProviderRecord *pRecord = NULL;
  687. IWbemClassObject *pLogicalConsumer = NULL;
  688. if (SUCCEEDED(RetrieveProviderRecord(&pRecord, &pLogicalConsumer)))
  689. {
  690. CTemplateReleaseMe<CConsumerProviderRecord> rm1(pRecord);
  691. CReleaseMe rm2(pLogicalConsumer);
  692. //
  693. // Report the MSFT_WmiConsumerProviderSinkUnloaded event.
  694. //
  695. pRecord->FireNCSinkEvent(
  696. MSFT_WmiConsumerProviderSinkUnloaded,
  697. pLogicalConsumer);
  698. }
  699. }