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