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.

563 lines
11 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. MultiSzHelper.cpp
  5. Abstract:
  6. Implements the CMultiSzHelper class
  7. Author:
  8. Mohit Srivastava 22-March-01
  9. Revision History:
  10. --*/
  11. #include "MultiSzHelper.h"
  12. #include <iiscnfg.h>
  13. #include <dbgutil.h>
  14. #include <atlbase.h>
  15. #include "utils.h"
  16. //
  17. // CMultiSz
  18. //
  19. CMultiSz::CMultiSz()
  20. {
  21. m_pMbp = NULL;
  22. m_pNamespace = NULL;
  23. m_pFormattedMultiSz = NULL;
  24. }
  25. CMultiSz::CMultiSz(
  26. METABASE_PROPERTY* i_pMbp,
  27. CWbemServices* i_pNamespace)
  28. {
  29. DBG_ASSERT(i_pMbp != NULL);
  30. DBG_ASSERT(i_pNamespace != NULL);
  31. m_pMbp = i_pMbp;
  32. m_pNamespace = i_pNamespace;
  33. m_pFormattedMultiSz = NULL;
  34. if(m_pMbp != NULL)
  35. {
  36. TFormattedMultiSz* pFormattedMultiSz = NULL;
  37. for(ULONG i = 0; ; i++)
  38. {
  39. pFormattedMultiSz = TFormattedMultiSzData::apFormattedMultiSz[i];
  40. if(pFormattedMultiSz == NULL)
  41. {
  42. break;
  43. }
  44. else if(pFormattedMultiSz->dwPropId == m_pMbp->dwMDIdentifier)
  45. {
  46. m_pFormattedMultiSz = pFormattedMultiSz;
  47. break;
  48. }
  49. }
  50. }
  51. }
  52. CMultiSz::~CMultiSz()
  53. {
  54. }
  55. HRESULT CMultiSz::ToMetabaseForm(
  56. const VARIANT* i_pvt,
  57. LPWSTR* o_pmsz,
  58. PDWORD io_pdw)
  59. {
  60. DBG_ASSERT(i_pvt != NULL);
  61. DBG_ASSERT(o_pmsz != NULL);
  62. DBG_ASSERT(io_pdw != NULL);
  63. *o_pmsz = NULL;
  64. *io_pdw = NULL;
  65. return CreateMultiSzFromSafeArray(
  66. *i_pvt,
  67. o_pmsz,
  68. io_pdw);
  69. }
  70. HRESULT CMultiSz::ToWmiForm(
  71. LPCWSTR i_msz,
  72. VARIANT* io_pvt)
  73. {
  74. DBG_ASSERT(i_msz != NULL);
  75. DBG_ASSERT(io_pvt != NULL);
  76. return LoadSafeArrayFromMultiSz(
  77. i_msz,
  78. *io_pvt);
  79. }
  80. //
  81. // private
  82. //
  83. HRESULT CMultiSz::CreateMultiSzFromSafeArray(
  84. const VARIANT& i_vt,
  85. WCHAR** o_pmsz,
  86. DWORD* io_pdw
  87. )
  88. /*++
  89. Synopsis:
  90. Arguments: [i_vt] -
  91. [o_pmsz] -
  92. [io_pdw] -
  93. --*/
  94. {
  95. DBG_ASSERT(i_vt.vt == (VT_ARRAY | VT_BSTR) || i_vt.vt == (VT_ARRAY | VT_UNKNOWN));
  96. DBG_ASSERT(o_pmsz != NULL);
  97. DBG_ASSERT(io_pdw != NULL);
  98. HRESULT hr = S_OK;
  99. if(i_vt.parray == NULL)
  100. {
  101. *o_pmsz = NULL;
  102. *io_pdw = 0;
  103. }
  104. WCHAR* msz = NULL;
  105. long iLo,iUp,c;
  106. SAFEARRAY* psa = i_vt.parray;
  107. long i = 0;
  108. BSTR bstr = NULL;
  109. hr = SafeArrayGetLBound(psa,1,&iLo);
  110. if(FAILED(hr))
  111. {
  112. goto exit;
  113. }
  114. hr = SafeArrayGetUBound(psa,1,&iUp);
  115. if(FAILED(hr))
  116. {
  117. goto exit;
  118. }
  119. for (*io_pdw=0, c = iLo; c <= iUp; c++)
  120. {
  121. if(m_pFormattedMultiSz)
  122. {
  123. DBG_ASSERT(m_pMbp != NULL);
  124. DBG_ASSERT(m_pNamespace != NULL);
  125. CComPtr<IWbemClassObject> spObj;
  126. hr = SafeArrayGetElement(psa, &c, &spObj);
  127. if(FAILED(hr))
  128. {
  129. goto exit;
  130. }
  131. hr = UnparseEntry(spObj, &bstr);
  132. if(FAILED(hr))
  133. {
  134. goto exit;
  135. }
  136. }
  137. else
  138. {
  139. hr = SafeArrayGetElement(psa,&c,&bstr);
  140. if(FAILED(hr))
  141. {
  142. goto exit;
  143. }
  144. }
  145. *io_pdw = *io_pdw + wcslen(bstr) + 1;
  146. hr = MzCat(&msz,bstr);
  147. if(FAILED(hr))
  148. {
  149. goto exit;
  150. }
  151. SysFreeString(bstr);
  152. bstr = NULL;
  153. }
  154. *io_pdw +=1;
  155. *o_pmsz = msz;
  156. exit:
  157. if(FAILED(hr))
  158. {
  159. delete [] msz;
  160. msz = NULL;
  161. }
  162. SysFreeString(bstr);
  163. bstr = NULL;
  164. return hr;
  165. }
  166. HRESULT CMultiSz::MzCat(
  167. WCHAR** io_ppdst,
  168. const WCHAR* i_psz
  169. )
  170. /*++
  171. Synopsis:
  172. The metabase has this animal called METADATA_STRINGSZ which has the
  173. following form: <string><null><string><null><null>. MzCat concatenates
  174. strings in the defined way. *io_ppdst has the new pointer upon exit. The
  175. previous value of *io_ppdst is delelted. *io_ppdst == NULL is handled.
  176. Arguments: [io_ppdst] -
  177. [i_psz] -
  178. --*/
  179. {
  180. DBG_ASSERT(io_ppdst != NULL);
  181. WCHAR *psrc;
  182. WCHAR *pdst;
  183. WCHAR *pnew;
  184. int ilen;
  185. if (i_psz == NULL)
  186. return WBEM_E_FAILED;
  187. if (*io_ppdst)
  188. {
  189. for ( ilen=0, psrc = *io_ppdst
  190. ; *psrc || *(psrc+1)
  191. ; psrc++, ilen++
  192. )
  193. {
  194. ;
  195. }
  196. ilen = ilen + wcslen(i_psz)+3;
  197. }
  198. else ilen = wcslen(i_psz)+2;
  199. pnew = pdst = new WCHAR[ilen];
  200. if (!pdst)
  201. return WBEM_E_OUT_OF_MEMORY;
  202. if (*io_ppdst)
  203. {
  204. for ( psrc = *io_ppdst
  205. ; *psrc || *(psrc+1)
  206. ; pdst++, psrc++
  207. )
  208. {
  209. *pdst = *psrc;
  210. }
  211. *pdst = L'\0';
  212. pdst++;
  213. }
  214. wcscpy(pdst,i_psz);
  215. *(pnew+ilen-1)=L'\0';
  216. delete *io_ppdst;
  217. *io_ppdst=pnew;
  218. return WBEM_S_NO_ERROR;
  219. }
  220. HRESULT CMultiSz::LoadSafeArrayFromMultiSz(
  221. LPCWSTR i_msz,
  222. VARIANT& io_vt)
  223. /*++
  224. Synopsis:
  225. Arguments: [i_msz] -
  226. [io_vt] -
  227. Return Value:
  228. --*/
  229. {
  230. DBG_ASSERT(i_msz != NULL);
  231. LPCWSTR msz;
  232. HRESULT hr = WBEM_S_NO_ERROR;
  233. DWORD c;
  234. SAFEARRAYBOUND aDim;
  235. SAFEARRAY* psa = NULL;
  236. long i = 0;
  237. VARTYPE vtypeData = (m_pFormattedMultiSz) ? VT_UNKNOWN : VT_BSTR;
  238. CComPtr<IWbemClassObject> spClass;
  239. //
  240. // figure the dimensions of the multisz
  241. //
  242. for (c=1,msz=i_msz; *msz||*(msz+1); msz++)
  243. {
  244. if(!*msz)
  245. {
  246. c++;
  247. }
  248. }
  249. aDim.lLbound = 0;
  250. aDim.cElements= c;
  251. psa = SafeArrayCreate(vtypeData, 1, &aDim);
  252. if (!psa)
  253. {
  254. hr = WBEM_E_OUT_OF_MEMORY;
  255. goto exit;
  256. }
  257. if( m_pFormattedMultiSz )
  258. {
  259. HRESULT hr = S_OK;
  260. hr = m_pNamespace->GetObject(
  261. m_pFormattedMultiSz->wszWmiClassName,
  262. 0,
  263. NULL,
  264. &spClass,
  265. NULL);
  266. if(FAILED(hr))
  267. {
  268. goto exit;
  269. }
  270. }
  271. for (msz=i_msz; ; i++)
  272. {
  273. if(m_pFormattedMultiSz)
  274. {
  275. DBG_ASSERT(m_pMbp != NULL);
  276. DBG_ASSERT(m_pNamespace != NULL);
  277. CComPtr<IWbemClassObject> spObj;
  278. hr = spClass->SpawnInstance(0, &spObj);
  279. if(FAILED(hr))
  280. {
  281. goto exit;
  282. }
  283. hr = ParseEntry(msz, spObj);
  284. if(FAILED(hr))
  285. {
  286. goto exit;
  287. }
  288. hr = SafeArrayPutElement(psa, &i, spObj);
  289. if(FAILED(hr))
  290. {
  291. goto exit;
  292. }
  293. }
  294. else
  295. {
  296. CComBSTR sbstr = msz;
  297. if(sbstr.m_str == NULL)
  298. {
  299. hr = WBEM_E_OUT_OF_MEMORY;
  300. goto exit;
  301. }
  302. hr = SafeArrayPutElement(psa, &i, (BSTR)sbstr);
  303. if(FAILED(hr))
  304. {
  305. goto exit;
  306. }
  307. }
  308. msz += wcslen(msz) + 1;
  309. if (!*msz)
  310. {
  311. break;
  312. }
  313. }
  314. io_vt.vt = VT_ARRAY | vtypeData;
  315. io_vt.parray = psa;
  316. exit:
  317. if (psa && FAILED(hr))
  318. {
  319. SafeArrayDestroy(psa);
  320. }
  321. return hr;
  322. }
  323. HRESULT CMultiSz::ParseEntry(
  324. LPCWSTR i_wszEntry,
  325. IWbemClassObject* io_pObj)
  326. /*++
  327. Synopsis:
  328. Arguments: [i_wszEntry] -
  329. [io_pObj] - WMI object corresponding to the particular entry.
  330. SpawnInstance should have been called by caller.
  331. Return Value:
  332. --*/
  333. {
  334. DBG_ASSERT(i_wszEntry != NULL);
  335. DBG_ASSERT(io_pObj != NULL);
  336. DBG_ASSERT(m_pFormattedMultiSz != NULL);
  337. HRESULT hr = WBEM_S_NO_ERROR;
  338. ULONG idx = 0;
  339. LPCWSTR wszValue = NULL;
  340. ULONG NrFields = 0;
  341. CComPtr<IWbemClassObject> spObj = io_pObj; // dest object
  342. //
  343. // Make a copy of the entry. Put on stack or heap depending on size.
  344. //
  345. WCHAR wszBufStack[64];
  346. LPWSTR wszBufDyn = NULL;
  347. LPWSTR wszEntry = NULL;
  348. ULONG cchEntry = wcslen(i_wszEntry);
  349. if((cchEntry+1) < 64)
  350. {
  351. wszEntry = wszBufStack;
  352. }
  353. else
  354. {
  355. wszBufDyn = new WCHAR[cchEntry+1];
  356. if(wszBufDyn == NULL)
  357. {
  358. hr = WBEM_E_OUT_OF_MEMORY;
  359. goto exit;
  360. }
  361. wszEntry = wszBufDyn;
  362. }
  363. memcpy(wszEntry, i_wszEntry, sizeof(WCHAR) * (cchEntry + 1));
  364. //
  365. // get the number of fields
  366. //
  367. if(m_pFormattedMultiSz->awszFields != NULL)
  368. {
  369. for(idx = 0; m_pFormattedMultiSz->awszFields[idx] != NULL; idx++)
  370. {
  371. }
  372. NrFields = idx;
  373. DBG_ASSERT(NrFields <= MAX_FIELDS);
  374. }
  375. //
  376. // Parse
  377. //
  378. ULONG jdx = 0;
  379. LONG idxEndOfLastString = -1;
  380. for(idx = 0; idx < (cchEntry+1) && jdx < NrFields; idx++)
  381. {
  382. if( wszEntry[idx] == m_pFormattedMultiSz->wcDelim ||
  383. wszEntry[idx] == L'\0' )
  384. {
  385. //
  386. // If there's only one spot left in our array, we take the remaining
  387. // string -- including delimeters -- and put it as the last element
  388. //
  389. if(jdx != NrFields-1)
  390. {
  391. wszEntry[idx] = L'\0';
  392. }
  393. CComVariant vtEntry;
  394. vtEntry = wszEntry + idxEndOfLastString + 1;
  395. if(vtEntry.vt == VT_ERROR)
  396. {
  397. hr = vtEntry.scode;
  398. goto exit;
  399. }
  400. hr = spObj->Put(
  401. m_pFormattedMultiSz->awszFields[jdx],
  402. 0,
  403. &vtEntry,
  404. 0);
  405. if(FAILED(hr))
  406. {
  407. goto exit;
  408. }
  409. jdx++;
  410. idxEndOfLastString = idx;
  411. }
  412. }
  413. exit:
  414. delete [] wszBufDyn;
  415. wszBufDyn = NULL;
  416. return hr;
  417. }
  418. HRESULT CMultiSz::UnparseEntry(
  419. IWbemClassObject* i_pObj,
  420. BSTR* o_pbstrEntry)
  421. {
  422. DBG_ASSERT(i_pObj != NULL);
  423. DBG_ASSERT(o_pbstrEntry != NULL);
  424. DBG_ASSERT(m_pFormattedMultiSz != NULL);
  425. *o_pbstrEntry = NULL;
  426. HRESULT hr = S_OK;
  427. LPCWSTR* awszFields = m_pFormattedMultiSz->awszFields;
  428. CComBSTR sbstrUnparsed;
  429. if(awszFields == NULL)
  430. {
  431. goto exit;
  432. }
  433. WCHAR wszDelim[2];
  434. wszDelim[0] = m_pFormattedMultiSz->wcDelim;
  435. wszDelim[1] = L'\0';
  436. for(ULONG i = 0; awszFields[i] != NULL; i++)
  437. {
  438. CComVariant vtValue;
  439. hr = i_pObj->Get(
  440. awszFields[i],
  441. 0,
  442. &vtValue,
  443. NULL,
  444. NULL);
  445. if(FAILED(hr))
  446. {
  447. goto exit;
  448. }
  449. if(vtValue.vt == VT_BSTR && vtValue.bstrVal != NULL)
  450. {
  451. sbstrUnparsed += vtValue.bstrVal;
  452. if(sbstrUnparsed.m_str == NULL)
  453. {
  454. hr = WBEM_E_OUT_OF_MEMORY;
  455. goto exit;
  456. }
  457. }
  458. if(awszFields[i+1] != NULL)
  459. {
  460. sbstrUnparsed += wszDelim;
  461. if(sbstrUnparsed.m_str == NULL)
  462. {
  463. hr = WBEM_E_OUT_OF_MEMORY;
  464. goto exit;
  465. }
  466. }
  467. }
  468. //
  469. // Set out parameters if everything succeeded
  470. //
  471. *o_pbstrEntry = sbstrUnparsed.Detach();
  472. exit:
  473. return hr;
  474. }