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

938 lines
26 KiB

  1. //=============================================================================
  2. // This file contains the code for the classes which implement a live WMI
  3. // data source.
  4. //=============================================================================
  5. #include "stdafx.h"
  6. #include "wmilive.h"
  7. #include "resource.h"
  8. //-----------------------------------------------------------------------------
  9. // It's necessary to modify the security settings on a new WMI interface.
  10. //-----------------------------------------------------------------------------
  11. inline HRESULT ChangeWBEMSecurity(IUnknown * pUnknown)
  12. {
  13. IClientSecurity * pCliSec = NULL;
  14. HRESULT hr = pUnknown->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
  15. if (FAILED(hr))
  16. return hr;
  17. hr = pCliSec->SetBlanket(pUnknown, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
  18. pCliSec->Release();
  19. return hr;
  20. }
  21. //=============================================================================
  22. // CWMILiveObject Functions
  23. //
  24. // The constructor/destructor are really straight forward.
  25. //=============================================================================
  26. CWMILiveObject::CWMILiveObject() : m_pObject(NULL), m_pServices(NULL)
  27. {
  28. }
  29. CWMILiveObject::~CWMILiveObject()
  30. {
  31. if (m_pObject != NULL)
  32. {
  33. m_pObject->Release();
  34. m_pObject = NULL;
  35. }
  36. if (m_pServices != NULL)
  37. {
  38. m_pServices->Release();
  39. m_pServices = NULL;
  40. }
  41. }
  42. //-----------------------------------------------------------------------------
  43. // The Create functions will either create the object from a WMI object, or
  44. // from a service pointer and a path.
  45. //-----------------------------------------------------------------------------
  46. HRESULT CWMILiveObject::Create(IWbemServices * pServices, IWbemClassObject * pObject)
  47. {
  48. ASSERT(pObject && "calling CWMILiveObject::Create with a null object");
  49. if (m_pObject != NULL)
  50. m_pObject->Release();
  51. m_pObject = pObject;
  52. if (m_pObject)
  53. m_pObject->AddRef();
  54. m_pServices = pServices;
  55. if (m_pServices)
  56. m_pServices->AddRef();
  57. return S_OK;
  58. }
  59. HRESULT CWMILiveObject::Create(IWbemServices * pServices, LPCTSTR szObjectPath)
  60. {
  61. ASSERT(pServices && szObjectPath);
  62. if (m_pObject != NULL)
  63. {
  64. m_pObject->Release();
  65. m_pObject = NULL; // must be NULL or GetObject bitches
  66. }
  67. #ifdef UNICODE
  68. BSTR bstrPath = SysAllocString(szObjectPath);
  69. #else
  70. USES_CONVERSION;
  71. LPOLESTR szWidePath = T2OLE(szObjectPath);
  72. BSTR bstrPath = SysAllocString(szWidePath);
  73. #endif
  74. HRESULT hr;
  75. if (bstrPath)
  76. {
  77. hr = pServices->GetObject(bstrPath, 0L, NULL, &m_pObject, NULL);
  78. SysFreeString(bstrPath);
  79. }
  80. else
  81. hr = E_OUTOFMEMORY;
  82. m_pServices = pServices;
  83. if (m_pServices)
  84. m_pServices->AddRef();
  85. return hr;
  86. }
  87. //-----------------------------------------------------------------------------
  88. // The simple GetValue returns the named value as a variant.
  89. //
  90. // The pointer to an existing uninitialized VARIANT structure that receives
  91. // the property value, if found. Because this is an output parameter, this
  92. // method calls VariantInit on this VARIANT, so you must be sure that this
  93. // is not pointing to an active VARIANT.
  94. //
  95. // Note: You must call VariantClear on the returned VARIANT when its value
  96. // is no longer required. This will prevent memory leaks in the client process.
  97. //-----------------------------------------------------------------------------
  98. HRESULT CWMILiveObject::GetValue(LPCTSTR szProperty, VARIANT * pvarValue)
  99. {
  100. ASSERT(szProperty && pvarValue);
  101. if (m_pObject == NULL)
  102. {
  103. ASSERT(0 && "CWMILiveObject::GetValue called on a null object");
  104. return E_FAIL;
  105. }
  106. #ifdef UNICODE
  107. BSTR bstrProperty = SysAllocString(szProperty);
  108. #else
  109. USES_CONVERSION;
  110. LPOLESTR szWideProperty = T2OLE(szProperty);
  111. BSTR bstrProperty = SysAllocString(szWideProperty);
  112. #endif
  113. HRESULT hr;
  114. if (bstrProperty)
  115. {
  116. hr = m_pObject->Get(bstrProperty, 0L, pvarValue, NULL, NULL);
  117. SysFreeString(bstrProperty);
  118. if (FAILED(hr))
  119. hr = E_MSINFO_NOPROPERTY;
  120. }
  121. else
  122. hr = E_FAIL;
  123. return hr;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Get the named value as a string. Handle this even if the result is an
  127. // array of values. The caller is responsible for freeing the string.
  128. //-----------------------------------------------------------------------------
  129. HRESULT CWMILiveObject::GetValueString(LPCTSTR szProperty, CString * pstrValue)
  130. {
  131. ASSERT(pstrValue);
  132. VARIANT variant;
  133. HRESULT hr = GetValue(szProperty, &variant);
  134. if (SUCCEEDED(hr))
  135. {
  136. // If the property we just got is an array, we should convert it to string
  137. // containing a list of the items in the array.
  138. if ((variant.vt & VT_ARRAY) && (variant.vt & VT_BSTR) && variant.parray)
  139. {
  140. if (SafeArrayGetDim(variant.parray) == 1)
  141. {
  142. long lLower = 0, lUpper = 0;
  143. SafeArrayGetLBound(variant.parray, 1, &lLower);
  144. SafeArrayGetUBound(variant.parray, 1, &lUpper);
  145. CComBSTR bstrWorking;
  146. BSTR bstr = NULL;
  147. for (long i = lLower; i <= lUpper; i++)
  148. if (SUCCEEDED(SafeArrayGetElement(variant.parray, &i, (wchar_t*)&bstr)))
  149. {
  150. if (i != lLower)
  151. bstrWorking.Append(L", ");
  152. bstrWorking.AppendBSTR(bstr);
  153. }
  154. *pstrValue = bstrWorking;
  155. }
  156. }
  157. else if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK)
  158. {
  159. CComBSTR bstrWorking(V_BSTR(&variant));
  160. unsigned int i, nLength = bstrWorking.Length();
  161. BOOL fNonPrintingChar = FALSE;
  162. for (i = 0; i < nLength && !fNonPrintingChar; i++)
  163. if (((BSTR)bstrWorking)[i] < (WCHAR)0x20) // the 0x20 is from the XML spec
  164. fNonPrintingChar = TRUE;
  165. if (fNonPrintingChar)
  166. {
  167. CString strWorking;
  168. for (i = 0; i < nLength; i++)
  169. {
  170. WCHAR c = ((BSTR)bstrWorking)[i];
  171. if (c >= (WCHAR)0x20)
  172. strWorking += c;
  173. else
  174. {
  175. CString strTemp;
  176. strTemp.Format(_T("&#x%04x;"), c);
  177. strWorking += strTemp;
  178. }
  179. }
  180. *pstrValue = strWorking;
  181. }
  182. else
  183. *pstrValue = bstrWorking;
  184. }
  185. else
  186. {
  187. hr = E_MSINFO_NOVALUE;
  188. }
  189. }
  190. VariantClear(&variant);
  191. return hr;
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Get the named value as a DWORD.
  195. //-----------------------------------------------------------------------------
  196. HRESULT CWMILiveObject::GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue)
  197. {
  198. ASSERT(pdwValue);
  199. VARIANT variant;
  200. HRESULT hr = GetValue(szProperty, &variant);
  201. if (SUCCEEDED(hr))
  202. {
  203. if (VariantChangeType(&variant, &variant, 0, VT_I4) == S_OK)
  204. *pdwValue = V_I4(&variant);
  205. else
  206. hr = E_MSINFO_NOVALUE;
  207. }
  208. return hr;
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Get the named value as a SYSTEMTIME.
  212. //-----------------------------------------------------------------------------
  213. HRESULT CWMILiveObject::GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue)
  214. {
  215. ASSERT(psystimeValue);
  216. VARIANT variant;
  217. HRESULT hr = GetValue(szProperty, &variant);
  218. if (SUCCEEDED(hr))
  219. {
  220. if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK)
  221. {
  222. USES_CONVERSION;
  223. LPTSTR szDate = OLE2T(V_BSTR(&variant));
  224. // Parse the date string into the SYSTEMTIME struct. It would be better to
  225. // get the date from WMI directly, but there was a problem with this. TBD -
  226. // look into whether or not we can do this now.
  227. ZeroMemory(psystimeValue, sizeof(SYSTEMTIME));
  228. psystimeValue->wSecond = (unsigned short)_ttoi(szDate + 12); szDate[12] = _T('\0');
  229. psystimeValue->wMinute = (unsigned short)_ttoi(szDate + 10); szDate[10] = _T('\0');
  230. psystimeValue->wHour = (unsigned short)_ttoi(szDate + 8); szDate[ 8] = _T('\0');
  231. psystimeValue->wDay = (unsigned short)_ttoi(szDate + 6); szDate[ 6] = _T('\0');
  232. psystimeValue->wMonth = (unsigned short)_ttoi(szDate + 4); szDate[ 4] = _T('\0');
  233. psystimeValue->wYear = (unsigned short)_ttoi(szDate + 0);
  234. }
  235. else
  236. hr = E_MSINFO_NOVALUE;
  237. }
  238. return hr;
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Get the named value as a double float.
  242. //-----------------------------------------------------------------------------
  243. HRESULT CWMILiveObject::GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue)
  244. {
  245. ASSERT(pdblValue);
  246. VARIANT variant;
  247. HRESULT hr = GetValue(szProperty, &variant);
  248. if (SUCCEEDED(hr))
  249. {
  250. if (VariantChangeType(&variant, &variant, 0, VT_R8) == S_OK)
  251. *pdblValue = V_R8(&variant);
  252. else
  253. hr = E_MSINFO_NOVALUE;
  254. }
  255. return hr;
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Check for a value map value. If there isn't one, just use the untranslated
  259. // value.
  260. //-----------------------------------------------------------------------------
  261. HRESULT CWMILiveObject::GetValueValueMap(LPCTSTR szProperty, CString * pstrValue)
  262. {
  263. CString strResult;
  264. HRESULT hr = GetValueString(szProperty, &strResult);
  265. if (SUCCEEDED(hr))
  266. {
  267. CString strClass;
  268. CString strValueMapVal;
  269. if (m_pServices && SUCCEEDED(GetValueString(_T("__CLASS"), &strClass)))
  270. if (SUCCEEDED(CWMILiveHelper::CheckValueMap(m_pServices, strClass, szProperty, strResult, strValueMapVal)))
  271. strResult = strValueMapVal;
  272. }
  273. *pstrValue = strResult;
  274. return hr;
  275. }
  276. //=============================================================================
  277. // CWMILiveObjectCollection Functions
  278. //
  279. // The constructor and destructor for CWMILiveObjectCollection are very
  280. // straightforward.
  281. //=============================================================================
  282. CWMILiveObjectCollection::CWMILiveObjectCollection(IWbemServices * pServices) : m_pServices(pServices), m_pEnum(NULL)
  283. {
  284. ASSERT(m_pServices);
  285. if (m_pServices)
  286. m_pServices->AddRef();
  287. }
  288. CWMILiveObjectCollection::~CWMILiveObjectCollection()
  289. {
  290. if (m_pServices)
  291. m_pServices->Release();
  292. if (m_pEnum)
  293. m_pEnum->Release();
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Create the collection of WMI objects (a WMI enumerator) based on the
  297. // class name and the requested properties.
  298. //-----------------------------------------------------------------------------
  299. HRESULT CWMILiveObjectCollection::Create(LPCTSTR szClass, LPCTSTR szProperties)
  300. {
  301. ASSERT(szClass);
  302. if (m_pEnum)
  303. m_pEnum->Release();
  304. // Build the appopriate WQL query statement from the class and requested properties.
  305. LPCTSTR szWQLProperties = (szProperties && szProperties[0]) ? szProperties : _T("*");
  306. LPTSTR szQuery = new TCHAR[_tcsclen(szWQLProperties) + _tcsclen(szClass) + 14 /* length of "SELECT FROM " + 1 */];
  307. if (szQuery == NULL)
  308. return E_OUTOFMEMORY;
  309. wsprintf(szQuery, _T("SELECT %s FROM %s"), szWQLProperties, szClass);
  310. HRESULT hr = CreateWQL(szQuery);
  311. delete [] szQuery;
  312. return hr;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Create the collection of WMI objects (a WMI enumerator) based on the query.
  316. //-----------------------------------------------------------------------------
  317. HRESULT CWMILiveObjectCollection::CreateWQL(LPCTSTR szQuery)
  318. {
  319. ASSERT(szClass);
  320. if (m_pEnum)
  321. m_pEnum->Release();
  322. // Perform the query using our saved services pointer.
  323. HRESULT hr;
  324. BSTR bstrLanguage = SysAllocString(L"WQL");
  325. #ifdef UNICODE
  326. BSTR bstrQuery = SysAllocString(szQuery);
  327. #else
  328. USES_CONVERSION;
  329. LPOLESTR szWideQuery = T2OLE(szQuery);
  330. BSTR bstrQuery = SysAllocString(szWideQuery);
  331. #endif
  332. if (bstrLanguage && bstrQuery)
  333. hr = m_pServices->ExecQuery(bstrLanguage, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, 0, &m_pEnum);
  334. else
  335. hr = E_OUTOFMEMORY;
  336. if (SUCCEEDED(hr))
  337. ChangeWBEMSecurity(m_pEnum);
  338. if (bstrQuery)
  339. SysFreeString(bstrQuery);
  340. if (bstrLanguage)
  341. SysFreeString(bstrLanguage);
  342. return hr;
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Create this class of an existing enumerator. This may be a little odd,
  346. // since the enumerators will interact if both are advancing.
  347. //-----------------------------------------------------------------------------
  348. HRESULT CWMILiveObjectCollection::Create(IEnumWbemClassObject * pEnum)
  349. {
  350. if (m_pEnum)
  351. m_pEnum->Release();
  352. m_pEnum = pEnum;
  353. if (m_pEnum)
  354. {
  355. m_pEnum->AddRef();
  356. ChangeWBEMSecurity(m_pEnum);
  357. }
  358. return S_OK;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // Return the next item in the WMI enumerator as a CWMILiveObject object.
  362. //-----------------------------------------------------------------------------
  363. HRESULT CWMILiveObjectCollection::GetNext(CWMIObject ** ppObject)
  364. {
  365. ASSERT(ppObject);
  366. if (m_pEnum == NULL)
  367. {
  368. ASSERT(0 && "CWMILiveObjectCollection::GetNext called on a null enumerator");
  369. return E_FAIL;
  370. }
  371. IWbemClassObject * pRealWMIObject = NULL;
  372. ULONG uReturned;
  373. HRESULT hr = m_pEnum->Next(TIMEOUT, 1, &pRealWMIObject, &uReturned);
  374. if (hr == S_OK && uReturned == 1)
  375. {
  376. if (*ppObject == NULL)
  377. *ppObject = new CWMILiveObject;
  378. if (*ppObject)
  379. {
  380. hr = ((CWMILiveObject *)(*ppObject))->Create(m_pServices, pRealWMIObject); // this will AddRef the pointer
  381. if (FAILED(hr))
  382. {
  383. delete (CWMILiveObject *)(*ppObject);
  384. *ppObject = NULL;
  385. }
  386. }
  387. else
  388. hr = E_OUTOFMEMORY;
  389. pRealWMIObject->Release();
  390. }
  391. return hr;
  392. }
  393. //=============================================================================
  394. // CWMILiveHelper Functions
  395. //
  396. // The constructor/destructor are really straight forward.
  397. //=============================================================================
  398. CWMILiveHelper::CWMILiveHelper() : m_hrError(S_OK), m_strMachine(_T("")), m_strNamespace(_T("")), m_pServices(NULL)
  399. {
  400. }
  401. CWMILiveHelper::~CWMILiveHelper()
  402. {
  403. if (m_pServices)
  404. {
  405. m_pServices->Release();
  406. m_pServices = NULL;
  407. }
  408. if (m_pIWbemServices)
  409. {
  410. m_pIWbemServices->Release();
  411. m_pIWbemServices = NULL;
  412. }
  413. Version5ClearCache();
  414. }
  415. //-----------------------------------------------------------------------------
  416. // Enumerate creates a CWMILiveObjectCollection based on the class.
  417. //-----------------------------------------------------------------------------
  418. HRESULT CWMILiveHelper::Enumerate(LPCTSTR szClass, CWMIObjectCollection ** ppCollection, LPCTSTR szProperties)
  419. {
  420. ASSERT(m_pServices);
  421. if (m_pServices == NULL)
  422. return E_FAIL;
  423. ASSERT(ppCollection);
  424. if (ppCollection == NULL)
  425. return E_INVALIDARG;
  426. CWMILiveObjectCollection * pLiveCollection;
  427. if (*ppCollection)
  428. pLiveCollection = (CWMILiveObjectCollection *) *ppCollection;
  429. else
  430. pLiveCollection = new CWMILiveObjectCollection(m_pServices);
  431. if (pLiveCollection == NULL)
  432. return E_FAIL; // TBD - memory failure
  433. CString strProperties(szProperties);
  434. StringReplace(strProperties, _T("MSIAdvanced"), _T(""));
  435. HRESULT hr = pLiveCollection->Create(szClass, strProperties);
  436. if (SUCCEEDED(hr))
  437. *ppCollection = (CWMIObjectCollection *) pLiveCollection;
  438. else
  439. delete pLiveCollection;
  440. return hr;
  441. }
  442. //-----------------------------------------------------------------------------
  443. // WQLQuery creates a CWMILiveObjectCollection based on the query.
  444. //-----------------------------------------------------------------------------
  445. HRESULT CWMILiveHelper::WQLQuery(LPCTSTR szQuery, CWMIObjectCollection ** ppCollection)
  446. {
  447. ASSERT(m_pServices);
  448. if (m_pServices == NULL)
  449. return E_FAIL;
  450. ASSERT(ppCollection);
  451. if (ppCollection == NULL)
  452. return E_INVALIDARG;
  453. CWMILiveObjectCollection * pLiveCollection;
  454. if (*ppCollection)
  455. pLiveCollection = (CWMILiveObjectCollection *) *ppCollection;
  456. else
  457. pLiveCollection = new CWMILiveObjectCollection(m_pServices);
  458. if (pLiveCollection == NULL)
  459. return E_FAIL; // TBD - memory failure
  460. HRESULT hr = pLiveCollection->CreateWQL(szQuery);
  461. if (SUCCEEDED(hr))
  462. *ppCollection = (CWMIObjectCollection *) pLiveCollection;
  463. else
  464. delete pLiveCollection;
  465. return hr;
  466. }
  467. //-----------------------------------------------------------------------------
  468. // Get the named object.
  469. //-----------------------------------------------------------------------------
  470. HRESULT CWMILiveHelper::GetObject(LPCTSTR szObjectPath, CWMIObject ** ppObject)
  471. {
  472. ASSERT(ppObject);
  473. if (ppObject == NULL)
  474. return E_INVALIDARG;
  475. CString strPath(szObjectPath);
  476. if (strPath.Find(_T(":")) == -1)
  477. {
  478. // The path passed in is not a full object path if it doesn't have a colon.
  479. CString strMachine(_T("."));
  480. CString strNamespace(_T("cimv2"));
  481. if (!m_strMachine.IsEmpty())
  482. strMachine = m_strMachine;
  483. if (!m_strNamespace.IsEmpty())
  484. strNamespace = m_strNamespace;
  485. strPath = CString(_T("\\\\")) + strMachine + CString(_T("\\root\\")) + strNamespace + CString(_T(":")) + strPath;
  486. }
  487. HRESULT hr = E_FAIL;
  488. CWMILiveObject * pObject = NULL;
  489. if (m_pServices)
  490. {
  491. pObject = new CWMILiveObject;
  492. if (pObject)
  493. hr = pObject->Create(m_pServices, strPath);
  494. }
  495. if (SUCCEEDED(hr))
  496. *ppObject = pObject;
  497. else if (pObject)
  498. delete pObject;
  499. return hr;
  500. }
  501. //-----------------------------------------------------------------------------
  502. // Create this WMI helper based on the machine and namespace.
  503. //-----------------------------------------------------------------------------
  504. HRESULT CWMILiveHelper::Create(LPCTSTR szMachine, LPCTSTR szNamespace)
  505. {
  506. if (m_pServices)
  507. m_pServices->Release();
  508. m_strMachine = _T(".");
  509. if (szMachine && *szMachine)
  510. {
  511. m_strMachine = szMachine;
  512. if (m_strMachine.Left(2) == _T("\\\\"))
  513. m_strMachine = m_strMachine.Right(m_strMachine.GetLength() - 2);
  514. }
  515. m_strNamespace = _T("cimv2");
  516. if (szNamespace && *szNamespace)
  517. m_strNamespace = szNamespace;
  518. // We get a WBEM interface pointer by first creating a WBEM locator interface, then
  519. // using it to connect to a server to get an IWbemServices pointer.
  520. CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);
  521. IWbemServices * pService = NULL;
  522. IWbemLocator * pIWbemLocator = NULL;
  523. HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pIWbemLocator);
  524. if (SUCCEEDED(hr))
  525. {
  526. if (pIWbemLocator)
  527. {
  528. CString strWMINamespace;
  529. strWMINamespace.Format(_T("\\\\%s\\root\\%s"), m_strMachine, m_strNamespace);
  530. BSTR pNamespace = strWMINamespace.AllocSysString();
  531. if (pNamespace)
  532. {
  533. hr = pIWbemLocator->ConnectServer(pNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pService);
  534. SysFreeString(pNamespace);
  535. }
  536. pIWbemLocator->Release();
  537. pIWbemLocator = NULL;
  538. }
  539. }
  540. if (pService && SUCCEEDED(hr))
  541. ChangeWBEMSecurity(pService);
  542. m_hrError = hr;
  543. m_pServices = pService;
  544. return hr;
  545. }
  546. //-----------------------------------------------------------------------------
  547. // Get a new WMI helper for the specified namespace.
  548. //
  549. // TBD - this should do something.
  550. //-----------------------------------------------------------------------------
  551. HRESULT CWMILiveHelper::NewNamespace(LPCTSTR szNamespace, CWMIHelper **ppNewHelper)
  552. {
  553. return E_FAIL;
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Get the current namespace of this WMI helper.
  557. //
  558. // TBD - this should do something.
  559. //-----------------------------------------------------------------------------
  560. HRESULT CWMILiveHelper::GetNamespace(CString * pstrNamespace)
  561. {
  562. return E_FAIL;
  563. }
  564. //-----------------------------------------------------------------------------
  565. // Check to see if there is an associated value in a value map for this
  566. // combination of class, property and value. This is lifted from the
  567. // version 5.0 code.
  568. //-----------------------------------------------------------------------------
  569. CMapStringToString g_mapValueMapV7;
  570. HRESULT CWMILiveHelper::CheckValueMap(IWbemServices * pServices, const CString& strClass, const CString& strProperty, const CString& strVal, CString &strResult)
  571. {
  572. IWbemClassObject * pWBEMClassObject = NULL;
  573. HRESULT hrMap = S_OK, hr = S_OK;
  574. VARIANT vArray, vMapArray;
  575. IWbemQualifierSet * qual = NULL;
  576. if (!pServices)
  577. return E_FAIL;
  578. // Check the cache of saved values.
  579. CString strLookup = strClass + CString(_T(".")) + strProperty + CString(_T(":")) + strVal;
  580. if (g_mapValueMapV7.Lookup(strLookup, strResult))
  581. return S_OK;
  582. // Get the class object (not instance) for this class.
  583. CString strFullClass(_T("\\\\.\\root\\cimv2:"));
  584. strFullClass += strClass;
  585. BSTR bstrObjectPath = strFullClass.AllocSysString();
  586. hr = pServices->GetObject(bstrObjectPath, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pWBEMClassObject, NULL);
  587. ::SysFreeString(bstrObjectPath);
  588. if (FAILED(hr))
  589. return hr;
  590. // Get the qualifiers from the class object.
  591. BSTR bstrProperty = strProperty.AllocSysString();
  592. hr = pWBEMClassObject->GetPropertyQualifierSet(bstrProperty, &qual);
  593. ::SysFreeString(bstrProperty);
  594. if (SUCCEEDED(hr) && qual)
  595. {
  596. // Get the ValueMap and Value arrays.
  597. hrMap = qual->Get(L"ValueMap", 0, &vMapArray, NULL);
  598. hr = qual->Get(L"Values", 0, &vArray, NULL);
  599. if (SUCCEEDED(hr) && vArray.vt == (VT_BSTR | VT_ARRAY))
  600. {
  601. // Get the property value we're mapping.
  602. long index;
  603. if (SUCCEEDED(hrMap))
  604. {
  605. SAFEARRAY * pma = V_ARRAY(&vMapArray);
  606. long lLowerBound = 0, lUpperBound = 0 ;
  607. SafeArrayGetLBound(pma, 1, &lLowerBound);
  608. SafeArrayGetUBound(pma, 1, &lUpperBound);
  609. BSTR vMap;
  610. for (long x = lLowerBound; x <= lUpperBound; x++)
  611. {
  612. SafeArrayGetElement(pma, &x, &vMap);
  613. CString strMapVal(vMap);
  614. if (0 == strVal.CompareNoCase(strMapVal))
  615. {
  616. index = x;
  617. break; // found it
  618. }
  619. }
  620. }
  621. else
  622. {
  623. // Shouldn't hit this case - if mof is well formed
  624. // means there is no value map where we are expecting one.
  625. // If the strVal we are looking for is a number, treat it
  626. // as an index for the Values array. If it's a string,
  627. // then this is an error.
  628. TCHAR * szTest = NULL;
  629. index = _tcstol((LPCTSTR)strVal, &szTest, 10);
  630. if (szTest == NULL || (index == 0 && *szTest != 0) || strVal.IsEmpty())
  631. hr = E_FAIL;
  632. }
  633. // Lookup the string.
  634. if (SUCCEEDED(hr))
  635. {
  636. SAFEARRAY * psa = V_ARRAY(&vArray);
  637. long ix[1] = {index};
  638. BSTR str2;
  639. hr = SafeArrayGetElement(psa, ix, &str2);
  640. if (SUCCEEDED(hr))
  641. {
  642. strResult = str2;
  643. SysFreeString(str2);
  644. hr = S_OK;
  645. }
  646. else
  647. {
  648. hr = WBEM_E_VALUE_OUT_OF_RANGE;
  649. }
  650. }
  651. }
  652. qual->Release();
  653. }
  654. if (SUCCEEDED(hr))
  655. g_mapValueMapV7.SetAt(strLookup, strResult);
  656. return hr;
  657. }
  658. //-----------------------------------------------------------------------------
  659. // This function supplies a string for a given MSInfo specific HRESULT.
  660. //-----------------------------------------------------------------------------
  661. CString gstrNoValue, gstrNoProperty;
  662. CString GetMSInfoHRESULTString(HRESULT hr)
  663. {
  664. switch (hr)
  665. {
  666. case E_MSINFO_NOVALUE:
  667. if (gstrNoValue.IsEmpty())
  668. {
  669. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  670. gstrNoValue.LoadString(IDS_ERROR_NOVALUE);
  671. }
  672. return (gstrNoValue);
  673. case E_MSINFO_NOPROPERTY:
  674. if (gstrNoProperty.IsEmpty())
  675. {
  676. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  677. gstrNoProperty.LoadString(IDS_ERROR_NOPROPERTY);
  678. }
  679. return (gstrNoProperty);
  680. default:
  681. return (CString(_T("")));
  682. }
  683. }
  684. //-----------------------------------------------------------------------------
  685. // This is a wrapper for the GetObject() method in IWbemServices. This is
  686. // called when there is a certain set of properties to get.
  687. //
  688. // Turns out this doesn't speed us up appreciably on our WMI uses.
  689. //-----------------------------------------------------------------------------
  690. /*
  691. HRESULT CWMILiveObject::PartialInstanceGetObject(IWbemServices * pServices, BSTR bstrPath, IWbemClassObject ** ppObject, LPCTSTR szProperties)
  692. {
  693. HRESULT hr = WBEM_S_NO_ERROR;
  694. if ((pServices != NULL) && (bstrPath != NULL) && (ppObject != NULL))
  695. {
  696. IWbemContext * pWbemContext = NULL;
  697. hr = CoCreateInstance(CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER, IID_IWbemContext, (void**) &pWbemContext);
  698. CStringArray csaProperties;
  699. CString strProperties(szProperties), strProperty;
  700. int index = 0;
  701. while (!strProperties.IsEmpty())
  702. {
  703. strProperty = strProperties.SpanExcluding(_T(", "));
  704. strProperties = strProperties.Mid(strProperty.GetLength());
  705. strProperties.TrimLeft(_T(", "));
  706. csaProperties.SetAtGrow(index++, strProperty);
  707. }
  708. if (pWbemContext != NULL)
  709. {
  710. variant_t vValue;
  711. V_VT(&vValue) = VT_BOOL;
  712. V_BOOL(&vValue) = VARIANT_TRUE;
  713. // First set the value that says we are using Get extensions
  714. if ((SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue))) &&
  715. (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_CLIENT_REQUEST", 0L, &vValue))) )
  716. {
  717. // Delete any unneeded properties
  718. pWbemContext->DeleteValue(L"__GET_EXT_KEYS_ONLY", 0L);
  719. // Now build the array of properties
  720. SAFEARRAYBOUND rgsabound [ 1 ] ;
  721. rgsabound[0].cElements = csaProperties.GetSize() ;
  722. rgsabound[0].lLbound = 0 ;
  723. V_ARRAY(&vValue) = SafeArrayCreate ( VT_BSTR , 1 , rgsabound ) ;
  724. if ( V_ARRAY(&vValue) )
  725. {
  726. V_VT(&vValue) = VT_BSTR | VT_ARRAY;
  727. for (long x=0; x < csaProperties.GetSize(); x++)
  728. {
  729. bstr_t bstrProp = csaProperties[x];
  730. SafeArrayPutElement(
  731. V_ARRAY(&vValue),
  732. &x,
  733. (LPVOID) (BSTR) bstrProp);
  734. }
  735. // Put the array into the context object
  736. if (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_PROPERTIES", 0L, &vValue)))
  737. {
  738. hr = pServices->GetObject(bstrPath, 0, pWbemContext, ppObject, 0);
  739. vValue.Clear();
  740. V_VT(&vValue) = VT_BOOL;
  741. V_BOOL(&vValue) = VARIANT_FALSE;
  742. pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue);
  743. }
  744. }
  745. else
  746. {
  747. }
  748. }
  749. }
  750. else
  751. {
  752. hr = WBEM_E_INVALID_PARAMETER;
  753. }
  754. }
  755. else
  756. {
  757. hr = WBEM_E_INVALID_PARAMETER;
  758. }
  759. return hr;
  760. }
  761. */