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 */
154 RtlpInitNlsSections(ULONG Mod1Start,
161 UNICODE_STRING UnicodeString;
162 OBJECT_ATTRIBUTES ObjectAttributes;
163 HANDLE DirectoryHandle;
164 HANDLE SectionHandle;
166 LARGE_INTEGER SectionSize;
168 DPRINT("Ansi section start: 0x%08lX\n", Mod1Start);
169 DPRINT("Ansi section end: 0x%08lX\n", Mod1End);
170 DPRINT("Oem section start: 0x%08lX\n", Mod2Start);
171 DPRINT("Oem section end: 0x%08lX\n", Mod2End);
172 DPRINT("Upcase section start: 0x%08lX\n", Mod3Start);
173 DPRINT("Upcase section end: 0x%08lX\n", Mod3End);
175 /* Create the '\NLS' directory */
176 RtlInitUnicodeStringFromLiteral(&UnicodeString,
178 InitializeObjectAttributes(&ObjectAttributes,
183 Status = NtCreateDirectoryObject(&DirectoryHandle,
186 if (!NT_SUCCESS(Status))
189 /* Create the 'NlsSectionUnicode' section */
190 RtlInitUnicodeStringFromLiteral(&UnicodeString,
191 L"NlsSectionUnicode");
192 InitializeObjectAttributes(&ObjectAttributes,
197 SectionSize.QuadPart = (Mod1End - Mod1Start) +
198 (Mod2End - Mod2Start) + (Mod3End - Mod3Start);
199 DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart);
201 Status = NtCreateSection(&SectionHandle,
208 if (!NT_SUCCESS(Status))
212 /* create and initialize code page table */
214 /* map the nls table into the 'NlsSectionUnicode' section */
217 NtClose(SectionHandle);
218 NtClose(DirectoryHandle);
220 return(STATUS_SUCCESS);
225 RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData,
226 PWCHAR UnicodeString,
235 if (NlsData->DbcsFlag == FALSE)
237 /* single-byte code page */
238 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
239 Size = UnicodeSize / sizeof(WCHAR);
243 if (ResultSize != NULL)
244 *ResultSize = Size * sizeof(WCHAR);
246 for (i = 0; i < Size; i++)
248 *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString];
255 /* multi-byte code page */
259 return(STATUS_SUCCESS);
264 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
267 *AnsiCodePage = NlsAnsiCodePage;
268 *OemCodePage = NlsOemCodePage;
271 #endif /* LIBCAPTIVE */
274 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
283 if (NlsMbCodePageTag == FALSE)
285 /* single-byte code page */
286 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
287 Size = UnicodeSize / sizeof(WCHAR);
291 if (ResultSize != NULL)
292 *ResultSize = Size * sizeof(WCHAR);
294 for (i = 0; i < Size; i++)
296 *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString];
303 /* multi-byte code page */
307 return(STATUS_SUCCESS);
312 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
316 if (NlsMbCodePageTag == FALSE)
318 /* single-byte code page */
319 *UnicodeSize = MbSize * sizeof (WCHAR);
323 /* multi-byte code page */
327 return(STATUS_SUCCESS);
332 RtlOemToUnicodeN(PWCHAR UnicodeString,
341 if (NlsMbOemCodePageTag == FALSE)
343 /* single-byte code page */
344 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
345 Size = UnicodeSize / sizeof(WCHAR);
349 if (ResultSize != NULL)
350 *ResultSize = Size * sizeof(WCHAR);
352 for (i = 0; i < Size; i++)
354 *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString];
361 /* multi-byte code page */
365 return(STATUS_SUCCESS);
371 RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
375 PWCHAR UnicodeString,
381 if (NlsData->DbcsFlag == 0)
383 /* single-byte code page */
384 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
387 Size = UnicodeSize / sizeof(WCHAR);
389 if (ResultSize != NULL)
392 for (i = 0; i < Size; i++)
394 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString];
401 /* multi-byte code page */
405 return(STATUS_SUCCESS);
408 #endif /* LIBCAPTIVE */
412 RtlUnicodeToMultiByteN(PCHAR MbString,
415 PWCHAR UnicodeString,
421 if (NlsMbCodePageTag == FALSE)
423 /* single-byte code page */
424 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
427 Size = UnicodeSize / sizeof(WCHAR);
429 if (ResultSize != NULL)
432 for (i = 0; i < Size; i++)
434 *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString];
441 /* multi-byte code page */
445 return(STATUS_SUCCESS);
450 RtlUnicodeToMultiByteSize(PULONG MbSize,
451 PWCHAR UnicodeString,
454 if (NlsMbCodePageTag == FALSE)
456 /* single-byte code page */
457 *MbSize = UnicodeSize / sizeof (WCHAR);
461 /* multi-byte code page */
465 return(STATUS_SUCCESS);
470 RtlUnicodeToOemN(PCHAR OemString,
473 PWCHAR UnicodeString,
479 if (NlsMbOemCodePageTag == FALSE)
481 /* single-byte code page */
482 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
485 Size = UnicodeSize / sizeof(WCHAR);
487 if (ResultSize != NULL)
490 for (i = 0; i < Size; i++)
492 *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString];
499 /* multi-byte code page */
503 return(STATUS_SUCCESS);
509 RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
513 PWCHAR UnicodeString,
520 if (NlsData->DbcsFlag == 0)
522 /* single-byte code page */
523 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
526 Size = UnicodeSize / sizeof(WCHAR);
528 if (ResultSize != NULL)
531 for (i = 0; i < Size; i++)
533 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
534 *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc];
541 /* multi-byte code page */
545 return(STATUS_SUCCESS);
548 #endif /* LIBCAPTIVE */
551 RtlUpcaseUnicodeToMultiByteN(PCHAR MbString,
554 PWCHAR UnicodeString,
561 if (NlsMbCodePageTag == FALSE)
563 /* single-byte code page */
564 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
567 Size = UnicodeSize / sizeof(WCHAR);
569 if (ResultSize != NULL)
572 for (i = 0; i < Size; i++)
574 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
575 *MbString = UnicodeToAnsiTable[(unsigned int)wc];
582 /* multi-byte code page */
586 return(STATUS_SUCCESS);
591 RtlUpcaseUnicodeToOemN(PCHAR OemString,
594 PWCHAR UnicodeString,
601 if (NlsMbOemCodePageTag == FALSE)
603 /* single-byte code page */
604 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
607 Size = UnicodeSize / sizeof(WCHAR);
609 if (ResultSize != NULL)
612 for (i = 0; i < Size; i++)
614 wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
615 *OemString = UnicodeToOemTable[(unsigned int)wc];
622 /* multi-byte code page */
626 return(STATUS_SUCCESS);