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.

2612 lines
70 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1998 by Microsoft Corporation
  4. //
  5. // WBEM2XML.CPP
  6. //
  7. // alanbos 18-Feb-98 Created.
  8. //
  9. // The WBEM -> XML translator
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <wbemidl.h>
  14. #include <genlex.h>
  15. #include <opathlex.h>
  16. #include <objpath.h>
  17. #include "wmiconv.h"
  18. #include "wmi2xml.h"
  19. // This is the set of the names of properties that the control
  20. // looks for in an IWbemContext object for modifying its output
  21. const LPCWSTR CWmiToXml::s_wmiToXmlArgs[] =
  22. {
  23. L"AllowWMIExtensions", // VT_BOOL - self-explanatory
  24. L"PathLevel", // VT_I4 see typedef enum PathLevel in wmi2xml.h
  25. L"IncludeQualifiers", // VT_BOOL - self-explanatory
  26. L"IncludeClassOrigin", // VT_BOOL - self-explanatory
  27. L"LocalOnly", // VT_BOOL - local elements (methods, properties, qualifiers) are mapped.
  28. L"ExcludeSystemProperties", // VT_BOOL - Excludes any WMI System Properties
  29. };
  30. static OLECHAR *CDATASTART = OLESTR("<![CDATA[");
  31. static OLECHAR *CDATAEND = OLESTR("]]>");
  32. static OLECHAR *AMPERSAND = OLESTR("&amp;");
  33. static OLECHAR *LEFTCHEVRON = OLESTR("&lt;");
  34. static OLECHAR *RIGHTCHEVRON = OLESTR("&gt;");
  35. static BYTE XMLNEWLINE [] = { 0x0D, 0x00, 0x0A, 0x00 };
  36. extern long g_cObj;
  37. CWmiToXml::CWmiToXml()
  38. {
  39. m_cRef = 0;
  40. m_iPathLevel = pathLevelAnonymous; // RAJESHR - Is this a good default
  41. m_bAllowWMIExtensions = VARIANT_TRUE;
  42. m_bLocalOnly = VARIANT_FALSE; // RAJESHR - Change this when core team allows us to set __RELPATH
  43. m_iQualifierFilter = wmiXMLQualifierFilterNone;
  44. m_iClassOriginFilter = wmiXMLClassOriginFilterAll;
  45. m_bExcludeSystemProperties = VARIANT_FALSE;
  46. InterlockedIncrement(&g_cObj);
  47. }
  48. //***************************************************************************
  49. //
  50. // CWmiToXml::~CWmiToXml
  51. //
  52. // DESCRIPTION:
  53. //
  54. // Destructor.
  55. //
  56. //***************************************************************************
  57. CWmiToXml::~CWmiToXml(void)
  58. {
  59. InterlockedDecrement(&g_cObj);
  60. }
  61. //***************************************************************************
  62. // HRESULT CWmiToXml::QueryInterface
  63. // long CWmiToXml::AddRef
  64. // long CWmiToXml::Release
  65. //
  66. // DESCRIPTION:
  67. //
  68. // Standard Com IUNKNOWN functions.
  69. //
  70. //***************************************************************************
  71. STDMETHODIMP CWmiToXml::QueryInterface (
  72. IN REFIID riid,
  73. OUT LPVOID *ppv
  74. )
  75. {
  76. *ppv=NULL;
  77. if (IID_IUnknown==riid)
  78. *ppv = reinterpret_cast<IUnknown*>(this);
  79. else if (IID_IWbemXMLConvertor==riid)
  80. *ppv = reinterpret_cast<IWbemXMLConvertor*>(this);
  81. if (NULL!=*ppv)
  82. {
  83. ((LPUNKNOWN)*ppv)->AddRef();
  84. return NOERROR;
  85. }
  86. return ResultFromScode(E_NOINTERFACE);
  87. }
  88. STDMETHODIMP_(ULONG) CWmiToXml::AddRef(void)
  89. {
  90. InterlockedIncrement(&m_cRef);
  91. return m_cRef;
  92. }
  93. STDMETHODIMP_(ULONG) CWmiToXml::Release(void)
  94. {
  95. InterlockedDecrement(&m_cRef);
  96. if (0L!=m_cRef)
  97. return m_cRef;
  98. delete this;
  99. return 0;
  100. }
  101. /*
  102. * This function takes in an IWbemClassObject that represents a Class and
  103. * produces a <CLASS> element in the outputstream
  104. */
  105. STDMETHODIMP CWmiToXml::MapClass (IStream *pOutputStream, IWbemClassObject *pObject, IWbemQualifierSet *pQualSet, BSTR *ppPropertyList, DWORD dwNumProperties, BSTR strClassBasis)
  106. {
  107. HRESULT hr = WBEM_E_FAILED;
  108. long flav = 0;
  109. VARIANT var;
  110. // Write the CLASS tag and its attributes
  111. //===========================================
  112. WRITEBSTR( OLESTR("<CLASS NAME=\""))
  113. // Write the CLASSNAME
  114. VariantInit (&var);
  115. if (WBEM_S_NO_ERROR == pObject->Get(L"__CLASS", 0, &var, NULL, &flav))
  116. {
  117. if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
  118. WRITEBSTR( var.bstrVal)
  119. }
  120. VariantClear (&var);
  121. WRITEBSTR( OLESTR("\""))
  122. // Write the SUPERCLASS if specified
  123. VariantInit (&var);
  124. if (WBEM_S_NO_ERROR == pObject->Get(L"__SUPERCLASS", 0, &var, NULL, &flav))
  125. {
  126. if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
  127. {
  128. WRITEBSTR( OLESTR(" SUPERCLASS=\""))
  129. WRITEBSTR( var.bstrVal)
  130. WRITEBSTR( OLESTR("\""))
  131. }
  132. }
  133. VariantClear (&var);
  134. WRITEBSTR( OLESTR(">"))
  135. WRITENEWLINE
  136. // Map the Qualifiers of the class
  137. if (pQualSet)
  138. hr = MapQualifiers (pOutputStream, pQualSet);
  139. else
  140. hr = S_OK;
  141. // Map the Properties
  142. if (SUCCEEDED(hr))
  143. hr = MapProperties(pOutputStream, pObject, ppPropertyList, dwNumProperties, strClassBasis, true);
  144. // Map the Methods
  145. if (SUCCEEDED(hr))
  146. hr = MapMethods (pOutputStream, pObject);
  147. // Terminate the CLASS element
  148. WRITEBSTR( OLESTR("</CLASS>"))
  149. WRITENEWLINE
  150. return hr;
  151. }
  152. STDMETHODIMP CWmiToXml::MapClassPath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
  153. {
  154. HRESULT hr = E_FAIL;
  155. WRITEBSTR( OLESTR("<CLASSPATH>"))
  156. WRITENEWLINE
  157. if(SUCCEEDED(hr = MapNamespacePath (pOutputStream, pParsedPath)))
  158. {
  159. WRITENEWLINE
  160. hr = MapClassName (pOutputStream, pParsedPath->m_pClass);
  161. }
  162. WRITEBSTR( OLESTR("</CLASSPATH>"))
  163. return hr;
  164. }
  165. STDMETHODIMP CWmiToXml::MapLocalClassPath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
  166. {
  167. HRESULT hr = E_FAIL;
  168. WRITEBSTR( OLESTR("<LOCALCLASSPATH>"))
  169. WRITENEWLINE
  170. if(SUCCEEDED(hr = MapLocalNamespacePath (pOutputStream, pParsedPath)))
  171. {
  172. WRITENEWLINE
  173. hr = MapClassName (pOutputStream, pParsedPath->m_pClass);
  174. }
  175. WRITEBSTR( OLESTR("</LOCALCLASSPATH>"))
  176. return hr;
  177. }
  178. STDMETHODIMP CWmiToXml::MapClassName (IStream *pOutputStream, BSTR bsClassName)
  179. {
  180. WRITEBSTR( OLESTR("<CLASSNAME NAME=\""))
  181. WRITEBSTR( bsClassName)
  182. WRITEBSTR( OLESTR("\"/>"))
  183. return S_OK;
  184. }
  185. /*
  186. * This function takes in an IWbemClassObject that represents an Instance and
  187. * produces an <INSTANCE> element in the outputstream
  188. */
  189. STDMETHODIMP CWmiToXml::MapInstance (IStream *pOutputStream, IWbemClassObject *pObject, IWbemQualifierSet *pQualSet, BSTR *ppPropertyList, DWORD dwNumProperties, BSTR strClassBasis)
  190. {
  191. HRESULT hr = WBEM_E_FAILED;
  192. // Write the beginning of the INSTANCE Tag and its attributes
  193. //===========================================================
  194. WRITEBSTR( OLESTR("<INSTANCE CLASSNAME=\""))
  195. // Write the CLASSNAME
  196. long flav = 0;
  197. VARIANT var;
  198. VariantInit (&var);
  199. if (WBEM_S_NO_ERROR == pObject->Get(L"__CLASS", 0, &var, NULL, &flav))
  200. {
  201. if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
  202. {
  203. WRITEBSTR( var.bstrVal)
  204. WRITEBSTR( OLESTR("\">"))
  205. WRITENEWLINE
  206. }
  207. }
  208. VariantClear (&var);
  209. // Map Instance Qualifiers if any
  210. if (pQualSet)
  211. hr = MapQualifiers (pOutputStream, pQualSet);
  212. else
  213. hr = S_OK;
  214. // Map the properties of the instance
  215. if(SUCCEEDED(hr))
  216. hr = MapProperties (pOutputStream, pObject, ppPropertyList, dwNumProperties, strClassBasis, false);
  217. // Terminate the INSTANCE element
  218. WRITEBSTR( OLESTR("</INSTANCE>"))
  219. WRITENEWLINE
  220. return hr;
  221. }
  222. STDMETHODIMP CWmiToXml::MapInstancePath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
  223. {
  224. WRITEBSTR( OLESTR("<INSTANCEPATH>"))
  225. WRITENEWLINE
  226. HRESULT hr = E_FAIL;
  227. if(SUCCEEDED(hr = MapNamespacePath (pOutputStream, pParsedPath)))
  228. {
  229. WRITENEWLINE
  230. hr = MapInstanceName (pOutputStream, pParsedPath);
  231. WRITENEWLINE
  232. }
  233. WRITEBSTR( OLESTR("</INSTANCEPATH>"))
  234. return hr;
  235. }
  236. STDMETHODIMP CWmiToXml::MapLocalInstancePath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
  237. {
  238. WRITEBSTR( OLESTR("<LOCALINSTANCEPATH>"))
  239. WRITENEWLINE
  240. HRESULT hr = E_FAIL;
  241. if(SUCCEEDED(hr = MapLocalNamespacePath (pOutputStream, pParsedPath)))
  242. {
  243. WRITENEWLINE
  244. hr = MapInstanceName (pOutputStream, pParsedPath);
  245. WRITENEWLINE
  246. }
  247. WRITEBSTR( OLESTR("</LOCALINSTANCEPATH>"))
  248. return hr;
  249. }
  250. STDMETHODIMP CWmiToXml::MapInstanceName (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
  251. {
  252. WRITEBSTR( OLESTR("<INSTANCENAME CLASSNAME=\""))
  253. WRITEBSTR( pParsedPath->m_pClass)
  254. WRITEBSTR( OLESTR("\">"))
  255. WRITENEWLINE
  256. // Now write the key bindings - only if not singleton
  257. if (!(pParsedPath->m_bSingletonObj))
  258. {
  259. if ((1 == pParsedPath->m_dwNumKeys) &&
  260. !((pParsedPath->m_paKeys [0])->m_pName))
  261. {
  262. // Use the short form
  263. WRITENEWLINE
  264. MapKeyValue (pOutputStream, (pParsedPath->m_paKeys [0])->m_vValue);
  265. WRITENEWLINE
  266. }
  267. else
  268. {
  269. // Write each key-value binding
  270. //=============================
  271. for (DWORD numKey = 0; numKey < pParsedPath->m_dwNumKeys; numKey++)
  272. {
  273. WRITEBSTR( OLESTR("<KEYBINDING "))
  274. // Write the key name
  275. WRITEBSTR( OLESTR(" NAME=\""))
  276. WRITEBSTR( (pParsedPath->m_paKeys [numKey])->m_pName)
  277. WRITEBSTR( OLESTR("\">"))
  278. WRITENEWLINE
  279. // Write the key value
  280. MapKeyValue (pOutputStream, (pParsedPath->m_paKeys [numKey])->m_vValue);
  281. WRITENEWLINE
  282. WRITEBSTR( OLESTR("</KEYBINDING>"))
  283. WRITENEWLINE
  284. }
  285. }
  286. }
  287. else
  288. {
  289. // Nothing to be done here, since the spec says that
  290. // INSTANCENAMEs without any keybindings are assumed to be singleton instances
  291. }
  292. WRITEBSTR( OLESTR("</INSTANCENAME>"))
  293. return S_OK;
  294. }
  295. STDMETHODIMP CWmiToXml::MapNamespacePath (IStream *pOutputStream, BSTR bsNamespacePath)
  296. {
  297. CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace);
  298. ParsedObjectPath *pParsedPath = NULL;
  299. pathParser.Parse (bsNamespacePath, &pParsedPath) ;
  300. HRESULT hr = E_FAIL;
  301. if (pParsedPath)
  302. {
  303. hr = MapNamespacePath (pOutputStream, pParsedPath);
  304. pathParser.Free(pParsedPath);
  305. }
  306. else
  307. hr = WBEM_E_INVALID_SYNTAX;
  308. return hr;
  309. }
  310. STDMETHODIMP CWmiToXml::MapNamespacePath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
  311. {
  312. WRITEBSTR( OLESTR("<NAMESPACEPATH>"))
  313. WRITENEWLINE
  314. WRITEBSTR( OLESTR("<HOST>"))
  315. if (pParsedPath->m_pServer)
  316. WRITEWSTR( pParsedPath->m_pServer)
  317. else
  318. WRITEBSTR( OLESTR("."))
  319. WRITEBSTR( OLESTR("</HOST>"))
  320. WRITENEWLINE
  321. // Map the local namespaces
  322. HRESULT hr = MapLocalNamespacePath (pOutputStream, pParsedPath);
  323. WRITEBSTR( OLESTR("</NAMESPACEPATH>"))
  324. return hr;
  325. }
  326. STDMETHODIMP CWmiToXml::MapLocalNamespacePath (IStream *pOutputStream, BSTR bsNamespacePath)
  327. {
  328. CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace);
  329. ParsedObjectPath *pParsedPath = NULL;
  330. pathParser.Parse (bsNamespacePath, &pParsedPath) ;
  331. HRESULT hr = E_FAIL;
  332. if (pParsedPath)
  333. {
  334. hr = MapLocalNamespacePath (pOutputStream, pParsedPath);
  335. pathParser.Free(pParsedPath);
  336. }
  337. else
  338. hr = E_FAIL;
  339. return hr;
  340. }
  341. STDMETHODIMP CWmiToXml::MapLocalNamespacePath (IStream *pOutputStream, ParsedObjectPath *pObjectPath)
  342. {
  343. WRITEBSTR( OLESTR("<LOCALNAMESPACEPATH>"))
  344. WRITENEWLINE
  345. // Map each of the namespace components
  346. for (DWORD dwIndex = 0; dwIndex < pObjectPath->m_dwNumNamespaces; dwIndex++)
  347. {
  348. WRITEBSTR( OLESTR("<NAMESPACE NAME=\""))
  349. WRITEWSTR( pObjectPath->m_paNamespaces [dwIndex])
  350. WRITEBSTR( OLESTR("\"/>"))
  351. WRITENEWLINE
  352. }
  353. WRITEBSTR( OLESTR("</LOCALNAMESPACEPATH>"))
  354. return WBEM_S_NO_ERROR;
  355. }
  356. STDMETHODIMP CWmiToXml::MapReferenceProperty (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, VARIANT &var, bool isArray, long flavor, bool bIsClass)
  357. {
  358. // CIM does not allow array references, only scalar references
  359. if(isArray && !m_bAllowWMIExtensions)
  360. return S_OK;
  361. HRESULT hr = WBEM_S_NO_ERROR;
  362. IWbemQualifierSet *pQualSet = NULL;
  363. if (WBEM_S_NO_ERROR == pObject->GetPropertyQualifierSet (name, &pQualSet))
  364. {
  365. // The property name
  366. if (isArray)
  367. WRITEBSTR( OLESTR("<PROPERTY.REFARRAY NAME=\""))
  368. else
  369. WRITEBSTR( OLESTR("<PROPERTY.REFERENCE NAME=\""))
  370. // The property name
  371. WRITEBSTR( name)
  372. WRITEBSTR( OLESTR("\""))
  373. // The originating class of this property
  374. BSTR propertyOrigin = NULL;
  375. if (WBEM_S_NO_ERROR == pObject->GetPropertyOrigin (name, &propertyOrigin))
  376. {
  377. MapClassOrigin (pOutputStream, propertyOrigin, bIsClass);
  378. SysFreeString(propertyOrigin);
  379. hr = S_OK;
  380. }
  381. if(SUCCEEDED(hr))
  382. MapLocal (pOutputStream, flavor);
  383. // The strong class of this property
  384. if(SUCCEEDED(hr))
  385. MapStrongType (pOutputStream, pQualSet);
  386. // Size of array
  387. if(SUCCEEDED(hr) && isArray)
  388. MapArraySize (pOutputStream, pQualSet);
  389. WRITEBSTR( OLESTR(">"))
  390. WRITENEWLINE
  391. // Map the qualifiers
  392. if(SUCCEEDED(hr))
  393. hr = MapQualifiers (pOutputStream, pQualSet);
  394. if(SUCCEEDED(hr))
  395. hr = MapReferenceValue (pOutputStream, isArray, var);
  396. if (isArray)
  397. WRITEBSTR( OLESTR("</PROPERTY.REFARRAY>"))
  398. else
  399. WRITEBSTR( OLESTR("</PROPERTY.REFERENCE>"))
  400. pQualSet->Release ();
  401. }
  402. return hr;
  403. }
  404. //***************************************************************************
  405. //
  406. // CWmiToXml::IsReference
  407. //
  408. // DESCRIPTION:
  409. //
  410. // The purpose of this function is to examine a single
  411. // VARIANT value and determine whether it represents a
  412. // reference or not.
  413. //
  414. // This is required because when mapping from a reference
  415. // property value we may encounter nested references within
  416. // the object path. Unfortunately the object path syntax
  417. // is such that we cannot be certain whether a key value
  418. // represents a reference or a string, datetime or char
  419. // property. (This is because a textual object path does
  420. // not contain as much information as its XML equivalent.)
  421. //
  422. // This function performs a heuristic test on the value to
  423. // determine whether it is a reference.
  424. //
  425. //***************************************************************************
  426. bool CWmiToXml::IsReference (VARIANT &var, ParsedObjectPath **ppObjectPath)
  427. {
  428. ParsedObjectPath *pObjectPath = NULL;
  429. *ppObjectPath = NULL;
  430. bool isValidPath = false;
  431. // RAJESHR - could get the class of which this is a property value
  432. // and retrieve the type of the current key property - that would
  433. // be the authoritative answer but it doesn't come cheap.
  434. if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
  435. {
  436. // Parse the object path
  437. CObjectPathParser parser (e_ParserAcceptRelativeNamespace);
  438. BOOL status = parser.Parse (var.bstrVal, &pObjectPath);
  439. if ((0 == status) && pObjectPath)
  440. {
  441. // If it's an instance path we should be OK
  442. if (pObjectPath->IsInstance ())
  443. isValidPath = true;
  444. else if (pObjectPath->IsClass ())
  445. {
  446. // Hmmm - could be a classpath. If we have a server
  447. // and some namespaces that would be a lot better
  448. if (pObjectPath->m_pServer && (0 < pObjectPath->m_dwNumNamespaces))
  449. {
  450. // RAJESHR - At this point we could assume that it is a reference
  451. // However, we've found a case in PCHealth where they do a
  452. // select * from Win32_ProgramGroup and it so happens that
  453. // one of the properties has a value "ntdev\rajeshr:Accessories"
  454. // which is CIM_STRING but actually matches a WMI class path
  455. // So, we need to try to connect ot this machine or namespace here
  456. // to check whether it is a classpath.
  457. }
  458. else
  459. {
  460. // A potential local class path
  461. // RAJESHR - try grabbing the class to see if it exists in
  462. // the current namespace.
  463. }
  464. }
  465. }
  466. // Apply one more heuristic - see whether it begins with "umi:"
  467. else
  468. {
  469. if(_wcsnicmp(var.bstrVal, L"umi:", wcslen(L"umi:")) == 0)
  470. isValidPath = true;
  471. }
  472. if (isValidPath)
  473. *ppObjectPath = pObjectPath;
  474. else
  475. {
  476. // Reject for now - too ambiguous
  477. parser.Free(pObjectPath);
  478. pObjectPath = NULL;
  479. }
  480. }
  481. return isValidPath;
  482. }
  483. HRESULT CWmiToXml::MapReferenceValue (IStream *pOutputStream, bool isArray, VARIANT &var)
  484. {
  485. HRESULT hr = WBEM_S_NO_ERROR;
  486. if (VT_NULL == var.vt)
  487. return WBEM_S_NO_ERROR;
  488. if (isArray)
  489. {
  490. long uBound = 0;
  491. if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
  492. return WBEM_E_FAILED;
  493. WRITEBSTR( OLESTR("<VALUE.REFARRAY>"))
  494. for (long i = 0; i<=uBound; i++)
  495. {
  496. BSTR pNextElement = NULL;
  497. if(SUCCEEDED(hr = SafeArrayGetElement(var.parray, (LONG *)&i, (LPVOID )&pNextElement )))
  498. {
  499. // Map the value - this will be a classpath or instancepath
  500. if ((NULL != pNextElement) && (wcslen (pNextElement) > 0))
  501. {
  502. // Parse the object path
  503. // We have 2 possibilities here
  504. // 1. The path is a Nova style path in which case it can be transformed into
  505. // a DMTF style VALUE.REFERENCE
  506. // 2. It is a Whistler style scoped path or an UMI path. In this case,
  507. // we have to transform it into a VALUE element (inside a VALUE.REFERENCE element)
  508. // with the exact string representation of the path
  509. // The second vase is indicated it the parsing fails.
  510. CObjectPathParser parser (e_ParserAcceptRelativeNamespace);
  511. ParsedObjectPath *pObjectPath = NULL;
  512. BOOL status = parser.Parse (pNextElement, &pObjectPath) ;
  513. // pObjectPath might be NULL here, in which case it falls under category 2 above
  514. MapReferenceValue (pOutputStream, pObjectPath, pNextElement);
  515. if (pObjectPath)
  516. parser.Free(pObjectPath);
  517. }
  518. SysFreeString(pNextElement);
  519. }
  520. }
  521. WRITEBSTR( OLESTR("</VALUE.REFARRAY>"))
  522. }
  523. else
  524. {
  525. // Map the value - this will be a classpath or instancepath
  526. if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
  527. {
  528. // Parse the object path
  529. CObjectPathParser parser (e_ParserAcceptRelativeNamespace);
  530. ParsedObjectPath *pObjectPath = NULL;
  531. BOOL status = parser.Parse (var.bstrVal, &pObjectPath) ;
  532. // We have 2 possibilities here
  533. // 1. The path is a Nova style path in which case it can be transformed into
  534. // a DMTF style VALUE.REFERENCE
  535. // 2. It is a Whistler style scoped path or an UMI path. In this case,
  536. // we have to transform it into a VALUE element (inside a VALUE.REFERENCE element)
  537. // with the exact string representation of the path
  538. // The second vase is indicated it the parsing fails.
  539. MapReferenceValue (pOutputStream, pObjectPath, var.bstrVal);
  540. if (pObjectPath)
  541. parser.Free(pObjectPath);
  542. }
  543. }
  544. return hr;
  545. }
  546. // This function maps a reference value to XML
  547. // We have 2 possibilities for the path in the reference value :
  548. // 1. The path is a Nova style path in which case it can be transformed into
  549. // a DMTF style VALUE.REFERENCE
  550. // 2. It is a Whistler style scoped path or an UMI path. In this case,
  551. // we have to transform it into a VALUE element (inside a VALUE.REFERENCE element)
  552. // with the exact string representation of the path
  553. // The second vase is indicated by a NULL value for pObjectPath, in which case, we just
  554. // use the contents of strPath
  555. void CWmiToXml::MapReferenceValue (IStream *pOutputStream, ParsedObjectPath *pObjectPath, BSTR strPath)
  556. {
  557. WRITEBSTR( OLESTR("<VALUE.REFERENCE>"))
  558. WRITENEWLINE
  559. // Is it a Nova-style or DMTF style path?
  560. if(pObjectPath)
  561. {
  562. BOOL bIsAbsolutePath = (NULL != pObjectPath->m_pServer);
  563. BOOL bIsRelativePath = FALSE;
  564. if (!bIsAbsolutePath)
  565. bIsRelativePath = (0 < pObjectPath->m_dwNumNamespaces);
  566. // Is this is a class or is it an instance?
  567. if (pObjectPath->IsClass ())
  568. {
  569. if (bIsAbsolutePath)
  570. MapClassPath (pOutputStream, pObjectPath);
  571. else if (bIsRelativePath)
  572. MapLocalClassPath (pOutputStream, pObjectPath);
  573. else
  574. MapClassName (pOutputStream, pObjectPath->m_pClass);
  575. }
  576. else if (pObjectPath->IsInstance ())
  577. {
  578. if (bIsAbsolutePath)
  579. MapInstancePath (pOutputStream, pObjectPath);
  580. else if (bIsRelativePath)
  581. MapLocalInstancePath (pOutputStream, pObjectPath);
  582. else
  583. MapInstanceName (pOutputStream, pObjectPath);
  584. }
  585. }
  586. else // Ugh it is a Whistler or WMI Path
  587. {
  588. WRITEBSTR( OLESTR("<VALUE>"))
  589. MapStringValue(pOutputStream, strPath);
  590. WRITEBSTR( OLESTR("</VALUE>"))
  591. }
  592. WRITENEWLINE
  593. WRITEBSTR( OLESTR("</VALUE.REFERENCE>"))
  594. }
  595. STDMETHODIMP CWmiToXml::MapQualifiers (IStream *pOutputStream,
  596. IWbemQualifierSet *pQualSet, IWbemQualifierSet *pQualSet2)
  597. {
  598. if (wmiXMLQualifierFilterNone != m_iQualifierFilter)
  599. {
  600. // Map the requested filter to the flags value - default is ALL
  601. LONG lFlags = 0;
  602. if (wmiXMLQualifierFilterLocal == m_iQualifierFilter)
  603. lFlags = WBEM_FLAG_LOCAL_ONLY;
  604. else if (wmiXMLQualifierFilterPropagated == m_iQualifierFilter)
  605. lFlags = WBEM_FLAG_PROPAGATED_ONLY;
  606. else if (wmiXMLQualifierFilterAll == m_iQualifierFilter)
  607. {
  608. if(m_bLocalOnly == VARIANT_TRUE)
  609. lFlags = WBEM_FLAG_LOCAL_ONLY;
  610. // Else you get all qualifiers
  611. }
  612. pQualSet->BeginEnumeration (lFlags);
  613. VARIANT var;
  614. VariantInit (&var);
  615. long flavor = 0;
  616. BSTR name = NULL;
  617. while (WBEM_S_NO_ERROR == pQualSet->Next (0, &name, &var, &flavor))
  618. {
  619. MapQualifier (pOutputStream, name, flavor, var);
  620. SysFreeString (name);
  621. name = NULL;
  622. VariantClear (&var);
  623. }
  624. pQualSet->EndEnumeration ();
  625. // Now check the subsiduary set for any qualifiers not in the first set
  626. if (pQualSet2)
  627. {
  628. pQualSet2->BeginEnumeration (lFlags);
  629. while (WBEM_S_NO_ERROR == pQualSet2->Next (0, &name, &var, &flavor))
  630. {
  631. // Is this qualifier in the primary set?
  632. if (WBEM_E_NOT_FOUND == pQualSet->Get (name, 0, NULL, NULL))
  633. MapQualifier (pOutputStream, name, flavor, var);
  634. SysFreeString (name);
  635. name = NULL;
  636. VariantClear (&var);
  637. }
  638. pQualSet2->EndEnumeration ();
  639. }
  640. }
  641. return WBEM_S_NO_ERROR;
  642. }
  643. void CWmiToXml::MapLocal (IStream *pOutputStream, long flavor)
  644. {
  645. // default is FALSE
  646. if (WBEM_FLAVOR_ORIGIN_PROPAGATED == (WBEM_FLAVOR_MASK_ORIGIN & flavor))
  647. WRITEBSTR( OLESTR(" PROPAGATED=\"true\""))
  648. }
  649. STDMETHODIMP CWmiToXml::MapQualifier (IStream *pOutputStream, BSTR name, long flavor, VARIANT &var)
  650. {
  651. // The qualifier name
  652. WRITEBSTR( OLESTR("<QUALIFIER NAME=\""))
  653. WRITEBSTR( name)
  654. WRITEBSTR( OLESTR("\""))
  655. MapLocal (pOutputStream, flavor);
  656. // The qualifier CIM type
  657. WRITEBSTR( OLESTR(" TYPE=\""))
  658. switch (var.vt & ~VT_ARRAY)
  659. {
  660. case VT_I4:
  661. WRITEBSTR( OLESTR("sint32"))
  662. break;
  663. case VT_R8:
  664. WRITEBSTR( OLESTR("real64"))
  665. break;
  666. case VT_BOOL:
  667. WRITEBSTR( OLESTR("boolean"))
  668. break;
  669. case VT_BSTR:
  670. WRITEBSTR( OLESTR("string"))
  671. break;
  672. }
  673. WRITEBSTR( OLESTR("\""))
  674. // Whether the qualifier is overridable - default is TRUE
  675. if (WBEM_FLAVOR_NOT_OVERRIDABLE == (WBEM_FLAVOR_MASK_PERMISSIONS & flavor))
  676. WRITEBSTR( OLESTR(" OVERRIDABLE=\"false\""))
  677. // Whether the qualifier is propagated to subclasses - default is TRUE
  678. if (!(WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS & flavor))
  679. WRITEBSTR( OLESTR(" TOSUBCLASS=\"false\""))
  680. // Whether the qualifier is propagated to instances - default is FALSE
  681. if ((WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE & flavor))
  682. WRITEBSTR( OLESTR(" TOINSTANCE=\"true\""))
  683. /* RAJESHR - This change has been put off until the CIM DTD gets modified
  684. * Whether the qualifier is propagated to instances - default is FALSE
  685. * This is absent from the CIM DTD
  686. if (m_bAllowWMIExtensions && (WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE & flavor))
  687. WRITEBSTR( OLESTR(" TOINSTANCE=\"true\""))
  688. */
  689. // Whether the qualifier is an amended one - default is FALSE
  690. // This is absent from the CIM DTD
  691. if (m_bAllowWMIExtensions && (WBEM_FLAVOR_AMENDED & flavor))
  692. WRITEBSTR( OLESTR(" AMENDED=\"true\""))
  693. // Currently set TRANSLATABLE as "FALSE" by default. WMI does not use this flavor
  694. WRITEBSTR( OLESTR(">"))
  695. WRITENEWLINE
  696. // Now map the value
  697. MapValue (pOutputStream, var);
  698. WRITEBSTR( OLESTR("</QUALIFIER>"))
  699. return WBEM_S_NO_ERROR;
  700. }
  701. STDMETHODIMP CWmiToXml::MapValue (IStream *pOutputStream, VARIANT &var)
  702. {
  703. if (VT_NULL == var.vt)
  704. return WBEM_S_NO_ERROR;
  705. if (var.vt & VT_ARRAY)
  706. {
  707. long uBound = 0;
  708. if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
  709. return WBEM_E_FAILED;
  710. WRITEBSTR( OLESTR("<VALUE.ARRAY>"))
  711. for (long i = 0; i <= uBound; i++)
  712. {
  713. WRITEBSTR( OLESTR("<VALUE>"))
  714. // Write the value itself
  715. switch (var.vt & ~VT_ARRAY)
  716. {
  717. case VT_I4:
  718. {
  719. long val = 0;
  720. SafeArrayGetElement (var.parray, &i, &val);
  721. MapLongValue (pOutputStream, val);
  722. }
  723. break;
  724. case VT_R8:
  725. {
  726. double val = 0;
  727. SafeArrayGetElement (var.parray, &i, &val);
  728. MapDoubleValue (pOutputStream, val);
  729. }
  730. break;
  731. case VT_BOOL:
  732. {
  733. VARIANT_BOOL val = 0;
  734. SafeArrayGetElement (var.parray, &i, &val);
  735. MapBoolValue (pOutputStream, (val) ? TRUE : FALSE);
  736. }
  737. break;
  738. case VT_BSTR:
  739. {
  740. BSTR val = NULL;
  741. SafeArrayGetElement (var.parray, &i, &val);
  742. MapStringValue (pOutputStream, val);
  743. SysFreeString (val);
  744. }
  745. break;
  746. }
  747. WRITEBSTR( OLESTR("</VALUE>"))
  748. WRITENEWLINE
  749. }
  750. WRITEBSTR( OLESTR("</VALUE.ARRAY>"))
  751. }
  752. else
  753. {
  754. // Simple value
  755. WRITEBSTR( OLESTR("<VALUE>"))
  756. switch (var.vt)
  757. {
  758. case VT_I4:
  759. MapLongValue (pOutputStream, var.lVal);
  760. break;
  761. case VT_R8:
  762. MapDoubleValue (pOutputStream, var.dblVal);
  763. break;
  764. case VT_BOOL:
  765. MapBoolValue (pOutputStream, (var.boolVal) ? TRUE : FALSE);
  766. break;
  767. case VT_BSTR:
  768. MapStringValue (pOutputStream, var.bstrVal);
  769. break;
  770. }
  771. WRITEBSTR( OLESTR("</VALUE>"))
  772. }
  773. return WBEM_S_NO_ERROR;
  774. }
  775. // This function is used to create a KEYVALUE element
  776. // This element, besides having the value of the property
  777. // also has a type indicator in the form of the VALUETYPE attribute
  778. STDMETHODIMP CWmiToXml::MapKeyValue (IStream *pOutputStream, VARIANT &var)
  779. {
  780. ParsedObjectPath *pObjectPath = NULL;
  781. // This could be simple value or a reference value
  782. // Note that keys are not allowed to be arrays
  783. if (IsReference (var, &pObjectPath))
  784. {
  785. // If the above function returns true, then we're sure that the variant is of type VT_BSTR
  786. MapReferenceValue (pOutputStream, pObjectPath, var.bstrVal);
  787. delete pObjectPath;
  788. }
  789. else
  790. {
  791. // Simple value
  792. WRITEBSTR( OLESTR("<KEYVALUE"))
  793. switch (var.vt)
  794. {
  795. case VT_I4:
  796. WRITEBSTR( OLESTR(" VALUETYPE=\"numeric\">"))
  797. MapLongValue (pOutputStream, var.lVal);
  798. break;
  799. case VT_R8:
  800. WRITEBSTR( OLESTR(" VALUETYPE=\"numeric\">"))
  801. MapDoubleValue (pOutputStream, var.dblVal);
  802. break;
  803. case VT_BOOL:
  804. WRITEBSTR( OLESTR(" VALUETYPE=\"boolean\">"))
  805. MapBoolValue (pOutputStream, (var.boolVal) ? TRUE : FALSE);
  806. break;
  807. case VT_BSTR:
  808. WRITEBSTR(OLESTR(" VALUETYPE=\"string\">"))
  809. // RAJESHR - We assume that the object path parser will have suitably unescaped
  810. // the escaped characters in the object path
  811. // If this is not the case, then we need to unescape it manually
  812. MapStringValue (pOutputStream, var.bstrVal);
  813. break;
  814. }
  815. WRITEBSTR( OLESTR("</KEYVALUE>"))
  816. }
  817. return WBEM_S_NO_ERROR;
  818. }
  819. // In this function we produce PROPERTY elements for each of the properties of an IWbemClassObject
  820. // or if a property list is specified, then only for each of the properties in that list
  821. STDMETHODIMP CWmiToXml::MapProperties (IStream *pOutputStream, IWbemClassObject *pObject, BSTR *ppPropertyList, DWORD dwNumProperties, BSTR strClassBasis, bool bIsClass)
  822. {
  823. // Check to see if a property list is specified. If so, we map only those properties
  824. if (dwNumProperties && ppPropertyList)
  825. {
  826. VARIANT var;
  827. VariantInit (&var);
  828. long flavor = 0;
  829. CIMTYPE cimtype = CIM_ILLEGAL;
  830. for (DWORD i = 0; i < dwNumProperties; i++)
  831. {
  832. // A class basis may be optionally specified for this class
  833. // this happens in case of Enumerations and we have to filter out derived class properties
  834. // since the DMTF concept of SHALLOW enumeration is differnet from WMI's definition
  835. if (PropertyDefinedForClass (pObject, ppPropertyList [i], strClassBasis))
  836. {
  837. if (WBEM_S_NO_ERROR == pObject->Get (ppPropertyList [i], 0, &var, &cimtype, &flavor))
  838. {
  839. switch (cimtype & ~CIM_FLAG_ARRAY)
  840. {
  841. case CIM_OBJECT:
  842. MapObjectProperty (pOutputStream, pObject, ppPropertyList [i], var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
  843. break;
  844. case CIM_REFERENCE:
  845. MapReferenceProperty (pOutputStream, pObject, ppPropertyList [i], var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor,bIsClass);
  846. break;
  847. default:
  848. MapProperty (pOutputStream, pObject, ppPropertyList [i], var, cimtype & ~CIM_FLAG_ARRAY,
  849. (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
  850. break;
  851. }
  852. VariantClear (&var);
  853. }
  854. }
  855. }
  856. }
  857. else
  858. {
  859. // Note that we cannot set the LOCAL_ONLY flag for the enumeration since this is mutually exclusive
  860. // with the NONSYSTEM Flag.
  861. // Hence we use the property flavour to check whether it is local or not below.
  862. // We dont want System propertied going to DMTF servers
  863. if(SUCCEEDED(pObject->BeginEnumeration (
  864. (m_bAllowWMIExtensions == VARIANT_FALSE || m_bExcludeSystemProperties == VARIANT_TRUE)? WBEM_FLAG_NONSYSTEM_ONLY : 0)))
  865. {
  866. VARIANT var;
  867. VariantInit (&var);
  868. long flavor = 0;
  869. CIMTYPE cimtype = CIM_ILLEGAL;
  870. BSTR name = NULL;
  871. while (WBEM_S_NO_ERROR == pObject->Next (0, &name, &var, &cimtype, &flavor))
  872. {
  873. // If only local properties are being asked for, then skip this if it is not local
  874. // Dont skip system properties though
  875. if(m_bLocalOnly == VARIANT_FALSE ||
  876. (m_bLocalOnly == VARIANT_TRUE &&
  877. ((flavor == WBEM_FLAVOR_ORIGIN_LOCAL) || (flavor == WBEM_FLAVOR_ORIGIN_SYSTEM)) ))
  878. {
  879. // A class basis may be optionally specified for this call
  880. // this happens in case of Enumerations and we have to filter out derived class properties
  881. // since the DMTF concept of SHALLOW enumeration is differnet from WMI's definition
  882. if (PropertyDefinedForClass (pObject, name,strClassBasis))
  883. {
  884. switch (cimtype & ~CIM_FLAG_ARRAY)
  885. {
  886. case CIM_OBJECT:
  887. MapObjectProperty (pOutputStream, pObject, name, var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
  888. break;
  889. case CIM_REFERENCE:
  890. MapReferenceProperty (pOutputStream, pObject, name, var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
  891. break;
  892. default:
  893. MapProperty (pOutputStream, pObject, name, var, cimtype & ~CIM_FLAG_ARRAY,
  894. (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
  895. break;
  896. }
  897. }
  898. }
  899. SysFreeString (name);
  900. VariantClear (&var);
  901. }
  902. }
  903. pObject->EndEnumeration ();
  904. }
  905. return WBEM_S_NO_ERROR;
  906. }
  907. STDMETHODIMP CWmiToXml::MapProperty (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, VARIANT &var, CIMTYPE cimtype,
  908. BOOL isArray, long flavor, bool bIsClass)
  909. {
  910. HRESULT hr = WBEM_S_NO_ERROR;
  911. // The property name
  912. if (isArray)
  913. WRITEBSTR( OLESTR("<PROPERTY.ARRAY NAME=\""))
  914. else
  915. WRITEBSTR( OLESTR("<PROPERTY NAME=\""))
  916. WRITEBSTR( name)
  917. WRITEBSTR( OLESTR("\""));
  918. // The originating class of this property
  919. BSTR propertyOrigin = NULL;
  920. if (WBEM_S_NO_ERROR == pObject->GetPropertyOrigin (name, &propertyOrigin))
  921. {
  922. MapClassOrigin (pOutputStream, propertyOrigin, bIsClass);
  923. SysFreeString(propertyOrigin);
  924. }
  925. MapLocal (pOutputStream, flavor);
  926. // The property CIM type
  927. hr = MapType (pOutputStream, cimtype);
  928. // Get the Qualifier Set of the property at this time
  929. // Note that system properties do not have qualifiers sets
  930. // Map the Array Size attribute if this is an array type
  931. IWbemQualifierSet *pQualSet= NULL;
  932. if (SUCCEEDED(hr) && (_wcsnicmp(name, L"__", 2) != 0) )
  933. {
  934. if(WBEM_S_NO_ERROR == (hr = pObject->GetPropertyQualifierSet (name, &pQualSet)))
  935. {
  936. if (isArray)
  937. MapArraySize (pOutputStream, pQualSet);
  938. }
  939. }
  940. WRITEBSTR( OLESTR(">"))
  941. WRITENEWLINE
  942. // Map the qualifiers (note that system properties have no qualifiers)
  943. if(SUCCEEDED(hr) && pQualSet)
  944. hr = MapQualifiers (pOutputStream, pQualSet);
  945. // Now map the value
  946. if(SUCCEEDED(hr))
  947. hr = MapValue (pOutputStream, cimtype, isArray, var);
  948. if (isArray)
  949. WRITEBSTR( OLESTR("</PROPERTY.ARRAY>"))
  950. else
  951. WRITEBSTR( OLESTR("</PROPERTY>"))
  952. if(pQualSet)
  953. pQualSet->Release ();
  954. return hr;
  955. }
  956. STDMETHODIMP CWmiToXml::MapObjectProperty (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, VARIANT &var,
  957. BOOL isArray, long flavor, bool bIsClass)
  958. {
  959. HRESULT hr = WBEM_S_NO_ERROR;
  960. IWbemQualifierSet *pQualSet= NULL;
  961. /*
  962. * Only map embedded objects when WMI extensions are allowed
  963. */
  964. if (m_bAllowWMIExtensions)
  965. {
  966. if (WBEM_S_NO_ERROR == (hr = pObject->GetPropertyQualifierSet (name, &pQualSet)))
  967. {
  968. // The property name
  969. if (isArray)
  970. WRITEBSTR( OLESTR("<PROPERTY.OBJECTARRAY NAME=\""))
  971. else
  972. WRITEBSTR( OLESTR("<PROPERTY.OBJECT NAME=\""))
  973. WRITEBSTR( name)
  974. WRITEBSTR( OLESTR("\""));
  975. // The originating class of this property
  976. BSTR propertyOrigin = NULL;
  977. if (WBEM_S_NO_ERROR == pObject->GetPropertyOrigin (name, &propertyOrigin))
  978. {
  979. MapClassOrigin (pOutputStream, propertyOrigin, bIsClass);
  980. SysFreeString(propertyOrigin);
  981. }
  982. MapLocal (pOutputStream, flavor);
  983. MapStrongType (pOutputStream, pQualSet);
  984. if (isArray)
  985. MapArraySize (pOutputStream, pQualSet);
  986. WRITEBSTR( OLESTR(">"))
  987. WRITENEWLINE
  988. MapQualifiers (pOutputStream, pQualSet);
  989. // Now map the value
  990. hr = MapEmbeddedObjectValue (pOutputStream, isArray, var);
  991. if (isArray)
  992. WRITEBSTR( OLESTR("</PROPERTY.OBJECTARRAY>"))
  993. else
  994. WRITEBSTR( OLESTR("</PROPERTY.OBJECT>"))
  995. pQualSet->Release ();
  996. }
  997. }
  998. return hr;
  999. }
  1000. void CWmiToXml::MapArraySize (IStream *pOutputStream, IWbemQualifierSet *pQualSet)
  1001. {
  1002. // RAJESHR - RAID 29167 covers the fact that case (1) below
  1003. // should not be valid (but this is what the MOF compiler
  1004. // does) - need to change the code when that bug is fixed
  1005. // to be more strict.
  1006. /*
  1007. * We defined the ARRAYSIZE element if the qualifier set
  1008. * satisfies one of the following constraints:
  1009. *
  1010. * 1) MAX is present with a positive integer value, and MIN
  1011. * is absent.
  1012. *
  1013. * 2) MAX and MIN are both present, with the same positive
  1014. * integer value.
  1015. */
  1016. VARIANT var;
  1017. VariantInit (&var);
  1018. BOOL isFixed = FALSE;
  1019. if (WBEM_S_NO_ERROR == pQualSet->Get(L"MAX", 0, &var, NULL))
  1020. {
  1021. if ((V_VT(&var) == VT_I4) && (0 < var.lVal))
  1022. {
  1023. // Promising - have a candidate MAX value. Now
  1024. // look for a MIN
  1025. long arraySize = var.lVal;
  1026. if (WBEM_S_NO_ERROR == pQualSet->Get(L"MIN", 0, &var, NULL))
  1027. {
  1028. if ((V_VT(&var) == VT_I4) && (0 < var.lVal))
  1029. {
  1030. // Have a value - check if it's the same as MAX
  1031. isFixed = (arraySize == var.lVal);
  1032. }
  1033. }
  1034. else
  1035. isFixed = TRUE; // NO MIN only max
  1036. }
  1037. }
  1038. if (isFixed)
  1039. {
  1040. WRITEBSTR( OLESTR(" ARRAYSIZE=\""))
  1041. MapLongValue (pOutputStream, var.lVal);
  1042. WRITEBSTR( OLESTR("\""))
  1043. }
  1044. VariantClear (&var);
  1045. }
  1046. void CWmiToXml::MapStrongType (IStream *pOutputStream, IWbemQualifierSet *pQualSet)
  1047. {
  1048. VARIANT var;
  1049. VariantInit(&var);
  1050. if ((WBEM_S_NO_ERROR == pQualSet->Get(L"CIMTYPE", 0, &var, NULL))
  1051. && (VT_BSTR == var.vt))
  1052. {
  1053. // Split out the class (if any) from the ref
  1054. LPWSTR ptr = wcschr (var.bstrVal, OLECHAR(':'));
  1055. if ((NULL != ptr) && (1 < wcslen(ptr)))
  1056. {
  1057. int classLen = wcslen(ptr) - 1;
  1058. LPWSTR classPtr = NULL;
  1059. if(classPtr = new OLECHAR[classLen + 1])
  1060. {
  1061. wcscpy (classPtr, ptr+1);
  1062. BSTR pszClass = NULL;
  1063. if(pszClass = SysAllocString(classPtr))
  1064. {
  1065. WRITEBSTR( OLESTR(" REFERENCECLASS=\""))
  1066. WRITEBSTR( pszClass)
  1067. WRITEBSTR( OLESTR("\""))
  1068. SysFreeString(pszClass);
  1069. }
  1070. delete [] classPtr;
  1071. }
  1072. }
  1073. }
  1074. VariantClear(&var);
  1075. }
  1076. STDMETHODIMP CWmiToXml::MapType (IStream *pOutputStream, CIMTYPE cimtype)
  1077. {
  1078. HRESULT hr = WBEM_S_NO_ERROR;
  1079. WRITEBSTR( OLESTR(" TYPE=\""))
  1080. switch (cimtype)
  1081. {
  1082. case CIM_SINT8:
  1083. WRITEBSTR( OLESTR("sint8"))
  1084. break;
  1085. case CIM_UINT8:
  1086. WRITEBSTR( OLESTR("uint8"))
  1087. break;
  1088. case CIM_SINT16:
  1089. WRITEBSTR( OLESTR("sint16"))
  1090. break;
  1091. case CIM_UINT16:
  1092. WRITEBSTR( OLESTR("uint16"))
  1093. break;
  1094. case CIM_SINT32:
  1095. WRITEBSTR( OLESTR("sint32"))
  1096. break;
  1097. case CIM_UINT32:
  1098. WRITEBSTR( OLESTR("uint32"))
  1099. break;
  1100. case CIM_SINT64:
  1101. WRITEBSTR( OLESTR("sint64"))
  1102. break;
  1103. case CIM_UINT64:
  1104. WRITEBSTR( OLESTR("uint64"))
  1105. break;
  1106. case CIM_REAL32:
  1107. WRITEBSTR( OLESTR("real32"))
  1108. break;
  1109. case CIM_REAL64:
  1110. WRITEBSTR( OLESTR("real64"))
  1111. break;
  1112. case CIM_BOOLEAN:
  1113. WRITEBSTR( OLESTR("boolean"))
  1114. break;
  1115. case CIM_STRING:
  1116. WRITEBSTR( OLESTR("string"))
  1117. break;
  1118. case CIM_DATETIME:
  1119. WRITEBSTR( OLESTR("datetime"))
  1120. break;
  1121. case CIM_CHAR16:
  1122. WRITEBSTR( OLESTR("char16"))
  1123. break;
  1124. default:
  1125. // Don't recognize this type
  1126. hr = WBEM_E_FAILED;
  1127. }
  1128. WRITEBSTR( OLESTR("\""))
  1129. return hr;
  1130. }
  1131. STDMETHODIMP CWmiToXml::MapValue (IStream *pOutputStream, CIMTYPE cimtype, BOOL isArray, VARIANT &var)
  1132. {
  1133. if (VT_NULL == var.vt)
  1134. return WBEM_S_NO_ERROR;
  1135. if (isArray)
  1136. {
  1137. long uBound = 0;
  1138. if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
  1139. return WBEM_E_FAILED;
  1140. WRITEBSTR( OLESTR("<VALUE.ARRAY>"))
  1141. for (long i = 0; i <= uBound; i++)
  1142. {
  1143. WRITEBSTR( OLESTR("<VALUE>"))
  1144. switch (cimtype)
  1145. {
  1146. case CIM_UINT8:
  1147. {
  1148. unsigned char val = 0;
  1149. SafeArrayGetElement (var.parray, &i, &val);
  1150. MapByteValue (pOutputStream, val);
  1151. }
  1152. break;
  1153. case CIM_SINT8:
  1154. case CIM_SINT16:
  1155. {
  1156. short val = 0;
  1157. SafeArrayGetElement (var.parray, &i, &val);
  1158. MapShortValue (pOutputStream, val);
  1159. }
  1160. break;
  1161. case CIM_UINT16:
  1162. case CIM_UINT32:
  1163. case CIM_SINT32:
  1164. {
  1165. long val = 0;
  1166. SafeArrayGetElement (var.parray, &i, &val);
  1167. MapLongValue (pOutputStream, val);
  1168. }
  1169. break;
  1170. case CIM_REAL32:
  1171. {
  1172. float val = 0;
  1173. SafeArrayGetElement (var.parray, &i, &val);
  1174. MapFloatValue (pOutputStream, val);
  1175. }
  1176. break;
  1177. case CIM_REAL64:
  1178. {
  1179. double val = 0;
  1180. SafeArrayGetElement (var.parray, &i, &val);
  1181. MapDoubleValue (pOutputStream, val);
  1182. }
  1183. break;
  1184. case CIM_BOOLEAN:
  1185. {
  1186. VARIANT_BOOL val = 0;
  1187. SafeArrayGetElement (var.parray, &i, &val);
  1188. MapBoolValue (pOutputStream, (val)? TRUE : FALSE);
  1189. }
  1190. break;
  1191. case CIM_CHAR16:
  1192. {
  1193. long val = 0;
  1194. SafeArrayGetElement (var.parray, &i, &val);
  1195. MapCharValue (pOutputStream, val);
  1196. }
  1197. break;
  1198. case CIM_STRING:
  1199. {
  1200. BSTR val = NULL;
  1201. SafeArrayGetElement (var.parray, &i, &val);
  1202. MapStringValue (pOutputStream, val);
  1203. SysFreeString (val);
  1204. }
  1205. break;
  1206. case CIM_UINT64:
  1207. case CIM_SINT64:
  1208. case CIM_DATETIME:
  1209. {
  1210. BSTR val = NULL;
  1211. SafeArrayGetElement (var.parray, &i, &val);
  1212. WRITEBSTR( val)
  1213. SysFreeString(val);
  1214. }
  1215. break;
  1216. }
  1217. WRITEBSTR( OLESTR("</VALUE>"))
  1218. WRITENEWLINE
  1219. }
  1220. WRITEBSTR( OLESTR("</VALUE.ARRAY>"))
  1221. }
  1222. else
  1223. {
  1224. // Simple value
  1225. WRITEBSTR( OLESTR("<VALUE>"))
  1226. switch (cimtype)
  1227. {
  1228. case CIM_UINT8:
  1229. MapByteValue (pOutputStream, var.bVal);
  1230. break;
  1231. case CIM_SINT8:
  1232. case CIM_SINT16:
  1233. MapShortValue (pOutputStream, var.iVal);
  1234. break;
  1235. case CIM_UINT16:
  1236. case CIM_UINT32:
  1237. case CIM_SINT32:
  1238. MapLongValue (pOutputStream, var.lVal);
  1239. break;
  1240. case CIM_REAL32:
  1241. MapFloatValue (pOutputStream, var.fltVal);
  1242. break;
  1243. case CIM_REAL64:
  1244. MapDoubleValue (pOutputStream, var.dblVal);
  1245. break;
  1246. case CIM_BOOLEAN:
  1247. MapBoolValue (pOutputStream, (var.boolVal) ? TRUE : FALSE);
  1248. break;
  1249. case CIM_CHAR16:
  1250. MapCharValue (pOutputStream, var.lVal);
  1251. break;
  1252. case CIM_STRING:
  1253. MapStringValue (pOutputStream, var.bstrVal);
  1254. break;
  1255. case CIM_UINT64:
  1256. case CIM_SINT64:
  1257. case CIM_DATETIME:
  1258. WRITEBSTR( var.bstrVal)
  1259. break;
  1260. }
  1261. WRITEBSTR( OLESTR("</VALUE>"))
  1262. }
  1263. return WBEM_S_NO_ERROR;
  1264. }
  1265. STDMETHODIMP CWmiToXml::MapEmbeddedObjectValue (IStream *pOutputStream, BOOL isArray, VARIANT &var)
  1266. {
  1267. HRESULT hr = WBEM_S_NO_ERROR;
  1268. if (VT_NULL == var.vt)
  1269. return WBEM_S_NO_ERROR;
  1270. if (isArray)
  1271. {
  1272. long uBound = 0;
  1273. if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
  1274. return WBEM_E_FAILED;
  1275. WRITEBSTR(OLESTR("<VALUE.OBJECTARRAY>"))
  1276. for (long i = 0; i<=uBound; i++)
  1277. {
  1278. IUnknown *pNextElement = NULL;
  1279. if(SUCCEEDED(hr = SafeArrayGetElement(var.parray, (LONG *)&i, (LPVOID )&pNextElement )))
  1280. {
  1281. IWbemClassObject *pEmbeddedObject = NULL;
  1282. if(SUCCEEDED(hr = pNextElement->QueryInterface(IID_IWbemClassObject, (LPVOID *)&pEmbeddedObject)))
  1283. {
  1284. // Note that we always use PathLevelAnonymous here since embedded objects are VALUE.OBJECTs as per the DTD
  1285. CWmiToXml wbemToXml;
  1286. wbemToXml.m_iPathLevel = pathLevelAnonymous;
  1287. wbemToXml.m_bAllowWMIExtensions = m_bAllowWMIExtensions;
  1288. wbemToXml.m_iQualifierFilter = m_iQualifierFilter;
  1289. wbemToXml.m_iClassOriginFilter = m_iClassOriginFilter;
  1290. WRITEBSTR(OLESTR("<VALUE.OBJECT>"))
  1291. hr = wbemToXml.MapObjectToXML(pEmbeddedObject, NULL, 0, NULL, pOutputStream, NULL);
  1292. WRITEBSTR(OLESTR("</VALUE.OBJECT>"))
  1293. pEmbeddedObject->Release();
  1294. }
  1295. pNextElement->Release();
  1296. pNextElement = NULL;
  1297. }
  1298. }
  1299. WRITEBSTR(OLESTR("</VALUE.OBJECTARRAY>"))
  1300. }
  1301. else
  1302. {
  1303. // Note that we always use PathLevelAnonymous here since embedded objects are VALUE.OBJECTs as per the DTD
  1304. IWbemClassObject *pEmbeddedObject = NULL;
  1305. if(SUCCEEDED(hr = (var.punkVal)->QueryInterface(IID_IWbemClassObject, (LPVOID *)&pEmbeddedObject)))
  1306. {
  1307. WRITEBSTR(OLESTR("<VALUE.OBJECT>"))
  1308. CWmiToXml wbemToXml;
  1309. wbemToXml.m_iPathLevel = pathLevelAnonymous;
  1310. wbemToXml.m_bAllowWMIExtensions = m_bAllowWMIExtensions;
  1311. wbemToXml.m_iQualifierFilter = m_iQualifierFilter;
  1312. wbemToXml.m_iClassOriginFilter = m_iClassOriginFilter;
  1313. hr = wbemToXml.MapObjectToXML(pEmbeddedObject, NULL, 0, NULL, pOutputStream, NULL);
  1314. pEmbeddedObject->Release();
  1315. WRITEBSTR(OLESTR("</VALUE.OBJECT>"))
  1316. }
  1317. }
  1318. return WBEM_S_NO_ERROR;
  1319. }
  1320. STDMETHODIMP CWmiToXml::MapMethods (IStream *pOutputStream, IWbemClassObject *pObject)
  1321. {
  1322. HRESULT hr = WBEM_S_NO_ERROR;
  1323. // Map the requested filter (local only) to the flags value - default is ALL
  1324. LONG lFlags = 0;
  1325. if (VARIANT_TRUE == m_bLocalOnly)
  1326. lFlags = WBEM_FLAG_LOCAL_ONLY;
  1327. pObject->BeginMethodEnumeration (lFlags);
  1328. BSTR name = NULL;
  1329. IWbemClassObject *pInParams = NULL;
  1330. IWbemClassObject *pOutParams = NULL;
  1331. while (WBEM_S_NO_ERROR == pObject->NextMethod (0, &name, &pInParams, &pOutParams))
  1332. {
  1333. MapMethod (pOutputStream, pObject, name, pInParams, pOutParams);
  1334. if (pInParams)
  1335. {
  1336. pInParams->Release ();
  1337. pInParams = NULL;
  1338. }
  1339. if (pOutParams)
  1340. {
  1341. pOutParams->Release ();
  1342. pOutParams = NULL;
  1343. }
  1344. SysFreeString (name);
  1345. }
  1346. pObject->EndMethodEnumeration ();
  1347. return WBEM_S_NO_ERROR;
  1348. }
  1349. void CWmiToXml::MapMethod (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, IWbemClassObject *pInParams, IWbemClassObject *pOutParams)
  1350. {
  1351. HRESULT result = E_FAIL;
  1352. CIMTYPE returnCimtype = 0;
  1353. VARIANT vVariant;
  1354. VariantInit(&vVariant);
  1355. // First we need the return type of the method, if any
  1356. if (pOutParams)
  1357. {
  1358. if (SUCCEEDED(result = pOutParams->Get (L"ReturnValue", 0, &vVariant, &returnCimtype, NULL)))
  1359. {
  1360. switch(returnCimtype)
  1361. {
  1362. case CIM_OBJECT:
  1363. if(m_bAllowWMIExtensions)
  1364. WRITEBSTR(OLESTR("<METHOD.OBJECT NAME=\""))
  1365. else
  1366. {
  1367. // Just skip this method if WMI extensions are not allowed
  1368. VariantClear(&vVariant);
  1369. return;
  1370. }
  1371. break;
  1372. case CIM_REFERENCE:
  1373. if(m_bAllowWMIExtensions)
  1374. WRITEBSTR(OLESTR("<METHOD.REFERENCE NAME=\""))
  1375. else
  1376. {
  1377. // Just skip this method if WMI extensions are not allowed
  1378. VariantClear(&vVariant);
  1379. return;
  1380. }
  1381. break;
  1382. default:
  1383. WRITEBSTR(OLESTR("<METHOD NAME=\""))
  1384. break;
  1385. }
  1386. }
  1387. else if (result == WBEM_E_NOT_FOUND) // So this method returns a void
  1388. {
  1389. WRITEBSTR(OLESTR("<METHOD NAME=\""))
  1390. }
  1391. }
  1392. else // This method returns a VOID
  1393. {
  1394. WRITEBSTR(OLESTR("<METHOD NAME=\""))
  1395. }
  1396. // The method name
  1397. WRITEBSTR(name)
  1398. WRITEBSTR(OLESTR("\" "))
  1399. // The method return type (default is void). This is the type of
  1400. // the ReturnType property if present (otherwise defaults to void)
  1401. MapMethodReturnType(pOutputStream, &vVariant, returnCimtype, pOutParams);
  1402. VariantClear(&vVariant);
  1403. // The class origin
  1404. BSTR methodOrigin = NULL;
  1405. if (WBEM_S_NO_ERROR == pObject->GetMethodOrigin (name, &methodOrigin))
  1406. {
  1407. MapClassOrigin (pOutputStream, methodOrigin, true);
  1408. SysFreeString(methodOrigin);
  1409. }
  1410. WRITEBSTR( OLESTR(">"))
  1411. WRITENEWLINE
  1412. // Now do the qualifiers of the method
  1413. IWbemQualifierSet *pQualSet = NULL;
  1414. if (WBEM_S_NO_ERROR == pObject->GetMethodQualifierSet (name, &pQualSet))
  1415. {
  1416. MapQualifiers (pOutputStream, pQualSet);
  1417. pQualSet->Release ();
  1418. pQualSet = NULL;
  1419. }
  1420. VARIANT idVar;
  1421. VariantInit (&idVar);
  1422. idVar.vt = VT_I4;
  1423. idVar.lVal = 0;
  1424. long nextId = 0; // The next method ID to expect
  1425. long fixedIndex = 0;
  1426. // For each id,
  1427. // Get the name of the parameter (could be in, out or both)
  1428. // If just an in-parameter or just an out-parameter it's easy
  1429. // If both it's a bit tricky
  1430. //=========================================================================
  1431. while (TRUE)
  1432. {
  1433. BSTR nextInParamName = NULL;
  1434. BSTR nextOutParamName = NULL;
  1435. if (pInParams)
  1436. {
  1437. SAFEARRAY *pArray = NULL;
  1438. if (WBEM_S_NO_ERROR ==
  1439. pInParams->GetNames (L"ID", WBEM_FLAG_ONLY_IF_IDENTICAL|WBEM_FLAG_NONSYSTEM_ONLY,
  1440. &idVar, &pArray))
  1441. {
  1442. // Did we get a match?
  1443. if (pArray)
  1444. {
  1445. if ((1 == pArray->cDims) && (1 == (pArray->rgsabound[0]).cElements))
  1446. SafeArrayGetElement (pArray, &fixedIndex, &nextInParamName);
  1447. SafeArrayDestroy (pArray);
  1448. }
  1449. }
  1450. }
  1451. if (pOutParams)
  1452. {
  1453. SAFEARRAY *pArray = NULL;
  1454. if (WBEM_S_NO_ERROR ==
  1455. pOutParams->GetNames (L"ID", WBEM_FLAG_ONLY_IF_IDENTICAL|WBEM_FLAG_NONSYSTEM_ONLY,
  1456. &idVar, &pArray))
  1457. {
  1458. // Did we get a match?
  1459. if (pArray)
  1460. {
  1461. if ((1 == pArray->cDims) && (1 == (pArray->rgsabound[0]).cElements))
  1462. SafeArrayGetElement (pArray, &fixedIndex, &nextOutParamName);
  1463. SafeArrayDestroy (pArray);
  1464. }
  1465. }
  1466. }
  1467. // If [in] or [out] this is easy
  1468. if ((nextInParamName && !nextOutParamName) || (!nextInParamName && nextOutParamName))
  1469. {
  1470. VARIANT var;
  1471. VariantInit (&var);
  1472. IWbemQualifierSet *pParamQualSet = NULL;
  1473. CIMTYPE cimtype = 0;
  1474. if (nextInParamName)
  1475. {
  1476. if (WBEM_S_NO_ERROR == pInParams->Get (nextInParamName, 0, &var, &cimtype, NULL))
  1477. {
  1478. pInParams->GetPropertyQualifierSet (nextInParamName, &pParamQualSet);
  1479. MapParameter(pOutputStream, nextInParamName, pParamQualSet, cimtype);
  1480. }
  1481. }
  1482. else
  1483. {
  1484. if (WBEM_S_NO_ERROR == pOutParams->Get (nextOutParamName, 0, &var, &cimtype, NULL))
  1485. {
  1486. pOutParams->GetPropertyQualifierSet (nextOutParamName, &pParamQualSet);
  1487. MapParameter(pOutputStream, nextOutParamName, pParamQualSet, cimtype);
  1488. }
  1489. }
  1490. if (pParamQualSet)
  1491. pParamQualSet->Release ();
  1492. VariantClear (&var);
  1493. }
  1494. else if (nextInParamName && nextOutParamName)
  1495. {
  1496. // The [in,out] case and we have to do a merge
  1497. if (0 == _wcsicmp (nextInParamName, nextOutParamName))
  1498. {
  1499. VARIANT var;
  1500. VariantInit (&var);
  1501. CIMTYPE cimtype = 0;
  1502. IWbemQualifierSet *pInParamQualSet = NULL;
  1503. IWbemQualifierSet *pOutParamQualSet = NULL;
  1504. if (WBEM_S_NO_ERROR == pInParams->Get (nextInParamName, 0, &var, &cimtype, NULL))
  1505. {
  1506. pInParams->GetPropertyQualifierSet (nextInParamName, &pInParamQualSet);
  1507. pOutParams->GetPropertyQualifierSet (nextInParamName, &pOutParamQualSet);
  1508. MapParameter(pOutputStream, nextInParamName, pInParamQualSet, cimtype, pOutParamQualSet);
  1509. }
  1510. if (pInParamQualSet)
  1511. pInParamQualSet->Release ();
  1512. if (pOutParamQualSet)
  1513. pOutParamQualSet->Release ();
  1514. VariantClear (&var);
  1515. }
  1516. else
  1517. {
  1518. // Bad news - conflicting IDs in the [in] and [out] parameter set
  1519. // This cannot be a valid method definition
  1520. SysFreeString (nextInParamName);
  1521. SysFreeString (nextOutParamName);
  1522. break;
  1523. }
  1524. }
  1525. else
  1526. {
  1527. // Next id not found - stop now and break out
  1528. SysFreeString (nextInParamName);
  1529. SysFreeString (nextOutParamName);
  1530. break;
  1531. }
  1532. SysFreeString (nextInParamName);
  1533. SysFreeString (nextOutParamName);
  1534. idVar.iVal = idVar.iVal + 1;
  1535. }
  1536. switch(returnCimtype)
  1537. {
  1538. case CIM_OBJECT:
  1539. WRITEBSTR(OLESTR("</METHOD.OBJECT>"))
  1540. break;
  1541. case CIM_REFERENCE:
  1542. WRITEBSTR(OLESTR("</METHOD.REFERENCE>"))
  1543. break;
  1544. default:
  1545. WRITEBSTR(OLESTR("</METHOD>"))
  1546. break;
  1547. }
  1548. }
  1549. STDMETHODIMP CWmiToXml::MapMethodReturnType(IStream *pOutputStream, VARIANT *pValue, CIMTYPE returnCimType, IWbemClassObject *pOutputParams)
  1550. {
  1551. HRESULT hr = E_FAIL;
  1552. switch(returnCimType)
  1553. {
  1554. // Write a REFERENCECLASS
  1555. case CIM_OBJECT:
  1556. case CIM_REFERENCE:
  1557. {
  1558. IWbemQualifierSet *pQualifierSet = NULL;
  1559. if(SUCCEEDED(hr = pOutputParams->GetPropertyQualifierSet(L"ReturnValue", &pQualifierSet)))
  1560. {
  1561. // Map the type of the return class
  1562. MapStrongType(pOutputStream, pQualifierSet);
  1563. pQualifierSet->Release();
  1564. }
  1565. }
  1566. break;
  1567. default:
  1568. hr = MapType(pOutputStream, returnCimType);
  1569. break;
  1570. }
  1571. return hr;
  1572. }
  1573. void CWmiToXml::MapClassOrigin (IStream *pOutputStream, BSTR &classOrigin, bool bIsClass)
  1574. {
  1575. if ( (bIsClass && (m_iClassOriginFilter & wmiXMLClassOriginFilterClass)) ||
  1576. (m_iClassOriginFilter & wmiXMLClassOriginFilterInstance) )
  1577. {
  1578. WRITEBSTR( OLESTR(" CLASSORIGIN=\""))
  1579. WRITEBSTR( classOrigin)
  1580. WRITEBSTR( OLESTR("\""))
  1581. }
  1582. }
  1583. void CWmiToXml::MapParameter (IStream *pOutputStream, BSTR paramName,
  1584. IWbemQualifierSet *pQualSet,
  1585. CIMTYPE cimtype,
  1586. IWbemQualifierSet *pQualSet2)
  1587. {
  1588. /*
  1589. * For vanilla CIM XML we don't handle embedded object parameters
  1590. */
  1591. if ((CIM_OBJECT != (cimtype & ~CIM_FLAG_ARRAY)) || m_bAllowWMIExtensions)
  1592. {
  1593. if (cimtype & CIM_FLAG_ARRAY)
  1594. {
  1595. // Map the array parameter
  1596. if (CIM_REFERENCE == (cimtype & ~CIM_FLAG_ARRAY))
  1597. {
  1598. WRITEBSTR( OLESTR("<PARAMETER.REFARRAY NAME=\""))
  1599. WRITEBSTR( paramName)
  1600. WRITEBSTR( OLESTR("\" "))
  1601. MapStrongType (pOutputStream, pQualSet);
  1602. WRITEBSTR( OLESTR(" "))
  1603. MapArraySize (pOutputStream, pQualSet);
  1604. WRITEBSTR( OLESTR(">"))
  1605. WRITENEWLINE
  1606. // Map the qualifiers of the parameter
  1607. if (pQualSet || pQualSet2)
  1608. MapQualifiers (pOutputStream, pQualSet, pQualSet2);
  1609. WRITEBSTR( OLESTR("</PARAMETER.REFARRAY>"))
  1610. }
  1611. else if (CIM_OBJECT == (cimtype & ~CIM_FLAG_ARRAY))
  1612. {
  1613. WRITEBSTR( OLESTR("<PARAMETER.OBJECTARRAY NAME=\""))
  1614. WRITEBSTR( paramName)
  1615. WRITEBSTR( OLESTR("\" "))
  1616. MapStrongType (pOutputStream, pQualSet);
  1617. WRITEBSTR( OLESTR(" "))
  1618. MapArraySize (pOutputStream, pQualSet);
  1619. WRITEBSTR( OLESTR(">"))
  1620. WRITENEWLINE
  1621. // Map the qualifiers of the parameter
  1622. if (pQualSet || pQualSet2)
  1623. MapQualifiers (pOutputStream, pQualSet, pQualSet2);
  1624. WRITEBSTR( OLESTR("</PARAMETER.OBJECTARRAY>"))
  1625. }
  1626. else
  1627. {
  1628. WRITEBSTR( OLESTR("<PARAMETER.ARRAY NAME=\""))
  1629. WRITEBSTR( paramName)
  1630. WRITEBSTR( OLESTR("\" "))
  1631. MapType (pOutputStream, cimtype & ~CIM_FLAG_ARRAY);
  1632. WRITEBSTR( OLESTR(" "))
  1633. MapArraySize (pOutputStream, pQualSet);
  1634. WRITEBSTR( OLESTR(">"))
  1635. WRITENEWLINE
  1636. // Map the qualifiers of the parameter
  1637. if (pQualSet || pQualSet2)
  1638. MapQualifiers (pOutputStream, pQualSet, pQualSet2);
  1639. WRITEBSTR( OLESTR("</PARAMETER.ARRAY>"))
  1640. }
  1641. }
  1642. else if (cimtype == CIM_REFERENCE)
  1643. {
  1644. // Map the reference parameter
  1645. WRITEBSTR( OLESTR("<PARAMETER.REFERENCE NAME=\""))
  1646. WRITEBSTR( paramName)
  1647. WRITEBSTR( OLESTR("\" "))
  1648. MapStrongType (pOutputStream, pQualSet);
  1649. WRITEBSTR( OLESTR(">"))
  1650. WRITENEWLINE
  1651. // Map the qualifiers of the parameter
  1652. if (pQualSet || pQualSet2)
  1653. MapQualifiers (pOutputStream, pQualSet, pQualSet2);
  1654. WRITEBSTR( OLESTR("</PARAMETER.REFERENCE>"))
  1655. }
  1656. else if (cimtype == CIM_OBJECT)
  1657. {
  1658. WRITEBSTR( OLESTR("<PARAMETER.OBJECT NAME=\""))
  1659. WRITEBSTR( paramName)
  1660. WRITEBSTR( OLESTR("\" "))
  1661. MapStrongType (pOutputStream, pQualSet);
  1662. WRITEBSTR( OLESTR(">"))
  1663. WRITENEWLINE
  1664. // Map the qualifiers of the parameter
  1665. if (pQualSet || pQualSet2)
  1666. MapQualifiers (pOutputStream, pQualSet, pQualSet2);
  1667. WRITEBSTR( OLESTR("</PARAMETER.OBJECT>"))
  1668. }
  1669. else
  1670. {
  1671. // Vanilla parameter
  1672. WRITEBSTR( OLESTR("<PARAMETER NAME=\""))
  1673. WRITEBSTR( paramName)
  1674. WRITEBSTR( OLESTR("\" "))
  1675. MapType (pOutputStream, cimtype);
  1676. WRITEBSTR( OLESTR(">"))
  1677. WRITENEWLINE
  1678. // Map the qualifiers of the parameter
  1679. if (pQualSet || pQualSet2)
  1680. MapQualifiers (pOutputStream, pQualSet, pQualSet2);
  1681. WRITEBSTR( OLESTR("</PARAMETER>"))
  1682. }
  1683. }
  1684. }
  1685. void CWmiToXml::MapByteValue (IStream *pOutputStream, unsigned char val)
  1686. {
  1687. OLECHAR wStr[32];
  1688. swprintf (wStr, L"%d", val);
  1689. WRITEBSTR( wStr)
  1690. }
  1691. void CWmiToXml::MapLongValue (IStream *pOutputStream, long val)
  1692. {
  1693. OLECHAR wStr[32];
  1694. swprintf (wStr, L"%d", val);
  1695. WRITEBSTR( wStr)
  1696. }
  1697. void CWmiToXml::MapShortValue (IStream *pOutputStream, short val)
  1698. {
  1699. OLECHAR wStr[32];
  1700. swprintf (wStr, L"%d", val);
  1701. WRITEBSTR( wStr)
  1702. }
  1703. void CWmiToXml::MapDoubleValue (IStream *pOutputStream, double val)
  1704. {
  1705. VARIANT varSrc,varDst;
  1706. VariantInit(&varSrc);
  1707. VariantInit(&varDst);
  1708. varSrc.vt = VT_R8;
  1709. varSrc.dblVal = val;
  1710. if(SUCCEEDED(VariantChangeType(&varDst,&varSrc,0,VT_BSTR)))
  1711. {
  1712. MapStringValue(pOutputStream,varDst.bstrVal);
  1713. }
  1714. VariantClear(&varSrc);
  1715. VariantClear(&varDst);
  1716. }
  1717. void CWmiToXml::MapFloatValue (IStream *pOutputStream, float val)
  1718. {
  1719. VARIANT varSrc,varDst;
  1720. VariantInit(&varDst);
  1721. VariantInit(&varSrc);
  1722. varSrc.vt = VT_R4;
  1723. varSrc.fltVal = val;
  1724. if(SUCCEEDED(VariantChangeType(&varDst,&varSrc,0,VT_BSTR)))
  1725. {
  1726. MapStringValue(pOutputStream,varDst.bstrVal);
  1727. }
  1728. VariantClear(&varSrc);
  1729. VariantClear(&varDst);
  1730. }
  1731. void CWmiToXml::MapCharValue (IStream *pOutputStream, long val)
  1732. {
  1733. // As per the XML Spec, the following are invalid character values in an XML Stream:
  1734. // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
  1735. // As per the CIM Operations spec, they need to be escaped as follows:
  1736. // If the value is not a legal XML character
  1737. // (as defined in [2, section 2.2] by the Char production)
  1738. // then it MUST be escaped using a \x<hex> escape convention
  1739. // where <hex> is a hexadecimal constant consisting of
  1740. // between one and four digits
  1741. if( val < 0x9 ||
  1742. (val == 0xB || val == 0xC) ||
  1743. (val > 0xD && val <0x20) ||
  1744. (val >0xD7FF && val < 0xE000) ||
  1745. (val > 0xFFFD)
  1746. )
  1747. {
  1748. // Map it in the escaped manner
  1749. OLECHAR charStr [7];
  1750. swprintf (charStr, L"\\x%04x", val&0xffff);
  1751. charStr[6] = NULL;
  1752. WRITEBSTR( charStr)
  1753. }
  1754. else
  1755. {
  1756. // FIrst check to see if is one of the reserved characters in XML - < & and >
  1757. // Map it in the normal manner
  1758. if(val == '<')
  1759. WRITELT
  1760. else if (val == '>')
  1761. WRITEGT
  1762. else if (val == '&')
  1763. WRITEAMP
  1764. else
  1765. {
  1766. // Map it in the normal manner
  1767. WCHAR charStr [2];
  1768. swprintf (charStr, L"%c", val);
  1769. charStr[1] = NULL;
  1770. WRITEBSTR(charStr)
  1771. }
  1772. }
  1773. }
  1774. void CWmiToXml::MapBoolValue (IStream *pOutputStream, BOOL val)
  1775. {
  1776. if (TRUE == val)
  1777. WRITEBSTR( OLESTR("TRUE"))
  1778. else
  1779. WRITEBSTR( OLESTR("FALSE"))
  1780. }
  1781. void CWmiToXml::MapStringValue (IStream *pOutputStream, BSTR &val)
  1782. {
  1783. /*
  1784. * Quote from http://www.w3.org/TR/REC-xml:
  1785. *
  1786. * The ampersand character (&) and the left angle bracket (<) may
  1787. * appear in their literal form only when used as markup delimiters,
  1788. * or within a comment, a processing instruction, or a CDATA section.
  1789. *
  1790. * If they are needed elsewhere, they must be escaped using either
  1791. * numeric character references or the strings "&amp;" and "&lt;"
  1792. * respectively.
  1793. *
  1794. * The right angle bracket (>) must, for compatibility, be escaped
  1795. * using "&gt;" or a character reference when it appears in the string
  1796. * "]]>" in content, when that string is not marking the end of a CDATA
  1797. * section.
  1798. *
  1799. * In the content of elements, character data is any string of characters
  1800. * which does not contain the start-delimiter of any markup. In a CDATA
  1801. * section, character data is any string of characters not including the
  1802. * CDATA-section-close delimiter, "]]>".
  1803. */
  1804. // Check that < or & do not occur in the value
  1805. size_t length = wcslen (val);
  1806. size_t offset = 0;
  1807. OLECHAR *pWchar = NULL;
  1808. if ((offset = wcscspn (val, L"<&")) < length)
  1809. {
  1810. // A reserved character (< &) appears in the value -
  1811. // need to escape. We can use CDATA if it does not
  1812. // contain the string ]]>
  1813. if (wcsstr (val, CDATAEND))
  1814. {
  1815. // Bad luck - can't use CDATA. Have to escape
  1816. // each reserved character and the CDATAEND sequence!
  1817. // Easiest way to do this is escape all occurences
  1818. // of >.
  1819. // < -> &lt;
  1820. // & -> &amp;
  1821. // > -> &gt;
  1822. offset = wcscspn (val, L"<&>");
  1823. OLECHAR *pStr = (OLECHAR *)val;
  1824. while (TRUE)
  1825. {
  1826. // Write the initial block that's safe
  1827. if (offset > 0)
  1828. WRITEWSTRL( pStr, offset);
  1829. pStr += offset;
  1830. // Escape the offending character
  1831. if (L'<' == *pStr)
  1832. WRITELT
  1833. else if (L'>' == *pStr)
  1834. WRITEGT
  1835. else
  1836. WRITEAMP
  1837. // Skip over the reserved character
  1838. pStr += 1;
  1839. // Find the next position
  1840. if ((offset = wcscspn (pStr, L"<&>")) >= wcslen (pStr))
  1841. break;
  1842. }
  1843. // Any data left?
  1844. if (pStr && wcslen (pStr))
  1845. WRITEWSTR (pStr)
  1846. }
  1847. else
  1848. {
  1849. // Can escape the whole value inside a CDATA
  1850. WRITECDATASTART
  1851. WRITEBSTR( val)
  1852. WRITECDATAEND
  1853. }
  1854. }
  1855. else if (pWchar = wcsstr (val, CDATAEND))
  1856. {
  1857. // Yuck we need to escape the > inside this sequence
  1858. //
  1859. // ]]> -> ]]&gt;
  1860. OLECHAR *pStr = (OLECHAR *)val;
  1861. while (TRUE)
  1862. {
  1863. offset = wcslen (pStr) - wcslen (pWchar);
  1864. // Write the initial block that's safe
  1865. // (NOTE: the additional two characters for the "]]"
  1866. // which we don't need to escape)
  1867. WRITEWSTRL( pStr,(offset+2));
  1868. // Skip over the CDATAEND sequence
  1869. pStr += offset + 3;
  1870. // Escape the offending character
  1871. WRITEGT
  1872. // Find the next position
  1873. if (!(pWchar = wcsstr (pStr, CDATAEND)))
  1874. break;
  1875. }
  1876. // Any data left?
  1877. if (pStr && wcslen (pStr))
  1878. WRITEWSTR (pStr)
  1879. }
  1880. else
  1881. {
  1882. // Just write the value
  1883. WRITEBSTR( val)
  1884. }
  1885. }
  1886. void CWmiToXml::MapReturnParameter(IStream *pOutputStream, BSTR strParameterName, VARIANT &variant)
  1887. {
  1888. // Could be a PARAMETER or PARAMETER.ARRAY
  1889. if(variant.vt & VT_ARRAY)
  1890. WRITEBSTR( OLESTR("<PARAMVALUE.ARRAY NAME=\""))
  1891. else
  1892. WRITEBSTR( OLESTR("<PARAMVALUE NAME=\""))
  1893. WRITEBSTR( strParameterName);
  1894. WRITEBSTR( OLESTR("\">"));
  1895. // Convert the property value to XML
  1896. MapValue(pOutputStream, variant);
  1897. if(variant.vt & VT_ARRAY)
  1898. WRITEBSTR( OLESTR("</PARAMVALUE.ARRAY>"))
  1899. else
  1900. WRITEBSTR( OLESTR("</PARAMVALUE>"))
  1901. }
  1902. BOOL CWmiToXml::PropertyDefinedForClass (IWbemClassObject *pObject, BSTR bsPropertyName, BSTR strClassBasis)
  1903. {
  1904. BOOL result = TRUE;
  1905. // Given (a) Class basis for enumeration and
  1906. // (b) property name, determine
  1907. // (1) CLASSORIGIN of property
  1908. // (2) Dynasty of class
  1909. // And thereby check whether property was defined
  1910. // at the level of the class basis.
  1911. // If no class basis is supplied, then we always return TRUE
  1912. //============================================================
  1913. if (strClassBasis && pObject)
  1914. {
  1915. // Get Property originating class
  1916. BSTR bsOrigClass = NULL;
  1917. if (SUCCEEDED (pObject->GetPropertyOrigin (bsPropertyName, &bsOrigClass)))
  1918. {
  1919. // Derivation is the Class hierarchy of the current class or instance.
  1920. // The first element is the immediate superclass, the next is its parent,
  1921. // and so on; the last element is the base class.
  1922. // Now work through the derivation array. If we meet the
  1923. // propertys' originating class before the class basis,
  1924. // we conclude that the property was not defined in the
  1925. // class basis
  1926. // If we have been give a class basis, get the __DERIVATION
  1927. // property for each object
  1928. VARIANT vDerivation;
  1929. VariantInit(&vDerivation);
  1930. if (SUCCEEDED(pObject->Get (L"__DERIVATION", 0, &vDerivation, NULL, NULL)))
  1931. {
  1932. SAFEARRAY *pArray = vDerivation.parray;
  1933. if (pArray && (1 == pArray->cDims) && (0 < pArray->rgsabound [0].cElements))
  1934. {
  1935. int lBound = pArray->rgsabound [0].lLbound;
  1936. int uBound = pArray->rgsabound [0].cElements + lBound;
  1937. BOOL bDone = FALSE;
  1938. for (long i = lBound; (i < uBound) && !bDone; i++)
  1939. {
  1940. BSTR bsClass = NULL;
  1941. if (SUCCEEDED (SafeArrayGetElement (pArray, &i, &bsClass)))
  1942. {
  1943. if (0 == _wcsicmp (bsOrigClass, bsClass))
  1944. {
  1945. result = FALSE;
  1946. bDone = TRUE;
  1947. }
  1948. else if (0 == _wcsicmp (strClassBasis, bsClass))
  1949. bDone = TRUE;
  1950. SysFreeString (bsClass);
  1951. }
  1952. }
  1953. }
  1954. VariantClear(&vDerivation);
  1955. }
  1956. SysFreeString (bsOrigClass);
  1957. }
  1958. }
  1959. return result;
  1960. }
  1961. // Functions of the IWbemXMLConvertor interface
  1962. HRESULT STDMETHODCALLTYPE CWmiToXml::MapObjectToXML(
  1963. /* [in] */ IWbemClassObject *pObject,
  1964. /* [in] */ BSTR *ppPropertyList, DWORD dwNumProperties,
  1965. /* [in] */ IWbemContext *pInputFlags,
  1966. /* [in] */ IStream *pOutputStream,
  1967. /* [in[ */ BSTR strClassBasis)
  1968. {
  1969. // Set private members from arguments
  1970. GetFlagsFromContext(pInputFlags);
  1971. HRESULT hr = WBEM_E_FAILED;
  1972. // Is this a class or an instance?
  1973. VARIANT var;
  1974. VariantInit (&var);
  1975. long flav = 0;
  1976. bool bIsClass = false;
  1977. if (SUCCEEDED (pObject->Get(L"__GENUS", 0, &var, NULL, &flav)))
  1978. bIsClass = (WBEM_GENUS_CLASS == var.lVal);
  1979. else
  1980. bIsClass = VARIANT_FALSE; // For now, assume that it is an instance. RAJESHR is this correct?
  1981. VariantClear (&var);
  1982. // Initalize the object path
  1983. VariantInit (&var);
  1984. // For pathLevelAnonymous (anonymous objects), we dont need anything more
  1985. // For pathLevelNamed (named objects), we only need __RELPATH for a class and __RELPATH for an instance
  1986. // For pathLevelLocal, I wish core team had some concept
  1987. // of machine-relative path, but they dont and hence we need the __PATH
  1988. // For pathLevelFull, we definitely need __PATH
  1989. LPWSTR lpszPath = NULL;
  1990. switch(m_iPathLevel)
  1991. {
  1992. case pathLevelAnonymous:
  1993. break;
  1994. case pathLevelNamed:
  1995. lpszPath = L"__RELPATH";
  1996. break;
  1997. default:
  1998. lpszPath = L"__PATH";
  1999. }
  2000. // Get the object path
  2001. ParsedObjectPath *pParsedPath = NULL;
  2002. CObjectPathParser pathParser;
  2003. if(m_iPathLevel != pathLevelAnonymous)
  2004. {
  2005. if(FAILED(pObject->Get (lpszPath, 0, &var, NULL, NULL)))
  2006. return WBEM_E_FAILED;
  2007. // Now Parse it
  2008. if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
  2009. {
  2010. pathParser.Parse (var.bstrVal, &pParsedPath) ;
  2011. if(!pParsedPath)
  2012. {
  2013. VariantClear (&var);
  2014. return WBEM_E_FAILED;
  2015. }
  2016. }
  2017. else
  2018. {
  2019. VariantClear (&var);
  2020. return WBEM_E_FAILED;
  2021. }
  2022. VariantClear (&var);
  2023. }
  2024. // Get the object Qualifier Set
  2025. IWbemQualifierSet *pQualSet= NULL;
  2026. pObject->GetQualifierSet (&pQualSet);
  2027. // Whether we generate a named object or not depends
  2028. // on what was requested
  2029. if (pathLevelNamed == m_iPathLevel)
  2030. {
  2031. if(!bIsClass)
  2032. MapInstanceName(pOutputStream, pParsedPath);
  2033. // Nothing to be done for a class
  2034. }
  2035. else if (pathLevelLocal == m_iPathLevel)
  2036. {
  2037. if(bIsClass)
  2038. MapLocalClassPath(pOutputStream, pParsedPath);
  2039. else
  2040. MapLocalInstancePath(pOutputStream, pParsedPath);
  2041. }
  2042. else if (pathLevelFull == m_iPathLevel)
  2043. {
  2044. if (bIsClass)
  2045. MapClassPath (pOutputStream, pParsedPath);
  2046. else
  2047. MapInstancePath (pOutputStream, pParsedPath);
  2048. }
  2049. hr = (bIsClass) ? MapClass (pOutputStream, pObject, pQualSet, ppPropertyList, dwNumProperties, strClassBasis) :
  2050. MapInstance (pOutputStream, pObject, pQualSet, ppPropertyList, dwNumProperties, strClassBasis);
  2051. if (pQualSet)
  2052. pQualSet->Release ();
  2053. if(pParsedPath)
  2054. pathParser.Free(pParsedPath);
  2055. return hr;
  2056. }
  2057. HRESULT STDMETHODCALLTYPE CWmiToXml::MapInstanceNameToXML(
  2058. /* [in] */ BSTR strInstanceName,
  2059. /* [in] */ IWbemContext *pInputFlags,
  2060. /* [in] */ IStream *pOutputStream)
  2061. {
  2062. // Set private members from arguments
  2063. GetFlagsFromContext(pInputFlags);
  2064. HRESULT hr = WBEM_E_FAILED;
  2065. if (strInstanceName)
  2066. {
  2067. CObjectPathParser pathParser;
  2068. ParsedObjectPath *pParsedPath = NULL;
  2069. pathParser.Parse (strInstanceName, &pParsedPath) ;
  2070. if(pParsedPath)
  2071. {
  2072. hr = MapInstanceName (pOutputStream, pParsedPath);;
  2073. pathParser.Free(pParsedPath);
  2074. }
  2075. }
  2076. return hr;
  2077. }
  2078. HRESULT STDMETHODCALLTYPE CWmiToXml::MapPropertyToXML(
  2079. /* [in] */ IWbemClassObject *pObject,
  2080. /* [in] */ BSTR strPropertyName,
  2081. /* [in] */ IWbemContext *pInputFlags,
  2082. /* [in] */ IStream *pOutputStream)
  2083. {
  2084. // Set private members from arguments
  2085. GetFlagsFromContext(pInputFlags);
  2086. VARIANT var;
  2087. VariantInit (&var);
  2088. CIMTYPE cimtype;
  2089. long flavor;
  2090. HRESULT hr = pObject->Get (strPropertyName, 0, &var, &cimtype, &flavor);
  2091. if (SUCCEEDED (hr))
  2092. {
  2093. if (CIM_REFERENCE == (cimtype & ~CIM_FLAG_ARRAY))
  2094. MapReferenceValue (pOutputStream, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, var);
  2095. else
  2096. MapValue (pOutputStream, cimtype & ~CIM_FLAG_ARRAY, (cimtype & CIM_FLAG_ARRAY) ?
  2097. TRUE : FALSE, var);
  2098. }
  2099. VariantClear (&var);
  2100. return hr;
  2101. }
  2102. HRESULT STDMETHODCALLTYPE CWmiToXml::MapClassNameToXML(
  2103. /* [in] */ BSTR strClassName,
  2104. /* [in] */ IWbemContext *pInputFlags,
  2105. /* [in] */ IStream *pOutputStream)
  2106. {
  2107. MapClassName(pOutputStream, strClassName);
  2108. return S_OK;
  2109. }
  2110. HRESULT STDMETHODCALLTYPE CWmiToXml::MapInstancePathToXML(
  2111. /* [in] */ BSTR strInstancePath,
  2112. /* [in] */ IWbemContext *pInputFlags,
  2113. /* [in] */ IStream *pOutputStream)
  2114. {
  2115. // Set private members from arguments
  2116. GetFlagsFromContext(pInputFlags);
  2117. HRESULT hr = WBEM_E_FAILED;
  2118. if (strInstancePath)
  2119. {
  2120. CObjectPathParser pathParser;
  2121. ParsedObjectPath *pParsedPath = NULL;
  2122. pathParser.Parse (strInstancePath, &pParsedPath) ;
  2123. if (pParsedPath)
  2124. {
  2125. hr = MapInstancePath (pOutputStream, pParsedPath);;
  2126. pathParser.Free(pParsedPath);
  2127. }
  2128. }
  2129. return hr;
  2130. }
  2131. HRESULT STDMETHODCALLTYPE CWmiToXml::MapClassPathToXML(
  2132. /* [in] */ BSTR strClassPath,
  2133. /* [in] */ IWbemContext *pInputFlags,
  2134. /* [in] */ IStream *pOutputStream)
  2135. {
  2136. // Set private members from arguments
  2137. GetFlagsFromContext(pInputFlags);
  2138. HRESULT hr = WBEM_E_FAILED;
  2139. if (strClassPath)
  2140. {
  2141. CObjectPathParser pathParser;
  2142. ParsedObjectPath *pParsedPath = NULL;
  2143. pathParser.Parse (strClassPath, &pParsedPath) ;
  2144. if (pParsedPath)
  2145. {
  2146. hr = MapClassPath (pOutputStream, pParsedPath);;
  2147. pathParser.Free(pParsedPath);
  2148. }
  2149. }
  2150. return hr;
  2151. }
  2152. HRESULT STDMETHODCALLTYPE CWmiToXml::MapMethodResultToXML(
  2153. /* [in] */ IWbemClassObject *pMethodResult,
  2154. /* [in] */ IWbemContext *pInputFlags,
  2155. /* [in] */ IStream *pOutputStream)
  2156. {
  2157. // Set private members from arguments
  2158. GetFlagsFromContext(pInputFlags);
  2159. HRESULT hr = WBEM_E_FAILED;
  2160. // First Map the return Value
  2161. // The property "ReturnValue" indicates the return value of the method call, if any
  2162. VARIANT retValueVariant;
  2163. VariantInit(&retValueVariant);
  2164. CIMTYPE cimtype;
  2165. long flavour;
  2166. if(SUCCEEDED(pMethodResult->Get(L"ReturnValue", 0, &retValueVariant, &cimtype, &flavour)))
  2167. {
  2168. WRITEBSTR( OLESTR("<RETURNVALUE>"));
  2169. MapValue(pOutputStream, retValueVariant);
  2170. WRITEBSTR( OLESTR("</RETURNVALUE>"));
  2171. VariantClear(&retValueVariant);
  2172. }
  2173. // Map each of its non-system properties, except for the "ReturnValue" property which
  2174. // we've already mapped
  2175. if(SUCCEEDED(hr = pMethodResult->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY)))
  2176. {
  2177. BSTR strName = NULL;
  2178. VARIANT variant;
  2179. VariantInit(&variant);
  2180. while(SUCCEEDED(hr = pMethodResult->Next(0, &strName, &variant, &cimtype, &flavour)) && hr != WBEM_S_NO_MORE_DATA)
  2181. {
  2182. if(_wcsicmp(strName, L"ReturnValue") != 0)
  2183. MapReturnParameter(pOutputStream, strName, variant);
  2184. VariantClear(&variant);
  2185. }
  2186. }
  2187. return hr;
  2188. }
  2189. // Get all the flags from the IWbemContextObject
  2190. void CWmiToXml::GetFlagsFromContext(IWbemContext *pInputFlags)
  2191. {
  2192. if(pInputFlags)
  2193. {
  2194. if(SUCCEEDED(pInputFlags->BeginEnumeration(0)))
  2195. {
  2196. VARIANT vNextArgValue;
  2197. VariantInit(&vNextArgValue);
  2198. BSTR strNextArgName = NULL;
  2199. while(pInputFlags->Next(0, &strNextArgName, &vNextArgValue) != WBEM_S_NO_MORE_DATA)
  2200. {
  2201. // VARIANT_BOOL bAllowWMIExtensions,
  2202. if(_wcsicmp(s_wmiToXmlArgs[WMI_EXTENSIONS_ARG], strNextArgName) == 0)
  2203. m_bAllowWMIExtensions = vNextArgValue.boolVal;
  2204. // VARIANT_BOOL bLocalOnly,
  2205. else if(_wcsicmp(s_wmiToXmlArgs[LOCAL_ONLY_ARG], strNextArgName) == 0)
  2206. m_bLocalOnly = vNextArgValue.boolVal;
  2207. // PathLevel m_iPathLevel;
  2208. else if(_wcsicmp(s_wmiToXmlArgs[PATH_LEVEL_ARG], strNextArgName) == 0)
  2209. m_iPathLevel = (PathLevel)vNextArgValue.lVal;
  2210. // WmiXMLQualifierFilterEnum m_iQualifierFilter
  2211. else if(_wcsicmp(s_wmiToXmlArgs[QUALIFIER_FILTER_ARG], strNextArgName) == 0)
  2212. m_iQualifierFilter = (vNextArgValue.boolVal == VARIANT_TRUE)? wmiXMLQualifierFilterAll : wmiXMLQualifierFilterNone;
  2213. // WmiXMLClassOriginFilterEnum iClassOriginFilter
  2214. else if(_wcsicmp(s_wmiToXmlArgs[CLASS_ORIGIN_FILTER_ARG], strNextArgName) == 0)
  2215. m_iClassOriginFilter = (vNextArgValue.boolVal == VARIANT_TRUE) ? wmiXMLClassOriginFilterAll : wmiXMLClassOriginFilterNone;
  2216. // VARIANT_BOOL bExcludeSystemProperties
  2217. else if(_wcsicmp(s_wmiToXmlArgs[EXCLUDE_SYSTEM_PROPERTIES_ARG], strNextArgName) == 0)
  2218. m_bExcludeSystemProperties = vNextArgValue.boolVal;
  2219. VariantClear(&vNextArgValue);
  2220. }
  2221. pInputFlags->EndEnumeration();
  2222. }
  2223. }
  2224. }