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

4436 lines
118 KiB

  1. //=============================================================================
  2. //
  3. // Copyright (c) 1996-1999, Microsoft Corporation, All rights reserved
  4. //
  5. // NSREP.CPP
  6. //
  7. // See nsrep.h for documentation
  8. //
  9. // History:
  10. //
  11. //=============================================================================
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. #include "ess.h"
  15. #include "esssink.h"
  16. #include "permbind.h"
  17. #include "aggreg.h"
  18. #include "persistcfg.h"
  19. #include "WinMgmtR.h"
  20. #include <ql.h>
  21. #include <cominit.h>
  22. #include <genutils.h>
  23. #include "NCEvents.h" // For the non-COM event stuff
  24. #include <tempbind.h>
  25. #include <wbemutil.h>
  26. #include <tchar.h>
  27. long g_lNumNamespaces = 0;
  28. long g_lNumInternalTempSubscriptions = 0;
  29. long g_lNumTempSubscriptions = 0;
  30. #define ENSURE_INITIALIZED \
  31. hres = EnsureInitPending(); \
  32. if ( FAILED(hres) ) \
  33. return hres; \
  34. hres = WaitForInitialization(); \
  35. if ( FAILED(hres) ) \
  36. return hres; \
  37. CInUpdate iu(this);
  38. // The use of this pointer to initialize parent class is valid in this context
  39. #pragma warning(disable : 4355)
  40. class CEnumSink : public CObjectSink
  41. {
  42. protected:
  43. CEssNamespace* m_pNamespace;
  44. HANDLE m_hEvent;
  45. CEssThreadObject* m_pThreadObj;
  46. public:
  47. CEnumSink(CEssNamespace* pNamespace)
  48. : m_pNamespace(pNamespace),
  49. m_hEvent(CreateEvent(NULL, FALSE, FALSE, NULL)),
  50. m_pThreadObj(GetCurrentEssThreadObject())
  51. {}
  52. ~CEnumSink(){SetEvent(m_hEvent);}
  53. void ReleaseAndWait()
  54. {
  55. HANDLE h = m_hEvent;
  56. Release();
  57. WaitForSingleObject(h, INFINITE);
  58. CloseHandle(h);
  59. }
  60. virtual HRESULT Process(IWbemClassObject* pObj) = 0;
  61. STDMETHOD(Indicate)(long lNumObjects, IWbemClassObject** apObjects)
  62. {
  63. SetConstructedEssThreadObject(m_pThreadObj);
  64. for(int i = 0; i < lNumObjects; i++)
  65. Process(apObjects[i]);
  66. return S_OK;
  67. }
  68. STDMETHOD(SetStatus)(long, HRESULT, BSTR, IWbemClassObject*)
  69. {
  70. return S_OK;
  71. }
  72. };
  73. class CFilterEnumSink : public CEnumSink
  74. {
  75. public:
  76. CFilterEnumSink(CEssNamespace* pNamespace) : CEnumSink(pNamespace){}
  77. virtual HRESULT Process(IWbemClassObject* pObj)
  78. {
  79. return m_pNamespace->AddEventFilter(pObj, TRUE);
  80. }
  81. };
  82. class CConsumerEnumSink : public CEnumSink
  83. {
  84. public:
  85. CConsumerEnumSink(CEssNamespace* pNamespace) : CEnumSink(pNamespace){}
  86. virtual HRESULT Process(IWbemClassObject* pObj)
  87. {
  88. return m_pNamespace->AddEventConsumer(pObj, 0, TRUE);
  89. }
  90. };
  91. class CBindingEnumSink : public CEnumSink
  92. {
  93. public:
  94. CBindingEnumSink(CEssNamespace* pNamespace) : CEnumSink(pNamespace){}
  95. virtual HRESULT Process(IWbemClassObject* pObj)
  96. {
  97. return m_pNamespace->AddBinding(pObj);
  98. }
  99. };
  100. #ifdef __WHISTLER_UNCUT
  101. class CMonitorEnumSink : public CEnumSink
  102. {
  103. public:
  104. CMonitorEnumSink(CEssNamespace* pNamespace) : CEnumSink(pNamespace){}
  105. virtual HRESULT Process(IWbemClassObject* pObj)
  106. {
  107. return m_pNamespace->AddMonitor(pObj);
  108. }
  109. };
  110. #endif
  111. class CPostponedReleaseRequest : public CPostponedRequest
  112. {
  113. protected:
  114. IUnknown* m_pUnk;
  115. public:
  116. CPostponedReleaseRequest(IUnknown* pToRelease) : m_pUnk(pToRelease)
  117. {
  118. try
  119. {
  120. if(m_pUnk)
  121. m_pUnk->AddRef();
  122. }
  123. catch(...)
  124. {
  125. }
  126. }
  127. HRESULT Execute(CEssNamespace* pNamespace)
  128. {
  129. try
  130. {
  131. if(m_pUnk)
  132. m_pUnk->Release();
  133. }
  134. catch(...)
  135. {
  136. }
  137. return WBEM_S_NO_ERROR;
  138. }
  139. ~CPostponedReleaseRequest()
  140. {
  141. try
  142. {
  143. if(m_pUnk)
  144. m_pUnk->Release();
  145. }
  146. catch(...)
  147. {
  148. }
  149. }
  150. };
  151. class CPostponedRegisterNotificationSinkRequest : public CPostponedRequest
  152. {
  153. protected:
  154. WString m_wsQuery;
  155. WString m_wsQueryLanguage;
  156. DWORD m_lFlags;
  157. DWORD m_dwQosFlags;
  158. CWbemPtr<IWbemObjectSink> m_pSink;
  159. CWbemPtr<CEssNamespace> m_pNamespace;
  160. CNtSid m_OwnerSid;
  161. public:
  162. HRESULT SetRegistration( CEssNamespace* pNamespace,
  163. LPCWSTR wszQueryLanguage,
  164. LPCWSTR wszQuery,
  165. long lFlags,
  166. DWORD dwQosFlags,
  167. IWbemObjectSink* pSink,
  168. PSID pOwnerSid )
  169. {
  170. m_pSink = pSink;
  171. m_lFlags = lFlags;
  172. m_dwQosFlags = dwQosFlags;
  173. m_pNamespace = pNamespace;
  174. try
  175. {
  176. m_wsQuery = wszQuery;
  177. m_wsQueryLanguage = wszQueryLanguage;
  178. m_OwnerSid = CNtSid(pOwnerSid);
  179. }
  180. catch( CX_MemoryException )
  181. {
  182. return WBEM_E_OUT_OF_MEMORY;
  183. }
  184. return WBEM_S_NO_ERROR;
  185. }
  186. HRESULT Execute( CEssNamespace* pNamespace )
  187. {
  188. HRESULT hr;
  189. //
  190. // we must set up a new thread object and then restore the
  191. // old one where we're done. Reason for this is that we don't
  192. // want our call into the other namespace to affect the postponed
  193. // list of this one.
  194. //
  195. CEssThreadObject* pOldThreadObject = GetCurrentEssThreadObject();
  196. SetCurrentEssThreadObject(NULL);
  197. if ( GetCurrentEssThreadObject() == NULL )
  198. {
  199. return WBEM_E_OUT_OF_MEMORY;
  200. }
  201. {
  202. CInUpdate iu( m_pNamespace );
  203. hr = m_pNamespace->InternalRegisterNotificationSink(
  204. m_wsQueryLanguage,
  205. m_wsQuery,
  206. m_lFlags,
  207. WMIMSG_QOS_FLAG(m_dwQosFlags),
  208. NULL,
  209. m_pSink,
  210. TRUE,
  211. m_OwnerSid.GetPtr() );
  212. }
  213. if ( SUCCEEDED(hr) )
  214. {
  215. hr = m_pNamespace->FirePostponedOperations();
  216. }
  217. else
  218. {
  219. m_pNamespace->FirePostponedOperations();
  220. }
  221. delete GetCurrentEssThreadObject();
  222. SetConstructedEssThreadObject( pOldThreadObject );
  223. return hr;
  224. }
  225. };
  226. class CPostponedRemoveNotificationSinkRequest : public CPostponedRequest
  227. {
  228. protected:
  229. CWbemPtr<IWbemObjectSink> m_pSink;
  230. CWbemPtr<CEssNamespace> m_pNamespace;
  231. public:
  232. CPostponedRemoveNotificationSinkRequest( CEssNamespace* pNamespace,
  233. IWbemObjectSink* pSink )
  234. : m_pSink( pSink ), m_pNamespace( pNamespace ) { }
  235. HRESULT Execute( CEssNamespace* pNamespace )
  236. {
  237. HRESULT hr;
  238. //
  239. // we must set up a new thread object and then restore the
  240. // old one where we're done. Reason for this is that we don't
  241. // want our call into the other namespace to affect the postponed
  242. // list of this one.
  243. //
  244. CEssThreadObject* pOldThreadObject = GetCurrentEssThreadObject();
  245. SetCurrentEssThreadObject(NULL);
  246. if ( GetCurrentEssThreadObject() == NULL )
  247. {
  248. return WBEM_E_OUT_OF_MEMORY;
  249. }
  250. {
  251. CInUpdate iu( m_pNamespace );
  252. hr = m_pNamespace->InternalRemoveNotificationSink( m_pSink );
  253. }
  254. if ( SUCCEEDED(hr) )
  255. {
  256. hr = m_pNamespace->FirePostponedOperations();
  257. }
  258. else
  259. {
  260. m_pNamespace->FirePostponedOperations();
  261. }
  262. delete GetCurrentEssThreadObject();
  263. SetConstructedEssThreadObject( pOldThreadObject );
  264. return hr;
  265. }
  266. };
  267. //******************************************************************************
  268. // public
  269. //
  270. // See ess.h for documentation
  271. //
  272. //******************************************************************************
  273. CEssNamespace::CEssNamespace(CEss* pEss) :
  274. m_ClassDeletionSink(this), m_bInResync(FALSE),
  275. m_Bindings(this), m_hInitComplete(INVALID_HANDLE_VALUE),
  276. m_EventProviderCache(this), m_Poller(this),
  277. m_ConsumerProviderCache(this), m_hresInit(WBEM_E_CRITICAL_ERROR),
  278. m_ClassCache(this), m_eState(e_Quiet),
  279. m_pMonitorProvider(NULL), m_pCoreEventProvider(NULL),
  280. m_pEss(pEss), m_wszName(NULL), m_pCoreSvc(NULL), m_pFullSvc(NULL),
  281. m_lRef(0), m_pInternalCoreSvc(NULL), m_pInternalFullSvc(NULL),
  282. m_pProviderFactory(NULL), m_bStage1Complete(FALSE)
  283. {
  284. PSID pRawSid;
  285. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  286. g_lNumNamespaces++;
  287. if(AllocateAndInitializeSid( &id, 2,
  288. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  289. 0,0,0,0,0,0,&pRawSid))
  290. {
  291. m_sidAdministrators = CNtSid(pRawSid);
  292. // We're done with this
  293. FreeSid( pRawSid );
  294. }
  295. }
  296. ULONG CEssNamespace::AddRef()
  297. {
  298. return InterlockedIncrement(&m_lRef);
  299. }
  300. ULONG CEssNamespace::Release()
  301. {
  302. long lRef = InterlockedDecrement(&m_lRef);
  303. if(lRef == 0)
  304. delete this;
  305. return lRef;
  306. }
  307. //
  308. // this function is intended to be called in the same control path as
  309. // the one which constructs the namespace object. Any initialization that
  310. // cannot be defferred is done here.
  311. //
  312. HRESULT CEssNamespace::PreInitialize( LPCWSTR wszName )
  313. {
  314. HRESULT hres;
  315. m_wszName = new WCHAR[wcslen(wszName)+1];
  316. if(m_wszName == NULL)
  317. {
  318. hres = WBEM_E_OUT_OF_MEMORY;
  319. return hres;
  320. }
  321. wcscpy(m_wszName, wszName);
  322. //
  323. // create the event that will be used to signal any threads waiting
  324. // for initialization to finish.
  325. //
  326. m_hInitComplete = CreateEvent( NULL, TRUE, FALSE, NULL );
  327. if ( NULL == m_hInitComplete )
  328. {
  329. return WBEM_E_CRITICAL_ERROR;
  330. }
  331. //
  332. // Obtain repository only service. This is used for acessing all
  333. // static ess objects.
  334. //
  335. hres = m_pEss->GetNamespacePointer( m_wszName, TRUE, &m_pCoreSvc );
  336. if(FAILED(hres))
  337. {
  338. return WBEM_E_INVALID_NAMESPACE; // not there anymore!
  339. }
  340. hres = m_pCoreSvc->QueryInterface( IID_IWbemInternalServices,
  341. (void**)&m_pInternalCoreSvc );
  342. if(FAILED(hres))
  343. {
  344. return WBEM_E_CRITICAL_ERROR;
  345. }
  346. //
  347. // Obtain full service. This is used accessing class objects
  348. // ( which may involve accessing class providers.
  349. //
  350. hres = m_pEss->GetNamespacePointer( m_wszName, FALSE, &m_pFullSvc );
  351. if(FAILED(hres))
  352. {
  353. return WBEM_E_INVALID_NAMESPACE; // not there anymore!
  354. }
  355. hres = m_pFullSvc->QueryInterface( IID_IWbemInternalServices,
  356. (void**)&m_pInternalFullSvc );
  357. if(FAILED(hres))
  358. {
  359. return WBEM_E_CRITICAL_ERROR;
  360. }
  361. //
  362. // Get provider factory
  363. //
  364. hres = m_pEss->GetProviderFactory( m_wszName,
  365. m_pFullSvc,
  366. &m_pProviderFactory);
  367. if(FAILED(hres))
  368. {
  369. ERRORTRACE((LOG_ESS, "No provider factory in %S: 0x%X\n",
  370. m_wszName, hres));
  371. }
  372. //
  373. // we want to ensure that core stays loaded between the PreInitialize()
  374. // call and the Initialize() call. This is only ever an issue when the
  375. // Initialize() call is defferred. Reason to ensure this is because we
  376. // must keep core loaded when we have permanent subscriptions. If we
  377. // haven't initialized yet, then we don't know if we have any. AddRef()
  378. // core here and will then decrement in Initialize() to ensure this.
  379. //
  380. IncrementObjectCount();
  381. //
  382. // Namespace always starts out in the Quiet state. Caller must make
  383. // a MarkAsInitPendingIfQuiet() call if they are going to schedule
  384. // initialization.
  385. //
  386. return WBEM_S_NO_ERROR;
  387. }
  388. HRESULT CEssNamespace::EnsureInitPending()
  389. {
  390. {
  391. CInCritSec ics(&m_csLevel1);
  392. if ( m_eState != e_Quiet )
  393. {
  394. return WBEM_S_FALSE;
  395. }
  396. }
  397. CWbemPtr<CEssNamespace> pNamespace;
  398. return m_pEss->GetNamespaceObject( m_wszName, TRUE, &pNamespace );
  399. }
  400. BOOL CEssNamespace::MarkAsInitPendingIfQuiet()
  401. {
  402. CInCritSec ics( &m_csLevel1 );
  403. if ( m_eState != e_Quiet )
  404. {
  405. return FALSE;
  406. }
  407. m_eState = e_InitializePending;
  408. return TRUE;
  409. };
  410. HRESULT CEssNamespace::Initialize()
  411. {
  412. HRESULT hres;
  413. DEBUGTRACE((LOG_ESS,"Initializing namespace %S\n", m_wszName ));
  414. //
  415. // need to modify level2 members. Grab namespace lock.
  416. //
  417. {
  418. CInUpdate iu(this);
  419. {
  420. CInCritSec ics( &m_csLevel1 );
  421. if ( m_eState == e_Shutdown )
  422. {
  423. return WBEM_E_SHUTTING_DOWN;
  424. }
  425. _DBG_ASSERT( m_eState == e_InitializePending );
  426. }
  427. //
  428. // Load and process subscription objects
  429. //
  430. hres = PerformSubscriptionInitialization();
  431. m_bStage1Complete = TRUE;
  432. }
  433. //
  434. // execute postponed operations outside of namespace lock.
  435. // if some of them fail to execute, it doesn't mean that the namespace
  436. // can't be initialized. just log the error.
  437. //
  438. HRESULT hres2 = FirePostponedOperations();
  439. if ( FAILED(hres2) )
  440. {
  441. ERRORTRACE((LOG_ESS,"Failed to execute postponed operations when "
  442. "performing initialization in namespace %S. HR=0x%x\n",
  443. m_wszName, hres2));
  444. }
  445. return hres;
  446. }
  447. HRESULT CEssNamespace::CompleteInitialization()
  448. {
  449. HRESULT hres;
  450. DEBUGTRACE((LOG_ESS,"Completing Initialization for namespace %S\n",
  451. m_wszName));
  452. //
  453. // need to modify level2 members. Grab namespace lock.
  454. //
  455. {
  456. CInUpdate iu(this);
  457. {
  458. CInCritSec ics( &m_csLevel1 );
  459. if ( m_eState == e_Shutdown )
  460. {
  461. return WBEM_E_SHUTTING_DOWN;
  462. }
  463. _DBG_ASSERT( m_eState == e_InitializePending );
  464. }
  465. //
  466. // load and process all objects that deal with event providers.
  467. //
  468. hres = PerformProviderInitialization();
  469. }
  470. //
  471. // execute postponed operations outside of namespace lock.
  472. // if some of them fail to execute, it doesn't mean that the namespace
  473. // can't be initialized. just log the error.
  474. //
  475. HRESULT hres2 = FirePostponedOperations();
  476. if ( FAILED(hres2) )
  477. {
  478. ERRORTRACE((LOG_ESS,"Failed to execute postponed operations when "
  479. "completing initialization in namespace %S. HR=0x%x\n",
  480. m_wszName, hres2));
  481. }
  482. return hres;
  483. }
  484. void CEssNamespace::MarkAsInitialized( HRESULT hres )
  485. {
  486. //
  487. // we need to grab the level1 critsec here because we're going to be
  488. // modifying the state of the namespace and because we're going to be
  489. // using the defferred events list.
  490. //
  491. CInCritSec ics( &m_csLevel1 );
  492. if ( m_eState == e_Shutdown )
  493. {
  494. return;
  495. }
  496. _DBG_ASSERT( m_eState == e_InitializePending );
  497. //
  498. // transition to Initialized.
  499. //
  500. if ( SUCCEEDED(hres) && m_pCoreEventProvider != NULL )
  501. {
  502. //
  503. // while holding level1, handle any deferred events
  504. //
  505. for( int i=0; i < m_aDeferredEvents.GetSize(); i++ )
  506. {
  507. //
  508. // iterate through 1 by 1 because later we may propagate
  509. // context for each event here.
  510. //
  511. HRESULT hr;
  512. CEventContext Context;
  513. hr = m_pCoreEventProvider->Fire( *m_aDeferredEvents[i], &Context );
  514. if ( FAILED(hr) )
  515. {
  516. ERRORTRACE((LOG_ESS,"Could not fire deferred event in "
  517. "namespace '%S'. HR=0x%x\n", m_wszName, hr ));
  518. }
  519. delete m_aDeferredEvents[i];
  520. }
  521. if ( m_aDeferredEvents.GetSize() > 0 )
  522. {
  523. DEBUGTRACE((LOG_ESS,"Fired %d deferred events after init "
  524. "complete in namespace '%S'.\n",
  525. m_aDeferredEvents.GetSize(),m_wszName));
  526. }
  527. m_aDeferredEvents.RemoveAll();
  528. }
  529. //
  530. // release the ref we were holding to keep core loaded between PreInit()
  531. // and now.
  532. //
  533. DecrementObjectCount();
  534. m_eState = e_Initialized;
  535. m_hresInit = hres;
  536. SetEvent( m_hInitComplete );
  537. }
  538. HRESULT CEssNamespace::WaitForInitialization()
  539. {
  540. HRESULT hres;
  541. //
  542. // The level1 or level2 locks cannot be held when calling this function.
  543. // The reason for this is because we may be we waiting on the initialize
  544. // event.
  545. //
  546. CInCritSec ics(&m_csLevel1);
  547. if ( m_eState == e_Shutdown )
  548. {
  549. return WBEM_E_SHUTTING_DOWN;
  550. }
  551. if ( m_eState == e_Initialized )
  552. {
  553. return m_hresInit;
  554. }
  555. _DBG_ASSERT( m_eState == e_InitializePending );
  556. _DBG_ASSERT( m_hInitComplete != INVALID_HANDLE_VALUE )
  557. //
  558. // wait for initialization to complete.
  559. //
  560. LeaveCriticalSection( &m_csLevel1 );
  561. m_pEss->TriggerDeferredInitialization();
  562. DWORD dwRes = WaitForSingleObject( m_hInitComplete, 20*60*1000 );
  563. EnterCriticalSection( &m_csLevel1 );
  564. if ( dwRes != WAIT_OBJECT_0 )
  565. {
  566. return WBEM_E_CRITICAL_ERROR;
  567. }
  568. return m_hresInit;
  569. }
  570. BOOL CEssNamespace::DoesThreadOwnNamespaceLock()
  571. {
  572. return m_csLevel2.GetLockCount() != -1 &&
  573. m_csLevel2.GetOwningThreadId() == GetCurrentThreadId();
  574. }
  575. void CEssNamespace::LogOp( LPCWSTR wszOp, IWbemClassObject* pObj )
  576. {
  577. if ( LoggingLevelEnabled(2) )
  578. {
  579. _DBG_ASSERT(pObj!=NULL);
  580. BSTR bstrText;
  581. if ( SUCCEEDED(pObj->GetObjectText( 0, &bstrText )) )
  582. {
  583. DEBUGTRACE((LOG_ESS,"%S in namespace %S. Object is %S\n",
  584. wszOp, m_wszName, bstrText ));
  585. SysFreeString( bstrText );
  586. }
  587. }
  588. }
  589. CQueueingEventSink* CEssNamespace::GetQueueingEventSink( LPCWSTR wszSinkName )
  590. {
  591. HRESULT hr;
  592. //
  593. // TODO: For now there is a 1 to 1 mapping between a sink and a consumer.
  594. // ( consumer inherits from queueing sink ). This will not always be
  595. // the case. Here, the sink name is really the standard path to the cons.
  596. //
  597. CEventConsumer* pCons;
  598. hr = m_Bindings.FindEventConsumer( wszSinkName, &pCons );
  599. if ( FAILED(hr) )
  600. {
  601. return NULL;
  602. }
  603. return pCons;
  604. }
  605. //******************************************************************************
  606. // public
  607. //
  608. // See ess.h for documentation
  609. //
  610. //******************************************************************************
  611. BOOL CEssNamespace::IsNeededOnStartup()
  612. {
  613. return m_Bindings.DoesHavePermanentConsumers();
  614. }
  615. void CEssNamespace::SetActive()
  616. {
  617. //
  618. // Inform ESS of our newely active status so that it can make sure
  619. // we are reloaded the next time around
  620. //
  621. m_pEss->SetNamespaceActive(m_wszName);
  622. }
  623. void CEssNamespace::SetInactive()
  624. {
  625. //
  626. // Inform ESS of our newely inactive status so that it does not have to
  627. // reload us the next time around
  628. //
  629. m_pEss->SetNamespaceInactive(m_wszName);
  630. }
  631. //
  632. // This is a quick and dirty shutdown of the namespace that is used when the
  633. // process is shutting down.
  634. //
  635. HRESULT CEssNamespace::Park()
  636. {
  637. // bool bSkipClean = true;
  638. //
  639. // DWORD dwVal = 0;
  640. // Registry r(WBEM_REG_WINMGMT);
  641. //
  642. // if ( r.GetDWORDStr( _TEXT("Force Clean Shutdown"), &dwVal )
  643. // == Registry::no_error)
  644. // {
  645. // bSkipClean = false;
  646. // }
  647. //
  648. // m_Bindings.Clear( bSkipClean );
  649. m_Bindings.Clear( false );
  650. FirePostponedOperations();
  651. return S_OK;
  652. }
  653. //
  654. // This is the slow and clean shutdown that is used when the namespace is
  655. // purged.
  656. //
  657. HRESULT CEssNamespace::Shutdown()
  658. {
  659. {
  660. //
  661. // we want to wait until all update operations have completed, then
  662. // we'll mark the namespace as shutdown.
  663. //
  664. CInUpdate iu(this);
  665. //
  666. // we will also be modifying the level1 members too so need level1
  667. // lock.
  668. //
  669. CInCritSec ics(&m_csLevel1);
  670. m_eState = e_Shutdown;
  671. }
  672. //
  673. // at this point all new calls into the namespace will be rejected.
  674. //
  675. //
  676. // wake up any threads waiting for Initialization.
  677. //
  678. SetEvent( m_hInitComplete );
  679. InternalRemoveNotificationSink(&m_ClassDeletionSink);
  680. m_EventProviderCache.Shutdown();
  681. m_Bindings.Clear( false );
  682. m_Poller.Clear();
  683. m_ConsumerProviderCache.Clear();
  684. FirePostponedOperations();
  685. return WBEM_S_NO_ERROR;
  686. }
  687. CEssNamespace::~CEssNamespace()
  688. {
  689. //
  690. // Do not call shutdown here. Shutdown() is an operation that incurrs
  691. // postponed operations and triggering them to fire here is not usually
  692. // expected by the caller. If the caller wants to call shutdown on their
  693. // own then they are welcome to do so.
  694. //
  695. g_lNumNamespaces--;
  696. delete [] m_wszName;
  697. if(m_pCoreSvc)
  698. m_pCoreSvc->Release();
  699. if(m_pFullSvc)
  700. m_pFullSvc->Release();
  701. if(m_pInternalCoreSvc)
  702. m_pInternalCoreSvc->Release();
  703. if(m_pInternalFullSvc)
  704. m_pInternalFullSvc->Release();
  705. if(m_pProviderFactory)
  706. m_pProviderFactory->Release();
  707. if(m_pCoreEventProvider)
  708. m_pCoreEventProvider->Release();
  709. if(m_pMonitorProvider)
  710. m_pMonitorProvider->Release();
  711. if ( m_hInitComplete != INVALID_HANDLE_VALUE )
  712. CloseHandle( m_hInitComplete );
  713. for( int i=0; i < m_aDeferredEvents.GetSize(); i++ )
  714. delete m_aDeferredEvents[i];
  715. }
  716. HRESULT CEssNamespace::GetNamespacePointer(
  717. RELEASE_ME IWbemServices** ppNamespace)
  718. {
  719. //
  720. // This function returns the full svc pointer for use outside this class.
  721. // We want to ensure that we don't use the full service ptr until we've
  722. // completed stage 1 initialization. Reason is that we don't want to
  723. // load class providers until the second stage of initialization.
  724. //
  725. _DBG_ASSERT( m_bStage1Complete );
  726. if(m_pFullSvc == NULL)
  727. return WBEM_E_CRITICAL_ERROR;
  728. *ppNamespace = m_pFullSvc;
  729. (*ppNamespace)->AddRef();
  730. return S_OK;
  731. }
  732. HRESULT CEssNamespace::ActOnSystemEvent(CEventRepresentation& Event,
  733. long lFlags)
  734. {
  735. HRESULT hres;
  736. // This macro will execute its parameter if updates are allowed at this time on
  737. // this thread, and schedule it otherwise (in the case of an event provider
  738. // calling back
  739. #define PERFORM_IF_ALLOWED(OP) OP
  740. // Check the type
  741. // ==============
  742. if(Event.IsInstanceEvent())
  743. {
  744. // Instance creation, deletion or modification event. Check class
  745. // ==============================================================
  746. if(!wbem_wcsicmp(CLASS_OF(Event), EVENT_FILTER_CLASS))
  747. {
  748. return PERFORM_IF_ALLOWED(ReloadEventFilter(OBJECT_OF(Event)));
  749. }
  750. else if(!wbem_wcsicmp(CLASS_OF(Event), BINDING_CLASS))
  751. {
  752. return PERFORM_IF_ALLOWED(ReloadBinding(OBJECT_OF(Event)));
  753. }
  754. #ifdef __WHISTLER_UNCUT
  755. else if(!wbem_wcsicmp(CLASS_OF(Event), MONITOR_CLASS))
  756. {
  757. return PERFORM_IF_ALLOWED(ReloadMonitor(OBJECT_OF(Event)));
  758. }
  759. #endif
  760. else if(!wbem_wcsicmp(CLASS_OF(Event),
  761. EVENT_PROVIDER_REGISTRATION_CLASS))
  762. {
  763. return PERFORM_IF_ALLOWED(
  764. ReloadEventProviderRegistration(OBJECT_OF(Event)));
  765. }
  766. else if(!wbem_wcsicmp(CLASS_OF(Event),
  767. CONSUMER_PROVIDER_REGISTRATION_CLASS))
  768. {
  769. return PERFORM_IF_ALLOWED(
  770. ReloadConsumerProviderRegistration(OBJECT_OF(Event)));
  771. }
  772. else if(OBJECT_OF(Event)->InheritsFrom(PROVIDER_CLASS) == S_OK)
  773. {
  774. return PERFORM_IF_ALLOWED(ReloadProvider(OBJECT_OF(Event)));
  775. }
  776. else if(OBJECT_OF(Event)->InheritsFrom(CONSUMER_CLASS) == S_OK)
  777. {
  778. return PERFORM_IF_ALLOWED(ReloadEventConsumer(OBJECT_OF(Event),
  779. lFlags));
  780. }
  781. else if(OBJECT_OF(Event)->InheritsFrom(TIMER_BASE_CLASS) == S_OK)
  782. {
  783. return PERFORM_IF_ALLOWED(ReloadTimerInstruction(OBJECT_OF(Event)));
  784. }
  785. else
  786. {
  787. return WBEM_S_FALSE;
  788. }
  789. }
  790. else if(Event.type == e_EventTypeClassDeletion)
  791. {
  792. //
  793. // For now --- only for deletions. Force-mode modifications are not
  794. // properly handled at the moment.
  795. //
  796. return PERFORM_IF_ALLOWED(
  797. HandleClassChange(CLASS_OF(Event), OBJECT_OF(Event)));
  798. }
  799. else if(Event.type == e_EventTypeClassCreation)
  800. {
  801. return PERFORM_IF_ALLOWED(
  802. HandleClassCreation(CLASS_OF(Event), OBJECT_OF(Event)));
  803. }
  804. else if(Event.type == e_EventTypeNamespaceDeletion)
  805. {
  806. // Construct full namespace name (ours + child)
  807. // ============================================
  808. LPWSTR wszFullName = new WCHAR[
  809. wcslen(m_wszName) + wcslen(Event.wsz2) + 2];
  810. if(wszFullName == NULL)
  811. return WBEM_E_OUT_OF_MEMORY;
  812. CVectorDeleteMe<WCHAR> vdm( wszFullName );
  813. swprintf(wszFullName, L"%s\\%s", m_wszName, Event.wsz2);
  814. // Get the main object to purge that namespace
  815. // ===========================================
  816. return m_pEss->PurgeNamespace(wszFullName);
  817. }
  818. else
  819. {
  820. // Not of interest
  821. // ===============
  822. return WBEM_S_FALSE;
  823. }
  824. }
  825. HRESULT CEssNamespace::ValidateSystemEvent(CEventRepresentation& Event)
  826. {
  827. HRESULT hr;
  828. // Check the type
  829. // ==============
  830. if(Event.IsInstanceEvent())
  831. {
  832. IWbemClassObject* pPrevObj = NULL;
  833. IWbemClassObject* pObj = NULL;
  834. if(Event.type == e_EventTypeInstanceCreation)
  835. pObj = OBJECT_OF(Event);
  836. else if(Event.type == e_EventTypeInstanceDeletion)
  837. pPrevObj = OBJECT_OF(Event);
  838. else if(Event.type == e_EventTypeInstanceModification)
  839. {
  840. pObj = OBJECT_OF(Event);
  841. pPrevObj = OTHER_OBJECT_OF(Event);
  842. }
  843. // Instance creation, deletion or modification event. Check class
  844. // ==============================================================
  845. if(!wbem_wcsicmp(CLASS_OF(Event), EVENT_FILTER_CLASS))
  846. {
  847. hr = CheckEventFilter(pPrevObj, pObj);
  848. }
  849. else if(!wbem_wcsicmp(CLASS_OF(Event), BINDING_CLASS))
  850. {
  851. hr = CheckBinding(pPrevObj, pObj);
  852. }
  853. else if(!wbem_wcsicmp(CLASS_OF(Event),
  854. EVENT_PROVIDER_REGISTRATION_CLASS))
  855. {
  856. hr = CheckEventProviderRegistration(OBJECT_OF(Event));
  857. }
  858. else if(OBJECT_OF(Event)->InheritsFrom(CONSUMER_CLASS) == S_OK)
  859. {
  860. hr = CheckEventConsumer(pPrevObj, pObj);
  861. }
  862. else if(OBJECT_OF(Event)->InheritsFrom(TIMER_BASE_CLASS) == S_OK)
  863. {
  864. hr = CheckTimerInstruction(pObj);
  865. }
  866. else
  867. {
  868. hr = WBEM_S_FALSE;
  869. }
  870. //
  871. // even some of the validation routines use postponed operations.
  872. //
  873. FirePostponedOperations();
  874. }
  875. else
  876. {
  877. // Not of interest
  878. // ===============
  879. hr = WBEM_S_FALSE;
  880. }
  881. return hr;
  882. }
  883. HRESULT CEssNamespace::CheckEventConsumer(IWbemClassObject* pPrevConsumerObj,
  884. IWbemClassObject* pConsumerObj)
  885. {
  886. HRESULT hres;
  887. ENSURE_INITIALIZED
  888. hres = CheckSecurity(pPrevConsumerObj, pConsumerObj);
  889. return hres;
  890. }
  891. PSID CEssNamespace::GetSidFromObject(IWbemClassObject* pObj)
  892. {
  893. HRESULT hres;
  894. VARIANT vSid;
  895. VariantInit(&vSid);
  896. CClearMe cm1(&vSid);
  897. hres = pObj->Get(OWNER_SID_PROPNAME, 0, &vSid, NULL, NULL);
  898. if(FAILED(hres) || V_VT(&vSid) != (VT_UI1 | VT_ARRAY))
  899. {
  900. return NULL;
  901. }
  902. // Construct an actual PSID from the SAFEARRAY
  903. // ===========================================
  904. PSID pOriginal = NULL;
  905. hres = SafeArrayAccessData(V_ARRAY(&vSid), (void**)&pOriginal);
  906. if(FAILED(hres))
  907. {
  908. return NULL;
  909. }
  910. CUnaccessMe uam(V_ARRAY(&vSid));
  911. long cOriginal;
  912. if ( FAILED(SafeArrayGetUBound( V_ARRAY(&vSid), 1, &cOriginal ) ))
  913. {
  914. return NULL;
  915. }
  916. cOriginal++; // SafeArrayGetUBound() is -1 based
  917. //
  918. // validate SID.
  919. //
  920. DWORD dwSidLength = GetLengthSid(pOriginal);
  921. if ( dwSidLength > cOriginal || !IsValidSid(pOriginal) )
  922. {
  923. return NULL;
  924. }
  925. // Make a copy and return it
  926. // =========================
  927. PSID pCopy = (PSID)new BYTE[dwSidLength];
  928. if(pCopy == NULL)
  929. return NULL;
  930. if(!CopySid(dwSidLength, pCopy, pOriginal))
  931. {
  932. delete [] (BYTE*)pCopy;
  933. return NULL;
  934. }
  935. return pCopy;
  936. }
  937. HRESULT CEssNamespace::CheckSecurity(IWbemClassObject* pPrevObj,
  938. IWbemClassObject* pObj)
  939. {
  940. HRESULT hres;
  941. if(!IsNT())
  942. return WBEM_S_NO_ERROR;
  943. // Retrieve the SID of the calling user
  944. // ====================================
  945. hres = WbemCoImpersonateClient();
  946. if(FAILED(hres))
  947. return hres;
  948. CNtSid Sid;
  949. hres = CDerivedObjectSecurity::RetrieveSidFromCall(&Sid);
  950. WbemCoRevertToSelf();
  951. if(FAILED(hres))
  952. return hres;
  953. // If modifying an existing object, check override security
  954. // ========================================================
  955. if(pPrevObj)
  956. {
  957. hres = CheckOverwriteSecurity(pPrevObj, Sid);
  958. if(FAILED(hres))
  959. return hres;
  960. }
  961. // If creating a new version of an object, ensure Sid correctness
  962. // ==============================================================
  963. if(pObj)
  964. {
  965. hres = EnsureSessionSid(pObj, Sid);
  966. if(FAILED(hres))
  967. return hres;
  968. }
  969. return WBEM_S_NO_ERROR;
  970. }
  971. HRESULT CEssNamespace::EnsureSessionSid(IWbemClassObject* pObj, CNtSid& Sid)
  972. {
  973. HRESULT hres;
  974. //
  975. // Check for the special case of administrators --- they can use the
  976. // Administrators SID instead of their own for off-line operations.
  977. //
  978. hres = IsCallerAdministrator();
  979. if(FAILED(hres) && hres != WBEM_E_ACCESS_DENIED)
  980. return hres;
  981. if(SUCCEEDED(hres))
  982. {
  983. //
  984. // This is an admin --- check if there is a SID in the object already
  985. //
  986. PSID pOldSid = GetSidFromObject(pObj);
  987. if(pOldSid == NULL)
  988. {
  989. //
  990. // No SID --- just put an owner SID in there
  991. //
  992. return PutSidInObject(pObj, Sid);
  993. }
  994. else
  995. {
  996. CVectorDeleteMe<BYTE> vdm((BYTE*)pOldSid);
  997. //
  998. // There is a SID there already --- the only allowed ones are the
  999. // user himself or the Administrators. Make sure it is one of those
  1000. //
  1001. if(!EqualSid(pOldSid, Sid.GetPtr()) &&
  1002. !EqualSid(pOldSid, GetAdministratorsSid().GetPtr()))
  1003. {
  1004. //
  1005. // Invalid SID found --- replace with the owner SID
  1006. //
  1007. return PutSidInObject(pObj, Sid);
  1008. }
  1009. //
  1010. // Valid SID found --- leave it there
  1011. //
  1012. return WBEM_S_NO_ERROR;
  1013. }
  1014. }
  1015. //
  1016. // User not an administrator --- just stick his SID into the object
  1017. //
  1018. return PutSidInObject(pObj, Sid);
  1019. }
  1020. HRESULT CEssNamespace::PutSidInObject(IWbemClassObject* pObj, CNtSid& Sid)
  1021. {
  1022. HRESULT hres;
  1023. //
  1024. // Clear it first
  1025. //
  1026. VARIANT vSid;
  1027. VariantInit(&vSid);
  1028. V_VT(&vSid) = VT_NULL;
  1029. CClearMe cm1(&vSid);
  1030. hres = pObj->Put(OWNER_SID_PROPNAME, 0, &vSid, 0);
  1031. if(FAILED(hres))
  1032. return hres;
  1033. //
  1034. // Construct a safearray for it
  1035. //
  1036. V_VT(&vSid) = VT_ARRAY | VT_UI1;
  1037. SAFEARRAYBOUND sab;
  1038. sab.cElements = Sid.GetSize();
  1039. sab.lLbound = 0;
  1040. V_ARRAY(&vSid) = SafeArrayCreate(VT_UI1, 1, &sab);
  1041. if(V_ARRAY(&vSid) == NULL)
  1042. return WBEM_E_OUT_OF_MEMORY;
  1043. // Copy the SID in there
  1044. // =====================
  1045. BYTE* abSid = NULL;
  1046. hres = SafeArrayAccessData(V_ARRAY(&vSid), (void**)&abSid);
  1047. if(FAILED(hres))
  1048. return WBEM_E_OUT_OF_MEMORY;
  1049. CUnaccessMe uam(V_ARRAY(&vSid));
  1050. if(!CopySid(Sid.GetSize(), (PSID)abSid, Sid.GetPtr()))
  1051. return WBEM_E_OUT_OF_MEMORY;
  1052. // Put it into the consumer
  1053. // ========================
  1054. hres = pObj->Put(OWNER_SID_PROPNAME, 0, &vSid, 0);
  1055. return hres;
  1056. }
  1057. HRESULT CEssNamespace::CheckOverwriteSecurity(IWbemClassObject* pPrevObj,
  1058. CNtSid& ActingSid)
  1059. {
  1060. HRESULT hres;
  1061. if(!IsNT())
  1062. return WBEM_S_NO_ERROR;
  1063. // Retrieve owner SID from the old object
  1064. // ======================================
  1065. PSID pOwnerSid = GetSidFromObject(pPrevObj);
  1066. if(pOwnerSid == NULL)
  1067. return WBEM_E_OUT_OF_MEMORY;
  1068. CVectorDeleteMe<BYTE> vdm((BYTE*)pOwnerSid);
  1069. // Compare the owner sid with the acting SID. If same, allow access
  1070. // =================================================================
  1071. if(EqualSid(pOwnerSid, ActingSid.GetPtr()))
  1072. return WBEM_S_NO_ERROR;
  1073. // Not the same --- still hope that the acting SID is an Admin
  1074. // ===========================================================
  1075. hres = IsCallerAdministrator();
  1076. if(FAILED(hres))
  1077. return hres;
  1078. //
  1079. // OK --- an admin can overwrite
  1080. //
  1081. return WBEM_S_NO_ERROR;
  1082. }
  1083. HRESULT CEssNamespace::IsCallerAdministrator()
  1084. {
  1085. HRESULT hres;
  1086. hres = WbemCoImpersonateClient();
  1087. if(FAILED(hres))
  1088. return hres;
  1089. HANDLE hToken;
  1090. if(!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken))
  1091. return WBEM_E_FAILED;
  1092. CCloseMe ccm(hToken);
  1093. if(CNtSecurity::IsUserInGroup(hToken, GetAdministratorsSid()))
  1094. return WBEM_S_NO_ERROR;
  1095. return WBEM_E_ACCESS_DENIED;
  1096. }
  1097. HRESULT CEssNamespace::CheckEventFilter(IWbemClassObject* pOldFilterObj,
  1098. IWbemClassObject* pFilterObj)
  1099. {
  1100. HRESULT hres;
  1101. ENSURE_INITIALIZED
  1102. // Check security
  1103. // ==============
  1104. hres = CheckSecurity(pOldFilterObj, pFilterObj);
  1105. if(FAILED(hres))
  1106. return hres;
  1107. // Check everything else
  1108. // =====================
  1109. return CPermanentFilter::CheckValidity(pFilterObj);
  1110. }
  1111. HRESULT CEssNamespace::ReloadEventFilter(IWbemClassObject* pFilterObjTemplate)
  1112. {
  1113. HRESULT hres;
  1114. LogOp( L"ReloadEventFilter", pFilterObjTemplate );
  1115. ENSURE_INITIALIZED
  1116. // Start by deleting this event filter from our records, if there
  1117. // ==============================================================
  1118. hres = RemoveEventFilter(pFilterObjTemplate);
  1119. if(FAILED(hres))
  1120. return hres;
  1121. // Determine the current state of this filter in the database
  1122. // ==========================================================
  1123. IWbemClassObject* pFilterObj = NULL;
  1124. hres = GetCurrentState(pFilterObjTemplate, &pFilterObj);
  1125. if(FAILED(hres))
  1126. return hres;
  1127. if(pFilterObj == NULL)
  1128. {
  1129. // The filter has been deleted --- no further action is needed
  1130. // ===========================================================
  1131. return S_OK;
  1132. }
  1133. CReleaseMe rm1(pFilterObj);
  1134. // Now create it if necessary
  1135. // ==========================
  1136. hres = AddEventFilter(pFilterObj);
  1137. if(FAILED(hres))
  1138. return hres;
  1139. return hres;
  1140. }
  1141. //******************************************************************************
  1142. //
  1143. // Starting with the namespace locked and the filter deleted from the records,
  1144. // AddEventFilter updates the records to the state of this filter in the
  1145. // database.
  1146. //
  1147. //******************************************************************************
  1148. HRESULT CEssNamespace::AddEventFilter(IWbemClassObject* pFilterObj,
  1149. BOOL bInRestart)
  1150. {
  1151. HRESULT hres;
  1152. // Construct the new filter
  1153. // ========================
  1154. CPermanentFilter* pFilter = new CPermanentFilter(this);
  1155. if(pFilter == NULL)
  1156. return WBEM_E_OUT_OF_MEMORY;
  1157. pFilter->AddRef();
  1158. CReleaseMe rm2(pFilter);
  1159. // Initialize it
  1160. // =============
  1161. hres = pFilter->Initialize(pFilterObj);
  1162. if(FAILED(hres))
  1163. return hres;
  1164. // Add it to the table
  1165. // ===================
  1166. hres = m_Bindings.AddEventFilter(pFilter);
  1167. if(FAILED(hres))
  1168. return hres;
  1169. if(!bInRestart)
  1170. {
  1171. // Process all the bindings that this filter might have
  1172. // ====================================================
  1173. hres = AssertBindings(pFilterObj);
  1174. if(FAILED(hres))
  1175. return hres;
  1176. }
  1177. return hres;
  1178. }
  1179. //******************************************************************************
  1180. //
  1181. // Starting with the namespace locked, RemoveEventFilter updates the records
  1182. // to remove all mention of this filter. Note: this is *not* the function to be
  1183. // called in response to the database instance-deletion event, as the filter
  1184. // could have been recreated in the interim.
  1185. //
  1186. //******************************************************************************
  1187. HRESULT CEssNamespace::RemoveEventFilter(IWbemClassObject* pFilterObj)
  1188. {
  1189. HRESULT hres;
  1190. // Calculate the key for this filter
  1191. // =================================
  1192. BSTR strKey = CPermanentFilter::ComputeKeyFromObj(pFilterObj);
  1193. if(strKey == NULL)
  1194. return WBEM_E_OUT_OF_MEMORY;
  1195. CSysFreeMe sfm1(strKey);
  1196. // Remove it from the table, thus deactivating it
  1197. // ==============================================
  1198. hres = m_Bindings.RemoveEventFilter(strKey);
  1199. if(hres == WBEM_E_NOT_FOUND)
  1200. return S_FALSE;
  1201. return hres;
  1202. }
  1203. //*****************************************************************************
  1204. //
  1205. // Called in response to an instance operation event related to an event
  1206. // consumer object.
  1207. //
  1208. //*****************************************************************************
  1209. HRESULT CEssNamespace::ReloadEventConsumer(
  1210. IWbemClassObject* pConsumerObjTemplate,
  1211. long lFlags)
  1212. {
  1213. HRESULT hres;
  1214. LogOp( L"ReloadConsumer", pConsumerObjTemplate );
  1215. ENSURE_INITIALIZED
  1216. // Start by deleting this event consumer from our records, if there
  1217. // ================================================================
  1218. hres = RemoveEventConsumer(pConsumerObjTemplate);
  1219. if(FAILED(hres))
  1220. return hres;
  1221. // Determine the current state of this Consumer in the database
  1222. // ============================================================
  1223. IWbemClassObject* pConsumerObj = NULL;
  1224. hres = GetCurrentState(pConsumerObjTemplate, &pConsumerObj);
  1225. if(FAILED(hres))
  1226. return hres;
  1227. if(pConsumerObj == NULL)
  1228. {
  1229. // The Consumer has been deleted --- no further action is needed
  1230. // =============================================================
  1231. return S_OK;
  1232. }
  1233. CReleaseMe rm1(pConsumerObj);
  1234. // Now create it if necessary
  1235. // ==========================
  1236. hres = AddEventConsumer(pConsumerObjTemplate, lFlags, FALSE);
  1237. return hres;
  1238. }
  1239. //******************************************************************************
  1240. //
  1241. // Starting with the namespace locked and the consumer deleted from the records
  1242. // AddEventConsumer updates the records to the state of this consumer in the
  1243. // database.
  1244. //
  1245. //******************************************************************************
  1246. HRESULT CEssNamespace::AddEventConsumer(IWbemClassObject* pConsumerObj,
  1247. long lFlags,
  1248. BOOL bInRestart)
  1249. {
  1250. HRESULT hres;
  1251. // Construct the new Consumer
  1252. // ==========================
  1253. CPermanentConsumer* pConsumer = new CPermanentConsumer(this);
  1254. if(pConsumer == NULL)
  1255. return WBEM_E_OUT_OF_MEMORY;
  1256. pConsumer->AddRef();
  1257. CReleaseMe rm2(pConsumer);
  1258. // Initialize it
  1259. // =============
  1260. hres = pConsumer->Initialize(pConsumerObj);
  1261. if(FAILED(hres))
  1262. return hres;
  1263. //
  1264. // Validate if required
  1265. //
  1266. if(lFlags & WBEM_FLAG_STRONG_VALIDATION)
  1267. {
  1268. hres = pConsumer->Validate(pConsumerObj);
  1269. if(FAILED(hres))
  1270. {
  1271. return hres;
  1272. }
  1273. }
  1274. // Add it to the table
  1275. // ===================
  1276. hres = m_Bindings.AddEventConsumer(pConsumer);
  1277. if(FAILED(hres))
  1278. return hres;
  1279. if(!bInRestart)
  1280. {
  1281. // Process all the bindings that this consumer might have
  1282. // ======================================================
  1283. hres = AssertBindings(pConsumerObj);
  1284. if(FAILED(hres))
  1285. return hres;
  1286. }
  1287. return hres;
  1288. }
  1289. //******************************************************************************
  1290. //
  1291. // Starting with the namespace locked, RemoveEventConsumer updates the records
  1292. // to remove all mention of this consumer.
  1293. //
  1294. //******************************************************************************
  1295. HRESULT CEssNamespace::RemoveEventConsumer(IWbemClassObject* pConsumerObj)
  1296. {
  1297. HRESULT hres;
  1298. // Calculate the key for this filter
  1299. // =================================
  1300. BSTR strKey = CPermanentConsumer::ComputeKeyFromObj(this, pConsumerObj);
  1301. if(strKey == NULL)
  1302. return WBEM_E_OUT_OF_MEMORY;
  1303. CSysFreeMe sfm1(strKey);
  1304. // Remove it from the table
  1305. // ========================
  1306. hres = m_Bindings.RemoveEventConsumer(strKey);
  1307. if(hres == WBEM_E_NOT_FOUND)
  1308. return S_FALSE;
  1309. return hres;
  1310. }
  1311. HRESULT CEssNamespace::CheckBinding(IWbemClassObject* pPrevBindingObj,
  1312. IWbemClassObject* pBindingObj)
  1313. {
  1314. HRESULT hres;
  1315. ENSURE_INITIALIZED
  1316. //
  1317. // Check security
  1318. //
  1319. hres = CheckSecurity(pPrevBindingObj, pBindingObj);
  1320. if(FAILED(hres))
  1321. return hres;
  1322. //
  1323. // Construct a fake binding to test correctness
  1324. //
  1325. CPermanentBinding* pBinding = new CPermanentBinding;
  1326. if(pBinding == NULL)
  1327. return WBEM_E_OUT_OF_MEMORY;
  1328. pBinding->AddRef();
  1329. CTemplateReleaseMe<CPermanentBinding> trm(pBinding);
  1330. hres = pBinding->Initialize(pBindingObj);
  1331. if(FAILED(hres))
  1332. return hres;
  1333. return S_OK;
  1334. }
  1335. //******************************************************************************
  1336. //
  1337. // Called in response to an instance operation event related to a binding
  1338. // instance.
  1339. //
  1340. //******************************************************************************
  1341. HRESULT CEssNamespace::ReloadBinding(IWbemClassObject* pBindingObjTemplate)
  1342. {
  1343. HRESULT hres;
  1344. LogOp( L"ReloadBinding", pBindingObjTemplate );
  1345. ENSURE_INITIALIZED
  1346. // Retrieve consumer and provider keys from the binding
  1347. // ====================================================
  1348. BSTR strPrelimConsumerKey = NULL;
  1349. BSTR strFilterKey = NULL;
  1350. hres = CPermanentBinding::ComputeKeysFromObject(pBindingObjTemplate,
  1351. &strPrelimConsumerKey, &strFilterKey);
  1352. if(FAILED(hres))
  1353. return hres;
  1354. CSysFreeMe sfm1(strPrelimConsumerKey);
  1355. CSysFreeMe sfm2(strFilterKey);
  1356. // Get real paths from these possibly abbreviated ones
  1357. // ===================================================
  1358. BSTR strConsumerKey = NULL;
  1359. hres = m_pInternalCoreSvc->GetNormalizedPath( strPrelimConsumerKey,
  1360. &strConsumerKey);
  1361. if(FAILED(hres))
  1362. return hres;
  1363. CSysFreeMe sfm3(strConsumerKey);
  1364. // Start by deleting this binding from our records, if there
  1365. // =========================================================
  1366. hres = RemoveBinding(strFilterKey, strConsumerKey);
  1367. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  1368. return hres;
  1369. // Determine the current state of this binding in the database
  1370. // ============================================================
  1371. IWbemClassObject* pBindingObj = NULL;
  1372. hres = GetCurrentState(pBindingObjTemplate, &pBindingObj);
  1373. if(FAILED(hres))
  1374. return hres;
  1375. if(pBindingObj == NULL)
  1376. {
  1377. // The Binding has been deleted --- no further action is needed
  1378. // =============================================================
  1379. return S_OK;
  1380. }
  1381. CReleaseMe rm1(pBindingObj);
  1382. // Now create it if necessary
  1383. // ==========================
  1384. hres = AddBinding(strFilterKey, strConsumerKey, pBindingObjTemplate);
  1385. return hres;
  1386. }
  1387. HRESULT CEssNamespace::AddBinding(IWbemClassObject* pBindingObj)
  1388. {
  1389. HRESULT hres;
  1390. // Retrieve consumer and provider keys from the binding
  1391. // ====================================================
  1392. BSTR strPrelimConsumerKey = NULL;
  1393. BSTR strFilterKey = NULL;
  1394. hres = CPermanentBinding::ComputeKeysFromObject(pBindingObj,
  1395. &strPrelimConsumerKey, &strFilterKey);
  1396. if(FAILED(hres))
  1397. return hres;
  1398. CSysFreeMe sfm1(strPrelimConsumerKey);
  1399. CSysFreeMe sfm2(strFilterKey);
  1400. // Get real paths from these possibly abbreviated ones
  1401. // ===================================================
  1402. BSTR strConsumerKey = NULL;
  1403. hres = m_pInternalCoreSvc->GetNormalizedPath( strPrelimConsumerKey,
  1404. &strConsumerKey );
  1405. if(FAILED(hres))
  1406. return hres;
  1407. CSysFreeMe sfm3(strConsumerKey);
  1408. return AddBinding(strFilterKey, strConsumerKey, pBindingObj);
  1409. }
  1410. HRESULT CEssNamespace::AddBinding(LPCWSTR wszFilterKey, LPCWSTR wszConsumerKey,
  1411. IWbemClassObject* pBindingObj)
  1412. {
  1413. HRESULT hres;
  1414. // Create a new binding
  1415. // ====================
  1416. CPermanentBinding* pBinding = new CPermanentBinding;
  1417. if(pBinding == NULL)
  1418. return WBEM_E_OUT_OF_MEMORY;
  1419. pBinding->AddRef();
  1420. CReleaseMe rm1(pBinding);
  1421. // Initialize it with the information we have
  1422. // ==========================================
  1423. hres = pBinding->Initialize(pBindingObj);
  1424. if(FAILED(hres))
  1425. return hres;
  1426. // Extract its creator's SID
  1427. // ========================
  1428. PSID pSid = CPermanentBinding::GetSidFromObject(pBindingObj);
  1429. if ( pSid == NULL )
  1430. {
  1431. return WBEM_E_OUT_OF_MEMORY;
  1432. }
  1433. hres = m_Bindings.Bind( wszFilterKey, wszConsumerKey, pBinding, pSid );
  1434. delete [] pSid;
  1435. return hres;
  1436. }
  1437. HRESULT CEssNamespace::RemoveBinding(LPCWSTR wszFilterKey,
  1438. LPCWSTR wszConsumerKey)
  1439. {
  1440. HRESULT hres;
  1441. hres = m_Bindings.Unbind(wszFilterKey, wszConsumerKey);
  1442. if(hres == WBEM_E_NOT_FOUND)
  1443. return S_FALSE;
  1444. return hres;
  1445. }
  1446. //******************************************************************************
  1447. //
  1448. // Reads all the bindings referencing a given objects from the database and
  1449. // asserts them.
  1450. //
  1451. //******************************************************************************
  1452. class CAssertBindingsSink : public CObjectSink
  1453. {
  1454. protected:
  1455. CEssNamespace* m_pNamespace;
  1456. public:
  1457. CAssertBindingsSink(CEssNamespace* pNamespace) : m_pNamespace(pNamespace)
  1458. {
  1459. AddRef();
  1460. }
  1461. STDMETHOD(Indicate)(long lNumObjects, IWbemClassObject** apObjects)
  1462. {
  1463. for(long i = 0; i < lNumObjects; i++)
  1464. {
  1465. m_pNamespace->AddBinding(apObjects[i]);
  1466. }
  1467. return S_OK;
  1468. }
  1469. };
  1470. HRESULT CEssNamespace::AssertBindings(IWbemClassObject* pEndpoint)
  1471. {
  1472. // Get the relative path of the endpoint
  1473. // =====================================
  1474. VARIANT vRelPath;
  1475. VariantInit(&vRelPath);
  1476. CClearMe cm1(&vRelPath);
  1477. HRESULT hres = pEndpoint->Get(L"__RELPATH", 0, &vRelPath, NULL, NULL);
  1478. if(FAILED(hres))
  1479. return hres;
  1480. if(V_VT(&vRelPath) != VT_BSTR)
  1481. return WBEM_E_INVALID_OBJECT;
  1482. BSTR strRelPath = V_BSTR(&vRelPath);
  1483. // Issue the query
  1484. // ===============
  1485. BSTR strQuery = SysAllocStringLen(NULL, 200 + wcslen(strRelPath));
  1486. if(strQuery == NULL)
  1487. return WBEM_E_OUT_OF_MEMORY;
  1488. CSysFreeMe sfm1(strQuery);
  1489. swprintf(strQuery, L"references of {%s} where "
  1490. L"ResultClass = __FilterToConsumerBinding", strRelPath);
  1491. CAssertBindingsSink Sink(this);
  1492. hres = ExecQuery(strQuery, 0, &Sink);
  1493. return hres;
  1494. }
  1495. HRESULT CEssNamespace::ReloadTimerInstruction(
  1496. IWbemClassObject* pInstObjTemplate)
  1497. {
  1498. HRESULT hres;
  1499. LogOp( L"ReloadTimerInstruction", pInstObjTemplate );
  1500. ENSURE_INITIALIZED
  1501. hres = RemoveTimerInstruction(pInstObjTemplate);
  1502. if(FAILED(hres))
  1503. return hres;
  1504. // Get the current version from the namespace
  1505. // ==========================================
  1506. IWbemClassObject* pInstObj = NULL;
  1507. hres = GetCurrentState(pInstObjTemplate, &pInstObj);
  1508. if(FAILED(hres))
  1509. return hres;
  1510. if(pInstObj == NULL)
  1511. {
  1512. // The instruction has been deleted --- no further action is needed
  1513. // ================================================================
  1514. return S_OK;
  1515. }
  1516. CReleaseMe rm1(pInstObj);
  1517. // Add it to the generator
  1518. // =======================
  1519. hres = AddTimerInstruction(pInstObj);
  1520. if(FAILED(hres))
  1521. return hres;
  1522. return hres;
  1523. }
  1524. HRESULT CEssNamespace::AddTimerInstruction(IWbemClassObject* pInstObj)
  1525. {
  1526. return m_pEss->GetTimerGenerator().
  1527. LoadTimerEventObject(m_wszName, pInstObj);
  1528. }
  1529. //******************************************************************************
  1530. // public
  1531. //
  1532. // See ess.h for documentation
  1533. //
  1534. //******************************************************************************
  1535. HRESULT CEssNamespace::RemoveTimerInstruction(IWbemClassObject* pOldObject)
  1536. {
  1537. HRESULT hres;
  1538. VARIANT vID;
  1539. VariantInit(&vID);
  1540. hres = pOldObject->Get(TIMER_ID_PROPNAME, 0, &vID, NULL, NULL);
  1541. if(FAILED(hres)) return hres;
  1542. m_pEss->GetTimerGenerator().Remove(m_wszName, V_BSTR(&vID));
  1543. VariantClear(&vID);
  1544. return S_OK;
  1545. }
  1546. //******************************************************************************
  1547. // public
  1548. //
  1549. // See ess.h for documentation
  1550. //
  1551. //******************************************************************************
  1552. #ifdef __WHISTLER_UNCUT
  1553. HRESULT CEssNamespace::CheckMonitor(IWbemClassObject* pOldMonitorObj,
  1554. IWbemClassObject* pMonitorObj)
  1555. {
  1556. HRESULT hres;
  1557. ENSURE_INITIALIZED
  1558. // Check security
  1559. // ==============
  1560. hres = CheckSecurity(pOldMonitorObj, pMonitorObj);
  1561. if(FAILED(hres))
  1562. return hres;
  1563. // BUGBUG: any other checks?
  1564. return WBEM_S_NO_ERROR;
  1565. }
  1566. HRESULT CEssNamespace::ReloadMonitor(IWbemClassObject* pMonitorObjTemplate)
  1567. {
  1568. HRESULT hres;
  1569. LogOp( L"ReloadMonitor", pMonitorObjTemplate );
  1570. ENSURE_INITIALIZED
  1571. //
  1572. // Start by deleting this monitor from our records, if there
  1573. //
  1574. hres = RemoveMonitor(pMonitorObjTemplate);
  1575. if(FAILED(hres))
  1576. return hres;
  1577. //
  1578. // Determine the current state of this monitor in the database
  1579. //
  1580. IWbemClassObject* pMonitorObj = NULL;
  1581. hres = GetCurrentState(pMonitorObjTemplate, &pMonitorObj);
  1582. if(FAILED(hres))
  1583. return hres;
  1584. if(pMonitorObj == NULL)
  1585. {
  1586. //
  1587. // The monitor has been deleted --- no further action is needed
  1588. //
  1589. return S_OK;
  1590. }
  1591. CReleaseMe rm1(pMonitorObj);
  1592. // Now create it if necessary
  1593. // ==========================
  1594. hres = AddMonitor(pMonitorObj);
  1595. if(FAILED(hres))
  1596. return hres;
  1597. return hres;
  1598. }
  1599. //******************************************************************************
  1600. //
  1601. //
  1602. //******************************************************************************
  1603. HRESULT CEssNamespace::AddMonitor(IWbemClassObject* pMonitorObj)
  1604. {
  1605. HRESULT hres;
  1606. if(m_pMonitorProvider == NULL)
  1607. return WBEM_E_UNEXPECTED;
  1608. //
  1609. // Get the information from the monitor object
  1610. //
  1611. BSTR strKey, strQuery;
  1612. long lFlags;
  1613. hres = CMonitorProvider::GetMonitorInfo(pMonitorObj, &strKey,
  1614. &strQuery, &lFlags);
  1615. if(FAILED(hres))
  1616. {
  1617. ERRORTRACE((LOG_ESS, "A monitor was could not be cracked "
  1618. "in namespace '%S' as invalid: 0x%X\n", GetName(), hres));
  1619. return hres;
  1620. }
  1621. CSysFreeMe sfm1(strKey);
  1622. CSysFreeMe sfm2(strQuery);
  1623. //
  1624. // Attempt to add the monitor to the monitor provider
  1625. //
  1626. hres = m_pMonitorProvider->AddMonitor(strKey, strQuery,
  1627. lFlags, GetCurrentEssContext());
  1628. if(FAILED(hres))
  1629. {
  1630. ERRORTRACE((LOG_ESS, "Monitor '%S' at '%S' was rejected in "
  1631. "namespace '%S' with error code 0x%X\n",
  1632. strQuery, strKey, GetName()));
  1633. return hres;
  1634. }
  1635. return hres;
  1636. }
  1637. //******************************************************************************
  1638. //
  1639. // Starting with the namespace locked, RemoveMonitor updates the records
  1640. // to remove all mention of this monitor. Note: this is *not* the function to
  1641. // be
  1642. // called in response to the database instance-deletion event, as the monitor
  1643. // could have been recreated in the interim.
  1644. //
  1645. //******************************************************************************
  1646. HRESULT CEssNamespace::RemoveMonitor(IWbemClassObject* pMonitorObj)
  1647. {
  1648. HRESULT hres;
  1649. if(m_pMonitorProvider == NULL)
  1650. return WBEM_E_UNEXPECTED;
  1651. //
  1652. // Calculate the key form this monitor
  1653. //
  1654. BSTR strKey;
  1655. hres = CMonitorProvider::GetMonitorInfo(pMonitorObj, &strKey,
  1656. NULL, NULL);
  1657. if(FAILED(hres))
  1658. {
  1659. ERRORTRACE((LOG_ESS, "A monitor was could not be cracked "
  1660. "in namespace '%S' as invalid: 0x%X\n", GetName(), hres));
  1661. return hres;
  1662. }
  1663. CSysFreeMe sfm1(strKey);
  1664. //
  1665. // Remove it from the provider
  1666. //
  1667. hres = m_pMonitorProvider->RemoveMonitor(strKey, GetCurrentEssContext());
  1668. if(hres == WBEM_E_NOT_FOUND)
  1669. return S_FALSE;
  1670. return hres;
  1671. }
  1672. #endif
  1673. HRESULT CEssNamespace::SignalEvent( READ_ONLY CEventRepresentation& Event,
  1674. long lFlags )
  1675. {
  1676. HRESULT hres;
  1677. //
  1678. // we cannot hold any turns in an exec line or hold the namespace lock
  1679. // when calling this function. This is because this function will
  1680. // aquire the proxy lock.
  1681. //
  1682. CPostponedList* pList;
  1683. _DBG_ASSERT( !DoesThreadOwnNamespaceLock() );
  1684. _DBG_ASSERT( !(pList=GetCurrentPostponedList()) ||
  1685. !pList->IsHoldingTurns() );
  1686. // BUGBUG: need to propagate security context to this function ?
  1687. CWbemPtr<CCoreEventProvider> pCoreEventProvider;
  1688. {
  1689. //
  1690. // we need to figure out if we need to deffer the event or signal it.
  1691. // we deffer events when we are in the init pending or init state.
  1692. //
  1693. CInCritSec ics( &m_csLevel1 );
  1694. if ( m_eState == e_Initialized )
  1695. {
  1696. pCoreEventProvider = m_pCoreEventProvider;
  1697. }
  1698. else if ( m_eState == e_InitializePending )
  1699. {
  1700. //
  1701. // Copy and add to defferred list.
  1702. //
  1703. CEventRepresentation* pEvRep = Event.MakePermanentCopy();
  1704. if ( pEvRep == NULL )
  1705. {
  1706. return WBEM_E_OUT_OF_MEMORY;
  1707. }
  1708. if ( m_aDeferredEvents.Add( pEvRep ) < 0 )
  1709. {
  1710. delete pEvRep;
  1711. return WBEM_E_OUT_OF_MEMORY;
  1712. }
  1713. }
  1714. }
  1715. if ( pCoreEventProvider != NULL )
  1716. {
  1717. CEventContext Context;
  1718. hres = pCoreEventProvider->Fire( Event, &Context );
  1719. if(FAILED(hres))
  1720. {
  1721. return hres;
  1722. }
  1723. }
  1724. return WBEM_S_NO_ERROR;
  1725. }
  1726. //******************************************************************************
  1727. // public
  1728. //
  1729. // See ess.h for documentation
  1730. //
  1731. //******************************************************************************
  1732. HRESULT CEssNamespace::ProcessEvent(READ_ONLY CEventRepresentation& Event,
  1733. long lFlags)
  1734. {
  1735. // Ignore internal operations
  1736. // ==========================
  1737. if(Event.wsz2 != NULL &&
  1738. (!wbem_wcsicmp(Event.wsz2, L"__TimerNextFiring") ||
  1739. !wbem_wcsicmp(Event.wsz2, L"__ListOfEventActiveNamespaces")))
  1740. {
  1741. return WBEM_S_NO_ERROR;
  1742. }
  1743. HRESULT hres, hresReturn = WBEM_S_NO_ERROR;
  1744. // Analyze it for system changes
  1745. // =============================
  1746. hres = ActOnSystemEvent(Event, lFlags);
  1747. if(FAILED(hres))
  1748. {
  1749. //
  1750. // Check if this operation needs to be failed if invalid
  1751. //
  1752. if( lFlags & WBEM_FLAG_STRONG_VALIDATION )
  1753. {
  1754. hresReturn = hres;
  1755. }
  1756. else
  1757. {
  1758. ERRORTRACE((LOG_ESS, "Event subsystem was unable to perform the "
  1759. "necessary operations to accomodate a change to the system "
  1760. "state.\nThe state of the database may not reflect the state "
  1761. "of the event subsystem (%X)\n", hres));
  1762. }
  1763. }
  1764. // Fire postponed operations
  1765. // =========================
  1766. hres = FirePostponedOperations();
  1767. if(FAILED(hres))
  1768. {
  1769. ERRORTRACE((LOG_ESS,"Event subsystem was unable to perform the (post) "
  1770. "necessary operations to accomodate a change to the system state.\n"
  1771. "The state of the database may not reflect the state of the event "
  1772. "subsystem (%X)\n", hres));
  1773. }
  1774. // Deliver it to consumers
  1775. // =======================
  1776. hres = SignalEvent( Event, lFlags );
  1777. if(FAILED(hres))
  1778. {
  1779. ERRORTRACE((LOG_ESS, "Event subsystem was unable to deliver a "
  1780. "repository intrinsic event to some consumers (%X)\n", hres));
  1781. }
  1782. return hresReturn;
  1783. }
  1784. HRESULT CEssNamespace::ProcessQueryObjectSinkEvent( READ_ONLY CEventRepresentation& Event )
  1785. {
  1786. HRESULT hres = S_FALSE;
  1787. CRefedPointerArray< CEventFilter > apEventFilters;
  1788. if ( m_Bindings.GetEventFilters( apEventFilters ) )
  1789. {
  1790. if ( apEventFilters.GetSize( ) > 0 )
  1791. {
  1792. //
  1793. // Convert to real event
  1794. //
  1795. IWbemClassObject* pEvent;
  1796. HRESULT hr = Event.MakeWbemObject( this, &pEvent );
  1797. if( FAILED( hr ) )
  1798. {
  1799. return hr;
  1800. }
  1801. CReleaseMe rm1( pEvent );
  1802. //
  1803. // Fire all matching filters
  1804. //
  1805. for( int i = 0; i < apEventFilters.GetSize( ); ++i )
  1806. {
  1807. CEventContext Context;
  1808. CEventFilter* pEventFilter = apEventFilters[i];
  1809. hr = pEventFilter->Indicate( 1, &pEvent, &Context );
  1810. if ( FAILED( hr ) )
  1811. {
  1812. return hr;
  1813. }
  1814. //
  1815. // Return S_FALSE if all of the Indicates returns S_FALSE
  1816. //
  1817. if ( S_FALSE != hr )
  1818. {
  1819. hres = S_OK;
  1820. }
  1821. }
  1822. }
  1823. }
  1824. else
  1825. {
  1826. return E_FAIL;
  1827. }
  1828. return hres;
  1829. }
  1830. HRESULT CEssNamespace::RegisterNotificationSink( WBEM_CWSTR wszQueryLanguage,
  1831. WBEM_CWSTR wszQuery,
  1832. long lFlags,
  1833. WMIMSG_QOS_FLAG lQosFlags,
  1834. IWbemContext* pContext,
  1835. IWbemObjectSink* pSink )
  1836. {
  1837. HRESULT hres;
  1838. //
  1839. // Report the MSFT_WmiRegisterNotificationSink event.
  1840. //
  1841. FIRE_NCEVENT( g_hNCEvents[MSFT_WmiRegisterNotificationSink],
  1842. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  1843. // Data follows...
  1844. (LPCWSTR) m_wszName,
  1845. wszQueryLanguage,
  1846. wszQuery,
  1847. (DWORD64) pSink);
  1848. DEBUGTRACE((LOG_ESS,"Registering notification sink with query %S in "
  1849. "namespace %S.\n", wszQuery, m_wszName ));
  1850. {
  1851. ENSURE_INITIALIZED
  1852. hres = InternalRegisterNotificationSink( wszQueryLanguage,
  1853. wszQuery,
  1854. lFlags,
  1855. lQosFlags,
  1856. pContext,
  1857. pSink,
  1858. FALSE,
  1859. NULL );
  1860. }
  1861. if(FAILED(hres))
  1862. {
  1863. // Clean up and return
  1864. FirePostponedOperations();
  1865. return hres;
  1866. }
  1867. // Filter and consumer are in place --- fire external operations
  1868. // =============================================================
  1869. hres = FirePostponedOperations();
  1870. if(FAILED(hres))
  1871. {
  1872. {
  1873. CInUpdate iu(this);
  1874. InternalRemoveNotificationSink( pSink );
  1875. }
  1876. //
  1877. // need to make sure that we fire postponed here too. Remember that
  1878. // we cannot hold the namespace lock when firing postponed ops.
  1879. //
  1880. FirePostponedOperations();
  1881. }
  1882. else
  1883. {
  1884. InterlockedIncrement(&g_lNumTempSubscriptions);
  1885. }
  1886. return hres;
  1887. }
  1888. HRESULT CEssNamespace::InternalRegisterNotificationSink(
  1889. WBEM_CWSTR wszQueryLanguage,
  1890. WBEM_CWSTR wszQuery,
  1891. long lFlags,
  1892. WMIMSG_QOS_FLAG lQosFlags,
  1893. IWbemContext* pContext,
  1894. IWbemObjectSink* pSink,
  1895. bool bInternal,
  1896. PSID pOwnerSid )
  1897. {
  1898. HRESULT hres;
  1899. if(wbem_wcsicmp(wszQueryLanguage, L"WQL"))
  1900. return WBEM_E_INVALID_QUERY_TYPE;
  1901. LPWSTR wszConsumerKey = NULL;
  1902. CVectorDeleteMe<WCHAR> vdm2(&wszConsumerKey);
  1903. wszConsumerKey = CTempConsumer::ComputeKeyFromSink(pSink);
  1904. if ( NULL == wszConsumerKey )
  1905. {
  1906. return WBEM_E_OUT_OF_MEMORY;
  1907. }
  1908. bool bInterNamespace = pOwnerSid != NULL;
  1909. #ifdef __WHISTLER_UNCUT
  1910. //
  1911. // Check if this is a monitoring request
  1912. //
  1913. if(lFlags & WBEM_FLAG_MONITOR)
  1914. {
  1915. if(m_pMonitorProvider == NULL)
  1916. return WBEM_E_NOT_SUPPORTED;
  1917. //
  1918. // Issue a subscription for anything eminating from the monitor we are
  1919. // about to create. We are going to use the consumer key as the key
  1920. // for the monitor --- this means that ONE CANNOT issue more than one
  1921. // monitor against the same sink!
  1922. //
  1923. WCHAR* wszNewQuery = new WCHAR[wcslen(wszConsumerKey) + 200];
  1924. if ( wszNewQuery == NULL )
  1925. {
  1926. return WBEM_E_OUT_MEMORY;
  1927. }
  1928. CVectorDeleteMe<WCHAR> vdm1(wszNewQuery);
  1929. swprintf(wszNewQuery, L"select * from "MONITOR_BASE_EVENT_CLASS
  1930. L" where "MONITORNAME_EVENT_PROPNAME L" = \"%s\"",
  1931. wszConsumerKey);
  1932. hres = InternalRegisterNotificationSink(L"WQL", wszNewQuery,
  1933. lFlags & ~WBEM_FLAG_MONITOR, lQosFlags, pContext, pSink, NULL);
  1934. if(FAILED(hres))
  1935. return hres;
  1936. //
  1937. // Construct the new monitor
  1938. //
  1939. hres = m_pMonitorProvider->AddMonitor(wszConsumerKey, wszQuery,
  1940. lFlags, pContext);
  1941. if(FAILED(hres))
  1942. return hres;
  1943. return WBEM_S_NO_ERROR;
  1944. }
  1945. //
  1946. // Normal subscription
  1947. //
  1948. #endif
  1949. LPWSTR wszFilterKey = NULL;
  1950. CVectorDeleteMe<WCHAR> vdm1(&wszFilterKey);
  1951. {
  1952. // Create a new temporary filter and add it to the binding table
  1953. // =============================================================
  1954. CTempFilter* pFilter = new CTempFilter(this);
  1955. if(pFilter == NULL)
  1956. return WBEM_E_OUT_OF_MEMORY;
  1957. hres = pFilter->Initialize( wszQueryLanguage,
  1958. wszQuery,
  1959. lFlags,
  1960. pOwnerSid,
  1961. bInternal,
  1962. pContext,
  1963. pSink );
  1964. if(FAILED(hres))
  1965. {
  1966. delete pFilter;
  1967. return hres;
  1968. }
  1969. hres = m_Bindings.AddEventFilter(pFilter);
  1970. if(FAILED(hres))
  1971. {
  1972. delete pFilter;
  1973. return hres;
  1974. }
  1975. wszFilterKey = pFilter->GetKey().CreateLPWSTRCopy();
  1976. if(wszFilterKey == NULL)
  1977. return WBEM_E_OUT_OF_MEMORY;
  1978. // Check if this sink has already been used by looking for it in the
  1979. // binding table
  1980. // =================================================================
  1981. CTempConsumer* pConsumer = NULL;
  1982. if(FAILED(m_Bindings.FindEventConsumer(wszConsumerKey, NULL)))
  1983. {
  1984. // Create a new temporary consumer and add it to the table
  1985. // =======================================================
  1986. pConsumer = _new CTempConsumer(this);
  1987. if(pConsumer == NULL)
  1988. return WBEM_E_OUT_OF_MEMORY;
  1989. hres = pConsumer->Initialize( bInterNamespace, pSink);
  1990. if(FAILED(hres))
  1991. return hres;
  1992. hres = m_Bindings.AddEventConsumer(pConsumer);
  1993. if(FAILED(hres))
  1994. {
  1995. // Undo filter creation
  1996. // ====================
  1997. m_Bindings.RemoveEventFilter(wszFilterKey);
  1998. return hres;
  1999. }
  2000. }
  2001. // Bind them together
  2002. // ==================
  2003. CBinding* pBinding = new CTempBinding( lFlags,
  2004. lQosFlags,
  2005. bInterNamespace );
  2006. if(pBinding == NULL)
  2007. return WBEM_E_OUT_OF_MEMORY;
  2008. pBinding->AddRef();
  2009. CReleaseMe rm1(pBinding);
  2010. //
  2011. // SPAGETTI WARNING: From this point on, we must flush the postponed
  2012. // operation cache, or we may leak memory. But not before all the
  2013. // CReleaseMe calls have fired.
  2014. //
  2015. hres = m_Bindings.Bind(wszFilterKey, wszConsumerKey, pBinding, NULL);
  2016. // Check that the filter is active --- otherwise activatioin must have
  2017. // failed.
  2018. // ===================================================================
  2019. if(SUCCEEDED(hres) && !pFilter->IsActive())
  2020. hres = pFilter->GetFilterError();
  2021. if(FAILED(hres))
  2022. {
  2023. //
  2024. // The core will deliver the SetStatus call to the consumer based
  2025. // on the return code from the ESS. Since we are failing, we should
  2026. // not call SetStatus ourselves.
  2027. //
  2028. if(pConsumer)
  2029. pConsumer->Shutdown(true); // quiet
  2030. m_Bindings.RemoveEventFilter(wszFilterKey);
  2031. m_Bindings.RemoveEventConsumer(wszConsumerKey);
  2032. }
  2033. else
  2034. {
  2035. InterlockedIncrement(&g_lNumInternalTempSubscriptions);
  2036. }
  2037. }
  2038. return hres;
  2039. }
  2040. HRESULT CEssNamespace::RemoveNotificationSink( IWbemObjectSink* pSink )
  2041. {
  2042. // Fire a MSFT_WmiCancelNotificationSink if necessary.
  2043. if (IS_NCEVENT_ACTIVE(MSFT_WmiCancelNotificationSink))
  2044. {
  2045. LPWSTR wszConsumerKey = CTempConsumer::ComputeKeyFromSink(pSink);
  2046. if (wszConsumerKey != NULL)
  2047. {
  2048. CVectorDeleteMe<WCHAR> vdm0(wszConsumerKey);
  2049. CInUpdate iu(this);
  2050. // Find the consumer in question
  2051. CEventConsumer *pConsumer = NULL;
  2052. if (SUCCEEDED(m_Bindings.FindEventConsumer(wszConsumerKey, &pConsumer)))
  2053. {
  2054. CRefedPointerSmallArray<CEventFilter>
  2055. apFilters;
  2056. CReleaseMe rm1(pConsumer);
  2057. // Make addrefed copies of all its associated filters
  2058. if (SUCCEEDED(pConsumer->GetAssociatedFilters(apFilters))
  2059. && apFilters.GetSize())
  2060. {
  2061. int nFilters = apFilters.GetSize();
  2062. LPWSTR wszQuery = NULL,
  2063. wszQueryLanguage = NULL;
  2064. BOOL bExact;
  2065. apFilters[0]->
  2066. GetCoveringQuery(wszQueryLanguage, wszQuery, bExact, NULL);
  2067. CVectorDeleteMe<WCHAR> vdm1(wszQueryLanguage);
  2068. CVectorDeleteMe<WCHAR> vdm2(wszQuery);
  2069. //
  2070. // Report the MSFT_WmiRegisterNotificationSink event.
  2071. //
  2072. FIRE_NCEVENT(
  2073. g_hNCEvents[MSFT_WmiCancelNotificationSink],
  2074. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  2075. // Data follows...
  2076. (LPCWSTR) m_wszName,
  2077. wszQueryLanguage,
  2078. wszQuery,
  2079. (DWORD64) pSink);
  2080. }
  2081. }
  2082. }
  2083. }
  2084. HRESULT hres;
  2085. {
  2086. CInUpdate iu( this );
  2087. hres = InternalRemoveNotificationSink( pSink );
  2088. }
  2089. FirePostponedOperations();
  2090. if ( SUCCEEDED(hres) )
  2091. {
  2092. InterlockedDecrement( &g_lNumTempSubscriptions );
  2093. }
  2094. return hres;
  2095. }
  2096. HRESULT CEssNamespace::InternalRemoveNotificationSink(IWbemObjectSink* pSink)
  2097. {
  2098. HRESULT hres;
  2099. LPWSTR wszKey = CTempConsumer::ComputeKeyFromSink(pSink);
  2100. if(wszKey == NULL)
  2101. return WBEM_E_OUT_OF_MEMORY;
  2102. CVectorDeleteMe<WCHAR> vdm1(wszKey);
  2103. #ifdef __WHISTLER_UNCUT
  2104. //
  2105. // Remove any monitors that may be associated with it
  2106. //
  2107. if(m_pMonitorProvider)
  2108. m_pMonitorProvider->RemoveMonitor(wszKey, GetCurrentEssContext());
  2109. #endif
  2110. // Find the consumer container
  2111. // ===========================
  2112. hres = m_Bindings.RemoveConsumerWithFilters(wszKey);
  2113. if(FAILED(hres))
  2114. return hres;
  2115. else
  2116. InterlockedDecrement( &g_lNumInternalTempSubscriptions );
  2117. return hres;
  2118. }
  2119. void CEssNamespace::FireNCFilterEvent(DWORD dwIndex, CEventFilter *pFilter)
  2120. {
  2121. if (IS_NCEVENT_ACTIVE(dwIndex))
  2122. {
  2123. LPWSTR wszQuery = NULL;
  2124. LPWSTR wszQueryLanguage = NULL;
  2125. BOOL bExact;
  2126. CWbemPtr<CEssNamespace> pNamespace;
  2127. GetFilterEventNamespace(pFilter, &pNamespace);
  2128. // I'll assume we should use the current namespace if it's null.
  2129. if (!pNamespace)
  2130. pNamespace = this;
  2131. pFilter->GetCoveringQuery(wszQueryLanguage, wszQuery, bExact, NULL);
  2132. CVectorDeleteMe<WCHAR> vdm1(wszQueryLanguage);
  2133. CVectorDeleteMe<WCHAR> vdm2(wszQuery);
  2134. //
  2135. // Report the event.
  2136. //
  2137. FIRE_NCEVENT(
  2138. g_hNCEvents[dwIndex],
  2139. WMI_SENDCOMMIT_SET_NOT_REQUIRED,
  2140. // Data follows...
  2141. pNamespace ? (LPCWSTR) pNamespace->GetName() : NULL,
  2142. (LPCWSTR) (WString) pFilter->GetKey(),
  2143. wszQueryLanguage,
  2144. wszQuery);
  2145. }
  2146. }
  2147. //*****************************************************************************
  2148. //
  2149. // Called by the filter when it notices that it has consumers. The filter is
  2150. // guaranteed to be either valid or temporarily invalid and not active. It is
  2151. // guaranteed that no more than 1 activation/deactivation can occur on the
  2152. // same filter at the same time.
  2153. //
  2154. //*****************************************************************************
  2155. HRESULT CEssNamespace::ActivateFilter(READ_ONLY CEventFilter* pFilter)
  2156. {
  2157. HRESULT hres, hresAttempt;
  2158. hresAttempt = AttemptToActivateFilter(pFilter);
  2159. if(FAILED(hresAttempt))
  2160. {
  2161. pFilter->MarkAsTemporarilyInvalid(hresAttempt);
  2162. //
  2163. // We need to log an event about our inability to activate the filter
  2164. // unless we shall report this failure to the caller. We can only
  2165. // report this to the caller if the filter is being created (not
  2166. // reactivated), and the caller is not using a force-mode
  2167. //
  2168. if(pFilter->DoesAllowInvalid() || pFilter->HasBeenValid())
  2169. {
  2170. LPWSTR wszQuery = NULL;
  2171. LPWSTR wszQueryLanguage = NULL;
  2172. BOOL bExact;
  2173. hres = pFilter->GetCoveringQuery( wszQueryLanguage,
  2174. wszQuery,
  2175. bExact,
  2176. NULL);
  2177. if(FAILED(hres))
  2178. return hres;
  2179. CVectorDeleteMe<WCHAR> vdm1(wszQueryLanguage);
  2180. CVectorDeleteMe<WCHAR> vdm2(wszQuery);
  2181. //
  2182. // Don't change this one: could be Nova customer dependencies
  2183. //
  2184. m_pEss->GetEventLog().Report( EVENTLOG_ERROR_TYPE,
  2185. WBEM_MC_CANNOT_ACTIVATE_FILTER,
  2186. m_wszName,
  2187. wszQuery,
  2188. (CHex)hresAttempt );
  2189. ERRORTRACE((LOG_ESS, "Could not activate filter %S in namespace "
  2190. "%S. HR=0x%x\n", wszQuery, m_wszName, hresAttempt ));
  2191. }
  2192. }
  2193. else
  2194. {
  2195. //
  2196. // Report the MSFT_WmiFilterActivated event.
  2197. //
  2198. FireNCFilterEvent(MSFT_WmiFilterActivated, pFilter);
  2199. pFilter->MarkAsValid();
  2200. }
  2201. return hresAttempt;
  2202. }
  2203. //******************************************************************************
  2204. //
  2205. // Worker for ActivateFilter --- does all the work but does not mark the filter
  2206. // status
  2207. //
  2208. //******************************************************************************
  2209. HRESULT CEssNamespace::AttemptToActivateFilter(READ_ONLY CEventFilter* pFilter)
  2210. {
  2211. HRESULT hres = WBEM_S_NO_ERROR;
  2212. //
  2213. // Get the query information from the filter
  2214. //
  2215. LPWSTR wszQueryLanguage = NULL;
  2216. LPWSTR wszQuery = NULL;
  2217. BOOL bExact;
  2218. QL_LEVEL_1_RPN_EXPRESSION* pExp = NULL;
  2219. hres = pFilter->GetCoveringQuery(wszQueryLanguage, wszQuery, bExact, &pExp);
  2220. if(FAILED(hres))
  2221. {
  2222. WMIESS_REPORT((WMIESS_CANNOT_GET_FILTER_QUERY, m_wszName, pFilter));
  2223. return hres;
  2224. }
  2225. CVectorDeleteMe<WCHAR> vdm1(wszQueryLanguage);
  2226. CVectorDeleteMe<WCHAR> vdm2(wszQuery);
  2227. CDeleteMe<QL_LEVEL_1_RPN_EXPRESSION> dm1(pExp);
  2228. if(!bExact)
  2229. {
  2230. //
  2231. // We don't support inexact filter, nor do we have any now
  2232. //
  2233. return WBEM_E_NOT_SUPPORTED;
  2234. }
  2235. //
  2236. // Check if the events are supposed to come from this namespace or some
  2237. // other one. Cross-namespace filters are all we are interested in the
  2238. // initialize phase, since we're going to reprocess normal filters
  2239. // after loading provider registrations ( In CompleteInitialization() )
  2240. //
  2241. CEssNamespace* pOtherNamespace = NULL;
  2242. hres = GetFilterEventNamespace(pFilter, &pOtherNamespace);
  2243. if(FAILED(hres))
  2244. return hres;
  2245. if( pOtherNamespace )
  2246. {
  2247. CTemplateReleaseMe<CEssNamespace> rm0(pOtherNamespace);
  2248. if ( m_bInResync )
  2249. {
  2250. //
  2251. // we don't need to do anything in the other namespace during
  2252. // resync of this one, so no work to do here. Actually, since
  2253. // resync doesn't do a deactivate, the registration is still there
  2254. // so be careful of double registration if removing this check.
  2255. //
  2256. return WBEM_S_FALSE;
  2257. }
  2258. DEBUGTRACE((LOG_ESS,"Activating cross-namespace filter %p with query "
  2259. "%S in namespace %S from namespace %S.\n", pFilter,
  2260. wszQuery, pOtherNamespace->GetName(), m_wszName ));
  2261. //
  2262. // Register this notification sink with the other namespace, as
  2263. // if it were a temporary consumer. Make the registration
  2264. // synchronous, as whatever asynchronicity we need will be
  2265. // provided by the ultimate consumer handling. This needs to be a
  2266. // postponed operation though, else we could have a deadlock
  2267. // scenario if at the same time cross namespace subscriptions
  2268. // were registered in both namespaces.
  2269. //
  2270. //
  2271. // BUGBUG: security propagation
  2272. //
  2273. CPostponedRegisterNotificationSinkRequest* pReq;
  2274. pReq = new CPostponedRegisterNotificationSinkRequest;
  2275. if ( pReq == NULL )
  2276. {
  2277. return WBEM_E_OUT_OF_MEMORY;
  2278. }
  2279. hres = pReq->SetRegistration( pOtherNamespace,
  2280. wszQueryLanguage,
  2281. wszQuery,
  2282. pFilter->GetForceFlags(),
  2283. WMIMSG_FLAG_QOS_SYNCHRONOUS,
  2284. pFilter->GetNonFilteringSink(),
  2285. pFilter->GetOwner() );
  2286. if(FAILED(hres))
  2287. {
  2288. return hres;
  2289. }
  2290. CPostponedList* pList = GetCurrentPostponedList();
  2291. _DBG_ASSERT( pList != NULL );
  2292. hres = pList->AddRequest( this, pReq );
  2293. if ( FAILED(hres) )
  2294. {
  2295. return hres;
  2296. }
  2297. return WBEM_S_NO_ERROR;
  2298. }
  2299. else if ( m_eState == e_Initialized || m_bInResync )
  2300. {
  2301. //
  2302. // Filter is being activated in this namespace. We must avoid
  2303. // processing filters before we're fully initialized. This can
  2304. // happen when one namespace is initializing its cross namespace
  2305. // subscription to one that is still initializing. We do not process
  2306. // filters before we're initialized because (1) we are not allowed to
  2307. // access class providers during stage1 init and (2) we're going to
  2308. // resync everything anyways during stage2 init.
  2309. //
  2310. DEBUGTRACE((LOG_ESS,"Activating filter %p with query %S "
  2311. "in namespace %S.\n", pFilter, wszQuery, m_wszName ));
  2312. // Retrieve its non-filtering sink
  2313. // ===============================
  2314. CAbstractEventSink* pNonFilter = pFilter->GetNonFilteringSink();
  2315. if(pNonFilter == NULL)
  2316. return WBEM_E_OUT_OF_MEMORY;
  2317. //
  2318. // Register for class modification events of relevance for this filter
  2319. //
  2320. hres = RegisterFilterForAllClassChanges(pFilter, pExp);
  2321. if(FAILED(hres))
  2322. {
  2323. ERRORTRACE((LOG_ESS,"Unable to register for class changes related "
  2324. "to filter %S in namespace %S: 0x%x\n", wszQuery, GetName(),
  2325. hres));
  2326. return hres;
  2327. }
  2328. //
  2329. // Prepare filter for action
  2330. //
  2331. hres = pFilter->GetReady(wszQuery, pExp);
  2332. if( SUCCEEDED(hres) )
  2333. {
  2334. //
  2335. // Register it in the core tables
  2336. //
  2337. hres = m_EventProviderCache.LoadProvidersForQuery(wszQuery,
  2338. pExp, pNonFilter);
  2339. if(SUCCEEDED(hres))
  2340. {
  2341. hres = m_Poller.ActivateFilter(pFilter, wszQuery, pExp);
  2342. if(FAILED(hres))
  2343. {
  2344. // Need to deactivate providers
  2345. // ============================
  2346. m_EventProviderCache.ReleaseProvidersForQuery(
  2347. pNonFilter);
  2348. }
  2349. }
  2350. }
  2351. }
  2352. if(FAILED(hres))
  2353. {
  2354. //
  2355. // Keep this filter registered for its class change events, as one of
  2356. // them could make it valid!
  2357. //
  2358. }
  2359. return hres;
  2360. }
  2361. //*****************************************************************************
  2362. //
  2363. // Retrieves the namespace pointer for the event namespace for this filter.
  2364. // If current, returns NULL.
  2365. //
  2366. //*****************************************************************************
  2367. HRESULT CEssNamespace::GetFilterEventNamespace(CEventFilter* pFilter,
  2368. RELEASE_ME CEssNamespace** ppNamespace)
  2369. {
  2370. HRESULT hres;
  2371. *ppNamespace = NULL;
  2372. LPWSTR wszNamespace = NULL;
  2373. hres = pFilter->GetEventNamespace(&wszNamespace);
  2374. if(FAILED(hres))
  2375. {
  2376. WMIESS_REPORT((WMIESS_INVALID_FILTER_NAMESPACE, m_wszName, pFilter,
  2377. wszNamespace));
  2378. return hres;
  2379. }
  2380. CVectorDeleteMe<WCHAR> vdm0(wszNamespace);
  2381. if(wszNamespace && wbem_wcsicmp(wszNamespace, m_wszName))
  2382. {
  2383. //
  2384. // Different namespace: Find it in the list.
  2385. //
  2386. hres = m_pEss->GetNamespaceObject( wszNamespace, TRUE, ppNamespace );
  2387. if(FAILED(hres))
  2388. {
  2389. WMIESS_REPORT((WMIESS_CANNOT_OPEN_FILTER_NAMESPACE, m_wszName,
  2390. pFilter, wszNamespace));
  2391. return hres;
  2392. }
  2393. //
  2394. // Check if we got back our current namespace --- could happen if the
  2395. // spelling is different, etc
  2396. //
  2397. if(*ppNamespace == this)
  2398. {
  2399. (*ppNamespace)->Release();
  2400. *ppNamespace = NULL;
  2401. }
  2402. return S_OK;
  2403. }
  2404. else
  2405. {
  2406. // Same namespace
  2407. *ppNamespace = NULL;
  2408. return S_OK;
  2409. }
  2410. }
  2411. HRESULT CEssNamespace::RegisterFilterForAllClassChanges(CEventFilter* pFilter,
  2412. QL_LEVEL_1_RPN_EXPRESSION* pExpr)
  2413. {
  2414. HRESULT hres;
  2415. //
  2416. // Do nothing for class operation filters. They simply serve as their own
  2417. // "class change" filters
  2418. //
  2419. if(!wbem_wcsicmp(pExpr->bsClassName, L"__ClassOperationEvent") ||
  2420. !wbem_wcsicmp(pExpr->bsClassName, L"__ClassCreationEvent") ||
  2421. !wbem_wcsicmp(pExpr->bsClassName, L"__ClassDeletionEvent") ||
  2422. !wbem_wcsicmp(pExpr->bsClassName, L"__ClassModificationEvent"))
  2423. {
  2424. pFilter->MarkReconstructOnHit();
  2425. return WBEM_S_NO_ERROR;
  2426. }
  2427. //
  2428. // get the sink for class change notifications.
  2429. //
  2430. IWbemObjectSink* pClassChangeSink = pFilter->GetClassChangeSink(); // NOREF
  2431. _DBG_ASSERT( pClassChangeSink != NULL );
  2432. //
  2433. // since the class change sink will be modifying internal namespace
  2434. // structures, we must wrap with an internal operations sink. This is so
  2435. // the thread that performs the indicate will be guaranteed to have a
  2436. // valid thread object associated with it.
  2437. //
  2438. CWbemPtr<CEssInternalOperationSink> pInternalOpSink;
  2439. pInternalOpSink = new CEssInternalOperationSink( pClassChangeSink );
  2440. if ( pInternalOpSink == NULL )
  2441. {
  2442. return WBEM_E_OUT_OF_MEMORY;
  2443. }
  2444. //
  2445. // store the new sink with the filter because we need it later to unreg
  2446. //
  2447. CWbemPtr<IWbemObjectSink> pOldInternalOpSink;
  2448. hres = pFilter->SetActualClassChangeSink( pInternalOpSink,
  2449. &pOldInternalOpSink );
  2450. if ( FAILED(hres) )
  2451. {
  2452. return hres;
  2453. }
  2454. _DBG_ASSERT( pOldInternalOpSink == NULL );
  2455. return RegisterSinkForAllClassChanges( pInternalOpSink, pExpr );
  2456. }
  2457. HRESULT CEssNamespace::RegisterSinkForAllClassChanges(IWbemObjectSink* pSink,
  2458. QL_LEVEL_1_RPN_EXPRESSION* pExpr)
  2459. {
  2460. HRESULT hres;
  2461. //
  2462. // First of all, the class we are looking for is of interest
  2463. //
  2464. hres = RegisterSinkForClassChanges(pSink, pExpr->bsClassName);
  2465. if(FAILED(hres))
  2466. return hres;
  2467. //
  2468. // Now, iterate over all the tokens looking for ISAs. We need those classes
  2469. // too.
  2470. //
  2471. for(int i = 0; i < pExpr->nNumTokens; i++)
  2472. {
  2473. QL_LEVEL_1_TOKEN* pToken = pExpr->pArrayOfTokens + i;
  2474. if(pToken->nTokenType == QL1_OP_EXPRESSION &&
  2475. (pToken->nOperator == QL1_OPERATOR_ISA ||
  2476. pToken->nOperator == QL1_OPERATOR_ISNOTA) &&
  2477. V_VT(&pToken->vConstValue) == VT_BSTR)
  2478. {
  2479. hres = RegisterSinkForClassChanges(pSink,
  2480. V_BSTR(&pToken->vConstValue));
  2481. if(FAILED(hres))
  2482. {
  2483. UnregisterSinkFromAllClassChanges(pSink);
  2484. return hres;
  2485. }
  2486. }
  2487. }
  2488. // Somehow need to keep this filter subscribed to various events until all
  2489. // the classes show up
  2490. return WBEM_S_NO_ERROR;
  2491. }
  2492. HRESULT CEssNamespace::RegisterSinkForClassChanges(IWbemObjectSink* pSink,
  2493. LPCWSTR wszClassName)
  2494. {
  2495. //
  2496. // Do not register for changes to system classes --- they do not change!
  2497. //
  2498. if(wszClassName[0] == L'_')
  2499. {
  2500. return WBEM_S_NO_ERROR;
  2501. }
  2502. //
  2503. // Just issue the appropriate query against the namespace. The filter
  2504. // will know what to do when called
  2505. //
  2506. LPWSTR wszQuery = new WCHAR[wcslen(wszClassName) + 100];
  2507. if ( wszQuery == NULL )
  2508. {
  2509. return WBEM_E_OUT_OF_MEMORY;
  2510. }
  2511. swprintf(wszQuery, L"select * from __ClassOperationEvent where "
  2512. L"TargetClass isa \"%s\"", wszClassName);
  2513. CVectorDeleteMe<WCHAR> vdm( wszQuery );
  2514. return InternalRegisterNotificationSink(L"WQL",
  2515. wszQuery, 0, WMIMSG_FLAG_QOS_SYNCHRONOUS,
  2516. GetCurrentEssContext(), pSink, true, NULL );
  2517. }
  2518. HRESULT CEssNamespace::RegisterProviderForClassChanges( LPCWSTR wszClassName,
  2519. LPCWSTR wszProvName )
  2520. {
  2521. try
  2522. {
  2523. CInCritSec ics(&m_csLevel1);
  2524. m_mapProviderInterestClasses[wszClassName].insert( wszProvName );
  2525. }
  2526. catch(CX_MemoryException)
  2527. {
  2528. return WBEM_E_OUT_OF_MEMORY;
  2529. }
  2530. return S_OK;
  2531. }
  2532. HRESULT CEssNamespace::UnregisterFilterFromAllClassChanges(
  2533. CEventFilter* pFilter)
  2534. {
  2535. HRESULT hres;
  2536. //
  2537. // unbind the filter from the actual class change sink and use it to unreg
  2538. //
  2539. CWbemPtr<IWbemObjectSink> pActualClassChangeSink;
  2540. hres = pFilter->SetActualClassChangeSink( NULL, &pActualClassChangeSink );
  2541. if ( FAILED(hres) )
  2542. {
  2543. return hres;
  2544. }
  2545. if ( pActualClassChangeSink != NULL )
  2546. {
  2547. hres = UnregisterSinkFromAllClassChanges( pActualClassChangeSink );
  2548. }
  2549. return hres;
  2550. }
  2551. HRESULT CEssNamespace::UnregisterSinkFromAllClassChanges(
  2552. IWbemObjectSink* pSink)
  2553. {
  2554. return InternalRemoveNotificationSink(pSink);
  2555. }
  2556. HRESULT CEssNamespace::DeactivateFilter( READ_ONLY CEventFilter* pFilter )
  2557. {
  2558. HRESULT hres;
  2559. DEBUGTRACE((LOG_ESS,"Deactivating filter %p\n", pFilter ));
  2560. HRESULT hresGlobal = WBEM_S_NO_ERROR;
  2561. //
  2562. // Check if the events are supposed to come from this namespace or some
  2563. // other one.
  2564. //
  2565. CEssNamespace* pOtherNamespace = NULL;
  2566. hres = GetFilterEventNamespace(pFilter, &pOtherNamespace);
  2567. if(FAILED(hres))
  2568. return hres;
  2569. if( pOtherNamespace )
  2570. {
  2571. CTemplateReleaseMe<CEssNamespace> rm0(pOtherNamespace);
  2572. //
  2573. // Unregister this notification sink with the other namespace,
  2574. // as if it were a temporary consumer. This needs to be a
  2575. // postponed operation though, else we could have a deadlock
  2576. // scenario if at the same time cross namespace subscriptions
  2577. // were registered in both namespaces.
  2578. //
  2579. CPostponedRemoveNotificationSinkRequest* pReq;
  2580. pReq = new CPostponedRemoveNotificationSinkRequest(
  2581. pOtherNamespace,
  2582. pFilter->GetNonFilteringSink() );
  2583. if ( pReq == NULL )
  2584. {
  2585. return WBEM_E_OUT_OF_MEMORY;
  2586. }
  2587. CPostponedList* pList = GetCurrentPostponedList();
  2588. _DBG_ASSERT( pList != NULL );
  2589. hres = pList->AddRequest( this, pReq );
  2590. if ( FAILED(hres) )
  2591. {
  2592. delete pReq;
  2593. return hres;
  2594. }
  2595. return WBEM_S_NO_ERROR;
  2596. }
  2597. else
  2598. {
  2599. //
  2600. // Current namespace --- unregister for real
  2601. //
  2602. // Retrieve its non-filtering sink
  2603. // ===============================
  2604. CAbstractEventSink* pNonFilter = pFilter->GetNonFilteringSink();
  2605. if(pNonFilter == NULL)
  2606. return WBEM_E_OUT_OF_MEMORY;
  2607. //
  2608. // Report the MSFT_WmiFilterDeactivated event.
  2609. //
  2610. FireNCFilterEvent(MSFT_WmiFilterDeactivated, pFilter);
  2611. //
  2612. // Unregister it from class change notifications
  2613. //
  2614. hres = UnregisterFilterFromAllClassChanges(pFilter);
  2615. if(FAILED(hres))
  2616. hresGlobal = hres;
  2617. // Deactivate in providers, poller, and static search
  2618. // ==================================================
  2619. hres = m_EventProviderCache.ReleaseProvidersForQuery(pNonFilter);
  2620. if(FAILED(hres))
  2621. hresGlobal = hres;
  2622. hres = m_Poller.DeactivateFilter(pFilter);
  2623. if(FAILED(hres))
  2624. hresGlobal = hres;
  2625. pFilter->SetInactive();
  2626. return hres;
  2627. }
  2628. }
  2629. HRESULT CEssNamespace::HandleClassCreation( LPCWSTR wszClassName,
  2630. IWbemClassObject* pClass)
  2631. {
  2632. //
  2633. // Check if this is a class that a provider is waiting for.
  2634. //
  2635. ProviderSet setProviders;
  2636. {
  2637. CInCritSec ics( &m_csLevel1 );
  2638. ClassToProviderMap::iterator it;
  2639. it = m_mapProviderInterestClasses.find( wszClassName );
  2640. if ( it != m_mapProviderInterestClasses.end() )
  2641. {
  2642. //
  2643. // copy the interested provider list.
  2644. //
  2645. setProviders = it->second;
  2646. //
  2647. // remove the entry from the map.
  2648. //
  2649. m_mapProviderInterestClasses.erase( it );
  2650. }
  2651. }
  2652. if ( setProviders.size() > 0 )
  2653. {
  2654. //
  2655. // reload interested providers.
  2656. //
  2657. DEBUGTRACE((LOG_ESS,"Reloading some providers in namespace %S due to "
  2658. "creation of %S class\n", m_wszName, wszClassName ));
  2659. ProviderSet::iterator itProv;
  2660. for( itProv=setProviders.begin(); itProv!=setProviders.end(); itProv++)
  2661. {
  2662. ReloadProvider( 0, *itProv );
  2663. }
  2664. }
  2665. return S_OK;
  2666. }
  2667. //*****************************************************************************
  2668. //
  2669. // Updates internal structures to reflect a change to this class. Assumes that
  2670. // the namespace is already locked.
  2671. // Very few errors are reported from this function, since class changes cannot
  2672. // be vetoed.
  2673. //
  2674. //*****************************************************************************
  2675. HRESULT CEssNamespace::HandleClassChange(LPCWSTR wszClassName,
  2676. IWbemClassObject* pClass)
  2677. {
  2678. // Check if the class in question is an event consumer class
  2679. // =========================================================
  2680. if(pClass->InheritsFrom(CONSUMER_CLASS) == S_OK)
  2681. {
  2682. CInUpdate iu(this);
  2683. HandleConsumerClassDeletion(wszClassName);
  2684. }
  2685. return WBEM_S_NO_ERROR;
  2686. }
  2687. HRESULT CEssNamespace::HandleConsumerClassDeletion(LPCWSTR wszClassName)
  2688. {
  2689. // There are two varieties: non-singleton and singleton
  2690. // ====================================================
  2691. LPWSTR wszPrefix = new WCHAR[wcslen(wszClassName) + 2];
  2692. if(wszPrefix == NULL)
  2693. return WBEM_E_OUT_OF_MEMORY;
  2694. CVectorDeleteMe<WCHAR> vdm( wszPrefix );
  2695. swprintf(wszPrefix, L"%s.", wszClassName);
  2696. m_Bindings.RemoveConsumersStartingWith(wszPrefix);
  2697. swprintf(wszPrefix, L"%s=", wszClassName);
  2698. m_Bindings.RemoveConsumersStartingWith(wszPrefix);
  2699. return WBEM_S_NO_ERROR;
  2700. }
  2701. HRESULT CEssNamespace::ReloadProvider( long lFlags, LPCWSTR wszProvider )
  2702. {
  2703. HRESULT hres;
  2704. WString wsRelpath;
  2705. //
  2706. // we only have to do this for event providers. Check to see if
  2707. // we know about this try to see if we even have any event providers to reload ...
  2708. //
  2709. try
  2710. {
  2711. wsRelpath = L"__Win32Provider.Name='";
  2712. wsRelpath += wszProvider;
  2713. wsRelpath += L"'";
  2714. }
  2715. catch( CX_MemoryException )
  2716. {
  2717. return WBEM_E_OUT_OF_MEMORY;
  2718. }
  2719. CWbemPtr<_IWmiObject> pObj;
  2720. hres = GetInstance( wsRelpath, &pObj );
  2721. if ( SUCCEEDED(hres) )
  2722. {
  2723. {
  2724. ENSURE_INITIALIZED
  2725. CInResync ir(this);
  2726. //
  2727. // note : in case of reloading event provider due to notification
  2728. // from provss, we only need to handle event providers since
  2729. // consumer providers already have a reloading mechanism.
  2730. //
  2731. m_EventProviderCache.RemoveProvider(pObj);
  2732. hres = AddProvider( pObj );
  2733. }
  2734. if ( SUCCEEDED(hres) )
  2735. {
  2736. hres = FirePostponedOperations();
  2737. }
  2738. else
  2739. {
  2740. FirePostponedOperations();
  2741. }
  2742. }
  2743. return hres;
  2744. }
  2745. HRESULT CEssNamespace::ReloadProvider(IWbemClassObject* pProvObjTemplate)
  2746. {
  2747. HRESULT hres;
  2748. LogOp( L"ReloadProvider", pProvObjTemplate );
  2749. ENSURE_INITIALIZED
  2750. CInResync ir(this);
  2751. // Start by deleting this provider from our records, if there
  2752. // ==========================================================
  2753. hres = RemoveProvider(pProvObjTemplate);
  2754. if(FAILED(hres))
  2755. return hres;
  2756. // Determine the current state of this provider in the database
  2757. // ============================================================
  2758. IWbemClassObject* pProvObj = NULL;
  2759. hres = GetCurrentState(pProvObjTemplate, &pProvObj);
  2760. if(FAILED(hres))
  2761. return hres;
  2762. if(pProvObj == NULL)
  2763. {
  2764. // The provider has been deleted --- no further action is needed
  2765. // =============================================================
  2766. return S_OK;
  2767. }
  2768. CReleaseMe rm1(pProvObj);
  2769. // Now create it if necessary
  2770. // ==========================
  2771. hres = AddProvider(pProvObj);
  2772. if(FAILED(hres))
  2773. return hres;
  2774. return hres;
  2775. }
  2776. HRESULT CEssNamespace::ReloadEventProviderRegistration(
  2777. IWbemClassObject* pProvRegObjTemplate)
  2778. {
  2779. HRESULT hres;
  2780. LogOp( L"ReloadEventProviderRegistration", pProvRegObjTemplate );
  2781. ENSURE_INITIALIZED
  2782. CInResync ir(this);
  2783. // Start by deleting this provider from our records, if there
  2784. // ==========================================================
  2785. hres = RemoveEventProviderRegistration(pProvRegObjTemplate);
  2786. if(FAILED(hres))
  2787. return hres;
  2788. // Determine the current state of this registration in the database
  2789. // ================================================================
  2790. IWbemClassObject* pProvRegObj = NULL;
  2791. hres = GetCurrentState(pProvRegObjTemplate, &pProvRegObj);
  2792. if(FAILED(hres))
  2793. return hres;
  2794. if(pProvRegObj == NULL)
  2795. {
  2796. // The registration has been deleted --- no further action is needed
  2797. // =================================================================
  2798. return S_OK;
  2799. }
  2800. CReleaseMe rm1(pProvRegObj);
  2801. // Now create it if necessary
  2802. // ==========================
  2803. hres = AddEventProviderRegistration(pProvRegObj);
  2804. if(FAILED(hres))
  2805. return hres;
  2806. return hres;
  2807. }
  2808. HRESULT CEssNamespace::ReloadConsumerProviderRegistration(
  2809. IWbemClassObject* pProvRegObjTemplate)
  2810. {
  2811. CInUpdate iu(this);
  2812. // Reset consumer provider info in all the consumers using this consumer
  2813. // provider. That's all we need to do --- they will simply pick up the new
  2814. // data on next delivery. We don't even need to get the current version,
  2815. // since all we need is the key
  2816. // ========================================================================
  2817. return RemoveConsumerProviderRegistration(pProvRegObjTemplate);
  2818. }
  2819. //*****************************************************************************
  2820. //
  2821. // Assumes that the namespace is locked and PrepareForResync has been called
  2822. // Adds this provider to the records. Expects ReactivateAllFilters and
  2823. // CommitResync to be called later
  2824. //
  2825. //*****************************************************************************
  2826. HRESULT CEssNamespace::AddProvider(READ_ONLY IWbemClassObject* pProv)
  2827. {
  2828. HRESULT hres;
  2829. hres = m_EventProviderCache.AddProvider(pProv);
  2830. return hres;
  2831. }
  2832. HRESULT CEssNamespace::CheckEventProviderRegistration(IWbemClassObject* pReg)
  2833. {
  2834. HRESULT hres;
  2835. ENSURE_INITIALIZED
  2836. hres = m_EventProviderCache.CheckProviderRegistration(pReg);
  2837. return hres;
  2838. }
  2839. HRESULT CEssNamespace::CheckTimerInstruction(IWbemClassObject* pInst)
  2840. {
  2841. HRESULT hres;
  2842. ENSURE_INITIALIZED
  2843. hres = GetTimerGenerator().CheckTimerInstruction(pInst);
  2844. return hres;
  2845. }
  2846. //*****************************************************************************
  2847. //
  2848. // Assumes that the namespace is locked and PrepareForResync has been called
  2849. // Adds this event provider registration to the records. Expects
  2850. // ReactivateAllFilters and CommitResync to be called later
  2851. //
  2852. //*****************************************************************************
  2853. HRESULT CEssNamespace::AddEventProviderRegistration(
  2854. IWbemClassObject* pReg)
  2855. {
  2856. HRESULT hres;
  2857. hres = m_EventProviderCache.AddProviderRegistration(pReg);
  2858. return hres;
  2859. }
  2860. //*****************************************************************************
  2861. //
  2862. // Assumes that the namespace is locked and PrepareForResync has been called
  2863. // Removes this provider from the records. Expects ReactivateAllFilters and
  2864. // CommitResync to be called later
  2865. //
  2866. //*****************************************************************************
  2867. HRESULT CEssNamespace::RemoveProvider(READ_ONLY IWbemClassObject* pProv)
  2868. {
  2869. HRESULT hres;
  2870. // Handle event consumer providers
  2871. // ===============================
  2872. IWbemClassObject* pConsProvReg;
  2873. hres = m_ConsumerProviderCache.
  2874. GetConsumerProviderRegFromProviderReg(pProv, &pConsProvReg);
  2875. if(SUCCEEDED(hres))
  2876. {
  2877. RemoveConsumerProviderRegistration(pConsProvReg);
  2878. pConsProvReg->Release();
  2879. }
  2880. // Handle event providers
  2881. // ======================
  2882. hres = m_EventProviderCache.RemoveProvider(pProv);
  2883. return hres;
  2884. }
  2885. //*****************************************************************************
  2886. //
  2887. // Assumes that the namespace is locked and PrepareForResync has been called
  2888. // Adds this event provider registration to the records. Expects
  2889. // ReactivateAllFilters and CommitResync to be called later
  2890. //
  2891. //*****************************************************************************
  2892. HRESULT CEssNamespace::RemoveEventProviderRegistration(
  2893. READ_ONLY IWbemClassObject* pReg)
  2894. {
  2895. HRESULT hres;
  2896. hres = m_EventProviderCache.RemoveProviderRegistration(pReg);
  2897. return hres;
  2898. }
  2899. DWORD CEssNamespace::GetProvidedEventMask(IWbemClassObject* pClass)
  2900. {
  2901. return m_EventProviderCache.GetProvidedEventMask(pClass);
  2902. }
  2903. //*****************************************************************************
  2904. //
  2905. // This function is called before a major update to the records. Without any
  2906. // calls to external components, it "deactivates" all the filters, in a sense
  2907. // that when all of them are "reactivated", the system will arrive in a
  2908. // consistent state (usage counts, etc). CommitResync will then perform any
  2909. // necessary activations/deactivations based on the new state
  2910. //
  2911. //*****************************************************************************
  2912. HRESULT CEssNamespace::PrepareForResync()
  2913. {
  2914. m_bInResync = TRUE;
  2915. // Ask the poller to "virtually" stop all polling instructions, without
  2916. // actually stopping them physically
  2917. // ====================================================================
  2918. m_Poller.VirtuallyStopPolling();
  2919. // Ask provider cache to "virtually" release all its providers, without
  2920. // actually releasing them physically
  2921. // ====================================================================
  2922. m_EventProviderCache.VirtuallyReleaseProviders();
  2923. // Ask core search to mark all filters so that it would know which ones are
  2924. // gone after the resync
  2925. // ========================================================================
  2926. DEBUGTRACE((LOG_ESS,"Prepared resync in namespace %S\n", m_wszName ));
  2927. return WBEM_S_NO_ERROR;
  2928. }
  2929. HRESULT CEssNamespace::ReactivateAllFilters()
  2930. {
  2931. DEBUGTRACE((LOG_ESS,"Reactivating all filters in namespace %S\n",
  2932. m_wszName ));
  2933. return m_Bindings.ReactivateAllFilters();
  2934. }
  2935. HRESULT CEssNamespace::CommitResync()
  2936. {
  2937. m_bInResync = FALSE;
  2938. // Tell provider cache to perform all the loadings and unloadings it
  2939. // needs to perform based on the new data
  2940. // =================================================================
  2941. m_EventProviderCache.CommitProviderUsage();
  2942. // Tell the poller to cancel unnecessary instructions
  2943. // ==================================================
  2944. m_Poller.CancelUnnecessaryPolling();
  2945. DEBUGTRACE((LOG_ESS,"Committed resync in namespace %S\n", m_wszName ));
  2946. return WBEM_S_NO_ERROR;
  2947. }
  2948. HRESULT CEssNamespace::RemoveConsumerProviderRegistration(
  2949. IWbemClassObject* pReg)
  2950. {
  2951. // Get the name of the consumer provider being deleteed
  2952. // ====================================================
  2953. BSTR strProvRef = CConsumerProviderCache::GetProviderRefFromRecord(pReg);
  2954. if(strProvRef == NULL)
  2955. {
  2956. ERRORTRACE((LOG_ESS, "Invalid consumer provider record is being deleted"
  2957. "\n"));
  2958. return WBEM_S_FALSE;
  2959. }
  2960. CSysFreeMe sfm1(strProvRef);
  2961. // Reset it in all the consumers
  2962. // =============================
  2963. m_Bindings.ResetProviderRecords(strProvRef);
  2964. // Remove it from the cache
  2965. // ========================
  2966. m_ConsumerProviderCache.RemoveConsumerProvider(strProvRef);
  2967. return WBEM_S_NO_ERROR;
  2968. }
  2969. HRESULT CEssNamespace::ScheduleDelivery(CQueueingEventSink* pDest)
  2970. {
  2971. return m_pEss->EnqueueDeliver(pDest);
  2972. }
  2973. HRESULT CEssNamespace::DecorateObject(IWbemClassObject* pObj)
  2974. {
  2975. return m_pEss->DecorateObject(pObj, m_wszName);
  2976. }
  2977. HRESULT CEssNamespace::EnsureConsumerWatchInstruction()
  2978. {
  2979. return m_Bindings.EnsureConsumerWatchInstruction();
  2980. }
  2981. HRESULT CEssNamespace::AddSleepCharge(DWORD dwSleep)
  2982. {
  2983. return m_pEss->AddSleepCharge(dwSleep);
  2984. }
  2985. HRESULT CEssNamespace::AddCache()
  2986. {
  2987. return m_pEss->AddCache();
  2988. }
  2989. HRESULT CEssNamespace::RemoveCache()
  2990. {
  2991. return m_pEss->RemoveCache();
  2992. }
  2993. HRESULT CEssNamespace::AddToCache(DWORD dwAdd, DWORD dwMemberTotal,
  2994. DWORD* pdwSleep)
  2995. {
  2996. return m_pEss->AddToCache(dwAdd, dwMemberTotal, pdwSleep);
  2997. }
  2998. HRESULT CEssNamespace::RemoveFromCache(DWORD dwRemove)
  2999. {
  3000. return m_pEss->RemoveFromCache(dwRemove);
  3001. }
  3002. HRESULT CEssNamespace::PerformSubscriptionInitialization()
  3003. {
  3004. HRESULT hres;
  3005. DWORD dwRead;
  3006. //
  3007. // must use repository only svc ptr here, else we can deadlock when
  3008. // class providers try to call back in.
  3009. //
  3010. #ifdef __WHISTLER_UNCUT
  3011. // Enumerator all EventMonitors
  3012. // ============================
  3013. CMonitorEnumSink* pMonitorSink = new CMonitorEnumSink(this);
  3014. if ( NULL == pMonitorSink )
  3015. {
  3016. return WBEM_E_OUT_OF_MEMORY;
  3017. }
  3018. pMonitorSink->AddRef();
  3019. m_pInternalCoreSvc->InternalCreateInstanceEnum(MONITOR_CLASS, 0,
  3020. pMonitorSink);
  3021. pMonitorSink->ReleaseAndWait();
  3022. #endif
  3023. // Enumerator all EventFilters
  3024. // ===========================
  3025. CFilterEnumSink* pFilterSink = new CFilterEnumSink(this);
  3026. if ( NULL == pFilterSink )
  3027. {
  3028. return WBEM_E_OUT_OF_MEMORY;
  3029. }
  3030. pFilterSink->AddRef();
  3031. m_pInternalCoreSvc->InternalCreateInstanceEnum( EVENT_FILTER_CLASS, 0,
  3032. pFilterSink);
  3033. pFilterSink->ReleaseAndWait();
  3034. // Enumerator all consumers
  3035. // ========================
  3036. CConsumerEnumSink* pConsumerSink = new CConsumerEnumSink(this);
  3037. if ( NULL == pConsumerSink )
  3038. {
  3039. return WBEM_E_OUT_OF_MEMORY;
  3040. }
  3041. pConsumerSink->AddRef();
  3042. m_pInternalCoreSvc->InternalCreateInstanceEnum( CONSUMER_CLASS, 0,
  3043. pConsumerSink);
  3044. pConsumerSink->ReleaseAndWait();
  3045. // Enumerator all bindings
  3046. // =======================
  3047. CBindingEnumSink* pBindingSink = new CBindingEnumSink(this);
  3048. if ( NULL == pBindingSink )
  3049. {
  3050. return WBEM_E_OUT_OF_MEMORY;
  3051. }
  3052. pBindingSink->AddRef();
  3053. m_pInternalCoreSvc->InternalCreateInstanceEnum( BINDING_CLASS, 0,
  3054. pBindingSink);
  3055. pBindingSink->ReleaseAndWait();
  3056. return WBEM_S_NO_ERROR;
  3057. }
  3058. HRESULT CEssNamespace::PerformProviderInitialization()
  3059. {
  3060. HRESULT hres;
  3061. DWORD dwRead;
  3062. //
  3063. // make sure that we resync all subscriptions after we've processed
  3064. // provider objs
  3065. //
  3066. CInResync ir( this );
  3067. //
  3068. // Enumerate all the providers
  3069. //
  3070. IEnumWbemClassObject* penumProvs;
  3071. hres = m_pCoreSvc->CreateInstanceEnum( PROVIDER_CLASS,
  3072. WBEM_FLAG_DEEP,
  3073. GetCurrentEssContext(),
  3074. &penumProvs );
  3075. if ( SUCCEEDED(hres) )
  3076. {
  3077. CReleaseMe rm1(penumProvs);
  3078. // Add them all to ESS
  3079. // ===================
  3080. IWbemClassObject* pProvObj;
  3081. while((hres=penumProvs->Next(INFINITE, 1, &pProvObj, &dwRead)) == S_OK)
  3082. {
  3083. hres = AddProvider(pProvObj);
  3084. pProvObj->Release();
  3085. if(FAILED(hres))
  3086. {
  3087. // Already logged.
  3088. }
  3089. }
  3090. }
  3091. if ( FAILED(hres) )
  3092. {
  3093. ERRORTRACE((LOG_ESS, "Error 0x%X occurred enumerating event providers "
  3094. "in namespace %S. Some event providers may not be active\n", hres,
  3095. m_wszName));
  3096. }
  3097. //
  3098. // Enumerate all the provider registrations
  3099. //
  3100. IEnumWbemClassObject* penumRegs;
  3101. hres = m_pCoreSvc->CreateInstanceEnum( EVENT_PROVIDER_REGISTRATION_CLASS,
  3102. WBEM_FLAG_DEEP,
  3103. GetCurrentEssContext(),
  3104. &penumRegs);
  3105. if ( SUCCEEDED(hres) )
  3106. {
  3107. CReleaseMe rm2(penumRegs);
  3108. // Add them all to ESS
  3109. // ===================
  3110. IWbemClassObject* pRegObj;
  3111. while((hres = penumRegs->Next(INFINITE, 1, &pRegObj, &dwRead)) == S_OK)
  3112. {
  3113. hres = AddEventProviderRegistration(pRegObj);
  3114. pRegObj->Release();
  3115. if(FAILED(hres))
  3116. {
  3117. // Already logged
  3118. }
  3119. }
  3120. }
  3121. if(FAILED(hres))
  3122. {
  3123. ERRORTRACE((LOG_ESS, "Error 0x%X occurred enumerating event providers "
  3124. "registrations in namespace %S. "
  3125. "Some event providers may not be active\n", hres, m_wszName));
  3126. }
  3127. //
  3128. // Create and initialize the core provider.
  3129. //
  3130. CWbemPtr<CCoreEventProvider> pCoreEventProvider = new CCoreEventProvider;
  3131. if ( pCoreEventProvider != NULL )
  3132. {
  3133. hres = pCoreEventProvider->SetNamespace(this);
  3134. if ( SUCCEEDED(hres) )
  3135. {
  3136. LPCWSTR awszQuery[5] =
  3137. {
  3138. L"select * from __InstanceOperationEvent",
  3139. L"select * from __ClassOperationEvent",
  3140. L"select * from __NamespaceOperationEvent",
  3141. L"select * from __SystemEvent",
  3142. L"select * from __TimerEvent"
  3143. };
  3144. hres = m_EventProviderCache.AddSystemProvider(pCoreEventProvider,
  3145. L"$Core",
  3146. 5,
  3147. awszQuery );
  3148. }
  3149. }
  3150. else
  3151. {
  3152. hres = WBEM_E_OUT_OF_MEMORY;
  3153. }
  3154. if ( SUCCEEDED(hres) )
  3155. {
  3156. pCoreEventProvider->AddRef();
  3157. m_pCoreEventProvider = pCoreEventProvider;
  3158. }
  3159. else
  3160. {
  3161. ERRORTRACE((LOG_ESS, "Core event provider cannot initialize due "
  3162. "to critical errors. HR=0x%x\n", hres));
  3163. }
  3164. #ifdef __WHISTLER_UNCUT
  3165. //
  3166. // Create and initialize the monitor provider.
  3167. //
  3168. CWbemPtr<CMonitorProvider> pMonitorProvider = new CMonitorProvider;
  3169. if ( pMonitorProvider != NULL )
  3170. {
  3171. hres = pMonitorProvider->SetNamespace(this);
  3172. if ( SUCCEEDED(hres) )
  3173. {
  3174. LPCWSTR wszQuery = L"select * from "MONITOR_BASE_EVENT_CLASS;
  3175. hres = m_EventProviderCache.AddSystemProvider( pMonitorProvider,
  3176. L"__Monitor",
  3177. 1,
  3178. &wszQuery );
  3179. }
  3180. }
  3181. else
  3182. {
  3183. hres = WBEM_E_OUT_OF_MEMORY;
  3184. }
  3185. if ( SUCCEEDED(hres) )
  3186. {
  3187. pMonitorProvider->AddRef();
  3188. m_pMonitorProvider = pMonitorProvider;
  3189. }
  3190. else
  3191. {
  3192. ERRORTRACE((LOG_ESS, "Monitor event provider cannot initialize due "
  3193. "to critical errors. HR=0x%x\n", hres));
  3194. }
  3195. #endif
  3196. // Initialize timer generator
  3197. // ==========================
  3198. hres = InitializeTimerGenerator();
  3199. if(FAILED(hres))
  3200. {
  3201. ERRORTRACE((LOG_ESS, "Error 0x%X occurred initializing the timer "
  3202. "in namespace %S. Some timer instructions may not be active\n",
  3203. hres, m_wszName));
  3204. }
  3205. return WBEM_S_NO_ERROR;
  3206. }
  3207. HRESULT CEssNamespace::InitializeTimerGenerator()
  3208. {
  3209. return m_pEss->InitializeTimerGenerator( m_wszName, m_pCoreSvc );
  3210. }
  3211. HRESULT CEssNamespace::FirePostponedOperations()
  3212. {
  3213. HRESULT hr, hrReturn = WBEM_S_NO_ERROR;
  3214. //
  3215. // Update lock cannot be held when calling this function and there
  3216. // are operations to execute.
  3217. //
  3218. _DBG_ASSERT( !DoesThreadOwnNamespaceLock() );
  3219. //
  3220. // execute both primary and event postponed ops until empty.
  3221. //
  3222. CPostponedList* pList = GetCurrentPostponedList();
  3223. CPostponedList* pEventList = GetCurrentPostponedEventList();
  3224. do
  3225. {
  3226. //
  3227. // execute the primary postponed ops.
  3228. //
  3229. if( pList != NULL )
  3230. {
  3231. hr = pList->Execute(this, CPostponedList::e_ReturnOneError);
  3232. if ( SUCCEEDED(hrReturn) )
  3233. {
  3234. hrReturn = hr;
  3235. }
  3236. }
  3237. //
  3238. // now execute postponed events
  3239. //
  3240. if ( pEventList != NULL )
  3241. {
  3242. hr = pEventList->Execute(this, CPostponedList::e_ReturnOneError);
  3243. if ( SUCCEEDED(hrReturn) )
  3244. {
  3245. hrReturn = hr;
  3246. }
  3247. }
  3248. }
  3249. while( pList != NULL && !pList->IsEmpty() );
  3250. return hrReturn;
  3251. }
  3252. HRESULT CEssNamespace::PostponeRelease(IUnknown* pUnk)
  3253. {
  3254. CPostponedList* pList = GetCurrentPostponedList();
  3255. if(pList == NULL)
  3256. {
  3257. //
  3258. // Just execute it
  3259. //
  3260. pUnk->Release();
  3261. return WBEM_S_NO_ERROR;
  3262. }
  3263. CPostponedReleaseRequest* pReq = new CPostponedReleaseRequest(pUnk);
  3264. if(pReq == NULL)
  3265. return WBEM_E_OUT_OF_MEMORY;
  3266. //
  3267. // this is a namespace agnostic postponed request, so specify null.
  3268. //
  3269. return pList->AddRequest( NULL, pReq );
  3270. }
  3271. HRESULT CEssNamespace::GetProviderNamespacePointer(IWbemServices** ppServices)
  3272. {
  3273. IWbemServices* pServices = NULL;
  3274. HRESULT hres = m_pEss->GetNamespacePointer(m_wszName, FALSE, &pServices);
  3275. if(FAILED(hres))
  3276. return hres;
  3277. IWbemUnloadingControl* pControl = NULL;
  3278. pServices->QueryInterface(IID_IWbemUnloadingControl,
  3279. (void**)&pControl);
  3280. if(pControl)
  3281. {
  3282. pControl->SetMustPreventUnloading(true);
  3283. pControl->Release();
  3284. }
  3285. *ppServices = pServices;
  3286. return WBEM_S_NO_ERROR;
  3287. }
  3288. void CEssNamespace::IncrementObjectCount()
  3289. {
  3290. m_pEss->IncrementObjectCount();
  3291. }
  3292. void CEssNamespace::DecrementObjectCount()
  3293. {
  3294. m_pEss->DecrementObjectCount();
  3295. }
  3296. HRESULT CEssNamespace::LockForUpdate()
  3297. {
  3298. m_csLevel2.Enter();
  3299. return WBEM_S_NO_ERROR;
  3300. }
  3301. HRESULT CEssNamespace::UnlockForUpdate()
  3302. {
  3303. m_ClassCache.Clear();
  3304. m_csLevel2.Leave();
  3305. return WBEM_S_NO_ERROR;
  3306. }
  3307. HRESULT CEssNamespace::GetCurrentState( IWbemClassObject* pTemplate,
  3308. IWbemClassObject** ppObj)
  3309. {
  3310. HRESULT hres;
  3311. *ppObj = NULL;
  3312. // Retrieve the path
  3313. // =================
  3314. VARIANT vPath;
  3315. hres = pTemplate->Get(L"__RELPATH", 0, &vPath, NULL, NULL);
  3316. if(FAILED(hres))
  3317. return hres;
  3318. CClearMe cm1(&vPath);
  3319. if(V_VT(&vPath) != VT_BSTR)
  3320. return WBEM_E_INVALID_OBJECT;
  3321. // Get it from the namespace
  3322. // =========================
  3323. _IWmiObject* pObj;
  3324. hres = GetInstance( V_BSTR(&vPath), &pObj );
  3325. if( hres == WBEM_E_NOT_FOUND )
  3326. return WBEM_S_FALSE;
  3327. *ppObj = pObj;
  3328. return hres;
  3329. }
  3330. CWinMgmtTimerGenerator& CEssNamespace::GetTimerGenerator()
  3331. {
  3332. return m_pEss->GetTimerGenerator();
  3333. }
  3334. HRESULT CEssNamespace::RaiseErrorEvent(IWbemEvent* pEvent)
  3335. {
  3336. CEventRepresentation Event;
  3337. Event.type = e_EventTypeSystem;
  3338. Event.nObjects = 1;
  3339. Event.apObjects = &pEvent;
  3340. HRESULT hres;
  3341. hres = SignalEvent( Event, 0 );
  3342. if(FAILED(hres))
  3343. {
  3344. ERRORTRACE((LOG_ESS, "Event subsystem was unable to deliver an "
  3345. "error event to some consumers (%X)\n", hres));
  3346. }
  3347. return S_OK;
  3348. }
  3349. HRESULT CEssNamespace::GetClassFromCore( LPCWSTR wszClassName,
  3350. _IWmiObject** ppClass )
  3351. {
  3352. HRESULT hres;
  3353. CWbemPtr<IWbemClassObject> pClass;
  3354. *ppClass = NULL;
  3355. //
  3356. // want to ensure that we don't use the full service ptr until we've
  3357. // completed stage 1 initialization. Reason is that we don't want to
  3358. // load class providers until the second stage of initialization.
  3359. //
  3360. _DBG_ASSERT( m_bStage1Complete );
  3361. //
  3362. // must use full service because will need to support dynamic classes.
  3363. //
  3364. hres = m_pInternalFullSvc->InternalGetClass( wszClassName, &pClass );
  3365. if ( FAILED(hres) )
  3366. {
  3367. return hres;
  3368. }
  3369. return pClass->QueryInterface( IID__IWmiObject, (void**)ppClass );
  3370. }
  3371. HRESULT CEssNamespace::GetInstance( LPCWSTR wszPath,
  3372. _IWmiObject** ppInstance )
  3373. {
  3374. HRESULT hres;
  3375. CWbemPtr<IWbemClassObject> pInstance;
  3376. *ppInstance = NULL;
  3377. hres = m_pInternalCoreSvc->InternalGetInstance( wszPath, &pInstance );
  3378. if ( FAILED(hres) )
  3379. {
  3380. return hres;
  3381. }
  3382. return pInstance->QueryInterface( IID__IWmiObject, (void**)ppInstance );
  3383. }
  3384. HRESULT CEssNamespace::GetDbInstance( LPCWSTR wszDbKey,
  3385. _IWmiObject** ppInstance)
  3386. {
  3387. HRESULT hres;
  3388. CWbemPtr<IWbemClassObject> pInstance;
  3389. *ppInstance = NULL;
  3390. hres = m_pInternalCoreSvc->GetDbInstance( wszDbKey, &pInstance );
  3391. if ( FAILED(hres) )
  3392. {
  3393. return hres;
  3394. }
  3395. return pInstance->QueryInterface( IID__IWmiObject, (void**)ppInstance );
  3396. }
  3397. HRESULT CEssNamespace::CreateInstanceEnum(LPCWSTR wszClass, long lFlags,
  3398. IWbemObjectSink* pSink)
  3399. {
  3400. return m_pInternalCoreSvc->InternalCreateInstanceEnum(wszClass, lFlags, pSink);
  3401. }
  3402. HRESULT CEssNamespace::ExecQuery(LPCWSTR wszQuery, long lFlags,
  3403. IWbemObjectSink* pSink)
  3404. {
  3405. return m_pInternalCoreSvc->InternalExecQuery(L"WQL", wszQuery, lFlags, pSink);
  3406. }
  3407. HRESULT CEssNamespace::GetToken(PSID pSid, IWbemToken** ppToken)
  3408. {
  3409. return m_pEss->GetToken(pSid, ppToken);
  3410. }
  3411. void CEssNamespace::DumpStatistics(FILE* f, long lFlags)
  3412. {
  3413. CInUpdate iu(this);
  3414. fprintf(f, "------- Namespace '%S' ----------\n", m_wszName);
  3415. m_Bindings.DumpStatistics(f, lFlags);
  3416. m_ConsumerProviderCache.DumpStatistics(f, lFlags);
  3417. m_EventProviderCache.DumpStatistics(f, lFlags);
  3418. m_Poller.DumpStatistics(f, lFlags);
  3419. }
  3420. HRESULT CEssMetaData::GetClass( LPCWSTR wszName, IWbemContext* pContext,
  3421. _IWmiObject** ppClass)
  3422. {
  3423. return m_pNamespace->m_ClassCache.GetClass(wszName, pContext, ppClass);
  3424. }
  3425. STDMETHODIMP CEssNamespace::CConsumerClassDeletionSink::Indicate(
  3426. long lNumObjects,
  3427. IWbemClassObject** apObjects)
  3428. {
  3429. HRESULT hres;
  3430. for(long i = 0; i < lNumObjects; i++)
  3431. {
  3432. _IWmiObject* pEvent = NULL;
  3433. apObjects[i]->QueryInterface(IID__IWmiObject, (void**)&pEvent);
  3434. CReleaseMe rm1(pEvent);
  3435. //
  3436. // Get the class name of the class being deleted
  3437. //
  3438. VARIANT vObj;
  3439. hres = pEvent->Get(L"TargetClass", 0, &vObj, NULL, NULL);
  3440. if(SUCCEEDED(hres))
  3441. {
  3442. CClearMe cm1(&vObj);
  3443. IWbemClassObject* pClass;
  3444. V_UNKNOWN(&vObj)->QueryInterface(IID_IWbemClassObject,
  3445. (void**)&pClass);
  3446. CReleaseMe rm2(pClass);
  3447. VARIANT vClass;
  3448. hres = pClass->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  3449. if(SUCCEEDED(hres))
  3450. {
  3451. CClearMe cm(&vClass);
  3452. m_pOuter->HandleConsumerClassDeletion(V_BSTR(&vClass));
  3453. }
  3454. }
  3455. }
  3456. return WBEM_S_NO_ERROR;
  3457. }
  3458. HRESULT CEssNamespace::LoadEventProvider(LPCWSTR wszProviderName,
  3459. IWbemEventProvider** ppProv)
  3460. {
  3461. HRESULT hres;
  3462. *ppProv = NULL;
  3463. //
  3464. // Get provider pointer from the provider subsystem
  3465. //
  3466. if(m_pProviderFactory == NULL)
  3467. return WBEM_E_CRITICAL_ERROR;
  3468. WmiInternalContext t_InternalContext ;
  3469. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ;
  3470. hres = m_pProviderFactory->GetProvider(
  3471. t_InternalContext ,
  3472. 0, // lFlags
  3473. GetCurrentEssContext(),
  3474. 0,
  3475. NULL,
  3476. NULL,
  3477. 0,
  3478. wszProviderName,
  3479. IID_IWbemEventProvider,
  3480. (LPVOID *) ppProv
  3481. );
  3482. return hres;
  3483. }
  3484. HRESULT CEssNamespace::LoadConsumerProvider(LPCWSTR wszProviderName,
  3485. IUnknown** ppProv)
  3486. {
  3487. HRESULT hres;
  3488. *ppProv = NULL;
  3489. //
  3490. // Get provider pointer from the provider subsystem
  3491. //
  3492. if(m_pProviderFactory == NULL)
  3493. return WBEM_E_CRITICAL_ERROR;
  3494. WmiInternalContext t_InternalContext ;
  3495. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ;
  3496. hres = m_pProviderFactory->GetProvider(
  3497. t_InternalContext ,
  3498. 0, // lFlags
  3499. GetCurrentEssContext(),
  3500. 0,
  3501. NULL,
  3502. NULL,
  3503. 0,
  3504. wszProviderName,
  3505. IID_IUnknown,
  3506. (LPVOID *) ppProv
  3507. );
  3508. return hres;
  3509. }