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.

558 lines
16 KiB

  1. /////////////////////////////////////////////////////////////////////////////////
  2. /////////////////////////////////////////////////////////////////////////////////
  3. //
  4. // File: PropVar.c
  5. //
  6. // Purpose: This file provides Office-aware routines which
  7. // operate on PropVariants. They are Office-aware in
  8. // that they only operate on the subset of
  9. // VarTypes which are used by Office.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////////
  12. /////////////////////////////////////////////////////////////////////////////////
  13. #include "priv.h"
  14. #pragma hdrstop
  15. /////////////////////////////////////////////////////////////////////////////////
  16. //
  17. // Function: FPropVarLoad
  18. //
  19. // Purpse: Load data into a PropVariant. If the target PropVariant
  20. // already contains data, it will be freed.
  21. //
  22. // Note that new memory is allocated, if necessary, to hold
  23. // the data in the PropVariant. Also note that the
  24. // resulting PropVariant should be freed by the caller using
  25. // PropVariantClear.
  26. //
  27. // Inputs: LPPROPVARIANT - to be loaded. This should be a valid
  28. // (i.e. intialized) PropVariant.
  29. // VARTYPE - of the new PropVariant (must be a member of
  30. // the limited set used by Office).
  31. // LPVOID - Either the data to be loaded, or a pointer
  32. // to such data, depending on the type.
  33. //
  34. // Output: TRUE if and only if successful.
  35. //
  36. /////////////////////////////////////////////////////////////////////////////////
  37. BOOL
  38. FPropVarLoad
  39. ( LPPROPVARIANT lppropvar,
  40. VARTYPE vt,
  41. LPVOID const lpv )
  42. {
  43. // ------
  44. // Locals
  45. // ------
  46. BOOL fSuccess = FALSE; // Return code
  47. ULONG cch, cb;
  48. // ----------
  49. // Initialize
  50. // ----------
  51. Assert (lppropvar != NULL);
  52. Assert (lpv != NULL);
  53. // Free any data currently in the PropVariant.
  54. PropVariantClear (lppropvar);
  55. // ---------------------------------------------------
  56. // Set the value of the PropVariant based on the type.
  57. // ---------------------------------------------------
  58. switch (vt)
  59. {
  60. // Strings
  61. case VT_LPTSTR:
  62. // Determine the character and byte count.
  63. cch = lstrlen(lpv); // Doesn't include the NULL.
  64. cb = (cch + 1) * sizeof(TCHAR); // *Does* include the NULL.
  65. // Allocate memory in the PropVariant.
  66. lppropvar->pwszVal = CoTaskMemAlloc (cb);
  67. if (lppropvar->pwszVal == NULL)
  68. {
  69. goto Exit;
  70. }
  71. // Copy the string to the PropVariant and terminate it.
  72. StringCchCopy( (LPTSTR)lppropvar->pwszVal, cch + 1, lpv );
  73. lppropvar->pwszVal[cch] = TEXT('\0');
  74. break;
  75. // DWORDs
  76. case VT_I4:
  77. lppropvar->lVal = *(DWORD*) lpv;
  78. break;
  79. // FileTime
  80. case VT_FILETIME:
  81. CopyMemory( &lppropvar->filetime, lpv, sizeof(FILETIME) );
  82. break;
  83. // Double
  84. case VT_R8:
  85. CopyMemory( &lppropvar->dblVal, lpv, sizeof(double) );
  86. break;
  87. // Bool
  88. case VT_BOOL:
  89. lppropvar->boolVal = *(VARIANT_BOOL*) lpv ? VARIANT_TRUE : VARIANT_FALSE;
  90. break;
  91. // Invalid type.
  92. default:
  93. goto Exit;
  94. }
  95. // Set the VT of the PropVariant, and we're done.
  96. lppropvar->vt = vt;
  97. // ----
  98. // Exit
  99. // ----
  100. fSuccess = TRUE;
  101. Exit:
  102. return (fSuccess);
  103. } // FPropVarLoad
  104. ////////////////////////////////////////////////////////////////////////////////
  105. //
  106. // Function: FCoStrToWStr
  107. //
  108. // Purpose: Convert a COM string (ANSI) to a COM wide-string.
  109. // ("COM" because the string is allocated using
  110. // the COM heap).
  111. //
  112. // Inputs: LPWSTR* - The converted string.
  113. // LPSTR - The original string.
  114. // UINT - The ANSI code page.
  115. //
  116. // Output: TRUE if and only if successful.
  117. //
  118. ////////////////////////////////////////////////////////////////////////////////
  119. BOOL
  120. FCoStrToWStr( LPWSTR *lplpwstr,
  121. const LPSTR lpstr,
  122. UINT uCodePage)
  123. {
  124. // ------
  125. // Locals
  126. // ------
  127. BOOL fSuccess = FALSE; // Return value.
  128. ULONG cchBuffer = 0; // Size of converted string (includes NULL).
  129. Assert (lpstr != NULL && lplpwstr != NULL);
  130. // ------------------
  131. // Convert the string
  132. // ------------------
  133. // Make two passes. The first will calculate the
  134. // size of the target buffer, the second will actually
  135. // make the conversion.
  136. *lplpwstr = NULL;
  137. while (TRUE)
  138. {
  139. cchBuffer = MultiByteToWideChar(
  140. uCodePage, // Source code page
  141. 0, // Default flags
  142. lpstr, // Source string
  143. -1, // Default length
  144. *lplpwstr, // Destination string
  145. cchBuffer ); // Max dest string characters.
  146. // Is this the second pass (when the conversion should
  147. // have taken place)?
  148. if (*lplpwstr != NULL)
  149. {
  150. // If we got a good result, then we're done.
  151. if (cchBuffer != 0)
  152. {
  153. break;
  154. }
  155. // 0 was returned. There was an error.
  156. else
  157. {
  158. AssertSz (0, TEXT("Couldn't convert MBCS to Wide"));
  159. goto Exit;
  160. }
  161. }
  162. // Otherwise, this is the first pass. We need to
  163. // allocate a buffer.
  164. else
  165. {
  166. // We should have gotten a positive buffer size.
  167. if (cchBuffer == 0)
  168. {
  169. AssertSz(0, TEXT("MultiByteToWideChar returned invalid target buffer size"));
  170. goto Exit;
  171. }
  172. // Allocate memory for the converted string.
  173. else
  174. {
  175. *lplpwstr = (LPWSTR) CoTaskMemAlloc( cchBuffer * 2 );
  176. if ( *lplpwstr == NULL)
  177. {
  178. AssertSz (0, TEXT("Could not allocate memory for wide string"));
  179. goto Exit;
  180. }
  181. }
  182. } // if( *lplpwstr != NULL ... else
  183. } // while (TRUE)
  184. // ----
  185. // Exit
  186. // ----
  187. fSuccess = TRUE;
  188. Exit:
  189. // If there was a problem, free the Unicode string.
  190. if (!fSuccess)
  191. {
  192. CoTaskMemFree (*lplpwstr);
  193. *lplpwstr = NULL;
  194. }
  195. return (fSuccess);
  196. } // FCoStrToWStr
  197. ////////////////////////////////////////////////////////////////////////////////
  198. //
  199. // Function: FCoWStrToStr
  200. //
  201. // Purpose: Convert a COM wide-string to an ANSI string.
  202. // ("COM" because the string is allocated using
  203. // the COM heap).
  204. //
  205. // Inputs: LPSTR* - The converted string.
  206. // LPWSTR - The source string.
  207. // UINT - The ANSI code page.
  208. //
  209. // Output: TRUE if and only if successful.
  210. //
  211. ////////////////////////////////////////////////////////////////////////////////
  212. BOOL
  213. FCoWStrToStr( LPSTR *lplpstr,
  214. const LPWSTR lpwstr,
  215. UINT uCodePage)
  216. {
  217. // ------
  218. // Locals
  219. // ------
  220. BOOL fSuccess = FALSE; // Return result
  221. ULONG cch; // Charcters in original string (w/o NULL).
  222. ULONG cbBuffer = 0; // Size of target buffer (including NULL)
  223. Assert (lpwstr != NULL && lplpstr != NULL);
  224. // ------------------
  225. // Convert the String
  226. // ------------------
  227. // We'll make two calls to WideCharToMultiByte.
  228. // In the first, we'll determine the size required
  229. // for the multi-byte string. We'll use this
  230. // to allocate memory. In the second pass, we'll actually
  231. // make the conversion.
  232. cch = wcslen( lpwstr ); // How big is the source string?
  233. *lplpstr = NULL; // Initialize the target buffer.
  234. while (TRUE)
  235. {
  236. cbBuffer = WideCharToMultiByte(
  237. uCodePage, // Source code page
  238. 0, // Default flags
  239. lpwstr, // Source string
  240. cch + 1, // # chars in wide string (including NULL)
  241. *lplpstr, // Destination string
  242. cbBuffer, // Size of destination buffer
  243. NULL, NULL ); // No default character
  244. // Is this the second pass (when the conversion should
  245. // have taken place)?
  246. if (*lplpstr != NULL)
  247. {
  248. // If we got a good result, then we're done.
  249. if (cbBuffer != 0)
  250. {
  251. break;
  252. }
  253. // 0 was returned. There was an error.
  254. else
  255. {
  256. AssertSz (0, TEXT("Couldn't convert Wide to MBCS"));
  257. goto Exit;
  258. }
  259. }
  260. // Otherwise, this is the first pass. We need to
  261. // allocate a buffer.
  262. else
  263. {
  264. // We should have gotten a positive buffer size.
  265. if (cbBuffer == 0)
  266. {
  267. AssertSz(0, TEXT("WideCharMultiByte returned invalid target buffer size"));
  268. goto Exit;
  269. }
  270. // Allocate memory for the converted string.
  271. else
  272. {
  273. *lplpstr = (LPSTR) CoTaskMemAlloc( cbBuffer );
  274. if ( *lplpstr == NULL)
  275. {
  276. AssertSz (0, TEXT("Could not allocate memory for wide string"));
  277. goto Exit;
  278. }
  279. }
  280. } // if( lpstr != NULL ... else
  281. } // while (TRUE)
  282. // ----
  283. // Exit
  284. // ----
  285. fSuccess = TRUE;
  286. Exit:
  287. // If there was a problem, free the new string.
  288. if (!fSuccess)
  289. {
  290. CoTaskMemFree (*lplpstr);
  291. *lplpstr = NULL;
  292. }
  293. return (fSuccess);
  294. } // FCoWStrToStr
  295. //////////////////////////////////////////////////////////////////////////////
  296. //
  297. // Function: FPropVarConvertString
  298. //
  299. // Purpose: Convert a PropVariant from VT_LPSTR to VT_LPWSTR,
  300. // or vice-versa. The correct direction is inferred
  301. // from the input. The source PropVariant is not
  302. // modified.
  303. //
  304. // If the PropVariant is a Vector, all elements are
  305. // converted.
  306. //
  307. // Inputs: LPPROPVARIANT - The buffer in which to put the
  308. // converted PropVariant.
  309. // LPPROPVARIANT - The source of the conversion.
  310. // UINT - The code page of VT_LPSTRs.
  311. //
  312. // Output: TRUE if successful. If unsuccessful, the original
  313. // PropVariant will be returned unmodified.
  314. //
  315. // Pre-Conditions:
  316. // The input must be either a VT_LPSTR or a VT_LPWSTR
  317. // (with or without the VT_VECTOR bit set).
  318. // &&
  319. // The destination PropVariant is VT_EMPTY.
  320. // &&
  321. // The code page must not be CP_WINUNICODE (Unicode
  322. // LPSTRs are not legal in the SumInfo property sets).
  323. //
  324. //////////////////////////////////////////////////////////////////////////////
  325. BOOL FPropVarConvertString( LPPROPVARIANT lppropvarDest,
  326. const LPPROPVARIANT lppropvarSource,
  327. UINT uCodePage)
  328. {
  329. // ------
  330. // Locals
  331. // ------
  332. BOOL fSuccess = FALSE; // Return code.
  333. BOOL fConvertToAnsi; // Indicates the direction of the conversion.
  334. LPSTR *lplpstrDest; // Pointer to pointer to a converted string.
  335. LPSTR lpstrSource; // Pointer to a string to be converted.
  336. ULONG cElems; // The number of strings still requiring conversion
  337. ULONG ulIndex = 0; // Index into vector (if this VT is a vector)
  338. // ----------
  339. // Initialize
  340. // ----------
  341. Assert(lppropvarDest != NULL && lppropvarSource != NULL);
  342. Assert(lppropvarDest->vt == VT_EMPTY);
  343. Assert(uCodePage != CP_WINUNICODE);
  344. // Determine the direction of the conversion.
  345. fConvertToAnsi = (lppropvarSource->vt & ~VT_VECTOR) == VT_LPSTR
  346. ? FALSE
  347. : TRUE;
  348. // -----------------------------------
  349. // Initialize based on the Vector bit.
  350. // -----------------------------------
  351. if (lppropvarSource->vt & VT_VECTOR)
  352. {
  353. // We're a vector.
  354. cElems = lppropvarSource->calpstr.cElems;
  355. // Allocate an array of string pointers, putting it in
  356. // lppropvarDest.
  357. lppropvarDest->calpstr.pElems = CoTaskMemAlloc( cElems
  358. * sizeof(*lppropvarDest->calpstr.pElems) );
  359. if (lppropvarDest->calpstr.pElems == NULL)
  360. {
  361. AssertSz(0,TEXT("Couldn't allocate memory for pElemsNew"));
  362. goto Exit;
  363. }
  364. // Fill this new buffer so we don't get confused in the error path.
  365. ZeroMemory(lppropvarDest->calpstr.pElems, cElems * sizeof(*lppropvarDest->calpstr.pElems));
  366. lppropvarDest->calpstr.cElems = cElems;
  367. // Initialize the pointers for the first string to convert.
  368. lplpstrDest = &lppropvarDest->calpstr.pElems[ 0 ];
  369. lpstrSource = lppropvarSource->calpstr.pElems[ 0 ];
  370. } // if (lppropvar->vt & VT_VECTOR)
  371. else
  372. {
  373. // We're not a vector, initialize to the only string.
  374. cElems = 1;
  375. lplpstrDest = &lppropvarDest->pszVal;
  376. lpstrSource = lppropvarSource->pszVal;
  377. }
  378. // ---------------------
  379. // Convert the String(s)
  380. // ---------------------
  381. while (cElems)
  382. {
  383. if (fConvertToAnsi)
  384. {
  385. if (!FCoWStrToStr ((LPSTR*)lplpstrDest, (LPWSTR) lpstrSource,
  386. uCodePage))
  387. {
  388. goto Exit;
  389. }
  390. }
  391. else
  392. {
  393. if (!FCoStrToWStr ((LPWSTR*) lplpstrDest, (LPSTR) lpstrSource,
  394. uCodePage))
  395. {
  396. goto Exit;
  397. }
  398. }
  399. // Move on to the next entry, if there is one.
  400. if (--cElems)
  401. {
  402. ulIndex++;
  403. lplpstrDest = &lppropvarDest->calpstr.pElems[ ulIndex ];
  404. lpstrSource = lppropvarSource->calpstr.pElems[ ulIndex ];
  405. } // if (--cElems)
  406. } // while (cElems)
  407. // Switch the destination VT to VT_LPSTR (for ansi strings) or VT_LPWSTR
  408. // (for Unicode strings), preserving all other bits.
  409. lppropvarDest->vt = (lppropvarSource->vt & ~(VT_LPSTR|VT_LPWSTR))
  410. |
  411. (fConvertToAnsi ? VT_LPSTR : VT_LPWSTR);
  412. // ----
  413. // Exit
  414. // ----
  415. fSuccess = TRUE;
  416. Exit:
  417. if (!fSuccess)
  418. PropVariantClear (lppropvarDest);
  419. return( fSuccess );
  420. } // FPropVarConvertString