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