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.

2872 lines
71 KiB

  1. /*++
  2. Copyright (C) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. // OpWrap.cpp
  8. #include "stdafx.h"
  9. #include "OpWrap.h"
  10. #include "resource.h"
  11. #include "OpView.h"
  12. #include "MainFrm.h"
  13. void Trace(LPCTSTR szFormat, ...)
  14. {
  15. va_list ap;
  16. TCHAR szMessage[512];
  17. va_start(ap, szFormat);
  18. _vstprintf(szMessage, szFormat, ap);
  19. va_end(ap);
  20. lstrcat(szMessage, _T("\n"));
  21. OutputDebugString(szMessage);
  22. }
  23. CString GetEmbeddedObjectText(IUnknown *pUnk)
  24. {
  25. IWbemClassObjectPtr pObj;
  26. CString strRet;
  27. if (pUnk)
  28. {
  29. pUnk->QueryInterface(
  30. IID_IWbemClassObject,
  31. (LPVOID*) &pObj);
  32. if (pObj != NULL)
  33. {
  34. CObjInfo obj;
  35. obj.SetObj(pObj);
  36. strRet = obj.GetObjText();
  37. }
  38. }
  39. else
  40. strRet.LoadString(IDS_NULL);
  41. return strRet;
  42. }
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CObjInfo
  45. CObjInfo::~CObjInfo()
  46. {
  47. }
  48. BOOL CObjInfo::GetPropValue(int iIndex, CString &strValue, BOOL bTranslate)
  49. {
  50. BOOL bRet;
  51. _variant_t var;
  52. CPropInfo &prop = (*m_ppProps)[iIndex];
  53. ValueToVariant(iIndex, &var);
  54. bRet = prop.VariantToString(&var, strValue, bTranslate);
  55. // Otherwise the destructor freaks out because it doesn't know what to do
  56. // with VT_I8.
  57. if (var.vt == VT_I8)
  58. var.vt = VT_I4;
  59. return bRet;
  60. }
  61. CString CObjInfo::GetStringPropValue(int iIndex)
  62. {
  63. _bstr_t strProp = m_ppProps->GetData()[iIndex].m_strName;
  64. return GetStringPropValue(strProp);
  65. }
  66. CString CObjInfo::GetStringPropValue(LPCWSTR szName)
  67. {
  68. CString strRet;
  69. _variant_t var;
  70. if (m_pObj != NULL)
  71. {
  72. m_pObj->Get(
  73. szName,
  74. 0,
  75. &var,
  76. NULL,
  77. NULL);
  78. }
  79. if (var.vt == VT_BSTR)
  80. strRet = var.bstrVal;
  81. return strRet;
  82. }
  83. #define KEY_PROP_FORMAT _T("\t\t%s (%s)* = %s\n")
  84. #define NON_KEY_PROP_FORMAT _T("\t\t%s (%s) = %s\n")
  85. void CObjInfo::Export(CStdioFile *pFile, BOOL bShowSystem, BOOL bTranslate,
  86. int iLevel)
  87. {
  88. #ifdef _DEBUG
  89. // Don't leave this in here! It's a hack I'm using to check out the
  90. // internal layout of IWbemClassObject.
  91. DoDebugStuff();
  92. #endif
  93. CPropInfo *pProps;
  94. int nItems;
  95. // Get out if the object isn't valid (like on an object where the
  96. // refresh failed).
  97. if (m_pObj == NULL)
  98. return;
  99. pProps = GetProps()->GetData();
  100. nItems = GetProps()->GetSize();
  101. // Add the object path.
  102. for (int i = 0; i <= iLevel; i++)
  103. pFile->Write(_T("\t"), sizeof(TCHAR));
  104. pFile->WriteString(GetObjText());
  105. pFile->Write(_T("\n"), sizeof(TCHAR));
  106. for (i = 0; i < nItems; i++)
  107. {
  108. if (bShowSystem || pProps[i].m_iFlavor != WBEM_FLAVOR_ORIGIN_SYSTEM)
  109. {
  110. CString strLine,
  111. strType,
  112. strValue;
  113. _variant_t vValue;
  114. IUnknown **pUnks = NULL;
  115. int nUnks = 0,
  116. iImage;
  117. BOOL bArray;
  118. pProps[i].GetPropType(strType, &iImage);
  119. ValueToVariant(i, &vValue);
  120. if (vValue.vt == VT_UNKNOWN)
  121. {
  122. bArray = FALSE;
  123. nUnks = 1;
  124. pUnks = &vValue.punkVal;
  125. }
  126. else if (vValue.vt == ((int) VT_UNKNOWN | VT_ARRAY))
  127. {
  128. bArray = TRUE;
  129. nUnks = vValue.parray->rgsabound[0].cElements;
  130. pUnks = (IUnknown**) vValue.parray->pvData;
  131. }
  132. else
  133. pProps[i].VariantToString(&vValue, strValue, bTranslate, TRUE);
  134. strLine.Format(
  135. pProps[i].m_bKey ? KEY_PROP_FORMAT : NON_KEY_PROP_FORMAT,
  136. (LPCTSTR) pProps[i].m_strName,
  137. (LPCTSTR) strType,
  138. (LPCTSTR) strValue);
  139. // Add some additional space if we're in a nested level.
  140. for (int i = 0; i < iLevel; i++)
  141. pFile->Write(_T("\t"), sizeof(TCHAR));
  142. pFile->WriteString(strLine);
  143. // Now do the embedded object stuff.
  144. if (nUnks)
  145. {
  146. for (int i = 0; i < nUnks; i++)
  147. {
  148. IWbemClassObjectPtr pObj;
  149. HRESULT hr;
  150. hr =
  151. pUnks[i]->QueryInterface(
  152. IID_IWbemClassObject,
  153. (LPVOID*) &pObj);
  154. if (SUCCEEDED(hr))
  155. {
  156. CObjInfo info;
  157. info.SetObj(pObj);
  158. info.SetBaseImage(IMAGE_OBJECT);
  159. info.LoadProps(NULL);
  160. info.Export(pFile, bShowSystem, bTranslate, iLevel + 2);
  161. // This looks bad, but normally this is done by a
  162. // controlling COpWrap. In this case we faked one, so
  163. // we have to get rid of it ourselves.
  164. delete info.GetProps();
  165. }
  166. }
  167. }
  168. // Otherwise the destructor freaks out because it doesn't know what to do
  169. // with VT_I8.
  170. if (vValue.vt == VT_I8)
  171. vValue.vt = VT_I4;
  172. }
  173. }
  174. // Leave room for another one.
  175. pFile->Write(_T("\n"), sizeof(TCHAR));
  176. }
  177. CString CObjInfo::GetObjText()
  178. {
  179. CString strRet = GetStringPropValue(L"__RELPATH");
  180. if (strRet.IsEmpty())
  181. {
  182. CString strClass = GetStringPropValue(L"__CLASS");
  183. if (!strClass.IsEmpty())
  184. strRet.Format(IDS_CLASS_NO_KEY, (LPCTSTR) strClass);
  185. else
  186. strRet.LoadString(IDS_NO_KEY);
  187. }
  188. return strRet;
  189. }
  190. #define MAX_STR_SIZE 4096
  191. BOOL CObjInfo::ValueToVariant(int iIndex, VARIANT *pVar)
  192. {
  193. CPropInfo &prop = (*m_ppProps)[iIndex];
  194. BOOL bRet = FALSE;
  195. VariantClear(pVar);
  196. pVar->vt = VT_NULL;
  197. if (prop.m_iHandle && !(prop.m_type & CIM_FLAG_ARRAY))
  198. {
  199. BOOL bString = prop.m_vt == VT_BSTR;
  200. long nRead = 0;
  201. if (bString)
  202. {
  203. WCHAR szBuff[MAX_STR_SIZE];
  204. bRet =
  205. SUCCEEDED(m_pAccess->ReadPropertyValue(
  206. prop.m_iHandle,
  207. prop.m_dwExpectedSize,
  208. &nRead,
  209. (LPBYTE) szBuff)) && nRead != 0;
  210. if (bRet)
  211. {
  212. pVar->vt = VT_BSTR;
  213. V_BSTR(pVar) = SysAllocString(szBuff);
  214. }
  215. }
  216. else
  217. {
  218. bRet =
  219. SUCCEEDED(m_pAccess->ReadPropertyValue(
  220. prop.m_iHandle,
  221. prop.m_dwExpectedSize,
  222. &nRead,
  223. (LPBYTE) &V_BSTR(pVar))) &&
  224. (nRead == prop.m_dwExpectedSize);
  225. if (bRet)
  226. pVar->vt = prop.m_vt;
  227. }
  228. }
  229. else
  230. {
  231. bRet = SUCCEEDED(m_pObj->Get(
  232. _bstr_t(prop.m_strName),
  233. 0,
  234. pVar,
  235. NULL,
  236. NULL));
  237. }
  238. return bRet;
  239. }
  240. CString GetStringPropType(int iIndex);
  241. void CObjInfo::GetPropInfo(
  242. int iIndex,
  243. CString &strValue,
  244. CString &strType,
  245. int *piImage,
  246. int *piFlavor,
  247. BOOL bTranslate)
  248. {
  249. CPropInfo &info = (*m_ppProps)[iIndex];
  250. info.GetPropType(strType, piImage);
  251. strValue = _T("");
  252. *piFlavor = info.m_iFlavor;
  253. GetPropValue(iIndex, strValue, bTranslate);
  254. }
  255. void CObjInfo::SetObj(IWbemClassObject *pObj)
  256. {
  257. m_pObj = pObj;
  258. pObj->QueryInterface(
  259. IID_IWbemObjectAccess,
  260. (LPVOID*) &m_pAccess);
  261. }
  262. BOOL IsVarStringArray(VARIANT *pVar)
  263. {
  264. return pVar->vt == (VT_BSTR | VT_ARRAY) &&
  265. pVar->parray->rgsabound[0].cElements != 0;
  266. }
  267. // This converts a BitMap qualifier value string into a bitmask scalar value.
  268. // If the number is a decimal number we have to shift it (e.g. convert '3',
  269. // or bit 3 (zero based), into 0x8.
  270. // If the number is hex, just use wcstoul to convert it into a DWORD.
  271. DWORD CObjInfo::BitmaskStrToValue(LPCWSTR szStr)
  272. {
  273. WCHAR *szBad;
  274. if (szStr[0] && towupper(szStr[1]) != 'X')
  275. return 1 << wcstoul(szStr, &szBad, 0);
  276. else
  277. return wcstoul(szStr, &szBad, 0);
  278. }
  279. HRESULT CObjInfo::LoadProps(IWbemServices *pNamespace)
  280. {
  281. // We need to get the class definition for the amended qualifiers.
  282. IWbemClassObjectPtr pClass;
  283. CString strClass = GetStringPropValue(L"__CLASS");
  284. if (!m_ppProps)
  285. m_ppProps = new CPropInfoArray;
  286. if (pNamespace)
  287. {
  288. pNamespace->GetObject(
  289. _bstr_t(strClass),
  290. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  291. NULL,
  292. &pClass,
  293. NULL);
  294. }
  295. SAFEARRAY *pArr = NULL;
  296. HRESULT hr;
  297. CMap<CString, LPCTSTR, BOOL, BOOL>
  298. mapNameToKey;
  299. _variant_t vTrue(true);
  300. // Find our key properties
  301. if (SUCCEEDED(m_pObj->GetNames(
  302. L"KEY",
  303. WBEM_FLAG_ONLY_IF_IDENTICAL,
  304. &vTrue,
  305. &pArr)) && pArr->rgsabound[0].cElements != 0)
  306. {
  307. BSTR *pNames = (BSTR*) pArr->pvData;
  308. for (int i = 0;
  309. i < pArr->rgsabound[0].cElements;
  310. i++)
  311. {
  312. mapNameToKey.SetAt(_bstr_t(pNames[i]), TRUE);
  313. }
  314. SafeArrayDestroy(pArr);
  315. }
  316. // Find out how big we need to make our array.
  317. if (SUCCEEDED(hr = m_pObj->GetNames(
  318. NULL,
  319. WBEM_FLAG_ALWAYS,
  320. NULL,
  321. &pArr)) && pArr->rgsabound[0].cElements != 0)
  322. {
  323. BSTR *pNames = (BSTR*) pArr->pvData;
  324. m_ppProps->SetSize(pArr->rgsabound[0].cElements);
  325. for (int i = 0;
  326. i < pArr->rgsabound[0].cElements && SUCCEEDED(hr);
  327. i++)
  328. {
  329. BOOL bKey; // This value isn't really used, but we need it for the
  330. // mapNameToKey.Lookup call.
  331. CPropInfo &info = (*m_ppProps)[i];
  332. CIMTYPE type;
  333. m_pObj->Get(pNames[i], 0, NULL, &type, &info.m_iFlavor);
  334. info.m_strName = (LPCWSTR) _bstr_t(pNames[i]);
  335. BOOL bSystemProp = info.m_iFlavor == WBEM_FLAVOR_ORIGIN_SYSTEM;
  336. // Don't bother getting the handle for system props since they don't
  337. // exist.
  338. if (!bSystemProp)
  339. m_pAccess->GetPropertyHandle(pNames[i], NULL, &info.m_iHandle);
  340. info.SetType(type);
  341. if (mapNameToKey.Lookup(info.m_strName, bKey))
  342. info.m_bKey = TRUE;
  343. // Load up the valuemap/bitmap values.
  344. IWbemQualifierSetPtr pQuals;
  345. if (pClass != NULL &&
  346. SUCCEEDED(pClass->GetPropertyQualifierSet(pNames[i], &pQuals)))
  347. {
  348. _variant_t vValues;
  349. // Try to get the Values/Valuemap stuff.
  350. if (SUCCEEDED(pQuals->Get(L"Values", 0, &vValues, NULL)) &&
  351. IsVarStringArray(&vValues))
  352. {
  353. _variant_t vMap;
  354. BOOL bUsingMap;
  355. bUsingMap = SUCCEEDED(pQuals->Get(L"ValueMap", 0, &vMap, NULL)) &&
  356. IsVarStringArray(&vMap) &&
  357. vMap.parray->rgsabound[0].cElements ==
  358. vValues.parray->rgsabound[0].cElements;
  359. // Indicate whether this property will be using
  360. // m_mapValues.
  361. info.m_bValueMap =
  362. vValues.parray->rgsabound[0].cElements != 0;
  363. // Clear this out in case we're refreshing our data.
  364. info.m_mapValues.RemoveAll();
  365. for (int i = 0; i < vValues.parray->rgsabound[0].cElements;
  366. i++)
  367. {
  368. CString strKey,
  369. strValue;
  370. if (bUsingMap)
  371. strKey = ((BSTR*)(vMap.parray->pvData))[i];
  372. else
  373. strKey.Format(_T("%d"), i);
  374. strValue = ((BSTR*)(vValues.parray->pvData))[i];
  375. info.m_mapValues.SetAt(strKey, strValue);
  376. }
  377. }
  378. // Try to get the Values/Valuemap stuff.
  379. if (SUCCEEDED(pQuals->Get(L"BitValues", 0, &vValues, NULL)) &&
  380. IsVarStringArray(&vValues))
  381. {
  382. _variant_t vMap;
  383. BOOL bUsingBitmap;
  384. bUsingBitmap = SUCCEEDED(pQuals->Get(L"BitMap", 0, &vMap, NULL)) &&
  385. IsVarStringArray(&vMap) &&
  386. vMap.parray->rgsabound[0].cElements ==
  387. vValues.parray->rgsabound[0].cElements;
  388. // Indicate whether this property will be using
  389. // m_bitmaskValues.
  390. info.m_bBitmask =
  391. vValues.parray->rgsabound[0].cElements != 0;
  392. if (info.m_bBitmask)
  393. info.m_bitmaskValues.SetSize(
  394. vValues.parray->rgsabound[0].cElements);
  395. for (int i = 0; i < vValues.parray->rgsabound[0].cElements;
  396. i++)
  397. {
  398. CString strValue;
  399. CBitmaskInfo &value = info.m_bitmaskValues[i];
  400. if (bUsingBitmap)
  401. value.m_dwBitmaskValue =
  402. BitmaskStrToValue(((BSTR*)(vMap.parray->pvData))[i]);
  403. else
  404. value.m_dwBitmaskValue = 1 << i;
  405. value.m_strName = ((BSTR*)(vValues.parray->pvData))[i];
  406. }
  407. }
  408. }
  409. }
  410. SafeArrayDestroy(pArr);
  411. }
  412. // Load up the methods.
  413. m_ppProps->LoadMethods(pClass);
  414. return hr;
  415. }
  416. /////////////////////////////////////////////////////////////////////////////
  417. // COpWrap
  418. COpWrap::COpWrap() :
  419. m_nCount(0),
  420. m_status(WBEM_STATUS_COMPLETE),
  421. m_nExpectedStatusCalls(0),
  422. m_lRef(0)
  423. {
  424. }
  425. COpWrap::COpWrap(
  426. WMI_OP_TYPE type,
  427. LPCTSTR szText,
  428. BOOL bOption) :
  429. m_nCount(0),
  430. m_strOpText(szText),
  431. m_type(type),
  432. m_status(WBEM_STATUS_COMPLETE),
  433. m_bOption(bOption),
  434. m_nExpectedStatusCalls(0),
  435. m_lRef(0)
  436. {
  437. Init();
  438. }
  439. COpWrap::~COpWrap()
  440. {
  441. }
  442. STDMETHODIMP_(ULONG) CObjSink::AddRef(void)
  443. {
  444. LONG lRet = InterlockedIncrement(&m_lRef);
  445. //Trace("Addref = %d", m_lRef);
  446. return lRet;
  447. }
  448. STDMETHODIMP_(ULONG) CObjSink::Release(void)
  449. {
  450. LONG lRet = InterlockedDecrement(&m_lRef);
  451. //Trace("Release = %d", m_lRef);
  452. if (lRet == 0)
  453. delete this;
  454. return lRet;
  455. }
  456. HRESULT STDMETHODCALLTYPE CObjSink::Indicate(
  457. LONG lObjectCount,
  458. IWbemClassObject **ppObjArray)
  459. {
  460. return m_pWrap->Indicate(lObjectCount, ppObjArray);
  461. }
  462. HRESULT STDMETHODCALLTYPE CObjSink::SetStatus(
  463. LONG lFlags,
  464. HRESULT hResult,
  465. BSTR strParam,
  466. IWbemClassObject *pObjParam)
  467. {
  468. return m_pWrap->SetStatus(lFlags, hResult, strParam, pObjParam);
  469. }
  470. const COpWrap& COpWrap::operator=(const COpWrap &other)
  471. {
  472. m_strOpText = other.m_strOpText;
  473. m_type = other.m_type;
  474. m_bOption = other.m_bOption;
  475. return *this;
  476. }
  477. HRESULT COpWrap::Execute(IWbemServices *pNamespace)
  478. {
  479. _bstr_t strWQL = L"WQL",
  480. strText = m_strOpText;
  481. m_hr = S_OK;
  482. m_pNamespace = pNamespace;
  483. m_nCount = 0;
  484. m_status = WBEM_STATUS_PROGRESS;
  485. m_strProps.RemoveAll();
  486. m_piDisplayCols.RemoveAll();
  487. m_mapClassToProps.Flush();
  488. m_hr = S_OK;
  489. m_nExpectedStatusCalls++;
  490. CObjSink *pSink = new CObjSink(this);
  491. m_pObjSink = pSink;
  492. // It seems like WMI never does this. Why?
  493. //pSink->AddRef();
  494. switch(m_type)
  495. {
  496. case WMI_QUERY:
  497. m_hr =
  498. pNamespace->ExecQueryAsync(
  499. strWQL,
  500. strText,
  501. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  502. NULL,
  503. m_pObjSink);
  504. //(IWbemObjectSink*) this);
  505. break;
  506. case WMI_EVENT_QUERY:
  507. m_hr =
  508. pNamespace->ExecNotificationQueryAsync(
  509. strWQL,
  510. strText,
  511. WBEM_FLAG_USE_AMENDED_QUALIFIERS |
  512. (m_bOption ? WBEM_FLAG_MONITOR : 0),
  513. NULL,
  514. m_pObjSink);
  515. //(IWbemObjectSink*) this);
  516. break;
  517. case WMI_ENUM_OBJ:
  518. m_hr =
  519. pNamespace->CreateInstanceEnumAsync(
  520. strText,
  521. //WBEM_FLAG_FORWARD_ONLY | // WMI doesn't seem to like this. Why?
  522. WBEM_FLAG_USE_AMENDED_QUALIFIERS |
  523. (m_bOption ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW),
  524. NULL,
  525. m_pObjSink);
  526. //(IWbemObjectSink*) this);
  527. break;
  528. case WMI_GET_OBJ:
  529. m_hr =
  530. pNamespace->GetObjectAsync(
  531. strText,
  532. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  533. NULL,
  534. m_pObjSink);
  535. //(IWbemObjectSink*) this);
  536. break;
  537. case WMI_ENUM_CLASS:
  538. {
  539. // First see if we can get the class. If we do, set m_strOpText
  540. // to be the 'pretty' class name.
  541. IWbemClassObject *pClass = NULL;
  542. m_hr =
  543. pNamespace->GetObject(
  544. strText,
  545. 0,
  546. NULL,
  547. &pClass,
  548. NULL);
  549. if (SUCCEEDED(m_hr))
  550. {
  551. _variant_t var;
  552. pClass->Get(
  553. L"__CLASS",
  554. 0,
  555. &var,
  556. NULL,
  557. NULL);
  558. if (var.vt == VT_BSTR)
  559. m_strOpText = var.bstrVal;
  560. pClass->Release();
  561. }
  562. m_hr =
  563. pNamespace->CreateClassEnumAsync(
  564. strText,
  565. //WBEM_FLAG_FORWARD_ONLY | // WMI doesn't seem to like this. Why?
  566. WBEM_FLAG_USE_AMENDED_QUALIFIERS |
  567. m_bOption ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW,
  568. NULL,
  569. m_pObjSink);
  570. //(IWbemObjectSink*) this);
  571. break;
  572. }
  573. case WMI_GET_CLASS:
  574. m_hr =
  575. pNamespace->GetObjectAsync(
  576. strText,
  577. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  578. NULL,
  579. m_pObjSink);
  580. //(IWbemObjectSink*) this);
  581. break;
  582. case WMI_CREATE_CLASS:
  583. {
  584. BSTR bstrClass = *(LPCWSTR) strText == 0 ? NULL :
  585. (BSTR) strText;
  586. IWbemClassObject *pSuperClass = NULL;
  587. // Get the superclass.
  588. m_hr =
  589. pNamespace->GetObject(
  590. bstrClass,
  591. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  592. NULL,
  593. &pSuperClass,
  594. NULL);
  595. if (SUCCEEDED(m_hr))
  596. {
  597. IWbemClassObject *pClass = NULL;
  598. // If bstrClass isn't null then we didn't get a top-level
  599. // class, which means we now need to spawn a derived class.
  600. if (bstrClass)
  601. {
  602. m_hr =
  603. pSuperClass->SpawnDerivedClass(
  604. 0,
  605. &pClass);
  606. if (SUCCEEDED(m_hr))
  607. {
  608. Indicate(1, &pClass);
  609. // Show the user this object already needs to be saved.
  610. m_objInfo.SetModified(TRUE);
  611. pClass->Release();
  612. // Fake the status callback.
  613. SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, NULL);
  614. }
  615. }
  616. else
  617. {
  618. Indicate(1, &pSuperClass);
  619. // Fake the status callback.
  620. SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, NULL);
  621. }
  622. pSuperClass->Release();
  623. }
  624. break;
  625. }
  626. case WMI_CREATE_OBJ:
  627. {
  628. IWbemClassObject *pClass = NULL;
  629. // Get the superclass.
  630. m_hr =
  631. pNamespace->GetObject(
  632. strText,
  633. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  634. NULL,
  635. &pClass,
  636. NULL);
  637. if (SUCCEEDED(m_hr))
  638. {
  639. IWbemClassObject *pObject = NULL;
  640. m_hr =
  641. pClass->SpawnInstance(
  642. 0,
  643. &pObject);
  644. if (SUCCEEDED(m_hr))
  645. {
  646. Indicate(1, &pObject);
  647. // Show the user this object already needs to be saved.
  648. m_objInfo.SetModified(TRUE);
  649. pObject->Release();
  650. // Fake the status callback.
  651. SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, NULL);
  652. }
  653. pClass->Release();
  654. }
  655. break;
  656. }
  657. }
  658. if (FAILED(m_hr))
  659. {
  660. IWbemClassObjectPtr pErrorObj;
  661. pErrorObj.Attach(GetWMIErrorObject(), FALSE);
  662. if (!m_nExpectedStatusCalls)
  663. m_nExpectedStatusCalls = 1;
  664. SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, pErrorObj);
  665. }
  666. return m_hr;
  667. }
  668. HRESULT COpWrap::RefreshPropInfo(CObjInfo *pInfo)
  669. {
  670. if (!pInfo->IsInstance())
  671. {
  672. HRESULT hr = pInfo->LoadProps(m_pNamespace);
  673. if (SUCCEEDED(hr))
  674. AddPropsToGlobalIndex(pInfo);
  675. return hr;
  676. }
  677. else
  678. return S_OK;
  679. }
  680. HRESULT COpWrap::LoadPropInfo(CObjInfo *pInfo)
  681. {
  682. CString strClass = pInfo->GetStringPropValue(L"__CLASS");
  683. m_cs.Lock();
  684. CPropInfoArray *pProps;
  685. if (!m_mapClassToProps.Lookup(strClass, pProps))
  686. {
  687. // Since it's not in our map it must have gotten deleted.
  688. pInfo->SetProps(NULL);
  689. pInfo->LoadProps(m_pNamespace);
  690. pProps = pInfo->GetProps();
  691. m_mapClassToProps.SetAt(strClass, pProps);
  692. AddPropsToGlobalIndex(pInfo);
  693. }
  694. else
  695. pInfo->SetProps(pProps);
  696. m_cs.Unlock();
  697. return S_OK;
  698. }
  699. HRESULT STDMETHODCALLTYPE COpWrap::Indicate(
  700. LONG lObjectCount,
  701. IWbemClassObject **ppObjArray)
  702. {
  703. for (LONG i = 0; i < lObjectCount; i++, m_nCount++)
  704. {
  705. CObjPtr ptr(ppObjArray[i]);
  706. m_listObj.AddTail(ptr);
  707. CObjInfo *pInfo;
  708. if (!IsObject())
  709. pInfo = new CObjInfo;
  710. else
  711. pInfo = &m_objInfo;
  712. pInfo->SetObj(ppObjArray[i]);
  713. pInfo->SetBaseImage(m_iChildImage);
  714. LoadPropInfo(pInfo);
  715. g_pOpView->PostMessage(WM_OBJ_INDICATE, (WPARAM) this, (LPARAM) pInfo);
  716. }
  717. return S_OK;
  718. }
  719. CString COpWrap::GetWbemErrorText(HRESULT hres)
  720. {
  721. CString strRet,
  722. strError,
  723. strFacility;
  724. IWbemStatusCodeText *pStatus = NULL;
  725. SCODE sc = CoCreateInstance(
  726. CLSID_WbemStatusCodeText,
  727. 0,
  728. CLSCTX_INPROC_SERVER,
  729. IID_IWbemStatusCodeText,
  730. (LPVOID *) &pStatus);
  731. if (sc == S_OK)
  732. {
  733. BSTR bstr = NULL;
  734. if (SUCCEEDED(pStatus->GetErrorCodeText(hres, 0, 0, &bstr)))
  735. {
  736. strError = bstr;
  737. SysFreeString(bstr);
  738. }
  739. if (SUCCEEDED(pStatus->GetFacilityCodeText(hres, 0, 0, &bstr)))
  740. {
  741. strFacility = bstr;
  742. SysFreeString(bstr);
  743. }
  744. pStatus->Release();
  745. }
  746. if (!strError.IsEmpty() && !strFacility.IsEmpty())
  747. {
  748. strRet.FormatMessage(
  749. IDS_ERROR_FORMAT,
  750. hres,
  751. (LPCSTR) strFacility,
  752. (LPCSTR) strError);
  753. }
  754. else
  755. {
  756. strRet.FormatMessage(IDS_ERROR_FAILED, hres);
  757. }
  758. return strRet;
  759. }
  760. HRESULT STDMETHODCALLTYPE COpWrap::SetStatus(
  761. LONG lFlags,
  762. HRESULT hResult,
  763. BSTR strParam,
  764. IWbemClassObject *pObjParam)
  765. {
  766. if (m_nExpectedStatusCalls)
  767. {
  768. m_status = lFlags;
  769. m_hr = hResult;
  770. if (SUCCEEDED(hResult))
  771. m_strErrorText.Empty();
  772. else
  773. m_strErrorText = GetWbemErrorText(hResult);
  774. g_pOpView->PostMessage(WM_OP_STATUS, (WPARAM) this, 0);
  775. m_nExpectedStatusCalls--;
  776. m_pErrorObj = pObjParam;
  777. }
  778. return S_OK;
  779. }
  780. void COpWrap::SetHoldsObjects()
  781. {
  782. switch(m_type)
  783. {
  784. case WMI_QUERY:
  785. {
  786. CString strQuery = m_strOpText;
  787. strQuery.MakeUpper();
  788. strQuery.TrimLeft();
  789. if (strQuery.Find(_T("ASSOCIATORS")) != -1 ||
  790. strQuery.Find(_T("REFERENCES")) != -1)
  791. m_bShowPathsOnly = TRUE;
  792. else
  793. m_bShowPathsOnly = FALSE;
  794. break;
  795. }
  796. case WMI_ENUM_OBJ:
  797. case WMI_GET_OBJ:
  798. case WMI_EVENT_QUERY:
  799. case WMI_CREATE_OBJ:
  800. m_bShowPathsOnly = FALSE;
  801. break;
  802. default:
  803. case WMI_ENUM_CLASS:
  804. case WMI_GET_CLASS:
  805. case WMI_CREATE_CLASS:
  806. m_bShowPathsOnly = TRUE;
  807. }
  808. }
  809. void COpWrap::GetPropValue(
  810. CObjInfo *pInfo,
  811. int iGlobalIndex,
  812. CString &strValue,
  813. BOOL bTranslate)
  814. {
  815. int iIndex;
  816. if (pInfo->GetProps()->m_mapGlobalToLocalIndex.Lookup(iGlobalIndex, iIndex))
  817. pInfo->GetPropValue(iIndex, strValue, bTranslate);
  818. }
  819. CString COpWrap::GetClassName()
  820. {
  821. CString strRet;
  822. if (m_type != WMI_ENUM_CLASS)
  823. {
  824. if (m_listObj.GetCount())
  825. {
  826. CObjPtr &pObj = m_listObj.GetAt(m_listObj.GetHeadPosition());
  827. _variant_t var;
  828. if (SUCCEEDED(pObj->Get(
  829. L"__CLASS",
  830. 0,
  831. &var,
  832. NULL,
  833. NULL)) && var.vt == VT_BSTR)
  834. {
  835. strRet = var.bstrVal;
  836. }
  837. }
  838. }
  839. else
  840. {
  841. return m_strOpText;
  842. }
  843. return strRet;
  844. }
  845. CString COpWrap::GetCaption()
  846. {
  847. CString strRet;
  848. switch(m_type)
  849. {
  850. case WMI_CREATE_CLASS:
  851. if (!m_strOpText.IsEmpty())
  852. strRet.Format(IDS_SUBCLASS_OF, (LPCTSTR) m_strOpText);
  853. else
  854. strRet.LoadString(IDS_TOPLEVEL_CLASS);
  855. break;
  856. case WMI_GET_CLASS:
  857. strRet = GetClassName();
  858. if (strRet.IsEmpty())
  859. strRet = m_strOpText;
  860. break;
  861. case WMI_ENUM_CLASS:
  862. if (!m_strOpText.IsEmpty())
  863. strRet.Format(IDS_ENUM_CLASS_CAPTION, (LPCTSTR) m_strOpText);
  864. else
  865. strRet.LoadString(m_bOption ? IDS_ALL_CLASSES :
  866. IDS_TOP_LEVEL_CLASSES);
  867. break;
  868. case WMI_GET_OBJ:
  869. case WMI_EVENT_QUERY:
  870. case WMI_QUERY:
  871. strRet = m_strOpText;
  872. break;
  873. case WMI_CREATE_OBJ:
  874. strRet.Format(IDS_INSTANCE_OF, (LPCTSTR) m_strOpText);
  875. break;
  876. case WMI_ENUM_OBJ:
  877. {
  878. CString strClass = GetClassName();
  879. if (strClass.IsEmpty())
  880. strClass = m_strOpText;
  881. strRet.Format(IDS_ENUM_OBJ_CAPTION, (LPCTSTR) strClass);
  882. break;
  883. }
  884. }
  885. return strRet;
  886. }
  887. #define DEF_MAX_COLS 100
  888. #define DEF_COL_SIZE 100
  889. int COpWrap::GetPropIndex(LPCTSTR szName, BOOL bAddToDisplay)
  890. {
  891. for (int i = 0; i <= m_strProps.GetUpperBound(); i++)
  892. {
  893. if (m_strProps[i] == szName)
  894. return i;
  895. }
  896. m_strProps.Add(szName);
  897. if (bAddToDisplay)
  898. {
  899. m_piDisplayCols.Add(i);
  900. if (m_piDisplayCols.GetUpperBound() >
  901. m_piDisplayColsWidth.GetUpperBound())
  902. {
  903. m_piDisplayColsWidth.Add(DEF_COL_SIZE);
  904. }
  905. }
  906. return i;
  907. }
  908. void COpWrap::AddPropsToGlobalIndex(CObjInfo *pInfo)
  909. {
  910. CPropInfoArray *ppProps = pInfo->GetProps();
  911. if (ppProps)
  912. {
  913. CPropInfo *pProps = ppProps->GetData();
  914. int nItems = ppProps->GetSize();
  915. for (int i = 0; i < nItems; i++)
  916. {
  917. int iGlobalIndex = GetPropIndex(pProps[i].m_strName,
  918. !(pProps[i].m_iFlavor == WBEM_FLAVOR_ORIGIN_SYSTEM));
  919. ppProps->m_mapGlobalToLocalIndex.SetAt(iGlobalIndex, i);
  920. }
  921. }
  922. }
  923. void CPropInfoArray::LoadMethods(IWbemClassObject *pClass)
  924. {
  925. HRESULT hr;
  926. // Flush the list.
  927. while(m_listMethods.GetCount())
  928. m_listMethods.RemoveHead();
  929. m_nStaticMethods = 0;
  930. if (pClass && SUCCEEDED(hr = pClass->BeginMethodEnumeration(0)))
  931. {
  932. BSTR pName = NULL;
  933. while(1)
  934. {
  935. hr =
  936. pClass->NextMethod(
  937. 0,
  938. &pName,
  939. NULL,
  940. NULL);
  941. if (FAILED(hr) || hr == WBEM_S_NO_MORE_DATA)
  942. break;
  943. IWbemQualifierSetPtr pQuals;
  944. CMethodInfo method;
  945. method.m_strName = pName;
  946. SysFreeString(pName);
  947. if (SUCCEEDED(hr = pClass->GetMethodQualifierSet(
  948. pName,
  949. &pQuals)))
  950. {
  951. _variant_t vStatic;
  952. if (SUCCEEDED(hr = pQuals->Get(
  953. L"static",
  954. 0,
  955. &vStatic,
  956. NULL)) && vStatic.vt == VT_BOOL && (bool) vStatic == true)
  957. {
  958. method.m_bStatic = TRUE;
  959. m_nStaticMethods++;
  960. }
  961. _variant_t vDesc;
  962. if (SUCCEEDED(hr = pQuals->Get(
  963. L"Description",
  964. 0,
  965. &vDesc,
  966. NULL)) && vDesc.vt == VT_BSTR)
  967. {
  968. method.m_strDescription = vDesc.bstrVal;
  969. }
  970. m_listMethods.AddTail(method);
  971. }
  972. }
  973. }
  974. }
  975. int COpWrap::GetImage()
  976. {
  977. if (m_status == WBEM_STATUS_PROGRESS)
  978. return m_iImageBase + 1; // + 1 == busy
  979. else
  980. {
  981. if (SUCCEEDED(m_hr))
  982. // If we're an object, use our m_objInfo to get the image.
  983. return IsObject() ? m_objInfo.GetImage() : m_iImageBase;
  984. else
  985. // + 2 == error
  986. return m_iImageBase + 2;
  987. }
  988. }
  989. void COpWrap::CancelOp(IWbemServices *pNamespace)
  990. {
  991. if (m_status == WBEM_STATUS_PROGRESS)
  992. {
  993. HRESULT hr;
  994. if (FAILED(hr = pNamespace->CancelAsyncCall(m_pObjSink)))
  995. {
  996. //((IWbemObjectSink*) this)->Release();
  997. SetStatus(
  998. WBEM_STATUS_COMPLETE,
  999. hr,
  1000. NULL,
  1001. NULL);
  1002. }
  1003. }
  1004. }
  1005. IMPLEMENT_SERIAL(COpWrap, CObject, VERSIONABLE_SCHEMA|1)
  1006. void COpWrap::Serialize(CArchive &archive)
  1007. {
  1008. if (archive.IsLoading())
  1009. {
  1010. int type;
  1011. archive >> type;
  1012. m_type = (WMI_OP_TYPE) type;
  1013. archive >> m_strOpText;
  1014. archive >> m_bOption;
  1015. int nCols;
  1016. archive >> nCols;
  1017. if (nCols > 0)
  1018. {
  1019. m_piDisplayColsWidth.SetSize(nCols);
  1020. for (int i = 0; i < nCols; i++)
  1021. {
  1022. int iVal;
  1023. archive >> iVal;
  1024. m_piDisplayColsWidth[i] = iVal;
  1025. }
  1026. }
  1027. Init();
  1028. }
  1029. else
  1030. {
  1031. archive.SetObjectSchema(1);
  1032. archive << (int) m_type;
  1033. archive << m_strOpText;
  1034. archive << m_bOption;
  1035. int nCols = m_piDisplayColsWidth.GetUpperBound() + 1;
  1036. archive << nCols;
  1037. for (int i = 0; i < nCols; i++)
  1038. archive << m_piDisplayColsWidth[i];
  1039. }
  1040. }
  1041. void COpWrap::Init()
  1042. {
  1043. m_hr = S_OK;
  1044. SetHoldsObjects();
  1045. switch(m_type)
  1046. {
  1047. case WMI_QUERY:
  1048. m_iImageBase = IMAGE_QUERY;
  1049. m_iChildImage = IMAGE_OBJECT;
  1050. break;
  1051. case WMI_ENUM_OBJ:
  1052. m_iImageBase = IMAGE_ENUM_OBJ;
  1053. m_iChildImage = IMAGE_OBJECT;
  1054. break;
  1055. case WMI_CREATE_OBJ:
  1056. case WMI_GET_OBJ:
  1057. m_iImageBase = IMAGE_OBJECT;
  1058. m_iChildImage = IMAGE_OBJECT;
  1059. break;
  1060. case WMI_EVENT_QUERY:
  1061. m_iImageBase = IMAGE_EVENT_QUERY;
  1062. m_iChildImage = IMAGE_OBJECT;
  1063. break;
  1064. case WMI_ENUM_CLASS:
  1065. m_iImageBase = IMAGE_ENUM_CLASS;
  1066. m_iChildImage = IMAGE_CLASS;
  1067. break;
  1068. case WMI_CREATE_CLASS:
  1069. case WMI_GET_CLASS:
  1070. m_iImageBase = IMAGE_CLASS;
  1071. m_iChildImage = IMAGE_CLASS;
  1072. break;
  1073. }
  1074. }
  1075. /////////////////////////////////////////////////////////////////////////////
  1076. // CClassToProps
  1077. CClassToProps::~CClassToProps()
  1078. {
  1079. Flush();
  1080. }
  1081. void CClassToProps::Flush()
  1082. {
  1083. POSITION pos = GetStartPosition();
  1084. CPropInfoArray *pProps;
  1085. CString strClass;
  1086. while (pos)
  1087. {
  1088. GetNextAssoc(pos, strClass, pProps);
  1089. delete pProps;
  1090. }
  1091. RemoveAll();
  1092. }
  1093. /////////////////////////////////////////////////////////////////////////////
  1094. // CPropInfo
  1095. // Copy constructor.
  1096. CPropInfo::CPropInfo(const CPropInfo& other)
  1097. {
  1098. *this = other;
  1099. }
  1100. const CPropInfo& CPropInfo::operator=(const CPropInfo& other)
  1101. {
  1102. m_strName = other.m_strName;
  1103. m_iHandle = other.m_iHandle;
  1104. m_type = other.m_type;
  1105. m_iFlavor = other.m_iFlavor;
  1106. m_bKey = other.m_bKey;
  1107. m_dwExpectedSize = other.m_dwExpectedSize;
  1108. m_vt = other.m_vt;
  1109. m_bSigned = other.m_bSigned;
  1110. m_bValueMap = other.m_bValueMap;
  1111. m_bBitmask = other.m_bBitmask;
  1112. // Copy the m_mapValues member.
  1113. POSITION pos = other.m_mapValues.GetStartPosition();
  1114. m_mapValues.RemoveAll();
  1115. while (pos)
  1116. {
  1117. CString strKey,
  1118. strValue;
  1119. other.m_mapValues.GetNextAssoc(pos, strKey, strValue);
  1120. m_mapValues.SetAt(strKey, strValue);
  1121. }
  1122. // Copy the m_bitmaskValues member.
  1123. int nItems = other.m_bitmaskValues.GetSize();
  1124. m_bitmaskValues.SetSize(nItems);
  1125. for (int i = 0; i < nItems; i++)
  1126. m_bitmaskValues[i] = other.m_bitmaskValues[i];
  1127. return *this;
  1128. }
  1129. void CPropInfo::SetType(CIMTYPE type)
  1130. {
  1131. m_type = type;
  1132. m_bSigned = FALSE;
  1133. switch(m_type & ~CIM_FLAG_ARRAY)
  1134. {
  1135. default:
  1136. case CIM_EMPTY:
  1137. m_dwExpectedSize = 0;
  1138. //m_dwArrayItemSize = 0;
  1139. m_vt = VT_EMPTY;
  1140. break;
  1141. case CIM_SINT8:
  1142. m_bSigned = TRUE;
  1143. m_dwExpectedSize = 1;
  1144. // Fall through...
  1145. case CIM_UINT8:
  1146. m_dwExpectedSize = 1;
  1147. //m_dwArrayItemSize = 1;
  1148. m_vt = VT_UI1;
  1149. break;
  1150. case CIM_SINT16:
  1151. m_bSigned = TRUE;
  1152. // Fall through...
  1153. case CIM_CHAR16:
  1154. case CIM_UINT16:
  1155. m_dwExpectedSize = 2;
  1156. //m_dwArrayItemSize = 4;
  1157. m_vt = VT_I2;
  1158. break;
  1159. case CIM_SINT64:
  1160. m_bSigned = TRUE;
  1161. // Fall through...
  1162. case CIM_UINT64:
  1163. m_dwExpectedSize = sizeof(__int64);
  1164. //m_dwArrayItemSize = sizeof(__int64);
  1165. m_vt = VT_I8;
  1166. break;
  1167. case CIM_REAL32:
  1168. m_dwExpectedSize = sizeof(float);
  1169. //m_dwArrayItemSize = sizeof(float);
  1170. m_vt = VT_R4;
  1171. break;
  1172. case CIM_REAL64:
  1173. m_dwExpectedSize = sizeof(double);
  1174. //m_dwArrayItemSize = sizeof(double);
  1175. m_vt = VT_R8;
  1176. break;
  1177. case CIM_BOOLEAN:
  1178. m_dwExpectedSize = sizeof(short);
  1179. //m_dwArrayItemSize = sizeof(short);
  1180. m_vt = VT_BOOL;
  1181. break;
  1182. case CIM_STRING:
  1183. case CIM_DATETIME:
  1184. case CIM_REFERENCE:
  1185. m_dwExpectedSize = MAX_STR_SIZE;
  1186. //m_dwArrayItemSize = sizeof(BSTR*);
  1187. m_vt = VT_BSTR;
  1188. break;
  1189. case CIM_OBJECT:
  1190. m_dwExpectedSize = sizeof(LPVOID);
  1191. //m_dwArrayItemSize = sizeof(BSTR*);
  1192. m_vt = VT_UNKNOWN;
  1193. break;
  1194. case CIM_SINT32:
  1195. m_bSigned = TRUE;
  1196. // Fall through...
  1197. case CIM_UINT32:
  1198. m_dwExpectedSize = sizeof(DWORD);
  1199. //m_dwArrayItemSize = sizeof(DWORD);
  1200. m_vt = VT_I4;
  1201. break;
  1202. }
  1203. if (m_type & CIM_FLAG_ARRAY)
  1204. m_vt = (VARENUM) ((int) m_vt | VT_ARRAY);
  1205. }
  1206. void CPropInfo::GetPropType(
  1207. CString &strType,
  1208. int *piImage,
  1209. BOOL bIgnoreArrayFlag)
  1210. {
  1211. DWORD dwStrID;
  1212. *piImage = IMAGE_PROP_BINARY;
  1213. switch(m_type & ~CIM_FLAG_ARRAY)
  1214. {
  1215. default:
  1216. case CIM_EMPTY:
  1217. dwStrID = IDS_CIM_EMPTY;
  1218. break;
  1219. case CIM_SINT8:
  1220. dwStrID = IDS_CIM_SINT8;
  1221. break;
  1222. case CIM_UINT8:
  1223. dwStrID = IDS_CIM_UINT8;
  1224. break;
  1225. case CIM_SINT16:
  1226. dwStrID = IDS_CIM_SINT16;
  1227. break;
  1228. case CIM_UINT16:
  1229. dwStrID = IDS_CIM_UINT16;
  1230. break;
  1231. case CIM_SINT64:
  1232. dwStrID = IDS_CIM_SINT64;
  1233. break;
  1234. case CIM_UINT64:
  1235. dwStrID = IDS_CIM_UINT64;
  1236. break;
  1237. case CIM_REAL32:
  1238. dwStrID = IDS_CIM_REAL32;
  1239. break;
  1240. case CIM_REAL64:
  1241. dwStrID = IDS_CIM_REAL64;
  1242. break;
  1243. case CIM_BOOLEAN:
  1244. dwStrID = IDS_CIM_BOOLEAN;
  1245. break;
  1246. case CIM_DATETIME:
  1247. dwStrID = IDS_CIM_DATETIME;
  1248. break;
  1249. case CIM_REFERENCE:
  1250. dwStrID = IDS_CIM_REFERENCE;
  1251. *piImage = IMAGE_PROP_OBJECT;
  1252. break;
  1253. case CIM_CHAR16:
  1254. dwStrID = IDS_CIM_CHAR16;
  1255. break;
  1256. case CIM_OBJECT:
  1257. dwStrID = IDS_CIM_OBJECT;
  1258. break;
  1259. case CIM_STRING:
  1260. dwStrID = IDS_CIM_STRING;
  1261. *piImage = IMAGE_PROP_TEXT;
  1262. break;
  1263. case CIM_UINT32:
  1264. dwStrID = IDS_CIM_UINT32;
  1265. break;
  1266. case CIM_SINT32:
  1267. dwStrID = IDS_CIM_SINT32;
  1268. break;
  1269. }
  1270. strType.LoadString(dwStrID);
  1271. if ((m_type & CIM_FLAG_ARRAY) && !bIgnoreArrayFlag)
  1272. {
  1273. CString strArray;
  1274. strArray.LoadString(IDS_CIM_ARRAY);
  1275. strType += _T(" | ");
  1276. strType += strArray;
  1277. }
  1278. if (m_bKey)
  1279. *piImage = *piImage + 1;
  1280. }
  1281. DWORD64 ato64u(LPCTSTR szVal)
  1282. {
  1283. DWORD64 dwRet = 0;
  1284. _stscanf(szVal, _T("%I64u"), &dwRet);
  1285. return dwRet;
  1286. }
  1287. BOOL CPropInfo::SetArrayItem(VARIANT *pVar, DWORD dwIndex, DWORD dwValue)
  1288. {
  1289. ASSERT(m_vt & VT_ARRAY);
  1290. ASSERT(pVar->vt & VT_ARRAY);
  1291. ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
  1292. DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
  1293. LPBYTE pDest = (LPBYTE) pVar->parray->pvData + (dwArrayItemSize * dwIndex);
  1294. BOOL bRet = TRUE;
  1295. switch(dwArrayItemSize)
  1296. {
  1297. case 1:
  1298. *(char*) pDest = dwValue;
  1299. break;
  1300. case 2:
  1301. *(short*) pDest = dwValue;
  1302. break;
  1303. case 4:
  1304. *(int*) pDest = dwValue;
  1305. break;
  1306. default:
  1307. bRet = FALSE;
  1308. }
  1309. return bRet;
  1310. }
  1311. DWORD CPropInfo::GetArrayItem(VARIANT *pVar, DWORD dwIndex)
  1312. {
  1313. ASSERT(m_vt & VT_ARRAY);
  1314. ASSERT(pVar->vt & VT_ARRAY);
  1315. ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
  1316. DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
  1317. LPBYTE pSrc = (LPBYTE) pVar->parray->pvData +
  1318. (dwArrayItemSize * dwIndex);
  1319. DWORD dwRet = 0;
  1320. switch(dwArrayItemSize)
  1321. {
  1322. case 1:
  1323. dwRet = *(char*) pSrc;
  1324. break;
  1325. case 2:
  1326. dwRet = *(short*) pSrc;
  1327. break;
  1328. case 4:
  1329. dwRet = *(int*) pSrc;
  1330. break;
  1331. }
  1332. return dwRet;
  1333. }
  1334. // This one doesn't handle arrays since we'll never go from a single string to
  1335. // an array.
  1336. BOOL CPropInfo::StringToVariant(LPCSTR szValue, VARIANT *pVar, BOOL bTranslate)
  1337. {
  1338. BOOL bRet;
  1339. VARENUM typeRaw = (VARENUM) (m_vt & ~VT_ARRAY);
  1340. VariantClear(pVar);
  1341. pVar->vt = typeRaw;
  1342. if (pVar->vt == VT_I8)
  1343. pVar->vt = VT_BSTR;
  1344. LPVOID pData = &V_BSTR(pVar);
  1345. bRet = StringToVariantBlob(szValue, pData, bTranslate);
  1346. return bRet;
  1347. }
  1348. // TODO: Need to be able to accept dates with month names.
  1349. LPTSTR IntToDMTF(LPTSTR szOut, int iValue, int iDigits)
  1350. {
  1351. _ASSERT(iDigits <= 6 && iDigits >= 0);
  1352. if (iValue == -1)
  1353. {
  1354. memcpy(szOut, _T("******"), iDigits * sizeof(TCHAR));
  1355. szOut[iDigits] = 0;
  1356. }
  1357. else
  1358. {
  1359. char szFormat[100] = _T("%0*d");
  1360. szFormat[2] = '0' + iDigits;
  1361. wsprintf(szOut, szFormat, iValue);
  1362. }
  1363. return szOut;
  1364. }
  1365. enum LOCALE_TOKEN
  1366. {
  1367. L_UNKNOWN,
  1368. L_MONTH_1,
  1369. L_MONTH_2,
  1370. L_MONTH_3,
  1371. L_MONTH_4,
  1372. L_MONTH_5,
  1373. L_MONTH_6,
  1374. L_MONTH_7,
  1375. L_MONTH_8,
  1376. L_MONTH_9,
  1377. L_MONTH_10,
  1378. L_MONTH_11,
  1379. L_MONTH_12,
  1380. L_DATE_SEP,
  1381. L_TIME_SEP,
  1382. L_AM,
  1383. L_PM,
  1384. L_UTC
  1385. };
  1386. class CLocaleInfo
  1387. {
  1388. public:
  1389. TCHAR szDateSep[MAX_PATH],
  1390. szTimeSep[MAX_PATH],
  1391. szPM[MAX_PATH],
  1392. szAM[MAX_PATH],
  1393. szUTC[MAX_PATH],
  1394. szLongMonths[12][MAX_PATH],
  1395. szShortMonths[12][MAX_PATH];
  1396. CLocaleInfo() { Init(); }
  1397. void Init();
  1398. LOCALE_TOKEN GetNextToken(LPCTSTR *ppszCurrent);
  1399. protected:
  1400. BOOL CheckAndIncrement(LPCTSTR szCheckAgainst, LPCTSTR *ppszCurrent);
  1401. };
  1402. LOCALE_TOKEN CLocaleInfo::GetNextToken(LPCTSTR *ppszCurrent)
  1403. {
  1404. if (CheckAndIncrement(szDateSep, ppszCurrent))
  1405. return L_DATE_SEP;
  1406. else if (CheckAndIncrement(szTimeSep, ppszCurrent))
  1407. return L_TIME_SEP;
  1408. else if (CheckAndIncrement(szAM, ppszCurrent))
  1409. return L_AM;
  1410. else if (CheckAndIncrement(szPM, ppszCurrent))
  1411. return L_PM;
  1412. else if (CheckAndIncrement(szUTC, ppszCurrent))
  1413. return L_UTC;
  1414. else
  1415. {
  1416. for (int i = 0; i < 12; i++)
  1417. {
  1418. if (CheckAndIncrement(szLongMonths[i], ppszCurrent))
  1419. return (LOCALE_TOKEN) (L_MONTH_1 + i);
  1420. }
  1421. for (i = 0; i < 12; i++)
  1422. {
  1423. if (CheckAndIncrement(szShortMonths[i], ppszCurrent))
  1424. return (LOCALE_TOKEN) (L_MONTH_1 + i);
  1425. }
  1426. }
  1427. return L_UNKNOWN;
  1428. }
  1429. BOOL CLocaleInfo::CheckAndIncrement(LPCTSTR szCheckAgainst, LPCTSTR *ppszCurrent)
  1430. {
  1431. // Get past the spaces.
  1432. while (isspace(**ppszCurrent))
  1433. (*ppszCurrent)++;
  1434. int nLen = _tcslen(szCheckAgainst);
  1435. BOOL bRet;
  1436. if (!_tcsncmp(szCheckAgainst, *ppszCurrent, nLen))
  1437. {
  1438. bRet = TRUE;
  1439. *ppszCurrent += nLen;
  1440. }
  1441. else
  1442. bRet = FALSE;
  1443. return bRet;
  1444. }
  1445. void CLocaleInfo::Init()
  1446. {
  1447. GetLocaleInfo(
  1448. LOCALE_USER_DEFAULT,
  1449. LOCALE_SDATE,
  1450. szDateSep,
  1451. sizeof(szDateSep) / sizeof(TCHAR));
  1452. _tcsupr(szDateSep);
  1453. GetLocaleInfo(
  1454. LOCALE_USER_DEFAULT,
  1455. LOCALE_STIME,
  1456. szTimeSep,
  1457. sizeof(szTimeSep) / sizeof(TCHAR));
  1458. _tcsupr(szTimeSep);
  1459. GetLocaleInfo(
  1460. LOCALE_USER_DEFAULT,
  1461. LOCALE_S2359,
  1462. szPM,
  1463. sizeof(szPM) / sizeof(TCHAR));
  1464. _tcsupr(szPM);
  1465. GetLocaleInfo(
  1466. LOCALE_USER_DEFAULT,
  1467. LOCALE_S1159,
  1468. szAM,
  1469. sizeof(szAM) / sizeof(TCHAR));
  1470. _tcsupr(szAM);
  1471. for (int i = 0; i < 12; i++)
  1472. {
  1473. GetLocaleInfo(
  1474. LOCALE_USER_DEFAULT,
  1475. LOCALE_SMONTHNAME1 + i,
  1476. szLongMonths[i],
  1477. sizeof(szLongMonths[0]) / sizeof(TCHAR));
  1478. _tcsupr(szLongMonths[i]);
  1479. GetLocaleInfo(
  1480. LOCALE_USER_DEFAULT,
  1481. LOCALE_SABBREVMONTHNAME1 + i,
  1482. szShortMonths[i],
  1483. sizeof(szShortMonths[0]) / sizeof(TCHAR));
  1484. _tcsupr(szShortMonths[i]);
  1485. }
  1486. CString strUTC;
  1487. strUTC.LoadString(IDS_UTC_TOKEN);
  1488. lstrcpy(szUTC, strUTC);
  1489. }
  1490. enum DATE_STATE
  1491. {
  1492. S_BEGIN,
  1493. S_MONTH,
  1494. S_DAY,
  1495. S_YEAR,
  1496. S_HOUR,
  1497. S_MINUTE,
  1498. S_SECOND,
  1499. S_NEED_UTC,
  1500. };
  1501. BOOL DoAMPM(LOCALE_TOKEN token, int *piHour, DATE_STATE *pState)
  1502. {
  1503. BOOL bRet;
  1504. ASSERT(*piHour != -1);
  1505. if (*pState == S_HOUR || *pState == S_MINUTE || *pState == S_SECOND)
  1506. {
  1507. bRet = TRUE;
  1508. if (*piHour == 12 && token == L_AM)
  1509. *piHour = 0;
  1510. else if (*piHour < 12 && token == L_PM)
  1511. *piHour += 12;
  1512. *pState = S_NEED_UTC;
  1513. }
  1514. else
  1515. bRet = FALSE;
  1516. return bRet;
  1517. }
  1518. BOOL DoUTC(int *piOffset, LPCTSTR *pszCurrent, TCHAR *pcOffsetSign, DATE_STATE *pState)
  1519. {
  1520. // Until we prove otherwise...
  1521. BOOL bRet = FALSE;
  1522. TCHAR cSign = **pszCurrent;
  1523. if (cSign == '+' || cSign == '-')
  1524. {
  1525. // Get past the sign.
  1526. (*pszCurrent)++;
  1527. if (isdigit(**pszCurrent))
  1528. {
  1529. *piOffset = _ttoi(*pszCurrent) * 60;
  1530. // Get past the number.
  1531. while (isdigit(**pszCurrent))
  1532. (*pszCurrent)++;
  1533. if (**pszCurrent != ')')
  1534. {
  1535. // Get past the separator.
  1536. while (!isdigit(**pszCurrent) && **pszCurrent)
  1537. (*pszCurrent)++;
  1538. *piOffset += _ttoi(*pszCurrent);
  1539. }
  1540. // Find the end of this thing.
  1541. while (**pszCurrent != ')' && **pszCurrent)
  1542. (*pszCurrent)++;
  1543. if (**pszCurrent == ')')
  1544. {
  1545. *pcOffsetSign = cSign;
  1546. *pState = S_BEGIN;
  1547. (*pszCurrent)++;
  1548. bRet = TRUE;
  1549. }
  1550. }
  1551. }
  1552. return bRet;
  1553. }
  1554. BOOL StringDateTimeToDMTF(LPCTSTR szDateTime, CString &strDateTime)
  1555. {
  1556. CLocaleInfo info;
  1557. DATE_STATE state = S_BEGIN;
  1558. BOOL bMonthFromString = FALSE,
  1559. bPM = FALSE,
  1560. bAM = FALSE;
  1561. int iDay = -1,
  1562. iMonth = -1,
  1563. iYear = -1,
  1564. iHour = -1,
  1565. iMin = -1,
  1566. iSec = -1,
  1567. iMicro = -1,
  1568. iOffset = -1;
  1569. char szOffsetSign[2] = _T("*");
  1570. BOOL bRet = TRUE;
  1571. CString strTemp = szDateTime;
  1572. // So we can do case insensitive compares.
  1573. strTemp.MakeUpper();
  1574. LPCTSTR szCurrent = strTemp;
  1575. while (*szCurrent && bRet)
  1576. {
  1577. while (isspace(*szCurrent))
  1578. szCurrent++;
  1579. ////////////////////////////////////////////////////
  1580. // State action == number found
  1581. if (isdigit(*szCurrent))
  1582. {
  1583. // Reset if we were potentially looking for a UTC and we didn't get it.
  1584. if (state == S_NEED_UTC)
  1585. state = S_BEGIN;
  1586. int iNumber = _ttoi(szCurrent);
  1587. // Get past the current number.
  1588. while (isdigit(*szCurrent))
  1589. szCurrent++;
  1590. LOCALE_TOKEN token = info.GetNextToken(&szCurrent);
  1591. switch(state)
  1592. {
  1593. ////////////////////////////////////////////////////
  1594. // Begin state
  1595. case S_BEGIN:
  1596. if (token == L_TIME_SEP)
  1597. {
  1598. iHour = iNumber;
  1599. state = S_HOUR;
  1600. }
  1601. else if (token == L_DATE_SEP || token == L_UNKNOWN)
  1602. {
  1603. iMonth = iNumber;
  1604. state = S_MONTH;
  1605. }
  1606. else if (token == L_AM || token == L_PM)
  1607. {
  1608. iHour = iNumber;
  1609. state = S_HOUR;
  1610. bRet = DoAMPM(token, &iHour, &state);
  1611. //bAM = token == L_AM;
  1612. //bPM = !bAM;
  1613. //state = S_NEED_UTC;
  1614. }
  1615. else
  1616. bRet = FALSE;
  1617. break;
  1618. ////////////////////////////////////////////////////
  1619. // Date states
  1620. case S_MONTH:
  1621. if (token == L_DATE_SEP)
  1622. {
  1623. iDay = iNumber;
  1624. state = S_DAY;
  1625. }
  1626. else if (token == L_UNKNOWN)
  1627. {
  1628. iYear = iNumber;
  1629. state = S_BEGIN;
  1630. }
  1631. else
  1632. bRet = FALSE;
  1633. break;
  1634. case S_DAY:
  1635. if (token == L_UNKNOWN)
  1636. {
  1637. iYear = iNumber;
  1638. state = S_BEGIN;
  1639. }
  1640. else
  1641. bRet = FALSE;
  1642. break;
  1643. //case S_YEAR:
  1644. // iYear = iNumber;
  1645. // state = S_BEGIN;
  1646. // break;
  1647. ////////////////////////////////////////////////////
  1648. // Time states
  1649. case S_HOUR:
  1650. iMin = iNumber;
  1651. if (token == L_TIME_SEP)
  1652. state = S_MINUTE;
  1653. else if (token == L_AM || token == L_PM)
  1654. bRet = DoAMPM(token, &iHour, &state);
  1655. else if (token == L_UTC)
  1656. bRet = DoUTC(&iOffset, &szCurrent, &szOffsetSign[0], &state);
  1657. else
  1658. bRet = FALSE;
  1659. break;
  1660. case S_MINUTE:
  1661. iSec = iNumber;
  1662. if (token == L_AM || token == L_PM)
  1663. bRet = DoAMPM(token, &iHour, &state);
  1664. else if (token == L_UTC)
  1665. bRet = DoUTC(&iOffset, &szCurrent, &szOffsetSign[0], &state);
  1666. else
  1667. bRet = FALSE;
  1668. break;
  1669. default:
  1670. bRet = FALSE;
  1671. break;
  1672. }
  1673. } // End of state action == number found.
  1674. else
  1675. {
  1676. ////////////////////////////////////////////////////
  1677. // State action == some token
  1678. LOCALE_TOKEN token = info.GetNextToken(&szCurrent);
  1679. // Reset if we were potentially looking for a UTC and we didn't get it.
  1680. if (state == S_NEED_UTC && token != L_UTC)
  1681. state = S_BEGIN;
  1682. // token == string month found
  1683. if (token >= L_MONTH_1 && token <= L_MONTH_12)
  1684. {
  1685. // Move past any non-digits beyond the string date, such as a
  1686. // separator or a comma, etc.
  1687. while (!isdigit(*szCurrent) && *szCurrent)
  1688. szCurrent++;
  1689. if (state == S_BEGIN)
  1690. {
  1691. iMonth = token - L_MONTH_1 + 1;
  1692. state = S_MONTH;
  1693. bMonthFromString = TRUE;
  1694. }
  1695. else if (state == S_MONTH && !bMonthFromString)
  1696. {
  1697. iDay = iMonth;
  1698. iMonth = token - L_MONTH_1 + 1;
  1699. state = S_DAY;
  1700. }
  1701. else
  1702. bRet = FALSE;
  1703. }
  1704. else if (token == L_AM || token == L_PM)
  1705. {
  1706. if (state == S_HOUR || state == S_MINUTE || state == S_SECOND)
  1707. {
  1708. //bAM = token == L_AM;
  1709. //bPM = !bAM;
  1710. bRet = DoAMPM(token, &iHour, &state);
  1711. //state = S_NEED_UTC;
  1712. }
  1713. else
  1714. bRet = FALSE;
  1715. }
  1716. else if (state == S_NEED_UTC)
  1717. {
  1718. bRet = DoUTC(&iOffset, &szCurrent, &szOffsetSign[0], &state);
  1719. }
  1720. else if (token == L_UNKNOWN)
  1721. szCurrent++;
  1722. else
  1723. bRet = FALSE;
  1724. }
  1725. }
  1726. // At this point, we may need to juggle our day and month around, depending
  1727. // on what the order is for the current locale.
  1728. if (iDay != -1 && iMonth != -1 && iYear != -1)
  1729. {
  1730. TCHAR szOrder[2] = _T("0");
  1731. GetLocaleInfo(
  1732. LOCALE_USER_DEFAULT,
  1733. LOCALE_IDATE,
  1734. szOrder,
  1735. sizeof(szOrder) / sizeof(TCHAR));
  1736. // dd/mm/yy
  1737. if (*szOrder == '1')
  1738. {
  1739. int iTemp = iDay;
  1740. iDay = iMonth;
  1741. iMonth = iDay;
  1742. }
  1743. // yy/mm/dd
  1744. else if (*szOrder == '2')
  1745. {
  1746. int iTemp = iDay;
  1747. iDay = iYear;
  1748. iYear = iDay;
  1749. }
  1750. }
  1751. // Finally, splice it all together.
  1752. TCHAR szOut[100] = _T(""),
  1753. szTemp[20];
  1754. lstrcat(szOut, IntToDMTF(szTemp, iYear, 4));
  1755. lstrcat(szOut, IntToDMTF(szTemp, iMonth, 2));
  1756. lstrcat(szOut, IntToDMTF(szTemp, iDay, 2));
  1757. lstrcat(szOut, IntToDMTF(szTemp, iHour, 2));
  1758. lstrcat(szOut, IntToDMTF(szTemp, iMin, 2));
  1759. lstrcat(szOut, IntToDMTF(szTemp, iSec, 2));
  1760. lstrcat(szOut, _T("."));
  1761. lstrcat(szOut, IntToDMTF(szTemp, iMicro, 6));
  1762. lstrcat(szOut, szOffsetSign);
  1763. lstrcat(szOut, IntToDMTF(szTemp, iOffset, 3));
  1764. strDateTime = szOut;
  1765. return TRUE;
  1766. }
  1767. BOOL IsDMTF(LPCTSTR szDate)
  1768. {
  1769. for (int i = 0; i < 14; i++)
  1770. {
  1771. if (!isdigit(szDate[i]) && szDate[i] != '*')
  1772. return FALSE;
  1773. }
  1774. if (szDate[14] != '.')
  1775. return FALSE;
  1776. for (i = 15; i < 21; i++)
  1777. {
  1778. if (!isdigit(szDate[i]) && szDate[i] != '*')
  1779. return FALSE;
  1780. }
  1781. if (szDate[21] != '-' && szDate[21] != '+' && szDate[21] != '*')
  1782. return FALSE;
  1783. for (i = 22; i < 25; i++)
  1784. {
  1785. if (!isdigit(szDate[i]) && szDate[i] != '*')
  1786. return FALSE;
  1787. }
  1788. return TRUE;
  1789. }
  1790. BOOL CPropInfo::StringToVariantBlob(LPCTSTR szValue, LPVOID pData,
  1791. BOOL bTranslate)
  1792. {
  1793. BOOL bRet = TRUE;
  1794. char *szTemp;
  1795. CString strValue;
  1796. VARENUM typeRaw = (VARENUM) (m_vt & ~VT_ARRAY);
  1797. // This one is special-cased from the others because the value will
  1798. // usually be in a localized form, even if bTranslate == FALSE.
  1799. if (typeRaw == VT_BOOL)
  1800. {
  1801. CString strTrue;
  1802. strTrue.LoadString(IDS_TRUE);
  1803. if (!lstrcmpi(strTrue, szValue))
  1804. *(short*) pData = VARIANT_TRUE;
  1805. else
  1806. *(short*) pData = atoi(szValue) ? VARIANT_TRUE : VARIANT_FALSE;
  1807. }
  1808. else
  1809. {
  1810. // Translate if necessary.
  1811. if (bTranslate && m_bValueMap)
  1812. {
  1813. // TODO: We could make this faster if we added a reverse lookup
  1814. // map. For now we'll do a sequential search.
  1815. POSITION pos = m_mapValues.GetStartPosition();
  1816. CString strKey;
  1817. while(pos)
  1818. {
  1819. m_mapValues.GetNextAssoc(pos, strKey, strValue);
  1820. if (!lstrcmpi(szValue, strValue))
  1821. {
  1822. szValue = strKey;
  1823. break;
  1824. }
  1825. }
  1826. }
  1827. switch(typeRaw)
  1828. {
  1829. case VT_I8:
  1830. case VT_BSTR:
  1831. {
  1832. if (GetRawCIMType() != CIM_DATETIME)
  1833. *(BSTR*) pData = _bstr_t(szValue).copy();
  1834. else
  1835. {
  1836. if (!IsDMTF(szValue))
  1837. {
  1838. CString strRet;
  1839. StringDateTimeToDMTF(szValue, strRet);
  1840. _ASSERT(IsDMTF(strRet));
  1841. *(BSTR*) pData = strRet.AllocSysString();
  1842. }
  1843. else
  1844. *(BSTR*) pData = _bstr_t(szValue).copy();
  1845. }
  1846. break;
  1847. }
  1848. case VT_R8:
  1849. *(double*) pData = atof(szValue);
  1850. break;
  1851. case VT_R4:
  1852. *(float*) pData = atof(szValue);
  1853. break;
  1854. case VT_UI1:
  1855. *(char*) pData = m_bSigned ? atoi(szValue) : strtoul(szValue, &szTemp, 10);
  1856. break;
  1857. case VT_I2:
  1858. *(short*) pData = m_bSigned ? atoi(szValue) : strtoul(szValue, &szTemp, 10);
  1859. break;
  1860. case VT_I4:
  1861. *(int*) pData = m_bSigned ? atoi(szValue) : strtoul(szValue, &szTemp, 10);
  1862. break;
  1863. //case VT_I8:
  1864. // *(DWORD64*) pData = m_bSigned ? _atoi64(szValue) : ato64u(szValue);
  1865. // break;
  1866. }
  1867. }
  1868. return bRet;
  1869. }
  1870. // We have to pass the vt as contained on the actual variant because WMI sometimes
  1871. // uses a different VARENUM for Gets/Puts (go figure).
  1872. BOOL CPropInfo::VariantBlobToString(VARENUM vt, LPVOID pData, CString &strValue,
  1873. BOOL bTranslate, BOOL bQuoteStrings)
  1874. {
  1875. VARENUM vtRaw = (VARENUM) (vt & ~VT_ARRAY);
  1876. strValue.Empty();
  1877. switch(vtRaw)
  1878. {
  1879. case VT_BSTR:
  1880. strValue = *(BSTR*) pData;
  1881. break;
  1882. case VT_R8:
  1883. strValue.Format(_T("%.5f"), *(double*) pData);
  1884. break;
  1885. case VT_R4:
  1886. strValue.Format(_T("%.5f"), *(float*) pData);
  1887. break;
  1888. case VT_UI1:
  1889. {
  1890. if (m_bSigned)
  1891. strValue.Format(_T("%d"), *(char*) pData);
  1892. else
  1893. strValue.Format(_T("%u"), *(BYTE*) pData);
  1894. break;
  1895. }
  1896. case VT_I2:
  1897. {
  1898. if (m_bSigned)
  1899. strValue.Format(_T("%d"), *(short*) pData);
  1900. else
  1901. strValue.Format(_T("%u"), *(WORD*) pData);
  1902. break;
  1903. }
  1904. case VT_I4:
  1905. {
  1906. if (m_bSigned)
  1907. strValue.Format(_T("%d"), *(int*) pData);
  1908. else
  1909. strValue.Format(_T("%u"), *(DWORD*) pData);
  1910. break;
  1911. }
  1912. case VT_I8:
  1913. {
  1914. if (m_bSigned)
  1915. strValue.Format(_T("%I64d"), *(__int64*) pData);
  1916. else
  1917. strValue.Format(_T("%I64u"), *(DWORD64*) pData);
  1918. break;
  1919. }
  1920. case VT_BOOL:
  1921. strValue.LoadString(*(short*) pData ? IDS_TRUE : IDS_FALSE);
  1922. break;
  1923. case VT_UNKNOWN:
  1924. //strValue.Format(IDS_EMBEDDED_OBJECT, *(IUnknown*) pData);
  1925. strValue = GetEmbeddedObjectText(*(IUnknown**) pData);
  1926. break;
  1927. }
  1928. if (bTranslate && !strValue.IsEmpty())
  1929. {
  1930. if (m_bValueMap)
  1931. {
  1932. CString strKey = strValue;
  1933. m_mapValues.Lookup(strKey, strValue);
  1934. }
  1935. else if (m_bBitmask)
  1936. {
  1937. DWORD nSize = m_bitmaskValues.GetSize(),
  1938. dwValue = *(DWORD*) pData;
  1939. // Clear this out.
  1940. strValue.Empty();
  1941. for (int i = 0; i < nSize; i++)
  1942. {
  1943. CString strPart;
  1944. if (dwValue & m_bitmaskValues[i].m_dwBitmaskValue)
  1945. {
  1946. if (!strValue.IsEmpty())
  1947. strValue += _T(" | ");
  1948. strValue += m_bitmaskValues[i].m_strName;
  1949. }
  1950. }
  1951. }
  1952. else if (GetRawCIMType() == CIM_DATETIME)
  1953. {
  1954. struct DATETIME_INFO
  1955. {
  1956. TCHAR szYear[5],
  1957. szMonth[3],
  1958. szDay[3],
  1959. szHour[3],
  1960. szMin[3],
  1961. szSec[3],
  1962. szMicro[7],
  1963. cSep,
  1964. szOffset[4];
  1965. } datetime;
  1966. ZeroMemory(&datetime, sizeof(datetime));
  1967. if (_stscanf(
  1968. strValue,
  1969. _T("%4c%2c%2c%2c%2c%2c.%6c%c%3c"),
  1970. datetime.szYear,
  1971. datetime.szMonth,
  1972. datetime.szDay,
  1973. datetime.szHour,
  1974. datetime.szMin,
  1975. datetime.szSec,
  1976. datetime.szMicro,
  1977. &datetime.cSep,
  1978. datetime.szOffset) == 9)
  1979. {
  1980. SYSTEMTIME systime;
  1981. TCHAR szDate[100] = _T(""),
  1982. szTime[100] = _T("");
  1983. // _stscanf seems to be screwing this up, so fix it.
  1984. datetime.szOffset[3] = 0;
  1985. ZeroMemory(&systime, sizeof(systime));
  1986. // Figure out the date.
  1987. if (*datetime.szYear != '*' && *datetime.szMonth != '*')
  1988. {
  1989. DWORD dwFlag;
  1990. TCHAR szFormat[10],
  1991. *pszFormat;
  1992. systime.wYear = (WORD) _ttoi(datetime.szYear);
  1993. systime.wMonth = (WORD) _ttoi(datetime.szMonth);
  1994. if (*datetime.szDay == '*')
  1995. {
  1996. // This would have been nice to use, but it only lives
  1997. // on W2K.
  1998. //dwFlag = DATE_YEARMONTH;
  1999. TCHAR szSep[100];
  2000. if (GetLocaleInfo(
  2001. LOCALE_USER_DEFAULT,
  2002. LOCALE_SDATE,
  2003. szSep,
  2004. sizeof(szSep) / sizeof(TCHAR)))
  2005. {
  2006. // Otherwise GetDateFormat will fail, even though
  2007. // it doesn't need it!
  2008. systime.wDay = 1;
  2009. wsprintf(szFormat, _T("MM%syyyy"), szSep);
  2010. dwFlag = 0;
  2011. pszFormat = szFormat;
  2012. }
  2013. }
  2014. else
  2015. {
  2016. dwFlag = DATE_SHORTDATE;
  2017. pszFormat = NULL;
  2018. systime.wDay = (WORD) _ttoi(datetime.szDay);
  2019. }
  2020. GetDateFormat(
  2021. LOCALE_USER_DEFAULT,
  2022. dwFlag,
  2023. &systime,
  2024. pszFormat,
  2025. szDate,
  2026. sizeof(szDate) / sizeof(TCHAR));
  2027. }
  2028. // Figure out the time.
  2029. if (*datetime.szHour != '*')
  2030. {
  2031. DWORD dwFlag = 0;
  2032. systime.wHour = (WORD) _ttoi(datetime.szHour);
  2033. if (*datetime.szMin == '*')
  2034. dwFlag = TIME_NOMINUTESORSECONDS;
  2035. else
  2036. {
  2037. systime.wMinute = (WORD) _ttoi(datetime.szMin);
  2038. if (*datetime.szSec == '*')
  2039. dwFlag = TIME_NOSECONDS;
  2040. else
  2041. systime.wSecond = (WORD) _ttoi(datetime.szSec);
  2042. }
  2043. GetTimeFormat(
  2044. LOCALE_USER_DEFAULT,
  2045. dwFlag,
  2046. &systime,
  2047. NULL,
  2048. szTime,
  2049. sizeof(szTime) / sizeof(TCHAR));
  2050. if (*szTime &&
  2051. (datetime.cSep == '-' || datetime.cSep == '+') &&
  2052. *datetime.szOffset != '*')
  2053. {
  2054. CString strOffset;
  2055. DWORD dwMinutes = _ttoi(datetime.szOffset);
  2056. strOffset.FormatMessage(
  2057. IDS_UTC, datetime.cSep, dwMinutes / 60,
  2058. dwMinutes % 60);
  2059. strcat(szTime, strOffset);
  2060. }
  2061. }
  2062. strValue = szDate;
  2063. if (*szTime)
  2064. {
  2065. if (!strValue.IsEmpty())
  2066. strValue += _T(" ");
  2067. strValue += szTime;
  2068. }
  2069. }
  2070. }
  2071. }
  2072. if (bQuoteStrings && GetRawCIMType() == CIM_STRING)
  2073. {
  2074. CString strTemp;
  2075. strTemp.Format(_T("\"%s\""), (LPCTSTR) strValue);
  2076. strValue = strTemp;
  2077. }
  2078. return TRUE;
  2079. }
  2080. DWORD CPropInfo::GetArrayItemCount(VARIANT *pVar)
  2081. {
  2082. return pVar->parray->rgsabound[0].cElements;
  2083. }
  2084. BOOL CPropInfo::ArrayItemToString(VARIANT *pVar, DWORD dwIndex,
  2085. CString &strValue, BOOL bTranslate)
  2086. {
  2087. ASSERT(m_vt & VT_ARRAY);
  2088. ASSERT(pVar->vt & VT_ARRAY);
  2089. ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
  2090. BOOL bRet = TRUE;
  2091. LPBYTE pData = (LPBYTE) pVar->parray->pvData;
  2092. CString strItem;
  2093. DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
  2094. if (VariantBlobToString(
  2095. (VARENUM) pVar->vt,
  2096. pData + (dwArrayItemSize * dwIndex),
  2097. strItem,
  2098. bTranslate,
  2099. FALSE))
  2100. strValue = strItem;
  2101. return bRet;
  2102. }
  2103. BOOL CPropInfo::PrepArrayVar(VARIANT *pVar, DWORD dwSize)
  2104. {
  2105. BOOL bRet = FALSE;
  2106. ASSERT((m_vt & VT_ARRAY) != 0);
  2107. VariantClear(pVar);
  2108. if (dwSize > 0)
  2109. {
  2110. SAFEARRAYBOUND bound;
  2111. pVar->vt = m_vt;
  2112. if (pVar->vt == (VT_I8 | VT_ARRAY))
  2113. pVar->vt = VT_BSTR | VT_ARRAY;
  2114. bound.lLbound = 0;
  2115. bound.cElements = dwSize;
  2116. pVar->parray = SafeArrayCreate(pVar->vt & ~VT_ARRAY, 1, &bound);
  2117. bRet = pVar->parray != NULL;
  2118. }
  2119. else
  2120. {
  2121. pVar->vt = VT_NULL;
  2122. bRet = TRUE;
  2123. }
  2124. return bRet;
  2125. }
  2126. BOOL CPropInfo::StringToArrayItem(LPCTSTR szItem, VARIANT *pVar, DWORD dwIndex,
  2127. BOOL bTranslate)
  2128. {
  2129. //ASSERT(m_vt & VT_ARRAY);
  2130. ASSERT(pVar->vt & VT_ARRAY);
  2131. ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
  2132. BOOL bRet = TRUE;
  2133. LPBYTE pData = (LPBYTE) pVar->parray->pvData;
  2134. DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
  2135. bRet =
  2136. StringToVariantBlob(szItem, pData + (dwArrayItemSize * dwIndex),
  2137. bTranslate);
  2138. return bRet;
  2139. }
  2140. int CPropInfo::GetArrayItemSize(VARENUM vt)
  2141. {
  2142. switch(vt & ~VT_ARRAY)
  2143. {
  2144. case VT_UI1:
  2145. case VT_I1:
  2146. return 1;
  2147. case VT_BOOL:
  2148. case VT_I2:
  2149. return 2;
  2150. case VT_I4:
  2151. return 4;
  2152. case VT_I8:
  2153. return 8;
  2154. case VT_UNKNOWN:
  2155. case VT_BSTR:
  2156. return sizeof(BSTR*);
  2157. case VT_R4:
  2158. return sizeof(float);
  2159. case VT_R8:
  2160. return sizeof(double);
  2161. default:
  2162. // This shouldn't happen! If it does, add another case statement.
  2163. ASSERT(FALSE);
  2164. return 0;
  2165. }
  2166. }
  2167. BOOL CPropInfo::VariantToString(VARIANT *pVar, CString &strValue,
  2168. BOOL bTranslate, BOOL bQuoteStrings)
  2169. {
  2170. BOOL bRet = TRUE;
  2171. if (pVar->vt != VT_NULL)
  2172. {
  2173. if (pVar->vt & VT_ARRAY)
  2174. {
  2175. DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
  2176. strValue.Empty();
  2177. LPBYTE pData = (LPBYTE) pVar->parray->pvData;
  2178. CString strItem;
  2179. for (int i = 0; i < pVar->parray->rgsabound[0].cElements;
  2180. i++, pData += dwArrayItemSize)
  2181. {
  2182. VariantBlobToString((VARENUM) pVar->vt, pData, strItem,
  2183. bTranslate, bQuoteStrings);
  2184. if (i != 0)
  2185. strValue += _T(", ");
  2186. strValue += strItem;
  2187. }
  2188. }
  2189. else
  2190. {
  2191. LPVOID pData = &V_BSTR(pVar);
  2192. VariantBlobToString((VARENUM) pVar->vt, pData, strValue,
  2193. bTranslate, bQuoteStrings);
  2194. }
  2195. }
  2196. else
  2197. strValue.LoadString(IDS_NULL);
  2198. return bRet;
  2199. }
  2200. // Use this to get __ExtendedStatus.
  2201. IWbemClassObject *GetWMIErrorObject()
  2202. {
  2203. IWbemClassObject *pObj = NULL;
  2204. IErrorInfo *pInfo = NULL;
  2205. if (SUCCEEDED(GetErrorInfo(0, &pInfo)) && pInfo != NULL)
  2206. {
  2207. pInfo->QueryInterface(IID_IWbemClassObject, (LPVOID*) &pObj);
  2208. pInfo->Release();
  2209. }
  2210. return pObj;
  2211. }
  2212. // Wbemcomn.dll prototypes.
  2213. typedef HRESULT (IWbemClassObject::*FPGET_PROPERTY_HANDLE_EX)(LPCWSTR, CIMTYPE*, long*);
  2214. typedef LPVOID (IWbemClassObject::*FPGET_ARRAY_BY_HANDLE)(long);
  2215. void CObjInfo::DoDebugStuff()
  2216. {
  2217. // I tried doing directly (from GetProcAddress into memember vars) but
  2218. // I couldn't come up with a conversion the compiler would let me do.
  2219. // So, do it the hardway.
  2220. HINSTANCE hWbemComn = GetModuleHandle(_T("wbemcomn.dll"));
  2221. FARPROC fpGetPropertyHandleEx =
  2222. GetProcAddress(
  2223. hWbemComn,
  2224. "?GetPropertyHandleEx@CWbemObject@@QAEJPBGPAJ1@Z");
  2225. FARPROC fpGetArrayByHandle =
  2226. GetProcAddress(
  2227. hWbemComn,
  2228. "?GetArrayByHandle@CWbemObject@@QAEPAVCUntypedArray@@J@Z");
  2229. FPGET_PROPERTY_HANDLE_EX
  2230. m_fpGetPropertyHandleEx;
  2231. FPGET_ARRAY_BY_HANDLE
  2232. m_fpGetArrayByHandle;
  2233. memcpy(
  2234. &m_fpGetPropertyHandleEx,
  2235. &fpGetPropertyHandleEx,
  2236. sizeof(fpGetPropertyHandleEx));
  2237. memcpy(
  2238. &m_fpGetArrayByHandle,
  2239. &fpGetArrayByHandle,
  2240. sizeof(fpGetArrayByHandle));
  2241. SAFEARRAY *pArr = NULL;
  2242. if (SUCCEEDED(m_pObj->GetNames(NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &pArr)))
  2243. {
  2244. BSTR *pNames = (BSTR*) pArr->pvData;
  2245. int nItems = pArr->rgsabound[0].cElements;
  2246. for (int i = 0; i < nItems; i++)
  2247. {
  2248. CIMTYPE type;
  2249. long handle;
  2250. if (SUCCEEDED(
  2251. (m_pObj->*m_fpGetPropertyHandleEx)(
  2252. pNames[i],
  2253. &type,
  2254. &handle)))
  2255. {
  2256. LPVOID pData = (m_pObj->*m_fpGetArrayByHandle)(handle);
  2257. int x;
  2258. x = 3;
  2259. HRESULT hr;
  2260. _variant_t vValue;
  2261. hr =
  2262. m_pObj->Get(
  2263. pNames[i],
  2264. 0,
  2265. &vValue,
  2266. &type,
  2267. NULL);
  2268. BSTR *pStrings = NULL;
  2269. if (vValue.vt == (VT_BSTR | VT_ARRAY))
  2270. pStrings = (BSTR*) vValue.parray->pvData;
  2271. hr =
  2272. m_pObj->Put(
  2273. pNames[i],
  2274. 0,
  2275. &vValue,
  2276. 0);
  2277. }
  2278. }
  2279. SafeArrayDestroy(pArr);
  2280. }
  2281. }