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.

296 lines
10 KiB

  1. /***
  2. *w_cmp.c - W versions of CompareString.
  3. *
  4. * Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Use either CompareStringA or CompareStringW depending on which is
  8. * available
  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 Test for invalid MB chars using global preset flag.
  16. * 11-09-93 CFW Allow user to pass in code page.
  17. * 11-18-93 CFW Test for entry point function stubs.
  18. * 02-23-94 CFW Use W flavor whenever possible.
  19. * 03-31-94 CFW Include awint.h.
  20. * 05-09-94 CFW Do not let CompareString compare past NULL.
  21. * 06-03-94 CFW Test for empty string early.
  22. * 11/01-94 CFW But not too early for MB strings.
  23. * 12-21-94 CFW Remove invalid MB chars NT 3.1 hack.
  24. * 12-27-94 CFW Call direct, all OS's have stubs.
  25. * 01-10-95 CFW Debug CRT allocs.
  26. * 02-06-95 CFW assert -> _ASSERTE.
  27. * 02-15-97 RDK For narrow comparsion, try W version first so Windows NT
  28. * can process nonANSI codepage correctly.
  29. * 05-15-97 GJF Split off from aw_cmp.c. Replaced use of _malloc_crt
  30. * and _free_crt with _alloca. Also, detab-ed and cleaned
  31. * up the code a bit.
  32. * 05-27-98 GJF Changed wcsncnt() so that it will never examine the
  33. * (cnt + 1)-th byte of the string.
  34. * 08-18-98 GJF Use _malloc_crt if _alloca fails.
  35. * 04-28-99 GJF Changed dwFlags arg value to 0 in WideCharToMultiByte
  36. * calls to avoid problems with codepage 1258 on NT 5.0.
  37. * 12-10-99 GB Added support for recovery from stack overflow around
  38. * _alloca().
  39. * 05-17-00 GB Use ERROR_CALL_NOT_IMPLEMENTED for existance of W API
  40. * 08-23-00 GB Fixed bug with non Ansi CP on Win9x.
  41. *
  42. *******************************************************************************/
  43. #include <cruntime.h>
  44. #include <internal.h>
  45. #include <dbgint.h>
  46. #include <stdlib.h>
  47. #include <setlocal.h>
  48. #include <locale.h>
  49. #include <awint.h>
  50. #include <dbgint.h>
  51. #include <malloc.h>
  52. #define USE_W 1
  53. #define USE_A 2
  54. /***
  55. *int __cdecl wcsncnt - count wide characters in a string, up to n.
  56. *
  57. *Purpose:
  58. * Internal local support function. Counts characters in string before NULL.
  59. * If NULL not found in n chars, then return n.
  60. *
  61. *Entry:
  62. * const wchar_t *string - start of string
  63. * int n - byte count
  64. *
  65. *Exit:
  66. * returns number of wide characaters from start of string to
  67. * NULL (exclusive), up to n.
  68. *
  69. *Exceptions:
  70. *
  71. *******************************************************************************/
  72. static int __cdecl wcsncnt (
  73. const wchar_t *string,
  74. int cnt
  75. )
  76. {
  77. int n = cnt;
  78. wchar_t *cp = (wchar_t *)string;
  79. while (n-- && *cp)
  80. cp++;
  81. return cnt - n - 1;
  82. }
  83. /***
  84. *int __cdecl __crtCompareStringW - Get type information about a wide string.
  85. *
  86. *Purpose:
  87. * Internal support function. Assumes info in wide string format. Tries
  88. * to use NLS API call CompareStringW if available and uses CompareStringA
  89. * if it must. If neither are available it fails and returns 0.
  90. *
  91. *Entry:
  92. * LCID Locale - locale context for the comparison.
  93. * DWORD dwCmpFlags - see NT\Chicago docs
  94. * LPCWSTR lpStringn - wide string to be compared
  95. * int cchCountn - wide char (word) count (NOT including NULL)
  96. * (-1 if NULL terminated)
  97. * int code_page - for MB/WC conversion. If 0, use __lc_codepage
  98. *
  99. *Exit:
  100. * Success: 1 - if lpString1 < lpString2
  101. * 2 - if lpString1 == lpString2
  102. * 3 - if lpString1 > lpString2
  103. * Failure: 0
  104. *
  105. *Exceptions:
  106. *
  107. *******************************************************************************/
  108. int __cdecl __crtCompareStringW(
  109. LCID Locale,
  110. DWORD dwCmpFlags,
  111. LPCWSTR lpString1,
  112. int cchCount1,
  113. LPCWSTR lpString2,
  114. int cchCount2,
  115. int code_page
  116. )
  117. {
  118. static int f_use = 0;
  119. /*
  120. * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
  121. * Must actually call the function to ensure it's not a stub.
  122. */
  123. if (0 == f_use)
  124. {
  125. if (0 != CompareStringW(0, 0, L"\0", 1, L"\0", 1))
  126. f_use = USE_W;
  127. else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
  128. f_use = USE_A;
  129. }
  130. /*
  131. * CompareString will compare past NULL. Must find NULL if in string
  132. * before cchCountn wide characters.
  133. */
  134. if (cchCount1 > 0)
  135. cchCount1= wcsncnt(lpString1, cchCount1);
  136. if (cchCount2 > 0)
  137. cchCount2= wcsncnt(lpString2, cchCount2);
  138. if (!cchCount1 || !cchCount2)
  139. return (cchCount1 - cchCount2 == 0) ? 2 :
  140. (cchCount1 - cchCount2 < 0) ? 1 : 3;
  141. /* Use "W" version */
  142. if (USE_W == f_use)
  143. {
  144. return CompareStringW( Locale,
  145. dwCmpFlags,
  146. lpString1,
  147. cchCount1,
  148. lpString2,
  149. cchCount2 );
  150. }
  151. /* Use "A" version */
  152. if (USE_A == f_use || f_use == 0)
  153. {
  154. int buff_size1;
  155. int buff_size2;
  156. unsigned char *buffer1;
  157. unsigned char *buffer2;
  158. int retcode = 0;
  159. int malloc_flag1 = 0;
  160. int malloc_flag2 = 0;
  161. int AnsiCP;
  162. /*
  163. * Use __lc_codepage for conversion if code_page not specified
  164. */
  165. if (0 == Locale)
  166. Locale = __lc_handle[LC_CTYPE];
  167. if (0 == code_page)
  168. code_page = __lc_codepage;
  169. /*
  170. * Always use Ansi codepage with Ansi WinAPI because they use
  171. * Ansi codepage
  172. */
  173. if ( code_page != (AnsiCP = __ansicp(Locale)))
  174. {
  175. if (AnsiCP != -1)
  176. code_page = AnsiCP;
  177. }
  178. /*
  179. * Convert strings and return the requested information.
  180. */
  181. /* find out how big a buffer we need (includes NULL if any) */
  182. if ( 0 == (buff_size1 = WideCharToMultiByte( code_page,
  183. 0,
  184. lpString1,
  185. cchCount1,
  186. NULL,
  187. 0,
  188. NULL,
  189. NULL )) )
  190. return 0;
  191. /* allocate enough space for chars */
  192. __try {
  193. buffer1 = (unsigned char *)_alloca( buff_size1 * sizeof(char) );
  194. }
  195. __except( EXCEPTION_EXECUTE_HANDLER ) {
  196. _resetstkoflw();
  197. buffer1 = NULL;
  198. }
  199. if ( buffer1 == NULL ) {
  200. if ( (buffer1 = (unsigned char *)_malloc_crt(buff_size1 * sizeof(char)))
  201. == NULL )
  202. return 0;
  203. malloc_flag1++;
  204. }
  205. /* do the conversion */
  206. if ( 0 == WideCharToMultiByte( code_page,
  207. 0,
  208. lpString1,
  209. cchCount1,
  210. buffer1,
  211. buff_size1,
  212. NULL,
  213. NULL ) )
  214. goto error_cleanup;
  215. /* find out how big a buffer we need (includes NULL if any) */
  216. if ( 0 == (buff_size2 = WideCharToMultiByte( code_page,
  217. 0,
  218. lpString2,
  219. cchCount2,
  220. NULL,
  221. 0,
  222. NULL,
  223. NULL )) )
  224. goto error_cleanup;
  225. /* allocate enough space for chars */
  226. __try {
  227. buffer2 = (unsigned char *)_alloca( buff_size2 * sizeof(char) );
  228. }
  229. __except( EXCEPTION_EXECUTE_HANDLER ) {
  230. _resetstkoflw();
  231. buffer2 = NULL;
  232. }
  233. if ( buffer2 == NULL ) {
  234. if ( (buffer2 = (unsigned char *)_malloc_crt(buff_size2 * sizeof(char)))
  235. == NULL )
  236. goto error_cleanup;
  237. malloc_flag2++;
  238. }
  239. /* do the conversion */
  240. if ( 0 != WideCharToMultiByte( code_page,
  241. 0,
  242. lpString2,
  243. cchCount2,
  244. buffer2,
  245. buff_size2,
  246. NULL,
  247. NULL ) )
  248. retcode = CompareStringA( Locale,
  249. dwCmpFlags,
  250. buffer1,
  251. buff_size1,
  252. buffer2,
  253. buff_size2 );
  254. if ( malloc_flag2 )
  255. _free_crt(buffer2);
  256. error_cleanup:
  257. if ( malloc_flag1 )
  258. _free_crt(buffer1);
  259. return retcode;
  260. }
  261. else /* f_use is neither USE_A nor USE_W */
  262. return 0;
  263. }