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.
27 #include <ddk/ntddk.h>
28 //#include <internal/nls.h>
31 #include <internal/debug.h>
35 /* GLOBALS *******************************************************************/
37 BOOLEAN NlsMbCodePageTag = FALSE;
38 BOOLEAN NlsMbOemCodePageTag = FALSE;
40 BYTE NlsLeadByteInfo = 0; /* ? */
42 USHORT NlsOemLeadByteInfo = 0;
44 USHORT NlsAnsiCodePage = 0;
45 USHORT NlsOemCodePage = 0; /* not exported */
47 PWCHAR AnsiToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */
48 PWCHAR OemToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */
50 PCHAR UnicodeToAnsiTable = NULL; /* size: 65536*sizeof(CHAR) */
51 PCHAR UnicodeToOemTable =NULL; /* size: 65536*sizeof(CHAR) */
53 PWCHAR UnicodeUpcaseTable = NULL; /* size: 65536*sizeof(WCHAR) */
54 PWCHAR UnicodeLowercaseTable = NULL; /* size: 65536*sizeof(WCHAR) */
57 /* FUNCTIONS *****************************************************************/
60 RtlpInitNlsTables(VOID)
66 /* allocate and initialize ansi->unicode table */
67 AnsiToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
68 if (AnsiToUnicodeTable == NULL)
70 DbgPrint("Allocation of 'AnsiToUnicodeTable' failed\n");
74 pwc = AnsiToUnicodeTable;
75 for (i = 0; i < 256; i++, pwc++)
78 /* allocate and initialize oem->unicode table */
79 OemToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
80 if (OemToUnicodeTable == NULL)
82 DbgPrint("Allocation of 'OemToUnicodeTable' failed\n");
86 pwc = OemToUnicodeTable;
87 for (i = 0; i < 256; i++, pwc++)
90 /* allocate and initialize unicode->ansi table */
91 UnicodeToAnsiTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR));
92 if (UnicodeToAnsiTable == NULL)
94 DbgPrint("Allocation of 'UnicodeToAnsiTable' failed\n");
98 pc = UnicodeToAnsiTable;
99 for (i = 0; i < 256; i++, pc++)
101 for (; i < 65536; i++, pc++)
104 /* allocate and initialize unicode->oem table */
105 UnicodeToOemTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR));
106 if (UnicodeToOemTable == NULL)
108 DbgPrint("Allocation of 'UnicodeToOemTable' failed\n");
112 pc = UnicodeToOemTable;
113 for (i = 0; i < 256; i++, pc++)
115 for (; i < 65536; i++, pc++)
118 /* allocate and initialize unicode upcase table */
119 UnicodeUpcaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR));
120 if (UnicodeUpcaseTable == NULL)
122 DbgPrint("Allocation of 'UnicodeUpcaseTable' failed\n");
126 pwc = UnicodeUpcaseTable;
127 for (i = 0; i < 65536; i++, pwc++)
129 for (i = 'a'; i < ('z'+ 1); i++)
130 UnicodeUpcaseTable[i] = (WCHAR)i + (L'A' - L'a');
133 /* allocate and initialize unicode lowercase table */
134 UnicodeLowercaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR));
135 if (UnicodeLowercaseTable == NULL)
137 DbgPrint("Allocation of 'UnicodeLowercaseTable' failed\n");
141 pwc = UnicodeLowercaseTable;
142 for (i = 0; i < 65536; i++, pwc++)
144 for (i = 'A'; i < ('Z'+ 1); i++)
145 UnicodeLowercaseTable[i] = (WCHAR)i - (L'A' - L'a');
147 /* FIXME: initialize codepage info */
153 RtlpInitNlsSections(ULONG Mod1Start,
160 UNICODE_STRING UnicodeString;
161 OBJECT_ATTRIBUTES ObjectAttributes;
162 HANDLE DirectoryHandle;
163 HANDLE SectionHandle;
165 LARGE_INTEGER SectionSize;
167 DPRINT("Ansi section start: 0x%08lX\n", Mod1Start);
168 DPRINT("Ansi section end: 0x%08lX\n", Mod1End);
169 DPRINT("Oem section start: 0x%08lX\n", Mod2Start);
170 DPRINT("Oem section end: 0x%08lX\n", Mod2End);
171 DPRINT("Upcase section start: 0x%08lX\n", Mod3Start);
172 DPRINT("Upcase section end: 0x%08lX\n", Mod3End);
174 /* Create the '\NLS' directory */
175 RtlInitUnicodeStringFromLiteral(&UnicodeString,
177 InitializeObjectAttributes(&ObjectAttributes,
182 Status = NtCreateDirectoryObject(&DirectoryHandle,
185 if (!NT_SUCCESS(Status))
188 /* Create the 'NlsSectionUnicode' section */
189 RtlInitUnicodeStringFromLiteral(&UnicodeString,
190 L"NlsSectionUnicode");
191 InitializeObjectAttributes(&ObjectAttributes,
196 SectionSize.QuadPart = (Mod1End - Mod1Start) +
197 (Mod2End - Mod2Start) + (Mod3End - Mod3Start);
198 DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart);
200 Status = NtCreateSection(&SectionHandle,
207 if (!NT_SUCCESS(Status))
211 /* create and initialize code page table */
213 /* map the nls table into the 'NlsSectionUnicode' section */
216 NtClose(SectionHandle);
217 NtClose(DirectoryHandle);
219 return(STATUS_SUCCESS);
224 RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData,
225 PWCHAR UnicodeString,
234 if (NlsData->DbcsFlag == FALSE)
236 /* single-byte code page */
237 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
238 Size = UnicodeSize / sizeof(WCHAR);
242 if (ResultSize != NULL)
243 *ResultSize = Size * sizeof(WCHAR);
245 for (i = 0; i < Size; i++)
247 *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString];
254 /* multi-byte code page */
258 return(STATUS_SUCCESS);
263 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
266 *AnsiCodePage = NlsAnsiCodePage;
267 *OemCodePage = NlsOemCodePage;
272 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
281 if (NlsMbCodePageTag == FALSE)
283 /* single-byte code page */
284 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
285 Size = UnicodeSize / sizeof(WCHAR);
289 if (ResultSize != NULL)
290 *ResultSize = Size * sizeof(WCHAR);
292 for (i = 0; i < Size; i++)
294 *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString];
301 /* multi-byte code page */
305 return(STATUS_SUCCESS);
310 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
314 if (NlsMbCodePageTag == FALSE)
316 /* single-byte code page */
317 *UnicodeSize = MbSize * sizeof (WCHAR);
321 /* multi-byte code page */
325 return(STATUS_SUCCESS);
330 RtlOemToUnicodeN(PWCHAR UnicodeString,
339 if (NlsMbOemCodePageTag == FALSE)
341 /* single-byte code page */
342 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
343 Size = UnicodeSize / sizeof(WCHAR);
347 if (ResultSize != NULL)
348 *ResultSize = Size * sizeof(WCHAR);
350 for (i = 0; i < Size; i++)
352 *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString];
359 /* multi-byte code page */
363 return(STATUS_SUCCESS);
368 RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
372 PWCHAR UnicodeString,
378 if (NlsData->DbcsFlag == 0)
380 /* single-byte code page */
381 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
384 Size = UnicodeSize / sizeof(WCHAR);
386 if (ResultSize != NULL)
389 for (i = 0; i < Size; i++)
391 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString];
398 /* multi-byte code page */
402 return(STATUS_SUCCESS);
408 RtlUnicodeToMultiByteN(PCHAR MbString,
411 PWCHAR UnicodeString,
417 if (NlsMbCodePageTag == FALSE)
419 /* single-byte code page */
420 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
423 Size = UnicodeSize / sizeof(WCHAR);
425 if (ResultSize != NULL)
428 for (i = 0; i < Size; i++)
430 *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString];
437 /* multi-byte code page */
441 return(STATUS_SUCCESS);
446 RtlUnicodeToMultiByteSize(PULONG MbSize,
447 PWCHAR UnicodeString,
450 if (NlsMbCodePageTag == FALSE)
452 /* single-byte code page */
453 *MbSize = UnicodeSize / sizeof (WCHAR);
457 /* multi-byte code page */
461 return(STATUS_SUCCESS);
466 RtlUnicodeToOemN(PCHAR OemString,
469 PWCHAR UnicodeString,
475 if (NlsMbOemCodePageTag == FALSE)
477 /* single-byte code page */
478 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
481 Size = UnicodeSize / sizeof(WCHAR);
483 if (ResultSize != NULL)
486 for (i = 0; i < Size; i++)
488 *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString];
495 /* multi-byte code page */
499 return(STATUS_SUCCESS);
504 RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
508 PWCHAR UnicodeString,
515 if (NlsData->DbcsFlag == 0)
517 /* single-byte code page */
518 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
521 Size = UnicodeSize / sizeof(WCHAR);
523 if (ResultSize != NULL)
526 for (i = 0; i < Size; i++)
528 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
529 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc];
536 /* multi-byte code page */
540 return(STATUS_SUCCESS);
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);