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