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