update for HEAD-2003021201
[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 <ctype.h>
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 PWSTR Source)
207 {
208   PWCHAR 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 PWSTR 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
1080 NTSTATUS
1081 STDCALL
1082 RtlUnicodeStringToCountedOemString(IN OUT POEM_STRING DestinationString,
1083                                    IN PUNICODE_STRING SourceString,
1084                                    IN BOOLEAN AllocateDestinationString)
1085 {
1086   NTSTATUS Status;
1087   ULONG Length;
1088   ULONG Size;
1089   
1090   if (NlsMbOemCodePageTag == TRUE)
1091     Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1092   else
1093     Length = SourceString->Length / sizeof(WCHAR) + 1;
1094   
1095   if (Length > 0x0000FFFF)
1096     return STATUS_INVALID_PARAMETER_2;
1097   
1098   DestinationString->Length = (WORD)(Length - 1);
1099   
1100   if (AllocateDestinationString)
1101     {
1102       DestinationString->Buffer = ExAllocatePoolWithTag (NonPagedPool,
1103                                                          Length,
1104                                                          TAG_ASTR);
1105       
1106       if (DestinationString->Buffer == NULL)
1107         return STATUS_NO_MEMORY;
1108       
1109       RtlZeroMemory (DestinationString->Buffer,
1110                      Length);
1111       DestinationString->MaximumLength = (WORD)Length;
1112         }
1113   else
1114     {
1115       if (Length > DestinationString->MaximumLength)
1116         {
1117           if (DestinationString->MaximumLength == 0)
1118             return STATUS_BUFFER_OVERFLOW;
1119           DestinationString->Length =
1120             DestinationString->MaximumLength - 1;
1121         }
1122     }
1123   
1124   Status = RtlUnicodeToOemN (DestinationString->Buffer,
1125                              DestinationString->Length,
1126                              &Size,
1127                              SourceString->Buffer,
1128                              SourceString->Length);
1129   if (!NT_SUCCESS(Status))
1130     {
1131       if (AllocateDestinationString)
1132         ExFreePool (DestinationString->Buffer);
1133
1134       return Status;
1135     }
1136   
1137   DestinationString->Buffer[Size] = 0;
1138   
1139   return STATUS_SUCCESS;
1140 }
1141
1142
1143 NTSTATUS
1144 STDCALL
1145 RtlUnicodeStringToInteger(IN PUNICODE_STRING String,
1146                           IN ULONG Base,
1147                           OUT PULONG Value)
1148 {
1149         PWCHAR Str;
1150         ULONG lenmin = 0;
1151         ULONG i;
1152         ULONG Val;
1153         BOOLEAN addneg = FALSE;
1154
1155     *Value = 0;
1156         Str = String->Buffer;
1157
1158         for (i = 0; i < String->Length / sizeof(WCHAR); i++)
1159         {
1160                 if (*Str == L'b')
1161                 {
1162                         Base = 2;
1163                         lenmin++;
1164                 }
1165                 else if (*Str == L'o')
1166                 {
1167                         Base = 8;
1168                         lenmin++;
1169                 }
1170                 else if (*Str == L'd')
1171                 {
1172                         Base = 10;
1173                         lenmin++;
1174                 }
1175                 else if (*Str == L'x')
1176                 {
1177                         Base = 16;
1178                         lenmin++;
1179                 }
1180                 else if (*Str == L'+')
1181                 {
1182                         lenmin++;
1183                 }
1184                 else if (*Str == L'-')
1185                 {
1186                         addneg = TRUE;
1187                         lenmin++;
1188                 }
1189                 else if ((*Str > L'1') && (Base == 2))
1190                 {
1191                         return STATUS_INVALID_PARAMETER;
1192                 }
1193                 else if (((*Str > L'7') || (*Str < L'0')) && (Base == 8))
1194                 {
1195                         return STATUS_INVALID_PARAMETER;
1196                 }
1197                 else if (((*Str > L'9') || (*Str < L'0')) && (Base == 10))
1198                 {
1199                         return STATUS_INVALID_PARAMETER;
1200                 }
1201                 else if ((((*Str > L'9') || (*Str < L'0')) ||
1202                           ((towupper (*Str) > L'F') ||
1203                            (towupper (*Str) < L'A'))) && (Base == 16))
1204                 {
1205                         return STATUS_INVALID_PARAMETER;
1206                 }
1207                 else
1208                         Str++;
1209         }
1210
1211         Str = String->Buffer + lenmin;
1212
1213         if (Base == 0)
1214                 Base = 10;
1215
1216         while (iswxdigit (*Str) &&
1217                (Val = iswdigit (*Str) ? *Str - L'0' : (iswlower (*Str)
1218                 ? toupper (*Str) : *Str) - L'A' + 10) < Base)
1219         {
1220                 *Value = *Value * Base + Val;
1221                 Str++;
1222         }
1223
1224         if (addneg == TRUE)
1225                 *Value *= -1;
1226
1227         return STATUS_SUCCESS;
1228 }
1229
1230
1231 ULONG
1232 STDCALL
1233 RtlUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString)
1234 {
1235   ULONG Size;
1236
1237   RtlUnicodeToMultiByteSize(&Size,
1238                             UnicodeString->Buffer,
1239                             UnicodeString->Length);
1240   return(Size+1);
1241 }
1242
1243
1244 NTSTATUS
1245 STDCALL
1246 RtlUnicodeStringToOemString(IN OUT POEM_STRING DestinationString,
1247                             IN PUNICODE_STRING SourceString,
1248                             IN BOOLEAN AllocateDestinationString)
1249 {
1250   NTSTATUS Status;
1251   ULONG Length;
1252   
1253   if (NlsMbOemCodePageTag == TRUE){
1254     Length = RtlUnicodeStringToAnsiSize (SourceString); Length--;
1255   }
1256   else
1257     Length = SourceString->Length / sizeof(WCHAR);
1258   
1259   if (AllocateDestinationString == TRUE)
1260     {
1261       DestinationString->MaximumLength = Length + sizeof(CHAR);
1262       DestinationString->Buffer =
1263         ExAllocatePoolWithTag (NonPagedPool,
1264                                DestinationString->MaximumLength,
1265                                TAG_OSTR);
1266       if (DestinationString->Buffer == NULL)
1267         return STATUS_NO_MEMORY;
1268     }
1269   else
1270     {
1271       if (Length >= DestinationString->MaximumLength)
1272         return STATUS_BUFFER_TOO_SMALL;
1273     }
1274   DestinationString->Length = Length;
1275   
1276   RtlZeroMemory(DestinationString->Buffer,
1277                 DestinationString->Length);
1278   
1279   Status = RtlUnicodeToOemN(DestinationString->Buffer,
1280                             DestinationString->Length,
1281                             NULL,
1282                             SourceString->Buffer,
1283                             SourceString->Length);
1284   if (!NT_SUCCESS(Status))
1285     {
1286       if (AllocateDestinationString)
1287         ExFreePool(DestinationString->Buffer);
1288       return Status;
1289     }
1290   
1291   DestinationString->Buffer[Length] = 0;
1292   
1293   return STATUS_SUCCESS;
1294 }
1295
1296
1297 WCHAR
1298 STDCALL
1299 RtlUpcaseUnicodeChar(IN WCHAR Source)
1300 {
1301   if (Source < L'a')
1302     return(Source);
1303
1304   if (Source <= L'z')
1305     return(Source - (L'a' - L'A'));
1306
1307   /* FIXME: characters above 'z' */
1308
1309   return(Source);
1310 }
1311
1312
1313 NTSTATUS STDCALL
1314 RtlUpcaseUnicodeString(IN OUT PUNICODE_STRING DestinationString,
1315                        IN PUNICODE_STRING SourceString,
1316                        IN BOOLEAN AllocateDestinationString)
1317 {
1318   ULONG i;
1319   PWCHAR Src, Dest;
1320   
1321   if (AllocateDestinationString == TRUE)
1322     {
1323       DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR);
1324       DestinationString->Buffer = 
1325         ExAllocatePoolWithTag(NonPagedPool,
1326                               SourceString->Length + sizeof(WCHAR),
1327                               TAG_USTR);
1328       if (DestinationString->Buffer == NULL)
1329         return(STATUS_NO_MEMORY);
1330     }
1331   else
1332     {
1333       if (SourceString->Length >= DestinationString->MaximumLength)
1334         return(STATUS_BUFFER_TOO_SMALL);
1335     }
1336   DestinationString->Length = SourceString->Length;
1337   
1338   Src = SourceString->Buffer;
1339   Dest = DestinationString->Buffer;
1340   for (i=0; i < SourceString->Length / sizeof(WCHAR); i++)
1341     {
1342       *Dest = RtlUpcaseUnicodeChar(*Src);
1343       Dest++;
1344       Src++;
1345     }
1346   *Dest = 0;
1347   
1348   return(STATUS_SUCCESS);
1349 }
1350
1351
1352 NTSTATUS
1353 STDCALL
1354 RtlUpcaseUnicodeStringToAnsiString(IN OUT PANSI_STRING DestinationString,
1355                                    IN PUNICODE_STRING SourceString,
1356                                    IN BOOLEAN AllocateDestinationString)
1357 {
1358   NTSTATUS Status;
1359   ULONG Length;
1360   
1361   if (NlsMbCodePageTag == TRUE){
1362     Length = RtlUnicodeStringToAnsiSize(SourceString); Length--;
1363   }
1364   else
1365     Length = SourceString->Length / sizeof(WCHAR);
1366   
1367   if (AllocateDestinationString == TRUE)
1368     {
1369       DestinationString->MaximumLength = Length + sizeof(CHAR);
1370       DestinationString->Buffer = 
1371         ExAllocatePoolWithTag(NonPagedPool,
1372                               DestinationString->MaximumLength,
1373                               TAG_ASTR);
1374       if (DestinationString->Buffer == NULL)
1375         return(STATUS_NO_MEMORY);
1376     }
1377   else
1378     {
1379       if (Length >= DestinationString->MaximumLength)
1380         return(STATUS_BUFFER_TOO_SMALL);
1381     }
1382   DestinationString->Length = Length;
1383   
1384   RtlZeroMemory(DestinationString->Buffer,
1385                 DestinationString->Length);
1386   
1387   Status = RtlUpcaseUnicodeToMultiByteN(DestinationString->Buffer,
1388                                         DestinationString->Length,
1389                                         NULL,
1390                                         SourceString->Buffer,
1391                                         SourceString->Length);
1392   if (!NT_SUCCESS(Status))
1393     {
1394       if (AllocateDestinationString)
1395         ExFreePool(DestinationString->Buffer);
1396       return(Status);
1397     }
1398   
1399   DestinationString->Buffer[Length] = 0;
1400   
1401   return(STATUS_SUCCESS);
1402 }
1403
1404
1405 NTSTATUS
1406 STDCALL
1407 RtlUpcaseUnicodeStringToCountedOemString(IN OUT POEM_STRING DestinationString,
1408                                          IN PUNICODE_STRING SourceString,
1409                                          IN BOOLEAN AllocateDestinationString)
1410 {
1411   NTSTATUS Status;
1412   ULONG Length;
1413   ULONG Size;
1414
1415   if (NlsMbCodePageTag == TRUE)
1416     Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/;
1417   else
1418     Length = SourceString->Length / sizeof(WCHAR) + 1;
1419
1420   if (Length > 0x0000FFFF)
1421     return(STATUS_INVALID_PARAMETER_2);
1422
1423   DestinationString->Length = (WORD)(Length - 1);
1424
1425   if (AllocateDestinationString == TRUE)
1426     {
1427       DestinationString->Buffer =
1428         ExAllocatePoolWithTag(NonPagedPool,
1429                               Length,
1430                               TAG_OSTR);
1431       if (DestinationString->Buffer == NULL)
1432         return(STATUS_NO_MEMORY);
1433
1434       RtlZeroMemory(DestinationString->Buffer,
1435                     Length);
1436       DestinationString->MaximumLength = (WORD)Length;
1437     }
1438   else
1439     {
1440       if (Length > DestinationString->MaximumLength)
1441         {
1442           if (DestinationString->MaximumLength == 0)
1443             return(STATUS_BUFFER_OVERFLOW);
1444           DestinationString->Length =
1445             DestinationString->MaximumLength - 1;
1446         }
1447     }
1448
1449   Status = RtlUpcaseUnicodeToOemN(DestinationString->Buffer,
1450                                   DestinationString->Length,
1451                                   &Size,
1452                                   SourceString->Buffer,
1453                                   SourceString->Length);
1454   if (!NT_SUCCESS(Status))
1455     {
1456       if (AllocateDestinationString)
1457         ExFreePool(DestinationString->Buffer);
1458       return(Status);
1459     }
1460
1461   DestinationString->Buffer[Size] = 0;
1462
1463   return(STATUS_SUCCESS);
1464 }
1465
1466
1467 NTSTATUS
1468 STDCALL
1469 RtlUpcaseUnicodeStringToOemString(IN OUT POEM_STRING DestinationString,
1470                                   IN PUNICODE_STRING SourceString,
1471                                   IN BOOLEAN AllocateDestinationString)
1472 {
1473   NTSTATUS Status;
1474   ULONG Length;
1475
1476   if (NlsMbOemCodePageTag == TRUE) {
1477     Length = RtlUnicodeStringToOemSize(SourceString); Length--;
1478   }
1479   else
1480     Length = SourceString->Length / sizeof(WCHAR);
1481
1482   if (AllocateDestinationString == TRUE)
1483     {
1484       DestinationString->MaximumLength = Length + sizeof(CHAR);
1485       DestinationString->Buffer =
1486         ExAllocatePoolWithTag(NonPagedPool,
1487                               DestinationString->MaximumLength,
1488                               TAG_OSTR);
1489       if (DestinationString->Buffer == NULL)
1490         return(STATUS_NO_MEMORY);
1491     }
1492   else
1493     {
1494       if (Length >= DestinationString->MaximumLength)
1495         return(STATUS_BUFFER_TOO_SMALL);
1496     }
1497   DestinationString->Length = Length;
1498
1499   RtlZeroMemory(DestinationString->Buffer,
1500                 DestinationString->Length);
1501
1502   Status = RtlUpcaseUnicodeToOemN(DestinationString->Buffer,
1503                                   DestinationString->Length,
1504                                   NULL,
1505                                   SourceString->Buffer,
1506                                   SourceString->Length);
1507   if (!NT_SUCCESS(Status))
1508     {
1509       if (AllocateDestinationString)
1510         ExFreePool(DestinationString->Buffer);
1511       return(Status);
1512     }
1513
1514   DestinationString->Buffer[Length] = 0;
1515
1516   return(STATUS_SUCCESS);
1517 }
1518
1519
1520 CHAR
1521 STDCALL
1522 RtlUpperChar(IN CHAR Source)
1523 {
1524   WCHAR Unicode;
1525   CHAR Destination;
1526
1527         if (NlsMbCodePageTag == FALSE)
1528         {
1529                 /* single-byte code page */
1530                 /* ansi->unicode */
1531                 Unicode = (WCHAR)Source;
1532 #if 0
1533                 Unicode = NlsAnsiToUnicodeData[Source];
1534 #endif
1535
1536                 /* upcase conversion */
1537                 Unicode = RtlUpcaseUnicodeChar (Unicode);
1538
1539                 /* unicode -> ansi */
1540                 Destination = (CHAR)Unicode;
1541 #if 0
1542                 Destination = NlsUnicodeToAnsiData[Unicode];
1543 #endif
1544         }
1545         else
1546         {
1547                 /* single-byte code page */
1548                 /* FIXME: implement the multi-byte stuff!! */
1549                 Destination = Source;
1550         }
1551
1552   return(Destination);
1553 }
1554
1555
1556 VOID
1557 STDCALL
1558 RtlUpperString(PSTRING DestinationString,
1559                PSTRING SourceString)
1560 {
1561   ULONG Length;
1562   ULONG i;
1563   PCHAR Src;
1564   PCHAR Dest;
1565
1566   Length = min(SourceString->Length,
1567                DestinationString->MaximumLength - 1);
1568
1569   Src = SourceString->Buffer;
1570   Dest = DestinationString->Buffer;
1571   for (i = 0; i < Length; i++)
1572     {
1573       *Dest = RtlUpperChar(*Src);
1574       Src++;
1575       Dest++;
1576     }
1577   *Dest = 0;
1578
1579   DestinationString->Length = SourceString->Length;
1580 }
1581
1582
1583 ULONG
1584 STDCALL
1585 RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString)
1586 {
1587   return RtlAnsiStringToUnicodeSize(AnsiString);
1588 }
1589
1590
1591 ULONG
1592 STDCALL
1593 RtlxOemStringToUnicodeSize(IN POEM_STRING OemString)
1594 {
1595   return RtlOemStringToUnicodeSize((PANSI_STRING)OemString);
1596 }
1597
1598
1599 ULONG
1600 STDCALL
1601 RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString)
1602 {
1603   return RtlUnicodeStringToAnsiSize(UnicodeString);
1604 }
1605
1606
1607 ULONG
1608 STDCALL
1609 RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString)
1610 {
1611   return RtlUnicodeStringToOemSize(UnicodeString);
1612 }
1613
1614 /* EOF */