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.

6926 lines
186 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. EVALTREE.CPP
  5. Abstract:
  6. WBEM Evaluation Tree
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <stdio.h>
  11. #pragma warning(disable:4786)
  12. #include <wbemcomn.h>
  13. #include <fastall.h>
  14. #include <genutils.h>
  15. #include "evaltree.h"
  16. #include "TreeChecker.h"
  17. #include "evaltree.inl"
  18. #include "TwoPropNode.h"
  19. #include "dumbnode.h"
  20. // #define DUMP_EVAL_TREES 1
  21. HRESULT CoreGetNumParents(_IWmiObject* pClass, ULONG *plNumParents)
  22. {
  23. /*
  24. *plNumParents = ((CWbemObject*)pClass)->GetNumParents();
  25. */
  26. DWORD dwSize;
  27. HRESULT hres = pClass->GetDerivation(0, 0, plNumParents, &dwSize, NULL);
  28. if(hres != WBEM_E_BUFFER_TOO_SMALL && hres != S_OK)
  29. return WBEM_E_FAILED;
  30. return S_OK;
  31. }
  32. RELEASE_ME _IWmiObject* CoreGetEmbeddedObj(_IWmiObject* pObj, long lHandle)
  33. {
  34. _IWmiObject* pEmbedded = NULL;
  35. HRESULT hres = pObj->GetPropAddrByHandle(lHandle, 0, NULL,
  36. (void**)&pEmbedded);
  37. if(FAILED(hres))
  38. return NULL;
  39. return pEmbedded;
  40. }
  41. INTERNAL CCompressedString* CoreGetPropertyString(_IWmiObject* pObj,
  42. long lHandle)
  43. {
  44. CCompressedString* pcs = NULL;
  45. HRESULT hres = pObj->GetPropAddrByHandle(lHandle,
  46. WMIOBJECT_FLAG_ENCODING_V1, NULL,
  47. (void**)&pcs);
  48. if(FAILED(hres))
  49. return NULL;
  50. return pcs;
  51. }
  52. INTERNAL CCompressedString* CoreGetClassInternal(_IWmiObject* pObj)
  53. {
  54. CCompressedString* pcs = NULL;
  55. HRESULT hres = pObj->GetPropAddrByHandle(FASTOBJ_CLASSNAME_PROP_HANDLE,
  56. WMIOBJECT_FLAG_ENCODING_V1, NULL,
  57. (void**)&pcs);
  58. if(FAILED(hres))
  59. return NULL;
  60. return pcs;
  61. }
  62. INTERNAL CCompressedString* CoreGetParentAtIndex(_IWmiObject* pObj, long lIndex)
  63. {
  64. return ((CWbemObject*)pObj)->GetParentAtIndex(lIndex);
  65. }
  66. bool CoreIsDerived(_IWmiObject* pThis, _IWmiObject* pFrom)
  67. {
  68. CCompressedString* pcs = CoreGetClassInternal(pFrom);
  69. if(pcs == NULL)
  70. return false;
  71. try
  72. {
  73. return (pThis->InheritsFrom(pcs->CreateWStringCopy()) == S_OK);
  74. }
  75. catch (CX_MemoryException)
  76. {
  77. return false;
  78. }
  79. }
  80. //******************************************************************************
  81. //******************************************************************************
  82. // TOKEN VALUE
  83. //******************************************************************************
  84. //******************************************************************************
  85. CTokenValue::CTokenValue()
  86. {
  87. VariantInit(&m_v);
  88. }
  89. CTokenValue::CTokenValue(CTokenValue& Other)
  90. {
  91. VariantInit(&m_v);
  92. *this = Other;
  93. }
  94. CTokenValue::~CTokenValue()
  95. {
  96. VariantClear(&m_v);
  97. }
  98. bool CTokenValue::SetVariant(VARIANT& v)
  99. {
  100. if(FAILED(VariantCopy(&m_v, &v)))
  101. return false;
  102. // Convert to a better type
  103. // ========================
  104. if(V_VT(&v) == VT_I2 || V_VT(&v) == VT_UI1)
  105. {
  106. if(FAILED(VariantChangeType(&m_v, &m_v, 0, VT_I4)))
  107. return false;
  108. }
  109. else if(V_VT(&v) == VT_R4)
  110. {
  111. if(FAILED(VariantChangeType(&m_v, &m_v, 0, VT_R8)))
  112. return false;
  113. }
  114. return true;
  115. }
  116. void CTokenValue::operator=(CTokenValue& Other)
  117. {
  118. if(!SetVariant(Other.m_v))
  119. throw CX_MemoryException();
  120. }
  121. CTokenValue::operator unsigned __int64() const
  122. {
  123. if(V_VT(&m_v) == VT_I4)
  124. {
  125. return V_I4(&m_v);
  126. }
  127. else if(V_VT(&m_v) == VT_BSTR)
  128. {
  129. unsigned __int64 ui64;
  130. if(ReadUI64(V_BSTR(&m_v), ui64))
  131. return ui64;
  132. else
  133. return 0; // TBD: errors
  134. }
  135. else return 0;
  136. }
  137. CTokenValue::operator unsigned long() const
  138. {
  139. if(V_VT(&m_v) == VT_I4)
  140. {
  141. return V_I4(&m_v);
  142. }
  143. else if(V_VT(&m_v) == VT_BSTR)
  144. {
  145. unsigned __int64 ui64;
  146. if(ReadUI64(V_BSTR(&m_v), ui64))
  147. return (unsigned long)ui64;
  148. else
  149. return 0; // TBD: errors
  150. }
  151. else return 0;
  152. }
  153. CTokenValue::operator __int64() const
  154. {
  155. if(V_VT(&m_v) == VT_I4)
  156. {
  157. return V_I4(&m_v);
  158. }
  159. else if(V_VT(&m_v) == VT_BSTR)
  160. {
  161. __int64 i64;
  162. if(ReadI64(V_BSTR(&m_v), i64))
  163. return i64;
  164. else
  165. return 0; // TBD: errors
  166. }
  167. else return 0;
  168. }
  169. CTokenValue::operator short() const
  170. {
  171. if(V_VT(&m_v) == VT_I4)
  172. return V_I4(&m_v);
  173. else if(V_VT(&m_v) == VT_BOOL)
  174. return V_BOOL(&m_v);
  175. else return 0;
  176. }
  177. CTokenValue::operator float() const
  178. {
  179. if(V_VT(&m_v) == VT_I4)
  180. return V_I4(&m_v);
  181. else if(V_VT(&m_v) == VT_R8)
  182. return V_R8(&m_v);
  183. else return 0;
  184. }
  185. CTokenValue::operator double() const
  186. {
  187. if(V_VT(&m_v) == VT_I4)
  188. return V_I4(&m_v);
  189. else if(V_VT(&m_v) == VT_R8)
  190. return V_R8(&m_v);
  191. else return 0;
  192. }
  193. CTokenValue::operator WString() const
  194. {
  195. if(V_VT(&m_v) == VT_BSTR)
  196. return WString(V_BSTR(&m_v));
  197. else
  198. return WString(L"");
  199. }
  200. int CTokenValue::Compare(const CTokenValue& Other) const
  201. {
  202. switch(V_VT(&m_v))
  203. {
  204. case VT_I4:
  205. return V_I4(&m_v) - V_I4(&Other.m_v);
  206. case VT_R8:
  207. return (V_R8(&m_v) - V_R8(&Other.m_v)<0 ? -1 : 1);
  208. case VT_BSTR:
  209. return wbem_wcsicmp(V_BSTR(&m_v), V_BSTR(&Other.m_v));
  210. case VT_BOOL:
  211. return V_BOOL(&m_v) - V_BOOL(&Other.m_v);
  212. }
  213. return 0;
  214. }
  215. //******************************************************************************
  216. //******************************************************************************
  217. // OBJECT INFO
  218. //******************************************************************************
  219. //******************************************************************************
  220. bool CObjectInfo::SetLength(long lLength)
  221. {
  222. if(lLength > m_lLength)
  223. {
  224. delete [] m_apObj;
  225. m_apObj = new _IWmiObject*[lLength];
  226. if (m_apObj == NULL)
  227. return false;
  228. memset(m_apObj, 0, lLength * sizeof(_IWmiObject*));
  229. }
  230. m_lLength = lLength;
  231. return true;
  232. }
  233. void CObjectInfo::Clear()
  234. {
  235. for(long i = 1; i < m_lLength; i++)
  236. {
  237. if(m_apObj[i])
  238. m_apObj[i]->Release();
  239. m_apObj[i] = NULL;
  240. }
  241. m_apObj[0] = NULL; // do not release
  242. }
  243. void CObjectInfo::SetObjectAt(long lIndex, READ_ONLY _IWmiObject* pObj)
  244. {
  245. if(m_apObj[lIndex])
  246. m_apObj[lIndex]->Release();
  247. m_apObj[lIndex] = pObj;
  248. }
  249. CObjectInfo::~CObjectInfo()
  250. {
  251. for(long i = 0; i < m_lLength; i++)
  252. {
  253. if(m_apObj[i])
  254. m_apObj[i]->Release();
  255. }
  256. delete [] m_apObj;
  257. }
  258. //******************************************************************************
  259. //******************************************************************************
  260. // IMPLICATION LIST
  261. //******************************************************************************
  262. //******************************************************************************
  263. CImplicationList::CRecord::CRecord(const CImplicationList::CRecord& Other)
  264. : m_PropName(Other.m_PropName), m_pClass(Other.m_pClass),
  265. m_lObjIndex(Other.m_lObjIndex), m_nNull(Other.m_nNull)
  266. {
  267. if(m_pClass)
  268. m_pClass->AddRef();
  269. for(int i = 0; i < Other.m_awsNotClasses.Size(); i++)
  270. {
  271. if(m_awsNotClasses.Add(Other.m_awsNotClasses[i]) !=
  272. CWStringArray::no_error)
  273. {
  274. throw CX_MemoryException();
  275. }
  276. }
  277. }
  278. CImplicationList::CRecord::~CRecord()
  279. {
  280. if(m_pClass)
  281. m_pClass->Release();
  282. }
  283. HRESULT CImplicationList::CRecord::ImproveKnown(_IWmiObject* pClass)
  284. {
  285. if ( pClass == NULL )
  286. {
  287. //
  288. // not much we can improve on, but NULL is still a valid param.
  289. //
  290. return WBEM_S_NO_ERROR;
  291. }
  292. if(m_nNull == EVAL_VALUE_TRUE)
  293. {
  294. // Contradiction
  295. // =============
  296. return WBEM_E_TYPE_MISMATCH;
  297. }
  298. m_nNull = EVAL_VALUE_FALSE;
  299. ULONG lNumParents, lRecordNumParents;
  300. HRESULT hres = CoreGetNumParents(pClass, &lNumParents);
  301. if(FAILED(hres))
  302. return hres;
  303. if(m_pClass)
  304. {
  305. hres = CoreGetNumParents(m_pClass, &lRecordNumParents);
  306. if(FAILED(hres))
  307. return hres;
  308. }
  309. if(m_pClass == NULL || lNumParents > lRecordNumParents)
  310. {
  311. // Better than before. Check for inconsistencies
  312. // =============================================
  313. if(m_pClass)
  314. {
  315. if(!CoreIsDerived(pClass, m_pClass))
  316. return WBEM_E_TYPE_MISMATCH;
  317. }
  318. for(int i = 0; i < m_awsNotClasses.Size(); i++)
  319. {
  320. if(pClass->InheritsFrom(m_awsNotClasses[i]) == S_OK)
  321. {
  322. // Contradiction
  323. // =============
  324. return WBEM_E_TYPE_MISMATCH;
  325. }
  326. }
  327. // Replace
  328. // =======
  329. pClass->AddRef();
  330. if(m_pClass)
  331. m_pClass->Release();
  332. m_pClass = pClass;
  333. }
  334. else
  335. {
  336. // Verify that we are a parent of the selected and do not replace
  337. // ==============================================================
  338. if(!CoreIsDerived(m_pClass, pClass))
  339. return WBEM_E_TYPE_MISMATCH;
  340. }
  341. return WBEM_S_NO_ERROR;
  342. }
  343. HRESULT CImplicationList::CRecord::ImproveKnownNot(LPCWSTR wszClassName)
  344. {
  345. if(m_nNull == EVAL_VALUE_TRUE)
  346. {
  347. // Contradiction
  348. // =============
  349. return WBEM_E_TYPE_MISMATCH;
  350. }
  351. // Check for inconsistencies
  352. // =========================
  353. if(m_nNull == EVAL_VALUE_FALSE && m_pClass &&
  354. m_pClass->InheritsFrom(wszClassName) == S_OK)
  355. {
  356. // Contradiction
  357. // =============
  358. return WBEM_E_TYPE_MISMATCH;
  359. }
  360. try
  361. {
  362. if(m_awsNotClasses.Add(wszClassName) < 0)
  363. return WBEM_E_OUT_OF_MEMORY;
  364. }
  365. catch (CX_MemoryException)
  366. {
  367. return WBEM_E_OUT_OF_MEMORY;
  368. }
  369. m_nNull = EVAL_VALUE_FALSE;
  370. return WBEM_S_NO_ERROR;
  371. }
  372. HRESULT CImplicationList::CRecord::ImproveKnownNull()
  373. {
  374. if(m_nNull == EVAL_VALUE_FALSE)
  375. {
  376. return WBEM_E_TYPE_MISMATCH;
  377. }
  378. m_nNull = EVAL_VALUE_TRUE;
  379. return WBEM_S_NO_ERROR;
  380. }
  381. void CImplicationList::CRecord::Dump(FILE* f, int nOffset)
  382. {
  383. LPWSTR wszProp = m_PropName.GetText();
  384. CEvalNode::PrintOffset(f, nOffset);
  385. fprintf(f, "Learn about %S:\n", wszProp);
  386. if(m_pClass)
  387. {
  388. VARIANT v;
  389. m_pClass->Get(L"__CLASS", 0, &v, NULL, NULL);
  390. CEvalNode::PrintOffset(f, nOffset+1);
  391. fprintf(f, "Is of class %S\n", V_BSTR(&v));
  392. }
  393. for(int i = 0; i < m_awsNotClasses.Size(); i++)
  394. {
  395. CEvalNode::PrintOffset(f, nOffset+1);
  396. fprintf(f, "Not of class %S\n", m_awsNotClasses[i]);
  397. }
  398. if(m_nNull == EVAL_VALUE_TRUE)
  399. {
  400. CEvalNode::PrintOffset(f, nOffset+1);
  401. fprintf(f, "Is NULL\n");
  402. }
  403. }
  404. CImplicationList::CImplicationList(long lFlags)
  405. : m_lNextIndex(1), m_lRequiredDepth(1), m_pParent(NULL), m_lFlags(lFlags)
  406. {
  407. CPropertyName Empty;
  408. CRecord* pRecord = new CRecord(Empty, 0);
  409. if(pRecord == NULL)
  410. throw CX_MemoryException();
  411. if(m_apRecords.Add(pRecord) < 0)
  412. throw CX_MemoryException();
  413. }
  414. CImplicationList::CImplicationList(CImplicationList& Other, bool bLink)
  415. : m_lNextIndex(Other.m_lNextIndex),
  416. m_lRequiredDepth(Other.m_lRequiredDepth),
  417. m_pParent(NULL), m_lFlags(Other.m_lFlags)
  418. {
  419. if(bLink)
  420. m_pParent = &Other;
  421. for(int i = 0; i < Other.m_apRecords.GetSize(); i++)
  422. {
  423. CRecord* pOtherRecord = Other.m_apRecords[i];
  424. CRecord* pNewRecord = new CRecord(*pOtherRecord);
  425. if(pNewRecord == NULL)
  426. throw CX_MemoryException();
  427. if(m_apRecords.Add(pNewRecord) < 0)
  428. throw CX_MemoryException();
  429. }
  430. }
  431. CImplicationList::~CImplicationList()
  432. {
  433. m_lNextIndex = 0;
  434. }
  435. void CImplicationList::FindBestComputedContainer(CPropertyName* pPropName,
  436. long* plRecord, long* plMatched)
  437. {
  438. // Look for the largest match
  439. // ==========================
  440. long lMax = -1;
  441. long lMaxRecord = -1;
  442. for(long lRecord = 0; lRecord < m_apRecords.GetSize(); lRecord++)
  443. {
  444. CRecord* pRecord = m_apRecords[lRecord];
  445. if ( pRecord->m_lObjIndex == -1 )
  446. {
  447. //
  448. // we only consider computed records
  449. //
  450. continue;
  451. }
  452. for(int i = 0; i < pPropName->GetNumElements() &&
  453. i < pRecord->m_PropName.GetNumElements();
  454. i++)
  455. {
  456. if(wbem_wcsicmp(pPropName->GetStringAt(i),
  457. pRecord->m_PropName.GetStringAt(i)))
  458. break;
  459. }
  460. if(i > lMax)
  461. {
  462. lMax = i;
  463. lMaxRecord = lRecord;
  464. }
  465. }
  466. if(plRecord)
  467. *plRecord = lMaxRecord;
  468. if(plMatched)
  469. *plMatched = lMax;
  470. }
  471. HRESULT CImplicationList::FindRecordForProp(CPropertyName* pPropName,
  472. long lNumElements,
  473. long* plRecord)
  474. {
  475. if(lNumElements == -1)
  476. {
  477. if(pPropName)
  478. lNumElements = pPropName->GetNumElements();
  479. else
  480. lNumElements = 0;
  481. }
  482. //
  483. // Look for the exact match
  484. //
  485. for(long lRecord = 0; lRecord < m_apRecords.GetSize(); lRecord++)
  486. {
  487. CRecord* pRecord = m_apRecords[lRecord];
  488. if(pRecord->m_PropName.GetNumElements() != lNumElements)
  489. continue;
  490. for(int i = 0; i < lNumElements; i++)
  491. {
  492. if(wbem_wcsicmp(pPropName->GetStringAt(i),
  493. pRecord->m_PropName.GetStringAt(i)))
  494. break;
  495. }
  496. if(i == lNumElements)
  497. {
  498. break;
  499. }
  500. }
  501. if(lRecord < m_apRecords.GetSize())
  502. {
  503. // Found it!
  504. *plRecord = lRecord;
  505. return S_OK;
  506. }
  507. else
  508. return WBEM_E_NOT_FOUND;
  509. }
  510. HRESULT CImplicationList::FindBestComputedContainer(CPropertyName* pPropName,
  511. long* plFirstUnknownProp, long* plObjIndex,
  512. RELEASE_ME _IWmiObject** ppContainerClass)
  513. {
  514. if (!pPropName)
  515. return WBEM_E_FAILED;
  516. long lMax, lMaxRecord;
  517. FindBestComputedContainer(pPropName, &lMaxRecord, &lMax);
  518. if(lMaxRecord < 0)
  519. return WBEM_E_FAILED;
  520. if(plFirstUnknownProp)
  521. *plFirstUnknownProp = lMax;
  522. CRecord* pRecord = m_apRecords[lMaxRecord];
  523. if(plObjIndex)
  524. *plObjIndex = pRecord->m_lObjIndex;
  525. if(ppContainerClass)
  526. {
  527. *ppContainerClass = pRecord->m_pClass;
  528. if(pRecord->m_pClass)
  529. pRecord->m_pClass->AddRef();
  530. }
  531. return WBEM_S_NO_ERROR;
  532. }
  533. HRESULT CImplicationList::FindClassForProp(CPropertyName* pPropName,
  534. long lNumElements, RELEASE_ME _IWmiObject** ppClass)
  535. {
  536. // don't have a property name? djinn one up for use...
  537. CPropertyName* pPropNameLocal;
  538. CPropertyName blank;
  539. if (pPropName)
  540. pPropNameLocal = pPropName;
  541. else
  542. pPropNameLocal = &blank;
  543. long lRecord;
  544. CRecord* pRecord;
  545. if(SUCCEEDED(FindRecordForProp(pPropNameLocal, -1, &lRecord)))
  546. {
  547. //
  548. // A record is there --- return its class
  549. //
  550. *ppClass = m_apRecords[lRecord]->m_pClass;
  551. if(*ppClass)
  552. {
  553. (*ppClass)->AddRef();
  554. return WBEM_S_NO_ERROR;
  555. }
  556. else
  557. return WBEM_E_NOT_FOUND;
  558. }
  559. else
  560. return WBEM_E_NOT_FOUND;
  561. }
  562. HRESULT CImplicationList::FindOrCreateRecordForProp(CPropertyName* pPropName,
  563. CImplicationList::CRecord** ppRecord)
  564. {
  565. // don't have a property name? djinn one up for use...
  566. CPropertyName* pPropNameLocal;
  567. CPropertyName blank;
  568. if (pPropName)
  569. pPropNameLocal = pPropName;
  570. else
  571. pPropNameLocal = &blank;
  572. long lRecord;
  573. CRecord* pRecord;
  574. if(SUCCEEDED(FindRecordForProp(pPropNameLocal, -1, &lRecord)))
  575. {
  576. //
  577. // A record is there --- improve it
  578. //
  579. pRecord = m_apRecords[lRecord];
  580. }
  581. else
  582. {
  583. try
  584. {
  585. pRecord = new CRecord(*pPropNameLocal, -1);
  586. if(pRecord == NULL)
  587. return WBEM_E_OUT_OF_MEMORY;
  588. }
  589. catch (CX_MemoryException)
  590. {
  591. return WBEM_E_OUT_OF_MEMORY;
  592. }
  593. if(m_apRecords.Add(pRecord) < 0)
  594. return WBEM_E_OUT_OF_MEMORY;
  595. }
  596. *ppRecord = pRecord;
  597. return WBEM_S_NO_ERROR;
  598. }
  599. HRESULT CImplicationList::ImproveKnown(CPropertyName* pPropName,
  600. _IWmiObject* pClass)
  601. {
  602. CRecord* pRecord;
  603. HRESULT hres = FindOrCreateRecordForProp(pPropName, &pRecord);
  604. if(FAILED(hres))
  605. return hres;
  606. return pRecord->ImproveKnown(pClass);
  607. }
  608. HRESULT CImplicationList::ImproveKnownNot(CPropertyName* pPropName,
  609. LPCWSTR wszClassName)
  610. {
  611. CRecord* pRecord;
  612. HRESULT hres = FindOrCreateRecordForProp(pPropName, &pRecord);
  613. if(FAILED(hres))
  614. return hres;
  615. return pRecord->ImproveKnownNot(wszClassName);
  616. }
  617. HRESULT CImplicationList::ImproveKnownNull(CPropertyName* pPropName)
  618. {
  619. CRecord* pRecord;
  620. HRESULT hres = FindOrCreateRecordForProp(pPropName, &pRecord);
  621. if(FAILED(hres))
  622. return hres;
  623. return pRecord->ImproveKnownNull();
  624. }
  625. HRESULT CImplicationList::AddComputation(CPropertyName& PropName,
  626. _IWmiObject* pClass, long* plObjIndex)
  627. {
  628. CRecord* pRecord;
  629. HRESULT hres = FindOrCreateRecordForProp(&PropName, &pRecord);
  630. if(FAILED(hres))
  631. return hres;
  632. if(pClass)
  633. {
  634. hres = pRecord->ImproveKnown(pClass);
  635. if(FAILED(hres))
  636. return hres;
  637. }
  638. pRecord->m_lObjIndex = m_lNextIndex;
  639. *plObjIndex = m_lNextIndex++;
  640. RequireDepth(m_lNextIndex);
  641. return WBEM_S_NO_ERROR;
  642. }
  643. long CImplicationList::GetRequiredDepth()
  644. {
  645. return m_lRequiredDepth;
  646. }
  647. void CImplicationList::RequireDepth(long lDepth)
  648. {
  649. if(lDepth > m_lRequiredDepth)
  650. {
  651. m_lRequiredDepth = lDepth;
  652. if(m_pParent)
  653. m_pParent->RequireDepth(lDepth);
  654. }
  655. }
  656. HRESULT CImplicationList::MergeIn(CImplicationList* pList)
  657. {
  658. //
  659. // Add everything we learn from the second list into our own
  660. //
  661. HRESULT hres;
  662. for(int i = 0; i < pList->m_apRecords.GetSize(); i++)
  663. {
  664. CRecord* pRecord = pList->m_apRecords[i];
  665. hres = MergeIn(pRecord);
  666. if(FAILED(hres))
  667. return hres;
  668. }
  669. return S_OK;
  670. }
  671. HRESULT CImplicationList::MergeIn(CImplicationList::CRecord* pRecord)
  672. {
  673. HRESULT hres;
  674. //
  675. // Add everything we learn from the record into our own list
  676. //
  677. if(pRecord->m_pClass)
  678. {
  679. hres = ImproveKnown(&pRecord->m_PropName, pRecord->m_pClass);
  680. if(FAILED(hres))
  681. return hres;
  682. }
  683. for(int i = 0; i < pRecord->m_awsNotClasses.Size(); i++)
  684. {
  685. hres = ImproveKnownNot(&pRecord->m_PropName,
  686. pRecord->m_awsNotClasses[i]);
  687. if(FAILED(hres))
  688. return hres;
  689. }
  690. if(pRecord->m_nNull == EVAL_VALUE_TRUE)
  691. {
  692. hres = ImproveKnownNull(&pRecord->m_PropName);
  693. if(FAILED(hres))
  694. return hres;
  695. }
  696. return WBEM_S_NO_ERROR;
  697. }
  698. void CImplicationList::Dump(FILE* f, int nOffset)
  699. {
  700. for(int i = 0; i < m_apRecords.GetSize(); i++)
  701. m_apRecords[i]->Dump(f, nOffset);
  702. }
  703. //******************************************************************************
  704. //******************************************************************************
  705. // EVAL NODE
  706. //******************************************************************************
  707. //******************************************************************************
  708. CEvalNode::CEvalNode()
  709. {
  710. #ifdef CHECK_TREES
  711. g_treeChecker.AddNode(this);
  712. #endif
  713. }
  714. CEvalNode::CEvalNode(const CEvalNode& other)
  715. {
  716. #ifdef CHECK_TREES
  717. g_treeChecker.AddNode(this);
  718. #endif
  719. }
  720. CEvalNode::~CEvalNode()
  721. {
  722. #ifdef CHECK_TREES
  723. g_treeChecker.RemoveNode(this);
  724. #endif
  725. }
  726. void CEvalNode::PrintOffset(FILE* f, int nOffset)
  727. {
  728. for(int i = 0; i < nOffset; i++)
  729. {
  730. fprintf(f, " ");
  731. }
  732. }
  733. void CEvalNode::DumpNode(FILE* f, int nOffset, CEvalNode* pNode)
  734. {
  735. if(pNode == NULL)
  736. {
  737. PrintOffset(f, nOffset);
  738. fprintf(f, "FALSE\n");
  739. }
  740. else pNode->Dump(f, nOffset);
  741. }
  742. CEvalNode* CEvalNode::CloneNode(const CEvalNode* pNode)
  743. {
  744. if(pNode == NULL)
  745. return NULL;
  746. else
  747. return pNode->Clone();
  748. }
  749. bool CEvalNode::IsNoop(CEvalNode* pNode, int nOp)
  750. {
  751. if(pNode)
  752. return pNode->IsNoop(nOp);
  753. else
  754. return CValueNode::IsNoop(NULL, nOp);
  755. }
  756. #ifdef CHECK_TREES
  757. void CEvalNode::CheckNode(CTreeChecker *pCheck)
  758. {
  759. pCheck->CheckoffNode(this);
  760. }
  761. #endif
  762. //******************************************************************************
  763. //******************************************************************************
  764. // SORTED ARRAY
  765. //******************************************************************************
  766. //******************************************************************************
  767. // construct from a 'normal' array
  768. CSortedArray::CSortedArray(unsigned nElements, QueryID* pArray) : CFlexArray(nElements)
  769. {
  770. memcpy(GetArrayPtr(), pArray, nElements * sizeof(void*));
  771. SetSize(nElements);
  772. }
  773. int CSortedArray::CopyDataFrom(const QueryID* pArray, unsigned nElements)
  774. {
  775. EnsureExtent(nElements);
  776. SetSize(nElements);
  777. memcpy(GetArrayPtr(), pArray, nElements * sizeof(void*));
  778. return nElements;
  779. }
  780. unsigned CSortedArray::Find(QueryID n)
  781. {
  782. unsigned ret = InvalidID;
  783. // bailout if empty
  784. if(Size() == 0)
  785. return InvalidID;
  786. unsigned lBound = 0;
  787. unsigned uBound = Size() -1;
  788. // bailout checks - if it's on the boundary, don't search
  789. // if it's outside the boundaries, we ain't got it
  790. if (n == GetAt(uBound))
  791. ret = uBound;
  792. else if (n == GetAt(lBound))
  793. ret = lBound;
  794. else if ((n > GetAt(lBound)) && (n < GetAt(uBound)))
  795. {
  796. // binary search
  797. // warning: break in middle of loop
  798. do
  799. {
  800. unsigned testBound = (lBound + uBound) / 2;
  801. if (n < GetAt(testBound))
  802. uBound = testBound;
  803. else if (n > GetAt(testBound))
  804. lBound = testBound;
  805. else
  806. {
  807. ret = testBound;
  808. break;
  809. }
  810. } while (lBound < uBound -1);
  811. }
  812. return ret;
  813. }
  814. // inserts n in proper position
  815. // no dups allowed
  816. void CSortedArray::Insert(QueryID n)
  817. {
  818. // looks a lot like 'find'
  819. unsigned lBound = 0;
  820. unsigned uBound = Size() == 0 ? 0 : Size() -1;
  821. unsigned testBound = InvalidID;
  822. // check boundaries, empty array, out of bounds conditions...
  823. if ((Size() == 0) || (n < GetAt(lBound)))
  824. CFlexArray::InsertAt(0, (void *)n);
  825. else if (n > GetAt(uBound))
  826. Add(n);
  827. else if ((n != GetAt(uBound)) && (n != GetAt(lBound)))
  828. {
  829. // binary search
  830. // warning: break in middle of loop
  831. do
  832. {
  833. testBound = (lBound + uBound) / 2;
  834. if (n < GetAt(testBound))
  835. uBound = testBound;
  836. else if (n > GetAt(testBound))
  837. lBound = testBound;
  838. else
  839. break;
  840. } while (lBound < uBound -1);
  841. // at this point, three cases:
  842. // 1) we found the item at testBound
  843. // 2) we didn't find it, uBound = lBound +1
  844. // 3) we didn't find it, uBound == lBound
  845. if (n != GetAt(testBound))
  846. {
  847. if (n < GetAt(lBound))
  848. InsertAt(lBound, (void *)n);
  849. else
  850. InsertAt(uBound, (void *)n);
  851. }
  852. }
  853. }
  854. // removes element with value of n
  855. // NOT the nth element
  856. bool CSortedArray::Remove(QueryID n)
  857. {
  858. unsigned index;
  859. index = Find(n);
  860. if (index != InvalidID)
  861. {
  862. CFlexArray::RemoveAt(index);
  863. return true;
  864. }
  865. else
  866. return false;
  867. }
  868. //returns zero if arrays are equivalent
  869. // same number of USED elements w/ same values
  870. // LEVN: changed to return < 0 if less, > 0 if more
  871. int CSortedArray::Compare(CSortedArray& otherArray)
  872. {
  873. int nCompare = Size() - otherArray.Size();
  874. if(nCompare)
  875. return nCompare;
  876. nCompare = memcmp(GetArrayPtr(), otherArray.GetArrayPtr(),
  877. Size() * sizeof(void*));
  878. return nCompare;
  879. }
  880. // changes all QueryID's to begin at newBase
  881. // e.g. if the array is {0,1,5}
  882. // Rebase(6) will change to {6,7,11}
  883. void CSortedArray::Rebase(QueryID newBase)
  884. {
  885. for (int i = 0; i < Size(); i++)
  886. SetAt(i, (void *)(GetAt(i) + newBase));
  887. }
  888. // adds the values from the other array into this one
  889. int CSortedArray::AddDataFrom(const CSortedArray& otherArray)
  890. {
  891. // Check for emptiness
  892. if(otherArray.Size() == 0)
  893. return no_error;
  894. // Ensure there is enough room in our array for the union
  895. // ======================================================
  896. if(EnsureExtent(m_nSize + otherArray.m_nSize))
  897. return out_of_memory;
  898. // Start merging from the end
  899. // ==========================
  900. int nThisSourceIndex = m_nSize - 1;
  901. int nThisDestIndex = m_nSize + otherArray.m_nSize - 1;
  902. int nOtherIndex = otherArray.m_nSize - 1;
  903. while(nThisSourceIndex >= 0 && nOtherIndex >= 0)
  904. {
  905. int nCompare =
  906. (QueryID)m_pArray[nThisSourceIndex] - (QueryID)otherArray[nOtherIndex];
  907. if(nCompare < 0)
  908. {
  909. m_pArray[nThisDestIndex--] = otherArray[nOtherIndex--];
  910. }
  911. else if(nCompare > 0)
  912. {
  913. m_pArray[nThisDestIndex--] = m_pArray[nThisSourceIndex--];
  914. }
  915. else
  916. {
  917. m_pArray[nThisDestIndex--] = otherArray[nOtherIndex--];
  918. nThisSourceIndex--;
  919. }
  920. }
  921. // Add remainders
  922. // ==============
  923. while(nThisSourceIndex >= 0)
  924. m_pArray[nThisDestIndex--] = m_pArray[nThisSourceIndex--];
  925. while(nOtherIndex >= 0)
  926. m_pArray[nThisDestIndex--] = otherArray[nOtherIndex--];
  927. // Move the array forward if needed
  928. // ================================
  929. if(nThisDestIndex >= 0)
  930. {
  931. for(int i = nThisDestIndex+1; i < m_nSize + otherArray.m_nSize; i++)
  932. {
  933. m_pArray[i-nThisDestIndex-1] = m_pArray[i];
  934. }
  935. }
  936. m_nSize = m_nSize + otherArray.m_nSize - (nThisDestIndex+1);
  937. return no_error;
  938. }
  939. // adds the values from the other array into this one
  940. int CSortedArray::AddDataFrom(const QueryID* pOtherArray, unsigned nValues)
  941. {
  942. // Check for emptiness
  943. if(nValues == 0)
  944. return no_error;
  945. // Ensure there is enough room in our array for the union
  946. // ======================================================
  947. if(EnsureExtent(m_nSize + nValues))
  948. return out_of_memory;
  949. // Start merging from the end
  950. // ==========================
  951. int nThisSourceIndex = m_nSize - 1;
  952. int nThisDestIndex = m_nSize + nValues - 1;
  953. int nOtherIndex = nValues - 1;
  954. while(nThisSourceIndex >= 0 && nOtherIndex >= 0)
  955. {
  956. int nCompare =
  957. (QueryID)m_pArray[nThisSourceIndex] - (QueryID)pOtherArray[nOtherIndex];
  958. if(nCompare < 0)
  959. {
  960. m_pArray[nThisDestIndex--] = (void*)pOtherArray[nOtherIndex--];
  961. }
  962. else if(nCompare > 0)
  963. {
  964. m_pArray[nThisDestIndex--] = m_pArray[nThisSourceIndex--];
  965. }
  966. else
  967. {
  968. m_pArray[nThisDestIndex--] = (void*)pOtherArray[nOtherIndex--];
  969. nThisSourceIndex--;
  970. }
  971. }
  972. // Add remainders
  973. // ==============
  974. while(nThisSourceIndex >= 0)
  975. m_pArray[nThisDestIndex--] = m_pArray[nThisSourceIndex--];
  976. while(nOtherIndex >= 0)
  977. m_pArray[nThisDestIndex--] = (void*)pOtherArray[nOtherIndex--];
  978. // Move the array forward if needed
  979. // ================================
  980. if(nThisDestIndex >= 0)
  981. {
  982. for(int i = nThisDestIndex+1; i < m_nSize + nValues; i++)
  983. {
  984. m_pArray[i-nThisDestIndex-1] = m_pArray[i];
  985. }
  986. }
  987. m_nSize = m_nSize + nValues - (nThisDestIndex+1);
  988. return no_error;
  989. }
  990. // copies this array to destination
  991. // only copies size number of elements
  992. // returns number of elements copied
  993. unsigned CSortedArray::CopyTo(QueryID* pDest, unsigned size)
  994. {
  995. unsigned mySize = Size();
  996. unsigned nElementsToCopy = min(size, mySize);
  997. if (nElementsToCopy)
  998. memcpy(pDest, GetArrayPtr(), nElementsToCopy * sizeof(void*));
  999. return nElementsToCopy;
  1000. }
  1001. //******************************************************************************
  1002. //******************************************************************************
  1003. // VALUE NODE
  1004. //******************************************************************************
  1005. //******************************************************************************
  1006. CValueNode::CValueNode(int nNumValues)
  1007. {
  1008. }
  1009. CValueNode::~CValueNode()
  1010. {
  1011. // this page intentionally left blank
  1012. }
  1013. /* virtual */ int CValueNode::GetType()
  1014. {
  1015. return EVAL_NODE_TYPE_VALUE;
  1016. }
  1017. // changes all QueryID's in all arrays to begin at newBase
  1018. // e.g. if the array is {0,1,5}
  1019. // Rebase(6) will change to {6,7,11}
  1020. void CValueNode::Rebase(QueryID newBase)
  1021. {
  1022. for (int i = 0; i < m_nValues; i++)
  1023. m_trueIDs[i] += newBase;
  1024. }
  1025. // returns array index of n
  1026. // or InvalidID if not found
  1027. unsigned CValueNode::FindQueryID(QueryID n)
  1028. {
  1029. unsigned ret = InvalidID;
  1030. if ( m_nValues == 0 )
  1031. {
  1032. return ret;
  1033. }
  1034. unsigned lBound = 0;
  1035. unsigned uBound = m_nValues - 1;
  1036. // bailout checks - if it's on the boundary, don't search
  1037. // if it's outside the boundaries, we ain't got it
  1038. if (n == m_trueIDs[uBound])
  1039. ret = uBound;
  1040. else if (n == m_trueIDs[lBound])
  1041. ret = lBound;
  1042. else if ((n > m_trueIDs[lBound]) && (n < m_trueIDs[uBound]))
  1043. {
  1044. // binary search
  1045. // warning: break in middle of loop
  1046. do
  1047. {
  1048. unsigned testBound = (lBound + uBound) / 2;
  1049. if (n < m_trueIDs[testBound])
  1050. uBound = testBound;
  1051. else if (n > m_trueIDs[testBound])
  1052. lBound = testBound;
  1053. else
  1054. {
  1055. ret = testBound;
  1056. break;
  1057. }
  1058. } while (lBound < uBound -1);
  1059. }
  1060. return ret;
  1061. }
  1062. bool CValueNode::RemoveQueryID(QueryID nQuery)
  1063. {
  1064. unsigned n;
  1065. if ((n = FindQueryID(nQuery)) != InvalidID)
  1066. {
  1067. if ((m_nValues > 1) && (n != m_nValues -1))
  1068. memcpy(&(m_trueIDs[n]), &(m_trueIDs[n+1]), (m_nValues -n -1) * sizeof(QueryID));
  1069. if (m_nValues > 0)
  1070. m_trueIDs[--m_nValues] = InvalidID;
  1071. }
  1072. return (n != InvalidID);
  1073. }
  1074. // combines two arrays, new array has all elements that appear in either
  1075. // BUT NOT in the corresponding NOT array
  1076. void CValueNode::ORarrays(CSortedArray& array1, CSortedArray& array1Not,
  1077. CSortedArray& array2, CSortedArray& array2Not,
  1078. CSortedArray& output)
  1079. {
  1080. unsigned array1Index = 0;
  1081. unsigned array2Index = 0;
  1082. // walk through both arrays, always adding smallest value to new array
  1083. while (array1Index < array1.Size() && array2Index < array2.Size())
  1084. {
  1085. if (array1.GetAt(array1Index) == array2.GetAt(array2Index))
  1086. {
  1087. // found match, add to array & bump up both cursors
  1088. output.Add(array1.GetAt(array1Index));
  1089. array1Index++;
  1090. array2Index++;
  1091. }
  1092. else if (array2.GetAt(array2Index) < array1.GetAt(array1Index))
  1093. {
  1094. // add it, but only if it's NOT in the NOT array
  1095. if (array2Not.Find(array2.GetAt(array2Index)) != InvalidID)
  1096. output.Add(array2.GetAt(array2Index));
  1097. array2Index++;
  1098. }
  1099. else
  1100. {
  1101. if (array1Not.Find(array1.GetAt(array1Index)) != InvalidID)
  1102. output.Add(array1.GetAt(array1Index));
  1103. array1Index++;
  1104. }
  1105. }
  1106. // run out whichever array we didn't finish
  1107. while (array1Index < array1.Size())
  1108. if (array1Not.Find(array1.GetAt(array1Index)) != InvalidID)
  1109. output.Add(array1.GetAt(array1Index++));
  1110. while (array2Index < array2.Size())
  1111. if (array2Not.Find(array2.GetAt(array2Index)) != InvalidID)
  1112. output.Add(array2.GetAt(array2Index++));
  1113. }
  1114. void CValueNode::ORarrays(CSortedArray& array1,
  1115. CSortedArray& array2,
  1116. CSortedArray& output)
  1117. {
  1118. unsigned array1Index = 0;
  1119. unsigned array2Index = 0;
  1120. // walk through both arrays, always adding smallest value to new array
  1121. while (array1Index < array1.Size() && array2Index < array2.Size())
  1122. {
  1123. if (array1.GetAt(array1Index) == array2.GetAt(array2Index))
  1124. {
  1125. // found match, add to array & bump up both cursors
  1126. output.Add(array1.GetAt(array1Index));
  1127. array1Index++;
  1128. array2Index++;
  1129. }
  1130. else if (array2.GetAt(array2Index) < array1.GetAt(array1Index))
  1131. {
  1132. // add it
  1133. output.Add(array2.GetAt(array2Index));
  1134. array2Index++;
  1135. }
  1136. else
  1137. {
  1138. output.Add(array1.GetAt(array1Index));
  1139. array1Index++;
  1140. }
  1141. }
  1142. // run out whichever array we didn't finish
  1143. while (array1Index < array1.Size())
  1144. output.Add(array1.GetAt(array1Index++));
  1145. while (array2Index < array2.Size())
  1146. output.Add(array2.GetAt(array2Index++));
  1147. }
  1148. // pointers point to arrays that are at the corresponding sizes
  1149. // caller is responsible for ensuring that the output array is large enough
  1150. // return value #elements inserted into new array;
  1151. unsigned CValueNode::ORarrays(QueryID* pArray1, unsigned size1,
  1152. QueryID* pArray2, unsigned size2,
  1153. QueryID* pOutput)
  1154. {
  1155. unsigned nElements = 0;
  1156. // if ((pArray1 == NULL) && (pArray2 == NULL))
  1157. // really shouldn't happen - one side has should have come from this
  1158. // else
  1159. if (pArray2 == NULL)
  1160. {
  1161. nElements = size1;
  1162. memcpy(pOutput, pArray1, sizeof(QueryID) * size1);
  1163. }
  1164. else if (pArray2 == NULL)
  1165. {
  1166. nElements = size1;
  1167. memcpy(pOutput, pArray1, sizeof(QueryID) * size1);
  1168. }
  1169. else
  1170. {
  1171. QueryID* pQID1 = pArray1;
  1172. QueryID* pQID2 = pArray2;
  1173. QueryID* pOut = pOutput;
  1174. // note that the 'ends' are really one past the end, careful now...
  1175. QueryID* pEnd1 = pQID1 + size1;
  1176. QueryID* pEnd2 = pQID2 + size2;
  1177. // walk through both arrays, always adding smallest value to new array
  1178. while ((pQID1 < pEnd1) && (pQID2 < pEnd2))
  1179. {
  1180. if (*pQID1 == *pQID2)
  1181. {
  1182. // found match, add to array & bump up both cursors
  1183. *pOut++ = *pQID1++;
  1184. pQID2++;
  1185. nElements++;
  1186. }
  1187. else if (*pQID2 < *pQID1)
  1188. {
  1189. // add it
  1190. *pOut++ = *pQID2++;
  1191. nElements++;
  1192. }
  1193. else
  1194. {
  1195. // other side must be smaller, add IT.
  1196. *pOut++ = *pQID1++;
  1197. nElements++;
  1198. }
  1199. }
  1200. // run out whichever array we didn't finish
  1201. // only one should ever hit
  1202. while (pQID1 < pEnd1)
  1203. {
  1204. *pOut++ = *pQID1++;
  1205. nElements++;
  1206. }
  1207. while (pQID2 < pEnd2)
  1208. {
  1209. *pOut++ = *pQID2++;
  1210. nElements++;
  1211. }
  1212. }
  1213. return nElements;
  1214. }
  1215. void CValueNode::ANDarrays(CSortedArray& array1, CSortedArray& array2, CSortedArray& output)
  1216. {
  1217. // going to march down both arrays
  1218. // only put value in new array if it appears in both.
  1219. unsigned array1Index = 0;
  1220. unsigned array2Index = 0;
  1221. while (array1Index < array1.Size() && array2Index < array2.Size())
  1222. {
  1223. if (array1.GetAt(array1Index) == array2.GetAt(array2Index))
  1224. {
  1225. // found match, add to array & bump up both cursors
  1226. output.Add(array1.GetAt(array1Index));
  1227. array1Index++;
  1228. array2Index++;
  1229. }
  1230. else if (array1.GetAt(array1Index) > array2.GetAt(array2Index))
  1231. array2Index++;
  1232. else
  1233. array1Index++;
  1234. }
  1235. }
  1236. unsigned CValueNode::ANDarrays(QueryID* pArray1, unsigned size1,
  1237. QueryID* pArray2, unsigned size2,
  1238. QueryID* pOutput)
  1239. {
  1240. unsigned nElements = 0;
  1241. if ((pArray1 != NULL) &&
  1242. (pArray2 != NULL))
  1243. {
  1244. QueryID* pQID1 = pArray1;
  1245. QueryID* pQID2 = pArray2;
  1246. QueryID* pOut = pOutput;
  1247. // note that the 'ends' are really one past the end, careful now...
  1248. QueryID* pEnd1 = pQID1 + size1;
  1249. QueryID* pEnd2 = pQID2 + size2;
  1250. // walk through both arrays, adding any values that appear in both
  1251. while ((pQID1 < pEnd1) && (pQID2 < pEnd2))
  1252. {
  1253. if (*pQID1 == *pQID2)
  1254. {
  1255. // found match, add to array & bump up both cursors
  1256. *pOut++ = *pQID1++;
  1257. pQID2++;
  1258. nElements++;
  1259. }
  1260. else if (*pQID2 < *pQID1)
  1261. pQID2++;
  1262. else
  1263. pQID1++;
  1264. }
  1265. }
  1266. return nElements;
  1267. }
  1268. void CValueNode::CombineArrays(CSortedArray& array1, CSortedArray& array2, CSortedArray& output)
  1269. {
  1270. // march down both arrays
  1271. unsigned array1Index = 0;
  1272. unsigned array2Index = 0;
  1273. while (array1Index < array1.Size() && array2Index < array2.Size())
  1274. {
  1275. if (array1.GetAt(array1Index) == array2.GetAt(array2Index))
  1276. {
  1277. // found match, add to array & bump up both cursors
  1278. output.Add(array1.GetAt(array1Index));
  1279. array1Index++;
  1280. array2Index++;
  1281. }
  1282. else if (array1.GetAt(array1Index) > array2.GetAt(array2Index))
  1283. {
  1284. output.Add(array2.GetAt(array2Index));
  1285. array2Index++;
  1286. }
  1287. else
  1288. {
  1289. output.Add(array1.GetAt(array1Index));
  1290. array1Index++;
  1291. }
  1292. }
  1293. // run out whichever array we didn't finish
  1294. while (array1Index < array1.Size())
  1295. output.Add(array1.GetAt(array1Index++));
  1296. while (array2Index < array2.Size())
  1297. output.Add(array2.GetAt(array2Index++));
  1298. }
  1299. unsigned CValueNode::CombineArrays(QueryID* pArray1, unsigned size1,
  1300. QueryID* pArray2, unsigned size2,
  1301. QueryID* pOutput)
  1302. {
  1303. unsigned nElements = 0;
  1304. // if ((pArray1 == NULL) && (pArray2 == NULL))
  1305. // really shouldn't happen - one side has should have come from this
  1306. // else
  1307. if (pArray2 == NULL)
  1308. {
  1309. nElements = size1;
  1310. memcpy(pOutput, pArray1, sizeof(QueryID) * size1);
  1311. }
  1312. else if (pArray1 == NULL)
  1313. {
  1314. nElements = size2;
  1315. memcpy(pOutput, pArray2, sizeof(QueryID) * size2);
  1316. }
  1317. else
  1318. {
  1319. QueryID* pQID1 = pArray1;
  1320. QueryID* pQID2 = pArray2;
  1321. QueryID* pOut = pOutput;
  1322. // note that the 'ends' are really one past the end, careful now...
  1323. QueryID* pEnd1 = pQID1 + size1;
  1324. QueryID* pEnd2 = pQID2 + size2;
  1325. while ((pQID1 < pEnd1) && (pQID2 < pEnd2))
  1326. {
  1327. if (*pQID1 == *pQID2)
  1328. {
  1329. // found match, add to array & bump up both cursors
  1330. *pOut++ = *pQID1++;
  1331. pQID2++;
  1332. nElements++;
  1333. }
  1334. else if (*pQID2 < *pQID1)
  1335. {
  1336. // add it
  1337. *pOut++ = *pQID2++;
  1338. nElements++;
  1339. }
  1340. else
  1341. {
  1342. // other side must be smaller, add IT.
  1343. *pOut++ = *pQID1++;
  1344. nElements++;
  1345. }
  1346. }
  1347. // run out whichever array we didn't finish
  1348. // only one should ever hit
  1349. while (pQID1 < pEnd1)
  1350. {
  1351. *pOut++ = *pQID1++;
  1352. nElements++;
  1353. }
  1354. while (pQID2 < pEnd2)
  1355. {
  1356. *pOut++ = *pQID2++;
  1357. nElements++;
  1358. }
  1359. }
  1360. return nElements;
  1361. }
  1362. // size of new arrays is predicated on the assumption that
  1363. // there will usually be more TRUE nodes than INVALID ones
  1364. HRESULT CValueNode::CombineWith(CEvalNode* pRawArg2, int nOp,
  1365. CContextMetaData* pNamespace,
  1366. CImplicationList& Implications,
  1367. bool bDeleteThis, bool bDeleteArg2,
  1368. CEvalNode** ppRes)
  1369. {
  1370. HRESULT hRes = WBEM_S_NO_ERROR;
  1371. CValueNode* pArg2 = (CValueNode*)pRawArg2;
  1372. // Check for immediate solutions
  1373. // =============================
  1374. if(nOp != EVAL_OP_AND)
  1375. {
  1376. if(IsAllFalse(pArg2) && bDeleteThis)
  1377. {
  1378. // Just return this!
  1379. // =================
  1380. *ppRes = this;
  1381. if(bDeleteArg2)
  1382. delete pArg2;
  1383. return WBEM_S_NO_ERROR;
  1384. }
  1385. else if(IsAllFalse(this) && bDeleteArg2)
  1386. {
  1387. // Just return arg2!
  1388. // =================
  1389. *ppRes = pRawArg2;
  1390. if(bDeleteThis)
  1391. delete this;
  1392. return WBEM_S_NO_ERROR;
  1393. }
  1394. }
  1395. // if we got enough room in a stack array, we'll use that,
  1396. // elsewise we'll allocate one from the heap
  1397. const unsigned NewArraySize = 128;
  1398. QueryID newArray[NewArraySize];
  1399. QueryID* pNewArray = newArray;
  1400. CDeleteMe<QueryID> deleteMe;
  1401. CValueNode* pNew;
  1402. unsigned nElements;
  1403. unsigned arg2Values;
  1404. QueryID* arg2Array;
  1405. if (pArg2)
  1406. {
  1407. arg2Values = pArg2->m_nValues;
  1408. arg2Array = pArg2->m_trueIDs;
  1409. }
  1410. else
  1411. {
  1412. arg2Values = 0;
  1413. arg2Array = NULL;
  1414. }
  1415. if (nOp == EVAL_OP_AND)
  1416. {
  1417. if (max(m_nValues, arg2Values) > NewArraySize)
  1418. {
  1419. pNewArray = new QueryID[max(m_nValues, arg2Values)];
  1420. if(pNewArray == NULL)
  1421. return WBEM_E_OUT_OF_MEMORY;
  1422. deleteMe = pNewArray;
  1423. }
  1424. nElements = ANDarrays(m_trueIDs, m_nValues,
  1425. arg2Array, arg2Values,
  1426. pNewArray);
  1427. }
  1428. // HMH: it sure looks to me like OR and COMBINE are the same for this case
  1429. // I'm too afraid to risk changing it, tho
  1430. else if (nOp == EVAL_OP_OR)
  1431. {
  1432. if (max(m_nValues, arg2Values) > NewArraySize)
  1433. {
  1434. pNewArray = new QueryID[max(m_nValues, arg2Values)];
  1435. if(pNewArray == NULL)
  1436. return WBEM_E_OUT_OF_MEMORY;
  1437. deleteMe = pNewArray;
  1438. }
  1439. nElements = ORarrays(m_trueIDs, m_nValues,
  1440. arg2Array, arg2Values,
  1441. pNewArray);
  1442. }
  1443. else if ((nOp == EVAL_OP_COMBINE) || (nOp == EVAL_OP_INVERSE_COMBINE))
  1444. {
  1445. if ((m_nValues + arg2Values) > NewArraySize)
  1446. {
  1447. pNewArray = new QueryID[m_nValues + arg2Values];
  1448. if(pNewArray == NULL)
  1449. return WBEM_E_OUT_OF_MEMORY;
  1450. deleteMe = pNewArray;
  1451. }
  1452. nElements = CombineArrays(m_trueIDs, m_nValues,
  1453. arg2Array, arg2Values,
  1454. pNewArray);
  1455. }
  1456. // check to see if we can reuse a node, note this could result in the array 'shrinking'
  1457. if (nElements == 0)
  1458. *ppRes = NULL;
  1459. else if (bDeleteThis && (nElements <= m_nValues))
  1460. {
  1461. *ppRes = this;
  1462. memcpy(m_trueIDs, pNewArray, nElements * sizeof(QueryID));
  1463. m_nValues = nElements;
  1464. bDeleteThis = false;
  1465. }
  1466. else if (bDeleteArg2 && pArg2 && (nElements <= pArg2->m_nValues))
  1467. {
  1468. *ppRes = pArg2;
  1469. memcpy(pArg2->m_trueIDs, pNewArray, nElements * sizeof(QueryID));
  1470. pArg2->m_nValues = nElements;
  1471. bDeleteArg2 = false;
  1472. }
  1473. else if (pNew = CreateNode(nElements))
  1474. { // can't reuse one, start a new one
  1475. *ppRes = pNew;
  1476. memcpy(pNew->m_trueIDs, pNewArray, nElements * sizeof(QueryID));
  1477. }
  1478. else
  1479. hRes = WBEM_E_OUT_OF_MEMORY;
  1480. // Delete what needed deletion
  1481. // ===========================
  1482. // deleteMe will take care of the array pointer if allocated
  1483. if(bDeleteThis)
  1484. delete this;
  1485. if(bDeleteArg2)
  1486. delete pArg2;
  1487. return WBEM_S_NO_ERROR;
  1488. }
  1489. //static
  1490. bool CValueNode::IsNoop(CValueNode* pNode, int nOp)
  1491. {
  1492. if(nOp == EVAL_OP_OR)
  1493. return IsAllFalse(pNode);
  1494. else if(nOp == EVAL_OP_AND)
  1495. return false; // BUGBUG: would be nice to have IsAllTrue, but can't
  1496. else if(nOp == EVAL_OP_COMBINE || nOp == EVAL_OP_INVERSE_COMBINE)
  1497. return IsAllFalse(pNode);
  1498. else
  1499. {
  1500. //?
  1501. return false;
  1502. }
  1503. }
  1504. HRESULT CValueNode::TryShortCircuit(CEvalNode* pArg2, int nOp,
  1505. bool bDeleteThis, bool bDeleteArg2,
  1506. CEvalNode** ppRes)
  1507. {
  1508. if(IsAllFalse(this))
  1509. {
  1510. if(nOp == EVAL_OP_AND)
  1511. {
  1512. // FALSE & X is FALSE
  1513. if(bDeleteThis)
  1514. *ppRes = this;
  1515. else
  1516. {
  1517. *ppRes = Clone();
  1518. if(*ppRes == NULL)
  1519. return WBEM_E_OUT_OF_MEMORY;
  1520. }
  1521. if(bDeleteArg2)
  1522. delete pArg2;
  1523. return WBEM_S_NO_ERROR;
  1524. }
  1525. else // OR and COMBINE are identical in this case
  1526. {
  1527. // FALSE | X is X
  1528. //
  1529. // Well, this is true, but the problem is with optimizations.
  1530. // Some branches in X might not be valid under the implications in
  1531. // this branch of the tree, and so need to be removed. For now, I
  1532. // will simply turn off this short-circuiting path. It may turn out
  1533. // that there are some critical performance gains to be had by
  1534. // keeping it, in which case we would need to put this back and
  1535. // make an efficient pass through it, checking branches.
  1536. //
  1537. return WBEM_S_FALSE;
  1538. /*
  1539. if(bDeleteArg2)
  1540. *ppRes = pArg2;
  1541. else if (pArg2)
  1542. {
  1543. *ppRes = pArg2->Clone();
  1544. if(*ppRes == NULL)
  1545. return WBEM_E_OUT_OF_MEMORY;
  1546. }
  1547. else
  1548. *ppRes = NULL;
  1549. if(bDeleteThis)
  1550. delete this;
  1551. return WBEM_S_NO_ERROR;
  1552. */
  1553. }
  1554. }
  1555. return WBEM_S_FALSE;
  1556. }
  1557. HRESULT CValueNode::Project(CContextMetaData* pMeta,
  1558. CImplicationList& Implications,
  1559. CProjectionFilter* pFilter,
  1560. EProjectionType eType, bool bDeleteThis,
  1561. CEvalNode** ppNewNode)
  1562. {
  1563. //
  1564. // Projection of a constant is, again, a constant
  1565. //
  1566. if(bDeleteThis)
  1567. {
  1568. *ppNewNode = this;
  1569. }
  1570. else
  1571. {
  1572. *ppNewNode = Clone();
  1573. if(*ppNewNode == NULL)
  1574. return WBEM_E_OUT_OF_MEMORY;
  1575. }
  1576. return S_OK;
  1577. }
  1578. CEvalNode* CValueNode::Clone() const
  1579. {
  1580. CValueNode* pNew;
  1581. if (pNew = CreateNode(m_nValues))
  1582. memcpy(pNew->m_trueIDs, m_trueIDs, m_nValues * sizeof(QueryID));
  1583. return pNew;
  1584. }
  1585. int CValueNode::Compare(CEvalNode* pRawOther)
  1586. {
  1587. if (!pRawOther)
  1588. return m_nValues;
  1589. CValueNode* pOther = (CValueNode*)pRawOther;
  1590. int nCompare = m_nValues - pOther->m_nValues;
  1591. if ((nCompare == 0) && (m_nValues != 0))
  1592. nCompare = memcmp(m_trueIDs, pOther->m_trueIDs, m_nValues * sizeof(QueryID));
  1593. return nCompare;
  1594. }
  1595. CValueNode* CValueNode::GetStandardTrue()
  1596. {
  1597. CValueNode* pNew = CreateNode(1);
  1598. if(pNew)
  1599. pNew->m_trueIDs[0] = 0;
  1600. return pNew;
  1601. }
  1602. CValueNode* CValueNode::GetStandardInvalid()
  1603. {
  1604. return new CInvalidNode;
  1605. }
  1606. /*static*/ CValueNode* CValueNode::CreateNode(size_t nNumValues)
  1607. {
  1608. return new(nNumValues) CValueNode;
  1609. }
  1610. /*static*/ CValueNode* CValueNode::CreateNode(CSortedArray& values)
  1611. {
  1612. CValueNode* pNode;
  1613. pNode = new(values.Size()) CValueNode;
  1614. if (pNode)
  1615. values.CopyTo(pNode->m_trueIDs, values.Size());
  1616. return pNode;
  1617. }
  1618. void* CValueNode::operator new( size_t stAllocateBlock, unsigned nEntries)
  1619. {
  1620. void *pvTemp;
  1621. if (pvTemp = ::new byte[ stAllocateBlock + ((nEntries ==0)? 0 : ((nEntries -1)* sizeof(QueryID)))] )
  1622. ((CValueNode*)pvTemp)->m_nValues = nEntries;
  1623. return pvTemp;
  1624. }
  1625. // VC 5 only allows one delete operator per class
  1626. #if _MSC_VER >= 1200
  1627. void CValueNode::operator delete( void *p, unsigned nEntries )
  1628. {
  1629. ::delete[] (byte*)p;
  1630. }
  1631. #endif
  1632. void CValueNode::Dump(FILE* f, int nOffset)
  1633. {
  1634. PrintOffset(f, nOffset);
  1635. fprintf(f, "TRUE: ");
  1636. for (int i = 0; i < m_nValues; i++)
  1637. {
  1638. fprintf(f, "%u", m_trueIDs[i]);
  1639. if(i < m_nValues-1)
  1640. fprintf(f, ", %u", m_trueIDs[i]);
  1641. }
  1642. fprintf(f, "\n");
  1643. }
  1644. void CInvalidNode::Dump(FILE* f, int nOffset)
  1645. {
  1646. PrintOffset(f, nOffset);
  1647. fprintf(f, "Invalid node (0x%p)\n", this);
  1648. }
  1649. //******************************************************************************
  1650. //******************************************************************************
  1651. // EMBEDDING INFO
  1652. //******************************************************************************
  1653. //******************************************************************************
  1654. CEmbeddingInfo::CEmbeddingInfo()
  1655. : m_lNumJumps(0), m_aJumps(NULL), m_lStartingObjIndex(0)
  1656. {
  1657. }
  1658. CEmbeddingInfo::CEmbeddingInfo(const CEmbeddingInfo& Other)
  1659. : m_lNumJumps(0), m_aJumps(NULL), m_lStartingObjIndex(0)
  1660. {
  1661. *this = Other;
  1662. }
  1663. void CEmbeddingInfo::operator=(const CEmbeddingInfo& Other)
  1664. {
  1665. m_EmbeddedObjPropName = Other.m_EmbeddedObjPropName;
  1666. m_lNumJumps = Other.m_lNumJumps;
  1667. m_lStartingObjIndex = Other.m_lStartingObjIndex;
  1668. delete [] m_aJumps;
  1669. if(m_lNumJumps > 0)
  1670. {
  1671. m_aJumps = new JumpInfo[m_lNumJumps];
  1672. if (m_aJumps == NULL)
  1673. throw CX_MemoryException();
  1674. memcpy(m_aJumps, Other.m_aJumps, m_lNumJumps * sizeof(JumpInfo));
  1675. }
  1676. else m_aJumps = NULL;
  1677. }
  1678. CEmbeddingInfo::~CEmbeddingInfo()
  1679. {
  1680. delete [] m_aJumps;
  1681. }
  1682. bool CEmbeddingInfo::IsEmpty() const
  1683. {
  1684. return (m_EmbeddedObjPropName.GetNumElements() == 0);
  1685. }
  1686. bool CEmbeddingInfo::SetPropertyNameButLast(const CPropertyName& Name)
  1687. {
  1688. try
  1689. {
  1690. m_EmbeddedObjPropName.Empty();
  1691. for(int i = 0; i < Name.GetNumElements() - 1; i++)
  1692. {
  1693. m_EmbeddedObjPropName.AddElement(Name.GetStringAt(i));
  1694. }
  1695. return true;
  1696. }
  1697. catch (CX_MemoryException)
  1698. {
  1699. return false;
  1700. }
  1701. }
  1702. int CEmbeddingInfo::ComparePrecedence(const CEmbeddingInfo* pOther)
  1703. {
  1704. if (pOther)
  1705. {
  1706. int nCompare = m_EmbeddedObjPropName.GetNumElements() -
  1707. pOther->m_EmbeddedObjPropName.GetNumElements();
  1708. if(nCompare) return nCompare;
  1709. for(int i = 0; i < m_EmbeddedObjPropName.GetNumElements(); i++)
  1710. {
  1711. nCompare = wbem_wcsicmp(m_EmbeddedObjPropName.GetStringAt(i),
  1712. pOther->m_EmbeddedObjPropName.GetStringAt(i));
  1713. if(nCompare) return nCompare;
  1714. }
  1715. }
  1716. return 0;
  1717. }
  1718. BOOL CEmbeddingInfo::operator==(const CEmbeddingInfo& Other)
  1719. {
  1720. if(m_lStartingObjIndex != Other.m_lStartingObjIndex)
  1721. return FALSE;
  1722. if(m_lNumJumps != Other.m_lNumJumps)
  1723. return FALSE;
  1724. if(m_aJumps == NULL)
  1725. {
  1726. if(Other.m_aJumps == NULL)
  1727. return TRUE;
  1728. else
  1729. return FALSE;
  1730. }
  1731. else
  1732. {
  1733. if(Other.m_aJumps == NULL)
  1734. return FALSE;
  1735. else
  1736. return (memcmp(m_aJumps, Other.m_aJumps,
  1737. m_lNumJumps * sizeof(JumpInfo)) == 0);
  1738. }
  1739. }
  1740. HRESULT CEmbeddingInfo::Compile( CContextMetaData* pNamespace,
  1741. CImplicationList& Implications,
  1742. _IWmiObject** ppResultClass )
  1743. {
  1744. HRESULT hres;
  1745. long lFirstUnknownProp;
  1746. _IWmiObject* pContainerClass;
  1747. hres = Implications.FindBestComputedContainer( &m_EmbeddedObjPropName,
  1748. &lFirstUnknownProp,
  1749. &m_lStartingObjIndex,
  1750. &pContainerClass );
  1751. if(FAILED(hres))
  1752. return hres;
  1753. int nNumEmbeddedJumps = m_EmbeddedObjPropName.GetNumElements();
  1754. if(lFirstUnknownProp < nNumEmbeddedJumps)
  1755. {
  1756. // Not everything is already loaded
  1757. // ================================
  1758. delete [] m_aJumps;
  1759. m_lNumJumps = nNumEmbeddedJumps - lFirstUnknownProp;
  1760. m_aJumps = new JumpInfo[m_lNumJumps];
  1761. if (!m_aJumps)
  1762. return WBEM_E_OUT_OF_MEMORY;
  1763. JumpInfo* pji = NULL;
  1764. for(int i = lFirstUnknownProp; i < nNumEmbeddedJumps; i++)
  1765. {
  1766. if(pContainerClass == NULL)
  1767. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  1768. // Get the handle of this property
  1769. // ===============================
  1770. CIMTYPE ct;
  1771. pji = m_aJumps + i - lFirstUnknownProp;
  1772. pji->lTarget = -1;
  1773. hres = pContainerClass->GetPropertyHandleEx(
  1774. (LPWSTR)m_EmbeddedObjPropName.GetStringAt(i), 0L, &ct,
  1775. &pji->lJump );
  1776. if(FAILED(hres) || ct != CIM_OBJECT)
  1777. {
  1778. // Invalid. Return
  1779. pContainerClass->Release();
  1780. return WBEM_E_INVALID_PROPERTY;
  1781. }
  1782. //
  1783. // Check if the implications know anything about the class name
  1784. // for this property
  1785. //
  1786. _IWmiObject* pNewContainerClass = NULL;
  1787. hres = Implications.FindClassForProp(&m_EmbeddedObjPropName,
  1788. i+1, &pNewContainerClass);
  1789. if(FAILED(hres))
  1790. {
  1791. //
  1792. // Nothing implied --- have to go with the CIMTYPE qualifier
  1793. //
  1794. //
  1795. // Get CIMTYPE qualifier
  1796. //
  1797. CVar vCimtype;
  1798. DWORD dwSize;
  1799. hres = pContainerClass->GetPropQual(
  1800. (LPWSTR)m_EmbeddedObjPropName.GetStringAt(i),
  1801. L"CIMTYPE", 0, 0, NULL, NULL, &dwSize, NULL);
  1802. if(hres != WBEM_E_BUFFER_TOO_SMALL)
  1803. return WBEM_E_INVALID_PROPERTY;
  1804. LPWSTR wszCimType = (LPWSTR)new BYTE[dwSize];
  1805. if(wszCimType == NULL)
  1806. return WBEM_E_OUT_OF_MEMORY;
  1807. CVectorDeleteMe<BYTE> vdm((BYTE*)wszCimType);
  1808. CIMTYPE ctQualType;
  1809. hres = pContainerClass->GetPropQual(
  1810. (LPWSTR)m_EmbeddedObjPropName.GetStringAt(i),
  1811. L"CIMTYPE", 0, dwSize, &ctQualType, NULL, &dwSize,
  1812. wszCimType);
  1813. if(FAILED(hres) || ctQualType != CIM_STRING)
  1814. return WBEM_E_INVALID_PROPERTY;
  1815. //
  1816. // Figure out what it references, if available
  1817. //
  1818. WCHAR* pwc = wcschr(wszCimType, L':');
  1819. if(pwc)
  1820. {
  1821. // Information about the class is available
  1822. // ========================================
  1823. hres = pNamespace->GetClass(pwc+1, &pNewContainerClass);
  1824. if(FAILED(hres))
  1825. {
  1826. return WBEM_E_INVALID_CIM_TYPE;
  1827. }
  1828. }
  1829. }
  1830. pContainerClass->Release();
  1831. pContainerClass = pNewContainerClass;
  1832. }
  1833. // Get a location for the result and store in the last jump info elem
  1834. // ==================================================================
  1835. Implications.AddComputation( m_EmbeddedObjPropName,
  1836. pContainerClass,
  1837. &pji->lTarget );
  1838. }
  1839. else
  1840. {
  1841. // Everything is covered
  1842. // =====================
  1843. delete [] m_aJumps;
  1844. m_aJumps = NULL;
  1845. m_lNumJumps = 0;
  1846. }
  1847. if(ppResultClass)
  1848. {
  1849. *ppResultClass = pContainerClass;
  1850. }
  1851. else
  1852. {
  1853. if(pContainerClass)
  1854. pContainerClass->Release();
  1855. }
  1856. return WBEM_S_NO_ERROR;
  1857. }
  1858. HRESULT CEmbeddingInfo::GetContainerObject( CObjectInfo& ObjInfo,
  1859. INTERNAL _IWmiObject** ppInst)
  1860. {
  1861. if( m_lNumJumps == 0 )
  1862. {
  1863. *ppInst = ObjInfo.GetObjectAt(m_lStartingObjIndex);
  1864. return WBEM_S_NO_ERROR;
  1865. }
  1866. _IWmiObject* pCurrent = ObjInfo.GetObjectAt(m_lStartingObjIndex);
  1867. pCurrent->AddRef();
  1868. for(int i = 0; i < m_lNumJumps; i++)
  1869. {
  1870. _IWmiObject* pNew = NULL;
  1871. HRESULT hres = pCurrent->GetPropAddrByHandle( m_aJumps[i].lJump, 0, NULL, ( void** )&pNew );
  1872. if( FAILED( hres ) )
  1873. {
  1874. return hres;
  1875. }
  1876. pCurrent->Release();
  1877. pCurrent = pNew;
  1878. if(pNew == NULL)
  1879. {
  1880. *ppInst = pCurrent;
  1881. return WBEM_S_FALSE;
  1882. }
  1883. //
  1884. // save the object if required.
  1885. //
  1886. if ( m_aJumps[i].lTarget != -1 )
  1887. {
  1888. ObjInfo.SetObjectAt( m_aJumps[i].lTarget, pCurrent );
  1889. }
  1890. }
  1891. *ppInst = pCurrent;
  1892. return WBEM_S_NO_ERROR;
  1893. }
  1894. bool CEmbeddingInfo::AreJumpsRelated(const CEmbeddingInfo* pInfo)
  1895. {
  1896. if ( !pInfo )
  1897. {
  1898. return false;
  1899. }
  1900. //
  1901. // look through the targets of the info and see if we depend on any.
  1902. //
  1903. for( int i=0; i < pInfo->m_lNumJumps; i++ )
  1904. {
  1905. if ( pInfo->m_aJumps[i].lTarget == m_lStartingObjIndex )
  1906. {
  1907. return true;
  1908. }
  1909. }
  1910. return false;
  1911. }
  1912. bool CEmbeddingInfo::MixInJumps(const CEmbeddingInfo* pInfo)
  1913. {
  1914. //
  1915. // Assumes AreJumpsRelated() has been called and returned TRUE.
  1916. //
  1917. m_lStartingObjIndex = pInfo->m_lStartingObjIndex;
  1918. JumpInfo* aNewJumps = new JumpInfo[m_lNumJumps + pInfo->m_lNumJumps];
  1919. if(aNewJumps == NULL)
  1920. return false;
  1921. if( pInfo->m_lNumJumps > 0 )
  1922. {
  1923. memcpy( aNewJumps,
  1924. pInfo->m_aJumps,
  1925. sizeof(JumpInfo)*(pInfo->m_lNumJumps) );
  1926. }
  1927. if( m_lNumJumps > 0 )
  1928. {
  1929. memcpy( aNewJumps + pInfo->m_lNumJumps,
  1930. m_aJumps,
  1931. sizeof(JumpInfo)*m_lNumJumps );
  1932. }
  1933. m_lNumJumps += pInfo->m_lNumJumps;
  1934. delete [] m_aJumps;
  1935. m_aJumps = aNewJumps;
  1936. return true;
  1937. }
  1938. void CEmbeddingInfo::Dump(FILE* f)
  1939. {
  1940. fprintf(f, "Name=");
  1941. int i;
  1942. for(i = 0; i < m_EmbeddedObjPropName.GetNumElements(); i++)
  1943. {
  1944. if(i != 0)
  1945. fprintf(f, ".");
  1946. fprintf(f, "%S", m_EmbeddedObjPropName.GetStringAt(i));
  1947. }
  1948. fprintf(f, ", Alg=%d -> (", m_lStartingObjIndex);
  1949. for(i = 0; i < m_lNumJumps; i++)
  1950. {
  1951. if(i != 0)
  1952. fprintf(f, ", ");
  1953. fprintf(f, "0x%x : %d", m_aJumps[i].lJump, m_aJumps[i].lTarget );
  1954. }
  1955. fprintf(f, ")");
  1956. }
  1957. //******************************************************************************
  1958. //******************************************************************************
  1959. // BRANCHING NODE
  1960. //******************************************************************************
  1961. //******************************************************************************
  1962. CNodeWithImplications::CNodeWithImplications(const CNodeWithImplications& Other)
  1963. : CEvalNode(Other), m_pExtraImplications(NULL)
  1964. {
  1965. if(Other.m_pExtraImplications)
  1966. {
  1967. m_pExtraImplications =
  1968. new CImplicationList(*Other.m_pExtraImplications, false); // no link
  1969. if(m_pExtraImplications == NULL)
  1970. throw CX_MemoryException();
  1971. }
  1972. }
  1973. void CNodeWithImplications::Dump(FILE* f, int nOffset)
  1974. {
  1975. if(m_pExtraImplications)
  1976. m_pExtraImplications->Dump(f, nOffset);
  1977. }
  1978. CBranchingNode::CBranchingNode()
  1979. : CNodeWithImplications(), m_pNullBranch(NULL), m_pInfo(NULL)
  1980. {
  1981. m_pNullBranch = CValueNode::GetStandardFalse();
  1982. }
  1983. CBranchingNode::CBranchingNode(const CBranchingNode& Other, BOOL bChildren)
  1984. : CNodeWithImplications(Other), m_pInfo(NULL)
  1985. {
  1986. if (Other.m_pInfo)
  1987. {
  1988. m_pInfo = new CEmbeddingInfo(*(Other.m_pInfo));
  1989. if(m_pInfo == NULL)
  1990. throw CX_MemoryException();
  1991. }
  1992. int i;
  1993. if(bChildren)
  1994. {
  1995. m_pNullBranch = (CBranchingNode*)CloneNode(Other.m_pNullBranch);
  1996. if(m_pNullBranch == NULL && Other.m_pNullBranch != NULL)
  1997. throw CX_MemoryException();
  1998. for(i = 0; i < Other.m_apBranches.GetSize(); i++)
  1999. {
  2000. CBranchingNode* pNewBranch =
  2001. (CBranchingNode*)CloneNode(Other.m_apBranches[i]);
  2002. if(pNewBranch == NULL && Other.m_apBranches[i] != NULL)
  2003. throw CX_MemoryException();
  2004. if(m_apBranches.Add(pNewBranch) < 0)
  2005. throw CX_MemoryException();
  2006. }
  2007. }
  2008. else
  2009. {
  2010. m_pNullBranch = CValueNode::GetStandardFalse();
  2011. }
  2012. }
  2013. /* virtual */ int CBranchingNode::GetType()
  2014. {
  2015. return EVAL_NODE_TYPE_BRANCH;
  2016. }
  2017. CBranchingNode::~CBranchingNode()
  2018. {
  2019. delete m_pNullBranch;
  2020. delete m_pInfo;
  2021. }
  2022. bool CBranchingNode::MixInJumps( const CEmbeddingInfo* pJump )
  2023. {
  2024. bool bRet;
  2025. if ( !pJump )
  2026. {
  2027. return true;
  2028. }
  2029. //
  2030. // we want to find the first node in the tree that is related to the
  2031. // ancestor embedding info. If this node is related, then we mix in the
  2032. // jumps and return. If not, then we propagate the info down the tree.
  2033. //
  2034. if ( m_pInfo )
  2035. {
  2036. if ( m_pInfo->AreJumpsRelated( pJump ) )
  2037. {
  2038. return m_pInfo->MixInJumps( pJump );
  2039. }
  2040. }
  2041. for(int i = 0; i < m_apBranches.GetSize(); i++)
  2042. {
  2043. if ( CEvalNode::GetType(m_apBranches[i]) == EVAL_NODE_TYPE_BRANCH )
  2044. {
  2045. if ( !((CBranchingNode*)m_apBranches[i])->MixInJumps( pJump ) )
  2046. {
  2047. return false;
  2048. }
  2049. }
  2050. }
  2051. return true;
  2052. }
  2053. bool CBranchingNode::SetEmbeddedObjPropName(CPropertyName& Name)
  2054. {
  2055. try
  2056. {
  2057. if (!m_pInfo)
  2058. {
  2059. m_pInfo = new CEmbeddingInfo;
  2060. if(m_pInfo == NULL)
  2061. return false;
  2062. }
  2063. m_pInfo->SetEmbeddedObjPropName(Name);
  2064. return true;
  2065. }
  2066. catch (CX_MemoryException)
  2067. {
  2068. return false;
  2069. }
  2070. }
  2071. void CBranchingNode::SetNullBranch(CEvalNode* pBranch)
  2072. {
  2073. delete m_pNullBranch;
  2074. m_pNullBranch = pBranch;
  2075. }
  2076. DELETE_ME CBranchIterator* CBranchingNode::GetBranchIterator()
  2077. {
  2078. return new CDefaultBranchIterator(this);
  2079. }
  2080. int CBranchingNode::ComparePrecedence(CBranchingNode* pArg1,
  2081. CBranchingNode* pArg2)
  2082. {
  2083. int nCompare;
  2084. nCompare = pArg1->GetSubType() - pArg2->GetSubType();
  2085. if(nCompare) return nCompare;
  2086. // Compare embedding specs
  2087. // =======================
  2088. if (pArg1->m_pInfo && pArg2->m_pInfo)
  2089. {
  2090. nCompare = pArg1->m_pInfo->ComparePrecedence(pArg2->m_pInfo);
  2091. if(nCompare) return nCompare;
  2092. }
  2093. else if (pArg2->m_pInfo)
  2094. return -1;
  2095. else if (pArg1->m_pInfo)
  2096. return 1;
  2097. // Embedding are the same --- compare lower levels
  2098. // ===============================================
  2099. return pArg1->ComparePrecedence(pArg2);
  2100. }
  2101. DWORD CBranchingNode::ApplyPredicate(CLeafPredicate* pPred)
  2102. {
  2103. DWORD dwRes;
  2104. for(int i = 0; i < m_apBranches.GetSize(); i++)
  2105. {
  2106. if(m_apBranches[i] == NULL)
  2107. dwRes = (*pPred)(NULL);
  2108. else
  2109. dwRes = m_apBranches[i]->ApplyPredicate(pPred);
  2110. if(dwRes & WBEM_DISPOSITION_FLAG_DELETE)
  2111. {
  2112. m_apBranches.SetAt(i, NULL);
  2113. dwRes &= ~WBEM_DISPOSITION_FLAG_DELETE;
  2114. }
  2115. if(dwRes & WBEM_DISPOSITION_FLAG_INVALIDATE)
  2116. {
  2117. m_apBranches.SetAt(i, CValueNode::GetStandardInvalid());
  2118. dwRes &= ~WBEM_DISPOSITION_FLAG_INVALIDATE;
  2119. }
  2120. if(dwRes == WBEM_DISPOSITION_STOPLEVEL)
  2121. return WBEM_DISPOSITION_NORMAL;
  2122. if(dwRes == WBEM_DISPOSITION_STOPALL)
  2123. return dwRes;
  2124. }
  2125. if(m_pNullBranch)
  2126. dwRes = m_pNullBranch->ApplyPredicate(pPred);
  2127. else
  2128. dwRes = (*pPred)(NULL);
  2129. if(dwRes & WBEM_DISPOSITION_FLAG_DELETE)
  2130. {
  2131. delete m_pNullBranch;
  2132. m_pNullBranch = NULL;
  2133. dwRes &= ~WBEM_DISPOSITION_FLAG_DELETE;
  2134. }
  2135. if(dwRes & WBEM_DISPOSITION_FLAG_INVALIDATE)
  2136. {
  2137. delete m_pNullBranch;
  2138. m_pNullBranch = CValueNode::GetStandardInvalid();
  2139. dwRes &= ~WBEM_DISPOSITION_FLAG_INVALIDATE;
  2140. }
  2141. if(dwRes == WBEM_DISPOSITION_STOPALL)
  2142. return dwRes;
  2143. return WBEM_DISPOSITION_NORMAL;
  2144. }
  2145. HRESULT CBranchingNode::Project(CContextMetaData* pMeta,
  2146. CImplicationList& Implications,
  2147. CProjectionFilter* pFilter, EProjectionType eType,
  2148. bool bDeleteThis, CEvalNode** ppNewNode)
  2149. {
  2150. HRESULT hres;
  2151. try
  2152. {
  2153. //
  2154. // Record what we learn by even getting here
  2155. //
  2156. CImplicationList TheseImplications(Implications);
  2157. if(GetExtraImplications())
  2158. {
  2159. hres = TheseImplications.MergeIn(GetExtraImplications());
  2160. if(FAILED(hres))
  2161. return hres;
  2162. }
  2163. // BUGBUG: we could be more efficient and not clone the node when
  2164. // bDeleteThis is not specified.
  2165. CBranchingNode* pNew;
  2166. if(bDeleteThis)
  2167. {
  2168. pNew = this;
  2169. }
  2170. else
  2171. {
  2172. pNew = (CBranchingNode*)Clone();
  2173. if(pNew == NULL)
  2174. return WBEM_E_OUT_OF_MEMORY;
  2175. }
  2176. // BUGBUG: it is not always necessary to project all children. Could be
  2177. // more efficient, but can't find the perfect algorithm...
  2178. //
  2179. // Project all our children
  2180. //
  2181. CBranchIterator* pit = pNew->GetBranchIterator();
  2182. if(pit == NULL)
  2183. return WBEM_E_OUT_OF_MEMORY;
  2184. CDeleteMe<CBranchIterator> dm(pit);
  2185. while(pit->IsValid())
  2186. {
  2187. if(CEvalNode::IsInvalid(pit->GetNode()))
  2188. continue;
  2189. CImplicationList BranchImplications(TheseImplications);
  2190. pit->RecordBranch(pMeta, BranchImplications);
  2191. CEvalNode* pNewBranch;
  2192. hres = CEvalTree::Project(pMeta, BranchImplications,
  2193. pit->GetNode(), pFilter, eType,
  2194. true, &pNewBranch);
  2195. if(FAILED(hres))
  2196. return hres;
  2197. pit->SetNode(pNewBranch); // old one already deleted
  2198. pit->Advance();
  2199. }
  2200. //
  2201. // Determine if this is an "in" node for this filter
  2202. //
  2203. bool bIn = pFilter->IsInSet(this);
  2204. if(bIn)
  2205. {
  2206. //
  2207. // For nodes martching the filter that's it --- both necessary and
  2208. // sufficient conditions are simply projections of what's below
  2209. //
  2210. *ppNewNode = pNew;
  2211. }
  2212. else
  2213. {
  2214. //
  2215. // The node does not match the filter. Now is when the difference
  2216. // between sufficient and necessary conditions applies
  2217. //
  2218. int nBranchOp;
  2219. if(eType == e_Sufficient)
  2220. {
  2221. //
  2222. // For a condition to be sufficient for the truth of the entire
  2223. // node, it should appear in every single branch of the node.
  2224. // Therefore, we must AND all the branches together. Except for
  2225. // invalid ones --- they can't happen, so we can omit them from
  2226. // the analysis
  2227. //
  2228. nBranchOp = EVAL_OP_AND;
  2229. }
  2230. else if(eType == e_Necessary)
  2231. {
  2232. //
  2233. // For a condition to be necessary for this node, it has to
  2234. // appear in at least one branch. Therefore, we must OR all
  2235. // the branches together. Except for invalid ones.
  2236. //
  2237. nBranchOp = EVAL_OP_OR;
  2238. }
  2239. else
  2240. return WBEM_E_INVALID_PARAMETER;
  2241. //
  2242. // Perform the needed operation on them all
  2243. //
  2244. CBranchIterator* pitInner = pNew->GetBranchIterator();
  2245. if(pitInner == NULL)
  2246. return WBEM_E_OUT_OF_MEMORY;
  2247. CDeleteMe<CBranchIterator> dm(pitInner);
  2248. //
  2249. // Merge all of the, in, one at a time, deleting them as we go.
  2250. // It is safe to delete them always, since we cloned the entire node
  2251. // in the beginning if deletion was not allowed.
  2252. //
  2253. CEvalNode* pCombination = NULL;
  2254. bool bInited = false;
  2255. while(pitInner->IsValid())
  2256. {
  2257. if(CEvalNode::IsInvalid(pitInner->GetNode()))
  2258. continue;
  2259. if(bInited)
  2260. {
  2261. hres = CEvalTree::Combine(pCombination, pitInner->GetNode(),
  2262. nBranchOp,
  2263. pMeta, Implications,
  2264. true, true, &pCombination);
  2265. if(FAILED(hres))
  2266. return hres;
  2267. }
  2268. else
  2269. {
  2270. pCombination = pitInner->GetNode();
  2271. bInited = true;
  2272. }
  2273. pitInner->SetNode(NULL);
  2274. pitInner->Advance();
  2275. }
  2276. if(!bInited)
  2277. {
  2278. //
  2279. // No valid nodes??
  2280. //
  2281. pCombination = CValueNode::GetStandardInvalid();
  2282. }
  2283. //
  2284. // The combination is it.
  2285. //
  2286. *ppNewNode = pCombination;
  2287. delete pNew;
  2288. }
  2289. }
  2290. catch (CX_MemoryException)
  2291. {
  2292. return WBEM_E_OUT_OF_MEMORY;
  2293. }
  2294. return S_OK;
  2295. }
  2296. int CBranchingNode::Compare(CEvalNode* pRawOther)
  2297. {
  2298. CBranchingNode* pOther = (CBranchingNode*)pRawOther;
  2299. int nCompare;
  2300. nCompare = GetSubType() - pOther->GetSubType();
  2301. if(nCompare) return nCompare;
  2302. // First, compare embeddings
  2303. // =========================
  2304. if(m_pInfo == NULL && pOther->m_pInfo != NULL)
  2305. return -1;
  2306. if(m_pInfo != NULL && pOther->m_pInfo == NULL)
  2307. return 1;
  2308. if(m_pInfo != NULL && pOther->m_pInfo != NULL)
  2309. {
  2310. nCompare = m_pInfo->ComparePrecedence(pOther->m_pInfo);
  2311. if(nCompare)
  2312. return nCompare;
  2313. }
  2314. if(m_apBranches.GetSize() != pOther->m_apBranches.GetSize())
  2315. return m_apBranches.GetSize() - pOther->m_apBranches.GetSize();
  2316. // Then, compare derived portions
  2317. // ==============================
  2318. nCompare = SubCompare(pOther);
  2319. if(nCompare)
  2320. return nCompare;
  2321. // Finally, compare children
  2322. // =========================
  2323. for(int i = 0; i < m_apBranches.GetSize(); i++)
  2324. {
  2325. nCompare = CEvalTree::Compare(m_apBranches[i], pOther->m_apBranches[i]);
  2326. if(nCompare)
  2327. return nCompare;
  2328. }
  2329. return 0;
  2330. }
  2331. HRESULT CBranchingNode::CombineWith(CEvalNode* pRawArg2, int nOp,
  2332. CContextMetaData* pNamespace,
  2333. CImplicationList& Implications,
  2334. bool bDeleteThis, bool bDeleteArg2,
  2335. CEvalNode** ppRes)
  2336. {
  2337. CBranchingNode* pArg2 = (CBranchingNode*)pRawArg2;
  2338. HRESULT hres;
  2339. // Compare arguments for precedence
  2340. // ================================
  2341. int nCompare = ComparePrecedence(this, pArg2);
  2342. if(nCompare < 0)
  2343. {
  2344. // Put pArg1 first and continue
  2345. // ============================
  2346. hres = CombineInOrderWith(pArg2, nOp,
  2347. pNamespace, Implications, bDeleteThis, bDeleteArg2, ppRes);
  2348. }
  2349. else if(nCompare > 0)
  2350. {
  2351. // Put pArg2 first and continue (reverse delete indicators!!)
  2352. // ==========================================================
  2353. hres = pArg2->CombineInOrderWith(this, FlipEvalOp(nOp),
  2354. pNamespace, Implications, bDeleteArg2, bDeleteThis, ppRes);
  2355. }
  2356. else
  2357. {
  2358. // They are about the same property. Combine lookup lists.
  2359. // =======================================================
  2360. hres = CombineBranchesWith(pArg2, nOp, pNamespace, Implications,
  2361. bDeleteThis, bDeleteArg2, ppRes);
  2362. }
  2363. return hres;
  2364. }
  2365. HRESULT CBranchingNode::CombineInOrderWith(CEvalNode* pArg2,
  2366. int nOp, CContextMetaData* pNamespace,
  2367. CImplicationList& OrigImplications,
  2368. bool bDeleteThis, bool bDeleteArg2,
  2369. CEvalNode** ppRes)
  2370. {
  2371. HRESULT hres;
  2372. CBranchingNode* pNew = NULL;
  2373. if(bDeleteThis)
  2374. {
  2375. pNew = this;
  2376. }
  2377. else
  2378. {
  2379. //
  2380. // I'd like to clone self here, but can't because there is no
  2381. // such virtual method. Something to be improved, perhaps
  2382. //
  2383. pNew = (CBranchingNode*)Clone();
  2384. if(pNew == NULL)
  2385. return WBEM_E_OUT_OF_MEMORY;
  2386. }
  2387. try
  2388. {
  2389. CImplicationList Implications(OrigImplications);
  2390. hres = pNew->AdjustCompile(pNamespace, Implications);
  2391. if(FAILED(hres))
  2392. return hres;
  2393. //
  2394. // Maintain a counter telling us whether any invalid branches (that
  2395. // cannot occur under these implications) were detected. If so, we
  2396. // need to re-optimize this node
  2397. //
  2398. bool bInvalidBranchesDetected = false;
  2399. for(int i = 0; i < m_apBranches.GetSize(); i++)
  2400. {
  2401. CEvalNode* pNewBranch = NULL;
  2402. CImplicationList BranchImplications(Implications);
  2403. hres = RecordBranch(pNamespace, BranchImplications, i);
  2404. if(SUCCEEDED(hres))
  2405. {
  2406. // Always delete the branch --- if bDeleteThis, we should, and
  2407. // if not, we cloned it!
  2408. hres = CEvalTree::Combine(pNew->m_apBranches[i], pArg2, nOp,
  2409. pNamespace, BranchImplications, true, false, &pNewBranch);
  2410. if(FAILED(hres))
  2411. {
  2412. delete pNew;
  2413. return hres;
  2414. }
  2415. pNew->m_apBranches.Discard(i);
  2416. }
  2417. else
  2418. {
  2419. pNewBranch = CValueNode::GetStandardInvalid();
  2420. bInvalidBranchesDetected = true;
  2421. }
  2422. pNew->m_apBranches.SetAt(i, pNewBranch);
  2423. }
  2424. CEvalNode* pNewBranch = NULL;
  2425. CImplicationList BranchImplications(Implications);
  2426. hres = RecordBranch(pNamespace, BranchImplications, -1);
  2427. if(SUCCEEDED(hres))
  2428. {
  2429. //
  2430. // Always delete the branch --- if bDeleteThis, we should, and
  2431. // if not, we cloned it!
  2432. //
  2433. hres = CEvalTree::Combine(pNew->GetNullBranch(), pArg2, nOp,
  2434. pNamespace, BranchImplications, true, false, &pNewBranch);
  2435. if(FAILED(hres))
  2436. {
  2437. delete pNew;
  2438. return hres;
  2439. }
  2440. pNew->m_pNullBranch = NULL;
  2441. }
  2442. else
  2443. {
  2444. pNewBranch = CValueNode::GetStandardInvalid();
  2445. bInvalidBranchesDetected = true;
  2446. }
  2447. pNew->SetNullBranch(pNewBranch);
  2448. if(bDeleteArg2)
  2449. delete pArg2;
  2450. //
  2451. // If invalid branches were cut, re-optimize
  2452. //
  2453. if(bInvalidBranchesDetected)
  2454. {
  2455. HRESULT hr = pNew->Optimize(pNamespace, ppRes);
  2456. if (*ppRes != pNew)
  2457. delete pNew;
  2458. return hr;
  2459. }
  2460. else
  2461. {
  2462. *ppRes = pNew;
  2463. return WBEM_S_NO_ERROR;
  2464. }
  2465. }
  2466. catch (CX_MemoryException)
  2467. {
  2468. return WBEM_E_OUT_OF_MEMORY;
  2469. }
  2470. }
  2471. BOOL CBranchingNode::AreAllSame(CEvalNode** apNodes, int nSize,
  2472. int* pnFoundIndex)
  2473. {
  2474. BOOL bFoundTwo = FALSE;
  2475. *pnFoundIndex = -1;
  2476. CEvalNode* pFound = NULL;
  2477. for(int i = 0; i < nSize; i++)
  2478. {
  2479. // ignore invalid nodes --- they don't count
  2480. if(CEvalNode::IsInvalid(apNodes[i]))
  2481. continue;
  2482. if(*pnFoundIndex == -1)
  2483. {
  2484. //
  2485. // This is the first valid chils this node has. Record it --- it
  2486. // might be the only one
  2487. //
  2488. *pnFoundIndex = i;
  2489. pFound = apNodes[i];
  2490. }
  2491. else if(CEvalTree::Compare(apNodes[i], pFound) != 0)
  2492. {
  2493. bFoundTwo = TRUE;
  2494. break;
  2495. }
  2496. }
  2497. return !bFoundTwo;
  2498. }
  2499. HRESULT CBranchingNode::StoreBranchImplications(CContextMetaData* pNamespace,
  2500. int nBranchIndex, CEvalNode* pResult)
  2501. {
  2502. if(pResult)
  2503. {
  2504. CImplicationList* pBranchImplications = NULL;
  2505. try
  2506. {
  2507. pBranchImplications = new CImplicationList;
  2508. if(pBranchImplications == NULL)
  2509. return WBEM_E_OUT_OF_MEMORY;
  2510. }
  2511. catch (CX_MemoryException)
  2512. {
  2513. return WBEM_E_OUT_OF_MEMORY;
  2514. }
  2515. HRESULT hres = RecordBranch(pNamespace, *pBranchImplications,
  2516. nBranchIndex);
  2517. if(FAILED(hres))
  2518. {
  2519. delete pBranchImplications;
  2520. return hres;
  2521. }
  2522. if(pBranchImplications->IsEmpty())
  2523. {
  2524. // Nothing useful to say!
  2525. delete pBranchImplications;
  2526. pBranchImplications = NULL;
  2527. }
  2528. pResult->SetExtraImplications(pBranchImplications); // acquires
  2529. }
  2530. return WBEM_S_NO_ERROR;
  2531. }
  2532. HRESULT CBranchingNode::Optimize(CContextMetaData* pNamespace,
  2533. CEvalNode** ppNew)
  2534. {
  2535. int i;
  2536. HRESULT hres;
  2537. // Optimize all branches
  2538. // =====================
  2539. for(i = 0; i < m_apBranches.GetSize(); i++)
  2540. {
  2541. if(m_apBranches[i])
  2542. {
  2543. CEvalNode* pNew = NULL;
  2544. m_apBranches[i]->Optimize(pNamespace, &pNew);
  2545. if(pNew != m_apBranches[i])
  2546. {
  2547. m_apBranches.SetAt(i, pNew);
  2548. }
  2549. }
  2550. }
  2551. if(CEvalNode::GetType(m_pNullBranch) == EVAL_NODE_TYPE_BRANCH)
  2552. {
  2553. CEvalNode* pNew;
  2554. ((CBranchingNode*)m_pNullBranch)->Optimize(pNamespace, &pNew);
  2555. if(pNew != m_pNullBranch)
  2556. {
  2557. SetNullBranch(pNew);
  2558. }
  2559. }
  2560. // Self-optimize
  2561. // =============
  2562. OptimizeSelf();
  2563. // Count the number of branches
  2564. // ============================
  2565. int nFoundIndex = -1;
  2566. BOOL bFoundTwo = !AreAllSame(m_apBranches.GetArrayPtr(),
  2567. m_apBranches.GetSize(), &nFoundIndex);
  2568. if(bFoundTwo)
  2569. {
  2570. *ppNew = this;
  2571. return WBEM_S_NO_ERROR;
  2572. }
  2573. if(nFoundIndex == -1)
  2574. {
  2575. if(CEvalNode::IsInvalid(m_pNullBranch))
  2576. {
  2577. //
  2578. // Totally invalid, the whole lot
  2579. //
  2580. *ppNew = m_pNullBranch;
  2581. m_pNullBranch = NULL;
  2582. }
  2583. else
  2584. {
  2585. //
  2586. // There are no valid branches, except for the NullBranch.
  2587. // We can replace ourselves with the NullBranch
  2588. //
  2589. *ppNew = m_pNullBranch;
  2590. m_pNullBranch = NULL;
  2591. //
  2592. // Now, we need to copy
  2593. // the branch implications into the "extras". This is because
  2594. // the information about which branch was taken in this test is
  2595. // critical to the compilation of the lower nodes --- it tells them
  2596. // about the classes of some of our embedded objects.
  2597. //
  2598. hres = StoreBranchImplications(pNamespace, -1, *ppNew);
  2599. if(FAILED(hres))
  2600. return hres;
  2601. //
  2602. // since this node is going away, mix in the embedding info it
  2603. // has with the child node.
  2604. //
  2605. if ( CEvalNode::GetType(*ppNew) == EVAL_NODE_TYPE_BRANCH )
  2606. {
  2607. CBranchingNode* pBranchNode = (CBranchingNode*)*ppNew;
  2608. if(!pBranchNode->MixInJumps( m_pInfo ))
  2609. return WBEM_E_OUT_OF_MEMORY;
  2610. }
  2611. }
  2612. }
  2613. else
  2614. {
  2615. //
  2616. // There is one valid branch in the regular list. Two hopes: that the
  2617. // NullBranch is invalid, or that it is the same as the only valid
  2618. // branch in the regular list
  2619. //
  2620. if(CEvalNode::IsInvalid(m_pNullBranch) ||
  2621. CEvalTree::Compare(m_pNullBranch, m_apBranches[nFoundIndex]) == 0)
  2622. {
  2623. //
  2624. // Hurray. We could replace ourselves with the remaining branch.
  2625. //
  2626. m_apBranches.SetAt(nFoundIndex, NULL, ppNew);
  2627. //
  2628. // Now, we need to copy
  2629. // the branch implications into the "extras". This is because
  2630. // the information about which branch was taken in this test is
  2631. // critical to the compilation of the lower nodes --- it tells them
  2632. // about the classes of some of our embedded objects.
  2633. //
  2634. hres = StoreBranchImplications(pNamespace, nFoundIndex, *ppNew);
  2635. if(FAILED(hres))
  2636. return hres;
  2637. //
  2638. // since this node is going away, mix in the embedding info it
  2639. // has with the child node.
  2640. //
  2641. if ( CEvalNode::GetType(*ppNew) == EVAL_NODE_TYPE_BRANCH )
  2642. {
  2643. CBranchingNode* pBranchNode = (CBranchingNode*)*ppNew;
  2644. if(!pBranchNode->MixInJumps( m_pInfo ))
  2645. return WBEM_E_OUT_OF_MEMORY;
  2646. }
  2647. }
  2648. else
  2649. {
  2650. *ppNew = this;
  2651. }
  2652. return WBEM_S_NO_ERROR;
  2653. }
  2654. return WBEM_S_NO_ERROR;
  2655. }
  2656. void CBranchingNode::Dump(FILE* f, int nOffset)
  2657. {
  2658. CNodeWithImplications::Dump(f, nOffset);
  2659. if (m_pInfo)
  2660. {
  2661. PrintOffset(f, nOffset);
  2662. fprintf(f, "Embedding: ");
  2663. m_pInfo->Dump(f);
  2664. fprintf(f, "\n");
  2665. }
  2666. }
  2667. //******************************************************************************
  2668. //******************************************************************************
  2669. // PROPERTY NODE
  2670. //******************************************************************************
  2671. //******************************************************************************
  2672. bool CPropertyNode::SetPropertyInfo(LPCWSTR wszPropName, long lPropHandle)
  2673. {
  2674. m_lPropHandle = lPropHandle;
  2675. try
  2676. {
  2677. m_wsPropName = wszPropName;
  2678. }
  2679. catch (CX_MemoryException)
  2680. {
  2681. return false;
  2682. }
  2683. return true;
  2684. }
  2685. int CPropertyNode::ComparePrecedence(CBranchingNode* pOther)
  2686. {
  2687. CPropertyNode* pOtherNode = (CPropertyNode*)pOther;
  2688. return m_lPropHandle - pOtherNode->m_lPropHandle;
  2689. }
  2690. bool CPropertyNode::SetEmbeddingInfo(const CEmbeddingInfo* pInfo)
  2691. {
  2692. try
  2693. {
  2694. if ((pInfo == NULL) || (pInfo->IsEmpty()))
  2695. {
  2696. delete m_pInfo;
  2697. m_pInfo = NULL;
  2698. }
  2699. else if (!m_pInfo)
  2700. {
  2701. m_pInfo = new CEmbeddingInfo(*pInfo);
  2702. if(m_pInfo == NULL)
  2703. return false;
  2704. }
  2705. else
  2706. *m_pInfo = *pInfo;
  2707. }
  2708. catch (CX_MemoryException)
  2709. {
  2710. return false;
  2711. }
  2712. return true;
  2713. }
  2714. HRESULT CPropertyNode::SetNullTest(int nOperator)
  2715. {
  2716. if(nOperator == QL1_OPERATOR_EQUALS)
  2717. {
  2718. if(m_apBranches.Add(CValueNode::GetStandardFalse()) < 0)
  2719. return WBEM_E_OUT_OF_MEMORY;
  2720. CEvalNode* pTrue = CValueNode::GetStandardTrue();
  2721. if(pTrue == NULL)
  2722. return WBEM_E_OUT_OF_MEMORY;
  2723. SetNullBranch(pTrue);
  2724. }
  2725. else if(nOperator == QL1_OPERATOR_NOTEQUALS)
  2726. {
  2727. CEvalNode* pTrue = CValueNode::GetStandardTrue();
  2728. if(pTrue == NULL)
  2729. return WBEM_E_OUT_OF_MEMORY;
  2730. if(m_apBranches.Add(pTrue) < 0)
  2731. {
  2732. delete pTrue;
  2733. return WBEM_E_OUT_OF_MEMORY;
  2734. }
  2735. SetNullBranch(CValueNode::GetStandardFalse());
  2736. }
  2737. else
  2738. return WBEM_E_INVALID_QUERY;
  2739. return WBEM_S_NO_ERROR;
  2740. }
  2741. HRESULT CPropertyNode::SetOperator(int nOperator)
  2742. {
  2743. m_apBranches.RemoveAll();
  2744. #define GET_STD_TRUE CValueNode::GetStandardTrue()
  2745. #define GET_STD_FALSE CValueNode::GetStandardFalse()
  2746. #define ADD_STD_TRUE {CEvalNode* p = GET_STD_TRUE; \
  2747. if(p == NULL) return WBEM_E_OUT_OF_MEMORY; \
  2748. if(m_apBranches.Add(p) < 0) {delete p; return WBEM_E_OUT_OF_MEMORY;}}
  2749. #define ADD_STD_FALSE {CEvalNode* p = GET_STD_FALSE; \
  2750. if(m_apBranches.Add(p) < 0) {delete p; return WBEM_E_OUT_OF_MEMORY;}}
  2751. switch(nOperator)
  2752. {
  2753. case QL1_OPERATOR_EQUALS:
  2754. ADD_STD_FALSE;
  2755. ADD_STD_TRUE;
  2756. ADD_STD_FALSE;
  2757. break;
  2758. case QL1_OPERATOR_NOTEQUALS:
  2759. ADD_STD_TRUE;
  2760. ADD_STD_FALSE;
  2761. ADD_STD_TRUE;
  2762. break;
  2763. case QL1_OPERATOR_LESS:
  2764. ADD_STD_TRUE;
  2765. ADD_STD_FALSE;
  2766. ADD_STD_FALSE;
  2767. break;
  2768. case QL1_OPERATOR_GREATER:
  2769. ADD_STD_FALSE;
  2770. ADD_STD_FALSE;
  2771. ADD_STD_TRUE;
  2772. break;
  2773. case QL1_OPERATOR_LESSOREQUALS:
  2774. ADD_STD_TRUE;
  2775. ADD_STD_TRUE;
  2776. ADD_STD_FALSE;
  2777. break;
  2778. case QL1_OPERATOR_GREATEROREQUALS:
  2779. ADD_STD_FALSE;
  2780. ADD_STD_TRUE;
  2781. ADD_STD_TRUE;
  2782. break;
  2783. case QL1_OPERATOR_LIKE:
  2784. ADD_STD_TRUE;
  2785. ADD_STD_FALSE;
  2786. break;
  2787. case QL1_OPERATOR_UNLIKE:
  2788. ADD_STD_FALSE;
  2789. ADD_STD_TRUE;
  2790. break;
  2791. default:
  2792. return WBEM_E_CRITICAL_ERROR;
  2793. }
  2794. return WBEM_S_NO_ERROR;
  2795. }
  2796. //******************************************************************************
  2797. //******************************************************************************
  2798. // STRING PROPERTY NODE
  2799. //******************************************************************************
  2800. //******************************************************************************
  2801. CStringPropNode::CStringPropNode(const CStringPropNode& Other, BOOL bChildren)
  2802. : CFullCompareNode<CInternalString>(Other, bChildren)
  2803. {
  2804. }
  2805. CStringPropNode::~CStringPropNode()
  2806. {
  2807. }
  2808. HRESULT CStringPropNode::Evaluate(CObjectInfo& ObjInfo,
  2809. INTERNAL CEvalNode** ppNext)
  2810. {
  2811. *ppNext = NULL;
  2812. HRESULT hres;
  2813. _IWmiObject* pObj;
  2814. hres = GetContainerObject(ObjInfo, &pObj);
  2815. if( S_OK != hres )
  2816. {
  2817. return hres;
  2818. }
  2819. // Get the property from the object
  2820. // ================================
  2821. CCompressedString* pcs = CoreGetPropertyString(pObj, m_lPropHandle);
  2822. CInternalString is;
  2823. if(pcs == NULL)
  2824. {
  2825. *ppNext = m_pNullBranch;
  2826. return WBEM_S_NO_ERROR;
  2827. }
  2828. is.AcquireCompressedString(pcs);
  2829. // Search for the value
  2830. // ====================
  2831. TTestPointIterator it;
  2832. bool bMatch = m_aTestPoints.Find(is, &it);
  2833. if(bMatch)
  2834. *ppNext = it->m_pAt;
  2835. else if(it == m_aTestPoints.End())
  2836. *ppNext = m_pRightMost;
  2837. else
  2838. *ppNext = it->m_pLeftOf;
  2839. is.Unbind();
  2840. return WBEM_S_NO_ERROR;
  2841. }
  2842. void CStringPropNode::Dump(FILE* f, int nOffset)
  2843. {
  2844. CBranchingNode::Dump(f, nOffset);
  2845. PrintOffset(f, nOffset);
  2846. fprintf(f, "LastPropName = (0x%x)\n", m_lPropHandle);
  2847. for(TConstTestPointIterator it = m_aTestPoints.Begin();
  2848. it != m_aTestPoints.End(); it++)
  2849. {
  2850. PrintOffset(f, nOffset);
  2851. if (it != m_aTestPoints.Begin())
  2852. {
  2853. TConstTestPointIterator itPrev(it);
  2854. itPrev--;
  2855. fprintf(f, "%s < ", itPrev->m_Test.GetText());
  2856. }
  2857. fprintf(f, "X < %s\n", it->m_Test.GetText());
  2858. DumpNode(f, nOffset +1, it->m_pLeftOf);
  2859. PrintOffset(f, nOffset);
  2860. fprintf(f, "X = %s\n", it->m_Test.GetText());
  2861. DumpNode(f, nOffset +1, it->m_pAt);
  2862. }
  2863. PrintOffset(f, nOffset);
  2864. if (it != m_aTestPoints.Begin())
  2865. {
  2866. TConstTestPointIterator itPrev(it);
  2867. itPrev--;
  2868. fprintf(f, "X > %s\n", itPrev->m_Test.GetText());
  2869. }
  2870. else
  2871. fprintf(f, "ANY\n");
  2872. DumpNode(f, nOffset+1, m_pRightMost);
  2873. PrintOffset(f, nOffset);
  2874. fprintf(f, "NULL->\n");
  2875. DumpNode(f, nOffset+1, m_pNullBranch);
  2876. }
  2877. /*****************************************************************************
  2878. CLikeStringPropNode
  2879. ******************************************************************************/
  2880. CLikeStringPropNode::CLikeStringPropNode( const CLikeStringPropNode& Other,
  2881. BOOL bChildren )
  2882. : CPropertyNode( Other, bChildren )
  2883. {
  2884. m_Like = Other.m_Like;
  2885. }
  2886. int CLikeStringPropNode::ComparePrecedence( CBranchingNode* pRawOther )
  2887. {
  2888. int nCompare = CPropertyNode::ComparePrecedence( pRawOther );
  2889. if( nCompare )
  2890. {
  2891. return nCompare;
  2892. }
  2893. CLikeStringPropNode* pOther = (CLikeStringPropNode*)pRawOther;
  2894. return _wcsicmp( m_Like.GetExpression(), pOther->m_Like.GetExpression() );
  2895. }
  2896. int CLikeStringPropNode::SubCompare( CEvalNode* pRawOther )
  2897. {
  2898. int nCompare;
  2899. CLikeStringPropNode* pOther = (CLikeStringPropNode*)pRawOther;
  2900. _DBG_ASSERT( m_apBranches.GetSize() == 2 );
  2901. _DBG_ASSERT( pOther->m_apBranches.GetSize() == 2 );
  2902. nCompare = CEvalTree::Compare( m_apBranches[0], pOther->m_apBranches[0] );
  2903. if ( nCompare )
  2904. {
  2905. return nCompare;
  2906. }
  2907. nCompare = CEvalTree::Compare( m_apBranches[1], pOther->m_apBranches[1] );
  2908. if ( nCompare )
  2909. {
  2910. return nCompare;
  2911. }
  2912. return CEvalTree::Compare( m_pNullBranch, pOther->m_pNullBranch );
  2913. }
  2914. HRESULT CLikeStringPropNode::Evaluate( CObjectInfo& ObjInfo,
  2915. CEvalNode** ppNext )
  2916. {
  2917. *ppNext = NULL;
  2918. HRESULT hr;
  2919. //
  2920. // get the string value.
  2921. //
  2922. _IWmiObject* pObj;
  2923. hr = GetContainerObject( ObjInfo, &pObj );
  2924. if( S_OK != hr )
  2925. {
  2926. return hr;
  2927. }
  2928. CCompressedString* pcs = CoreGetPropertyString( pObj, m_lPropHandle );
  2929. //
  2930. // if null, then simply take null branch.
  2931. //
  2932. if( pcs == NULL )
  2933. {
  2934. *ppNext = m_pNullBranch;
  2935. return WBEM_S_NO_ERROR;
  2936. }
  2937. CInternalString is;
  2938. is.AcquireCompressedString(pcs);
  2939. WString ws = is;
  2940. //
  2941. // run through like filter. take branch accordingly.
  2942. //
  2943. if ( m_Like.Match( ws ) )
  2944. {
  2945. *ppNext = m_apBranches[0];
  2946. }
  2947. else
  2948. {
  2949. *ppNext = m_apBranches[1];
  2950. }
  2951. is.Unbind();
  2952. return WBEM_S_NO_ERROR;
  2953. }
  2954. HRESULT CLikeStringPropNode::SetTest( VARIANT& v )
  2955. {
  2956. if ( V_VT(&v) != VT_BSTR )
  2957. {
  2958. return WBEM_E_TYPE_MISMATCH;
  2959. }
  2960. try
  2961. {
  2962. m_Like.SetExpression( V_BSTR(&v) );
  2963. }
  2964. catch(CX_MemoryException)
  2965. {
  2966. return WBEM_E_OUT_OF_MEMORY;
  2967. }
  2968. return WBEM_S_NO_ERROR;
  2969. }
  2970. HRESULT CLikeStringPropNode::CombineBranchesWith(
  2971. CBranchingNode* pRawArg2,
  2972. int nOp,
  2973. CContextMetaData* pNamespace,
  2974. CImplicationList& Implications,
  2975. bool bDeleteThis,
  2976. bool bDeleteArg2,
  2977. CEvalNode** ppRes )
  2978. {
  2979. HRESULT hres;
  2980. *ppRes = NULL;
  2981. CLikeStringPropNode* pArg2 = (CLikeStringPropNode*)pRawArg2;
  2982. if ( !bDeleteThis )
  2983. {
  2984. return ((CLikeStringPropNode*)Clone())->CombineBranchesWith(
  2985. pRawArg2, nOp, pNamespace, Implications, true, // reuse clone!
  2986. bDeleteArg2, ppRes );
  2987. }
  2988. CEvalNode* pNew = NULL;
  2989. //
  2990. // merge the 'match' branches
  2991. //
  2992. hres = CEvalTree::Combine( m_apBranches[0], pArg2->m_apBranches[0], nOp,
  2993. pNamespace, Implications, true, bDeleteArg2,
  2994. &pNew );
  2995. if(FAILED(hres))
  2996. return hres;
  2997. m_apBranches.Discard( 0 );
  2998. m_apBranches.SetAt( 0, pNew );
  2999. if( bDeleteArg2 )
  3000. {
  3001. pArg2->m_apBranches.Discard( 0 );
  3002. }
  3003. //
  3004. // merge the 'nomatch' branches
  3005. //
  3006. hres = CEvalTree::Combine( m_apBranches[1], pArg2->m_apBranches[1], nOp,
  3007. pNamespace, Implications, true, bDeleteArg2,
  3008. &pNew );
  3009. if(FAILED(hres))
  3010. return hres;
  3011. m_apBranches.Discard( 1 );
  3012. m_apBranches.SetAt( 1, pNew );
  3013. if( bDeleteArg2 )
  3014. {
  3015. pArg2->m_apBranches.Discard( 1 );
  3016. }
  3017. //
  3018. // merge the 'null' branches
  3019. //
  3020. hres = CEvalTree::Combine( m_pNullBranch, pArg2->m_pNullBranch, nOp,
  3021. pNamespace, Implications, true, bDeleteArg2,
  3022. &pNew );
  3023. if(FAILED(hres))
  3024. return hres;
  3025. m_pNullBranch = pNew;
  3026. if( bDeleteArg2 )
  3027. pArg2->m_pNullBranch = NULL;
  3028. //
  3029. // Delete what needs deleting
  3030. //
  3031. if(bDeleteArg2)
  3032. delete pArg2;
  3033. *ppRes = this;
  3034. return WBEM_S_NO_ERROR;
  3035. }
  3036. HRESULT CLikeStringPropNode::OptimizeSelf()
  3037. {
  3038. _DBG_ASSERT( m_apBranches.GetSize() == 2 );
  3039. return WBEM_S_NO_ERROR;
  3040. }
  3041. void CLikeStringPropNode::Dump(FILE* f, int nOffset)
  3042. {
  3043. CBranchingNode::Dump(f, nOffset);
  3044. PrintOffset(f, nOffset);
  3045. fprintf(f, "LastPropName = (0x%x)\n", m_lPropHandle);
  3046. PrintOffset( f, nOffset );
  3047. fprintf(f, "Like Expression : %S\n", m_Like.GetExpression() );
  3048. PrintOffset( f, nOffset );
  3049. fprintf(f, "Match : \n" );
  3050. DumpNode(f, nOffset+1, m_apBranches[0] );
  3051. PrintOffset( f, nOffset );
  3052. fprintf(f, "NoMatch : \n" );
  3053. DumpNode(f, nOffset+1, m_apBranches[1] );
  3054. PrintOffset( f, nOffset );
  3055. fprintf(f, "NULL : \n" );
  3056. DumpNode(f, nOffset+1, m_pNullBranch );
  3057. }
  3058. //******************************************************************************
  3059. //******************************************************************************
  3060. // INHERITANCE NODE
  3061. //******************************************************************************
  3062. //******************************************************************************
  3063. CInheritanceNode::CInheritanceNode()
  3064. : m_lDerivationIndex(-1),
  3065. m_lNumPoints(0), m_apcsTestPoints(NULL)
  3066. {
  3067. // Add a none-of-the-above node
  3068. // ============================
  3069. m_apBranches.Add(CValueNode::GetStandardFalse());
  3070. }
  3071. CInheritanceNode::CInheritanceNode(const CInheritanceNode& Other,
  3072. BOOL bChildren)
  3073. : CBranchingNode(Other, bChildren),
  3074. m_lDerivationIndex(Other.m_lDerivationIndex)
  3075. {
  3076. m_lNumPoints = Other.m_lNumPoints;
  3077. m_apcsTestPoints = new CCompressedString*[m_lNumPoints];
  3078. if(m_apcsTestPoints == NULL)
  3079. throw CX_MemoryException();
  3080. for(int i = 0; i < m_lNumPoints; i++)
  3081. {
  3082. m_apcsTestPoints[i] = (CCompressedString*)
  3083. _new BYTE[Other.m_apcsTestPoints[i]->GetLength()];
  3084. if(m_apcsTestPoints[i] == NULL)
  3085. throw CX_MemoryException();
  3086. memcpy((void*)m_apcsTestPoints[i],
  3087. (void*)Other.m_apcsTestPoints[i],
  3088. Other.m_apcsTestPoints[i]->GetLength());
  3089. }
  3090. }
  3091. /* virtual */ long CInheritanceNode::GetSubType()
  3092. {
  3093. return EVAL_NODE_TYPE_INHERITANCE;
  3094. }
  3095. CInheritanceNode::~CInheritanceNode()
  3096. {
  3097. RemoveAllTestPoints();
  3098. }
  3099. void CInheritanceNode::RemoveAllTestPoints()
  3100. {
  3101. for(int i = 0; i < m_lNumPoints; i++)
  3102. {
  3103. delete [] (BYTE*)m_apcsTestPoints[i];
  3104. }
  3105. delete [] m_apcsTestPoints;
  3106. m_apcsTestPoints = NULL;
  3107. }
  3108. bool CInheritanceNode::SetPropertyInfo(CContextMetaData* pNamespace,
  3109. CPropertyName& PropName)
  3110. {
  3111. return SetEmbeddedObjPropName(PropName);
  3112. }
  3113. HRESULT CInheritanceNode::AddClass(CContextMetaData* pNamespace,
  3114. LPCWSTR wszClassName, CEvalNode* pDestination)
  3115. {
  3116. HRESULT hres;
  3117. // Get the class from the namespace
  3118. // ================================
  3119. _IWmiObject* pObj = NULL;
  3120. hres = pNamespace->GetClass(wszClassName, &pObj);
  3121. if(FAILED(hres))
  3122. return hres;
  3123. hres = AddClass(pNamespace, wszClassName, pObj, pDestination);
  3124. pObj->Release();
  3125. return hres;
  3126. }
  3127. HRESULT CInheritanceNode::AddClass(CContextMetaData* pNamespace,
  3128. LPCWSTR wszClassName, _IWmiObject* pClass,
  3129. CEvalNode* pDestination)
  3130. {
  3131. // Get the number of items in its derivation --- that's the index where we
  3132. // need to look for its name in its children
  3133. // =======================================================================
  3134. ULONG lDerivationIndex;
  3135. HRESULT hRes = CoreGetNumParents(pClass, &lDerivationIndex);
  3136. if (FAILED (hRes))
  3137. return hRes;
  3138. if(m_lDerivationIndex == -1)
  3139. {
  3140. // We don't have a currently set derivation index --- this is the first
  3141. // ====================================================================
  3142. m_lDerivationIndex = lDerivationIndex;
  3143. }
  3144. else if(m_lDerivationIndex != lDerivationIndex)
  3145. {
  3146. // Can't add this class --- derivation index mismatch
  3147. // ==================================================
  3148. return WBEM_E_FAILED;
  3149. }
  3150. // Allocate a compressed string
  3151. // ============================
  3152. int nLength = CCompressedString::ComputeNecessarySpace(wszClassName);
  3153. CCompressedString* pcs = (CCompressedString*)new BYTE[nLength];
  3154. if (pcs)
  3155. pcs->SetFromUnicode(wszClassName);
  3156. else
  3157. return WBEM_E_OUT_OF_MEMORY;
  3158. // Extend the lists by one
  3159. // =======================
  3160. CCompressedString** apcsNewTestPoints =
  3161. new CCompressedString*[m_lNumPoints+1];
  3162. if (!apcsNewTestPoints)
  3163. return WBEM_E_OUT_OF_MEMORY;
  3164. // Insert it into the list of tests and the list of branches
  3165. // =========================================================
  3166. int i = 0;
  3167. while(i < m_lNumPoints && pcs->CheapCompare(*m_apcsTestPoints[i]) > 0)
  3168. {
  3169. apcsNewTestPoints[i] = m_apcsTestPoints[i];
  3170. i++;
  3171. }
  3172. apcsNewTestPoints[i] = pcs;
  3173. m_apBranches.InsertAt(i+1, pDestination);
  3174. while(i < m_lNumPoints)
  3175. {
  3176. apcsNewTestPoints[i+1] = m_apcsTestPoints[i];
  3177. }
  3178. // Set the new list
  3179. // ================
  3180. delete [] m_apcsTestPoints;
  3181. m_apcsTestPoints = apcsNewTestPoints;
  3182. m_lNumPoints++;
  3183. return WBEM_S_NO_ERROR;
  3184. }
  3185. HRESULT CInheritanceNode::RecordBranch(CContextMetaData* pNamespace,
  3186. CImplicationList& Implications, long lBranchIndex)
  3187. {
  3188. HRESULT hres = WBEM_S_NO_ERROR;
  3189. if(lBranchIndex == -1)
  3190. {
  3191. // Recording NULL branch
  3192. // =====================
  3193. hres = Implications.ImproveKnownNull(GetEmbeddedObjPropName());
  3194. }
  3195. else if(lBranchIndex == 0)
  3196. {
  3197. // Recording none of the above branch
  3198. // ==================================
  3199. for(int i = 0; i < m_lNumPoints; i++)
  3200. {
  3201. LPWSTR wszClassName = NULL;
  3202. try
  3203. {
  3204. wszClassName =
  3205. m_apcsTestPoints[i]->CreateWStringCopy().UnbindPtr();
  3206. }
  3207. catch (CX_MemoryException)
  3208. {
  3209. return WBEM_E_OUT_OF_MEMORY;
  3210. }
  3211. if(wszClassName == NULL)
  3212. return WBEM_E_OUT_OF_MEMORY;
  3213. CVectorDeleteMe<WCHAR> vdm(wszClassName);
  3214. hres = Implications.ImproveKnownNot(GetEmbeddedObjPropName(),
  3215. wszClassName);
  3216. if(FAILED(hres))
  3217. {
  3218. // Contradicts known information --- fail recording
  3219. // ================================================
  3220. return hres;
  3221. }
  3222. }
  3223. }
  3224. else
  3225. {
  3226. // Normal branch --- record the class
  3227. // ==================================
  3228. BSTR strClassName = m_apcsTestPoints[lBranchIndex - 1]->
  3229. CreateBSTRCopy();
  3230. _IWmiObject* pObj = NULL;
  3231. hres = pNamespace->GetClass(strClassName, &pObj);
  3232. SysFreeString(strClassName);
  3233. if(FAILED(hres))
  3234. return hres;
  3235. hres = Implications.ImproveKnown(GetEmbeddedObjPropName(), pObj);
  3236. pObj->Release();
  3237. }
  3238. return hres;
  3239. }
  3240. int CInheritanceNode::ComparePrecedence(CBranchingNode* pOther)
  3241. {
  3242. CInheritanceNode* pInhOther = (CInheritanceNode*)pOther;
  3243. return (m_lDerivationIndex - pInhOther->m_lDerivationIndex);
  3244. }
  3245. int CInheritanceNode::SubCompare(CEvalNode* pOther)
  3246. {
  3247. CInheritanceNode* pInhOther = (CInheritanceNode*)pOther;
  3248. int nCompare;
  3249. nCompare = m_lDerivationIndex - pInhOther->m_lDerivationIndex;
  3250. if(nCompare)
  3251. return nCompare;
  3252. nCompare = m_lNumPoints - pInhOther->m_lNumPoints;
  3253. if(nCompare)
  3254. return nCompare;
  3255. for(int i = 0; i < m_lNumPoints; i++)
  3256. {
  3257. nCompare = m_apcsTestPoints[i]->CompareNoCase(
  3258. *pInhOther->m_apcsTestPoints[i]);
  3259. if(nCompare)
  3260. return nCompare;
  3261. }
  3262. return 0;
  3263. }
  3264. void CInheritanceNode::RemoveTestPoint(int i)
  3265. {
  3266. delete [] m_apcsTestPoints[i];
  3267. memcpy((void*)(m_apcsTestPoints + i),
  3268. (void*)(m_apcsTestPoints + i + 1),
  3269. sizeof(CCompressedString*) * (m_lNumPoints - i - 1));
  3270. m_lNumPoints--;
  3271. }
  3272. HRESULT CInheritanceNode::OptimizeSelf()
  3273. {
  3274. for(int i = 0; i < m_lNumPoints; i++)
  3275. {
  3276. // Compare this branch to the "nothing" branch
  3277. // ===========================================
  3278. if(CEvalNode::IsInvalid(m_apBranches[i+1]) ||
  3279. CEvalTree::Compare(m_apBranches[0], m_apBranches[i+1]) == 0)
  3280. {
  3281. RemoveTestPoint(i);
  3282. m_apBranches.RemoveAt(i+1);
  3283. i--;
  3284. continue;
  3285. }
  3286. // Check if this node is another class check on the same object
  3287. // ============================================================
  3288. if(CEvalNode::GetType(m_apBranches[i+1]) != EVAL_NODE_TYPE_BRANCH)
  3289. continue;
  3290. CBranchingNode* pBranch = (CBranchingNode*)(m_apBranches[i+1]);
  3291. if(pBranch->GetSubType() == EVAL_NODE_TYPE_INHERITANCE &&
  3292. pBranch->GetEmbeddedObjPropName() == GetEmbeddedObjPropName())
  3293. {
  3294. // If the "none-of-the-above" branch of this child is the same
  3295. // as the "none-of-the-above" branch of ourselves, we can replace
  3296. // our "none-of-the-above" branch with this node, since anything
  3297. // that is falling under none-of-the-above now will fall under
  3298. // none-of-the-above of our child (otherwise there is an
  3299. // optimization flaw in the child).
  3300. // IMPORTANT: this will no longer be true if we change the
  3301. // precedence order of inheritance nodes!!!
  3302. if(CEvalTree::Compare(m_apBranches[0], pBranch->GetBranches()[0])
  3303. == 0)
  3304. {
  3305. m_apBranches.SetAt(0, pBranch);
  3306. m_apBranches.GetArrayPtr()[i+1] = NULL;
  3307. m_apBranches.RemoveAt(i+1);
  3308. RemoveTestPoint(i);
  3309. i--;
  3310. }
  3311. }
  3312. }
  3313. return S_OK;
  3314. }
  3315. HRESULT CInheritanceNode::Optimize(CContextMetaData* pNamespace,
  3316. CEvalNode** ppNew)
  3317. {
  3318. // Delegate to the normal branch optimization process
  3319. // ==================================================
  3320. *ppNew = NULL;
  3321. HRESULT hres = CBranchingNode::Optimize(pNamespace, ppNew);
  3322. if(FAILED(hres) || *ppNew != this)
  3323. return hres;
  3324. // Specific post-processing
  3325. // ========================
  3326. if(m_apBranches.GetSize() == 1)
  3327. {
  3328. // We are reduced to checking for NULL. If our non-NULL branch is
  3329. // talking about the same property, push the test there.
  3330. // ==============================================================
  3331. if (CEvalNode::GetType(m_apBranches[0]) != EVAL_NODE_TYPE_BRANCH)
  3332. return hres;
  3333. CBranchingNode* pBranch = (CBranchingNode*)(m_apBranches[0]);
  3334. if(pBranch && pBranch->GetSubType() == EVAL_NODE_TYPE_INHERITANCE &&
  3335. pBranch->GetEmbeddedObjPropName() == GetEmbeddedObjPropName())
  3336. {
  3337. pBranch->SetNullBranch(m_pNullBranch);
  3338. pBranch->Optimize(pNamespace, ppNew);
  3339. if(*ppNew != pBranch)
  3340. m_apBranches.RemoveAll();
  3341. else
  3342. m_apBranches.GetArrayPtr()[0] = NULL;
  3343. m_pNullBranch = NULL;
  3344. return S_OK;
  3345. }
  3346. }
  3347. return S_OK;
  3348. }
  3349. HRESULT CInheritanceNode::Evaluate(CObjectInfo& ObjInfo,
  3350. INTERNAL CEvalNode** ppNext)
  3351. {
  3352. _IWmiObject* pInst;
  3353. HRESULT hres = GetContainerObject(ObjInfo, &pInst);
  3354. if(FAILED(hres)) return hres;
  3355. if(pInst == NULL)
  3356. {
  3357. *ppNext = m_pNullBranch;
  3358. return WBEM_S_NO_ERROR;
  3359. }
  3360. // Get the parent at the right index
  3361. // =================================
  3362. CCompressedString* pcs;
  3363. ULONG lNumParents;
  3364. HRESULT hRes = CoreGetNumParents(pInst, &lNumParents);
  3365. if (FAILED(hRes))
  3366. return hRes;
  3367. if(lNumParents < m_lDerivationIndex)
  3368. {
  3369. if (m_apBranches.GetSize())
  3370. *ppNext = m_apBranches[0];
  3371. else
  3372. *ppNext = NULL;
  3373. return WBEM_S_NO_ERROR;
  3374. }
  3375. else if(lNumParents == m_lDerivationIndex)
  3376. {
  3377. pcs = CoreGetClassInternal(pInst);
  3378. }
  3379. else
  3380. {
  3381. pcs = CoreGetParentAtIndex(pInst, m_lDerivationIndex);
  3382. }
  3383. if(pcs == NULL)
  3384. {
  3385. //
  3386. // This class does not even have that long an ancestry --- clearly
  3387. // not derived from any of those
  3388. //
  3389. if (m_apBranches.GetSize())
  3390. *ppNext = m_apBranches[0];
  3391. else
  3392. *ppNext = NULL;
  3393. return WBEM_S_NO_ERROR;
  3394. }
  3395. // Search for the value
  3396. // ====================
  3397. long lLeft = -1;
  3398. long lRight = m_lNumPoints;
  3399. while(lRight > lLeft + 1)
  3400. {
  3401. long lMiddle = (lRight + lLeft) >> 1;
  3402. int nCompare = pcs->CheapCompare(*m_apcsTestPoints[lMiddle]);
  3403. if(nCompare < 0)
  3404. {
  3405. lRight = lMiddle;
  3406. }
  3407. else if(nCompare > 0)
  3408. {
  3409. lLeft = lMiddle;
  3410. }
  3411. else
  3412. {
  3413. *ppNext = m_apBranches[lMiddle+1];
  3414. return WBEM_S_NO_ERROR;
  3415. }
  3416. }
  3417. if (m_apBranches.GetSize())
  3418. *ppNext = m_apBranches[0];
  3419. else
  3420. *ppNext = NULL;
  3421. return WBEM_S_NO_ERROR;
  3422. }
  3423. HRESULT CInheritanceNode::Compile(CContextMetaData* pNamespace,
  3424. CImplicationList& Implications)
  3425. {
  3426. if (!m_pInfo)
  3427. {
  3428. m_pInfo = new CEmbeddingInfo;
  3429. if(m_pInfo == NULL)
  3430. return WBEM_E_OUT_OF_MEMORY;
  3431. }
  3432. HRESULT hres = CompileEmbeddingPortion(pNamespace, Implications, NULL);
  3433. return hres;
  3434. }
  3435. // Computes preliminary parameters for merging two inheritance nodes at the
  3436. // same level --- which children will be used, and how many times.
  3437. HRESULT CInheritanceNode::ComputeUsageForMerge(CInheritanceNode* pArg2,
  3438. CContextMetaData* pNamespace,
  3439. CImplicationList& OrigImplications,
  3440. bool bDeleteThis, bool bDeleteArg2,
  3441. DWORD* pdwFirstNoneCount,
  3442. DWORD* pdwSecondNoneCount,
  3443. bool* pbBothNonePossible)
  3444. {
  3445. HRESULT hres;
  3446. *pdwFirstNoneCount = 0;
  3447. *pdwSecondNoneCount = 0;
  3448. *pbBothNonePossible = false;
  3449. try
  3450. {
  3451. CImplicationList Implications(OrigImplications);
  3452. BOOL bFirstNonePossible, bSecondNonePossible;
  3453. CImplicationList NoneImplications(Implications);
  3454. hres = RecordBranch(pNamespace, NoneImplications, 0);
  3455. if(FAILED(hres))
  3456. {
  3457. bFirstNonePossible = FALSE;
  3458. bSecondNonePossible =
  3459. SUCCEEDED(pArg2->RecordBranch(pNamespace, NoneImplications, 0));
  3460. }
  3461. else
  3462. {
  3463. bFirstNonePossible = TRUE;
  3464. hres = pArg2->RecordBranch(pNamespace, NoneImplications, 0);
  3465. if(FAILED(hres))
  3466. {
  3467. // Check if the second one can survive in isolation
  3468. // ================================================
  3469. CImplicationList NoneImplications1(Implications);
  3470. bSecondNonePossible =
  3471. SUCCEEDED(pArg2->RecordBranch(pNamespace, NoneImplications1, 0));
  3472. }
  3473. else
  3474. {
  3475. bSecondNonePossible = TRUE;
  3476. }
  3477. }
  3478. if(bFirstNonePossible && bSecondNonePossible)
  3479. {
  3480. //
  3481. // Both of them will be used at least once: with each other!
  3482. //
  3483. *pdwFirstNoneCount = *pdwSecondNoneCount = 1;
  3484. *pbBothNonePossible = true;
  3485. }
  3486. //
  3487. // If we are not deleting something, the usage count should be infinite!
  3488. //
  3489. if(!bDeleteThis)
  3490. *pdwFirstNoneCount = 0xFFFFFFFF;
  3491. if(!bDeleteArg2)
  3492. *pdwSecondNoneCount = 0xFFFFFFFF;
  3493. //
  3494. // Merge lookup lists
  3495. //
  3496. long lFirstIndex = 0;
  3497. long lSecondIndex = 0;
  3498. while(lFirstIndex < m_lNumPoints || lSecondIndex < pArg2->m_lNumPoints)
  3499. {
  3500. //
  3501. // Retrieve the test points from both lists and compare them,
  3502. // taking care of boundary conditions
  3503. //
  3504. int nCompare;
  3505. CCompressedString* pcsFirstVal = NULL;
  3506. CCompressedString* pcsSecondVal = NULL;
  3507. if(lFirstIndex == m_lNumPoints)
  3508. {
  3509. nCompare = 1;
  3510. pcsSecondVal = pArg2->m_apcsTestPoints[lSecondIndex];
  3511. }
  3512. else if(lSecondIndex == pArg2->m_lNumPoints)
  3513. {
  3514. pcsFirstVal = m_apcsTestPoints[lFirstIndex];
  3515. nCompare = -1;
  3516. }
  3517. else
  3518. {
  3519. pcsFirstVal = m_apcsTestPoints[lFirstIndex];
  3520. pcsSecondVal = pArg2->m_apcsTestPoints[lSecondIndex];
  3521. nCompare = pcsFirstVal->CheapCompare(*pcsSecondVal);
  3522. }
  3523. if(nCompare < 0)
  3524. {
  3525. //
  3526. // At this index is the first value combined with second none
  3527. //
  3528. if(!bDeleteArg2) // not interesting
  3529. {
  3530. lFirstIndex++;
  3531. continue;
  3532. }
  3533. if(!bSecondNonePossible)
  3534. {
  3535. lFirstIndex++;
  3536. continue;
  3537. }
  3538. CImplicationList BranchImplications(Implications);
  3539. if(FAILED(RecordBranch(pNamespace, BranchImplications,
  3540. lFirstIndex+1)))
  3541. {
  3542. lFirstIndex++;
  3543. continue;
  3544. }
  3545. if(FAILED(pArg2->RecordBranch(pNamespace, BranchImplications, 0)))
  3546. {
  3547. lFirstIndex++;
  3548. continue;
  3549. }
  3550. (*pdwSecondNoneCount)++;
  3551. lFirstIndex++;
  3552. }
  3553. else if(nCompare > 0)
  3554. {
  3555. // At this index is the second value combined with first none
  3556. // ==========================================================
  3557. if(!bDeleteThis) // not interesting
  3558. {
  3559. lSecondIndex++;
  3560. continue;
  3561. }
  3562. if(!bFirstNonePossible)
  3563. {
  3564. lSecondIndex++;
  3565. continue;
  3566. }
  3567. CImplicationList BranchImplications(Implications);
  3568. if(FAILED(pArg2->RecordBranch(pNamespace, BranchImplications,
  3569. lSecondIndex+1)))
  3570. {
  3571. lSecondIndex++;
  3572. continue;
  3573. }
  3574. if(FAILED(RecordBranch(pNamespace, BranchImplications, 0)))
  3575. {
  3576. lSecondIndex++;
  3577. continue;
  3578. }
  3579. (*pdwFirstNoneCount)++;
  3580. lSecondIndex++;
  3581. }
  3582. else
  3583. {
  3584. // At this index is the combinations of the ats
  3585. // ============================================
  3586. lFirstIndex++;
  3587. lSecondIndex++;
  3588. }
  3589. }
  3590. }
  3591. catch (CX_MemoryException)
  3592. {
  3593. return WBEM_E_OUT_OF_MEMORY;
  3594. }
  3595. return S_OK;
  3596. }
  3597. HRESULT CInheritanceNode::CombineBranchesWith(CBranchingNode* pRawArg2, int nOp,
  3598. CContextMetaData* pNamespace,
  3599. CImplicationList& OrigImplications,
  3600. bool bDeleteThis, bool bDeleteArg2,
  3601. CEvalNode** ppRes)
  3602. {
  3603. HRESULT hres;
  3604. CInheritanceNode* pArg2 = (CInheritanceNode*)pRawArg2;
  3605. if(!bDeleteThis && bDeleteArg2)
  3606. {
  3607. // It is easier to combine in the other direction
  3608. // ==============================================
  3609. return pArg2->CombineBranchesWith(this, FlipEvalOp(nOp), pNamespace,
  3610. OrigImplications, bDeleteArg2, bDeleteThis, ppRes);
  3611. }
  3612. try
  3613. {
  3614. // Either clone or use our node
  3615. // ============================
  3616. CInheritanceNode* pNew = NULL;
  3617. if(bDeleteThis)
  3618. {
  3619. pNew = this;
  3620. }
  3621. else
  3622. {
  3623. // Clone this node without cloning the branches.
  3624. // =============================================
  3625. pNew = (CInheritanceNode*)CloneSelf();
  3626. if(pNew == NULL)
  3627. return WBEM_E_OUT_OF_MEMORY;
  3628. }
  3629. CImplicationList Implications(OrigImplications);
  3630. hres = pNew->AdjustCompile(pNamespace, Implications);
  3631. if(FAILED(hres))
  3632. return hres;
  3633. //
  3634. // Get overall information
  3635. //
  3636. DWORD dwFirstNoneCount, dwSecondNoneCount;
  3637. bool bBothNonePossible;
  3638. hres = ComputeUsageForMerge(pArg2, pNamespace, Implications,
  3639. bDeleteThis, bDeleteArg2,
  3640. &dwFirstNoneCount, &dwSecondNoneCount,
  3641. &bBothNonePossible);
  3642. if(FAILED(hres))
  3643. {
  3644. if(!bDeleteThis)
  3645. delete pNew;
  3646. return hres;
  3647. }
  3648. bool bFirstNonePossible = (dwFirstNoneCount > 0);
  3649. bool bSecondNonePossible = (dwSecondNoneCount > 0);
  3650. //
  3651. // Allocate a new array of test points and a new array of branches. We
  3652. // can't use the ones in pNew because we are using some of the
  3653. // elements in those arrays in this many times and don't want to trample
  3654. // them (since pNew and this might be the same). Therefore, we create
  3655. // and fill these arrays outside of the node and then place them into
  3656. // pNew when we are done.
  3657. //
  3658. // As we delete the child nodes in the Branches array, we will set them
  3659. // to NULL so that we can clear the branch array in the end
  3660. //
  3661. CCompressedString** apcsTestPoints =
  3662. new CCompressedString*[m_lNumPoints + pArg2->m_lNumPoints];
  3663. if(apcsTestPoints == NULL)
  3664. return WBEM_E_OUT_OF_MEMORY;
  3665. CUniquePointerArray<CEvalNode> apBranches;
  3666. //
  3667. // Merge none-of-the-above branches
  3668. //
  3669. if(bBothNonePossible)
  3670. {
  3671. //
  3672. // They have to be merged
  3673. //
  3674. CImplicationList NoneImplications(Implications);
  3675. hres = RecordBranch(pNamespace, NoneImplications, 0);
  3676. if(FAILED(hres))
  3677. return hres;
  3678. hres = pArg2->RecordBranch(pNamespace, NoneImplications, 0);
  3679. if(FAILED(hres))
  3680. return hres;
  3681. //
  3682. // We may delete our None nodes if and only if there predicted usage
  3683. // count (adjusted for usage that has already occurred) is dropping
  3684. // to 0 --- that is, noone will use these nodes further during this
  3685. // merge
  3686. //
  3687. CEvalNode* pNone = NULL;
  3688. bool bDeleteFirstBranch = (--dwFirstNoneCount == 0);
  3689. bool bDeleteSecondBranch = (--dwSecondNoneCount == 0);
  3690. CEvalTree::Combine(m_apBranches[0], pArg2->m_apBranches[0], nOp,
  3691. pNamespace, NoneImplications, bDeleteFirstBranch,
  3692. bDeleteSecondBranch, &pNone);
  3693. if(bDeleteSecondBranch)
  3694. pArg2->m_apBranches.Discard(0);
  3695. if(bDeleteFirstBranch)
  3696. m_apBranches.Discard(0);
  3697. if(apBranches.Add(pNone) < 0)
  3698. return WBEM_E_OUT_OF_MEMORY;
  3699. }
  3700. else
  3701. {
  3702. //
  3703. // Since both none is not possible, we set this branch to FALSE
  3704. //
  3705. if(apBranches.Add(NULL) < 0)
  3706. return WBEM_E_OUT_OF_MEMORY;
  3707. }
  3708. //
  3709. // Merge lookup lists
  3710. //
  3711. long lFirstIndex = 0;
  3712. long lSecondIndex = 0;
  3713. long lNewIndex = 0;
  3714. while(lFirstIndex < m_lNumPoints || lSecondIndex < pArg2->m_lNumPoints)
  3715. {
  3716. //
  3717. // Retrieve the test points from both lists and compare them,
  3718. // taking care of boundary conditions
  3719. //
  3720. int nCompare;
  3721. CCompressedString* pcsFirstVal = NULL;
  3722. CCompressedString* pcsSecondVal = NULL;
  3723. if(lFirstIndex == m_lNumPoints)
  3724. {
  3725. nCompare = 1;
  3726. pcsSecondVal = pArg2->m_apcsTestPoints[lSecondIndex];
  3727. }
  3728. else if(lSecondIndex == pArg2->m_lNumPoints)
  3729. {
  3730. pcsFirstVal = m_apcsTestPoints[lFirstIndex];
  3731. nCompare = -1;
  3732. }
  3733. else
  3734. {
  3735. pcsFirstVal = m_apcsTestPoints[lFirstIndex];
  3736. pcsSecondVal = pArg2->m_apcsTestPoints[lSecondIndex];
  3737. nCompare = pcsFirstVal->CheapCompare(*pcsSecondVal);
  3738. }
  3739. //
  3740. // Compute the branch to be added and its test point
  3741. //
  3742. CEvalNode* pNewBranch = NULL;
  3743. CCompressedString* pcsCurrentVal = NULL;
  3744. if(nCompare < 0)
  3745. {
  3746. //
  3747. // At this index is the first value combined with second none
  3748. //
  3749. if(!bSecondNonePossible)
  3750. {
  3751. lFirstIndex++;
  3752. continue;
  3753. }
  3754. CImplicationList BranchImplications(Implications);
  3755. if(FAILED(RecordBranch(pNamespace, BranchImplications,
  3756. lFirstIndex+1)))
  3757. {
  3758. lFirstIndex++;
  3759. continue;
  3760. }
  3761. pArg2->RecordBranch(pNamespace, BranchImplications, 0);
  3762. //
  3763. // We may delete our None nodes if and only if there predicted
  3764. // usage count (adjusted for usage that has already occurred) is
  3765. // dropping to 0 --- that is, noone will use these nodes further
  3766. // during this merge
  3767. //
  3768. bool bDeleteOtherBranch = (--dwSecondNoneCount == 0);
  3769. CEvalTree::Combine(m_apBranches[lFirstIndex+1],
  3770. pArg2->m_apBranches[0],
  3771. nOp, pNamespace, BranchImplications,
  3772. bDeleteThis, bDeleteOtherBranch,
  3773. &pNewBranch);
  3774. if(bDeleteOtherBranch)
  3775. pArg2->m_apBranches.Discard(0);
  3776. if(bDeleteThis)
  3777. m_apBranches.Discard(lFirstIndex+1);
  3778. pcsCurrentVal = pcsFirstVal;
  3779. lFirstIndex++;
  3780. }
  3781. else if(nCompare > 0)
  3782. {
  3783. // At this index is the second value combined with first none
  3784. // ==========================================================
  3785. if(!bFirstNonePossible)
  3786. {
  3787. lSecondIndex++;
  3788. continue;
  3789. }
  3790. CImplicationList BranchImplications(Implications);
  3791. if(FAILED(pArg2->RecordBranch(pNamespace, BranchImplications,
  3792. lSecondIndex+1)))
  3793. {
  3794. lSecondIndex++;
  3795. continue;
  3796. }
  3797. if(FAILED(RecordBranch(pNamespace, BranchImplications, 0)))
  3798. {
  3799. lSecondIndex++;
  3800. continue;
  3801. }
  3802. //
  3803. // We may delete our None nodes if and only if there predicted
  3804. // usage count (adjusted for usage that has already occurred) is
  3805. // dropping to 0 --- that is, noone will use these nodes further
  3806. // during this merge
  3807. //
  3808. bool bDeleteThisBranch = (--dwFirstNoneCount == 0);
  3809. CEvalTree::Combine(m_apBranches[0],
  3810. pArg2->m_apBranches[lSecondIndex+1],
  3811. nOp, pNamespace, BranchImplications,
  3812. bDeleteThisBranch, bDeleteArg2,
  3813. &pNewBranch);
  3814. if(bDeleteArg2)
  3815. pArg2->m_apBranches.Discard(lSecondIndex+1);
  3816. if(bDeleteThisBranch)
  3817. m_apBranches.Discard(0);
  3818. pcsCurrentVal = pcsSecondVal;
  3819. lSecondIndex++;
  3820. }
  3821. else
  3822. {
  3823. // At this index is the combinations of the ats
  3824. // ============================================
  3825. CImplicationList BranchImplications(Implications);
  3826. if(FAILED(RecordBranch(pNamespace, BranchImplications,
  3827. lFirstIndex+1)))
  3828. {
  3829. lSecondIndex++;
  3830. lFirstIndex++;
  3831. continue;
  3832. }
  3833. CEvalTree::Combine(m_apBranches[lFirstIndex+1],
  3834. pArg2->m_apBranches[lSecondIndex+1],
  3835. nOp, pNamespace, BranchImplications,
  3836. bDeleteThis, bDeleteArg2,
  3837. &pNewBranch);
  3838. if(bDeleteArg2)
  3839. pArg2->m_apBranches.Discard(lSecondIndex+1);
  3840. if(bDeleteThis)
  3841. m_apBranches.Discard(lFirstIndex+1);
  3842. pcsCurrentVal = pcsFirstVal; // doesn't matter --- same
  3843. lFirstIndex++;
  3844. lSecondIndex++;
  3845. }
  3846. //
  3847. // Add the newely constructed branch
  3848. //
  3849. if(apBranches.Add(pNewBranch) < 0)
  3850. return WBEM_E_OUT_OF_MEMORY;
  3851. //
  3852. // Add the newely constructed test point
  3853. //
  3854. apcsTestPoints[lNewIndex] =
  3855. (CCompressedString*)_new BYTE[pcsCurrentVal->GetLength()];
  3856. if(apcsTestPoints[lNewIndex] == NULL)
  3857. return WBEM_E_OUT_OF_MEMORY;
  3858. memcpy((void*)apcsTestPoints[lNewIndex],
  3859. (void*)pcsCurrentVal, pcsCurrentVal->GetLength());
  3860. lNewIndex++;
  3861. }
  3862. //
  3863. // Now that we are done with testing, place the test-point array into
  3864. // pNew
  3865. //
  3866. pNew->RemoveAllTestPoints();
  3867. pNew->m_apcsTestPoints = apcsTestPoints;
  3868. pNew->m_lNumPoints = lNewIndex;
  3869. //
  3870. // Replace the array of branches that we may have had (guaranteed to
  3871. // all be NULL, since we were NULLing them out as we went).
  3872. //
  3873. pNew->m_apBranches.RemoveAll();
  3874. for(int i = 0; i < apBranches.GetSize(); i++)
  3875. {
  3876. pNew->m_apBranches.Add(apBranches[i]);
  3877. apBranches.Discard(i);
  3878. }
  3879. //
  3880. // Merge the nulls
  3881. //
  3882. CImplicationList NullImplications(Implications);
  3883. hres = RecordBranch(pNamespace, Implications, -1);
  3884. if(SUCCEEDED(hres))
  3885. {
  3886. CEvalNode* pNewBranch = NULL;
  3887. hres = CEvalTree::Combine(m_pNullBranch, pArg2->m_pNullBranch, nOp,
  3888. pNamespace, NullImplications, bDeleteThis, bDeleteArg2,
  3889. &pNewBranch);
  3890. if(FAILED(hres))
  3891. return hres;
  3892. //
  3893. // Clear the old new branch, whatever it was, (it has been deleted,
  3894. // if it ever were there at all) and replace it with the new one.
  3895. //
  3896. pNew->m_pNullBranch = pNewBranch;
  3897. // Clear deleted branches
  3898. // ======================
  3899. if(bDeleteArg2)
  3900. pArg2->m_pNullBranch = NULL;
  3901. }
  3902. // Delete Arg2, if needed (reused portions have been nulled out)
  3903. // =============================================================
  3904. if(bDeleteArg2)
  3905. delete pArg2;
  3906. *ppRes = pNew;
  3907. return WBEM_S_NO_ERROR;
  3908. }
  3909. catch (CX_MemoryException)
  3910. {
  3911. return WBEM_E_OUT_OF_MEMORY;
  3912. }
  3913. }
  3914. HRESULT CInheritanceNode::Project(CContextMetaData* pMeta,
  3915. CImplicationList& Implications,
  3916. CProjectionFilter* pFilter,
  3917. EProjectionType eType, bool bDeleteThis,
  3918. CEvalNode** ppNewNode)
  3919. {
  3920. //
  3921. // There are two choices here: either it is about us, or we are not
  3922. // interested.
  3923. //
  3924. if(pFilter->IsInSet(this))
  3925. {
  3926. return CBranchingNode::Project(pMeta, Implications, pFilter, eType,
  3927. bDeleteThis, ppNewNode);
  3928. }
  3929. else
  3930. {
  3931. if(eType == e_Sufficient)
  3932. *ppNewNode = CValueNode::GetStandardFalse();
  3933. else
  3934. {
  3935. *ppNewNode = CValueNode::GetStandardTrue();
  3936. if(*ppNewNode == NULL)
  3937. return WBEM_E_OUT_OF_MEMORY;
  3938. }
  3939. if(bDeleteThis)
  3940. delete this;
  3941. return S_OK;
  3942. }
  3943. }
  3944. void CInheritanceNode::Dump(FILE* f, int nOffset)
  3945. {
  3946. CBranchingNode::Dump(f, nOffset);
  3947. PrintOffset(f, nOffset);
  3948. fprintf(f, "inheritance index %d: (0x%p)\n", m_lDerivationIndex, this);
  3949. for(int i = 0; i < m_lNumPoints; i++)
  3950. {
  3951. WString ws = m_apcsTestPoints[i]->CreateWStringCopy();
  3952. PrintOffset(f, nOffset);
  3953. fprintf(f, "%S->\n", (LPWSTR)ws);
  3954. DumpNode(f, nOffset+1, m_apBranches[i+1]);
  3955. }
  3956. PrintOffset(f, nOffset);
  3957. fprintf(f, "none of the above->\n");
  3958. DumpNode(f, nOffset+1, m_apBranches[0]);
  3959. PrintOffset(f, nOffset);
  3960. fprintf(f, "NULL->\n");
  3961. DumpNode(f, nOffset+1, m_pNullBranch);
  3962. }
  3963. #ifdef CHECK_TREES
  3964. void CBranchingNode::CheckNode(CTreeChecker *pCheck)
  3965. {
  3966. pCheck->CheckoffNode(this);
  3967. int nItems = m_apBranches.GetSize();
  3968. for (int i = 0; i < nItems; i++)
  3969. {
  3970. CEvalNode *pNode = m_apBranches[i];
  3971. if (pNode)
  3972. m_apBranches[i]->CheckNode(pCheck);
  3973. }
  3974. if (m_pNullBranch)
  3975. m_pNullBranch->CheckNode(pCheck);
  3976. }
  3977. #endif
  3978. //******************************************************************************
  3979. //******************************************************************************
  3980. //
  3981. // OR NODE
  3982. //
  3983. //******************************************************************************
  3984. //******************************************************************************
  3985. void COrNode::operator=(const COrNode& Other)
  3986. {
  3987. // Remove all our children
  3988. // =======================
  3989. m_apBranches.RemoveAll();
  3990. // Clone all the branches from the other
  3991. // =====================================
  3992. for(int i = 0; i < Other.m_apBranches.GetSize(); i++)
  3993. {
  3994. CEvalNode* pNewBranch = CloneNode(Other.m_apBranches[i]);
  3995. if(pNewBranch == NULL && Other.m_apBranches[i] != NULL)
  3996. throw CX_MemoryException();
  3997. if(m_apBranches.Add(pNewBranch) < 0)
  3998. throw CX_MemoryException();
  3999. }
  4000. }
  4001. HRESULT COrNode::CombineWith(CEvalNode* pArg2, int nOp,
  4002. CContextMetaData* pNamespace, CImplicationList& Implications,
  4003. bool bDeleteThis, bool bDeleteArg2,
  4004. CEvalNode** ppRes)
  4005. {
  4006. HRESULT hres;
  4007. *ppRes = NULL;
  4008. // We don't support AND combines on OR nodes
  4009. // =========================================
  4010. if(nOp == EVAL_OP_AND)
  4011. return WBEM_E_CRITICAL_ERROR;
  4012. // If the other is another OR node, delegate to the iterator
  4013. // =========================================================
  4014. if(CEvalNode::GetType(pArg2) == EVAL_NODE_TYPE_OR)
  4015. {
  4016. return CombineWithOrNode((COrNode*)pArg2, nOp, pNamespace, Implications,
  4017. bDeleteThis, bDeleteArg2, ppRes);
  4018. }
  4019. // Make a copy --- the new node will be mostly us
  4020. // ==============================================
  4021. COrNode* pNew = NULL;
  4022. if(!bDeleteThis)
  4023. {
  4024. pNew = (COrNode*)Clone();
  4025. if(pNew == NULL)
  4026. return WBEM_E_OUT_OF_MEMORY;
  4027. }
  4028. else
  4029. {
  4030. pNew = this;
  4031. }
  4032. *ppRes = pNew;
  4033. // Combining an OR node with a non-OR --- try all branches
  4034. // =======================================================
  4035. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4036. {
  4037. // Check if this branch is a good fit for the other node
  4038. // =====================================================
  4039. if(CEvalTree::IsMergeAdvisable(m_apBranches[i], pArg2, Implications) ==
  4040. WBEM_S_NO_ERROR)
  4041. {
  4042. // It is --- merge it in
  4043. // =====================
  4044. CEvalNode* pNewBranch = NULL;
  4045. hres = CEvalTree::Combine(m_apBranches[i], pArg2, nOp,
  4046. pNamespace, Implications,
  4047. bDeleteThis, bDeleteArg2, &pNewBranch);
  4048. if(FAILED(hres))
  4049. return hres;
  4050. if(bDeleteThis)
  4051. m_apBranches.Discard(i);
  4052. pNew->m_apBranches.SetAt(i, pNewBranch);
  4053. return WBEM_S_NO_ERROR;
  4054. }
  4055. }
  4056. // No branch was a good fit --- add the node to our list
  4057. // =====================================================
  4058. if(bDeleteArg2)
  4059. {
  4060. hres = pNew->AddBranch(pArg2);
  4061. }
  4062. else
  4063. {
  4064. CEvalNode* pNode = pArg2->Clone();
  4065. if(pNode == NULL)
  4066. return WBEM_E_OUT_OF_MEMORY;
  4067. hres = pNew->AddBranch(pNode);
  4068. }
  4069. if(FAILED(hres))
  4070. return hres;
  4071. return WBEM_S_NO_ERROR;
  4072. }
  4073. HRESULT COrNode::AddBranch(CEvalNode* pNewBranch)
  4074. {
  4075. // Search for a place in our array of branches
  4076. // ===========================================
  4077. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4078. {
  4079. int nCompare = CEvalTree::Compare(pNewBranch, m_apBranches[i]);
  4080. if(nCompare == 0)
  4081. {
  4082. // Could happen: sometimes we force an OR-merge
  4083. nCompare = -1;
  4084. }
  4085. if(nCompare < 0)
  4086. {
  4087. // pNewBranch comes before this branch, so insert it right here
  4088. // ============================================================
  4089. if(!m_apBranches.InsertAt(i, pNewBranch))
  4090. return WBEM_E_OUT_OF_MEMORY;
  4091. return WBEM_S_NO_ERROR;
  4092. }
  4093. }
  4094. // It is after all branches --- append
  4095. // ===================================
  4096. if(m_apBranches.Add(pNewBranch) < 0)
  4097. return WBEM_E_OUT_OF_MEMORY;
  4098. return WBEM_S_NO_ERROR;
  4099. }
  4100. HRESULT COrNode::CombineWithOrNode(COrNode* pArg2, int nOp,
  4101. CContextMetaData* pNamespace, CImplicationList& Implications,
  4102. bool bDeleteThis, bool bDeleteArg2, CEvalNode** ppRes)
  4103. {
  4104. // NOTE: this function may delete THIS in the middle of execution!!
  4105. // ================================================================
  4106. // Combine us with every branch of the other
  4107. // =========================================
  4108. CEvalNode* pCurrent = this;
  4109. bool bDeleteCurrent = bDeleteThis;
  4110. for(int i = 0; i < pArg2->m_apBranches.GetSize(); i++)
  4111. {
  4112. CEvalNode* pNew = NULL;
  4113. HRESULT hres = pCurrent->CombineWith(pArg2->m_apBranches[i], nOp,
  4114. pNamespace, Implications,
  4115. bDeleteCurrent, bDeleteArg2, &pNew);
  4116. if(FAILED(hres))
  4117. return hres;
  4118. pCurrent = pNew;
  4119. // At this point, we can safely delete pCurrent if needed --- it's ours
  4120. // ====================================================================
  4121. bDeleteCurrent = TRUE;
  4122. // If pArg2's branch has been deleted, reset it
  4123. // ============================================
  4124. if(bDeleteArg2)
  4125. pArg2->m_apBranches.Discard(i);
  4126. }
  4127. *ppRes = pCurrent;
  4128. if(bDeleteArg2)
  4129. delete pArg2;
  4130. return WBEM_S_NO_ERROR;
  4131. }
  4132. int COrNode::Compare(CEvalNode* pOther)
  4133. {
  4134. COrNode* pOtherNode = (COrNode*)pOther;
  4135. // Compare array sizes
  4136. // ===================
  4137. if(m_apBranches.GetSize() != pOtherNode->m_apBranches.GetSize())
  4138. return m_apBranches.GetSize() - pOtherNode->m_apBranches.GetSize();
  4139. // Compare individual nodes
  4140. // ========================
  4141. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4142. {
  4143. int nCompare = CEvalTree::Compare(m_apBranches[i],
  4144. pOtherNode->m_apBranches[i]);
  4145. if(nCompare != 0)
  4146. return nCompare;
  4147. }
  4148. return 0;
  4149. }
  4150. DWORD COrNode::ApplyPredicate(CLeafPredicate* pPred)
  4151. {
  4152. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4153. {
  4154. if (m_apBranches[i])
  4155. m_apBranches[i]->ApplyPredicate(pPred);
  4156. }
  4157. return WBEM_DISPOSITION_NORMAL;
  4158. }
  4159. HRESULT COrNode::Optimize(CContextMetaData* pNamespace, CEvalNode** ppNew)
  4160. {
  4161. HRESULT hres = WBEM_S_NO_ERROR;
  4162. // First, optimize all its branches
  4163. // ================================
  4164. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4165. {
  4166. CEvalNode* pNew = NULL;
  4167. if (m_apBranches[i])
  4168. {
  4169. hres = m_apBranches[i]->Optimize(pNamespace, &pNew);
  4170. if(FAILED(hres))
  4171. return hres;
  4172. }
  4173. if(pNew != m_apBranches[i])
  4174. {
  4175. // Replace, but check for emptiness first
  4176. // ======================================
  4177. if(!CEvalNode::IsAllFalse(pNew))
  4178. m_apBranches.SetAt(i, pNew);
  4179. else
  4180. {
  4181. delete pNew;
  4182. m_apBranches.RemoveAt(i);
  4183. i--;
  4184. }
  4185. }
  4186. }
  4187. if(m_apBranches.GetSize() == 0)
  4188. {
  4189. // We have no branches --- equivalent to no successes
  4190. // ==================================================
  4191. *ppNew = CValueNode::GetStandardFalse();
  4192. return WBEM_S_NO_ERROR;
  4193. }
  4194. else if(m_apBranches.GetSize() == 1)
  4195. {
  4196. // One branch --- equivalent to that branch
  4197. // ========================================
  4198. m_apBranches.RemoveAt(0, ppNew);
  4199. }
  4200. else
  4201. {
  4202. *ppNew = this;
  4203. }
  4204. return WBEM_S_NO_ERROR;
  4205. }
  4206. void COrNode::Dump(FILE* f, int nOffset)
  4207. {
  4208. PrintOffset(f, nOffset);
  4209. fprintf(f, "FOREST\n");
  4210. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4211. {
  4212. if (m_apBranches[i])
  4213. m_apBranches[i]->Dump(f, nOffset+1);
  4214. else
  4215. fprintf(f, "all false ValueNode (or error?)\n");
  4216. }
  4217. }
  4218. HRESULT COrNode::Evaluate(CObjectInfo& Info, CSortedArray& trueIDs)
  4219. {
  4220. for(int i = 0; i < m_apBranches.GetSize(); i++)
  4221. {
  4222. if (m_apBranches[i])
  4223. {
  4224. HRESULT hres = CEvalTree::Evaluate(Info, m_apBranches[i], trueIDs);
  4225. if(FAILED(hres))
  4226. return hres;
  4227. }
  4228. }
  4229. return WBEM_S_NO_ERROR;
  4230. }
  4231. HRESULT COrNode::Project(CContextMetaData* pMeta,
  4232. CImplicationList& Implications,
  4233. CProjectionFilter* pFilter,
  4234. EProjectionType eType, bool bDeleteThis,
  4235. CEvalNode** ppNewNode)
  4236. {
  4237. COrNode* pNew;
  4238. if(bDeleteThis)
  4239. pNew = this;
  4240. else
  4241. pNew = (COrNode*)Clone();
  4242. if(pNew == NULL)
  4243. return WBEM_E_OUT_OF_MEMORY;
  4244. //
  4245. // Simply project all the branches
  4246. //
  4247. for(int i = 0; i < pNew->m_apBranches.GetSize(); i++)
  4248. {
  4249. CEvalNode* pProjected = NULL;
  4250. HRESULT hres = CEvalTree::Project(pMeta, Implications,
  4251. pNew->m_apBranches[i], pFilter, eType,
  4252. true, // always delete --- has been cloned
  4253. &pProjected);
  4254. if(FAILED(hres))
  4255. return hres;
  4256. pNew->m_apBranches.Discard(i);
  4257. pNew->m_apBranches.SetAt(i, pProjected);
  4258. }
  4259. *ppNewNode = pNew;
  4260. return S_OK;
  4261. }
  4262. //******************************************************************************
  4263. //******************************************************************************
  4264. // PREDICATES
  4265. //******************************************************************************
  4266. //******************************************************************************
  4267. // NOTE: Not checking for NULL leaves, should be checked by caller
  4268. DWORD CEvalTree::CRemoveIndexPredicate::operator()(CValueNode* pLeaf)
  4269. {
  4270. if(pLeaf)
  4271. {
  4272. pLeaf->RemoveQueryID(m_nIndex);
  4273. if(pLeaf->GetNumTrues() == 0)
  4274. return WBEM_DISPOSITION_FLAG_DELETE;
  4275. }
  4276. return WBEM_DISPOSITION_NORMAL;
  4277. }
  4278. // NOTE: Not checking for NULL leaves, should be checked by caller
  4279. DWORD CEvalTree::CRebasePredicate::operator()(CValueNode* pLeaf)
  4280. {
  4281. if(pLeaf)
  4282. pLeaf->Rebase(m_newBase);
  4283. return WBEM_DISPOSITION_NORMAL;
  4284. }
  4285. // NOTE: Not checking for NULL leaves, should be checked by caller
  4286. DWORD CEvalTree::CRemoveFailureAtIndexPredicate::operator()(CValueNode* pLeaf)
  4287. {
  4288. if(pLeaf == NULL || pLeaf->GetAt(m_nIndex) != EVAL_VALUE_TRUE)
  4289. return WBEM_DISPOSITION_FLAG_INVALIDATE;
  4290. pLeaf->RemoveQueryID(m_nIndex);
  4291. if(pLeaf->GetNumTrues() == 0)
  4292. return WBEM_DISPOSITION_FLAG_DELETE;
  4293. return WBEM_DISPOSITION_NORMAL;
  4294. }
  4295. //******************************************************************************
  4296. //******************************************************************************
  4297. // EVALUATION TREE
  4298. //******************************************************************************
  4299. //******************************************************************************
  4300. CEvalTree::CEvalTree()
  4301. : m_lRef(0), m_pStart(NULL), m_nNumValues(0)
  4302. {
  4303. #ifdef CHECK_TREES
  4304. g_treeChecker.AddTree(this);
  4305. #endif
  4306. }
  4307. CEvalTree::CEvalTree(const CEvalTree& Other)
  4308. : m_lRef(0), m_pStart(NULL), m_nNumValues(0)
  4309. {
  4310. #ifdef CHECK_TREES
  4311. g_treeChecker.AddTree(this);
  4312. #endif
  4313. *this = Other;
  4314. }
  4315. CEvalTree::~CEvalTree()
  4316. {
  4317. #ifdef CHECK_TREES
  4318. g_treeChecker.RemoveTree(this);
  4319. #endif
  4320. delete m_pStart;
  4321. }
  4322. bool CEvalTree::SetBool(BOOL bVal)
  4323. {
  4324. CInCritSec ics(&m_cs);
  4325. delete m_pStart;
  4326. CValueNode* pNode;
  4327. if (bVal)
  4328. {
  4329. pNode = CValueNode::GetStandardTrue();
  4330. if(pNode == NULL)
  4331. return false;
  4332. }
  4333. else
  4334. pNode = CValueNode::GetStandardFalse();
  4335. m_pStart = pNode;
  4336. m_nNumValues = 1;
  4337. if(!m_ObjectInfo.SetLength(1))
  4338. return false;
  4339. return true;
  4340. }
  4341. bool CEvalTree::IsFalse()
  4342. {
  4343. return (m_pStart == NULL);
  4344. }
  4345. bool CEvalTree::IsValid()
  4346. {
  4347. return !CEvalNode::IsInvalid(m_pStart);
  4348. }
  4349. int CEvalTree::Compare(CEvalNode* pArg1, CEvalNode* pArg2)
  4350. {
  4351. if(pArg1 == NULL)
  4352. {
  4353. if(pArg2 == NULL)
  4354. return 0;
  4355. else
  4356. return 1;
  4357. }
  4358. else if(pArg2 == NULL)
  4359. return -1;
  4360. else if(CEvalNode::GetType(pArg1) != CEvalNode::GetType(pArg2))
  4361. return CEvalNode::GetType(pArg1) - CEvalNode::GetType(pArg2);
  4362. else return pArg1->Compare(pArg2);
  4363. }
  4364. HRESULT CEvalTree::CreateFromQuery(CContextMetaData* pNamespace,
  4365. LPCWSTR wszQuery, long lFlags, long lMaxTokens)
  4366. {
  4367. CTextLexSource src((LPWSTR)wszQuery);
  4368. QL1_Parser parser(&src);
  4369. QL_LEVEL_1_RPN_EXPRESSION *pExp = 0;
  4370. int nRes = parser.Parse(&pExp);
  4371. CDeleteMe<QL_LEVEL_1_RPN_EXPRESSION> deleteMe(pExp);
  4372. if (nRes)
  4373. return WBEM_E_INVALID_QUERY;
  4374. HRESULT hres = CreateFromQuery(pNamespace, pExp, lFlags, lMaxTokens);
  4375. return hres;
  4376. }
  4377. HRESULT CEvalTree::CreateFromQuery(CContextMetaData* pNamespace,
  4378. QL_LEVEL_1_RPN_EXPRESSION* pQuery, long lFlags, long lMaxTokens)
  4379. {
  4380. return CreateFromQuery(pNamespace, pQuery->bsClassName, pQuery->nNumTokens,
  4381. pQuery->pArrayOfTokens, lFlags, lMaxTokens);
  4382. }
  4383. HRESULT CEvalTree::CreateFromQuery(CContextMetaData* pNamespace,
  4384. LPCWSTR wszClassName, int nNumTokens, QL_LEVEL_1_TOKEN* apTokens,
  4385. long lFlags, long lMaxTokens)
  4386. {
  4387. CInCritSec ics(&m_cs);
  4388. HRESULT hres;
  4389. // Create basic implication list
  4390. // =============================
  4391. _IWmiObject* pObj = NULL;
  4392. hres = pNamespace->GetClass(wszClassName, &pObj);
  4393. if(FAILED(hres))
  4394. {
  4395. return hres;
  4396. }
  4397. CReleaseMe rm1(pObj);
  4398. try
  4399. {
  4400. CImplicationList Implications(lFlags);
  4401. CPropertyName EmptyName;
  4402. Implications.ImproveKnown(&EmptyName, pObj);
  4403. #ifdef CHECK_TREES
  4404. CheckTrees();
  4405. #endif
  4406. CEvalNode* pWhere = NULL;
  4407. if(nNumTokens)
  4408. {
  4409. // Convert the token list to DNF
  4410. // =============================
  4411. CDNFExpression DNF;
  4412. QL_LEVEL_1_TOKEN* pEnd = apTokens + nNumTokens - 1;
  4413. hres = DNF.CreateFromTokens(pEnd, 0, lMaxTokens);
  4414. if(FAILED(hres))
  4415. return hres;
  4416. if(pEnd != apTokens - 1)
  4417. {
  4418. return WBEM_E_CRITICAL_ERROR;
  4419. }
  4420. DNF.Sort();
  4421. // Build a tree for the token list
  4422. // ===============================
  4423. hres = CreateFromDNF(pNamespace, Implications, &DNF, &pWhere);
  4424. if(FAILED(hres))
  4425. {
  4426. return hres;
  4427. }
  4428. }
  4429. else
  4430. {
  4431. pWhere = CValueNode::GetStandardTrue();
  4432. if(pWhere == NULL)
  4433. return WBEM_E_OUT_OF_MEMORY;
  4434. }
  4435. // Add inheritance check
  4436. // =====================
  4437. CInheritanceNode* pInhNode = new CInheritanceNode;
  4438. if (!pInhNode)
  4439. return WBEM_E_OUT_OF_MEMORY;
  4440. hres = pInhNode->AddClass(pNamespace, wszClassName, (_IWmiObject*)pObj,
  4441. pWhere);
  4442. if(FAILED(hres))
  4443. {
  4444. delete pWhere;
  4445. delete pInhNode;
  4446. return hres;
  4447. }
  4448. if(!m_ObjectInfo.SetLength(Implications.GetRequiredDepth()))
  4449. {
  4450. delete pInhNode;
  4451. return WBEM_E_OUT_OF_MEMORY;
  4452. }
  4453. delete m_pStart;
  4454. m_pStart = pInhNode;
  4455. m_nNumValues = 1;
  4456. #ifdef CHECK_TREES
  4457. CheckTrees();
  4458. #endif
  4459. Optimize(pNamespace);
  4460. #ifdef CHECK_TREES
  4461. CheckTrees();
  4462. #endif
  4463. return WBEM_S_NO_ERROR;
  4464. }
  4465. catch (CX_MemoryException)
  4466. {
  4467. return WBEM_E_OUT_OF_MEMORY;
  4468. }
  4469. }
  4470. // extension of BuildFromToken to build nodes that have two properties
  4471. // e.g. this would service "select * from class where prop1 < prop2"
  4472. HRESULT CEvalTree::BuildTwoPropFromToken(CContextMetaData* pNamespace,
  4473. CImplicationList& Implications,
  4474. QL_LEVEL_1_TOKEN& Token, CEvalNode** ppRes)
  4475. {
  4476. HRESULT hres;
  4477. CEmbeddingInfo leftInfo, rightInfo;
  4478. if(!leftInfo.SetPropertyNameButLast(Token.PropertyName))
  4479. return WBEM_E_OUT_OF_MEMORY;
  4480. if(!rightInfo.SetPropertyNameButLast(Token.PropertyName2))
  4481. return WBEM_E_OUT_OF_MEMORY;
  4482. _IWmiObject* pLeftClass;
  4483. hres = leftInfo.Compile(pNamespace, Implications, &pLeftClass);
  4484. if(FAILED(hres))
  4485. return hres;
  4486. if(pLeftClass == NULL)
  4487. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  4488. _IWmiObject* pRightClass;
  4489. hres = rightInfo.Compile(pNamespace, Implications, &pRightClass);
  4490. if(FAILED(hres))
  4491. return hres;
  4492. if(pRightClass == NULL)
  4493. {
  4494. pLeftClass->Release();
  4495. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  4496. }
  4497. // Get the property types and handles
  4498. // ==================================
  4499. LPCWSTR wszLeftPropName = Token.PropertyName.GetStringAt(
  4500. Token.PropertyName.GetNumElements() - 1);
  4501. LPCWSTR wszRightPropName = Token.PropertyName2.GetStringAt(
  4502. Token.PropertyName2.GetNumElements() - 1);
  4503. CIMTYPE ctLeft, ctRight;
  4504. long lLeftPropHandle, lRightPropHandle;
  4505. hres = pLeftClass->GetPropertyHandleEx(wszLeftPropName, 0L, &ctLeft,
  4506. &lLeftPropHandle);
  4507. pLeftClass->Release();
  4508. if(FAILED(hres)) return hres;
  4509. hres = pRightClass->GetPropertyHandleEx(wszRightPropName, 0L, &ctRight,
  4510. &lRightPropHandle);
  4511. pRightClass->Release();
  4512. if(FAILED(hres)) return hres;
  4513. if( ((ctLeft & CIM_FLAG_ARRAY) != 0) || (ctLeft == CIM_OBJECT)
  4514. || ((ctRight & CIM_FLAG_ARRAY) != 0) || (ctRight == CIM_OBJECT) )
  4515. return WBEM_E_NOT_SUPPORTED;
  4516. // if the type of either node is reference or date, go to dumb
  4517. if ( (ctLeft == CIM_DATETIME) ||
  4518. (ctLeft == CIM_REFERENCE) ||
  4519. (ctRight == CIM_DATETIME) ||
  4520. (ctRight == CIM_REFERENCE)
  4521. )
  4522. {
  4523. if(ctLeft != ctRight)
  4524. return WBEM_E_TYPE_MISMATCH;
  4525. CDumbNode* pDumb = NULL;
  4526. try
  4527. {
  4528. pDumb = new CDumbNode(Token);
  4529. if(pDumb == NULL)
  4530. return WBEM_E_OUT_OF_MEMORY;
  4531. }
  4532. catch (CX_MemoryException)
  4533. {
  4534. return WBEM_E_OUT_OF_MEMORY;
  4535. }
  4536. hres = pDumb->Validate(pLeftClass);
  4537. if(FAILED(hres))
  4538. {
  4539. delete pDumb;
  4540. return hres;
  4541. }
  4542. *ppRes = pDumb;
  4543. return WBEM_S_NO_ERROR;
  4544. }
  4545. // if the node is mismatched (different types in either node)
  4546. // we'll want to create the most flexible node needed to hold both types
  4547. CIMTYPE ctNode = ctLeft;
  4548. CPropertyNode* pNode = NULL;
  4549. try
  4550. {
  4551. bool bMismatchedNode = (ctLeft != ctRight);
  4552. if (bMismatchedNode)
  4553. {
  4554. // we'll be real forgiving about strings matching strings
  4555. if ( (ctLeft == CIM_STRING) ||
  4556. (ctRight == CIM_STRING)
  4557. )
  4558. pNode = new CTwoMismatchedStringNode;
  4559. else if ( (ctRight == CIM_REAL32) ||
  4560. (ctRight == CIM_REAL64) ||
  4561. (ctLeft == CIM_REAL32) ||
  4562. (ctLeft == CIM_REAL64)
  4563. )
  4564. pNode = new CTwoMismatchedFloatNode;
  4565. else if ( (ctLeft == CIM_UINT64) ||
  4566. (ctRight == CIM_UINT64)
  4567. )
  4568. pNode = new CTwoMismatchedUInt64Node;
  4569. else if ( (ctLeft == CIM_SINT64 ) ||
  4570. (ctRight == CIM_SINT64 )
  4571. )
  4572. pNode = new CTwoMismatchedInt64Node;
  4573. else if ( (ctRight == CIM_UINT32) ||
  4574. (ctLeft == CIM_UINT32)
  4575. )
  4576. pNode = new CTwoMismatchedUIntNode;
  4577. else
  4578. pNode = new CTwoMismatchedIntNode;
  4579. }
  4580. else
  4581. // not mistmatched - go with the exact type
  4582. {
  4583. // Create the Proper node
  4584. // =====================
  4585. switch(ctNode)
  4586. {
  4587. case CIM_SINT8:
  4588. pNode = new TTwoScalarPropNode<signed char>;
  4589. break;
  4590. case CIM_UINT8:
  4591. pNode = new TTwoScalarPropNode<unsigned char>;
  4592. break;
  4593. case CIM_SINT16:
  4594. pNode = new TTwoScalarPropNode<short>;
  4595. break;
  4596. case CIM_UINT16:
  4597. case CIM_CHAR16:
  4598. pNode = new TTwoScalarPropNode<unsigned short>;
  4599. break;
  4600. case CIM_SINT32:
  4601. pNode = new TTwoScalarPropNode<long>;
  4602. break;
  4603. case CIM_UINT32:
  4604. pNode = new TTwoScalarPropNode<unsigned long>;
  4605. break;
  4606. case CIM_SINT64:
  4607. pNode = new TTwoScalarPropNode<__int64>;
  4608. break;
  4609. case CIM_UINT64:
  4610. pNode = new TTwoScalarPropNode<unsigned __int64>;
  4611. break;
  4612. case CIM_REAL32:
  4613. pNode = new TTwoScalarPropNode<float>;
  4614. break;
  4615. case CIM_REAL64:
  4616. pNode = new TTwoScalarPropNode<double>;
  4617. break;
  4618. case CIM_BOOLEAN:
  4619. pNode = new TTwoScalarPropNode<VARIANT_BOOL>;
  4620. break;
  4621. case CIM_STRING:
  4622. pNode = new CTwoStringPropNode;
  4623. break;
  4624. case CIM_DATETIME:
  4625. case CIM_REFERENCE:
  4626. {
  4627. CDumbNode* pDumb = new CDumbNode(Token);
  4628. hres = pDumb->Validate(pLeftClass);
  4629. if(FAILED(hres))
  4630. {
  4631. delete pDumb;
  4632. return hres;
  4633. }
  4634. else
  4635. {
  4636. *ppRes = pDumb;
  4637. return WBEM_S_NO_ERROR;
  4638. }
  4639. }
  4640. return WBEM_S_NO_ERROR;
  4641. default:
  4642. return WBEM_E_CRITICAL_ERROR;
  4643. }
  4644. }
  4645. }
  4646. catch (CX_MemoryException)
  4647. {
  4648. return WBEM_E_OUT_OF_MEMORY;
  4649. }
  4650. if (!pNode)
  4651. return WBEM_E_OUT_OF_MEMORY;
  4652. if(!pNode->SetEmbeddingInfo(&leftInfo))
  4653. return WBEM_E_OUT_OF_MEMORY;
  4654. if(!pNode->SetPropertyInfo(wszLeftPropName, lLeftPropHandle))
  4655. return WBEM_E_OUT_OF_MEMORY;
  4656. ((CTwoPropNode*)pNode)->SetRightEmbeddingInfo(&rightInfo);
  4657. ((CTwoPropNode*)pNode)->SetRightPropertyInfo(wszRightPropName,
  4658. lRightPropHandle);
  4659. hres = pNode->SetOperator(Token.nOperator);
  4660. if(FAILED(hres))
  4661. return hres;
  4662. *ppRes = pNode;
  4663. return WBEM_S_NO_ERROR;
  4664. }
  4665. HRESULT CEvalTree::BuildFromToken(CContextMetaData* pNamespace,
  4666. CImplicationList& Implications,
  4667. QL_LEVEL_1_TOKEN& Token, CEvalNode** ppRes)
  4668. {
  4669. HRESULT hres;
  4670. if (Token.m_bPropComp)
  4671. {
  4672. hres = BuildTwoPropFromToken(pNamespace, Implications, Token, ppRes);
  4673. if(hres == WBEMESS_E_REGISTRATION_TOO_BROAD ||
  4674. hres == WBEM_E_INVALID_PROPERTY)
  4675. {
  4676. //
  4677. // Not enough information to use efficient evaluation
  4678. //
  4679. CDumbNode* pNode = NULL;
  4680. try
  4681. {
  4682. pNode = new CDumbNode(Token);
  4683. if(pNode == NULL)
  4684. return WBEM_E_OUT_OF_MEMORY;
  4685. }
  4686. catch (CX_MemoryException)
  4687. {
  4688. return WBEM_E_OUT_OF_MEMORY;
  4689. }
  4690. *ppRes = pNode;
  4691. return WBEM_S_NO_ERROR;
  4692. }
  4693. else
  4694. return hres;
  4695. }
  4696. //
  4697. // Retrieve event class definition
  4698. //
  4699. _IWmiObject* pEventClass;
  4700. hres = Implications.FindClassForProp(NULL, 0, &pEventClass);
  4701. if(FAILED(hres))
  4702. return hres;
  4703. if(pEventClass == NULL)
  4704. return WBEM_E_INVALID_QUERY;
  4705. CReleaseMe rm1((IWbemClassObject*)pEventClass);
  4706. if(Token.nOperator == QL1_OPERATOR_ISA)
  4707. {
  4708. //
  4709. // Inheritance node are rarely applicable in Nova --- we have no way
  4710. // of telling *which definition* of the class is being referenced. Thus,
  4711. // we only construct an inheritance node in one case --- where the
  4712. // embedded object in question is a property of an instance operation
  4713. // event. These we trust.
  4714. //
  4715. if(pEventClass->InheritsFrom(L"__InstanceOperationEvent") == S_OK)
  4716. {
  4717. //
  4718. // OK, can use an inheritance node
  4719. //
  4720. if(V_VT(&Token.vConstValue) != VT_BSTR)
  4721. return WBEM_E_INVALID_QUERY;
  4722. BSTR strClassName = V_BSTR(&Token.vConstValue);
  4723. CInheritanceNode* pNode = NULL;
  4724. try
  4725. {
  4726. pNode = new CInheritanceNode;
  4727. if (!pNode)
  4728. return WBEM_E_OUT_OF_MEMORY;
  4729. }
  4730. catch (CX_MemoryException)
  4731. {
  4732. return WBEM_E_OUT_OF_MEMORY;
  4733. }
  4734. CDeleteMe<CInheritanceNode> deleteMe(pNode);
  4735. CEvalNode* pTrue = CValueNode::GetStandardTrue();
  4736. if(pTrue == NULL)
  4737. return WBEM_E_OUT_OF_MEMORY;
  4738. hres = pNode->AddClass(pNamespace, strClassName, pTrue);
  4739. if(FAILED(hres))
  4740. return hres;
  4741. if(!pNode->SetPropertyInfo(pNamespace, Token.PropertyName))
  4742. return WBEM_E_OUT_OF_MEMORY;
  4743. hres = pNode->Compile(pNamespace, Implications);
  4744. if(FAILED(hres))
  4745. return hres;
  4746. // Record the fact that TRUE branch is being taken
  4747. // ===============================================
  4748. pNode->RecordBranch(pNamespace, Implications, 1);
  4749. // in the event that we made it this far,
  4750. // we no longer WANT to delete node
  4751. deleteMe = NULL;
  4752. *ppRes = pNode;
  4753. return WBEM_S_NO_ERROR;
  4754. }
  4755. else
  4756. {
  4757. //
  4758. // May not use an inheritance node --- use a dumb one instead
  4759. //
  4760. CDumbNode* pNode = NULL;
  4761. try
  4762. {
  4763. pNode = new CDumbNode(Token);
  4764. if(pNode == NULL)
  4765. return WBEM_E_OUT_OF_MEMORY;
  4766. }
  4767. catch (CX_MemoryException)
  4768. {
  4769. return WBEM_E_OUT_OF_MEMORY;
  4770. }
  4771. hres = pNode->Validate(pEventClass);
  4772. if(FAILED(hres))
  4773. {
  4774. delete pNode;
  4775. return hres;
  4776. }
  4777. *ppRes = pNode;
  4778. return WBEM_S_NO_ERROR;
  4779. }
  4780. }
  4781. else
  4782. {
  4783. //
  4784. // Attempt to compile the embedding portion. This will only succeed if
  4785. // the rest of the query implies enough information for us to know
  4786. // exactly what class the embedded object is
  4787. //
  4788. CEmbeddingInfo Info;
  4789. if(!Info.SetPropertyNameButLast(Token.PropertyName))
  4790. return WBEM_E_OUT_OF_MEMORY;
  4791. _IWmiObject* pClass;
  4792. hres = Info.Compile(pNamespace, Implications, &pClass);
  4793. if(hres == WBEMESS_E_REGISTRATION_TOO_BROAD ||
  4794. hres == WBEM_E_INVALID_PROPERTY || // invalid or not yet known?
  4795. pClass == NULL)
  4796. {
  4797. //
  4798. // Not enough information --- have to use the dumb node
  4799. //
  4800. CDumbNode* pNode = NULL;
  4801. try
  4802. {
  4803. pNode = new CDumbNode(Token);
  4804. if(pNode == NULL)
  4805. return WBEM_E_OUT_OF_MEMORY;
  4806. }
  4807. catch (CX_MemoryException)
  4808. {
  4809. return WBEM_E_OUT_OF_MEMORY;
  4810. }
  4811. hres = pNode->Validate(pEventClass);
  4812. if(FAILED(hres))
  4813. {
  4814. delete pNode;
  4815. return hres;
  4816. }
  4817. *ppRes = pNode;
  4818. return WBEM_S_NO_ERROR;
  4819. }
  4820. if(FAILED(hres))
  4821. return hres;
  4822. //
  4823. // We do know the class definition. Check if this is a system property,
  4824. // though, in which case we still have toi use a dumb node
  4825. //
  4826. LPCWSTR wszPropName = Token.PropertyName.GetStringAt(
  4827. Token.PropertyName.GetNumElements() - 1);
  4828. if(wszPropName == NULL)
  4829. return WBEM_E_OUT_OF_MEMORY;
  4830. if(wszPropName[0] == '_')
  4831. {
  4832. CDumbNode* pNode = NULL;
  4833. try
  4834. {
  4835. pNode = new CDumbNode(Token);
  4836. if(pNode == NULL)
  4837. return WBEM_E_OUT_OF_MEMORY;
  4838. }
  4839. catch (CX_MemoryException)
  4840. {
  4841. return WBEM_E_OUT_OF_MEMORY;
  4842. }
  4843. hres = pNode->Validate(pEventClass);
  4844. if(FAILED(hres))
  4845. {
  4846. delete pNode;
  4847. return hres;
  4848. }
  4849. *ppRes = pNode;
  4850. return WBEM_S_NO_ERROR;
  4851. }
  4852. // Get the property type and handle
  4853. // ================================
  4854. CIMTYPE ct;
  4855. long lPropHandle;
  4856. hres = pClass->GetPropertyHandleEx(wszPropName, 0L, &ct, &lPropHandle);
  4857. pClass->Release();
  4858. if(FAILED(hres)) return hres;
  4859. if(((ct & CIM_FLAG_ARRAY) != 0) || (ct == CIM_OBJECT))
  4860. return WBEM_E_NOT_SUPPORTED;
  4861. // Coerce the constant to the right type
  4862. // =====================================
  4863. VARIANT v;
  4864. VariantInit(&v);
  4865. CClearMe cm(&v);
  4866. if(V_VT(&Token.vConstValue) != VT_NULL)
  4867. {
  4868. hres = ChangeVariantToCIMTYPE(&v, &Token.vConstValue, ct);
  4869. if(FAILED(hres)) return hres;
  4870. }
  4871. else
  4872. {
  4873. V_VT(&v) = VT_NULL;
  4874. }
  4875. //
  4876. // Create the right node
  4877. //
  4878. CPropertyNode* pNode = NULL;
  4879. try
  4880. {
  4881. if ( Token.nOperator != QL1_OPERATOR_LIKE &&
  4882. Token.nOperator != QL1_OPERATOR_UNLIKE )
  4883. {
  4884. switch(ct)
  4885. {
  4886. case CIM_SINT8:
  4887. pNode = new CScalarPropNode<signed char>;
  4888. break;
  4889. case CIM_UINT8:
  4890. pNode = new CScalarPropNode<unsigned char>;
  4891. break;
  4892. case CIM_SINT16:
  4893. pNode = new CScalarPropNode<short>;
  4894. break;
  4895. case CIM_UINT16:
  4896. case CIM_CHAR16:
  4897. pNode = new CScalarPropNode<unsigned short>;
  4898. break;
  4899. case CIM_SINT32:
  4900. pNode = new CScalarPropNode<long>;
  4901. break;
  4902. case CIM_UINT32:
  4903. pNode = new CScalarPropNode<unsigned long>;
  4904. break;
  4905. case CIM_SINT64:
  4906. pNode = new CScalarPropNode<__int64>;
  4907. break;
  4908. case CIM_UINT64:
  4909. pNode = new CScalarPropNode<unsigned __int64>;
  4910. break;
  4911. case CIM_REAL32:
  4912. pNode = new CScalarPropNode<float>;
  4913. break;
  4914. case CIM_REAL64:
  4915. pNode = new CScalarPropNode<double>;
  4916. break;
  4917. case CIM_BOOLEAN:
  4918. pNode = new CScalarPropNode<VARIANT_BOOL>;
  4919. break;
  4920. case CIM_STRING:
  4921. pNode = new CStringPropNode;
  4922. break;
  4923. case CIM_DATETIME:
  4924. case CIM_REFERENCE:
  4925. {
  4926. CDumbNode* pDumb = new CDumbNode(Token);
  4927. if(pDumb == NULL)
  4928. return WBEM_E_OUT_OF_MEMORY;
  4929. hres = pDumb->Validate(pEventClass);
  4930. if(FAILED(hres))
  4931. {
  4932. delete pDumb;
  4933. return hres;
  4934. }
  4935. else
  4936. {
  4937. *ppRes = pDumb;
  4938. return WBEM_S_NO_ERROR;
  4939. }
  4940. }
  4941. default:
  4942. return WBEM_E_CRITICAL_ERROR;
  4943. }
  4944. }
  4945. else
  4946. {
  4947. if ( V_VT(&v) != VT_BSTR )
  4948. return WBEM_E_INVALID_QUERY;
  4949. pNode = new CLikeStringPropNode;
  4950. }
  4951. }
  4952. catch (CX_MemoryException)
  4953. {
  4954. return WBEM_E_OUT_OF_MEMORY;
  4955. }
  4956. if (!pNode)
  4957. return WBEM_E_OUT_OF_MEMORY;
  4958. if(!pNode->SetEmbeddingInfo(&Info))
  4959. {
  4960. delete pNode;
  4961. return WBEM_E_OUT_OF_MEMORY;
  4962. }
  4963. if(!pNode->SetPropertyInfo(wszPropName, lPropHandle))
  4964. {
  4965. delete pNode;
  4966. return WBEM_E_OUT_OF_MEMORY;
  4967. }
  4968. if(V_VT(&v) == VT_NULL)
  4969. {
  4970. pNode->SetNullTest(Token.nOperator);
  4971. }
  4972. else
  4973. {
  4974. //
  4975. // Check if the operator makes sense for the type
  4976. //
  4977. if(ct == CIM_BOOLEAN &&
  4978. (Token.nOperator != QL1_OPERATOR_EQUALS &&
  4979. Token.nOperator != QL1_OPERATOR_NOTEQUALS))
  4980. {
  4981. // No < > for booleans
  4982. return WBEM_E_INVALID_QUERY;
  4983. }
  4984. hres = pNode->SetOperator(Token.nOperator);
  4985. if(FAILED(hres))
  4986. return hres;
  4987. hres = pNode->SetTest(v);
  4988. if(FAILED(hres))
  4989. return hres;
  4990. }
  4991. *ppRes = pNode;
  4992. return WBEM_S_NO_ERROR;
  4993. }
  4994. }
  4995. HRESULT CEvalTree::Combine(CEvalNode* pArg1, CEvalNode* pArg2, int nOp,
  4996. CContextMetaData* pNamespace,
  4997. CImplicationList& Implications,
  4998. bool bDeleteArg1, bool bDeleteArg2,
  4999. CEvalNode** ppRes)
  5000. {
  5001. HRESULT hres;
  5002. try
  5003. {
  5004. //
  5005. // Apply the extra implications of the nodes being combined
  5006. //
  5007. CImplicationList* pArg1List = NULL;
  5008. if(pArg1 && pArg1->GetExtraImplications())
  5009. {
  5010. pArg1List = new CImplicationList(*pArg1->GetExtraImplications(),
  5011. false);
  5012. if(pArg1List == NULL)
  5013. return WBEM_E_OUT_OF_MEMORY;
  5014. }
  5015. CDeleteMe<CImplicationList> dm1(pArg1List);
  5016. CImplicationList* pArg2List = NULL;
  5017. if(pArg2 && pArg2->GetExtraImplications())
  5018. {
  5019. pArg2List = new CImplicationList(*pArg2->GetExtraImplications(),
  5020. false);
  5021. if(pArg2List == NULL)
  5022. return WBEM_E_OUT_OF_MEMORY;
  5023. }
  5024. CDeleteMe<CImplicationList> dm2(pArg2List);
  5025. if(pArg1List || pArg2List)
  5026. {
  5027. CImplicationList TheseImplications(Implications);
  5028. if(pArg1List)
  5029. {
  5030. hres = TheseImplications.MergeIn(pArg1List);
  5031. if(FAILED(hres))
  5032. return hres;
  5033. }
  5034. if(pArg2List)
  5035. {
  5036. hres = TheseImplications.MergeIn(pArg2List);
  5037. if(FAILED(hres))
  5038. return hres;
  5039. }
  5040. //
  5041. // Call inner combine to do everything but the implications
  5042. //
  5043. hres = InnerCombine(pArg1, pArg2, nOp, pNamespace,
  5044. TheseImplications,
  5045. bDeleteArg1, bDeleteArg2, ppRes);
  5046. }
  5047. else
  5048. {
  5049. //
  5050. // Call inner combine to do everything but the implications
  5051. //
  5052. hres = InnerCombine(pArg1, pArg2, nOp, pNamespace, Implications,
  5053. bDeleteArg1, bDeleteArg2, ppRes);
  5054. }
  5055. if(FAILED(hres))
  5056. return hres;
  5057. //
  5058. // The implication of the combined node is the combination of the
  5059. // individual node implications. It does not matter what the operation
  5060. // is: by the time we have arrived here, we have arrived to these
  5061. // respective
  5062. // points in the individual trees, so the implications have commenced.
  5063. // OK, I am convinced :-)
  5064. //
  5065. if(*ppRes)
  5066. {
  5067. CImplicationList* pResultList = NULL;
  5068. if(pArg1List || pArg2List)
  5069. {
  5070. //
  5071. // There is actually some implication info in one of them ---
  5072. // merge them
  5073. //
  5074. if(pArg1List == NULL)
  5075. {
  5076. pResultList = new CImplicationList(*pArg2List, false);
  5077. if(pResultList == NULL)
  5078. return WBEM_E_OUT_OF_MEMORY;
  5079. }
  5080. else
  5081. {
  5082. pResultList = new CImplicationList(*pArg1List, false);
  5083. if(pResultList == NULL)
  5084. return WBEM_E_OUT_OF_MEMORY;
  5085. if(pArg2List != NULL)
  5086. {
  5087. hres = pResultList->MergeIn(pArg2List);
  5088. if(FAILED(hres))
  5089. {
  5090. delete pResultList;
  5091. return hres;
  5092. }
  5093. }
  5094. }
  5095. }
  5096. return (*ppRes)->SetExtraImplications(pResultList); // acquires
  5097. }
  5098. else
  5099. return S_OK;
  5100. }
  5101. catch (CX_MemoryException)
  5102. {
  5103. return WBEM_E_OUT_OF_MEMORY;
  5104. }
  5105. }
  5106. HRESULT CEvalTree::InnerCombine(CEvalNode* pArg1, CEvalNode* pArg2, int nOp,
  5107. CContextMetaData* pNamespace,
  5108. CImplicationList& Implications,
  5109. bool bDeleteArg1, bool bDeleteArg2,
  5110. CEvalNode** ppRes)
  5111. {
  5112. HRESULT hres;
  5113. *ppRes = NULL;
  5114. if ((pArg1 == NULL) && (pArg2 == NULL))
  5115. return WBEM_S_NO_ERROR;
  5116. if(CEvalNode::IsInvalid(pArg1) || CEvalNode::IsInvalid(pArg2))
  5117. {
  5118. //
  5119. // Invalid branches cannot be taken, so the result is invalid
  5120. //
  5121. *ppRes = CValueNode::GetStandardInvalid();
  5122. if(bDeleteArg1)
  5123. delete pArg1;
  5124. if(bDeleteArg2)
  5125. delete pArg2;
  5126. return S_OK;
  5127. }
  5128. int arg1Type = CEvalNode::GetType(pArg1);
  5129. int arg2Type = CEvalNode::GetType(pArg2);
  5130. // Check if merging the nodes is called for
  5131. // ========================================
  5132. if(nOp != EVAL_OP_AND &&
  5133. IsMergeAdvisable(pArg1, pArg2, Implications) != WBEM_S_NO_ERROR)
  5134. {
  5135. // Create an OR node instead
  5136. // =========================
  5137. COrNode* pNew = NULL;
  5138. try
  5139. {
  5140. pNew = new COrNode;
  5141. if(pNew == NULL)
  5142. return WBEM_E_OUT_OF_MEMORY;
  5143. }
  5144. catch (CX_MemoryException)
  5145. {
  5146. return WBEM_E_OUT_OF_MEMORY;
  5147. }
  5148. if(bDeleteArg1)
  5149. {
  5150. hres = pNew->AddBranch(pArg1);
  5151. }
  5152. else
  5153. {
  5154. CEvalNode* pClone = pArg1->Clone();
  5155. if(pClone == NULL)
  5156. return WBEM_E_OUT_OF_MEMORY;
  5157. hres = pNew->AddBranch(pClone);
  5158. }
  5159. if(FAILED(hres))
  5160. return hres;
  5161. if(bDeleteArg2)
  5162. {
  5163. hres = pNew->AddBranch(pArg2);
  5164. }
  5165. else
  5166. {
  5167. CEvalNode* pClone = pArg2->Clone();
  5168. if(pClone == NULL)
  5169. return WBEM_E_OUT_OF_MEMORY;
  5170. hres = pNew->AddBranch(pClone);
  5171. }
  5172. if(FAILED(hres))
  5173. {
  5174. delete pNew;
  5175. return hres;
  5176. }
  5177. *ppRes = pNew;
  5178. return WBEM_S_NO_ERROR;
  5179. }
  5180. // Delegate same-type operations to the type
  5181. // =========================================
  5182. if(arg1Type == arg2Type)
  5183. {
  5184. if ( ((pArg1 == NULL) || (pArg2 == NULL))
  5185. // well, gosh - if we've already decided they're the same type, no reason for redundant checks...
  5186. && (arg1Type == EVAL_NODE_TYPE_VALUE))
  5187. {
  5188. if(nOp == EVAL_OP_AND)
  5189. {
  5190. // FALSE AND anything is FALSE
  5191. // ===========================
  5192. *ppRes = NULL;
  5193. if(bDeleteArg1)
  5194. delete pArg1;
  5195. if(bDeleteArg2)
  5196. delete pArg2;
  5197. return WBEM_S_NO_ERROR;
  5198. }
  5199. // FALSE combined in any other way with anything is that thing
  5200. // ===========================================================
  5201. if (pArg1)
  5202. {
  5203. if (bDeleteArg1)
  5204. *ppRes = pArg1;
  5205. else
  5206. *ppRes = pArg1->Clone();
  5207. if(*ppRes == NULL)
  5208. return WBEM_E_OUT_OF_MEMORY;
  5209. }
  5210. else if (pArg2)
  5211. {
  5212. if (bDeleteArg2)
  5213. *ppRes = pArg2;
  5214. else
  5215. *ppRes = pArg2->Clone();
  5216. if(*ppRes == NULL)
  5217. return WBEM_E_OUT_OF_MEMORY;
  5218. }
  5219. else
  5220. // can't touch this
  5221. *ppRes = NULL;
  5222. return WBEM_S_NO_ERROR;
  5223. }
  5224. else // not value nodes
  5225. return pArg1->CombineWith(pArg2, nOp, pNamespace, Implications,
  5226. bDeleteArg1, bDeleteArg2, ppRes);
  5227. }
  5228. // Check if one is an OR
  5229. // =====================
  5230. if(arg1Type == EVAL_NODE_TYPE_OR)
  5231. return pArg1->CombineWith(pArg2, nOp, pNamespace, Implications,
  5232. bDeleteArg1, bDeleteArg2, ppRes);
  5233. if(arg2Type == EVAL_NODE_TYPE_OR)
  5234. return pArg2->CombineWith(pArg1, FlipEvalOp(nOp), pNamespace,
  5235. Implications, bDeleteArg2, bDeleteArg1, ppRes);
  5236. // One leaf, one branch
  5237. // ====================
  5238. if(arg1Type == EVAL_NODE_TYPE_VALUE)
  5239. {
  5240. return CombineLeafWithBranch((CValueNode*)pArg1, (CBranchingNode*)pArg2,
  5241. nOp, pNamespace, Implications, bDeleteArg1, bDeleteArg2, ppRes);
  5242. }
  5243. else // it's pArg2
  5244. {
  5245. return CombineLeafWithBranch((CValueNode*)pArg2, (CBranchingNode*)pArg1,
  5246. FlipEvalOp(nOp), pNamespace, Implications,
  5247. bDeleteArg2, bDeleteArg1, ppRes);
  5248. }
  5249. }
  5250. // static
  5251. HRESULT CEvalTree::CombineLeafWithBranch(CValueNode* pArg1,
  5252. CBranchingNode* pArg2, int nOp,
  5253. CContextMetaData* pNamespace,
  5254. CImplicationList& Implications,
  5255. bool bDeleteArg1, bool bDeleteArg2,
  5256. CEvalNode** ppRes)
  5257. {
  5258. HRESULT hres;
  5259. if (pArg1 == NULL)
  5260. {
  5261. *ppRes = NULL;
  5262. if(nOp == EVAL_OP_AND)
  5263. {
  5264. // Anding a FALSE with something --- getting a FALSE!
  5265. // ==================================================
  5266. if(bDeleteArg2)
  5267. delete pArg2;
  5268. return WBEM_S_NO_ERROR;
  5269. }
  5270. else
  5271. {
  5272. // Anything else combined with FALSE gives itself!
  5273. // ===============================================
  5274. // Well, this is true, but the problem is with optimizations.
  5275. // Some branches in X might not be valid under the implications in
  5276. // this branch of the tree, and so need to be removed. For now, I
  5277. // will simply turn off this short-circuiting path. It may turn out
  5278. // that there are some critical performance gains to be had by
  5279. // keeping it, in which case we would need to put this back and
  5280. // make an efficient pass through it, checking branches.
  5281. //
  5282. /*
  5283. if(bDeleteArg2)
  5284. *ppRes = pArg2;
  5285. else
  5286. *ppRes = pArg2->Clone();
  5287. return WBEM_S_NO_ERROR;
  5288. */
  5289. }
  5290. }
  5291. else
  5292. {
  5293. // Try to short-circuit
  5294. // ====================
  5295. hres = pArg1->TryShortCircuit(pArg2, nOp, bDeleteArg1, bDeleteArg2, ppRes);
  5296. if(FAILED(hres))
  5297. return hres; // hard-failure
  5298. if(hres == WBEM_S_NO_ERROR)
  5299. return WBEM_S_NO_ERROR; // short-circuit succeeded
  5300. }
  5301. // Didn't short-circuit
  5302. // ====================
  5303. return ((CBranchingNode*)pArg2)->CombineInOrderWith(pArg1,
  5304. FlipEvalOp(nOp), pNamespace, Implications,
  5305. bDeleteArg2, bDeleteArg1, ppRes);
  5306. }
  5307. HRESULT CEvalTree::Evaluate(CObjectInfo& Info, CEvalNode* pStart,
  5308. CSortedArray& trueIDs)
  5309. {
  5310. HRESULT hres;
  5311. // Loop as long as we are still seeing branching nodes
  5312. // ===================================================
  5313. CEvalNode* pCurrent = pStart;
  5314. int nType;
  5315. while((nType = CEvalNode::GetType(pCurrent)) == EVAL_NODE_TYPE_BRANCH)
  5316. {
  5317. hres = ((CBranchingNode*)pCurrent)->Evaluate(Info, &pCurrent);
  5318. if(FAILED(hres)) return hres;
  5319. }
  5320. if(nType == EVAL_NODE_TYPE_OR)
  5321. {
  5322. hres = ((COrNode*)pCurrent)->Evaluate(Info, trueIDs);
  5323. if(FAILED(hres)) return hres;
  5324. }
  5325. else // VALUE
  5326. {
  5327. if (CValueNode::AreAnyTrue((CValueNode*)pCurrent))
  5328. ((CValueNode*)pCurrent)->AddTruesTo(trueIDs);
  5329. }
  5330. return WBEM_S_NO_ERROR;
  5331. }
  5332. HRESULT CEvalTree::Evaluate(IWbemObjectAccess* pObj, CSortedArray& trueIDs)
  5333. {
  5334. CInCritSec ics(&m_cs);
  5335. trueIDs.SetSize(0);
  5336. HRESULT hres = WBEM_S_NO_ERROR;
  5337. if(m_pStart != NULL)
  5338. {
  5339. m_ObjectInfo.SetObjectAt(0, (_IWmiObject*)pObj);
  5340. hres = Evaluate(m_ObjectInfo, m_pStart, trueIDs);
  5341. m_ObjectInfo.Clear();
  5342. }
  5343. return hres;
  5344. }
  5345. HRESULT CEvalTree::Optimize(CContextMetaData* pNamespace)
  5346. {
  5347. CInCritSec ics(&m_cs);
  5348. if(m_pStart == NULL)
  5349. return WBEM_S_NO_ERROR;
  5350. CEvalNode* pNew = NULL;
  5351. HRESULT hres = m_pStart->Optimize(pNamespace, &pNew);
  5352. if(pNew != m_pStart)
  5353. {
  5354. delete m_pStart;
  5355. m_pStart = pNew;
  5356. }
  5357. if(CEvalNode::GetType(m_pStart) == EVAL_NODE_TYPE_VALUE)
  5358. {
  5359. if(!m_ObjectInfo.SetLength(1))
  5360. return WBEM_E_OUT_OF_MEMORY;
  5361. }
  5362. return hres;
  5363. }
  5364. HRESULT CEvalTree::CombineWith(CEvalTree& Other, CContextMetaData* pNamespace,
  5365. int nOp, long lFlags)
  5366. {
  5367. CInCritSec ics(&m_cs);
  5368. HRESULT hres;
  5369. try
  5370. {
  5371. CImplicationList Implications(lFlags);
  5372. //
  5373. // Compute required object info depth. We are not set up to configure
  5374. // it properly, so we'll estimate the upper bound as the sum of the
  5375. // depths of the trees being merged. Except that the first object
  5376. // doesn't count --- it's the event itself. Unless one of the objects
  5377. // is empty --- in that case it doesn't mention the event itself, and
  5378. // so we should not subtract that 1.
  5379. //
  5380. long lRequiredDepth =
  5381. m_ObjectInfo.GetLength() + Other.m_ObjectInfo.GetLength();
  5382. if(m_ObjectInfo.GetLength() > 0 && Other.m_ObjectInfo.GetLength() > 0)
  5383. lRequiredDepth--;
  5384. //
  5385. // Combine our Start node with the new tree's. Ours will be deleted in
  5386. // the process.
  5387. //
  5388. CEvalNode* pNew;
  5389. hres = CEvalTree::Combine(m_pStart, Other.m_pStart, nOp, pNamespace,
  5390. Implications,
  5391. true, // delete ours
  5392. false, // don't touch theirs
  5393. &pNew);
  5394. if(FAILED(hres))
  5395. {
  5396. m_pStart = NULL;
  5397. return hres;
  5398. }
  5399. m_pStart = pNew;
  5400. if(!m_ObjectInfo.SetLength(lRequiredDepth))
  5401. return WBEM_E_OUT_OF_MEMORY;
  5402. if(nOp == EVAL_OP_COMBINE || nOp == EVAL_OP_INVERSE_COMBINE)
  5403. m_nNumValues += Other.m_nNumValues;
  5404. return WBEM_S_NO_ERROR;
  5405. }
  5406. catch (CX_MemoryException)
  5407. {
  5408. return WBEM_E_OUT_OF_MEMORY;
  5409. }
  5410. }
  5411. HRESULT CEvalTree::IsMergeAdvisable(CEvalNode* pArg1, CEvalNode* pArg2,
  5412. CImplicationList& Implications)
  5413. {
  5414. if(Implications.IsMergeMandatory())
  5415. return S_OK;
  5416. int arg1Type = CEvalNode::GetType(pArg1);
  5417. int arg2Type = CEvalNode::GetType(pArg2);
  5418. // if we have ONE non-false ValueNode, and ONE Branch Node, do not merge
  5419. if ( ((arg1Type == EVAL_NODE_TYPE_VALUE)
  5420. &&
  5421. (arg2Type == EVAL_NODE_TYPE_BRANCH)
  5422. &&
  5423. !CValueNode::IsAllFalse((CValueNode*)pArg1))
  5424. ||
  5425. ((arg2Type == EVAL_NODE_TYPE_VALUE)
  5426. &&
  5427. (arg1Type == EVAL_NODE_TYPE_BRANCH)
  5428. &&
  5429. !CValueNode::IsAllFalse((CValueNode*)pArg2))
  5430. )
  5431. return WBEM_S_FALSE;
  5432. else
  5433. // otherwise, if one of the nodes is not Branching, certainly yes (how hard can it be?)
  5434. if(arg1Type != EVAL_NODE_TYPE_BRANCH ||
  5435. arg2Type != EVAL_NODE_TYPE_BRANCH)
  5436. {
  5437. return WBEM_S_NO_ERROR;
  5438. }
  5439. // They are both branching. If not about the same property, then certainly
  5440. // inadvisable, since there is very little to be gained
  5441. // ========================================================================
  5442. CBranchingNode* pBranching1 = (CBranchingNode*)pArg1;
  5443. CBranchingNode* pBranching2 = (CBranchingNode*)pArg2;
  5444. if(CBranchingNode::ComparePrecedence(pBranching1, pBranching2))
  5445. return WBEM_S_FALSE;
  5446. // Check if the nodes are inheritance --- in that case we can only merge if
  5447. // they have identical checks
  5448. // ========================================================================
  5449. if(pBranching1->GetSubType() == EVAL_NODE_TYPE_INHERITANCE)
  5450. {
  5451. // So is the other one, given that precedence is identical
  5452. // =======================================================
  5453. if(((CInheritanceNode*)pBranching1)->SubCompare(
  5454. (CInheritanceNode*)pBranching2) != 0)
  5455. {
  5456. return WBEM_S_FALSE;
  5457. }
  5458. else
  5459. {
  5460. return WBEM_S_NO_ERROR;
  5461. }
  5462. }
  5463. else if(pBranching1->GetSubType() == EVAL_NODE_TYPE_DUMB)
  5464. {
  5465. //
  5466. // Only merge if identical
  5467. //
  5468. if(((CDumbNode*)pBranching1)->SubCompare(
  5469. (CDumbNode*)pBranching2) != 0)
  5470. {
  5471. return WBEM_S_FALSE;
  5472. }
  5473. else
  5474. {
  5475. return WBEM_S_NO_ERROR;
  5476. }
  5477. }
  5478. // Same property. TBD: better checks
  5479. // ==================================
  5480. return WBEM_S_NO_ERROR;
  5481. }
  5482. HRESULT CEvalTree::RemoveIndex(int nIndex)
  5483. {
  5484. CInCritSec ics(&m_cs);
  5485. if(m_pStart != NULL)
  5486. {
  5487. CRemoveIndexPredicate P(nIndex);
  5488. m_pStart->ApplyPredicate(&P);
  5489. m_nNumValues--;
  5490. }
  5491. return S_OK;
  5492. }
  5493. HRESULT CEvalTree::UtilizeGuarantee(CEvalTree& Guaranteed,
  5494. CContextMetaData* pNamespace)
  5495. {
  5496. CInCritSec ics(&m_cs);
  5497. #ifdef DUMP_EVAL_TREES
  5498. FILE* f;
  5499. f = fopen("c:\\log", "a");
  5500. fprintf(f, "\n\nORIGINAL:\n");
  5501. Dump(f);
  5502. fprintf(f, "\n\nGUARANTEE:\n");
  5503. Guaranteed.Dump(f);
  5504. fflush(f);
  5505. #endif
  5506. #ifdef CHECK_TREES
  5507. CheckTrees();
  5508. #endif
  5509. //
  5510. // Combine them together
  5511. //
  5512. //
  5513. // This is a single-valued tree -- rebase it to 1 to distinguish from
  5514. // the guarantee
  5515. //
  5516. Rebase(1);
  5517. HRESULT hres = CombineWith(Guaranteed, pNamespace, EVAL_OP_COMBINE,
  5518. WBEM_FLAG_MANDATORY_MERGE);
  5519. if(FAILED(hres)) return hres;
  5520. #ifdef DUMP_EVAL_TREES
  5521. fprintf(f, "AFTER MERGE:\n");
  5522. Dump(f);
  5523. fflush(f);
  5524. #endif
  5525. // Eliminate all nodes where Guaranteed is failing
  5526. // ===============================================
  5527. if(m_pStart)
  5528. {
  5529. CRemoveFailureAtIndexPredicate P(0);
  5530. hres = m_pStart->ApplyPredicate(&P);
  5531. if(FAILED(hres)) return hres;
  5532. }
  5533. m_nNumValues--;
  5534. #ifdef CHECK_TREES
  5535. CheckTrees();
  5536. #endif
  5537. #ifdef DUMP_EVAL_TREES
  5538. fprintf(f, "AFTER REMOVE:\n");
  5539. Dump(f);
  5540. fflush(f);
  5541. #endif
  5542. hres = Optimize(pNamespace);
  5543. if(FAILED(hres)) return hres;
  5544. Rebase((QueryID)-1);
  5545. #ifdef CHECK_TREES
  5546. CheckTrees();
  5547. #endif
  5548. #ifdef DUMP_EVAL_TREES
  5549. fprintf(f, "AFTER OPTIMIZE:\n");
  5550. Dump(f);
  5551. fclose(f);
  5552. #endif
  5553. return S_OK;
  5554. }
  5555. HRESULT CEvalTree::ApplyPredicate(CLeafPredicate* pPred)
  5556. {
  5557. CInCritSec ics(&m_cs);
  5558. if(m_pStart != NULL)
  5559. m_pStart->ApplyPredicate(pPred);
  5560. return S_OK;
  5561. }
  5562. void CEvalTree::operator=(const CEvalTree& Other)
  5563. {
  5564. CInCritSec ics(&m_cs);
  5565. delete m_pStart;
  5566. m_pStart = (Other.m_pStart ? Other.m_pStart->Clone() : NULL);
  5567. if(m_pStart == NULL && Other.m_pStart != NULL)
  5568. throw CX_MemoryException();
  5569. m_nNumValues = Other.m_nNumValues;
  5570. if(!m_ObjectInfo.SetLength(m_nNumValues))
  5571. throw CX_MemoryException();
  5572. }
  5573. // renumber the QueryIDs in the leaves of the tree
  5574. void CEvalTree::Rebase(QueryID newBase)
  5575. {
  5576. CRebasePredicate predRebase(newBase);
  5577. ApplyPredicate(&predRebase);
  5578. }
  5579. bool CEvalTree::Clear()
  5580. {
  5581. CInCritSec ics(&m_cs);
  5582. delete m_pStart;
  5583. m_pStart = CValueNode::GetStandardFalse();
  5584. if(!m_ObjectInfo.SetLength(1))
  5585. return false;
  5586. m_nNumValues = 0;
  5587. return true;
  5588. }
  5589. void CEvalTree::Dump(FILE* f)
  5590. {
  5591. CEvalNode::DumpNode(f, 0, m_pStart);
  5592. }
  5593. #ifdef CHECK_TREES
  5594. void CEvalTree::CheckNodes(CTreeChecker *pChecker)
  5595. {
  5596. CInCritSec ics2(&m_cs);
  5597. if (m_pStart)
  5598. m_pStart->CheckNode(pChecker);
  5599. }
  5600. #endif
  5601. HRESULT CEvalTree::CreateFromConjunction(CContextMetaData* pNamespace,
  5602. CImplicationList& Implications,
  5603. CConjunction* pConj,
  5604. CEvalNode** ppRes)
  5605. {
  5606. HRESULT hres;
  5607. *ppRes = NULL;
  5608. // Build them for all tokens and AND together
  5609. // ==========================================
  5610. try
  5611. {
  5612. CImplicationList BranchImplications(Implications);
  5613. for(int i = 0; i < pConj->GetNumTokens(); i++)
  5614. {
  5615. CEvalNode* pNew = NULL;
  5616. hres = CEvalTree::BuildFromToken(pNamespace, BranchImplications,
  5617. *pConj->GetTokenAt(i), &pNew);
  5618. if(FAILED(hres))
  5619. {
  5620. delete *ppRes;
  5621. return hres;
  5622. }
  5623. if(i > 0)
  5624. {
  5625. CEvalNode* pOld = *ppRes;
  5626. CEvalTree::Combine(pOld, pNew, EVAL_OP_AND, pNamespace,
  5627. Implications, true, true, ppRes); // delete both
  5628. }
  5629. else
  5630. {
  5631. *ppRes = pNew;
  5632. }
  5633. }
  5634. return WBEM_S_NO_ERROR;
  5635. }
  5636. catch (CX_MemoryException)
  5637. {
  5638. return WBEM_E_OUT_OF_MEMORY;
  5639. }
  5640. }
  5641. HRESULT CEvalTree::CreateFromDNF(CContextMetaData* pNamespace,
  5642. CImplicationList& Implications,
  5643. CDNFExpression* pDNF,
  5644. CEvalNode** ppRes)
  5645. {
  5646. HRESULT hres;
  5647. // Check if there is only one conjunction to talk about
  5648. // ====================================================
  5649. if(pDNF->GetNumTerms() == 1)
  5650. {
  5651. // Just build that one
  5652. // ===================
  5653. return CreateFromConjunction(pNamespace, Implications,
  5654. pDNF->GetTermAt(0), ppRes);
  5655. }
  5656. // Build them for all conjunctions and OR together
  5657. // ===============================================
  5658. CEvalNode* pRes = NULL;
  5659. for(int i = 0; i < pDNF->GetNumTerms(); i++)
  5660. {
  5661. CEvalNode* pNew;
  5662. hres = CreateFromConjunction(pNamespace, Implications,
  5663. pDNF->GetTermAt(i), &pNew);
  5664. if(FAILED(hres))
  5665. {
  5666. delete pRes;
  5667. return hres;
  5668. }
  5669. if(pRes == NULL)
  5670. {
  5671. pRes = pNew;
  5672. }
  5673. else
  5674. {
  5675. CEvalNode* pNewRes = NULL;
  5676. hres = CEvalTree::Combine(pRes, pNew, EVAL_OP_COMBINE,
  5677. pNamespace, Implications, true, true, &pNewRes);
  5678. if(FAILED(hres))
  5679. {
  5680. delete pRes;
  5681. delete pNew;
  5682. return hres;
  5683. }
  5684. pRes = pNewRes;
  5685. }
  5686. }
  5687. *ppRes = pRes;
  5688. return WBEM_S_NO_ERROR;
  5689. }
  5690. HRESULT CEvalTree::CreateProjection(CEvalTree& Old, CContextMetaData* pMeta,
  5691. CProjectionFilter* pFilter,
  5692. EProjectionType eType, bool bDeleteOld)
  5693. {
  5694. delete m_pStart;
  5695. m_pStart = NULL;
  5696. try
  5697. {
  5698. CImplicationList Implications;
  5699. return CEvalTree::Project(pMeta, Implications, Old.m_pStart, pFilter,
  5700. eType, bDeleteOld, &m_pStart);
  5701. }
  5702. catch (CX_MemoryException)
  5703. {
  5704. return WBEM_E_OUT_OF_MEMORY;
  5705. }
  5706. }
  5707. HRESULT CEvalTree::Project(CContextMetaData* pMeta,
  5708. CImplicationList& Implications,
  5709. CEvalNode* pOldNode, CProjectionFilter* pFilter,
  5710. EProjectionType eType, bool bDeleteOld,
  5711. CEvalNode** ppNewNode)
  5712. {
  5713. if(pOldNode == NULL)
  5714. {
  5715. *ppNewNode = NULL;
  5716. return WBEM_S_NO_ERROR;
  5717. }
  5718. return pOldNode->Project(pMeta, Implications, pFilter, eType, bDeleteOld,
  5719. ppNewNode);
  5720. }
  5721. CPropertyProjectionFilter::CPropertyProjectionFilter()
  5722. {
  5723. m_papProperties = new CUniquePointerArray<CPropertyName>;
  5724. if(m_papProperties == NULL)
  5725. throw CX_MemoryException();
  5726. }
  5727. CPropertyProjectionFilter::~CPropertyProjectionFilter()
  5728. {
  5729. delete m_papProperties;
  5730. }
  5731. bool CPropertyProjectionFilter::IsInSet(CEvalNode* pNode)
  5732. {
  5733. if(CEvalNode::GetType(pNode) != EVAL_NODE_TYPE_BRANCH)
  5734. return false;
  5735. CBranchingNode* pBranchingNode = (CBranchingNode*)pNode;
  5736. CPropertyName* pEmbeddedObjName = pBranchingNode->GetEmbeddedObjPropName();
  5737. CPropertyName ThisName;
  5738. if(pEmbeddedObjName)
  5739. ThisName = *pEmbeddedObjName;
  5740. int nSubType = pBranchingNode->GetSubType();
  5741. if(nSubType == EVAL_NODE_TYPE_SCALAR || nSubType == EVAL_NODE_TYPE_STRING)
  5742. {
  5743. //
  5744. // Derived from CPropertyNode --- get its property name
  5745. //
  5746. ThisName.AddElement(
  5747. ((CPropertyNode*)pBranchingNode)->GetPropertyName());
  5748. }
  5749. else if(nSubType == EVAL_NODE_TYPE_INHERITANCE)
  5750. {
  5751. // No extra name parts
  5752. }
  5753. else
  5754. {
  5755. //
  5756. // Two-prop, perhaps. Just say no
  5757. //
  5758. return false;
  5759. }
  5760. //
  5761. // Search for the name in our list
  5762. //
  5763. for(int i = 0; i < m_papProperties->GetSize(); i++)
  5764. {
  5765. if(*(m_papProperties->GetAt(i)) == ThisName)
  5766. return true;
  5767. }
  5768. return false;
  5769. }
  5770. bool CPropertyProjectionFilter::AddProperty(const CPropertyName& Prop)
  5771. {
  5772. CPropertyName* pProp = NULL;
  5773. try
  5774. {
  5775. pProp = new CPropertyName(Prop);
  5776. if(pProp == NULL)
  5777. return false;
  5778. }
  5779. catch (CX_MemoryException)
  5780. {
  5781. return false;
  5782. }
  5783. if(m_papProperties->Add(pProp) < 0)
  5784. return false;
  5785. return true;
  5786. }