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