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.

681 lines
20 KiB

  1. //=============================================================================
  2. //
  3. // Copyright (c) 1996-1999, Microsoft Corporation, All rights reserved
  4. //
  5. // PERMFILT.CPP
  6. //
  7. // This file implements the classes for standard event filters.
  8. //
  9. // History:
  10. //
  11. // 11/27/96 a-levn Compiles.
  12. //
  13. //=============================================================================
  14. #include "precomp.h"
  15. #include <sddl.h>
  16. #include <stdio.h>
  17. #include "pragmas.h"
  18. #include "permfilt.h"
  19. #include "ess.h"
  20. #include <genutils.h>
  21. long CPermanentFilter::mstatic_lNameHandle = 0;
  22. long CPermanentFilter::mstatic_lLanguageHandle = 0;
  23. long CPermanentFilter::mstatic_lQueryHandle = 0;
  24. long CPermanentFilter::mstatic_lEventNamespaceHandle = 0;
  25. long CPermanentFilter::mstatic_lEventAccessHandle = 0;
  26. long CPermanentFilter::mstatic_lGuardNamespaceHandle = 0;
  27. long CPermanentFilter::mstatic_lGuardHandle = 0;
  28. long CPermanentFilter::mstatic_lSidHandle = 0;
  29. bool CPermanentFilter::mstatic_bHandlesInitialized = false;
  30. //static
  31. HRESULT CPermanentFilter::InitializeHandles( _IWmiObject* pObject )
  32. {
  33. if(mstatic_bHandlesInitialized)
  34. return S_FALSE;
  35. CIMTYPE ct;
  36. pObject->GetPropertyHandle(FILTER_KEY_PROPNAME, &ct,
  37. &mstatic_lNameHandle);
  38. pObject->GetPropertyHandle(FILTER_LANGUAGE_PROPNAME, &ct,
  39. &mstatic_lLanguageHandle);
  40. pObject->GetPropertyHandle(FILTER_QUERY_PROPNAME, &ct,
  41. &mstatic_lQueryHandle);
  42. pObject->GetPropertyHandle(FILTER_EVENTNAMESPACE_PROPNAME, &ct,
  43. &mstatic_lEventNamespaceHandle);
  44. pObject->GetPropertyHandleEx(FILTER_EVENTACCESS_PROPNAME, 0, &ct,
  45. &mstatic_lEventAccessHandle );
  46. pObject->GetPropertyHandle(FILTER_GUARDNAMESPACE_PROPNAME, &ct,
  47. &mstatic_lGuardNamespaceHandle);
  48. pObject->GetPropertyHandle(FILTER_GUARD_PROPNAME, &ct,
  49. &mstatic_lGuardHandle);
  50. pObject->GetPropertyHandleEx(OWNER_SID_PROPNAME, 0, &ct,
  51. &mstatic_lSidHandle);
  52. mstatic_bHandlesInitialized = true;
  53. return S_OK;
  54. }
  55. //******************************************************************************
  56. // public
  57. //
  58. // See stdtrig.h for documentation
  59. //
  60. //******************************************************************************
  61. CPermanentFilter::CPermanentFilter(CEssNamespace* pNamespace)
  62. : CGenericFilter(pNamespace), m_pEventAccessRelativeSD(NULL)
  63. {
  64. }
  65. CPermanentFilter::~CPermanentFilter()
  66. {
  67. if ( m_pEventAccessRelativeSD != NULL )
  68. {
  69. LocalFree( m_pEventAccessRelativeSD );
  70. }
  71. }
  72. HRESULT CPermanentFilter::Initialize( IWbemClassObject* pObj )
  73. {
  74. HRESULT hres;
  75. CWbemPtr<_IWmiObject> pFilterObj;
  76. hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pFilterObj );
  77. if ( FAILED(hres) )
  78. {
  79. return hres;
  80. }
  81. InitializeHandles( pFilterObj );
  82. // Check class
  83. // ===========
  84. if(pFilterObj->InheritsFrom(L"__EventFilter") != S_OK)
  85. return WBEM_E_INVALID_OBJECT;
  86. // Determine the query language
  87. // ============================
  88. ULONG ulFlags;
  89. CCompressedString* pcsLanguage;
  90. hres = pFilterObj->GetPropAddrByHandle( mstatic_lLanguageHandle,
  91. WMIOBJECT_FLAG_ENCODING_V1,
  92. &ulFlags,
  93. (void**)&pcsLanguage );
  94. if( hres != S_OK || pcsLanguage == NULL)
  95. {
  96. ERRORTRACE((LOG_ESS, "Event filter with invalid query language is "
  97. "rejected\n"));
  98. return WBEM_E_INVALID_OBJECT;
  99. }
  100. if( pcsLanguage->CompareNoCase("WQL") != 0 )
  101. {
  102. ERRORTRACE((LOG_ESS, "Event filter with invalid query language '%S' is "
  103. "rejected\n", pcsLanguage->CreateWStringCopy()));
  104. return WBEM_E_INVALID_QUERY_TYPE;
  105. }
  106. // Get the query
  107. // =============
  108. CCompressedString* pcsQuery;
  109. hres = pFilterObj->GetPropAddrByHandle( mstatic_lQueryHandle,
  110. WMIOBJECT_FLAG_ENCODING_V1,
  111. &ulFlags,
  112. (void**)&pcsQuery );
  113. if( hres != S_OK )
  114. {
  115. return WBEM_E_INVALID_OBJECT;
  116. }
  117. LPWSTR wszQuery = pcsQuery->CreateWStringCopy().UnbindPtr();
  118. if(wszQuery == NULL)
  119. return WBEM_E_OUT_OF_MEMORY;
  120. CVectorDeleteMe<WCHAR> vdm1(wszQuery);
  121. // Store it temporarily (until Park is called)
  122. // ===========================================
  123. // Figure out how much space we need
  124. // =================================
  125. int nSpace = pcsQuery->GetLength();
  126. // Allocate this string on the temporary heap
  127. // ==========================================
  128. m_pcsQuery = (CCompressedString*)CTemporaryHeap::Alloc(nSpace);
  129. if(m_pcsQuery == NULL)
  130. return WBEM_E_OUT_OF_MEMORY;
  131. // Copy the contents
  132. // =================
  133. memcpy((void*)m_pcsQuery, pcsQuery, nSpace);
  134. //
  135. // Get the event namespace
  136. //
  137. if(mstatic_lEventNamespaceHandle) // to protect against old repositories
  138. {
  139. CCompressedString* pcsEventNamespace;
  140. hres = pFilterObj->GetPropAddrByHandle( mstatic_lEventNamespaceHandle,
  141. WMIOBJECT_FLAG_ENCODING_V1,
  142. &ulFlags,
  143. (void**)&pcsEventNamespace );
  144. if( FAILED(hres) )
  145. {
  146. return hres;
  147. }
  148. else if ( hres == S_OK ) // o.k if event namespace is null.
  149. {
  150. if( !(m_isEventNamespace = pcsEventNamespace))
  151. {
  152. return WBEM_E_OUT_OF_MEMORY;
  153. }
  154. }
  155. }
  156. CCompressedString* pcsGuard = NULL;
  157. if(mstatic_lGuardHandle) // to protect against old repositories
  158. {
  159. hres = pFilterObj->GetPropAddrByHandle( mstatic_lGuardHandle,
  160. WMIOBJECT_FLAG_ENCODING_V1,
  161. &ulFlags,
  162. (void**)&pcsGuard );
  163. if( FAILED(hres) )
  164. return hres;
  165. }
  166. if(pcsGuard)
  167. {
  168. CCompressedString* pcsGuardNamespace = NULL;
  169. if(mstatic_lGuardNamespaceHandle) // to protect against old repositories
  170. {
  171. hres = pFilterObj->GetPropAddrByHandle(
  172. mstatic_lGuardNamespaceHandle,
  173. WMIOBJECT_FLAG_ENCODING_V1,
  174. &ulFlags,
  175. (void**)&pcsGuardNamespace );
  176. if( FAILED(hres) )
  177. return hres;
  178. }
  179. //
  180. // Check query type
  181. //
  182. VARIANT vType;
  183. VariantInit(&vType);
  184. CClearMe cm1(&vType);
  185. hres = pFilterObj->Get(FILTER_GUARDLANG_PROPNAME, 0, &vType, NULL,
  186. NULL);
  187. if(FAILED(hres))
  188. {
  189. ERRORTRACE((LOG_ESS, "Condition without a query type? Not valid\n"));
  190. return hres;
  191. }
  192. if(V_VT(&vType) != VT_BSTR)
  193. {
  194. ERRORTRACE((LOG_ESS, "Condition without a query type? Not "
  195. "valid\n"));
  196. return WBEM_E_INVALID_OBJECT;
  197. }
  198. if(wbem_wcsicmp(V_BSTR(&vType), L"WQL"))
  199. {
  200. ERRORTRACE((LOG_ESS, "Condition with invalid query type %S is "
  201. "rejected\n", V_BSTR(&vType)));
  202. return hres;
  203. }
  204. if(pcsGuardNamespace)
  205. hres = SetGuardQuery(pcsGuard->CreateWStringCopy(),
  206. pcsGuardNamespace->CreateWStringCopy());
  207. else
  208. hres = SetGuardQuery(pcsGuard->CreateWStringCopy(), NULL);
  209. if( FAILED(hres) )
  210. return hres;
  211. }
  212. //
  213. // Record the name of this filter
  214. //
  215. CCompressedString* pcsKey;
  216. hres = pFilterObj->GetPropAddrByHandle( mstatic_lNameHandle,
  217. WMIOBJECT_FLAG_ENCODING_V1,
  218. &ulFlags,
  219. (void**)&pcsKey );
  220. if( hres != S_OK )
  221. {
  222. return WBEM_E_INVALID_OBJECT;
  223. }
  224. if(!(m_isKey = pcsKey))
  225. return WBEM_E_OUT_OF_MEMORY;
  226. // Get the SID
  227. // ===========
  228. PSID pSid;
  229. ULONG ulNumElements;
  230. hres = pFilterObj->GetArrayPropAddrByHandle( mstatic_lSidHandle,
  231. 0,
  232. &ulNumElements,
  233. &pSid );
  234. if ( hres != S_OK )
  235. {
  236. return WBEM_E_INVALID_OBJECT;
  237. }
  238. m_pOwnerSid = new BYTE[ulNumElements];
  239. if ( m_pOwnerSid == NULL )
  240. {
  241. return WBEM_E_OUT_OF_MEMORY;
  242. }
  243. memcpy( m_pOwnerSid, pSid, ulNumElements );
  244. //
  245. // Get the event access SD
  246. //
  247. if( mstatic_lEventAccessHandle ) // to protect against old repositories
  248. {
  249. CCompressedString* pcsEventAccess;
  250. hres = pFilterObj->GetPropAddrByHandle( mstatic_lEventAccessHandle,
  251. WMIOBJECT_FLAG_ENCODING_V1,
  252. &ulFlags,
  253. (void**)&pcsEventAccess );
  254. if( FAILED(hres) )
  255. {
  256. return hres;
  257. }
  258. else if ( hres == S_OK ) // o.k if event access is null.
  259. {
  260. WString wsEventAccess;
  261. try
  262. {
  263. wsEventAccess = pcsEventAccess->CreateWStringCopy();
  264. }
  265. catch( CX_MemoryException )
  266. {
  267. return WBEM_E_OUT_OF_MEMORY;
  268. }
  269. ULONG cEventAccessRelativeSD;
  270. if ( !ConvertStringSecurityDescriptorToSecurityDescriptorW(
  271. wsEventAccess,
  272. SDDL_REVISION_1,
  273. &m_pEventAccessRelativeSD,
  274. &cEventAccessRelativeSD ) )
  275. {
  276. WString wsKey = m_isKey;
  277. try { wsKey = m_isKey; } catch( CX_MemoryException ) {}
  278. ERRORTRACE((LOG_ESS, "Filter '%S' contained invalid SDDL "
  279. "string for event access SD.\n", wsKey ));
  280. return HRESULT_FROM_WIN32( GetLastError() );
  281. }
  282. //
  283. // convert the self-relative SD to an absolute SD so we can
  284. // set the owner and group fields ( required by AccessCheck )
  285. //
  286. if ( !InitializeSecurityDescriptor( &m_EventAccessAbsoluteSD,
  287. SECURITY_DESCRIPTOR_REVISION ))
  288. {
  289. return HRESULT_FROM_WIN32( GetLastError() );
  290. }
  291. PACL pAcl;
  292. BOOL bAclPresent, bAclDefaulted;
  293. if ( !GetSecurityDescriptorDacl( m_pEventAccessRelativeSD,
  294. &bAclPresent,
  295. &pAcl,
  296. &bAclDefaulted ) )
  297. {
  298. return HRESULT_FROM_WIN32( GetLastError() );
  299. }
  300. if ( !SetSecurityDescriptorDacl( &m_EventAccessAbsoluteSD,
  301. bAclPresent,
  302. pAcl,
  303. bAclDefaulted ) )
  304. {
  305. return HRESULT_FROM_WIN32( GetLastError() );
  306. }
  307. if ( !GetSecurityDescriptorSacl( m_pEventAccessRelativeSD,
  308. &bAclPresent,
  309. &pAcl,
  310. &bAclDefaulted ) )
  311. {
  312. return HRESULT_FROM_WIN32( GetLastError() );
  313. }
  314. if ( !SetSecurityDescriptorSacl( &m_EventAccessAbsoluteSD,
  315. bAclPresent,
  316. pAcl,
  317. bAclDefaulted ) )
  318. {
  319. return HRESULT_FROM_WIN32( GetLastError() );
  320. }
  321. //
  322. // always need to set the owner and group sids. We do this for
  323. // two reasons (1) we want to override the user putting in anything
  324. // they want for these fields, and (2) we want to ensure that
  325. // these fields are set because AccessCheck() requires it.
  326. //
  327. if ( !SetSecurityDescriptorOwner( &m_EventAccessAbsoluteSD,
  328. m_pOwnerSid,
  329. TRUE ) )
  330. {
  331. return HRESULT_FROM_WIN32( GetLastError() );
  332. }
  333. if ( !SetSecurityDescriptorGroup( &m_EventAccessAbsoluteSD,
  334. m_pOwnerSid,
  335. TRUE ) )
  336. {
  337. return HRESULT_FROM_WIN32( GetLastError() );
  338. }
  339. }
  340. }
  341. // Initialize the generic filter accordingly
  342. // =========================================
  343. hres = CGenericFilter::Create(L"WQL", wszQuery);
  344. if(FAILED(hres))
  345. return hres;
  346. return WBEM_S_NO_ERROR;
  347. }
  348. const PSECURITY_DESCRIPTOR CPermanentFilter::GetEventAccessSD()
  349. {
  350. if ( m_pEventAccessRelativeSD != NULL )
  351. {
  352. return &m_EventAccessAbsoluteSD;
  353. }
  354. return NULL;
  355. }
  356. HRESULT CPermanentFilter::GetCoveringQuery(DELETE_ME LPWSTR& wszQueryLanguage,
  357. DELETE_ME LPWSTR& wszQuery, BOOL& bExact,
  358. QL_LEVEL_1_RPN_EXPRESSION** ppExp)
  359. {
  360. HRESULT hres;
  361. if(m_pcsQuery == NULL)
  362. {
  363. hres = RetrieveQuery(wszQuery);
  364. }
  365. else
  366. {
  367. wszQuery = m_pcsQuery->CreateWStringCopy().UnbindPtr();
  368. if(wszQuery == NULL)
  369. hres = WBEM_E_OUT_OF_MEMORY;
  370. else
  371. hres = WBEM_S_NO_ERROR;
  372. }
  373. if(FAILED(hres))
  374. return hres;
  375. if(ppExp)
  376. {
  377. // Parse it
  378. // ========
  379. CTextLexSource src(wszQuery);
  380. QL1_Parser parser(&src);
  381. int nRes = parser.Parse(ppExp);
  382. if (nRes)
  383. {
  384. ERRORTRACE((LOG_ESS, "Unable to construct event filter with "
  385. "unparsable "
  386. "query '%S'. The filter is not active\n", wszQuery));
  387. return WBEM_E_UNPARSABLE_QUERY;
  388. }
  389. }
  390. bExact = TRUE;
  391. wszQueryLanguage = CloneWstr(L"WQL");
  392. return WBEM_S_NO_ERROR;
  393. }
  394. HRESULT CPermanentFilter::RetrieveQuery(DELETE_ME LPWSTR& wszQuery)
  395. {
  396. HRESULT hres;
  397. //
  398. // Construct db path
  399. //
  400. BSTR strPath = SysAllocStringLen(NULL, m_isKey.GetLength() + 100);
  401. if(strPath == NULL)
  402. return WBEM_E_OUT_OF_MEMORY;
  403. CSysFreeMe sfm1(strPath);
  404. swprintf(strPath, L"__EventFilter=\"%s\"", (LPCWSTR)(WString)m_isKey);
  405. //
  406. // Retrieve the object
  407. //
  408. _IWmiObject* pFilterObj;
  409. hres = m_pNamespace->GetDbInstance(strPath, &pFilterObj);
  410. if(FAILED(hres))
  411. return WBEM_E_INVALID_OBJECT;
  412. CReleaseMe rm(pFilterObj);
  413. InitializeHandles(pFilterObj);
  414. // Extract its properties
  415. // ======================
  416. ULONG ulFlags;
  417. CCompressedString* pcsQuery;
  418. hres = pFilterObj->GetPropAddrByHandle( mstatic_lQueryHandle,
  419. WMIOBJECT_FLAG_ENCODING_V1,
  420. &ulFlags,
  421. (void**)&pcsQuery );
  422. if( hres != S_OK )
  423. {
  424. return WBEM_E_INVALID_OBJECT;
  425. }
  426. wszQuery = pcsQuery->CreateWStringCopy().UnbindPtr();
  427. if(wszQuery == NULL)
  428. return WBEM_E_OUT_OF_MEMORY;
  429. return WBEM_S_NO_ERROR;
  430. }
  431. HRESULT CPermanentFilter::GetEventNamespace(
  432. DELETE_ME LPWSTR* pwszNamespace)
  433. {
  434. if(m_isEventNamespace.IsEmpty())
  435. *pwszNamespace = NULL;
  436. else
  437. {
  438. *pwszNamespace = m_isEventNamespace.CreateLPWSTRCopy();
  439. if(*pwszNamespace == NULL)
  440. return WBEM_E_OUT_OF_MEMORY;
  441. }
  442. return S_OK;
  443. }
  444. SYSFREE_ME BSTR
  445. CPermanentFilter::ComputeKeyFromObj( IWbemClassObject* pObj )
  446. {
  447. HRESULT hres;
  448. CWbemPtr<_IWmiObject> pFilterObj;
  449. hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pFilterObj );
  450. if ( FAILED(hres) )
  451. {
  452. return NULL;
  453. }
  454. InitializeHandles(pFilterObj);
  455. ULONG ulFlags;
  456. CCompressedString* pcsKey;
  457. hres = pFilterObj->GetPropAddrByHandle( mstatic_lNameHandle,
  458. WMIOBJECT_FLAG_ENCODING_V1,
  459. &ulFlags,
  460. (void**)&pcsKey );
  461. if( hres != S_OK )
  462. {
  463. return NULL;
  464. }
  465. return pcsKey->CreateBSTRCopy();
  466. }
  467. SYSFREE_ME BSTR CPermanentFilter::ComputeKeyFromPath(
  468. LPCWSTR wszPath)
  469. {
  470. // Find the first quote
  471. // ====================
  472. WCHAR* pwcFirstQuote = wcschr(wszPath, L'"');
  473. if(pwcFirstQuote == NULL)
  474. return NULL;
  475. // Find the next quote
  476. // ===================
  477. WCHAR* pwcLastQuote = wcschr(pwcFirstQuote+1, L'"');
  478. if(pwcLastQuote == NULL)
  479. return NULL;
  480. return SysAllocStringLen(pwcFirstQuote+1, pwcLastQuote - pwcFirstQuote - 1);
  481. }
  482. HRESULT CPermanentFilter::CheckValidity( IWbemClassObject* pObj )
  483. {
  484. HRESULT hres;
  485. CWbemPtr<_IWmiObject> pFilterObj;
  486. hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pFilterObj );
  487. if ( FAILED(hres) )
  488. {
  489. return hres;
  490. }
  491. InitializeHandles(pFilterObj);
  492. //
  493. // Check class
  494. //
  495. if(pFilterObj->InheritsFrom(L"__EventFilter") != S_OK)
  496. return WBEM_E_INVALID_OBJECT;
  497. //
  498. // Check the query language
  499. //
  500. ULONG ulFlags;
  501. CCompressedString* pcsLanguage;
  502. hres = pFilterObj->GetPropAddrByHandle( mstatic_lLanguageHandle,
  503. WMIOBJECT_FLAG_ENCODING_V1,
  504. &ulFlags,
  505. (void**)&pcsLanguage );
  506. if( hres != S_OK )
  507. {
  508. return WBEM_E_INVALID_QUERY_TYPE;
  509. }
  510. if(pcsLanguage->CompareNoCase("WQL") != 0)
  511. return WBEM_E_INVALID_QUERY_TYPE;
  512. //
  513. // Get the query
  514. //
  515. CCompressedString* pcsQuery;
  516. hres = pFilterObj->GetPropAddrByHandle( mstatic_lQueryHandle,
  517. WMIOBJECT_FLAG_ENCODING_V1,
  518. &ulFlags,
  519. (void**)&pcsQuery );
  520. if( hres != S_OK )
  521. {
  522. return WBEM_E_INVALID_OBJECT;
  523. }
  524. LPWSTR wszQuery = pcsQuery->CreateWStringCopy().UnbindPtr();
  525. if(wszQuery == NULL)
  526. return WBEM_E_OUT_OF_MEMORY;
  527. CVectorDeleteMe<WCHAR> vdm(wszQuery);
  528. //
  529. // Make sure it is parsable
  530. //
  531. CTextLexSource src(wszQuery);
  532. QL1_Parser parser(&src);
  533. QL_LEVEL_1_RPN_EXPRESSION* pExp = NULL;
  534. int nRes = parser.Parse(&pExp);
  535. if (nRes)
  536. return WBEM_E_UNPARSABLE_QUERY;
  537. delete pExp;
  538. return WBEM_S_NO_ERROR;
  539. }
  540. HRESULT CPermanentFilter::ObtainToken(IWbemToken** ppToken)
  541. {
  542. //
  543. // Get us a token from the token cache
  544. //
  545. return m_pNamespace->GetToken(GetOwner(), ppToken);
  546. }
  547. void CPermanentFilter::Park()
  548. {
  549. if(m_pcsQuery)
  550. CTemporaryHeap::Free(m_pcsQuery, m_pcsQuery->GetLength());
  551. m_pcsQuery = NULL;
  552. }