Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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