Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4125 lines
111 KiB

  1. //******************************************************************************
  2. //
  3. // PROVREG.CPP
  4. //
  5. // Copyright (C) 1996-1999 Microsoft Corporation
  6. //
  7. //******************************************************************************
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include <parmdefs.h>
  11. #include <ql.h>
  12. #include "ess.h"
  13. #include <wbemutil.h>
  14. #include <cominit.h>
  15. #include <objpath.h>
  16. #include <provinit.h>
  17. #include <winmgmtr.h>
  18. #include <newobj.h>
  19. #include <comutl.h>
  20. #include "NCEvents.h"
  21. _IWmiObject* g_pCopy;
  22. #define WBEM_MAX_FILTER_ID 0x80000000
  23. inline BOOL IsRpcError( HRESULT hr )
  24. {
  25. //
  26. // we'll consider any error but a wbem error to be an rpc error.
  27. //
  28. return HRESULT_FACILITY(hr) != FACILITY_ITF;
  29. }
  30. CWbemInterval CEventProviderWatchInstruction::mstatic_Interval;
  31. CEventProviderWatchInstruction::CEventProviderWatchInstruction(
  32. CEventProviderCache* pCache)
  33. : CBasicUnloadInstruction(mstatic_Interval), m_pCache(pCache)
  34. {
  35. }
  36. void CEventProviderWatchInstruction::staticInitialize(IWbemServices* pRoot)
  37. {
  38. mstatic_Interval = CBasicUnloadInstruction::staticRead(pRoot, GetCurrentEssContext(),
  39. L"__EventProviderCacheControl=@");
  40. }
  41. HRESULT CEventProviderWatchInstruction::Fire(long, CWbemTime)
  42. {
  43. CInCritSec ics(&m_cs);
  44. if(!m_bTerminate)
  45. {
  46. SetCurrentEssThreadObject(NULL);
  47. if ( GetCurrentEssThreadObject() != NULL )
  48. {
  49. m_pCache->UnloadUnusedProviders(m_Interval);
  50. delete GetCurrentEssThreadObject();
  51. ClearCurrentEssThreadObject();
  52. }
  53. }
  54. return WBEM_S_FALSE;
  55. }
  56. //******************************************************************************
  57. //******************************************************************************
  58. //
  59. // PROVIDER SINK (SERVER)
  60. //
  61. //******************************************************************************
  62. //******************************************************************************
  63. CProviderSinkServer::CEventDestination::CEventDestination(
  64. WBEM_REMOTE_TARGET_ID_TYPE id,
  65. CAbstractEventSink* pSink)
  66. : m_id(id), m_pSink(pSink)
  67. {
  68. if(m_pSink)
  69. m_pSink->AddRef();
  70. }
  71. CProviderSinkServer::CEventDestination::CEventDestination(
  72. const CEventDestination& Other)
  73. : m_id(Other.m_id), m_pSink(Other.m_pSink)
  74. {
  75. if(m_pSink)
  76. m_pSink->AddRef();
  77. }
  78. CProviderSinkServer::CEventDestination::~CEventDestination()
  79. {
  80. if(m_pSink)
  81. m_pSink->Release();
  82. }
  83. CProviderSinkServer::CProviderSinkServer()
  84. : m_lRef(0), m_pNamespace(NULL), m_pMetaData(NULL), m_Stub(this), m_idNext(0),
  85. m_pPseudoProxy(NULL), m_pPseudoSink(NULL), m_pReqSink(NULL), m_lLocks(0)
  86. {
  87. }
  88. HRESULT CProviderSinkServer::Initialize( CEssNamespace* pNamespace,
  89. IWbemEventProviderRequirements* pReqSink )
  90. {
  91. HRESULT hres;
  92. //
  93. // This sink owns us, so we intentionally do not AddRef it
  94. //
  95. m_pReqSink = pReqSink;
  96. m_pMetaData = new CEssMetaData(pNamespace);
  97. if(m_pMetaData == NULL)
  98. return WBEM_E_OUT_OF_MEMORY;
  99. m_pMetaData->AddRef();
  100. m_pNamespace = pNamespace;
  101. m_pNamespace->AddRef();
  102. //
  103. // create the pseudo proxy and sink.
  104. //
  105. hres = WbemCoCreateInstance( CLSID_WbemFilterProxy,
  106. NULL,
  107. CLSCTX_INPROC_SERVER,
  108. IID_IWbemLocalFilterProxy,
  109. (void**)&m_pPseudoProxy );
  110. if( FAILED(hres) )
  111. {
  112. return hres;
  113. }
  114. hres = m_pPseudoProxy->SetStub( &m_Stub );
  115. if(FAILED(hres))
  116. {
  117. return hres;
  118. }
  119. return m_pPseudoProxy->GetMainSink(&m_pPseudoSink);
  120. }
  121. HRESULT CProviderSinkServer::GetMainProxy(IWbemEventSink** ppSink)
  122. {
  123. _DBG_ASSERT( m_pPseudoSink != NULL );
  124. m_pPseudoSink->AddRef();
  125. *ppSink = m_pPseudoSink;
  126. return WBEM_S_NO_ERROR;
  127. }
  128. CProviderSinkServer::~CProviderSinkServer()
  129. {
  130. if(m_pPseudoProxy)
  131. m_pPseudoProxy->Release();
  132. if(m_pPseudoSink)
  133. m_pPseudoSink->Release();
  134. if(m_pMetaData)
  135. m_pMetaData->Release();
  136. if(m_pNamespace)
  137. m_pNamespace->Release();
  138. }
  139. ULONG STDMETHODCALLTYPE CProviderSinkServer::AddRef()
  140. {
  141. return InterlockedIncrement(&m_lRef);
  142. }
  143. ULONG STDMETHODCALLTYPE CProviderSinkServer::Release()
  144. {
  145. long lRef = InterlockedDecrement(&m_lRef);
  146. if(lRef == 0)
  147. delete this;
  148. return lRef;
  149. }
  150. HRESULT STDMETHODCALLTYPE CProviderSinkServer::QueryInterface(REFIID riid,
  151. void** ppv)
  152. {
  153. if(riid == IID_IUnknown || riid == IID_IMarshal)
  154. *ppv = (IMarshal*)this;
  155. else
  156. return E_NOINTERFACE;
  157. ((IUnknown*)*ppv)->AddRef();
  158. return S_OK;
  159. }
  160. HRESULT STDMETHODCALLTYPE CProviderSinkServer::DeliverEvent(
  161. DWORD dwNumEvents,
  162. IWbemClassObject** apEvents,
  163. WBEM_REM_TARGETS* aTargets,
  164. CEventContext* pContext)
  165. {
  166. if(aTargets == NULL || aTargets->m_aTargets == NULL || apEvents == NULL)
  167. {
  168. ERRORTRACE((LOG_ESS, "NULL parameter received from a "
  169. "filter proxy for an event provider. Either an internal "
  170. "error has occurred, or a DENIAL OF SERVICE ATTACK has "
  171. "been thwarted\n"));
  172. return WBEM_E_INVALID_PARAMETER;
  173. }
  174. //
  175. // ensure that there is no ess thread object associated with this thread.
  176. // to avoid making the design more complicated we are not going to support
  177. // postpone operations being used on event signaling threads. If we did
  178. // we have to start creating thread objects and firing postponed ops on
  179. // every event signaling - it would be rather messy and inefficient to
  180. // say the least.
  181. //
  182. CEssThreadObject* pThreadObj = GetCurrentEssThreadObject();
  183. if ( pThreadObj != NULL )
  184. {
  185. ClearCurrentEssThreadObject();
  186. }
  187. for(DWORD i = 0; i < dwNumEvents; i++)
  188. {
  189. DeliverOneEvent(apEvents[i], aTargets + i, pContext);
  190. }
  191. if ( pThreadObj != NULL )
  192. {
  193. SetConstructedEssThreadObject( pThreadObj );
  194. }
  195. return WBEM_S_NO_ERROR;
  196. }
  197. HRESULT CProviderSinkServer::DeliverOneEvent( IWbemClassObject* pEvent,
  198. WBEM_REM_TARGETS* pTargets,
  199. CEventContext* pContext )
  200. {
  201. HRESULT hres;
  202. _DBG_ASSERT( pContext != NULL );
  203. if(pEvent == NULL)
  204. {
  205. ERRORTRACE((LOG_ESS, "NULL parameter received from a "
  206. "filter proxy for an event provider. Either an internal "
  207. "error has occurred, or a DENIAL OF SERVICE ATTACK has "
  208. "been thwarted\n"));
  209. return WBEM_E_INVALID_PARAMETER;
  210. }
  211. //
  212. // allocate the context to be used if we need to switch to a per event
  213. // context ( e.g. when the event has a SD ).
  214. //
  215. CEventContext PerEventContext;
  216. //
  217. // take care of the event SD here. If there is an SD associated with the
  218. // context, then we always use that one. If not, then we take the one
  219. // associated with the event. In the latter case, it is important to
  220. // pull the SD out here because sometimes we perform the access check
  221. // after the SD has been projected out from the event ( this happens in
  222. // cross-namespace subscriptions.
  223. //
  224. if ( pContext->GetSD() == NULL )
  225. {
  226. ULONG cEventSD;
  227. PBYTE pEventSD = (PBYTE)GetSD( pEvent, &cEventSD );
  228. if ( pEventSD != NULL )
  229. {
  230. //
  231. // must use a different context for the event,
  232. // since it has its own SD
  233. //
  234. pContext = &PerEventContext;
  235. //
  236. // we must copy the SD here because it is not guaranteed to be
  237. // aligned properly since it is a ptr to the direct event object
  238. // data. The bytes MUST NOT be treated as an SD until it has
  239. // been copied.
  240. //
  241. if ( !pContext->SetSD( cEventSD, pEventSD, TRUE ) )
  242. {
  243. return WBEM_E_OUT_OF_MEMORY;
  244. }
  245. if ( !IsValidSecurityDescriptor(
  246. (PSECURITY_DESCRIPTOR)pContext->GetSD() ) )
  247. {
  248. return WBEM_E_INVALID_OBJECT;
  249. }
  250. }
  251. }
  252. else
  253. {
  254. if ( !IsValidSecurityDescriptor(
  255. (PSECURITY_DESCRIPTOR)pContext->GetSD() ) )
  256. {
  257. return WBEM_E_INVALID_PARAMETER;
  258. }
  259. }
  260. //
  261. // clone the event
  262. //
  263. IWbemEvent* pClone = NULL;
  264. /*
  265. _IWmiObject* pEventEx;
  266. pEvent->QueryInterface(IID__IWmiObject, (void**)&pEventEx);
  267. pClone = m_InstanceManager.Clone(pEventEx);
  268. pEventEx->Release();
  269. if(pClone == NULL)
  270. return WBEM_E_OUT_OF_MEMORY;
  271. */
  272. hres = pEvent->Clone(&pClone);
  273. if(FAILED(hres))
  274. return hres;
  275. /*
  276. pClone = pEvent;
  277. pClone->AddRef();
  278. */
  279. CReleaseMe rm1(pClone);
  280. if(pTargets->m_lNumTargets > 1)
  281. return MultiTargetDeliver(pClone, pTargets, pContext);
  282. // Single target
  283. // =============
  284. // Check validity
  285. // ==============
  286. long lDestId = pTargets->m_aTargets[0];
  287. CAbstractEventSink* pDest = NULL;
  288. {
  289. CInCritSec ics(&m_cs);
  290. hres = FindDestinations(1, pTargets->m_aTargets, &pDest);
  291. if(FAILED(hres))
  292. return hres;
  293. if(!pDest)
  294. // No longer there --- that's OK
  295. return WBEM_S_FALSE;
  296. }
  297. hres = pDest->Indicate(1, &pClone, pContext);
  298. pDest->Release();
  299. return hres;
  300. }
  301. HRESULT CProviderSinkServer::MultiTargetDeliver(IWbemEvent* pEvent,
  302. WBEM_REM_TARGETS* pTargets,
  303. CEventContext* pContext)
  304. {
  305. HRESULT hres;
  306. // Convert the target IDs to the actual targets
  307. // ============================================
  308. CTempArray<CAbstractEventSink*> apSinks;
  309. if(!INIT_TEMP_ARRAY(apSinks, pTargets->m_lNumTargets))
  310. return WBEM_E_OUT_OF_MEMORY;
  311. {
  312. CInCritSec ics(&m_cs);
  313. hres = FindDestinations(pTargets->m_lNumTargets, pTargets->m_aTargets,
  314. (CAbstractEventSink**)apSinks);
  315. if(FAILED(hres))
  316. return hres;
  317. }
  318. HRESULT hresGlobal = WBEM_S_NO_ERROR;
  319. for(int i = 0; i < pTargets->m_lNumTargets; i++)
  320. {
  321. if(apSinks[i])
  322. {
  323. hres = apSinks[i]->Indicate(1, &pEvent, pContext);
  324. if(FAILED(hres))
  325. hresGlobal = hres;
  326. apSinks[i]->Release();
  327. }
  328. }
  329. // DEBUGTRACE((LOG_ESS, "Done delivering\n"));
  330. return hresGlobal;
  331. }
  332. // assumes: locked
  333. HRESULT CProviderSinkServer::FindDestinations(long lNum,
  334. IN WBEM_REMOTE_TARGET_ID_TYPE* aidTargets,
  335. RELEASE_ME CAbstractEventSink** apSinks)
  336. {
  337. //
  338. // Do a binary search for each one. The range will be getting progressively
  339. // smaller with each element we find
  340. //
  341. long lLastFoundIndex = -1;
  342. for(long i = 0; i < lNum; i++)
  343. {
  344. long lMinIndex = lLastFoundIndex+1;
  345. long lMaxIndex = m_apDestinations.GetSize() - 1;
  346. long lFound = -1;
  347. WBEM_REMOTE_TARGET_ID_TYPE idCurrent = aidTargets[i];
  348. //
  349. // Search the remaining portion of the array
  350. //
  351. while(lMinIndex <= lMaxIndex)
  352. {
  353. long lMidIndex = (lMinIndex + lMaxIndex) / 2;
  354. WBEM_REMOTE_TARGET_ID_TYPE idMid = m_apDestinations[lMidIndex]->m_id;
  355. if(idMid == idCurrent)
  356. {
  357. lFound = lMidIndex;
  358. break;
  359. }
  360. else if(idCurrent < idMid)
  361. {
  362. lMaxIndex = lMidIndex - 1;
  363. }
  364. else
  365. {
  366. lMinIndex = lMidIndex + 1;
  367. }
  368. }
  369. if(lFound < 0)
  370. {
  371. //
  372. // Invalid target ID -- OK, so NULL target then
  373. //
  374. apSinks[i] = NULL;
  375. }
  376. else
  377. {
  378. apSinks[i] = m_apDestinations[lFound]->m_pSink;
  379. (apSinks[i])->AddRef();
  380. //
  381. // The rest of the IDs can only be found to the right of this one
  382. // because the targets are sorted
  383. //
  384. lLastFoundIndex = lFound;
  385. }
  386. }
  387. return WBEM_S_NO_ERROR;
  388. }
  389. HRESULT STDMETHODCALLTYPE CProviderSinkServer::DeliverStatus(long lFlags,
  390. HRESULT hresStatus,
  391. LPCWSTR wszStatus, IWbemClassObject* pErrorObj,
  392. WBEM_REM_TARGETS* pTargets,
  393. CEventContext* pContext)
  394. {
  395. return WBEM_E_UNEXPECTED;
  396. }
  397. HRESULT STDMETHODCALLTYPE CProviderSinkServer::DeliverProviderRequest(
  398. long lFlags)
  399. {
  400. if(m_pReqSink)
  401. return m_pReqSink->DeliverProviderRequest(lFlags);
  402. else
  403. return WBEM_E_UNEXPECTED;
  404. }
  405. // assumes: locked
  406. HRESULT CProviderSinkServer::GetDestinations(
  407. CUniquePointerArray<CEventDestination>& apDestinations)
  408. {
  409. for(int i = 0; i < m_apDestinations.GetSize(); i++)
  410. {
  411. CEventDestination* pNew = new CEventDestination(*m_apDestinations[i]);
  412. if(pNew == NULL)
  413. return WBEM_E_OUT_OF_MEMORY;
  414. if(apDestinations.Add(pNew) < 0)
  415. {
  416. delete pNew;
  417. return WBEM_E_OUT_OF_MEMORY;
  418. }
  419. }
  420. return WBEM_S_NO_ERROR;
  421. }
  422. // assumes in m_cs;
  423. HRESULT CProviderSinkServer::AddDestination(CAbstractEventSink* pDest,
  424. WBEM_REMOTE_TARGET_ID_TYPE* pID)
  425. {
  426. HRESULT hres = WBEM_S_NO_ERROR;
  427. //
  428. // Allocate a new destination ID
  429. //
  430. WBEM_REMOTE_TARGET_ID_TYPE idNew = m_idNext++;
  431. if(m_idNext > WBEM_MAX_FILTER_ID / 2)
  432. {
  433. //
  434. // 32-bit integer roll-over! This provider has processed over
  435. // 4000000000 filter creations! Canfetti is falling from the ceiling
  436. //
  437. DEBUGTRACE((LOG_ESS, "Filter ID rollover!!!\n"));
  438. // BUGBUG: Postpone a call to reactivate all filters!
  439. }
  440. //
  441. // Add a new destination entry
  442. //
  443. CEventDestination* pDestRecord = new CEventDestination(idNew, pDest);
  444. if(pDestRecord == NULL)
  445. return WBEM_E_OUT_OF_MEMORY;
  446. m_apDestinations.Add(pDestRecord);
  447. // Record the ID in the TARGETS
  448. // ============================
  449. *pID = idNew;
  450. return hres;
  451. }
  452. HRESULT CProviderSinkServer::AddFilter(LPCWSTR wszQuery,
  453. QL_LEVEL_1_RPN_EXPRESSION* pExp,
  454. CAbstractEventSink* pDest,
  455. WBEM_REMOTE_TARGET_ID_TYPE* pidRequest)
  456. {
  457. HRESULT hres;
  458. WBEM_REMOTE_TARGET_ID_TYPE idDest;
  459. CRefedPointerArray<IWbemFilterProxy> apProxies;
  460. {
  461. CInCritSec ics(&m_cs);
  462. // Copy proxies
  463. // ============
  464. if(!GetProxies(apProxies))
  465. return WBEM_E_OUT_OF_MEMORY;
  466. // Add to the list of destinations registered with the provider and
  467. // construct the target identification for the proxies
  468. // ================================================================
  469. hres = AddDestination(pDest, &idDest);
  470. if(FAILED(hres))
  471. return hres;
  472. }
  473. if(pidRequest)
  474. *pidRequest = idDest;
  475. // Go through all the proxies and schedule calls
  476. // =============================================
  477. HRESULT hresReal = WBEM_S_NO_ERROR;
  478. for(int i = 0; i < apProxies.GetSize(); i++)
  479. {
  480. IWbemLocalFilterProxy *pLocalProxy = NULL;
  481. // See if the proxy will allow us to call LocalAddFilter (in which case
  482. // it's the pseudo proxy).
  483. if (SUCCEEDED(apProxies[i]->QueryInterface(
  484. IID_IWbemLocalFilterProxy, (LPVOID*) &pLocalProxy)))
  485. {
  486. CReleaseMe rm1(pLocalProxy);
  487. hres = pLocalProxy->LocalAddFilter( GetCurrentEssContext(),
  488. wszQuery,
  489. pExp,
  490. idDest );
  491. hresReal = hres; // other errors do not matter
  492. }
  493. else
  494. {
  495. hres = apProxies[i]->AddFilter( GetCurrentEssContext(),
  496. wszQuery,
  497. idDest );
  498. }
  499. if( FAILED(hres) )
  500. {
  501. if ( IsRpcError(hres) )
  502. {
  503. UnregisterProxy( apProxies[i] );
  504. }
  505. ERRORTRACE((LOG_ESS, "Unable to add query %S to a remote provider "
  506. "proxy. Error code: %X\n", wszQuery, hres));
  507. }
  508. }
  509. return hresReal;
  510. }
  511. HRESULT CProviderSinkServer::RemoveFilter(CAbstractEventSink* pDest,
  512. WBEM_REMOTE_TARGET_ID_TYPE* pidRequest)
  513. {
  514. HRESULT hres;
  515. // Find and invalidate the filter in the list of destinations
  516. // ==========================================================
  517. CEventDestination* pToRemove = NULL;
  518. CRefedPointerArray<IWbemFilterProxy> apProxies;
  519. {
  520. CInCritSec ics(&m_cs);
  521. // Copy the proxies
  522. // ================
  523. if(!GetProxies(apProxies))
  524. return WBEM_E_OUT_OF_MEMORY;
  525. // Search for it in the array of destinations
  526. // ==========================================
  527. for(int i = 0; i < m_apDestinations.GetSize(); i++)
  528. {
  529. if(m_apDestinations[i]->m_pSink == pDest)
  530. {
  531. m_apDestinations.RemoveAt(i, &pToRemove);
  532. break;
  533. }
  534. }
  535. if(pToRemove == NULL)
  536. return WBEM_E_NOT_FOUND;
  537. }
  538. if(pidRequest)
  539. *pidRequest = pToRemove->m_id;
  540. // The filter is invalidated, but not removed. We are outside of the CS, so
  541. // events can be delivered (but no other changes can occur)
  542. // =========================================================================
  543. // Instruct all proxies to (later) remove this filter from consideration
  544. // =====================================================================
  545. for(int i = 0; i < apProxies.GetSize(); i++)
  546. {
  547. hres = apProxies[i]->RemoveFilter(GetCurrentEssContext(),
  548. pToRemove->m_id);
  549. if(FAILED(hres))
  550. {
  551. if ( IsRpcError(hres) )
  552. {
  553. UnregisterProxy( apProxies[i] );
  554. }
  555. ERRORTRACE((LOG_ESS, "Unable to remove filter %I64d from an event "
  556. "provider proxy: 0x%X\n", pToRemove->m_id, hres));
  557. }
  558. }
  559. //
  560. // Delete the destination in question
  561. //
  562. delete pToRemove;
  563. return WBEM_S_NO_ERROR;
  564. }
  565. // assumes all proxies are locked
  566. void CProviderSinkServer::RemoveAllFilters()
  567. {
  568. CRefedPointerArray<IWbemFilterProxy> apProxies;
  569. {
  570. CInCritSec ics(&m_cs);
  571. // Copy the proxies
  572. // ================
  573. if(!GetProxies(apProxies))
  574. return;
  575. //
  576. // Clear out both the list of destinations
  577. //
  578. m_apDestinations.RemoveAll();
  579. }
  580. //
  581. // Remove all filters from all proxies
  582. //
  583. for(int i = 0; i < apProxies.GetSize(); i++)
  584. {
  585. HRESULT hres =
  586. apProxies[i]->RemoveAllFilters(GetCurrentEssContext());
  587. if(FAILED(hres))
  588. {
  589. if ( IsRpcError(hres) )
  590. {
  591. UnregisterProxy( apProxies[i] );
  592. }
  593. ERRORTRACE((LOG_ESS, "Unable to remove all queries from a "
  594. "remote provider proxy. Error code: %X\n", hres));
  595. }
  596. }
  597. }
  598. //
  599. // Only allow utilization of the guarantee if the proxy's definition
  600. // matches the provider's definition. In other words, only when
  601. // the provider's registration has been successfully processed,
  602. // and the proxies are set up to reflect it, should utilization of
  603. // the guarantee be allowed. The reason for this is that an incomplete
  604. // source definition can cause bad things to happen when events are
  605. // evaluated using a filter that was optimized for that definition.
  606. //
  607. HRESULT CProviderSinkServer::AllowUtilizeGuarantee()
  608. {
  609. CRefedPointerArray<IWbemFilterProxy> apProxies;
  610. {
  611. CInCritSec ics(&m_cs);
  612. if ( !GetProxies( apProxies ) )
  613. {
  614. return WBEM_E_OUT_OF_MEMORY;
  615. }
  616. }
  617. for(int i = 0; i < apProxies.GetSize(); i++)
  618. {
  619. HRESULT hr = apProxies[i]->AllowUtilizeGuarantee();
  620. if ( FAILED(hr) && IsRpcError(hr) )
  621. {
  622. UnregisterProxy( apProxies[i] );
  623. }
  624. }
  625. return WBEM_S_NO_ERROR;
  626. }
  627. HRESULT CProviderSinkServer::AddDefinitionQuery(LPCWSTR wszQuery)
  628. {
  629. CRefedPointerArray<IWbemFilterProxy> apProxies;
  630. {
  631. CInCritSec ics(&m_cs);
  632. GetProxies(apProxies);
  633. if ( m_awsDefinitionQueries.Add(wszQuery) < 0 )
  634. {
  635. return WBEM_E_OUT_OF_MEMORY;
  636. }
  637. }
  638. //
  639. // we always try to add the definition to all proxies, but if there's an
  640. // error ( other than RPC ) we return it to the caller.
  641. //
  642. HRESULT hresReturn = WBEM_S_NO_ERROR;
  643. for(int i = 0; i < apProxies.GetSize(); i++)
  644. {
  645. HRESULT hres = apProxies[i]->AddDefinitionQuery(
  646. GetCurrentEssContext(), wszQuery);
  647. if( FAILED(hres) )
  648. {
  649. if ( IsRpcError(hres) )
  650. {
  651. UnregisterProxy( apProxies[i] );
  652. }
  653. else
  654. {
  655. hresReturn = hres;
  656. }
  657. ERRORTRACE((LOG_ESS, "Unable to add definition query %S to a "
  658. "provider proxy. Error code: %X\n", wszQuery, hres));
  659. }
  660. }
  661. return hresReturn;
  662. }
  663. // assumes: all proxies are locked
  664. void CProviderSinkServer::RemoveAllDefinitionQueries()
  665. {
  666. CInCritSec ics(&m_cs);
  667. m_awsDefinitionQueries.Empty();
  668. for(int i = 0; i < m_apProxies.GetSize(); i++)
  669. {
  670. HRESULT hres = m_apProxies[i]->RemoveAllDefinitionQueries(
  671. GetCurrentEssContext());
  672. if(FAILED(hres))
  673. {
  674. ERRORTRACE((LOG_ESS, "Unable to remove all definition queries from"
  675. " a provider proxy. Error code: %X\n", hres));
  676. }
  677. }
  678. }
  679. void CProviderSinkServer::Clear()
  680. {
  681. // Provider is being removed. First, we disconnect all proxies, ensuring
  682. // that no more events are delivered
  683. // ======================================================================
  684. CRefedPointerArray<IWbemFilterProxy> apProxies;
  685. {
  686. CInCritSec ics(&m_cs);
  687. GetProxies(apProxies);
  688. m_apProxies.RemoveAll();
  689. m_awsDefinitionQueries.Empty();
  690. }
  691. //
  692. // since we are going to disconnect the proxy it is illegal to own the
  693. // namespace lock. Reason is that disconnecting takes ownership of the
  694. // proxy lock.
  695. //
  696. _DBG_ASSERT( !m_pNamespace->DoesThreadOwnNamespaceLock() );
  697. for(int i = 0; i < apProxies.GetSize(); i++)
  698. {
  699. apProxies[i]->Disconnect();
  700. }
  701. // Now we clean up
  702. // ===============
  703. RemoveAllFilters();
  704. RemoveAllDefinitionQueries();
  705. m_pReqSink = NULL;
  706. CWbemPtr<IUnknown> pStubUnk;
  707. HRESULT hr = m_Stub.QueryInterface( IID_IUnknown, (void**)&pStubUnk );
  708. _DBG_ASSERT( SUCCEEDED(hr) );
  709. hr = CoDisconnectObject( pStubUnk, 0 );
  710. if ( FAILED( hr ) )
  711. {
  712. ERRORTRACE((LOG_ESS,"Failed Disconnecting Stub.\n"));
  713. }
  714. }
  715. HRESULT CProviderSinkServer::Lock()
  716. {
  717. //
  718. // it is illegal to lock proxies while holding the namespace lock.
  719. //
  720. _DBG_ASSERT( !m_pNamespace->DoesThreadOwnNamespaceLock() );
  721. // DEBUGTRACE((LOG_ESS, "Server %p locking all proxies\n", this));
  722. // First we lock all the proxies. In the interim, events are still
  723. // delivered. Once done, events are blocked in proxies
  724. // ================================================================
  725. CRefedPointerArray<IWbemFilterProxy> apProxies;
  726. {
  727. CInCritSec ics(&m_cs);
  728. //
  729. // First, check if we are already locked. If so, no need to bother
  730. // the proxies. Not only that, but since proxies are out-of-proc, we
  731. // would be re-locking them on a different thread, causing a deadlock.
  732. //
  733. if(m_lLocks++ > 0)
  734. return WBEM_S_NO_ERROR;
  735. GetProxies(apProxies);
  736. }
  737. for(int i = 0; i < apProxies.GetSize(); i++)
  738. {
  739. // DEBUGTRACE((LOG_ESS, "Server %p locking proxy %p\n", this,
  740. // apProxies[i]));
  741. HRESULT hres = apProxies[i]->Lock();
  742. if(FAILED(hres))
  743. {
  744. ERRORTRACE((LOG_ESS, "Unable to lock a remote provider proxy. "
  745. "Error code: %X\n", hres));
  746. //
  747. // if we couldn't lock it because of an RPC Error, simply
  748. // unregister, else we have big problems and should unlock all
  749. // the proxies and return the error.
  750. //
  751. if ( IsRpcError( hres ) )
  752. {
  753. UnregisterProxy( apProxies[i] );
  754. }
  755. else
  756. {
  757. for(int j = 0; j < i; j++)
  758. apProxies[j]->Unlock();
  759. return hres;
  760. }
  761. }
  762. }
  763. return WBEM_S_NO_ERROR;
  764. }
  765. BOOL CProviderSinkServer::GetProxies(
  766. CRefedPointerArray<IWbemFilterProxy>& apProxies)
  767. {
  768. CInCritSec ics(&m_cs);
  769. for(int i = 0; i < m_apProxies.GetSize(); i++)
  770. {
  771. if(apProxies.Add(m_apProxies[i]) < 0)
  772. return FALSE;
  773. }
  774. return TRUE;
  775. }
  776. void CProviderSinkServer::Unlock()
  777. {
  778. // DEBUGTRACE((LOG_ESS, "Server %p unlocking all proxies\n", this));
  779. CRefedPointerArray<IWbemFilterProxy> apProxies;
  780. {
  781. CInCritSec ics(&m_cs);
  782. //
  783. // First, check if this is the last unlock. If not, we didn't forward
  784. // this lock, so we shouldn't forward this unlock either
  785. //
  786. if(--m_lLocks != 0)
  787. return;
  788. GetProxies(apProxies);
  789. }
  790. for(int i = 0; i < apProxies.GetSize(); i++)
  791. {
  792. // DEBUGTRACE((LOG_ESS, "Server %p unlocking proxy %p\n", this,
  793. // apProxies[i]));
  794. HRESULT hres = apProxies[i]->Unlock();
  795. if(FAILED(hres))
  796. {
  797. ERRORTRACE((LOG_ESS, "Unable to unlock a remote provider proxy. "
  798. "Error code: %X\n", hres));
  799. if ( IsRpcError(hres) )
  800. {
  801. UnregisterProxy( apProxies[i] );
  802. }
  803. }
  804. }
  805. }
  806. HRESULT STDMETHODCALLTYPE CProviderSinkServer::RegisterProxy(
  807. IWbemFilterProxy* pProxy)
  808. {
  809. // Initialize it with ourselves
  810. // ============================
  811. HRESULT hres = pProxy->Initialize(m_pMetaData, &m_Stub);
  812. if(FAILED(hres))
  813. {
  814. ERRORTRACE((LOG_ESS, "Unable to initialize remote proxy: %X\n", hres));
  815. return hres;
  816. }
  817. {
  818. CInCritSec ics(&m_cs);
  819. // At this point, it is locked
  820. // ===========================
  821. if(m_apProxies.Add(pProxy) < 0)
  822. return WBEM_E_OUT_OF_MEMORY;
  823. //
  824. // Add all the definition queries to this proxy
  825. //
  826. int i;
  827. BOOL bUtilizeGuarantee = TRUE;
  828. for(i = 0; i < m_awsDefinitionQueries.Size(); i++)
  829. {
  830. hres = pProxy->AddDefinitionQuery( GetCurrentEssContext(),
  831. m_awsDefinitionQueries[i]);
  832. if(FAILED(hres))
  833. {
  834. //
  835. // TODO : We need to mark the provider as inactive.
  836. //
  837. ERRORTRACE((LOG_ESS, "Unable to add definition query '%S' to "
  838. "provider sink: 0x%X.\n",
  839. m_awsDefinitionQueries[i], hres));
  840. bUtilizeGuarantee = FALSE;
  841. }
  842. }
  843. if ( bUtilizeGuarantee )
  844. {
  845. pProxy->AllowUtilizeGuarantee();
  846. }
  847. //
  848. // Add all the filters to this proxy
  849. //
  850. for(i = 0; i < m_apDestinations.GetSize(); i++)
  851. {
  852. // Retrieve the filter from the event sink
  853. // =======================================
  854. CEventDestination* pDest = m_apDestinations[i];
  855. CEventFilter* pFilter = pDest->m_pSink->GetEventFilter();
  856. if(pFilter == NULL)
  857. {
  858. ERRORTRACE((LOG_ESS, "Internal error: non-filter sink in "
  859. "proxy\n"));
  860. continue;
  861. }
  862. LPWSTR wszQuery;
  863. LPWSTR wszQueryLanguage;
  864. BOOL bExact;
  865. if(SUCCEEDED(pFilter->GetCoveringQuery(wszQueryLanguage, wszQuery,
  866. bExact, NULL)) && bExact)
  867. {
  868. // Add this filter to this proxy
  869. // =============================
  870. hres = pProxy->AddFilter(GetCurrentEssContext(), wszQuery,
  871. pDest->m_id);
  872. if(FAILED(hres))
  873. {
  874. ERRORTRACE((LOG_ESS, "Unable to add query %S to a remote "
  875. "provider proxy. Error code: %X\n", wszQuery, hres));
  876. }
  877. delete [] wszQuery;
  878. delete [] wszQueryLanguage;
  879. }
  880. }
  881. //
  882. // Only unlock the remote proxy if we ourselves are not currently
  883. // locked. If we are, the proxy will get unlocked with all the others
  884. // since it is now added to m_apProxies.
  885. //
  886. if(m_lLocks == 0)
  887. pProxy->Unlock();
  888. }
  889. return WBEM_S_NO_ERROR;
  890. }
  891. HRESULT STDMETHODCALLTYPE CProviderSinkServer::UnregisterProxy(
  892. IWbemFilterProxy* pProxy)
  893. {
  894. CInCritSec ics(&m_cs);
  895. // Look for it
  896. // ===========
  897. for(int i = 0; i < m_apProxies.GetSize(); i++)
  898. {
  899. if(m_apProxies[i] == pProxy)
  900. {
  901. // It is safe to release it, since the caller has a ref-count
  902. // ==========================================================
  903. m_apProxies.RemoveAt(i);
  904. return WBEM_S_NO_ERROR;
  905. }
  906. }
  907. return WBEM_S_FALSE;
  908. }
  909. ULONG STDMETHODCALLTYPE CFilterStub::AddRef()
  910. {
  911. return m_pSink->AddRef();
  912. }
  913. ULONG STDMETHODCALLTYPE CFilterStub::Release()
  914. {
  915. return m_pSink->Release();
  916. }
  917. HRESULT STDMETHODCALLTYPE CFilterStub::QueryInterface(REFIID riid, void** ppv)
  918. {
  919. if(riid == IID_IUnknown || riid == IID_IWbemFilterStub)
  920. {
  921. *ppv = (IWbemFilterStub*)this;
  922. }
  923. else if(riid == IID_IWbemMultiTarget)
  924. {
  925. *ppv = (IWbemMultiTarget*)this;
  926. }
  927. else if ( riid == IID_IWbemFetchSmartMultiTarget )
  928. {
  929. *ppv = (IWbemFetchSmartMultiTarget*)this;
  930. }
  931. else if ( riid == IID_IWbemSmartMultiTarget )
  932. {
  933. *ppv = (IWbemSmartMultiTarget*)this;
  934. }
  935. else if( riid == IID_IWbemEventProviderRequirements)
  936. {
  937. *ppv = (IWbemEventProviderRequirements*)this;
  938. }
  939. else return E_NOINTERFACE;
  940. AddRef();
  941. return S_OK;
  942. }
  943. HRESULT STDMETHODCALLTYPE CFilterStub::RegisterProxy(IWbemFilterProxy* pProxy)
  944. {
  945. return m_pSink->RegisterProxy(pProxy);
  946. }
  947. HRESULT STDMETHODCALLTYPE CFilterStub::UnregisterProxy(IWbemFilterProxy* pProxy)
  948. {
  949. return m_pSink->UnregisterProxy(pProxy);
  950. }
  951. HRESULT STDMETHODCALLTYPE CFilterStub::DeliverEvent(DWORD dwNumEvents,
  952. IWbemClassObject** apEvents,
  953. WBEM_REM_TARGETS* aTargets,
  954. long lSDLength, BYTE* pSD)
  955. {
  956. CEventContext Context;
  957. Context.SetSD( lSDLength, pSD, FALSE );
  958. return m_pSink->DeliverEvent( dwNumEvents, apEvents, aTargets, &Context );
  959. }
  960. HRESULT STDMETHODCALLTYPE CFilterStub::DeliverStatus(long lFlags,
  961. HRESULT hresStatus,
  962. LPCWSTR wszStatus, IWbemClassObject* pErrorObj,
  963. WBEM_REM_TARGETS* pTargets,
  964. long lSDLength, BYTE* pSD)
  965. {
  966. CEventContext Context;
  967. Context.SetSD( lSDLength, pSD, FALSE );
  968. return m_pSink->DeliverStatus(lFlags, hresStatus, wszStatus, pErrorObj,
  969. pTargets, &Context);
  970. }
  971. HRESULT STDMETHODCALLTYPE CFilterStub::DeliverProviderRequest(long lFlags)
  972. {
  973. return m_pSink->DeliverProviderRequest(lFlags);
  974. }
  975. HRESULT STDMETHODCALLTYPE CFilterStub::GetSmartMultiTarget( IWbemSmartMultiTarget** ppSmartMultiTarget )
  976. {
  977. return QueryInterface( IID_IWbemSmartMultiTarget, (void**) ppSmartMultiTarget );
  978. }
  979. HRESULT STDMETHODCALLTYPE CFilterStub::DeliverEvent(ULONG dwNumEvents,
  980. ULONG dwBuffSize,
  981. BYTE* pBuffer,
  982. WBEM_REM_TARGETS* pTargets,
  983. long lSDLength, BYTE* pSD)
  984. {
  985. // Unwind the buffer into an object. Note that because m_ClassCache is
  986. // STL based, it is intrinsically thread-safe. Also, calling proxies are
  987. // serialized, so we shouldn't have any thread-safety problems here.
  988. CWbemMtgtDeliverEventPacket packet( (LPBYTE) pBuffer, dwBuffSize );
  989. long lObjectCount;
  990. IWbemClassObject ** pObjArray;
  991. HRESULT hr = packet.UnmarshalPacket( lObjectCount, pObjArray, m_ClassCache );
  992. if ( SUCCEEDED( hr ) )
  993. {
  994. // Number must be dwNumEvents
  995. if(lObjectCount == dwNumEvents)
  996. {
  997. // Now call the standard deliver event function and hand it the
  998. // object
  999. hr = DeliverEvent(dwNumEvents, pObjArray, pTargets, lSDLength, pSD);
  1000. }
  1001. else
  1002. {
  1003. hr = WBEM_E_UNEXPECTED;
  1004. }
  1005. // Release the objects in the array and clean up pObjArray
  1006. for ( int lCtr = 0; lCtr < lObjectCount; lCtr++ )
  1007. {
  1008. pObjArray[lCtr]->Release();
  1009. }
  1010. delete [] pObjArray;
  1011. } // IF UnmarshalPacket
  1012. return hr;
  1013. }
  1014. void CProviderSinkServer::GetStatistics(long* plProxies, long* plDestinations,
  1015. long* plFilters, long* plTargetLists, long* plTargets,
  1016. long* plPostponed)
  1017. {
  1018. *plProxies = m_apProxies.GetSize();
  1019. *plDestinations = m_apDestinations.GetSize();
  1020. /* BUGBUG: do properly for all sinks
  1021. ((CFilterProxy*)m_pSink)->GetStatistics(plFilters, plTargetLists,
  1022. plTargets, plPostponed);
  1023. */
  1024. }
  1025. //******************************************************************************
  1026. //******************************************************************************
  1027. //
  1028. // CRECORD :: CQUERY RECORD
  1029. //
  1030. //******************************************************************************
  1031. //******************************************************************************
  1032. CEventProviderCache::CRecord::CQueryRecord::CQueryRecord()
  1033. : m_strQuery(NULL), m_pEventClass(NULL),
  1034. m_dwEventMask(0), m_paInstanceClasses(NULL), m_pExpr(NULL)
  1035. {
  1036. }
  1037. HRESULT CEventProviderCache::CRecord::CQueryRecord::EnsureClasses(
  1038. CEssNamespace* pNamespace )
  1039. {
  1040. HRESULT hres = WBEM_S_NO_ERROR;
  1041. _IWmiObject* pClass;
  1042. if ( m_pEventClass == NULL )
  1043. {
  1044. if ( SUCCEEDED( pNamespace->GetClass( m_pExpr->bsClassName,
  1045. &pClass ) ) )
  1046. {
  1047. m_pEventClass = pClass;
  1048. }
  1049. else
  1050. {
  1051. hres = WBEM_S_FALSE;
  1052. }
  1053. }
  1054. if ( m_paInstanceClasses != NULL )
  1055. {
  1056. for(int i = 0; i < m_paInstanceClasses->GetNumClasses(); i++)
  1057. {
  1058. CClassInformation* pInfo = m_paInstanceClasses->GetClass(i);
  1059. if ( pInfo->m_pClass == NULL )
  1060. {
  1061. if ( SUCCEEDED( pNamespace->GetClass( pInfo->m_wszClassName,
  1062. &pClass) ) )
  1063. {
  1064. pInfo->m_pClass = pClass;
  1065. }
  1066. else
  1067. {
  1068. hres = WBEM_S_FALSE;
  1069. }
  1070. }
  1071. }
  1072. }
  1073. else
  1074. {
  1075. hres = WBEM_S_FALSE;
  1076. }
  1077. return hres;
  1078. }
  1079. void CEventProviderCache::CRecord::CQueryRecord::ReleaseClasses()
  1080. {
  1081. if ( m_pEventClass != NULL )
  1082. {
  1083. m_pEventClass->Release();
  1084. m_pEventClass = NULL;
  1085. }
  1086. if ( m_paInstanceClasses != NULL )
  1087. {
  1088. for(int i = 0; i < m_paInstanceClasses->GetNumClasses(); i++)
  1089. {
  1090. CClassInformation* pInfo = m_paInstanceClasses->GetClass(i);
  1091. if ( pInfo->m_pClass != NULL )
  1092. {
  1093. pInfo->m_pClass->Release();
  1094. pInfo->m_pClass = NULL;
  1095. }
  1096. }
  1097. }
  1098. }
  1099. HRESULT CEventProviderCache::CRecord::CQueryRecord::Initialize(
  1100. LPCWSTR wszQuery,
  1101. LPCWSTR wszProvName,
  1102. CEssNamespace* pNamespace,
  1103. bool bSystem)
  1104. {
  1105. HRESULT hres;
  1106. m_strQuery = SysAllocString(wszQuery);
  1107. if(m_strQuery == NULL)
  1108. return WBEM_E_OUT_OF_MEMORY;
  1109. // Parse the query
  1110. // ===============
  1111. CTextLexSource Source((LPWSTR)wszQuery);
  1112. QL1_Parser Parser(&Source);
  1113. if(Parser.Parse(&m_pExpr) != QL1_Parser::SUCCESS)
  1114. {
  1115. ERRORTRACE((LOG_ESS,
  1116. "Invalid query in provider registration: %S\n", wszQuery));
  1117. CEventLog Log; Log.Open();
  1118. Log.Report(EVENTLOG_ERROR_TYPE,
  1119. WBEM_MC_INVALID_EVENT_PROVIDER_QUERY,
  1120. wszQuery);
  1121. return WBEM_E_UNPARSABLE_QUERY;
  1122. }
  1123. if(!bSystem)
  1124. {
  1125. if(!wbem_wcsicmp(m_pExpr->bsClassName, L"__Event") ||
  1126. !wbem_wcsicmp(m_pExpr->bsClassName, L"__ExtrinsicEvent"))
  1127. {
  1128. ERRORTRACE((LOG_ESS,
  1129. "Provider claims to provide all events with "
  1130. "query: %S\n"
  1131. "We don't believe it, so we ignore the registration\n\n",
  1132. wszQuery));
  1133. CEventLog Log; Log.Open();
  1134. Log.Report(EVENTLOG_ERROR_TYPE,
  1135. WBEM_MC_EVENT_PROVIDER_QUERY_TOO_BROAD,
  1136. wszQuery);
  1137. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  1138. }
  1139. }
  1140. // Determine its event mask
  1141. // ========================
  1142. m_dwEventMask = CEventRepresentation::GetTypeMaskFromName(
  1143. m_pExpr->bsClassName);
  1144. // Check if the mask mentions any pollable events
  1145. // ==============================================
  1146. if(m_dwEventMask & INTRINSIC_EVENTS_MASK)
  1147. {
  1148. // Yes. Get instance classes for which it providers these events
  1149. // =============================================================
  1150. hres = CQueryAnalyser::GetDefiniteInstanceClasses(m_pExpr,
  1151. m_paInstanceClasses);
  1152. if(FAILED(hres))
  1153. {
  1154. ERRORTRACE((LOG_ESS,
  1155. "Unable to determine instance classes for which events"
  1156. "are provided by this query: %S\n", wszQuery));
  1157. CEventLog Log; Log.Open();
  1158. Log.Report(EVENTLOG_ERROR_TYPE,
  1159. WBEM_MC_INVALID_EVENT_PROVIDER_INTRINSIC_QUERY,
  1160. wszQuery);
  1161. return WBEM_E_UNINTERPRETABLE_PROVIDER_QUERY;
  1162. }
  1163. if(!bSystem && !m_paInstanceClasses->IsLimited())
  1164. {
  1165. ERRORTRACE((LOG_ESS,
  1166. "Provider claims to provide all intrinsic events with "
  1167. "query: %S\n"
  1168. "We don't believe it, so we ignore the registration\n\n",
  1169. wszQuery));
  1170. CEventLog Log; Log.Open();
  1171. Log.Report(EVENTLOG_ERROR_TYPE,
  1172. WBEM_MC_EVENT_PROVIDER_QUERY_TOO_BROAD,
  1173. wszQuery);
  1174. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  1175. }
  1176. // Get the actual classes from the namespace
  1177. // =========================================
  1178. for(int i = 0; i < m_paInstanceClasses->GetNumClasses(); i++)
  1179. {
  1180. CClassInformation* pInfo = m_paInstanceClasses->GetClass(i);
  1181. _IWmiObject* pClass = NULL;
  1182. hres = pNamespace->GetClass(pInfo->m_wszClassName, &pClass);
  1183. if(FAILED(hres))
  1184. {
  1185. ERRORTRACE((LOG_ESS,
  1186. "Could not get class %S for which provider claims"
  1187. " to provider events. Error code: %X\n",
  1188. pInfo->m_wszClassName, hres));
  1189. CEventLog Log; Log.Open();
  1190. Log.Report(EVENTLOG_ERROR_TYPE,
  1191. WBEM_MC_EVENT_PROVIDER_QUERY_NOT_FOUND,
  1192. wszQuery, pInfo->m_wszClassName);
  1193. //
  1194. // Before continuing, we register for class creation event on
  1195. // this class. This way, when it is finally created, we will
  1196. // reactivate stuff and bring the system back on track
  1197. //
  1198. hres = pNamespace->RegisterProviderForClassChanges(
  1199. pInfo->m_wszClassName,
  1200. wszProvName );
  1201. // ignore error code --- what can we do?
  1202. return WBEM_S_FALSE;
  1203. }
  1204. //
  1205. // don't store, we'll retrieve it later as necessary. This
  1206. // will require that the user call EnsureClasses() before calling
  1207. // any function that needs those classes.
  1208. //
  1209. pClass->Release();
  1210. }
  1211. }
  1212. // Get the event class
  1213. // ===================
  1214. _IWmiObject* pClass = NULL;
  1215. hres = pNamespace->GetClass(m_pExpr->bsClassName, &pClass);
  1216. if(FAILED(hres))
  1217. {
  1218. ERRORTRACE((LOG_ESS,
  1219. "Invalid event class %S in provider registration \n"
  1220. "Query was: %S\n\n", m_pExpr->bsClassName, wszQuery));
  1221. CEventLog Log; Log.Open();
  1222. Log.Report(EVENTLOG_ERROR_TYPE,
  1223. WBEM_MC_EVENT_PROVIDER_QUERY_NOT_FOUND,
  1224. wszQuery, m_pExpr->bsClassName);
  1225. //
  1226. // Before continuing, we register for class creation event on this
  1227. // class. This way, when it is finally created, we will reactivate
  1228. // stuff and bring the system back on track
  1229. //
  1230. hres = pNamespace->RegisterProviderForClassChanges(
  1231. m_pExpr->bsClassName,
  1232. wszProvName );
  1233. // ignore error code --- what can we do?
  1234. return WBEM_S_FALSE;
  1235. }
  1236. //
  1237. // don't store, we'll retrieve it later as necessary. This
  1238. // will require that the user call EnsureClasses() before calling
  1239. // any function that needs those classes.
  1240. //
  1241. CReleaseMe rmpClass( pClass );
  1242. if( pClass->InheritsFrom(L"__Event") != S_OK)
  1243. {
  1244. ERRORTRACE((LOG_ESS,
  1245. "Invalid event class %S in provider registration \n"
  1246. "Query was: %S\n\n", m_pExpr->bsClassName, wszQuery));
  1247. CEventLog Log; Log.Open();
  1248. Log.Report(EVENTLOG_ERROR_TYPE,
  1249. WBEM_MC_EVENT_PROVIDER_QUERY_NOT_EVENT,
  1250. wszQuery, m_pExpr->bsClassName);
  1251. return WBEM_S_FALSE;
  1252. }
  1253. return WBEM_S_NO_ERROR;
  1254. }
  1255. CEventProviderCache::CRecord::CQueryRecord::~CQueryRecord()
  1256. {
  1257. SysFreeString(m_strQuery);
  1258. if(m_pEventClass)
  1259. m_pEventClass->Release();
  1260. delete m_paInstanceClasses;
  1261. delete m_pExpr;
  1262. }
  1263. HRESULT CEventProviderCache::CRecord::CQueryRecord::Update(LPCWSTR wszClassName,
  1264. IWbemClassObject* pClass)
  1265. {
  1266. HRESULT hres = WBEM_S_FALSE;
  1267. // Check the event class
  1268. // =====================
  1269. if(!wbem_wcsicmp(wszClassName, m_pExpr->bsClassName))
  1270. {
  1271. if(pClass == NULL)
  1272. {
  1273. // This query record is hereby invalid
  1274. // ===================================
  1275. ERRORTRACE((LOG_ESS,
  1276. "Event provider query, %S, is invalidated by class "
  1277. "deletion of %S\n", m_strQuery, m_pExpr->bsClassName));
  1278. if(m_pEventClass)
  1279. m_pEventClass->Release();
  1280. m_pEventClass = NULL;
  1281. delete m_paInstanceClasses;
  1282. m_paInstanceClasses = NULL;
  1283. }
  1284. else
  1285. {
  1286. // Change the class definition
  1287. // ===========================
  1288. if(m_pEventClass)
  1289. {
  1290. m_pEventClass->Release();
  1291. pClass->Clone(&m_pEventClass);
  1292. }
  1293. }
  1294. hres = WBEM_S_NO_ERROR;
  1295. }
  1296. if(m_paInstanceClasses)
  1297. {
  1298. // Check the instance classes
  1299. // ==========================
  1300. for(int i = 0; i < m_paInstanceClasses->GetNumClasses(); i++)
  1301. {
  1302. CClassInformation* pInfo = m_paInstanceClasses->GetClass(i);
  1303. if(!wbem_wcsicmp(wszClassName, pInfo->m_wszClassName))
  1304. {
  1305. if(pClass)
  1306. {
  1307. // This class is no longer there
  1308. // =============================
  1309. ERRORTRACE((LOG_ESS,
  1310. "Class %S for which provider claims to provide"
  1311. " events is deleted", pInfo->m_wszClassName));
  1312. m_paInstanceClasses->RemoveClass(i);
  1313. i--;
  1314. }
  1315. else
  1316. {
  1317. // Change the class definition
  1318. // ===========================
  1319. if(pInfo->m_pClass)
  1320. {
  1321. pInfo->m_pClass->Release();
  1322. pClass->Clone(&pInfo->m_pClass);
  1323. }
  1324. }
  1325. hres = WBEM_S_NO_ERROR;
  1326. }
  1327. }
  1328. }
  1329. return hres;
  1330. }
  1331. HRESULT CEventProviderCache::CRecord::CQueryRecord::DoesIntersectWithQuery(
  1332. IN CRequest& Request, CEssNamespace* pNamespace)
  1333. {
  1334. HRESULT hres;
  1335. if(m_pEventClass == NULL)
  1336. {
  1337. // Inactive record
  1338. return WBEM_S_FALSE;
  1339. }
  1340. // Check that the classes are related --- one is derived from another
  1341. // ==================================================================
  1342. if(m_pEventClass->InheritsFrom(Request.GetQueryExpr()->bsClassName)
  1343. != WBEM_S_NO_ERROR &&
  1344. Request.GetEventClass(pNamespace)->InheritsFrom(m_pExpr->bsClassName)
  1345. != WBEM_S_NO_ERROR
  1346. )
  1347. {
  1348. // Not the right class.
  1349. // ====================
  1350. return WBEM_S_FALSE;
  1351. }
  1352. // For extrinsic providers, this is good enough. But for
  1353. // intrinsic providers, we need to check if the requested
  1354. // instance classes intersect with the provided ones
  1355. // ======================================================
  1356. if(Request.GetEventMask() & INSTANCE_EVENTS_MASK)
  1357. {
  1358. INTERNAL CClassInfoArray* pClasses = NULL;
  1359. hres = Request.GetInstanceClasses(pNamespace, &pClasses);
  1360. if(FAILED(hres))
  1361. {
  1362. ERRORTRACE((LOG_ESS,
  1363. "Failed to determine instance classes required by query '%S':"
  1364. "0x%X\n", Request.GetQuery(), hres));
  1365. return hres;
  1366. }
  1367. if(!CQueryAnalyser::CompareRequestedToProvided(
  1368. *pClasses,
  1369. *m_paInstanceClasses))
  1370. {
  1371. // This intrinsic provider does not need activation
  1372. // ================================================
  1373. return WBEM_S_FALSE;
  1374. }
  1375. }
  1376. // All test have been passed
  1377. // =========================
  1378. return WBEM_S_NO_ERROR;
  1379. }
  1380. DWORD CEventProviderCache::CRecord::CQueryRecord::GetProvidedEventMask(
  1381. IWbemClassObject* pClass,
  1382. BSTR strClassName)
  1383. {
  1384. if(m_pEventClass == NULL || m_paInstanceClasses == NULL)
  1385. {
  1386. // Not active as an intrinsic provider record
  1387. // ==========================================
  1388. return 0;
  1389. }
  1390. // Check that we supply intrinsic events
  1391. // =====================================
  1392. if((m_dwEventMask & INSTANCE_EVENTS_MASK) == 0)
  1393. return 0;
  1394. // Go through all the instance classes for which it provides events
  1395. // ================================================================
  1396. for(int k = 0; k < m_paInstanceClasses->GetNumClasses(); k++)
  1397. {
  1398. CClassInformation* pInfo = m_paInstanceClasses->GetClass(k);
  1399. if(pInfo->m_pClass == NULL)
  1400. {
  1401. // Non-existent class
  1402. // ==================
  1403. return 0;
  1404. }
  1405. //
  1406. // If desired class is derived from the provided class, then we are
  1407. // covered. If it is the other way around, we are not
  1408. //
  1409. if(pClass->InheritsFrom(pInfo->m_wszClassName) == S_OK)
  1410. return m_dwEventMask;
  1411. }
  1412. return 0;
  1413. }
  1414. //******************************************************************************
  1415. //******************************************************************************
  1416. //
  1417. // CRECORD
  1418. //
  1419. //******************************************************************************
  1420. //******************************************************************************
  1421. CEventProviderCache::CRecord::CRecord()
  1422. : m_strName(NULL), m_lRef(0), m_bStarted(false), m_lPermUsageCount(0),
  1423. m_bProviderSet(FALSE), m_lUsageCount(0), m_pProvider(NULL),
  1424. m_pQuerySink(NULL), m_pMainSink(NULL), m_pSecurity(NULL),
  1425. m_LastUse(CWbemTime::GetCurrentTime()), m_bRecorded(FALSE),
  1426. m_bNeedsResync(TRUE), m_strNamespace(NULL)
  1427. {
  1428. }
  1429. HRESULT CEventProviderCache::CRecord::Initialize( LPCWSTR wszName,
  1430. CEssNamespace* pNamespace )
  1431. {
  1432. m_pNamespace = pNamespace;
  1433. m_pNamespace->AddRef();
  1434. m_pMainSink = new CProviderSinkServer();
  1435. if(m_pMainSink == NULL)
  1436. return WBEM_E_OUT_OF_MEMORY;
  1437. m_pMainSink->AddRef();
  1438. m_strNamespace = SysAllocString(pNamespace->GetName());
  1439. if(m_strNamespace == NULL)
  1440. return WBEM_E_OUT_OF_MEMORY;
  1441. if ( wszName != NULL )
  1442. {
  1443. m_strName = SysAllocString(wszName);
  1444. if(m_strName == NULL)
  1445. return WBEM_E_OUT_OF_MEMORY;
  1446. }
  1447. return m_pMainSink->Initialize(pNamespace, this);
  1448. }
  1449. CEventProviderCache::CRecord::~CRecord()
  1450. {
  1451. if(m_pNamespace)
  1452. m_pNamespace->Release();
  1453. if( m_pMainSink )
  1454. {
  1455. //
  1456. // shutdown and release the sink server. We must postpone the
  1457. // shutdown though because it will release any outstanding
  1458. // proxies which cannot be done while holding the namespace lock.
  1459. //
  1460. CPostponedList* pList = GetCurrentPostponedList();
  1461. _DBG_ASSERT( pList != NULL );
  1462. CPostponedSinkServerShutdown* pReq;
  1463. pReq = new CPostponedSinkServerShutdown( m_pMainSink );
  1464. if ( pReq != NULL )
  1465. {
  1466. if ( FAILED(pList->AddRequest( m_pNamespace, pReq ) ) )
  1467. {
  1468. delete pReq;
  1469. }
  1470. }
  1471. m_pMainSink->Release();
  1472. }
  1473. UnloadProvider();
  1474. SysFreeString(m_strNamespace);
  1475. SysFreeString(m_strName);
  1476. }
  1477. ULONG CEventProviderCache::CRecord::AddRef()
  1478. {
  1479. return InterlockedIncrement(&m_lRef);
  1480. }
  1481. ULONG CEventProviderCache::CRecord::Release()
  1482. {
  1483. long lRef = InterlockedDecrement(&m_lRef);
  1484. if(lRef == 0)
  1485. delete this;
  1486. return lRef;
  1487. }
  1488. BOOL CEventProviderCache::CRecord::IsEmpty()
  1489. {
  1490. return ( !m_bProviderSet && m_apQueries.GetSize() == 0);
  1491. }
  1492. HRESULT CEventProviderCache::CRecord::SetProvider(IWbemClassObject* pWin32Prov)
  1493. {
  1494. HRESULT hres;
  1495. // Clean out the old data
  1496. // ======================
  1497. m_bProviderSet = FALSE;
  1498. VARIANT v;
  1499. VariantInit(&v);
  1500. CClearMe cm1(&v);
  1501. // Verity object validity
  1502. // ======================
  1503. if(pWin32Prov->InheritsFrom(WIN32_PROVIDER_CLASS) != WBEM_S_NO_ERROR)
  1504. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1505. // removed doublecheck - a decoupled provider does not have a clsid
  1506. // if(FAILED(pWin32Prov->Get(PROVIDER_CLSID_PROPNAME, 0, &v, NULL, NULL)) ||
  1507. // V_VT(&v) != VT_BSTR)
  1508. // return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1509. if(m_pProvider)
  1510. {
  1511. UnloadProvider();
  1512. }
  1513. // Store object for later use
  1514. // ==========================
  1515. m_bProviderSet = TRUE;
  1516. return WBEM_S_NO_ERROR;
  1517. }
  1518. HRESULT CEventProviderCache::CRecord::ResetProvider()
  1519. {
  1520. if(m_bProviderSet)
  1521. {
  1522. m_bProviderSet = FALSE;
  1523. return WBEM_S_NO_ERROR;
  1524. }
  1525. else
  1526. {
  1527. return WBEM_S_FALSE;
  1528. }
  1529. }
  1530. HRESULT CEventProviderCache::CRecord::GetProviderInfo(
  1531. IWbemClassObject* pRegistration,
  1532. BSTR& strName)
  1533. {
  1534. VARIANT v;
  1535. VariantInit(&v);
  1536. strName = NULL;
  1537. if(FAILED(pRegistration->Get(PROVIDER_NAME_PROPNAME, 0, &v, NULL, NULL)) ||
  1538. V_VT(&v) != VT_BSTR)
  1539. {
  1540. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1541. }
  1542. strName = V_BSTR(&v);
  1543. // VARIANT intentionally not cleared
  1544. return WBEM_S_NO_ERROR;
  1545. }
  1546. HRESULT CEventProviderCache::CRecord::GetRegistrationInfo(
  1547. IWbemClassObject* pRegistration,
  1548. BSTR& strName)
  1549. {
  1550. VARIANT v;
  1551. VariantInit(&v);
  1552. CClearMe cm1(&v);
  1553. strName = NULL;
  1554. if(FAILED(pRegistration->Get(EVPROVREG_PROVIDER_REF_PROPNAME, 0, &v,
  1555. NULL, NULL)) || V_VT(&v) != VT_BSTR)
  1556. {
  1557. ERRORTRACE((LOG_ESS, "NULL provider reference in event provider "
  1558. "registration! Registration is invalid\n"));
  1559. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1560. }
  1561. // Parse the path
  1562. // ==============
  1563. CObjectPathParser Parser;
  1564. ParsedObjectPath* pPath;
  1565. int nRes = Parser.Parse(V_BSTR(&v), &pPath);
  1566. if(nRes != CObjectPathParser::NoError)
  1567. {
  1568. ERRORTRACE((LOG_ESS, "Unparsable provider reference in event provider "
  1569. "registration: %S. Registration is invalid\n", V_BSTR(&v)));
  1570. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1571. }
  1572. //
  1573. // It would be good to check that the class specified here is valid, but
  1574. // we cannot just compare the name since this may be a derived class of
  1575. // __Win32Provider. And getting the class definition and comparing would
  1576. // be too expensive, so we'll just trust the provider here
  1577. //
  1578. //
  1579. // if(_wcsicmp(pPath->m_pClass, WIN32_PROVIDER_CLASS))
  1580. // {
  1581. // Parser.Free(pPath);
  1582. // return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1583. // }
  1584. if(pPath->m_dwNumKeys != 1)
  1585. {
  1586. Parser.Free(pPath);
  1587. ERRORTRACE((LOG_ESS, "Wrong number of keys in provider reference in "
  1588. "event provider registration: %S. Registration is invalid\n",
  1589. V_BSTR(&v)));
  1590. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1591. }
  1592. if(V_VT(&pPath->m_paKeys[0]->m_vValue) != VT_BSTR)
  1593. {
  1594. Parser.Free(pPath);
  1595. ERRORTRACE((LOG_ESS, "Wrong key type in provider reference in event "
  1596. "provider registration: %S. Registration is invalid\n",
  1597. V_BSTR(&v)));
  1598. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1599. }
  1600. strName = SysAllocString(V_BSTR(&pPath->m_paKeys[0]->m_vValue));
  1601. Parser.Free(pPath);
  1602. return WBEM_S_NO_ERROR;
  1603. }
  1604. HRESULT CEventProviderCache::CRecord::SetQueries(CEssNamespace* pNamespace,
  1605. IWbemClassObject* pRegistration)
  1606. {
  1607. HRESULT hres;
  1608. // Get the list of class names
  1609. // ===========================
  1610. VARIANT v;
  1611. VariantInit(&v);
  1612. if(FAILED(pRegistration->Get(EVPROVREG_QUERY_LIST_PROPNAME, 0, &v,
  1613. NULL, NULL)) || V_VT(&v) != (VT_BSTR | VT_ARRAY))
  1614. {
  1615. ResetQueries();
  1616. return WBEM_E_INVALID_PROVIDER_REGISTRATION;
  1617. }
  1618. CClearMe cm(&v);
  1619. SAFEARRAY* psa = V_ARRAY(&v);
  1620. long lLBound, lUBound;
  1621. SafeArrayGetLBound(psa, 1, &lLBound);
  1622. SafeArrayGetUBound(psa, 1, &lUBound);
  1623. long lElements = lUBound - lLBound + 1;
  1624. BSTR* astrQueries;
  1625. SafeArrayAccessData(psa, (void**)&astrQueries);
  1626. CUnaccessMe um(psa);
  1627. return SetQueries(pNamespace, lElements, (LPCWSTR*)astrQueries);
  1628. }
  1629. HRESULT CEventProviderCache::CRecord::SetQueries(CEssNamespace* pNamespace,
  1630. long lNumQueries,
  1631. LPCWSTR* awszQueries)
  1632. {
  1633. HRESULT hres;
  1634. ResetQueries();
  1635. // Create a record for each query
  1636. // ==============================
  1637. BOOL bUtilizeGuarantee = TRUE;
  1638. for(long lQueryIndex = 0; lQueryIndex < lNumQueries; lQueryIndex++)
  1639. {
  1640. hres = AddDefinitionQuery(pNamespace, awszQueries[lQueryIndex]);
  1641. if ( FAILED(hres) )
  1642. {
  1643. bUtilizeGuarantee = FALSE;
  1644. }
  1645. if( hres == WBEM_E_OUT_OF_MEMORY )
  1646. {
  1647. return hres;
  1648. }
  1649. }
  1650. if ( bUtilizeGuarantee )
  1651. {
  1652. m_pMainSink->AllowUtilizeGuarantee();
  1653. }
  1654. return WBEM_S_NO_ERROR;
  1655. }
  1656. // assumes: CProviderSinkServer locked!
  1657. HRESULT CEventProviderCache::CRecord::AddDefinitionQuery(
  1658. CEssNamespace* pNamespace,
  1659. LPCWSTR wszQuery)
  1660. {
  1661. HRESULT hres;
  1662. CQueryRecord* pNewQueryRecord = new CQueryRecord;
  1663. if(pNewQueryRecord == NULL)
  1664. return WBEM_E_OUT_OF_MEMORY;
  1665. hres = pNewQueryRecord->Initialize( wszQuery, m_strName, pNamespace, IsSystem());
  1666. if(FAILED(hres))
  1667. {
  1668. ERRORTRACE((LOG_ESS,
  1669. "Skipping provider %S invalid registration query %S\n",
  1670. m_strName, wszQuery));
  1671. }
  1672. else
  1673. {
  1674. hres = m_pMainSink->AddDefinitionQuery(wszQuery);
  1675. if(FAILED(hres))
  1676. {
  1677. ERRORTRACE((LOG_ESS,
  1678. "Skipping provider %S registration query %S\n"
  1679. " failed to merge: %X\n",
  1680. m_strName, wszQuery, hres));
  1681. }
  1682. if(m_apQueries.Add(pNewQueryRecord) < 0)
  1683. {
  1684. delete pNewQueryRecord;
  1685. hres = WBEM_E_OUT_OF_MEMORY;
  1686. }
  1687. }
  1688. return hres;
  1689. }
  1690. HRESULT CEventProviderCache::CRecord::ResetQueries()
  1691. {
  1692. m_apQueries.RemoveAll();
  1693. m_pMainSink->RemoveAllDefinitionQueries();
  1694. return WBEM_S_NO_ERROR;
  1695. }
  1696. HRESULT CEventProviderCache::CRecord::PostponeNewQuery(CExecLine::CTurn* pTurn,
  1697. DWORD dwId, LPCWSTR wszQueryLanguage, LPCWSTR wszQuery,
  1698. CAbstractEventSink* pDest)
  1699. {
  1700. CPostponedList* pList = GetCurrentPostponedList();
  1701. //
  1702. // if null, then no thread object associated with thread. caller may
  1703. // need to use an CEssInternalOperationSink.
  1704. //
  1705. _DBG_ASSERT( pList != NULL );
  1706. CPostponedNewQuery* pReq = new CPostponedNewQuery(this, dwId,
  1707. wszQueryLanguage, wszQuery, pTurn, pDest);
  1708. if(pReq == NULL)
  1709. {
  1710. return WBEM_E_OUT_OF_MEMORY;
  1711. }
  1712. HRESULT hr = pList->AddRequest( m_pNamespace, pReq);
  1713. if ( FAILED(hr) )
  1714. {
  1715. delete pReq;
  1716. return hr;
  1717. }
  1718. return WBEM_S_NO_ERROR;
  1719. }
  1720. HRESULT CEventProviderCache::CRecord::PostponeCancelQuery(
  1721. CExecLine::CTurn* pTurn, DWORD dwId)
  1722. {
  1723. CPostponedList* pList = GetCurrentPostponedList();
  1724. //
  1725. // if null, then no thread object associated with thread. caller may
  1726. // need to use an CEssInternalOperationSink.
  1727. //
  1728. _DBG_ASSERT( pList != NULL );
  1729. CPostponedCancelQuery* pReq = new CPostponedCancelQuery(this, pTurn, dwId);
  1730. if( pReq == NULL )
  1731. {
  1732. return WBEM_E_OUT_OF_MEMORY;
  1733. }
  1734. HRESULT hr = pList->AddRequest( m_pNamespace, pReq );
  1735. if ( FAILED(hr) )
  1736. {
  1737. delete pReq;
  1738. return hr;
  1739. }
  1740. return WBEM_S_NO_ERROR;
  1741. }
  1742. // assumes: no locks are held
  1743. HRESULT CEventProviderCache::CRecord::Exec_LoadProvider(
  1744. CEssNamespace* pNamespace)
  1745. {
  1746. HRESULT hres;
  1747. // Having locked the namespace, retrieve the necessary parameters
  1748. // ==============================================================
  1749. CLSID clsid;
  1750. IWbemObjectSink* pEventSink = NULL;
  1751. {
  1752. CInUpdate iu(pNamespace);
  1753. if(pNamespace->IsShutdown())
  1754. return WBEM_E_INVALID_NAMESPACE;
  1755. // Check if it is already loaded
  1756. // =============================
  1757. if(m_pProvider)
  1758. return WBEM_S_FALSE;
  1759. }
  1760. IWbemEventProvider* pProvider = NULL;
  1761. hres = m_pNamespace->LoadEventProvider(m_strName, &pProvider);
  1762. if(FAILED(hres))
  1763. {
  1764. ERRORTRACE((LOG_ESS, "Unable to load event provider '%S' in namespace "
  1765. "'%S': 0x%X\n", m_strName, m_pNamespace->GetName(), hres));
  1766. return hres;
  1767. }
  1768. CReleaseMe rm1(pProvider);
  1769. /* TAKEN CARE OF BY THE PROVSS
  1770. //
  1771. // In case this is a "framework" provider, inform it of its registration
  1772. //
  1773. IWbemProviderIdentity* pIdent = NULL;
  1774. hres = pProvider->QueryInterface(IID_IWbemProviderIdentity,
  1775. (void**)&pIdent);
  1776. if(SUCCEEDED(hres))
  1777. {
  1778. CReleaseMe rm(pIdent);
  1779. hres = pIdent->SetRegistrationObject(0, m_pWin32Prov);
  1780. if(hres == WBEM_E_PROVIDER_NOT_CAPABLE)
  1781. hres = WBEM_S_SUBJECT_TO_SDS;
  1782. if(FAILED(hres))
  1783. {
  1784. ERRORTRACE((LOG_ESS, "Event provider %S failed to accept its "
  1785. "registration object with error code 0x%X\n", m_strName, hres));
  1786. return hres;
  1787. }
  1788. }
  1789. */
  1790. //
  1791. // Deposit this and other provider pointers into the record
  1792. //
  1793. hres = SetProviderPointer(pNamespace, pProvider);
  1794. if(FAILED(hres))
  1795. return hres;
  1796. //
  1797. // Report the MSFT_WmiEventProviderLoaded event.
  1798. //
  1799. FIRE_NCEVENT(
  1800. g_hNCEvents[MSFT_WmiEventProviderLoaded],
  1801. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  1802. // Data follows...
  1803. pNamespace->GetName(),
  1804. m_strName);
  1805. //
  1806. // Postpone start until all activations are done
  1807. //
  1808. CPostponedList* pList = GetCurrentPostponedList();
  1809. //
  1810. // if null, then no thread object associated with thread. caller may
  1811. // need to use an CEssInternalOperationSink.
  1812. //
  1813. _DBG_ASSERT( pList != NULL );
  1814. CPostponedProvideEvents* pReq = new CPostponedProvideEvents(this);
  1815. if(pReq == NULL)
  1816. {
  1817. return WBEM_E_OUT_OF_MEMORY;
  1818. }
  1819. hres = pList->AddRequest( m_pNamespace, pReq);
  1820. if ( FAILED(hres) )
  1821. {
  1822. delete pReq;
  1823. }
  1824. return hres;
  1825. }
  1826. HRESULT CEventProviderCache::CRecord::SetProviderPointer(
  1827. CEssNamespace* pNamespace,
  1828. IWbemEventProvider* pProvider)
  1829. {
  1830. HRESULT hres;
  1831. //
  1832. // Check the "smart provider" interface
  1833. //
  1834. IWbemEventProviderQuerySink* pQuerySink = NULL;
  1835. hres = pProvider->QueryInterface(IID_IWbemEventProviderQuerySink,
  1836. (void**)&pQuerySink);
  1837. CReleaseMe rm4(pQuerySink);
  1838. //
  1839. // Check the security interface
  1840. //
  1841. IWbemEventProviderSecurity* pSecurity = NULL;
  1842. hres = pProvider->QueryInterface(IID_IWbemEventProviderSecurity,
  1843. (void**)&pSecurity);
  1844. CReleaseMe rm5(pSecurity);
  1845. // Having locked the namespace, deposit the pointers into the record
  1846. // =================================================================
  1847. {
  1848. CInUpdate iu(pNamespace);
  1849. if(pNamespace->IsShutdown())
  1850. return WBEM_E_INVALID_NAMESPACE;
  1851. m_pProvider = pProvider;
  1852. pProvider->AddRef();
  1853. m_pQuerySink = pQuerySink;
  1854. if(pQuerySink)
  1855. pQuerySink->AddRef();
  1856. m_pSecurity = pSecurity;
  1857. if(pSecurity)
  1858. pSecurity->AddRef();
  1859. }
  1860. return WBEM_S_NO_ERROR;
  1861. }
  1862. HRESULT CEventProviderCache::CRecord::Exec_StartProvider(
  1863. CEssNamespace* pNamespace)
  1864. {
  1865. IWbemEventProvider* pProvider = NULL;
  1866. IWbemEventSink* pEventSink = NULL;
  1867. HRESULT hres;
  1868. {
  1869. CInUpdate iu(pNamespace);
  1870. if(m_bStarted)
  1871. return WBEM_S_NO_ERROR;
  1872. m_bStarted = true;
  1873. pProvider = m_pProvider;
  1874. if(pProvider)
  1875. pProvider->AddRef();
  1876. // Retrieve the sink to give to the provider
  1877. // =========================================
  1878. hres = m_pMainSink->GetMainProxy(&pEventSink);
  1879. if(FAILED(hres))
  1880. return hres;
  1881. }
  1882. CReleaseMe rm1(pProvider);
  1883. CReleaseMe rm2(pEventSink);
  1884. if(pProvider)
  1885. {
  1886. hres = pProvider->ProvideEvents(pEventSink, 0);
  1887. if(FAILED(hres))
  1888. {
  1889. ERRORTRACE((LOG_ESS,
  1890. "Could not start provider %S. Error: %X\n", m_strName, hres));
  1891. return WBEM_E_PROVIDER_FAILURE;
  1892. }
  1893. }
  1894. return WBEM_S_NO_ERROR;
  1895. }
  1896. HRESULT CEventProviderCache::CRecord::AddActiveProviderEntryToRegistry()
  1897. {
  1898. LONG lRes;
  1899. HKEY hkeyEss, hkeyNamespace, hkeyProvider;
  1900. DEBUGTRACE((LOG_ESS,"Adding provider %S from namespace %S to "
  1901. " registry as active provider\n", m_strName, m_strNamespace));
  1902. //
  1903. // open ess key. It is expected that this key is already created.
  1904. //
  1905. lRes = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  1906. WBEM_REG_ESS,
  1907. 0,
  1908. KEY_ALL_ACCESS,
  1909. &hkeyEss );
  1910. if ( lRes == ERROR_SUCCESS )
  1911. {
  1912. //
  1913. // open namespace key. It is expected that this key is already created.
  1914. //
  1915. lRes = RegOpenKeyExW( hkeyEss,
  1916. m_strNamespace,
  1917. 0,
  1918. KEY_ALL_ACCESS,
  1919. &hkeyNamespace );
  1920. if ( lRes == ERROR_SUCCESS )
  1921. {
  1922. //
  1923. // create the provider sub key.
  1924. //
  1925. lRes = RegCreateKeyExW( hkeyNamespace,
  1926. m_strName,
  1927. 0,
  1928. NULL,
  1929. REG_OPTION_NON_VOLATILE,
  1930. KEY_ALL_ACCESS,
  1931. NULL,
  1932. &hkeyProvider,
  1933. NULL );
  1934. if ( lRes == ERROR_SUCCESS )
  1935. {
  1936. RegCloseKey( hkeyProvider );
  1937. }
  1938. RegCloseKey( hkeyNamespace );
  1939. }
  1940. RegCloseKey( hkeyEss );
  1941. }
  1942. return HRESULT_FROM_WIN32( lRes );
  1943. }
  1944. HRESULT CEventProviderCache::CRecord::RemoveActiveProviderEntryFromRegistry()
  1945. {
  1946. LONG lRes;
  1947. HKEY hkeyEss, hkeyNamespace;
  1948. DEBUGTRACE((LOG_ESS,"Removing provider %S from namespace %S from "
  1949. " registry as active provider\n", m_strName, m_strNamespace));
  1950. //
  1951. // open ess key.
  1952. //
  1953. lRes = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  1954. WBEM_REG_ESS,
  1955. 0,
  1956. KEY_ALL_ACCESS,
  1957. &hkeyEss );
  1958. if ( lRes == ERROR_SUCCESS )
  1959. {
  1960. //
  1961. // open namespace key. It is expected that this key is already created.
  1962. //
  1963. lRes = RegOpenKeyExW( hkeyEss,
  1964. m_strNamespace,
  1965. 0,
  1966. KEY_ALL_ACCESS,
  1967. &hkeyNamespace );
  1968. if ( lRes == ERROR_SUCCESS )
  1969. {
  1970. //
  1971. // delete the provider sub key.
  1972. //
  1973. lRes = RegDeleteKeyW( hkeyNamespace, m_strName );
  1974. RegCloseKey( hkeyNamespace );
  1975. }
  1976. RegCloseKey( hkeyEss );
  1977. }
  1978. return HRESULT_FROM_WIN32( lRes );
  1979. }
  1980. void CEventProviderCache::CRecord::UnloadProvider()
  1981. {
  1982. HRESULT hr;
  1983. DEBUGTRACE((LOG_ESS,"Unloading Provider %S in namespace %S\n",
  1984. m_strName, m_strNamespace ));
  1985. //
  1986. // make sure the provider is removed from the provider cache. This is
  1987. // so if we load the provider again in the near future, we don't call
  1988. // ProvideEvents() on it twice.
  1989. //
  1990. if ( m_pProvider != NULL )
  1991. {
  1992. CWbemPtr<_IWmiProviderCache> pProvCache;
  1993. hr = m_pProvider->QueryInterface( IID__IWmiProviderCache,
  1994. (void**)&pProvCache );
  1995. if ( SUCCEEDED(hr) )
  1996. {
  1997. hr = pProvCache->Expel( 0, GetCurrentEssContext() );
  1998. if ( FAILED(hr) )
  1999. {
  2000. ERRORTRACE((LOG_ESS,"Could not expel provider %S from "
  2001. "provider cache in namespace %S. HR=0x%x\n",
  2002. m_strName,m_strNamespace,hr));
  2003. }
  2004. }
  2005. m_pNamespace->PostponeRelease(m_pProvider);
  2006. m_pProvider = NULL;
  2007. }
  2008. if(m_pQuerySink)
  2009. m_pNamespace->PostponeRelease(m_pQuerySink);
  2010. m_pQuerySink = NULL;
  2011. if(m_pSecurity)
  2012. m_pNamespace->PostponeRelease(m_pSecurity);
  2013. m_pSecurity = NULL;
  2014. m_bStarted = false;
  2015. //
  2016. // Report the MSFT_WmiEventProviderUnloaded event.
  2017. //
  2018. FIRE_NCEVENT(
  2019. g_hNCEvents[MSFT_WmiEventProviderUnloaded],
  2020. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  2021. // Data follows...
  2022. m_strNamespace,
  2023. m_strName);
  2024. }
  2025. HRESULT CEventProviderCache::CRecord::Exec_NewQuery(CEssNamespace* pNamespace,
  2026. CExecLine::CTurn* pTurn,
  2027. DWORD dwID, LPCWSTR wszLanguage, LPCWSTR wszQuery,
  2028. CAbstractEventSink* pDest)
  2029. {
  2030. HRESULT hres;
  2031. // Wait for our turn to make changes
  2032. // =================================
  2033. CExecLine::CInTurn it(&m_Line, pTurn);
  2034. hres = ActualExecNewQuery(pNamespace, dwID, wszLanguage, wszQuery, pDest);
  2035. if(FAILED(hres))
  2036. {
  2037. //
  2038. // Check: it could be provider needs to be restarted
  2039. //
  2040. if(HRESULT_FACILITY(hres) != FACILITY_ITF)
  2041. {
  2042. ERRORTRACE((LOG_ESS, "Non-WMI error code recieved from provider "
  2043. "%S: 0x%x. WMI will attempt to re-activate\n", m_strName,
  2044. hres));
  2045. {
  2046. CInUpdate iu( pNamespace );
  2047. UnloadProvider();
  2048. }
  2049. hres = ActualExecNewQuery(pNamespace, dwID, wszLanguage, wszQuery,
  2050. pDest);
  2051. }
  2052. }
  2053. if(FAILED(hres))
  2054. {
  2055. // Filter activation failed: deactivate
  2056. // =====================================
  2057. CInUpdate iu(pNamespace);
  2058. if(pNamespace->IsShutdown())
  2059. return WBEM_E_INVALID_NAMESPACE;
  2060. pNamespace->DeactivateFilter(pDest->GetEventFilter());
  2061. }
  2062. return hres;
  2063. }
  2064. HRESULT CEventProviderCache::CRecord::ActualExecNewQuery(
  2065. CEssNamespace* pNamespace,
  2066. DWORD dwID, LPCWSTR wszLanguage, LPCWSTR wszQuery,
  2067. CAbstractEventSink* pDest)
  2068. {
  2069. HRESULT hres;
  2070. // Ensure provider is loaded
  2071. // =========================
  2072. hres = Exec_LoadProvider(pNamespace);
  2073. if(FAILED(hres))
  2074. return hres;
  2075. // With namespace locked, check if the provider is loaded
  2076. // ======================================================
  2077. IWbemEventProviderQuerySink* pSink = NULL;
  2078. IWbemEventProviderSecurity* pSecurity = NULL;
  2079. PSID pCopySid = NULL;
  2080. {
  2081. CInUpdate iu(pNamespace);
  2082. if(pNamespace->IsShutdown())
  2083. return WBEM_E_INVALID_NAMESPACE;
  2084. if(m_pQuerySink != NULL)
  2085. {
  2086. pSink = m_pQuerySink;
  2087. pSink->AddRef();
  2088. }
  2089. if(m_pSecurity != NULL)
  2090. {
  2091. pSecurity = m_pSecurity;
  2092. pSecurity->AddRef();
  2093. // Make a copy of the filter's owner SID
  2094. // =====================================
  2095. PSID pActualSid = pDest->GetEventFilter()->GetOwner();
  2096. if(pActualSid != NULL)
  2097. {
  2098. pCopySid = new BYTE[GetLengthSid(pActualSid)];
  2099. if(pCopySid == NULL)
  2100. return WBEM_E_OUT_OF_MEMORY;
  2101. if(!CopySid(GetLengthSid(pActualSid), pCopySid, pActualSid))
  2102. {
  2103. delete [] pCopySid;
  2104. return WBEM_E_OUT_OF_MEMORY;
  2105. }
  2106. }
  2107. }
  2108. }
  2109. CReleaseMe rm1(pSink);
  2110. CReleaseMe rm2(pSecurity);
  2111. CVectorDeleteMe<BYTE> vdm((BYTE*)pCopySid);
  2112. //
  2113. // Check security, if possible. If provider does not support the interface,
  2114. // interpret as "check SDs", as this may be a new-model-only provider
  2115. //
  2116. hres = WBEM_S_SUBJECT_TO_SDS;
  2117. if(pSecurity)
  2118. {
  2119. DWORD dwSidLen = pCopySid ? GetLengthSid(pCopySid) : 0;
  2120. // Check security based on the SID or thread
  2121. // =========================================
  2122. if ( dwSidLen == 0 )
  2123. {
  2124. //
  2125. // Check security based on the thread. First save the current
  2126. // call context, then switch it back after we're done.
  2127. //
  2128. IUnknown *pOldCtx, *pTmpCtx;
  2129. CoSwitchCallContext( NULL, &pOldCtx );
  2130. pDest->GetEventFilter()->SetThreadSecurity();
  2131. hres = pSecurity->AccessCheck( wszLanguage,
  2132. wszQuery,
  2133. 0,
  2134. NULL );
  2135. CoSwitchCallContext( pOldCtx, &pTmpCtx );
  2136. }
  2137. else
  2138. {
  2139. hres = pSecurity->AccessCheck( wszLanguage,
  2140. wszQuery,
  2141. dwSidLen,
  2142. (BYTE*)pCopySid);
  2143. }
  2144. //
  2145. // Report the MSFT_WmiEventProviderAccessCheck event.
  2146. //
  2147. FIRE_NCEVENT(
  2148. g_hNCEvents[MSFT_WmiEventProviderAccessCheck],
  2149. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  2150. // Data follows...
  2151. m_strNamespace,
  2152. m_strName,
  2153. wszLanguage,
  2154. wszQuery,
  2155. pCopySid, dwSidLen,
  2156. hres);
  2157. }
  2158. if(hres == WBEM_E_PROVIDER_NOT_CAPABLE)
  2159. hres = WBEM_S_NO_ERROR;
  2160. if(SUCCEEDED(hres))
  2161. {
  2162. // Security check has been passed: decrement remaining count
  2163. // =========================================================
  2164. pDest->GetEventFilter()->DecrementRemainingSecurityChecks(hres);
  2165. }
  2166. else
  2167. {
  2168. ERRORTRACE((LOG_ESS, "Event provider refused consumer registration "
  2169. "query %S for security reasons: 0x%X\n", wszQuery, hres));
  2170. }
  2171. // Call "NewQuery" if required
  2172. // ===========================
  2173. if(SUCCEEDED(hres) && pSink)
  2174. {
  2175. hres = pSink->NewQuery(dwID, (LPWSTR)wszLanguage, (LPWSTR)wszQuery);
  2176. if(hres == WBEM_E_PROVIDER_NOT_CAPABLE)
  2177. hres = WBEM_S_NO_ERROR;
  2178. if(FAILED(hres))
  2179. {
  2180. ERRORTRACE((LOG_ESS, "Event provider refused consumer registration "
  2181. "query %S: error code 0x%X\n", wszQuery, hres));
  2182. }
  2183. //
  2184. // Report the MSFT_WmiEventProviderNewQuery event.
  2185. //
  2186. FIRE_NCEVENT(
  2187. g_hNCEvents[MSFT_WmiEventProviderNewQuery],
  2188. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  2189. // Data follows...
  2190. m_strNamespace,
  2191. m_strName,
  2192. wszLanguage,
  2193. wszQuery,
  2194. dwID,
  2195. hres);
  2196. }
  2197. return hres;
  2198. }
  2199. HRESULT CEventProviderCache::CRecord::Exec_CancelQuery(
  2200. CEssNamespace* pNamespace, CExecLine::CTurn* pTurn,
  2201. DWORD dwId)
  2202. {
  2203. CExecLine::CInTurn it(&m_Line, pTurn);
  2204. // With namespace locked, check if the provider is loaded
  2205. // ======================================================
  2206. IWbemEventProviderQuerySink* pSink = NULL;
  2207. {
  2208. CInUpdate iu(pNamespace);
  2209. if(pNamespace->IsShutdown())
  2210. return WBEM_E_INVALID_NAMESPACE;
  2211. if(m_pQuerySink == NULL)
  2212. return WBEM_S_FALSE;
  2213. pSink = m_pQuerySink;
  2214. pSink->AddRef();
  2215. }
  2216. CReleaseMe rm1(pSink);
  2217. // Make the call
  2218. // =============
  2219. HRESULT hr;
  2220. hr = pSink->CancelQuery(dwId);
  2221. //
  2222. // Report the MSFT_WmiEventProviderCancelQuery event.
  2223. //
  2224. FIRE_NCEVENT(
  2225. g_hNCEvents[MSFT_WmiEventProviderCancelQuery],
  2226. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  2227. // Data follows...
  2228. m_strNamespace,
  2229. m_strName,
  2230. dwId,
  2231. hr);
  2232. return hr;
  2233. }
  2234. HRESULT CEventProviderCache::CRecord::DeliverProviderRequest(
  2235. long lFlags)
  2236. {
  2237. HRESULT hres;
  2238. //
  2239. // The only requirement we support is WBEM_REQUIREMENT_RECHECK_SUBSCRIPTIONS
  2240. //
  2241. if(lFlags != WBEM_REQUIREMENTS_RECHECK_SUBSCRIPTIONS)
  2242. return WBEM_E_INVALID_PARAMETER;
  2243. //
  2244. // With this object locked, retrieve all the filters for this provider.
  2245. // Get provider pointers, as well
  2246. //
  2247. CProviderSinkServer::TDestinationArray apDestinations;
  2248. IWbemEventProviderQuerySink* pSink = NULL;
  2249. IWbemEventProviderSecurity* pSecurity = NULL;
  2250. {
  2251. CInUpdate iu(m_pMainSink->GetNamespace());
  2252. hres = m_pMainSink->GetDestinations(apDestinations);
  2253. if(FAILED(hres))
  2254. return hres;
  2255. if(m_pQuerySink != NULL)
  2256. {
  2257. pSink = m_pQuerySink;
  2258. pSink->AddRef();
  2259. }
  2260. if(m_pSecurity != NULL)
  2261. {
  2262. pSecurity = m_pSecurity;
  2263. pSecurity->AddRef();
  2264. }
  2265. }
  2266. CReleaseMe rm1(pSink);
  2267. CReleaseMe rm2(pSecurity);
  2268. //
  2269. // Iterate over them all, rechecking each with the provider
  2270. //
  2271. for(int i = 0; i < apDestinations.GetSize(); i++)
  2272. {
  2273. CProviderSinkServer::CEventDestination* pEventDest = apDestinations[i];
  2274. CAbstractEventSink* pDest = pEventDest->m_pSink;
  2275. //
  2276. // Retrieve the event filter associated with this sink
  2277. //
  2278. CEventFilter* pFilter = pDest->GetEventFilter();
  2279. if(pFilter == NULL)
  2280. {
  2281. ERRORTRACE((LOG_ESS, "Internal error: non-filter sink in proxy\n"));
  2282. continue;
  2283. }
  2284. //
  2285. // Retrieve the query from this filter.
  2286. //
  2287. LPWSTR wszQuery;
  2288. LPWSTR wszQueryLanguage;
  2289. BOOL bExact;
  2290. hres = pFilter->GetCoveringQuery(wszQueryLanguage, wszQuery,
  2291. bExact, NULL);
  2292. if(FAILED(hres) || !bExact)
  2293. continue;
  2294. CVectorDeleteMe<WCHAR> vdm1(wszQuery);
  2295. CVectorDeleteMe<WCHAR> vdm2(wszQueryLanguage);
  2296. //
  2297. // Check security first
  2298. //
  2299. if(pSecurity)
  2300. {
  2301. PSID pSid = pFilter->GetOwner();
  2302. if(pSid)
  2303. {
  2304. // Check security based on SID
  2305. hres = pSecurity->AccessCheck(wszQueryLanguage, wszQuery,
  2306. GetLengthSid(pSid),
  2307. (BYTE*)pSid);
  2308. }
  2309. else
  2310. {
  2311. //
  2312. // Check security based on the thread. First save the current
  2313. // call context, then switch it back after we're done.
  2314. //
  2315. IUnknown *pOldCtx, *pTmpCtx;
  2316. CoSwitchCallContext( NULL, &pOldCtx );
  2317. pFilter->SetThreadSecurity();
  2318. hres = pSecurity->AccessCheck( wszQueryLanguage,
  2319. wszQuery,
  2320. 0,
  2321. NULL );
  2322. CoSwitchCallContext( pOldCtx, &pTmpCtx );
  2323. }
  2324. if(FAILED(hres))
  2325. {
  2326. //
  2327. // Increment remaining security checks, thus disabling filter
  2328. //
  2329. ERRORTRACE((LOG_ESS, "Disabling filter %S as provider denies "
  2330. " access for this user: 0x%X\n", wszQuery, hres));
  2331. pFilter->IncrementRemainingSecurityChecks();
  2332. }
  2333. }
  2334. if(SUCCEEDED(hres) && pSink)
  2335. {
  2336. //
  2337. // Check everything else --- do a NewQuery
  2338. //
  2339. hres = pSink->NewQuery(pEventDest->m_id, (LPWSTR)wszQueryLanguage,
  2340. (LPWSTR)wszQuery);
  2341. if(FAILED(hres))
  2342. {
  2343. ERRORTRACE((LOG_ESS, "Disabling filter %S as provider refuses "
  2344. "registration: error code 0x%X\n", wszQuery, hres));
  2345. }
  2346. }
  2347. }
  2348. return WBEM_S_NO_ERROR;
  2349. }
  2350. CExecLine::CTurn* CEventProviderCache::CRecord::GetInLine()
  2351. {
  2352. return m_Line.GetInLine();
  2353. }
  2354. void CEventProviderCache::CRecord::DiscardTurn(CExecLine::CTurn* pTurn)
  2355. {
  2356. m_Line.DiscardTurn(pTurn);
  2357. }
  2358. HRESULT CEventProviderCache::CRecord::Activate(CEssNamespace* pNamespace,
  2359. CRequest* pRequest,
  2360. WBEM_REMOTE_TARGET_ID_TYPE idRequest)
  2361. {
  2362. CExecLine::CTurn* pTurn = GetInLine();
  2363. if(pTurn == NULL)
  2364. return WBEM_E_OUT_OF_MEMORY;
  2365. m_lUsageCount++;
  2366. m_LastUse = CWbemTime::GetCurrentTime();
  2367. if ( pRequest->GetDest()->GetEventFilter()->IsPermanent() )
  2368. {
  2369. m_lPermUsageCount++;
  2370. CheckPermanentUsage();
  2371. }
  2372. // Notify him of the new query, if required
  2373. // ========================================
  2374. HRESULT hr;
  2375. hr = PostponeNewQuery( pTurn,
  2376. idRequest,
  2377. L"WQL",
  2378. pRequest->GetQuery(),
  2379. pRequest->GetDest() );
  2380. if ( FAILED(hr) )
  2381. {
  2382. DiscardTurn( pTurn );
  2383. return hr;
  2384. }
  2385. return WBEM_S_NO_ERROR;
  2386. }
  2387. HRESULT CEventProviderCache::CRecord::Deactivate( CAbstractEventSink* pDest,
  2388. WBEM_REMOTE_TARGET_ID_TYPE idRequest )
  2389. {
  2390. if( !m_bProviderSet )
  2391. {
  2392. // Provider is not registered.
  2393. // ===========================
  2394. return WBEM_S_FALSE;
  2395. }
  2396. // Notify him of the cancellation, if required
  2397. // ===========================================
  2398. CExecLine::CTurn* pTurn = GetInLine();
  2399. if(pTurn == NULL)
  2400. {
  2401. return WBEM_E_OUT_OF_MEMORY;
  2402. }
  2403. HRESULT hr = PostponeCancelQuery(pTurn, idRequest);
  2404. if ( FAILED(hr) )
  2405. {
  2406. DiscardTurn( pTurn );
  2407. return hr;
  2408. }
  2409. m_lUsageCount--;
  2410. m_LastUse = CWbemTime::GetCurrentTime();
  2411. if ( pDest->GetEventFilter()->IsPermanent() )
  2412. {
  2413. //
  2414. // TODO: Out usage counts can easily get out of wack because of
  2415. // mismatched Activate/Deactivates in the presence of failures.
  2416. // _DBG_ASSERT( m_lPermUsageCount > 0 );
  2417. //
  2418. m_lPermUsageCount--;
  2419. CheckPermanentUsage();
  2420. }
  2421. return WBEM_S_NO_ERROR;
  2422. }
  2423. HRESULT CEventProviderCache::CRecord::DeactivateFilter(
  2424. CAbstractEventSink* pDest)
  2425. {
  2426. HRESULT hres;
  2427. // Try to remove it from our stub
  2428. // ==============================
  2429. WBEM_REMOTE_TARGET_ID_TYPE idRequest;
  2430. hres = m_pMainSink->RemoveFilter(pDest, &idRequest);
  2431. if(hres == WBEM_E_NOT_FOUND) // not there --- no problem
  2432. return WBEM_S_FALSE;
  2433. else if(FAILED(hres))
  2434. return hres;
  2435. hres = Deactivate( pDest, idRequest);
  2436. return hres;
  2437. }
  2438. HRESULT CEventProviderCache::CRecord::ActivateIfNeeded(CRequest& Request,
  2439. IN CEssNamespace* pNamespace)
  2440. {
  2441. HRESULT hres;
  2442. // Go through all the classes supplied by the provider and see if ours
  2443. // is an ancestor of any of them.
  2444. // ===================================================================
  2445. for(int j = 0; j < m_apQueries.GetSize(); j++)
  2446. {
  2447. CQueryRecord* pQueryRecord = m_apQueries[j];
  2448. _DBG_ASSERT( pQueryRecord != NULL );
  2449. pQueryRecord->EnsureClasses( pNamespace );
  2450. hres = pQueryRecord->DoesIntersectWithQuery(Request, pNamespace);
  2451. pQueryRecord->ReleaseClasses();
  2452. if(FAILED(hres))
  2453. {
  2454. // Something is wrong with the query itself --- no point in
  2455. // continuing to other registrations
  2456. // ========================================================
  2457. return hres;
  2458. }
  2459. else if(hres == WBEM_S_NO_ERROR)
  2460. {
  2461. DEBUGTRACE((LOG_ESS,"Activating filter '%S' with provider %S\n",
  2462. Request.GetQuery(), m_strName ));
  2463. // First, increment the number of remaining security checks on this
  2464. // filter, since, even though we are adding it to the proxy, we do
  2465. // not want events reaching it until the provider said OK
  2466. // ================================================================
  2467. Request.GetDest()->GetEventFilter()->
  2468. IncrementRemainingSecurityChecks();
  2469. // Add this filter to the proxies
  2470. // ==============================
  2471. WBEM_REMOTE_TARGET_ID_TYPE idRequest;
  2472. hres = m_pMainSink->AddFilter(Request.GetQuery(),
  2473. Request.GetQueryExpr(),
  2474. Request.GetDest(),
  2475. &idRequest);
  2476. if(FAILED(hres)) return hres;
  2477. // Schedule activation of this record, which will involve loading
  2478. // and notifying the provider. Also at that time, filter's security
  2479. // check count will be reduced and events can start flowing
  2480. // ================================================================
  2481. hres = Activate(pNamespace, &Request, idRequest);
  2482. if(hres != WBEM_S_NO_ERROR) // S_FALSE means no provider
  2483. {
  2484. m_pMainSink->RemoveFilter(Request.GetDest());
  2485. return hres;
  2486. }
  2487. // No point in continuing --- the provider has been activated
  2488. // ==========================================================
  2489. break;
  2490. }
  2491. }
  2492. return WBEM_S_NO_ERROR;
  2493. }
  2494. HRESULT CEventProviderCache::CRecord::CancelAllQueries()
  2495. {
  2496. HRESULT hres;
  2497. //
  2498. // With this object locked, retrieve all the filters for this provider.
  2499. // Get provider pointers, as well
  2500. //
  2501. CProviderSinkServer::TDestinationArray apDestinations;
  2502. IWbemEventProviderQuerySink* pSink = NULL;
  2503. {
  2504. CInUpdate iu(m_pMainSink->GetNamespace());
  2505. if(m_pQuerySink == NULL)
  2506. {
  2507. //
  2508. // Nothing to cancel!
  2509. //
  2510. return WBEM_S_FALSE;
  2511. }
  2512. hres = m_pMainSink->GetDestinations(apDestinations);
  2513. if(FAILED(hres))
  2514. return hres;
  2515. pSink = m_pQuerySink;
  2516. pSink->AddRef();
  2517. }
  2518. CReleaseMe rm1(pSink);
  2519. //
  2520. // Iterate over them all, rechecking each with the provider
  2521. //
  2522. for(int i = 0; i < apDestinations.GetSize(); i++)
  2523. {
  2524. CProviderSinkServer::CEventDestination* pEventDest = apDestinations[i];
  2525. //
  2526. // Notify the provider of the cancellation
  2527. //
  2528. CExecLine::CTurn* pTurn = GetInLine();
  2529. if( pTurn == NULL )
  2530. {
  2531. return WBEM_E_OUT_OF_MEMORY;
  2532. }
  2533. hres = PostponeCancelQuery(pTurn, pEventDest->m_id);
  2534. if( FAILED(hres) )
  2535. {
  2536. DiscardTurn( pTurn );
  2537. return hres;
  2538. }
  2539. }
  2540. return S_OK;
  2541. }
  2542. //
  2543. // takes care of storing permanently the 'permanent' usage state of a provider
  2544. //
  2545. void CEventProviderCache::CRecord::CheckPermanentUsage()
  2546. {
  2547. HRESULT hr;
  2548. if ( IsSystem() )
  2549. {
  2550. return;
  2551. }
  2552. if ( m_lPermUsageCount == 0 && m_bRecorded )
  2553. {
  2554. hr = RemoveActiveProviderEntryFromRegistry();
  2555. //
  2556. // no matter what the outcome, make sure to set recorded to false.
  2557. //
  2558. m_bRecorded = FALSE;
  2559. //
  2560. // since a namespace is deactivated before the filters are deactivated,
  2561. // ( because filter deactivation is postponed ), it is possible that
  2562. // the namespace key will be deleted by the time we get here.
  2563. // this happens when we're deactivating the last permanent consumer
  2564. // in the namespace.
  2565. //
  2566. if ( FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) )
  2567. {
  2568. ERRORTRACE((LOG_ESS,"Error removing active provider entry "
  2569. "from registry in namespace %S. HR=0x%x\n",
  2570. m_pNamespace->GetName(), hr ));
  2571. }
  2572. }
  2573. else if ( m_lPermUsageCount > 0 && !m_bRecorded )
  2574. {
  2575. hr = AddActiveProviderEntryToRegistry();
  2576. if ( SUCCEEDED(hr) )
  2577. {
  2578. m_bRecorded = TRUE;
  2579. }
  2580. else
  2581. {
  2582. ERRORTRACE((LOG_ESS,"Error adding active provider entry "
  2583. "to registry in namespace %S. HR=0x%x\n",
  2584. m_pNamespace->GetName(), hr ));
  2585. }
  2586. }
  2587. }
  2588. void CEventProviderCache::CRecord::ResetUsage()
  2589. {
  2590. DEBUGTRACE((LOG_ESS,"Resetting provider '%S' in namespace '%S' to prepare "
  2591. "for resync.\n", m_strName, m_strNamespace ));
  2592. //
  2593. // set a flag so that when all filters are reactivated we know to
  2594. // process them for this record.
  2595. //
  2596. m_bNeedsResync = TRUE;
  2597. CancelAllQueries();
  2598. m_lUsageCount = 0;
  2599. //
  2600. // when the changes to the event provider cache is committed, we will
  2601. // enumerate all records and remove ones having a perm usage count still 0
  2602. // from the registry.
  2603. //
  2604. m_lPermUsageCount = 0;
  2605. m_pMainSink->RemoveAllFilters();
  2606. }
  2607. bool CEventProviderCache::CRecord::DeactivateIfNotUsed()
  2608. {
  2609. if(m_lUsageCount == 0 && m_pProvider)
  2610. {
  2611. // Stop the provider
  2612. // =================
  2613. UnloadProvider();
  2614. DEBUGTRACE((LOG_ESS, "Unloading event provider %S\n", m_strName));
  2615. return true;
  2616. }
  2617. else
  2618. return false;
  2619. }
  2620. bool CEventProviderCache::CRecord::IsUnloadable()
  2621. {
  2622. return (IsActive() && GetUsageCount() == 0);
  2623. }
  2624. DWORD CEventProviderCache::CRecord::GetProvidedEventMask(
  2625. IWbemClassObject* pClass,
  2626. BSTR strClassName)
  2627. {
  2628. DWORD dwEventMask = 0;
  2629. // Go through all its registered queries
  2630. // =====================================
  2631. for(int j = 0; j < m_apQueries.GetSize(); j++)
  2632. {
  2633. CRecord::CQueryRecord* pQueryRecord = m_apQueries.GetAt(j);
  2634. _DBG_ASSERT( pQueryRecord != NULL );
  2635. pQueryRecord->EnsureClasses( m_pNamespace );
  2636. dwEventMask |= pQueryRecord->GetProvidedEventMask(pClass, strClassName);
  2637. pQueryRecord->ReleaseClasses();
  2638. }
  2639. return dwEventMask;
  2640. }
  2641. bool CEventProviderCache::CSystemRecord::DeactivateIfNotUsed()
  2642. {
  2643. //
  2644. // System providers cannot be deactivated
  2645. //
  2646. return false;
  2647. }
  2648. bool CEventProviderCache::CSystemRecord::IsUnloadable()
  2649. {
  2650. //
  2651. // System providers cannot be deactivated
  2652. //
  2653. return false;
  2654. }
  2655. /*
  2656. HRESULT CEventProviderCache::CSystemRecord::PostponeNewQuery(
  2657. CExecLine::CTurn* pTurn, DWORD dwId,
  2658. LPCWSTR wszQueryLanguage, LPCWSTR wszQuery,
  2659. CAbstractEventSink* pDest)
  2660. {
  2661. //
  2662. // System providers do not need calls to them postponed!
  2663. //
  2664. return Exec_NewQuery(m_pNamespace, pTurn, dwId, wszQueryLanguage, wszQuery,
  2665. pDest);
  2666. }
  2667. HRESULT CEventProviderCache::CSystemRecord::PostponeCancelQuery(
  2668. CExecLine::CTurn* pTurn, DWORD dwId)
  2669. {
  2670. //
  2671. // System providers do not need calls to them postponed!
  2672. //
  2673. return Exec_CancelQuery(m_pNamespace, pTurn, dwId);
  2674. }
  2675. */
  2676. //******************************************************************************
  2677. //******************************************************************************
  2678. //
  2679. // REQUEST
  2680. //
  2681. //******************************************************************************
  2682. //******************************************************************************
  2683. CEventProviderCache::CRequest::CRequest(IN CAbstractEventSink* pDest,
  2684. LPWSTR wszQuery, QL_LEVEL_1_RPN_EXPRESSION* pExp)
  2685. : m_pDest(pDest),
  2686. m_wszQuery(wszQuery), m_pExpr(pExp),
  2687. m_dwEventMask(0), m_papInstanceClasses(NULL), m_pEventClass(NULL)
  2688. {
  2689. }
  2690. CEventProviderCache::CRequest::~CRequest()
  2691. {
  2692. // Do not delete namespace, language, and query, and QL -- they were STOREd
  2693. // ========================================================================
  2694. if(m_papInstanceClasses)
  2695. delete m_papInstanceClasses;
  2696. if(m_pEventClass)
  2697. m_pEventClass->Release();
  2698. }
  2699. INTERNAL QL_LEVEL_1_RPN_EXPRESSION* CEventProviderCache::CRequest::
  2700. GetQueryExpr()
  2701. {
  2702. return m_pExpr;
  2703. }
  2704. DWORD CEventProviderCache::CRequest::GetEventMask()
  2705. {
  2706. if(m_dwEventMask == 0)
  2707. {
  2708. QL_LEVEL_1_RPN_EXPRESSION* pExpr = GetQueryExpr();
  2709. if(pExpr == NULL)
  2710. return 0;
  2711. m_dwEventMask =
  2712. CEventRepresentation::GetTypeMaskFromName(pExpr->bsClassName);
  2713. }
  2714. return m_dwEventMask;
  2715. }
  2716. HRESULT CEventProviderCache::CRequest::GetInstanceClasses(
  2717. CEssNamespace* pNamespace,
  2718. INTERNAL CClassInfoArray** ppClasses)
  2719. {
  2720. *ppClasses = NULL;
  2721. if(!m_papInstanceClasses)
  2722. {
  2723. QL_LEVEL_1_RPN_EXPRESSION* pExpr = GetQueryExpr();
  2724. if(pExpr == NULL)
  2725. return WBEM_E_OUT_OF_MEMORY;
  2726. HRESULT hres = CQueryAnalyser::GetPossibleInstanceClasses(
  2727. pExpr, m_papInstanceClasses);
  2728. if(FAILED(hres))
  2729. {
  2730. return hres;
  2731. }
  2732. if(m_papInstanceClasses == NULL)
  2733. return WBEM_E_OUT_OF_MEMORY;
  2734. // Get the actual classes from the namespace
  2735. // =========================================
  2736. for(int i = 0; i < m_papInstanceClasses->GetNumClasses(); i++)
  2737. {
  2738. CClassInformation* pInfo = m_papInstanceClasses->GetClass(i);
  2739. _IWmiObject* pClass = NULL;
  2740. hres = pNamespace->GetClass(pInfo->m_wszClassName, &pClass);
  2741. if(FAILED(hres))
  2742. {
  2743. ERRORTRACE((LOG_ESS,
  2744. "Could not get class %S for which intrinsic events"
  2745. " are requested. Error code: %X\n",
  2746. pInfo->m_wszClassName, hres));
  2747. delete m_papInstanceClasses;
  2748. m_papInstanceClasses = NULL;
  2749. if(hres == WBEM_E_NOT_FOUND)
  2750. hres = WBEM_E_INVALID_CLASS;
  2751. return hres;
  2752. }
  2753. pInfo->m_pClass = pClass;
  2754. }
  2755. }
  2756. *ppClasses = m_papInstanceClasses;
  2757. return WBEM_S_NO_ERROR;
  2758. }
  2759. INTERNAL IWbemClassObject* CEventProviderCache::CRequest::GetEventClass(
  2760. CEssNamespace* pNamespace)
  2761. {
  2762. HRESULT hres;
  2763. if(m_pEventClass == NULL)
  2764. {
  2765. QL_LEVEL_1_RPN_EXPRESSION* pExpr = GetQueryExpr();
  2766. if(pExpr == NULL)
  2767. return NULL;
  2768. _IWmiObject* pClass = NULL;
  2769. hres = pNamespace->GetClass(pExpr->bsClassName, &pClass);
  2770. if(FAILED(hres))
  2771. {
  2772. return NULL;
  2773. }
  2774. m_pEventClass = pClass;
  2775. }
  2776. return m_pEventClass;
  2777. }
  2778. HRESULT CEventProviderCache::CRequest::CheckValidity(CEssNamespace* pNamespace)
  2779. {
  2780. if(GetQueryExpr() == NULL)
  2781. return WBEM_E_INVALID_QUERY;
  2782. if(GetEventClass(pNamespace) == NULL)
  2783. return WBEM_E_INVALID_CLASS;
  2784. return WBEM_S_NO_ERROR;
  2785. }
  2786. //******************************************************************************
  2787. //******************************************************************************
  2788. //
  2789. // PROVIDER CACHE
  2790. //
  2791. //******************************************************************************
  2792. //******************************************************************************
  2793. CEventProviderCache::CEventProviderCache(CEssNamespace* pNamespace)
  2794. : m_pNamespace(pNamespace), m_pInstruction(NULL), m_bInResync(FALSE)
  2795. {
  2796. }
  2797. CEventProviderCache::~CEventProviderCache()
  2798. {
  2799. Shutdown();
  2800. }
  2801. // assumes: in m_cs
  2802. long CEventProviderCache::FindRecord(LPCWSTR wszName)
  2803. {
  2804. for(long l = 0; l < m_aRecords.GetSize(); l++)
  2805. {
  2806. if(!_wcsicmp(wszName, m_aRecords[l]->m_strName))
  2807. {
  2808. return l;
  2809. }
  2810. }
  2811. return -1;
  2812. }
  2813. HRESULT CEventProviderCache::AddProvider(IWbemClassObject* pWin32Prov)
  2814. {
  2815. HRESULT hres;
  2816. CInCritSec ics(&m_cs);
  2817. if(m_pNamespace == NULL)
  2818. return WBEM_E_INVALID_NAMESPACE;
  2819. // Determine provider's name
  2820. // =========================
  2821. BSTR strName;
  2822. hres = CRecord::GetProviderInfo(pWin32Prov, strName);
  2823. if(FAILED(hres))
  2824. return hres;
  2825. CSysFreeMe sfm1(strName);
  2826. // Check if it exists
  2827. // ==================
  2828. long lIndex = FindRecord(strName);
  2829. if(lIndex != -1)
  2830. {
  2831. // Already there
  2832. // =============
  2833. hres = m_aRecords[lIndex]->SetProvider(pWin32Prov);
  2834. if(FAILED(hres))
  2835. return hres;
  2836. return WBEM_S_FALSE;
  2837. }
  2838. // Create a new provider record
  2839. // ============================
  2840. CRecord* pNewRecord = _new CRecord;
  2841. if(pNewRecord == NULL)
  2842. return WBEM_E_OUT_OF_MEMORY;
  2843. pNewRecord->AddRef();
  2844. CTemplateReleaseMe<CRecord> rm1(pNewRecord);
  2845. hres = pNewRecord->Initialize( strName, m_pNamespace );
  2846. if(FAILED(hres))
  2847. return hres;
  2848. hres = pNewRecord->SetProvider(pWin32Prov);
  2849. if(FAILED(hres))
  2850. return hres;
  2851. // Store it
  2852. // ========
  2853. if(m_aRecords.Add(pNewRecord) < 0)
  2854. {
  2855. delete pNewRecord;
  2856. return WBEM_E_OUT_OF_MEMORY;
  2857. }
  2858. return WBEM_S_NO_ERROR;
  2859. }
  2860. HRESULT CEventProviderCache::AddSystemProvider(IWbemEventProvider* pProvider,
  2861. LPCWSTR wszName,
  2862. long lNumQueries,
  2863. LPCWSTR* awszQueries)
  2864. {
  2865. CInCritSec ics(&m_cs);
  2866. HRESULT hres;
  2867. //
  2868. // First of all, construct a system provider record and add it
  2869. //
  2870. CSystemRecord* pNewRecord = new CSystemRecord;
  2871. if(pNewRecord == NULL)
  2872. return WBEM_E_OUT_OF_MEMORY;
  2873. pNewRecord->AddRef();
  2874. CTemplateReleaseMe<CSystemRecord> rm1(pNewRecord);
  2875. hres = pNewRecord->Initialize( wszName, m_pNamespace);
  2876. if(FAILED(hres))
  2877. return hres;
  2878. //
  2879. // Now, add all the queries in
  2880. //
  2881. hres = pNewRecord->SetQueries(m_pNamespace, lNumQueries, awszQueries);
  2882. if(FAILED(hres))
  2883. return hres;
  2884. //
  2885. // Populate it with the provider pointer
  2886. //
  2887. hres = pNewRecord->SetProviderPointer(m_pNamespace, pProvider);
  2888. if(FAILED(hres))
  2889. return hres;
  2890. //
  2891. // Launch it
  2892. //
  2893. hres = pNewRecord->Exec_StartProvider(m_pNamespace);
  2894. if(FAILED(hres))
  2895. return hres;
  2896. m_aRecords.Add(pNewRecord);
  2897. return WBEM_S_NO_ERROR;
  2898. }
  2899. HRESULT CEventProviderCache::RemoveProvider(IWbemClassObject* pWin32Prov)
  2900. {
  2901. CInCritSec ics(&m_cs);
  2902. HRESULT hres;
  2903. // Determine provider's name
  2904. // =========================
  2905. BSTR strName;
  2906. hres = CRecord::GetProviderInfo(pWin32Prov, strName);
  2907. if(FAILED(hres))
  2908. return hres;
  2909. // Find this record
  2910. // ================
  2911. long lIndex = FindRecord(strName);
  2912. SysFreeString(strName);
  2913. if(lIndex == -1)
  2914. {
  2915. return WBEM_S_FALSE;
  2916. }
  2917. else
  2918. {
  2919. m_aRecords[lIndex]->ResetUsage();
  2920. m_aRecords[lIndex]->ResetProvider();
  2921. if(m_aRecords[lIndex]->IsEmpty())
  2922. {
  2923. m_aRecords.RemoveAt(lIndex);
  2924. }
  2925. return WBEM_S_NO_ERROR;
  2926. }
  2927. }
  2928. HRESULT CEventProviderCache::CheckProviderRegistration(
  2929. IWbemClassObject* pRegistration)
  2930. {
  2931. CInCritSec ics(&m_cs);
  2932. if(m_pNamespace == NULL)
  2933. return WBEM_E_INVALID_NAMESPACE;
  2934. HRESULT hres;
  2935. // Create a new provider record
  2936. // ============================
  2937. CRecord* pRecord = new CRecord;
  2938. if(pRecord == NULL)
  2939. return WBEM_E_OUT_OF_MEMORY;
  2940. CDeleteMe<CRecord> dm1(pRecord);
  2941. hres = pRecord->Initialize( NULL, m_pNamespace );
  2942. if(FAILED(hres))
  2943. return hres;
  2944. // Set the queries into it
  2945. // =======================
  2946. hres = pRecord->SetQueries(m_pNamespace, pRegistration);
  2947. return hres;
  2948. }
  2949. HRESULT CEventProviderCache::AddProviderRegistration(
  2950. IWbemClassObject* pRegistration)
  2951. {
  2952. HRESULT hres;
  2953. BSTR strName;
  2954. if( m_pNamespace == NULL )
  2955. {
  2956. return WBEM_E_INVALID_NAMESPACE;
  2957. }
  2958. hres = CRecord::GetRegistrationInfo( pRegistration, strName );
  2959. if( FAILED(hres) )
  2960. {
  2961. return hres;
  2962. }
  2963. CSysFreeMe sfm( strName );
  2964. CInCritSec ics(&m_cs);
  2965. long lIndex = FindRecord( strName );
  2966. if(lIndex == -1)
  2967. {
  2968. CRecord* pRecord = new CRecord;
  2969. if(pRecord == NULL)
  2970. return WBEM_E_OUT_OF_MEMORY;
  2971. hres = pRecord->Initialize( strName, m_pNamespace );
  2972. if(FAILED(hres))
  2973. {
  2974. delete pRecord;
  2975. return hres;
  2976. }
  2977. hres = pRecord->SetQueries(m_pNamespace, pRegistration);
  2978. if ( FAILED(hres) )
  2979. {
  2980. delete pRecord;
  2981. return hres;
  2982. }
  2983. lIndex = m_aRecords.Add(pRecord);
  2984. if(lIndex == -1)
  2985. {
  2986. delete pRecord;
  2987. return WBEM_E_OUT_OF_MEMORY;
  2988. }
  2989. }
  2990. else
  2991. {
  2992. hres = m_aRecords[lIndex]->SetQueries(m_pNamespace, pRegistration);
  2993. }
  2994. return hres;
  2995. }
  2996. HRESULT CEventProviderCache::RemoveProviderRegistration(
  2997. IWbemClassObject* pRegistration)
  2998. {
  2999. HRESULT hres;
  3000. BSTR strName;
  3001. hres = CRecord::GetRegistrationInfo( pRegistration, strName );
  3002. if( FAILED(hres) )
  3003. {
  3004. return hres;
  3005. }
  3006. CSysFreeMe sfm( strName );
  3007. CInCritSec ics(&m_cs);
  3008. long lIndex = FindRecord( strName );
  3009. if(lIndex == -1)
  3010. return WBEM_S_FALSE;
  3011. // Set registration info
  3012. // =====================
  3013. m_aRecords[lIndex]->ResetUsage();
  3014. m_aRecords[lIndex]->ResetQueries();
  3015. if(m_aRecords[lIndex]->IsEmpty())
  3016. {
  3017. m_aRecords.RemoveAt(lIndex);
  3018. }
  3019. return WBEM_S_NO_ERROR;
  3020. }
  3021. HRESULT CEventProviderCache::ReleaseProvidersForQuery(CAbstractEventSink* pDest)
  3022. {
  3023. CInCritSec ics(&m_cs);
  3024. HRESULT hres;
  3025. // Search all the providers
  3026. // ========================
  3027. for(int i = 0; i < m_aRecords.GetSize(); i++)
  3028. {
  3029. CRecord* pRecord = m_aRecords[i];
  3030. hres = pRecord->DeactivateFilter(pDest);
  3031. // If failures occur, they are logged. Continue.
  3032. }
  3033. // Make sure unload instruction is running
  3034. // =======================================
  3035. EnsureUnloadInstruction();
  3036. return WBEM_S_NO_ERROR;
  3037. }
  3038. HRESULT CEventProviderCache::LoadProvidersForQuery(LPWSTR wszQuery,
  3039. QL_LEVEL_1_RPN_EXPRESSION* pExp, CAbstractEventSink* pDest)
  3040. {
  3041. CInCritSec ics(&m_cs);
  3042. if(m_pNamespace == NULL)
  3043. return WBEM_E_INVALID_NAMESPACE;
  3044. HRESULT hres;
  3045. // DEBUGTRACE((LOG_ESS, "Activating providers for %S (%p)\n",
  3046. // wszQuery, pDest));
  3047. // Create a request record
  3048. // =======================
  3049. CRequest Request(pDest, wszQuery, pExp);
  3050. // Check query validity
  3051. // ====================
  3052. hres = Request.CheckValidity(m_pNamespace);
  3053. if(FAILED(hres))
  3054. return hres;
  3055. // Search all the providers
  3056. // ========================
  3057. HRESULT hresGlobal = WBEM_S_NO_ERROR;
  3058. for(int i = 0; i < m_aRecords.GetSize(); i++)
  3059. {
  3060. CRecord* pRecord = m_aRecords[i];
  3061. if ( !m_bInResync || pRecord->NeedsResync() )
  3062. {
  3063. HRESULT hr = pRecord->ActivateIfNeeded(Request, m_pNamespace);
  3064. if(FAILED(hr))
  3065. hresGlobal = hr;
  3066. }
  3067. }
  3068. return hresGlobal;
  3069. }
  3070. void CEventProviderCache::EnsureUnloadInstruction()
  3071. {
  3072. if(m_pInstruction == NULL && m_pNamespace != NULL)
  3073. {
  3074. m_pInstruction = new CEventProviderWatchInstruction(this);
  3075. if(m_pInstruction != NULL)
  3076. {
  3077. m_pInstruction->AddRef();
  3078. m_pNamespace->GetTimerGenerator().Set(m_pInstruction);
  3079. }
  3080. }
  3081. }
  3082. DWORD CEventProviderCache::GetProvidedEventMask(IWbemClassObject* pClass)
  3083. {
  3084. HRESULT hres;
  3085. CInCritSec ics(&m_cs);
  3086. VARIANT v;
  3087. VariantInit(&v);
  3088. hres = pClass->Get(L"__CLASS", 0, &v, NULL, NULL);
  3089. if(FAILED(hres))
  3090. return hres;
  3091. CClearMe cm1(&v);
  3092. DWORD dwProvidedMask = 0;
  3093. // Search all the providers
  3094. // ========================
  3095. for(int i = 0; i < m_aRecords.GetSize(); i++)
  3096. {
  3097. CRecord* pRecord = m_aRecords[i];
  3098. dwProvidedMask |= pRecord->GetProvidedEventMask(pClass, V_BSTR(&v));
  3099. }
  3100. return dwProvidedMask;
  3101. }
  3102. HRESULT CEventProviderCache::VirtuallyReleaseProviders()
  3103. {
  3104. //
  3105. // just need to record the fact that we are in resync. This allows us to
  3106. // handle reactivation of filters differently than when not in resync.
  3107. // For example, during resync we only process reactivations for provider
  3108. // records that had changed causing the resync in the first place.
  3109. //
  3110. CInCritSec ics(&m_cs);
  3111. m_bInResync = TRUE;
  3112. return WBEM_S_NO_ERROR;
  3113. }
  3114. HRESULT CEventProviderCache::CommitProviderUsage()
  3115. {
  3116. CInCritSec ics(&m_cs);
  3117. // Called after VirtuallyReleaseProviders and re-activating all filters
  3118. // to actually deactivate all the providers whose usage count went to 0.
  3119. // =====================================================================
  3120. //
  3121. // need to process all records and ensure that any having a perm usage
  3122. // count of 0 be removed from the registry. Also make sure that we
  3123. // reset each records resync flag.
  3124. //
  3125. for( int i=0; i < m_aRecords.GetSize(); i++ )
  3126. {
  3127. m_aRecords[i]->ResetNeedsResync();
  3128. m_aRecords[i]->CheckPermanentUsage();
  3129. }
  3130. // At this point, there is nothing to be done. When unload instruction
  3131. // executes, providers that are no longer needed will be unloaded. All we
  3132. // need to do is allow the unload instruction to proceed.
  3133. // ======================================================================
  3134. m_bInResync = FALSE;
  3135. EnsureUnloadInstruction();
  3136. return WBEM_S_NO_ERROR;
  3137. }
  3138. HRESULT CEventProviderCache::UnloadUnusedProviders(CWbemInterval Interval)
  3139. {
  3140. //
  3141. // Extract the namespace pointer while locked to examine it for
  3142. // shutdownness
  3143. //
  3144. CEssNamespace* pNamespace = NULL;
  3145. {
  3146. CInCritSec ics(&m_cs);
  3147. pNamespace = m_pNamespace;
  3148. pNamespace->AddRef();
  3149. }
  3150. CTemplateReleaseMe<CEssNamespace> rm1(pNamespace);
  3151. {
  3152. CInUpdate iu(pNamespace);
  3153. if(pNamespace->IsShutdown())
  3154. return WBEM_S_FALSE;
  3155. if(m_bInResync)
  3156. {
  3157. // Usage counters are not up-to-date --- wait for the next time
  3158. // ============================================================
  3159. return WBEM_S_FALSE;
  3160. }
  3161. BOOL bDeactivated = FALSE;
  3162. BOOL bActiveLeft = FALSE;
  3163. for(int i = 0; i < m_aRecords.GetSize(); i++)
  3164. {
  3165. CRecord* pRecord = m_aRecords[i];
  3166. if(pRecord->IsActive() &&
  3167. CWbemTime::GetCurrentTime() - pRecord->m_LastUse > Interval)
  3168. {
  3169. if(pRecord->DeactivateIfNotUsed())
  3170. bDeactivated = TRUE;
  3171. }
  3172. //
  3173. // Check if we need to come back for this one
  3174. //
  3175. if(pRecord->IsUnloadable())
  3176. bActiveLeft = TRUE;
  3177. }
  3178. if(bDeactivated)
  3179. pNamespace->GetTimerGenerator().ScheduleFreeUnusedLibraries();
  3180. if(!bActiveLeft && m_pInstruction)
  3181. {
  3182. m_pInstruction->Terminate();
  3183. m_pInstruction->Release();
  3184. m_pInstruction = NULL;
  3185. }
  3186. }
  3187. pNamespace->FirePostponedOperations();
  3188. return WBEM_S_NO_ERROR;
  3189. }
  3190. HRESULT CEventProviderCache::Shutdown()
  3191. {
  3192. CInCritSec ics(&m_cs);
  3193. if(m_pInstruction)
  3194. {
  3195. m_pInstruction->Terminate();
  3196. m_pInstruction->Release();
  3197. m_pInstruction = NULL;
  3198. }
  3199. m_aRecords.RemoveAll();
  3200. m_pNamespace = NULL;
  3201. return WBEM_S_NO_ERROR;
  3202. }
  3203. void CEventProviderCache::DumpStatistics(FILE* f, long lFlags)
  3204. {
  3205. CInCritSec ics(&m_cs);
  3206. long lLoaded = 0;
  3207. long lQueries = 0;
  3208. long lProxies = 0;
  3209. long lFilters = 0;
  3210. long lDestinations = 0;
  3211. long lTargetLists = 0;
  3212. long lTargets = 0;
  3213. long lPostponed = 0;
  3214. for(int i = 0; i < m_aRecords.GetSize(); i++)
  3215. {
  3216. CRecord* pRecord = m_aRecords[i];
  3217. if(pRecord->m_pProvider)
  3218. lLoaded++;
  3219. lQueries += pRecord->m_apQueries.GetSize();
  3220. long lThisProxies = 0;
  3221. long lThisFilters = 0;
  3222. long lThisTargetLists = 0;
  3223. long lThisTargets = 0;
  3224. long lThisPostponed = 0;
  3225. long lThisDestinations = 0;
  3226. pRecord->m_pMainSink->GetStatistics(&lThisProxies, &lThisDestinations,
  3227. &lThisFilters, &lThisTargetLists,
  3228. &lThisTargets, &lThisPostponed);
  3229. lProxies += lThisProxies;
  3230. lDestinations += lThisDestinations;
  3231. lFilters += lThisFilters;
  3232. lTargetLists += lThisTargetLists;
  3233. lTargets += lThisTargets;
  3234. lPostponed += lThisPostponed;
  3235. }
  3236. fprintf(f, "%d provider records, %d definition queries, %d proxies\n"
  3237. "%d destinations, %d proxy filters, %d proxy target lists\n"
  3238. "%d proxy targets, %d postponed in proxies\n",
  3239. m_aRecords.GetSize(), lQueries, lProxies, lDestinations, lFilters,
  3240. lTargetLists, lTargets, lPostponed);
  3241. }
  3242. CPostponedNewQuery::CPostponedNewQuery(CEventProviderCache::CRecord* pRecord,
  3243. DWORD dwId, LPCWSTR wszQueryLanguage, LPCWSTR wszQuery,
  3244. CExecLine::CTurn* pTurn, CAbstractEventSink* pDest)
  3245. : m_pRecord(pRecord), m_dwId(dwId), m_pTurn(pTurn), m_pcsQuery(NULL),
  3246. m_pDest(pDest)
  3247. {
  3248. m_pRecord->AddRef();
  3249. m_pDest->AddRef();
  3250. // Figure out how much space we need
  3251. // =================================
  3252. int nSpace = CCompressedString::ComputeNecessarySpace(wszQuery);
  3253. // Allocate this string on the temporary heap
  3254. // ==========================================
  3255. m_pcsQuery = (CCompressedString*)CTemporaryHeap::Alloc(nSpace);
  3256. if(m_pcsQuery == NULL)
  3257. return;
  3258. m_pcsQuery->SetFromUnicode(wszQuery);
  3259. }
  3260. CPostponedNewQuery::~CPostponedNewQuery()
  3261. {
  3262. if(m_pTurn)
  3263. m_pRecord->DiscardTurn(m_pTurn);
  3264. if(m_pcsQuery)
  3265. CTemporaryHeap::Free(m_pcsQuery, m_pcsQuery->GetLength());
  3266. if(m_pDest)
  3267. m_pDest->Release();
  3268. m_pRecord->Release();
  3269. }
  3270. HRESULT CPostponedNewQuery::Execute(CEssNamespace* pNamespace)
  3271. {
  3272. if(m_pcsQuery == NULL)
  3273. return WBEM_E_OUT_OF_MEMORY;
  3274. HRESULT hres = m_pRecord->Exec_NewQuery(pNamespace, m_pTurn, m_dwId,
  3275. L"WQL", m_pcsQuery->CreateWStringCopy(),
  3276. m_pDest);
  3277. m_pTurn = NULL;
  3278. return hres;
  3279. }
  3280. void* CPostponedNewQuery::operator new(size_t nSize)
  3281. {
  3282. return CTemporaryHeap::Alloc(nSize);
  3283. }
  3284. void CPostponedNewQuery::operator delete(void* p)
  3285. {
  3286. CTemporaryHeap::Free(p, sizeof(CPostponedNewQuery));
  3287. }