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