branch update for HEAD-2003050101
[reactos.git] / lib / ntdll / rtl / unicode.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            lib/ntdll/rtl/unicode.c
6  * PURPOSE:         String functions
7  * PROGRAMMER:      Jason Filby (jasonfilby@yahoo.com)
8  * UPDATE HISTORY:
9  *                  Created 10/08/98
10  */
11
12 #include <ddk/ntddk.h>
13 #include <ntdll/rtl.h>
14 //#include <internal/nls.h>
15 #include <ctype.h>
16 #include <ntos/minmax.h>
17 #define NDEBUG
18 #include <ntdll/ntdll.h>
19
20 /* FUNCTIONS *****************************************************************/
21
22 WCHAR
23 STDCALL
24 RtlAnsiCharToUnicodeChar(
25         IN      CHAR    AnsiChar)
26 {
27         ULONG Size;
28         WCHAR UnicodeChar;
29
30         Size = 1;
31 #if 0
32         Size = (NlsLeadByteInfo[AnsiChar] == 0) ? 1 : 2;
33 #endif
34
35         RtlMultiByteToUnicodeN (&UnicodeChar,
36                                 sizeof(WCHAR),
37                                 NULL,
38                                 &AnsiChar,
39                                 Size);
40
41         return UnicodeChar;
42 }
43
44
45 ULONG
46 STDCALL
47 RtlAnsiStringToUnicodeSize(
48         IN      PANSI_STRING    AnsiString)
49 {
50         ULONG Size;
51
52         RtlMultiByteToUnicodeSize (&Size,
53                                    AnsiString->Buffer,
54                                    AnsiString->Length);
55
56         return Size;
57 }
58
59
60 NTSTATUS
61 STDCALL
62 RtlAnsiStringToUnicodeString(
63         IN OUT  PUNICODE_STRING DestinationString,
64         IN      PANSI_STRING    SourceString,
65         IN      BOOLEAN         AllocateDestinationString)
66 {
67         NTSTATUS Status;
68         ULONG Length;
69
70         if (NlsMbCodePageTag == TRUE)
71                 Length = RtlAnsiStringToUnicodeSize (SourceString);
72         else
73                 Length = SourceString->Length * sizeof(WCHAR);
74
75         if (Length > 65535)
76                 return STATUS_INVALID_PARAMETER_2;
77
78         if (AllocateDestinationString == TRUE)
79         {
80                 DestinationString->MaximumLength = Length + sizeof(WCHAR);
81                 DestinationString->Buffer =
82                         RtlAllocateHeap (RtlGetProcessHeap (),
83                                          0,
84                                          DestinationString->MaximumLength);
85                 if (DestinationString->Buffer == NULL)
86                         return STATUS_NO_MEMORY;
87         }
88         else
89         {
90                 if (Length + sizeof(WCHAR) > DestinationString->MaximumLength)
91                 {
92                         DPRINT("STATUS_BUFFER_TOO_SMALL\n");
93                         return STATUS_BUFFER_TOO_SMALL;
94                 }
95         }
96         DestinationString->Length = Length;
97
98         RtlZeroMemory (DestinationString->Buffer,
99                        DestinationString->Length);
100
101         Status = RtlMultiByteToUnicodeN (DestinationString->Buffer,
102                                          DestinationString->Length,
103                                          NULL,
104                                          SourceString->Buffer,
105                                          SourceString->Length);
106         if (!NT_SUCCESS(Status))
107         {
108                 if (AllocateDestinationString)
109                 {
110                         RtlFreeHeap (RtlGetProcessHeap (),
111                                      0,
112                                      DestinationString->Buffer);
113                 }
114                 return Status;
115         }
116
117         DestinationString->Buffer[Length / sizeof(WCHAR)] = 0;
118
119         return STATUS_SUCCESS;
120 }
121
122
123 NTSTATUS
124 STDCALL
125 RtlAppendAsciizToString(
126         IN OUT  PSTRING Destination,
127         IN      PCSZ    Source)
128 {
129         ULONG Length;
130         PCHAR Ptr;
131
132         if (Source == NULL)
133                 return STATUS_SUCCESS;
134
135         Length = strlen (Source);
136         if (Destination->Length + Length >= Destination->MaximumLength)
137                 return STATUS_BUFFER_TOO_SMALL;
138
139         Ptr = Destination->Buffer + Destination->Length;
140         memmove (Ptr,
141                  Source,
142                  Length);
143         Ptr += Length;
144         *Ptr = 0;
145
146         Destination->Length += Length;
147
148         return STATUS_SUCCESS;
149 }
150
151
152 NTSTATUS
153 STDCALL
154 RtlAppendStringToString(
155         IN OUT  PSTRING Destination,
156         IN      PSTRING Source)
157 {
158         PCHAR Ptr;
159
160         if (Source->Length == 0)
161                 return STATUS_SUCCESS;
162
163         if (Destination->Length + Source->Length >= Destination->MaximumLength)
164                 return STATUS_BUFFER_TOO_SMALL;
165
166         Ptr = Destination->Buffer + Destination->Length;
167         memmove (Ptr,
168                  Source->Buffer,
169                  Source->Length);
170         Ptr += Source->Length;
171         *Ptr = 0;
172
173         Destination->Length += Source->Length;
174
175         return STATUS_SUCCESS;
176 }
177
178
179 NTSTATUS
180 STDCALL
181 RtlAppendUnicodeStringToString(
182         IN OUT  PUNICODE_STRING Destination,
183         IN      PUNICODE_STRING Source)
184 {
185         PWCHAR Src;
186         PWCHAR Dest;
187         ULONG  i;
188
189         if ((Source->Length + Destination->Length) >= Destination->MaximumLength)
190                 return STATUS_BUFFER_TOO_SMALL;
191
192         Src  = Source->Buffer;
193         Dest = Destination->Buffer + (Destination->Length / sizeof (WCHAR));
194         for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
195         {
196                 *Dest = *Src;
197                 Dest++;
198                 Src++;
199         }
200         *Dest = 0;
201
202         Destination->Length += Source->Length;
203
204         return STATUS_SUCCESS;
205 }
206
207
208 NTSTATUS STDCALL
209 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination,
210                          IN PWSTR Source)
211 {
212   PWCHAR Src;
213   PWCHAR Dest;
214   ULONG i;
215   ULONG slen;
216
217   slen = wcslen(Source) * sizeof(WCHAR);
218
219   if (Destination->Length + slen >= Destination->MaximumLength)
220     return(STATUS_BUFFER_TOO_SMALL);
221
222   Src = Source;
223   Dest = Destination->Buffer + (Destination->Length / sizeof(WCHAR));
224
225   for (i = 0; i < (slen / sizeof(WCHAR)); i++)
226     {
227       *Dest = *Src;
228       Dest++;
229       Src++;
230     }
231   *Dest = 0;
232
233   Destination->Length += slen;
234
235   return(STATUS_SUCCESS);
236 }
237
238
239 NTSTATUS
240 STDCALL
241 RtlCharToInteger(
242         IN      PCSZ    String,
243         IN      ULONG   Base,
244         IN OUT  PULONG  Value)
245 {
246         ULONG Val;
247
248         *Value = 0;
249
250         if (Base == 0)
251         {
252                 Base = 10;
253                 if (*String == '0')
254                 {
255                         Base = 8;
256                         String++;
257                         if ((*String == 'x') && isxdigit (String[1]))
258                         {
259                                 String++;
260                                 Base = 16;
261                         }
262                 }
263         }
264
265         if (!isxdigit (*String))
266                 return STATUS_INVALID_PARAMETER;
267
268         while (isxdigit (*String) &&
269                (Val = isdigit (*String) ? * String - '0' : (islower (*String)
270                 ? toupper (*String) : *String) - 'A' + 10) < Base)
271         {
272                 *Value = *Value * Base + Val;
273                 String++;
274         }
275
276         return STATUS_SUCCESS;
277 }
278
279
280 LONG
281 STDCALL
282 RtlCompareString(
283         IN      PSTRING String1,
284         IN      PSTRING String2,
285         IN      BOOLEAN CaseInsensitive)
286 {
287         ULONG len1, len2;
288         PCHAR s1, s2;
289         CHAR  c1, c2;
290
291         if (String1 && String2)
292         {
293                 len1 = String1->Length;
294                 len2 = String2->Length;
295                 s1 = String1->Buffer;
296                 s2 = String2->Buffer;
297
298                 if (s1 && s2)
299                 {
300                         if (CaseInsensitive)
301                         {
302                                 while (1)
303                                 {
304                                         c1 = len1-- ? RtlUpperChar (*s1++) : 0;
305                                         c2 = len2-- ? RtlUpperChar (*s2++) : 0;
306                                         if (!c1 || !c2 || c1 != c2)
307                                                 return c1 - c2;
308                                 }
309                         }
310                         else
311                         {
312                                 while (1)
313                                 {
314                                         c1 = len1-- ? *s1++ : 0;
315                                         c2 = len2-- ? *s2++ : 0;
316                                         if (!c1 || !c2 || c1 != c2)
317                                                 return c1 - c2;
318                                 }
319                         }
320                 }
321         }
322
323         return 0;
324 }
325
326
327 LONG
328 STDCALL
329 RtlCompareUnicodeString(
330         IN      PUNICODE_STRING String1,
331         IN      PUNICODE_STRING String2,
332         IN      BOOLEAN         CaseInsensitive)
333 {
334         ULONG len1, len2;
335         PWCHAR s1, s2;
336         WCHAR  c1, c2;
337
338         if (String1 && String2)
339         {
340                 len1 = String1->Length / sizeof(WCHAR);
341                 len2 = String2->Length / sizeof(WCHAR);
342                 s1 = String1->Buffer;
343                 s2 = String2->Buffer;
344
345                 if (s1 && s2)
346                 {
347                         if (CaseInsensitive)
348                         {
349                                 while (1)
350                                 {
351                                         c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
352                                         c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
353                                         if (!c1 || !c2 || c1 != c2)
354                                                 return c1 - c2;
355                                 }
356                         }
357                         else
358                         {
359                                 while (1)
360                                 {
361                                         c1 = len1-- ? *s1++ : 0;
362                                         c2 = len2-- ? *s2++ : 0;
363                                         if (!c1 || !c2 || c1 != c2)
364                                                 return c1 - c2;
365                                 }
366                         }
367                 }
368         }
369
370         return 0;
371 }
372
373
374 VOID
375 STDCALL
376 RtlCopyString(
377         IN OUT  PSTRING DestinationString,
378         IN      PSTRING SourceString)
379 {
380         ULONG copylen, i;
381         PCHAR Src, Dest;
382
383         if (SourceString == NULL)
384         {
385                 DestinationString->Length = 0;
386                 return;
387         }
388
389         copylen = min (DestinationString->MaximumLength - sizeof(CHAR),
390                        SourceString->Length);
391         Src = SourceString->Buffer;
392         Dest = DestinationString->Buffer;
393
394         for (i = 0; i < copylen; i++)
395         {
396                 *Dest = *Src;
397                 Dest++;
398                 Src++;
399         }
400         *Dest = 0;
401
402         DestinationString->Length = copylen;
403 }
404
405
406 VOID
407 STDCALL
408 RtlCopyUnicodeString(
409         IN OUT  PUNICODE_STRING DestinationString,
410         IN      PUNICODE_STRING SourceString)
411 {
412         ULONG copylen, i;
413         PWCHAR Src, Dest;
414
415         if (SourceString == NULL)
416         {
417                 DestinationString->Length = 0;
418                 return;
419         }
420
421         copylen = min (DestinationString->MaximumLength - sizeof(WCHAR),
422                        SourceString->Length);
423         Src = SourceString->Buffer;
424         Dest = DestinationString->Buffer;
425
426         for (i = 0; i < (copylen / sizeof (WCHAR)); i++)
427         {
428                 *Dest = *Src;
429                 Dest++;
430                 Src++;
431         }
432         *Dest = 0;
433
434         DestinationString->Length = copylen;
435 }
436
437
438 BOOLEAN
439 STDCALL
440 RtlCreateUnicodeString(
441         IN OUT  PUNICODE_STRING Destination,
442         IN      PWSTR           Source)
443 {
444         ULONG Length;
445
446         Length = (wcslen (Source) + 1) * sizeof(WCHAR);
447
448         Destination->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
449                                                0,
450                                                Length);
451         if (Destination->Buffer == NULL)
452                 return FALSE;
453
454         memmove (Destination->Buffer,
455                  Source,
456                  Length);
457
458         Destination->MaximumLength = Length;
459         Destination->Length = Length - sizeof (WCHAR);
460
461         return TRUE;
462 }
463
464
465 BOOLEAN
466 STDCALL
467 RtlCreateUnicodeStringFromAsciiz(
468         OUT     PUNICODE_STRING Destination,
469                                   IN    PCSZ            Source)
470 {
471         ANSI_STRING AnsiString;
472         NTSTATUS Status;
473
474         RtlInitAnsiString (&AnsiString,
475                            Source);
476
477         Status = RtlAnsiStringToUnicodeString (Destination,
478                                                &AnsiString,
479                                                TRUE);
480
481         return NT_SUCCESS(Status);
482 }
483
484
485 NTSTATUS
486 STDCALL
487 RtlDowncaseUnicodeString(
488         IN OUT  PUNICODE_STRING DestinationString,
489         IN      PUNICODE_STRING SourceString,
490         IN      BOOLEAN         AllocateDestinationString)
491 {
492         ULONG i;
493         PWCHAR Src, Dest;
494
495         if (AllocateDestinationString == TRUE)
496         {
497                 DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR);
498                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
499                                                              0,
500                                                              SourceString->Length + sizeof(WCHAR));
501         }
502         else
503         {
504                 if (SourceString->Length >= DestinationString->MaximumLength)
505                         return STATUS_BUFFER_TOO_SMALL;
506         }
507         DestinationString->Length = SourceString->Length;
508
509         Src = SourceString->Buffer;
510         Dest = DestinationString->Buffer;
511         for (i=0; i < SourceString->Length / sizeof(WCHAR); i++)
512         {
513                 if (*Src < L'A')
514                 {
515                         *Dest = *Src;
516                 }
517                 else if (*Src <= L'Z')
518                 {
519                         *Dest = (*Src + (L'a' - L'A'));
520                 }
521                 else
522                 {
523                         /* FIXME: characters above 'Z' */
524                         *Dest = *Src;
525                 }
526
527                 Dest++;
528                 Src++;
529         }
530         *Dest = 0;
531
532         return STATUS_SUCCESS;
533 }
534
535
536 BOOLEAN
537 STDCALL
538 RtlEqualComputerName(
539         IN      PUNICODE_STRING ComputerName1,
540         IN      PUNICODE_STRING ComputerName2)
541 {
542         return RtlEqualDomainName (ComputerName1,
543                                    ComputerName2);
544 }
545
546
547 BOOLEAN
548 STDCALL
549 RtlEqualDomainName (
550         IN      PUNICODE_STRING DomainName1,
551         IN      PUNICODE_STRING DomainName2
552         )
553 {
554         OEM_STRING OemString1;
555         OEM_STRING OemString2;
556         BOOLEAN Result;
557
558         RtlUpcaseUnicodeStringToOemString (&OemString1,
559                                            DomainName1,
560                                            TRUE);
561         RtlUpcaseUnicodeStringToOemString (&OemString2,
562                                            DomainName2,
563                                            TRUE);
564
565         Result = RtlEqualString (&OemString1,
566                                  &OemString2,
567                                  FALSE);
568
569         RtlFreeOemString (&OemString1);
570         RtlFreeOemString (&OemString2);
571
572         return Result;
573 }
574
575
576 BOOLEAN
577 STDCALL
578 RtlEqualString(
579         IN      PSTRING String1,
580         IN      PSTRING String2,
581         IN      BOOLEAN CaseInsensitive)
582 {
583         ULONG i;
584         CHAR c1, c2;
585         PCHAR p1, p2;
586
587         if (String1->Length != String2->Length)
588                 return FALSE;
589
590         p1 = String1->Buffer;
591         p2 = String2->Buffer;
592         for (i = 0; i < String1->Length; i++)
593         {
594                 if (CaseInsensitive == TRUE)
595                 {
596                         c1 = RtlUpperChar (*p1);
597                         c2 = RtlUpperChar (*p2);
598                 }
599                 else
600                 {
601                         c1 = *p1;
602                         c2 = *p2;
603                 }
604
605                 if (c1 != c2)
606                         return FALSE;
607
608                 p1++;
609                 p2++;
610         }
611
612         return TRUE;
613 }
614
615
616 BOOLEAN
617 STDCALL
618 RtlEqualUnicodeString(
619         IN      PUNICODE_STRING String1,
620         IN      PUNICODE_STRING String2,
621         IN      BOOLEAN         CaseInsensitive)
622 {
623         ULONG i;
624         WCHAR wc1, wc2;
625         PWCHAR pw1, pw2;
626
627         if (String1->Length != String2->Length)
628                 return FALSE;
629
630         pw1 = String1->Buffer;
631         pw2 = String2->Buffer;
632
633         for (i = 0; i < String1->Length / sizeof(WCHAR); i++)
634         {
635                 if (CaseInsensitive == TRUE)
636                 {
637                         wc1 = RtlUpcaseUnicodeChar (*pw1);
638                         wc2 = RtlUpcaseUnicodeChar (*pw2);
639                 }
640                 else
641                 {
642                         wc1 = *pw1;
643                         wc2 = *pw2;
644                 }
645
646                 if (wc1 != wc2)
647                         return FALSE;
648
649                 pw1++;
650                 pw2++;
651         }
652
653         return TRUE;
654 }
655
656
657 VOID
658 STDCALL
659 RtlEraseUnicodeString(
660         IN      PUNICODE_STRING String)
661 {
662         if (String->Buffer == NULL)
663                 return;
664
665         if (String->MaximumLength == 0)
666                 return;
667
668         memset (String->Buffer,
669                 0,
670                 String->MaximumLength);
671
672         String->Length = 0;
673 }
674
675
676 VOID
677 STDCALL
678 RtlFreeAnsiString(
679         IN      PANSI_STRING    AnsiString)
680 {
681         if (AnsiString->Buffer == NULL)
682                 return;
683
684         RtlFreeHeap (RtlGetProcessHeap (),
685                      0,
686                      AnsiString->Buffer);
687
688         AnsiString->Buffer = NULL;
689         AnsiString->Length = 0;
690         AnsiString->MaximumLength = 0;
691 }
692
693
694 VOID
695 STDCALL
696 RtlFreeOemString(
697         IN      POEM_STRING     OemString)
698 {
699         if (OemString->Buffer == NULL)
700                 return;
701
702         RtlFreeHeap (RtlGetProcessHeap (),
703                      0,
704                      OemString->Buffer);
705
706         OemString->Buffer = NULL;
707         OemString->Length = 0;
708         OemString->MaximumLength = 0;
709 }
710
711
712 VOID
713 STDCALL
714 RtlFreeUnicodeString(
715         IN      PUNICODE_STRING UnicodeString)
716 {
717         if (UnicodeString->Buffer == NULL)
718                 return;
719
720         RtlFreeHeap (RtlGetProcessHeap (),
721                      0,
722                      UnicodeString->Buffer);
723
724         UnicodeString->Buffer = NULL;
725         UnicodeString->Length = 0;
726         UnicodeString->MaximumLength = 0;
727 }
728
729
730 VOID
731 STDCALL
732 RtlInitAnsiString(
733         IN OUT  PANSI_STRING    DestinationString,
734         IN      PCSZ            SourceString)
735 {
736         ULONG DestSize;
737
738         if(SourceString==NULL)
739         {
740                 DestinationString->Length = 0;
741                 DestinationString->MaximumLength = 0;
742         }
743         else
744         {
745                 DestSize = strlen ((const char *)SourceString);
746                 DestinationString->Length = DestSize;
747                 DestinationString->MaximumLength = DestSize + 1;
748         }
749         DestinationString->Buffer = (PCHAR)SourceString;
750 }
751
752
753 VOID
754 STDCALL
755 RtlInitString(
756         IN OUT  PSTRING DestinationString,
757         IN      PCSZ    SourceString)
758 {
759         ULONG DestSize;
760
761         if (SourceString == NULL)
762         {
763                 DestinationString->Length = 0;
764                 DestinationString->MaximumLength = 0;
765         }
766         else
767         {
768                 DestSize = strlen((const char *)SourceString);
769                 DestinationString->Length = DestSize;
770                 DestinationString->MaximumLength = DestSize + sizeof(CHAR);
771         }
772         DestinationString->Buffer = (PCHAR)SourceString;
773 }
774
775
776 VOID
777 STDCALL
778 RtlInitUnicodeString(
779         IN OUT  PUNICODE_STRING DestinationString,
780         IN      PCWSTR          SourceString)
781 {
782         ULONG DestSize;
783
784         if (SourceString==NULL)
785         {
786                 DestinationString->Length=0;
787                 DestinationString->MaximumLength=0;
788         }
789         else
790         {
791                 DestSize = wcslen((PWSTR)SourceString) * sizeof(WCHAR);
792                 DestinationString->Length = DestSize;
793                 DestinationString->MaximumLength = DestSize + sizeof(WCHAR);
794         }
795         DestinationString->Buffer = (PWSTR)SourceString;
796 }
797
798
799 NTSTATUS
800 STDCALL
801 RtlIntegerToChar(
802         IN      ULONG   Value,
803         IN      ULONG   Base,
804         IN      ULONG   Length,
805         IN OUT  PCHAR   String)
806 {
807         ULONG Radix;
808         CHAR  temp[33];
809         ULONG v = Value;
810         ULONG i;
811         PCHAR tp;
812         PCHAR sp;
813
814         Radix = Base;
815         if (Radix == 0)
816                 Radix = 10;
817
818         if ((Radix != 2) && (Radix != 8) &&
819             (Radix != 10) && (Radix != 16))
820                 return STATUS_INVALID_PARAMETER;
821
822         tp = temp;
823         while (v || tp == temp)
824         {
825                 i = v % Radix;
826                 v = v / Radix;
827                 if (i < 10)
828                         *tp = i + '0';
829                 else
830                         *tp = i + 'a' - 10;
831                 tp++;
832         }
833
834         if (tp - temp >= Length)
835                 return STATUS_BUFFER_TOO_SMALL;
836
837         sp = String;
838         while (tp > temp)
839                 *sp++ = *--tp;
840         *sp = 0;
841
842         return STATUS_SUCCESS;
843 }
844
845
846 NTSTATUS
847 STDCALL
848 RtlIntegerToUnicodeString(
849         IN      ULONG           Value,
850         IN      ULONG           Base,   /* optional */
851         IN OUT  PUNICODE_STRING String)
852 {
853         ANSI_STRING AnsiString;
854         CHAR Buffer[33];
855         NTSTATUS Status;
856
857         Status = RtlIntegerToChar (Value,
858                                    Base,
859                                    33,
860                                    Buffer);
861         if (!NT_SUCCESS(Status))
862                 return Status;
863
864         AnsiString.Buffer = Buffer;
865         AnsiString.Length = strlen (Buffer);
866         AnsiString.MaximumLength = 33;
867
868         Status = RtlAnsiStringToUnicodeString (String,
869                                                &AnsiString,
870                                                FALSE);
871
872         return Status;
873 }
874
875
876 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
877
878 ULONG STDCALL
879 RtlIsTextUnicode (PVOID Buffer,
880                   ULONG Length,
881                   ULONG *Flags)
882 {
883   PWSTR s = Buffer;
884   ULONG in_flags = (ULONG)-1;
885   ULONG out_flags = 0;
886
887   if (Length == 0)
888     goto done;
889
890   if (Flags != 0)
891     in_flags = *Flags;
892
893   /*
894    * Apply various tests to the text string. According to the
895    * docs, each test "passed" sets the corresponding flag in
896    * the output flags. But some of the tests are mutually
897    * exclusive, so I don't see how you could pass all tests ...
898    */
899
900   /* Check for an odd length ... pass if even. */
901   if (!(Length & 1))
902     out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
903
904   /* Check for the BOM (byte order mark). */
905   if (*s == 0xFEFF)
906     out_flags |= IS_TEXT_UNICODE_SIGNATURE;
907
908 #if 0
909   /* Check for the reverse BOM (byte order mark). */
910   if (*s == 0xFFFE)
911     out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
912 #endif
913
914   /* FIXME: Add more tests */
915
916   /*
917    * Check whether the string passed all of the tests.
918    */
919   in_flags &= ITU_IMPLEMENTED_TESTS;
920   if ((out_flags & in_flags) != in_flags)
921     Length = 0;
922
923 done:
924   if (Flags != 0)
925     *Flags = out_flags;
926
927   return Length;
928 }
929
930
931 NTSTATUS
932 STDCALL
933 RtlLargeIntegerToChar(
934         IN      PLARGE_INTEGER  Value,
935         IN      ULONG           Base,
936         IN      ULONG           Length,
937         IN OUT  PCHAR           String)
938 {
939         ULONG Radix;
940         CHAR  temp[65];
941         ULONGLONG v = Value->QuadPart;
942         ULONG i;
943         PCHAR tp;
944         PCHAR sp;
945
946         Radix = Base;
947         if (Radix == 0)
948                 Radix = 10;
949
950         if ((Radix != 2) && (Radix != 8) &&
951             (Radix != 10) && (Radix != 16))
952                 return STATUS_INVALID_PARAMETER;
953
954         tp = temp;
955         while (v || tp == temp)
956         {
957                 i = v % Radix;
958                 v = v / Radix;
959                 if (i < 10)
960                         *tp = i + '0';
961                 else
962                         *tp = i + 'a' - 10;
963                 tp++;
964         }
965
966         if (tp - temp >= Length)
967                 return STATUS_BUFFER_TOO_SMALL;
968
969         sp = String;
970         while (tp > temp)
971                 *sp++ = *--tp;
972         *sp = 0;
973
974         return STATUS_SUCCESS;
975 }
976
977
978 ULONG
979 STDCALL
980 RtlOemStringToUnicodeSize(
981         IN      POEM_STRING     OemString)
982 {
983         ULONG Size;
984
985         RtlMultiByteToUnicodeSize (&Size,
986                                    OemString->Buffer,
987                                    OemString->Length);
988
989         return Size;
990 }
991
992
993 NTSTATUS
994 STDCALL
995 RtlOemStringToUnicodeString(
996         IN OUT  PUNICODE_STRING DestinationString,
997         IN      POEM_STRING     SourceString,
998         IN      BOOLEAN         AllocateDestinationString)
999 {
1000         NTSTATUS Status;
1001         ULONG Length;
1002
1003         if (NlsMbCodePageTag == TRUE)
1004                 Length = RtlAnsiStringToUnicodeSize (SourceString);
1005         else
1006                 Length = SourceString->Length * sizeof(WCHAR);
1007
1008         if (Length > 65535)
1009                 return STATUS_INVALID_PARAMETER_2;
1010
1011         if (AllocateDestinationString == TRUE)
1012         {
1013                 DestinationString->MaximumLength = Length + sizeof(WCHAR);
1014                 DestinationString->Buffer =
1015                         RtlAllocateHeap (RtlGetProcessHeap (),
1016                                          0,
1017                                          DestinationString->MaximumLength);
1018                 if (DestinationString->Buffer == NULL)
1019                         return STATUS_NO_MEMORY;
1020         }
1021         else
1022         {
1023                 if (Length + sizeof(WCHAR) > DestinationString->MaximumLength)
1024                 {
1025                         DPRINT("STATUS_BUFFER_TOO_SMALL\n");
1026                         return STATUS_BUFFER_TOO_SMALL;
1027                 }
1028         }
1029         DestinationString->Length = Length;
1030
1031         RtlZeroMemory (DestinationString->Buffer,
1032                        DestinationString->Length);
1033
1034         Status = RtlOemToUnicodeN (DestinationString->Buffer,
1035                                    DestinationString->Length,
1036                                    NULL,
1037                                    SourceString->Buffer,
1038                                    SourceString->Length);
1039         if (!NT_SUCCESS(Status))
1040         {
1041                 if (AllocateDestinationString)
1042                 {
1043                         RtlFreeHeap (RtlGetProcessHeap (),
1044                                      0,
1045                                      DestinationString->Buffer);
1046                 }
1047                 return Status;
1048         }
1049
1050         DestinationString->Buffer[Length / sizeof(WCHAR)] = 0;
1051
1052         return STATUS_SUCCESS;
1053 }
1054
1055
1056 BOOLEAN
1057 STDCALL
1058 RtlPrefixString(
1059         PANSI_STRING    String1,
1060         PANSI_STRING    String2,
1061         BOOLEAN         CaseInsensitive)
1062 {
1063         PCHAR pc1;
1064         PCHAR pc2;
1065         ULONG Length;
1066
1067         if (String2->Length < String1->Length)
1068                 return FALSE;
1069
1070         Length = String1->Length;
1071         pc1 = String1->Buffer;
1072         pc2 = String2->Buffer;
1073
1074         if (pc1 && pc2)
1075         {
1076                 if (CaseInsensitive)
1077                 {
1078                         while (Length--)
1079                         {
1080                                 if (RtlUpperChar (*pc1++) != RtlUpperChar (*pc2++))
1081                                         return FALSE;
1082                         }
1083                 }
1084                 else
1085                 {
1086                         while (Length--)
1087                         {
1088                                 if (*pc1++ != *pc2++)
1089                                         return FALSE;
1090                         }
1091                 }
1092                 return TRUE;
1093         }
1094         return FALSE;
1095 }
1096
1097
1098 BOOLEAN
1099 STDCALL
1100 RtlPrefixUnicodeString(
1101         PUNICODE_STRING String1,
1102         PUNICODE_STRING String2,
1103         BOOLEAN         CaseInsensitive)
1104 {
1105         PWCHAR pc1;
1106         PWCHAR pc2;
1107         ULONG Length;
1108
1109         if (String2->Length < String1->Length)
1110                 return FALSE;
1111
1112         Length = String1->Length / 2;
1113         pc1 = String1->Buffer;
1114         pc2  = String2->Buffer;
1115
1116         if (pc1 && pc2)
1117         {
1118                 if (CaseInsensitive)
1119                 {
1120                         while (Length--)
1121                         {
1122                                 if (RtlUpcaseUnicodeChar (*pc1++)
1123                                     != RtlUpcaseUnicodeChar (*pc2++))
1124                                         return FALSE;
1125                         }
1126                 }
1127                 else
1128                 {
1129                         while (Length--)
1130                         {
1131                                 if( *pc1++ != *pc2++ )
1132                                         return FALSE;
1133                         }
1134                 }
1135                 return TRUE;
1136         }
1137         return FALSE;
1138 }
1139
1140
1141 ULONG
1142 STDCALL
1143 RtlUnicodeStringToAnsiSize(
1144         IN      PUNICODE_STRING UnicodeString)
1145 {
1146         ULONG Size;
1147
1148         RtlUnicodeToMultiByteSize (&Size,
1149                                    UnicodeString->Buffer,
1150                                    UnicodeString->Length);
1151
1152         return Size+1; //NB: incl. nullterm
1153 }
1154
1155
1156 NTSTATUS
1157 STDCALL
1158 RtlUnicodeStringToAnsiString(
1159         IN OUT  PANSI_STRING    DestinationString,
1160         IN      PUNICODE_STRING SourceString,
1161         IN      BOOLEAN         AllocateDestinationString)
1162 {
1163         NTSTATUS Status;
1164         ULONG Length;
1165
1166         if (NlsMbCodePageTag == TRUE)
1167                 Length = RtlUnicodeStringToAnsiSize (SourceString);
1168         else
1169                 Length = SourceString->Length / sizeof(WCHAR);
1170
1171         if (AllocateDestinationString == TRUE)
1172         {
1173                 DestinationString->MaximumLength = Length + sizeof(CHAR);
1174                 DestinationString->Buffer =
1175                         RtlAllocateHeap (RtlGetProcessHeap (),
1176                                          0,
1177                                          DestinationString->MaximumLength);
1178                 if (DestinationString->Buffer == NULL)
1179                         return STATUS_NO_MEMORY;
1180         }
1181         else
1182         {
1183                 if (Length >= DestinationString->MaximumLength)
1184                         return STATUS_BUFFER_TOO_SMALL;
1185         }
1186         DestinationString->Length = Length;
1187
1188         RtlZeroMemory (DestinationString->Buffer,
1189                        DestinationString->Length);
1190
1191         Status = RtlUnicodeToMultiByteN (DestinationString->Buffer,
1192                                          DestinationString->Length,
1193                                          NULL,
1194                                          SourceString->Buffer,
1195                                          SourceString->Length);
1196         if (!NT_SUCCESS(Status))
1197         {
1198                 if (AllocateDestinationString == TRUE)
1199                 {
1200                         RtlFreeHeap (RtlGetProcessHeap (),
1201                                      0,
1202                                      DestinationString->Buffer);
1203                 }
1204                 return Status;
1205         }
1206
1207         DestinationString->Buffer[Length] = 0;
1208
1209         return STATUS_SUCCESS;
1210 }
1211
1212
1213 NTSTATUS
1214 STDCALL
1215 RtlUnicodeStringToInteger(
1216         IN      PUNICODE_STRING String,
1217         IN      ULONG           Base,
1218         OUT     PULONG          Value)
1219 {
1220         PWCHAR Str;
1221         ULONG lenmin = 0;
1222         ULONG i;
1223         ULONG Val;
1224         BOOLEAN addneg = FALSE;
1225
1226         *Value = 0;
1227         Str = String->Buffer;
1228
1229         for (i = 0; i < String->Length / sizeof(WCHAR); i++)
1230         {
1231                 if (*Str == L'b')
1232                 {
1233                         Base = 2;
1234                         lenmin++;
1235                 }
1236                 else if (*Str == L'o')
1237                 {
1238                         Base = 8;
1239                         lenmin++;
1240                 }
1241                 else if (*Str == L'd')
1242                 {
1243                         Base = 10;
1244                         lenmin++;
1245                 }
1246                 else if (*Str == L'x')
1247                 {
1248                         Base = 16;
1249                         lenmin++;
1250                 }
1251                 else if (*Str == L'+')
1252                 {
1253                         lenmin++;
1254                 }
1255                 else if (*Str == L'-')
1256                 {
1257                         addneg = TRUE;
1258                         lenmin++;
1259                 }
1260                 else if ((*Str > L'1') && (Base == 2))
1261                 {
1262                         return STATUS_INVALID_PARAMETER;
1263                 }
1264                 else if (((*Str > L'7') || (*Str < L'0')) && (Base == 8))
1265                 {
1266                         return STATUS_INVALID_PARAMETER;
1267                 }
1268                 else if (((*Str > L'9') || (*Str < L'0')) && (Base == 10))
1269                 {
1270                         return STATUS_INVALID_PARAMETER;
1271                 }
1272                 else if ((((*Str > L'9') || (*Str < L'0')) ||
1273                           ((towupper (*Str) > L'F') ||
1274                            (towupper (*Str) < L'A'))) && (Base == 16))
1275                 {
1276                         return STATUS_INVALID_PARAMETER;
1277                 }
1278                 else
1279                         Str++;
1280         }
1281
1282         Str = String->Buffer + lenmin;
1283
1284         if (Base == 0)
1285                 Base = 10;
1286
1287         while (iswxdigit (*Str) &&
1288                (Val = iswdigit (*Str) ? *Str - L'0' : (iswlower (*Str)
1289                 ? toupper (*Str) : *Str) - L'A' + 10) < Base)
1290         {
1291                 *Value = *Value * Base + Val;
1292                 Str++;
1293         }
1294
1295         if (addneg == TRUE)
1296                 *Value *= -1;
1297
1298         return STATUS_SUCCESS;
1299 }
1300
1301
1302 ULONG
1303 STDCALL
1304 RtlUnicodeStringToOemSize(
1305         IN      PUNICODE_STRING UnicodeString)
1306 {
1307         ULONG Size;
1308
1309         RtlUnicodeToMultiByteSize (&Size,
1310                                    UnicodeString->Buffer,
1311                                    UnicodeString->Length);
1312
1313         return Size+1; //NB: incl. nullterm
1314 }
1315
1316
1317 NTSTATUS
1318 STDCALL
1319 RtlUnicodeStringToCountedOemString(
1320         IN OUT  POEM_STRING     DestinationString,
1321         IN      PUNICODE_STRING SourceString,
1322         IN      BOOLEAN         AllocateDestinationString)
1323 {
1324         NTSTATUS Status;
1325         ULONG Length;
1326         ULONG Size;
1327
1328         if (NlsMbOemCodePageTag == TRUE)
1329                 Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1330         else
1331                 Length = SourceString->Length / sizeof(WCHAR) + 1;
1332
1333         if (Length > 0x0000FFFF)
1334                 return STATUS_INVALID_PARAMETER_2;
1335
1336         DestinationString->Length = (WORD)(Length - 1);
1337
1338         if (AllocateDestinationString)
1339         {
1340                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
1341                                                              0,
1342                                                              Length);
1343                 if (DestinationString->Buffer == NULL)
1344                         return STATUS_NO_MEMORY;
1345
1346                 RtlZeroMemory (DestinationString->Buffer,
1347                                Length);
1348                 DestinationString->MaximumLength = (WORD)Length;
1349         }
1350         else
1351         {
1352                 if (Length > DestinationString->MaximumLength)
1353                 {
1354                         if (DestinationString->MaximumLength == 0)
1355                                 return STATUS_BUFFER_OVERFLOW;
1356                         DestinationString->Length =
1357                                 DestinationString->MaximumLength - 1;
1358                 }
1359         }
1360
1361         Status = RtlUnicodeToOemN (DestinationString->Buffer,
1362                                    DestinationString->Length,
1363                                    &Size,
1364                                    SourceString->Buffer,
1365                                    SourceString->Length);
1366         if (!NT_SUCCESS(Status))
1367         {
1368                 if (AllocateDestinationString)
1369                 {
1370                         RtlFreeHeap (RtlGetProcessHeap (),
1371                                      0,
1372                                      DestinationString->Buffer);
1373                 }
1374                 return Status;
1375         }
1376
1377         DestinationString->Buffer[Size] = 0;
1378
1379         return STATUS_SUCCESS;
1380 }
1381
1382
1383 NTSTATUS
1384 STDCALL
1385 RtlUnicodeStringToOemString(
1386         IN OUT  POEM_STRING     DestinationString,
1387         IN      PUNICODE_STRING SourceString,
1388         IN      BOOLEAN         AllocateDestinationString)
1389 {
1390         NTSTATUS Status;
1391         ULONG Length;
1392         ULONG Size;
1393
1394         if (NlsMbOemCodePageTag == TRUE)
1395                 Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1396         else
1397                 Length = SourceString->Length / sizeof(WCHAR) + 1;
1398
1399         if (Length > 0x0000FFFF)
1400                 return STATUS_INVALID_PARAMETER_2;
1401
1402         DestinationString->Length = (WORD)(Length - 1);
1403
1404         if (AllocateDestinationString)
1405         {
1406                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
1407                                                              0,
1408                                                              Length);
1409                 if (DestinationString->Buffer == NULL)
1410                         return STATUS_NO_MEMORY;
1411
1412                 RtlZeroMemory (DestinationString->Buffer,
1413                                Length);
1414                 DestinationString->MaximumLength = (WORD)Length;
1415         }
1416         else
1417         {
1418                 if (Length > DestinationString->MaximumLength)
1419                 {
1420                         if (DestinationString->MaximumLength == 0)
1421                                 return STATUS_BUFFER_OVERFLOW;
1422                         DestinationString->Length =
1423                                 DestinationString->MaximumLength - 1;
1424                 }
1425         }
1426
1427         Status = RtlUnicodeToOemN (DestinationString->Buffer,
1428                                    DestinationString->Length,
1429                                    &Size,
1430                                    SourceString->Buffer,
1431                                    SourceString->Length);
1432         if (!NT_SUCCESS(Status))
1433         {
1434                 if (AllocateDestinationString)
1435                 {
1436                         RtlFreeHeap (RtlGetProcessHeap (),
1437                                      0,
1438                                      DestinationString->Buffer);
1439                 }
1440                 return Status;
1441         }
1442
1443         DestinationString->Buffer[Size] = 0;
1444
1445         return STATUS_SUCCESS;
1446 }
1447
1448
1449 WCHAR
1450 STDCALL
1451 RtlUpcaseUnicodeChar(IN WCHAR   Source)
1452 {
1453         if (Source < L'a')
1454                 return Source;
1455
1456         if (Source <= L'z')
1457                 return (Source - (L'a' - L'A'));
1458
1459         /* FIXME: characters above 'z' */
1460
1461         return Source;
1462 }
1463
1464
1465 NTSTATUS
1466 STDCALL
1467 RtlUpcaseUnicodeString(
1468         IN OUT  PUNICODE_STRING DestinationString,
1469         IN      PUNICODE_STRING SourceString,
1470         IN      BOOLEAN         AllocateDestinationString)
1471 {
1472         ULONG i;
1473         PWCHAR Src, Dest;
1474
1475         if (AllocateDestinationString == TRUE)
1476         {
1477                 DestinationString->MaximumLength=SourceString->Length+sizeof(WCHAR);
1478                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
1479                                                              0,
1480                                                              SourceString->Length + sizeof(WCHAR));
1481                 if (DestinationString->Buffer == NULL)
1482                         return STATUS_NO_MEMORY;
1483         }
1484         else
1485         {
1486                 if (SourceString->Length >= DestinationString->MaximumLength)
1487                         return STATUS_BUFFER_TOO_SMALL;
1488         }
1489         DestinationString->Length = SourceString->Length;
1490
1491         Src = SourceString->Buffer;
1492         Dest = DestinationString->Buffer;
1493         for (i = 0; i < SourceString->Length / sizeof(WCHAR); i++)
1494         {
1495                 *Dest = RtlUpcaseUnicodeChar (*Src);
1496                 Dest++;
1497                 Src++;
1498         }
1499         *Dest = 0;
1500
1501         return STATUS_SUCCESS;
1502 }
1503
1504
1505 NTSTATUS
1506 STDCALL
1507 RtlUpcaseUnicodeStringToAnsiString(
1508         IN OUT  PANSI_STRING    DestinationString,
1509         IN      PUNICODE_STRING SourceString,
1510         IN      BOOLEAN         AllocateDestinationString)
1511 {
1512         NTSTATUS Status;
1513         ULONG Length;
1514         ULONG Size;
1515
1516         if (NlsMbCodePageTag == TRUE)
1517                 Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1518         else
1519                 Length = SourceString->Length / sizeof(WCHAR) + 1;
1520
1521         if (Length > 0x0000FFFF)
1522                 return STATUS_INVALID_PARAMETER_2;
1523
1524         DestinationString->Length = (WORD)(Length - 1);
1525
1526         if (AllocateDestinationString == TRUE)
1527         {
1528                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
1529                                                              0,
1530                                                              DestinationString->MaximumLength);
1531                 if (DestinationString->Buffer == NULL)
1532                         return STATUS_NO_MEMORY;
1533
1534                 RtlZeroMemory (DestinationString->Buffer,
1535                                Length);
1536                 DestinationString->MaximumLength = (WORD)Length;
1537         }
1538         else
1539         {
1540                 if (Length > DestinationString->MaximumLength)
1541                 {
1542                         if (!DestinationString->MaximumLength)
1543                                 return STATUS_BUFFER_OVERFLOW;
1544                         DestinationString->Length =
1545                                 DestinationString->MaximumLength - 1;
1546                 }
1547         }
1548
1549         Status = RtlUpcaseUnicodeToMultiByteN (DestinationString->Buffer,
1550                                                DestinationString->Length,
1551                                                &Size,
1552                                                SourceString->Buffer,
1553                                                SourceString->Length);
1554         if (!NT_SUCCESS(Status))
1555         {
1556                 if (AllocateDestinationString)
1557                 {
1558                         RtlFreeHeap (RtlGetProcessHeap (),
1559                                      0,
1560                                      DestinationString->Buffer);
1561                 }
1562                 return Status;
1563         }
1564
1565         DestinationString->Buffer[Size] = 0;
1566
1567         return STATUS_SUCCESS;
1568 }
1569
1570
1571 NTSTATUS
1572 STDCALL
1573 RtlUpcaseUnicodeStringToCountedOemString(
1574         IN OUT  POEM_STRING     DestinationString,
1575         IN      PUNICODE_STRING SourceString,
1576         IN      BOOLEAN         AllocateDestinationString)
1577 {
1578         NTSTATUS Status;
1579         ULONG Length;
1580         ULONG Size;
1581
1582         if (NlsMbCodePageTag == TRUE)
1583                 Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1584         else
1585                 Length = SourceString->Length / sizeof(WCHAR) + 1;
1586
1587         if (Length > 0x0000FFFF)
1588                 return STATUS_INVALID_PARAMETER_2;
1589
1590         DestinationString->Length = (WORD)(Length - 1);
1591
1592         if (AllocateDestinationString == TRUE)
1593         {
1594                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
1595                                                              0,
1596                                                              Length);
1597                 if (DestinationString->Buffer == NULL)
1598                         return STATUS_NO_MEMORY;
1599
1600                 RtlZeroMemory (DestinationString->Buffer,
1601                                Length);
1602                 DestinationString->MaximumLength = (WORD)Length;
1603         }
1604         else
1605         {
1606                 if (Length > DestinationString->MaximumLength)
1607                 {
1608                         if (DestinationString->MaximumLength == 0)
1609                                 return STATUS_BUFFER_OVERFLOW;
1610                         DestinationString->Length =
1611                                 DestinationString->MaximumLength - 1;
1612                 }
1613         }
1614
1615         Status = RtlUpcaseUnicodeToOemN (DestinationString->Buffer,
1616                                          DestinationString->Length,
1617                                          &Size,
1618                                          SourceString->Buffer,
1619                                          SourceString->Length);
1620         if (!NT_SUCCESS(Status))
1621         {
1622                 if (AllocateDestinationString)
1623                 {
1624                         RtlFreeHeap (RtlGetProcessHeap (),
1625                                      0,
1626                                      DestinationString->Buffer);
1627                 }
1628                 return Status;
1629         }
1630
1631         DestinationString->Buffer[Size] = 0;
1632
1633         return STATUS_SUCCESS;
1634 }
1635
1636
1637 NTSTATUS
1638 STDCALL
1639 RtlUpcaseUnicodeStringToOemString (
1640         IN OUT  POEM_STRING     DestinationString,
1641         IN      PUNICODE_STRING SourceString,
1642         IN      BOOLEAN         AllocateDestinationString
1643         )
1644 {
1645         NTSTATUS Status;
1646         ULONG Length;
1647         ULONG Size;
1648
1649         if (NlsMbOemCodePageTag == TRUE)
1650                 Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1651         else
1652                 Length = SourceString->Length / sizeof(WCHAR) + 1;
1653
1654         if (Length > 0x0000FFFF)
1655                 return STATUS_INVALID_PARAMETER_2;
1656
1657         DestinationString->Length = (WORD)(Length - 1);
1658
1659         if (AllocateDestinationString == TRUE)
1660         {
1661                 DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
1662                                                              0,
1663                                                              Length);
1664                 if (DestinationString->Buffer == NULL)
1665                         return STATUS_NO_MEMORY;
1666
1667                 RtlZeroMemory (DestinationString->Buffer,
1668                                Length);
1669                 DestinationString->MaximumLength = (WORD)Length;
1670         }
1671         else
1672         {
1673                 if (Length > DestinationString->MaximumLength)
1674                 {
1675                         if (DestinationString->MaximumLength == 0)
1676                                 return STATUS_BUFFER_OVERFLOW;
1677                         DestinationString->Length =
1678                                 DestinationString->MaximumLength - 1;
1679                 }
1680         }
1681
1682         Status = RtlUpcaseUnicodeToOemN (DestinationString->Buffer,
1683                                          DestinationString->Length,
1684                                          &Size,
1685                                          SourceString->Buffer,
1686                                          SourceString->Length);
1687         if (!NT_SUCCESS(Status))
1688         {
1689                 if (AllocateDestinationString)
1690                 {
1691                         RtlFreeHeap (RtlGetProcessHeap (),
1692                                      0,
1693                                      DestinationString->Buffer);
1694                 }
1695                 return Status;
1696         }
1697
1698         DestinationString->Buffer[Size] = 0;
1699
1700         return STATUS_SUCCESS;
1701 }
1702
1703
1704 CHAR
1705 STDCALL
1706 RtlUpperChar (
1707         IN      CHAR    Source
1708         )
1709 {
1710         WCHAR   Unicode;
1711         CHAR    Destination;
1712
1713         if (NlsMbCodePageTag == FALSE)
1714         {
1715                 /* single-byte code page */
1716                 /* ansi->unicode */
1717                 Unicode = (WCHAR)Source;
1718 #if 0
1719                 Unicode = NlsAnsiToUnicodeData[Source];
1720 #endif
1721
1722                 /* upcase conversion */
1723                 Unicode = RtlUpcaseUnicodeChar (Unicode);
1724
1725                 /* unicode -> ansi */
1726                 Destination = (CHAR)Unicode;
1727 #if 0
1728                 Destination = NlsUnicodeToAnsiData[Unicode];
1729 #endif
1730         }
1731         else
1732         {
1733                 /* single-byte code page */
1734                 /* FIXME: implement the multi-byte stuff!! */
1735                 Destination = Source;
1736         }
1737
1738         return Destination;
1739 }
1740
1741
1742 VOID
1743 STDCALL
1744 RtlUpperString(
1745         IN OUT  PSTRING DestinationString,
1746         IN      PSTRING SourceString)
1747 {
1748         ULONG Length;
1749         ULONG i;
1750         PCHAR Src;
1751         PCHAR Dest;
1752
1753         Length = min(SourceString->Length, DestinationString->MaximumLength - 1);
1754
1755         Src = SourceString->Buffer;
1756         Dest = DestinationString->Buffer;
1757         for (i = 0; i < Length; i++)
1758         {
1759                 *Dest = RtlUpperChar (*Src);
1760                 Src++;
1761                 Dest++;
1762         }
1763         *Dest = 0;
1764
1765         DestinationString->Length = SourceString->Length;
1766 }
1767
1768
1769 ULONG
1770 STDCALL
1771 RtlxAnsiStringToUnicodeSize(IN  PANSI_STRING    AnsiString)
1772 {
1773         return RtlAnsiStringToUnicodeSize(AnsiString);
1774 }
1775
1776
1777 ULONG
1778 STDCALL
1779 RtlxOemStringToUnicodeSize(IN   POEM_STRING     OemString)
1780 {
1781         return RtlAnsiStringToUnicodeSize((PANSI_STRING)OemString);
1782 }
1783
1784
1785 ULONG
1786 STDCALL
1787 RtlxUnicodeStringToAnsiSize(IN  PUNICODE_STRING UnicodeString)
1788 {
1789         return RtlUnicodeStringToAnsiSize(UnicodeString);
1790 }
1791
1792
1793 ULONG
1794 STDCALL
1795 RtlxUnicodeStringToOemSize(IN   PUNICODE_STRING UnicodeString)
1796 {
1797         return RtlUnicodeStringToAnsiSize(UnicodeString);
1798 }
1799
1800 /* EOF */