3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/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 * 1) Add multi-byte translation code.
15 #include <ddk/ntddk.h>
21 /* GLOBALS *******************************************************************/
23 USHORT NlsAnsiCodePage = 0; /* exported */
24 BOOLEAN NlsMbCodePageTag = FALSE; /* exported */
25 PWCHAR NlsAnsiToUnicodeTable = NULL;
26 PCHAR NlsUnicodeToAnsiTable = NULL;
27 PUSHORT NlsLeadByteInfo = NULL;
30 USHORT NlsOemCodePage = 0;
31 BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */
32 PWCHAR NlsOemToUnicodeTable = NULL;
33 PCHAR NlsUnicodeToOemTable = NULL;
34 PUSHORT NlsOemLeadByteInfo = NULL;
37 PUSHORT NlsUnicodeUpcaseTable = NULL;
38 PUSHORT NlsUnicodeLowercaseTable = NULL;
41 /* FUNCTIONS *****************************************************************/
44 * RtlConsoleMultiByteToUnicodeN@24
49 RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP,
59 if (CustomCP->DBCSCodePage == 0)
61 /* single-byte code page */
62 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
63 Size = UnicodeSize / sizeof(WCHAR);
67 if (ResultSize != NULL)
68 *ResultSize = Size * sizeof(WCHAR);
70 for (i = 0; i < Size; i++)
72 *UnicodeString = CustomCP->MultiByteTable[(int)*CustomString];
79 /* multi-byte code page */
84 return STATUS_SUCCESS;
89 RtlDowncaseUnicodeChar (IN WCHAR Source)
97 return Source + (L'a' - L'A');
102 Offset = ((USHORT)Source >> 8);
103 DPRINT("Offset: %hx\n", Offset);
105 Offset = NlsUnicodeLowercaseTable[Offset];
106 DPRINT("Offset: %hx\n", Offset);
108 Offset += (((USHORT)Source & 0x00F0) >> 4);
109 DPRINT("Offset: %hx\n", Offset);
111 Offset = NlsUnicodeLowercaseTable[Offset];
112 DPRINT("Offset: %hx\n", Offset);
114 Offset += ((USHORT)Source & 0x000F);
115 DPRINT("Offset: %hx\n", Offset);
117 Offset = NlsUnicodeLowercaseTable[Offset];
118 DPRINT("Offset: %hx\n", Offset);
120 DPRINT("Result: %hx\n", Source + (SHORT)Offset);
122 return Source + (SHORT)Offset;
127 RtlGetDefaultCodePage(OUT PUSHORT AnsiCodePage,
128 OUT PUSHORT OemCodePage)
130 *AnsiCodePage = NlsAnsiCodePage;
131 *OemCodePage = NlsOemCodePage;
139 RtlInitCodePageTable(IN PUSHORT TableBase,
140 OUT PCPTABLEINFO CodePageTable)
142 PNLS_FILE_HEADER NlsFileHeader;
146 DPRINT("RtlInitCodePageTable() called\n");
148 NlsFileHeader = (PNLS_FILE_HEADER)TableBase;
150 CodePageTable->CodePage = NlsFileHeader->CodePage;
151 CodePageTable->MaximumCharacterSize = NlsFileHeader->MaximumCharacterSize;
152 CodePageTable->DefaultChar = NlsFileHeader->DefaultChar;
153 CodePageTable->UniDefaultChar = NlsFileHeader->UniDefaultChar;
154 CodePageTable->TransDefaultChar = NlsFileHeader->TransDefaultChar;
155 CodePageTable->TransUniDefaultChar = NlsFileHeader->TransUniDefaultChar;
157 RtlCopyMemory(&CodePageTable->LeadByte,
158 &NlsFileHeader->LeadByte,
161 /* Set Pointer to start of multi byte table */
162 Ptr = (PUSHORT)((ULONG_PTR)TableBase + 2 * NlsFileHeader->HeaderSize);
164 /* Get offset to the wide char table */
165 Offset = (USHORT)(*Ptr++) + NlsFileHeader->HeaderSize + 1;
167 /* Set pointer to the multi byte table */
168 CodePageTable->MultiByteTable = Ptr;
170 /* Skip ANSI and OEM table */
175 /* Set pointer to DBCS ranges */
176 CodePageTable->DBCSRanges = (PUSHORT)Ptr;
180 CodePageTable->DBCSCodePage = 1;
181 CodePageTable->DBCSOffsets = (PUSHORT)++Ptr;
185 CodePageTable->DBCSCodePage = 0;
186 CodePageTable->DBCSOffsets = 0;
189 CodePageTable->WideCharTable = (PVOID)((ULONG_PTR)TableBase + 2 * Offset);
197 RtlInitNlsTables(IN PUSHORT AnsiTableBase,
198 IN PUSHORT OemTableBase,
199 IN PUSHORT CaseTableBase,
200 OUT PNLSTABLEINFO NlsTable)
202 DPRINT("RtlInitNlsTables()called\n");
204 if (AnsiTableBase == NULL ||
205 OemTableBase == NULL ||
206 CaseTableBase == NULL)
209 RtlInitCodePageTable (AnsiTableBase,
210 &NlsTable->AnsiTableInfo);
212 RtlInitCodePageTable (OemTableBase,
213 &NlsTable->OemTableInfo);
215 NlsTable->UpperCaseTable = (PUSHORT)CaseTableBase + 2;
216 NlsTable->LowerCaseTable = (PUSHORT)CaseTableBase + *((PUSHORT)CaseTableBase + 1) + 2;
224 RtlMultiByteToUnicodeN (IN OUT PWCHAR UnicodeString,
225 IN ULONG UnicodeSize,
226 OUT PULONG ResultSize,
233 if (NlsMbCodePageTag == FALSE)
235 /* single-byte code page */
236 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
237 Size = UnicodeSize / sizeof(WCHAR);
241 if (ResultSize != NULL)
242 *ResultSize = Size * sizeof(WCHAR);
244 for (i = 0; i < Size; i++)
246 *UnicodeString = NlsAnsiToUnicodeTable[*((unsigned char *) MbString)];
253 /* multi-byte code page */
258 return STATUS_SUCCESS;
266 RtlMultiByteToUnicodeSize (OUT PULONG UnicodeSize,
270 if (NlsMbCodePageTag == FALSE)
272 /* single-byte code page */
273 *UnicodeSize = MbSize * sizeof (WCHAR);
277 /* multi-byte code page */
282 return STATUS_SUCCESS;
290 RtlOemToUnicodeN (PWCHAR UnicodeString,
299 if (NlsMbOemCodePageTag == FALSE)
301 /* single-byte code page */
302 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
303 Size = UnicodeSize / sizeof(WCHAR);
307 if (ResultSize != NULL)
308 *ResultSize = Size * sizeof(WCHAR);
310 for (i = 0; i < Size; i++)
312 *UnicodeString = NlsOemToUnicodeTable[(INT)*OemString];
319 /* multi-byte code page */
324 return STATUS_SUCCESS;
332 RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
334 DPRINT("RtlResetRtlTranslations() called\n");
337 NlsAnsiToUnicodeTable = NlsTable->AnsiTableInfo.MultiByteTable;
338 NlsUnicodeToAnsiTable = NlsTable->AnsiTableInfo.WideCharTable;
339 NlsMbCodePageTag = (NlsTable->AnsiTableInfo.DBCSCodePage != 0);
340 NlsLeadByteInfo = NlsTable->AnsiTableInfo.DBCSOffsets;
341 NlsAnsiCodePage = NlsTable->AnsiTableInfo.CodePage;
342 DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage);
345 NlsOemToUnicodeTable = NlsTable->OemTableInfo.MultiByteTable;
346 NlsUnicodeToOemTable = NlsTable->OemTableInfo.WideCharTable;
347 NlsMbOemCodePageTag = (NlsTable->OemTableInfo.DBCSCodePage != 0);
348 NlsOemLeadByteInfo = NlsTable->OemTableInfo.DBCSOffsets;
349 NlsOemCodePage = NlsTable->OemTableInfo.CodePage;
350 DPRINT("Oem codepage %hu\n", NlsOemCodePage);
352 /* Set Unicode case map data */
353 NlsUnicodeUpcaseTable = NlsTable->UpperCaseTable;
354 NlsUnicodeLowercaseTable = NlsTable->LowerCaseTable;
362 RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
366 PWCHAR UnicodeString,
372 if (CustomCP->DBCSCodePage == 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 = ((PCHAR)CustomCP->WideCharTable)[*UnicodeString];
392 /* multi-byte code page */
397 return STATUS_SUCCESS;
405 RtlUnicodeToMultiByteN (PCHAR MbString,
408 PWCHAR UnicodeString,
414 if (NlsMbCodePageTag == FALSE)
416 /* single-byte code page */
417 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
420 Size = UnicodeSize / sizeof(WCHAR);
422 if (ResultSize != NULL)
425 for (i = 0; i < Size; i++)
427 *MbString = NlsUnicodeToAnsiTable[*UnicodeString];
434 /* multi-byte code page */
439 return STATUS_SUCCESS;
447 RtlUnicodeToMultiByteSize (PULONG MbSize,
448 PWCHAR UnicodeString,
451 if (NlsMbCodePageTag == FALSE)
453 /* single-byte code page */
454 *MbSize = UnicodeSize / sizeof (WCHAR);
458 /* multi-byte code page */
464 return STATUS_SUCCESS;
472 RtlUnicodeToOemN (PCHAR OemString,
475 PWCHAR UnicodeString,
481 if (NlsMbOemCodePageTag == FALSE)
483 /* single-byte code page */
484 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
487 Size = UnicodeSize / sizeof(WCHAR);
489 if (ResultSize != NULL)
492 for (i = 0; i < Size; i++)
494 *OemString = NlsUnicodeToOemTable[*UnicodeString];
501 /* multi-byte code page */
506 return STATUS_SUCCESS;
514 RtlUpcaseUnicodeChar(IN WCHAR Source)
522 return (Source - (L'a' - L'A'));
524 Offset = ((USHORT)Source >> 8);
525 Offset = NlsUnicodeUpcaseTable[Offset];
527 Offset += (((USHORT)Source & 0x00F0) >> 4);
528 Offset = NlsUnicodeUpcaseTable[Offset];
530 Offset += ((USHORT)Source & 0x000F);
531 Offset = NlsUnicodeUpcaseTable[Offset];
533 return Source + (SHORT)Offset;
541 RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP,
545 PWCHAR UnicodeString,
552 if (CustomCP->DBCSCodePage == 0)
554 /* single-byte code page */
555 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
558 Size = UnicodeSize / sizeof(WCHAR);
560 if (ResultSize != NULL)
563 for (i = 0; i < Size; i++)
565 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
566 *CustomString = ((PCHAR)CustomCP->WideCharTable)[UpcaseChar];
573 /* multi-byte code page */
578 return STATUS_SUCCESS;
586 RtlUpcaseUnicodeToMultiByteN (PCHAR MbString,
589 PWCHAR UnicodeString,
596 if (NlsMbCodePageTag == FALSE)
598 /* single-byte code page */
599 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
602 Size = UnicodeSize / sizeof(WCHAR);
604 if (ResultSize != NULL)
607 for (i = 0; i < Size; i++)
609 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
610 *MbString = NlsUnicodeToAnsiTable[UpcaseChar];
617 /* multi-byte code page */
622 return STATUS_SUCCESS;
630 RtlUpcaseUnicodeToOemN (PCHAR OemString,
633 PWCHAR UnicodeString,
640 if (NlsMbOemCodePageTag == FALSE)
642 /* single-byte code page */
643 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
646 Size = UnicodeSize / sizeof(WCHAR);
648 if (ResultSize != NULL)
651 for (i = 0; i < Size; i++)
653 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
654 *OemString = NlsUnicodeToOemTable[UpcaseChar];
661 /* multi-byte code page */
666 return STATUS_SUCCESS;
674 RtlUpperChar (IN CHAR Source)
679 if (NlsMbCodePageTag == FALSE)
681 /* single-byte code page */
684 Unicode = NlsAnsiToUnicodeTable[(INT)Source];
686 /* upcase conversion */
687 Unicode = RtlUpcaseUnicodeChar (Unicode);
689 /* unicode -> ansi */
690 Destination = NlsUnicodeToAnsiTable[Unicode];
694 /* single-byte code page */
695 /* FIXME: implement the multi-byte stuff!! */
696 Destination = Source;