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