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.

2624 lines
70 KiB

  1. //******************************************************************************
  2. //
  3. // FILTPROX.CPP
  4. //
  5. // Copyright (C) 1996-1999 Microsoft Corporation
  6. //
  7. //******************************************************************************
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include "pragmas.h"
  11. #include <wbemcomn.h>
  12. #include "filtprox.h"
  13. #include <eventrep.h>
  14. #include <evtools.h>
  15. #include <wbemdcpl.h>
  16. #include <newnew.h>
  17. #include <winntsec.h>
  18. #ifdef DBG
  19. #define _ESSCLI_ASSERT(X) { if (!(X)) { DebugBreak(); } }
  20. #else
  21. #define _ESSCLI_ASSERT(X)
  22. #endif
  23. CTempMemoryManager g_TargetsManager;
  24. bool TempSetTargets(WBEM_REM_TARGETS* pTargets, CSortedArray* pTrues)
  25. {
  26. int nSize = pTrues->Size();
  27. pTargets->m_lNumTargets = nSize;
  28. pTargets->m_aTargets = (WBEM_REMOTE_TARGET_ID_TYPE*)
  29. g_TargetsManager.Allocate(
  30. sizeof(WBEM_REMOTE_TARGET_ID_TYPE) * nSize);
  31. if(pTargets->m_aTargets == NULL)
  32. return false;
  33. for(int i = 0; i < nSize; i++)
  34. {
  35. pTargets->m_aTargets[i] = (WBEM_REMOTE_TARGET_ID_TYPE)pTrues->GetAt(i);
  36. }
  37. return true;
  38. }
  39. void TempClearTargets(WBEM_REM_TARGETS* pTargets)
  40. {
  41. g_TargetsManager.Free(pTargets->m_aTargets,
  42. sizeof(WBEM_REMOTE_TARGET_ID_TYPE) * pTargets->m_lNumTargets);
  43. }
  44. //******************************************************************************
  45. //******************************************************************************
  46. // META DATA
  47. //******************************************************************************
  48. //******************************************************************************
  49. HRESULT CWrappingMetaData::GetClass(LPCWSTR wszName, IWbemContext* pContext,
  50. _IWmiObject** ppClass)
  51. {
  52. HRESULT hres;
  53. IWbemClassObject* pObj;
  54. *ppClass = NULL;
  55. hres = m_pDest->GetClass(wszName, pContext, &pObj);
  56. if ( FAILED(hres) )
  57. {
  58. return hres;
  59. }
  60. CReleaseMe rm1(pObj);
  61. return pObj->QueryInterface(IID__IWmiObject, (void**)ppClass);
  62. }
  63. //******************************************************************************
  64. //******************************************************************************
  65. // FILTER PROXY MANAGER
  66. //******************************************************************************
  67. //******************************************************************************
  68. CFilterProxyManager::CFilterProxyManager(CLifeControl* pControl)
  69. : CFilterProxyManagerBase( pControl ), m_lRef(0), m_pStub(NULL),
  70. m_pMetaData(NULL), m_pMultiTarget(NULL), m_pSpecialContext(NULL),
  71. m_XProxy(this), m_lExtRef(0),
  72. m_hthreadSend(NULL),
  73. m_heventDone(NULL),
  74. m_heventBufferNotFull(NULL),
  75. m_heventBufferFull(NULL),
  76. m_heventEventsPending(NULL),
  77. m_dwLastSentStamp(0),
  78. m_pMultiTargetStream( NULL )
  79. {
  80. }
  81. CFilterProxyManager::~CFilterProxyManager()
  82. {
  83. StopSendThread();
  84. if(m_pMetaData)
  85. m_pMetaData->Release();
  86. if(m_pStub)
  87. m_pStub->Release();
  88. if(m_pMultiTarget)
  89. m_pMultiTarget->Release();
  90. }
  91. ULONG STDMETHODCALLTYPE CFilterProxyManager::AddRef()
  92. {
  93. // This is an AddRef from a client. Increment a special counter as well
  94. // ====================================================================
  95. InterlockedIncrement(&m_lExtRef);
  96. return InterlockedIncrement(&m_lRef);
  97. }
  98. ULONG STDMETHODCALLTYPE CFilterProxyManager::Release()
  99. {
  100. // This is a Release from a client. Check if the client has released all
  101. // references to the proxy, in which case we need to disconnect ourselves
  102. // ======================================================================
  103. if(InterlockedDecrement(&m_lExtRef) == 0)
  104. {
  105. EnterCriticalSection(&m_cs);
  106. IWbemFilterStub* pStub = m_pStub;
  107. InterlockedIncrement(&m_lRef);
  108. LeaveCriticalSection(&m_cs);
  109. if(pStub)
  110. pStub->UnregisterProxy(&m_XProxy);
  111. InterlockedDecrement(&m_lRef);
  112. }
  113. long lRef = InterlockedDecrement(&m_lRef);
  114. if(lRef == 0) delete this;
  115. return lRef;
  116. }
  117. ULONG STDMETHODCALLTYPE CFilterProxyManager::AddRefProxy()
  118. {
  119. // AddRef from proxy.
  120. return InterlockedIncrement(&m_lRef);
  121. }
  122. ULONG STDMETHODCALLTYPE CFilterProxyManager::ReleaseProxy()
  123. {
  124. // Release from proxy.
  125. long lRef = InterlockedDecrement(&m_lRef);
  126. if(lRef == 0) delete this;
  127. return lRef;
  128. }
  129. HRESULT STDMETHODCALLTYPE CFilterProxyManager::QueryInterface(REFIID riid, void** ppv)
  130. {
  131. if(riid == IID_IUnknown)
  132. *ppv = (IUnknown*)this;
  133. else if(riid == IID_IMarshal)
  134. *ppv = (IMarshal*)this;
  135. else if(riid == IID_IWbemFilterProxy || riid == IID_IWbemLocalFilterProxy)
  136. *ppv = (IWbemLocalFilterProxy*)&m_XProxy;
  137. else
  138. return E_NOINTERFACE;
  139. ((IUnknown*)*ppv)->AddRef();
  140. return S_OK;
  141. }
  142. HRESULT STDMETHODCALLTYPE CFilterProxyManager::Initialize(IWbemMetaData* pMetaData,
  143. IWbemMultiTarget* pMultiTarget)
  144. {
  145. CInCritSec ics(&m_cs);
  146. if(m_pMetaData)
  147. m_pMetaData->Release();
  148. m_pMetaData = new CWrappingMetaData(pMetaData);
  149. if(m_pMetaData)
  150. m_pMetaData->AddRef();
  151. else
  152. return WBEM_E_OUT_OF_MEMORY;
  153. if(m_pMultiTarget)
  154. m_pMultiTarget->Release();
  155. m_pMultiTarget = pMultiTarget;
  156. if(m_pMultiTarget)
  157. m_pMultiTarget->AddRef();
  158. if(GetMainProxy() == NULL)
  159. return WBEM_E_OUT_OF_MEMORY;
  160. return S_OK;
  161. }
  162. HRESULT CFilterProxyManager::SetStub(IWbemFilterStub* pStub)
  163. {
  164. if(m_pStub)
  165. m_pStub->Release();
  166. m_pStub = pStub;
  167. if(m_pStub)
  168. m_pStub->AddRef();
  169. // Initialize ourselves
  170. // ====================
  171. HRESULT hres = m_pStub->RegisterProxy(&m_XProxy);
  172. if(FAILED(hres))
  173. {
  174. ERRORTRACE((LOG_ESS, "Failed to register proxy with stub: %X\n", hres));
  175. return hres;
  176. }
  177. return S_OK;
  178. }
  179. HRESULT STDMETHODCALLTYPE CFilterProxyManager::Lock()
  180. {
  181. if(m_Lock.Enter()) // old implementation: == WAIT_OBJECT_0)
  182. {
  183. return S_OK;
  184. }
  185. else
  186. return WBEM_E_CRITICAL_ERROR;
  187. }
  188. HRESULT STDMETHODCALLTYPE CFilterProxyManager::Unlock()
  189. {
  190. m_Lock.Leave();
  191. return S_OK;
  192. }
  193. HRESULT STDMETHODCALLTYPE CFilterProxyManager::AddFilter(IWbemContext* pContext,
  194. LPCWSTR wszQuery,
  195. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  196. {
  197. // Parse the query
  198. // ===============
  199. CTextLexSource Source((LPWSTR)wszQuery);
  200. QL1_Parser Parser(&Source);
  201. QL_LEVEL_1_RPN_EXPRESSION* pExp;
  202. if(Parser.Parse(&pExp) != QL1_Parser::SUCCESS)
  203. {
  204. ERRORTRACE((LOG_ESS, "Filter proxy unable to parse %S\n", wszQuery));
  205. return WBEM_E_UNPARSABLE_QUERY;
  206. }
  207. CDeleteMe<QL_LEVEL_1_RPN_EXPRESSION> dm(pExp);
  208. return AddFilter(pContext, wszQuery, pExp, idFilter);
  209. }
  210. HRESULT CFilterProxyManager::AddFilter(IWbemContext* pContext,
  211. LPCWSTR wszQuery,
  212. QL_LEVEL_1_RPN_EXPRESSION* pExp,
  213. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  214. {
  215. CInCritSec ics(&m_cs);
  216. //
  217. // Record the filter in our array
  218. //
  219. m_mapQueries[idFilter] = wszQuery;
  220. //
  221. // Add the filter to all our subproxies
  222. //
  223. HRESULT hresGlobal = S_OK;
  224. for(int i = 0; i < m_apProxies.GetSize(); i++)
  225. {
  226. HRESULT hres;
  227. if(m_apProxies[i] == NULL)
  228. continue;
  229. hres = m_apProxies[i]->AddFilter(GetProperContext(pContext),
  230. wszQuery, pExp, idFilter);
  231. if(FAILED(hres))
  232. {
  233. ERRORTRACE((LOG_ESS, "Unable to add filter %S to sub-proxy in "
  234. "process %d.\n", wszQuery, GetCurrentProcessId()));
  235. hresGlobal = hres;
  236. }
  237. }
  238. return hresGlobal;
  239. }
  240. HRESULT STDMETHODCALLTYPE CFilterProxyManager::RemoveFilter(
  241. IWbemContext* pContext,
  242. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  243. {
  244. CInCritSec ics(&m_cs);
  245. //
  246. // Remove the filter from our array
  247. //
  248. m_mapQueries.erase(idFilter);
  249. //
  250. // Remove the filter from all our subproxies
  251. //
  252. HRESULT hresGlobal = S_OK;
  253. for(int i = 0; i < m_apProxies.GetSize(); i++)
  254. {
  255. HRESULT hres;
  256. if(m_apProxies[i] == NULL)
  257. continue;
  258. hres = m_apProxies[i]->RemoveFilter(GetProperContext(pContext),
  259. idFilter);
  260. if(FAILED(hres))
  261. {
  262. ERRORTRACE((LOG_ESS, "Unable to remove filter from sub-proxy in "
  263. "process %d.\n", GetCurrentProcessId()));
  264. hresGlobal = hres;
  265. }
  266. }
  267. return hresGlobal;
  268. }
  269. HRESULT STDMETHODCALLTYPE CFilterProxyManager::RemoveAllFilters(IWbemContext* pContext)
  270. {
  271. CInCritSec ics(&m_cs);
  272. //
  273. // Clear our filter array
  274. //
  275. m_mapQueries.clear();
  276. //
  277. // Remove all filters from all our subproxies
  278. //
  279. HRESULT hresGlobal = S_OK;
  280. for(int i = 0; i < m_apProxies.GetSize(); i++)
  281. {
  282. HRESULT hres;
  283. if(m_apProxies[i] == NULL)
  284. continue;
  285. hres = m_apProxies[i]->RemoveAllFilters(GetProperContext(pContext));
  286. if(FAILED(hres))
  287. {
  288. ERRORTRACE((LOG_ESS, "Unable to remove all filters from sub-proxy "
  289. "in process %d.\n", GetCurrentProcessId()));
  290. hresGlobal = hres;
  291. }
  292. }
  293. return hresGlobal;
  294. }
  295. HRESULT STDMETHODCALLTYPE CFilterProxyManager::AllowUtilizeGuarantee()
  296. {
  297. CInCritSec ics(&m_cs);
  298. //
  299. // Definition queries should be sent to the main (first) proxy only
  300. //
  301. if(m_apProxies.GetSize() == 0)
  302. return WBEM_E_UNEXPECTED;
  303. if(m_apProxies[0] == NULL)
  304. return WBEM_S_FALSE;
  305. return m_apProxies[0]->AllowUtilizeGuarantee();
  306. }
  307. HRESULT STDMETHODCALLTYPE CFilterProxyManager::AddDefinitionQuery(
  308. IWbemContext* pContext, LPCWSTR wszQuery)
  309. {
  310. CInCritSec ics(&m_cs);
  311. //
  312. // Definition queries should be sent to the main (first) proxy only
  313. //
  314. if(m_apProxies.GetSize() == 0)
  315. return WBEM_E_UNEXPECTED;
  316. if(m_apProxies[0] == NULL)
  317. return WBEM_S_FALSE;
  318. return m_apProxies[0]->AddDefinitionQuery(GetProperContext(pContext),
  319. wszQuery);
  320. }
  321. HRESULT STDMETHODCALLTYPE CFilterProxyManager::RemoveAllDefinitionQueries(
  322. IWbemContext* pContext)
  323. {
  324. //
  325. // Definition queries should be sent to the main (first) proxy only
  326. //
  327. if(m_apProxies.GetSize() == 0)
  328. return WBEM_E_UNEXPECTED;
  329. if(m_apProxies[0] == NULL)
  330. return WBEM_S_FALSE;
  331. return m_apProxies[0]->RemoveAllDefinitionQueries(
  332. GetProperContext(pContext));
  333. }
  334. HRESULT STDMETHODCALLTYPE CFilterProxyManager::Disconnect()
  335. {
  336. // We must make sure that once Disconnect returns, no events will be
  337. // delivered
  338. // =================================================================
  339. CInLock<CFilterProxyManager> il(this);
  340. {
  341. CInCritSec ics(&m_cs);
  342. if(m_pMetaData)
  343. m_pMetaData->Release();
  344. m_pMetaData = NULL;
  345. if(m_pStub)
  346. m_pStub->Release();
  347. m_pStub = NULL;
  348. if(m_pMultiTarget)
  349. m_pMultiTarget->Release();
  350. m_pMultiTarget = NULL;
  351. }
  352. return WBEM_S_NO_ERROR;
  353. }
  354. IWbemContext* CFilterProxyManager::GetProperContext(IWbemContext* pCurrentContext)
  355. {
  356. // If we are a real, out-of-proc, proxy, we should not use this context,
  357. // because the thread that owns it is currently stuck in an RPC call to us
  358. // and will not be able to process dependent requests. Instead, we must
  359. // use the "special" context that will cause the thread pool to always
  360. // create a new thread if needed
  361. // =======================================================================
  362. if(m_pSpecialContext)
  363. return m_pSpecialContext;
  364. else
  365. return pCurrentContext;
  366. }
  367. HRESULT CFilterProxyManager::SetStatus(long lFlags, HRESULT hResult,
  368. BSTR strResult, IWbemClassObject* pErrorObj)
  369. {
  370. HRESULT hres;
  371. CWbemPtr<IWbemMultiTarget> pMultiTarget;
  372. {
  373. CInLock<CFilterProxyManager> il(this);
  374. if(m_pMultiTarget == NULL)
  375. return WBEM_E_UNEXPECTED;
  376. pMultiTarget = m_pMultiTarget;
  377. }
  378. //
  379. // There is only one reason we support this call: to re-check all
  380. // subscriptions for validity/security
  381. //
  382. if(lFlags != WBEM_STATUS_REQUIREMENTS ||
  383. hResult != WBEM_REQUIREMENTS_RECHECK_SUBSCRIPTIONS)
  384. {
  385. return WBEM_E_INVALID_PARAMETER;
  386. }
  387. //
  388. // Retrieve "special" interface we use for this purpose
  389. //
  390. IWbemEventProviderRequirements* pReq = NULL;
  391. hres = pMultiTarget->QueryInterface(IID_IWbemEventProviderRequirements,
  392. (void**)&pReq);
  393. if(FAILED(hres))
  394. return hres;
  395. CReleaseMe rm1(pReq);
  396. return pReq->DeliverProviderRequest(hResult);
  397. }
  398. STDMETHODIMP CFilterProxyManager::GetRestrictedSink(
  399. long lNumQueries,
  400. const LPCWSTR* awszQueries,
  401. IUnknown* pCallback,
  402. IWbemEventSink** ppSink)
  403. {
  404. // Basic parameter validation
  405. if(lNumQueries < 1)
  406. return WBEM_E_INVALID_PARAMETER;
  407. if(ppSink == NULL)
  408. return WBEM_E_INVALID_PARAMETER;
  409. *ppSink = NULL;
  410. HRESULT hres;
  411. //
  412. // Construct a new filter proxy
  413. //
  414. CFilterProxy* pNewProxy = new CFilterProxy(this, pCallback);
  415. if(pNewProxy == NULL)
  416. return WBEM_E_OUT_OF_MEMORY;
  417. //
  418. // Add all the definition queries
  419. //
  420. for(long i = 0; i < lNumQueries; i++)
  421. {
  422. LPCWSTR wszQuery = awszQueries[i];
  423. if(wszQuery == NULL)
  424. {
  425. delete pNewProxy;
  426. return WBEM_E_INVALID_PARAMETER;
  427. }
  428. hres = pNewProxy->AddDefinitionQuery(NULL, wszQuery);
  429. if(FAILED(hres))
  430. {
  431. delete pNewProxy;
  432. return hres;
  433. }
  434. }
  435. //
  436. // if we made it here, then all definition queries were correctly added
  437. // and we can now utilize these definitions for optimizing the filter.
  438. //
  439. pNewProxy->AllowUtilizeGuarantee();
  440. {
  441. CInCritSec ics(&m_cs);
  442. for(TIterator it = m_mapQueries.begin(); it != m_mapQueries.end(); it++)
  443. {
  444. // Parse the query
  445. // ===============
  446. LPCWSTR wszQuery = it->second;
  447. WBEM_REMOTE_TARGET_ID_TYPE idFilter = it->first;
  448. CTextLexSource Source(wszQuery);
  449. QL1_Parser Parser(&Source);
  450. QL_LEVEL_1_RPN_EXPRESSION* pExp;
  451. if(Parser.Parse(&pExp) != QL1_Parser::SUCCESS)
  452. {
  453. ERRORTRACE((LOG_ESS, "Filter proxy unable to parse %S\n",
  454. wszQuery));
  455. continue;
  456. }
  457. CDeleteMe<QL_LEVEL_1_RPN_EXPRESSION> dm(pExp);
  458. pNewProxy->AddFilter(NULL, wszQuery, pExp, idFilter);
  459. }
  460. if(m_apProxies.Add(pNewProxy) < 0)
  461. {
  462. delete pNewProxy;
  463. return WBEM_E_OUT_OF_MEMORY;
  464. }
  465. pNewProxy->SetRunning();
  466. }
  467. return pNewProxy->QueryInterface(IID_IWbemEventSink, (void**)ppSink);
  468. }
  469. STDMETHODIMP CFilterProxyManager::GetUnmarshalClass(REFIID riid, void* pv,
  470. DWORD dwDestContext, void* pvReserved, DWORD mshlFlags,
  471. CLSID* pClsid)
  472. {
  473. *pClsid = CLSID_WbemFilterProxy;
  474. return WBEM_S_NO_ERROR;
  475. }
  476. STDMETHODIMP CFilterProxyManager::GetMarshalSizeMax(REFIID riid, void* pv,
  477. DWORD dwDestContext, void* pvReserved, DWORD mshlFlags,
  478. ULONG* plSize)
  479. {
  480. return CoGetMarshalSizeMax(plSize, IID_IWbemFilterStub, m_pStub,
  481. dwDestContext, pvReserved, mshlFlags);
  482. }
  483. STDMETHODIMP CFilterProxyManager::MarshalInterface(IStream* pStream, REFIID riid,
  484. void* pv, DWORD dwDestContext, void* pvReserved,
  485. DWORD mshlFlags)
  486. {
  487. return CoMarshalInterface(pStream, IID_IWbemFilterStub,
  488. m_pStub, dwDestContext, pvReserved, mshlFlags);
  489. }
  490. STDMETHODIMP CFilterProxyManager::UnmarshalInterface(IStream* pStream, REFIID riid,
  491. void** ppv)
  492. {
  493. //
  494. // before unmarshaling, we must first check we are unmarshaling due to
  495. // a call from wmi ( or local system rather ). Because we're going to
  496. // be calling back 'blindly' to the passed in reference, we need to
  497. // ensure we're not going to 'give away the farm'. Remember that this
  498. // custom marshaler can be used in any DCOM server, so we must ensure
  499. // that it can't be misused to get an arbitrary process to call you back
  500. // at potentially impersonate level.
  501. //
  502. CWbemPtr<IServerSecurity> pSec;
  503. HRESULT hr = CoGetCallContext( IID_IServerSecurity, (void**)&pSec );
  504. if ( SUCCEEDED(hr) )
  505. {
  506. CNtSid ProcessSid( CNtSid::CURRENT_USER );
  507. if ( ProcessSid.GetStatus() != CNtSid::NoError )
  508. return WBEM_E_ACCESS_DENIED;
  509. hr = pSec->ImpersonateClient();
  510. if ( FAILED(hr) )
  511. return hr;
  512. CNtSid CallerSid( CNtSid::CURRENT_THREAD );
  513. pSec->RevertToSelf();
  514. if ( CallerSid.GetStatus() != CNtSid::NoError )
  515. return WBEM_E_ACCESS_DENIED;
  516. PSID pLocalSystemSid;
  517. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  518. if ( AllocateAndInitializeSid( &id,
  519. 1,
  520. SECURITY_LOCAL_SYSTEM_RID,
  521. 0,0,0,0,0,0,0,
  522. &pLocalSystemSid ) )
  523. {
  524. BOOL bOk = EqualSid( CallerSid.GetPtr(), pLocalSystemSid ) ||
  525. EqualSid( CallerSid.GetPtr(), ProcessSid.GetPtr() );
  526. FreeSid( pLocalSystemSid );
  527. if ( !bOk )
  528. return WBEM_E_ACCESS_DENIED;
  529. }
  530. else
  531. {
  532. return WBEM_E_OUT_OF_MEMORY;
  533. }
  534. }
  535. // Unmarshal the stub pointer
  536. // ==========================
  537. HRESULT hres = CoUnmarshalInterface(pStream, IID_IWbemFilterStub,
  538. (void**)&m_pStub);
  539. if(FAILED(hres))
  540. {
  541. ERRORTRACE((LOG_ESS, "Unable to unmarshal filter stub: %X\n", hres));
  542. return hres;
  543. }
  544. // Since we are unmarshalling, this must be a real proxy. Real proxies
  545. // should use a "special" context when calling back into CIMOM to make sure
  546. // that they do not cause a deadlock, because a thread in CIMOM is stuck in
  547. // an RPC call to this proxy and is not processing dependent requests.
  548. // ========================================================================
  549. IWbemCausalityAccess* pCausality = NULL;
  550. hres = CoCreateInstance(CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER,
  551. IID_IWbemCausalityAccess, (void**)&pCausality);
  552. if(FAILED(hres))
  553. {
  554. ERRORTRACE((LOG_ESS, "Unable to create a context object in proxy: "
  555. "error code 0x%X\n", hres));
  556. return hres;
  557. }
  558. CReleaseMe rm1(pCausality);
  559. hres = pCausality->MakeSpecial();
  560. if(FAILED(hres))
  561. {
  562. ERRORTRACE((LOG_ESS, "Unable to construct special context object in "
  563. "proxy: error code 0x%X\n", hres));
  564. return hres;
  565. }
  566. hres = pCausality->QueryInterface(IID_IWbemContext,
  567. (void**)&m_pSpecialContext);
  568. if(FAILED(hres))
  569. {
  570. // Out of memory?
  571. // ==============
  572. return hres;
  573. }
  574. // Initialize ourselves
  575. // ====================
  576. hres = m_pStub->RegisterProxy(&m_XProxy);
  577. if(FAILED(hres))
  578. {
  579. ERRORTRACE((LOG_ESS, "Failed to register proxy with stub: %X\n", hres));
  580. return hres;
  581. }
  582. //
  583. // What we must return is our main proxy
  584. //
  585. if(GetMainProxy())
  586. return GetMainProxy()->QueryInterface(riid, ppv);
  587. else
  588. return WBEM_E_CRITICAL_ERROR;
  589. }
  590. INTERNAL IWbemEventSink* CFilterProxyManager::GetMainProxy()
  591. {
  592. //
  593. // We are being asked for the sink to give to the provider. It is possible
  594. // that we do not have a sink --- that will be the case if the provider
  595. // has unloaded. In that case, we must be sure to create it!
  596. //
  597. if(m_apProxies.GetSize() == 0)
  598. {
  599. CFilterProxy* pMainProxy = new CFilterProxy(this);
  600. if(pMainProxy == NULL)
  601. return NULL;
  602. pMainProxy->SetRunning();
  603. if(m_apProxies.Add(pMainProxy) < 0)
  604. {
  605. delete pMainProxy;
  606. return NULL;
  607. }
  608. return pMainProxy;
  609. }
  610. else
  611. {
  612. if(m_apProxies[0] == NULL)
  613. {
  614. CFilterProxy* pMainProxy = new CFilterProxy(this);
  615. if(pMainProxy == NULL)
  616. return NULL;
  617. pMainProxy->SetRunning();
  618. m_apProxies.SetAt(0, pMainProxy);
  619. }
  620. return m_apProxies[0];
  621. }
  622. }
  623. HRESULT CFilterProxyManager::GetMetaData(RELEASE_ME CWrappingMetaData** ppMeta)
  624. {
  625. *ppMeta = m_pMetaData;
  626. (*ppMeta)->AddRef();
  627. return S_OK;
  628. }
  629. HRESULT CFilterProxyManager::RemoveProxy(CFilterProxy* pProxy)
  630. {
  631. //
  632. // Called when a proxy is fully released by the client, and calls on the
  633. // manager to self-destruct
  634. //
  635. CFilterProxy* pOldProxy = NULL;
  636. {
  637. CInCritSec ics(&m_cs);
  638. for(int i = 0; i < m_apProxies.GetSize(); i++)
  639. {
  640. if(m_apProxies[i] == pProxy)
  641. {
  642. RemoveProxyLatency(pProxy);
  643. m_apProxies.RemoveAt(i, &pOldProxy);
  644. break;
  645. }
  646. }
  647. }
  648. if(pOldProxy)
  649. {
  650. // We don't do a release because pProxy's refcount is already 0 (which
  651. // is why we're in this function). Normally RemoveAt would have
  652. // deleted it, but since we passed in &pOldProxy, it didn't. We do this
  653. // so pOldProxy doesn't do its final release of the manager which could
  654. // destruct the manager while we're holding onto the manager's lock.
  655. delete pOldProxy;
  656. return WBEM_S_NO_ERROR;
  657. }
  658. else
  659. return WBEM_E_NOT_FOUND;
  660. }
  661. STDMETHODIMP CFilterProxyManager::ReleaseMarshalData(IStream* pStream)
  662. {
  663. return CoReleaseMarshalData(pStream);
  664. }
  665. STDMETHODIMP CFilterProxyManager::DisconnectObject(DWORD dwReserved)
  666. {
  667. // BUGBUG
  668. return WBEM_E_UNEXPECTED;
  669. }
  670. HRESULT CFilterProxyManager::DeliverEvent(long lNumToSend,
  671. IWbemClassObject** apEvents,
  672. WBEM_REM_TARGETS* aTargets,
  673. long lSDLength, BYTE* pSD)
  674. {
  675. //
  676. // we need to hold the proxy lock when signalling an event.
  677. // the reason for this is that when a call to disconnect() returns,
  678. // we can be absolutely sure that no events will be delivered to the
  679. // stub. Without locking here, just after the check for multitarget,
  680. // disconnect could be called setting multitarget to null and then
  681. // returning, however, just after the DeliverEvent call is made.
  682. //
  683. CInLock<CFilterProxyManager> il(this);
  684. if(m_pMultiTarget)
  685. return m_pMultiTarget->DeliverEvent(lNumToSend, apEvents, aTargets,
  686. lSDLength, pSD);
  687. else
  688. return CO_E_OBJNOTCONNECTED;
  689. }
  690. HRESULT CFilterProxyManager::DeliverEventMT(long lNumToSend,
  691. IWbemClassObject** apEvents,
  692. WBEM_REM_TARGETS* aTargets,
  693. long lSDLength, BYTE* pSD,
  694. IWbemMultiTarget * pMultiTarget)
  695. {
  696. //
  697. // we need to hold the proxy lock when signalling an event. There are
  698. // two reasons for this. The first is that during resync of ess, it
  699. // must ensure that no events are delivered, else they would be lost.
  700. // the way ess ensures this is by grabbing the locks of all the proxies.
  701. // The other reason is so that when a call to disconnect() returns,
  702. // we can be absolutely sure that no events will be delivered to the
  703. // stub. Without locking here, just after the check for multitarget,
  704. // disconnect could be called setting multitarget to null and then
  705. // returning, however, just after the DeliverEvent call is made.
  706. //
  707. // This assertion is for this func to be called in other place than
  708. // SendThreadProc in the future.
  709. _DBG_ASSERT( pMultiTarget );
  710. CInLock<CFilterProxyManager> il(this);
  711. return pMultiTarget->DeliverEvent(lNumToSend, apEvents, aTargets, lSDLength, pSD);
  712. }
  713. ULONG CFilterProxyManager::XProxy::AddRef()
  714. {
  715. return m_pObject->AddRefProxy();
  716. }
  717. ULONG CFilterProxyManager::XProxy::Release()
  718. {
  719. return m_pObject->ReleaseProxy();
  720. }
  721. HRESULT CFilterProxyManager::XProxy::QueryInterface(REFIID riid, void** ppv)
  722. {
  723. if(riid == IID_IUnknown || riid == IID_IWbemFilterProxy ||
  724. riid == IID_IWbemLocalFilterProxy)
  725. {
  726. *ppv = (IWbemLocalFilterProxy*)this;
  727. AddRef();
  728. return S_OK;
  729. }
  730. else
  731. {
  732. return E_NOINTERFACE;
  733. }
  734. }
  735. HRESULT CFilterProxyManager::XProxy::Initialize(IWbemMetaData* pMetaData,
  736. IWbemMultiTarget* pMultiTarget)
  737. {
  738. ENTER_API_CALL
  739. return m_pObject->Initialize(pMetaData, pMultiTarget);
  740. EXIT_API_CALL
  741. }
  742. HRESULT CFilterProxyManager::XProxy::Lock() // Deprecated ?
  743. {
  744. ENTER_API_CALL
  745. return m_pObject->Lock();
  746. EXIT_API_CALL
  747. }
  748. HRESULT CFilterProxyManager::XProxy::Unlock() // Deprecated ?
  749. {
  750. ENTER_API_CALL
  751. return m_pObject->Unlock();
  752. EXIT_API_CALL
  753. }
  754. HRESULT CFilterProxyManager::XProxy::AddFilter(IWbemContext* pContext,
  755. LPCWSTR wszQuery,
  756. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  757. {
  758. ENTER_API_CALL
  759. return m_pObject->AddFilter(pContext, wszQuery, idFilter);
  760. EXIT_API_CALL
  761. }
  762. HRESULT CFilterProxyManager::XProxy::RemoveFilter(IWbemContext* pContext,
  763. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  764. {
  765. ENTER_API_CALL
  766. return m_pObject->RemoveFilter(pContext, idFilter);
  767. EXIT_API_CALL
  768. }
  769. HRESULT CFilterProxyManager::XProxy::RemoveAllFilters(IWbemContext* pContext)
  770. {
  771. ENTER_API_CALL
  772. return m_pObject->RemoveAllFilters(pContext);
  773. EXIT_API_CALL
  774. }
  775. HRESULT CFilterProxyManager::XProxy::AddDefinitionQuery(IWbemContext* pContext,
  776. LPCWSTR wszQuery)
  777. {
  778. ENTER_API_CALL
  779. return m_pObject->AddDefinitionQuery(pContext, wszQuery);
  780. EXIT_API_CALL
  781. }
  782. HRESULT CFilterProxyManager::XProxy::AllowUtilizeGuarantee()
  783. {
  784. ENTER_API_CALL
  785. return m_pObject->AllowUtilizeGuarantee();
  786. EXIT_API_CALL
  787. }
  788. HRESULT CFilterProxyManager::XProxy::RemoveAllDefinitionQueries(
  789. IWbemContext* pContext)
  790. {
  791. ENTER_API_CALL
  792. return m_pObject->RemoveAllDefinitionQueries(pContext);
  793. EXIT_API_CALL
  794. }
  795. HRESULT CFilterProxyManager::XProxy::Disconnect()
  796. {
  797. ENTER_API_CALL
  798. return m_pObject->Disconnect();
  799. EXIT_API_CALL
  800. }
  801. HRESULT CFilterProxyManager::XProxy::SetStub(IWbemFilterStub* pStub)
  802. {
  803. return m_pObject->SetStub(pStub);
  804. }
  805. HRESULT CFilterProxyManager::XProxy::LocalAddFilter(IWbemContext* pContext,
  806. LPCWSTR wszQuery,
  807. void* pExp,
  808. WBEM_REMOTE_TARGET_ID_TYPE Id)
  809. {
  810. return m_pObject->AddFilter(pContext, wszQuery,
  811. (QL_LEVEL_1_RPN_EXPRESSION*)pExp, Id);
  812. }
  813. HRESULT CFilterProxyManager::XProxy::GetMainSink(IWbemEventSink** ppSink)
  814. {
  815. *ppSink = m_pObject->GetMainProxy();
  816. if(*ppSink)
  817. {
  818. (*ppSink)->AddRef();
  819. return S_OK;
  820. }
  821. else
  822. return E_UNEXPECTED;
  823. }
  824. void CFilterProxyManager::CalcMaxSendLatency()
  825. {
  826. LockBatching();
  827. DWORD dwLatency = 0xFFFFFFFF;
  828. for (CLatencyMapItor i = m_mapLatencies.begin();
  829. i != m_mapLatencies.end();
  830. i++)
  831. {
  832. if ((*i).second < dwLatency)
  833. dwLatency = (*i).second;
  834. }
  835. m_dwMaxSendLatency = dwLatency;
  836. UnlockBatching();
  837. }
  838. HRESULT CFilterProxyManager::SetProxyLatency(CFilterProxy *pProxy, DWORD dwLatency)
  839. {
  840. LockBatching();
  841. BOOL bWasEmpty = m_mapLatencies.size() == 0;
  842. // Add this proxy.
  843. m_mapLatencies[pProxy] = dwLatency;
  844. HRESULT hr = S_OK;
  845. // If our map was previously empty, start the send thread.
  846. if ( bWasEmpty )
  847. {
  848. m_dwMaxSendLatency = dwLatency;
  849. _DBG_ASSERT( NULL == m_hthreadSend );
  850. if ( NULL == m_hthreadSend )
  851. {
  852. _DBG_ASSERT( NULL == m_pMultiTargetStream );
  853. //
  854. // IWbemMultiTarget interface pointer is mashaled to make the
  855. // interface pointer available for cross apartment access
  856. //
  857. hr = CoMarshalInterThreadInterfaceInStream( IID_IWbemMultiTarget,
  858. m_pMultiTarget,
  859. &m_pMultiTargetStream );
  860. if ( SUCCEEDED( hr ) )
  861. {
  862. if ( FALSE == StartSendThread( ) )
  863. {
  864. ERRORTRACE((LOG_ESS, "Failed to set proxy latency due to thread creation error : 0x%X\n", GetLastError( ) ) );
  865. m_pMultiTargetStream->Release( );
  866. m_pMultiTargetStream = NULL;
  867. hr = E_FAIL;
  868. }
  869. }
  870. else
  871. {
  872. m_pMultiTargetStream = NULL;
  873. ERRORTRACE((LOG_ESS, "Failed to set proxy latency due to marshaling error : 0x%X\n", hr ) );
  874. }
  875. }
  876. }
  877. else
  878. {
  879. // If dwLatency is smaller than m_dwMaxSendLatency, set
  880. // m_dwMaxSendLatency to the new smallest value.
  881. if (dwLatency < m_dwMaxSendLatency)
  882. m_dwMaxSendLatency = dwLatency;
  883. }
  884. UnlockBatching();
  885. return hr;
  886. }
  887. void CFilterProxyManager::RemoveProxyLatency(CFilterProxy *pProxy)
  888. {
  889. LockBatching();
  890. // Try to find the proxy.
  891. CLatencyMapItor item = m_mapLatencies.find(pProxy);
  892. // Did we find it?
  893. if (item != m_mapLatencies.end())
  894. {
  895. // Remove it.
  896. m_mapLatencies.erase(item);
  897. // If there are no more proxies that care about batching, stop the
  898. // send thread.
  899. if (m_mapLatencies.size() == 0)
  900. StopSendThread();
  901. else
  902. {
  903. DWORD dwLatency = (*item).second;
  904. // If the latency value we just removed is the same as
  905. // m_dwMaxSendLatency, recalc m_dwMaxSendLatency.
  906. if (dwLatency == m_dwMaxSendLatency)
  907. CalcMaxSendLatency();
  908. }
  909. }
  910. UnlockBatching();
  911. }
  912. BOOL CFilterProxyManager::StartSendThread()
  913. {
  914. LockBatching();
  915. if ( NULL == m_hthreadSend )
  916. {
  917. DWORD dwID;
  918. do
  919. {
  920. m_heventDone = CreateEvent( NULL, FALSE, FALSE, NULL );
  921. if ( NULL == m_heventDone )
  922. {
  923. break;
  924. }
  925. m_heventBufferNotFull = CreateEvent( NULL, TRUE, TRUE, NULL );
  926. if ( NULL == m_heventBufferNotFull )
  927. {
  928. break;
  929. }
  930. m_heventBufferFull = CreateEvent( NULL, TRUE, FALSE, NULL );
  931. if ( NULL == m_heventBufferFull )
  932. {
  933. break;
  934. }
  935. m_heventEventsPending = CreateEvent( NULL, TRUE, FALSE, NULL );
  936. if ( NULL == m_heventEventsPending )
  937. {
  938. break;
  939. }
  940. m_hthreadSend = CreateThread( NULL,
  941. 0,
  942. (LPTHREAD_START_ROUTINE) SendThreadProc,
  943. this,
  944. 0,
  945. &dwID );
  946. }
  947. while( FALSE );
  948. if ( NULL == m_hthreadSend )
  949. {
  950. if (m_heventDone)
  951. {
  952. CloseHandle(m_heventDone);
  953. m_heventDone = NULL;
  954. }
  955. if (m_heventBufferNotFull)
  956. {
  957. CloseHandle(m_heventBufferNotFull);
  958. m_heventBufferNotFull = NULL;
  959. }
  960. if (m_heventBufferFull)
  961. {
  962. CloseHandle(m_heventBufferFull);
  963. m_heventBufferFull = NULL;
  964. }
  965. if (m_heventEventsPending)
  966. {
  967. CloseHandle(m_heventEventsPending);
  968. m_heventEventsPending = NULL;
  969. }
  970. }
  971. }
  972. UnlockBatching();
  973. return ( NULL != m_hthreadSend );
  974. }
  975. void CFilterProxyManager::StopSendThread()
  976. {
  977. LockBatching();
  978. if (m_hthreadSend && m_heventDone)
  979. {
  980. SetEvent(m_heventDone);
  981. WaitForSingleObject(m_hthreadSend, 3000);
  982. CloseHandle(m_hthreadSend);
  983. m_hthreadSend = NULL;
  984. }
  985. if (m_heventDone)
  986. {
  987. CloseHandle(m_heventDone);
  988. m_heventDone = NULL;
  989. }
  990. if (m_heventBufferNotFull)
  991. {
  992. CloseHandle(m_heventBufferNotFull);
  993. m_heventBufferNotFull = NULL;
  994. }
  995. if (m_heventBufferFull)
  996. {
  997. CloseHandle(m_heventBufferFull);
  998. m_heventBufferFull = NULL;
  999. }
  1000. if (m_heventEventsPending)
  1001. {
  1002. CloseHandle(m_heventEventsPending);
  1003. m_heventEventsPending = NULL;
  1004. }
  1005. UnlockBatching();
  1006. }
  1007. DWORD WINAPI CFilterProxyManager::SendThreadProc(CFilterProxyManager *pThis)
  1008. {
  1009. HANDLE hWait[2] = { pThis->m_heventDone, pThis->m_heventEventsPending },
  1010. hwaitSendLatency[2] = { pThis->m_heventDone, pThis->m_heventBufferFull },
  1011. heventBufferNotFull = pThis->m_heventBufferNotFull;
  1012. HRESULT hres;
  1013. IWbemMultiTarget * pMultiTarget = NULL;
  1014. _DBG_ASSERT( pThis->m_pMultiTargetStream );
  1015. if ( NULL == pThis->m_pMultiTargetStream )
  1016. {
  1017. return 1;
  1018. }
  1019. CoInitializeEx( NULL, COINIT_MULTITHREADED );
  1020. //
  1021. // IWbemMultiTarget interface pointer is unmarshaled to use in this
  1022. // thread (in case of cross apartment).
  1023. //
  1024. hres = CoGetInterfaceAndReleaseStream( pThis->m_pMultiTargetStream,
  1025. IID_IWbemMultiTarget,
  1026. ( void ** )&pMultiTarget );
  1027. if( FAILED( hres ) )
  1028. {
  1029. ERRORTRACE((LOG_ESS, "Failed to run batching thread due to unmarshaling errors: 0x%X\n", hres));
  1030. // pThis->m_pMultiTargetStream->Release( );
  1031. pThis->m_pMultiTargetStream = NULL;
  1032. CoUninitialize( );
  1033. return 1;
  1034. }
  1035. pThis->m_pMultiTargetStream = NULL;
  1036. _DBG_ASSERT( pMultiTarget );
  1037. while (WaitForMultipleObjects(2, hWait, FALSE, INFINITE) != 0)
  1038. {
  1039. // If we have a send latency, wait for that time or until the send
  1040. // buffer is full. If the done event fires, get out.
  1041. if (pThis->m_dwMaxSendLatency)
  1042. {
  1043. if (WaitForMultipleObjects(2, hwaitSendLatency, FALSE,
  1044. pThis->m_dwMaxSendLatency) == 0)
  1045. break;
  1046. // Reset m_heventBufferFull.
  1047. ResetEvent(hwaitSendLatency[1]);
  1048. }
  1049. CInCritSec csBuffer(&pThis->m_csBuffer);
  1050. int nItems = pThis->m_batch.GetItemCount();
  1051. hres = pThis->DeliverEventMT(
  1052. nItems,
  1053. pThis->m_batch.GetObjs(),
  1054. pThis->m_batch.GetTargets(),
  1055. 0,
  1056. &CFilterProxy::mstatic_EmptySD,
  1057. pMultiTarget);
  1058. // Increment this so the filter proxies will know to clear out their
  1059. // buffer size when they next get an event to batch.
  1060. pThis->m_dwLastSentStamp++;
  1061. pThis->m_batch.RemoveAll();
  1062. SetEvent(heventBufferNotFull);
  1063. // Reset m_heventEventsPending
  1064. ResetEvent(hWait[1]);
  1065. }
  1066. // Make sure our batch buffer is empty before we exit.
  1067. CInCritSec csBuffer(&pThis->m_csBuffer);
  1068. int nItems = pThis->m_batch.GetItemCount();
  1069. if ( nItems )
  1070. {
  1071. pThis->DeliverEventMT(
  1072. nItems,
  1073. pThis->m_batch.GetObjs(),
  1074. pThis->m_batch.GetTargets(),
  1075. 0,
  1076. &CFilterProxy::mstatic_EmptySD,
  1077. pMultiTarget);
  1078. }
  1079. CoUninitialize( );
  1080. return 0;
  1081. }
  1082. DWORD CFilterProxyManager::GetLastSentStamp()
  1083. {
  1084. return m_dwLastSentStamp;
  1085. }
  1086. //*****************************************************************************
  1087. //*****************************************************************************
  1088. //
  1089. // FILTER PROXY
  1090. //
  1091. //*****************************************************************************
  1092. //*****************************************************************************
  1093. CTimeKeeper CFilterProxy::mstatic_TimeKeeper;
  1094. BYTE CFilterProxy::mstatic_EmptySD = 0;
  1095. CFilterProxy::CFilterProxy(CFilterProxyManager* pManager, IUnknown* pCallback)
  1096. : m_lRef(0), m_pManager(pManager), m_pMetaData(NULL),
  1097. m_lSDLength(0), m_pSD(&mstatic_EmptySD), m_pProvider(NULL),
  1098. m_pQuerySink(NULL), m_bRunning(false),
  1099. m_typeBatch(WBEM_FLAG_MUST_NOT_BATCH), m_bUtilizeGuarantee(false),
  1100. m_dwCurrentBufferSize(0), m_bBatching(FALSE),
  1101. m_wSourceVersion(0), m_wAppliedSourceVersion(0)
  1102. {
  1103. m_SourceDefinition.SetBool(FALSE);
  1104. if(m_pManager)
  1105. {
  1106. m_pManager->AddRef();
  1107. m_pManager->GetMetaData(&m_pMetaData);
  1108. }
  1109. if(pCallback)
  1110. {
  1111. pCallback->QueryInterface(IID_IWbemEventProvider, (void**)&m_pProvider);
  1112. pCallback->QueryInterface(IID_IWbemEventProviderQuerySink,
  1113. (void**)&m_pQuerySink);
  1114. }
  1115. }
  1116. CFilterProxy::~CFilterProxy()
  1117. {
  1118. if (m_pMetaData)
  1119. m_pMetaData->Release();
  1120. if (m_pManager)
  1121. m_pManager->Release();
  1122. }
  1123. ULONG STDMETHODCALLTYPE CFilterProxy::AddRef()
  1124. {
  1125. return InterlockedIncrement(&m_lRef);
  1126. }
  1127. ULONG STDMETHODCALLTYPE CFilterProxy::Release()
  1128. {
  1129. //
  1130. // CFilterProxy is deleted by CFilterProxyManager --- it never goes away
  1131. // on a Release
  1132. //
  1133. long lRef = InterlockedDecrement(&m_lRef);
  1134. if(lRef == 0)
  1135. {
  1136. //
  1137. // Inform the manager that we are no longer needed. This call can
  1138. // destroy this object!
  1139. //
  1140. m_pManager->RemoveProxy(this);
  1141. }
  1142. return lRef;
  1143. }
  1144. HRESULT STDMETHODCALLTYPE CFilterProxy::QueryInterface(REFIID riid, void** ppv)
  1145. {
  1146. if( riid == IID_IUnknown ||
  1147. riid == IID_IWbemObjectSink ||
  1148. riid == IID_IWbemEventSink)
  1149. {
  1150. *ppv = (IWbemEventSink*)this;
  1151. }
  1152. else if(riid == IID_IMarshal)
  1153. {
  1154. *ppv = (IMarshal*)this;
  1155. }
  1156. else
  1157. return E_NOINTERFACE;
  1158. ((IUnknown*)*ppv)->AddRef();
  1159. return S_OK;
  1160. }
  1161. HRESULT CFilterProxy::Lock()
  1162. {
  1163. return m_pManager->Lock();
  1164. }
  1165. HRESULT CFilterProxy::Unlock()
  1166. {
  1167. return m_pManager->Unlock();
  1168. }
  1169. HRESULT CFilterProxy::SetRunning()
  1170. {
  1171. HRESULT hres;
  1172. bool bActive = false;
  1173. IWbemEventProvider* pProvider = NULL;
  1174. {
  1175. CInCritSec ics(&m_cs);
  1176. if(m_bRunning)
  1177. return WBEM_S_FALSE;
  1178. else
  1179. {
  1180. m_bRunning = true;
  1181. if(m_pProvider)
  1182. {
  1183. bActive = (IsActive() == WBEM_S_NO_ERROR);
  1184. pProvider = m_pProvider;
  1185. pProvider->AddRef();
  1186. }
  1187. }
  1188. }
  1189. //
  1190. // If here, we are just now marking it for running. Notify the callback if
  1191. // there are any sinks
  1192. //
  1193. if(bActive && pProvider)
  1194. {
  1195. hres = pProvider->ProvideEvents(NULL, WBEM_FLAG_START_PROVIDING);
  1196. if(FAILED(hres))
  1197. {
  1198. ERRORTRACE((LOG_ESS, "Restricted sink refused to stop "
  1199. "error code 0x%X\n", hres));
  1200. }
  1201. }
  1202. return WBEM_S_NO_ERROR;
  1203. }
  1204. HRESULT CFilterProxy::AddFilter(IWbemContext* pContext,
  1205. LPCWSTR wszQuery,
  1206. QL_LEVEL_1_RPN_EXPRESSION* pExp,
  1207. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  1208. {
  1209. HRESULT hres;
  1210. // Compile the query
  1211. // =================
  1212. CContextMetaData MetaData(m_pMetaData, pContext);
  1213. CEvalTree Tree;
  1214. hres = Tree.CreateFromQuery( &MetaData, pExp, WBEM_FLAG_MANDATORY_MERGE );
  1215. if(FAILED(hres))
  1216. {
  1217. ERRORTRACE((LOG_ESS, "Filter proxy unable to parse %S, "
  1218. "error code: %X\n", wszQuery, hres));
  1219. return hres;
  1220. }
  1221. //
  1222. // merge the query into the rest of the filter.
  1223. //
  1224. {
  1225. CInCritSec ics(&m_cs);
  1226. if ( m_bUtilizeGuarantee )
  1227. {
  1228. //
  1229. // Utilize source definition
  1230. // =========================
  1231. //
  1232. // assert that our source definition hasn't changed since the last
  1233. // time a filter was added. This would be bad, since the tree
  1234. // doesn't account for the new source queries. Also assert that
  1235. // the source tree is valid and is not empty. ( These last two may
  1236. // have to be removed in the future. For now they shouldn't be
  1237. // false )
  1238. //
  1239. _ESSCLI_ASSERT( m_wAppliedSourceVersion == 0 ||
  1240. m_wAppliedSourceVersion == m_wSourceVersion );
  1241. _ESSCLI_ASSERT( m_SourceDefinition.IsValid() );
  1242. _ESSCLI_ASSERT( !m_SourceDefinition.IsFalse() );
  1243. hres = Tree.UtilizeGuarantee(m_SourceDefinition, &MetaData);
  1244. if(FAILED(hres))
  1245. {
  1246. ERRORTRACE((LOG_ESS,
  1247. "Filter proxy unable to utilize guarantee for %S, "
  1248. "error code: %X\n", wszQuery, hres));
  1249. return hres;
  1250. }
  1251. //
  1252. // Check if anything is left of it
  1253. //
  1254. if(!Tree.IsValid())
  1255. {
  1256. //
  1257. // Utilization of the guarantee shows that this filter cannot
  1258. // be satisftied by events coming through this proxy
  1259. //
  1260. return WBEM_S_FALSE;
  1261. }
  1262. }
  1263. //
  1264. // Add consumer information to it
  1265. //
  1266. Tree.Rebase((QueryID)idFilter);
  1267. #ifdef DUMP_DEBUG_TREES
  1268. FILE* f = fopen("c:\\try.log", "a");
  1269. fprintf(f, "\n\nAdding filter\n");
  1270. Tree.Dump(f);
  1271. fprintf(f, " to existing filter: \n");
  1272. m_Filter.Dump(f);
  1273. #endif
  1274. hres = m_Filter.CombineWith(Tree, &MetaData, EVAL_OP_COMBINE);
  1275. if(FAILED(hres))
  1276. {
  1277. ERRORTRACE((LOG_ESS, "Filter proxy unable to combine %S with the "
  1278. "rest, error code: %X\n", wszQuery, hres));
  1279. return hres;
  1280. }
  1281. m_wAppliedSourceVersion = m_wSourceVersion;
  1282. }
  1283. //
  1284. // Now, we need to notify the provider of a new filter being issued
  1285. //
  1286. IWbemEventProviderQuerySink* pQuerySink = NULL;
  1287. IWbemEventProvider* pProvider = NULL;
  1288. {
  1289. CInCritSec ics(&m_cs);
  1290. if(m_pQuerySink)
  1291. {
  1292. pQuerySink = m_pQuerySink;
  1293. pQuerySink->AddRef();
  1294. }
  1295. if(m_pProvider)
  1296. {
  1297. pProvider = m_pProvider;
  1298. pProvider->AddRef();
  1299. }
  1300. }
  1301. //
  1302. // Call provider's NewQuery, if supported
  1303. //
  1304. if(pQuerySink)
  1305. {
  1306. hres = pQuerySink->NewQuery(idFilter, L"WQL", (LPWSTR)wszQuery);
  1307. if(FAILED(hres))
  1308. {
  1309. ERRORTRACE((LOG_ESS, "Restricted sink refused consumer "
  1310. "registration query %S: error code 0x%X\n",
  1311. wszQuery, hres));
  1312. // Too bad --- restricted sinks cannot veto subscriptions
  1313. }
  1314. }
  1315. //
  1316. // If we are adding this filter to a running proxy, and this is the very
  1317. // first filter on it, we should call ProvideEvents immediately. Not so if
  1318. // we are configuring a proxy that is not running yet --- in that case, we
  1319. // need to wait until all outstanding filters have been put in place
  1320. //
  1321. if(m_bRunning && (IsActive() == WBEM_S_FALSE) && pProvider)
  1322. {
  1323. hres = pProvider->ProvideEvents((IWbemObjectSink*)this,
  1324. WBEM_FLAG_START_PROVIDING);
  1325. if(FAILED(hres))
  1326. {
  1327. ERRORTRACE((LOG_ESS, "Restricted sink refused a call to "
  1328. "ProvideEvents with 0x%X\n", hres));
  1329. }
  1330. }
  1331. #ifdef DUMP_DEBUG_TREES
  1332. fprintf(f, " to obtain: \n");
  1333. m_Filter.Dump(f);
  1334. fclose(f);
  1335. #endif
  1336. return WBEM_S_NO_ERROR;
  1337. }
  1338. HRESULT CFilterProxy::RemoveFilter(IWbemContext* pContext,
  1339. WBEM_REMOTE_TARGET_ID_TYPE idFilter)
  1340. {
  1341. HRESULT hres;
  1342. IWbemEventProviderQuerySink* pQuerySink = NULL;
  1343. IWbemEventProvider* pProvider = NULL;
  1344. bool bActive;
  1345. {
  1346. CInCritSec ics(&m_cs);
  1347. if(m_pQuerySink)
  1348. {
  1349. pQuerySink = m_pQuerySink;
  1350. pQuerySink->AddRef();
  1351. }
  1352. if(m_pProvider)
  1353. {
  1354. pProvider = m_pProvider;
  1355. pProvider->AddRef();
  1356. }
  1357. hres = m_Filter.RemoveIndex(idFilter);
  1358. if(FAILED(hres))
  1359. {
  1360. ERRORTRACE((LOG_ESS, "Unable to remove index %d from the filter "
  1361. "proxy\n", idFilter));
  1362. return hres;
  1363. }
  1364. CContextMetaData MetaData(m_pMetaData, pContext);
  1365. hres = m_Filter.Optimize(&MetaData);
  1366. if(FAILED(hres))
  1367. return hres;
  1368. bActive = (IsActive() == WBEM_S_NO_ERROR);
  1369. }
  1370. //
  1371. // Call provider's NewQuery, if supported
  1372. //
  1373. if(pQuerySink)
  1374. {
  1375. hres = pQuerySink->CancelQuery(idFilter);
  1376. if(FAILED(hres))
  1377. {
  1378. ERRORTRACE((LOG_ESS, "Restricted sink refused consumer "
  1379. "registration query cancellation: error code 0x%X\n",
  1380. hres));
  1381. }
  1382. }
  1383. //
  1384. // If we are left with no queries, notify provider of that fact
  1385. //
  1386. if(!bActive && pProvider)
  1387. {
  1388. hres = pProvider->ProvideEvents(NULL, WBEM_FLAG_STOP_PROVIDING);
  1389. if(FAILED(hres))
  1390. {
  1391. ERRORTRACE((LOG_ESS, "Restricted sink refused to stop "
  1392. "error code 0x%X\n", hres));
  1393. }
  1394. }
  1395. #ifdef DUMP_DEBUG_TREES
  1396. FILE* f = fopen("c:\\try.log", "a");
  1397. fprintf(f, "Removed at %d to obtain: \n", idFilter);
  1398. m_Filter.Dump(f);
  1399. fclose(f);
  1400. #endif
  1401. return WBEM_S_NO_ERROR;
  1402. }
  1403. HRESULT CFilterProxy::RemoveAllFilters(IWbemContext* pContext)
  1404. {
  1405. CInCritSec ics(&m_cs);
  1406. m_wAppliedSourceVersion = 0;
  1407. if(!m_Filter.Clear())
  1408. return WBEM_E_OUT_OF_MEMORY;
  1409. return WBEM_S_NO_ERROR;
  1410. }
  1411. HRESULT CFilterProxy::AllowUtilizeGuarantee()
  1412. {
  1413. //
  1414. // ess shouldn't be calling this function if the tree is invalid.
  1415. //
  1416. _DBG_ASSERT( m_SourceDefinition.IsValid() );
  1417. //
  1418. // ess thinks its o.k. to utilize the guarantee, however there are cases
  1419. // where the soruce definition could still be false ( e.g. when there are
  1420. // no source definition queries or when all of the source definition
  1421. // queries are contradictions ).
  1422. //
  1423. CInCritSec ics(&m_cs);
  1424. if ( !m_SourceDefinition.IsFalse() )
  1425. {
  1426. m_bUtilizeGuarantee = true;
  1427. }
  1428. return WBEM_S_NO_ERROR;
  1429. }
  1430. HRESULT CFilterProxy::AddDefinitionQuery( IWbemContext* pContext,
  1431. LPCWSTR wszQuery )
  1432. {
  1433. HRESULT hres;
  1434. // Compile the query
  1435. // =================
  1436. CContextMetaData MetaData(m_pMetaData, pContext);
  1437. CEvalTree Tree;
  1438. hres = Tree.CreateFromQuery( &MetaData,
  1439. wszQuery,
  1440. WBEM_FLAG_MANDATORY_MERGE,
  1441. 0x7FFFFFFF ); // no limit
  1442. if(FAILED(hres))
  1443. {
  1444. return hres;
  1445. }
  1446. {
  1447. CInCritSec ics(&m_cs);
  1448. //
  1449. // we shouldn't be adding definition queries when there are currently
  1450. // existing filters.
  1451. //
  1452. _ESSCLI_ASSERT( m_Filter.IsFalse() );
  1453. // Merge the query into the rest
  1454. // =============================
  1455. hres = m_SourceDefinition.CombineWith(Tree, &MetaData, EVAL_OP_OR,
  1456. WBEM_FLAG_MANDATORY_MERGE);
  1457. if(FAILED(hres))
  1458. return hres;
  1459. m_wSourceVersion++;
  1460. }
  1461. return WBEM_S_NO_ERROR;
  1462. }
  1463. HRESULT CFilterProxy::RemoveAllDefinitionQueries( IWbemContext* pContext)
  1464. {
  1465. CInCritSec ics(&m_cs);
  1466. m_wSourceVersion = 0;
  1467. m_SourceDefinition.SetBool(FALSE);
  1468. m_bUtilizeGuarantee = false;
  1469. return WBEM_S_NO_ERROR;
  1470. }
  1471. HRESULT CFilterProxy::ProcessOne( IUnknown* pUnk,
  1472. long lSDLength,
  1473. BYTE* pSD )
  1474. {
  1475. //
  1476. // NOTE: not in a critical section yet
  1477. //
  1478. HRESULT hres;
  1479. //
  1480. // Check overall validity
  1481. //
  1482. if( pUnk == NULL )
  1483. {
  1484. ERRORTRACE((LOG_ESS, "Event provider returned a NULL event!\n"));
  1485. return WBEM_E_INVALID_PARAMETER;
  1486. }
  1487. CWbemObject* pObj = (CWbemObject*)(IWbemClassObject*)pUnk;
  1488. if( pObj->IsObjectInstance() != WBEM_S_NO_ERROR )
  1489. {
  1490. ERRORTRACE((LOG_ESS, "CLASS object received from event provider!\n"));
  1491. return WBEM_E_INVALID_PARAMETER;
  1492. }
  1493. //
  1494. // Run the event through the filter
  1495. //
  1496. CSortedArray aTrues, aSourceTrues;
  1497. CFilterProxyManager* pManager = NULL;
  1498. {
  1499. CInCritSec ics(&m_cs);
  1500. hres = FilterEvent( pObj, aTrues );
  1501. if ( hres == WBEM_S_NO_ERROR )
  1502. {
  1503. _DBG_ASSERT( aTrues.Size() > 0 );
  1504. }
  1505. else
  1506. {
  1507. return hres;
  1508. }
  1509. pManager = m_pManager;
  1510. if( pManager )
  1511. {
  1512. pManager->AddRef();
  1513. }
  1514. else
  1515. {
  1516. return WBEM_S_FALSE;
  1517. }
  1518. }
  1519. CReleaseMe rm2(pManager);
  1520. //
  1521. // the event has made it through the filter ..
  1522. //
  1523. SetGenerationTime(pObj);
  1524. if (IsBatching())
  1525. {
  1526. BatchEvent((IWbemClassObject*) pUnk, &aTrues);
  1527. hres = S_OK;
  1528. }
  1529. else
  1530. {
  1531. // Some delivery is required --- construct the blob and the targets
  1532. // ================================================================
  1533. WBEM_REM_TARGETS RemTargets;
  1534. if(!TempSetTargets(&RemTargets, &aTrues))
  1535. return WBEM_E_OUT_OF_MEMORY;
  1536. hres = pManager->DeliverEvent(1, (IWbemClassObject**)&pObj,
  1537. &RemTargets, lSDLength, pSD);
  1538. TempClearTargets(&RemTargets);
  1539. if(FAILED(hres))
  1540. {
  1541. ERRORTRACE((LOG_ESS, "Filter stub failed to process an event: "
  1542. "0x%X\n", hres));
  1543. }
  1544. }
  1545. return hres;
  1546. }
  1547. void CFilterProxy::SetGenerationTime(_IWmiObject* pObj)
  1548. {
  1549. mstatic_TimeKeeper.DecorateObject(pObj);
  1550. }
  1551. void CFilterProxyManager::AddEvent(
  1552. IWbemClassObject *pObj,
  1553. CSortedArray *pTrues)
  1554. {
  1555. LockBatching();
  1556. BOOL bWasEmpty = m_batch.GetItemCount() == 0;
  1557. m_batch.AddEvent(pObj, pTrues);
  1558. if (bWasEmpty)
  1559. SetEvent(m_heventEventsPending);
  1560. UnlockBatching();
  1561. }
  1562. void CFilterProxyManager::WaitForEmptyBatch()
  1563. {
  1564. LockBatching();
  1565. // Once we get the lock and the batch has already been cleared out, we
  1566. // don't need to do anything else.
  1567. if (m_batch.GetItemCount() == 0)
  1568. {
  1569. UnlockBatching();
  1570. return;
  1571. }
  1572. // We need to wait for the send thread to finish sending what's
  1573. // in our buffer.
  1574. // Wake up the send latency thread if necessary.
  1575. if (m_dwMaxSendLatency)
  1576. SetEvent(m_heventBufferFull);
  1577. // So we'll block until the send thread sets the event.
  1578. ResetEvent(m_heventBufferNotFull);
  1579. UnlockBatching();
  1580. WaitForSingleObject(m_heventBufferNotFull, INFINITE);
  1581. }
  1582. void CFilterProxy::BatchEvent(
  1583. IWbemClassObject *pObj,
  1584. CSortedArray *pTrues)
  1585. {
  1586. BOOL bRet = FALSE;
  1587. _IWmiObject *pWmiObj = (_IWmiObject*) pObj;
  1588. DWORD dwObjSize = 0;
  1589. pWmiObj->GetObjectMemory(
  1590. NULL,
  1591. 0,
  1592. &dwObjSize);
  1593. CInCritSec ics(&m_cs);
  1594. // See if the manager has sent off its batch of events since we last
  1595. // batched an event.
  1596. if (m_dwLastSentStamp != m_pManager->GetLastSentStamp())
  1597. m_dwCurrentBufferSize = 0;
  1598. // See if we have enough room to add our event.
  1599. if (m_dwCurrentBufferSize >= m_dwMaxBufferSize)
  1600. {
  1601. m_pManager->WaitForEmptyBatch();
  1602. m_dwCurrentBufferSize = 0;
  1603. }
  1604. m_dwCurrentBufferSize += dwObjSize;
  1605. m_dwLastSentStamp = m_pManager->GetLastSentStamp();
  1606. m_pManager->AddEvent(pObj, pTrues);
  1607. }
  1608. HRESULT CFilterProxy::FilterEvent( _IWmiObject* pObj, CSortedArray& raTrues )
  1609. {
  1610. HRESULT hr;
  1611. //
  1612. // evaluate
  1613. //
  1614. try
  1615. {
  1616. //
  1617. // this code is in a try catch because if a provider generates
  1618. // events that it has not registered to, then we do bad things to
  1619. // class objects. A potential fix could be do extra checking on
  1620. // our part, but is expensive when using the public interfaces. A
  1621. // more advantageous fix should be making the class object code
  1622. // perform the checking for us ( e.g. when we ask for a property
  1623. // using an invalid handle, etc ). It can do this checking much
  1624. // faster. When this checking is performed by the class object
  1625. // code, we should remove this try catch. see RAID 166026
  1626. //
  1627. hr = m_Filter.Evaluate( pObj, raTrues );
  1628. }
  1629. catch( ... )
  1630. {
  1631. //
  1632. // check to see if the provider is generating an event its not
  1633. // supposed to. If so, then handle AV and return error, else
  1634. // rethrow - there's something else wrong.
  1635. //
  1636. CSortedArray aSourceTrues;
  1637. hr = m_SourceDefinition.Evaluate( pObj, aSourceTrues );
  1638. if ( SUCCEEDED(hr) && aSourceTrues.Size() == 0 )
  1639. {
  1640. ERRORTRACE((LOG_ESS, "Filter Proxy encountered case where "
  1641. "event provider is signaling events that are not "
  1642. "covered by its registration!!\n"));
  1643. hr = WBEM_E_INVALID_OBJECT;
  1644. }
  1645. else
  1646. {
  1647. throw;
  1648. }
  1649. }
  1650. //
  1651. // check events that make it through the filter against source definition.
  1652. // if we're not utilizing guarantee, then there's no need to check the
  1653. // event against the source definition because its already factored into
  1654. // the filter.
  1655. //
  1656. if (SUCCEEDED(hr) && raTrues.Size() == 0 )
  1657. {
  1658. hr = WBEM_S_FALSE;
  1659. }
  1660. else if ( SUCCEEDED(hr) && m_bUtilizeGuarantee )
  1661. {
  1662. //
  1663. // run the event through the source tree to ensure that the
  1664. // provider is providing the events its supposed to.
  1665. //
  1666. CSortedArray aSourceTrues;
  1667. hr = m_SourceDefinition.Evaluate( pObj, aSourceTrues );
  1668. if ( SUCCEEDED(hr) && aSourceTrues.Size() == 0 )
  1669. {
  1670. ERRORTRACE((LOG_ESS, "Filter Proxy encountered case where "
  1671. "event provider is signaling events that are not "
  1672. "covered by its registration!!\n"));
  1673. hr = WBEM_E_INVALID_OBJECT;
  1674. }
  1675. }
  1676. return hr;
  1677. }
  1678. HRESULT CFilterProxy::BatchMany(long nEvents, IUnknown **ppObjects)
  1679. {
  1680. HRESULT hr = S_OK;
  1681. for ( long i = 0; i < nEvents && SUCCEEDED(hr); i++ )
  1682. {
  1683. //
  1684. // Check overall validity
  1685. //
  1686. if( ppObjects[i] == NULL )
  1687. {
  1688. ERRORTRACE((LOG_ESS, "Event provider returned a NULL event!\n"));
  1689. return WBEM_E_INVALID_PARAMETER;
  1690. }
  1691. CWbemObject *pObj = (CWbemObject*)(IWbemClassObject*)ppObjects[i];
  1692. if( pObj->IsObjectInstance() != WBEM_S_NO_ERROR )
  1693. {
  1694. ERRORTRACE((LOG_ESS, "CLASS object received from event provider!\n"));
  1695. return WBEM_E_INVALID_PARAMETER;
  1696. }
  1697. //
  1698. // Run the event through the filter
  1699. //
  1700. CInCritSec ics(&m_cs);
  1701. CSortedArray aTrues;
  1702. hr = FilterEvent( pObj, aTrues );
  1703. if ( hr == WBEM_S_NO_ERROR )
  1704. {
  1705. _DBG_ASSERT( aTrues.Size() > 0 );
  1706. //
  1707. // Delivery is required --- add this event to the list
  1708. //
  1709. SetGenerationTime(pObj);
  1710. BatchEvent(pObj, &aTrues);
  1711. }
  1712. }
  1713. return hr;
  1714. }
  1715. class CDeleteTargetsArray
  1716. {
  1717. protected:
  1718. WBEM_REM_TARGETS *m_pData;
  1719. int *m_piSize;
  1720. public:
  1721. CDeleteTargetsArray(WBEM_REM_TARGETS *pData, int *piSize) :
  1722. m_pData(pData),
  1723. m_piSize(piSize)
  1724. {
  1725. }
  1726. ~CDeleteTargetsArray()
  1727. {
  1728. int nSize = *m_piSize;
  1729. for (DWORD i = 0; i < nSize; i++)
  1730. TempClearTargets(m_pData + i);
  1731. }
  1732. };
  1733. HRESULT CFilterProxy::ProcessMany(long lNumObjects,
  1734. IUnknown** apObjects,
  1735. long lSDLength, BYTE* pSD)
  1736. {
  1737. //
  1738. // NOTE: not in critical section
  1739. //
  1740. HRESULT hres;
  1741. if (IsBatching())
  1742. return BatchMany(lNumObjects, apObjects);
  1743. //
  1744. // Allocate appropriate arrays on the stack
  1745. //
  1746. CTempArray<IWbemClassObject*> apEventsToSend;
  1747. INIT_TEMP_ARRAY(apEventsToSend, lNumObjects);
  1748. if(apEventsToSend == NULL)
  1749. return WBEM_E_OUT_OF_MEMORY;
  1750. CTempArray<WBEM_REM_TARGETS> aTargetsToSend;
  1751. INIT_TEMP_ARRAY(aTargetsToSend, lNumObjects);
  1752. if(aTargetsToSend == NULL)
  1753. return WBEM_E_OUT_OF_MEMORY;
  1754. int lNumToSend = 0;
  1755. // Make sure the array gets cleaned up.
  1756. CDeleteTargetsArray deleteMe(aTargetsToSend, &lNumToSend);
  1757. //
  1758. // Iterate over events supplied and move those that need to be delivered
  1759. // into delivery arrays
  1760. //
  1761. CFilterProxyManager* pManager = NULL;
  1762. {
  1763. //
  1764. // We could choose a smaller window, but I am betting that the cost of
  1765. // entering and exiting the cs many times will outweigh the benefits
  1766. // of slightly smaller windows
  1767. //
  1768. CInCritSec ics(&m_cs);
  1769. for(long i = 0; i < lNumObjects; i++)
  1770. {
  1771. //
  1772. // Check overall validity
  1773. //
  1774. if( apObjects[i] == NULL )
  1775. {
  1776. ERRORTRACE((LOG_ESS, "Event provider returned a NULL event!\n"));
  1777. return WBEM_E_INVALID_PARAMETER;
  1778. }
  1779. CWbemObject *pObj = (CWbemObject*)(IWbemClassObject*)apObjects[i];
  1780. if( pObj->IsObjectInstance() != WBEM_S_NO_ERROR )
  1781. {
  1782. ERRORTRACE((LOG_ESS, "CLASS object received from event provider!\n"));
  1783. return WBEM_E_INVALID_PARAMETER;
  1784. }
  1785. //
  1786. // Run the event through the filter
  1787. //
  1788. CSortedArray aTrues;
  1789. hres = FilterEvent( pObj, aTrues );
  1790. if ( hres == WBEM_S_FALSE )
  1791. {
  1792. ;
  1793. }
  1794. else if ( hres == WBEM_S_NO_ERROR )
  1795. {
  1796. _DBG_ASSERT( aTrues.Size() > 0 );
  1797. //
  1798. // Delivery is required --- add this event to the list
  1799. //
  1800. SetGenerationTime(pObj);
  1801. apEventsToSend[lNumToSend] = pObj;
  1802. if(!TempSetTargets(aTargetsToSend + lNumToSend, &aTrues))
  1803. return WBEM_E_OUT_OF_MEMORY;
  1804. lNumToSend++;
  1805. }
  1806. else
  1807. {
  1808. return hres;
  1809. }
  1810. }
  1811. //
  1812. // If any events need to be delivered, get the delivery pointer
  1813. //
  1814. if(lNumToSend > 0)
  1815. {
  1816. pManager = m_pManager;
  1817. if(pManager)
  1818. pManager->AddRef();
  1819. else
  1820. return WBEM_S_FALSE;
  1821. }
  1822. }
  1823. CReleaseMe rm1(pManager);
  1824. //
  1825. // If any events need to be delivered, deliver
  1826. //
  1827. if(lNumToSend > 0)
  1828. {
  1829. hres = pManager->DeliverEvent(lNumToSend, apEventsToSend,
  1830. aTargetsToSend,
  1831. lSDLength, pSD);
  1832. if(FAILED(hres))
  1833. {
  1834. ERRORTRACE((LOG_ESS, "Filter stub failed to process an event: "
  1835. "error code %X\n", hres));
  1836. }
  1837. return hres;
  1838. }
  1839. return WBEM_S_FALSE;
  1840. }
  1841. HRESULT STDMETHODCALLTYPE CFilterProxy::Indicate(long lNumObjects,
  1842. IWbemClassObject** apObjects)
  1843. {
  1844. return IndicateWithSD(lNumObjects, (IUnknown**)apObjects,
  1845. m_lSDLength, m_pSD);
  1846. }
  1847. HRESULT STDMETHODCALLTYPE CFilterProxy::SetStatus(long lFlags, HRESULT hResult,
  1848. BSTR strResult, IWbemClassObject* pErrorObj)
  1849. {
  1850. return m_pManager->SetStatus(lFlags, hResult, strResult, pErrorObj);
  1851. }
  1852. STDMETHODIMP CFilterProxy::IndicateWithSD(long lNumObjects,
  1853. IUnknown** apObjects, long lSDLength, BYTE* pSD)
  1854. {
  1855. if(lNumObjects <= 0 || apObjects == NULL)
  1856. return WBEM_E_INVALID_PARAMETER;
  1857. if(pSD == NULL)
  1858. {
  1859. //
  1860. // Use proxy defaults
  1861. //
  1862. lSDLength = m_lSDLength;
  1863. pSD = m_pSD;
  1864. }
  1865. try
  1866. {
  1867. //
  1868. // Special-case single event
  1869. //
  1870. if(lNumObjects == 1)
  1871. return ProcessOne(*apObjects, lSDLength, pSD);
  1872. else
  1873. return ProcessMany(lNumObjects, apObjects, lSDLength, pSD);
  1874. }
  1875. catch(...)
  1876. {
  1877. return WBEM_E_OUT_OF_MEMORY;
  1878. }
  1879. }
  1880. STDMETHODIMP CFilterProxy::IsActive()
  1881. {
  1882. CInCritSec ics(&m_cs);
  1883. return (m_Filter.IsFalse()?WBEM_S_FALSE:WBEM_S_NO_ERROR);
  1884. return WBEM_S_NO_ERROR;
  1885. }
  1886. STDMETHODIMP CFilterProxy::SetSinkSecurity(
  1887. long lSDLength,
  1888. BYTE* pSD)
  1889. {
  1890. CInCritSec ics(&m_cs);
  1891. //
  1892. // Check for validity
  1893. //
  1894. if(lSDLength < 0)
  1895. return WBEM_E_INVALID_PARAMETER;
  1896. if(lSDLength > 0)
  1897. {
  1898. SECURITY_DESCRIPTOR* pDesc = (SECURITY_DESCRIPTOR*)pSD;
  1899. if(!IsValidSecurityDescriptor(pDesc))
  1900. return WBEM_E_INVALID_PARAMETER;
  1901. if(pDesc->Owner == NULL || pDesc->Group == NULL)
  1902. return WBEM_E_INVALID_PARAMETER;
  1903. if(GetSecurityDescriptorLength(pSD) != (DWORD)lSDLength)
  1904. return WBEM_E_INVALID_PARAMETER;
  1905. }
  1906. else
  1907. {
  1908. if(pSD != NULL)
  1909. return WBEM_E_INVALID_PARAMETER;
  1910. }
  1911. //
  1912. // Store the SD in the proxy
  1913. //
  1914. if(m_pSD && m_pSD != &mstatic_EmptySD)
  1915. delete [] m_pSD;
  1916. if(lSDLength)
  1917. {
  1918. m_pSD = new BYTE[lSDLength];
  1919. if(m_pSD == NULL)
  1920. return WBEM_E_OUT_OF_MEMORY;
  1921. memcpy(m_pSD, pSD, lSDLength);
  1922. }
  1923. else
  1924. {
  1925. //
  1926. // Cannot let m_pSD be NULL
  1927. //
  1928. m_pSD = &mstatic_EmptySD;
  1929. }
  1930. m_lSDLength = lSDLength;
  1931. return WBEM_S_NO_ERROR;
  1932. }
  1933. STDMETHODIMP CFilterProxy::GetRestrictedSink(
  1934. long lNumQueries,
  1935. const LPCWSTR* awszQueries,
  1936. IUnknown* pCallback,
  1937. IWbemEventSink** ppSink)
  1938. {
  1939. return m_pManager->GetRestrictedSink(lNumQueries, awszQueries,
  1940. pCallback, ppSink);
  1941. }
  1942. STDMETHODIMP CFilterProxy::SetBatchingParameters(
  1943. LONG lFlags,
  1944. DWORD dwMaxBufferSize,
  1945. DWORD dwMaxSendLatency)
  1946. {
  1947. HRESULT hr = S_OK;
  1948. CInCritSec ics(&m_cs);
  1949. switch(lFlags)
  1950. {
  1951. // TODO: WBEM_FLAG_BATCH_IF_NEEDED currently works the same as
  1952. // WBEM_FLAG_MUST_NOT_BATCH. At some point this needs allow
  1953. // subscriptions to determine the batching behavior.
  1954. case WBEM_FLAG_BATCH_IF_NEEDED:
  1955. case WBEM_FLAG_MUST_NOT_BATCH:
  1956. m_typeBatch = (WBEM_BATCH_TYPE) lFlags;
  1957. m_pManager->RemoveProxyLatency(this);
  1958. m_bBatching = FALSE;
  1959. break;
  1960. case WBEM_FLAG_MUST_BATCH:
  1961. m_typeBatch = (WBEM_BATCH_TYPE) lFlags;
  1962. m_dwMaxSendLatency = dwMaxSendLatency;
  1963. m_dwMaxBufferSize = dwMaxBufferSize;
  1964. m_dwLastSentStamp = m_pManager->GetLastSentStamp();
  1965. hr = m_pManager->SetProxyLatency(this, dwMaxSendLatency);
  1966. m_bBatching = TRUE;
  1967. break;
  1968. default:
  1969. hr = WBEM_E_INVALID_PARAMETER;
  1970. break;
  1971. }
  1972. return hr;
  1973. }
  1974. // Assumes pMainProxy is locked
  1975. HRESULT CFilterProxy::TransferFiltersFromMain(CFilterProxy* pMain)
  1976. {
  1977. HRESULT hres;
  1978. //
  1979. // Move all the normal filters
  1980. //
  1981. try
  1982. {
  1983. m_Filter = pMain->m_Filter;
  1984. }
  1985. catch(CX_MemoryException)
  1986. {
  1987. return WBEM_E_OUT_OF_MEMORY;
  1988. }
  1989. if ( m_bUtilizeGuarantee )
  1990. {
  1991. // Utilize source definition
  1992. // =========================
  1993. CContextMetaData MetaData(m_pMetaData, NULL);
  1994. hres = m_Filter.UtilizeGuarantee(m_SourceDefinition, &MetaData);
  1995. if(FAILED(hres))
  1996. {
  1997. ERRORTRACE((LOG_ESS, "Filter proxy unable to utilize guarantee for"
  1998. " a new proxy; error code: %X\n", hres));
  1999. return hres;
  2000. }
  2001. }
  2002. return WBEM_S_NO_ERROR;
  2003. }
  2004. STDMETHODIMP CFilterProxy::GetUnmarshalClass(REFIID riid, void* pv,
  2005. DWORD dwDestContext, void* pvReserved, DWORD mshlFlags,
  2006. CLSID* pClsid)
  2007. {
  2008. return m_pManager->GetUnmarshalClass(riid, pv, dwDestContext, pvReserved,
  2009. mshlFlags, pClsid);
  2010. }
  2011. STDMETHODIMP CFilterProxy::GetMarshalSizeMax(REFIID riid, void* pv,
  2012. DWORD dwDestContext, void* pvReserved, DWORD mshlFlags,
  2013. ULONG* plSize)
  2014. {
  2015. return m_pManager->GetMarshalSizeMax(riid, pv, dwDestContext, pvReserved,
  2016. mshlFlags, plSize);
  2017. }
  2018. STDMETHODIMP CFilterProxy::MarshalInterface(IStream* pStream, REFIID riid,
  2019. void* pv, DWORD dwDestContext, void* pvReserved,
  2020. DWORD mshlFlags)
  2021. {
  2022. return m_pManager->MarshalInterface(pStream, riid, pv, dwDestContext,
  2023. pvReserved, mshlFlags);
  2024. }
  2025. /////////////////////////////////////////////////////////////////////////////
  2026. // CEventBatch
  2027. #define INIT_SIZE 32
  2028. #define GROW_SIZE 32
  2029. CEventBatch::CEventBatch() :
  2030. m_ppObjs(NULL),
  2031. m_pTargets(NULL),
  2032. m_nItems(0),
  2033. m_dwSize(0)
  2034. {
  2035. m_ppObjs = new IWbemClassObject*[INIT_SIZE];
  2036. if (!m_ppObjs)
  2037. throw CX_MemoryException();
  2038. m_pTargets = new WBEM_REM_TARGETS[INIT_SIZE];
  2039. if (!m_pTargets)
  2040. throw CX_MemoryException();
  2041. m_dwSize = INIT_SIZE;
  2042. }
  2043. CEventBatch::~CEventBatch()
  2044. {
  2045. RemoveAll();
  2046. if (m_ppObjs)
  2047. delete [] m_ppObjs;
  2048. if (m_pTargets)
  2049. delete [] m_pTargets;
  2050. }
  2051. BOOL CEventBatch::EnsureAdditionalSize(DWORD nAdditionalNeeded)
  2052. {
  2053. if (m_nItems + nAdditionalNeeded > m_dwSize)
  2054. {
  2055. DWORD nNewSize = m_nItems + nAdditionalNeeded + GROW_SIZE;
  2056. IWbemClassObject **ppNewObjs;
  2057. WBEM_REM_TARGETS *pNewTargets;
  2058. ppNewObjs = new IWbemClassObject*[nNewSize];
  2059. if (!ppNewObjs)
  2060. throw CX_MemoryException();
  2061. pNewTargets = new WBEM_REM_TARGETS[nNewSize];
  2062. if (!pNewTargets)
  2063. {
  2064. delete [] ppNewObjs;
  2065. throw CX_MemoryException();
  2066. }
  2067. // Copy the data from the old pointers to the new pointers.
  2068. memcpy(ppNewObjs, m_ppObjs, m_nItems * sizeof(ppNewObjs[0]));
  2069. memcpy(pNewTargets, m_pTargets, m_nItems * sizeof(pNewTargets[0]));
  2070. // Get rid of the old pointers.
  2071. delete [] m_ppObjs;
  2072. delete [] m_pTargets;
  2073. // Set our member pointers with the new pointers.
  2074. m_ppObjs = ppNewObjs;
  2075. m_pTargets = pNewTargets;
  2076. m_dwSize = nNewSize;
  2077. }
  2078. return TRUE;
  2079. }
  2080. BOOL CEventBatch::AddEvent(IWbemClassObject *pObj, CSortedArray *pTrues)
  2081. {
  2082. BOOL bRet = FALSE;
  2083. if (EnsureAdditionalSize(1))
  2084. {
  2085. if (SUCCEEDED(pObj->Clone(&m_ppObjs[m_nItems])))
  2086. {
  2087. if(!TempSetTargets(m_pTargets + m_nItems, pTrues))
  2088. return FALSE;
  2089. m_nItems++;
  2090. bRet = TRUE;
  2091. }
  2092. }
  2093. return bRet;
  2094. }
  2095. void CEventBatch::RemoveAll()
  2096. {
  2097. for (DWORD i = 0; i < m_nItems; i++)
  2098. {
  2099. m_ppObjs[i]->Release();
  2100. TempClearTargets(m_pTargets + i);
  2101. }
  2102. m_nItems = 0;
  2103. }