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.

2499 lines
88 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: nlsxlat.c
  3. *
  4. * Copyright (c) 1985-91, Microsoft Corporation
  5. *
  6. * This modules contains the private routines for character translation:
  7. * 8-bit <=> Unicode.
  8. *
  9. * History:
  10. * 03-Jan-1992 gregoryw
  11. * 16-Feb-1993 JulieB Added Upcase Routines & Macros.
  12. * 17-Feb-1993 JulieB Fixed Tables; Fixed DBCS Code.
  13. * 08-Mar-1993 JulieB Moved Upcase Macro to ntrtlp.h.
  14. \***************************************************************************/
  15. #include "ntrtlp.h"
  16. NTSTATUS
  17. RtlConsoleMultiByteToUnicodeN(
  18. OUT PWCH UnicodeString,
  19. IN ULONG MaxBytesInUnicodeString,
  20. OUT PULONG BytesInUnicodeString OPTIONAL,
  21. IN PCH MultiByteString,
  22. IN ULONG BytesInMultiByteString,
  23. OUT PULONG pdwSpecialChar );
  24. VOID
  25. RtlpInitUpcaseTable(
  26. IN PUSHORT TableBase,
  27. OUT PNLSTABLEINFO CodePageTable
  28. );
  29. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  30. #pragma alloc_text(PAGE,RtlConsoleMultiByteToUnicodeN)
  31. #pragma alloc_text(PAGE,RtlMultiByteToUnicodeN)
  32. #pragma alloc_text(PAGE,RtlOemToUnicodeN)
  33. #pragma alloc_text(PAGE,RtlUnicodeToMultiByteN)
  34. #pragma alloc_text(PAGE,RtlUpcaseUnicodeToMultiByteN)
  35. #pragma alloc_text(PAGE,RtlUnicodeToOemN)
  36. #pragma alloc_text(PAGE,RtlUpcaseUnicodeToOemN)
  37. #pragma alloc_text(PAGE,RtlpDidUnicodeToOemWork)
  38. #pragma alloc_text(PAGE,RtlCustomCPToUnicodeN)
  39. #pragma alloc_text(PAGE,RtlUnicodeToCustomCPN)
  40. #pragma alloc_text(PAGE,RtlUpcaseUnicodeToCustomCPN)
  41. #pragma alloc_text(PAGE,RtlInitCodePageTable)
  42. #pragma alloc_text(PAGE,RtlpInitUpcaseTable)
  43. #pragma alloc_text(PAGE,RtlInitNlsTables)
  44. #pragma alloc_text(PAGE,RtlResetRtlTranslations)
  45. #pragma alloc_text(PAGE,RtlMultiByteToUnicodeSize)
  46. #pragma alloc_text(PAGE,RtlUnicodeToMultiByteSize)
  47. #pragma alloc_text(PAGE,RtlGetDefaultCodePage)
  48. #endif
  49. //
  50. // Various defines and convenient macros for data access
  51. //
  52. #define DBCS_TABLE_SIZE 256
  53. /*
  54. * Global data used by the translation routines.
  55. *
  56. */
  57. #if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  58. #pragma data_seg("PAGEDATA")
  59. #pragma const_seg("PAGECONST")
  60. #endif
  61. //
  62. // Upcase and Lowercase data
  63. //
  64. PUSHORT Nls844UnicodeUpcaseTable = NULL;
  65. PUSHORT Nls844UnicodeLowercaseTable = NULL;
  66. //
  67. // ACP related data
  68. //
  69. USHORT NlsLeadByteInfoTable[DBCS_TABLE_SIZE] = {0}; // Lead byte info. for ACP
  70. USHORT NlsAnsiCodePage = 0; // Default ANSI code page
  71. USHORT NlsOemCodePage = 0; // Default OEM code page
  72. const PUSHORT NlsLeadByteInfo = NlsLeadByteInfoTable;
  73. PUSHORT NlsMbAnsiCodePageTables = NULL; // Multibyte to Unicode translation tables
  74. PUSHORT NlsAnsiToUnicodeData = NULL; // Ansi CP to Unicode translation table
  75. PCH NlsUnicodeToAnsiData = NULL; // Unicode to Ansi CP translation table
  76. PUSHORT NlsUnicodeToMbAnsiData = NULL; // Unicode to Multibyte Ansi CP translation table
  77. BOOLEAN NlsMbCodePageTag = FALSE; // TRUE -> Multibyte ACP, FALSE -> Singlebyte ACP
  78. //
  79. // OEM related data
  80. //
  81. USHORT NlsOemLeadByteInfoTable[DBCS_TABLE_SIZE] = {0}; // Lead byte info. for 0CP
  82. const PUSHORT NlsOemLeadByteInfo = NlsOemLeadByteInfoTable;
  83. PUSHORT NlsMbOemCodePageTables = NULL; // OEM Multibyte to Unicode translation tables
  84. PUSHORT NlsOemToUnicodeData = NULL; // Oem CP to Unicode translation table
  85. PCH NlsUnicodeToOemData = NULL; // Unicode to Oem CP translation table
  86. PUSHORT NlsUnicodeToMbOemData = NULL; // Unicode to Multibyte Oem CP translation table
  87. BOOLEAN NlsMbOemCodePageTag = FALSE; // TRUE -> Multibyte OCP, FALSE -> Singlebyte OCP
  88. //
  89. // Default info taken from data files
  90. //
  91. USHORT UnicodeDefaultChar = 0;
  92. USHORT OemDefaultChar = 0;
  93. USHORT OemTransUniDefaultChar = 0;
  94. //
  95. // Default info NOT taken from data files
  96. //
  97. #define UnicodeNull 0x0000
  98. NTSTATUS
  99. RtlConsoleMultiByteToUnicodeN(
  100. OUT PWCH UnicodeString,
  101. IN ULONG MaxBytesInUnicodeString,
  102. OUT PULONG BytesInUnicodeString OPTIONAL,
  103. IN PCH MultiByteString,
  104. IN ULONG BytesInMultiByteString,
  105. OUT PULONG pdwSpecialChar )
  106. /*++
  107. Routine Description:
  108. This function is a superset of MultiByteToUnicode for the
  109. console. It works just like the other, except it will detect
  110. if any characters were under 0x20.
  111. This functions converts the specified ansi source string into a
  112. Unicode string. The translation is done with respect to the
  113. ANSI Code Page (ACP) installed at boot time. Single byte characters
  114. in the range 0x00 - 0x7f are simply zero extended as a performance
  115. enhancement. In some far eastern code pages 0x5c is defined as the
  116. Yen sign. For system translation we always want to consider 0x5c
  117. to be the backslash character. We get this for free by zero extending.
  118. NOTE: This routine only supports precomposed Unicode characters.
  119. Arguments:
  120. UnicodeString - Returns a unicode string that is equivalent to
  121. the ansi source string.
  122. MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
  123. written to UnicodeString. If this causes UnicodeString to be a
  124. truncated equivalent of MultiByteString, no error condition results.
  125. BytesInUnicodeString - Returns the number of bytes in the returned
  126. unicode string pointed to by UnicodeString.
  127. MultiByteString - Supplies the ansi source string that is to be
  128. converted to unicode.
  129. BytesInMultiByteString - The number of bytes in the string pointed to
  130. by MultiByteString.
  131. pdwSpecialChar - will be zero if non detected, else it will contain the
  132. approximate index (can be off by 32).
  133. Return Value:
  134. SUCCESS - The conversion was successful.
  135. --*/
  136. {
  137. ULONG LoopCount;
  138. PUSHORT TranslateTable;
  139. ULONG MaxCharsInUnicodeString;
  140. RTL_PAGED_CODE();
  141. *pdwSpecialChar = 0;
  142. MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
  143. if (!NlsMbCodePageTag) {
  144. LoopCount = (MaxCharsInUnicodeString < BytesInMultiByteString) ?
  145. MaxCharsInUnicodeString : BytesInMultiByteString;
  146. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  147. *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
  148. TranslateTable = NlsAnsiToUnicodeData; // used to help the mips compiler
  149. quick_copy:
  150. switch( LoopCount ) {
  151. default:
  152. if ((UCHAR)MultiByteString[0x1F] < 0x20) goto bad_case;
  153. UnicodeString[0x1F] = TranslateTable[(UCHAR)MultiByteString[0x1F]];
  154. case 0x1F:
  155. if ((UCHAR)MultiByteString[0x1E] < 0x20) goto bad_case;
  156. UnicodeString[0x1E] = TranslateTable[(UCHAR)MultiByteString[0x1E]];
  157. case 0x1E:
  158. if ((UCHAR)MultiByteString[0x1D] < 0x20) goto bad_case;
  159. UnicodeString[0x1D] = TranslateTable[(UCHAR)MultiByteString[0x1D]];
  160. case 0x1D:
  161. if ((UCHAR)MultiByteString[0x1C] < 0x20) goto bad_case;
  162. UnicodeString[0x1C] = TranslateTable[(UCHAR)MultiByteString[0x1C]];
  163. case 0x1C:
  164. if ((UCHAR)MultiByteString[0x1B] < 0x20) goto bad_case;
  165. UnicodeString[0x1B] = TranslateTable[(UCHAR)MultiByteString[0x1B]];
  166. case 0x1B:
  167. if ((UCHAR)MultiByteString[0x1A] < 0x20) goto bad_case;
  168. UnicodeString[0x1A] = TranslateTable[(UCHAR)MultiByteString[0x1A]];
  169. case 0x1A:
  170. if ((UCHAR)MultiByteString[0x19] < 0x20) goto bad_case;
  171. UnicodeString[0x19] = TranslateTable[(UCHAR)MultiByteString[0x19]];
  172. case 0x19:
  173. if ((UCHAR)MultiByteString[0x18] < 0x20) goto bad_case;
  174. UnicodeString[0x18] = TranslateTable[(UCHAR)MultiByteString[0x18]];
  175. case 0x18:
  176. if ((UCHAR)MultiByteString[0x17] < 0x20) goto bad_case;
  177. UnicodeString[0x17] = TranslateTable[(UCHAR)MultiByteString[0x17]];
  178. case 0x17:
  179. if ((UCHAR)MultiByteString[0x16] < 0x20) goto bad_case;
  180. UnicodeString[0x16] = TranslateTable[(UCHAR)MultiByteString[0x16]];
  181. case 0x16:
  182. if ((UCHAR)MultiByteString[0x15] < 0x20) goto bad_case;
  183. UnicodeString[0x15] = TranslateTable[(UCHAR)MultiByteString[0x15]];
  184. case 0x15:
  185. if ((UCHAR)MultiByteString[0x14] < 0x20) goto bad_case;
  186. UnicodeString[0x14] = TranslateTable[(UCHAR)MultiByteString[0x14]];
  187. case 0x14:
  188. if ((UCHAR)MultiByteString[0x13] < 0x20) goto bad_case;
  189. UnicodeString[0x13] = TranslateTable[(UCHAR)MultiByteString[0x13]];
  190. case 0x13:
  191. if ((UCHAR)MultiByteString[0x12] < 0x20) goto bad_case;
  192. UnicodeString[0x12] = TranslateTable[(UCHAR)MultiByteString[0x12]];
  193. case 0x12:
  194. if ((UCHAR)MultiByteString[0x11] < 0x20) goto bad_case;
  195. UnicodeString[0x11] = TranslateTable[(UCHAR)MultiByteString[0x11]];
  196. case 0x11:
  197. if ((UCHAR)MultiByteString[0x10] < 0x20) goto bad_case;
  198. UnicodeString[0x10] = TranslateTable[(UCHAR)MultiByteString[0x10]];
  199. case 0x10:
  200. if ((UCHAR)MultiByteString[0x0F] < 0x20) goto bad_case;
  201. UnicodeString[0x0F] = TranslateTable[(UCHAR)MultiByteString[0x0F]];
  202. case 0x0F:
  203. if ((UCHAR)MultiByteString[0x0E] < 0x20) goto bad_case;
  204. UnicodeString[0x0E] = TranslateTable[(UCHAR)MultiByteString[0x0E]];
  205. case 0x0E:
  206. if ((UCHAR)MultiByteString[0x0D] < 0x20) goto bad_case;
  207. UnicodeString[0x0D] = TranslateTable[(UCHAR)MultiByteString[0x0D]];
  208. case 0x0D:
  209. if ((UCHAR)MultiByteString[0x0C] < 0x20) goto bad_case;
  210. UnicodeString[0x0C] = TranslateTable[(UCHAR)MultiByteString[0x0C]];
  211. case 0x0C:
  212. if ((UCHAR)MultiByteString[0x0B] < 0x20) goto bad_case;
  213. UnicodeString[0x0B] = TranslateTable[(UCHAR)MultiByteString[0x0B]];
  214. case 0x0B:
  215. if ((UCHAR)MultiByteString[0x0A] < 0x20) goto bad_case;
  216. UnicodeString[0x0A] = TranslateTable[(UCHAR)MultiByteString[0x0A]];
  217. case 0x0A:
  218. if ((UCHAR)MultiByteString[0x09] < 0x20) goto bad_case;
  219. UnicodeString[0x09] = TranslateTable[(UCHAR)MultiByteString[0x09]];
  220. case 0x09:
  221. if ((UCHAR)MultiByteString[0x08] < 0x20) goto bad_case;
  222. UnicodeString[0x08] = TranslateTable[(UCHAR)MultiByteString[0x08]];
  223. case 0x08:
  224. if ((UCHAR)MultiByteString[0x07] < 0x20) goto bad_case;
  225. UnicodeString[0x07] = TranslateTable[(UCHAR)MultiByteString[0x07]];
  226. case 0x07:
  227. if ((UCHAR)MultiByteString[0x06] < 0x20) goto bad_case;
  228. UnicodeString[0x06] = TranslateTable[(UCHAR)MultiByteString[0x06]];
  229. case 0x06:
  230. if ((UCHAR)MultiByteString[0x05] < 0x20) goto bad_case;
  231. UnicodeString[0x05] = TranslateTable[(UCHAR)MultiByteString[0x05]];
  232. case 0x05:
  233. if ((UCHAR)MultiByteString[0x04] < 0x20) goto bad_case;
  234. UnicodeString[0x04] = TranslateTable[(UCHAR)MultiByteString[0x04]];
  235. case 0x04:
  236. if ((UCHAR)MultiByteString[0x03] < 0x20) goto bad_case;
  237. UnicodeString[0x03] = TranslateTable[(UCHAR)MultiByteString[0x03]];
  238. case 0x03:
  239. if ((UCHAR)MultiByteString[0x02] < 0x20) goto bad_case;
  240. UnicodeString[0x02] = TranslateTable[(UCHAR)MultiByteString[0x02]];
  241. case 0x02:
  242. if ((UCHAR)MultiByteString[0x01] < 0x20) goto bad_case;
  243. UnicodeString[0x01] = TranslateTable[(UCHAR)MultiByteString[0x01]];
  244. case 0x01:
  245. if ((UCHAR)MultiByteString[0x00] < 0x20) goto bad_case;
  246. UnicodeString[0x00] = TranslateTable[(UCHAR)MultiByteString[0x00]];
  247. case 0x00:
  248. ;
  249. }
  250. if ( LoopCount > 0x20 ) {
  251. LoopCount -= 0x20;
  252. UnicodeString += 0x20;
  253. MultiByteString += 0x20;
  254. goto quick_copy;
  255. }
  256. /* end of copy... */
  257. } else {
  258. register USHORT Entry;
  259. PWCH UnicodeStringAnchor = UnicodeString;
  260. TranslateTable = (PUSHORT)NlsMbAnsiCodePageTables;
  261. //
  262. // The ACP is a multibyte code page. Check each character
  263. // to see if it is a lead byte before doing the translation.
  264. //
  265. while (MaxCharsInUnicodeString && BytesInMultiByteString) {
  266. MaxCharsInUnicodeString--;
  267. BytesInMultiByteString--;
  268. if (NlsLeadByteInfo[*(PUCHAR)MultiByteString]) {
  269. //
  270. // Lead byte - Make sure there is a trail byte. If not,
  271. // pass back a space rather than an error. Some 3.x
  272. // applications pass incorrect strings and don't expect
  273. // to get an error.
  274. //
  275. if (BytesInMultiByteString == 0)
  276. {
  277. *UnicodeString++ = UnicodeNull;
  278. break;
  279. }
  280. //
  281. // Get the unicode character.
  282. //
  283. Entry = NlsLeadByteInfo[*(PUCHAR)MultiByteString++];
  284. *UnicodeString = (WCHAR)TranslateTable[ Entry + *(PUCHAR)MultiByteString++ ];
  285. UnicodeString++;
  286. //
  287. // Decrement count of bytes in multibyte string to account
  288. // for the double byte character.
  289. //
  290. BytesInMultiByteString--;
  291. } else {
  292. //
  293. // Single byte character.
  294. //
  295. if ((UCHAR)MultiByteString[0x00] < 0x20)
  296. *pdwSpecialChar = 1;
  297. *UnicodeString++ = NlsAnsiToUnicodeData[*(PUCHAR)MultiByteString++];
  298. }
  299. }
  300. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  301. *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
  302. }
  303. return STATUS_SUCCESS;
  304. bad_case:
  305. //
  306. // this is a low probability case, so we optimized the loop. If have a
  307. // special char, finish trans and notify caller.
  308. //
  309. *pdwSpecialChar = 1;
  310. return RtlMultiByteToUnicodeN(UnicodeString, MaxBytesInUnicodeString,
  311. NULL, MultiByteString, LoopCount);
  312. }
  313. NTSTATUS
  314. RtlMultiByteToUnicodeN(
  315. OUT PWCH UnicodeString,
  316. IN ULONG MaxBytesInUnicodeString,
  317. OUT PULONG BytesInUnicodeString OPTIONAL,
  318. IN PCSTR MultiByteString,
  319. IN ULONG BytesInMultiByteString)
  320. /*++
  321. Routine Description:
  322. This functions converts the specified ansi source string into a
  323. Unicode string. The translation is done with respect to the
  324. ANSI Code Page (ACP) installed at boot time. Single byte characters
  325. in the range 0x00 - 0x7f are simply zero extended as a performance
  326. enhancement. In some far eastern code pages 0x5c is defined as the
  327. Yen sign. For system translation we always want to consider 0x5c
  328. to be the backslash character. We get this for free by zero extending.
  329. NOTE: This routine only supports precomposed Unicode characters.
  330. Arguments:
  331. UnicodeString - Returns a unicode string that is equivalent to
  332. the ansi source string.
  333. MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
  334. written to UnicodeString. If this causes UnicodeString to be a
  335. truncated equivalent of MultiByteString, no error condition results.
  336. BytesInUnicodeString - Returns the number of bytes in the returned
  337. unicode string pointed to by UnicodeString.
  338. MultiByteString - Supplies the ansi source string that is to be
  339. converted to unicode. For single-byte character sets, this address
  340. CAN be the same as UnicodeString.
  341. BytesInMultiByteString - The number of bytes in the string pointed to
  342. by MultiByteString.
  343. Return Value:
  344. SUCCESS - The conversion was successful.
  345. --*/
  346. {
  347. ULONG LoopCount;
  348. ULONG TmpCount;
  349. PUSHORT TranslateTable;
  350. ULONG MaxCharsInUnicodeString;
  351. RTL_PAGED_CODE();
  352. MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
  353. if (!NlsMbCodePageTag) {
  354. LoopCount = (MaxCharsInUnicodeString < BytesInMultiByteString) ?
  355. MaxCharsInUnicodeString : BytesInMultiByteString;
  356. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  357. *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
  358. TranslateTable = NlsAnsiToUnicodeData; // used to help the mips compiler
  359. TmpCount = LoopCount & 0x1F;
  360. UnicodeString += (LoopCount - TmpCount);
  361. MultiByteString += (LoopCount - TmpCount);
  362. quick_copy:
  363. switch( TmpCount ) {
  364. default:
  365. UnicodeString[0x1F] = TranslateTable[(UCHAR)MultiByteString[0x1F]];
  366. case 0x1F:
  367. UnicodeString[0x1E] = TranslateTable[(UCHAR)MultiByteString[0x1E]];
  368. case 0x1E:
  369. UnicodeString[0x1D] = TranslateTable[(UCHAR)MultiByteString[0x1D]];
  370. case 0x1D:
  371. UnicodeString[0x1C] = TranslateTable[(UCHAR)MultiByteString[0x1C]];
  372. case 0x1C:
  373. UnicodeString[0x1B] = TranslateTable[(UCHAR)MultiByteString[0x1B]];
  374. case 0x1B:
  375. UnicodeString[0x1A] = TranslateTable[(UCHAR)MultiByteString[0x1A]];
  376. case 0x1A:
  377. UnicodeString[0x19] = TranslateTable[(UCHAR)MultiByteString[0x19]];
  378. case 0x19:
  379. UnicodeString[0x18] = TranslateTable[(UCHAR)MultiByteString[0x18]];
  380. case 0x18:
  381. UnicodeString[0x17] = TranslateTable[(UCHAR)MultiByteString[0x17]];
  382. case 0x17:
  383. UnicodeString[0x16] = TranslateTable[(UCHAR)MultiByteString[0x16]];
  384. case 0x16:
  385. UnicodeString[0x15] = TranslateTable[(UCHAR)MultiByteString[0x15]];
  386. case 0x15:
  387. UnicodeString[0x14] = TranslateTable[(UCHAR)MultiByteString[0x14]];
  388. case 0x14:
  389. UnicodeString[0x13] = TranslateTable[(UCHAR)MultiByteString[0x13]];
  390. case 0x13:
  391. UnicodeString[0x12] = TranslateTable[(UCHAR)MultiByteString[0x12]];
  392. case 0x12:
  393. UnicodeString[0x11] = TranslateTable[(UCHAR)MultiByteString[0x11]];
  394. case 0x11:
  395. UnicodeString[0x10] = TranslateTable[(UCHAR)MultiByteString[0x10]];
  396. case 0x10:
  397. UnicodeString[0x0F] = TranslateTable[(UCHAR)MultiByteString[0x0F]];
  398. case 0x0F:
  399. UnicodeString[0x0E] = TranslateTable[(UCHAR)MultiByteString[0x0E]];
  400. case 0x0E:
  401. UnicodeString[0x0D] = TranslateTable[(UCHAR)MultiByteString[0x0D]];
  402. case 0x0D:
  403. UnicodeString[0x0C] = TranslateTable[(UCHAR)MultiByteString[0x0C]];
  404. case 0x0C:
  405. UnicodeString[0x0B] = TranslateTable[(UCHAR)MultiByteString[0x0B]];
  406. case 0x0B:
  407. UnicodeString[0x0A] = TranslateTable[(UCHAR)MultiByteString[0x0A]];
  408. case 0x0A:
  409. UnicodeString[0x09] = TranslateTable[(UCHAR)MultiByteString[0x09]];
  410. case 0x09:
  411. UnicodeString[0x08] = TranslateTable[(UCHAR)MultiByteString[0x08]];
  412. case 0x08:
  413. UnicodeString[0x07] = TranslateTable[(UCHAR)MultiByteString[0x07]];
  414. case 0x07:
  415. UnicodeString[0x06] = TranslateTable[(UCHAR)MultiByteString[0x06]];
  416. case 0x06:
  417. UnicodeString[0x05] = TranslateTable[(UCHAR)MultiByteString[0x05]];
  418. case 0x05:
  419. UnicodeString[0x04] = TranslateTable[(UCHAR)MultiByteString[0x04]];
  420. case 0x04:
  421. UnicodeString[0x03] = TranslateTable[(UCHAR)MultiByteString[0x03]];
  422. case 0x03:
  423. UnicodeString[0x02] = TranslateTable[(UCHAR)MultiByteString[0x02]];
  424. case 0x02:
  425. UnicodeString[0x01] = TranslateTable[(UCHAR)MultiByteString[0x01]];
  426. case 0x01:
  427. UnicodeString[0x00] = TranslateTable[(UCHAR)MultiByteString[0x00]];
  428. case 0x00:
  429. ;
  430. }
  431. if ( LoopCount >= 0x20 ) {
  432. TmpCount = 0x20;
  433. LoopCount -= 0x20;
  434. UnicodeString -= 0x20;
  435. MultiByteString -= 0x20;
  436. goto quick_copy;
  437. }
  438. /* end of copy... */
  439. } else {
  440. register USHORT Entry;
  441. PWCH UnicodeStringAnchor = UnicodeString;
  442. TranslateTable = (PUSHORT)NlsMbAnsiCodePageTables;
  443. //
  444. // The ACP is a multibyte code page. Check each character
  445. // to see if it is a lead byte before doing the translation.
  446. //
  447. while (MaxCharsInUnicodeString && BytesInMultiByteString) {
  448. MaxCharsInUnicodeString--;
  449. BytesInMultiByteString--;
  450. if (NlsLeadByteInfo[*(PUCHAR)MultiByteString]) {
  451. //
  452. // Lead byte - Make sure there is a trail byte. If not,
  453. // pass back a space rather than an error. Some 3.x
  454. // applications pass incorrect strings and don't expect
  455. // to get an error.
  456. //
  457. if (BytesInMultiByteString == 0)
  458. {
  459. *UnicodeString++ = UnicodeNull;
  460. break;
  461. }
  462. //
  463. // Get the unicode character.
  464. //
  465. Entry = NlsLeadByteInfo[*(PUCHAR)MultiByteString++];
  466. *UnicodeString = (WCHAR)TranslateTable[ Entry + *(PUCHAR)MultiByteString++ ];
  467. UnicodeString++;
  468. //
  469. // Decrement count of bytes in multibyte string to account
  470. // for the double byte character.
  471. //
  472. BytesInMultiByteString--;
  473. } else {
  474. //
  475. // Single byte character.
  476. //
  477. *UnicodeString++ = NlsAnsiToUnicodeData[*(PUCHAR)MultiByteString++];
  478. }
  479. }
  480. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  481. *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
  482. }
  483. return STATUS_SUCCESS;
  484. }
  485. NTSTATUS
  486. RtlOemToUnicodeN(
  487. OUT PWCH UnicodeString,
  488. IN ULONG MaxBytesInUnicodeString,
  489. OUT PULONG BytesInUnicodeString OPTIONAL,
  490. IN PCH OemString,
  491. IN ULONG BytesInOemString)
  492. /*++
  493. Routine Description:
  494. This functions converts the specified oem source string into a
  495. Unicode string. The translation is done with respect to the
  496. OEM Code Page (OCP) installed at boot time. Single byte characters
  497. in the range 0x00 - 0x7f are simply zero extended as a performance
  498. enhancement. In some far eastern code pages 0x5c is defined as the
  499. Yen sign. For system translation we always want to consider 0x5c
  500. to be the backslash character. We get this for free by zero extending.
  501. NOTE: This routine only supports precomposed Unicode characters.
  502. Arguments:
  503. UnicodeString - Returns a unicode string that is equivalent to
  504. the oem source string.
  505. MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
  506. written to UnicodeString. If this causes UnicodeString to be a
  507. truncated equivalent of OemString, no error condition results.
  508. BytesInUnicodeString - Returns the number of bytes in the returned
  509. unicode string pointed to by UnicodeString.
  510. OemString - Supplies the oem source string that is to be
  511. converted to unicode.
  512. BytesInOemString - The number of bytes in the string pointed to
  513. by OemString.
  514. Return Value:
  515. SUCCESS - The conversion was successful
  516. STATUS_ILLEGAL_CHARACTER - The final Oem character was illegal
  517. STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
  518. the whole Oem string. It was converted correct to the point though.
  519. --*/
  520. {
  521. ULONG LoopCount;
  522. PUSHORT TranslateTable;
  523. ULONG MaxCharsInUnicodeString;
  524. RTL_PAGED_CODE();
  525. // The OCP is a multibyte code page. Check each character
  526. // to see if it is a lead byte before doing the translation.
  527. MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
  528. if (!NlsMbOemCodePageTag) {
  529. LoopCount = (MaxCharsInUnicodeString < BytesInOemString) ?
  530. MaxCharsInUnicodeString : BytesInOemString;
  531. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  532. *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
  533. TranslateTable = NlsOemToUnicodeData; // used to help the mips compiler
  534. quick_copy:
  535. switch( LoopCount ) {
  536. default:
  537. UnicodeString[0x0F] = TranslateTable[(UCHAR)OemString[0x0F]];
  538. case 0x0F:
  539. UnicodeString[0x0E] = TranslateTable[(UCHAR)OemString[0x0E]];
  540. case 0x0E:
  541. UnicodeString[0x0D] = TranslateTable[(UCHAR)OemString[0x0D]];
  542. case 0x0D:
  543. UnicodeString[0x0C] = TranslateTable[(UCHAR)OemString[0x0C]];
  544. case 0x0C:
  545. UnicodeString[0x0B] = TranslateTable[(UCHAR)OemString[0x0B]];
  546. case 0x0B:
  547. UnicodeString[0x0A] = TranslateTable[(UCHAR)OemString[0x0A]];
  548. case 0x0A:
  549. UnicodeString[0x09] = TranslateTable[(UCHAR)OemString[0x09]];
  550. case 0x09:
  551. UnicodeString[0x08] = TranslateTable[(UCHAR)OemString[0x08]];
  552. case 0x08:
  553. UnicodeString[0x07] = TranslateTable[(UCHAR)OemString[0x07]];
  554. case 0x07:
  555. UnicodeString[0x06] = TranslateTable[(UCHAR)OemString[0x06]];
  556. case 0x06:
  557. UnicodeString[0x05] = TranslateTable[(UCHAR)OemString[0x05]];
  558. case 0x05:
  559. UnicodeString[0x04] = TranslateTable[(UCHAR)OemString[0x04]];
  560. case 0x04:
  561. UnicodeString[0x03] = TranslateTable[(UCHAR)OemString[0x03]];
  562. case 0x03:
  563. UnicodeString[0x02] = TranslateTable[(UCHAR)OemString[0x02]];
  564. case 0x02:
  565. UnicodeString[0x01] = TranslateTable[(UCHAR)OemString[0x01]];
  566. case 0x01:
  567. UnicodeString[0x00] = TranslateTable[(UCHAR)OemString[0x00]];
  568. case 0x00:
  569. ;
  570. }
  571. if ( LoopCount > 0x10 ) {
  572. LoopCount -= 0x10;
  573. OemString += 0x10;
  574. UnicodeString += 0x10;
  575. goto quick_copy;
  576. }
  577. /* end of copy... */
  578. } else {
  579. register USHORT Entry;
  580. PWCH UnicodeStringAnchor = UnicodeString;
  581. TranslateTable = (PUSHORT)NlsMbOemCodePageTables;
  582. while (MaxCharsInUnicodeString && BytesInOemString) {
  583. MaxCharsInUnicodeString--;
  584. BytesInOemString--;
  585. if (NlsOemLeadByteInfo[*(PUCHAR)OemString]) {
  586. //
  587. // Lead byte - Make sure there is a trail byte. If not,
  588. // pass back a space rather than an error. Some 3.x
  589. // applications pass incorrect strings and don't expect
  590. // to get an error.
  591. //
  592. if (BytesInOemString == 0)
  593. {
  594. *UnicodeString++ = UnicodeNull;
  595. break;
  596. }
  597. //
  598. // Get the unicode character.
  599. //
  600. Entry = NlsOemLeadByteInfo[*(PUCHAR)OemString++];
  601. *UnicodeString = TranslateTable[ Entry + *(PUCHAR)OemString++ ];
  602. UnicodeString++;
  603. //
  604. // Decrement count of bytes in oem string to account
  605. // for the double byte character.
  606. //
  607. BytesInOemString--;
  608. } else {
  609. //
  610. // Single byte character.
  611. //
  612. *UnicodeString++ = NlsOemToUnicodeData[*(PUCHAR)OemString++];
  613. }
  614. }
  615. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  616. *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
  617. }
  618. //
  619. // Check if we were able to use all of the source Oem String
  620. //
  621. return (BytesInOemString <= MaxCharsInUnicodeString) ?
  622. STATUS_SUCCESS :
  623. STATUS_BUFFER_OVERFLOW;
  624. }
  625. NTSTATUS
  626. RtlMultiByteToUnicodeSize(
  627. OUT PULONG BytesInUnicodeString,
  628. IN PCSTR MultiByteString,
  629. IN ULONG BytesInMultiByteString)
  630. /*++
  631. Routine Description:
  632. This functions determines how many bytes would be needed to represent
  633. the specified ANSI source string in Unicode string (not counting the
  634. null terminator)
  635. The translation is done with respect to the ANSI Code Page (ACP) installed
  636. at boot time. Single byte characters in the range 0x00 - 0x7f are simply
  637. zero extended as a performance enhancement. In some far eastern code pages
  638. 0x5c is defined as the Yen sign. For system translation we always want to
  639. consider 0x5c to be the backslash character. We get this for free by zero
  640. extending.
  641. NOTE: This routine only supports precomposed Unicode characters.
  642. Arguments:
  643. BytesInUnicodeString - Returns the number of bytes a Unicode translation
  644. of the ANSI string pointed to by MultiByteString would contain.
  645. MultiByteString - Supplies the ansi source string whose Unicode length
  646. is to be calculated.
  647. BytesInMultiByteString - The number of bytes in the string pointed to
  648. by MultiByteString.
  649. Return Value:
  650. SUCCESS - The conversion was successful
  651. --*/
  652. {
  653. ULONG cbUnicode = 0;
  654. RTL_PAGED_CODE();
  655. if (NlsMbCodePageTag) {
  656. //
  657. // The ACP is a multibyte code page. Check each character
  658. // to see if it is a lead byte before doing the translation.
  659. //
  660. while (BytesInMultiByteString--) {
  661. if (NlsLeadByteInfo[*(PUCHAR)MultiByteString++]) {
  662. //
  663. // Lead byte - translate the trail byte using the table
  664. // that corresponds to this lead byte. NOTE: make sure
  665. // we have a trail byte to convert.
  666. //
  667. if (BytesInMultiByteString == 0) {
  668. //
  669. // RtlMultibyteToUnicodeN() uses the unicode
  670. // default character if the last multibyte
  671. // character is a lead byte.
  672. //
  673. cbUnicode += sizeof(WCHAR);
  674. break;
  675. } else {
  676. BytesInMultiByteString--;
  677. MultiByteString++;
  678. }
  679. }
  680. cbUnicode += sizeof(WCHAR);
  681. }
  682. *BytesInUnicodeString = cbUnicode;
  683. } else {
  684. //
  685. // The ACP is a single byte code page.
  686. //
  687. *BytesInUnicodeString = BytesInMultiByteString * sizeof(WCHAR);
  688. }
  689. return STATUS_SUCCESS;
  690. }
  691. NTSTATUS
  692. RtlUnicodeToMultiByteSize(
  693. OUT PULONG BytesInMultiByteString,
  694. IN PWCH UnicodeString,
  695. IN ULONG BytesInUnicodeString)
  696. /*++
  697. Routine Description:
  698. This functions determines how many bytes would be needed to represent
  699. the specified Unicode source string as an ANSI string (not counting the
  700. null terminator)
  701. Arguments:
  702. BytesInMultiByteString - Returns the number of bytes an ANSI translation
  703. of the Unicode string pointed to by UnicodeString would contain.
  704. UnicodeString - Supplies the unicode source string whose ANSI length
  705. is to be calculated.
  706. BytesInUnicodeString - The number of bytes in the the string pointed to by
  707. UnicodeString.
  708. Return Value:
  709. SUCCESS - The conversion was successful
  710. !SUCCESS - The conversion failed. A unicode character was encountered
  711. that has no translation for the current ANSI Code Page (ACP).
  712. --*/
  713. {
  714. ULONG cbMultiByte = 0;
  715. ULONG CharsInUnicodeString;
  716. RTL_PAGED_CODE();
  717. /*
  718. * convert from bytes to chars for easier loop handling.
  719. */
  720. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  721. if (NlsMbCodePageTag) {
  722. USHORT MbChar;
  723. while (CharsInUnicodeString--) {
  724. MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
  725. if (HIBYTE(MbChar) == 0) {
  726. cbMultiByte++ ;
  727. } else {
  728. cbMultiByte += 2;
  729. }
  730. }
  731. *BytesInMultiByteString = cbMultiByte;
  732. }
  733. else {
  734. *BytesInMultiByteString = CharsInUnicodeString;
  735. }
  736. return STATUS_SUCCESS;
  737. }
  738. NTSTATUS
  739. RtlUnicodeToMultiByteN(
  740. OUT PCH MultiByteString,
  741. IN ULONG MaxBytesInMultiByteString,
  742. OUT PULONG BytesInMultiByteString OPTIONAL,
  743. IN PWCH UnicodeString,
  744. IN ULONG BytesInUnicodeString)
  745. /*++
  746. Routine Description:
  747. This functions converts the specified unicode source string into an
  748. ansi string. The translation is done with respect to the
  749. ANSI Code Page (ACP) loaded at boot time.
  750. Arguments:
  751. MultiByteString - Returns an ansi string that is equivalent to the
  752. unicode source string. If the translation can not be done,
  753. an error is returned.
  754. MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
  755. written to MultiByteString. If this causes MultiByteString to be a
  756. truncated equivalent of UnicodeString, no error condition results.
  757. BytesInMultiByteString - Returns the number of bytes in the returned
  758. ansi string pointed to by MultiByteString.
  759. UnicodeString - Supplies the unicode source string that is to be
  760. converted to ansi.
  761. BytesInUnicodeString - The number of bytes in the the string pointed to by
  762. UnicodeString.
  763. Return Value:
  764. SUCCESS - The conversion was successful
  765. --*/
  766. {
  767. ULONG TmpCount;
  768. ULONG LoopCount;
  769. PCH TranslateTable;
  770. ULONG CharsInUnicodeString;
  771. RTL_PAGED_CODE();
  772. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  773. //
  774. // Convert Unicode byte count to character count. Byte count of
  775. // multibyte string is equivalent to character count.
  776. //
  777. if (!NlsMbCodePageTag) {
  778. LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
  779. CharsInUnicodeString : MaxBytesInMultiByteString;
  780. if (ARGUMENT_PRESENT(BytesInMultiByteString))
  781. *BytesInMultiByteString = LoopCount;
  782. TranslateTable = NlsUnicodeToAnsiData; // used to help the mips compiler
  783. TmpCount = LoopCount & 0x0F;
  784. UnicodeString += TmpCount;
  785. MultiByteString += TmpCount;
  786. do
  787. {
  788. switch( TmpCount ) {
  789. default:
  790. UnicodeString += 0x10;
  791. MultiByteString += 0x10;
  792. MultiByteString[-0x10] = TranslateTable[UnicodeString[-0x10]];
  793. case 0x0F:
  794. MultiByteString[-0x0F] = TranslateTable[UnicodeString[-0x0F]];
  795. case 0x0E:
  796. MultiByteString[-0x0E] = TranslateTable[UnicodeString[-0x0E]];
  797. case 0x0D:
  798. MultiByteString[-0x0D] = TranslateTable[UnicodeString[-0x0D]];
  799. case 0x0C:
  800. MultiByteString[-0x0C] = TranslateTable[UnicodeString[-0x0C]];
  801. case 0x0B:
  802. MultiByteString[-0x0B] = TranslateTable[UnicodeString[-0x0B]];
  803. case 0x0A:
  804. MultiByteString[-0x0A] = TranslateTable[UnicodeString[-0x0A]];
  805. case 0x09:
  806. MultiByteString[-0x09] = TranslateTable[UnicodeString[-0x09]];
  807. case 0x08:
  808. MultiByteString[-0x08] = TranslateTable[UnicodeString[-0x08]];
  809. case 0x07:
  810. MultiByteString[-0x07] = TranslateTable[UnicodeString[-0x07]];
  811. case 0x06:
  812. MultiByteString[-0x06] = TranslateTable[UnicodeString[-0x06]];
  813. case 0x05:
  814. MultiByteString[-0x05] = TranslateTable[UnicodeString[-0x05]];
  815. case 0x04:
  816. MultiByteString[-0x04] = TranslateTable[UnicodeString[-0x04]];
  817. case 0x03:
  818. MultiByteString[-0x03] = TranslateTable[UnicodeString[-0x03]];
  819. case 0x02:
  820. MultiByteString[-0x02] = TranslateTable[UnicodeString[-0x02]];
  821. case 0x01:
  822. MultiByteString[-0x01] = TranslateTable[UnicodeString[-0x01]];
  823. case 0x00:
  824. ;
  825. }
  826. LoopCount -= TmpCount;
  827. TmpCount = 0x10;
  828. } while ( LoopCount > 0 );
  829. /* end of copy... */
  830. } else {
  831. USHORT MbChar;
  832. PCH MultiByteStringAnchor = MultiByteString;
  833. while ( CharsInUnicodeString && MaxBytesInMultiByteString ) {
  834. MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
  835. if (HIBYTE(MbChar) != 0) {
  836. //
  837. // Need at least 2 bytes to copy a double byte char.
  838. // Don't want to truncate in the middle of a DBCS char.
  839. //
  840. if (MaxBytesInMultiByteString-- < 2) {
  841. break;
  842. }
  843. *MultiByteString++ = HIBYTE(MbChar); // lead byte
  844. }
  845. *MultiByteString++ = LOBYTE(MbChar);
  846. MaxBytesInMultiByteString--;
  847. CharsInUnicodeString--;
  848. }
  849. if (ARGUMENT_PRESENT(BytesInMultiByteString))
  850. *BytesInMultiByteString = (ULONG)(MultiByteString - MultiByteStringAnchor);
  851. }
  852. return STATUS_SUCCESS;
  853. }
  854. NTSTATUS
  855. RtlUpcaseUnicodeToMultiByteN(
  856. OUT PCH MultiByteString,
  857. IN ULONG MaxBytesInMultiByteString,
  858. OUT PULONG BytesInMultiByteString OPTIONAL,
  859. IN PWCH UnicodeString,
  860. IN ULONG BytesInUnicodeString)
  861. /*++
  862. Routine Description:
  863. This functions upper cases the specified unicode source string and
  864. converts it into an ansi string. The translation is done with respect
  865. to the ANSI Code Page (ACP) loaded at boot time.
  866. Arguments:
  867. MultiByteString - Returns an ansi string that is equivalent to the
  868. upper case of the unicode source string. If the translation can
  869. not be done, an error is returned.
  870. MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
  871. written to MultiByteString. If this causes MultiByteString to be a
  872. truncated equivalent of UnicodeString, no error condition results.
  873. BytesInMultiByteString - Returns the number of bytes in the returned
  874. ansi string pointed to by MultiByteString.
  875. UnicodeString - Supplies the unicode source string that is to be
  876. converted to ansi.
  877. BytesInUnicodeString - The number of bytes in the the string pointed to by
  878. UnicodeString.
  879. Return Value:
  880. SUCCESS - The conversion was successful
  881. --*/
  882. {
  883. ULONG TmpCount;
  884. ULONG LoopCount;
  885. PCH TranslateTable;
  886. ULONG CharsInUnicodeString;
  887. UCHAR SbChar;
  888. WCHAR UnicodeChar;
  889. RTL_PAGED_CODE();
  890. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  891. //
  892. // Convert Unicode byte count to character count. Byte count of
  893. // multibyte string is equivalent to character count.
  894. //
  895. if (!NlsMbCodePageTag) {
  896. LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
  897. CharsInUnicodeString : MaxBytesInMultiByteString;
  898. if (ARGUMENT_PRESENT(BytesInMultiByteString))
  899. *BytesInMultiByteString = LoopCount;
  900. TranslateTable = NlsUnicodeToAnsiData; // used to help the mips compiler
  901. TmpCount = LoopCount & 0x0F;
  902. UnicodeString += TmpCount;
  903. MultiByteString += TmpCount;
  904. do
  905. {
  906. //
  907. // Convert to ANSI and back to Unicode before upper casing
  908. // to ensure the visual best fits are converted and
  909. // upper cased properly.
  910. //
  911. switch( TmpCount ) {
  912. default:
  913. UnicodeString += 0x10;
  914. MultiByteString += 0x10;
  915. SbChar = TranslateTable[UnicodeString[-0x10]];
  916. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  917. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  918. MultiByteString[-0x10] = TranslateTable[UnicodeChar];
  919. case 0x0F:
  920. SbChar = TranslateTable[UnicodeString[-0x0F]];
  921. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  922. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  923. MultiByteString[-0x0F] = TranslateTable[UnicodeChar];
  924. case 0x0E:
  925. SbChar = TranslateTable[UnicodeString[-0x0E]];
  926. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  927. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  928. MultiByteString[-0x0E] = TranslateTable[UnicodeChar];
  929. case 0x0D:
  930. SbChar = TranslateTable[UnicodeString[-0x0D]];
  931. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  932. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  933. MultiByteString[-0x0D] = TranslateTable[UnicodeChar];
  934. case 0x0C:
  935. SbChar = TranslateTable[UnicodeString[-0x0C]];
  936. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  937. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  938. MultiByteString[-0x0C] = TranslateTable[UnicodeChar];
  939. case 0x0B:
  940. SbChar = TranslateTable[UnicodeString[-0x0B]];
  941. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  942. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  943. MultiByteString[-0x0B] = TranslateTable[UnicodeChar];
  944. case 0x0A:
  945. SbChar = TranslateTable[UnicodeString[-0x0A]];
  946. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  947. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  948. MultiByteString[-0x0A] = TranslateTable[UnicodeChar];
  949. case 0x09:
  950. SbChar = TranslateTable[UnicodeString[-0x09]];
  951. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  952. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  953. MultiByteString[-0x09] = TranslateTable[UnicodeChar];
  954. case 0x08:
  955. SbChar = TranslateTable[UnicodeString[-0x08]];
  956. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  957. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  958. MultiByteString[-0x08] = TranslateTable[UnicodeChar];
  959. case 0x07:
  960. SbChar = TranslateTable[UnicodeString[-0x07]];
  961. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  962. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  963. MultiByteString[-0x07] = TranslateTable[UnicodeChar];
  964. case 0x06:
  965. SbChar = TranslateTable[UnicodeString[-0x06]];
  966. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  967. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  968. MultiByteString[-0x06] = TranslateTable[UnicodeChar];
  969. case 0x05:
  970. SbChar = TranslateTable[UnicodeString[-0x05]];
  971. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  972. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  973. MultiByteString[-0x05] = TranslateTable[UnicodeChar];
  974. case 0x04:
  975. SbChar = TranslateTable[UnicodeString[-0x04]];
  976. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  977. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  978. MultiByteString[-0x04] = TranslateTable[UnicodeChar];
  979. case 0x03:
  980. SbChar = TranslateTable[UnicodeString[-0x03]];
  981. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  982. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  983. MultiByteString[-0x03] = TranslateTable[UnicodeChar];
  984. case 0x02:
  985. SbChar = TranslateTable[UnicodeString[-0x02]];
  986. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  987. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  988. MultiByteString[-0x02] = TranslateTable[UnicodeChar];
  989. case 0x01:
  990. SbChar = TranslateTable[UnicodeString[-0x01]];
  991. UnicodeChar = NlsAnsiToUnicodeData[SbChar];
  992. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  993. MultiByteString[-0x01] = TranslateTable[UnicodeChar];
  994. case 0x00:
  995. ;
  996. }
  997. LoopCount -= TmpCount;
  998. TmpCount = 0x10;
  999. } while ( LoopCount > 0 );
  1000. /* end of copy... */
  1001. } else {
  1002. USHORT MbChar;
  1003. register USHORT Entry;
  1004. PCH MultiByteStringAnchor = MultiByteString;
  1005. while ( CharsInUnicodeString && MaxBytesInMultiByteString ) {
  1006. //
  1007. // Convert to ANSI and back to Unicode before upper casing
  1008. // to ensure the visual best fits are converted and
  1009. // upper cased properly.
  1010. //
  1011. MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
  1012. if ( NlsLeadByteInfo[HIBYTE(MbChar)] ) {
  1013. //
  1014. // Lead byte - translate the trail byte using the table
  1015. // that corresponds to this lead byte.
  1016. //
  1017. Entry = NlsLeadByteInfo[HIBYTE(MbChar)];
  1018. UnicodeChar = (WCHAR)NlsMbAnsiCodePageTables[ Entry + LOBYTE(MbChar) ];
  1019. } else {
  1020. //
  1021. // Single byte character.
  1022. //
  1023. UnicodeChar = NlsAnsiToUnicodeData[LOBYTE(MbChar)];
  1024. }
  1025. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1026. MbChar = NlsUnicodeToMbAnsiData[UnicodeChar];
  1027. if (HIBYTE(MbChar) != 0) {
  1028. //
  1029. // Need at least 2 bytes to copy a double byte char.
  1030. // Don't want to truncate in the middle of a DBCS char.
  1031. //
  1032. if (MaxBytesInMultiByteString-- < 2) {
  1033. break;
  1034. }
  1035. *MultiByteString++ = HIBYTE(MbChar); // lead byte
  1036. }
  1037. *MultiByteString++ = LOBYTE(MbChar);
  1038. MaxBytesInMultiByteString--;
  1039. CharsInUnicodeString--;
  1040. }
  1041. if (ARGUMENT_PRESENT(BytesInMultiByteString))
  1042. *BytesInMultiByteString = (ULONG)(MultiByteString - MultiByteStringAnchor);
  1043. }
  1044. return STATUS_SUCCESS;
  1045. }
  1046. NTSTATUS
  1047. RtlUnicodeToOemN(
  1048. OUT PCH OemString,
  1049. IN ULONG MaxBytesInOemString,
  1050. OUT PULONG BytesInOemString OPTIONAL,
  1051. IN PWCH UnicodeString,
  1052. IN ULONG BytesInUnicodeString)
  1053. /*++
  1054. Routine Description:
  1055. This functions converts the specified unicode source string into an
  1056. oem string. The translation is done with respect to the OEM Code
  1057. Page (OCP) loaded at boot time.
  1058. Arguments:
  1059. OemString - Returns an oem string that is equivalent to the
  1060. unicode source string. If the translation can not be done,
  1061. an error is returned.
  1062. MaxBytesInOemString - Supplies the maximum number of bytes to be
  1063. written to OemString. If this causes OemString to be a
  1064. truncated equivalent of UnicodeString, no error condition results.
  1065. BytesInOemString - Returns the number of bytes in the returned
  1066. oem string pointed to by OemString.
  1067. UnicodeString - Supplies the unicode source string that is to be
  1068. converted to oem.
  1069. BytesInUnicodeString - The number of bytes in the the string pointed to by
  1070. UnicodeString.
  1071. Return Value:
  1072. SUCCESS - The conversion was successful
  1073. STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
  1074. the whole Oem string. It was converted correct to the point though.
  1075. --*/
  1076. {
  1077. ULONG TmpCount;
  1078. ULONG LoopCount;
  1079. PCH TranslateTable;
  1080. ULONG CharsInUnicodeString;
  1081. RTL_PAGED_CODE();
  1082. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  1083. //
  1084. // Convert Unicode byte count to character count. Byte count of
  1085. // multibyte string is equivalent to character count.
  1086. //
  1087. if (!NlsMbOemCodePageTag) {
  1088. LoopCount = (CharsInUnicodeString < MaxBytesInOemString) ?
  1089. CharsInUnicodeString : MaxBytesInOemString;
  1090. if (ARGUMENT_PRESENT(BytesInOemString))
  1091. *BytesInOemString = LoopCount;
  1092. TranslateTable = NlsUnicodeToOemData; // used to help the mips compiler
  1093. TmpCount = LoopCount & 0x0F;
  1094. UnicodeString += TmpCount;
  1095. OemString += TmpCount;
  1096. do
  1097. {
  1098. switch( TmpCount ) {
  1099. default:
  1100. UnicodeString += 0x10;
  1101. OemString += 0x10;
  1102. OemString[-0x10] = TranslateTable[UnicodeString[-0x10]];
  1103. case 0x0F:
  1104. OemString[-0x0F] = TranslateTable[UnicodeString[-0x0F]];
  1105. case 0x0E:
  1106. OemString[-0x0E] = TranslateTable[UnicodeString[-0x0E]];
  1107. case 0x0D:
  1108. OemString[-0x0D] = TranslateTable[UnicodeString[-0x0D]];
  1109. case 0x0C:
  1110. OemString[-0x0C] = TranslateTable[UnicodeString[-0x0C]];
  1111. case 0x0B:
  1112. OemString[-0x0B] = TranslateTable[UnicodeString[-0x0B]];
  1113. case 0x0A:
  1114. OemString[-0x0A] = TranslateTable[UnicodeString[-0x0A]];
  1115. case 0x09:
  1116. OemString[-0x09] = TranslateTable[UnicodeString[-0x09]];
  1117. case 0x08:
  1118. OemString[-0x08] = TranslateTable[UnicodeString[-0x08]];
  1119. case 0x07:
  1120. OemString[-0x07] = TranslateTable[UnicodeString[-0x07]];
  1121. case 0x06:
  1122. OemString[-0x06] = TranslateTable[UnicodeString[-0x06]];
  1123. case 0x05:
  1124. OemString[-0x05] = TranslateTable[UnicodeString[-0x05]];
  1125. case 0x04:
  1126. OemString[-0x04] = TranslateTable[UnicodeString[-0x04]];
  1127. case 0x03:
  1128. OemString[-0x03] = TranslateTable[UnicodeString[-0x03]];
  1129. case 0x02:
  1130. OemString[-0x02] = TranslateTable[UnicodeString[-0x02]];
  1131. case 0x01:
  1132. OemString[-0x01] = TranslateTable[UnicodeString[-0x01]];
  1133. case 0x00:
  1134. ;
  1135. }
  1136. LoopCount -= TmpCount;
  1137. TmpCount = 0x10;
  1138. } while ( LoopCount > 0 );
  1139. /* end of copy... */
  1140. } else {
  1141. register USHORT MbChar;
  1142. PCH OemStringAnchor = OemString;
  1143. while ( CharsInUnicodeString && MaxBytesInOemString ) {
  1144. MbChar = NlsUnicodeToMbOemData[ *UnicodeString++ ];
  1145. if (HIBYTE(MbChar) != 0) {
  1146. //
  1147. // Need at least 2 bytes to copy a double byte char.
  1148. // Don't want to truncate in the middle of a DBCS char.
  1149. //
  1150. if (MaxBytesInOemString-- < 2) {
  1151. break;
  1152. }
  1153. *OemString++ = HIBYTE(MbChar); // lead byte
  1154. }
  1155. *OemString++ = LOBYTE(MbChar);
  1156. MaxBytesInOemString--;
  1157. CharsInUnicodeString--;
  1158. }
  1159. if (ARGUMENT_PRESENT(BytesInOemString))
  1160. *BytesInOemString = (ULONG)(OemString - OemStringAnchor);
  1161. }
  1162. //
  1163. // Check if we were able to use all of the source Unicode String
  1164. //
  1165. return ( CharsInUnicodeString <= MaxBytesInOemString ) ?
  1166. STATUS_SUCCESS :
  1167. STATUS_BUFFER_OVERFLOW;
  1168. }
  1169. NTSTATUS
  1170. RtlUpcaseUnicodeToOemN(
  1171. OUT PCH OemString,
  1172. IN ULONG MaxBytesInOemString,
  1173. OUT PULONG BytesInOemString OPTIONAL,
  1174. IN PWCH UnicodeString,
  1175. IN ULONG BytesInUnicodeString)
  1176. /*++
  1177. Routine Description:
  1178. This functions upper cases the specified unicode source string and
  1179. converts it into an oem string. The translation is done with respect
  1180. to the OEM Code Page (OCP) loaded at boot time.
  1181. Arguments:
  1182. OemString - Returns an oem string that is equivalent to the upper
  1183. case of the unicode source string. If the translation can not
  1184. be done, an error is returned.
  1185. MaxBytesInOemString - Supplies the maximum number of bytes to be
  1186. written to OemString. If this causes OemString to be a
  1187. truncated equivalent of UnicodeString, no error condition results.
  1188. BytesInOemString - Returns the number of bytes in the returned
  1189. oem string pointed to by OemString.
  1190. UnicodeString - Supplies the unicode source string that is to be
  1191. converted to oem.
  1192. BytesInUnicodeString - The number of bytes in the the string pointed
  1193. to by UnicodeString.
  1194. Return Value:
  1195. SUCCESS - The conversion was successful
  1196. STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to
  1197. hold the whole Oem string. It was converted correctly to that
  1198. point, though.
  1199. --*/
  1200. {
  1201. ULONG TmpCount;
  1202. ULONG LoopCount;
  1203. PCH TranslateTable;
  1204. ULONG CharsInUnicodeString;
  1205. UCHAR SbChar;
  1206. WCHAR UnicodeChar;
  1207. RTL_PAGED_CODE();
  1208. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  1209. //
  1210. // Convert Unicode byte count to character count. Byte count of
  1211. // multibyte string is equivalent to character count.
  1212. //
  1213. if (!NlsMbOemCodePageTag) {
  1214. LoopCount = (CharsInUnicodeString < MaxBytesInOemString) ?
  1215. CharsInUnicodeString : MaxBytesInOemString;
  1216. if (ARGUMENT_PRESENT(BytesInOemString))
  1217. *BytesInOemString = LoopCount;
  1218. TranslateTable = NlsUnicodeToOemData; // used to help the mips compiler
  1219. TmpCount = LoopCount & 0x0F;
  1220. UnicodeString += TmpCount;
  1221. OemString += TmpCount;
  1222. do
  1223. {
  1224. //
  1225. // Convert to OEM and back to Unicode before upper casing
  1226. // to ensure the visual best fits are converted and
  1227. // upper cased properly.
  1228. //
  1229. switch( TmpCount ) {
  1230. default:
  1231. UnicodeString += 0x10;
  1232. OemString += 0x10;
  1233. SbChar = TranslateTable[UnicodeString[-0x10]];
  1234. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1235. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1236. OemString[-0x10] = TranslateTable[UnicodeChar];
  1237. case 0x0F:
  1238. SbChar = TranslateTable[UnicodeString[-0x0F]];
  1239. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1240. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1241. OemString[-0x0F] = TranslateTable[UnicodeChar];
  1242. case 0x0E:
  1243. SbChar = TranslateTable[UnicodeString[-0x0E]];
  1244. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1245. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1246. OemString[-0x0E] = TranslateTable[UnicodeChar];
  1247. case 0x0D:
  1248. SbChar = TranslateTable[UnicodeString[-0x0D]];
  1249. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1250. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1251. OemString[-0x0D] = TranslateTable[UnicodeChar];
  1252. case 0x0C:
  1253. SbChar = TranslateTable[UnicodeString[-0x0C]];
  1254. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1255. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1256. OemString[-0x0C] = TranslateTable[UnicodeChar];
  1257. case 0x0B:
  1258. SbChar = TranslateTable[UnicodeString[-0x0B]];
  1259. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1260. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1261. OemString[-0x0B] = TranslateTable[UnicodeChar];
  1262. case 0x0A:
  1263. SbChar = TranslateTable[UnicodeString[-0x0A]];
  1264. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1265. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1266. OemString[-0x0A] = TranslateTable[UnicodeChar];
  1267. case 0x09:
  1268. SbChar = TranslateTable[UnicodeString[-0x09]];
  1269. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1270. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1271. OemString[-0x09] = TranslateTable[UnicodeChar];
  1272. case 0x08:
  1273. SbChar = TranslateTable[UnicodeString[-0x08]];
  1274. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1275. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1276. OemString[-0x08] = TranslateTable[UnicodeChar];
  1277. case 0x07:
  1278. SbChar = TranslateTable[UnicodeString[-0x07]];
  1279. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1280. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1281. OemString[-0x07] = TranslateTable[UnicodeChar];
  1282. case 0x06:
  1283. SbChar = TranslateTable[UnicodeString[-0x06]];
  1284. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1285. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1286. OemString[-0x06] = TranslateTable[UnicodeChar];
  1287. case 0x05:
  1288. SbChar = TranslateTable[UnicodeString[-0x05]];
  1289. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1290. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1291. OemString[-0x05] = TranslateTable[UnicodeChar];
  1292. case 0x04:
  1293. SbChar = TranslateTable[UnicodeString[-0x04]];
  1294. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1295. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1296. OemString[-0x04] = TranslateTable[UnicodeChar];
  1297. case 0x03:
  1298. SbChar = TranslateTable[UnicodeString[-0x03]];
  1299. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1300. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1301. OemString[-0x03] = TranslateTable[UnicodeChar];
  1302. case 0x02:
  1303. SbChar = TranslateTable[UnicodeString[-0x02]];
  1304. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1305. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1306. OemString[-0x02] = TranslateTable[UnicodeChar];
  1307. case 0x01:
  1308. SbChar = TranslateTable[UnicodeString[-0x01]];
  1309. UnicodeChar = NlsOemToUnicodeData[SbChar];
  1310. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1311. OemString[-0x01] = TranslateTable[UnicodeChar];
  1312. case 0x00:
  1313. ;
  1314. }
  1315. LoopCount -= TmpCount;
  1316. TmpCount = 0x10;
  1317. } while ( LoopCount > 0 );
  1318. /* end of copy... */
  1319. } else {
  1320. USHORT MbChar;
  1321. register USHORT Entry;
  1322. PCH OemStringAnchor = OemString;
  1323. while ( CharsInUnicodeString && MaxBytesInOemString ) {
  1324. //
  1325. // Convert to OEM and back to Unicode before upper casing
  1326. // to ensure the visual best fits are converted and
  1327. // upper cased properly.
  1328. //
  1329. MbChar = NlsUnicodeToMbOemData[ *UnicodeString++ ];
  1330. if (NlsOemLeadByteInfo[HIBYTE(MbChar)]) {
  1331. //
  1332. // Lead byte - translate the trail byte using the table
  1333. // that corresponds to this lead byte.
  1334. //
  1335. Entry = NlsOemLeadByteInfo[HIBYTE(MbChar)];
  1336. UnicodeChar = (WCHAR)NlsMbOemCodePageTables[ Entry + LOBYTE(MbChar) ];
  1337. } else {
  1338. //
  1339. // Single byte character.
  1340. //
  1341. UnicodeChar = NlsOemToUnicodeData[LOBYTE(MbChar)];
  1342. }
  1343. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1344. MbChar = NlsUnicodeToMbOemData[UnicodeChar];
  1345. if (HIBYTE(MbChar) != 0) {
  1346. //
  1347. // Need at least 2 bytes to copy a double byte char.
  1348. // Don't want to truncate in the middle of a DBCS char.
  1349. //
  1350. if (MaxBytesInOemString-- < 2) {
  1351. break;
  1352. }
  1353. *OemString++ = HIBYTE(MbChar); // lead byte
  1354. }
  1355. *OemString++ = LOBYTE(MbChar);
  1356. MaxBytesInOemString--;
  1357. CharsInUnicodeString--;
  1358. }
  1359. if (ARGUMENT_PRESENT(BytesInOemString))
  1360. *BytesInOemString = (ULONG)(OemString - OemStringAnchor);
  1361. }
  1362. //
  1363. // Check if we were able to use all of the source Unicode String
  1364. //
  1365. return ( CharsInUnicodeString <= MaxBytesInOemString ) ?
  1366. STATUS_SUCCESS :
  1367. STATUS_BUFFER_OVERFLOW;
  1368. }
  1369. BOOLEAN
  1370. RtlpDidUnicodeToOemWork(
  1371. IN PCOEM_STRING OemString,
  1372. IN PCUNICODE_STRING UnicodeString
  1373. )
  1374. /*++
  1375. Routine Description:
  1376. This function looks for the default character in the Oem string, making
  1377. sure it was not a correct translation from the Unicode source string.
  1378. This allows us to test whether or not a translation was really successful.
  1379. Arguments:
  1380. OemString - The result of conversion from the unicode string.
  1381. UnicodeString - The source of the Oem string.
  1382. Return Value:
  1383. TRUE if the Unicode to Oem translation caused no default characters to be
  1384. inserted. FALSE otherwise.
  1385. --*/
  1386. {
  1387. ULONG OemOffset;
  1388. BOOLEAN Result = TRUE;
  1389. RTL_PAGED_CODE();
  1390. if (!NlsMbOemCodePageTag) {
  1391. for (OemOffset = 0;
  1392. OemOffset < OemString->Length;
  1393. OemOffset += 1) {
  1394. if ((OemString->Buffer[OemOffset] == (UCHAR)OemDefaultChar) &&
  1395. (UnicodeString->Buffer[OemOffset] != OemTransUniDefaultChar)) {
  1396. Result = FALSE;
  1397. break;
  1398. }
  1399. }
  1400. } else {
  1401. ULONG UnicodeOffset;
  1402. for (OemOffset = 0, UnicodeOffset = 0;
  1403. OemOffset < OemString->Length;
  1404. OemOffset += 1, UnicodeOffset += 1) {
  1405. //
  1406. // If we landed on a DBCS character handle it accordingly
  1407. //
  1408. if (NlsOemLeadByteInfo[(UCHAR)OemString->Buffer[OemOffset]]) {
  1409. USHORT DbcsChar;
  1410. ASSERT( OemOffset + 1 < OemString->Length );
  1411. DbcsChar = (OemString->Buffer[OemOffset] << 8) + (UCHAR)OemString->Buffer[OemOffset+1];
  1412. OemOffset++;
  1413. if ((DbcsChar == OemDefaultChar) &&
  1414. (UnicodeString->Buffer[UnicodeOffset] != OemTransUniDefaultChar)) {
  1415. Result = FALSE;
  1416. break;
  1417. }
  1418. continue;
  1419. }
  1420. if ((OemString->Buffer[OemOffset] == (UCHAR)OemDefaultChar) &&
  1421. (UnicodeString->Buffer[UnicodeOffset] != OemTransUniDefaultChar)) {
  1422. Result = FALSE;
  1423. break;
  1424. }
  1425. }
  1426. }
  1427. return Result;
  1428. }
  1429. NTSTATUS
  1430. RtlCustomCPToUnicodeN(
  1431. IN PCPTABLEINFO CustomCP,
  1432. OUT PWCH UnicodeString,
  1433. IN ULONG MaxBytesInUnicodeString,
  1434. OUT PULONG BytesInUnicodeString OPTIONAL,
  1435. IN PCH CustomCPString,
  1436. IN ULONG BytesInCustomCPString)
  1437. /*++
  1438. Routine Description:
  1439. This functions converts the specified CustomCP source string into a
  1440. Unicode string. The translation is done with respect to the
  1441. CustomCP Code Page specified. Single byte characters
  1442. in the range 0x00 - 0x7f are simply zero extended as a performance
  1443. enhancement. In some far eastern code pages 0x5c is defined as the
  1444. Yen sign. For system translation we always want to consider 0x5c
  1445. to be the backslash character. We get this for free by zero extending.
  1446. NOTE: This routine only supports precomposed Unicode characters.
  1447. Arguments:
  1448. CustomCP - Supplies the address of the code page that translations
  1449. are done relative to
  1450. UnicodeString - Returns a unicode string that is equivalent to
  1451. the CustomCP source string.
  1452. MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
  1453. written to UnicodeString. If this causes UnicodeString to be a
  1454. truncated equivalent of CustomCPString, no error condition results.
  1455. BytesInUnicodeString - Returns the number of bytes in the returned
  1456. unicode string pointed to by UnicodeString.
  1457. CustomCPString - Supplies the CustomCP source string that is to be
  1458. converted to unicode.
  1459. BytesInCustomCPString - The number of bytes in the string pointed to
  1460. by CustomCPString.
  1461. Return Value:
  1462. SUCCESS - The conversion was successful
  1463. STATUS_ILLEGAL_CHARACTER - The final CustomCP character was illegal
  1464. STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
  1465. the whole CustomCP string. It was converted correct to the point though.
  1466. --*/
  1467. {
  1468. ULONG LoopCount;
  1469. PUSHORT TranslateTable;
  1470. ULONG MaxCharsInUnicodeString;
  1471. RTL_PAGED_CODE();
  1472. MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
  1473. if (!(CustomCP->DBCSCodePage)) {
  1474. //
  1475. // The Custom CP is a single byte code page.
  1476. //
  1477. LoopCount = (MaxCharsInUnicodeString < BytesInCustomCPString) ?
  1478. MaxCharsInUnicodeString : BytesInCustomCPString;
  1479. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  1480. *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
  1481. TranslateTable = CustomCP->MultiByteTable;
  1482. quick_copy:
  1483. switch( LoopCount ) {
  1484. default:
  1485. UnicodeString[0x0F] = TranslateTable[(UCHAR)CustomCPString[0x0F]];
  1486. case 0x0F:
  1487. UnicodeString[0x0E] = TranslateTable[(UCHAR)CustomCPString[0x0E]];
  1488. case 0x0E:
  1489. UnicodeString[0x0D] = TranslateTable[(UCHAR)CustomCPString[0x0D]];
  1490. case 0x0D:
  1491. UnicodeString[0x0C] = TranslateTable[(UCHAR)CustomCPString[0x0C]];
  1492. case 0x0C:
  1493. UnicodeString[0x0B] = TranslateTable[(UCHAR)CustomCPString[0x0B]];
  1494. case 0x0B:
  1495. UnicodeString[0x0A] = TranslateTable[(UCHAR)CustomCPString[0x0A]];
  1496. case 0x0A:
  1497. UnicodeString[0x09] = TranslateTable[(UCHAR)CustomCPString[0x09]];
  1498. case 0x09:
  1499. UnicodeString[0x08] = TranslateTable[(UCHAR)CustomCPString[0x08]];
  1500. case 0x08:
  1501. UnicodeString[0x07] = TranslateTable[(UCHAR)CustomCPString[0x07]];
  1502. case 0x07:
  1503. UnicodeString[0x06] = TranslateTable[(UCHAR)CustomCPString[0x06]];
  1504. case 0x06:
  1505. UnicodeString[0x05] = TranslateTable[(UCHAR)CustomCPString[0x05]];
  1506. case 0x05:
  1507. UnicodeString[0x04] = TranslateTable[(UCHAR)CustomCPString[0x04]];
  1508. case 0x04:
  1509. UnicodeString[0x03] = TranslateTable[(UCHAR)CustomCPString[0x03]];
  1510. case 0x03:
  1511. UnicodeString[0x02] = TranslateTable[(UCHAR)CustomCPString[0x02]];
  1512. case 0x02:
  1513. UnicodeString[0x01] = TranslateTable[(UCHAR)CustomCPString[0x01]];
  1514. case 0x01:
  1515. UnicodeString[0x00] = TranslateTable[(UCHAR)CustomCPString[0x00]];
  1516. case 0x00:
  1517. ;
  1518. }
  1519. if ( LoopCount > 0x10 ) {
  1520. LoopCount -= 0x10;
  1521. CustomCPString += 0x10;
  1522. UnicodeString += 0x10;
  1523. goto quick_copy;
  1524. }
  1525. /* end of copy... */
  1526. } else {
  1527. register USHORT Entry;
  1528. PWCH UnicodeStringAnchor = UnicodeString;
  1529. PUSHORT NlsCustomLeadByteInfo = CustomCP->DBCSOffsets;
  1530. //
  1531. // The CP is a multibyte code page. Check each character
  1532. // to see if it is a lead byte before doing the translation.
  1533. //
  1534. TranslateTable = (PUSHORT)(CustomCP->DBCSOffsets);
  1535. while (MaxCharsInUnicodeString && BytesInCustomCPString) {
  1536. MaxCharsInUnicodeString--;
  1537. BytesInCustomCPString--;
  1538. if (NlsCustomLeadByteInfo[*(PUCHAR)CustomCPString]) {
  1539. //
  1540. // Lead byte - Make sure there is a trail byte. If not,
  1541. // pass back a space rather than an error. Some 3.x
  1542. // applications pass incorrect strings and don't expect
  1543. // to get an error.
  1544. //
  1545. if (BytesInCustomCPString == 0)
  1546. {
  1547. *UnicodeString++ = UnicodeNull;
  1548. break;
  1549. }
  1550. //
  1551. // Get the unicode character.
  1552. //
  1553. Entry = NlsCustomLeadByteInfo[*(PUCHAR)CustomCPString++];
  1554. *UnicodeString = TranslateTable[ Entry + *(PUCHAR)CustomCPString++ ];
  1555. UnicodeString++;
  1556. //
  1557. // Decrement count of bytes in multibyte string to account
  1558. // for the double byte character.
  1559. //
  1560. BytesInCustomCPString--;
  1561. } else {
  1562. //
  1563. // Single byte character.
  1564. //
  1565. *UnicodeString++ = (CustomCP->MultiByteTable)[*(PUCHAR)CustomCPString++];
  1566. }
  1567. }
  1568. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  1569. *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
  1570. }
  1571. //
  1572. // Check if we were able to use all of the source CustomCP String
  1573. //
  1574. return ( BytesInCustomCPString <= MaxCharsInUnicodeString ) ?
  1575. STATUS_SUCCESS :
  1576. STATUS_BUFFER_OVERFLOW;
  1577. }
  1578. NTSTATUS
  1579. RtlUnicodeToCustomCPN(
  1580. IN PCPTABLEINFO CustomCP,
  1581. OUT PCH CustomCPString,
  1582. IN ULONG MaxBytesInCustomCPString,
  1583. OUT PULONG BytesInCustomCPString OPTIONAL,
  1584. IN PWCH UnicodeString,
  1585. IN ULONG BytesInUnicodeString)
  1586. /*++
  1587. Routine Description:
  1588. This functions converts the specified unicode source string into an
  1589. CustomCP string. The translation is done with respect to the
  1590. CustomCP Code Page specified by CustomCp.
  1591. Arguments:
  1592. CustomCP - Supplies the address of the code page that translations
  1593. are done relative to
  1594. CustomCPString - Returns an CustomCP string that is equivalent to the
  1595. unicode source string. If the translation can not be done,
  1596. an error is returned.
  1597. MaxBytesInCustomCPString - Supplies the maximum number of bytes to be
  1598. written to CustomCPString. If this causes CustomCPString to be a
  1599. truncated equivalent of UnicodeString, no error condition results.
  1600. BytesInCustomCPString - Returns the number of bytes in the returned
  1601. CustomCP string pointed to by CustomCPString.
  1602. UnicodeString - Supplies the unicode source string that is to be
  1603. converted to CustomCP.
  1604. BytesInUnicodeString - The number of bytes in the the string pointed to by
  1605. UnicodeString.
  1606. Return Value:
  1607. SUCCESS - The conversion was successful
  1608. STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
  1609. the whole CustomCP string. It was converted correct to the point though.
  1610. --*/
  1611. {
  1612. ULONG TmpCount;
  1613. ULONG LoopCount;
  1614. PCH TranslateTable;
  1615. PUSHORT WideTranslateTable;
  1616. ULONG CharsInUnicodeString;
  1617. RTL_PAGED_CODE();
  1618. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  1619. //
  1620. // Convert Unicode byte count to character count. Byte count of
  1621. // multibyte string is equivalent to character count.
  1622. //
  1623. if (!(CustomCP->DBCSCodePage)) {
  1624. LoopCount = (CharsInUnicodeString < MaxBytesInCustomCPString) ?
  1625. CharsInUnicodeString : MaxBytesInCustomCPString;
  1626. if (ARGUMENT_PRESENT(BytesInCustomCPString))
  1627. *BytesInCustomCPString = LoopCount;
  1628. TranslateTable = CustomCP->WideCharTable;
  1629. TmpCount = LoopCount & 0x0F;
  1630. UnicodeString += TmpCount;
  1631. CustomCPString += TmpCount;
  1632. do
  1633. {
  1634. switch( TmpCount ) {
  1635. default:
  1636. UnicodeString += 0x10;
  1637. CustomCPString += 0x10;
  1638. CustomCPString[-0x10] = TranslateTable[UnicodeString[-0x10]];
  1639. case 0x0F:
  1640. CustomCPString[-0x0F] = TranslateTable[UnicodeString[-0x0F]];
  1641. case 0x0E:
  1642. CustomCPString[-0x0E] = TranslateTable[UnicodeString[-0x0E]];
  1643. case 0x0D:
  1644. CustomCPString[-0x0D] = TranslateTable[UnicodeString[-0x0D]];
  1645. case 0x0C:
  1646. CustomCPString[-0x0C] = TranslateTable[UnicodeString[-0x0C]];
  1647. case 0x0B:
  1648. CustomCPString[-0x0B] = TranslateTable[UnicodeString[-0x0B]];
  1649. case 0x0A:
  1650. CustomCPString[-0x0A] = TranslateTable[UnicodeString[-0x0A]];
  1651. case 0x09:
  1652. CustomCPString[-0x09] = TranslateTable[UnicodeString[-0x09]];
  1653. case 0x08:
  1654. CustomCPString[-0x08] = TranslateTable[UnicodeString[-0x08]];
  1655. case 0x07:
  1656. CustomCPString[-0x07] = TranslateTable[UnicodeString[-0x07]];
  1657. case 0x06:
  1658. CustomCPString[-0x06] = TranslateTable[UnicodeString[-0x06]];
  1659. case 0x05:
  1660. CustomCPString[-0x05] = TranslateTable[UnicodeString[-0x05]];
  1661. case 0x04:
  1662. CustomCPString[-0x04] = TranslateTable[UnicodeString[-0x04]];
  1663. case 0x03:
  1664. CustomCPString[-0x03] = TranslateTable[UnicodeString[-0x03]];
  1665. case 0x02:
  1666. CustomCPString[-0x02] = TranslateTable[UnicodeString[-0x02]];
  1667. case 0x01:
  1668. CustomCPString[-0x01] = TranslateTable[UnicodeString[-0x01]];
  1669. case 0x00:
  1670. ;
  1671. }
  1672. LoopCount -= TmpCount;
  1673. TmpCount = 0x10;
  1674. } while ( LoopCount > 0 );
  1675. /* end of copy... */
  1676. } else {
  1677. USHORT MbChar;
  1678. PCH CustomCPStringAnchor = CustomCPString;
  1679. WideTranslateTable = CustomCP->WideCharTable;
  1680. while (CharsInUnicodeString && MaxBytesInCustomCPString) {
  1681. MbChar = WideTranslateTable[ *UnicodeString++ ];
  1682. if (HIBYTE(MbChar) != 0) {
  1683. //
  1684. // Need at least 2 bytes to copy a double byte char.
  1685. // Don't want to truncate in the middle of a DBCS char.
  1686. //
  1687. if (MaxBytesInCustomCPString-- < 2) {
  1688. break;
  1689. }
  1690. *CustomCPString++ = HIBYTE(MbChar); // lead byte
  1691. }
  1692. *CustomCPString++ = LOBYTE(MbChar);
  1693. MaxBytesInCustomCPString--;
  1694. CharsInUnicodeString--;
  1695. }
  1696. if (ARGUMENT_PRESENT(BytesInCustomCPString))
  1697. *BytesInCustomCPString = (ULONG)(CustomCPString - CustomCPStringAnchor);
  1698. }
  1699. //
  1700. // Check if we were able to use all of the source Unicode String
  1701. //
  1702. return ( CharsInUnicodeString <= MaxBytesInCustomCPString ) ?
  1703. STATUS_SUCCESS :
  1704. STATUS_BUFFER_OVERFLOW;
  1705. }
  1706. NTSTATUS
  1707. RtlUpcaseUnicodeToCustomCPN(
  1708. IN PCPTABLEINFO CustomCP,
  1709. OUT PCH CustomCPString,
  1710. IN ULONG MaxBytesInCustomCPString,
  1711. OUT PULONG BytesInCustomCPString OPTIONAL,
  1712. IN PWCH UnicodeString,
  1713. IN ULONG BytesInUnicodeString)
  1714. /*++
  1715. Routine Description:
  1716. This functions upper cases the specified unicode source string and
  1717. converts it into a CustomCP string. The translation is done with
  1718. respect to the CustomCP Code Page specified by CustomCp.
  1719. Arguments:
  1720. CustomCP - Supplies the address of the code page that translations
  1721. are done relative to
  1722. CustomCPString - Returns an CustomCP string that is equivalent to the
  1723. unicode source string. If the translation can not be done,
  1724. an error is returned.
  1725. MaxBytesInCustomCPString - Supplies the maximum number of bytes to be
  1726. written to CustomCPString. If this causes CustomCPString to be a
  1727. truncated equivalent of UnicodeString, no error condition results.
  1728. BytesInCustomCPString - Returns the number of bytes in the returned
  1729. CustomCP string pointed to by CustomCPString.
  1730. UnicodeString - Supplies the unicode source string that is to be
  1731. converted to CustomCP.
  1732. BytesInUnicodeString - The number of bytes in the the string pointed
  1733. to by UnicodeString.
  1734. Return Value:
  1735. SUCCESS - The conversion was successful
  1736. STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to
  1737. hold the whole CustomCP string. It was converted correctly to
  1738. that point, though.
  1739. --*/
  1740. {
  1741. ULONG TmpCount;
  1742. ULONG LoopCount;
  1743. PCH TranslateTable;
  1744. PUSHORT WideTranslateTable;
  1745. ULONG CharsInUnicodeString;
  1746. UCHAR SbChar;
  1747. WCHAR UnicodeChar;
  1748. RTL_PAGED_CODE();
  1749. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  1750. //
  1751. // Convert Unicode byte count to character count. Byte count of
  1752. // multibyte string is equivalent to character count.
  1753. //
  1754. if (!(CustomCP->DBCSCodePage)) {
  1755. LoopCount = (CharsInUnicodeString < MaxBytesInCustomCPString) ?
  1756. CharsInUnicodeString : MaxBytesInCustomCPString;
  1757. if (ARGUMENT_PRESENT(BytesInCustomCPString))
  1758. *BytesInCustomCPString = LoopCount;
  1759. TranslateTable = CustomCP->WideCharTable;
  1760. TmpCount = LoopCount & 0x0F;
  1761. UnicodeString += TmpCount;
  1762. CustomCPString += TmpCount;
  1763. do
  1764. {
  1765. //
  1766. // Convert to Single Byte and back to Unicode before upper
  1767. // casing to ensure the visual best fits are converted and
  1768. // upper cased properly.
  1769. //
  1770. switch( TmpCount ) {
  1771. default:
  1772. UnicodeString += 0x10;
  1773. CustomCPString += 0x10;
  1774. SbChar = TranslateTable[UnicodeString[-0x10]];
  1775. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1776. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1777. CustomCPString[-0x10] = TranslateTable[UnicodeChar];
  1778. case 0x0F:
  1779. SbChar = TranslateTable[UnicodeString[-0x0F]];
  1780. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1781. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1782. CustomCPString[-0x0F] = TranslateTable[UnicodeChar];
  1783. case 0x0E:
  1784. SbChar = TranslateTable[UnicodeString[-0x0E]];
  1785. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1786. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1787. CustomCPString[-0x0E] = TranslateTable[UnicodeChar];
  1788. case 0x0D:
  1789. SbChar = TranslateTable[UnicodeString[-0x0D]];
  1790. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1791. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1792. CustomCPString[-0x0D] = TranslateTable[UnicodeChar];
  1793. case 0x0C:
  1794. SbChar = TranslateTable[UnicodeString[-0x0C]];
  1795. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1796. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1797. CustomCPString[-0x0C] = TranslateTable[UnicodeChar];
  1798. case 0x0B:
  1799. SbChar = TranslateTable[UnicodeString[-0x0B]];
  1800. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1801. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1802. CustomCPString[-0x0B] = TranslateTable[UnicodeChar];
  1803. case 0x0A:
  1804. SbChar = TranslateTable[UnicodeString[-0x0A]];
  1805. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1806. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1807. CustomCPString[-0x0A] = TranslateTable[UnicodeChar];
  1808. case 0x09:
  1809. SbChar = TranslateTable[UnicodeString[-0x09]];
  1810. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1811. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1812. CustomCPString[-0x09] = TranslateTable[UnicodeChar];
  1813. case 0x08:
  1814. SbChar = TranslateTable[UnicodeString[-0x08]];
  1815. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1816. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1817. CustomCPString[-0x08] = TranslateTable[UnicodeChar];
  1818. case 0x07:
  1819. SbChar = TranslateTable[UnicodeString[-0x07]];
  1820. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1821. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1822. CustomCPString[-0x07] = TranslateTable[UnicodeChar];
  1823. case 0x06:
  1824. SbChar = TranslateTable[UnicodeString[-0x06]];
  1825. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1826. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1827. CustomCPString[-0x06] = TranslateTable[UnicodeChar];
  1828. case 0x05:
  1829. SbChar = TranslateTable[UnicodeString[-0x05]];
  1830. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1831. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1832. CustomCPString[-0x05] = TranslateTable[UnicodeChar];
  1833. case 0x04:
  1834. SbChar = TranslateTable[UnicodeString[-0x04]];
  1835. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1836. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1837. CustomCPString[-0x04] = TranslateTable[UnicodeChar];
  1838. case 0x03:
  1839. SbChar = TranslateTable[UnicodeString[-0x03]];
  1840. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1841. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1842. CustomCPString[-0x03] = TranslateTable[UnicodeChar];
  1843. case 0x02:
  1844. SbChar = TranslateTable[UnicodeString[-0x02]];
  1845. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1846. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1847. CustomCPString[-0x02] = TranslateTable[UnicodeChar];
  1848. case 0x01:
  1849. SbChar = TranslateTable[UnicodeString[-0x01]];
  1850. UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
  1851. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1852. CustomCPString[-0x01] = TranslateTable[UnicodeChar];
  1853. case 0x00:
  1854. ;
  1855. }
  1856. LoopCount -= TmpCount;
  1857. TmpCount = 0x10;
  1858. } while ( LoopCount > 0 );
  1859. /* end of copy... */
  1860. } else {
  1861. USHORT MbChar;
  1862. register USHORT Entry;
  1863. PCH CustomCPStringAnchor = CustomCPString;
  1864. PUSHORT NlsCustomLeadByteInfo = CustomCP->DBCSOffsets;
  1865. WideTranslateTable = CustomCP->WideCharTable;
  1866. while ( CharsInUnicodeString && MaxBytesInCustomCPString ) {
  1867. //
  1868. // Convert to Single Byte and back to Unicode before upper
  1869. // casing to ensure the visual best fits are converted and
  1870. // upper cased properly.
  1871. //
  1872. MbChar = WideTranslateTable[ *UnicodeString++ ];
  1873. if (NlsCustomLeadByteInfo[HIBYTE(MbChar)]) {
  1874. //
  1875. // Lead byte - translate the trail byte using the table
  1876. // that corresponds to this lead byte.
  1877. //
  1878. Entry = NlsCustomLeadByteInfo[HIBYTE(MbChar)];
  1879. UnicodeChar = NlsCustomLeadByteInfo[ Entry + LOBYTE(MbChar) ];
  1880. } else {
  1881. //
  1882. // Single byte character.
  1883. //
  1884. UnicodeChar = (CustomCP->MultiByteTable)[LOBYTE(MbChar)];
  1885. }
  1886. UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
  1887. MbChar = WideTranslateTable[UnicodeChar];
  1888. if (HIBYTE(MbChar) != 0) {
  1889. //
  1890. // Need at least 2 bytes to copy a double byte char.
  1891. // Don't want to truncate in the middle of a DBCS char.
  1892. //
  1893. if (MaxBytesInCustomCPString-- < 2) {
  1894. break;
  1895. }
  1896. *CustomCPString++ = HIBYTE(MbChar); // lead byte
  1897. }
  1898. *CustomCPString++ = LOBYTE(MbChar);
  1899. MaxBytesInCustomCPString--;
  1900. CharsInUnicodeString--;
  1901. }
  1902. if (ARGUMENT_PRESENT(BytesInCustomCPString))
  1903. *BytesInCustomCPString = (ULONG)(CustomCPString - CustomCPStringAnchor);
  1904. }
  1905. //
  1906. // Check if we were able to use all of the source Unicode String
  1907. //
  1908. return ( CharsInUnicodeString <= MaxBytesInCustomCPString ) ?
  1909. STATUS_SUCCESS :
  1910. STATUS_BUFFER_OVERFLOW;
  1911. }
  1912. #define MB_TBL_SIZE 256 /* size of MB tables */
  1913. #define GLYPH_TBL_SIZE MB_TBL_SIZE /* size of GLYPH tables */
  1914. #define DBCS_TBL_SIZE 256 /* size of DBCS tables */
  1915. #define GLYPH_HEADER 1 /* size of GLYPH table header */
  1916. #define DBCS_HEADER 1 /* size of DBCS table header */
  1917. #define LANG_HEADER 1 /* size of LANGUAGE file header */
  1918. #define UP_HEADER 1 /* size of UPPERCASE table header */
  1919. #define LO_HEADER 1 /* size of LOWERCASE table header */
  1920. VOID
  1921. RtlInitCodePageTable(
  1922. IN PUSHORT TableBase,
  1923. OUT PCPTABLEINFO CodePageTable
  1924. )
  1925. {
  1926. USHORT offMB;
  1927. USHORT offWC;
  1928. PUSHORT pGlyph;
  1929. PUSHORT pRange;
  1930. RTL_PAGED_CODE();
  1931. //
  1932. // Get the offsets.
  1933. //
  1934. offMB = TableBase[0];
  1935. offWC = offMB + TableBase[offMB];
  1936. //
  1937. // Attach Code Page Info to CP hash node.
  1938. //
  1939. CodePageTable->CodePage = TableBase[1];
  1940. CodePageTable->MaximumCharacterSize = TableBase[2];
  1941. CodePageTable->DefaultChar = TableBase[3]; // default character (MB)
  1942. CodePageTable->UniDefaultChar = TableBase[4]; // default character (Unicode)
  1943. CodePageTable->TransDefaultChar = TableBase[5]; // trans of default char (Unicode)
  1944. CodePageTable->TransUniDefaultChar = TableBase[6]; // trans of Uni default char (MB)
  1945. RtlCopyMemory(
  1946. &CodePageTable->LeadByte,
  1947. &TableBase[7],
  1948. MAXIMUM_LEADBYTES
  1949. );
  1950. CodePageTable->MultiByteTable = (TableBase + offMB + 1);
  1951. pGlyph = CodePageTable->MultiByteTable + MB_TBL_SIZE;
  1952. if (pGlyph[0] != 0) {
  1953. pRange = CodePageTable->DBCSRanges = pGlyph + GLYPH_HEADER + GLYPH_TBL_SIZE;
  1954. }
  1955. else {
  1956. pRange = CodePageTable->DBCSRanges = pGlyph + GLYPH_HEADER;
  1957. }
  1958. //
  1959. // Attach DBCS information to CP hash node.
  1960. //
  1961. if (pRange[0] > 0) {
  1962. CodePageTable->DBCSOffsets = pRange + DBCS_HEADER;
  1963. CodePageTable->DBCSCodePage = 1;
  1964. }
  1965. else {
  1966. CodePageTable->DBCSCodePage = 0;
  1967. CodePageTable->DBCSOffsets = NULL;
  1968. }
  1969. CodePageTable->WideCharTable = (TableBase + offWC + 1);
  1970. }
  1971. VOID
  1972. RtlpInitUpcaseTable(
  1973. IN PUSHORT TableBase,
  1974. OUT PNLSTABLEINFO CodePageTable
  1975. )
  1976. {
  1977. USHORT offUP;
  1978. USHORT offLO;
  1979. //
  1980. // Get the offsets.
  1981. //
  1982. offUP = LANG_HEADER;
  1983. offLO = offUP + TableBase[offUP];
  1984. CodePageTable->UpperCaseTable = TableBase + offUP + UP_HEADER;
  1985. CodePageTable->LowerCaseTable = TableBase + offLO + LO_HEADER;
  1986. }
  1987. VOID
  1988. RtlInitNlsTables(
  1989. IN PUSHORT AnsiNlsBase,
  1990. IN PUSHORT OemNlsBase,
  1991. IN PUSHORT LanguageNlsBase,
  1992. OUT PNLSTABLEINFO TableInfo
  1993. )
  1994. {
  1995. RTL_PAGED_CODE();
  1996. RtlInitCodePageTable(AnsiNlsBase,&TableInfo->AnsiTableInfo);
  1997. RtlInitCodePageTable(OemNlsBase,&TableInfo->OemTableInfo);
  1998. RtlpInitUpcaseTable(LanguageNlsBase,TableInfo);
  1999. }
  2000. VOID
  2001. RtlResetRtlTranslations(
  2002. PNLSTABLEINFO TableInfo
  2003. )
  2004. {
  2005. RTL_PAGED_CODE();
  2006. if ( TableInfo->AnsiTableInfo.DBCSCodePage ) {
  2007. RtlMoveMemory(NlsLeadByteInfo,TableInfo->AnsiTableInfo.DBCSOffsets,DBCS_TBL_SIZE*sizeof(USHORT));
  2008. }
  2009. else {
  2010. RtlZeroMemory(NlsLeadByteInfo,DBCS_TBL_SIZE*sizeof(USHORT));
  2011. }
  2012. NlsMbAnsiCodePageTables = (PUSHORT)TableInfo->AnsiTableInfo.DBCSOffsets;
  2013. NlsAnsiToUnicodeData = TableInfo->AnsiTableInfo.MultiByteTable;
  2014. NlsUnicodeToAnsiData = (PCH)TableInfo->AnsiTableInfo.WideCharTable;
  2015. NlsUnicodeToMbAnsiData = (PUSHORT)TableInfo->AnsiTableInfo.WideCharTable;
  2016. NlsMbCodePageTag = TableInfo->AnsiTableInfo.DBCSCodePage ? TRUE : FALSE;
  2017. NlsAnsiCodePage = TableInfo->AnsiTableInfo.CodePage;
  2018. if ( TableInfo->OemTableInfo.DBCSCodePage ) {
  2019. RtlMoveMemory(NlsOemLeadByteInfo,TableInfo->OemTableInfo.DBCSOffsets,DBCS_TBL_SIZE*sizeof(USHORT));
  2020. }
  2021. else {
  2022. RtlZeroMemory(NlsOemLeadByteInfo,DBCS_TBL_SIZE*sizeof(USHORT));
  2023. }
  2024. NlsMbOemCodePageTables = (PUSHORT)TableInfo->OemTableInfo.DBCSOffsets;
  2025. NlsOemToUnicodeData = TableInfo->OemTableInfo.MultiByteTable;
  2026. NlsUnicodeToOemData = (PCH)TableInfo->OemTableInfo.WideCharTable;
  2027. NlsUnicodeToMbOemData = (PUSHORT)TableInfo->OemTableInfo.WideCharTable;
  2028. NlsMbOemCodePageTag = TableInfo->OemTableInfo.DBCSCodePage ? TRUE : FALSE;
  2029. NlsOemCodePage = TableInfo->OemTableInfo.CodePage;
  2030. OemDefaultChar = TableInfo->OemTableInfo.DefaultChar;
  2031. OemTransUniDefaultChar = TableInfo->OemTableInfo.TransDefaultChar;
  2032. Nls844UnicodeUpcaseTable = TableInfo->UpperCaseTable;
  2033. Nls844UnicodeLowercaseTable = TableInfo->LowerCaseTable;
  2034. UnicodeDefaultChar = TableInfo->AnsiTableInfo.UniDefaultChar;
  2035. }
  2036. void
  2037. RtlGetDefaultCodePage(
  2038. OUT PUSHORT AnsiCodePage,
  2039. OUT PUSHORT OemCodePage
  2040. )
  2041. {
  2042. RTL_PAGED_CODE();
  2043. *AnsiCodePage = NlsAnsiCodePage;
  2044. *OemCodePage = NlsOemCodePage;
  2045. }