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 */
147 RtlpInitNlsSections(ULONG Mod1Start,
154 UNICODE_STRING UnicodeString;
155 OBJECT_ATTRIBUTES ObjectAttributes;
156 HANDLE DirectoryHandle;
157 HANDLE SectionHandle;
159 LARGE_INTEGER SectionSize;
161 DPRINT("Ansi section start: 0x%08lX\n", Mod1Start);
162 DPRINT("Ansi section end: 0x%08lX\n", Mod1End);
163 DPRINT("Oem section start: 0x%08lX\n", Mod2Start);
164 DPRINT("Oem section end: 0x%08lX\n", Mod2End);
165 DPRINT("Upcase section start: 0x%08lX\n", Mod3Start);
166 DPRINT("Upcase section end: 0x%08lX\n", Mod3End);
168 /* Create the '\NLS' directory */
169 RtlInitUnicodeStringFromLiteral(&UnicodeString,
171 InitializeObjectAttributes(&ObjectAttributes,
176 Status = NtCreateDirectoryObject(&DirectoryHandle,
179 if (!NT_SUCCESS(Status))
182 /* Create the 'NlsSectionUnicode' section */
183 RtlInitUnicodeStringFromLiteral(&UnicodeString,
184 L"NlsSectionUnicode");
185 InitializeObjectAttributes(&ObjectAttributes,
190 SectionSize.QuadPart = (Mod1End - Mod1Start) +
191 (Mod2End - Mod2Start) + (Mod3End - Mod3Start);
192 DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart);
194 Status = NtCreateSection(&SectionHandle,
201 if (!NT_SUCCESS(Status))
205 /* create and initialize code page table */
207 /* map the nls table into the 'NlsSectionUnicode' section */
210 NtClose(SectionHandle);
211 NtClose(DirectoryHandle);
213 return(STATUS_SUCCESS);
218 RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData,
219 PWCHAR UnicodeString,
228 if (NlsData->DbcsFlag == FALSE)
230 /* single-byte code page */
231 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
232 Size = UnicodeSize / sizeof(WCHAR);
236 if (ResultSize != NULL)
237 *ResultSize = Size * sizeof(WCHAR);
239 for (i = 0; i < Size; i++)
241 *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString];
248 /* multi-byte code page */
252 return(STATUS_SUCCESS);
257 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
260 *AnsiCodePage = NlsAnsiCodePage;
261 *OemCodePage = NlsOemCodePage;
266 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
275 if (NlsMbCodePageTag == FALSE)
277 /* single-byte code page */
278 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
279 Size = UnicodeSize / sizeof(WCHAR);
283 if (ResultSize != NULL)
284 *ResultSize = Size * sizeof(WCHAR);
286 for (i = 0; i < Size; i++)
288 *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString];
295 /* multi-byte code page */
299 return(STATUS_SUCCESS);
304 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
308 if (NlsMbCodePageTag == FALSE)
310 /* single-byte code page */
311 *UnicodeSize = MbSize * sizeof (WCHAR);
315 /* multi-byte code page */
319 return(STATUS_SUCCESS);
324 RtlOemToUnicodeN(PWCHAR UnicodeString,
333 if (NlsMbOemCodePageTag == FALSE)
335 /* single-byte code page */
336 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
337 Size = UnicodeSize / sizeof(WCHAR);
341 if (ResultSize != NULL)
342 *ResultSize = Size * sizeof(WCHAR);
344 for (i = 0; i < Size; i++)
346 *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString];
353 /* multi-byte code page */
357 return(STATUS_SUCCESS);
362 RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
366 PWCHAR UnicodeString,
372 if (NlsData->DbcsFlag == 0)
374 /* single-byte code page */
375 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
378 Size = UnicodeSize / sizeof(WCHAR);
380 if (ResultSize != NULL)
383 for (i = 0; i < Size; i++)
385 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString];
392 /* multi-byte code page */
396 return(STATUS_SUCCESS);
402 RtlUnicodeToMultiByteN(PCHAR MbString,
405 PWCHAR UnicodeString,
411 if (NlsMbCodePageTag == FALSE)
413 /* single-byte code page */
414 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
417 Size = UnicodeSize / sizeof(WCHAR);
419 if (ResultSize != NULL)
422 for (i = 0; i < Size; i++)
424 *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString];
431 /* multi-byte code page */
435 return(STATUS_SUCCESS);
440 RtlUnicodeToMultiByteSize(PULONG MbSize,
441 PWCHAR UnicodeString,
444 if (NlsMbCodePageTag == FALSE)
446 /* single-byte code page */
447 *MbSize = UnicodeSize / sizeof (WCHAR);
451 /* multi-byte code page */
455 return(STATUS_SUCCESS);
460 RtlUnicodeToOemN(PCHAR OemString,
463 PWCHAR UnicodeString,
469 if (NlsMbOemCodePageTag == FALSE)
471 /* single-byte code page */
472 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
475 Size = UnicodeSize / sizeof(WCHAR);
477 if (ResultSize != NULL)
480 for (i = 0; i < Size; i++)
482 *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString];
489 /* multi-byte code page */
493 return(STATUS_SUCCESS);
498 RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
502 PWCHAR UnicodeString,
509 if (NlsData->DbcsFlag == 0)
511 /* single-byte code page */
512 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
515 Size = UnicodeSize / sizeof(WCHAR);
517 if (ResultSize != NULL)
520 for (i = 0; i < Size; i++)
522 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
523 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc];
530 /* multi-byte code page */
534 return(STATUS_SUCCESS);
539 RtlUpcaseUnicodeToMultiByteN(PCHAR MbString,
542 PWCHAR UnicodeString,
549 if (NlsMbCodePageTag == FALSE)
551 /* single-byte code page */
552 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
555 Size = UnicodeSize / sizeof(WCHAR);
557 if (ResultSize != NULL)
560 for (i = 0; i < Size; i++)
562 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
563 *MbString = UnicodeToAnsiTable[(unsigned int)wc];
570 /* multi-byte code page */
574 return(STATUS_SUCCESS);
579 RtlUpcaseUnicodeToOemN(PCHAR OemString,
582 PWCHAR UnicodeString,
589 if (NlsMbOemCodePageTag == FALSE)
591 /* single-byte code page */
592 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
595 Size = UnicodeSize / sizeof(WCHAR);
597 if (ResultSize != NULL)
600 for (i = 0; i < Size; i++)
602 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
603 *OemString = UnicodeToOemTable[(unsigned int)wc];
610 /* multi-byte code page */
614 return(STATUS_SUCCESS);