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