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

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