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