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