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

2479 lines
63 KiB

  1. //=============================================================================
  2. //
  3. // Copyright (c) 1996-1999, Microsoft Corporation, All rights reserved
  4. //
  5. // ESS.CPP
  6. //
  7. // Implements the class that contains all the fuctionality of the ESS by
  8. // virtue of containing all the necessary components.
  9. //
  10. // See ess.h for documentation
  11. //
  12. // History:
  13. //
  14. // 11/27/96 a-levn Compiles.
  15. // 1/6/97 a-levn Updated to initialize TSS.
  16. //
  17. //=============================================================================
  18. #include "precomp.h"
  19. #include <stdio.h>
  20. #include <wmimsg.h>
  21. #include "ess.h"
  22. #include "persistcfg.h"
  23. #include "WinMgmtR.h"
  24. #include "GenUtils.h" // For SetObjectAccess
  25. #include "NCEvents.h"
  26. #include "Quota.h"
  27. #define BOOT_PHASE_MS 60*2*1000
  28. #define WBEM_REG_ESS_ACTIVE_NAMESPACES __TEXT("List of event-active namespaces")
  29. #define WBEM_ESS_OPEN_FOR_BUSINESS_EVENT_NAME L"WBEM_ESS_OPEN_FOR_BUSINESS"
  30. // The use of this pointer to initialize parent class is valid in this context
  31. #pragma warning(disable : 4355)
  32. //
  33. // this guid is used to identify the MSMQ queues that are used for guaranteed
  34. // delivery. A type guid is a property of an MSMQ queue, so one can tell
  35. // by looking at an MSMQ queue if its an ess one or not.
  36. //
  37. // {555471B4-0BE3-4e42-A98B-347AF72898FA}
  38. //
  39. const CLSID g_guidQueueType =
  40. { 0x555471b4, 0xbe3, 0x4e42, {0xa9, 0x8b, 0x34, 0x7a, 0xf7, 0x28, 0x98, 0xfa}};
  41. #pragma warning(push)
  42. // not all control paths return due to infinite loop
  43. #pragma warning(disable:4715)
  44. DWORD DumpThread(CEss* pEss)
  45. {
  46. while(1)
  47. {
  48. FILE* f = fopen("c:\\stat.log", "a");
  49. if(f == NULL)
  50. return 1;
  51. pEss->DumpStatistics(f, 0);
  52. fclose(f);
  53. Sleep(10000);
  54. }
  55. return 0;
  56. }
  57. #pragma warning(pop)
  58. DWORD RegDeleteSubKeysW( HKEY hkey )
  59. {
  60. FILETIME ft;
  61. DWORD dwIndex=0;
  62. LONG lRes = ERROR_SUCCESS;
  63. LONG lResReturn = lRes;
  64. DWORD dwBuffSize = 256;
  65. DWORD cName = dwBuffSize;
  66. LPWSTR wszName = new WCHAR[dwBuffSize];
  67. if ( wszName == NULL )
  68. {
  69. return ERROR_NOT_ENOUGH_MEMORY;
  70. }
  71. CWStringArray awsKeysToDelete;
  72. //
  73. // enumerate through all subkeys and make recursive call.
  74. //
  75. while( lRes == ERROR_SUCCESS &&
  76. ( lRes=RegEnumKeyExW( hkey, dwIndex, wszName, &cName, NULL,
  77. NULL, NULL, &ft ) ) != ERROR_NO_MORE_ITEMS )
  78. {
  79. if ( lRes == ERROR_SUCCESS )
  80. {
  81. HKEY hkeySub;
  82. //
  83. // open key and make recursive call.
  84. //
  85. lRes = RegOpenKeyExW( hkey,
  86. wszName,
  87. 0,
  88. KEY_ALL_ACCESS,
  89. &hkeySub );
  90. if ( lRes == ERROR_SUCCESS )
  91. {
  92. lRes = RegDeleteSubKeysW( hkeySub );
  93. RegCloseKey( hkeySub );
  94. }
  95. //
  96. // defer deletion of key until we're done enumerating.
  97. //
  98. try
  99. {
  100. awsKeysToDelete.Add( wszName );
  101. }
  102. catch( CX_MemoryException )
  103. {
  104. lRes = ERROR_NOT_ENOUGH_MEMORY;
  105. }
  106. //
  107. // we want to try to keep going if we fail.
  108. //
  109. if ( lRes != ERROR_SUCCESS )
  110. {
  111. lResReturn = lRes;
  112. lRes = ERROR_SUCCESS;
  113. }
  114. dwIndex++;
  115. }
  116. else if ( lRes == ERROR_MORE_DATA )
  117. {
  118. dwBuffSize += 256;
  119. delete [] wszName;
  120. wszName = new WCHAR[dwBuffSize];
  121. if ( wszName == NULL )
  122. {
  123. lRes = ERROR_NOT_ENOUGH_MEMORY;
  124. }
  125. }
  126. cName = dwBuffSize;
  127. }
  128. delete [] wszName;
  129. for( int i=0; i < awsKeysToDelete.Size(); i++ )
  130. {
  131. lRes = RegDeleteKeyW( hkey, awsKeysToDelete[i] );
  132. if ( lRes != ERROR_SUCCESS )
  133. {
  134. lResReturn = lRes;
  135. }
  136. }
  137. return lResReturn;
  138. }
  139. /****************************************************************************
  140. CProviderReloadRequest
  141. *****************************************************************************/
  142. class CProviderReloadRequest : public CExecRequest
  143. {
  144. protected:
  145. CEss* m_pEss;
  146. long m_lFlags;
  147. CWbemPtr<IWbemContext> m_pContext;
  148. WString m_wsNamespace;
  149. WString m_wsProvider;
  150. public:
  151. CProviderReloadRequest( CEss* pEss,
  152. long lFlags,
  153. IWbemContext* pContext,
  154. LPCWSTR wszNamespace,
  155. LPCWSTR wszProvider )
  156. : m_pEss( pEss ), m_lFlags( lFlags ), m_pContext( pContext ),
  157. m_wsNamespace(wszNamespace), m_wsProvider( wszProvider ) {}
  158. HRESULT Execute();
  159. };
  160. HRESULT CProviderReloadRequest::Execute()
  161. {
  162. HRESULT hr;
  163. _DBG_ASSERT( GetCurrentEssThreadObject() == NULL );
  164. SetCurrentEssThreadObject( m_pContext );
  165. if ( GetCurrentEssThreadObject() != NULL )
  166. {
  167. hr = m_pEss->ReloadProvider( m_lFlags,
  168. m_wsNamespace,
  169. m_wsProvider );
  170. delete GetCurrentEssThreadObject();
  171. ClearCurrentEssThreadObject();
  172. }
  173. else
  174. {
  175. hr = WBEM_E_OUT_OF_MEMORY;
  176. }
  177. return hr;
  178. }
  179. /****************************************************************************
  180. CEssProvSSSink
  181. *****************************************************************************/
  182. class CEssProvSSSink : public CUnkBase<_IWmiProvSSSink, &IID__IWmiProvSSSink >
  183. {
  184. CEss* m_pEss;
  185. public:
  186. CEssProvSSSink( CEss* pEss ) : m_pEss( pEss ),
  187. CUnkBase< _IWmiProvSSSink, &IID__IWmiProvSSSink >( NULL ) { }
  188. STDMETHOD(Synchronize)( long lFlags,
  189. IWbemContext* pContext,
  190. LPCWSTR wszNamespace,
  191. LPCWSTR wszProvider );
  192. };
  193. STDMETHODIMP CEssProvSSSink::Synchronize( long lFlags,
  194. IWbemContext* pContext,
  195. LPCWSTR wszNamespace,
  196. LPCWSTR wszProvider )
  197. {
  198. HRESULT hr;
  199. CProviderReloadRequest* pReq;
  200. try
  201. {
  202. pReq = new CProviderReloadRequest( m_pEss,
  203. lFlags,
  204. pContext,
  205. wszNamespace,
  206. wszProvider );
  207. }
  208. catch( CX_MemoryException )
  209. {
  210. pReq = NULL;
  211. }
  212. if ( pReq != NULL )
  213. {
  214. hr = m_pEss->Enqueue( pReq );
  215. if ( FAILED(hr) )
  216. {
  217. delete pReq;
  218. }
  219. }
  220. else
  221. {
  222. hr = WBEM_E_OUT_OF_MEMORY;
  223. }
  224. return hr;
  225. }
  226. /***************************************************************************
  227. CNamespaceInitRequest - Used to execute a single namespace initialize. It
  228. can be set to perform various stages of Namespace initialization.
  229. ****************************************************************************/
  230. class CNamespaceInitRequest : public CExecRequest
  231. {
  232. protected:
  233. BOOL m_bActiveOnStart;
  234. CWbemPtr<CEssNamespace> m_pNamespace;
  235. CWbemPtr<IWbemContext> m_pContext;
  236. public:
  237. CNamespaceInitRequest( CEssNamespace* pNamespace, BOOL bActiveOnStart )
  238. : m_pNamespace(pNamespace), m_bActiveOnStart( bActiveOnStart )
  239. {
  240. m_pContext = GetCurrentEssContext();
  241. }
  242. HRESULT Execute()
  243. {
  244. HRESULT hr = WBEM_S_NO_ERROR;
  245. _DBG_ASSERT( GetCurrentEssThreadObject() == NULL );
  246. SetCurrentEssThreadObject( m_pContext );
  247. if ( GetCurrentEssThreadObject() != NULL )
  248. {
  249. //
  250. // if this namespace was active on boot, then it has already had
  251. // its Initialize() called.
  252. //
  253. if ( !m_bActiveOnStart )
  254. {
  255. hr = m_pNamespace->Initialize();
  256. }
  257. if ( SUCCEEDED(hr) )
  258. {
  259. hr = m_pNamespace->CompleteInitialization();
  260. }
  261. m_pNamespace->MarkAsInitialized( hr );
  262. delete GetCurrentEssThreadObject();
  263. ClearCurrentEssThreadObject();
  264. }
  265. else
  266. {
  267. hr = WBEM_E_OUT_OF_MEMORY;
  268. }
  269. //
  270. // if we're initializing because the namespace was active on
  271. // startup then notify ess that we're done because its waiting
  272. // for all active namespaces to finish initializing.
  273. //
  274. if ( m_bActiveOnStart )
  275. {
  276. m_pNamespace->GetEss()->NotifyActiveNamespaceInitComplete();
  277. }
  278. if(FAILED(hr))
  279. {
  280. ERRORTRACE((LOG_ESS, "ESS failed to initialize a namespace "
  281. "'%S'. Error code 0x%X\n", m_pNamespace->GetName(), hr));
  282. }
  283. return hr;
  284. }
  285. };
  286. /**************************************************************************
  287. CInitActiveNamespacesRequest - Used to initialize 1 or more active event
  288. namespaces. An active event namespace is one that was active on the last
  289. shutdown. The reason for initialization of multiple namespaces together is
  290. that the Stage1 Initialization of dependent active namespaces must complete
  291. before the Stage2 Initialization of any one of them. This is so all
  292. inter-namespace subscriptions can be put in place before event providers
  293. are activated in any one of them. Enforcing that all stage1 initialization
  294. of dependent active namespaces does not cause a problem of all namespaces
  295. being doomed by one faulty class provider in any single namespace because
  296. stage1 init is guaranteed not to access any providers. All stage2 init of
  297. dependent active namespace, which may access providers, is performed
  298. asynchronously.
  299. ****************************************************************************/
  300. class CInitActiveNamespacesRequest : public CExecRequest
  301. {
  302. protected:
  303. CEss* m_pEss;
  304. CRefedPointerArray<CEssNamespace> m_apNamespaces;
  305. CWbemPtr<IWbemContext> m_pContext;
  306. public:
  307. CInitActiveNamespacesRequest( CEss* pEss ) : m_pEss(pEss)
  308. {
  309. m_pContext = GetCurrentEssContext();
  310. }
  311. int GetNumNamespaces() { return m_apNamespaces.GetSize(); }
  312. void Reset()
  313. {
  314. m_apNamespaces.RemoveAll();
  315. }
  316. HRESULT Add( CEssNamespace* pNamespace )
  317. {
  318. if ( m_apNamespaces.Add( pNamespace ) < 0 )
  319. {
  320. return WBEM_E_OUT_OF_MEMORY;
  321. }
  322. return WBEM_S_NO_ERROR;
  323. }
  324. HRESULT Execute()
  325. {
  326. HRESULT hr;
  327. HRESULT hrGlobal = WBEM_S_NO_ERROR;
  328. _DBG_ASSERT( GetCurrentEssThreadObject() == NULL );
  329. SetCurrentEssThreadObject( m_pContext );
  330. if ( GetCurrentEssThreadObject() == NULL )
  331. {
  332. for( int i=0; i < m_apNamespaces.GetSize(); i++ )
  333. {
  334. m_pEss->NotifyActiveNamespaceInitComplete();
  335. }
  336. return WBEM_E_OUT_OF_MEMORY;
  337. }
  338. for( int i=0; i < m_apNamespaces.GetSize(); i++ )
  339. {
  340. hr = m_apNamespaces[i]->Initialize();
  341. if ( FAILED(hr) )
  342. {
  343. ERRORTRACE((LOG_ESS, "ESS failed to initialize active "
  344. "namespace '%S'. Error code 0x%x\n",
  345. m_apNamespaces[i]->GetName(), hr ));
  346. m_apNamespaces[i]->MarkAsInitialized(hr);
  347. m_apNamespaces.SetAt(i, NULL);
  348. m_pEss->NotifyActiveNamespaceInitComplete();
  349. hrGlobal = hr;
  350. }
  351. }
  352. for( int i=0; i < m_apNamespaces.GetSize(); i++ )
  353. {
  354. if ( m_apNamespaces[i] == NULL )
  355. {
  356. continue;
  357. }
  358. CNamespaceInitRequest* pReq;
  359. pReq = new CNamespaceInitRequest( m_apNamespaces[i], TRUE );
  360. if ( pReq != NULL )
  361. {
  362. hr = m_pEss->Enqueue( pReq );
  363. }
  364. else
  365. {
  366. hr = WBEM_E_OUT_OF_MEMORY;
  367. }
  368. if ( FAILED(hr) )
  369. {
  370. ERRORTRACE((LOG_ESS, "ESS failed to issue request for "
  371. "completion of init for namespace '%S'. HR=0x%x\n",
  372. m_apNamespaces[i]->GetName(), hr ));
  373. m_apNamespaces[i]->MarkAsInitialized( hr );
  374. m_pEss->NotifyActiveNamespaceInitComplete();
  375. hrGlobal = hr;
  376. }
  377. }
  378. _DBG_ASSERT( GetCurrentEssContext() == m_pContext );
  379. delete GetCurrentEssThreadObject();
  380. ClearCurrentEssThreadObject();
  381. return hrGlobal;
  382. }
  383. };
  384. inline LPWSTR NormalizeNamespaceString( LPCWSTR wszName )
  385. {
  386. int cLen = wcslen( wszName );
  387. LPWSTR wszNormName = new WCHAR[cLen+5]; // 5 is for '\\.\' + '\0'
  388. if ( wszNormName == NULL )
  389. {
  390. return NULL;
  391. }
  392. if ( wcsncmp( wszName, L"\\\\", 2 ) == 0 ||
  393. wcsncmp( wszName, L"//", 2 ) == 0 )
  394. {
  395. wcscpy( wszNormName, wszName );
  396. }
  397. else
  398. {
  399. wcscpy( wszNormName, L"\\\\.\\" );
  400. wcscat( wszNormName, wszName );
  401. }
  402. //
  403. // also convert all backwards slashes to forward slashes so that the
  404. // normalized name can serve as both a valid wmi namespace string and as
  405. // a valid persistent string ( wrt msmq and registry keys ).
  406. //
  407. WCHAR* pch = wszNormName;
  408. while( *pch != '\0' )
  409. {
  410. if ( *pch == '\\' )
  411. {
  412. *pch = '/';
  413. }
  414. pch++;
  415. }
  416. return wszNormName;
  417. }
  418. //******************************************************************************
  419. // public
  420. //
  421. // See ess.h for documentation
  422. //
  423. //******************************************************************************
  424. CEss::CEss() : m_pLocator(NULL), m_pCoreServices(NULL), m_Queue(this),
  425. m_TimerGenerator(this), m_hExitBootPhaseTimer(NULL),
  426. m_wszServerName(NULL), m_lObjectCount(0), m_lNumActiveNamespaces(0),
  427. m_pLifeControl(NULL), m_hReadyEvent(NULL), m_pProvSS(NULL), m_bLastCallForCoreCalled(FALSE),
  428. m_pProvSSSink(NULL), m_pTokenCache(NULL), m_pDecorator(NULL),
  429. m_hRecoveryThread(NULL), m_lOutstandingActiveNamespaceInit(0),
  430. m_bMSMQDisabled(FALSE),
  431. m_LimitControl(LOG_ESS, L"events held for consumers",
  432. L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
  433. L"Low Threshold On Events (B)",
  434. L"High Threshold On Events (B)",
  435. L"Max Wait On Events (ms)")
  436. {
  437. // Set the defaults for the limit control and read it from the registry
  438. // ====================================================================
  439. m_LimitControl.SetMin(10000000);
  440. m_LimitControl.SetMax(20000000);
  441. m_LimitControl.SetSleepAtMax(2000);
  442. m_LimitControl.Reread();
  443. InitNCEvents();
  444. }
  445. //******************************************************************************
  446. // public
  447. //
  448. // See ess.h for documentation
  449. //
  450. //******************************************************************************
  451. HRESULT CEss::LastCallForCore(LONG lIsSystemShutdown)
  452. {
  453. m_bLastCallForCoreCalled = TRUE;
  454. // Shut down the timer generator (needs persistence)
  455. // =================================================
  456. m_TimerGenerator.SaveAndRemove(lIsSystemShutdown);
  457. return WBEM_S_NO_ERROR;
  458. }
  459. HRESULT CEss::Shutdown(BOOL bIsSystemShutdown)
  460. {
  461. HRESULT hres;
  462. _DBG_ASSERT(m_bLastCallForCoreCalled);
  463. if ( m_hReadyEvent != NULL )
  464. {
  465. //
  466. // we must reset the ready event before parking the namespace.
  467. // this way providers can maybe tell why they are being shutdown.
  468. //
  469. ResetEvent( m_hReadyEvent );
  470. }
  471. CInCritSec ics(&m_cs);
  472. // Get persistent storage up-to-date
  473. // =================================
  474. {
  475. m_TimerGenerator.SaveAndRemove((LONG)FALSE);
  476. TNamespaceIterator it = m_mapNamespaces.begin();
  477. while(it != m_mapNamespaces.end())
  478. {
  479. it->second->Park();
  480. it++;
  481. }
  482. }
  483. return WBEM_S_NO_ERROR;
  484. }
  485. HRESULT CEss::RequestStartOnBoot(BOOL bStart)
  486. {
  487. CPersistentConfig per;
  488. per.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_ESS_NEEDS_LOADING, bStart);
  489. SaveActiveNamespaceList();
  490. return WBEM_S_NO_ERROR;
  491. }
  492. CEss::~CEss()
  493. {
  494. if ( m_hReadyEvent != NULL )
  495. {
  496. CloseHandle( m_hReadyEvent );
  497. }
  498. if( GetCurrentEssThreadObject() == NULL )
  499. {
  500. SetCurrentEssThreadObject(NULL);
  501. }
  502. m_EventLog.Close();
  503. if(m_pTokenCache)
  504. {
  505. m_pTokenCache->Shutdown();
  506. }
  507. //
  508. // make sure that recovery has finished.
  509. //
  510. if ( m_hRecoveryThread != NULL )
  511. {
  512. WaitForSingleObject( m_hRecoveryThread, INFINITE );
  513. CloseHandle( m_hRecoveryThread );
  514. m_hRecoveryThread = NULL;
  515. }
  516. //
  517. // Shutdown the quotas. This must be done before we cleanup the
  518. // namespaces because it uses the root namespace for registering
  519. // for quota change events.
  520. //
  521. g_quotas.Shutdown();
  522. m_TimerGenerator.Shutdown();
  523. // Clear the namespace map
  524. // =======================
  525. BOOL bLeft = TRUE;
  526. do
  527. {
  528. // Retrieve the next namespace object and remove it from the map
  529. // =============================================================
  530. CEssNamespace* pNamespace = NULL;
  531. {
  532. CInCritSec ics(&m_cs);
  533. TNamespaceIterator it = m_mapNamespaces.begin();
  534. if(it != m_mapNamespaces.end())
  535. {
  536. pNamespace = it->second;
  537. m_mapNamespaces.erase(it);
  538. }
  539. }
  540. // Shut it down if retrieved
  541. // =========================
  542. if(pNamespace)
  543. {
  544. pNamespace->Shutdown();
  545. pNamespace->Release();
  546. }
  547. // Check if any are left
  548. // =====================
  549. {
  550. CInCritSec ics(&m_cs);
  551. bLeft = !m_mapNamespaces.empty();
  552. }
  553. } while(bLeft);
  554. //
  555. // make sure we remove the callback timer so that we're sure that no
  556. // callbacks occur after we destruct. Make sure that we're not holding
  557. // the critsec at this point because their could be a deadlock, since
  558. // the callback could be executing right now and be waiting for the
  559. // critsec. We would then deadlock when calling DeleteTimerQueueTimer()
  560. //
  561. if ( m_hExitBootPhaseTimer != NULL )
  562. {
  563. DeleteTimerQueueTimer( NULL,
  564. m_hExitBootPhaseTimer,
  565. INVALID_HANDLE_VALUE );
  566. }
  567. m_Queue.Shutdown();
  568. delete GetCurrentEssThreadObject();
  569. ClearCurrentEssThreadObject();
  570. if ( m_pProvSS != NULL && m_pProvSSSink != NULL )
  571. {
  572. m_pProvSS->UnRegisterNotificationSink( 0, NULL, m_pProvSSSink );
  573. }
  574. CEventRepresentation::Shutdown();
  575. CEventAggregator::Shutdown();
  576. if(m_pLocator)
  577. m_pLocator->Release();
  578. if(m_pCoreServices)
  579. m_pCoreServices->Release();
  580. if(m_pProvSS)
  581. m_pProvSS->Release();
  582. if(m_pProvSSSink)
  583. m_pProvSSSink->Release();
  584. if(m_pDecorator)
  585. m_pDecorator->Release();
  586. if(m_pLifeControl)
  587. m_pLifeControl->Release();
  588. delete [] m_wszServerName;
  589. m_pTokenCache->Release();
  590. CEssThreadObject::ClearSpecialContext();
  591. for( int i=0; i < m_aDeferredNSInitRequests.GetSize(); i++ )
  592. delete m_aDeferredNSInitRequests[i];
  593. DeinitNCEvents();
  594. }
  595. HRESULT CEss::SetNamespaceActive(LPCWSTR wszNamespace)
  596. {
  597. LONG lRes;
  598. HKEY hkeyEss, hkeyNamespace;
  599. DEBUGTRACE((LOG_ESS,"Namespace %S is becoming Active\n", wszNamespace));
  600. //
  601. // If this is the first active namespace, request that WinMgmt load us the
  602. // next time around
  603. //
  604. if(m_lNumActiveNamespaces++ == 0)
  605. {
  606. RequestStartOnBoot(TRUE);
  607. }
  608. //
  609. // open ess key.
  610. //
  611. lRes = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  612. WBEM_REG_ESS,
  613. 0,
  614. KEY_ALL_ACCESS,
  615. &hkeyEss );
  616. //
  617. // open or create namespace key.
  618. //
  619. if ( lRes == ERROR_SUCCESS )
  620. {
  621. lRes = RegCreateKeyExW( hkeyEss,
  622. wszNamespace,
  623. 0,
  624. NULL,
  625. REG_OPTION_NON_VOLATILE,
  626. KEY_ALL_ACCESS,
  627. NULL,
  628. &hkeyNamespace,
  629. NULL );
  630. if ( lRes == ERROR_SUCCESS )
  631. {
  632. RegCloseKey( hkeyNamespace );
  633. }
  634. RegCloseKey( hkeyEss );
  635. }
  636. if ( lRes != ERROR_SUCCESS )
  637. {
  638. ERRORTRACE((LOG_ESS,"Error adding active namespace key %S to "
  639. "registry. Res=%d\n", wszNamespace, lRes ));
  640. }
  641. return HRESULT_FROM_WIN32( lRes );
  642. }
  643. HRESULT CEss::SetNamespaceInactive(LPCWSTR wszNamespace)
  644. {
  645. LONG lRes;
  646. HKEY hkeyEss, hkeyNamespace;
  647. DEBUGTRACE((LOG_ESS,"Namespace %S is becoming Inactive\n", wszNamespace));
  648. //
  649. // If this is the last active namespace, request that WinMgmt not load us
  650. // the next time around
  651. //
  652. if(--m_lNumActiveNamespaces == 0)
  653. {
  654. RequestStartOnBoot(FALSE);
  655. }
  656. //
  657. // open ess key.
  658. //
  659. lRes = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  660. WBEM_REG_ESS,
  661. 0,
  662. KEY_ALL_ACCESS,
  663. &hkeyEss );
  664. //
  665. // delete namespace key
  666. //
  667. if ( lRes == ERROR_SUCCESS )
  668. {
  669. lRes = RegOpenKeyExW( hkeyEss,
  670. wszNamespace,
  671. 0,
  672. KEY_ALL_ACCESS,
  673. &hkeyNamespace );
  674. if ( lRes == ERROR_SUCCESS )
  675. {
  676. lRes = RegDeleteSubKeysW( hkeyNamespace );
  677. RegCloseKey( hkeyNamespace );
  678. }
  679. if ( lRes == ERROR_SUCCESS )
  680. {
  681. lRes = RegDeleteKeyW( hkeyEss, wszNamespace );
  682. }
  683. RegCloseKey( hkeyEss );
  684. }
  685. if ( lRes != ERROR_SUCCESS )
  686. {
  687. ERRORTRACE((LOG_ESS,"Error removing active namespace key %S from "
  688. "registry. Res=%d\n", wszNamespace, lRes ));
  689. }
  690. return HRESULT_FROM_WIN32(lRes);
  691. }
  692. HRESULT CEss::SaveActiveNamespaceList()
  693. {
  694. CWStringArray wsNamespaces;
  695. //
  696. // Iterate through the namespaces
  697. //
  698. DWORD dwTotalLen = 0;
  699. {
  700. CInCritSec ics(&m_cs);
  701. for(TNamespaceIterator it = m_mapNamespaces.begin();
  702. it != m_mapNamespaces.end(); it++)
  703. {
  704. if(it->second->IsNeededOnStartup())
  705. {
  706. LPCWSTR wszName = it->second->GetName();
  707. if(wsNamespaces.Add(wszName) < 0)
  708. return WBEM_E_OUT_OF_MEMORY;
  709. dwTotalLen += wcslen(wszName) + 1;
  710. }
  711. }
  712. }
  713. dwTotalLen += 1;
  714. //
  715. // Allocate a buffer for all of these strings and copy them all in,
  716. // separated by NULLs.
  717. //
  718. WCHAR* awcBuffer = new WCHAR[dwTotalLen];
  719. if(awcBuffer == NULL)
  720. return WBEM_E_OUT_OF_MEMORY;
  721. CVectorDeleteMe<WCHAR> vdm(awcBuffer);
  722. WCHAR* pwcCurrent = awcBuffer;
  723. for(int i = 0; i < wsNamespaces.Size(); i++)
  724. {
  725. LPCWSTR wszName = wsNamespaces[i];
  726. wcscpy(pwcCurrent, wszName);
  727. pwcCurrent += wcslen(wszName)+1;
  728. }
  729. *pwcCurrent = NULL;
  730. //
  731. // Store this string in the registry
  732. //
  733. Registry r(WBEM_REG_WINMGMT);
  734. int nRes = r.SetBinary(WBEM_REG_ESS_ACTIVE_NAMESPACES, (byte*)awcBuffer,
  735. dwTotalLen * sizeof(WCHAR));
  736. if(nRes != Registry::no_error)
  737. return WBEM_E_FAILED;
  738. //
  739. // Return S_FALSE if no namespaces are active
  740. //
  741. if(wsNamespaces.Size() > 0)
  742. return S_OK;
  743. else
  744. return S_FALSE;
  745. }
  746. #ifdef __WHISTLER_UNCUT
  747. /* NOTE - a better way to do the guaranteed delivery design would be
  748. to have the queuing sink be responsible fo performing recovery. When
  749. we have an active namespace on boot, we should go through all the bindings
  750. and look for ones that are guaranteed. We then perform try to open their
  751. queue and perform recovery for each one of them. As for garbage collection,
  752. all we have to do is delete all of our queues when we detect that we performed
  753. recovery. We would also enumerate the bindings and delete any associated
  754. queues when a namespace is deleted. */
  755. inline HRESULT CEss::GetQueueManager( IWmiMessageQueueManager** ppQueueMgr )
  756. {
  757. HRESULT hr;
  758. *ppQueueMgr = NULL;
  759. if(m_bMSMQDisabled)
  760. return WMIMSG_E_REQSVCNOTAVAIL;
  761. //
  762. // first obtain a pointer to the queue manager.
  763. //
  764. hr = CoCreateInstance( CLSID_WmiMessageQueueManager,
  765. NULL,
  766. CLSCTX_INPROC,
  767. IID_IWmiMessageQueueManager,
  768. (void**)ppQueueMgr );
  769. if ( FAILED(hr) )
  770. {
  771. return hr;
  772. }
  773. return WBEM_S_NO_ERROR;
  774. }
  775. ULONG WINAPI CEss::PerformRecovery( void* pCtx )
  776. {
  777. HRESULT hr;
  778. try
  779. {
  780. CEss* pSelf = (CEss*)pCtx;
  781. //
  782. // obtain queue manager. normally we'd hold onto the queue manager
  783. // since it would be used later, however, we don't want to keep
  784. // msmq loaded if we never need it. We'll refetch the queue manager
  785. // later if necessary.
  786. //
  787. CWbemPtr<IWmiMessageQueueManager> pQueueMgr;
  788. hr = pSelf->GetQueueManager( &pQueueMgr );
  789. if ( FAILED(hr) )
  790. {
  791. if(hr == WMIMSG_E_REQSVCNOTAVAIL)
  792. pSelf->m_bMSMQDisabled = TRUE;
  793. return hr;
  794. }
  795. //
  796. // get all the persistent queues that are registered with MSMQ.
  797. // we filter based on our type guid.
  798. //
  799. LPWSTR* pwszNames;
  800. ULONG cNames;
  801. hr = pQueueMgr->GetAllNames( g_guidQueueType,
  802. TRUE,
  803. &pwszNames,
  804. &cNames );
  805. if ( FAILED(hr) )
  806. {
  807. if(hr == WMIMSG_E_REQSVCNOTAVAIL)
  808. pSelf->m_bMSMQDisabled = TRUE;
  809. return hr;
  810. }
  811. //
  812. // go through all the names.Recover ones that are registered as sinks.
  813. // destroy the ones that are aren't registered as sinks. Note that
  814. // that there is a possibility that a sink could get registered or
  815. // unregistered while we are doing this, however this case is fully
  816. // supported.
  817. //
  818. ULONG i;
  819. for(i=0; i < cNames; i++ )
  820. {
  821. DWORD dwQoS;
  822. WString wsSinkName;
  823. WString wsNamespace;
  824. hr = CQueueingEventSink::QueueNameToSinkName( pwszNames[i],
  825. wsSinkName,
  826. wsNamespace,
  827. dwQoS );
  828. if ( FAILED(hr) )
  829. {
  830. break;
  831. }
  832. //
  833. // obtain the namespace and from that obtain the sink.
  834. //
  835. CEssNamespace* pNamespace;
  836. CQueueingEventSink* pQueueingSink = NULL;
  837. {
  838. CInCritSec ics( &pSelf->m_cs );
  839. pNamespace = pSelf->m_mapNamespaces[wsNamespace];
  840. }
  841. if ( pNamespace != NULL )
  842. {
  843. pQueueingSink = pNamespace->GetQueueingEventSink(wsSinkName);
  844. }
  845. if ( pQueueingSink == NULL )
  846. {
  847. hr = pQueueMgr->Destroy( pwszNames[i] );
  848. //
  849. // the queue may be destroyed between the time we obtained the
  850. // name of the queue and now. This happens if a call to remove
  851. // the sink is made during recovery.
  852. //
  853. if ( FAILED(hr) )
  854. {
  855. if ( hr != WMIMSG_E_TARGETNOTFOUND )
  856. {
  857. break;
  858. }
  859. hr = WBEM_S_NO_ERROR;
  860. }
  861. }
  862. else
  863. {
  864. hr = pQueueingSink->Recover( pwszNames[i], dwQoS );
  865. }
  866. if ( FAILED(hr) )
  867. {
  868. ERRORTRACE((LOG_ESS, "Could not recover queue: %S , HR: 0x%x",
  869. pwszNames[i], hr));
  870. }
  871. }
  872. for(i=0; i < cNames; i++ )
  873. {
  874. CoTaskMemFree( pwszNames[i] );
  875. }
  876. CoTaskMemFree( pwszNames );
  877. }
  878. catch( ... )
  879. {
  880. ERRORTRACE((LOG_ESS, "Exception Thrown in Recovery Thread !!"));
  881. }
  882. return 0;
  883. }
  884. HRESULT CEss::DestroyPersistentQueue( LPCWSTR wszQueueName )
  885. {
  886. HRESULT hr;
  887. CWbemPtr<IWmiMessageQueueManager> pQueueMgr;
  888. hr = GetQueueManager( &pQueueMgr );
  889. if ( FAILED(hr) )
  890. {
  891. return hr;
  892. }
  893. return pQueueMgr->Destroy( wszQueueName );
  894. }
  895. HRESULT CEss::CreatePersistentQueue( LPCWSTR wszQueueName, DWORD dwQoS )
  896. {
  897. HRESULT hr;
  898. CWbemPtr<IWmiMessageQueueManager> pQueueMgr;
  899. hr = GetQueueManager( &pQueueMgr );
  900. if ( FAILED(hr) )
  901. {
  902. return hr;
  903. }
  904. //
  905. // TODO: SD should allow only local system access.
  906. //
  907. return pQueueMgr->Create( wszQueueName,
  908. g_guidQueueType,
  909. FALSE,
  910. dwQoS,
  911. INFINITE,
  912. NULL );
  913. }
  914. HRESULT CEss::InitiateRecovery()
  915. {
  916. HRESULT hr;
  917. //
  918. // perform actual recovery on a background thread. We want to
  919. // keep any interaction with msmq off the main initialization
  920. // thread. This is because we may need to wait for the msmq
  921. // service to come up.
  922. //
  923. m_hRecoveryThread = CreateThread( NULL,
  924. 0,
  925. PerformRecovery,
  926. this,
  927. 0,
  928. NULL );
  929. if ( m_hRecoveryThread == INVALID_HANDLE_VALUE )
  930. {
  931. m_hRecoveryThread = NULL;
  932. return HRESULT_FROM_WIN32( GetLastError() );
  933. }
  934. return WBEM_S_NO_ERROR;
  935. }
  936. #endif
  937. HRESULT CEss::Initialize( LPCWSTR wszServerName,
  938. long lFlags,
  939. _IWmiCoreServices* pCoreServices,
  940. IWbemDecorator* pDecorator )
  941. {
  942. HRESULT hres;
  943. try
  944. {
  945. m_EventLog.Open();
  946. hres = CoCreateInstance(CLSID_WbemTokenCache, NULL, CLSCTX_ALL,
  947. IID_IWbemTokenCache, (void**)&m_pTokenCache);
  948. if(FAILED(hres))
  949. {
  950. ERRORTRACE((LOG_ESS, "Cannot create a token cache: 0x%x\n", hres));
  951. return hres;
  952. }
  953. m_wszServerName = _new WCHAR[wcslen(wszServerName)+1];
  954. if(m_wszServerName == NULL)
  955. return WBEM_E_OUT_OF_MEMORY;
  956. wcscpy(m_wszServerName, wszServerName);
  957. m_pCoreServices = pCoreServices;
  958. m_pCoreServices->AddRef();
  959. //
  960. // Get provider subsystem and register our callback with it.
  961. //
  962. hres = m_pCoreServices->GetProviderSubsystem(0, &m_pProvSS);
  963. if( SUCCEEDED(hres) )
  964. {
  965. m_pProvSSSink = new CEssProvSSSink( this );
  966. if ( m_pProvSSSink == NULL )
  967. {
  968. return WBEM_E_OUT_OF_MEMORY;
  969. }
  970. m_pProvSSSink->AddRef();
  971. hres = m_pProvSS->RegisterNotificationSink( 0, NULL, m_pProvSSSink );
  972. if ( FAILED(hres) )
  973. {
  974. ERRORTRACE((LOG_ESS, "Failed to register notification sink "
  975. "with provider subsystem: 0x%X\n",hres));
  976. }
  977. }
  978. else
  979. {
  980. ERRORTRACE((LOG_ESS, "No provider subsystem: 0x%X\n", hres));
  981. }
  982. // Store the "decorator"
  983. // =====================
  984. m_pDecorator = pDecorator;
  985. m_pDecorator->AddRef();
  986. m_pDecorator->QueryInterface(IID_IWbemLifeControl, (void**)&m_pLifeControl);
  987. CInObjectCount ioc(this);
  988. // Connect to the default namespace
  989. // ================================
  990. IWbemServices* pRoot;
  991. hres = m_pCoreServices->GetServices(L"root", NULL,NULL,
  992. WMICORE_FLAG_REPOSITORY | WMICORE_CLIENT_TYPE_ESS,
  993. IID_IWbemServices, (void**)&pRoot);
  994. if(FAILED(hres)) return hres;
  995. CReleaseMe rm1(pRoot);
  996. // Pre-load event classes
  997. // ======================
  998. hres = CEventRepresentation::Initialize(pRoot, pDecorator);
  999. if(FAILED(hres)) return hres;
  1000. // Initialize aggregator
  1001. // =====================
  1002. CEventAggregator::Initialize(pRoot);
  1003. // Initialize timer instructions
  1004. // =============================
  1005. CConsumerProviderWatchInstruction::staticInitialize(pRoot);
  1006. CEventProviderWatchInstruction::staticInitialize(pRoot);
  1007. CConsumerWatchInstruction::staticInitialize(pRoot);
  1008. //
  1009. // construct an event announcing to the world that ESS is open for business
  1010. //
  1011. //
  1012. // Construct a security descriptor
  1013. //
  1014. CNtSecurityDescriptor SD;
  1015. SID_IDENTIFIER_AUTHORITY idNtAuthority = SECURITY_NT_AUTHORITY;
  1016. PSID pRawSid = NULL;
  1017. if(!AllocateAndInitializeSid(&idNtAuthority, 2,
  1018. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  1019. 0,0,0,0,0,0,&pRawSid))
  1020. {
  1021. return WBEM_E_OUT_OF_MEMORY;
  1022. }
  1023. CNtSid SidAdmins(pRawSid);
  1024. FreeSid(pRawSid);
  1025. pRawSid = NULL;
  1026. SID_IDENTIFIER_AUTHORITY idWorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1027. if(!AllocateAndInitializeSid( &idWorldAuthority, 1,
  1028. SECURITY_WORLD_RID,
  1029. 0, 0,0,0,0,0,0,&pRawSid))
  1030. {
  1031. return WBEM_E_OUT_OF_MEMORY;
  1032. }
  1033. CNtSid SidEveryone(pRawSid);
  1034. FreeSid(pRawSid);
  1035. CNtAce AceAdmins(EVENT_ALL_ACCESS, ACCESS_ALLOWED_ACE_TYPE, 0, SidAdmins);
  1036. CNtAce AceOthers(SYNCHRONIZE, ACCESS_ALLOWED_ACE_TYPE, 0, SidEveryone);
  1037. CNtAcl Acl;
  1038. if(!Acl.AddAce(&AceAdmins))
  1039. return WBEM_E_OUT_OF_MEMORY;
  1040. if(!Acl.AddAce(&AceOthers))
  1041. return WBEM_E_OUT_OF_MEMORY;
  1042. if(!SD.SetDacl(&Acl))
  1043. return WBEM_E_OUT_OF_MEMORY;
  1044. SECURITY_ATTRIBUTES sa;
  1045. sa.nLength = sizeof sa;
  1046. sa.lpSecurityDescriptor = SD.GetPtr();
  1047. sa.bInheritHandle = FALSE;
  1048. m_hReadyEvent = CreateEventW( &sa,
  1049. TRUE,
  1050. FALSE,
  1051. WBEM_ESS_OPEN_FOR_BUSINESS_EVENT_NAME );
  1052. if( m_hReadyEvent == NULL )
  1053. {
  1054. ERRORTRACE((LOG_ESS, "Unable to create 'ready' event: 0x%X\n",
  1055. GetLastError()));
  1056. return WBEM_E_CRITICAL_ERROR;
  1057. }
  1058. // Pre-load default namespace
  1059. // ==========================
  1060. LoadActiveNamespaces(pRoot, lFlags == WMIESS_INIT_REPOSITORY_RECOVERED );
  1061. CTemporaryHeap::Compact();
  1062. #ifdef __WHISTLER_UNCUT
  1063. //
  1064. // Now that all the namespaces have been initialized, initiate recovery
  1065. // of guaranteed delivery queues.
  1066. //
  1067. hres = InitiateRecovery();
  1068. if ( FAILED(hres) )
  1069. {
  1070. ERRORTRACE((LOG_ESS,
  1071. "Unable to initiate recovery of guaranteed delivery queues: 0x%X\n",
  1072. hres));
  1073. return WBEM_E_CRITICAL_ERROR;
  1074. }
  1075. #endif
  1076. #ifdef __DUMP_STATISTICS
  1077. #pragma message("Statistics dump in effect")
  1078. DWORD dw;
  1079. CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DumpThread,
  1080. this, 0, &dw));
  1081. #endif
  1082. //
  1083. // Initialize the quotas.
  1084. //
  1085. g_quotas.Init(this);
  1086. }
  1087. catch(...)
  1088. {
  1089. throw;
  1090. return WBEM_E_OUT_OF_MEMORY;
  1091. }
  1092. return WBEM_S_NO_ERROR;
  1093. }
  1094. void CEss::NotifyActiveNamespaceInitComplete()
  1095. {
  1096. _DBG_ASSERT( m_lOutstandingActiveNamespaceInit > 0 );
  1097. if ( InterlockedDecrement( &m_lOutstandingActiveNamespaceInit ) == 0 )
  1098. {
  1099. if ( SetEvent( m_hReadyEvent ) )
  1100. {
  1101. DEBUGTRACE((LOG_ESS,"ESS is now open for business.\n"));
  1102. }
  1103. else
  1104. {
  1105. ERRORTRACE((LOG_ESS,"ESS could not set ready event. res=%d\n",
  1106. GetLastError() ));
  1107. }
  1108. }
  1109. }
  1110. HRESULT CEss::CreateNamespaceObject( LPCWSTR wszNormName,
  1111. CEssNamespace** ppNamespace )
  1112. {
  1113. HRESULT hr;
  1114. *ppNamespace = NULL;
  1115. CWbemPtr<CEssNamespace> pNamespace = NULL;
  1116. try
  1117. {
  1118. pNamespace = new CEssNamespace(this);
  1119. }
  1120. catch(CX_MemoryException)
  1121. {
  1122. return WBEM_E_OUT_OF_MEMORY;
  1123. }
  1124. if( pNamespace == NULL )
  1125. {
  1126. return WBEM_E_OUT_OF_MEMORY;
  1127. }
  1128. hr = pNamespace->PreInitialize( wszNormName );
  1129. if ( FAILED(hr) )
  1130. {
  1131. return hr;
  1132. }
  1133. try
  1134. {
  1135. m_mapNamespaces[wszNormName] = pNamespace;
  1136. }
  1137. catch(CX_MemoryException)
  1138. {
  1139. return WBEM_E_OUT_OF_MEMORY;
  1140. }
  1141. pNamespace->AddRef(); // for the map
  1142. pNamespace->AddRef();
  1143. *ppNamespace = pNamespace;
  1144. return WBEM_S_NO_ERROR;
  1145. }
  1146. HRESULT CEss::GetNamespaceObject( LPCWSTR wszName,
  1147. BOOL bEnsureActivation,
  1148. CEssNamespace** ppNamespace)
  1149. {
  1150. HRESULT hres;
  1151. *ppNamespace = NULL;
  1152. CWbemPtr<CEssNamespace> pNamespace;
  1153. //
  1154. // need to normalize namespace name
  1155. //
  1156. LPWSTR wszNormName = NormalizeNamespaceString( wszName );
  1157. if ( wszNormName == NULL )
  1158. {
  1159. return WBEM_E_OUT_OF_MEMORY;
  1160. }
  1161. CVectorDeleteMe<WCHAR> dmwszNormName( wszNormName );
  1162. {
  1163. CInCritSec ics(&m_cs);
  1164. //
  1165. // Search the map
  1166. //
  1167. TNamespaceIterator it;
  1168. try
  1169. {
  1170. it = m_mapNamespaces.find(wszNormName);
  1171. }
  1172. catch (CX_MemoryException &)
  1173. {
  1174. return WBEM_E_OUT_OF_MEMORY;
  1175. };
  1176. if(it != m_mapNamespaces.end())
  1177. {
  1178. // Found it
  1179. // ========
  1180. pNamespace = it->second;
  1181. }
  1182. else
  1183. {
  1184. // Not found --- create a new one
  1185. // ==============================
  1186. hres = CreateNamespaceObject( wszNormName, &pNamespace );
  1187. if ( FAILED(hres) )
  1188. {
  1189. return hres;
  1190. }
  1191. }
  1192. }
  1193. //
  1194. // ensure that initialization is pending if necessary
  1195. //
  1196. if ( bEnsureActivation && pNamespace->MarkAsInitPendingIfQuiet() )
  1197. {
  1198. //
  1199. // kick off initialization for this namespace on another thread.
  1200. //
  1201. CNamespaceInitRequest* pReq;
  1202. pReq = new CNamespaceInitRequest( pNamespace, FALSE );
  1203. if ( pReq == NULL )
  1204. {
  1205. pNamespace->MarkAsInitialized( WBEM_E_OUT_OF_MEMORY );
  1206. return WBEM_E_OUT_OF_MEMORY;
  1207. }
  1208. hres = ScheduleNamespaceInitialize( pReq );
  1209. if ( FAILED(hres) )
  1210. {
  1211. delete pReq;
  1212. pNamespace->MarkAsInitialized( WBEM_E_OUT_OF_MEMORY );
  1213. return hres;
  1214. }
  1215. }
  1216. pNamespace->AddRef();
  1217. *ppNamespace = pNamespace;
  1218. return WBEM_S_NO_ERROR;
  1219. }
  1220. //
  1221. // Creates a namespace object for the specified namespace and adds it
  1222. // to the request object.
  1223. //
  1224. HRESULT CEss::PrepareNamespaceInitRequest( LPCWSTR wszNamespace,
  1225. CInitActiveNamespacesRequest* pRequest )
  1226. {
  1227. HRESULT hr = WBEM_S_NO_ERROR;
  1228. DEBUGTRACE((LOG_ESS,
  1229. "Preparing a namespace init request for active namespace %S\n",
  1230. wszNamespace ));
  1231. CWbemPtr<CEssNamespace> pNamespace;
  1232. LPWSTR wszNormName = NormalizeNamespaceString( wszNamespace );
  1233. if ( wszNormName != NULL )
  1234. {
  1235. hr = CreateNamespaceObject( wszNormName, &pNamespace );
  1236. if ( SUCCEEDED(hr) )
  1237. {
  1238. hr = pRequest->Add( pNamespace );
  1239. //
  1240. // make sure to tell the namespace that init is pending.
  1241. //
  1242. BOOL bIsPending = pNamespace->MarkAsInitPendingIfQuiet();
  1243. _DBG_ASSERT( bIsPending );
  1244. }
  1245. delete [] wszNormName;
  1246. }
  1247. else
  1248. {
  1249. hr = WBEM_E_OUT_OF_MEMORY;
  1250. }
  1251. if ( FAILED(hr) )
  1252. {
  1253. ERRORTRACE((LOG_ESS, "Error 0x%X occurred when preparing active "
  1254. "namespace %S for initialization \n", hr, wszNamespace ));
  1255. }
  1256. return hr;
  1257. }
  1258. //
  1259. // This method prepares a request object that will initialize the specified
  1260. // namespace and all descendent namespaces as if they were all active dependant
  1261. // namespaces. This is useful when the Active namespace information could not
  1262. // be obtained from the last shutdown.
  1263. //
  1264. HRESULT CEss::RecursivePrepareNamespaceInitRequests(
  1265. LPCWSTR wszNamespace,
  1266. IWbemServices* pSvc,
  1267. CInitActiveNamespacesRequest* pRequest )
  1268. {
  1269. HRESULT hr;
  1270. hr = PrepareNamespaceInitRequest( wszNamespace, pRequest );
  1271. if ( FAILED(hr) )
  1272. {
  1273. return hr;
  1274. }
  1275. //
  1276. // Enumerate all child namespaces and make recursive call for each
  1277. //
  1278. CWbemPtr<IEnumWbemClassObject> penumChildren;
  1279. hr = pSvc->CreateInstanceEnum( L"__NAMESPACE",
  1280. 0,
  1281. GetCurrentEssContext(),
  1282. &penumChildren );
  1283. if( FAILED(hr) )
  1284. {
  1285. ERRORTRACE((LOG_ESS, "Error 0x%X occurred enumerating child "
  1286. "namespaces of namespace %S. Some child namespaces may not be "
  1287. "active\n", hr, wszNamespace ));
  1288. //
  1289. // don't treat this as error, since this namespace was created and
  1290. // added to the request. Just no more work to do here.
  1291. //
  1292. return WBEM_S_NO_ERROR;
  1293. }
  1294. DWORD dwRead;
  1295. IWbemClassObject* pChildObj;
  1296. while((hr=penumChildren->Next(INFINITE, 1, &pChildObj, &dwRead)) == S_OK)
  1297. {
  1298. VARIANT vName;
  1299. VariantInit(&vName);
  1300. CClearMe cm1(&vName);
  1301. hr = pChildObj->Get( L"Name", 0, &vName, NULL, NULL );
  1302. pChildObj->Release();
  1303. if( FAILED(hr) )
  1304. {
  1305. return hr;
  1306. }
  1307. if ( V_VT(&vName) != VT_BSTR )
  1308. {
  1309. return WBEM_E_CRITICAL_ERROR;
  1310. }
  1311. //
  1312. // form the full name of the namespace
  1313. //
  1314. WString wsFullName;
  1315. try
  1316. {
  1317. wsFullName = wszNamespace;
  1318. wsFullName += L"\\";
  1319. wsFullName += V_BSTR(&vName);
  1320. }
  1321. catch( CX_MemoryException )
  1322. {
  1323. return WBEM_E_OUT_OF_MEMORY;
  1324. }
  1325. //
  1326. // get the svc ptr for the namespace. Must be repository only.
  1327. //
  1328. CWbemPtr<IWbemServices> pChildSvc;
  1329. long lFlags = WMICORE_FLAG_REPOSITORY | WMICORE_CLIENT_TYPE_ESS;
  1330. hr = m_pCoreServices->GetServices( wsFullName,NULL,NULL,
  1331. lFlags,
  1332. IID_IWbemServices,
  1333. (void**)&pChildSvc );
  1334. if ( SUCCEEDED(hr) )
  1335. {
  1336. //
  1337. // make the recursive call.
  1338. //
  1339. RecursivePrepareNamespaceInitRequests( wsFullName,
  1340. pChildSvc,
  1341. pRequest );
  1342. }
  1343. else
  1344. {
  1345. ERRORTRACE((LOG_ESS,
  1346. "Failed to open child namespace %S in %S: 0x%x\n",
  1347. V_BSTR(&vName), wszNamespace, hr));
  1348. }
  1349. }
  1350. return WBEM_S_NO_ERROR;
  1351. }
  1352. //
  1353. // This method prepares namespace init requests for active namespaces. It
  1354. // uses persisted information to determine the active namespaces. Each
  1355. // ActiveNamespaceInit request may contain multiple namespaces. This allows
  1356. // dependent namespaces to be initialized together. For now, all active
  1357. // namespaces are treated as inter-dependent - so only one request will be
  1358. // added to the list. If there is no persisted information about active
  1359. // namespaces, then all existing namespaces are treated as active dependent
  1360. // ones.
  1361. //
  1362. HRESULT CEss::PrepareNamespaceInitRequests( IWbemServices* pRoot,
  1363. BOOL bRediscover,
  1364. InitActiveNsRequestList& aRequests)
  1365. {
  1366. HRESULT hr = WBEM_S_NO_ERROR;
  1367. CInitActiveNamespacesRequest* pReq;
  1368. pReq = new CInitActiveNamespacesRequest(this);
  1369. if ( pReq == NULL )
  1370. {
  1371. return WBEM_E_OUT_OF_MEMORY;
  1372. }
  1373. //
  1374. // Get the list of active namespaces from the registry
  1375. //
  1376. LONG lRes;
  1377. DWORD dwDisp;
  1378. HKEY hkeyEss, hkeyNamespace;
  1379. lRes = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
  1380. WBEM_REG_ESS,
  1381. 0,
  1382. NULL,
  1383. REG_OPTION_NON_VOLATILE,
  1384. KEY_ALL_ACCESS,
  1385. NULL,
  1386. &hkeyEss,
  1387. &dwDisp );
  1388. if ( lRes == ERROR_SUCCESS )
  1389. {
  1390. if ( !bRediscover )
  1391. {
  1392. FILETIME ft;
  1393. DWORD dwIndex = 0;
  1394. DWORD dwBuffSize = 256;
  1395. LPWSTR wszName = new WCHAR[dwBuffSize];
  1396. DWORD cName = dwBuffSize;
  1397. if ( wszName == NULL )
  1398. {
  1399. hr = WBEM_E_OUT_OF_MEMORY;
  1400. }
  1401. while( SUCCEEDED(hr) && (lRes=RegEnumKeyExW( hkeyEss, dwIndex,
  1402. wszName, &cName, NULL,
  1403. NULL, NULL, &ft ) )
  1404. != ERROR_NO_MORE_ITEMS )
  1405. {
  1406. if ( lRes == ERROR_SUCCESS )
  1407. {
  1408. hr = PrepareNamespaceInitRequest( wszName, pReq );
  1409. dwIndex++;
  1410. }
  1411. else if ( lRes == ERROR_MORE_DATA )
  1412. {
  1413. dwBuffSize += 256;
  1414. delete [] wszName;
  1415. wszName = new WCHAR[dwBuffSize];
  1416. if ( wszName == NULL )
  1417. {
  1418. hr = WBEM_E_OUT_OF_MEMORY;
  1419. }
  1420. }
  1421. else
  1422. {
  1423. hr = HRESULT_FROM_WIN32( lRes );
  1424. }
  1425. cName = dwBuffSize;
  1426. }
  1427. delete [] wszName;
  1428. if ( FAILED(hr) )
  1429. {
  1430. ERRORTRACE((LOG_ESS,"Failed enumerating active namespaces. "
  1431. "Treating all namespaces as active. HR=0x%x\n", hr));
  1432. //
  1433. // reset our registry data. We'll rediscover it again.
  1434. //
  1435. RegDeleteSubKeysW( hkeyEss );
  1436. //
  1437. // Also need to reset request object to clear any requests
  1438. // that were added on this enumeration.
  1439. //
  1440. pReq->Reset();
  1441. }
  1442. }
  1443. else
  1444. {
  1445. //
  1446. // reset our registry data. We'll rediscover it again.
  1447. //
  1448. RegDeleteSubKeysW( hkeyEss );
  1449. hr = WBEM_S_FALSE;
  1450. }
  1451. RegCloseKey( hkeyEss );
  1452. }
  1453. else
  1454. {
  1455. hr = HRESULT_FROM_WIN32( lRes );
  1456. }
  1457. //
  1458. // If there was any problem or we just created the key for the
  1459. // first time or we are simply told to rediscover, then we have to recurse
  1460. // namespaces and discover.
  1461. //
  1462. if ( hr != WBEM_S_NO_ERROR || dwDisp != REG_OPENED_EXISTING_KEY )
  1463. {
  1464. DEBUGTRACE((LOG_ESS,"ESS Treating all namespaces as active during "
  1465. "Initialize\n"));
  1466. //
  1467. // recurse namespaces from root
  1468. //
  1469. RecursivePrepareNamespaceInitRequests( L"root", pRoot, pReq );
  1470. }
  1471. if ( aRequests.Add( pReq ) < 0 )
  1472. {
  1473. delete pReq;
  1474. return WBEM_E_OUT_OF_MEMORY;
  1475. }
  1476. return WBEM_S_NO_ERROR;
  1477. }
  1478. //
  1479. // This method schedules all active namespaces for initialization.
  1480. //
  1481. HRESULT CEss::LoadActiveNamespaces( IWbemServices* pRoot, BOOL bRediscover )
  1482. {
  1483. HRESULT hr;
  1484. InitActiveNsRequestList aRequests;
  1485. hr = PrepareNamespaceInitRequests( pRoot, bRediscover, aRequests );
  1486. if ( FAILED(hr) )
  1487. {
  1488. return hr;
  1489. }
  1490. //
  1491. // hold an active namespace init count while we schedule requests.
  1492. // this will keep ess from transitioning to ready until it has
  1493. // scheduled all requests.
  1494. //
  1495. m_lOutstandingActiveNamespaceInit = 1;
  1496. for( int i=0; i < aRequests.GetSize(); i++ )
  1497. {
  1498. int cNamespaces = aRequests[i]->GetNumNamespaces();
  1499. if ( cNamespaces > 0 )
  1500. {
  1501. InterlockedExchangeAdd( &m_lOutstandingActiveNamespaceInit,
  1502. cNamespaces );
  1503. }
  1504. hr = ScheduleNamespaceInitialize( aRequests[i] );
  1505. if ( FAILED(hr) )
  1506. {
  1507. InterlockedExchangeAdd( &m_lOutstandingActiveNamespaceInit,
  1508. 0-cNamespaces );
  1509. delete aRequests[i];
  1510. }
  1511. }
  1512. NotifyActiveNamespaceInitComplete();
  1513. return WBEM_S_NO_ERROR;
  1514. }
  1515. //
  1516. // This method schedules a namespace init request. It handles deferring
  1517. // initialization if the machine is currently booting. If the request
  1518. // is known to only initialize inactive namespaces, then we do not defer
  1519. // initialization even in the boot phase. This is so we don't cause events
  1520. // in inactive namespaces to be queued up while we're waiting for the deferred
  1521. // initialization to complete.
  1522. //
  1523. HRESULT CEss::ScheduleNamespaceInitialize( CExecRequest* pRequest )
  1524. {
  1525. DWORD dwTickCount = GetTickCount();
  1526. if ( dwTickCount >= BOOT_PHASE_MS )
  1527. {
  1528. HRESULT hres = Enqueue(pRequest);
  1529. if( FAILED(hres) )
  1530. {
  1531. return hres;
  1532. }
  1533. return WBEM_S_NO_ERROR;
  1534. }
  1535. if ( m_hExitBootPhaseTimer == NULL )
  1536. {
  1537. //
  1538. // cause a timer to be fired that will activate the thread queue
  1539. // after we're out of the boot phase.
  1540. //
  1541. if ( !CreateTimerQueueTimer( &m_hExitBootPhaseTimer,
  1542. NULL,
  1543. ExitBootPhaseCallback,
  1544. this,
  1545. BOOT_PHASE_MS-dwTickCount,
  1546. 0,
  1547. WT_EXECUTEINTIMERTHREAD ) )
  1548. {
  1549. return HRESULT_FROM_WIN32( GetLastError() );
  1550. }
  1551. }
  1552. if ( m_aDeferredNSInitRequests.Add( pRequest ) < 0 )
  1553. {
  1554. return WBEM_E_OUT_OF_MEMORY;
  1555. }
  1556. return WBEM_S_FALSE;
  1557. }
  1558. void CALLBACK CEss::ExitBootPhaseCallback( LPVOID pvThis, BOOLEAN )
  1559. {
  1560. DEBUGTRACE((LOG_ESS, "Exiting Boot Phase.\n" ));
  1561. ((CEss*)pvThis)->ExecuteDeferredNSInitRequests();
  1562. }
  1563. void CEss::ExecuteDeferredNSInitRequests()
  1564. {
  1565. HRESULT hr;
  1566. CInCritSec ics( &m_cs );
  1567. for( int i=0; i < m_aDeferredNSInitRequests.GetSize(); i++ )
  1568. {
  1569. hr = Enqueue( m_aDeferredNSInitRequests[i] );
  1570. if ( FAILED(hr) )
  1571. {
  1572. ERRORTRACE((LOG_ESS, "Critical Error. Could not enqueue "
  1573. "deferred namespace init requests\n"));
  1574. delete m_aDeferredNSInitRequests[i];
  1575. }
  1576. }
  1577. m_aDeferredNSInitRequests.RemoveAll();
  1578. }
  1579. void CEss::TriggerDeferredInitialization()
  1580. {
  1581. if ( GetTickCount() >= BOOT_PHASE_MS )
  1582. {
  1583. //
  1584. // avoid calling execute() if possible since it grabs an ess wide cs.
  1585. //
  1586. return;
  1587. }
  1588. DEBUGTRACE((LOG_ESS, "Triggering ESS Namespace Requests "
  1589. "during Boot phase\n" ));
  1590. ExecuteDeferredNSInitRequests();
  1591. }
  1592. HRESULT CEss::GetNamespacePointer( LPCWSTR wszNamespace,
  1593. BOOL bRepositoryOnly,
  1594. RELEASE_ME IWbemServices** ppNamespace )
  1595. {
  1596. HRESULT hres;
  1597. if( m_pLocator == NULL )
  1598. {
  1599. if( m_pCoreServices != NULL )
  1600. {
  1601. long lFlags = WMICORE_CLIENT_TYPE_ESS;
  1602. if ( bRepositoryOnly )
  1603. {
  1604. lFlags |= WMICORE_FLAG_REPOSITORY;
  1605. }
  1606. hres = m_pCoreServices->GetServices( wszNamespace, NULL,NULL,
  1607. lFlags,
  1608. IID_IWbemServices,
  1609. (void**)ppNamespace );
  1610. }
  1611. else
  1612. {
  1613. hres = WBEM_E_CRITICAL_ERROR;
  1614. }
  1615. }
  1616. else
  1617. {
  1618. BSTR strNamespace = SysAllocString(wszNamespace);
  1619. hres = m_pLocator->ConnectServer( strNamespace, NULL, NULL, 0, 0, NULL,
  1620. NULL, ppNamespace);
  1621. SysFreeString(strNamespace);
  1622. if ( SUCCEEDED(hres) )
  1623. {
  1624. hres = WBEM_S_FALSE;
  1625. }
  1626. }
  1627. return hres;
  1628. }
  1629. HRESULT CEss::ReloadProvider( long lFlags,
  1630. LPCWSTR wszNamespace,
  1631. LPCWSTR wszProvider )
  1632. {
  1633. HRESULT hr;
  1634. try
  1635. {
  1636. CInObjectCount ioc(this);
  1637. CWbemPtr<CEssNamespace> pNamespace;
  1638. hr = GetNamespaceObject( wszNamespace, FALSE, &pNamespace);
  1639. if ( SUCCEEDED(hr) )
  1640. {
  1641. DEBUGTRACE((LOG_ESS,"Reloading Provider %S in namespace %S at "
  1642. "request of external subsystem\n ",
  1643. wszProvider, wszNamespace ));
  1644. hr = pNamespace->ReloadProvider( lFlags, wszProvider );
  1645. }
  1646. }
  1647. catch( CX_MemoryException )
  1648. {
  1649. hr = WBEM_E_OUT_OF_MEMORY;
  1650. }
  1651. return hr;
  1652. }
  1653. //******************************************************************************
  1654. // public
  1655. //
  1656. // See ess.h for documentation
  1657. //
  1658. //******************************************************************************
  1659. HRESULT CEss::ProcessEvent(READ_ONLY CEventRepresentation& Event, long lFlags)
  1660. {
  1661. HRESULT hres;
  1662. try
  1663. {
  1664. CInObjectCount ioc(this);
  1665. // Find the right namespace object
  1666. // ===============================
  1667. CEssNamespace* pNamespace = NULL;
  1668. hres = GetNamespaceObject(Event.wsz1, FALSE, &pNamespace);
  1669. if(FAILED(hres))
  1670. return hres;
  1671. CTemplateReleaseMe<CEssNamespace> rm1(pNamespace);
  1672. // Get it to process the event
  1673. // ===========================
  1674. return pNamespace->ProcessEvent(Event, lFlags);
  1675. }
  1676. catch(...)
  1677. {
  1678. throw;
  1679. return WBEM_E_OUT_OF_MEMORY;
  1680. }
  1681. }
  1682. HRESULT CEss::ProcessQueryObjectSinkEvent( READ_ONLY CEventRepresentation& Event )
  1683. {
  1684. HRESULT hres;
  1685. try
  1686. {
  1687. CInObjectCount ioc(this);
  1688. //
  1689. // Find the right namespace object
  1690. //
  1691. CEssNamespace* pNamespace = NULL;
  1692. hres = GetNamespaceObject(Event.wsz1, FALSE, &pNamespace);
  1693. if( FAILED( hres ) )
  1694. {
  1695. return hres;
  1696. }
  1697. CTemplateReleaseMe<CEssNamespace> rm1(pNamespace);
  1698. //
  1699. // Get it to process the event
  1700. //
  1701. return pNamespace->ProcessQueryObjectSinkEvent( Event );
  1702. }
  1703. catch(...)
  1704. {
  1705. throw;
  1706. return WBEM_E_OUT_OF_MEMORY;
  1707. }
  1708. }
  1709. HRESULT CEss::VerifyInternalEvent(READ_ONLY CEventRepresentation& Event)
  1710. {
  1711. HRESULT hres;
  1712. try
  1713. {
  1714. CInObjectCount ioc(this);
  1715. // Find the right namespace object
  1716. // ===============================
  1717. CEssNamespace* pNamespace = NULL;
  1718. hres = GetNamespaceObject(Event.wsz1, FALSE, &pNamespace);
  1719. if(FAILED(hres))
  1720. return hres;
  1721. CTemplateReleaseMe<CEssNamespace> rm1(pNamespace);
  1722. // Get it to process the event
  1723. // ===========================
  1724. return pNamespace->ValidateSystemEvent(Event);
  1725. }
  1726. catch(...)
  1727. {
  1728. throw;
  1729. return WBEM_E_OUT_OF_MEMORY;
  1730. }
  1731. }
  1732. HRESULT CEss::RegisterNotificationSink( WBEM_CWSTR wszNamespace,
  1733. WBEM_CWSTR wszQueryLanguage,
  1734. WBEM_CWSTR wszQuery,
  1735. long lFlags,
  1736. IWbemContext* pContext,
  1737. IWbemObjectSink* pSink )
  1738. {
  1739. HRESULT hres;
  1740. try
  1741. {
  1742. if(_wcsicmp(wszQueryLanguage, L"WQL"))
  1743. return WBEM_E_INVALID_QUERY_TYPE;
  1744. CInObjectCount ioc(this);
  1745. // Find the right namespace object
  1746. // ===============================
  1747. CEssNamespace* pNamespace = NULL;
  1748. hres = GetNamespaceObject(wszNamespace, FALSE, &pNamespace);
  1749. if(FAILED(hres))
  1750. return hres;
  1751. CTemplateReleaseMe<CEssNamespace> rm1(pNamespace);
  1752. // Get the object to do it
  1753. // =======================
  1754. HRESULT hr;
  1755. hr = pNamespace->RegisterNotificationSink( wszQueryLanguage,
  1756. wszQuery,
  1757. lFlags,
  1758. WMIMSG_FLAG_QOS_EXPRESS,
  1759. pContext,
  1760. pSink );
  1761. return hr;
  1762. }
  1763. catch(...)
  1764. {
  1765. throw;
  1766. return WBEM_E_OUT_OF_MEMORY;
  1767. }
  1768. }
  1769. HRESULT CEss::RemoveNotificationSink(IWbemObjectSink* pSink)
  1770. {
  1771. HRESULT hres;
  1772. try
  1773. {
  1774. CInObjectCount ioc(this);
  1775. // Create a list of AddRefed namespace objects that we can use
  1776. // ===========================================================
  1777. CRefedPointerArray<CEssNamespace> apNamespaces;
  1778. {
  1779. CInCritSec ics(&m_cs);
  1780. for(TNamespaceIterator it = m_mapNamespaces.begin();
  1781. it != m_mapNamespaces.end();
  1782. it++)
  1783. {
  1784. if(apNamespaces.Add(it->second) < 0)
  1785. return WBEM_E_OUT_OF_MEMORY;
  1786. }
  1787. }
  1788. // Get all of them to remove this sink
  1789. // ===================================
  1790. HRESULT hresGlobal = WBEM_E_NOT_FOUND;
  1791. for(int i = 0; i < apNamespaces.GetSize(); i++)
  1792. {
  1793. hres = apNamespaces[i]->RemoveNotificationSink(pSink);
  1794. if(FAILED(hres))
  1795. {
  1796. if(hres != WBEM_E_NOT_FOUND)
  1797. {
  1798. // Actual error --- take note
  1799. // ==========================
  1800. hresGlobal = hres;
  1801. }
  1802. }
  1803. else
  1804. {
  1805. // Found some
  1806. // ==========
  1807. if(hresGlobal == WBEM_E_NOT_FOUND)
  1808. hresGlobal = WBEM_S_NO_ERROR;
  1809. }
  1810. }
  1811. return hresGlobal;
  1812. }
  1813. catch(...)
  1814. {
  1815. throw;
  1816. return WBEM_E_OUT_OF_MEMORY;
  1817. }
  1818. }
  1819. HRESULT CEss::PurgeNamespace(LPCWSTR wszNamespace)
  1820. {
  1821. LPWSTR wszNormName = NormalizeNamespaceString( wszNamespace );
  1822. if ( wszNormName == NULL )
  1823. {
  1824. return WBEM_E_OUT_OF_MEMORY;
  1825. }
  1826. CVectorDeleteMe<WCHAR> dmwszNormName( wszNormName );
  1827. CEssNamespace* pNamespace = NULL;
  1828. {
  1829. CInCritSec ics(&m_cs);
  1830. // Purge it from the timer generator
  1831. // =================================
  1832. m_TimerGenerator.Remove(wszNormName);
  1833. // Find it in the map
  1834. // ==================
  1835. TNamespaceIterator it;
  1836. try
  1837. {
  1838. it = m_mapNamespaces.find(wszNormName);
  1839. }
  1840. catch (CX_MemoryException &)
  1841. {
  1842. return WBEM_E_OUT_OF_MEMORY;
  1843. };
  1844. if(it == m_mapNamespaces.end())
  1845. return WBEM_S_FALSE;
  1846. // Keep it for later
  1847. // =================
  1848. pNamespace = it->second;
  1849. // Remove it from the map
  1850. // ======================
  1851. m_mapNamespaces.erase(it);
  1852. }
  1853. // Wait for initialization to complete
  1854. // ===================================
  1855. pNamespace->Shutdown();
  1856. pNamespace->Release();
  1857. return WBEM_S_NO_ERROR;
  1858. }
  1859. HRESULT CEss::DecorateObject(IWbemClassObject* pObj, LPCWSTR wszNamespace)
  1860. {
  1861. return CEventRepresentation::mstatic_pDecorator->DecorateObject(pObj,
  1862. (LPWSTR)wszNamespace);
  1863. }
  1864. HRESULT CEss::AddSleepCharge(DWORD dwSleep)
  1865. {
  1866. if(dwSleep)
  1867. Sleep(dwSleep);
  1868. return S_OK;
  1869. }
  1870. HRESULT CEss::AddCache()
  1871. {
  1872. return m_LimitControl.AddMember();
  1873. }
  1874. HRESULT CEss::RemoveCache()
  1875. {
  1876. return m_LimitControl.RemoveMember();
  1877. }
  1878. HRESULT CEss::AddToCache(DWORD dwAdd, DWORD dwMemberTotal, DWORD* pdwSleep)
  1879. {
  1880. DWORD dwSleep;
  1881. HRESULT hres = m_LimitControl.Add(dwAdd, dwMemberTotal, &dwSleep);
  1882. if(SUCCEEDED(hres))
  1883. {
  1884. if(pdwSleep)
  1885. *pdwSleep = dwSleep;
  1886. else
  1887. AddSleepCharge(dwSleep);
  1888. }
  1889. return hres;
  1890. }
  1891. HRESULT CEss::RemoveFromCache(DWORD dwRemove)
  1892. {
  1893. return m_LimitControl.Remove(dwRemove);
  1894. }
  1895. void CEss::IncrementObjectCount()
  1896. {
  1897. InterlockedIncrement(&m_lObjectCount);
  1898. if(m_pLifeControl)
  1899. m_pLifeControl->AddRefCore();
  1900. }
  1901. void CEss::DecrementObjectCount()
  1902. {
  1903. if(InterlockedDecrement(&m_lObjectCount) == 0)
  1904. {
  1905. // No need to purge the cache --- David knows I am ready to unload
  1906. }
  1907. if(m_pLifeControl)
  1908. m_pLifeControl->ReleaseCore();
  1909. }
  1910. HRESULT CEss::InitializeTimerGenerator(LPCWSTR wszNamespace,
  1911. IWbemServices* pNamespace)
  1912. {
  1913. return GetTimerGenerator().LoadTimerEventQueue(wszNamespace, pNamespace);
  1914. }
  1915. HRESULT CEss::EnqueueDeliver(CQueueingEventSink* pDest)
  1916. {
  1917. return m_Queue.EnqueueDeliver(pDest);
  1918. }
  1919. HRESULT CEss::Enqueue(CExecRequest* pReq)
  1920. {
  1921. return m_Queue.Enqueue(pReq);
  1922. }
  1923. HRESULT CEss::GetToken(PSID pSid, IWbemToken** ppToken)
  1924. {
  1925. return m_pTokenCache->GetToken((BYTE*)pSid, ppToken);
  1926. }
  1927. void CEss::DumpStatistics(FILE* f, long lFlags)
  1928. {
  1929. CInCritSec ics(&m_cs);
  1930. time_t t;
  1931. time(&t);
  1932. struct tm* ptm = localtime(&t);
  1933. fprintf(f, "Statistics at %s", asctime(ptm));
  1934. time(&t);
  1935. ptm = localtime(&t);
  1936. fprintf(f, "Commence at %s", asctime(ptm));
  1937. for(TNamespaceIterator it = m_mapNamespaces.begin();
  1938. it != m_mapNamespaces.end(); it++)
  1939. {
  1940. it->second->DumpStatistics(f, lFlags);
  1941. }
  1942. time(&t);
  1943. ptm = localtime(&t);
  1944. fprintf(f, "Done at %s\n", asctime(ptm));
  1945. }
  1946. HRESULT CEss::GetProviderFactory( LPCWSTR wszNamespaceName,
  1947. IWbemServices* pNamespace,
  1948. RELEASE_ME _IWmiProviderFactory** ppFactory )
  1949. {
  1950. HRESULT hres;
  1951. *ppFactory = NULL;
  1952. if ( m_pProvSS == NULL )
  1953. {
  1954. ERRORTRACE((LOG_ESS, "Trying to get Provider Factory, but "
  1955. "No provider subsystem!!\n"));
  1956. return WBEM_E_CRITICAL_ERROR;
  1957. }
  1958. //
  1959. // Get IWbemServicesEx, just for Steve
  1960. //
  1961. IWbemServicesEx* pEx;
  1962. hres = pNamespace->QueryInterface(IID_IWbemServicesEx, (void**)&pEx);
  1963. if(FAILED(hres))
  1964. {
  1965. ERRORTRACE((LOG_ESS, "No Ex interface: 0x%X\n", hres));
  1966. return hres;
  1967. }
  1968. CReleaseMe rm1(pEx);
  1969. //
  1970. // Get Provider factory
  1971. //
  1972. hres = m_pProvSS->Create( pEx,
  1973. 0,
  1974. GetCurrentEssContext(),
  1975. wszNamespaceName,
  1976. IID__IWmiProviderFactory,
  1977. (void**)ppFactory );
  1978. if(FAILED(hres))
  1979. {
  1980. ERRORTRACE((LOG_ESS, "No provider factory: 0x%X\n", hres));
  1981. }
  1982. return hres;
  1983. }