Implemented basic ANSI/OEM <--> Unicode translation tables.
[reactos.git] / reactos / ntoskrnl / rtl / nls.c
1 /* $Id: nls.c,v 1.6 2001/11/02 09:10:49 ekohl Exp $
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 RtlInitUnicodeString(&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 RtlInitUnicodeString(&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 */