Synchronize with trunk r58457.
[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 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 /*
293 * @implemented
294 */
295 NTSTATUS
296 NTAPI
297 RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
298 PCSTR MbString,
299 ULONG MbSize)
300 {
301 ULONG Length = 0;
302
303 PAGED_CODE_RTL();
304
305 if (!NlsMbCodePageTag)
306 {
307 /* single-byte code page */
308 *UnicodeSize = MbSize * sizeof (WCHAR);
309 }
310 else
311 {
312 /* multi-byte code page */
313 /* FIXME */
314
315 while (MbSize--)
316 {
317 UCHAR Char = *(PUCHAR)MbString++;
318
319 if (Char >= 0x80 && NlsLeadByteInfo[Char])
320 {
321 if (MbSize)
322 {
323 /* Move on */
324 MbSize--;
325 MbString++;
326 }
327 }
328
329 /* Increase returned size */
330 Length++;
331 }
332
333 /* Return final size */
334 *UnicodeSize = Length * sizeof(WCHAR);
335 }
336
337 /* Success */
338 return STATUS_SUCCESS;
339 }
340
341
342
343 /*
344 * @unimplemented
345 */
346 NTSTATUS NTAPI
347 RtlOemToUnicodeN (PWCHAR UnicodeString,
348 ULONG UnicodeSize,
349 PULONG ResultSize,
350 PCCH OemString,
351 ULONG OemSize)
352 {
353 ULONG Size = 0;
354 ULONG i;
355
356 if (NlsMbOemCodePageTag == FALSE)
357 {
358 /* single-byte code page */
359 if (OemSize > (UnicodeSize / sizeof(WCHAR)))
360 Size = UnicodeSize / sizeof(WCHAR);
361 else
362 Size = OemSize;
363
364 if (ResultSize != NULL)
365 *ResultSize = Size * sizeof(WCHAR);
366
367 for (i = 0; i < Size; i++)
368 {
369 *UnicodeString = NlsOemToUnicodeTable[(UCHAR)*OemString];
370 UnicodeString++;
371 OemString++;
372 }
373 }
374 else
375 {
376 /* multi-byte code page */
377 /* FIXME */
378
379 UCHAR Char;
380 USHORT OemLeadByteInfo;
381 PCCH OemEnd = OemString + OemSize;
382
383 for (i = 0; i < UnicodeSize / sizeof(WCHAR) && OemString < OemEnd; i++)
384 {
385 Char = *(PUCHAR)OemString++;
386
387 if (Char < 0x80)
388 {
389 *UnicodeString++ = Char;
390 continue;
391 }
392
393 OemLeadByteInfo = NlsOemLeadByteInfo[Char];
394
395 if (!OemLeadByteInfo)
396 {
397 *UnicodeString++ = NlsOemToUnicodeTable[Char];
398 continue;
399 }
400
401 if (OemString < OemEnd)
402 *UnicodeString++ =
403 NlsOemLeadByteInfo[OemLeadByteInfo + *(PUCHAR)OemString++];
404 }
405
406 if (ResultSize != NULL)
407 *ResultSize = i * sizeof(WCHAR);
408 }
409
410 return STATUS_SUCCESS;
411 }
412
413
414
415 /*
416 * @implemented
417 */
418 VOID NTAPI
419 RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
420 {
421 DPRINT("RtlResetRtlTranslations() called\n");
422
423 /* Set ANSI data */
424 NlsAnsiToUnicodeTable = (PWCHAR)NlsTable->AnsiTableInfo.MultiByteTable; /* Real type is PUSHORT */
425 NlsUnicodeToAnsiTable = NlsTable->AnsiTableInfo.WideCharTable;
426 NlsDbcsUnicodeToAnsiTable = (PWCHAR)NlsTable->AnsiTableInfo.WideCharTable;
427 NlsMbCodePageTag = (NlsTable->AnsiTableInfo.DBCSCodePage != 0);
428 NlsLeadByteInfo = NlsTable->AnsiTableInfo.DBCSOffsets;
429 NlsAnsiCodePage = NlsTable->AnsiTableInfo.CodePage;
430 DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage);
431
432 /* Set OEM data */
433 NlsOemToUnicodeTable = (PWCHAR)NlsTable->OemTableInfo.MultiByteTable; /* Real type is PUSHORT */
434 NlsUnicodeToOemTable = NlsTable->OemTableInfo.WideCharTable;
435 NlsDbcsUnicodeToOemTable = (PWCHAR)NlsTable->OemTableInfo.WideCharTable;
436 NlsMbOemCodePageTag = (NlsTable->OemTableInfo.DBCSCodePage != 0);
437 NlsOemLeadByteInfo = NlsTable->OemTableInfo.DBCSOffsets;
438 NlsOemCodePage = NlsTable->OemTableInfo.CodePage;
439 DPRINT("Oem codepage %hu\n", NlsOemCodePage);
440
441 /* Set Unicode case map data */
442 NlsUnicodeUpcaseTable = NlsTable->UpperCaseTable;
443 NlsUnicodeLowercaseTable = NlsTable->LowerCaseTable;
444
445 /* set the default characters for RtlpDidUnicodeToOemWork */
446 NlsOemDefaultChar = NlsTable->OemTableInfo.DefaultChar;
447 NlsUnicodeDefaultChar = NlsTable->OemTableInfo.TransDefaultChar;
448 }
449
450
451
452 /*
453 * @unimplemented
454 */
455 NTSTATUS NTAPI
456 RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
457 PCHAR CustomString,
458 ULONG CustomSize,
459 PULONG ResultSize,
460 PWCHAR UnicodeString,
461 ULONG UnicodeSize)
462 {
463 ULONG Size = 0;
464 ULONG i;
465
466 if (CustomCP->DBCSCodePage == 0)
467 {
468 /* single-byte code page */
469 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
470 Size = CustomSize;
471 else
472 Size = UnicodeSize / sizeof(WCHAR);
473
474 if (ResultSize != NULL)
475 *ResultSize = Size;
476
477 for (i = 0; i < Size; i++)
478 {
479 *CustomString = ((PCHAR)CustomCP->WideCharTable)[*UnicodeString];
480 CustomString++;
481 UnicodeString++;
482 }
483 }
484 else
485 {
486 /* multi-byte code page */
487 /* FIXME */
488 ASSERT(FALSE);
489 }
490
491 return STATUS_SUCCESS;
492 }
493
494
495
496 /*
497 * @unimplemented
498 */
499 NTSTATUS NTAPI
500 RtlUnicodeToMultiByteN (PCHAR MbString,
501 ULONG MbSize,
502 PULONG ResultSize,
503 PCWCH UnicodeString,
504 ULONG UnicodeSize)
505 {
506 ULONG Size = 0;
507 ULONG i;
508
509 PAGED_CODE_RTL();
510
511 if (NlsMbCodePageTag == FALSE)
512 {
513 /* single-byte code page */
514 Size = (UnicodeSize > (MbSize * sizeof (WCHAR)))
515 ? MbSize
516 : (UnicodeSize / sizeof (WCHAR));
517
518 if (ResultSize != NULL)
519 {
520 *ResultSize = Size;
521 }
522
523 for (i = 0; i < Size; i++)
524 {
525 *MbString++ = NlsUnicodeToAnsiTable[*UnicodeString++];
526 }
527 }
528 else
529 {
530 /* multi-byte code page */
531 /* FIXME */
532
533 USHORT WideChar;
534 USHORT MbChar;
535
536 for (i = MbSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
537 {
538 WideChar = *UnicodeString++;
539
540 if (WideChar < 0x80)
541 {
542 *MbString++ = LOBYTE(WideChar);
543 continue;
544 }
545
546 MbChar = NlsDbcsUnicodeToAnsiTable[WideChar];
547
548 if (!HIBYTE(MbChar))
549 {
550 *MbString++ = LOBYTE(MbChar);
551 continue;
552 }
553
554 if (i >= 2)
555 {
556 *MbString++ = HIBYTE(MbChar);
557 *MbString++ = LOBYTE(MbChar);
558 i--;
559 }
560 else break;
561 }
562
563 if (ResultSize != NULL)
564 *ResultSize = MbSize - i;
565 }
566
567 return STATUS_SUCCESS;
568 }
569
570 /*
571 * @implemented
572 */
573 NTSTATUS
574 NTAPI
575 RtlUnicodeToMultiByteSize(PULONG MbSize,
576 PCWCH UnicodeString,
577 ULONG UnicodeSize)
578 {
579 ULONG UnicodeLength = UnicodeSize / sizeof(WCHAR);
580 ULONG MbLength = 0;
581
582 if (!NlsMbCodePageTag)
583 {
584 /* single-byte code page */
585 *MbSize = UnicodeLength;
586 }
587 else
588 {
589 /* multi-byte code page */
590 /* FIXME */
591
592 while (UnicodeLength--)
593 {
594 USHORT WideChar = *UnicodeString++;
595
596 if (WideChar >= 0x80 && HIBYTE(NlsDbcsUnicodeToAnsiTable[WideChar]))
597 {
598 MbLength += sizeof(WCHAR);
599 }
600 else
601 {
602 MbLength++;
603 }
604 }
605
606 *MbSize = MbLength;
607 }
608
609 /* Success */
610 return STATUS_SUCCESS;
611 }
612
613 /*
614 * @unimplemented
615 */
616 NTSTATUS NTAPI
617 RtlUnicodeToOemN (PCHAR OemString,
618 ULONG OemSize,
619 PULONG ResultSize,
620 PCWCH UnicodeString,
621 ULONG UnicodeSize)
622 {
623 ULONG Size = 0;
624 ULONG i;
625
626 if (NlsMbOemCodePageTag == FALSE)
627 {
628 /* single-byte code page */
629 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
630 Size = OemSize;
631 else
632 Size = UnicodeSize / sizeof(WCHAR);
633
634 if (ResultSize != NULL)
635 *ResultSize = Size;
636
637 for (i = 0; i < Size; i++)
638 {
639 *OemString = NlsUnicodeToOemTable[*UnicodeString];
640 OemString++;
641 UnicodeString++;
642 }
643 }
644 else
645 {
646 /* multi-byte code page */
647 /* FIXME */
648
649 USHORT WideChar;
650 USHORT OemChar;
651
652 for (i = OemSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
653 {
654 WideChar = *UnicodeString++;
655
656 if (WideChar < 0x80)
657 {
658 *OemString++ = LOBYTE(WideChar);
659 continue;
660 }
661
662 OemChar = NlsDbcsUnicodeToOemTable[WideChar];
663
664 if (!HIBYTE(OemChar))
665 {
666 *OemString++ = LOBYTE(OemChar);
667 continue;
668 }
669
670 if (i >= 2)
671 {
672 *OemString++ = HIBYTE(OemChar);
673 *OemString++ = LOBYTE(OemChar);
674 i--;
675 }
676 else break;
677 }
678
679 if (ResultSize != NULL)
680 *ResultSize = OemSize - i;
681 }
682
683 return STATUS_SUCCESS;
684 }
685
686
687
688
689 /*
690 * @implemented
691 */
692 WCHAR NTAPI
693 RtlUpcaseUnicodeChar(IN WCHAR Source)
694 {
695 USHORT Offset;
696
697 if (Source < 'a')
698 return Source;
699
700 if (Source <= 'z')
701 return (Source - ('a' - 'A'));
702
703 Offset = ((USHORT)Source >> 8) & 0xFF;
704 Offset = NlsUnicodeUpcaseTable[Offset];
705
706 Offset += ((USHORT)Source >> 4) & 0xF;
707 Offset = NlsUnicodeUpcaseTable[Offset];
708
709 Offset += ((USHORT)Source & 0xF);
710 Offset = NlsUnicodeUpcaseTable[Offset];
711
712 return Source + (SHORT)Offset;
713 }
714
715
716
717 /*
718 * @unimplemented
719 */
720 NTSTATUS NTAPI
721 RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP,
722 PCHAR CustomString,
723 ULONG CustomSize,
724 PULONG ResultSize,
725 PWCHAR UnicodeString,
726 ULONG UnicodeSize)
727 {
728 WCHAR UpcaseChar;
729 ULONG Size = 0;
730 ULONG i;
731
732 if (CustomCP->DBCSCodePage == 0)
733 {
734 /* single-byte code page */
735 if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
736 Size = CustomSize;
737 else
738 Size = UnicodeSize / sizeof(WCHAR);
739
740 if (ResultSize != NULL)
741 *ResultSize = Size;
742
743 for (i = 0; i < Size; i++)
744 {
745 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
746 *CustomString = ((PCHAR)CustomCP->WideCharTable)[UpcaseChar];
747 CustomString++;
748 UnicodeString++;
749 }
750 }
751 else
752 {
753 /* multi-byte code page */
754 /* FIXME */
755 ASSERT(FALSE);
756 }
757
758 return STATUS_SUCCESS;
759 }
760
761
762 /*
763 * @unimplemented
764 */
765 NTSTATUS NTAPI
766 RtlUpcaseUnicodeToMultiByteN (PCHAR MbString,
767 ULONG MbSize,
768 PULONG ResultSize,
769 PCWCH UnicodeString,
770 ULONG UnicodeSize)
771 {
772 WCHAR UpcaseChar;
773 ULONG Size = 0;
774 ULONG i;
775
776 if (NlsMbCodePageTag == FALSE)
777 {
778 /* single-byte code page */
779 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
780 Size = MbSize;
781 else
782 Size = UnicodeSize / sizeof(WCHAR);
783
784 if (ResultSize != NULL)
785 *ResultSize = Size;
786
787 for (i = 0; i < Size; i++)
788 {
789 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
790 *MbString = NlsUnicodeToAnsiTable[UpcaseChar];
791 MbString++;
792 UnicodeString++;
793 }
794 }
795 else
796 {
797 /* multi-byte code page */
798 /* FIXME */
799 ASSERT(FALSE);
800 }
801
802 return STATUS_SUCCESS;
803 }
804
805
806 /*
807 * @unimplemented
808 */
809 NTSTATUS NTAPI
810 RtlUpcaseUnicodeToOemN (PCHAR OemString,
811 ULONG OemSize,
812 PULONG ResultSize,
813 PCWCH UnicodeString,
814 ULONG UnicodeSize)
815 {
816 WCHAR UpcaseChar;
817 ULONG Size = 0;
818 ULONG i;
819
820 ASSERT(NlsUnicodeToOemTable != NULL);
821
822 if (NlsMbOemCodePageTag == FALSE)
823 {
824 /* single-byte code page */
825 if (UnicodeSize > (OemSize * sizeof(WCHAR)))
826 Size = OemSize;
827 else
828 Size = UnicodeSize / sizeof(WCHAR);
829
830 if (ResultSize != NULL)
831 *ResultSize = Size;
832
833 for (i = 0; i < Size; i++)
834 {
835 UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
836 *OemString = NlsUnicodeToOemTable[UpcaseChar];
837 OemString++;
838 UnicodeString++;
839 }
840 }
841 else
842 {
843 /* multi-byte code page */
844 /* FIXME */
845
846 USHORT WideChar;
847 USHORT OemChar;
848
849 for (i = OemSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
850 {
851 WideChar = RtlUpcaseUnicodeChar(*UnicodeString++);
852
853 if (WideChar < 0x80)
854 {
855 *OemString++ = LOBYTE(WideChar);
856 continue;
857 }
858
859 OemChar = NlsDbcsUnicodeToOemTable[WideChar];
860
861 if (!HIBYTE(OemChar))
862 {
863 *OemString++ = LOBYTE(OemChar);
864 continue;
865 }
866
867 if (i >= 2)
868 {
869 *OemString++ = HIBYTE(OemChar);
870 *OemString++ = LOBYTE(OemChar);
871 i--;
872 }
873 else break;
874 }
875
876 if (ResultSize != NULL)
877 *ResultSize = OemSize - i;
878 }
879
880 return STATUS_SUCCESS;
881 }
882
883
884
885 /*
886 * @unimplemented
887 */
888 CHAR NTAPI
889 RtlUpperChar (IN CHAR Source)
890 {
891 WCHAR Unicode;
892 CHAR Destination;
893
894 /* Check for simple ANSI case */
895 if (Source <= 'z')
896 {
897 /* Check for simple downcase a-z case */
898 if (Source >= 'a')
899 {
900 /* Just XOR with the difference */
901 return Source ^ ('a' - 'A');
902 }
903 else
904 {
905 /* Otherwise return the same char, it's already upcase */
906 return Source;
907 }
908 }
909 else
910 {
911 if (NlsMbCodePageTag == FALSE)
912 {
913 /* single-byte code page */
914
915 /* ansi->unicode */
916 Unicode = NlsAnsiToUnicodeTable[(UCHAR)Source];
917
918 /* upcase conversion */
919 Unicode = RtlUpcaseUnicodeChar (Unicode);
920
921 /* unicode -> ansi */
922 Destination = NlsUnicodeToAnsiTable[(USHORT)Unicode];
923 }
924 else
925 {
926 /* multi-byte code page */
927 /* FIXME */
928 Destination = Source;
929 }
930 }
931
932 return Destination;
933 }
934
935 /* EOF */