Windows NT 4.0 source code leak
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.

213 lines
5.7 KiB

4 years ago
  1. /***
  2. *wcstombs.c - Convert wide char string to multibyte char string.
  3. *
  4. * Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Convert a wide char string into the equivalent multibyte char string.
  8. *
  9. *Revision History:
  10. * 08-24-90 KRS Module created.
  11. * 01-14-91 KRS Added _WINSTATIC for Windows DLL. Fix wctomb() call.
  12. * 03-18-91 KRS Fix check for NUL.
  13. * 03-20-91 KRS Ported from 16-bit tree.
  14. * 10-16-91 ETC Locale support under _INTL switch.
  15. * 12-09-91 ETC Updated nlsapi; added multithread.
  16. * 08-20-92 KRS Activated NLSAPI support.
  17. * 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
  18. * 09-02-92 SRW Get _INTL definition via ..\crt32.def
  19. * 01-06-93 CFW Added (count < n) to outer loop - avoid bad wctomb calls
  20. * 01-07-93 KRS Major code cleanup. Fix error return, comments.
  21. * 05-03-93 CFW Return pointer == NULL, return size, plus massive cleanup.
  22. * 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
  23. * 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
  24. *
  25. *******************************************************************************/
  26. #ifdef _NTSUBSET_
  27. #include <nt.h>
  28. #include <ntrtl.h>
  29. #include <nturtl.h>
  30. #endif
  31. #include <cruntime.h>
  32. #include <stdlib.h>
  33. #include <limits.h>
  34. #include <internal.h>
  35. #include <os2dll.h>
  36. #include <locale.h>
  37. #include <setlocal.h>
  38. #include <errno.h>
  39. #include <assert.h>
  40. /***
  41. *size_t wcstombs() - Convert wide char string to multibyte char string.
  42. *
  43. *Purpose:
  44. * Convert a wide char string into the equivalent multibyte char string,
  45. * according to the LC_CTYPE category of the current locale.
  46. * [ANSI].
  47. *
  48. * NOTE: Currently, the C libraries support the "C" locale only.
  49. * Non-C locale support now available under _INTL switch.
  50. *Entry:
  51. * char *s = pointer to destination multibyte char string
  52. * const wchar_t *pwc = pointer to source wide character string
  53. * size_t n = maximum number of bytes to store in s
  54. *
  55. *Exit:
  56. * If s != NULL, returns (size_t)-1 (if a wchar cannot be converted)
  57. * Otherwise: Number of bytes modified (<=n), not including
  58. * the terminating NUL, if any.
  59. *
  60. *Exceptions:
  61. * Returns (size_t)-1 if s is NULL or invalid mb character encountered.
  62. *
  63. *******************************************************************************/
  64. #ifdef MTHREAD
  65. size_t _CRTAPI1 wcstombs
  66. (
  67. char *s,
  68. const wchar_t *pwcs,
  69. size_t n
  70. )
  71. {
  72. int retval;
  73. _mlock (_LC_CTYPE_LOCK);
  74. retval = _wcstombs_lk(s, pwcs, n);
  75. _munlock (_LC_CTYPE_LOCK);
  76. return retval;
  77. }
  78. #endif /* MTHREAD */
  79. #ifdef MTHREAD
  80. size_t _CRTAPI1 _wcstombs_lk
  81. #else
  82. size_t _CRTAPI1 wcstombs
  83. #endif
  84. (
  85. char *s,
  86. const wchar_t *pwcs,
  87. size_t n
  88. )
  89. {
  90. int i, retval;
  91. size_t count = 0;
  92. char buffer[MB_LEN_MAX]; /* UNDONE: what about MTHREAD ? */
  93. BOOL defused = 0;
  94. if (s && n == 0)
  95. return (size_t) 0;
  96. assert(pwcs != NULL);
  97. /* if destination string exists, fill it in */
  98. if (s)
  99. {
  100. #if defined(_INTL) && !defined(_NTSUBSET_)
  101. if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
  102. _lc_codepage == _CLOCALECP)
  103. {
  104. #endif /* _INTL */
  105. #ifdef _NTSUBSET_
  106. {
  107. NTSTATUS Status;
  108. Status = RtlUnicodeToMultiByteN(s, n, (PULONG)&count, (wchar_t *)pwcs, (wcslen(pwcs)+1)*sizeof(WCHAR));
  109. if (NT_SUCCESS(Status))
  110. {
  111. return count - 1; /* don't count NUL */
  112. } else {
  113. errno = EILSEQ;
  114. count = (size_t)-1;
  115. }
  116. }
  117. #else
  118. /* C locale: easy and fast */
  119. while(count < n)
  120. {
  121. if (*pwcs > 255) /* validate high byte */
  122. {
  123. errno = EILSEQ;
  124. return (size_t)-1; /* error */
  125. }
  126. s[count] = (char) *pwcs;
  127. if (*pwcs++ == L'\0')
  128. return count;
  129. count++;
  130. }
  131. #endif
  132. return count;
  133. #if defined(_INTL) && !defined(_NTSUBSET_)
  134. } else {
  135. /* Assume that usually the buffer is large enough */
  136. if (((count=WideCharToMultiByte(_lc_codepage,
  137. WC_COMPOSITECHECK | WC_SEPCHARS,
  138. pwcs, -1, s, n, NULL, &defused)) != 0) && (!defused))
  139. return count - 1; /* don't count NUL */
  140. if (defused || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  141. {
  142. errno = EILSEQ;
  143. return (size_t)-1;
  144. }
  145. /* buffer not large enough, must do char by char */
  146. while (count < n)
  147. {
  148. if (((retval = WideCharToMultiByte (_lc_codepage, 0,
  149. pwcs, 1, buffer, MB_CUR_MAX, NULL, &defused)) == 0) || defused)
  150. {
  151. errno = EILSEQ;
  152. return (size_t)-1;
  153. }
  154. if (count + retval > n)
  155. return count;
  156. for (i = 0; i < retval; i++, count++) /* store character */
  157. if((s[count] = buffer[i])=='\0')
  158. return count; /* done if NUL */
  159. pwcs++;
  160. }
  161. return count;
  162. }
  163. #endif /* _INTL */
  164. }
  165. else { /* s == NULL, get size only, pwcs must be NUL-terminated */
  166. #if defined(_INTL) && !defined(_NTSUBSET_)
  167. if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
  168. _lc_codepage == _CLOCALECP)
  169. #endif /* _INTL */
  170. #ifdef _NTSUBSET_
  171. {
  172. NTSTATUS Status;
  173. Status = RtlUnicodeToMultiByteSize((PULONG)&count, (wchar_t *)pwcs, (wcslen(pwcs)+1)*sizeof(WCHAR));
  174. if (NT_SUCCESS(Status))
  175. {
  176. return count - 1; /* don't count NUL */
  177. } else {
  178. errno = EILSEQ;
  179. count = (size_t)-1;
  180. }
  181. }
  182. #else
  183. return wcslen(pwcs);
  184. #endif
  185. #if defined(_INTL) && !defined(_NTSUBSET_)
  186. else {
  187. if (((count=WideCharToMultiByte(_lc_codepage,
  188. WC_COMPOSITECHECK | WC_SEPCHARS,
  189. pwcs, -1, NULL, 0, NULL, &defused)) == 0) || (defused))
  190. {
  191. errno = EILSEQ;
  192. return (size_t)-1;
  193. }
  194. return count - 1;
  195. }
  196. #endif /* _INTL */
  197. }
  198. }