2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
5 * PURPOSE: National Language Support (NLS) functions
6 * PROGRAMMERS: Emanuele Aliberti
9 /* INCLUDES *****************************************************************/
16 /* GLOBALS *******************************************************************/
18 PUSHORT NlsUnicodeUpcaseTable
= NULL
;
19 PUSHORT NlsUnicodeLowercaseTable
= NULL
;
21 USHORT NlsAnsiCodePage
= 0; /* exported */
22 BOOLEAN NlsMbCodePageTag
= FALSE
; /* exported */
23 PWCHAR NlsAnsiToUnicodeTable
= NULL
;
24 PCHAR NlsUnicodeToAnsiTable
= NULL
;
25 PWCHAR NlsDbcsUnicodeToAnsiTable
= NULL
;
26 PUSHORT NlsLeadByteInfo
= NULL
; /* exported */
29 USHORT NlsOemCodePage
= 0;
30 BOOLEAN NlsMbOemCodePageTag
= FALSE
; /* exported */
31 PWCHAR NlsOemToUnicodeTable
= NULL
;
32 PCHAR NlsUnicodeToOemTable
=NULL
;
33 PWCHAR NlsDbcsUnicodeToOemTable
= NULL
;
34 PUSHORT NlsOemLeadByteInfo
= NULL
; /* exported */
38 /* FUNCTIONS *****************************************************************/
44 RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP
,
54 if (CustomCP
->DBCSCodePage
== 0)
56 /* single-byte code page */
57 if (CustomSize
> (UnicodeSize
/ sizeof(WCHAR
)))
58 Size
= UnicodeSize
/ sizeof(WCHAR
);
62 if (ResultSize
!= NULL
)
63 *ResultSize
= Size
* sizeof(WCHAR
);
65 for (i
= 0; i
< Size
; i
++)
67 *UnicodeString
= CustomCP
->MultiByteTable
[(UCHAR
)*CustomString
];
74 /* multi-byte code page */
79 return(STATUS_SUCCESS
);
85 RtlDowncaseUnicodeChar (IN WCHAR Source
)
93 return Source
+ (L
'a' - L
'A');
98 Offset
= ((USHORT
)Source
>> 8);
99 DPRINT("Offset: %hx\n", Offset
);
101 Offset
= NlsUnicodeLowercaseTable
[Offset
];
102 DPRINT("Offset: %hx\n", Offset
);
104 Offset
+= (((USHORT
)Source
& 0x00F0) >> 4);
105 DPRINT("Offset: %hx\n", Offset
);
107 Offset
= NlsUnicodeLowercaseTable
[Offset
];
108 DPRINT("Offset: %hx\n", Offset
);
110 Offset
+= ((USHORT
)Source
& 0x000F);
111 DPRINT("Offset: %hx\n", Offset
);
113 Offset
= NlsUnicodeLowercaseTable
[Offset
];
114 DPRINT("Offset: %hx\n", Offset
);
116 DPRINT("Result: %hx\n", Source
+ (SHORT
)Offset
);
118 return Source
+ (SHORT
)Offset
;
128 RtlGetDefaultCodePage(OUT PUSHORT AnsiCodePage
,
129 OUT PUSHORT OemCodePage
)
131 *AnsiCodePage
= NlsAnsiCodePage
;
132 *OemCodePage
= NlsOemCodePage
;
142 RtlInitCodePageTable(IN PUSHORT TableBase
,
143 OUT PCPTABLEINFO CodePageTable
)
145 PNLS_FILE_HEADER NlsFileHeader
;
149 DPRINT("RtlInitCodePageTable() called\n");
151 NlsFileHeader
= (PNLS_FILE_HEADER
)TableBase
;
153 CodePageTable
->CodePage
= NlsFileHeader
->CodePage
;
154 CodePageTable
->MaximumCharacterSize
= NlsFileHeader
->MaximumCharacterSize
;
155 CodePageTable
->DefaultChar
= NlsFileHeader
->DefaultChar
;
156 CodePageTable
->UniDefaultChar
= NlsFileHeader
->UniDefaultChar
;
157 CodePageTable
->TransDefaultChar
= NlsFileHeader
->TransDefaultChar
;
158 CodePageTable
->TransUniDefaultChar
= NlsFileHeader
->TransUniDefaultChar
;
160 RtlCopyMemory(&CodePageTable
->LeadByte
,
161 &NlsFileHeader
->LeadByte
,
164 /* Set Pointer to start of multi byte table */
165 Ptr
= (PUSHORT
)((ULONG_PTR
)TableBase
+ 2 * NlsFileHeader
->HeaderSize
);
167 /* Get offset to the wide char table */
168 Offset
= (USHORT
)(*Ptr
++) + NlsFileHeader
->HeaderSize
+ 1;
170 /* Set pointer to the multi byte table */
171 CodePageTable
->MultiByteTable
= Ptr
;
173 /* Skip ANSI and OEM table */
178 /* Set pointer to DBCS ranges */
179 CodePageTable
->DBCSRanges
= (PUSHORT
)Ptr
;
183 CodePageTable
->DBCSCodePage
= 1;
184 CodePageTable
->DBCSOffsets
= (PUSHORT
)++Ptr
;
188 CodePageTable
->DBCSCodePage
= 0;
189 CodePageTable
->DBCSOffsets
= 0;
192 CodePageTable
->WideCharTable
= (PVOID
)((ULONG_PTR
)TableBase
+ 2 * Offset
);
202 RtlInitNlsTables(IN PUSHORT AnsiTableBase
,
203 IN PUSHORT OemTableBase
,
204 IN PUSHORT CaseTableBase
,
205 OUT PNLSTABLEINFO NlsTable
)
207 DPRINT("RtlInitNlsTables()called\n");
209 if (AnsiTableBase
== NULL
||
210 OemTableBase
== NULL
||
211 CaseTableBase
== NULL
)
214 RtlInitCodePageTable (AnsiTableBase
,
215 &NlsTable
->AnsiTableInfo
);
217 RtlInitCodePageTable (OemTableBase
,
218 &NlsTable
->OemTableInfo
);
220 NlsTable
->UpperCaseTable
= (PUSHORT
)CaseTableBase
+ 2;
221 NlsTable
->LowerCaseTable
= (PUSHORT
)CaseTableBase
+ *((PUSHORT
)CaseTableBase
+ 1) + 2;
229 RtlMultiByteToUnicodeN(
230 IN PWCHAR UnicodeString
,
231 IN ULONG UnicodeSize
,
232 IN PULONG ResultSize
,
239 if (NlsMbCodePageTag
== FALSE
)
241 /* single-byte code page */
242 if (MbSize
> (UnicodeSize
/ sizeof(WCHAR
)))
243 Size
= UnicodeSize
/ sizeof(WCHAR
);
247 if (ResultSize
!= NULL
)
248 *ResultSize
= Size
* sizeof(WCHAR
);
250 for (i
= 0; i
< Size
; i
++)
251 UnicodeString
[i
] = NlsAnsiToUnicodeTable
[(UCHAR
)MbString
[i
]];
255 /* multi-byte code page */
260 return(STATUS_SUCCESS
);
270 RtlMultiByteToUnicodeSize(PULONG UnicodeSize
,
276 if (!NlsMbCodePageTag
)
278 /* single-byte code page */
279 *UnicodeSize
= MbSize
* sizeof (WCHAR
);
283 /* multi-byte code page */
286 if (NlsLeadByteInfo
[*(PUCHAR
)MbString
++])
290 /* partial char, ignore it */
302 /* Increase returned size */
306 /* Return final size */
307 *UnicodeSize
= Length
* sizeof(WCHAR
);
311 return STATUS_SUCCESS
;
320 RtlOemToUnicodeN (PWCHAR UnicodeString
,
329 if (NlsMbOemCodePageTag
== FALSE
)
331 /* single-byte code page */
332 if (OemSize
> (UnicodeSize
/ sizeof(WCHAR
)))
333 Size
= UnicodeSize
/ sizeof(WCHAR
);
337 if (ResultSize
!= NULL
)
338 *ResultSize
= Size
* sizeof(WCHAR
);
340 for (i
= 0; i
< Size
; i
++)
342 *UnicodeString
= NlsOemToUnicodeTable
[(INT
)*OemString
];
349 /* multi-byte code page */
354 return STATUS_SUCCESS
;
363 RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable
)
365 DPRINT("RtlResetRtlTranslations() called\n");
368 NlsAnsiToUnicodeTable
= NlsTable
->AnsiTableInfo
.MultiByteTable
;
369 NlsUnicodeToAnsiTable
= NlsTable
->AnsiTableInfo
.WideCharTable
;
370 NlsDbcsUnicodeToAnsiTable
= (PWCHAR
)NlsTable
->AnsiTableInfo
.WideCharTable
;
371 NlsMbCodePageTag
= (NlsTable
->AnsiTableInfo
.DBCSCodePage
!= 0);
372 NlsLeadByteInfo
= NlsTable
->AnsiTableInfo
.DBCSOffsets
;
373 NlsAnsiCodePage
= NlsTable
->AnsiTableInfo
.CodePage
;
374 DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage
);
377 NlsOemToUnicodeTable
= NlsTable
->OemTableInfo
.MultiByteTable
;
378 NlsUnicodeToOemTable
= NlsTable
->OemTableInfo
.WideCharTable
;
379 NlsDbcsUnicodeToOemTable
= (PWCHAR
)NlsTable
->OemTableInfo
.WideCharTable
;
380 NlsMbOemCodePageTag
= (NlsTable
->OemTableInfo
.DBCSCodePage
!= 0);
381 NlsOemLeadByteInfo
= NlsTable
->OemTableInfo
.DBCSOffsets
;
382 NlsOemCodePage
= NlsTable
->OemTableInfo
.CodePage
;
383 DPRINT("Oem codepage %hu\n", NlsOemCodePage
);
385 /* Set Unicode case map data */
386 NlsUnicodeUpcaseTable
= NlsTable
->UpperCaseTable
;
387 NlsUnicodeLowercaseTable
= NlsTable
->LowerCaseTable
;
396 RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP
,
400 PWCHAR UnicodeString
,
406 if (CustomCP
->DBCSCodePage
== 0)
408 /* single-byte code page */
409 if (UnicodeSize
> (CustomSize
* sizeof(WCHAR
)))
412 Size
= UnicodeSize
/ sizeof(WCHAR
);
414 if (ResultSize
!= NULL
)
417 for (i
= 0; i
< Size
; i
++)
419 *CustomString
= ((PCHAR
)CustomCP
->WideCharTable
)[*UnicodeString
];
426 /* multi-byte code page */
431 return STATUS_SUCCESS
;
440 RtlUnicodeToMultiByteN (PCHAR MbString
,
443 PWCHAR UnicodeString
,
449 if (NlsMbCodePageTag
== FALSE
)
451 /* single-byte code page */
452 Size
= (UnicodeSize
> (MbSize
* sizeof (WCHAR
)))
454 : (UnicodeSize
/ sizeof (WCHAR
));
456 if (ResultSize
!= NULL
)
461 for (i
= 0; i
< Size
; i
++)
463 *MbString
++ = NlsUnicodeToAnsiTable
[*UnicodeString
++];
468 /* multi-byte code page */
473 return STATUS_SUCCESS
;
481 RtlUnicodeToMultiByteSize(PULONG MbSize
,
482 PWCHAR UnicodeString
,
485 ULONG UnicodeLength
= UnicodeSize
/ sizeof(WCHAR
);
488 if (!NlsMbCodePageTag
)
490 /* single-byte code page */
491 *MbSize
= UnicodeLength
;
495 /* multi-byte code page */
496 while (UnicodeLength
--)
498 if (HIBYTE(NlsUnicodeToAnsiTable
[*UnicodeString
++]))
500 MbLength
+= sizeof(WCHAR
);
512 return STATUS_SUCCESS
;
519 RtlUnicodeToOemN (PCHAR OemString
,
522 PWCHAR UnicodeString
,
528 if (NlsMbOemCodePageTag
== FALSE
)
530 /* single-byte code page */
531 if (UnicodeSize
> (OemSize
* sizeof(WCHAR
)))
534 Size
= UnicodeSize
/ sizeof(WCHAR
);
536 if (ResultSize
!= NULL
)
539 for (i
= 0; i
< Size
; i
++)
541 *OemString
= NlsUnicodeToOemTable
[*UnicodeString
];
548 /* multi-byte code page */
553 return STATUS_SUCCESS
;
563 RtlUpcaseUnicodeChar(IN WCHAR Source
)
571 return (Source
- (L
'a' - L
'A'));
573 Offset
= ((USHORT
)Source
>> 8);
574 Offset
= NlsUnicodeUpcaseTable
[Offset
];
576 Offset
+= (((USHORT
)Source
& 0x00F0) >> 4);
577 Offset
= NlsUnicodeUpcaseTable
[Offset
];
579 Offset
+= ((USHORT
)Source
& 0x000F);
580 Offset
= NlsUnicodeUpcaseTable
[Offset
];
582 return Source
+ (SHORT
)Offset
;
591 RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP
,
595 PWCHAR UnicodeString
,
602 if (CustomCP
->DBCSCodePage
== 0)
604 /* single-byte code page */
605 if (UnicodeSize
> (CustomSize
* sizeof(WCHAR
)))
608 Size
= UnicodeSize
/ sizeof(WCHAR
);
610 if (ResultSize
!= NULL
)
613 for (i
= 0; i
< Size
; i
++)
615 UpcaseChar
= RtlUpcaseUnicodeChar(*UnicodeString
);
616 *CustomString
= ((PCHAR
)CustomCP
->WideCharTable
)[UpcaseChar
];
623 /* multi-byte code page */
628 return STATUS_SUCCESS
;
636 RtlUpcaseUnicodeToMultiByteN (PCHAR MbString
,
639 PWCHAR UnicodeString
,
646 if (NlsMbCodePageTag
== FALSE
)
648 /* single-byte code page */
649 if (UnicodeSize
> (MbSize
* sizeof(WCHAR
)))
652 Size
= UnicodeSize
/ sizeof(WCHAR
);
654 if (ResultSize
!= NULL
)
657 for (i
= 0; i
< Size
; i
++)
659 UpcaseChar
= RtlUpcaseUnicodeChar(*UnicodeString
);
660 *MbString
= NlsUnicodeToAnsiTable
[UpcaseChar
];
667 /* multi-byte code page */
672 return STATUS_SUCCESS
;
680 RtlUpcaseUnicodeToOemN (PCHAR OemString
,
683 PWCHAR UnicodeString
,
690 if (NlsMbOemCodePageTag
== FALSE
)
692 /* single-byte code page */
693 if (UnicodeSize
> (OemSize
* sizeof(WCHAR
)))
696 Size
= UnicodeSize
/ sizeof(WCHAR
);
698 if (ResultSize
!= NULL
)
701 for (i
= 0; i
< Size
; i
++)
703 UpcaseChar
= RtlUpcaseUnicodeChar(*UnicodeString
);
704 *OemString
= NlsUnicodeToOemTable
[UpcaseChar
];
711 /* multi-byte code page */
716 return STATUS_SUCCESS
;
725 RtlUpperChar (IN CHAR Source
)
730 if (NlsMbCodePageTag
== FALSE
)
732 /* single-byte code page */
735 Unicode
= NlsAnsiToUnicodeTable
[(UCHAR
)Source
];
737 /* upcase conversion */
738 Unicode
= RtlUpcaseUnicodeChar (Unicode
);
740 /* unicode -> ansi */
741 Destination
= NlsUnicodeToAnsiTable
[(USHORT
)Unicode
];
745 /* multi-byte code page */
747 Destination
= Source
;