1 /* $Id: nls.c,v 1.6 2001/11/02 09:10:49 ekohl Exp $
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 RtlInitUnicodeString(&UnicodeString
,
171 InitializeObjectAttributes(&ObjectAttributes
,
176 Status
= NtCreateDirectoryObject(&DirectoryHandle
,
179 if (!NT_SUCCESS(Status
))
182 /* Create the 'NlsSectionUnicode' section */
183 RtlInitUnicodeString(&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
);