3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/rtl/nls.c
6 * PURPOSE: National Language Support (NLS) functions
8 * 20/08/99 Created by Emanuele Aliberti
9 * 10/11/99 Added translation functions.
12 * Multi-byte code pages are not supported yet. Even single-byte code
13 * pages are not supported properly. Only stupid CHAR->WCHAR and
14 * WCHAR->CHAR (Attention: data loss!!!) translation is done.
17 * 1) Implement code to initialize the translation tables.
18 * 2) Use fixed translation table for translation.
19 * 3) Add loading of translation tables (NLS files).
20 * 4) Add multi-byte translation code.
23 #include <ddk/ntddk.h>
24 //#include <internal/nls.h>
27 #include <internal/debug.h>
29 /* GLOBALS *******************************************************************/
31 BOOLEAN NlsMbCodePageTag = FALSE;
32 BOOLEAN NlsMbOemCodePageTag = FALSE;
34 BYTE NlsLeadByteInfo = 0; /* ? */
36 USHORT NlsOemLeadByteInfo = 0;
38 USHORT NlsAnsiCodePage = 0;
39 USHORT NlsOemCodePage = 0; /* not exported */
41 PWCHAR AnsiToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */
42 PWCHAR OemToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */
44 PCHAR UnicodeToAnsiTable = NULL; /* size: 65536*sizeof(CHAR) */
45 PCHAR UnicodeToOemTable =NULL; /* size: 65536*sizeof(CHAR) */
47 PWCHAR UnicodeUpcaseTable = NULL; /* size: 65536*sizeof(WCHAR) */
48 PWCHAR UnicodeLowercaseTable = NULL; /* size: 65536*sizeof(WCHAR) */
51 /* FUNCTIONS *****************************************************************/
54 RtlpInitNlsTables(VOID)
60 /* allocate and initialize ansi->unicode table */
61 AnsiToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
62 if (AnsiToUnicodeTable == NULL)
64 DbgPrint("Allocation of 'AnsiToUnicodeTable' failed\n");
68 pwc = AnsiToUnicodeTable;
69 for (i = 0; i < 256; i++, pwc++)
72 /* allocate and initialize oem->unicode table */
73 OemToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
74 if (OemToUnicodeTable == NULL)
76 DbgPrint("Allocation of 'OemToUnicodeTable' failed\n");
80 pwc = OemToUnicodeTable;
81 for (i = 0; i < 256; i++, pwc++)
84 /* allocate and initialize unicode->ansi table */
85 UnicodeToAnsiTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR));
86 if (UnicodeToAnsiTable == NULL)
88 DbgPrint("Allocation of 'UnicodeToAnsiTable' failed\n");
92 pc = UnicodeToAnsiTable;
93 for (i = 0; i < 256; i++, pc++)
95 for (; i < 65536; i++, pc++)
98 /* allocate and initialize unicode->oem table */
99 UnicodeToOemTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR));
100 if (UnicodeToOemTable == NULL)
102 DbgPrint("Allocation of 'UnicodeToOemTable' failed\n");
106 pc = UnicodeToOemTable;
107 for (i = 0; i < 256; i++, pc++)
109 for (; i < 65536; i++, pc++)
112 /* allocate and initialize unicode upcase table */
113 UnicodeUpcaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR));
114 if (UnicodeUpcaseTable == NULL)
116 DbgPrint("Allocation of 'UnicodeUpcaseTable' failed\n");
120 pwc = UnicodeUpcaseTable;
121 for (i = 0; i < 65536; i++, pwc++)
123 for (i = 'a'; i < ('z'+ 1); i++)
124 UnicodeUpcaseTable[i] = (WCHAR)i + (L'A' - L'a');
127 /* allocate and initialize unicode lowercase table */
128 UnicodeLowercaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR));
129 if (UnicodeLowercaseTable == NULL)
131 DbgPrint("Allocation of 'UnicodeLowercaseTable' failed\n");
135 pwc = UnicodeLowercaseTable;
136 for (i = 0; i < 65536; i++, pwc++)
138 for (i = 'A'; i < ('Z'+ 1); i++)
139 UnicodeLowercaseTable[i] = (WCHAR)i - (L'A' - L'a');
141 /* FIXME: initialize codepage info */
148 RtlpInitNlsSections(ULONG Mod1Start,
155 UNICODE_STRING UnicodeString;
156 OBJECT_ATTRIBUTES ObjectAttributes;
157 HANDLE DirectoryHandle;
158 HANDLE SectionHandle;
160 LARGE_INTEGER SectionSize;
162 DPRINT("Ansi section start: 0x%08lX\n", Mod1Start);
163 DPRINT("Ansi section end: 0x%08lX\n", Mod1End);
164 DPRINT("Oem section start: 0x%08lX\n", Mod2Start);
165 DPRINT("Oem section end: 0x%08lX\n", Mod2End);
166 DPRINT("Upcase section start: 0x%08lX\n", Mod3Start);
167 DPRINT("Upcase section end: 0x%08lX\n", Mod3End);
169 /* Create the '\NLS' directory */
170 RtlInitUnicodeStringFromLiteral(&UnicodeString,
172 InitializeObjectAttributes(&ObjectAttributes,
177 Status = NtCreateDirectoryObject(&DirectoryHandle,
180 if (!NT_SUCCESS(Status))
183 /* Create the 'NlsSectionUnicode' section */
184 RtlInitUnicodeStringFromLiteral(&UnicodeString,
185 L"NlsSectionUnicode");
186 InitializeObjectAttributes(&ObjectAttributes,
191 SectionSize.QuadPart = (Mod1End - Mod1Start) +
192 (Mod2End - Mod2Start) + (Mod3End - Mod3Start);
193 DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart);
195 Status = NtCreateSection(&SectionHandle,
202 if (!NT_SUCCESS(Status))
206 /* create and initialize code page table */
208 /* map the nls table into the 'NlsSectionUnicode' section */
211 NtClose(SectionHandle);
212 NtClose(DirectoryHandle);
214 return(STATUS_SUCCESS);
219 RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData,
220 PWCHAR UnicodeString,
229 if (NlsData->DbcsFlag == FALSE)
231 /* single-byte code page */
232 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
233 Size = UnicodeSize / sizeof(WCHAR);
237 if (ResultSize != NULL)
238 *ResultSize = Size * sizeof(WCHAR);
240 for (i = 0; i < Size; i++)
242 *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString];
249 /* multi-byte code page */
253 return(STATUS_SUCCESS);
258 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
261 *AnsiCodePage = NlsAnsiCodePage;
262 *OemCodePage = NlsOemCodePage;
265 #endif /* LIBCAPTIVE */
268 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
277 if (NlsMbCodePageTag == FALSE)
279 /* single-byte code page */
280 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
281 Size = UnicodeSize / sizeof(WCHAR);
285 if (ResultSize != NULL)
286 *ResultSize = Size * sizeof(WCHAR);
288 for (i = 0; i < Size; i++)
290 *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString];
297 /* multi-byte code page */
301 return(STATUS_SUCCESS);
306 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
310 if (NlsMbCodePageTag == FALSE)
312 /* single-byte code page */
313 *UnicodeSize = MbSize * sizeof (WCHAR);
317 /* multi-byte code page */
321 return(STATUS_SUCCESS);
326 RtlOemToUnicodeN(PWCHAR UnicodeString,
335 if (NlsMbOemCodePageTag == FALSE)
337 /* single-byte code page */
338 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
339 Size = UnicodeSize / sizeof(WCHAR);
343 if (ResultSize != NULL)
344 *ResultSize = Size * sizeof(WCHAR);
346 for (i = 0; i < Size; i++)
348 *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString];
355 /* multi-byte code page */
359 return(STATUS_SUCCESS);
365 RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
369 PWCHAR UnicodeString,
375 if (NlsData->DbcsFlag == 0)
377 /* single-byte code page */
378 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
381 Size = UnicodeSize / sizeof(WCHAR);
383 if (ResultSize != NULL)
386 for (i = 0; i < Size; i++)
388 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString];
395 /* multi-byte code page */
399 return(STATUS_SUCCESS);
402 #endif /* LIBCAPTIVE */
406 RtlUnicodeToMultiByteN(PCHAR MbString,
409 PWCHAR UnicodeString,
415 if (NlsMbCodePageTag == FALSE)
417 /* single-byte code page */
418 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
421 Size = UnicodeSize / sizeof(WCHAR);
423 if (ResultSize != NULL)
426 for (i = 0; i < Size; i++)
428 *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString];
435 /* multi-byte code page */
439 return(STATUS_SUCCESS);
444 RtlUnicodeToMultiByteSize(PULONG MbSize,
445 PWCHAR UnicodeString,
448 if (NlsMbCodePageTag == FALSE)
450 /* single-byte code page */
451 *MbSize = UnicodeSize / sizeof (WCHAR);
455 /* multi-byte code page */
459 return(STATUS_SUCCESS);
464 RtlUnicodeToOemN(PCHAR OemString,
467 PWCHAR UnicodeString,
473 if (NlsMbOemCodePageTag == FALSE)
475 /* single-byte code page */
476 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
479 Size = UnicodeSize / sizeof(WCHAR);
481 if (ResultSize != NULL)
484 for (i = 0; i < Size; i++)
486 *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString];
493 /* multi-byte code page */
497 return(STATUS_SUCCESS);
503 RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
507 PWCHAR UnicodeString,
514 if (NlsData->DbcsFlag == 0)
516 /* single-byte code page */
517 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
520 Size = UnicodeSize / sizeof(WCHAR);
522 if (ResultSize != NULL)
525 for (i = 0; i < Size; i++)
527 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
528 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc];
535 /* multi-byte code page */
539 return(STATUS_SUCCESS);
542 #endif /* LIBCAPTIVE */
545 RtlUpcaseUnicodeToMultiByteN(PCHAR MbString,
548 PWCHAR UnicodeString,
555 if (NlsMbCodePageTag == FALSE)
557 /* single-byte code page */
558 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
561 Size = UnicodeSize / sizeof(WCHAR);
563 if (ResultSize != NULL)
566 for (i = 0; i < Size; i++)
568 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
569 *MbString = UnicodeToAnsiTable[(unsigned int)wc];
576 /* multi-byte code page */
580 return(STATUS_SUCCESS);
585 RtlUpcaseUnicodeToOemN(PCHAR OemString,
588 PWCHAR UnicodeString,
595 if (NlsMbOemCodePageTag == FALSE)
597 /* single-byte code page */
598 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
601 Size = UnicodeSize / sizeof(WCHAR);
603 if (ResultSize != NULL)
606 for (i = 0; i < Size; i++)
608 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
609 *OemString = UnicodeToOemTable[(unsigned int)wc];
616 /* multi-byte code page */
620 return(STATUS_SUCCESS);