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