branch update for HEAD-2003021201
[reactos.git] / ntoskrnl / rtl / nls.c
1 /* $Id$
2  *
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
7  * UPDATE HISTORY:
8  *                  20/08/99 Created by Emanuele Aliberti
9  *                  10/11/99 Added translation functions.
10  *
11  * NOTE:
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.
15  *
16  * TODO:
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.
21  */
22
23 #ifdef WIN32_REGDBG
24 #include "cm_win32.h"
25 #else
26
27 #include <ddk/ntddk.h>
28 //#include <internal/nls.h>
29
30 #define NDEBUG
31 #include <internal/debug.h>
32
33 #endif
34
35 /* GLOBALS *******************************************************************/
36
37 BOOLEAN NlsMbCodePageTag = FALSE;
38 BOOLEAN NlsMbOemCodePageTag = FALSE;
39
40 BYTE NlsLeadByteInfo = 0; /* ? */
41
42 USHORT NlsOemLeadByteInfo = 0;
43
44 USHORT NlsAnsiCodePage = 0;
45 USHORT NlsOemCodePage = 0; /* not exported */
46
47 PWCHAR AnsiToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */
48 PWCHAR OemToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */
49
50 PCHAR UnicodeToAnsiTable = NULL; /* size: 65536*sizeof(CHAR) */
51 PCHAR UnicodeToOemTable =NULL; /* size: 65536*sizeof(CHAR) */
52
53 PWCHAR UnicodeUpcaseTable = NULL; /* size: 65536*sizeof(WCHAR) */
54 PWCHAR UnicodeLowercaseTable = NULL; /* size: 65536*sizeof(WCHAR) */
55
56
57 /* FUNCTIONS *****************************************************************/
58
59 VOID
60 RtlpInitNlsTables(VOID)
61 {
62   INT i;
63   PCHAR pc;
64   PWCHAR pwc;
65
66   /* allocate and initialize ansi->unicode table */
67   AnsiToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
68   if (AnsiToUnicodeTable == NULL)
69     {
70       DbgPrint("Allocation of 'AnsiToUnicodeTable' failed\n");
71       KeBugCheck(0);
72     }
73
74   pwc = AnsiToUnicodeTable;
75   for (i = 0; i < 256; i++, pwc++)
76     *pwc = (WCHAR)i;
77
78   /* allocate and initialize oem->unicode table */
79   OemToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
80   if (OemToUnicodeTable == NULL)
81     {
82       DbgPrint("Allocation of 'OemToUnicodeTable' failed\n");
83       KeBugCheck(0);
84     }
85
86   pwc = OemToUnicodeTable;
87   for (i = 0; i < 256; i++, pwc++)
88     *pwc = (WCHAR)i;
89
90   /* allocate and initialize unicode->ansi table */
91   UnicodeToAnsiTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR));
92   if (UnicodeToAnsiTable == NULL)
93     {
94       DbgPrint("Allocation of 'UnicodeToAnsiTable' failed\n");
95       KeBugCheck(0);
96     }
97
98   pc = UnicodeToAnsiTable;
99   for (i = 0; i < 256; i++, pc++)
100     *pc = (CHAR)i;
101   for (; i < 65536; i++, pc++)
102     *pc = 0;
103
104   /* allocate and initialize unicode->oem table */
105   UnicodeToOemTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR));
106   if (UnicodeToOemTable == NULL)
107     {
108       DbgPrint("Allocation of 'UnicodeToOemTable' failed\n");
109       KeBugCheck(0);
110     }
111
112   pc = UnicodeToOemTable;
113   for (i = 0; i < 256; i++, pc++)
114     *pc = (CHAR)i;
115   for (; i < 65536; i++, pc++)
116     *pc = 0;
117
118   /* allocate and initialize unicode upcase table */
119   UnicodeUpcaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR));
120   if (UnicodeUpcaseTable == NULL)
121     {
122       DbgPrint("Allocation of 'UnicodeUpcaseTable' failed\n");
123       KeBugCheck(0);
124     }
125
126   pwc = UnicodeUpcaseTable;
127   for (i = 0; i < 65536; i++, pwc++)
128     *pwc = (WCHAR)i;
129   for (i = 'a'; i < ('z'+ 1); i++)
130     UnicodeUpcaseTable[i] = (WCHAR)i + (L'A' - L'a');
131
132
133   /* allocate and initialize unicode lowercase table */
134   UnicodeLowercaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR));
135   if (UnicodeLowercaseTable == NULL)
136     {
137       DbgPrint("Allocation of 'UnicodeLowercaseTable' failed\n");
138       KeBugCheck(0);
139     }
140
141   pwc = UnicodeLowercaseTable;
142   for (i = 0; i < 65536; i++, pwc++)
143     *pwc = (WCHAR)i;
144   for (i = 'A'; i < ('Z'+ 1); i++)
145     UnicodeLowercaseTable[i] = (WCHAR)i - (L'A' - L'a');
146
147   /* FIXME: initialize codepage info */
148
149 }
150
151 #ifndef LIBCAPTIVE
152
153 NTSTATUS
154 RtlpInitNlsSections(ULONG Mod1Start,
155                     ULONG Mod1End,
156                     ULONG Mod2Start,
157                     ULONG Mod2End,
158                     ULONG Mod3Start,
159                     ULONG Mod3End)
160 {
161   UNICODE_STRING UnicodeString;
162   OBJECT_ATTRIBUTES ObjectAttributes;
163   HANDLE DirectoryHandle;
164   HANDLE SectionHandle;
165   NTSTATUS Status;
166   LARGE_INTEGER SectionSize;
167
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);
174
175   /* Create the '\NLS' directory */
176   RtlInitUnicodeStringFromLiteral(&UnicodeString,
177                        L"\\NLS");
178   InitializeObjectAttributes(&ObjectAttributes,
179                              &UnicodeString,
180                              OBJ_PERMANENT,
181                              NULL,
182                              NULL);
183   Status = NtCreateDirectoryObject(&DirectoryHandle,
184                                    0,
185                                    &ObjectAttributes);
186   if (!NT_SUCCESS(Status))
187     return(Status);
188
189   /* Create the 'NlsSectionUnicode' section */
190   RtlInitUnicodeStringFromLiteral(&UnicodeString,
191                        L"NlsSectionUnicode");
192   InitializeObjectAttributes(&ObjectAttributes,
193                              &UnicodeString,
194                              OBJ_PERMANENT,
195                              DirectoryHandle,
196                              NULL);
197   SectionSize.QuadPart = (Mod1End - Mod1Start) +
198     (Mod2End - Mod2Start) + (Mod3End - Mod3Start);
199   DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart);
200
201   Status = NtCreateSection(&SectionHandle,
202                            SECTION_ALL_ACCESS,
203                            &ObjectAttributes,
204                            &SectionSize,
205                            PAGE_READWRITE,
206                            0,
207                            NULL);
208   if (!NT_SUCCESS(Status))
209     return(Status);
210
211
212   /* create and initialize code page table */
213
214   /* map the nls table into the 'NlsSectionUnicode' section */
215
216
217   NtClose(SectionHandle);
218   NtClose(DirectoryHandle);
219
220   return(STATUS_SUCCESS);
221 }
222
223
224 NTSTATUS STDCALL
225 RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData,
226                       PWCHAR UnicodeString,
227                       ULONG UnicodeSize,
228                       PULONG ResultSize,
229                       PCHAR CustomString,
230                       ULONG CustomSize)
231 {
232   ULONG Size = 0;
233   ULONG i;
234
235   if (NlsData->DbcsFlag == FALSE)
236     {
237       /* single-byte code page */
238       if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
239         Size = UnicodeSize / sizeof(WCHAR);
240       else
241         Size = CustomSize;
242
243       if (ResultSize != NULL)
244         *ResultSize = Size * sizeof(WCHAR);
245
246       for (i = 0; i < Size; i++)
247         {
248           *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString];
249           UnicodeString++;
250           CustomString++;
251         }
252     }
253   else
254     {
255       /* multi-byte code page */
256       /* FIXME */
257     }
258
259   return(STATUS_SUCCESS);
260 }
261
262
263 VOID STDCALL
264 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
265                       PUSHORT OemCodePage)
266 {
267   *AnsiCodePage = NlsAnsiCodePage;
268   *OemCodePage = NlsOemCodePage;
269 }
270
271 #endif /* LIBCAPTIVE */
272
273 NTSTATUS STDCALL
274 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
275                        ULONG UnicodeSize,
276                        PULONG ResultSize,
277                        PCHAR MbString,
278                        ULONG MbSize)
279 {
280   ULONG Size = 0;
281   ULONG i;
282
283   if (NlsMbCodePageTag == FALSE)
284     {
285       /* single-byte code page */
286       if (MbSize > (UnicodeSize / sizeof(WCHAR)))
287         Size = UnicodeSize / sizeof(WCHAR);
288       else
289         Size = MbSize;
290
291       if (ResultSize != NULL)
292         *ResultSize = Size * sizeof(WCHAR);
293
294       for (i = 0; i < Size; i++)
295         {
296           *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString];
297           UnicodeString++;
298           MbString++;
299         }
300     }
301   else
302     {
303       /* multi-byte code page */
304       /* FIXME */
305     }
306
307   return(STATUS_SUCCESS);
308 }
309
310
311 NTSTATUS STDCALL
312 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
313                           PCHAR MbString,
314                           ULONG MbSize)
315 {
316   if (NlsMbCodePageTag == FALSE)
317     {
318       /* single-byte code page */
319       *UnicodeSize = MbSize * sizeof (WCHAR);
320     }
321   else
322     {
323       /* multi-byte code page */
324       /* FIXME */
325     }
326
327   return(STATUS_SUCCESS);
328 }
329
330
331 NTSTATUS STDCALL
332 RtlOemToUnicodeN(PWCHAR UnicodeString,
333                  ULONG UnicodeSize,
334                  PULONG ResultSize,
335                  PCHAR OemString,
336                  ULONG OemSize)
337 {
338   ULONG Size = 0;
339   ULONG i;
340
341   if (NlsMbOemCodePageTag == FALSE)
342     {
343       /* single-byte code page */
344       if (OemSize > (UnicodeSize / sizeof(WCHAR)))
345         Size = UnicodeSize / sizeof(WCHAR);
346       else
347         Size = OemSize;
348
349       if (ResultSize != NULL)
350         *ResultSize = Size * sizeof(WCHAR);
351
352       for (i = 0; i < Size; i++)
353         {
354           *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString];
355           UnicodeString++;
356           OemString++;
357         }
358     }
359   else
360     {
361       /* multi-byte code page */
362       /* FIXME */
363     }
364
365   return(STATUS_SUCCESS);
366 }
367
368 #ifndef LIBCAPTIVE
369
370 NTSTATUS STDCALL
371 RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
372                       PCHAR CustomString,
373                       ULONG CustomSize,
374                       PULONG ResultSize,
375                       PWCHAR UnicodeString,
376                       ULONG UnicodeSize)
377 {
378   ULONG Size = 0;
379   ULONG i;
380
381   if (NlsData->DbcsFlag == 0)
382     {
383       /* single-byte code page */
384       if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
385         Size = CustomSize;
386       else
387         Size = UnicodeSize / sizeof(WCHAR);
388
389       if (ResultSize != NULL)
390         *ResultSize = Size;
391
392       for (i = 0; i < Size; i++)
393         {
394           *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString];
395           CustomString++;
396           UnicodeString++;
397         }
398     }
399   else
400     {
401       /* multi-byte code page */
402       /* FIXME */
403     }
404
405   return(STATUS_SUCCESS);
406 }
407
408 #endif /* LIBCAPTIVE */
409
410 NTSTATUS
411 STDCALL
412 RtlUnicodeToMultiByteN(PCHAR MbString,
413                        ULONG MbSize,
414                        PULONG ResultSize,
415                        PWCHAR UnicodeString,
416                        ULONG UnicodeSize)
417 {
418   ULONG Size = 0;
419   ULONG i;
420
421   if (NlsMbCodePageTag == FALSE)
422     {
423       /* single-byte code page */
424       if (UnicodeSize > (MbSize * sizeof(WCHAR)))
425         Size = MbSize;
426       else
427         Size = UnicodeSize / sizeof(WCHAR);
428
429       if (ResultSize != NULL)
430         *ResultSize = Size;
431
432       for (i = 0; i < Size; i++)
433         {
434           *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString];
435           MbString++;
436           UnicodeString++;
437         }
438     }
439   else
440     {
441       /* multi-byte code page */
442       /* FIXME */
443     }
444
445   return(STATUS_SUCCESS);
446 }
447
448
449 NTSTATUS STDCALL
450 RtlUnicodeToMultiByteSize(PULONG MbSize,
451                           PWCHAR UnicodeString,
452                           ULONG UnicodeSize)
453 {
454   if (NlsMbCodePageTag == FALSE)
455     {
456       /* single-byte code page */
457       *MbSize = UnicodeSize / sizeof (WCHAR);
458     }
459   else
460     {
461       /* multi-byte code page */
462       /* FIXME */
463     }
464
465   return(STATUS_SUCCESS);
466 }
467
468
469 NTSTATUS STDCALL
470 RtlUnicodeToOemN(PCHAR OemString,
471                  ULONG OemSize,
472                  PULONG ResultSize,
473                  PWCHAR UnicodeString,
474                  ULONG UnicodeSize)
475 {
476   ULONG Size = 0;
477   ULONG i;
478
479   if (NlsMbOemCodePageTag == FALSE)
480     {
481       /* single-byte code page */
482       if (UnicodeSize > (OemSize * sizeof(WCHAR)))
483         Size = OemSize;
484       else
485         Size = UnicodeSize / sizeof(WCHAR);
486
487       if (ResultSize != NULL)
488         *ResultSize = Size;
489
490       for (i = 0; i < Size; i++)
491         {
492           *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString];
493           OemString++;
494           UnicodeString++;
495         }
496     }
497   else
498     {
499       /* multi-byte code page */
500       /* FIXME */
501     }
502
503   return(STATUS_SUCCESS);
504 }
505
506 #ifndef LIBCAPTIVE
507
508 NTSTATUS STDCALL
509 RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
510                             PCHAR CustomString,
511                             ULONG CustomSize,
512                             PULONG ResultSize,
513                             PWCHAR UnicodeString,
514                             ULONG UnicodeSize)
515 {
516   ULONG Size = 0;
517   ULONG i;
518   WCHAR wc;
519
520   if (NlsData->DbcsFlag == 0)
521     {
522       /* single-byte code page */
523       if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
524         Size = CustomSize;
525       else
526         Size = UnicodeSize / sizeof(WCHAR);
527
528       if (ResultSize != NULL)
529         *ResultSize = Size;
530
531       for (i = 0; i < Size; i++)
532         {
533           wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
534           *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc];
535           CustomString++;
536           UnicodeString++;
537         }
538     }
539   else
540     {
541       /* multi-byte code page */
542       /* FIXME */
543     }
544
545   return(STATUS_SUCCESS);
546 }
547
548 #endif /* LIBCAPTIVE */
549
550 NTSTATUS STDCALL
551 RtlUpcaseUnicodeToMultiByteN(PCHAR MbString,
552                              ULONG MbSize,
553                              PULONG ResultSize,
554                              PWCHAR UnicodeString,
555                              ULONG UnicodeSize)
556 {
557   ULONG Size = 0;
558   ULONG i;
559   WCHAR wc;
560
561   if (NlsMbCodePageTag == FALSE)
562     {
563       /* single-byte code page */
564       if (UnicodeSize > (MbSize * sizeof(WCHAR)))
565         Size = MbSize;
566       else
567         Size = UnicodeSize / sizeof(WCHAR);
568
569       if (ResultSize != NULL)
570         *ResultSize = Size;
571
572       for (i = 0; i < Size; i++)
573         {
574           wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
575           *MbString = UnicodeToAnsiTable[(unsigned int)wc];
576           MbString++;
577           UnicodeString++;
578         }
579     }
580   else
581     {
582       /* multi-byte code page */
583       /* FIXME */
584     }
585
586   return(STATUS_SUCCESS);
587 }
588
589
590 NTSTATUS STDCALL
591 RtlUpcaseUnicodeToOemN(PCHAR OemString,
592                        ULONG OemSize,
593                        PULONG ResultSize,
594                        PWCHAR UnicodeString,
595                        ULONG UnicodeSize)
596 {
597   ULONG Size = 0;
598   ULONG i;
599   UCHAR wc;
600
601   if (NlsMbOemCodePageTag == FALSE)
602     {
603       /* single-byte code page */
604       if (UnicodeSize > (OemSize * sizeof(WCHAR)))
605         Size = OemSize;
606       else
607         Size = UnicodeSize / sizeof(WCHAR);
608
609       if (ResultSize != NULL)
610         *ResultSize = Size;
611
612       for (i = 0; i < Size; i++)
613         {
614           wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
615           *OemString = UnicodeToOemTable[(unsigned int)wc];
616           OemString++;
617           UnicodeString++;
618         }
619     }
620   else
621     {
622       /* multi-byte code page */
623       /* FIXME */
624     }
625
626   return(STATUS_SUCCESS);
627 }
628
629 /* EOF */