Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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