Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1097 lines
31 KiB

  1. // XMLObject.cpp: implementation of the CXMLObject class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. //hcp://system/sysinfo/msinfo.htm C:\WINDOWS\PCHEALTH\HELPCTR\System\SYSINFO\msinfo.htm
  5. #include "stdafx.h"
  6. #include "resource.h"
  7. #include "XMLObject.h"
  8. #include "msxml.h"
  9. #include "HistoryParser.h"
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[]=__FILE__;
  13. #define new DEBUG_NEW
  14. #endif
  15. //////////////////////////////////////////////////////////////////////
  16. // Construction/Destruction
  17. //////////////////////////////////////////////////////////////////////
  18. CXMLObject::CXMLObject()
  19. {
  20. }
  21. CXMLObject::~CXMLObject()
  22. {
  23. }
  24. //---------------------------------------------------------------------------
  25. // Creates a new CXMLObject, which basically wraps the INSTANCE xml node pased in as pNode
  26. // pNode will have been selected with a query something like
  27. // Snapshot/CIM/DECLARATION/DECLGROUP.WITHPATH/VALUE.OBJECTWITHPATH/INSTANCE[@CLASSNAME $ieq$ ";
  28. //
  29. //---------------------------------------------------------------------------
  30. HRESULT CXMLObject::Create(CComPtr<IXMLDOMNode> pNode, CString strClassName)
  31. {
  32. ASSERT(pNode != NULL && "NULL smart pointer passed in");
  33. m_pNode = pNode;
  34. m_strClassName = strClassName;
  35. return S_OK;
  36. }
  37. //---------------------------------------------------------------------------
  38. // Finds a specific property node in m_pNode
  39. //---------------------------------------------------------------------------
  40. HRESULT CXMLObject::GetPROPERTYNode(LPCTSTR szProperty,CComPtr<IXMLDOMNode>& pPropNode)
  41. {
  42. CString strSubQuery(_T(""));
  43. HRESULT hr;
  44. if (FALSE)
  45. {
  46. }
  47. else
  48. {
  49. strSubQuery = _T("PROPERTY[@NAME $ieq$");
  50. strSubQuery += _T('\"');
  51. strSubQuery += szProperty;
  52. strSubQuery += _T('\"');
  53. strSubQuery += _T("]");
  54. }
  55. CComBSTR bstrSubQuery(strSubQuery);
  56. hr = S_FALSE;
  57. hr = this->m_pNode->selectSingleNode(bstrSubQuery,&pPropNode);
  58. if (FAILED(hr) || !pPropNode)
  59. {
  60. return E_FAIL;
  61. }
  62. return S_OK;
  63. }
  64. //---------------------------------------------------------------------------
  65. // Tries to find the value specified by szProperty in associated INSTANCE node
  66. // (m_pNode)
  67. //---------------------------------------------------------------------------
  68. HRESULT CXMLObject::GetValue(LPCTSTR szProperty, VARIANT * pvarValue)
  69. {
  70. CComBSTR bstrAttributeText;
  71. CComPtr<IXMLDOMNode> pSubNode;
  72. HRESULT hr = GetPROPERTYNode(szProperty,pSubNode);
  73. if (FAILED(hr))
  74. {
  75. pvarValue->vt = VT_EMPTY;
  76. return E_MSINFO_NOVALUE;
  77. }
  78. ASSERT(pSubNode != NULL);
  79. CComVariant varAttr;
  80. varAttr.vt = VT_BSTR;
  81. hr = pSubNode->get_text(&varAttr.bstrVal);
  82. pvarValue->vt = VT_BSTR;
  83. pvarValue->bstrVal = varAttr.bstrVal;
  84. return S_OK;
  85. }
  86. //---------------------------------------------------------------------------
  87. // Finds value specified by szProperty, returns it as string
  88. //---------------------------------------------------------------------------
  89. HRESULT CXMLObject::GetValueString(LPCTSTR szProperty, CString * pstrValue)
  90. {
  91. try
  92. {
  93. if (!pstrValue)
  94. {
  95. ASSERT(0 && "NULL POINTER PASSED IN");
  96. return E_FAIL;
  97. }
  98. HRESULT hr;
  99. CComVariant ovValue;
  100. hr = this->GetValue(szProperty,&ovValue);
  101. //some properties have to be interpolated if not found...
  102. if (ovValue.vt == VT_EMPTY)
  103. {
  104. if (_tcsicmp(szProperty,_T("__PATH")) == 0)
  105. {
  106. return GetPath(pstrValue);
  107. }
  108. else if (_tcsicmp(szProperty,_T("Antecedent")) == 0)
  109. {
  110. ASSERT(this->m_strClassName.CompareNoCase("Win32_PNPAllocatedResource") == 0);
  111. this->GetAntecedent(pstrValue);
  112. return S_OK;
  113. }
  114. else if (_tcsicmp(szProperty,_T("Dependent")) == 0)
  115. {
  116. ASSERT(this->m_strClassName.CompareNoCase("Win32_PNPAllocatedResource") == 0);
  117. this->GetDependent(pstrValue);
  118. return S_OK;
  119. }
  120. else if (_tcsicmp(szProperty,_T("Caption")) == 0)
  121. {
  122. if (this->m_strClassName.CompareNoCase(_T("Win32_PnPEntity")) == 0)
  123. {
  124. //need to get PNP device name
  125. CString strPNPID;
  126. GetValueString(_T("DeviceID"),&strPNPID);
  127. CComPtr<IXMLDOMDocument> pDoc;
  128. if (FAILED(this->m_pNode->get_ownerDocument(&pDoc)) || !pDoc)
  129. {
  130. return E_MSINFO_NOVALUE;
  131. }
  132. *pstrValue = GetPNPNameByID(pDoc,CComBSTR(strPNPID));
  133. return S_OK;
  134. }
  135. else if (this->m_strClassName.CompareNoCase(_T("Win32_DMAChannel")) == 0)
  136. {
  137. return GetValueString(_T("Name"),pstrValue);
  138. }
  139. else if (this->m_strClassName.CompareNoCase(_T("Win32_StartupCommand")) == 0)
  140. {
  141. return GetValueString(_T("Name"),pstrValue);
  142. }
  143. else if (this->m_strClassName.CompareNoCase(_T("Win32_PortResource")) == 0)
  144. {
  145. return GetValueString(_T("Name"),pstrValue);
  146. }
  147. else if (this->m_strClassName.CompareNoCase(_T("Win32_IRQResource")) == 0)
  148. {
  149. return GetValueString(_T("Name"),pstrValue);
  150. }
  151. else if (this->m_strClassName.CompareNoCase(_T("Win32_DeviceMemoryAddress")) == 0)
  152. {
  153. return GetValueString(_T("Description"),pstrValue);
  154. }
  155. else if (this->m_strClassName.CompareNoCase(_T("Win32_StartupCommand")) == 0)
  156. {
  157. return GetValueString(_T("Name"),pstrValue);
  158. }
  159. }
  160. else if (_tcsicmp(szProperty,_T("Status")) == 0)
  161. {
  162. AfxSetResourceHandle(_Module.GetResourceInstance());
  163. VERIFY(pstrValue->LoadString(IDS_ERROR_NOVALUE) && _T("could not find string resource"));
  164. return S_OK;
  165. }
  166. else if (_tcsicmp(szProperty,_T("Name")) == 0 && m_strClassName.CompareNoCase(_T("Win32_Printer")) == 0)
  167. {
  168. return GetValueString(_T("DeviceID"),pstrValue);
  169. }
  170. else if (_tcsicmp(szProperty,_T("ServerName")) == 0 && m_strClassName.CompareNoCase(_T("Win32_Printer")) == 0)
  171. {
  172. return GetValueString(_T("PortName"),pstrValue);
  173. }
  174. else if (_tcsicmp(szProperty,_T("DriveType")) == 0 && m_strClassName.CompareNoCase(_T("Win32_LogicalDisk")) == 0)
  175. {
  176. return GetValueString(_T("Description"),pstrValue);
  177. }
  178. AfxSetResourceHandle(_Module.GetResourceInstance());
  179. VERIFY(pstrValue->LoadString(IDS_ERROR_NOVALUE) && _T("could not find string resource"));
  180. return hr;
  181. }
  182. if (ovValue.vt != VT_EMPTY)
  183. {
  184. USES_CONVERSION;
  185. CString strVal = OLE2A(ovValue.bstrVal);
  186. *pstrValue = strVal;
  187. return hr;
  188. }
  189. else
  190. {
  191. *pstrValue = _T("");
  192. AfxSetResourceHandle(_Module.GetResourceInstance());
  193. VERIFY(pstrValue->LoadString(IDS_ERROR_NOVALUE) && "could not find string resource");
  194. return S_OK;
  195. }
  196. }
  197. catch(COleException e)
  198. {
  199. ASSERT(0 && "conversion error?");
  200. }
  201. catch (...)
  202. {
  203. ASSERT(0 && "unknown error");
  204. }
  205. return E_FAIL;
  206. }
  207. //---------------------------------------------------------------------------
  208. // Finds value specified by szProperty, returns it as DWORD
  209. //---------------------------------------------------------------------------
  210. HRESULT CXMLObject::GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue)
  211. {
  212. if (!pdwValue)
  213. {
  214. ASSERT(0 && "NULL POINTER PASSED IN");
  215. return E_MSINFO_NOVALUE;
  216. }
  217. CComVariant varValue;
  218. HRESULT hr = GetValue(szProperty,&varValue);
  219. if (FAILED(hr))
  220. {
  221. return E_MSINFO_NOVALUE;
  222. }
  223. hr = varValue.ChangeType(VT_UI4);
  224. if (SUCCEEDED(hr))
  225. {
  226. *pdwValue = varValue.ulVal;
  227. }
  228. else
  229. {
  230. return E_MSINFO_NOVALUE;
  231. }
  232. return hr;
  233. }
  234. //---------------------------------------------------------------------------
  235. // Finds value specified by szProperty, returns it as SYSTEMTIME
  236. //---------------------------------------------------------------------------
  237. HRESULT CXMLObject::GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue)
  238. {
  239. if (!psystimeValue)
  240. {
  241. ASSERT(0 && "NULL POINTER PASSED IN");
  242. return E_MSINFO_NOVALUE;
  243. }
  244. VARIANT variant;
  245. HRESULT hr = GetValue(szProperty, &variant);
  246. if (SUCCEEDED(hr))
  247. {
  248. if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK)
  249. {
  250. USES_CONVERSION;
  251. LPTSTR szDate = OLE2T(V_BSTR(&variant));
  252. if (szDate == NULL || _tcslen(szDate) == 0)
  253. {
  254. //probably "PROPOGATED" value
  255. return E_MSINFO_NOVALUE;
  256. }
  257. // Parse the date string into the SYSTEMTIME struct. It would be better to
  258. // get the date from WMI directly, but there was a problem with this. TBD -
  259. // look into whether or not we can do this now.
  260. ZeroMemory(psystimeValue, sizeof(SYSTEMTIME));
  261. psystimeValue->wSecond = (unsigned short)_ttoi(szDate + 12); szDate[12] = _T('\0');
  262. psystimeValue->wMinute = (unsigned short)_ttoi(szDate + 10); szDate[10] = _T('\0');
  263. psystimeValue->wHour = (unsigned short)_ttoi(szDate + 8); szDate[ 8] = _T('\0');
  264. psystimeValue->wDay = (unsigned short)_ttoi(szDate + 6); szDate[ 6] = _T('\0');
  265. psystimeValue->wMonth = (unsigned short)_ttoi(szDate + 4); szDate[ 4] = _T('\0');
  266. psystimeValue->wYear = (unsigned short)_ttoi(szDate + 0);
  267. }
  268. else
  269. hr = E_MSINFO_NOVALUE;
  270. }
  271. return hr;
  272. }
  273. //---------------------------------------------------------------------------
  274. // Finds value specified by szProperty, returns it as FLOAT
  275. //---------------------------------------------------------------------------
  276. HRESULT CXMLObject::GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue)
  277. {
  278. if (!pdblValue)
  279. {
  280. ASSERT(0 && "NULL POINTER PASSED IN");
  281. return E_MSINFO_NOVALUE;
  282. }
  283. CComPtr<IXMLDOMNode> pPropNode;
  284. CComVariant varValue;
  285. HRESULT hr = GetPROPERTYNode(szProperty,pPropNode);
  286. if (FAILED(hr) || !pPropNode)
  287. {
  288. return E_MSINFO_NOVALUE;
  289. }
  290. varValue.vt = VT_BSTR;
  291. hr = pPropNode->get_text(&varValue.bstrVal);
  292. if (FAILED(hr))
  293. {
  294. ASSERT(0 && "could not get text from PROPERTY node");
  295. *pdblValue = (double) -1;
  296. return E_MSINFO_NOVALUE;
  297. }
  298. hr = varValue.ChangeType(VT_R4);
  299. if (FAILED(hr))
  300. {
  301. varValue.Clear();
  302. ASSERT(0 && "unable to convert between variant types");
  303. return E_MSINFO_NOVALUE;
  304. }
  305. *pdblValue = varValue.fltVal;
  306. return hr;
  307. }
  308. //---------------------------------------------------------------------------
  309. // This function exists to provide compatiblilty with CWMIObject. All it does
  310. // is a GetValueString(szProperty,pstrValue)
  311. //---------------------------------------------------------------------------
  312. HRESULT CXMLObject::GetValueValueMap(LPCTSTR szProperty, CString * pstrValue)
  313. {
  314. if (!pstrValue)
  315. {
  316. ASSERT(0 && "NULL POINTER PASSED IN");
  317. return E_MSINFO_NOVALUE;
  318. }
  319. return GetValueString(szProperty,pstrValue);
  320. }
  321. //////////////////////////////////////////////////////////////////////
  322. // CXMLObjectCollection Class
  323. //////////////////////////////////////////////////////////////////////
  324. //////////////////////////////////////////////////////////////////////
  325. // Construction/Destruction
  326. //////////////////////////////////////////////////////////////////////
  327. CXMLObjectCollection::CXMLObjectCollection(CComPtr<IXMLDOMDocument> pXMLDoc) : m_pXMLDoc(pXMLDoc)
  328. {
  329. }
  330. CXMLObjectCollection::~CXMLObjectCollection()
  331. {
  332. }
  333. //-----------------------------------------------------------------------------
  334. // Return the next node in list of INSTANCE nodes selected by
  335. // CXMLObjectCollection::Create, as a CXMLObject
  336. //-----------------------------------------------------------------------------
  337. HRESULT CXMLObjectCollection::GetNext(CWMIObject ** ppObject)
  338. {
  339. ASSERT(ppObject);
  340. if (m_pList == NULL)
  341. {
  342. ASSERT(0 && "CXMLObjectCollection::GetNext called on a null enumerator");
  343. return E_FAIL;
  344. }
  345. CComPtr<IXMLDOMNode> pNode;
  346. HRESULT hr = m_pList->nextNode(&pNode);
  347. if (!pNode)
  348. {
  349. //we're at end of m_pList
  350. return E_FAIL;
  351. }
  352. if (hr == S_OK && pNode)
  353. {
  354. if (*ppObject == NULL)
  355. {
  356. *ppObject = new CXMLObject();
  357. }
  358. if (*ppObject)
  359. {
  360. hr = ((CXMLObject *)(*ppObject))->Create(pNode,m_strClassName); // this will AddRef the pointer
  361. if (FAILED(hr))
  362. {
  363. delete (CXMLObject *)(*ppObject);
  364. *ppObject = NULL;
  365. }
  366. }
  367. if (*ppObject)
  368. {
  369. return hr;
  370. }
  371. else
  372. hr = E_OUTOFMEMORY;
  373. }
  374. return hr;
  375. }
  376. //---------------------------------------------------------------------------
  377. //
  378. //---------------------------------------------------------------------------
  379. HRESULT CXMLObjectCollection::Create(LPCTSTR szClass, LPCTSTR szProperties)
  380. {
  381. HRESULT hr;
  382. ASSERT(szClass);
  383. m_strClassName = szClass;
  384. CString strQuery;
  385. if (_tcsicmp(szClass,_T("Win32_PNPAllocatedResource")) == 0)
  386. {
  387. strQuery = _T("Snapshot//INSTANCENAME[@CLASSNAME");
  388. }
  389. else
  390. {
  391. strQuery = _T("Snapshot//INSTANCE[@CLASSNAME");
  392. }
  393. strQuery += _T("$ieq$");
  394. strQuery += _T('\"');
  395. strQuery += szClass;
  396. strQuery += _T('\"');
  397. strQuery += _T("]");
  398. long lListLen = 0;
  399. hr = this->m_pXMLDoc->getElementsByTagName(CComBSTR(strQuery),&m_pList);
  400. ASSERT(SUCCEEDED(hr) && "could not get list of instances to match this class");
  401. return hr;
  402. }
  403. //////////////////////////////////////////////////////////////////////
  404. // CXMLJelper Class
  405. //////////////////////////////////////////////////////////////////////
  406. //////////////////////////////////////////////////////////////////////
  407. // Construction/Destruction
  408. //////////////////////////////////////////////////////////////////////
  409. //extern CComPtr<IStream> g_pStream;
  410. CXMLHelper::CXMLHelper(CComPtr<IXMLDOMDocument> pXMLDoc): m_pXMLDoc(pXMLDoc)
  411. {
  412. }
  413. CXMLHelper::~CXMLHelper()
  414. {
  415. }
  416. //---------------------------------------------------------------------------
  417. // Gets a CXMLObjectCollection which contains a list of instances of the
  418. // class specified by szClass
  419. //---------------------------------------------------------------------------
  420. HRESULT CXMLHelper::Enumerate(LPCTSTR szClass, CWMIObjectCollection ** ppCollection, LPCTSTR szProperties)
  421. {
  422. CString strCorrectedClass = szClass;
  423. ASSERT(ppCollection);
  424. if (ppCollection == NULL)
  425. return E_INVALIDARG;
  426. CXMLObjectCollection * pXMLCollection;
  427. if (*ppCollection)
  428. pXMLCollection = (CXMLObjectCollection *) *ppCollection;
  429. else
  430. pXMLCollection = new CXMLObjectCollection(m_pXMLDoc);
  431. if (pXMLCollection == NULL)
  432. return E_FAIL; // TBD - memory failure
  433. HRESULT hr = pXMLCollection->Create(strCorrectedClass, szProperties);
  434. if (SUCCEEDED(hr))
  435. *ppCollection = (CWMIObjectCollection *) pXMLCollection;
  436. else
  437. delete pXMLCollection;
  438. return hr;
  439. }
  440. //---------------------------------------------------------------------------
  441. // finds the instance node that matches szObjectPath, and stores the node
  442. // in a CXMLObject
  443. // szObjectPath will be something like "Win32_DMAChannel.DMAChannel=2"
  444. //---------------------------------------------------------------------------
  445. HRESULT CXMLHelper::GetObject(LPCTSTR szObjectPath, CWMIObject ** ppObject)
  446. {
  447. ASSERT(ppObject);
  448. if (ppObject == NULL)
  449. return E_INVALIDARG;
  450. //
  451. //strip everything to left of ":"
  452. CString strPath(szObjectPath);
  453. int i = strPath.Find(_T(":"));
  454. if (i > -1)
  455. {
  456. strPath = strPath.Right(strPath.GetLength() - i - 1);
  457. }
  458. i = strPath.Find(_T("."));
  459. //separate the string into resource type (e.g. Win32_DMAChannel)
  460. CString strClassName;
  461. if (i > -1)
  462. {
  463. strClassName = strPath.Left(i);
  464. strPath = strPath.Right(strPath.GetLength() - i - 1);
  465. }
  466. //get the name of the attribute we're looking for in the XML file:
  467. CString strPropertyName;
  468. CString strPropertyValue;
  469. i = strPath.Find(_T("="));
  470. if (i > -1)
  471. {
  472. strPropertyName = strPath.Left(i);
  473. strPath = strPath.Right(strPath.GetLength() - i - 1);
  474. //get the value that we need to match in the antecedent
  475. strPropertyValue = strPath;
  476. }
  477. //Create the XML Query pattern to find a node that matches
  478. CString strQuery = _T("Snapshot//INSTANCE[@CLASSNAME $ieq$ ");
  479. strQuery += _T("\"");
  480. strQuery += strClassName;
  481. strQuery += _T("\"");
  482. strQuery += _T("]/PROPERTY[@NAME $ieq$ ");
  483. strQuery += _T("\"");
  484. strQuery += strPropertyName;
  485. strQuery += _T("\"]");
  486. CComBSTR bstrQuery(strQuery);
  487. CComPtr<IXMLDOMNodeList> pList;
  488. HRESULT hr;
  489. hr = m_pXMLDoc->getElementsByTagName(bstrQuery,&pList);
  490. if (FAILED(hr) || !pList)
  491. {
  492. return E_FAIL;
  493. }
  494. //find the node whose KEYVALUE node's value matches strPropertyValue
  495. long lListLen;
  496. hr = pList->get_length(&lListLen);
  497. for(int n = 0; n < lListLen; n++)
  498. {
  499. CComPtr<IXMLDOMNode> pNode;
  500. hr = pList->nextNode(&pNode);
  501. if (FAILED(hr) || !pNode)
  502. {
  503. return E_FAIL;
  504. }
  505. CComBSTR bstrValue;
  506. hr = pNode->get_text(&bstrValue);
  507. USES_CONVERSION;
  508. CString strValue = OLE2A(bstrValue);
  509. if (strValue.CompareNoCase(strPropertyValue) == 0)
  510. {
  511. CComPtr<IXMLDOMNode> pInstanceNode;
  512. hr = pNode->get_parentNode(&pInstanceNode);
  513. if (FAILED(hr) || !pInstanceNode)
  514. {
  515. ASSERT(0 && "could not get parent node of PROPERTY");
  516. return E_FAIL;
  517. }
  518. CXMLObject* pObject = new CXMLObject();
  519. pObject->Create(pInstanceNode,strClassName);
  520. *ppObject = pObject;
  521. return S_OK;
  522. }
  523. }
  524. return E_FAIL;
  525. };
  526. //---------------------------------------------------------------------------
  527. //Gets the text from the sub (child) node of pNode which is selected by bstrQuery
  528. //---------------------------------------------------------------------------
  529. HRESULT GetSubnodeText(CComPtr<IXMLDOMNode> pNode,CComBSTR bstrQuery, CString& strText)
  530. {
  531. HRESULT hr;
  532. CComPtr<IXMLDOMNode> pSubNode;
  533. hr = pNode->selectSingleNode(bstrQuery,&pSubNode);
  534. if (!SUCCEEDED(hr) || !pSubNode)
  535. {
  536. ASSERT(0 && "xml query matched no nodes");
  537. return E_FAIL;
  538. }
  539. CComBSTR bstrText;
  540. hr = pSubNode->get_text(&bstrText);
  541. ASSERT(SUCCEEDED(hr));
  542. USES_CONVERSION;
  543. strText = OLE2A(bstrText);
  544. return hr;
  545. }
  546. //---------------------------------------------------------------------------
  547. // Gets the Antecedent node component of an Association
  548. // m_pNode is probably an INSTANCE of Win32_PnPAllocatedResource;
  549. // we need to search for /PROPERTY.REFERENCE
  550. //---------------------------------------------------------------------------
  551. HRESULT CXMLObject::GetAntecedent(CString* pstrAntecedent)
  552. {
  553. HRESULT hr;
  554. CString strWMIPath;
  555. CComPtr<IXMLDOMNode> pSubNode;
  556. hr = m_pNode->selectSingleNode(CComBSTR(_T("KEYBINDING[@NAME $ieq$ \"Antecedent\"]")),&pSubNode);
  557. ASSERT(SUCCEEDED(hr));
  558. if (!SUCCEEDED(hr) || !pSubNode)
  559. {
  560. return E_FAIL;
  561. }
  562. CString strTemp;
  563. hr = GetSubnodeText(pSubNode,CComBSTR(_T("VALUE.REFERENCE/INSTANCEPATH/NAMESPACEPATH/HOST")),strTemp);
  564. ASSERT(SUCCEEDED(hr));
  565. strWMIPath = _T("\\\\");
  566. strWMIPath += strTemp;
  567. strWMIPath += _T("\\root");
  568. strWMIPath += _T("\\cimv2");
  569. CComPtr<IXMLDOMNode> pInstanceNode;
  570. hr = pSubNode->selectSingleNode(CComBSTR(_T("VALUE.REFERENCE/INSTANCEPATH/INSTANCENAME")),&pInstanceNode);
  571. CComPtr<IXMLDOMElement> pElement;
  572. hr = pInstanceNode->QueryInterface(IID_IXMLDOMElement,(void**) &pElement);
  573. if (!SUCCEEDED(hr) || !pElement)
  574. {
  575. return E_FAIL;
  576. }
  577. CComVariant varElement;
  578. hr = pElement->getAttribute(CComBSTR("CLASSNAME"),&varElement);
  579. pElement.Release();
  580. ASSERT(SUCCEEDED(hr));
  581. if (FAILED(hr))
  582. {
  583. return E_FAIL;
  584. }
  585. strWMIPath += _T(":");
  586. USES_CONVERSION;
  587. strWMIPath += OLE2A(varElement.bstrVal);
  588. //now get the "Keybinding Name"
  589. pInstanceNode.Release();
  590. pElement.Release();
  591. hr = pSubNode->selectSingleNode(CComBSTR(_T("VALUE.REFERENCE/INSTANCEPATH/INSTANCENAME/KEYBINDING")),&pInstanceNode);
  592. ASSERT(SUCCEEDED(hr));
  593. hr = pInstanceNode->QueryInterface(IID_IXMLDOMElement,(void**) &pElement);
  594. if (!SUCCEEDED(hr) || !pElement)
  595. {
  596. return E_FAIL;
  597. }
  598. hr = pElement->getAttribute(CComBSTR("NAME"),&varElement);
  599. if (!SUCCEEDED(hr) || !pElement)
  600. {
  601. return E_FAIL;
  602. }
  603. strWMIPath += _T(".");
  604. strWMIPath += OLE2A(varElement.bstrVal);
  605. //now get value on right of =
  606. CComBSTR bstrValue;
  607. hr = pInstanceNode->get_text(&bstrValue);
  608. strWMIPath += _T("=");
  609. strWMIPath += OLE2A(bstrValue);
  610. pInstanceNode.Release();
  611. pElement.Release();
  612. *pstrAntecedent = strWMIPath;
  613. return hr;
  614. }
  615. //---------------------------------------------------------------------------
  616. // Gets the Dependent node component of an Association
  617. // m_pNode is probably an INSTANCE of Win32_PnPAllocatedResource;
  618. // we need to search for /PROPERTY.REFERENCE
  619. //---------------------------------------------------------------------------
  620. HRESULT CXMLObject::GetDependent(CString* pstrDependent)
  621. {
  622. HRESULT hr;
  623. CString strWMIPath;
  624. CComPtr<IXMLDOMNode> pSubNode;
  625. hr = this->m_pNode->selectSingleNode(CComBSTR(_T("KEYBINDING[@NAME $ieq$ \"Dependent\"]")),&pSubNode);
  626. ASSERT(SUCCEEDED(hr));
  627. if (!SUCCEEDED(hr) || !pSubNode)
  628. {
  629. return E_FAIL;
  630. }
  631. CString strTemp;
  632. hr = GetSubnodeText(pSubNode,CComBSTR(_T("VALUE.REFERENCE/INSTANCEPATH/NAMESPACEPATH/HOST")),strTemp);
  633. ASSERT(SUCCEEDED(hr));
  634. strWMIPath = _T("\\\\");
  635. strWMIPath += strTemp;
  636. strWMIPath += _T("\\root");
  637. strWMIPath += _T("\\cimv2");
  638. CComPtr<IXMLDOMNode> pInstanceNode;
  639. hr = pSubNode->selectSingleNode(CComBSTR(_T("VALUE.REFERENCE/INSTANCEPATH/INSTANCENAME")),&pInstanceNode);
  640. CComPtr<IXMLDOMElement> pElement;
  641. hr = pInstanceNode->QueryInterface(IID_IXMLDOMElement,(void**) &pElement);
  642. if (!SUCCEEDED(hr) || !pElement)
  643. {
  644. return E_FAIL;
  645. }
  646. CComVariant varElement;
  647. hr = pElement->getAttribute(CComBSTR("CLASSNAME"),&varElement);
  648. pElement.Release();
  649. ASSERT(SUCCEEDED(hr));
  650. if (FAILED(hr))
  651. {
  652. return E_FAIL;
  653. }
  654. strWMIPath += _T(":");
  655. USES_CONVERSION;
  656. strWMIPath += OLE2A(varElement.bstrVal);
  657. //now get the "Keybinding Name"
  658. pInstanceNode.Release();
  659. pElement.Release();
  660. hr = pSubNode->selectSingleNode(CComBSTR(_T("VALUE.REFERENCE/INSTANCEPATH/INSTANCENAME/KEYBINDING")),&pInstanceNode);
  661. ASSERT(SUCCEEDED(hr));
  662. hr = pInstanceNode->QueryInterface(IID_IXMLDOMElement,(void**) &pElement);
  663. if (!SUCCEEDED(hr) || !pElement)
  664. {
  665. return E_FAIL;
  666. }
  667. hr = pElement->getAttribute(CComBSTR("NAME"),&varElement);
  668. if (!SUCCEEDED(hr) || !pElement)
  669. {
  670. return E_FAIL;
  671. }
  672. strWMIPath += _T(".");
  673. strWMIPath += OLE2A(varElement.bstrVal);
  674. //now get value on right of =
  675. pInstanceNode.Release();
  676. pElement.Release();
  677. hr = pSubNode->selectSingleNode(CComBSTR("VALUE.REFERENCE/INSTANCEPATH/INSTANCENAME/KEYBINDING/KEYVALUE"),&pInstanceNode);
  678. ASSERT(SUCCEEDED(hr));
  679. hr = pInstanceNode->QueryInterface(IID_IXMLDOMElement,(void**) &pElement);
  680. if (!SUCCEEDED(hr) || !pElement)
  681. {
  682. return E_FAIL;
  683. }
  684. hr = pElement->getAttribute(CComBSTR("VALUETYPE"),&varElement);
  685. CComBSTR bstrText;
  686. hr = pInstanceNode->get_text(&bstrText);
  687. if (!SUCCEEDED(hr) || !pElement)
  688. {
  689. return E_FAIL;
  690. }
  691. strWMIPath += _T("=");
  692. strWMIPath += OLE2A(bstrText);
  693. *pstrDependent = strWMIPath;
  694. return S_OK;
  695. }
  696. //---------------------------------------------------------------------------
  697. // Gets a pseudo WMI path from an INSTANCE node
  698. //---------------------------------------------------------------------------
  699. HRESULT CXMLObject::GetPath(CString* strPath)
  700. {
  701. HRESULT hr;
  702. *strPath = _T("\\\\A-STEPHL500\\root\\cimv2");
  703. *strPath += _T(":");
  704. *strPath += this->m_strClassName;
  705. *strPath += _T(".");
  706. CString strDependent;
  707. //Get INSTANCEPATH node, which is previous sibling to INSTANCE
  708. ASSERT(m_pNode != NULL && "NULL m_pNode");
  709. CComPtr<IXMLDOMNode> pInstancePathNode;
  710. hr = m_pNode->get_previousSibling(&pInstancePathNode);
  711. if (FAILED(hr) || !pInstancePathNode)
  712. {
  713. ASSERT(0 && "could not get INSTANCEPATH node from m_pNode");
  714. return E_FAIL;
  715. }
  716. // get INSTANCENAME
  717. CComPtr<IXMLDOMNode> pInstanceNameNode;
  718. hr = pInstancePathNode->selectSingleNode(CComBSTR(_T("INSTANCENAME")),&pInstanceNameNode);
  719. if (FAILED(hr) || !pInstanceNameNode)
  720. {
  721. ASSERT(0 && "could not get INSTANCENAME node from m_pNode");
  722. return E_FAIL;
  723. }
  724. // get KEYBINDING
  725. CComPtr<IXMLDOMNode> pKeyBindingNode;
  726. //hr = pInstanceNameNode->selectSingleNode(CComBSTR("KEYBINDING"),&pKeyBindingNode);
  727. hr = pInstanceNameNode->get_firstChild(&pKeyBindingNode);
  728. if (FAILED(hr) || !pKeyBindingNode)
  729. {
  730. ASSERT(0 && "could not get KEYBINDING node from m_pNode");
  731. return E_FAIL;
  732. }
  733. //get KEYBINDING name
  734. CComPtr<IXMLDOMElement> pNameElement;
  735. hr = pKeyBindingNode->QueryInterface(IID_IXMLDOMElement,(void**) &pNameElement);
  736. if (FAILED(hr) | !pNameElement)
  737. {
  738. ASSERT(0 && "could not QI pNode for Element");
  739. return E_FAIL;
  740. }
  741. CComVariant varKeybindingName;
  742. hr = pNameElement->getAttribute(CComBSTR(_T("NAME")),&varKeybindingName);
  743. if (FAILED(hr))
  744. {
  745. ASSERT(0 && "could not get NAME attribute from pNameElement");
  746. }
  747. USES_CONVERSION;
  748. *strPath += OLE2A(varKeybindingName.bstrVal);
  749. //get KEYBINDING value
  750. CComBSTR bstrKeyValue;
  751. hr = pKeyBindingNode->get_text(&bstrKeyValue);
  752. ASSERT(SUCCEEDED(hr) && "failed to get keybinding value");
  753. *strPath += _T("=");
  754. *strPath += OLE2A(bstrKeyValue);
  755. return S_OK;
  756. }
  757. //---------------------------------------------------------------------------
  758. // Refreshes the category
  759. //---------------------------------------------------------------------------
  760. BOOL CXMLSnapshotCategory::Refresh(CXMLDataSource * pSource, BOOL fRecursive)
  761. {
  762. if (!SUCCEEDED(pSource->Refresh(this)))
  763. {
  764. return FALSE;
  765. }
  766. if (fRecursive)
  767. {
  768. for(CMSInfoCategory* pChildCat = (CMSInfoCategory*) this->GetFirstChild();pChildCat != NULL;pChildCat = (CMSInfoCategory*) pChildCat->GetNextSibling())
  769. {
  770. if(pChildCat->GetDataSourceType() == XML_SNAPSHOT)
  771. {
  772. if (!((CXMLSnapshotCategory*)pChildCat)->Refresh(pSource,fRecursive))
  773. return FALSE;
  774. }
  775. }
  776. }
  777. return TRUE;
  778. }
  779. //---------------------------------------------------------------------------
  780. //Creates a snapshot category that parallels a cagetory in the "live" tree
  781. // by copying category name, etc from pLiveCat
  782. //---------------------------------------------------------------------------
  783. CXMLSnapshotCategory::CXMLSnapshotCategory(CMSInfoLiveCategory* pLiveCat,CXMLSnapshotCategory* pParent,CXMLSnapshotCategory* pPrevSibling) :
  784. CMSInfoLiveCategory(pLiveCat->m_uiCaption,
  785. pLiveCat->m_strName,
  786. pLiveCat->m_pRefreshFunction,
  787. pLiveCat->m_dwRefreshIndex,
  788. pParent,
  789. pPrevSibling,
  790. _T(""),
  791. NULL,
  792. TRUE,
  793. ALL_ENVIRONMENTS)
  794. {
  795. m_iColCount = pLiveCat->m_iColCount;
  796. m_pRefreshFunction = pLiveCat->m_pRefreshFunction;
  797. m_strCaption = pLiveCat->m_strCaption;
  798. if (m_iColCount)
  799. {
  800. m_acolumns = new CMSInfoColumn[m_iColCount];
  801. if (m_acolumns != NULL)
  802. {
  803. m_fDynamicColumns = TRUE;
  804. for (int i = 0; i < m_iColCount; i++)
  805. {
  806. m_acolumns[i].m_strCaption = pLiveCat->m_acolumns[i].m_strCaption;
  807. m_acolumns[i].m_uiCaption = pLiveCat->m_acolumns[i].m_uiCaption;
  808. m_acolumns[i].m_uiWidth = pLiveCat->m_acolumns[i].m_uiWidth;
  809. m_acolumns[i].m_fSorts = pLiveCat->m_acolumns[i].m_fSorts;
  810. m_acolumns[i].m_fLexical = pLiveCat->m_acolumns[i].m_fLexical;
  811. m_acolumns[i].m_fAdvanced = pLiveCat->m_acolumns[i].m_fAdvanced;
  812. }
  813. }
  814. }
  815. //build tree using existing live categories
  816. CMSInfoLiveCategory* pLiveChild = (CMSInfoLiveCategory*) pLiveCat->GetFirstChild();
  817. if (pLiveChild)
  818. {
  819. m_pFirstChild = NULL;
  820. CXMLSnapshotCategory* pPrevSS = NULL;
  821. for(;pLiveChild != NULL;pLiveChild = (CMSInfoLiveCategory*) pLiveChild->GetNextSibling())
  822. {
  823. CXMLSnapshotCategory* pNewSS = new CXMLSnapshotCategory(pLiveChild,this,pPrevSS);
  824. if (m_pFirstChild == NULL)
  825. {
  826. ASSERT(pPrevSS == NULL);
  827. m_pFirstChild = pNewSS;
  828. }
  829. pPrevSS = pNewSS;
  830. }
  831. }
  832. }
  833. //---------------------------------------------------------------------------
  834. // Creates a CXMLDatasource from an XML file specified in strFileName
  835. //---------------------------------------------------------------------------
  836. HRESULT CXMLDataSource::Create(CString strFileName, CMSInfoLiveCategory* pRootLiveCat,HWND hwnd)
  837. {
  838. m_hwnd = hwnd;
  839. m_pHistoryRoot = &catHistorySystemSummary;
  840. HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  841. IID_IXMLDOMDocument, (void**)&m_pXMLDoc);
  842. if (FAILED(hr) || !m_pXMLDoc)
  843. {
  844. ASSERT(0 && "unable to create instance of IID_IXMLDOMDocument");
  845. return E_FAIL;
  846. }
  847. VARIANT_BOOL varBSuccess;
  848. try
  849. {
  850. hr = m_pXMLDoc->load(CComVariant(strFileName),&varBSuccess);
  851. if (FAILED(hr) || !varBSuccess)
  852. {
  853. ASSERT(0 && "unable to load xml document");
  854. m_pXMLDoc = NULL;
  855. return E_FAIL;
  856. }
  857. }
  858. catch(...)
  859. {
  860. m_pXMLDoc = NULL;
  861. return E_FAIL;
  862. }
  863. //TD: verify that this is looks like a valid incident file or saved DCO stream
  864. this->m_pRoot = new CXMLSnapshotCategory(pRootLiveCat,NULL,NULL);
  865. return S_OK;
  866. }
  867. //---------------------------------------------------------------------------
  868. //
  869. //---------------------------------------------------------------------------
  870. HRESULT CXMLDataSource::Refresh(CXMLSnapshotCategory* pCat)
  871. {
  872. if (pCat->GetDataSourceType() != XML_SNAPSHOT || ! pCat->m_pRefreshFunction)
  873. {
  874. return S_OK;
  875. }
  876. CoInitialize(NULL);
  877. CXMLHelper* pWMI = new CXMLHelper(m_pXMLDoc);
  878. HRESULT hrWMI = E_FAIL;
  879. if (pWMI)
  880. hrWMI = pWMI->Create(_T(""));
  881. CMapPtrToPtr mapRefreshFuncToData;
  882. CPtrList lstCategoriesToRefresh;
  883. CMSInfoLiveCategory * pLiveCategory;
  884. HRESULT hr;
  885. if (pCat->m_iColCount)
  886. {
  887. pLiveCategory = (CMSInfoLiveCategory *) pCat;
  888. if (pLiveCategory->EverBeenRefreshed())
  889. {
  890. if (pWMI)
  891. delete pWMI;
  892. return S_OK;
  893. }
  894. CPtrList * aptrList = new CPtrList[pLiveCategory->m_iColCount];
  895. if (aptrList)
  896. {
  897. // Retrieve any refresh function specific storage that may have been created.
  898. void * pRefreshData;
  899. if (!mapRefreshFuncToData.Lookup((void *)pLiveCategory->m_pRefreshFunction, pRefreshData))
  900. pRefreshData = NULL;
  901. // Call the refresh function for this category, with the refresh index.
  902. hr = pLiveCategory->m_pRefreshFunction(pWMI,
  903. pLiveCategory->m_dwRefreshIndex,
  904. NULL,
  905. aptrList,
  906. pLiveCategory->m_iColCount,
  907. &pRefreshData);
  908. pLiveCategory->m_hrError = hr;
  909. // If the refresh function allocated some storage, save it.
  910. if (pRefreshData)
  911. mapRefreshFuncToData.SetAt((void *)pLiveCategory->m_pRefreshFunction, pRefreshData);
  912. if (SUCCEEDED(pLiveCategory->m_hrError))
  913. {
  914. // Get the number of rows of data.
  915. int iRowCount = (int)aptrList[0].GetCount();
  916. #ifdef _DEBUG
  917. for (int i = 0; i < pLiveCategory->m_iColCount; i++)
  918. ASSERT(iRowCount == aptrList[i].GetCount());
  919. #endif
  920. // Update the category's current data. This has to be done in a
  921. // critical section, since the main thread accesses this data.
  922. pLiveCategory->DeleteContent();
  923. if (iRowCount)
  924. pLiveCategory->AllocateContent(iRowCount);
  925. for (int j = 0; j < pLiveCategory->m_iColCount; j++)
  926. for (int i = 0; i < pLiveCategory->m_iRowCount; i++)
  927. {
  928. CMSIValue * pValue = (CMSIValue *) aptrList[j].RemoveHead();
  929. pLiveCategory->SetData(i, j, pValue->m_strValue, pValue->m_dwValue);
  930. // Set the advanced flag for either the first column, or
  931. // for any column which is advanced (any cell in a row
  932. // being advanced makes the whole row advanced).
  933. if (j == 0 || pValue->m_fAdvanced)
  934. pLiveCategory->SetAdvancedFlag(i, pValue->m_fAdvanced);
  935. delete pValue;
  936. }
  937. pCat->m_dwLastRefresh = ::GetTickCount();
  938. }
  939. else
  940. {
  941. // The refresh was cancelled or had an error - delete the new data. If the
  942. // refresh had an error, record the time the refresh was attempted.
  943. if (FAILED(pLiveCategory->m_hrError))
  944. pCat->m_dwLastRefresh = ::GetTickCount();
  945. }
  946. for (int iCol = 0; iCol < pLiveCategory->m_iColCount; iCol++)
  947. while (!aptrList[iCol].IsEmpty()) // shouldn't be true unless refresh cancelled
  948. delete (CMSIValue *) aptrList[iCol].RemoveHead();
  949. delete [] aptrList;
  950. }
  951. }
  952. RefreshFunction pFunc;
  953. void * pCache;
  954. for (POSITION pos = mapRefreshFuncToData.GetStartPosition(); pos;)
  955. {
  956. mapRefreshFuncToData.GetNextAssoc(pos, (void * &)pFunc, pCache);
  957. if (pFunc)
  958. pFunc(NULL, 0, NULL, NULL, 0, &pCache);
  959. }
  960. mapRefreshFuncToData.RemoveAll();
  961. if (pWMI)
  962. delete pWMI;
  963. CoUninitialize();
  964. return 0;
  965. }