Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

602 lines
15 KiB

  1. /*++
  2. Copyright (C) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. CVARIANT.CPP
  5. Abstract:
  6. Defines the CVarinat class which is a purpose object to
  7. wrap VARIANT structures.
  8. History:
  9. a-davj 4-27-95 Created.
  10. --*/
  11. #include "precomp.h"
  12. #include "impdyn.h"
  13. #include "cvariant.h"
  14. //#include <afxpriv.h>
  15. BSTR SysAllocBstrFromTCHAR(TCHAR * pFrom)
  16. {
  17. #ifdef UNICODE
  18. return SysAllocString(pFrom);
  19. #else
  20. WCHAR * pTemp = new WCHAR[lstrlen(pFrom)+1];
  21. if(pTemp == NULL)
  22. return NULL;
  23. mbstowcs(pTemp, pFrom, lstrlen(pFrom)+1);
  24. BSTR bRet = SysAllocString(pTemp);
  25. delete pTemp;
  26. return bRet;
  27. #endif
  28. }
  29. //***************************************************************************
  30. //
  31. // int CVariant::CalcNumStrings
  32. //
  33. // DESCRIPTION:
  34. //
  35. // Calculates the number of strings
  36. //
  37. // PARAMETERS:
  38. //
  39. // pTest points to string to test
  40. //
  41. // RETURN VALUE:
  42. // Return - the number of strings in a multistring block.
  43. //
  44. //***************************************************************************
  45. int CVariant::CalcNumStrings(
  46. IN TCHAR *pTest)
  47. {
  48. int iRet = 0;
  49. if(pTest == NULL)
  50. return 0;
  51. while(*pTest)
  52. {
  53. iRet++;
  54. pTest += lstrlen(pTest)+1;
  55. }
  56. return iRet;
  57. }
  58. //***************************************************************************
  59. //
  60. // CVariant::ChangeType
  61. //
  62. // DESCRIPTION:
  63. //
  64. // Changes the CVariant data into a new type.
  65. //
  66. // PARAMETERS:
  67. //
  68. // vtNew Type to convert to
  69. //
  70. // RETURN VALUE:
  71. //
  72. // S_OK if alright, otherwise an error set by OMSVariantChangeType
  73. //
  74. //***************************************************************************
  75. SCODE CVariant::ChangeType(
  76. IN VARTYPE vtNew)
  77. {
  78. SCODE sc;
  79. // if type doesnt need changing, then already done!
  80. if(vtNew == var.vt)
  81. return S_OK;
  82. // Create and initialize a temp VARIANT
  83. VARIANTARG vTemp;
  84. VariantInit(&vTemp);
  85. // Change to the desired type. Then delete the current value
  86. // and copy the temp copy
  87. sc = OMSVariantChangeType(&vTemp,&var,0,vtNew);
  88. OMSVariantClear(&var);
  89. var = vTemp; // structure copy
  90. return sc;
  91. }
  92. //***************************************************************************
  93. //
  94. // CVariant::Clear
  95. //
  96. // DESCRIPTION:
  97. //
  98. // Clears out the VARIANT.
  99. //
  100. //***************************************************************************
  101. void CVariant::Clear(void)
  102. {
  103. OMSVariantClear(&var);
  104. }
  105. //***************************************************************************
  106. //
  107. // CVariant::
  108. // CVariant::~CVariant
  109. //
  110. // DESCRIPTION:
  111. //
  112. // Constructor and destructor.
  113. //
  114. //***************************************************************************
  115. CVariant::CVariant()
  116. {
  117. VariantInit(&var);
  118. memset((void *)&var.lVal,0,8);
  119. }
  120. CVariant::CVariant(LPWSTR pwcStr)
  121. {
  122. VariantInit(&var);
  123. if(pwcStr)
  124. {
  125. var.bstrVal = SysAllocString(pwcStr);
  126. if(var.bstrVal)
  127. var.vt = VT_BSTR;
  128. }
  129. }
  130. CVariant::~CVariant()
  131. {
  132. OMSVariantClear(&var);
  133. }
  134. //***************************************************************************
  135. //
  136. // SCODE CVariant::DoPut
  137. //
  138. // DESCRIPTION:
  139. //
  140. // "Puts" the data out to the WBEM server (if pClassInt isnt NULL), or just
  141. // copies the data to the variant.
  142. //
  143. // PARAMETERS:
  144. //
  145. // lFlags flags to pass along to wbem server
  146. // pClassInt pointer to class/instance object
  147. // PropName property name
  148. // pVar variant value
  149. //
  150. // RETURN VALUE:
  151. //
  152. // S_OK if no error other wise see wbemsvc error codes when, pClass isnt
  153. // null, or see the OMSVariantChangeType function.
  154. //
  155. //***************************************************************************
  156. SCODE CVariant::DoPut(
  157. IN long lFlags,
  158. IN IWbemClassObject FAR * pClassInt,
  159. IN BSTR PropName,
  160. IN CVariant * pVar)
  161. {
  162. SCODE sc;
  163. if(pClassInt)
  164. {
  165. sc = pClassInt->Put(PropName,lFlags,&var,0);
  166. }
  167. else if(pVar)
  168. {
  169. pVar->Clear();
  170. sc = OMSVariantChangeType(&pVar->var,&var,0,var.vt);
  171. }
  172. else sc = WBEM_E_FAILED;
  173. return sc;
  174. }
  175. //***************************************************************************
  176. //
  177. // SCODE CVariant::GetArrayData
  178. //
  179. // DESCRIPTION:
  180. //
  181. // Converts array data into a single data block. This is used by the
  182. // registry provider when it writes out array data.
  183. //
  184. // PARAMETERS:
  185. //
  186. // ppData pointer to the return data. Note it is the job of the
  187. // caller to free this when the return code is S_OK
  188. // pdwSize Size of returned data
  189. //
  190. // RETURN VALUE:
  191. //
  192. // S_OK if all is well
  193. // WBEM_E_OUT_OF_MEMORY when we memory allocation fails
  194. // WBEM_E_FAILED when variant has bogus type.
  195. // ??? when failure is in SafeArrayGetElement
  196. //
  197. //***************************************************************************
  198. SCODE CVariant::GetArrayData(
  199. OUT void ** ppData,
  200. OUT DWORD * pdwSize)
  201. {
  202. SCODE sc;
  203. DWORD dwSoFar = 0;
  204. SAFEARRAY * psa;
  205. long ix[2] = {0,0};
  206. BYTE * pb;
  207. TCHAR * ptc;
  208. BOOL bString = ((var.vt & ~VT_ARRAY) == CHARTYPE ||(var.vt & ~VT_ARRAY) == VT_BSTR );
  209. int iNumElements = GetNumElements();
  210. int iSizeOfType = iTypeSize(var.vt);
  211. if(iSizeOfType < 1)
  212. return WBEM_E_FAILED;
  213. // Calculate necessary size;
  214. psa = var.parray;
  215. if(bString) {
  216. *pdwSize = CHARSIZE; // 1 for the final double null!
  217. for(ix[0] = 0; ix[0] < iNumElements; ix[0]++) {
  218. BSTR bstr;
  219. sc = SafeArrayGetElement(psa,ix,&bstr);
  220. if(FAILED(sc))
  221. return sc;
  222. #ifdef UNICODE
  223. *pdwSize += 2 * (wcslen(bstr) +1);
  224. #else
  225. int iWCSLen = wcslen(bstr) + 1;
  226. *pdwSize += wcstombs(NULL,bstr,iWCSLen) + 1;
  227. #endif
  228. SysFreeString(bstr);
  229. }
  230. }
  231. else {
  232. *pdwSize = iNumElements * iSizeOfType;
  233. }
  234. // Allocate the memory to be filled
  235. *ppData = CoTaskMemAlloc(*pdwSize);
  236. if(*ppData == NULL)
  237. return WBEM_E_OUT_OF_MEMORY;
  238. pb = (BYTE *)*ppData;
  239. ptc = (TCHAR *)*ppData;
  240. // loop for each array element
  241. sc = S_OK;
  242. for(ix[0] = 0; ix[0] < iNumElements && sc == S_OK; ix[0]++) {
  243. if (bString) {
  244. BSTR bstr;
  245. sc = SafeArrayGetElement(psa,ix,&bstr);
  246. if(sc != S_OK)
  247. break;
  248. DWORD dwBytesLeft = *pdwSize-dwSoFar;
  249. #ifdef UNICODE
  250. lstrcpyn(ptc,bstr,dwBytesLeft/2);
  251. #else
  252. wcstombs(ptc,bstr,dwBytesLeft);
  253. #endif
  254. dwSoFar += CHARSIZE * (lstrlen(ptc) + 1);
  255. ptc += lstrlen(ptc) + 1;
  256. SysFreeString(bstr);
  257. *ptc = 0; // double null
  258. }
  259. else {
  260. sc = SafeArrayGetElement(psa,ix,pb);
  261. pb += iSizeOfType;
  262. }
  263. }
  264. if(sc != S_OK)
  265. CoTaskMemFree(*ppData);
  266. return S_OK;
  267. }
  268. //***************************************************************************
  269. //
  270. // SCODE CVariant::GetData
  271. //
  272. // DESCRIPTION:
  273. //
  274. // Used by the registry provider to take the data from VARIANT arg format
  275. // into a raw block for output. Note that the data allocated and stuck into
  276. // *ppData should be freed using CoTaskMemFree!
  277. //
  278. // PARAMETERS:
  279. //
  280. // ppData Pointer to output data.
  281. // dwRegType Type to convert to
  282. // pdwSize Pointer to size of returned data
  283. //
  284. // RETURN VALUE:
  285. //
  286. // S_OK if all is well, otherwise a error code which is set by either
  287. // OMSVariantChangeType, or GetArrayData.
  288. //
  289. //***************************************************************************
  290. SCODE CVariant::GetData(
  291. OUT void ** ppData,
  292. IN DWORD dwRegType,
  293. OUT DWORD * pdwSize)
  294. {
  295. SCODE sc = S_OK;
  296. // Determine the type it may need to be converted to. Note that binary
  297. // data is not converted intentionally.
  298. switch(dwRegType) {
  299. case REG_DWORD:
  300. sc = ChangeType(VT_I4);
  301. break;
  302. case REG_SZ:
  303. sc = ChangeType(VT_BSTR);
  304. break;
  305. case REG_MULTI_SZ:
  306. sc = ChangeType(VT_BSTR | VT_ARRAY);
  307. break;
  308. default:
  309. break;
  310. }
  311. if(sc != S_OK)
  312. return sc;
  313. // Special case for arrays
  314. if(dwRegType == REG_BINARY || dwRegType == REG_MULTI_SZ)
  315. return GetArrayData(ppData, pdwSize);
  316. // Allocate some memory and move the data into it.
  317. if(dwRegType == REG_SZ) {
  318. #ifdef UNICODE
  319. *pdwSize = 2 * (wcslen(var.bstrVal)+1);
  320. *ppData = CoTaskMemAlloc(*pdwSize);
  321. if(*ppData == NULL)
  322. return WBEM_E_OUT_OF_MEMORY;
  323. StringCchCopyW((WCHAR *)*ppData, *pdwSize/sizeof(WCHAR),var.bstrVal);
  324. #else
  325. *ppData = WideToNarrow(var.bstrVal);
  326. if(*ppData == NULL)
  327. return WBEM_E_OUT_OF_MEMORY;
  328. *pdwSize = lstrlenA((char *)*ppData)+1;
  329. #endif
  330. }
  331. else {
  332. *pdwSize = iTypeSize(var.vt);
  333. *ppData = CoTaskMemAlloc(*pdwSize);
  334. if(*ppData == NULL)
  335. return WBEM_E_OUT_OF_MEMORY;
  336. memcpy(*ppData,(void *)&var.lVal,*pdwSize);
  337. }
  338. return S_OK;
  339. }
  340. //***************************************************************************
  341. //
  342. // CVariant::GetNumElements
  343. //
  344. // DESCRIPTION:
  345. //
  346. // Gets the number of elements in an array.
  347. //
  348. // RETURN VALUE:
  349. //
  350. // number of elements. Scalers return a 1.
  351. //
  352. //***************************************************************************
  353. DWORD CVariant::GetNumElements(void)
  354. {
  355. SCODE sc;
  356. if(!IsArray())
  357. return 1;
  358. SAFEARRAY * psa = var.parray;
  359. long uLower, uUpper;
  360. sc = SafeArrayGetLBound(psa,1,&uLower);
  361. sc |= SafeArrayGetUBound(psa,1,&uUpper);
  362. if(sc != S_OK)
  363. return 0;
  364. else
  365. return uUpper - uLower +1;
  366. }
  367. //***************************************************************************
  368. //
  369. // SCODE CVariant::SetArrayData
  370. //
  371. // DESCRIPTION:
  372. //
  373. // Sets the CVariant value using raw data. Used by the reg provider.
  374. //
  375. // PARAMETERS:
  376. //
  377. // pData pointer to data to set
  378. // vtSimple Type to set the data to
  379. // iSize size of data pointed to by pData
  380. //
  381. // RETURN VALUE:
  382. //
  383. // S_OK if OK.
  384. // WBEM_E_INVALID_PARAMETER if the arguments are bad
  385. // WBEM_E_OUT_OF_MEMORY if out of memory
  386. // other wise error from SafeArrayPutElement
  387. //
  388. //***************************************************************************
  389. SCODE CVariant::SetArrayData(
  390. IN void * pData,
  391. IN VARTYPE vtSimple,
  392. IN int iSize)
  393. {
  394. SCODE sc;
  395. int iNumElements;
  396. BYTE * pNext;
  397. long ix[2] = {0,0};
  398. DWORD dwLeftOver = 0;
  399. int iSizeOfType = iTypeSize(vtSimple);
  400. if(pData == NULL || iSizeOfType < 1 || iSize < 1)
  401. return WBEM_E_INVALID_PARAMETER;
  402. // Calculate the number of elements and make sure it is a type that
  403. // is supported
  404. if(vtSimple == VT_BSTR) {
  405. iNumElements = CalcNumStrings((TCHAR *)pData);
  406. }
  407. else {
  408. iNumElements = iSize / iSizeOfType;
  409. dwLeftOver = iSize % iSizeOfType;
  410. }
  411. // Allocate array
  412. int iNumCreate = (dwLeftOver) ? iNumElements + 1 : iNumElements;
  413. SAFEARRAY * psa = OMSSafeArrayCreate(vtSimple,iNumCreate);
  414. if(psa == NULL)
  415. return WBEM_E_FAILED;
  416. // Set each element of the array
  417. for(ix[0] = 0, pNext = (BYTE *)pData; ix[0] < iNumElements; ix[0]++) {
  418. if(vtSimple == VT_BSTR) {
  419. BSTR bstr;
  420. bstr = SysAllocBstrFromTCHAR((LPTSTR)pNext);
  421. if(bstr == NULL) { // todo, free previously allocated strings!
  422. SafeArrayDestroy(psa);
  423. return WBEM_E_OUT_OF_MEMORY;
  424. }
  425. sc = SafeArrayPutElement(psa,ix,(void*)bstr);
  426. pNext += sizeof(TCHAR)*(lstrlen((TCHAR *)pNext) + 1);
  427. SysFreeString(bstr);
  428. }
  429. else {
  430. sc = SafeArrayPutElement(psa,ix,pNext);
  431. pNext += iSizeOfType;
  432. }
  433. if(sc) { // todo, cleanup???
  434. SafeArrayDestroy(psa);
  435. return sc;
  436. }
  437. }
  438. // it is possible that the number of bytes being set doesnt evenly factor
  439. // into the type size. For instance, there may be 10 bytes of registry
  440. // data being put into a DWORD array. In this case, the last two bytes
  441. // are left overs
  442. if(dwLeftOver) {
  443. __int64 iTemp = 0;
  444. memcpy((void *)&iTemp,(void *)pNext,dwLeftOver);
  445. sc = SafeArrayPutElement(psa,ix,&iTemp);
  446. }
  447. var.vt = vtSimple | VT_ARRAY;
  448. var.parray = psa;
  449. return S_OK;
  450. }
  451. //***************************************************************************
  452. //
  453. // CVariant::SetData
  454. //
  455. // Sets the CVariant value using raw data. Used by the reg provider.
  456. //
  457. // DESCRIPTION:
  458. //
  459. // PARAMETERS:
  460. //
  461. // pData Data to be set
  462. // vtChangeTo Type to change the data to
  463. // iSize size of data pointed to by pData
  464. //
  465. // RETURN VALUE:
  466. //
  467. // S_OK if OK.
  468. // WBEM_E_INVALID_PARAMETER if the arguments are bad
  469. // WBEM_E_OUT_OF_MEMORY if out of memory
  470. // other wise error from SafeArrayPutElement
  471. //
  472. //***************************************************************************
  473. SCODE CVariant::SetData(
  474. IN void * pData,
  475. IN VARTYPE vtChangeTo,
  476. IN int iSize)
  477. {
  478. int iToSize = iTypeSize(vtChangeTo);
  479. // check arguments and clear the variant
  480. if(pData == NULL || iToSize < 1)
  481. return WBEM_E_INVALID_PARAMETER;
  482. OMSVariantClear(&var);
  483. if(iSize < 1)
  484. iSize = iToSize;
  485. // Special case for arrays!
  486. if(vtChangeTo & VT_ARRAY)
  487. return SetArrayData(pData,vtChangeTo & ~VT_ARRAY,iSize);
  488. if(vtChangeTo == CIM_SINT64 || vtChangeTo == CIM_UINT64)
  489. {
  490. // int64 and uint64 need to be converted to strings
  491. WCHAR wcTemp[50];
  492. __int64 iLong;
  493. memcpy((void *)&iLong, pData, 8);
  494. if(vtChangeTo == CIM_SINT64)
  495. StringCchPrintfW(wcTemp, 50, L"%I64d", iLong);
  496. else
  497. StringCchPrintfW(wcTemp, 50, L"%I64u", iLong);
  498. var.bstrVal = SysAllocString(wcTemp);
  499. if(var.bstrVal == NULL)
  500. return WBEM_E_OUT_OF_MEMORY;
  501. var.vt = VT_BSTR;
  502. }
  503. else if(vtChangeTo == VT_BSTR)
  504. {
  505. // All strings are stored as BSTRS
  506. var.bstrVal = SysAllocBstrFromTCHAR((LPTSTR)pData);
  507. if(var.bstrVal == NULL)
  508. return WBEM_E_OUT_OF_MEMORY;
  509. var.vt = VT_BSTR;
  510. }
  511. else
  512. {
  513. memcpy((void *)&var.lVal,pData,iToSize);
  514. var.vt = vtChangeTo;
  515. }
  516. return S_OK;
  517. }