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.

1029 lines
26 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
  4. //
  5. /////////////////////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include <aclapi.h>
  8. #include <groupsforuser.h>
  9. #include <sql_1.h>
  10. #include <flexq.h>
  11. static CFlexArray g_apRequests; // Shared between all CWMIEvent instances to provide a master event list
  12. extern CCriticalSection * g_pEventCs;
  13. extern CCriticalSection * g_pListCs;
  14. #include <helper.h>
  15. typedef WaitExceptionPtrFnc < CCriticalSection*, void ( CCriticalSection::* ) (), CCriticalSection::Enter, 1000 > EnterCS;
  16. typedef LeavePtrFnc < CCriticalSection*, void ( CCriticalSection::* ) (), CCriticalSection::Leave > LeaveCS;
  17. ////////////////////////////////////////////////////////////////////////////////////////////////
  18. class CFlexQueueEx : public CFlexQueue
  19. {
  20. public:
  21. void ResetQueue()
  22. {
  23. delete [] m_ppData;
  24. m_ppData = NULL;
  25. m_nSize = m_nHeadIndex = m_nTailIndex = 0;
  26. }
  27. };
  28. CFlexQueueEx Q;
  29. ////////////////////////////////////////////////////////////////////////////////////////////////
  30. void WINAPI EventCallbackRoutine(PWNODE_HEADER WnodeHeader, ULONG_PTR Context)
  31. {
  32. HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  33. bool bQueued = FALSE;
  34. if( SUCCEEDED( hr ) )
  35. {
  36. try
  37. {
  38. PWNODE_HEADER * pEventHeader = NULL;
  39. //scope the use of the critsec...
  40. {
  41. CAutoBlock block (g_pListCs);
  42. // Create a queue
  43. pEventHeader = new PWNODE_HEADER;
  44. if( pEventHeader )
  45. {
  46. *pEventHeader = WnodeHeader;
  47. bQueued = Q.Enqueue(pEventHeader);
  48. }
  49. }
  50. //
  51. // The following code will be rarely called when the Queue
  52. // does not grow due to memory exhaustion.
  53. //
  54. if( FALSE == bQueued ) {
  55. ((CWMIEvent*) Context)->WMIEventCallback(*pEventHeader);
  56. delete pEventHeader;
  57. }
  58. while( TRUE )
  59. {
  60. //scope the use of the critsec...
  61. {
  62. CAutoBlock block( g_pListCs );
  63. if( Q.GetQueueSize() == 0 )
  64. {
  65. Q.ResetQueue();
  66. break;
  67. }
  68. pEventHeader = (PWNODE_HEADER *) Q.Dequeue();
  69. if (pEventHeader == 0)
  70. {
  71. break;
  72. }
  73. }
  74. CWMIEvent * p = (CWMIEvent* ) Context;
  75. p->WMIEventCallback(*pEventHeader);
  76. }
  77. }
  78. catch( ... )
  79. {
  80. //don't throw outside of the provider, also make sure CoUninitialize happens...
  81. }
  82. CoUninitialize();
  83. }
  84. }
  85. /////////////////////////////////////////////////////////////////////
  86. void CWMIEvent::SetEventHandler(IWbemObjectSink __RPC_FAR * pHandler)
  87. {
  88. CAutoBlock Block(g_pEventCs);
  89. if( m_pEventHandler )
  90. {
  91. m_pEventHandler->Release();
  92. }
  93. m_pEventHandler = pHandler;
  94. if( m_pEventHandler )
  95. {
  96. m_pEventHandler->AddRef();
  97. }
  98. }
  99. /////////////////////////////////////////////////////////////////////
  100. void CWMIEvent::SetEventServices(IWbemServices __RPC_FAR * pServices)
  101. {
  102. CAutoBlock Block(g_pEventCs);
  103. if( m_pEventServices )
  104. {
  105. m_pEventServices->Release();
  106. }
  107. m_pEventServices = pServices;
  108. if( m_pEventServices )
  109. {
  110. m_pEventServices->AddRef();
  111. }
  112. }
  113. /////////////////////////////////////////////////////////////////////
  114. void CWMIEvent::SetEventRepository(IWbemServices __RPC_FAR * pServices)
  115. {
  116. CAutoBlock Block(g_pEventCs);
  117. if( m_pEventRepository )
  118. {
  119. m_pEventRepository->Release();
  120. }
  121. m_pEventRepository = pServices;
  122. if( m_pEventRepository )
  123. {
  124. m_pEventRepository->AddRef();
  125. }
  126. }
  127. /////////////////////////////////////////////////////////////////////
  128. void CWMIEvent::SetEventContext(IWbemContext __RPC_FAR * pCtx)
  129. {
  130. CAutoBlock Block(g_pEventCs);
  131. if( m_pEventCtx )
  132. {
  133. m_pEventCtx->Release();
  134. }
  135. m_pEventCtx = pCtx;
  136. if( m_pEventCtx )
  137. {
  138. m_pEventCtx->AddRef();
  139. }
  140. }
  141. ////////////////////////////////////////////////////////////////////////
  142. CWMIEvent::CWMIEvent(int nType) :
  143. m_nType ( nType ) ,
  144. m_pEventHandler ( NULL ) ,
  145. m_pEventServices ( NULL ) ,
  146. m_pEventRepository ( NULL ) ,
  147. m_pEventCtx ( NULL ) ,
  148. m_bInitialized ( FALSE )
  149. {
  150. if ( TRUE == ( m_bInitialized = m_HandleMap.IsValid () ) )
  151. {
  152. m_lRef = 0;
  153. if( m_nType != INTERNAL_EVENT )
  154. {
  155. InterlockedIncrement(&g_cObj);
  156. }
  157. }
  158. }
  159. ////////////////////////////////////////////////////////////////////////
  160. CWMIEvent::~CWMIEvent()
  161. {
  162. if ( m_bInitialized )
  163. {
  164. ReleaseAllPointers ();
  165. if( m_nType != INTERNAL_EVENT )
  166. {
  167. InterlockedDecrement(&g_cObj);
  168. }
  169. }
  170. }
  171. void CWMIEvent::ReleaseAllPointers()
  172. {
  173. IWbemObjectSink * pHandler = NULL;
  174. IWbemServices * pServices = NULL;
  175. IWbemServices * pRepository = NULL;
  176. IWbemContext * pCtx = NULL;
  177. {
  178. CAutoBlock Block(g_pEventCs);
  179. pHandler = m_pEventHandler;
  180. pServices = m_pEventServices;
  181. pRepository = m_pEventRepository;
  182. pCtx = m_pEventCtx;
  183. m_pEventCtx = NULL;
  184. m_pEventServices = NULL;
  185. m_pEventRepository = NULL;
  186. m_pEventHandler = NULL;
  187. }
  188. SAFE_RELEASE_PTR( pHandler );
  189. SAFE_RELEASE_PTR( pServices );
  190. SAFE_RELEASE_PTR( pRepository );
  191. SAFE_RELEASE_PTR( pCtx );
  192. }
  193. ////////////////////////////////////////////////////////////////////////
  194. BOOL CWMIEvent::RegisterForInternalEvents( )
  195. {
  196. BOOL fRc = FALSE;
  197. if( SUCCEEDED(RegisterForRequestedEvent(BINARY_MOF_ID,RUNTIME_BINARY_MOFS_ADDED,MOF_ADDED)))
  198. {
  199. if( SUCCEEDED(RegisterForRequestedEvent(BINARY_MOF_ID,RUNTIME_BINARY_MOFS_DELETED,MOF_DELETED)))
  200. {
  201. fRc = TRUE;
  202. }
  203. }
  204. if ( FALSE == fRc )
  205. {
  206. //
  207. // must clear global object so next
  208. // initialization will have a chance
  209. //
  210. DeleteBinaryMofResourceEvent () ;
  211. }
  212. return fRc;
  213. }
  214. ////////////////////////////////////////////////////////////////////////
  215. HRESULT CWMIEvent::RemoveWMIEvent(DWORD dwId)
  216. {
  217. HRESULT hr = S_OK;
  218. if( m_nType == WMIEVENT )
  219. {
  220. hr = CheckImpersonationLevel();
  221. }
  222. else
  223. {
  224. HRESULT t_TempResult = RevertToSelf();
  225. #ifdef DBG
  226. if ( FAILED ( t_TempResult ) )
  227. {
  228. DebugBreak();
  229. }
  230. #endif DBG
  231. }
  232. if( SUCCEEDED(hr))
  233. {
  234. CWMIManagement WMI;
  235. EnterCS ecs ( g_pEventCs );
  236. LeaveCS lcs ( g_pEventCs );
  237. // ================================
  238. // Remove all requests with this Id
  239. // ================================
  240. int nSize = g_apRequests.Size();
  241. int i = 0;
  242. while( i < nSize )
  243. {
  244. WMIEventRequest* pReq = (WMIEventRequest*) g_apRequests[i];
  245. //
  246. // we are about to remove standard events in this call
  247. // that means we must skip hardcoded handles
  248. //
  249. if( ( !IsBinaryMofResourceEvent ( WMI_RESOURCE_MOF_ADDED_GUID,pReq->gGuid ) ) &&
  250. ( !IsBinaryMofResourceEvent ( WMI_RESOURCE_MOF_REMOVED_GUID,pReq->gGuid ) ) )
  251. {
  252. if(pReq->dwId == dwId)
  253. {
  254. g_apRequests.RemoveAt(i);
  255. //
  256. // leave critical section as the same critical
  257. // section is used inside of the event callback
  258. //
  259. //
  260. // left mark for scope deletion of lcs FALSE
  261. // as we will re-enter the same critical section
  262. //
  263. // CancelWMIEventRegistartion nor
  264. // NoMoreEventConsumersRegistered doesn't throw exception !
  265. //
  266. lcs.Exec( FALSE );
  267. // Inform WMI we don't want this anymore as
  268. // long as there are no more these guids in
  269. // the list, there might be more than one
  270. // event consumer registered.
  271. // =========================================
  272. //
  273. // check agains 0 as we have removed from list already
  274. //
  275. if( NoMoreEventConsumersRegistered( pReq->gGuid ) == 0 )
  276. {
  277. ULONG_PTR uRc =(ULONG_PTR)this;
  278. WMI.CancelWMIEventRegistration(pReq->gGuid,uRc);
  279. }
  280. delete pReq;
  281. pReq = NULL;
  282. //
  283. // re-enter the same critical section here
  284. // its flag of execution is FALSE which means
  285. // that it will be left final time by destructor
  286. // of LeaveCS data type ( lcs )
  287. //
  288. EnterCS ecs1 ( g_pEventCs );
  289. nSize = g_apRequests.Size();
  290. }
  291. else
  292. {
  293. i++;
  294. }
  295. }
  296. else
  297. {
  298. i++;
  299. }
  300. }
  301. }
  302. CheckImpersonationLevel();
  303. return WBEM_S_NO_ERROR;
  304. }
  305. ////////////////////////////////////////////////////////////////////////
  306. HRESULT CWMIEvent::DeleteBinaryMofResourceEvent()
  307. {
  308. HRESULT t_TempResult = RevertToSelf();
  309. #ifdef DBG
  310. if ( FAILED ( t_TempResult ) )
  311. {
  312. DebugBreak();
  313. }
  314. #endif DBG
  315. CWMIManagement WMI;
  316. EnterCS ecs ( g_pEventCs );
  317. LeaveCS lcs ( g_pEventCs );
  318. // Remove all requests with this Id
  319. // ================================
  320. int nSize = g_apRequests.Size();
  321. int i = 0;
  322. while( i < nSize ){
  323. WMIEventRequest* pReq = (WMIEventRequest*) g_apRequests[i];
  324. if( ( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,pReq->gGuid)) ||
  325. ( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,pReq->gGuid)))
  326. {
  327. g_apRequests.RemoveAt(i);
  328. //
  329. // leave critical section as the same critical
  330. // section is used inside of the event callback
  331. //
  332. //
  333. // left mark for scope deletion of lcs FALSE
  334. // as we will re-enter the same critical section
  335. //
  336. // CancelWMIEventRegistartion doesn't throw exception !
  337. //
  338. lcs.Exec( FALSE );
  339. ULONG_PTR uRc =(ULONG_PTR)this;
  340. WMI.CancelWMIEventRegistration(pReq->gGuid,uRc);
  341. delete pReq;
  342. pReq = NULL;
  343. //
  344. // re-enter the same critical section here
  345. // its flag of execution is FALSE which means
  346. // that it will be left final time by destructor
  347. // of LeaveCS data type ( lcs )
  348. //
  349. EnterCS ecs1 ( g_pEventCs );
  350. nSize = g_apRequests.Size();
  351. }
  352. else
  353. {
  354. i++;
  355. }
  356. }
  357. CheckImpersonationLevel();
  358. return WBEM_S_NO_ERROR;
  359. }
  360. ////////////////////////////////////////////////////////////////////////
  361. int CWMIEvent::NoMoreEventConsumersRegistered(GUID gGuid)
  362. {
  363. EnterCS ecs(g_pEventCs);
  364. LeaveCS lcs(g_pEventCs);
  365. int nTotalNumberOfRegisteredEventConsumers = 0;
  366. WMIEventRequest * pEvent;
  367. for(int i = 0; i < g_apRequests.Size(); i++)
  368. {
  369. pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
  370. if( pEvent->gGuid == gGuid)
  371. {
  372. nTotalNumberOfRegisteredEventConsumers++;
  373. }
  374. }
  375. return nTotalNumberOfRegisteredEventConsumers;
  376. }
  377. ////////////////////////////////////////////////////////////////////////
  378. BOOL CWMIEvent::IsGuidInListIfSoGetCorrectContext(GUID gGuid, WMIEventRequest *& pEvent )
  379. {
  380. EnterCS ecs(g_pEventCs);
  381. LeaveCS lcs(g_pEventCs);
  382. for( int i = 0; i < g_apRequests.Size(); i++ )
  383. {
  384. pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
  385. if( pEvent->gGuid == gGuid){
  386. return TRUE;
  387. }
  388. }
  389. pEvent = NULL;
  390. return FALSE;
  391. }
  392. ////////////////////////////////////////////////////////////////////////
  393. BOOL CWMIEvent::IsGuidInList(WCHAR * wcsGuid, WMIEventRequest *& pEvent)
  394. {
  395. EnterCS ecs(g_pEventCs);
  396. LeaveCS lcs(g_pEventCs);
  397. BOOL fRc = FALSE;
  398. int Size = g_apRequests.Size();
  399. for(int i =0 ; i < Size; i++ ){
  400. pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
  401. if( (_wcsicmp(pEvent->wcsGuid,wcsGuid)) == 0 ){
  402. fRc = TRUE;
  403. break;
  404. }
  405. }
  406. return fRc;
  407. }
  408. ////////////////////////////////////////////////////////////////////////
  409. BOOL CWMIEvent::IsIndexInList ( WCHAR * wcsGuid, DWORD dwIndex )
  410. {
  411. EnterCS ecs(g_pEventCs);
  412. LeaveCS lcs(g_pEventCs);
  413. BOOL fRc = FALSE;
  414. int Size = g_apRequests.Size();
  415. for(int i =0 ; i < Size; i++ ){
  416. WMIEventRequest* pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
  417. if( (_wcsicmp(pEvent->wcsGuid,wcsGuid)) == 0 )
  418. {
  419. if ( pEvent->dwId == dwIndex )
  420. {
  421. fRc = TRUE;
  422. break;
  423. }
  424. }
  425. }
  426. return fRc;
  427. }
  428. ////////////////////////////////////////////////////////////////////////
  429. HRESULT CWMIEvent::RegisterForRequestedEvent( DWORD dwId, WCHAR * wcsClass, WORD wType)
  430. {
  431. BOOL fRegistered = FALSE;
  432. CWMIStandardShell WMI;
  433. HRESULT hr = WBEM_E_ACCESS_DENIED;
  434. BOOL fInternalEvent = TRUE;
  435. if( wType == STANDARD_EVENT )
  436. {
  437. fInternalEvent = FALSE;
  438. }
  439. if( SUCCEEDED(WMI.Initialize (
  440. wcsClass,
  441. fInternalEvent,
  442. &m_HandleMap,
  443. TRUE,
  444. WMIGUID_NOTIFICATION|WMIGUID_QUERY,
  445. m_pEventServices,
  446. m_pEventRepository,
  447. m_pEventHandler,
  448. m_pEventCtx
  449. )))
  450. {
  451. if( m_nType == WMIEVENT )
  452. {
  453. hr = CheckImpersonationLevel();
  454. }
  455. else
  456. {
  457. HRESULT t_TempResult = RevertToSelf();
  458. #ifdef DBG
  459. if ( FAILED ( t_TempResult ) )
  460. {
  461. DebugBreak();
  462. }
  463. #endif DBG
  464. hr = S_OK;
  465. }
  466. if( SUCCEEDED(hr) )
  467. {
  468. WCHAR wcsGuid[128];
  469. hr = WMI.SetGuidForEvent( wType, wcsGuid, 128 );
  470. if( SUCCEEDED(hr)){
  471. WMIEventRequest * pAlreadyRegisteredEvent;
  472. //===========================================================
  473. // Keep a record of this guy, see if it is already registered
  474. // if it is/isn't we call WDM with different flags
  475. //===========================================================
  476. fRegistered = IsGuidInList( wcsGuid, pAlreadyRegisteredEvent );
  477. //===========================================================
  478. // Register for the requested event
  479. //===========================================================
  480. ULONG_PTR uRc =(ULONG_PTR)this;
  481. CLSID Guid;
  482. hr = WMI.RegisterWMIEvent(wcsGuid,uRc,Guid,fRegistered);
  483. if( SUCCEEDED(hr) )
  484. {
  485. BOOL bRegister = TRUE ;
  486. if ( fRegistered )
  487. {
  488. //
  489. // verify that there is no event request
  490. // containing the index already in the global array
  491. //
  492. bRegister = !IsIndexInList ( wcsGuid, dwId ) ;
  493. }
  494. if ( bRegister )
  495. {
  496. //=======================================================
  497. // If we succeeded, then add it to our list of events we
  498. // are watching
  499. //=======================================================
  500. WMIEventRequest * pEvent = new WMIEventRequest;
  501. if( pEvent ) {
  502. pEvent->gGuid = Guid;
  503. pEvent->dwId = dwId;
  504. pEvent->fHardCoded = wType;
  505. wcscpy( pEvent->wcsGuid,wcsGuid);
  506. pEvent->SetClassName(wcsClass);
  507. pEvent->AddPtrs(m_pEventHandler,m_pEventServices,m_pEventRepository,m_pEventCtx);
  508. g_apRequests.Add(pEvent);
  509. } else hr = WBEM_E_OUT_OF_MEMORY;
  510. }
  511. }
  512. }
  513. }
  514. CheckImpersonationLevel();
  515. }
  516. return hr;
  517. }
  518. ////////////////////////////////////////////////////////////////////////
  519. CWMIEventProvider::CWMIEventProvider(int nType) : CWMIEvent(nType)
  520. {
  521. if ( m_bInitialized )
  522. {
  523. m_hResyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  524. DEBUGTRACE((THISPROVIDER,"Event Provider constructed\n"));
  525. }
  526. else
  527. {
  528. ERRORTRACE((THISPROVIDER,"Event Provider construction failed\n"));
  529. }
  530. }
  531. ////////////////////////////////////////////////////////////////////////
  532. CWMIEventProvider::~CWMIEventProvider()
  533. {
  534. if ( m_bInitialized )
  535. {
  536. UnInitializeProvider ( ) ;
  537. DEBUGTRACE((THISPROVIDER,"No longer registered for WDM events\n"));
  538. DEBUGTRACE((THISPROVIDER,"Event Provider denstructed\n"));
  539. }
  540. }
  541. ////////////////////////////////////////////////////////////////////////
  542. STDMETHODIMP CWMIEventProvider::QueryInterface(REFIID riid, void** ppv)
  543. {
  544. HRESULT hr = E_NOINTERFACE;
  545. *ppv = NULL;
  546. if(riid == IID_IUnknown)
  547. {
  548. *ppv = this;
  549. }
  550. else
  551. if(riid == IID_IWbemEventProvider)
  552. {
  553. *ppv = (IWbemEventProvider*)this;
  554. }
  555. else if(riid == IID_IWbemEventProviderQuerySink)
  556. {
  557. *ppv = (IWbemEventProviderQuerySink*)this;
  558. }
  559. else if (IsEqualIID(riid, IID_IWbemProviderInit))
  560. {
  561. *ppv = (IWbemProviderInit *) this ;
  562. }
  563. else if (IsEqualIID(riid, IID_IWbemEventProviderSecurity))
  564. {
  565. *ppv = (IWbemEventProviderSecurity *) this ;
  566. }
  567. if( *ppv)
  568. {
  569. AddRef();
  570. hr = S_OK;
  571. }
  572. return hr;
  573. }
  574. ////////////////////////////////////////////////////////////////////////
  575. ULONG STDMETHODCALLTYPE CWMIEventProvider::AddRef()
  576. {
  577. return InterlockedIncrement(&m_lRef);
  578. }
  579. ////////////////////////////////////////////////////////////////////////
  580. ULONG STDMETHODCALLTYPE CWMIEventProvider::Release()
  581. {
  582. long lRef = InterlockedDecrement(&m_lRef);
  583. if(lRef == 0){
  584. //**********************************************
  585. // reference count is zero, delete this object.
  586. // and do all of the cleanup for this user,
  587. //**********************************************
  588. delete this ;
  589. }
  590. return lRef;
  591. }
  592. /////////////////////////////////////////////////////////////////////
  593. STDMETHODIMP CWMIEventProvider::Initialize(LPWSTR wszUser, long lFlags,
  594. LPWSTR wszNamespace,
  595. LPWSTR wszLocale,
  596. IWbemServices* pNamespace,
  597. IWbemContext* pCtx,
  598. IWbemProviderInitSink* pSink)
  599. {
  600. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  601. if(pNamespace != NULL)
  602. {
  603. IWbemClassObject * pWMIClass = NULL;
  604. if ( SUCCEEDED ( hr = pNamespace->GetObject(WMI_EVENT_CLASS, 0, NULL, &pWMIClass, NULL) ) )
  605. {
  606. hr = InitializeProvider (
  607. wszNamespace,
  608. wszLocale,
  609. pNamespace,
  610. pCtx,
  611. pSink,
  612. &m_HandleMap,
  613. &m_pEventServices,
  614. &m_pEventRepository,
  615. &m_pEventCtx,
  616. FALSE
  617. ) ;
  618. }
  619. SAFE_RELEASE_PTR(pWMIClass);
  620. }
  621. return hr;
  622. }
  623. ////////////////////////////////////////////////////////////////////////
  624. STDMETHODIMP CWMIEventProvider::ProvideEvents(IWbemObjectSink __RPC_FAR *pSink,long lFlags)
  625. {
  626. EnterCS ecs(g_pEventCs);
  627. LeaveCS lcs(g_pEventCs);
  628. SetEventHandler(pSink);
  629. // ===============================================================================
  630. // Make sure any request added before this was called gets the updated handler
  631. // PROVIDING it isn't the binary mof guid
  632. // ===============================================================================
  633. for(int i = 0; i < g_apRequests.Size(); i++)
  634. {
  635. WMIEventRequest* pReq = (WMIEventRequest*) g_apRequests[i];
  636. if(!pReq->pHandler)
  637. {
  638. if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,pReq->gGuid) ||
  639. IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,pReq->gGuid) )
  640. {
  641. }
  642. else
  643. {
  644. if( !pReq->pHandler )
  645. {
  646. pReq->pHandler = pSink;
  647. }
  648. }
  649. }
  650. }
  651. return S_OK;
  652. }
  653. ////////////////////////////////////////////////////////////////////////
  654. STDMETHODIMP CWMIEventProvider::NewQuery( DWORD dwId, WBEM_WSTR wszLanguage, WBEM_WSTR wszQuery)
  655. {
  656. HRESULT hRes = WBEM_S_NO_ERROR;
  657. if (_wcsicmp(wszLanguage, L"WQL") != 0)
  658. {
  659. hRes = WBEM_E_INVALID_QUERY_TYPE;
  660. }
  661. if( hRes == WBEM_S_NO_ERROR )
  662. {
  663. // Parse the query
  664. // Construct the lex source
  665. // ========================
  666. CTextLexSource Source(wszQuery);
  667. // Use the lex source to set up for parser
  668. // =======================================
  669. SQL1_Parser QueryParser(&Source);
  670. SQL_LEVEL_1_RPN_EXPRESSION * pParse;
  671. int ParseRetValue = QueryParser.Parse(&pParse);
  672. if( SQL1_Parser::SUCCESS != ParseRetValue) {
  673. hRes = WBEM_E_INVALID_QUERY;
  674. }
  675. else{
  676. //Set the class
  677. if( pParse )
  678. {
  679. hRes = RegisterForRequestedEvent(dwId,pParse->bsClassName,STANDARD_EVENT);
  680. delete pParse;
  681. pParse = NULL;
  682. }
  683. }
  684. }
  685. return hRes;
  686. }
  687. ////////////////////////////////////////////////////////////////////////
  688. STDMETHODIMP CWMIEventProvider::CancelQuery(DWORD dwId)
  689. {
  690. HRESULT hr = WBEM_E_FAILED;
  691. hr = RemoveWMIEvent(dwId);
  692. return hr;
  693. }
  694. ////////////////////////////////////////////////////////////////////////
  695. STDMETHODIMP CWMIEventProvider::AccessCheck(WBEM_CWSTR wszLanguage,
  696. WBEM_CWSTR wszQuery,
  697. long lSidLength,
  698. const BYTE* aSid)
  699. {
  700. HRESULT hr = WBEM_E_ACCESS_DENIED;
  701. //=======================================================
  702. // Check platform
  703. //=======================================================
  704. if(!IsNT())
  705. return WBEM_S_FALSE;
  706. //=======================================================
  707. // Check query language
  708. //=======================================================
  709. if (_wcsicmp(wszLanguage, L"WQL") != 0) {
  710. return WBEM_E_INVALID_QUERY_TYPE;
  711. }
  712. //=======================================================
  713. // If the PSid is NULL, then check impersonation level
  714. // as usual - based on the thread
  715. //=======================================================
  716. PSID pSid = (PSID)aSid;
  717. HANDLE hToken = NULL;
  718. if(pSid == NULL){
  719. //=================================================
  720. // if this is the INTERNAL_EVENT class, then we
  721. // do not want the local events set up again.
  722. //=================================================
  723. BOOL VerifyLocalEventsAreSetup = TRUE;
  724. if( m_nType == INTERNAL_EVENT ){
  725. VerifyLocalEventsAreSetup = FALSE;
  726. }
  727. hr = CheckImpersonationLevel() ;
  728. }
  729. else{
  730. //=======================================================
  731. // Parse the query
  732. //=======================================================
  733. CTextLexSource Source(wszQuery);
  734. //=======================================================
  735. // Use the lex source to set up for parser
  736. //=======================================================
  737. SQL1_Parser QueryParser(&Source);
  738. SQL_LEVEL_1_RPN_EXPRESSION * pParse;
  739. int ParseRetValue = QueryParser.Parse(&pParse);
  740. if( SQL1_Parser::SUCCESS != ParseRetValue) {
  741. return WBEM_E_INVALID_QUERY;
  742. }
  743. else{
  744. if( pParse ){
  745. CWMIStandardShell WMI;
  746. if( SUCCEEDED(WMI.Initialize (
  747. pParse->bsClassName,
  748. FALSE,
  749. &m_HandleMap,
  750. TRUE,
  751. WMIGUID_NOTIFICATION|WMIGUID_QUERY,
  752. m_pEventServices,
  753. m_pEventRepository,
  754. m_pEventHandler,
  755. m_pEventCtx
  756. )))
  757. {
  758. CLSID * pGuid;
  759. pGuid = WMI.GuidPtr();
  760. if(pGuid != NULL)
  761. {
  762. //========================================
  763. // Get the ACL
  764. //========================================
  765. PACL pDacl;
  766. PSECURITY_DESCRIPTOR psd = NULL;
  767. SE_OBJECT_TYPE ObjectType = SE_WMIGUID_OBJECT;
  768. hr = WBEM_E_ACCESS_DENIED;
  769. WCHAR * GuidName = NULL;
  770. hr = UuidToString(pGuid, &GuidName);
  771. if (hr == RPC_S_OK)
  772. {
  773. hr = S_OK;
  774. DWORD dwRc = GetNamedSecurityInfo(GuidName,ObjectType,DACL_SECURITY_INFORMATION,NULL,NULL,&pDacl, NULL, &psd );
  775. if( dwRc != ERROR_SUCCESS )
  776. {
  777. ERRORTRACE((THISPROVIDER, "GetNamedSecurityInfo returned %ld.\n", dwRc ));
  778. hr = WBEM_E_ACCESS_DENIED;
  779. }
  780. }
  781. if( GuidName )
  782. {
  783. RpcStringFree(&GuidName);
  784. }
  785. if(SUCCEEDED(hr))
  786. {
  787. //====================================
  788. // This is our own ACL walker
  789. //====================================
  790. DWORD dwAccessMask;
  791. NTSTATUS st = GetAccessMask((PSID)pSid, pDacl, &dwAccessMask);
  792. if(st)
  793. {
  794. ERRORTRACE((THISPROVIDER, "WDM event provider unable "
  795. "to retrieve access mask for the creator of "
  796. "registration %S: NT status %d.\n"
  797. "Registration disabled\n", wszQuery,st));
  798. return WBEM_E_FAILED;
  799. }
  800. if((dwAccessMask & WMIGUID_QUERY) == 0)
  801. {
  802. hr = WBEM_E_ACCESS_DENIED;
  803. }
  804. else
  805. {
  806. hr = S_OK;
  807. m_nType = PERMANENT_EVENT;
  808. }
  809. }
  810. if( psd != NULL)
  811. {
  812. AccFree( psd );
  813. }
  814. }
  815. delete pParse;
  816. }
  817. }
  818. }
  819. }
  820. return hr;
  821. }
  822. ////////////////////////////////////////////////////////////////////////
  823. void CWMIEvent::WMIEventCallback(PWNODE_HEADER WnodeHeader)
  824. {
  825. LPGUID EventGuid = &WnodeHeader->Guid;
  826. ERRORTRACE((THISPROVIDER,"Received Event\n"));
  827. //=======================================================
  828. // We only support WNODE_FLAG_ALL_DATA and
  829. // WNODE_FLAG_SINGLE_INSTANCE
  830. //
  831. // Parse thru whatever it is and send it off to HMOM
  832. //=======================================================
  833. if( WnodeHeader )
  834. {
  835. HRESULT hr;
  836. WMIEventRequest * pEvent;
  837. //===========================================================
  838. // Make sure it is an event we want
  839. //===========================================================
  840. if( IsGuidInListIfSoGetCorrectContext( *EventGuid,pEvent))
  841. {
  842. CWMIStandardShell WMI;
  843. //=======================================================
  844. // See if a binary mof event is being added or deleted
  845. //=======================================================
  846. WORD wBinaryMofType = 0;
  847. BOOL fInternalEvent = FALSE;
  848. if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,WnodeHeader->Guid))
  849. {
  850. fInternalEvent = TRUE;
  851. wBinaryMofType = MOF_ADDED;
  852. }
  853. else if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,WnodeHeader->Guid))
  854. {
  855. fInternalEvent = TRUE;
  856. wBinaryMofType = MOF_DELETED;
  857. }
  858. IWbemServices* pServices = NULL;
  859. if( SUCCEEDED(pEvent->gipServices.Localize(&pServices)))
  860. {
  861. // release upon destruction
  862. OnDeleteObj0 <IWbemServices, ULONG(__stdcall IWbemServices:: *)(), IWbemServices::Release> pServicesRelease (pServices);
  863. IWbemServices* pRepository = NULL;
  864. if( SUCCEEDED(pEvent->gipRepository.Localize(&pRepository)))
  865. {
  866. // release upon destruction
  867. OnDeleteObj0 <IWbemServices, ULONG(__stdcall IWbemServices:: *)(), IWbemServices::Release> pRepositoryRelease (pRepository);
  868. if( SUCCEEDED(WMI.Initialize (
  869. pEvent->pwcsClass,
  870. fInternalEvent,
  871. &m_HandleMap,
  872. TRUE,
  873. WMIGUID_QUERY|WMIGUID_NOTIFICATION,
  874. pServices,
  875. pRepository,
  876. pEvent->pHandler,
  877. pEvent->pCtx
  878. )))
  879. {
  880. //=======================================================
  881. // If it was, then process it, otherwise go on... :)
  882. //=======================================================
  883. WMI.ProcessEvent(wBinaryMofType,WnodeHeader);
  884. }
  885. }
  886. }
  887. }
  888. }
  889. }