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.

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