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