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.

340 lines
8.4 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: StrUtils.cpp
  6. * Content: Implements the string utils
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/12/2000 rmt Created
  12. * 08/28/2000 masonb Voice Merge: Added check of return code of MultiByteToWideChar in STR_jkAnsiToWide
  13. * 09/16/2000 aarono fix STR_AllocAndConvertToANSI, ANSI doesn't mean 1 byte per DBCS character so we
  14. * must allow up to 2 bytes per char when allocating buffer (B#43286)
  15. *@@END_MSINTERNAL
  16. *
  17. ***************************************************************************/
  18. #include "dncmni.h"
  19. #undef DPF_MODNAME
  20. #define DPF_MODNAME "STR_WideToAnsi"
  21. //**********************************************************************
  22. // ------------------------------
  23. // WideToANSI - convert a wide string to an ANSI string
  24. //
  25. // Entry: Pointer to source wide string
  26. // Size of source string (in WCHAR units, -1 implies NULL-terminated)
  27. // Pointer to ANSI string destination
  28. // Pointer to size of ANSI destination
  29. //
  30. // Exit: Error code:
  31. // DPNERR_GENERIC = operation failed
  32. // DPN_OK = operation succeded
  33. // DPNERR_BUFFERTOOSMALL = destination buffer too small
  34. // ------------------------------
  35. HRESULT STR_WideToAnsi( const WCHAR *const pWCHARString,
  36. const DWORD dwWCHARStringLength,
  37. char *const pString,
  38. DWORD *const pdwStringLength )
  39. {
  40. HRESULT hr;
  41. int iReturn;
  42. BOOL fDefault;
  43. char cMilleniumHackBuffer;
  44. char *pMilleniumHackBuffer;
  45. DNASSERT( pWCHARString != NULL );
  46. DNASSERT( pdwStringLength != NULL );
  47. DNASSERT( ( pString != NULL ) || ( *pdwStringLength == 0 ) );
  48. //
  49. // Initialize. A hack needs to be implemented for WinME parameter
  50. // validation, because when you pass zero for a destination size, you
  51. // MUST have a valid pointer. Works on Win95, 98, NT4, Win2K, etc.....
  52. //
  53. hr = DPN_OK;
  54. if ( *pdwStringLength == 0 )
  55. {
  56. pMilleniumHackBuffer = &cMilleniumHackBuffer;
  57. }
  58. else
  59. {
  60. pMilleniumHackBuffer = pString;
  61. }
  62. fDefault = FALSE;
  63. iReturn = WideCharToMultiByte( CP_ACP, // code page (default ANSI)
  64. 0, // flags (none)
  65. pWCHARString, // pointer to WCHAR string
  66. dwWCHARStringLength, // size of WCHAR string
  67. pMilleniumHackBuffer, // pointer to destination ANSI string
  68. *pdwStringLength, // size of destination string
  69. NULL, // pointer to default for unmappable characters (none)
  70. &fDefault // pointer to flag indicating that default was used
  71. );
  72. if ( iReturn == 0 )
  73. {
  74. DWORD dwError;
  75. dwError = GetLastError();
  76. DPFX( DPFPREP, 0, "Failed to convert WCHAR to multi-byte!" );
  77. DisplayDNError( 0, dwError );
  78. hr = DPNERR_GENERIC;
  79. }
  80. else
  81. {
  82. if ( *pdwStringLength == 0 )
  83. {
  84. hr = DPNERR_BUFFERTOOSMALL;
  85. }
  86. else
  87. {
  88. DNASSERT( hr == DPN_OK );
  89. }
  90. *pdwStringLength = iReturn;
  91. }
  92. //
  93. // if you hit this ASSERT it's because you've probably got ASCII text as your
  94. // input WCHAR string. Double-check your input!!
  95. //
  96. DNASSERT( fDefault == FALSE );
  97. return hr;
  98. }
  99. //**********************************************************************
  100. //**********************************************************************
  101. // ------------------------------
  102. // ANSIToWide - convert an ANSI string to a wide string
  103. //
  104. // Entry: Pointer to source multi-byte (ANSI) string
  105. // Size of source string (-1 imples NULL-terminated)
  106. // Pointer to multi-byte string destination
  107. // Pointer to size of multi-byte destination (in WCHAR units)
  108. //
  109. // Exit: Error code:
  110. // DPNERR_GENERIC = operation failed
  111. // DPN_OK = operation succeded
  112. // DPNERR_BUFFERTOOSMALL = destination buffer too small
  113. // ------------------------------
  114. #undef DPF_MODNAME
  115. #define DPF_MODNAME "STR_AnsiToWide"
  116. HRESULT STR_AnsiToWide( const char *const pString,
  117. const DWORD dwStringLength,
  118. WCHAR *const pWCHARString,
  119. DWORD *const pdwWCHARStringLength )
  120. {
  121. HRESULT hr;
  122. int iReturn;
  123. WCHAR MilleniumHackBuffer;
  124. WCHAR *pMilleniumHackBuffer;
  125. DNASSERT( pString != NULL );
  126. DNASSERT( pdwWCHARStringLength != NULL );
  127. DNASSERT( ( pWCHARString != NULL ) || ( *pdwWCHARStringLength == 0 ) );
  128. //
  129. // Initialize. A hack needs to be implemented for WinME parameter
  130. // validation, because when you pass zero for a destination size, you
  131. // MUST have a valid pointer. Works on Win95, 98, NT4, Win2K, etc.....
  132. //
  133. hr = DPN_OK;
  134. if ( *pdwWCHARStringLength == 0 )
  135. {
  136. pMilleniumHackBuffer = &MilleniumHackBuffer;
  137. }
  138. else
  139. {
  140. pMilleniumHackBuffer = pWCHARString;
  141. }
  142. iReturn = MultiByteToWideChar( CP_ACP, // code page (default ANSI)
  143. 0, // flags (none)
  144. pString, // pointer to multi-byte string
  145. dwStringLength, // size of string (assume null-terminated)
  146. pMilleniumHackBuffer, // pointer to destination wide-char string
  147. *pdwWCHARStringLength // size of destination in WCHARs
  148. );
  149. if ( iReturn == 0 )
  150. {
  151. DWORD dwError;
  152. dwError = GetLastError();
  153. DPFX(DPFPREP, 0, "Failed to convert multi-byte to WCHAR!" );
  154. DisplayDNError( 0, dwError );
  155. hr = DPNERR_GENERIC;
  156. }
  157. else
  158. {
  159. if ( *pdwWCHARStringLength == 0 )
  160. {
  161. hr = DPNERR_BUFFERTOOSMALL;
  162. }
  163. else
  164. {
  165. DNASSERT( hr == DPN_OK );
  166. }
  167. *pdwWCHARStringLength = iReturn;
  168. }
  169. return hr;
  170. }
  171. //**********************************************************************
  172. /*
  173. ** WideToAnsi
  174. *
  175. * CALLED BY: everywhere
  176. *
  177. * PARAMETERS: lpStr - destination string
  178. * lpWStr - string to convert
  179. * cchStr - size of dest buffer
  180. *
  181. * DESCRIPTION:
  182. * converts unicode lpWStr to ansi lpStr.
  183. * fills in unconvertable chars w/ DPLAY_DEFAULT_CHAR "-"
  184. *
  185. *
  186. * RETURNS: if cchStr is 0, returns the size required to hold the string
  187. * otherwise, returns the number of chars converted
  188. *
  189. */
  190. #undef DPF_MODNAME
  191. #define DPF_MODNAME "STR_jkWideToAnsi"
  192. HRESULT STR_jkWideToAnsi(LPSTR lpStr,LPCWSTR lpWStr,int cchStr)
  193. {
  194. int rval;
  195. BOOL bDefault = FALSE;
  196. if (!lpWStr && cchStr)
  197. {
  198. // can't call us w/ null pointer & non-zero cch
  199. DNASSERT(FALSE);
  200. return DPNERR_INVALIDPARAM;
  201. }
  202. // use the default code page (CP_ACP)
  203. // -1 indicates WStr must be null terminated
  204. rval = WideCharToMultiByte(CP_ACP,0,lpWStr,-1,lpStr,cchStr,
  205. NULL,&bDefault);
  206. if (bDefault)
  207. {
  208. DPFX(DPFPREP,3,"!!! WARNING - used default string in WideToAnsi conversion.!!!");
  209. DPFX(DPFPREP,3,"!!! Possible bad unicode string - (you're not hiding ansi in there are you?) !!! ");
  210. return DPNERR_CONVERSION;
  211. }
  212. return DPN_OK;
  213. } // WideToAnsi
  214. // WideToAnsi
  215. //
  216. // Convert a WCHAR (Wide) string to a CHAR (ANSI) string
  217. //
  218. // CHAR *pStr CHAR string
  219. // WCHAR *pWStr WCHAR string
  220. // int iStrSize size (in bytes) of buffer pointed to by lpStr
  221. #undef DPF_MODNAME
  222. #define DPF_MODNAME "STR_AllocAndConvertToANSI"
  223. /*
  224. ** GetAnsiString
  225. *
  226. * CALLED BY: Everywhere
  227. *
  228. * PARAMETERS: *ppszAnsi - pointer to string
  229. * lpszWide - string to copy
  230. *
  231. * DESCRIPTION: handy utility function
  232. * allocs space for and converts lpszWide to ansi
  233. *
  234. * RETURNS: string length
  235. *
  236. */
  237. HRESULT STR_AllocAndConvertToANSI(LPSTR * ppszAnsi,LPCWSTR lpszWide)
  238. {
  239. int iStrLen;
  240. BOOL bDefault;
  241. DNASSERT(ppszAnsi);
  242. if (!lpszWide)
  243. {
  244. *ppszAnsi = NULL;
  245. return S_OK;
  246. }
  247. *ppszAnsi = new char[wcslen(lpszWide)*2+1];
  248. if (!*ppszAnsi)
  249. {
  250. DPFX(DPFPREP,0, "could not get ansi string -- out of memory");
  251. return E_OUTOFMEMORY;
  252. }
  253. iStrLen = WideCharToMultiByte(CP_ACP,0,lpszWide,-1,*ppszAnsi,wcslen(lpszWide)*2+1,
  254. NULL,&bDefault);
  255. return DPN_OK;
  256. } // OSAL_AllocAndConvertToANSI
  257. #undef DPF_MODNAME
  258. #define DPF_MODNAME "STR_jkAnsiToWide"
  259. /*
  260. ** AnsiToWide
  261. *
  262. * CALLED BY: everywhere
  263. *
  264. * PARAMETERS: lpWStr - dest string
  265. * lpStr - string to convert
  266. * cchWstr - size of dest buffer
  267. *
  268. * DESCRIPTION: converts Ansi lpStr to Unicode lpWstr
  269. *
  270. *
  271. * RETURNS: if cchStr is 0, returns the size required to hold the string
  272. * otherwise, returns the number of chars converted
  273. *
  274. */
  275. HRESULT STR_jkAnsiToWide(LPWSTR lpWStr,LPCSTR lpStr,int cchWStr)
  276. {
  277. int rval;
  278. if (!lpStr && cchWStr)
  279. {
  280. // can't call us w/ null pointer & non-zero cch
  281. DNASSERT(FALSE);
  282. return DPNERR_INVALIDPOINTER;
  283. }
  284. rval = MultiByteToWideChar(CP_ACP,0,lpStr,-1,lpWStr,cchWStr);
  285. if (!rval)
  286. {
  287. DPFX(DPFPREP,0,"MultiByteToWideChar failed in STR_jkAnsiToWide");
  288. return DPNERR_GENERIC;
  289. }
  290. else
  291. {
  292. return DPN_OK;
  293. }
  294. } // AnsiToWide