- Fixed some type casts to get correct index values into the nls tables.
[reactos.git] / reactos / ntoskrnl / rtl / nls.c
1 /* $Id: nls.c,v 1.21 2003/10/11 17:23:52 hbirr 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 * TODO:
12 * 1) Add multi-byte translation code.
13 */
14
15 #include <ddk/ntddk.h>
16 #include <internal/mm.h>
17 #include <internal/nls.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22
23 /* GLOBALS *******************************************************************/
24
25 USHORT NlsAnsiCodePage = 0; /* exported */
26 BOOLEAN NlsMbCodePageTag = FALSE; /* exported */
27 PWCHAR NlsAnsiToUnicodeTable = NULL;
28 PCHAR NlsUnicodeToAnsiTable = NULL;
29 PWCHAR NlsDbcsUnicodeToAnsiTable = NULL;
30 PUSHORT NlsLeadByteInfo = NULL; /* exported */
31
32
33 USHORT NlsOemCodePage = 0;
34 BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */
35 PWCHAR NlsOemToUnicodeTable = NULL;
36 PCHAR NlsUnicodeToOemTable =NULL;
37 PWCHAR NlsDbcsUnicodeToOemTable = NULL;
38 PUSHORT NlsOemLeadByteInfo = NULL; /* exported */
39
40
41 PUSHORT NlsUnicodeUpcaseTable = NULL;
42 PUSHORT NlsUnicodeLowercaseTable = NULL;
43
44
45 static PUSHORT NlsAnsiCodePageTable = NULL;
46 static ULONG NlsAnsiCodePageTableSize = 0;
47
48 static PUSHORT NlsOemCodePageTable = NULL;
49 static ULONG NlsOemCodePageTableSize = 0;
50
51 static PUSHORT NlsUnicodeCasemapTable = NULL;
52 static ULONG NlsUnicodeCasemapTableSize = 0;
53
54 PVOID NlsSectionObject = NULL;
55 static PVOID NlsSectionBase = NULL;
56 static ULONG NlsSectionViewSize = 0;
57
58 ULONG NlsAnsiTableOffset = 0;
59 ULONG NlsOemTableOffset = 0;
60 ULONG NlsUnicodeTableOffset = 0;
61
62
63 /* FUNCTIONS *****************************************************************/
64
65 VOID
66 RtlpImportAnsiCodePage(PUSHORT TableBase,
67 ULONG Size)
68 {
69 NlsAnsiCodePageTable = TableBase;
70 NlsAnsiCodePageTableSize = Size;
71 }
72
73
74 VOID
75 RtlpImportOemCodePage(PUSHORT TableBase,
76 ULONG Size)
77 {
78 NlsOemCodePageTable = TableBase;
79 NlsOemCodePageTableSize = Size;
80 }
81
82
83 VOID
84 RtlpImportUnicodeCasemap(PUSHORT TableBase,
85 ULONG Size)
86 {
87 NlsUnicodeCasemapTable = TableBase;
88 NlsUnicodeCasemapTableSize = Size;
89 }
90
91
92 VOID
93 RtlpCreateInitialNlsTables(VOID)
94 {
95 NLSTABLEINFO NlsTable;
96
97 if (NlsAnsiCodePageTable == NULL || NlsAnsiCodePageTableSize == 0 ||
98 NlsOemCodePageTable == NULL || NlsOemCodePageTableSize == 0 ||
99 NlsUnicodeCasemapTable == NULL || NlsUnicodeCasemapTableSize == 0)
100 {
101 KEBUGCHECKEX (0x32, STATUS_UNSUCCESSFUL, 1, 0, 0);
102 }
103
104 RtlInitNlsTables (NlsAnsiCodePageTable,
105 NlsOemCodePageTable,
106 NlsUnicodeCasemapTable,
107 &NlsTable);
108
109 RtlResetRtlTranslations (&NlsTable);
110 }
111
112
113 VOID
114 RtlpCreateNlsSection(VOID)
115 {
116 NLSTABLEINFO NlsTable;
117 LARGE_INTEGER SectionSize;
118 HANDLE SectionHandle;
119 NTSTATUS Status;
120
121 DPRINT("RtlpCreateNlsSection() called\n");
122
123 NlsSectionViewSize = ROUND_UP(NlsAnsiCodePageTableSize, PAGE_SIZE) +
124 ROUND_UP(NlsOemCodePageTableSize, PAGE_SIZE) +
125 ROUND_UP(NlsUnicodeCasemapTableSize, PAGE_SIZE);
126
127 DPRINT("NlsSectionViewSize %lx\n", NlsSectionViewSize);
128
129 SectionSize.QuadPart = (LONGLONG)NlsSectionViewSize;
130 Status = NtCreateSection(&SectionHandle,
131 SECTION_ALL_ACCESS,
132 NULL,
133 &SectionSize,
134 PAGE_READWRITE,
135 SEC_COMMIT,
136 NULL);
137 if (!NT_SUCCESS(Status))
138 {
139 DPRINT1("NtCreateSection() failed\n");
140 KEBUGCHECKEX(0x32, Status, 1, 1, 0);
141 }
142
143 Status = ObReferenceObjectByHandle(SectionHandle,
144 SECTION_ALL_ACCESS,
145 MmSectionObjectType,
146 KernelMode,
147 &NlsSectionObject,
148 NULL);
149 NtClose(SectionHandle);
150 if (!NT_SUCCESS(Status))
151 {
152 DPRINT1("ObReferenceObjectByHandle() failed\n");
153 KEBUGCHECKEX(0x32, Status, 1, 2, 0);
154 }
155
156 Status = MmMapViewInSystemSpace(NlsSectionObject,
157 &NlsSectionBase,
158 &NlsSectionViewSize);
159 if (!NT_SUCCESS(Status))
160 {
161 DPRINT1("MmMapViewInSystemSpace() failed\n");
162 KEBUGCHECKEX(0x32, Status, 1, 3, 0);
163 }
164
165 DPRINT("NlsSection: Base %p Size %lx\n",
166 NlsSectionBase,
167 NlsSectionViewSize);
168
169 NlsAnsiTableOffset = 0;
170 RtlCopyMemory((PVOID)((ULONG)NlsSectionBase + NlsAnsiTableOffset),
171 NlsAnsiCodePageTable,
172 NlsAnsiCodePageTableSize);
173
174 NlsOemTableOffset = NlsAnsiTableOffset + ROUND_UP(NlsAnsiCodePageTableSize, PAGE_SIZE);
175 RtlCopyMemory((PVOID)((ULONG)NlsSectionBase + NlsOemTableOffset),
176 NlsOemCodePageTable,
177 NlsOemCodePageTableSize);
178
179 NlsUnicodeTableOffset = NlsOemTableOffset + ROUND_UP(NlsOemCodePageTableSize, PAGE_SIZE);
180 RtlCopyMemory((PVOID)((ULONG)NlsSectionBase + NlsUnicodeTableOffset),
181 NlsUnicodeCasemapTable,
182 NlsUnicodeCasemapTableSize);
183
184 RtlInitNlsTables ((PVOID)((ULONG)NlsSectionBase + NlsAnsiTableOffset),
185 (PVOID)((ULONG)NlsSectionBase + NlsOemTableOffset),
186 (PVOID)((ULONG)NlsSectionBase + NlsUnicodeTableOffset),
187 &NlsTable);
188
189 RtlResetRtlTranslations (&NlsTable);
190 }
191
192
193 /*
194 * @unimplemented
195 */
196 NTSTATUS STDCALL
197 RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP,
198 PWCHAR UnicodeString,
199 ULONG UnicodeSize,
200 PULONG ResultSize,
201 PCHAR CustomString,
202 ULONG CustomSize)
203 {
204 ULONG Size = 0;
205 ULONG i;
206
207 if (CustomCP->DBCSCodePage == 0)
208 {
209 /* single-byte code page */
210 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
211 Size = UnicodeSize / sizeof(WCHAR);
212 else
213 Size = CustomSize;
214
215 if (ResultSize != NULL)
216 *ResultSize = Size * sizeof(WCHAR);
217
218 for (i = 0; i < Size; i++)
219 {
220 *UnicodeString = CustomCP->MultiByteTable[(UCHAR)*CustomString];
221 UnicodeString++;
222 CustomString++;
223 }
224 }
225 else
226 {
227 /* multi-byte code page */
228 /* FIXME */
229 }
230
231 return(STATUS_SUCCESS);
232 }
233
234
235 WCHAR
236 RtlDowncaseUnicodeChar (IN WCHAR Source)
237 {
238 USHORT Offset;
239
240 if (Source < L'A')
241 return Source;
242
243 if (Source <= L'Z')
244 return Source + (L'a' - L'A');
245
246 if (Source < 0x80)
247 return Source;
248
249 Offset = ((USHORT)Source >> 8);
250 Offset = NlsUnicodeLowercaseTable[Offset];
251
252 Offset += (((USHORT)Source & 0x00F0) >> 4);
253 Offset = NlsUnicodeLowercaseTable[Offset];
254
255 Offset += ((USHORT)Source & 0x000F);
256 Offset = NlsUnicodeLowercaseTable[Offset];
257
258 return Source + (SHORT)Offset;
259 }
260
261
262 /*
263 * @implemented
264 */
265 VOID STDCALL
266 RtlGetDefaultCodePage(PUSHORT AnsiCodePage,
267 PUSHORT OemCodePage)
268 {
269 *AnsiCodePage = NlsAnsiCodePage;
270 *OemCodePage = NlsOemCodePage;
271 }
272
273
274 /*
275 * @implemented
276 */
277 VOID STDCALL
278 RtlInitCodePageTable(IN PUSHORT TableBase,
279 OUT PCPTABLEINFO CodePageTable)
280 {
281 PNLS_FILE_HEADER NlsFileHeader;
282 PUSHORT Ptr;
283 USHORT Offset;
284
285 DPRINT("RtlInitCodePageTable() called\n");
286
287 NlsFileHeader = (PNLS_FILE_HEADER)TableBase;
288
289 CodePageTable->CodePage = NlsFileHeader->CodePage;
290 CodePageTable->MaximumCharacterSize = NlsFileHeader->MaximumCharacterSize;
291 CodePageTable->DefaultChar = NlsFileHeader->DefaultChar;
292 CodePageTable->UniDefaultChar = NlsFileHeader->UniDefaultChar;
293 CodePageTable->TransDefaultChar = NlsFileHeader->TransDefaultChar;
294 CodePageTable->TransUniDefaultChar = NlsFileHeader->TransUniDefaultChar;
295
296 RtlCopyMemory(&CodePageTable->LeadByte,
297 &NlsFileHeader->LeadByte,
298 MAXIMUM_LEADBYTES);
299
300 /* Set Pointer to start of multi byte table */
301 Ptr = (PUSHORT)((ULONG_PTR)TableBase + 2 * NlsFileHeader->HeaderSize);
302
303 /* Get offset to the wide char table */
304 Offset = (USHORT)(*Ptr++) + NlsFileHeader->HeaderSize + 1;
305
306 /* Set pointer to the multi byte table */
307 CodePageTable->MultiByteTable = Ptr;
308
309 /* Skip ANSI and OEM table */
310 Ptr += 256;
311 if (*Ptr++)
312 Ptr += 256;
313
314 /* Set pointer to DBCS ranges */
315 CodePageTable->DBCSRanges = (PUSHORT)Ptr;
316
317 if (*Ptr > 0)
318 {
319 CodePageTable->DBCSCodePage = 1;
320 CodePageTable->DBCSOffsets = (PUSHORT)++Ptr;
321 }
322 else
323 {
324 CodePageTable->DBCSCodePage = 0;
325 CodePageTable->DBCSOffsets = 0;
326 }
327
328 CodePageTable->WideCharTable = (PVOID)((ULONG_PTR)TableBase + 2 * Offset);
329 }
330
331
332 VOID STDCALL
333 RtlInitNlsTables(IN PUSHORT AnsiTableBase,
334 IN PUSHORT OemTableBase,
335 IN PUSHORT CaseTableBase,
336 OUT PNLSTABLEINFO NlsTable)
337 {
338 DPRINT("RtlInitNlsTables()called\n");
339
340 RtlInitCodePageTable (AnsiTableBase,
341 &NlsTable->AnsiTableInfo);
342
343 RtlInitCodePageTable (OemTableBase,
344 &NlsTable->OemTableInfo);
345
346 NlsTable->UpperCaseTable = (PUSHORT)CaseTableBase + 2;
347 NlsTable->LowerCaseTable = (PUSHORT)CaseTableBase + *((PUSHORT)CaseTableBase + 1) + 2;
348 }
349
350
351 /*
352 * @unimplemented
353 */
354 NTSTATUS STDCALL
355 RtlMultiByteToUnicodeN(PWCHAR UnicodeString,
356 ULONG UnicodeSize,
357 PULONG ResultSize,
358 const PCHAR MbString,
359 ULONG MbSize)
360 {
361 ULONG Size = 0;
362 ULONG i;
363
364 if (NlsMbCodePageTag == FALSE)
365 {
366 /* single-byte code page */
367 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
368 Size = UnicodeSize / sizeof(WCHAR);
369 else
370 Size = MbSize;
371
372 if (ResultSize != NULL)
373 *ResultSize = Size * sizeof(WCHAR);
374
375 for (i = 0; i < Size; i++)
376 UnicodeString[i] = NlsAnsiToUnicodeTable[(UCHAR)MbString[i]];
377 }
378 else
379 {
380 /* multi-byte code page */
381 /* FIXME */
382 }
383
384 return(STATUS_SUCCESS);
385 }
386
387
388 /*
389 * @implemented
390 */
391 NTSTATUS STDCALL
392 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
393 PCHAR MbString,
394 ULONG MbSize)
395 {
396 ULONG Length;
397
398 if (NlsMbCodePageTag == FALSE)
399 {
400 /* single-byte code page */
401 *UnicodeSize = MbSize * sizeof (WCHAR);
402 }
403 else
404 {
405 /* multi-byte code page */
406 for (Length = 0; MbSize; MbSize--, MbString++, Length++)
407 {
408 if (NlsLeadByteInfo[(UCHAR)*MbString] != 0)
409 {
410 if (!--MbSize)
411 break; /* partial char, ignore it */
412 MbString++;
413 }
414 }
415
416 *UnicodeSize = Length * sizeof(WCHAR);
417 }
418
419 return STATUS_SUCCESS;
420 }
421
422
423 /*
424 * @unimplemented
425 */
426 NTSTATUS STDCALL
427 RtlOemToUnicodeN(PWCHAR UnicodeString,
428 ULONG UnicodeSize,
429 PULONG ResultSize,
430 PCHAR OemString,
431 ULONG OemSize)
432 {
433 ULONG Size = 0;
434 ULONG i;
435
436 if (NlsMbOemCodePageTag == FALSE)
437 {
438 /* single-byte code page */
439 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
440 Size = UnicodeSize / sizeof(WCHAR);
441 else
442 Size = OemSize;
443
444 if (ResultSize != NULL)
445 *ResultSize = Size * sizeof(WCHAR);
446
447 for (i = 0; i < Size; i++)
448 {
449 *UnicodeString = NlsOemToUnicodeTable[(UCHAR)*OemString];
450 UnicodeString++;
451 OemString++;
452 }
453 }
454 else
455 {
456 /* multi-byte code page */
457 /* FIXME */
458 }
459
460 return(STATUS_SUCCESS);
461 }
462
463
464 VOID STDCALL
465 RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
466 {
467 DPRINT("RtlResetRtlTranslations() called\n");
468
469 /* Set ANSI data */
470 NlsAnsiToUnicodeTable = NlsTable->AnsiTableInfo.MultiByteTable;
471 NlsUnicodeToAnsiTable = NlsTable->AnsiTableInfo.WideCharTable;
472 NlsDbcsUnicodeToAnsiTable = (PWCHAR)NlsTable->AnsiTableInfo.WideCharTable;
473 NlsMbCodePageTag = (NlsTable->AnsiTableInfo.DBCSCodePage != 0);
474 NlsLeadByteInfo = NlsTable->AnsiTableInfo.DBCSOffsets;
475 NlsAnsiCodePage = NlsTable->AnsiTableInfo.CodePage;
476 DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage);
477
478 /* Set OEM data */
479 NlsOemToUnicodeTable = NlsTable->OemTableInfo.MultiByteTable;
480 NlsUnicodeToOemTable = NlsTable->OemTableInfo.WideCharTable;
481 NlsDbcsUnicodeToOemTable = (PWCHAR)NlsTable->OemTableInfo.WideCharTable;
482 NlsMbOemCodePageTag = (NlsTable->OemTableInfo.DBCSCodePage != 0);
483 NlsOemLeadByteInfo = NlsTable->OemTableInfo.DBCSOffsets;
484 NlsOemCodePage = NlsTable->OemTableInfo.CodePage;
485 DPRINT("Oem codepage %hu\n", NlsOemCodePage);
486
487 /* Set Unicode case map data */
488 NlsUnicodeUpcaseTable = NlsTable->UpperCaseTable;
489 NlsUnicodeLowercaseTable = NlsTable->LowerCaseTable;
490 }
491
492
493 /*
494 * @unimplemented
495 */
496 NTSTATUS STDCALL
497 RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
498 PCHAR CustomString,
499 ULONG CustomSize,
500 PULONG ResultSize,
501 PWCHAR UnicodeString,
502 ULONG UnicodeSize)
503 {
504 ULONG Size = 0;
505 ULONG i;
506
507 if (CustomCP->DBCSCodePage == 0)
508 {
509 /* single-byte code page */
510 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
511 Size = CustomSize;
512 else
513 Size = UnicodeSize / sizeof(WCHAR);
514
515 if (ResultSize != NULL)
516 *ResultSize = Size;
517
518 for (i = 0; i < Size; i++)
519 {
520 *CustomString = ((PCHAR)CustomCP->WideCharTable)[(USHORT)*UnicodeString];
521 CustomString++;
522 UnicodeString++;
523 }
524 }
525 else
526 {
527 /* multi-byte code page */
528 /* FIXME */
529 }
530
531 return(STATUS_SUCCESS);
532 }
533
534
535 /*
536 * @unimplemented
537 */
538 NTSTATUS
539 STDCALL
540 RtlUnicodeToMultiByteN(PCHAR MbString,
541 ULONG MbSize,
542 PULONG ResultSize,
543 PWCHAR UnicodeString,
544 ULONG UnicodeSize)
545 {
546 ULONG Size = 0;
547 ULONG i;
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 *MbString = NlsUnicodeToAnsiTable[(USHORT)*UnicodeString];
563 MbString++;
564 UnicodeString++;
565 }
566 }
567 else
568 {
569 /* multi-byte code page */
570 /* FIXME */
571 }
572
573 return(STATUS_SUCCESS);
574 }
575
576
577 /*
578 * @implemented
579 */
580 NTSTATUS STDCALL
581 RtlUnicodeToMultiByteSize(PULONG MbSize,
582 PWCHAR UnicodeString,
583 ULONG UnicodeSize)
584 {
585 ULONG UnicodeLength;
586 ULONG MbLength;
587
588 if (NlsMbCodePageTag == FALSE)
589 {
590 /* single-byte code page */
591 *MbSize = UnicodeSize / sizeof (WCHAR);
592 }
593 else
594 {
595 /* multi-byte code page */
596 UnicodeLength = UnicodeSize / sizeof(WCHAR);
597 MbLength = 0;
598 while (UnicodeLength > 0)
599 {
600 if (NlsLeadByteInfo[(USHORT)*UnicodeString] & 0xff00)
601 MbLength++;
602
603 MbLength++;
604 UnicodeLength--;
605 UnicodeString++;
606 }
607
608 *MbSize = MbLength;
609 }
610
611 return(STATUS_SUCCESS);
612 }
613
614
615 /*
616 * @unimplemented
617 */
618 NTSTATUS STDCALL
619 RtlUnicodeToOemN(PCHAR OemString,
620 ULONG OemSize,
621 PULONG ResultSize,
622 PWCHAR UnicodeString,
623 ULONG UnicodeSize)
624 {
625 ULONG Size = 0;
626 ULONG i;
627
628 if (NlsMbOemCodePageTag == FALSE)
629 {
630 /* single-byte code page */
631 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
632 Size = OemSize;
633 else
634 Size = UnicodeSize / sizeof(WCHAR);
635
636 if (ResultSize != NULL)
637 *ResultSize = Size;
638
639 for (i = 0; i < Size; i++)
640 {
641 *OemString = NlsUnicodeToOemTable[(USHORT)*UnicodeString];
642 OemString++;
643 UnicodeString++;
644 }
645 }
646 else
647 {
648 /* multi-byte code page */
649 /* FIXME */
650 }
651
652 return(STATUS_SUCCESS);
653 }
654
655
656 /*
657 * @implemented
658 */
659 WCHAR STDCALL
660 RtlUpcaseUnicodeChar(IN WCHAR Source)
661 {
662 USHORT Offset;
663
664 if (Source < L'a')
665 return Source;
666
667 if (Source <= L'z')
668 return (Source - (L'a' - L'A'));
669
670 Offset = ((USHORT)Source >> 8);
671 Offset = NlsUnicodeUpcaseTable[Offset];
672
673 Offset += (((USHORT)Source & 0x00F0) >> 4);
674 Offset = NlsUnicodeUpcaseTable[Offset];
675
676 Offset += ((USHORT)Source & 0x000F);
677 Offset = NlsUnicodeUpcaseTable[Offset];
678
679 return Source + (SHORT)Offset;
680 }
681
682
683 /*
684 * @unimplemented
685 */
686 NTSTATUS STDCALL
687 RtlUpcaseUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
688 PCHAR CustomString,
689 ULONG CustomSize,
690 PULONG ResultSize,
691 PWCHAR UnicodeString,
692 ULONG UnicodeSize)
693 {
694 ULONG Size = 0;
695 ULONG i;
696 WCHAR wc;
697
698 if (CustomCP->DBCSCodePage == 0)
699 {
700 /* single-byte code page */
701 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
702 Size = CustomSize;
703 else
704 Size = UnicodeSize / sizeof(WCHAR);
705
706 if (ResultSize != NULL)
707 *ResultSize = Size;
708
709 for (i = 0; i < Size; i++)
710 {
711 wc = RtlUpcaseUnicodeChar(*UnicodeString);
712 *CustomString = ((PCHAR)CustomCP->WideCharTable)[(USHORT)wc];
713 CustomString++;
714 UnicodeString++;
715 }
716 }
717 else
718 {
719 /* multi-byte code page */
720 /* FIXME */
721 }
722
723 return(STATUS_SUCCESS);
724 }
725
726
727 /*
728 * @unimplemented
729 */
730 NTSTATUS STDCALL
731 RtlUpcaseUnicodeToMultiByteN(PCHAR MbString,
732 ULONG MbSize,
733 PULONG ResultSize,
734 PWCHAR UnicodeString,
735 ULONG UnicodeSize)
736 {
737 ULONG Size = 0;
738 ULONG i;
739 WCHAR wc;
740
741 if (NlsMbCodePageTag == FALSE)
742 {
743 /* single-byte code page */
744 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
745 Size = MbSize;
746 else
747 Size = UnicodeSize / sizeof(WCHAR);
748
749 if (ResultSize != NULL)
750 *ResultSize = Size;
751
752 for (i = 0; i < Size; i++)
753 {
754 wc = RtlUpcaseUnicodeChar(*UnicodeString);
755 *MbString = NlsUnicodeToAnsiTable[(USHORT)wc];
756 MbString++;
757 UnicodeString++;
758 }
759 }
760 else
761 {
762 /* multi-byte code page */
763 /* FIXME */
764 }
765
766 return(STATUS_SUCCESS);
767 }
768
769
770 /*
771 * @unimplemented
772 */
773 NTSTATUS STDCALL
774 RtlUpcaseUnicodeToOemN(PCHAR OemString,
775 ULONG OemSize,
776 PULONG ResultSize,
777 PWCHAR UnicodeString,
778 ULONG UnicodeSize)
779 {
780 ULONG Size = 0;
781 ULONG i;
782 UCHAR wc;
783
784 if (NlsMbOemCodePageTag == FALSE)
785 {
786 /* single-byte code page */
787 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
788 Size = OemSize;
789 else
790 Size = UnicodeSize / sizeof(WCHAR);
791
792 if (ResultSize != NULL)
793 *ResultSize = Size;
794
795 for (i = 0; i < Size; i++)
796 {
797 wc = RtlUpcaseUnicodeChar(*UnicodeString);
798 *OemString = NlsUnicodeToOemTable[(USHORT)wc];
799 OemString++;
800 UnicodeString++;
801 }
802 }
803 else
804 {
805 /* multi-byte code page */
806 /* FIXME */
807 }
808
809 return(STATUS_SUCCESS);
810 }
811
812
813 /*
814 * @unimplemented
815 */
816 CHAR STDCALL
817 RtlUpperChar (IN CHAR Source)
818 {
819 WCHAR Unicode;
820 CHAR Destination;
821
822 if (NlsMbCodePageTag == FALSE)
823 {
824 /* single-byte code page */
825
826 /* ansi->unicode */
827 Unicode = NlsAnsiToUnicodeTable[(UCHAR)Source];
828
829 /* upcase conversion */
830 Unicode = RtlUpcaseUnicodeChar (Unicode);
831
832 /* unicode -> ansi */
833 Destination = NlsUnicodeToAnsiTable[(USHORT)Unicode];
834 }
835 else
836 {
837 /* multi-byte code page */
838 /* FIXME */
839 Destination = Source;
840 }
841
842 return Destination;
843 }
844
845 /* EOF */