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