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

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