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