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
152 NTSTATUS
153 RtlpInitNlsSections(ULONG Mod1Start,
154                     ULONG Mod1End,
155                     ULONG Mod2Start,
156                     ULONG Mod2End,
157                     ULONG Mod3Start,
158                     ULONG Mod3End)
159 {
160   UNICODE_STRING UnicodeString;
161   OBJECT_ATTRIBUTES ObjectAttributes;
162   HANDLE DirectoryHandle;
163   HANDLE SectionHandle;
164   NTSTATUS Status;
165   LARGE_INTEGER SectionSize;
166
167   DPRINT("Ansi section start: 0x%08lX\n", Mod1Start);
168   DPRINT("Ansi section end: 0x%08lX\n", Mod1End);
169   DPRINT("Oem section start: 0x%08lX\n", Mod2Start);
170   DPRINT("Oem section end: 0x%08lX\n", Mod2End);
171   DPRINT("Upcase section start: 0x%08lX\n", Mod3Start);
172   DPRINT("Upcase section end: 0x%08lX\n", Mod3End);
173
174   /* Create the '\NLS' directory */
175   RtlInitUnicodeStringFromLiteral(&UnicodeString,
176                        L"\\NLS");
177   InitializeObjectAttributes(&ObjectAttributes,
178                              &UnicodeString,
179                              OBJ_PERMANENT,
180                              NULL,
181                              NULL);
182   Status = NtCreateDirectoryObject(&DirectoryHandle,
183                                    0,
184                                    &ObjectAttributes);
185   if (!NT_SUCCESS(Status))
186     return(Status);
187
188   /* Create the 'NlsSectionUnicode' section */
189   RtlInitUnicodeStringFromLiteral(&UnicodeString,
190                        L"NlsSectionUnicode");
191   InitializeObjectAttributes(&ObjectAttributes,
192                              &UnicodeString,
193                              OBJ_PERMANENT,
194                              DirectoryHandle,
195                              NULL);
196   SectionSize.QuadPart = (Mod1End - Mod1Start) +
197     (Mod2End - Mod2Start) + (Mod3End - Mod3Start);
198   DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart);
199
200   Status = NtCreateSection(&SectionHandle,
201                            SECTION_ALL_ACCESS,
202                            &ObjectAttributes,
203                            &SectionSize,
204                            PAGE_READWRITE,
205                            0,
206                            NULL);
207   if (!NT_SUCCESS(Status))
208     return(Status);
209
210
211   /* create and initialize code page table */
212
213   /* map the nls table into the 'NlsSectionUnicode' section */
214
215
216   NtClose(SectionHandle);
217   NtClose(DirectoryHandle);
218
219   return(STATUS_SUCCESS);
220 }
221
222
223 NTSTATUS STDCALL
224 RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData,
225                       PWCHAR UnicodeString,
226                       ULONG UnicodeSize,
227                       PULONG ResultSize,
228                       PCHAR CustomString,
229                       ULONG CustomSize)
230 {
231   ULONG Size = 0;
232   ULONG i;
233
234   if (NlsData->DbcsFlag == FALSE)
235     {
236       /* single-byte code page */
237       if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
238         Size = UnicodeSize / sizeof(WCHAR);
239       else
240         Size = CustomSize;
241
242       if (ResultSize != NULL)
243         *ResultSize = Size * sizeof(WCHAR);
244
245       for (i = 0; i < Size; i++)
246         {
247           *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString];
248           UnicodeString++;
249           CustomString++;
250         }
251     }
252   else
253     {
254       /* multi-byte code page */
255       /* FIXME */
256     }
257
258   return(STATUS_SUCCESS);
259 }
260
261
262 VOID STDCALL
263 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
264                       PUSHORT OemCodePage)
265 {
266   *AnsiCodePage = NlsAnsiCodePage;
267   *OemCodePage = NlsOemCodePage;
268 }
269
270
271 NTSTATUS STDCALL
272 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
273                        ULONG UnicodeSize,
274                        PULONG ResultSize,
275                        PCHAR MbString,
276                        ULONG MbSize)
277 {
278   ULONG Size = 0;
279   ULONG i;
280
281   if (NlsMbCodePageTag == FALSE)
282     {
283       /* single-byte code page */
284       if (MbSize > (UnicodeSize / sizeof(WCHAR)))
285         Size = UnicodeSize / sizeof(WCHAR);
286       else
287         Size = MbSize;
288
289       if (ResultSize != NULL)
290         *ResultSize = Size * sizeof(WCHAR);
291
292       for (i = 0; i < Size; i++)
293         {
294           *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString];
295           UnicodeString++;
296           MbString++;
297         }
298     }
299   else
300     {
301       /* multi-byte code page */
302       /* FIXME */
303     }
304
305   return(STATUS_SUCCESS);
306 }
307
308
309 NTSTATUS STDCALL
310 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
311                           PCHAR MbString,
312                           ULONG MbSize)
313 {
314   if (NlsMbCodePageTag == FALSE)
315     {
316       /* single-byte code page */
317       *UnicodeSize = MbSize * sizeof (WCHAR);
318     }
319   else
320     {
321       /* multi-byte code page */
322       /* FIXME */
323     }
324
325   return(STATUS_SUCCESS);
326 }
327
328
329 NTSTATUS STDCALL
330 RtlOemToUnicodeN(PWCHAR UnicodeString,
331                  ULONG UnicodeSize,
332                  PULONG ResultSize,
333                  PCHAR OemString,
334                  ULONG OemSize)
335 {
336   ULONG Size = 0;
337   ULONG i;
338
339   if (NlsMbOemCodePageTag == FALSE)
340     {
341       /* single-byte code page */
342       if (OemSize > (UnicodeSize / sizeof(WCHAR)))
343         Size = UnicodeSize / sizeof(WCHAR);
344       else
345         Size = OemSize;
346
347       if (ResultSize != NULL)
348         *ResultSize = Size * sizeof(WCHAR);
349
350       for (i = 0; i < Size; i++)
351         {
352           *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString];
353           UnicodeString++;
354           OemString++;
355         }
356     }
357   else
358     {
359       /* multi-byte code page */
360       /* FIXME */
361     }
362
363   return(STATUS_SUCCESS);
364 }
365
366
367 NTSTATUS STDCALL
368 RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
369                       PCHAR CustomString,
370                       ULONG CustomSize,
371                       PULONG ResultSize,
372                       PWCHAR UnicodeString,
373                       ULONG UnicodeSize)
374 {
375   ULONG Size = 0;
376   ULONG i;
377
378   if (NlsData->DbcsFlag == 0)
379     {
380       /* single-byte code page */
381       if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
382         Size = CustomSize;
383       else
384         Size = UnicodeSize / sizeof(WCHAR);
385
386       if (ResultSize != NULL)
387         *ResultSize = Size;
388
389       for (i = 0; i < Size; i++)
390         {
391           *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString];
392           CustomString++;
393           UnicodeString++;
394         }
395     }
396   else
397     {
398       /* multi-byte code page */
399       /* FIXME */
400     }
401
402   return(STATUS_SUCCESS);
403 }
404
405
406 NTSTATUS
407 STDCALL
408 RtlUnicodeToMultiByteN(PCHAR MbString,
409                        ULONG MbSize,
410                        PULONG ResultSize,
411                        PWCHAR UnicodeString,
412                        ULONG UnicodeSize)
413 {
414   ULONG Size = 0;
415   ULONG i;
416
417   if (NlsMbCodePageTag == FALSE)
418     {
419       /* single-byte code page */
420       if (UnicodeSize > (MbSize * sizeof(WCHAR)))
421         Size = MbSize;
422       else
423         Size = UnicodeSize / sizeof(WCHAR);
424
425       if (ResultSize != NULL)
426         *ResultSize = Size;
427
428       for (i = 0; i < Size; i++)
429         {
430           *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString];
431           MbString++;
432           UnicodeString++;
433         }
434     }
435   else
436     {
437       /* multi-byte code page */
438       /* FIXME */
439     }
440
441   return(STATUS_SUCCESS);
442 }
443
444
445 NTSTATUS STDCALL
446 RtlUnicodeToMultiByteSize(PULONG MbSize,
447                           PWCHAR UnicodeString,
448                           ULONG UnicodeSize)
449 {
450   if (NlsMbCodePageTag == FALSE)
451     {
452       /* single-byte code page */
453       *MbSize = UnicodeSize / sizeof (WCHAR);
454     }
455   else
456     {
457       /* multi-byte code page */
458       /* FIXME */
459     }
460
461   return(STATUS_SUCCESS);
462 }
463
464
465 NTSTATUS STDCALL
466 RtlUnicodeToOemN(PCHAR OemString,
467                  ULONG OemSize,
468                  PULONG ResultSize,
469                  PWCHAR UnicodeString,
470                  ULONG UnicodeSize)
471 {
472   ULONG Size = 0;
473   ULONG i;
474
475   if (NlsMbOemCodePageTag == FALSE)
476     {
477       /* single-byte code page */
478       if (UnicodeSize > (OemSize * sizeof(WCHAR)))
479         Size = OemSize;
480       else
481         Size = UnicodeSize / sizeof(WCHAR);
482
483       if (ResultSize != NULL)
484         *ResultSize = Size;
485
486       for (i = 0; i < Size; i++)
487         {
488           *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString];
489           OemString++;
490           UnicodeString++;
491         }
492     }
493   else
494     {
495       /* multi-byte code page */
496       /* FIXME */
497     }
498
499   return(STATUS_SUCCESS);
500 }
501
502
503 NTSTATUS STDCALL
504 RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData,
505                             PCHAR CustomString,
506                             ULONG CustomSize,
507                             PULONG ResultSize,
508                             PWCHAR UnicodeString,
509                             ULONG UnicodeSize)
510 {
511   ULONG Size = 0;
512   ULONG i;
513   WCHAR wc;
514
515   if (NlsData->DbcsFlag == 0)
516     {
517       /* single-byte code page */
518       if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
519         Size = CustomSize;
520       else
521         Size = UnicodeSize / sizeof(WCHAR);
522
523       if (ResultSize != NULL)
524         *ResultSize = Size;
525
526       for (i = 0; i < Size; i++)
527         {
528           wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
529           *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc];
530           CustomString++;
531           UnicodeString++;
532         }
533     }
534   else
535     {
536       /* multi-byte code page */
537       /* FIXME */
538     }
539
540   return(STATUS_SUCCESS);
541 }
542
543
544 NTSTATUS STDCALL
545 RtlUpcaseUnicodeToMultiByteN(PCHAR MbString,
546                              ULONG MbSize,
547                              PULONG ResultSize,
548                              PWCHAR UnicodeString,
549                              ULONG UnicodeSize)
550 {
551   ULONG Size = 0;
552   ULONG i;
553   WCHAR wc;
554
555   if (NlsMbCodePageTag == FALSE)
556     {
557       /* single-byte code page */
558       if (UnicodeSize > (MbSize * sizeof(WCHAR)))
559         Size = MbSize;
560       else
561         Size = UnicodeSize / sizeof(WCHAR);
562
563       if (ResultSize != NULL)
564         *ResultSize = Size;
565
566       for (i = 0; i < Size; i++)
567         {
568           wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
569           *MbString = UnicodeToAnsiTable[(unsigned int)wc];
570           MbString++;
571           UnicodeString++;
572         }
573     }
574   else
575     {
576       /* multi-byte code page */
577       /* FIXME */
578     }
579
580   return(STATUS_SUCCESS);
581 }
582
583
584 NTSTATUS STDCALL
585 RtlUpcaseUnicodeToOemN(PCHAR OemString,
586                        ULONG OemSize,
587                        PULONG ResultSize,
588                        PWCHAR UnicodeString,
589                        ULONG UnicodeSize)
590 {
591   ULONG Size = 0;
592   ULONG i;
593   UCHAR wc;
594
595   if (NlsMbOemCodePageTag == FALSE)
596     {
597       /* single-byte code page */
598       if (UnicodeSize > (OemSize * sizeof(WCHAR)))
599         Size = OemSize;
600       else
601         Size = UnicodeSize / sizeof(WCHAR);
602
603       if (ResultSize != NULL)
604         *ResultSize = Size;
605
606       for (i = 0; i < Size; i++)
607         {
608           wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString];
609           *OemString = UnicodeToOemTable[(unsigned int)wc];
610           OemString++;
611           UnicodeString++;
612         }
613     }
614   else
615     {
616       /* multi-byte code page */
617       /* FIXME */
618     }
619
620   return(STATUS_SUCCESS);
621 }
622
623 /* EOF */