added #ifdef around headers to support private test build.
[reactos.git] / reactos / ntoskrnl / rtl / nls.c
1 /* $Id: nls.c,v 1.10 2002/11/10 13:36:59 robd 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 #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 */