3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
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.
21 /* GLOBALS *******************************************************************/
23 PUSHORT NlsUnicodeUpcaseTable
= NULL
;
24 PUSHORT NlsUnicodeLowercaseTable
= NULL
;
26 USHORT NlsAnsiCodePage
= 0; /* exported */
27 BOOLEAN NlsMbCodePageTag
= FALSE
; /* exported */
28 PWCHAR NlsAnsiToUnicodeTable
= NULL
;
29 PCHAR NlsUnicodeToAnsiTable
= NULL
;
30 PWCHAR NlsDbcsUnicodeToAnsiTable
= NULL
;
31 PUSHORT NlsLeadByteInfo
= NULL
; /* exported */
34 USHORT NlsOemCodePage
= 0;
35 BOOLEAN NlsMbOemCodePageTag
= FALSE
; /* exported */
36 PWCHAR NlsOemToUnicodeTable
= NULL
;
37 PCHAR NlsUnicodeToOemTable
=NULL
;
38 PWCHAR NlsDbcsUnicodeToOemTable
= NULL
;
39 PUSHORT NlsOemLeadByteInfo
= NULL
; /* exported */
46 /* FUNCTIONS *****************************************************************/
57 RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP
,
67 if (CustomCP
->DBCSCodePage
== 0)
69 /* single-byte code page */
70 if (CustomSize
> (UnicodeSize
/ sizeof(WCHAR
)))
71 Size
= UnicodeSize
/ sizeof(WCHAR
);
75 if (ResultSize
!= NULL
)
76 *ResultSize
= Size
* sizeof(WCHAR
);
78 for (i
= 0; i
< Size
; i
++)
80 *UnicodeString
= CustomCP
->MultiByteTable
[(UCHAR
)*CustomString
];
87 /* multi-byte code page */
92 return(STATUS_SUCCESS
);
98 RtlDowncaseUnicodeChar (IN WCHAR Source
)
106 return Source
+ (L
'a' - L
'A');
111 Offset
= ((USHORT
)Source
>> 8);
112 DPRINT("Offset: %hx\n", Offset
);
114 Offset
= NlsUnicodeLowercaseTable
[Offset
];
115 DPRINT("Offset: %hx\n", Offset
);
117 Offset
+= (((USHORT
)Source
& 0x00F0) >> 4);
118 DPRINT("Offset: %hx\n", Offset
);
120 Offset
= NlsUnicodeLowercaseTable
[Offset
];
121 DPRINT("Offset: %hx\n", Offset
);
123 Offset
+= ((USHORT
)Source
& 0x000F);
124 DPRINT("Offset: %hx\n", Offset
);
126 Offset
= NlsUnicodeLowercaseTable
[Offset
];
127 DPRINT("Offset: %hx\n", Offset
);
129 DPRINT("Result: %hx\n", Source
+ (SHORT
)Offset
);
131 return Source
+ (SHORT
)Offset
;
141 RtlGetDefaultCodePage(OUT PUSHORT AnsiCodePage
,
142 OUT PUSHORT OemCodePage
)
144 *AnsiCodePage
= NlsAnsiCodePage
;
145 *OemCodePage
= NlsOemCodePage
;
155 RtlInitCodePageTable(IN PUSHORT TableBase
,
156 OUT PCPTABLEINFO CodePageTable
)
158 PNLS_FILE_HEADER NlsFileHeader
;
162 DPRINT("RtlInitCodePageTable() called\n");
164 NlsFileHeader
= (PNLS_FILE_HEADER
)TableBase
;
166 CodePageTable
->CodePage
= NlsFileHeader
->CodePage
;
167 CodePageTable
->MaximumCharacterSize
= NlsFileHeader
->MaximumCharacterSize
;
168 CodePageTable
->DefaultChar
= NlsFileHeader
->DefaultChar
;
169 CodePageTable
->UniDefaultChar
= NlsFileHeader
->UniDefaultChar
;
170 CodePageTable
->TransDefaultChar
= NlsFileHeader
->TransDefaultChar
;
171 CodePageTable
->TransUniDefaultChar
= NlsFileHeader
->TransUniDefaultChar
;
173 RtlCopyMemory(&CodePageTable
->LeadByte
,
174 &NlsFileHeader
->LeadByte
,
177 /* Set Pointer to start of multi byte table */
178 Ptr
= (PUSHORT
)((ULONG_PTR
)TableBase
+ 2 * NlsFileHeader
->HeaderSize
);
180 /* Get offset to the wide char table */
181 Offset
= (USHORT
)(*Ptr
++) + NlsFileHeader
->HeaderSize
+ 1;
183 /* Set pointer to the multi byte table */
184 CodePageTable
->MultiByteTable
= Ptr
;
186 /* Skip ANSI and OEM table */
191 /* Set pointer to DBCS ranges */
192 CodePageTable
->DBCSRanges
= (PUSHORT
)Ptr
;
196 CodePageTable
->DBCSCodePage
= 1;
197 CodePageTable
->DBCSOffsets
= (PUSHORT
)++Ptr
;
201 CodePageTable
->DBCSCodePage
= 0;
202 CodePageTable
->DBCSOffsets
= 0;
205 CodePageTable
->WideCharTable
= (PVOID
)((ULONG_PTR
)TableBase
+ 2 * Offset
);
215 RtlInitNlsTables(IN PUSHORT AnsiTableBase
,
216 IN PUSHORT OemTableBase
,
217 IN PUSHORT CaseTableBase
,
218 OUT PNLSTABLEINFO NlsTable
)
220 DPRINT("RtlInitNlsTables()called\n");
222 if (AnsiTableBase
== NULL
||
223 OemTableBase
== NULL
||
224 CaseTableBase
== NULL
)
227 RtlInitCodePageTable (AnsiTableBase
,
228 &NlsTable
->AnsiTableInfo
);
230 RtlInitCodePageTable (OemTableBase
,
231 &NlsTable
->OemTableInfo
);
233 NlsTable
->UpperCaseTable
= (PUSHORT
)CaseTableBase
+ 2;
234 NlsTable
->LowerCaseTable
= (PUSHORT
)CaseTableBase
+ *((PUSHORT
)CaseTableBase
+ 1) + 2;
242 RtlMultiByteToUnicodeN(
243 IN PWCHAR UnicodeString
,
244 IN ULONG UnicodeSize
,
245 IN PULONG ResultSize
,
252 if (NlsMbCodePageTag
== FALSE
)
254 /* single-byte code page */
255 if (MbSize
> (UnicodeSize
/ sizeof(WCHAR
)))
256 Size
= UnicodeSize
/ sizeof(WCHAR
);
260 if (ResultSize
!= NULL
)
261 *ResultSize
= Size
* sizeof(WCHAR
);
263 for (i
= 0; i
< Size
; i
++)
264 UnicodeString
[i
] = NlsAnsiToUnicodeTable
[(UCHAR
)MbString
[i
]];
268 /* multi-byte code page */
273 return(STATUS_SUCCESS
);
282 RtlMultiByteToUnicodeSize(PULONG UnicodeSize
,
288 if (NlsMbCodePageTag
== FALSE
)
290 /* single-byte code page */
291 *UnicodeSize
= MbSize
* sizeof (WCHAR
);
295 /* multi-byte code page */
296 for (Length
= 0; MbSize
; MbSize
--, MbString
++, Length
++)
298 if (NlsLeadByteInfo
[(UCHAR
)*MbString
] != 0)
301 break; /* partial char, ignore it */
306 *UnicodeSize
= Length
* sizeof(WCHAR
);
309 return STATUS_SUCCESS
;
318 RtlOemToUnicodeN (PWCHAR UnicodeString
,
327 if (NlsMbOemCodePageTag
== FALSE
)
329 /* single-byte code page */
330 if (OemSize
> (UnicodeSize
/ sizeof(WCHAR
)))
331 Size
= UnicodeSize
/ sizeof(WCHAR
);
335 if (ResultSize
!= NULL
)
336 *ResultSize
= Size
* sizeof(WCHAR
);
338 for (i
= 0; i
< Size
; i
++)
340 *UnicodeString
= NlsOemToUnicodeTable
[(INT
)*OemString
];
347 /* multi-byte code page */
352 return STATUS_SUCCESS
;
361 RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable
)
363 DPRINT("RtlResetRtlTranslations() called\n");
366 NlsAnsiToUnicodeTable
= NlsTable
->AnsiTableInfo
.MultiByteTable
;
367 NlsUnicodeToAnsiTable
= NlsTable
->AnsiTableInfo
.WideCharTable
;
368 NlsDbcsUnicodeToAnsiTable
= (PWCHAR
)NlsTable
->AnsiTableInfo
.WideCharTable
;
369 NlsMbCodePageTag
= (NlsTable
->AnsiTableInfo
.DBCSCodePage
!= 0);
370 NlsLeadByteInfo
= NlsTable
->AnsiTableInfo
.DBCSOffsets
;
371 NlsAnsiCodePage
= NlsTable
->AnsiTableInfo
.CodePage
;
372 DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage
);
375 NlsOemToUnicodeTable
= NlsTable
->OemTableInfo
.MultiByteTable
;
376 NlsUnicodeToOemTable
= NlsTable
->OemTableInfo
.WideCharTable
;
377 NlsDbcsUnicodeToOemTable
= (PWCHAR
)NlsTable
->OemTableInfo
.WideCharTable
;
378 NlsMbOemCodePageTag
= (NlsTable
->OemTableInfo
.DBCSCodePage
!= 0);
379 NlsOemLeadByteInfo
= NlsTable
->OemTableInfo
.DBCSOffsets
;
380 NlsOemCodePage
= NlsTable
->OemTableInfo
.CodePage
;
381 DPRINT("Oem codepage %hu\n", NlsOemCodePage
);
383 /* Set Unicode case map data */
384 NlsUnicodeUpcaseTable
= NlsTable
->UpperCaseTable
;
385 NlsUnicodeLowercaseTable
= NlsTable
->LowerCaseTable
;
394 RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP
,
398 PWCHAR UnicodeString
,
404 if (CustomCP
->DBCSCodePage
== 0)
406 /* single-byte code page */
407 if (UnicodeSize
> (CustomSize
* sizeof(WCHAR
)))
410 Size
= UnicodeSize
/ sizeof(WCHAR
);
412 if (ResultSize
!= NULL
)
415 for (i
= 0; i
< Size
; i
++)
417 *CustomString
= ((PCHAR
)CustomCP
->WideCharTable
)[*UnicodeString
];
424 /* multi-byte code page */
429 return STATUS_SUCCESS
;
438 RtlUnicodeToMultiByteN (PCHAR MbString
,
441 PWCHAR UnicodeString
,
447 if (NlsMbCodePageTag
== FALSE
)
449 /* single-byte code page */
450 if (UnicodeSize
> (MbSize
* sizeof(WCHAR
)))
453 Size
= UnicodeSize
/ sizeof(WCHAR
);
455 if (ResultSize
!= NULL
)
458 for (i
= 0; i
< Size
; i
++)
460 *MbString
= NlsUnicodeToAnsiTable
[*UnicodeString
];
467 /* multi-byte code page */
472 return STATUS_SUCCESS
;
480 RtlUnicodeToMultiByteSize(PULONG MbSize
,
481 PWCHAR UnicodeString
,
487 if (NlsMbCodePageTag
== FALSE
)
489 /* single-byte code page */
490 *MbSize
= UnicodeSize
/ sizeof (WCHAR
);
494 /* multi-byte code page */
495 UnicodeLength
= UnicodeSize
/ sizeof(WCHAR
);
497 while (UnicodeLength
> 0)
499 if (NlsLeadByteInfo
[(USHORT
)*UnicodeString
] & 0xff00)
510 return(STATUS_SUCCESS
);
520 RtlUnicodeToOemN (PCHAR OemString
,
523 PWCHAR UnicodeString
,
529 if (NlsMbOemCodePageTag
== FALSE
)
531 /* single-byte code page */
532 if (UnicodeSize
> (OemSize
* sizeof(WCHAR
)))
535 Size
= UnicodeSize
/ sizeof(WCHAR
);
537 if (ResultSize
!= NULL
)
540 for (i
= 0; i
< Size
; i
++)
542 *OemString
= NlsUnicodeToOemTable
[*UnicodeString
];
549 /* multi-byte code page */
554 return STATUS_SUCCESS
;
564 RtlUpcaseUnicodeChar(IN WCHAR Source
)
572 return (Source
- (L
'a' - L
'A'));
574 Offset
= ((USHORT
)Source
>> 8);
575 Offset
= NlsUnicodeUpcaseTable
[Offset
];
577 Offset
+= (((USHORT
)Source
& 0x00F0) >> 4);
578 Offset
= NlsUnicodeUpcaseTable
[Offset
];
580 Offset
+= ((USHORT
)Source
& 0x000F);
581 Offset
= NlsUnicodeUpcaseTable
[Offset
];
583 return Source
+ (SHORT
)Offset
;
592 RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP
,
596 PWCHAR UnicodeString
,
603 if (CustomCP
->DBCSCodePage
== 0)
605 /* single-byte code page */
606 if (UnicodeSize
> (CustomSize
* sizeof(WCHAR
)))
609 Size
= UnicodeSize
/ sizeof(WCHAR
);
611 if (ResultSize
!= NULL
)
614 for (i
= 0; i
< Size
; i
++)
616 UpcaseChar
= RtlUpcaseUnicodeChar(*UnicodeString
);
617 *CustomString
= ((PCHAR
)CustomCP
->WideCharTable
)[UpcaseChar
];
624 /* multi-byte code page */
629 return STATUS_SUCCESS
;
637 RtlUpcaseUnicodeToMultiByteN (PCHAR MbString
,
640 PWCHAR UnicodeString
,
647 if (NlsMbCodePageTag
== FALSE
)
649 /* single-byte code page */
650 if (UnicodeSize
> (MbSize
* sizeof(WCHAR
)))
653 Size
= UnicodeSize
/ sizeof(WCHAR
);
655 if (ResultSize
!= NULL
)
658 for (i
= 0; i
< Size
; i
++)
660 UpcaseChar
= RtlUpcaseUnicodeChar(*UnicodeString
);
661 *MbString
= NlsUnicodeToAnsiTable
[UpcaseChar
];
668 /* multi-byte code page */
673 return STATUS_SUCCESS
;
681 RtlUpcaseUnicodeToOemN (PCHAR OemString
,
684 PWCHAR UnicodeString
,
691 if (NlsMbOemCodePageTag
== FALSE
)
693 /* single-byte code page */
694 if (UnicodeSize
> (OemSize
* sizeof(WCHAR
)))
697 Size
= UnicodeSize
/ sizeof(WCHAR
);
699 if (ResultSize
!= NULL
)
702 for (i
= 0; i
< Size
; i
++)
704 UpcaseChar
= RtlUpcaseUnicodeChar(*UnicodeString
);
705 *OemString
= NlsUnicodeToOemTable
[UpcaseChar
];
712 /* multi-byte code page */
717 return STATUS_SUCCESS
;
726 RtlUpperChar (IN CHAR Source
)
731 if (NlsMbCodePageTag
== FALSE
)
733 /* single-byte code page */
736 Unicode
= NlsAnsiToUnicodeTable
[(UCHAR
)Source
];
738 /* upcase conversion */
739 Unicode
= RtlUpcaseUnicodeChar (Unicode
);
741 /* unicode -> ansi */
742 Destination
= NlsUnicodeToAnsiTable
[(USHORT
)Unicode
];
746 /* multi-byte code page */
748 Destination
= Source
;