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