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.

246 lines
8.9 KiB

  1. /***
  2. *w_str.c - W version of GetStringType.
  3. *
  4. * Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Use either GetStringTypeA or GetStringTypeW depending on which is
  8. * unstubbed.
  9. *
  10. *Revision History:
  11. * 09-14-93 CFW Module created.
  12. * 09-17-93 CFW Use unsigned chars.
  13. * 09-23-93 CFW Correct NLS API params and comments about same.
  14. * 10-07-93 CFW Optimize WideCharToMultiByte, use NULL default char.
  15. * 10-22-93 CFW Remove bad verification test from "A" version.
  16. * 10-22-93 CFW Test for invalid MB chars using global preset flag.
  17. * 11-09-93 CFW Allow user to pass in code page.
  18. * 11-18-93 CFW Test for entry point function stubs.
  19. * 02-23-94 CFW Use W flavor whenever possible.
  20. * 03-31-94 CFW Include awint.h.
  21. * 04-18-94 CFW Use lcid value if passed in.
  22. * 04-18-94 CFW Use calloc and don't test the NULL.
  23. * 10-24-94 CFW Must verify GetStringType return.
  24. * 12-21-94 CFW Remove invalid MB chars NT 3.1 hack.
  25. * 12-27-94 CFW Call direct, all OS's have stubs.
  26. * 01-10-95 CFW Debug CRT allocs.
  27. * 02-15-97 RDK For narrow string type, try W version first so
  28. * Windows NT can process nonANSI codepage correctly.
  29. * 03-16-97 RDK Added error flag to __crtGetStringTypeA.
  30. * 05-12-97 GJF Split off from old aw_str.c and moved into a separate
  31. * file. Revised to use _alloca instead of malloc. Also,
  32. * removed some silly code and reformatted.
  33. * 08-19-98 GJF Use _malloc_crt if _alloca fails.
  34. * 04-28-99 GJF Changed dwFlags arg value to 0 in WideCharToMultiByte
  35. * calls to avoid problems with codepage 1258 on NT 5.0.
  36. * 12-10-99 GB Added support for recovery from stack overflow around
  37. * _alloca().
  38. * 05-17-00 GB Use ERROR_CALL_NOT_IMPLEMENTED for existance of W API
  39. * 08-23-00 GB Fixed bug with non Ansi CP on Win9x.
  40. *
  41. *******************************************************************************/
  42. #include <cruntime.h>
  43. #include <internal.h>
  44. #include <stdlib.h>
  45. #include <setlocal.h>
  46. #include <locale.h>
  47. #include <awint.h>
  48. #include <dbgint.h>
  49. #include <malloc.h>
  50. #define USE_W 1
  51. #define USE_A 2
  52. /***
  53. *int __cdecl __crtGetStringTypeW - Get type information about a wide string.
  54. *
  55. *Purpose:
  56. * Internal support function. Assumes info in wide string format. Tries
  57. * to use NLS API call GetStringTypeW if available and uses GetStringTypeA
  58. * if it must. If neither are available it fails and returns FALSE.
  59. *
  60. *Entry:
  61. * DWORD dwInfoType - see NT\Chicago docs
  62. * LPCWSTR lpSrcStr - wide string for which character types are
  63. * requested
  64. * int cchSrc - wide char (word) count of lpSrcStr (including
  65. * NULL if any)
  66. * LPWORD lpCharType - array to receive character type information
  67. * (must be same size as lpSrcStr)
  68. * int code_page - for MB/WC conversion. If 0, use __lc_codepage
  69. * int lcid - for A call, specify LCID, If 0, use
  70. * __lc_handle[LC_CTYPE].
  71. *
  72. *Exit:
  73. * Success: TRUE
  74. * Failure: FALSE
  75. *
  76. *Exceptions:
  77. *
  78. *******************************************************************************/
  79. BOOL __cdecl __crtGetStringTypeW(
  80. DWORD dwInfoType,
  81. LPCWSTR lpSrcStr,
  82. int cchSrc,
  83. LPWORD lpCharType,
  84. int code_page,
  85. int lcid
  86. )
  87. {
  88. static int f_use = 0;
  89. /*
  90. * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
  91. * Must actually call the function to ensure it's not a stub.
  92. */
  93. if (0 == f_use)
  94. {
  95. unsigned short dummy;
  96. if (0 != GetStringTypeW(CT_CTYPE1, L"\0", 1, &dummy))
  97. f_use = USE_W;
  98. else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
  99. f_use = USE_A;
  100. }
  101. /* Use "W" version */
  102. if (USE_W == f_use)
  103. {
  104. return GetStringTypeW(dwInfoType, lpSrcStr, cchSrc, lpCharType);
  105. }
  106. /* Use "A" version */
  107. if (USE_A == f_use || f_use == 0)
  108. {
  109. int buff_size;
  110. BOOL retbool;
  111. unsigned char *buffer;
  112. WORD * pwCharInfo;
  113. int malloc_flag1 = 0;
  114. int malloc_flag2 = 0;
  115. int AnsiCP;
  116. /*
  117. * Convert string and return the requested information. Note that
  118. * we are converting to a multibyte string so there is not a
  119. * one-to-one correspondence between number of wide chars in the
  120. * input string and the number of *bytes* in the buffer. However,
  121. * there had *better be* a one-to-one correspondence between the
  122. * number of wide characters and the number of WORDs in the
  123. * return buffer.
  124. */
  125. /*
  126. * Use __lc_codepage for conversion if code_page not specified
  127. */
  128. if (0 == lcid)
  129. lcid = __lc_handle[LC_CTYPE];
  130. if (0 == code_page)
  131. code_page = __lc_codepage;
  132. /*
  133. * Always use Ansi codepage with Ansi WinAPI because they use
  134. * Ansi codepage
  135. */
  136. if ( code_page != (AnsiCP = __ansicp(lcid)))
  137. {
  138. if (AnsiCP != -1)
  139. code_page = AnsiCP;
  140. }
  141. /* find out how big a buffer we need */
  142. if ( 0 == (buff_size = WideCharToMultiByte( code_page,
  143. 0,
  144. lpSrcStr,
  145. cchSrc,
  146. NULL,
  147. 0,
  148. NULL,
  149. NULL )) )
  150. return FALSE;
  151. /* allocate enough space for chars */
  152. __try {
  153. buffer = (unsigned char *)_alloca( sizeof(char) * buff_size );
  154. (void)memset( buffer, 0, sizeof(char) * buff_size );
  155. }
  156. __except( EXCEPTION_EXECUTE_HANDLER ) {
  157. _resetstkoflw();
  158. buffer = NULL;
  159. }
  160. if ( buffer == NULL ) {
  161. if ( (buffer = (unsigned char *)_calloc_crt(sizeof(char), buff_size))
  162. == NULL )
  163. return FALSE;
  164. malloc_flag1++;
  165. }
  166. /* do the conversion */
  167. if ( 0 == WideCharToMultiByte( code_page,
  168. 0,
  169. lpSrcStr,
  170. cchSrc,
  171. buffer,
  172. buff_size,
  173. NULL,
  174. NULL ) )
  175. goto error_cleanup;
  176. /* allocate enough space for result (+1 for sanity check) */
  177. __try {
  178. pwCharInfo = (WORD *)_alloca( sizeof(WORD) * (buff_size + 1) );
  179. }
  180. __except( EXCEPTION_EXECUTE_HANDLER ) {
  181. _resetstkoflw();
  182. pwCharInfo = NULL;
  183. }
  184. if ( pwCharInfo == NULL ) {
  185. if ( (pwCharInfo = (WORD *)_malloc_crt(sizeof(WORD) * (buff_size + 1)))
  186. == NULL )
  187. goto error_cleanup;
  188. malloc_flag2++;
  189. }
  190. /* do we use default lcid */
  191. if (0 == lcid)
  192. lcid = __lc_handle[LC_CTYPE];
  193. /* set to known value */
  194. pwCharInfo[cchSrc - 1] = pwCharInfo[cchSrc] = 0xFFFF;
  195. /* obtain result */
  196. retbool = GetStringTypeA( lcid, dwInfoType, buffer, buff_size,
  197. pwCharInfo );
  198. /*
  199. * GetStringTypeA does not reveal how many WORDs have been
  200. * modifed - to be safe we use another buffer and then
  201. * verify that EXACTLY cchSrc WORDs were modified. Note that
  202. * not all multibyte LCID/codepage combos are guaranteed to work.
  203. */
  204. if ( (pwCharInfo[cchSrc - 1] == 0xFFFF) || (pwCharInfo[cchSrc] != 0xFFFF) )
  205. retbool = FALSE;
  206. else
  207. memmove(lpCharType, pwCharInfo, cchSrc * sizeof(WORD));
  208. if ( malloc_flag2 )
  209. _free_crt(pwCharInfo);
  210. error_cleanup:
  211. if ( malloc_flag1 )
  212. _free_crt(buffer);
  213. return retbool;
  214. }
  215. else /* f_use is neither USE_A nor USE_W */
  216. return FALSE;
  217. }