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 RtlxAnsiStringToUnicodeSize(IN PCANSI_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 PCUNICODE_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 PCUNICODE_STRING String1
,
728 PCUNICODE_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 PCUNICODE_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 RtlxUnicodeStringToOemSize(
887 IN PCUNICODE_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 PCUNICODE_STRING UniSource
,
911 IN BOOLEAN AllocateDestinationString
)
913 NTSTATUS Status
= STATUS_SUCCESS
;
914 ULONG Length
; /* including nullterm */
916 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
917 AnsiDest
->Length
= Length
- sizeof(CHAR
);
919 if (AllocateDestinationString
)
921 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
922 if (AnsiDest
->Buffer
== NULL
)
923 return STATUS_NO_MEMORY
;
925 AnsiDest
->MaximumLength
= Length
;
927 else if (AnsiDest
->MaximumLength
== 0)
929 return STATUS_BUFFER_TOO_SMALL
;
931 else if (Length
> AnsiDest
->MaximumLength
)
933 /* make room for nullterm */
934 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
937 Status
= RtlUnicodeToMultiByteN (AnsiDest
->Buffer
,
943 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
945 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
949 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
958 * This function always writes a terminating '\0'.
959 * Does NOT perform a partial copy if unicode is too small!
963 RtlOemStringToUnicodeString(
964 IN OUT PUNICODE_STRING UniDest
,
965 IN PCOEM_STRING OemSource
,
966 IN BOOLEAN AllocateDestinationString
)
969 ULONG Length
; /* including nullterm */
971 Length
= RtlOemStringToUnicodeSize(OemSource
);
973 return STATUS_INVALID_PARAMETER_2
;
975 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
977 if (AllocateDestinationString
)
979 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
980 if (UniDest
->Buffer
== NULL
)
981 return STATUS_NO_MEMORY
;
983 UniDest
->MaximumLength
= Length
;
985 else if (Length
> UniDest
->MaximumLength
)
987 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
988 return STATUS_BUFFER_TOO_SMALL
;
991 /* FIXME: Do we need this????? -Gunnar */
992 RtlZeroMemory (UniDest
->Buffer
,
995 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1001 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1003 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1007 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1008 return STATUS_SUCCESS
;
1016 * This function always '\0' terminates the string returned.
1020 RtlUnicodeStringToOemString(
1021 IN OUT POEM_STRING OemDest
,
1022 IN PCUNICODE_STRING UniSource
,
1023 IN BOOLEAN AllocateDestinationString
)
1025 NTSTATUS Status
= STATUS_SUCCESS
;
1026 ULONG Length
; //including nullterm
1028 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1029 if (Length
> 0x0000FFFF)
1030 return STATUS_INVALID_PARAMETER_2
;
1032 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1034 if (AllocateDestinationString
)
1036 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1037 if (OemDest
->Buffer
== NULL
)
1038 return STATUS_NO_MEMORY
;
1040 OemDest
->MaximumLength
= Length
;
1042 else if (OemDest
->MaximumLength
== 0)
1044 return STATUS_BUFFER_TOO_SMALL
;
1046 else if (Length
> OemDest
->MaximumLength
)
1048 //make room for nullterm
1049 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1052 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1058 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1060 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1064 OemDest
->Buffer
[OemDest
->Length
] = 0;
1068 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1075 * The length of the string if all tests were passed, 0 otherwise.
1078 RtlIsTextUnicode (PVOID Buffer
,
1083 ULONG in_flags
= (ULONG
)-1;
1084 ULONG out_flags
= 0;
1093 * Apply various tests to the text string. According to the
1094 * docs, each test "passed" sets the corresponding flag in
1095 * the output flags. But some of the tests are mutually
1096 * exclusive, so I don't see how you could pass all tests ...
1099 /* Check for an odd length ... pass if even. */
1101 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1103 /* Check for the BOM (byte order mark). */
1105 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1108 /* Check for the reverse BOM (byte order mark). */
1110 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1113 /* FIXME: Add more tests */
1116 * Check whether the string passed all of the tests.
1118 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1119 if ((out_flags
& in_flags
) != in_flags
)
1134 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1135 * A partial copy is NOT performed if the dest buffer is too small!
1139 RtlOemStringToCountedUnicodeString(
1140 IN OUT PUNICODE_STRING UniDest
,
1141 IN PCOEM_STRING OemSource
,
1142 IN BOOLEAN AllocateDestinationString
)
1145 ULONG Length
; /* excluding nullterm */
1147 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1149 return STATUS_INVALID_PARAMETER_2
;
1151 if (AllocateDestinationString
== TRUE
)
1153 UniDest
->Buffer
= RtlpAllocateStringMemory (Length
, TAG_USTR
);
1154 if (UniDest
->Buffer
== NULL
)
1155 return STATUS_NO_MEMORY
;
1157 UniDest
->MaximumLength
= Length
;
1159 else if (Length
> UniDest
->MaximumLength
)
1161 return STATUS_BUFFER_TOO_SMALL
;
1164 UniDest
->Length
= Length
;
1166 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1172 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1174 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1185 * TRUE if the names are equal, FALSE if not
1188 * The comparison is case insensitive.
1192 RtlEqualComputerName(
1193 IN PUNICODE_STRING ComputerName1
,
1194 IN PUNICODE_STRING ComputerName2
)
1196 OEM_STRING OemString1
;
1197 OEM_STRING OemString2
;
1198 BOOLEAN Result
= FALSE
;
1200 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1202 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1204 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1205 RtlFreeOemString( &OemString2
);
1207 RtlFreeOemString( &OemString1
);
1217 * TRUE if the names are equal, FALSE if not
1220 * The comparison is case insensitive.
1224 RtlEqualDomainName (
1225 IN PUNICODE_STRING DomainName1
,
1226 IN PUNICODE_STRING DomainName2
1229 return RtlEqualComputerName(DomainName1
, DomainName2
);
1239 RtlEqualDomainName (
1240 IN PUNICODE_STRING DomainName1,
1241 IN PUNICODE_STRING DomainName2
1244 OEM_STRING OemString1;
1245 OEM_STRING OemString2;
1248 RtlUpcaseUnicodeStringToOemString (&OemString1,
1251 RtlUpcaseUnicodeStringToOemString (&OemString2,
1255 Result = RtlEqualString (&OemString1,
1259 RtlFreeOemString (&OemString1);
1260 RtlFreeOemString (&OemString2);
1270 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1272 * Convert a string representation of a GUID into a GUID.
1275 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1276 * guid [O] Destination for the converted GUID
1279 * Success: STATUS_SUCCESS. guid contains the converted value.
1280 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1283 * See RtlStringFromGUID.
1288 IN UNICODE_STRING
*str
,
1293 const WCHAR
*lpszCLSID
= str
->Buffer
;
1294 BYTE
* lpOut
= (BYTE
*)guid
;
1296 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1298 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1299 * to memory: DWORD... WORD WORD BYTES............
1306 if (*lpszCLSID
!= '{')
1307 return STATUS_INVALID_PARAMETER
;
1314 if (*lpszCLSID
!= '-')
1315 return STATUS_INVALID_PARAMETER
;
1319 if (*lpszCLSID
!= '}')
1320 return STATUS_INVALID_PARAMETER
;
1325 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1328 /* Read two hex digits as a byte value */
1329 if (ch
>= '0' && ch
<= '9')
1331 else if (ch
>= 'a' && ch
<= 'f')
1333 else if (ch
>= 'A' && ch
<= 'F')
1336 return STATUS_INVALID_PARAMETER
;
1338 if (ch2
>= '0' && ch2
<= '9')
1340 else if (ch2
>= 'a' && ch2
<= 'f')
1341 ch2
= ch2
- 'a' + 10;
1342 else if (ch2
>= 'A' && ch2
<= 'F')
1343 ch2
= ch2
- 'A' + 10;
1345 return STATUS_INVALID_PARAMETER
;
1347 byte
= ch
<< 4 | ch2
;
1351 #ifndef WORDS_BIGENDIAN
1352 /* For Big Endian machines, we store the data such that the
1353 * dword/word members can be read as DWORDS and WORDS correctly. */
1385 lpszCLSID
++; /* Skip 2nd character of byte */
1393 return STATUS_SUCCESS
;
1401 RtlEraseUnicodeString(
1402 IN PUNICODE_STRING String
)
1404 if (String
->Buffer
!= NULL
&&
1405 String
->MaximumLength
!= 0)
1407 RtlZeroMemory (String
->Buffer
,
1408 String
->MaximumLength
);
1419 RtlHashUnicodeString(
1420 IN CONST UNICODE_STRING
*String
,
1421 IN BOOLEAN CaseInSensitive
,
1422 IN ULONG HashAlgorithm
,
1423 OUT PULONG HashValue
)
1425 if (String
!= NULL
&& HashValue
!= NULL
)
1427 switch (HashAlgorithm
)
1429 case HASH_STRING_ALGORITHM_DEFAULT
:
1430 case HASH_STRING_ALGORITHM_X65599
:
1435 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1437 if (CaseInSensitive
)
1439 for (c
= String
->Buffer
;
1443 /* only uppercase characters if they are 'a' ... 'z'! */
1444 *HashValue
= ((65599 * (*HashValue
)) +
1445 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1446 (*c
) - L
'a' + L
'A' : (*c
)));
1451 for (c
= String
->Buffer
;
1455 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1458 return STATUS_SUCCESS
;
1463 return STATUS_INVALID_PARAMETER
;
1470 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1471 * Does a partial copy if the dest buffer is too small
1475 RtlUnicodeStringToCountedOemString(
1476 IN OUT POEM_STRING OemDest
,
1477 IN PUNICODE_STRING UniSource
,
1478 IN BOOLEAN AllocateDestinationString
)
1481 ULONG Length
; //excluding nullterm
1483 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1484 if (Length
> 0x0000FFFF)
1485 return STATUS_INVALID_PARAMETER_2
;
1487 OemDest
->Length
= (WORD
)(Length
);
1489 if (AllocateDestinationString
)
1491 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1492 if (OemDest
->Buffer
== NULL
)
1493 return STATUS_NO_MEMORY
;
1495 OemDest
->MaximumLength
= Length
;
1497 else if (OemDest
->MaximumLength
== 0)
1499 return STATUS_BUFFER_TOO_SMALL
;
1501 else if (Length
> OemDest
->MaximumLength
)
1503 OemDest
->Length
= OemDest
->MaximumLength
;
1506 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1512 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1514 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1525 RtlLargeIntegerToChar(
1526 IN PLARGE_INTEGER Value
,
1529 IN OUT PCHAR String
)
1533 ULONGLONG v
= Value
->QuadPart
;
1542 if ((Radix
!= 2) && (Radix
!= 8) &&
1543 (Radix
!= 10) && (Radix
!= 16))
1544 return STATUS_INVALID_PARAMETER
;
1547 while (v
|| tp
== temp
)
1558 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1559 return STATUS_BUFFER_TOO_SMALL
;
1566 return STATUS_SUCCESS
;
1573 * dest is never '\0' terminated because it may be equal to src, and src
1574 * might not be '\0' terminated. dest->Length is only set upon success.
1578 RtlUpcaseUnicodeString(
1579 IN OUT PUNICODE_STRING UniDest
,
1580 IN PCUNICODE_STRING UniSource
,
1581 IN BOOLEAN AllocateDestinationString
)
1586 if (AllocateDestinationString
== TRUE
)
1588 UniDest
->MaximumLength
= UniSource
->Length
;
1589 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1590 if (UniDest
->Buffer
== NULL
)
1591 return STATUS_NO_MEMORY
;
1593 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1595 return STATUS_BUFFER_TOO_SMALL
;
1598 UniDest
->Length
= UniSource
->Length
;
1600 Src
= UniSource
->Buffer
;
1601 Dest
= UniDest
->Buffer
;
1602 for (i
= 0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
1604 *Dest
= RtlUpcaseUnicodeChar (*Src
);
1609 return STATUS_SUCCESS
;
1616 * This function always writes a terminating '\0'.
1617 * It performs a partial copy if ansi is too small.
1621 RtlUpcaseUnicodeStringToAnsiString(
1622 IN OUT PANSI_STRING AnsiDest
,
1623 IN PUNICODE_STRING UniSource
,
1624 IN BOOLEAN AllocateDestinationString
)
1627 ULONG Length
; /* including nullterm */
1629 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1630 if (Length
> 0x0000FFFF)
1631 return STATUS_INVALID_PARAMETER_2
;
1633 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1635 if (AllocateDestinationString
)
1637 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1638 if (AnsiDest
->Buffer
== NULL
)
1639 return STATUS_NO_MEMORY
;
1641 AnsiDest
->MaximumLength
= Length
;
1643 else if (AnsiDest
->MaximumLength
== 0)
1645 return STATUS_BUFFER_TOO_SMALL
;
1647 else if (Length
> AnsiDest
->MaximumLength
)
1649 /* make room for nullterm */
1650 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1653 /* FIXME: do we need this??????? -Gunnar */
1654 RtlZeroMemory (AnsiDest
->Buffer
,
1657 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1663 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1665 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1669 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1677 * This function always writes a terminating '\0'.
1678 * It performs a partial copy if ansi is too small.
1682 RtlUpcaseUnicodeStringToCountedOemString(
1683 IN OUT POEM_STRING OemDest
,
1684 IN PCUNICODE_STRING UniSource
,
1685 IN BOOLEAN AllocateDestinationString
)
1688 ULONG Length
; /* excluding nullterm */
1690 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1691 if (Length
> 0x0000FFFF)
1692 return(STATUS_INVALID_PARAMETER_2
);
1694 OemDest
->Length
= (WORD
)(Length
);
1696 if (AllocateDestinationString
)
1698 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1699 if (OemDest
->Buffer
== NULL
)
1700 return(STATUS_NO_MEMORY
);
1702 /* FIXME: Do we need this????? */
1703 RtlZeroMemory (OemDest
->Buffer
, Length
);
1705 OemDest
->MaximumLength
= (WORD
)Length
;
1707 else if (OemDest
->MaximumLength
== 0)
1709 return(STATUS_BUFFER_TOO_SMALL
);
1711 else if (Length
> OemDest
->MaximumLength
)
1713 OemDest
->Length
= OemDest
->MaximumLength
;
1716 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1722 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1724 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1734 * Oem string is allways nullterminated
1735 * It performs a partial copy if oem is too small.
1739 RtlUpcaseUnicodeStringToOemString (
1740 IN OUT POEM_STRING OemDest
,
1741 IN PCUNICODE_STRING UniSource
,
1742 IN BOOLEAN AllocateDestinationString
1746 ULONG Length
; /* including nullterm */
1748 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1749 if (Length
> 0x0000FFFF)
1750 return STATUS_INVALID_PARAMETER_2
;
1752 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1754 if (AllocateDestinationString
)
1756 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1757 if (OemDest
->Buffer
== NULL
)
1758 return STATUS_NO_MEMORY
;
1760 /* FIXME: Do we need this???? */
1761 RtlZeroMemory (OemDest
->Buffer
, Length
);
1763 OemDest
->MaximumLength
= (WORD
)Length
;
1765 else if (OemDest
->MaximumLength
== 0)
1767 return STATUS_BUFFER_OVERFLOW
;
1769 else if (Length
> OemDest
->MaximumLength
)
1771 /* make room for nullterm */
1772 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1775 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
1781 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1783 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1787 OemDest
->Buffer
[OemDest
->Length
] = 0;
1795 * Bytes calculated including nullterm
1799 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1803 //this function returns size including nullterm
1804 RtlMultiByteToUnicodeSize(&Size
,
1818 RtlStringFromGUID (IN REFGUID Guid
,
1819 OUT PUNICODE_STRING GuidString
)
1821 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1828 return STATUS_INVALID_PARAMETER
;
1832 L
"{%08lX-%04X-%04X-%02X%02X-",
1838 BufferPtr
= Buffer
+ 25;
1841 for (i
= 2; i
< 8; i
++)
1843 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1844 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1847 *BufferPtr
++ = L
'}';
1848 *BufferPtr
++ = L
'\0';
1850 return RtlCreateUnicodeString (GuidString
, Buffer
);
1858 * Bytes calculated including nullterm
1862 RtlxUnicodeStringToAnsiSize(
1863 IN PCUNICODE_STRING UnicodeString
)
1867 //this function return size without nullterm!
1868 RtlUnicodeToMultiByteSize (&Size
,
1869 UnicodeString
->Buffer
,
1870 UnicodeString
->Length
);
1872 return Size
+ sizeof(CHAR
); //NB: incl. nullterm
1881 RtlCompareUnicodeString(
1882 IN PCUNICODE_STRING s1
,
1883 IN PCUNICODE_STRING s2
,
1884 IN BOOLEAN CaseInsensitive
)
1890 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1894 if (CaseInsensitive
)
1896 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1900 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1902 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1914 IN OUT PSTRING DestinationString
,
1915 IN PSTRING SourceString
)
1919 if(SourceString
== NULL
)
1921 DestinationString
->Length
= 0;
1925 copylen
= min (DestinationString
->MaximumLength
,
1926 SourceString
->Length
);
1928 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
1929 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
1931 DestinationString
->Buffer
[copylen
] = 0;
1933 DestinationString
->Length
= copylen
;
1943 RtlCopyUnicodeString(
1944 IN OUT PUNICODE_STRING DestinationString
,
1945 IN PCUNICODE_STRING SourceString
)
1949 if (SourceString
== NULL
)
1951 DestinationString
->Length
= 0;
1955 copylen
= min (DestinationString
->MaximumLength
,
1956 SourceString
->Length
);
1957 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
1958 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
1960 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
1962 DestinationString
->Length
= copylen
;
1969 * Creates a nullterminated UNICODE_STRING
1973 RtlCreateUnicodeString(
1974 IN OUT PUNICODE_STRING UniDest
,
1979 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
1980 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1981 if (UniDest
->Buffer
== NULL
)
1984 RtlCopyMemory (UniDest
->Buffer
,
1988 UniDest
->MaximumLength
= Length
;
1989 UniDest
->Length
= Length
- sizeof (WCHAR
);
1999 RtlCreateUnicodeStringFromAsciiz(
2000 OUT PUNICODE_STRING Destination
,
2003 ANSI_STRING AnsiString
;
2006 RtlInitAnsiString (&AnsiString
,
2009 Status
= RtlAnsiStringToUnicodeString (Destination
,
2013 return NT_SUCCESS(Status
);
2020 * Dest is never '\0' terminated because it may be equal to src, and src
2021 * might not be '\0' terminated.
2022 * Dest->Length is only set upon success.
2025 RtlDowncaseUnicodeString(
2026 IN OUT PUNICODE_STRING UniDest
,
2027 IN PCUNICODE_STRING UniSource
,
2028 IN BOOLEAN AllocateDestinationString
)
2033 if (AllocateDestinationString
)
2035 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2036 if (UniDest
->Buffer
== NULL
)
2037 return STATUS_NO_MEMORY
;
2039 UniDest
->MaximumLength
= UniSource
->Length
;
2041 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2043 return STATUS_BUFFER_TOO_SMALL
;
2046 UniDest
->Length
= UniSource
->Length
;
2048 Src
= UniSource
->Buffer
;
2049 Dest
= UniDest
->Buffer
;
2050 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2056 else if (*Src
<= L
'Z')
2058 *Dest
= (*Src
+ (L
'a' - L
'A'));
2062 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2069 return STATUS_SUCCESS
;
2076 * if src is NULL dest is unchanged.
2077 * dest is '\0' terminated when the MaximumLength allowes it.
2078 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2081 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2086 slen
= wcslen(Source
) * sizeof(WCHAR
);
2088 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2089 return(STATUS_BUFFER_TOO_SMALL
);
2091 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2092 Destination
->Length
+= slen
;
2093 /* append terminating '\0' if enough space */
2094 if( Destination
->MaximumLength
> Destination
->Length
)
2095 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2097 return(STATUS_SUCCESS
);
2104 * This function always writes a terminating '\0'.
2105 * If the dest buffer is too small a partial copy is NOT performed!
2109 RtlAnsiStringToUnicodeString(
2110 IN OUT PUNICODE_STRING UniDest
,
2111 IN PANSI_STRING AnsiSource
,
2112 IN BOOLEAN AllocateDestinationString
)
2115 ULONG Length
; //including nullterm
2117 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2118 if (Length
> 0xffff)
2119 return STATUS_INVALID_PARAMETER_2
;
2121 if (AllocateDestinationString
== TRUE
)
2123 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2124 if (UniDest
->Buffer
== NULL
)
2125 return STATUS_NO_MEMORY
;
2127 UniDest
->MaximumLength
= Length
;
2129 else if (Length
> UniDest
->MaximumLength
)
2131 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2132 return STATUS_BUFFER_TOO_SMALL
;
2135 UniDest
->Length
= Length
- sizeof(WCHAR
);
2137 //FIXME: We don't need this??? -Gunnar
2138 RtlZeroMemory (UniDest
->Buffer
,
2141 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2145 AnsiSource
->Length
);
2147 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2149 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
2153 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2161 * if src is NULL dest is unchanged.
2162 * dest is never '\0' terminated.
2166 RtlAppendAsciizToString(
2167 IN OUT PSTRING Destination
,
2174 return STATUS_SUCCESS
;
2176 Length
= strlen (Source
);
2177 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2178 return STATUS_BUFFER_TOO_SMALL
;
2180 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2187 Destination
->Length
+= Length
;
2189 return STATUS_SUCCESS
;
2197 RtlUpperString(PSTRING DestinationString
,
2198 PSTRING SourceString
)
2205 Length
= min(SourceString
->Length
,
2206 DestinationString
->MaximumLength
- 1);
2208 Src
= SourceString
->Buffer
;
2209 Dest
= DestinationString
->Buffer
;
2210 for (i
= 0; i
< Length
; i
++)
2212 *Dest
= RtlUpperChar(*Src
);
2218 DestinationString
->Length
= SourceString
->Length
;
2225 * See RtlpDuplicateUnicodeString
2229 RtlDuplicateUnicodeString(
2231 IN PCUNICODE_STRING SourceString
,
2232 OUT PUNICODE_STRING DestinationString
)
2234 if (SourceString
== NULL
|| DestinationString
== NULL
)
2235 return STATUS_INVALID_PARAMETER
;
2238 if ((SourceString
->Length
== 0) &&
2239 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2240 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2242 DestinationString
->Length
= 0;
2243 DestinationString
->MaximumLength
= 0;
2244 DestinationString
->Buffer
= NULL
;
2248 UINT DestMaxLength
= SourceString
->Length
;
2250 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2251 DestMaxLength
+= sizeof(UNICODE_NULL
);
2253 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2254 if (DestinationString
->Buffer
== NULL
)
2255 return STATUS_NO_MEMORY
;
2257 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2258 DestinationString
->Length
= SourceString
->Length
;
2259 DestinationString
->MaximumLength
= DestMaxLength
;
2261 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2262 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2265 return STATUS_SUCCESS
;
2272 RtlValidateUnicodeString(IN ULONG Flags
,
2273 IN PUNICODE_STRING UnicodeString
)
2275 /* currently no flags are supported! */
2279 ((UnicodeString
== NULL
) ||
2280 ((UnicodeString
->Length
!= 0) &&
2281 (UnicodeString
->Buffer
!= NULL
) &&
2282 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2283 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2284 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2286 /* a NULL pointer as a unicode string is considered to be a valid unicode
2288 return STATUS_SUCCESS
;
2292 return STATUS_INVALID_PARAMETER
;