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.

1066 lines
32 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. DUMBNODE.CPP
  5. Abstract:
  6. WBEM Dumb Node
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <stdio.h>
  11. #pragma warning(disable:4786)
  12. #include <wbemcomn.h>
  13. #include <genutils.h>
  14. #include "dumbnode.h"
  15. #include "CWbemTime.h"
  16. #include "datetimeparser.h"
  17. #define DUMBNODE_FALSE_BRANCH_INDEX 0
  18. #define DUMBNODE_TRUE_BRANCH_INDEX 1
  19. CDumbNode::CDumbNode(QL_LEVEL_1_TOKEN& Token)
  20. : m_Token(Token)
  21. {
  22. //
  23. // Add the branches for TRUE and FALSE
  24. //
  25. if(m_apBranches.Add(CValueNode::GetStandardFalse()) < 0)
  26. throw CX_MemoryException();
  27. CEvalNode* pNode = CValueNode::GetStandardTrue();
  28. if(pNode == NULL)
  29. throw CX_MemoryException();
  30. if(m_apBranches.Add( pNode ) < 0)
  31. {
  32. delete pNode;
  33. throw CX_MemoryException();
  34. }
  35. }
  36. HRESULT CDumbNode::Validate(IWbemClassObject* pClass)
  37. {
  38. HRESULT hres;
  39. //
  40. // Check if the property is even in the class
  41. //
  42. CIMTYPE ct;
  43. hres = pClass->Get(m_Token.PropertyName.GetStringAt(0), 0, NULL, &ct, NULL);
  44. if(FAILED(hres))
  45. return WBEM_E_INVALID_PROPERTY;
  46. if(m_Token.m_bPropComp)
  47. {
  48. hres = pClass->Get(m_Token.PropertyName2.GetStringAt(0), 0, NULL, &ct,
  49. NULL);
  50. if(FAILED(hres))
  51. return WBEM_E_INVALID_PROPERTY;
  52. }
  53. if(ct == CIM_REFERENCE)
  54. {
  55. //
  56. // Make sure that the operator is = or <>
  57. //
  58. if(m_Token.nOperator != QL_LEVEL_1_TOKEN::OP_EQUAL &&
  59. m_Token.nOperator != QL_LEVEL_1_TOKEN::OP_NOT_EQUAL)
  60. {
  61. return WBEM_E_INVALID_OPERATOR;
  62. }
  63. //
  64. // Make sure the path is parsable
  65. //
  66. if(!m_Token.m_bPropComp)
  67. {
  68. if(V_VT(&m_Token.vConstValue) != VT_BSTR)
  69. {
  70. if(V_VT(&m_Token.vConstValue) != VT_NULL)
  71. return WBEM_E_TYPE_MISMATCH;
  72. }
  73. else
  74. {
  75. LPWSTR wszNormal = NormalizePath(V_BSTR(&m_Token.vConstValue));
  76. if(wszNormal == NULL)
  77. return WBEM_E_INVALID_OBJECT_PATH;
  78. else
  79. delete [] wszNormal;
  80. }
  81. }
  82. }
  83. else if(ct == CIM_DATETIME)
  84. {
  85. //
  86. // If comparing to a constant, make sure the constant is a date
  87. //
  88. if(!m_Token.m_bPropComp)
  89. {
  90. if(V_VT(&m_Token.vConstValue) != VT_BSTR)
  91. {
  92. if(V_VT(&m_Token.vConstValue) != VT_NULL)
  93. return WBEM_E_TYPE_MISMATCH;
  94. }
  95. else
  96. {
  97. BSTR strConstVal = V_BSTR(&m_Token.vConstValue);
  98. #ifdef UNICODE
  99. CDateTimeParser dtConst(strConstVal);
  100. #else
  101. size_t cchBuffer = wcslen(strConstVal) * 4 + 1;
  102. char* szBuffer = new char[cchBuffer];
  103. if(szBuffer == NULL)
  104. return WBEM_E_OUT_OF_MEMORY;
  105. StringCchPrintf(szBuffer, cchBuffer, "%S", strConstVal);
  106. CDateTimeParser dtConst(szBuffer);
  107. delete [] szBuffer;
  108. #endif
  109. if(!dtConst.IsValidDateTime())
  110. return WBEM_E_VALUE_OUT_OF_RANGE;
  111. }
  112. }
  113. }
  114. return WBEM_S_NO_ERROR;
  115. }
  116. CDumbNode::CDumbNode(const CDumbNode& Other, BOOL bChildren)
  117. : CBranchingNode(Other, bChildren), m_Token(Other.m_Token)
  118. {
  119. }
  120. /* virtual */ long CDumbNode::GetSubType()
  121. {
  122. return EVAL_NODE_TYPE_DUMB;
  123. }
  124. CDumbNode::~CDumbNode()
  125. {
  126. }
  127. int CDumbNode::ComparePrecedence(CBranchingNode* pOther)
  128. {
  129. //
  130. // Dumb nodes can only be merged if they are identical. So, there
  131. // precedence (level) is the same as theie comparison order
  132. //
  133. return SubCompare(pOther);
  134. }
  135. int CDumbNode::SubCompare(CEvalNode* pOther)
  136. {
  137. CDumbNode* pDumbOther = (CDumbNode*)pOther;
  138. //
  139. // The easiest way to compare two tokens is to compare their textual
  140. // representations. Optimizations paths for the future abound.
  141. //
  142. LPWSTR wszThisText = m_Token.GetText();
  143. if ( wszThisText == NULL )
  144. throw CX_MemoryException();
  145. CVectorDeleteMe<WCHAR> vdm1(wszThisText);
  146. LPWSTR wszOtherText = pDumbOther->m_Token.GetText();
  147. if ( wszOtherText == NULL )
  148. throw CX_MemoryException();
  149. CVectorDeleteMe<WCHAR> vdm2(wszOtherText);
  150. return wbem_wcsicmp(wszThisText, wszOtherText);
  151. }
  152. HRESULT CDumbNode::OptimizeSelf()
  153. {
  154. //
  155. // Nothing to optimize for now. Optimizations abound.
  156. //
  157. return WBEM_S_NO_ERROR;
  158. }
  159. #define INVALID 2
  160. int CDumbNode::EvaluateToken(
  161. IWbemPropertySource *pTestObj,
  162. QL_LEVEL_1_TOKEN& Tok
  163. )
  164. {
  165. VARIANT PropVal, CompVal;
  166. VariantInit(&PropVal);
  167. VariantInit(&CompVal);
  168. CClearMe clv(&PropVal);
  169. CClearMe clv2(&CompVal);
  170. WBEM_WSTR wszCimType, wszCimType2;
  171. HRESULT hRes;
  172. // Special-case 'this'
  173. // ===================
  174. if(Tok.PropertyName.GetNumElements() == 1 &&
  175. !wbem_wcsicmp(Tok.PropertyName.GetStringAt(0), L"__THIS"))
  176. {
  177. wszCimType = WbemStringCopy(L"object");
  178. V_VT(&PropVal) = VT_UNKNOWN;
  179. hRes = pTestObj->QueryInterface(IID_IWbemClassObject,
  180. (void**)&V_UNKNOWN(&PropVal));
  181. }
  182. else
  183. {
  184. hRes = pTestObj->GetPropertyValue(&Tok.PropertyName, 0,
  185. &wszCimType, &PropVal);
  186. }
  187. if (FAILED(hRes))
  188. return FALSE;
  189. CMemFreeMe wsf(wszCimType);
  190. // Handle a property-to-property comparison,
  191. if (Tok.m_bPropComp != FALSE)
  192. {
  193. hRes = pTestObj->GetPropertyValue(&Tok.PropertyName2, 0,
  194. &wszCimType2, &CompVal);
  195. if (FAILED(hRes))
  196. return FALSE;
  197. }
  198. else
  199. {
  200. if(FAILED(VariantCopy(&CompVal, &Tok.vConstValue)))
  201. return INVALID;
  202. }
  203. // Handle NULLs
  204. // ============
  205. if(V_VT(&PropVal) == VT_NULL)
  206. {
  207. if(V_VT(&CompVal) == VT_NULL)
  208. {
  209. if(Tok.nOperator == QL_LEVEL_1_TOKEN::OP_EQUAL ||
  210. Tok.nOperator == QL_LEVEL_1_TOKEN::OP_LIKE )
  211. return TRUE;
  212. else if(Tok.nOperator == QL_LEVEL_1_TOKEN::OP_NOT_EQUAL ||
  213. Tok.nOperator == QL_LEVEL_1_TOKEN::OP_UNLIKE )
  214. return FALSE;
  215. else
  216. return INVALID;
  217. }
  218. else
  219. {
  220. if(Tok.nOperator == QL_LEVEL_1_TOKEN::OP_EQUAL ||
  221. Tok.nOperator == QL_LEVEL_1_TOKEN::OP_LIKE )
  222. return FALSE;
  223. else if(Tok.nOperator == QL_LEVEL_1_TOKEN::OP_NOT_EQUAL ||
  224. Tok.nOperator == QL_LEVEL_1_TOKEN::OP_UNLIKE )
  225. return TRUE;
  226. else
  227. return INVALID;
  228. }
  229. }
  230. else if(V_VT(&CompVal) == VT_NULL)
  231. {
  232. if(Tok.nOperator == QL_LEVEL_1_TOKEN::OP_EQUAL)
  233. return FALSE;
  234. else if(Tok.nOperator == QL_LEVEL_1_TOKEN::OP_NOT_EQUAL)
  235. return TRUE;
  236. else
  237. return INVALID;
  238. }
  239. // Handle references
  240. // =================
  241. if(wszCimType &&
  242. wbem_wcsnicmp(wszCimType, L"ref", 3) == 0 &&
  243. (wszCimType[3] == 0 || wszCimType[3] == L':'))
  244. {
  245. // This is a reference. The only operators allowed are = and !=
  246. // ============================================================
  247. if(V_VT(&PropVal) != VT_BSTR || V_VT(&CompVal) != VT_BSTR)
  248. return INVALID;
  249. LPWSTR va = CDumbNode::NormalizePath(V_BSTR(&PropVal));
  250. LPWSTR vb = CDumbNode::NormalizePath(V_BSTR(&CompVal));
  251. if(va == NULL || vb == NULL)
  252. {
  253. if(va)
  254. delete [] va;
  255. if(vb)
  256. delete [] vb;
  257. ERRORTRACE((LOG_ESS, "Invalid path %S or %S specified in an "
  258. "association\n", V_BSTR(&PropVal), V_BSTR(&CompVal)));
  259. return INVALID;
  260. }
  261. int nRet;
  262. switch (Tok.nOperator)
  263. {
  264. case QL_LEVEL_1_TOKEN::OP_EQUAL:
  265. nRet = (wbem_wcsicmp(va,vb) == 0);
  266. break;
  267. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  268. nRet = (wbem_wcsicmp(va, vb) != 0);
  269. break;
  270. default:
  271. nRet = INVALID;
  272. break;
  273. }
  274. delete [] va;
  275. delete [] vb;
  276. return nRet;
  277. }
  278. // Check if ISA is used
  279. // ====================
  280. if(Tok.nOperator == QL1_OPERATOR_ISA ||
  281. Tok.nOperator == QL1_OPERATOR_ISNOTA ||
  282. Tok.nOperator == QL1_OPERATOR_INV_ISA ||
  283. Tok.nOperator == QL1_OPERATOR_INV_ISNOTA)
  284. {
  285. // Account for inversion
  286. // =====================
  287. VARIANT* pv1;
  288. VARIANT* pv2;
  289. int bNeedDerived;
  290. if(Tok.nOperator == QL1_OPERATOR_ISA ||
  291. Tok.nOperator == QL1_OPERATOR_ISNOTA)
  292. {
  293. pv2 = &CompVal;
  294. pv1 = &PropVal;
  295. bNeedDerived = (Tok.nOperator == QL1_OPERATOR_ISA);
  296. }
  297. else
  298. {
  299. pv1 = &CompVal;
  300. pv2 = &PropVal;
  301. bNeedDerived = (Tok.nOperator == QL1_OPERATOR_INV_ISA);
  302. }
  303. // The second argument has to be a string
  304. // ======================================
  305. if(V_VT(pv2) != VT_BSTR)
  306. {
  307. return INVALID;
  308. }
  309. BSTR strParentClass = V_BSTR(pv2);
  310. // The first argument has to be an object or a string
  311. // ==================================================
  312. BOOL bDerived;
  313. if(V_VT(pv1) == VT_EMBEDDED_OBJECT)
  314. {
  315. IWbemClassObject* pObj = (IWbemClassObject*)V_EMBEDDED_OBJECT(pv1);
  316. bDerived = (pObj->InheritsFrom(strParentClass) == WBEM_S_NO_ERROR);
  317. }
  318. else if(V_VT(pv1) == VT_BSTR)
  319. {
  320. // TBD
  321. // ===
  322. return INVALID;
  323. }
  324. else
  325. {
  326. return INVALID;
  327. }
  328. // Now that we have bDerived, see if it matches the requirement
  329. // ============================================================
  330. if(bDerived == bNeedDerived)
  331. return TRUE;
  332. else
  333. return FALSE;
  334. }
  335. else if ( Tok.nOperator == QL1_OPERATOR_LIKE ||
  336. Tok.nOperator == QL1_OPERATOR_UNLIKE )
  337. {
  338. if ( Tok.m_bPropComp != FALSE )
  339. {
  340. return INVALID;
  341. }
  342. if ( FAILED(VariantChangeType( &PropVal, &PropVal, 0, VT_BSTR )) ||
  343. V_VT(&CompVal) != VT_BSTR )
  344. {
  345. return INVALID;
  346. }
  347. try
  348. {
  349. CLike Like( V_BSTR(&CompVal) );
  350. if ( Like.Match( V_BSTR(&PropVal) ) )
  351. {
  352. return Tok.nOperator == QL1_OPERATOR_LIKE ? TRUE : FALSE;
  353. }
  354. else
  355. {
  356. return Tok.nOperator == QL1_OPERATOR_UNLIKE ? TRUE : FALSE;
  357. }
  358. }
  359. catch( CX_MemoryException )
  360. {
  361. return INVALID;
  362. }
  363. }
  364. // Perform UINT32 workaround
  365. // =========================
  366. if(wszCimType && !wbem_wcsicmp(wszCimType, L"uint32") &&
  367. V_VT(&PropVal) == VT_I4)
  368. {
  369. DWORD dwVal = (DWORD)V_I4(&PropVal);
  370. WCHAR wszVal[20];
  371. StringCchPrintfW(wszVal,20,L"%lu", dwVal);
  372. V_VT(&PropVal) = VT_BSTR;
  373. V_BSTR(&PropVal) = SysAllocString(wszVal);
  374. }
  375. if(wszCimType &&
  376. (!wbem_wcsicmp(wszCimType, L"sint64") ||
  377. !wbem_wcsicmp(wszCimType, L"uint64") ||
  378. !wbem_wcsicmp(wszCimType, L"uint32")) &&
  379. V_VT(&CompVal) != VT_NULL && V_VT(&PropVal) != VT_NULL)
  380. {
  381. BOOL bUnsigned = (wbem_wcsicmp(wszCimType, L"uint64") == 0);
  382. // We have a 64-bit comparison where both sides are present.
  383. // =========================================================
  384. hRes = VariantChangeType(&CompVal, &CompVal, 0,
  385. VT_BSTR);
  386. if(FAILED(hRes))
  387. {
  388. return INVALID;
  389. }
  390. if(bUnsigned)
  391. {
  392. unsigned __int64 ui64Prop, ui64Const;
  393. if(!ReadUI64(V_BSTR(&PropVal), ui64Prop))
  394. return INVALID;
  395. if(!ReadUI64(V_BSTR(&CompVal), ui64Const))
  396. return INVALID;
  397. switch (Tok.nOperator)
  398. {
  399. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (ui64Prop == ui64Const);
  400. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  401. return (ui64Prop != ui64Const);
  402. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  403. return (ui64Prop >= ui64Const);
  404. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  405. return (ui64Prop <= ui64Const);
  406. case QL_LEVEL_1_TOKEN::OP_LESSTHAN:
  407. return (ui64Prop < ui64Const);
  408. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  409. return (ui64Prop > ui64Const);
  410. case QL_LEVEL_1_TOKEN::OP_LIKE: return (ui64Prop == ui64Const);
  411. }
  412. return INVALID;
  413. }
  414. else
  415. {
  416. __int64 i64Prop, i64Const;
  417. if(!ReadI64(V_BSTR(&PropVal), i64Prop))
  418. return INVALID;
  419. if(!ReadI64(V_BSTR(&CompVal), i64Const))
  420. return INVALID;
  421. switch (Tok.nOperator)
  422. {
  423. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (i64Prop == i64Const);
  424. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  425. return (i64Prop != i64Const);
  426. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  427. return (i64Prop >= i64Const);
  428. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  429. return (i64Prop <= i64Const);
  430. case QL_LEVEL_1_TOKEN::OP_LESSTHAN:
  431. return (i64Prop < i64Const);
  432. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  433. return (i64Prop > i64Const);
  434. case QL_LEVEL_1_TOKEN::OP_LIKE: return (i64Prop == i64Const);
  435. }
  436. return INVALID;
  437. }
  438. }
  439. if(wszCimType && !wbem_wcsicmp(wszCimType, L"char16") &&
  440. V_VT(&CompVal) == VT_BSTR && V_VT(&PropVal) != VT_NULL)
  441. {
  442. // Coerce strings correctly
  443. // ========================
  444. BSTR str = V_BSTR(&CompVal);
  445. if(wcslen(str) != 1)
  446. return INVALID;
  447. short va = V_I2(&PropVal);
  448. short vb = str[0];
  449. switch (Tok.nOperator)
  450. {
  451. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  452. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  453. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return (va >= vb);
  454. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return (va <= vb);
  455. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return (va < vb);
  456. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return (va > vb);
  457. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  458. }
  459. return INVALID;
  460. }
  461. if(wszCimType &&
  462. (!wbem_wcsicmp(wszCimType, L"datetime")) &&
  463. V_VT(&CompVal) == VT_BSTR && V_VT(&PropVal) == VT_BSTR)
  464. {
  465. // Parse the constant specified in the query according to the
  466. // SQL rules
  467. // ==========================================================
  468. BSTR strConstVal = V_BSTR(&CompVal);
  469. #ifdef UNICODE
  470. CDateTimeParser dtConst(strConstVal);
  471. #else
  472. size_t cchBuffer = wcslen(strConstVal) * 4 + 1;
  473. char* szBuffer = new char[cchBuffer];
  474. if(szBuffer == NULL)
  475. return WBEM_E_OUT_OF_MEMORY;
  476. StringCchPrintf(szBuffer, cchBuffer, "%S", strConstVal);
  477. CDateTimeParser dtConst(szBuffer);
  478. delete [] szBuffer;
  479. #endif
  480. if(!dtConst.IsValidDateTime())
  481. return INVALID;
  482. WCHAR wszConstValDMTF[26];
  483. dtConst.FillDMTF(wszConstValDMTF, 26);
  484. // Read both DMTF values and parse them
  485. // ====================================
  486. CWbemTime wtConst, wtProp;
  487. if(!wtConst.SetDMTF(wszConstValDMTF))
  488. return INVALID;
  489. if(!wtProp.SetDMTF(V_BSTR(&PropVal)))
  490. return INVALID;
  491. __int64 i64Const = wtConst.Get100nss();
  492. __int64 i64Prop = wtProp.Get100nss();
  493. switch (Tok.nOperator)
  494. {
  495. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (i64Prop == i64Const);
  496. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  497. return (i64Prop != i64Const);
  498. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  499. return (i64Prop >= i64Const);
  500. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  501. return (i64Prop <= i64Const);
  502. case QL_LEVEL_1_TOKEN::OP_LESSTHAN:
  503. return (i64Prop < i64Const);
  504. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  505. return (i64Prop > i64Const);
  506. case QL_LEVEL_1_TOKEN::OP_LIKE: return (i64Prop == i64Const);
  507. }
  508. }
  509. // Coerce types to match.
  510. // ======================
  511. if(V_VT(&CompVal) != VT_NULL && V_VT(&PropVal) != VT_NULL)
  512. {
  513. hRes = VariantChangeType(&CompVal, &CompVal, 0, V_VT(&PropVal));
  514. if(FAILED(hRes))
  515. {
  516. return INVALID;
  517. }
  518. }
  519. switch (V_VT(&CompVal))
  520. {
  521. case VT_NULL:
  522. return INVALID; // handled above
  523. case VT_I4:
  524. {
  525. if(V_VT(&PropVal) == VT_NULL)
  526. return INVALID;
  527. LONG va = V_I4(&PropVal);
  528. LONG vb = V_I4(&CompVal);
  529. switch (Tok.nOperator)
  530. {
  531. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  532. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  533. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return (va >= vb);
  534. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return (va <= vb);
  535. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return (va < vb);
  536. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return (va > vb);
  537. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  538. }
  539. }
  540. break;
  541. case VT_I2:
  542. {
  543. if(V_VT(&PropVal) == VT_NULL)
  544. return INVALID;
  545. short va = V_I2(&PropVal);
  546. short vb = V_I2(&CompVal);
  547. switch (Tok.nOperator)
  548. {
  549. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  550. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  551. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return (va >= vb);
  552. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return (va <= vb);
  553. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return (va < vb);
  554. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return (va > vb);
  555. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  556. }
  557. }
  558. break;
  559. case VT_UI1:
  560. {
  561. if(V_VT(&PropVal) == VT_NULL)
  562. return INVALID;
  563. BYTE va = V_I1(&PropVal);
  564. BYTE vb = V_I1(&CompVal);
  565. switch (Tok.nOperator)
  566. {
  567. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  568. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  569. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return (va >= vb);
  570. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return (va <= vb);
  571. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return (va < vb);
  572. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return (va > vb);
  573. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  574. }
  575. }
  576. break;
  577. case VT_BSTR:
  578. {
  579. if(V_VT(&PropVal) == VT_NULL)
  580. return INVALID;
  581. LPWSTR va = (LPWSTR) V_BSTR(&PropVal);
  582. LPWSTR vb = (LPWSTR) V_BSTR(&CompVal);
  583. int retCode = 0;
  584. BOOL bDidIt = TRUE;
  585. switch (Tok.nOperator)
  586. {
  587. case QL_LEVEL_1_TOKEN::OP_EQUAL:
  588. retCode = ( wbem_wcsicmp(va,vb) == 0);
  589. break;
  590. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  591. retCode = (wbem_wcsicmp(va, vb) != 0);
  592. break;
  593. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  594. retCode = (wbem_wcsicmp(va, vb) >= 0);
  595. break;
  596. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  597. retCode = (wbem_wcsicmp(va, vb) <= 0);
  598. break;
  599. case QL_LEVEL_1_TOKEN::OP_LESSTHAN:
  600. retCode = (wbem_wcsicmp(va, vb) < 0);
  601. break;
  602. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  603. retCode = (wbem_wcsicmp(va, vb) > 0);
  604. break;
  605. case QL_LEVEL_1_TOKEN::OP_LIKE:
  606. retCode = (wbem_wcsicmp(va,vb) == 0);
  607. break;
  608. default:
  609. bDidIt = FALSE;
  610. break;
  611. }
  612. VariantClear(&CompVal);
  613. if (bDidIt)
  614. {
  615. return retCode;
  616. }
  617. }
  618. break;
  619. case VT_R8:
  620. {
  621. if(V_VT(&PropVal) == VT_NULL)
  622. return INVALID;
  623. double va = V_R8(&PropVal);
  624. double vb = V_R8(&CompVal);
  625. switch (Tok.nOperator)
  626. {
  627. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  628. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  629. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return (va >= vb);
  630. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return (va <= vb);
  631. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return (va < vb);
  632. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return (va > vb);
  633. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  634. }
  635. }
  636. break;
  637. case VT_R4:
  638. {
  639. if(V_VT(&PropVal) == VT_NULL)
  640. return INVALID;
  641. float va = V_R4(&PropVal);
  642. float vb = V_R4(&CompVal);
  643. switch (Tok.nOperator)
  644. {
  645. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  646. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  647. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return (va >= vb);
  648. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return (va <= vb);
  649. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return (va < vb);
  650. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return (va > vb);
  651. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  652. }
  653. }
  654. break;
  655. case VT_BOOL:
  656. {
  657. if(V_VT(&PropVal) == VT_NULL)
  658. return INVALID;
  659. VARIANT_BOOL va = V_BOOL(&PropVal);
  660. if(va != VARIANT_FALSE) va = VARIANT_TRUE;
  661. VARIANT_BOOL vb = V_BOOL(&CompVal);
  662. if(vb != VARIANT_FALSE) vb = VARIANT_TRUE;
  663. switch (Tok.nOperator)
  664. {
  665. case QL_LEVEL_1_TOKEN::OP_EQUAL: return (va == vb);
  666. case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL: return (va != vb);
  667. case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: return INVALID;
  668. case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: return INVALID;
  669. case QL_LEVEL_1_TOKEN::OP_LESSTHAN: return INVALID;
  670. case QL_LEVEL_1_TOKEN::OP_GREATERTHAN: return INVALID;
  671. case QL_LEVEL_1_TOKEN::OP_LIKE: return (va == vb);
  672. }
  673. }
  674. break;
  675. }
  676. return FALSE;
  677. }
  678. LPWSTR CDumbNode::NormalizePath(LPCWSTR wszObjectPath)
  679. {
  680. CObjectPathParser Parser;
  681. ParsedObjectPath* pParsedPath;
  682. if(Parser.Parse((LPWSTR)wszObjectPath, &pParsedPath) !=
  683. CObjectPathParser::NoError ||
  684. !pParsedPath->IsObject())
  685. {
  686. return NULL;
  687. }
  688. if(pParsedPath->m_pClass == NULL)
  689. {
  690. return NULL;
  691. }
  692. //
  693. // Ignore the server and the namespaze
  694. //
  695. //
  696. // Check for it being a class
  697. //
  698. LPWSTR wszKey = NULL;
  699. if(!pParsedPath->IsInstance())
  700. {
  701. //
  702. // It's a class
  703. //
  704. DWORD cLen = wcslen(pParsedPath->m_pClass) +1;
  705. WCHAR* wszBuffer = new WCHAR[cLen];
  706. if(wszBuffer == NULL)
  707. return NULL;
  708. StringCchCopyW(wszBuffer, cLen, pParsedPath->m_pClass);
  709. return wszBuffer;
  710. }
  711. else
  712. {
  713. //
  714. // It's an instance
  715. //
  716. wszKey = pParsedPath->GetKeyString();
  717. if(wszKey == NULL)
  718. return NULL;
  719. CVectorDeleteMe<WCHAR> vdm(wszKey);
  720. DWORD cLen = wcslen(pParsedPath->m_pClass) + wcslen(wszKey) + 2;
  721. WCHAR* wszBuffer = new WCHAR[cLen];
  722. if(wszBuffer == NULL)
  723. return NULL;
  724. StringCchPrintfW(wszBuffer,cLen,L"%s.%s",pParsedPath->m_pClass,wszKey);
  725. return wszBuffer;
  726. }
  727. }
  728. HRESULT CDumbNode::Evaluate(CObjectInfo& ObjInfo,
  729. INTERNAL CEvalNode** ppNext)
  730. {
  731. _IWmiObject* pInst;
  732. HRESULT hres = GetContainerObject(ObjInfo, &pInst);
  733. if(FAILED(hres)) return hres;
  734. if(pInst == NULL)
  735. {
  736. *ppNext = m_pNullBranch;
  737. return WBEM_S_NO_ERROR;
  738. }
  739. //
  740. // Just evaluate the token, ala core.
  741. //
  742. IWbemPropertySource* pPropSource = NULL;
  743. hres = pInst->QueryInterface(IID_IWbemPropertySource, (void**)&pPropSource);
  744. if(FAILED(hres))
  745. return WBEM_E_CRITICAL_ERROR;
  746. CReleaseMe rm1(pPropSource);
  747. int nRes = EvaluateToken(pPropSource, m_Token);
  748. if(nRes == INVALID)
  749. *ppNext = m_pNullBranch;
  750. else if(nRes == FALSE)
  751. *ppNext = m_apBranches[DUMBNODE_FALSE_BRANCH_INDEX];
  752. else
  753. *ppNext = m_apBranches[DUMBNODE_TRUE_BRANCH_INDEX];
  754. return WBEM_S_NO_ERROR;
  755. }
  756. HRESULT CDumbNode::Compile(CContextMetaData* pNamespace,
  757. CImplicationList& Implications)
  758. {
  759. if (!m_pInfo)
  760. {
  761. try
  762. {
  763. m_pInfo = new CEmbeddingInfo;
  764. }
  765. catch(CX_MemoryException)
  766. {
  767. return WBEM_E_OUT_OF_MEMORY;
  768. }
  769. if(m_pInfo == NULL)
  770. return WBEM_E_OUT_OF_MEMORY;
  771. }
  772. HRESULT hres = CompileEmbeddingPortion(pNamespace, Implications, NULL);
  773. return hres;
  774. }
  775. HRESULT CDumbNode::CombineBranchesWith(CBranchingNode* pRawArg2, int nOp,
  776. CContextMetaData* pNamespace,
  777. CImplicationList& OrigImplications,
  778. bool bDeleteThis, bool bDeleteArg2,
  779. CEvalNode** ppRes)
  780. {
  781. HRESULT hres;
  782. //
  783. // There is only one case in which combining dumb nodes is allowed ---
  784. // when both of them are exactly the same
  785. //
  786. CDumbNode* pArg2 = (CDumbNode*)pRawArg2;
  787. if(SubCompare(pArg2) != 0)
  788. return WBEM_E_CRITICAL_ERROR;
  789. if(!bDeleteThis && bDeleteArg2)
  790. {
  791. // It is easier to combine in the other direction
  792. // ==============================================
  793. return pArg2->CombineBranchesWith(this, FlipEvalOp(nOp), pNamespace,
  794. OrigImplications, bDeleteArg2, bDeleteThis, ppRes);
  795. }
  796. // Either clone or use our node
  797. // ============================
  798. CDumbNode* pNew = NULL;
  799. if(bDeleteThis)
  800. {
  801. pNew = this;
  802. }
  803. else
  804. {
  805. // Clone this node without cloning the branches.
  806. // =============================================
  807. pNew = (CDumbNode*)CloneSelf();
  808. if(pNew == NULL)
  809. return WBEM_E_OUT_OF_MEMORY;
  810. }
  811. CImplicationList Implications(OrigImplications);
  812. pNew->AdjustCompile(pNamespace, Implications);
  813. // Merge all branches
  814. // ==================
  815. for(int i = 0; i < m_apBranches.GetSize(); i++)
  816. {
  817. // Prepare implications for taking this branch
  818. // ===========================================
  819. CImplicationList BranchImplications(Implications);
  820. CEvalNode* pNewBranch = NULL;
  821. hres = CEvalTree::Combine(m_apBranches[i],
  822. pArg2->m_apBranches[i],
  823. nOp, pNamespace, BranchImplications,
  824. bDeleteThis, bDeleteArg2,
  825. &pNewBranch);
  826. if(FAILED(hres))
  827. {
  828. if ( !bDeleteThis )
  829. delete pNew;
  830. return hres;
  831. }
  832. if(bDeleteThis)
  833. {
  834. m_apBranches.Discard(i);
  835. pNew->m_apBranches.SetAt(i, pNewBranch);
  836. }
  837. else
  838. {
  839. if(pNew->m_apBranches.Add(pNewBranch) < 0)
  840. return WBEM_E_OUT_OF_MEMORY;
  841. }
  842. if(bDeleteArg2)
  843. pArg2->m_apBranches.Discard(i);
  844. }
  845. // Merge the nulls
  846. // ===============
  847. CImplicationList NullImplications(Implications);
  848. CEvalNode* pNewBranch = NULL;
  849. hres = CEvalTree::Combine(m_pNullBranch, pArg2->m_pNullBranch, nOp,
  850. pNamespace, NullImplications, bDeleteThis, bDeleteArg2,
  851. &pNewBranch);
  852. if(FAILED(hres))
  853. {
  854. if ( !bDeleteThis )
  855. delete pNew;
  856. return hres;
  857. }
  858. // Clear the old new branch, whatever it was, and replace it with the
  859. // new one.
  860. // ==================================================================
  861. pNew->m_pNullBranch = pNewBranch;
  862. // Clear deleted branches
  863. // ======================
  864. if(bDeleteArg2)
  865. pArg2->m_pNullBranch = NULL;
  866. // Delete Arg2, if needed (reused portions have been nulled out)
  867. // =============================================================
  868. if(bDeleteArg2)
  869. delete pArg2;
  870. *ppRes = pNew;
  871. return WBEM_S_NO_ERROR;
  872. }
  873. void CDumbNode::Dump(FILE* f, int nOffset)
  874. {
  875. CBranchingNode::Dump(f, nOffset);
  876. LPWSTR wszText = m_Token.GetText();
  877. CVectorDeleteMe<WCHAR> vdm1(wszText);
  878. PrintOffset(f, nOffset);
  879. fprintf(f, "token %S:\n", wszText);
  880. PrintOffset(f, nOffset);
  881. fprintf(f, "FALSE->\n");
  882. DumpNode(f, nOffset+1, m_apBranches[DUMBNODE_FALSE_BRANCH_INDEX]);
  883. PrintOffset(f, nOffset);
  884. fprintf(f, "TRUE->\n");
  885. DumpNode(f, nOffset+1, m_apBranches[DUMBNODE_TRUE_BRANCH_INDEX]);
  886. PrintOffset(f, nOffset);
  887. fprintf(f, "NULL->\n");
  888. DumpNode(f, nOffset+1, m_pNullBranch);
  889. }