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.

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