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