4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
6 * Copyright (C) 2003 Thomas Mertes
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 /* GLOBALS *******************************************************************/
30 extern BOOLEAN NlsMbCodePageTag
;
31 extern BOOLEAN NlsMbOemCodePageTag
;
33 /* FUNCTIONS *****************************************************************/
40 RtlAnsiCharToUnicodeChar (IN CHAR AnsiChar
)
48 Size
= (NlsLeadByteInfo
[AnsiChar
] == 0) ? 1 : 2;
51 RtlMultiByteToUnicodeN (&UnicodeChar
,
65 * The calculated size in bytes including nullterm.
69 RtlAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
73 RtlMultiByteToUnicodeSize(&Size
,
86 * If src->length is zero dest is unchanged.
87 * Dest is never nullterminated.
91 RtlAppendStringToString(IN OUT PSTRING Destination
,
96 if (Source
->Length
== 0)
97 return(STATUS_SUCCESS
);
99 if (Destination
->Length
+ Source
->Length
>= Destination
->MaximumLength
)
100 return(STATUS_BUFFER_TOO_SMALL
);
102 Ptr
= Destination
->Buffer
+ Destination
->Length
;
106 Ptr
+= Source
->Length
;
109 Destination
->Length
+= Source
->Length
;
111 return(STATUS_SUCCESS
);
120 * If src->length is zero dest is unchanged.
121 * Dest is nullterminated when the MaximumLength allowes it.
122 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
126 RtlAppendUnicodeStringToString(
127 IN OUT PUNICODE_STRING Destination
,
128 IN PUNICODE_STRING Source
)
131 if ((Source
->Length
+ Destination
->Length
) > Destination
->MaximumLength
)
132 return STATUS_BUFFER_TOO_SMALL
;
134 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
->Buffer
, Source
->Length
);
135 Destination
->Length
+= Source
->Length
;
136 /* append terminating '\0' if enough space */
137 if( Destination
->MaximumLength
> Destination
->Length
)
138 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
140 return STATUS_SUCCESS
;
144 /**************************************************************************
145 * RtlCharToInteger (NTDLL.@)
147 * Converts a character string into its integer equivalent.
150 * Success: STATUS_SUCCESS. value contains the converted number
151 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
152 * STATUS_ACCESS_VIOLATION, if value is NULL.
155 * For base 0 it uses 10 as base and the string should be in the format
156 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
157 * For other bases the string should be in the format
158 * "{whitespace} [+|-] {digits}".
159 * No check is made for value overflow, only the lower 32 bits are assigned.
160 * If str is NULL it crashes, as the native function does.
163 * This function does not read garbage behind '\0' as the native version does.
168 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
169 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
170 PULONG value
) /* [O] Destination for the converted value */
174 ULONG RunningTotal
= 0;
177 while (*str
!= '\0' && *str
<= ' ') {
183 } else if (*str
== '-') {
194 } else if (str
[1] == 'o') {
197 } else if (str
[1] == 'x') {
202 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
203 return STATUS_INVALID_PARAMETER
;
207 return STATUS_ACCESS_VIOLATION
;
210 while (*str
!= '\0') {
212 if (chCurrent
>= '0' && chCurrent
<= '9') {
213 digit
= chCurrent
- '0';
214 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
215 digit
= chCurrent
- 'A' + 10;
216 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
217 digit
= chCurrent
- 'a' + 10;
221 if (digit
< 0 || digit
>= (int)base
) {
222 *value
= bMinus
? -RunningTotal
: RunningTotal
;
223 return STATUS_SUCCESS
;
226 RunningTotal
= RunningTotal
* base
+ digit
;
230 *value
= bMinus
? -RunningTotal
: RunningTotal
;
231 return STATUS_SUCCESS
;
242 IN BOOLEAN CaseInsensitive
)
248 len
= min(s1
->Length
, s2
->Length
);
254 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
258 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
260 if (!ret
) ret
= s1
->Length
- s2
->Length
;
269 * TRUE if strings are equal.
276 IN BOOLEAN CaseInsensitive
)
278 if (s1
->Length
!= s2
->Length
) return FALSE
;
279 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
287 * TRUE if strings are equal.
291 RtlEqualUnicodeString(
292 IN CONST UNICODE_STRING
*s1
,
293 IN CONST UNICODE_STRING
*s2
,
294 IN BOOLEAN CaseInsensitive
)
296 if (s1
->Length
!= s2
->Length
) return FALSE
;
297 return !RtlCompareUnicodeString((PUNICODE_STRING
)s1
, (PUNICODE_STRING
)s2
, CaseInsensitive
);
306 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
308 if (AnsiString
->Buffer
!= NULL
)
310 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
312 AnsiString
->Buffer
= NULL
;
313 AnsiString
->Length
= 0;
314 AnsiString
->MaximumLength
= 0;
324 RtlFreeOemString(IN POEM_STRING OemString
)
326 if (OemString
->Buffer
!= NULL
)
328 RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
330 OemString
->Buffer
= NULL
;
331 OemString
->Length
= 0;
332 OemString
->MaximumLength
= 0;
342 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
344 if (UnicodeString
->Buffer
!= NULL
)
346 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_USTR
);
348 UnicodeString
->Buffer
= NULL
;
349 UnicodeString
->Length
= 0;
350 UnicodeString
->MaximumLength
= 0;
359 RtlIsValidOemCharacter (
371 * If source is NULL the length of source is assumed to be 0.
375 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
376 IN PCSZ SourceString
)
380 if (SourceString
== NULL
)
382 DestinationString
->Length
= 0;
383 DestinationString
->MaximumLength
= 0;
387 DestSize
= strlen ((const char *)SourceString
);
388 DestinationString
->Length
= DestSize
;
389 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
391 DestinationString
->Buffer
= (PCHAR
)SourceString
;
400 * If source is NULL the length of source is assumed to be 0.
405 IN OUT PSTRING DestinationString
,
406 IN PCSZ SourceString
)
410 if (SourceString
== NULL
)
412 DestinationString
->Length
= 0;
413 DestinationString
->MaximumLength
= 0;
417 DestSize
= strlen((const char *)SourceString
);
418 DestinationString
->Length
= DestSize
;
419 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
421 DestinationString
->Buffer
= (PCHAR
)SourceString
;
429 * If source is NULL the length of source is assumed to be 0.
433 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
434 IN PCWSTR SourceString
)
438 DPRINT("RtlInitUnicodeString(DestinationString 0x%p, SourceString 0x%p)\n",
442 if (SourceString
== NULL
)
444 DestinationString
->Length
= 0;
445 DestinationString
->MaximumLength
= 0;
449 DestSize
= wcslen((PWSTR
)SourceString
) * sizeof(WCHAR
);
450 DestinationString
->Length
= DestSize
;
451 DestinationString
->MaximumLength
= DestSize
+ sizeof(WCHAR
);
453 DestinationString
->Buffer
= (PWSTR
)SourceString
;
460 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
461 IN PCWSTR SourceString
)
465 if (SourceString
!= NULL
)
467 Length
= wcslen(SourceString
) * sizeof(WCHAR
);
469 return STATUS_NAME_TOO_LONG
;
471 DestinationString
->Length
= Length
;
472 DestinationString
->MaximumLength
= Length
+ sizeof(WCHAR
);
473 DestinationString
->Buffer
= (PWSTR
)SourceString
;
477 DestinationString
->Length
= 0;
478 DestinationString
->MaximumLength
= 0;
479 DestinationString
->Buffer
= NULL
;
482 return STATUS_SUCCESS
;
489 * Writes at most length characters to the string str.
490 * Str is nullterminated when length allowes it.
491 * When str fits exactly in length characters the nullterm is ommitted.
512 if ((Radix
!= 2) && (Radix
!= 8) &&
513 (Radix
!= 10) && (Radix
!= 16))
515 return STATUS_INVALID_PARAMETER
;
519 while (v
|| tp
== temp
)
530 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
532 return STATUS_BUFFER_TOO_SMALL
;
540 return STATUS_SUCCESS
;
551 IN ULONG Base OPTIONAL
,
552 IN ULONG Length OPTIONAL
,
567 if ((Radix
!= 2) && (Radix
!= 8) &&
568 (Radix
!= 10) && (Radix
!= 16))
570 return STATUS_INVALID_PARAMETER
;
574 while (v
|| tp
== temp
)
585 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
587 return STATUS_BUFFER_TOO_SMALL
;
595 return STATUS_SUCCESS
;
605 RtlIntegerToUnicodeString(
607 IN ULONG Base
, /* optional */
608 IN OUT PUNICODE_STRING String
)
610 ANSI_STRING AnsiString
;
614 Status
= RtlIntegerToChar (Value
,
618 if (NT_SUCCESS(Status
))
620 AnsiString
.Buffer
= Buffer
;
621 AnsiString
.Length
= strlen (Buffer
);
622 AnsiString
.MaximumLength
= sizeof(Buffer
);
624 Status
= RtlAnsiStringToUnicodeString (String
,
638 RtlInt64ToUnicodeString (
640 IN ULONG Base OPTIONAL
,
641 IN OUT PUNICODE_STRING String
644 LARGE_INTEGER LargeInt
;
645 ANSI_STRING AnsiString
;
649 LargeInt
.QuadPart
= Value
;
651 Status
= RtlLargeIntegerToChar (&LargeInt
,
655 if (NT_SUCCESS(Status
))
657 AnsiString
.Buffer
= Buffer
;
658 AnsiString
.Length
= strlen (Buffer
);
659 AnsiString
.MaximumLength
= sizeof(Buffer
);
661 Status
= RtlAnsiStringToUnicodeString (String
,
674 * TRUE if String2 contains String1 as a prefix.
679 PANSI_STRING String1
,
680 PANSI_STRING String2
,
681 BOOLEAN CaseInsensitive
)
687 if (String2
->Length
< String1
->Length
)
690 Length
= String1
->Length
;
691 pc1
= String1
->Buffer
;
692 pc2
= String2
->Buffer
;
700 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
708 if (*pc1
++ != *pc2
++)
722 * TRUE if String2 contains String1 as a prefix.
726 RtlPrefixUnicodeString(
727 PUNICODE_STRING String1
,
728 PUNICODE_STRING String2
,
729 BOOLEAN CaseInsensitive
)
735 if (String2
->Length
< String1
->Length
)
738 Length
= String1
->Length
/ 2;
739 pc1
= String1
->Buffer
;
740 pc2
= String2
->Buffer
;
748 if (RtlUpcaseUnicodeChar (*pc1
++)
749 != RtlUpcaseUnicodeChar (*pc2
++))
757 if( *pc1
++ != *pc2
++ )
766 /**************************************************************************
767 * RtlUnicodeStringToInteger (NTDLL.@)
769 * Converts an unicode string into its integer equivalent.
772 * Success: STATUS_SUCCESS. value contains the converted number
773 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
774 * STATUS_ACCESS_VIOLATION, if value is NULL.
777 * For base 0 it uses 10 as base and the string should be in the format
778 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
779 * For other bases the string should be in the format
780 * "{whitespace} [+|-] {digits}".
781 * No check is made for value overflow, only the lower 32 bits are assigned.
782 * If str is NULL it crashes, as the native function does.
784 * Note that regardless of success or failure status, we should leave the
785 * partial value in Value. An error is never returned based on the chars
789 * This function does not read garbage on string length 0 as the native
794 RtlUnicodeStringToInteger(
795 PUNICODE_STRING str
, /* [I] Unicode string to be converted */
796 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
797 PULONG value
) /* [O] Destination for the converted value */
799 LPWSTR lpwstr
= str
->Buffer
;
800 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
804 ULONG RunningTotal
= 0;
807 while (CharsRemaining
>= 1 && *lpwstr
<= L
' ') {
812 if (CharsRemaining
>= 1) {
813 if (*lpwstr
== L
'+') {
816 } else if (*lpwstr
== L
'-') {
823 if (CharsRemaining
>= 2 && lpwstr
[0] == L
'0') {
824 if (lpwstr
[1] == L
'b' || lpwstr
[1] == L
'B') {
828 } else if (lpwstr
[1] == L
'o' || lpwstr
[1] == L
'O') {
832 } else if (lpwstr
[1] == L
'x' || lpwstr
[1] == L
'X') {
838 if (base
== 0 && newbase
== 0) {
840 } else if (base
== 0 && newbase
!= 0) {
842 } else if ((newbase
!= 0 && base
!= newbase
) ||
843 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
844 return STATUS_INVALID_PARAMETER
;
849 return STATUS_ACCESS_VIOLATION
;
852 while (CharsRemaining
>= 1) {
853 wchCurrent
= *lpwstr
;
854 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
855 digit
= wchCurrent
- L
'0';
856 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
857 digit
= wchCurrent
- L
'A' + 10;
858 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
859 digit
= wchCurrent
- L
'a' + 10;
863 if (digit
< 0 || digit
>= (int)base
) {
864 *value
= bMinus
? -RunningTotal
: RunningTotal
;
865 return STATUS_SUCCESS
;
868 RunningTotal
= RunningTotal
* base
+ digit
;
873 *value
= bMinus
? -RunningTotal
: RunningTotal
;
874 return STATUS_SUCCESS
;
882 * Bytes necessary for the conversion including nullterm.
886 RtlUnicodeStringToOemSize(
887 IN PUNICODE_STRING UnicodeString
)
891 RtlUnicodeToMultiByteSize (&Size
,
892 UnicodeString
->Buffer
,
893 UnicodeString
->Length
);
895 return Size
+1; //NB: incl. nullterm
903 * This function always writes a terminating '\0'.
904 * It performs a partial copy if ansi is too small.
908 RtlUnicodeStringToAnsiString(
909 IN OUT PANSI_STRING AnsiDest
,
910 IN PUNICODE_STRING UniSource
,
911 IN BOOLEAN AllocateDestinationString
)
913 NTSTATUS Status
= STATUS_SUCCESS
;
914 ULONG Length
; /* including nullterm */
916 if (NlsMbCodePageTag
== TRUE
)
918 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
921 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
923 AnsiDest
->Length
= Length
- sizeof(CHAR
);
925 if (AllocateDestinationString
)
927 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
928 if (AnsiDest
->Buffer
== NULL
)
929 return STATUS_NO_MEMORY
;
931 AnsiDest
->MaximumLength
= Length
;
933 else if (AnsiDest
->MaximumLength
== 0)
935 return STATUS_BUFFER_TOO_SMALL
;
937 else if (Length
> AnsiDest
->MaximumLength
)
939 /* make room for nullterm */
940 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
943 Status
= RtlUnicodeToMultiByteN (AnsiDest
->Buffer
,
949 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
951 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
955 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
964 * This function always writes a terminating '\0'.
965 * Does NOT perform a partial copy if unicode is too small!
969 RtlOemStringToUnicodeString(
970 IN OUT PUNICODE_STRING UniDest
,
971 IN POEM_STRING OemSource
,
972 IN BOOLEAN AllocateDestinationString
)
975 ULONG Length
; /* including nullterm */
977 if (NlsMbOemCodePageTag
== TRUE
)
978 Length
= RtlOemStringToUnicodeSize(OemSource
);
980 Length
= (OemSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
983 return STATUS_INVALID_PARAMETER_2
;
985 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
987 if (AllocateDestinationString
)
989 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
990 if (UniDest
->Buffer
== NULL
)
991 return STATUS_NO_MEMORY
;
993 UniDest
->MaximumLength
= Length
;
995 else if (Length
> UniDest
->MaximumLength
)
997 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
998 return STATUS_BUFFER_TOO_SMALL
;
1001 /* FIXME: Do we need this????? -Gunnar */
1002 RtlZeroMemory (UniDest
->Buffer
,
1005 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1011 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1013 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1017 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1018 return STATUS_SUCCESS
;
1026 * This function always '\0' terminates the string returned.
1030 RtlUnicodeStringToOemString(
1031 IN OUT POEM_STRING OemDest
,
1032 IN PUNICODE_STRING UniSource
,
1033 IN BOOLEAN AllocateDestinationString
)
1035 NTSTATUS Status
= STATUS_SUCCESS
;
1036 ULONG Length
; //including nullterm
1038 if (NlsMbOemCodePageTag
== TRUE
)
1039 Length
= RtlUnicodeStringToAnsiSize (UniSource
);
1041 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1043 if (Length
> 0x0000FFFF)
1044 return STATUS_INVALID_PARAMETER_2
;
1046 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1048 if (AllocateDestinationString
)
1050 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1051 if (OemDest
->Buffer
== NULL
)
1052 return STATUS_NO_MEMORY
;
1054 OemDest
->MaximumLength
= Length
;
1056 else if (OemDest
->MaximumLength
== 0)
1058 return STATUS_BUFFER_TOO_SMALL
;
1060 else if (Length
> OemDest
->MaximumLength
)
1062 //make room for nullterm
1063 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1066 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1072 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1074 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1078 OemDest
->Buffer
[OemDest
->Length
] = 0;
1082 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1089 * The length of the string if all tests were passed, 0 otherwise.
1092 RtlIsTextUnicode (PVOID Buffer
,
1097 ULONG in_flags
= (ULONG
)-1;
1098 ULONG out_flags
= 0;
1107 * Apply various tests to the text string. According to the
1108 * docs, each test "passed" sets the corresponding flag in
1109 * the output flags. But some of the tests are mutually
1110 * exclusive, so I don't see how you could pass all tests ...
1113 /* Check for an odd length ... pass if even. */
1115 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1117 /* Check for the BOM (byte order mark). */
1119 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1122 /* Check for the reverse BOM (byte order mark). */
1124 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1127 /* FIXME: Add more tests */
1130 * Check whether the string passed all of the tests.
1132 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1133 if ((out_flags
& in_flags
) != in_flags
)
1148 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1149 * A partial copy is NOT performed if the dest buffer is too small!
1153 RtlOemStringToCountedUnicodeString(
1154 IN OUT PUNICODE_STRING UniDest
,
1155 IN POEM_STRING OemSource
,
1156 IN BOOLEAN AllocateDestinationString
)
1159 ULONG Length
; /* excluding nullterm */
1161 if (NlsMbCodePageTag
== TRUE
)
1162 Length
= RtlOemStringToUnicodeSize(OemSource
) - sizeof(WCHAR
);
1164 Length
= OemSource
->Length
* sizeof(WCHAR
);
1167 return STATUS_INVALID_PARAMETER_2
;
1169 if (AllocateDestinationString
== TRUE
)
1171 UniDest
->Buffer
= RtlpAllocateStringMemory (Length
, TAG_USTR
);
1172 if (UniDest
->Buffer
== NULL
)
1173 return STATUS_NO_MEMORY
;
1175 UniDest
->MaximumLength
= Length
;
1177 else if (Length
> UniDest
->MaximumLength
)
1179 return STATUS_BUFFER_TOO_SMALL
;
1182 UniDest
->Length
= Length
;
1184 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1190 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1192 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1203 * TRUE if the names are equal, FALSE if not
1206 * The comparison is case insensitive.
1210 RtlEqualComputerName(
1211 IN PUNICODE_STRING ComputerName1
,
1212 IN PUNICODE_STRING ComputerName2
)
1214 OEM_STRING OemString1
;
1215 OEM_STRING OemString2
;
1216 BOOLEAN Result
= FALSE
;
1218 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1220 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1222 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1223 RtlFreeOemString( &OemString2
);
1225 RtlFreeOemString( &OemString1
);
1235 * TRUE if the names are equal, FALSE if not
1238 * The comparison is case insensitive.
1242 RtlEqualDomainName (
1243 IN PUNICODE_STRING DomainName1
,
1244 IN PUNICODE_STRING DomainName2
1247 return RtlEqualComputerName(DomainName1
, DomainName2
);
1257 RtlEqualDomainName (
1258 IN PUNICODE_STRING DomainName1,
1259 IN PUNICODE_STRING DomainName2
1262 OEM_STRING OemString1;
1263 OEM_STRING OemString2;
1266 RtlUpcaseUnicodeStringToOemString (&OemString1,
1269 RtlUpcaseUnicodeStringToOemString (&OemString2,
1273 Result = RtlEqualString (&OemString1,
1277 RtlFreeOemString (&OemString1);
1278 RtlFreeOemString (&OemString2);
1288 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1290 * Convert a string representation of a GUID into a GUID.
1293 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1294 * guid [O] Destination for the converted GUID
1297 * Success: STATUS_SUCCESS. guid contains the converted value.
1298 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1301 * See RtlStringFromGUID.
1306 IN UNICODE_STRING
*str
,
1311 const WCHAR
*lpszCLSID
= str
->Buffer
;
1312 BYTE
* lpOut
= (BYTE
*)guid
;
1314 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1316 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1317 * to memory: DWORD... WORD WORD BYTES............
1324 if (*lpszCLSID
!= '{')
1325 return STATUS_INVALID_PARAMETER
;
1332 if (*lpszCLSID
!= '-')
1333 return STATUS_INVALID_PARAMETER
;
1337 if (*lpszCLSID
!= '}')
1338 return STATUS_INVALID_PARAMETER
;
1343 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1346 /* Read two hex digits as a byte value */
1347 if (ch
>= '0' && ch
<= '9')
1349 else if (ch
>= 'a' && ch
<= 'f')
1351 else if (ch
>= 'A' && ch
<= 'F')
1354 return STATUS_INVALID_PARAMETER
;
1356 if (ch2
>= '0' && ch2
<= '9')
1358 else if (ch2
>= 'a' && ch2
<= 'f')
1359 ch2
= ch2
- 'a' + 10;
1360 else if (ch2
>= 'A' && ch2
<= 'F')
1361 ch2
= ch2
- 'A' + 10;
1363 return STATUS_INVALID_PARAMETER
;
1365 byte
= ch
<< 4 | ch2
;
1369 #ifndef WORDS_BIGENDIAN
1370 /* For Big Endian machines, we store the data such that the
1371 * dword/word members can be read as DWORDS and WORDS correctly. */
1403 lpszCLSID
++; /* Skip 2nd character of byte */
1411 return STATUS_SUCCESS
;
1419 RtlEraseUnicodeString(
1420 IN PUNICODE_STRING String
)
1422 if (String
->Buffer
!= NULL
&&
1423 String
->MaximumLength
!= 0)
1425 RtlZeroMemory (String
->Buffer
,
1426 String
->MaximumLength
);
1437 RtlHashUnicodeString(
1438 IN CONST UNICODE_STRING
*String
,
1439 IN BOOLEAN CaseInSensitive
,
1440 IN ULONG HashAlgorithm
,
1441 OUT PULONG HashValue
)
1443 if (String
!= NULL
&& HashValue
!= NULL
)
1445 switch (HashAlgorithm
)
1447 case HASH_STRING_ALGORITHM_DEFAULT
:
1448 case HASH_STRING_ALGORITHM_X65599
:
1453 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1455 if (CaseInSensitive
)
1457 for (c
= String
->Buffer
;
1461 /* only uppercase characters if they are 'a' ... 'z'! */
1462 *HashValue
= ((65599 * (*HashValue
)) +
1463 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1464 (*c
) - L
'a' + L
'A' : (*c
)));
1469 for (c
= String
->Buffer
;
1473 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1476 return STATUS_SUCCESS
;
1481 return STATUS_INVALID_PARAMETER
;
1488 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1489 * Does a partial copy if the dest buffer is too small
1493 RtlUnicodeStringToCountedOemString(
1494 IN OUT POEM_STRING OemDest
,
1495 IN PUNICODE_STRING UniSource
,
1496 IN BOOLEAN AllocateDestinationString
)
1499 ULONG Length
; //excluding nullterm
1501 if (NlsMbOemCodePageTag
== TRUE
)
1502 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1504 Length
= (UniSource
->Length
/ sizeof(WCHAR
));
1506 if (Length
> 0x0000FFFF)
1507 return STATUS_INVALID_PARAMETER_2
;
1509 OemDest
->Length
= (WORD
)(Length
);
1511 if (AllocateDestinationString
)
1513 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1514 if (OemDest
->Buffer
== NULL
)
1515 return STATUS_NO_MEMORY
;
1517 OemDest
->MaximumLength
= Length
;
1519 else if (OemDest
->MaximumLength
== 0)
1521 return STATUS_BUFFER_TOO_SMALL
;
1523 else if (Length
> OemDest
->MaximumLength
)
1525 OemDest
->Length
= OemDest
->MaximumLength
;
1528 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1534 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1536 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1547 RtlLargeIntegerToChar(
1548 IN PLARGE_INTEGER Value
,
1551 IN OUT PCHAR String
)
1555 ULONGLONG v
= Value
->QuadPart
;
1564 if ((Radix
!= 2) && (Radix
!= 8) &&
1565 (Radix
!= 10) && (Radix
!= 16))
1566 return STATUS_INVALID_PARAMETER
;
1569 while (v
|| tp
== temp
)
1580 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1581 return STATUS_BUFFER_TOO_SMALL
;
1588 return STATUS_SUCCESS
;
1595 * dest is never '\0' terminated because it may be equal to src, and src
1596 * might not be '\0' terminated. dest->Length is only set upon success.
1600 RtlUpcaseUnicodeString(
1601 IN OUT PUNICODE_STRING UniDest
,
1602 IN PCUNICODE_STRING UniSource
,
1603 IN BOOLEAN AllocateDestinationString
)
1608 if (AllocateDestinationString
== TRUE
)
1610 UniDest
->MaximumLength
= UniSource
->Length
;
1611 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1612 if (UniDest
->Buffer
== NULL
)
1613 return STATUS_NO_MEMORY
;
1615 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1617 return STATUS_BUFFER_TOO_SMALL
;
1620 UniDest
->Length
= UniSource
->Length
;
1622 Src
= UniSource
->Buffer
;
1623 Dest
= UniDest
->Buffer
;
1624 for (i
= 0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
1626 *Dest
= RtlUpcaseUnicodeChar (*Src
);
1631 return STATUS_SUCCESS
;
1638 * This function always writes a terminating '\0'.
1639 * It performs a partial copy if ansi is too small.
1643 RtlUpcaseUnicodeStringToAnsiString(
1644 IN OUT PANSI_STRING AnsiDest
,
1645 IN PUNICODE_STRING UniSource
,
1646 IN BOOLEAN AllocateDestinationString
)
1649 ULONG Length
; /* including nullterm */
1651 if (NlsMbCodePageTag
== TRUE
)
1652 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1654 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1656 if (Length
> 0x0000FFFF)
1657 return STATUS_INVALID_PARAMETER_2
;
1659 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1661 if (AllocateDestinationString
)
1663 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1664 if (AnsiDest
->Buffer
== NULL
)
1665 return STATUS_NO_MEMORY
;
1667 AnsiDest
->MaximumLength
= Length
;
1669 else if (AnsiDest
->MaximumLength
== 0)
1671 return STATUS_BUFFER_TOO_SMALL
;
1673 else if (Length
> AnsiDest
->MaximumLength
)
1675 /* make room for nullterm */
1676 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1679 /* FIXME: do we need this??????? -Gunnar */
1680 RtlZeroMemory (AnsiDest
->Buffer
,
1683 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1689 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1691 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1695 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1703 * This function always writes a terminating '\0'.
1704 * It performs a partial copy if ansi is too small.
1708 RtlUpcaseUnicodeStringToCountedOemString(
1709 IN OUT POEM_STRING OemDest
,
1710 IN PUNICODE_STRING UniSource
,
1711 IN BOOLEAN AllocateDestinationString
)
1714 ULONG Length
; /* excluding nullterm */
1716 if (NlsMbCodePageTag
== TRUE
)
1717 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1719 Length
= UniSource
->Length
/ sizeof(WCHAR
);
1721 if (Length
> 0x0000FFFF)
1722 return(STATUS_INVALID_PARAMETER_2
);
1724 OemDest
->Length
= (WORD
)(Length
);
1726 if (AllocateDestinationString
)
1728 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1729 if (OemDest
->Buffer
== NULL
)
1730 return(STATUS_NO_MEMORY
);
1732 /* FIXME: Do we need this????? */
1733 RtlZeroMemory (OemDest
->Buffer
, Length
);
1735 OemDest
->MaximumLength
= (WORD
)Length
;
1737 else if (OemDest
->MaximumLength
== 0)
1739 return(STATUS_BUFFER_TOO_SMALL
);
1741 else if (Length
> OemDest
->MaximumLength
)
1743 OemDest
->Length
= OemDest
->MaximumLength
;
1746 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1752 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1754 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1764 * Oem string is allways nullterminated
1765 * It performs a partial copy if oem is too small.
1769 RtlUpcaseUnicodeStringToOemString (
1770 IN OUT POEM_STRING OemDest
,
1771 IN PUNICODE_STRING UniSource
,
1772 IN BOOLEAN AllocateDestinationString
1776 ULONG Length
; /* including nullterm */
1778 if (NlsMbOemCodePageTag
== TRUE
)
1779 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1781 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1783 if (Length
> 0x0000FFFF)
1784 return STATUS_INVALID_PARAMETER_2
;
1786 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1788 if (AllocateDestinationString
)
1790 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1791 if (OemDest
->Buffer
== NULL
)
1792 return STATUS_NO_MEMORY
;
1794 /* FIXME: Do we need this???? */
1795 RtlZeroMemory (OemDest
->Buffer
, Length
);
1797 OemDest
->MaximumLength
= (WORD
)Length
;
1799 else if (OemDest
->MaximumLength
== 0)
1801 return STATUS_BUFFER_OVERFLOW
;
1803 else if (Length
> OemDest
->MaximumLength
)
1805 /* make room for nullterm */
1806 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1809 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
1815 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1817 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1821 OemDest
->Buffer
[OemDest
->Length
] = 0;
1829 * Bytes calculated including nullterm
1833 RtlOemStringToUnicodeSize(IN POEM_STRING OemString
)
1837 //this function returns size including nullterm
1838 RtlMultiByteToUnicodeSize(&Size
,
1852 RtlStringFromGUID (IN REFGUID Guid
,
1853 OUT PUNICODE_STRING GuidString
)
1855 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1862 return STATUS_INVALID_PARAMETER
;
1866 L
"{%08lX-%04X-%04X-%02X%02X-",
1872 BufferPtr
= Buffer
+ 25;
1875 for (i
= 2; i
< 8; i
++)
1877 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1878 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1881 *BufferPtr
++ = L
'}';
1882 *BufferPtr
++ = L
'\0';
1884 return RtlCreateUnicodeString (GuidString
, Buffer
);
1892 * Bytes calculated including nullterm
1896 RtlUnicodeStringToAnsiSize(
1897 IN PUNICODE_STRING UnicodeString
)
1901 //this function return size without nullterm!
1902 RtlUnicodeToMultiByteSize (&Size
,
1903 UnicodeString
->Buffer
,
1904 UnicodeString
->Length
);
1906 return Size
+ sizeof(CHAR
); //NB: incl. nullterm
1915 RtlCompareUnicodeString(
1916 IN PUNICODE_STRING s1
,
1917 IN PUNICODE_STRING s2
,
1918 IN BOOLEAN CaseInsensitive
)
1924 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1928 if (CaseInsensitive
)
1930 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1934 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1936 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1948 IN OUT PSTRING DestinationString
,
1949 IN PSTRING SourceString
)
1953 if(SourceString
== NULL
)
1955 DestinationString
->Length
= 0;
1959 copylen
= min (DestinationString
->MaximumLength
,
1960 SourceString
->Length
);
1962 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
1963 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
1965 DestinationString
->Buffer
[copylen
] = 0;
1967 DestinationString
->Length
= copylen
;
1977 RtlCopyUnicodeString(
1978 IN OUT PUNICODE_STRING DestinationString
,
1979 IN PUNICODE_STRING SourceString
)
1983 if (SourceString
== NULL
)
1985 DestinationString
->Length
= 0;
1989 copylen
= min (DestinationString
->MaximumLength
,
1990 SourceString
->Length
);
1991 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
1992 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
1994 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
1996 DestinationString
->Length
= copylen
;
2003 * Creates a nullterminated UNICODE_STRING
2007 RtlCreateUnicodeString(
2008 IN OUT PUNICODE_STRING UniDest
,
2013 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
2014 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2015 if (UniDest
->Buffer
== NULL
)
2018 RtlCopyMemory (UniDest
->Buffer
,
2022 UniDest
->MaximumLength
= Length
;
2023 UniDest
->Length
= Length
- sizeof (WCHAR
);
2033 RtlCreateUnicodeStringFromAsciiz(
2034 OUT PUNICODE_STRING Destination
,
2037 ANSI_STRING AnsiString
;
2040 RtlInitAnsiString (&AnsiString
,
2043 Status
= RtlAnsiStringToUnicodeString (Destination
,
2047 return NT_SUCCESS(Status
);
2054 * Dest is never '\0' terminated because it may be equal to src, and src
2055 * might not be '\0' terminated.
2056 * Dest->Length is only set upon success.
2059 RtlDowncaseUnicodeString(
2060 IN OUT PUNICODE_STRING UniDest
,
2061 IN PUNICODE_STRING UniSource
,
2062 IN BOOLEAN AllocateDestinationString
)
2067 if (AllocateDestinationString
)
2069 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2070 if (UniDest
->Buffer
== NULL
)
2071 return STATUS_NO_MEMORY
;
2073 UniDest
->MaximumLength
= UniSource
->Length
;
2075 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2077 return STATUS_BUFFER_TOO_SMALL
;
2080 UniDest
->Length
= UniSource
->Length
;
2082 Src
= UniSource
->Buffer
;
2083 Dest
= UniDest
->Buffer
;
2084 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2090 else if (*Src
<= L
'Z')
2092 *Dest
= (*Src
+ (L
'a' - L
'A'));
2096 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2103 return STATUS_SUCCESS
;
2110 * if src is NULL dest is unchanged.
2111 * dest is '\0' terminated when the MaximumLength allowes it.
2112 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2115 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2120 slen
= wcslen(Source
) * sizeof(WCHAR
);
2122 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2123 return(STATUS_BUFFER_TOO_SMALL
);
2125 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2126 Destination
->Length
+= slen
;
2127 /* append terminating '\0' if enough space */
2128 if( Destination
->MaximumLength
> Destination
->Length
)
2129 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2131 return(STATUS_SUCCESS
);
2138 * This function always writes a terminating '\0'.
2139 * If the dest buffer is too small a partial copy is NOT performed!
2143 RtlAnsiStringToUnicodeString(
2144 IN OUT PUNICODE_STRING UniDest
,
2145 IN PANSI_STRING AnsiSource
,
2146 IN BOOLEAN AllocateDestinationString
)
2149 ULONG Length
; //including nullterm
2151 if (NlsMbCodePageTag
== TRUE
)
2152 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2154 Length
= (AnsiSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
2156 if (Length
> 0xffff)
2157 return STATUS_INVALID_PARAMETER_2
;
2159 if (AllocateDestinationString
== TRUE
)
2161 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2162 if (UniDest
->Buffer
== NULL
)
2163 return STATUS_NO_MEMORY
;
2165 UniDest
->MaximumLength
= Length
;
2167 else if (Length
> UniDest
->MaximumLength
)
2169 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2170 return STATUS_BUFFER_TOO_SMALL
;
2173 UniDest
->Length
= Length
- sizeof(WCHAR
);
2175 //FIXME: We don't need this??? -Gunnar
2176 RtlZeroMemory (UniDest
->Buffer
,
2179 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2183 AnsiSource
->Length
);
2185 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2187 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
2191 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2199 * if src is NULL dest is unchanged.
2200 * dest is never '\0' terminated.
2204 RtlAppendAsciizToString(
2205 IN OUT PSTRING Destination
,
2212 return STATUS_SUCCESS
;
2214 Length
= strlen (Source
);
2215 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2216 return STATUS_BUFFER_TOO_SMALL
;
2218 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2225 Destination
->Length
+= Length
;
2227 return STATUS_SUCCESS
;
2235 RtlUpperString(PSTRING DestinationString
,
2236 PSTRING SourceString
)
2243 Length
= min(SourceString
->Length
,
2244 DestinationString
->MaximumLength
- 1);
2246 Src
= SourceString
->Buffer
;
2247 Dest
= DestinationString
->Buffer
;
2248 for (i
= 0; i
< Length
; i
++)
2250 *Dest
= RtlUpperChar(*Src
);
2256 DestinationString
->Length
= SourceString
->Length
;
2264 RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
2266 return RtlAnsiStringToUnicodeSize(AnsiString
);
2274 RtlxOemStringToUnicodeSize(IN POEM_STRING OemString
)
2276 return RtlOemStringToUnicodeSize(OemString
);
2285 RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString
)
2287 return RtlUnicodeStringToAnsiSize(UnicodeString
);
2295 RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString
)
2297 return RtlUnicodeStringToOemSize(UnicodeString
);
2304 * See RtlpDuplicateUnicodeString
2307 RtlDuplicateUnicodeString(
2309 IN PUNICODE_STRING SourceString
,
2310 PUNICODE_STRING DestinationString
)
2312 if (SourceString
== NULL
|| DestinationString
== NULL
)
2313 return STATUS_INVALID_PARAMETER
;
2316 if (SourceString
->Length
== 0 && AddNull
!= 3)
2318 DestinationString
->Length
= 0;
2319 DestinationString
->MaximumLength
= 0;
2320 DestinationString
->Buffer
= NULL
;
2324 UINT DestMaxLength
= SourceString
->Length
;
2327 DestMaxLength
+= sizeof(UNICODE_NULL
);
2329 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2330 if (DestinationString
->Buffer
== NULL
)
2331 return STATUS_NO_MEMORY
;
2333 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2334 DestinationString
->Length
= SourceString
->Length
;
2335 DestinationString
->MaximumLength
= DestMaxLength
;
2338 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2341 return STATUS_SUCCESS
;
2348 RtlValidateUnicodeString(IN ULONG Flags
,
2349 IN PUNICODE_STRING UnicodeString
)
2351 /* currently no flags are supported! */
2355 ((UnicodeString
== NULL
) ||
2356 ((UnicodeString
->Length
!= 0) &&
2357 (UnicodeString
->Buffer
!= NULL
) &&
2358 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2359 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2360 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2362 /* a NULL pointer as a unicode string is considered to be a valid unicode
2364 return STATUS_SUCCESS
;
2368 return STATUS_INVALID_PARAMETER
;