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.

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