[RTL/NTDLL]
[reactos.git] / reactos / lib / rtl / nls.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/nls.c
5 * PURPOSE: National Language Support (NLS) functions
6 * PROGRAMMERS: Emanuele Aliberti
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <rtl.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18 PUSHORT NlsUnicodeUpcaseTable = NULL;
19 PUSHORT NlsUnicodeLowercaseTable = NULL;
20
21 USHORT NlsAnsiCodePage = 0; /* exported */
22 BOOLEAN NlsMbCodePageTag = FALSE; /* exported */
23 PWCHAR NlsAnsiToUnicodeTable = NULL;
24 PCHAR NlsUnicodeToAnsiTable = NULL;
25 PWCHAR NlsDbcsUnicodeToAnsiTable = NULL;
26 PUSHORT NlsLeadByteInfo = NULL; /* exported */
27
28
29 USHORT NlsOemCodePage = 0;
30 BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */
31 PWCHAR NlsOemToUnicodeTable = NULL;
32 PCHAR NlsUnicodeToOemTable =NULL;
33 PWCHAR NlsDbcsUnicodeToOemTable = NULL;
34 PUSHORT _NlsOemLeadByteInfo = NULL; /* exported */
35
36 USHORT NlsOemDefaultChar = '\0';
37 USHORT NlsUnicodeDefaultChar = 0;
38
39
40 #define NlsOemLeadByteInfo _NlsOemLeadByteInfo
41 #define INIT_FUNCTION
42
43 /* FUNCTIONS *****************************************************************/
44
45 /*
46 * @unimplemented
47 */
48 NTSTATUS NTAPI
49 RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP,
50 PWCHAR UnicodeString,
51 ULONG UnicodeSize,
52 PULONG ResultSize,
53 PCHAR CustomString,
54 ULONG CustomSize)
55 {
56 ULONG Size = 0;
57 ULONG i;
58
59 if (CustomCP->DBCSCodePage == 0)
60 {
61 /* single-byte code page */
62 if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
63 Size = UnicodeSize / sizeof(WCHAR);
64 else
65 Size = CustomSize;
66
67 if (ResultSize != NULL)
68 *ResultSize = Size * sizeof(WCHAR);
69
70 for (i = 0; i < Size; i++)
71 {
72 *UnicodeString = CustomCP->MultiByteTable[(UCHAR)*CustomString];
73 UnicodeString++;
74 CustomString++;
75 }
76 }
77 else
78 {
79 /* multi-byte code page */
80 /* FIXME */
81 ASSERT(FALSE);
82 }
83
84 return(STATUS_SUCCESS);
85 }
86
87
88
89 WCHAR NTAPI
90 RtlDowncaseUnicodeChar (IN WCHAR Source)
91 {
92 USHORT Offset;
93
94 if (Source < L'A')
95 return Source;
96
97 if (Source <= L'Z')
98 return Source + (L'a' - L'A');
99
100 if (Source < 0x80)
101 return Source;
102
103 Offset = ((USHORT)Source >> 8);
104 DPRINT("Offset: %hx\n", Offset);
105
106 Offset = NlsUnicodeLowercaseTable[Offset];
107 DPRINT("Offset: %hx\n", Offset);
108
109 Offset += (((USHORT)Source & 0x00F0) >> 4);
110 DPRINT("Offset: %hx\n", Offset);
111
112 Offset = NlsUnicodeLowercaseTable[Offset];
113 DPRINT("Offset: %hx\n", Offset);
114
115 Offset += ((USHORT)Source & 0x000F);
116 DPRINT("Offset: %hx\n", Offset);
117
118 Offset = NlsUnicodeLowercaseTable[Offset];
119 DPRINT("Offset: %hx\n", Offset);
120
121 DPRINT("Result: %hx\n", Source + (SHORT)Offset);
122
123 return Source + (SHORT)Offset;
124 }
125
126
127
128
129 /*
130 * @implemented
131 */
132 VOID NTAPI
133 RtlGetDefaultCodePage(OUT PUSHORT AnsiCodePage,
134 OUT PUSHORT OemCodePage)
135 {
136 *AnsiCodePage = NlsAnsiCodePage;
137 *OemCodePage = NlsOemCodePage;
138 }
139
140
141
142
143 /*
144 * @implemented
145 */
146 VOID NTAPI
147 RtlInitCodePageTable(IN PUSHORT TableBase,
148 OUT PCPTABLEINFO CodePageTable)
149 {
150 PNLS_FILE_HEADER NlsFileHeader;
151
152 DPRINT("RtlInitCodePageTable() called\n");
153
154 NlsFileHeader = (PNLS_FILE_HEADER)TableBase;
155
156 /* Copy header fields first */
157 CodePageTable->CodePage = NlsFileHeader->CodePage;
158 CodePageTable->MaximumCharacterSize = NlsFileHeader->MaximumCharacterSize;
159 CodePageTable->DefaultChar = NlsFileHeader->DefaultChar;
160 CodePageTable->UniDefaultChar = NlsFileHeader->UniDefaultChar;
161 CodePageTable->TransDefaultChar = NlsFileHeader->TransDefaultChar;
162 CodePageTable->TransUniDefaultChar = NlsFileHeader->TransUniDefaultChar;
163
164 RtlCopyMemory(&CodePageTable->LeadByte,
165 &NlsFileHeader->LeadByte,
166 MAXIMUM_LEADBYTES);
167
168 /* Offset to wide char table is after the header */
169 CodePageTable->WideCharTable = TableBase + NlsFileHeader->HeaderSize + 1 +
170 TableBase[NlsFileHeader->HeaderSize];
171
172 /* Then multibyte table (256 wchars) follows */
173 CodePageTable->MultiByteTable = TableBase + NlsFileHeader->HeaderSize + 1;
174
175 /* Check the presence of glyph table (256 wchars) */
176 if (!CodePageTable->MultiByteTable[256])
177 CodePageTable->DBCSRanges = CodePageTable->MultiByteTable + 256 + 1;
178 else
179 CodePageTable->DBCSRanges = CodePageTable->MultiByteTable + 256 + 1 + 256;
180
181 /* Is this double-byte code page? */
182 if (*CodePageTable->DBCSRanges)
183 {
184 CodePageTable->DBCSCodePage = 1;
185 CodePageTable->DBCSOffsets = CodePageTable->DBCSRanges + 1;
186 }
187 else
188 {
189 CodePageTable->DBCSCodePage = 0;
190 CodePageTable->DBCSOffsets = NULL;
191 }
192 }
193
194
195
196
197 /*
198 * @implemented
199 */
200 VOID NTAPI
201 RtlInitNlsTables(IN PUSHORT AnsiTableBase,
202 IN PUSHORT OemTableBase,
203 IN PUSHORT CaseTableBase,
204 OUT PNLSTABLEINFO NlsTable)
205 {
206 DPRINT("RtlInitNlsTables()called\n");
207
208 if (AnsiTableBase == NULL ||
209 OemTableBase == NULL ||
210 CaseTableBase == NULL)
211 return;
212
213 RtlInitCodePageTable(AnsiTableBase, &NlsTable->AnsiTableInfo);
214
215 RtlInitCodePageTable(OemTableBase, &NlsTable->OemTableInfo);
216
217 NlsTable->UpperCaseTable = (PUSHORT)CaseTableBase + 2;
218 NlsTable->LowerCaseTable = (PUSHORT)CaseTableBase + *((PUSHORT)CaseTableBase + 1) + 2;
219 }
220
221
222 /*
223 * @unimplemented
224 */
225 NTSTATUS NTAPI
226 RtlMultiByteToUnicodeN(
227 OUT PWCHAR UnicodeString,
228 IN ULONG UnicodeSize,
229 OUT PULONG ResultSize,
230 IN PCSTR MbString,
231 IN ULONG MbSize)
232 {
233 ULONG Size = 0;
234 ULONG i;
235
236 PAGED_CODE_RTL();
237
238 if (NlsMbCodePageTag == FALSE)
239 {
240 /* single-byte code page */
241 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
242 Size = UnicodeSize / sizeof(WCHAR);
243 else
244 Size = MbSize;
245
246 if (ResultSize != NULL)
247 *ResultSize = Size * sizeof(WCHAR);
248
249 for (i = 0; i < Size; i++)
250 UnicodeString[i] = NlsAnsiToUnicodeTable[(UCHAR)MbString[i]];
251 }
252 else
253 {
254 /* multi-byte code page */
255 /* FIXME */
256
257 UCHAR Char;
258 USHORT LeadByteInfo;
259 PCSTR MbEnd = MbString + MbSize;
260
261 for (i = 0; i < UnicodeSize / sizeof(WCHAR) && MbString < MbEnd; i++)
262 {
263 Char = *(PUCHAR)MbString++;
264
265 if (Char < 0x80)
266 {
267 *UnicodeString++ = Char;
268 continue;
269 }
270
271 LeadByteInfo = NlsLeadByteInfo[Char];
272
273 if (!LeadByteInfo)
274 {
275 *UnicodeString++ = NlsAnsiToUnicodeTable[Char];
276 continue;
277 }
278
279 if (MbString < MbEnd)
280 *UnicodeString++ = NlsLeadByteInfo[LeadByteInfo + *(PUCHAR)MbString++];
281 }
282
283 if (ResultSize != NULL)
284 *ResultSize = i * sizeof(WCHAR);
285 }
286
287 return STATUS_SUCCESS;
288 }
289
290
291 /*
292 * @unimplemented
293 */
294 NTSTATUS
295 NTAPI
296 RtlConsoleMultiByteToUnicodeN(
297 OUT PWCHAR UnicodeString,
298 IN ULONG UnicodeSize,
299 OUT PULONG ResultSize,
300 IN PCSTR MbString,
301 IN ULONG MbSize,
302 OUT PULONG Unknown)
303 {
304 PAGED_CODE_RTL();
305
306 UNIMPLEMENTED;
307 DPRINT1("RtlConsoleMultiByteToUnicodeN calling RtlMultiByteToUnicodeN\n");
308 *Unknown = 1;
309 return RtlMultiByteToUnicodeN(UnicodeString,
310 UnicodeSize,
311 ResultSize,
312 MbString,
313 MbSize);
314 }
315
316
317
318 /*
319 * @implemented
320 */
321 NTSTATUS
322 NTAPI
323 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
324 PCSTR MbString,
325 ULONG MbSize)
326 {
327 ULONG Length = 0;
328
329 PAGED_CODE_RTL();
330
331 if (!NlsMbCodePageTag)
332 {
333 /* single-byte code page */
334 *UnicodeSize = MbSize * sizeof (WCHAR);
335 }
336 else
337 {
338 /* multi-byte code page */
339 /* FIXME */
340
341 while (MbSize--)
342 {
343 UCHAR Char = *(PUCHAR)MbString++;
344
345 if (Char >= 0x80 && NlsLeadByteInfo[Char])
346 {
347 if (MbSize)
348 {
349 /* Move on */
350 MbSize--;
351 MbString++;
352 }
353 }
354
355 /* Increase returned size */
356 Length++;
357 }
358
359 /* Return final size */
360 *UnicodeSize = Length * sizeof(WCHAR);
361 }
362
363 /* Success */
364 return STATUS_SUCCESS;
365 }
366
367
368
369 /*
370 * @unimplemented
371 */
372 NTSTATUS NTAPI
373 RtlOemToUnicodeN (PWCHAR UnicodeString,
374 ULONG UnicodeSize,
375 PULONG ResultSize,
376 PCCH OemString,
377 ULONG OemSize)
378 {
379 ULONG Size = 0;
380 ULONG i;
381
382 if (NlsMbOemCodePageTag == FALSE)
383 {
384 /* single-byte code page */
385 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
386 Size = UnicodeSize / sizeof(WCHAR);
387 else
388 Size = OemSize;
389
390 if (ResultSize != NULL)
391 *ResultSize = Size * sizeof(WCHAR);
392
393 for (i = 0; i < Size; i++)
394 {
395 *UnicodeString = NlsOemToUnicodeTable[(UCHAR)*OemString];
396 UnicodeString++;
397 OemString++;
398 }
399 }
400 else
401 {
402 /* multi-byte code page */
403 /* FIXME */
404
405 UCHAR Char;
406 USHORT OemLeadByteInfo;
407 PCCH OemEnd = OemString + OemSize;
408
409 for (i = 0; i < UnicodeSize / sizeof(WCHAR) && OemString < OemEnd; i++)
410 {
411 Char = *(PUCHAR)OemString++;
412
413 if (Char < 0x80)
414 {
415 *UnicodeString++ = Char;
416 continue;
417 }
418
419 OemLeadByteInfo = NlsOemLeadByteInfo[Char];
420
421 if (!OemLeadByteInfo)
422 {
423 *UnicodeString++ = NlsOemToUnicodeTable[Char];
424 continue;
425 }
426
427 if (OemString < OemEnd)
428 *UnicodeString++ =
429 NlsOemLeadByteInfo[OemLeadByteInfo + *(PUCHAR)OemString++];
430 }
431
432 if (ResultSize != NULL)
433 *ResultSize = i * sizeof(WCHAR);
434 }
435
436 return STATUS_SUCCESS;
437 }
438
439
440
441 /*
442 * @implemented
443 */
444 VOID NTAPI
445 RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
446 {
447 DPRINT("RtlResetRtlTranslations() called\n");
448
449 /* Set ANSI data */
450 NlsAnsiToUnicodeTable = (PWCHAR)NlsTable->AnsiTableInfo.MultiByteTable; /* Real type is PUSHORT */
451 NlsUnicodeToAnsiTable = NlsTable->AnsiTableInfo.WideCharTable;
452 NlsDbcsUnicodeToAnsiTable = (PWCHAR)NlsTable->AnsiTableInfo.WideCharTable;
453 NlsMbCodePageTag = (NlsTable->AnsiTableInfo.DBCSCodePage != 0);
454 NlsLeadByteInfo = NlsTable->AnsiTableInfo.DBCSOffsets;
455 NlsAnsiCodePage = NlsTable->AnsiTableInfo.CodePage;
456 DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage);
457
458 /* Set OEM data */
459 NlsOemToUnicodeTable = (PWCHAR)NlsTable->OemTableInfo.MultiByteTable; /* Real type is PUSHORT */
460 NlsUnicodeToOemTable = NlsTable->OemTableInfo.WideCharTable;
461 NlsDbcsUnicodeToOemTable = (PWCHAR)NlsTable->OemTableInfo.WideCharTable;
462 NlsMbOemCodePageTag = (NlsTable->OemTableInfo.DBCSCodePage != 0);
463 NlsOemLeadByteInfo = NlsTable->OemTableInfo.DBCSOffsets;
464 NlsOemCodePage = NlsTable->OemTableInfo.CodePage;
465 DPRINT("Oem codepage %hu\n", NlsOemCodePage);
466
467 /* Set Unicode case map data */
468 NlsUnicodeUpcaseTable = NlsTable->UpperCaseTable;
469 NlsUnicodeLowercaseTable = NlsTable->LowerCaseTable;
470
471 /* set the default characters for RtlpDidUnicodeToOemWork */
472 NlsOemDefaultChar = NlsTable->OemTableInfo.DefaultChar;
473 NlsUnicodeDefaultChar = NlsTable->OemTableInfo.TransDefaultChar;
474 }
475
476
477
478 /*
479 * @unimplemented
480 */
481 NTSTATUS NTAPI
482 RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
483 PCHAR CustomString,
484 ULONG CustomSize,
485 PULONG ResultSize,
486 PWCHAR UnicodeString,
487 ULONG UnicodeSize)
488 {
489 ULONG Size = 0;
490 ULONG i;
491
492 if (CustomCP->DBCSCodePage == 0)
493 {
494 /* single-byte code page */
495 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
496 Size = CustomSize;
497 else
498 Size = UnicodeSize / sizeof(WCHAR);
499
500 if (ResultSize != NULL)
501 *ResultSize = Size;
502
503 for (i = 0; i < Size; i++)
504 {
505 *CustomString = ((PCHAR)CustomCP->WideCharTable)[*UnicodeString];
506 CustomString++;
507 UnicodeString++;
508 }
509 }
510 else
511 {
512 /* multi-byte code page */
513 /* FIXME */
514 ASSERT(FALSE);
515 }
516
517 return STATUS_SUCCESS;
518 }
519
520
521
522 /*
523 * @unimplemented
524 */
525 NTSTATUS NTAPI
526 RtlUnicodeToMultiByteN (PCHAR MbString,
527 ULONG MbSize,
528 PULONG ResultSize,
529 PCWCH UnicodeString,
530 ULONG UnicodeSize)
531 {
532 ULONG Size = 0;
533 ULONG i;
534
535 PAGED_CODE_RTL();
536
537 if (NlsMbCodePageTag == FALSE)
538 {
539 /* single-byte code page */
540 Size = (UnicodeSize > (MbSize * sizeof (WCHAR)))
541 ? MbSize
542 : (UnicodeSize / sizeof (WCHAR));
543
544 if (ResultSize != NULL)
545 {
546 *ResultSize = Size;
547 }
548
549 for (i = 0; i < Size; i++)
550 {
551 *MbString++ = NlsUnicodeToAnsiTable[*UnicodeString++];
552 }
553 }
554 else
555 {
556 /* multi-byte code page */
557 /* FIXME */
558
559 USHORT WideChar;
560 USHORT MbChar;
561
562 for (i = MbSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
563 {
564 WideChar = *UnicodeString++;
565
566 if (WideChar < 0x80)
567 {
568 *MbString++ = LOBYTE(WideChar);
569 continue;
570 }
571
572 MbChar = NlsDbcsUnicodeToAnsiTable[WideChar];
573
574 if (!HIBYTE(MbChar))
575 {
576 *MbString++ = LOBYTE(MbChar);
577 continue;
578 }
579
580 if (i >= 2)
581 {
582 *MbString++ = HIBYTE(MbChar);
583 *MbString++ = LOBYTE(MbChar);
584 i--;
585 }
586 else break;
587 }
588
589 if (ResultSize != NULL)
590 *ResultSize = MbSize - i;
591 }
592
593 return STATUS_SUCCESS;
594 }
595
596 /*
597 * @implemented
598 */
599 NTSTATUS
600 NTAPI
601 RtlUnicodeToMultiByteSize(PULONG MbSize,
602 PCWCH UnicodeString,
603 ULONG UnicodeSize)
604 {
605 ULONG UnicodeLength = UnicodeSize / sizeof(WCHAR);
606 ULONG MbLength = 0;
607
608 if (!NlsMbCodePageTag)
609 {
610 /* single-byte code page */
611 *MbSize = UnicodeLength;
612 }
613 else
614 {
615 /* multi-byte code page */
616 /* FIXME */
617
618 while (UnicodeLength--)
619 {
620 USHORT WideChar = *UnicodeString++;
621
622 if (WideChar >= 0x80 && HIBYTE(NlsDbcsUnicodeToAnsiTable[WideChar]))
623 {
624 MbLength += sizeof(WCHAR);
625 }
626 else
627 {
628 MbLength++;
629 }
630 }
631
632 *MbSize = MbLength;
633 }
634
635 /* Success */
636 return STATUS_SUCCESS;
637 }
638
639 /*
640 * @unimplemented
641 */
642 NTSTATUS NTAPI
643 RtlUnicodeToOemN (PCHAR OemString,
644 ULONG OemSize,
645 PULONG ResultSize,
646 PCWCH UnicodeString,
647 ULONG UnicodeSize)
648 {
649 ULONG Size = 0;
650 ULONG i;
651
652 if (NlsMbOemCodePageTag == FALSE)
653 {
654 /* single-byte code page */
655 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
656 Size = OemSize;
657 else
658 Size = UnicodeSize / sizeof(WCHAR);
659
660 if (ResultSize != NULL)
661 *ResultSize = Size;
662
663 for (i = 0; i < Size; i++)
664 {
665 *OemString = NlsUnicodeToOemTable[*UnicodeString];
666 OemString++;
667 UnicodeString++;
668 }
669 }
670 else
671 {
672 /* multi-byte code page */
673 /* FIXME */
674
675 USHORT WideChar;
676 USHORT OemChar;
677
678 for (i = OemSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
679 {
680 WideChar = *UnicodeString++;
681
682 if (WideChar < 0x80)
683 {
684 *OemString++ = LOBYTE(WideChar);
685 continue;
686 }
687
688 OemChar = NlsDbcsUnicodeToOemTable[WideChar];
689
690 if (!HIBYTE(OemChar))
691 {
692 *OemString++ = LOBYTE(OemChar);
693 continue;
694 }
695
696 if (i >= 2)
697 {
698 *OemString++ = HIBYTE(OemChar);
699 *OemString++ = LOBYTE(OemChar);
700 i--;
701 }
702 else break;
703 }
704
705 if (ResultSize != NULL)
706 *ResultSize = OemSize - i;
707 }
708
709 return STATUS_SUCCESS;
710 }
711
712
713
714
715 /*
716 * @implemented
717 */
718 WCHAR NTAPI
719 RtlUpcaseUnicodeChar(IN WCHAR Source)
720 {
721 USHORT Offset;
722
723 if (Source < 'a')
724 return Source;
725
726 if (Source <= 'z')
727 return (Source - ('a' - 'A'));
728
729 Offset = ((USHORT)Source >> 8) & 0xFF;
730 Offset = NlsUnicodeUpcaseTable[Offset];
731
732 Offset += ((USHORT)Source >> 4) & 0xF;
733 Offset = NlsUnicodeUpcaseTable[Offset];
734
735 Offset += ((USHORT)Source & 0xF);
736 Offset = NlsUnicodeUpcaseTable[Offset];
737
738 return Source + (SHORT)Offset;
739 }
740
741
742
743 /*
744 * @unimplemented
745 */
746 NTSTATUS NTAPI
747 RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP,
748 PCHAR CustomString,
749 ULONG CustomSize,
750 PULONG ResultSize,
751 PWCHAR UnicodeString,
752 ULONG UnicodeSize)
753 {
754 WCHAR UpcaseChar;
755 ULONG Size = 0;
756 ULONG i;
757
758 if (CustomCP->DBCSCodePage == 0)
759 {
760 /* single-byte code page */
761 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
762 Size = CustomSize;
763 else
764 Size = UnicodeSize / sizeof(WCHAR);
765
766 if (ResultSize != NULL)
767 *ResultSize = Size;
768
769 for (i = 0; i < Size; i++)
770 {
771 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
772 *CustomString = ((PCHAR)CustomCP->WideCharTable)[UpcaseChar];
773 CustomString++;
774 UnicodeString++;
775 }
776 }
777 else
778 {
779 /* multi-byte code page */
780 /* FIXME */
781 ASSERT(FALSE);
782 }
783
784 return STATUS_SUCCESS;
785 }
786
787
788 /*
789 * @unimplemented
790 */
791 NTSTATUS NTAPI
792 RtlUpcaseUnicodeToMultiByteN (PCHAR MbString,
793 ULONG MbSize,
794 PULONG ResultSize,
795 PCWCH UnicodeString,
796 ULONG UnicodeSize)
797 {
798 WCHAR UpcaseChar;
799 ULONG Size = 0;
800 ULONG i;
801
802 if (NlsMbCodePageTag == FALSE)
803 {
804 /* single-byte code page */
805 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
806 Size = MbSize;
807 else
808 Size = UnicodeSize / sizeof(WCHAR);
809
810 if (ResultSize != NULL)
811 *ResultSize = Size;
812
813 for (i = 0; i < Size; i++)
814 {
815 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
816 *MbString = NlsUnicodeToAnsiTable[UpcaseChar];
817 MbString++;
818 UnicodeString++;
819 }
820 }
821 else
822 {
823 /* multi-byte code page */
824 /* FIXME */
825 ASSERT(FALSE);
826 }
827
828 return STATUS_SUCCESS;
829 }
830
831
832 /*
833 * @unimplemented
834 */
835 NTSTATUS NTAPI
836 RtlUpcaseUnicodeToOemN (PCHAR OemString,
837 ULONG OemSize,
838 PULONG ResultSize,
839 PCWCH UnicodeString,
840 ULONG UnicodeSize)
841 {
842 WCHAR UpcaseChar;
843 ULONG Size = 0;
844 ULONG i;
845
846 ASSERT(NlsUnicodeToOemTable != NULL);
847
848 if (NlsMbOemCodePageTag == FALSE)
849 {
850 /* single-byte code page */
851 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
852 Size = OemSize;
853 else
854 Size = UnicodeSize / sizeof(WCHAR);
855
856 if (ResultSize != NULL)
857 *ResultSize = Size;
858
859 for (i = 0; i < Size; i++)
860 {
861 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
862 *OemString = NlsUnicodeToOemTable[UpcaseChar];
863 OemString++;
864 UnicodeString++;
865 }
866 }
867 else
868 {
869 /* multi-byte code page */
870 /* FIXME */
871
872 USHORT WideChar;
873 USHORT OemChar;
874
875 for (i = OemSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
876 {
877 WideChar = RtlUpcaseUnicodeChar(*UnicodeString++);
878
879 if (WideChar < 0x80)
880 {
881 *OemString++ = LOBYTE(WideChar);
882 continue;
883 }
884
885 OemChar = NlsDbcsUnicodeToOemTable[WideChar];
886
887 if (!HIBYTE(OemChar))
888 {
889 *OemString++ = LOBYTE(OemChar);
890 continue;
891 }
892
893 if (i >= 2)
894 {
895 *OemString++ = HIBYTE(OemChar);
896 *OemString++ = LOBYTE(OemChar);
897 i--;
898 }
899 else break;
900 }
901
902 if (ResultSize != NULL)
903 *ResultSize = OemSize - i;
904 }
905
906 return STATUS_SUCCESS;
907 }
908
909
910
911 /*
912 * @unimplemented
913 */
914 CHAR NTAPI
915 RtlUpperChar (IN CHAR Source)
916 {
917 WCHAR Unicode;
918 CHAR Destination;
919
920 /* Check for simple ANSI case */
921 if (Source <= 'z')
922 {
923 /* Check for simple downcase a-z case */
924 if (Source >= 'a')
925 {
926 /* Just XOR with the difference */
927 return Source ^ ('a' - 'A');
928 }
929 else
930 {
931 /* Otherwise return the same char, it's already upcase */
932 return Source;
933 }
934 }
935 else
936 {
937 if (NlsMbCodePageTag == FALSE)
938 {
939 /* single-byte code page */
940
941 /* ansi->unicode */
942 Unicode = NlsAnsiToUnicodeTable[(UCHAR)Source];
943
944 /* upcase conversion */
945 Unicode = RtlUpcaseUnicodeChar (Unicode);
946
947 /* unicode -> ansi */
948 Destination = NlsUnicodeToAnsiTable[(USHORT)Unicode];
949 }
950 else
951 {
952 /* multi-byte code page */
953 /* FIXME */
954 Destination = Source;
955 }
956 }
957
958 return Destination;
959 }
960
961 /* EOF */