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.

265 lines
9.0 KiB

  1. /***
  2. *mbstowcs.c - Convert multibyte char string to wide char string.
  3. *
  4. * Copyright (c) 1990-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Convert a multibyte char string into the equivalent wide char string.
  8. *
  9. *Revision History:
  10. * 08-24-90 KRS Module created.
  11. * 03-20-91 KRS Ported from 16-bit tree.
  12. * 10-16-91 ETC Locale support under _INTL switch.
  13. * 12-09-91 ETC Updated nlsapi; added multithread.
  14. * 08-20-92 KRS Activated NLSAPI support.
  15. * 08-31-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
  16. * 09-02-92 SRW Get _INTL definition via ..\crt32.def
  17. * 02-09-93 CFW Always stuff WC 0 at end of output string of room (non _INTL).
  18. * 04-06-93 SKS Replace _CRTAPI* with _cdecl
  19. * 05-03-93 CFW Return pointer == NULL, return size, plus massive cleanup.
  20. * 06-01-93 CFW Minor optimization and beautify.
  21. * 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
  22. * 09-15-93 CFW Use ANSI conformant "__" names.
  23. * 09-21-93 CFW Avoid cast bug.
  24. * 09-27-93 GJF Merged NT SDK and Cuda.
  25. * 10-22-93 CFW Test for invalid MB chars using global preset flag.
  26. * 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
  27. * 02-03-94 GJF Merged in Steve Wood's latest change (affects
  28. * _NTSUBSET_ build only).
  29. * 02-07-94 CFW POSIXify.
  30. * 08-03-94 CFW Bug #15300; fix MBToWC workaround for small buffer.
  31. * 09-06-94 CFW Remove _INTL switch.
  32. * 10-18-94 BWT Fix build warning for call to RtlMultiByteToUnicodeN
  33. * 12-21-94 CFW Remove invalid MB chars NT 3.1 hack.
  34. * 01-07-95 CFW Mac merge cleanup.
  35. * 02-06-95 CFW assert -> _ASSERTE.
  36. * 04-19-95 CFW Rearrange & fix non-Win32 version.
  37. * 09-26-95 GJF New locking macro, and scheme, for functions which
  38. * reference the locale.
  39. * 04-01-96 BWT POSIX work.
  40. * 05-26-96 BWT Return the word count, not the byte count for
  41. * _NTSUBSET_/POSIX case.
  42. * 06-25-96 GJF Removed DLL_FOR_WIN32S. Replaced defined(_WIN32) with
  43. * !defined(_MAC). Polished the format a bit.
  44. * 07-27-98 GJF Revised multithread support based on threadlocinfo
  45. * struct.
  46. * 12-15-98 GJF Changes for 64-bit size_t.
  47. * 05-17-99 PML Remove all Macintosh support.
  48. *
  49. *******************************************************************************/
  50. #if defined(_NTSUBSET_) || defined(_POSIX_)
  51. #include <nt.h>
  52. #include <ntrtl.h>
  53. #include <nturtl.h>
  54. #endif
  55. #include <internal.h>
  56. #include <locale.h>
  57. #include <setlocal.h>
  58. #include <errno.h>
  59. #include <cruntime.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include <mtdll.h>
  63. #include <dbgint.h>
  64. #include <stdio.h>
  65. /***
  66. *size_t mbstowcs() - Convert multibyte char string to wide char string.
  67. *
  68. *Purpose:
  69. * Convert a multi-byte char string into the equivalent wide char string,
  70. * according to the LC_CTYPE category of the current locale.
  71. * [ANSI].
  72. *
  73. *Entry:
  74. * wchar_t *pwcs = pointer to destination wide character string buffer
  75. * const char *s = pointer to source multibyte character string
  76. * size_t n = maximum number of wide characters to store
  77. *
  78. *Exit:
  79. * If s != NULL, returns: number of words modified (<=n)
  80. * (size_t)-1 (if invalid mbcs)
  81. *
  82. *Exceptions:
  83. * Returns (size_t)-1 if s is NULL or invalid mbcs character encountered
  84. *
  85. *******************************************************************************/
  86. size_t __cdecl mbstowcs
  87. (
  88. wchar_t *pwcs,
  89. const char *s,
  90. size_t n
  91. )
  92. {
  93. #ifdef _MT
  94. pthreadlocinfo ptloci = _getptd()->ptlocinfo;
  95. if ( ptloci != __ptlocinfo )
  96. ptloci = __updatetlocinfo();
  97. return __mbstowcs_mt(ptloci, pwcs, s, n);
  98. }
  99. size_t __cdecl __mbstowcs_mt (
  100. pthreadlocinfo ptloci,
  101. wchar_t *pwcs,
  102. const char *s,
  103. size_t n
  104. )
  105. {
  106. #endif
  107. size_t count = 0;
  108. if (pwcs && n == 0)
  109. /* dest string exists, but 0 bytes converted */
  110. return (size_t) 0;
  111. _ASSERTE(s != NULL);
  112. #ifdef _WIN64
  113. /* n must fit into an int for MultiByteToWideChar */
  114. if ( n > INT_MAX )
  115. return (size_t)-1;
  116. #endif
  117. #if !defined(_NTSUBSET_) && !defined(_POSIX_)
  118. /* if destination string exists, fill it in */
  119. if (pwcs)
  120. {
  121. #ifdef _MT
  122. if (ptloci->lc_handle[LC_CTYPE] == _CLOCALEHANDLE)
  123. #else
  124. if (__lc_handle[LC_CTYPE] == _CLOCALEHANDLE)
  125. #endif
  126. {
  127. /* C locale: easy and fast */
  128. while (count < n)
  129. {
  130. *pwcs = (wchar_t) ((unsigned char)s[count]);
  131. if (!s[count])
  132. return count;
  133. count++;
  134. pwcs++;
  135. }
  136. return count;
  137. } else {
  138. int bytecnt, charcnt;
  139. unsigned char *p;
  140. /* Assume that the buffer is large enough */
  141. #ifdef _MT
  142. if ( (count = MultiByteToWideChar( ptloci->lc_codepage,
  143. #else
  144. if ( (count = MultiByteToWideChar( __lc_codepage,
  145. #endif
  146. MB_PRECOMPOSED |
  147. MB_ERR_INVALID_CHARS,
  148. s,
  149. -1,
  150. pwcs,
  151. (int)n )) != 0 )
  152. return count - 1; /* don't count NUL */
  153. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  154. {
  155. errno = EILSEQ;
  156. return (size_t)-1;
  157. }
  158. /* User-supplied buffer not large enough. */
  159. /* How many bytes are in n characters of the string? */
  160. charcnt = (int)n;
  161. for (p = (unsigned char *)s; (charcnt-- && *p); p++)
  162. {
  163. #ifdef _MT
  164. if (__isleadbyte_mt(ptloci, *p))
  165. #else
  166. if (isleadbyte(*p))
  167. #endif
  168. p++;
  169. }
  170. bytecnt = ((int) ((char *)p - (char *)s));
  171. #ifdef _MT
  172. if ( (count = MultiByteToWideChar( ptloci->lc_codepage,
  173. #else
  174. if ( (count = MultiByteToWideChar( __lc_codepage,
  175. #endif
  176. MB_PRECOMPOSED,
  177. s,
  178. bytecnt,
  179. pwcs,
  180. (int)n )) == 0 )
  181. {
  182. errno = EILSEQ;
  183. return (size_t)-1;
  184. }
  185. return count; /* no NUL in string */
  186. }
  187. }
  188. else { /* pwcs == NULL, get size only, s must be NUL-terminated */
  189. #ifdef _MT
  190. if (ptloci->lc_handle[LC_CTYPE] == _CLOCALEHANDLE)
  191. #else
  192. if (__lc_handle[LC_CTYPE] == _CLOCALEHANDLE)
  193. #endif
  194. return strlen(s);
  195. else {
  196. #ifdef _MT
  197. if ( (count = MultiByteToWideChar( ptloci->lc_codepage,
  198. #else
  199. if ( (count = MultiByteToWideChar( __lc_codepage,
  200. #endif
  201. MB_PRECOMPOSED |
  202. MB_ERR_INVALID_CHARS,
  203. s,
  204. -1,
  205. NULL,
  206. 0 )) == 0 )
  207. {
  208. errno = EILSEQ;
  209. return (size_t)-1;
  210. }
  211. return count - 1;
  212. }
  213. }
  214. #else /* _NTSUBSET_/_POSIX_ */
  215. if (pwcs) {
  216. NTSTATUS Status;
  217. int size;
  218. size = _mbstrlen(s);
  219. Status = RtlMultiByteToUnicodeN(pwcs,
  220. (ULONG) ( n * sizeof( *pwcs ) ),
  221. (PULONG)&size,
  222. (char *)s,
  223. size+1 );
  224. if (!NT_SUCCESS(Status)) {
  225. errno = EILSEQ;
  226. size = -1;
  227. } else {
  228. size = size / sizeof(*pwcs);
  229. if (pwcs[size-1] == L'\0') {
  230. size -= 1;
  231. }
  232. }
  233. return size;
  234. } else { /* pwcs == NULL, get size only, s must be NUL-terminated */
  235. return strlen(s);
  236. }
  237. #endif /* _NTSUBSET_/_POSIX_ */
  238. }