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 /* Convert from Mb String to Unicode Size */
74 RtlMultiByteToUnicodeSize(&Size
,
78 /* Return the size plus the null-char */
79 return(Size
+ sizeof(WCHAR
));
88 * If src->length is zero dest is unchanged.
89 * Dest is never nullterminated.
93 RtlAppendStringToString(IN OUT PSTRING Destination
,
98 if (Source
->Length
== 0)
99 return(STATUS_SUCCESS
);
101 if (Destination
->Length
+ Source
->Length
>= Destination
->MaximumLength
)
102 return(STATUS_BUFFER_TOO_SMALL
);
104 Ptr
= Destination
->Buffer
+ Destination
->Length
;
108 Ptr
+= Source
->Length
;
111 Destination
->Length
+= Source
->Length
;
113 return(STATUS_SUCCESS
);
122 * If src->length is zero dest is unchanged.
123 * Dest is nullterminated when the MaximumLength allowes it.
124 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
128 RtlAppendUnicodeStringToString(
129 IN OUT PUNICODE_STRING Destination
,
130 IN PCUNICODE_STRING Source
)
133 if ((Source
->Length
+ Destination
->Length
) > Destination
->MaximumLength
)
134 return STATUS_BUFFER_TOO_SMALL
;
136 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
->Buffer
, Source
->Length
);
137 Destination
->Length
+= Source
->Length
;
138 /* append terminating '\0' if enough space */
139 if( Destination
->MaximumLength
> Destination
->Length
)
140 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
142 return STATUS_SUCCESS
;
146 /**************************************************************************
147 * RtlCharToInteger (NTDLL.@)
149 * Converts a character string into its integer equivalent.
152 * Success: STATUS_SUCCESS. value contains the converted number
153 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
154 * STATUS_ACCESS_VIOLATION, if value is NULL.
157 * For base 0 it uses 10 as base and the string should be in the format
158 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
159 * For other bases the string should be in the format
160 * "{whitespace} [+|-] {digits}".
161 * No check is made for value overflow, only the lower 32 bits are assigned.
162 * If str is NULL it crashes, as the native function does.
165 * This function does not read garbage behind '\0' as the native version does.
170 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
171 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
172 PULONG value
) /* [O] Destination for the converted value */
176 ULONG RunningTotal
= 0;
179 while (*str
!= '\0' && *str
<= ' ') {
185 } else if (*str
== '-') {
196 } else if (str
[1] == 'o') {
199 } else if (str
[1] == 'x') {
204 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
205 return STATUS_INVALID_PARAMETER
;
209 return STATUS_ACCESS_VIOLATION
;
212 while (*str
!= '\0') {
214 if (chCurrent
>= '0' && chCurrent
<= '9') {
215 digit
= chCurrent
- '0';
216 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
217 digit
= chCurrent
- 'A' + 10;
218 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
219 digit
= chCurrent
- 'a' + 10;
223 if (digit
< 0 || digit
>= (int)base
) {
224 *value
= bMinus
? -RunningTotal
: RunningTotal
;
225 return STATUS_SUCCESS
;
228 RunningTotal
= RunningTotal
* base
+ digit
;
232 *value
= bMinus
? -RunningTotal
: RunningTotal
;
233 return STATUS_SUCCESS
;
244 IN BOOLEAN CaseInsensitive
)
250 len
= min(s1
->Length
, s2
->Length
);
256 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
260 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
262 if (!ret
) ret
= s1
->Length
- s2
->Length
;
271 * TRUE if strings are equal.
278 IN BOOLEAN CaseInsensitive
)
280 if (s1
->Length
!= s2
->Length
) return FALSE
;
281 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
289 * TRUE if strings are equal.
293 RtlEqualUnicodeString(
294 IN CONST UNICODE_STRING
*s1
,
295 IN CONST UNICODE_STRING
*s2
,
296 IN BOOLEAN CaseInsensitive
)
298 if (s1
->Length
!= s2
->Length
) return FALSE
;
299 return !RtlCompareUnicodeString((PUNICODE_STRING
)s1
, (PUNICODE_STRING
)s2
, CaseInsensitive
);
308 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
310 if (AnsiString
->Buffer
!= NULL
)
312 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
314 AnsiString
->Buffer
= NULL
;
315 AnsiString
->Length
= 0;
316 AnsiString
->MaximumLength
= 0;
326 RtlFreeOemString(IN POEM_STRING OemString
)
328 if (OemString
->Buffer
!= NULL
)
330 RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
332 OemString
->Buffer
= NULL
;
333 OemString
->Length
= 0;
334 OemString
->MaximumLength
= 0;
344 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
346 if (UnicodeString
->Buffer
!= NULL
)
348 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_USTR
);
350 UnicodeString
->Buffer
= NULL
;
351 UnicodeString
->Length
= 0;
352 UnicodeString
->MaximumLength
= 0;
361 RtlIsValidOemCharacter (
373 * If source is NULL the length of source is assumed to be 0.
377 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
378 IN PCSZ SourceString
)
382 if (SourceString
== NULL
)
384 DestinationString
->Length
= 0;
385 DestinationString
->MaximumLength
= 0;
389 DestSize
= strlen ((const char *)SourceString
);
390 DestinationString
->Length
= DestSize
;
391 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
393 DestinationString
->Buffer
= (PCHAR
)SourceString
;
402 * If source is NULL the length of source is assumed to be 0.
407 IN OUT PSTRING DestinationString
,
408 IN PCSZ SourceString
)
412 if (SourceString
== NULL
)
414 DestinationString
->Length
= 0;
415 DestinationString
->MaximumLength
= 0;
419 DestSize
= strlen((const char *)SourceString
);
420 DestinationString
->Length
= DestSize
;
421 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
423 DestinationString
->Buffer
= (PCHAR
)SourceString
;
431 * If source is NULL the length of source is assumed to be 0.
435 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
436 IN PCWSTR SourceString
)
440 DPRINT("RtlInitUnicodeString(DestinationString 0x%p, SourceString 0x%p)\n",
444 if (SourceString
== NULL
)
446 DestinationString
->Length
= 0;
447 DestinationString
->MaximumLength
= 0;
451 DestSize
= wcslen((PWSTR
)SourceString
) * sizeof(WCHAR
);
452 DestinationString
->Length
= DestSize
;
453 DestinationString
->MaximumLength
= DestSize
+ sizeof(WCHAR
);
455 DestinationString
->Buffer
= (PWSTR
)SourceString
;
462 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
463 IN PCWSTR SourceString
)
467 if (SourceString
!= NULL
)
469 Length
= wcslen(SourceString
) * sizeof(WCHAR
);
471 return STATUS_NAME_TOO_LONG
;
473 DestinationString
->Length
= Length
;
474 DestinationString
->MaximumLength
= Length
+ sizeof(WCHAR
);
475 DestinationString
->Buffer
= (PWSTR
)SourceString
;
479 DestinationString
->Length
= 0;
480 DestinationString
->MaximumLength
= 0;
481 DestinationString
->Buffer
= NULL
;
484 return STATUS_SUCCESS
;
491 * Writes at most length characters to the string str.
492 * Str is nullterminated when length allowes it.
493 * When str fits exactly in length characters the nullterm is ommitted.
514 if ((Radix
!= 2) && (Radix
!= 8) &&
515 (Radix
!= 10) && (Radix
!= 16))
517 return STATUS_INVALID_PARAMETER
;
521 while (v
|| tp
== temp
)
532 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
534 return STATUS_BUFFER_TOO_SMALL
;
542 return STATUS_SUCCESS
;
553 IN ULONG Base OPTIONAL
,
554 IN ULONG Length OPTIONAL
,
569 if ((Radix
!= 2) && (Radix
!= 8) &&
570 (Radix
!= 10) && (Radix
!= 16))
572 return STATUS_INVALID_PARAMETER
;
576 while (v
|| tp
== temp
)
587 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
589 return STATUS_BUFFER_TOO_SMALL
;
597 return STATUS_SUCCESS
;
607 RtlIntegerToUnicodeString(
609 IN ULONG Base
, /* optional */
610 IN OUT PUNICODE_STRING String
)
612 ANSI_STRING AnsiString
;
616 Status
= RtlIntegerToChar (Value
,
620 if (NT_SUCCESS(Status
))
622 AnsiString
.Buffer
= Buffer
;
623 AnsiString
.Length
= strlen (Buffer
);
624 AnsiString
.MaximumLength
= sizeof(Buffer
);
626 Status
= RtlAnsiStringToUnicodeString (String
,
640 RtlInt64ToUnicodeString (
642 IN ULONG Base OPTIONAL
,
643 IN OUT PUNICODE_STRING String
646 LARGE_INTEGER LargeInt
;
647 ANSI_STRING AnsiString
;
651 LargeInt
.QuadPart
= Value
;
653 Status
= RtlLargeIntegerToChar (&LargeInt
,
657 if (NT_SUCCESS(Status
))
659 AnsiString
.Buffer
= Buffer
;
660 AnsiString
.Length
= strlen (Buffer
);
661 AnsiString
.MaximumLength
= sizeof(Buffer
);
663 Status
= RtlAnsiStringToUnicodeString (String
,
676 * TRUE if String2 contains String1 as a prefix.
681 PANSI_STRING String1
,
682 PANSI_STRING String2
,
683 BOOLEAN CaseInsensitive
)
689 if (String2
->Length
< String1
->Length
)
692 Length
= String1
->Length
;
693 pc1
= String1
->Buffer
;
694 pc2
= String2
->Buffer
;
702 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
710 if (*pc1
++ != *pc2
++)
724 * TRUE if String2 contains String1 as a prefix.
728 RtlPrefixUnicodeString(
729 PCUNICODE_STRING String1
,
730 PCUNICODE_STRING String2
,
731 BOOLEAN CaseInsensitive
)
737 if (String2
->Length
< String1
->Length
)
740 Length
= String1
->Length
/ 2;
741 pc1
= String1
->Buffer
;
742 pc2
= String2
->Buffer
;
750 if (RtlUpcaseUnicodeChar (*pc1
++)
751 != RtlUpcaseUnicodeChar (*pc2
++))
759 if( *pc1
++ != *pc2
++ )
768 /**************************************************************************
769 * RtlUnicodeStringToInteger (NTDLL.@)
771 * Converts an unicode string into its integer equivalent.
774 * Success: STATUS_SUCCESS. value contains the converted number
775 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
776 * STATUS_ACCESS_VIOLATION, if value is NULL.
779 * For base 0 it uses 10 as base and the string should be in the format
780 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
781 * For other bases the string should be in the format
782 * "{whitespace} [+|-] {digits}".
783 * No check is made for value overflow, only the lower 32 bits are assigned.
784 * If str is NULL it crashes, as the native function does.
786 * Note that regardless of success or failure status, we should leave the
787 * partial value in Value. An error is never returned based on the chars
791 * This function does not read garbage on string length 0 as the native
796 RtlUnicodeStringToInteger(
797 PCUNICODE_STRING str
, /* [I] Unicode string to be converted */
798 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
799 PULONG value
) /* [O] Destination for the converted value */
801 LPWSTR lpwstr
= str
->Buffer
;
802 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
806 ULONG RunningTotal
= 0;
809 while (CharsRemaining
>= 1 && *lpwstr
<= L
' ') {
814 if (CharsRemaining
>= 1) {
815 if (*lpwstr
== L
'+') {
818 } else if (*lpwstr
== L
'-') {
825 if (CharsRemaining
>= 2 && lpwstr
[0] == L
'0') {
826 if (lpwstr
[1] == L
'b' || lpwstr
[1] == L
'B') {
830 } else if (lpwstr
[1] == L
'o' || lpwstr
[1] == L
'O') {
834 } else if (lpwstr
[1] == L
'x' || lpwstr
[1] == L
'X') {
840 if (base
== 0 && newbase
== 0) {
842 } else if (base
== 0 && newbase
!= 0) {
844 } else if ((newbase
!= 0 && base
!= newbase
) ||
845 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
846 return STATUS_INVALID_PARAMETER
;
851 return STATUS_ACCESS_VIOLATION
;
854 while (CharsRemaining
>= 1) {
855 wchCurrent
= *lpwstr
;
856 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
857 digit
= wchCurrent
- L
'0';
858 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
859 digit
= wchCurrent
- L
'A' + 10;
860 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
861 digit
= wchCurrent
- L
'a' + 10;
865 if (digit
< 0 || digit
>= (int)base
) {
866 *value
= bMinus
? -RunningTotal
: RunningTotal
;
867 return STATUS_SUCCESS
;
870 RunningTotal
= RunningTotal
* base
+ digit
;
875 *value
= bMinus
? -RunningTotal
: RunningTotal
;
876 return STATUS_SUCCESS
;
884 * Bytes necessary for the conversion including nullterm.
888 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
892 /* Convert the Unicode String to Mb Size */
893 RtlUnicodeToMultiByteSize(&Size
,
894 UnicodeString
->Buffer
,
895 UnicodeString
->Length
);
897 /* Return the size + the null char */
898 return (Size
+ sizeof(CHAR
));
906 * This function always writes a terminating '\0'.
907 * It performs a partial copy if ansi is too small.
911 RtlUnicodeStringToAnsiString(
912 IN OUT PANSI_STRING AnsiDest
,
913 IN PCUNICODE_STRING UniSource
,
914 IN BOOLEAN AllocateDestinationString
)
916 NTSTATUS Status
= STATUS_SUCCESS
;
917 ULONG Length
; /* including nullterm */
919 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
920 AnsiDest
->Length
= Length
- sizeof(CHAR
);
922 if (AllocateDestinationString
)
924 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
925 if (AnsiDest
->Buffer
== NULL
)
926 return STATUS_NO_MEMORY
;
928 AnsiDest
->MaximumLength
= Length
;
930 else if (AnsiDest
->MaximumLength
== 0)
932 return STATUS_BUFFER_TOO_SMALL
;
934 else if (Length
> AnsiDest
->MaximumLength
)
936 /* make room for nullterm */
937 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
940 Status
= RtlUnicodeToMultiByteN (AnsiDest
->Buffer
,
946 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
948 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
952 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
961 * This function always writes a terminating '\0'.
962 * Does NOT perform a partial copy if unicode is too small!
966 RtlOemStringToUnicodeString(
967 IN OUT PUNICODE_STRING UniDest
,
968 IN PCOEM_STRING OemSource
,
969 IN BOOLEAN AllocateDestinationString
)
972 ULONG Length
; /* including nullterm */
974 Length
= RtlOemStringToUnicodeSize(OemSource
);
976 return STATUS_INVALID_PARAMETER_2
;
978 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
980 if (AllocateDestinationString
)
982 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
983 if (UniDest
->Buffer
== NULL
)
984 return STATUS_NO_MEMORY
;
986 UniDest
->MaximumLength
= Length
;
988 else if (Length
> UniDest
->MaximumLength
)
990 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
991 return STATUS_BUFFER_TOO_SMALL
;
994 /* FIXME: Do we need this????? -Gunnar */
995 RtlZeroMemory (UniDest
->Buffer
,
998 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1004 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1006 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1010 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1011 return STATUS_SUCCESS
;
1019 * This function always '\0' terminates the string returned.
1023 RtlUnicodeStringToOemString(
1024 IN OUT POEM_STRING OemDest
,
1025 IN PCUNICODE_STRING UniSource
,
1026 IN BOOLEAN AllocateDestinationString
)
1028 NTSTATUS Status
= STATUS_SUCCESS
;
1029 ULONG Length
; //including nullterm
1031 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1032 if (Length
> 0x0000FFFF)
1033 return STATUS_INVALID_PARAMETER_2
;
1035 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1037 if (AllocateDestinationString
)
1039 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1040 if (OemDest
->Buffer
== NULL
)
1041 return STATUS_NO_MEMORY
;
1043 OemDest
->MaximumLength
= Length
;
1045 else if (OemDest
->MaximumLength
== 0)
1047 return STATUS_BUFFER_TOO_SMALL
;
1049 else if (Length
> OemDest
->MaximumLength
)
1051 //make room for nullterm
1052 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1055 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1061 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1063 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1067 OemDest
->Buffer
[OemDest
->Length
] = 0;
1071 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1078 * The length of the string if all tests were passed, 0 otherwise.
1081 RtlIsTextUnicode (PVOID Buffer
,
1086 ULONG in_flags
= (ULONG
)-1;
1087 ULONG out_flags
= 0;
1096 * Apply various tests to the text string. According to the
1097 * docs, each test "passed" sets the corresponding flag in
1098 * the output flags. But some of the tests are mutually
1099 * exclusive, so I don't see how you could pass all tests ...
1102 /* Check for an odd length ... pass if even. */
1104 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1106 /* Check for the BOM (byte order mark). */
1108 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1111 /* Check for the reverse BOM (byte order mark). */
1113 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1116 /* FIXME: Add more tests */
1119 * Check whether the string passed all of the tests.
1121 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1122 if ((out_flags
& in_flags
) != in_flags
)
1137 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1138 * A partial copy is NOT performed if the dest buffer is too small!
1142 RtlOemStringToCountedUnicodeString(
1143 IN OUT PUNICODE_STRING UniDest
,
1144 IN PCOEM_STRING OemSource
,
1145 IN BOOLEAN AllocateDestinationString
)
1148 ULONG Length
; /* excluding nullterm */
1150 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1152 return STATUS_INVALID_PARAMETER_2
;
1154 if (AllocateDestinationString
== TRUE
)
1156 UniDest
->Buffer
= RtlpAllocateStringMemory (Length
, TAG_USTR
);
1157 if (UniDest
->Buffer
== NULL
)
1158 return STATUS_NO_MEMORY
;
1160 UniDest
->MaximumLength
= Length
;
1162 else if (Length
> UniDest
->MaximumLength
)
1164 return STATUS_BUFFER_TOO_SMALL
;
1167 UniDest
->Length
= Length
;
1169 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1175 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1177 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1188 * TRUE if the names are equal, FALSE if not
1191 * The comparison is case insensitive.
1195 RtlEqualComputerName(
1196 IN PUNICODE_STRING ComputerName1
,
1197 IN PUNICODE_STRING ComputerName2
)
1199 OEM_STRING OemString1
;
1200 OEM_STRING OemString2
;
1201 BOOLEAN Result
= FALSE
;
1203 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1205 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1207 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1208 RtlFreeOemString( &OemString2
);
1210 RtlFreeOemString( &OemString1
);
1220 * TRUE if the names are equal, FALSE if not
1223 * The comparison is case insensitive.
1227 RtlEqualDomainName (
1228 IN PUNICODE_STRING DomainName1
,
1229 IN PUNICODE_STRING DomainName2
1232 return RtlEqualComputerName(DomainName1
, DomainName2
);
1242 RtlEqualDomainName (
1243 IN PUNICODE_STRING DomainName1,
1244 IN PUNICODE_STRING DomainName2
1247 OEM_STRING OemString1;
1248 OEM_STRING OemString2;
1251 RtlUpcaseUnicodeStringToOemString (&OemString1,
1254 RtlUpcaseUnicodeStringToOemString (&OemString2,
1258 Result = RtlEqualString (&OemString1,
1262 RtlFreeOemString (&OemString1);
1263 RtlFreeOemString (&OemString2);
1273 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1275 * Convert a string representation of a GUID into a GUID.
1278 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1279 * guid [O] Destination for the converted GUID
1282 * Success: STATUS_SUCCESS. guid contains the converted value.
1283 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1286 * See RtlStringFromGUID.
1291 IN UNICODE_STRING
*str
,
1296 const WCHAR
*lpszCLSID
= str
->Buffer
;
1297 BYTE
* lpOut
= (BYTE
*)guid
;
1299 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1301 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1302 * to memory: DWORD... WORD WORD BYTES............
1309 if (*lpszCLSID
!= '{')
1310 return STATUS_INVALID_PARAMETER
;
1317 if (*lpszCLSID
!= '-')
1318 return STATUS_INVALID_PARAMETER
;
1322 if (*lpszCLSID
!= '}')
1323 return STATUS_INVALID_PARAMETER
;
1328 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1331 /* Read two hex digits as a byte value */
1332 if (ch
>= '0' && ch
<= '9')
1334 else if (ch
>= 'a' && ch
<= 'f')
1336 else if (ch
>= 'A' && ch
<= 'F')
1339 return STATUS_INVALID_PARAMETER
;
1341 if (ch2
>= '0' && ch2
<= '9')
1343 else if (ch2
>= 'a' && ch2
<= 'f')
1344 ch2
= ch2
- 'a' + 10;
1345 else if (ch2
>= 'A' && ch2
<= 'F')
1346 ch2
= ch2
- 'A' + 10;
1348 return STATUS_INVALID_PARAMETER
;
1350 byte
= ch
<< 4 | ch2
;
1354 #ifndef WORDS_BIGENDIAN
1355 /* For Big Endian machines, we store the data such that the
1356 * dword/word members can be read as DWORDS and WORDS correctly. */
1388 lpszCLSID
++; /* Skip 2nd character of byte */
1396 return STATUS_SUCCESS
;
1404 RtlEraseUnicodeString(
1405 IN PUNICODE_STRING String
)
1407 if (String
->Buffer
!= NULL
&&
1408 String
->MaximumLength
!= 0)
1410 RtlZeroMemory (String
->Buffer
,
1411 String
->MaximumLength
);
1422 RtlHashUnicodeString(
1423 IN CONST UNICODE_STRING
*String
,
1424 IN BOOLEAN CaseInSensitive
,
1425 IN ULONG HashAlgorithm
,
1426 OUT PULONG HashValue
)
1428 if (String
!= NULL
&& HashValue
!= NULL
)
1430 switch (HashAlgorithm
)
1432 case HASH_STRING_ALGORITHM_DEFAULT
:
1433 case HASH_STRING_ALGORITHM_X65599
:
1438 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1440 if (CaseInSensitive
)
1442 for (c
= String
->Buffer
;
1446 /* only uppercase characters if they are 'a' ... 'z'! */
1447 *HashValue
= ((65599 * (*HashValue
)) +
1448 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1449 (*c
) - L
'a' + L
'A' : (*c
)));
1454 for (c
= String
->Buffer
;
1458 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1461 return STATUS_SUCCESS
;
1466 return STATUS_INVALID_PARAMETER
;
1473 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1474 * Does a partial copy if the dest buffer is too small
1478 RtlUnicodeStringToCountedOemString(
1479 IN OUT POEM_STRING OemDest
,
1480 IN PUNICODE_STRING UniSource
,
1481 IN BOOLEAN AllocateDestinationString
)
1484 ULONG Length
; //excluding nullterm
1486 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1487 if (Length
> 0x0000FFFF)
1488 return STATUS_INVALID_PARAMETER_2
;
1490 OemDest
->Length
= (WORD
)(Length
);
1492 if (AllocateDestinationString
)
1494 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1495 if (OemDest
->Buffer
== NULL
)
1496 return STATUS_NO_MEMORY
;
1498 OemDest
->MaximumLength
= Length
;
1500 else if (OemDest
->MaximumLength
== 0)
1502 return STATUS_BUFFER_TOO_SMALL
;
1504 else if (Length
> OemDest
->MaximumLength
)
1506 OemDest
->Length
= OemDest
->MaximumLength
;
1509 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1515 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1517 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1528 RtlLargeIntegerToChar(
1529 IN PLARGE_INTEGER Value
,
1532 IN OUT PCHAR String
)
1536 ULONGLONG v
= Value
->QuadPart
;
1545 if ((Radix
!= 2) && (Radix
!= 8) &&
1546 (Radix
!= 10) && (Radix
!= 16))
1547 return STATUS_INVALID_PARAMETER
;
1550 while (v
|| tp
== temp
)
1561 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1562 return STATUS_BUFFER_TOO_SMALL
;
1569 return STATUS_SUCCESS
;
1576 * dest is never '\0' terminated because it may be equal to src, and src
1577 * might not be '\0' terminated. dest->Length is only set upon success.
1581 RtlUpcaseUnicodeString(
1582 IN OUT PUNICODE_STRING UniDest
,
1583 IN PCUNICODE_STRING UniSource
,
1584 IN BOOLEAN AllocateDestinationString
)
1589 if (AllocateDestinationString
== TRUE
)
1591 UniDest
->MaximumLength
= UniSource
->Length
;
1592 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1593 if (UniDest
->Buffer
== NULL
)
1594 return STATUS_NO_MEMORY
;
1596 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1598 return STATUS_BUFFER_TOO_SMALL
;
1601 UniDest
->Length
= UniSource
->Length
;
1603 Src
= UniSource
->Buffer
;
1604 Dest
= UniDest
->Buffer
;
1605 for (i
= 0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
1607 *Dest
= RtlUpcaseUnicodeChar (*Src
);
1612 return STATUS_SUCCESS
;
1619 * This function always writes a terminating '\0'.
1620 * It performs a partial copy if ansi is too small.
1624 RtlUpcaseUnicodeStringToAnsiString(
1625 IN OUT PANSI_STRING AnsiDest
,
1626 IN PUNICODE_STRING UniSource
,
1627 IN BOOLEAN AllocateDestinationString
)
1630 ULONG Length
; /* including nullterm */
1632 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1633 if (Length
> 0x0000FFFF)
1634 return STATUS_INVALID_PARAMETER_2
;
1636 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1638 if (AllocateDestinationString
)
1640 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1641 if (AnsiDest
->Buffer
== NULL
)
1642 return STATUS_NO_MEMORY
;
1644 AnsiDest
->MaximumLength
= Length
;
1646 else if (AnsiDest
->MaximumLength
== 0)
1648 return STATUS_BUFFER_TOO_SMALL
;
1650 else if (Length
> AnsiDest
->MaximumLength
)
1652 /* make room for nullterm */
1653 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1656 /* FIXME: do we need this??????? -Gunnar */
1657 RtlZeroMemory (AnsiDest
->Buffer
,
1660 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1666 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1668 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1672 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1680 * This function always writes a terminating '\0'.
1681 * It performs a partial copy if ansi is too small.
1685 RtlUpcaseUnicodeStringToCountedOemString(
1686 IN OUT POEM_STRING OemDest
,
1687 IN PCUNICODE_STRING UniSource
,
1688 IN BOOLEAN AllocateDestinationString
)
1691 ULONG Length
; /* excluding nullterm */
1693 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1694 if (Length
> 0x0000FFFF)
1695 return(STATUS_INVALID_PARAMETER_2
);
1697 OemDest
->Length
= (WORD
)(Length
);
1699 if (AllocateDestinationString
)
1701 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1702 if (OemDest
->Buffer
== NULL
)
1703 return(STATUS_NO_MEMORY
);
1705 /* FIXME: Do we need this????? */
1706 RtlZeroMemory (OemDest
->Buffer
, Length
);
1708 OemDest
->MaximumLength
= (WORD
)Length
;
1710 else if (OemDest
->MaximumLength
== 0)
1712 return(STATUS_BUFFER_TOO_SMALL
);
1714 else if (Length
> OemDest
->MaximumLength
)
1716 OemDest
->Length
= OemDest
->MaximumLength
;
1719 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1725 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1727 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1737 * Oem string is allways nullterminated
1738 * It performs a partial copy if oem is too small.
1742 RtlUpcaseUnicodeStringToOemString (
1743 IN OUT POEM_STRING OemDest
,
1744 IN PCUNICODE_STRING UniSource
,
1745 IN BOOLEAN AllocateDestinationString
1749 ULONG Length
; /* including nullterm */
1751 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1752 if (Length
> 0x0000FFFF)
1753 return STATUS_INVALID_PARAMETER_2
;
1755 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1757 if (AllocateDestinationString
)
1759 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1760 if (OemDest
->Buffer
== NULL
)
1761 return STATUS_NO_MEMORY
;
1763 /* FIXME: Do we need this???? */
1764 RtlZeroMemory (OemDest
->Buffer
, Length
);
1766 OemDest
->MaximumLength
= (WORD
)Length
;
1768 else if (OemDest
->MaximumLength
== 0)
1770 return STATUS_BUFFER_OVERFLOW
;
1772 else if (Length
> OemDest
->MaximumLength
)
1774 /* make room for nullterm */
1775 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1778 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
1784 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1786 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1790 OemDest
->Buffer
[OemDest
->Length
] = 0;
1798 * Bytes calculated including nullterm
1802 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1806 /* Convert the Mb String to Unicode Size */
1807 RtlMultiByteToUnicodeSize(&Size
,
1811 /* Return the size + null-char */
1812 return (Size
+ sizeof(WCHAR
));
1822 RtlStringFromGUID (IN REFGUID Guid
,
1823 OUT PUNICODE_STRING GuidString
)
1825 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1832 return STATUS_INVALID_PARAMETER
;
1836 L
"{%08lX-%04X-%04X-%02X%02X-",
1842 BufferPtr
= Buffer
+ 25;
1845 for (i
= 2; i
< 8; i
++)
1847 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1848 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1851 *BufferPtr
++ = L
'}';
1852 *BufferPtr
++ = L
'\0';
1854 return RtlCreateUnicodeString (GuidString
, Buffer
);
1862 * Bytes calculated including nullterm
1866 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1870 /* Convert the Unicode String to Mb Size */
1871 RtlUnicodeToMultiByteSize(&Size
,
1872 UnicodeString
->Buffer
,
1873 UnicodeString
->Length
);
1875 /* Return the size + null-char */
1876 return (Size
+ sizeof(CHAR
));
1885 RtlCompareUnicodeString(
1886 IN PCUNICODE_STRING s1
,
1887 IN PCUNICODE_STRING s2
,
1888 IN BOOLEAN CaseInsensitive
)
1894 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1898 if (CaseInsensitive
)
1900 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1904 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1906 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1918 IN OUT PSTRING DestinationString
,
1919 IN PSTRING SourceString
)
1923 if(SourceString
== NULL
)
1925 DestinationString
->Length
= 0;
1929 copylen
= min (DestinationString
->MaximumLength
,
1930 SourceString
->Length
);
1932 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
1933 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
1935 DestinationString
->Buffer
[copylen
] = 0;
1937 DestinationString
->Length
= copylen
;
1947 RtlCopyUnicodeString(
1948 IN OUT PUNICODE_STRING DestinationString
,
1949 IN PCUNICODE_STRING SourceString
)
1953 if (SourceString
== NULL
)
1955 DestinationString
->Length
= 0;
1959 copylen
= min (DestinationString
->MaximumLength
,
1960 SourceString
->Length
);
1961 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
1962 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
1964 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
1966 DestinationString
->Length
= copylen
;
1973 * Creates a nullterminated UNICODE_STRING
1977 RtlCreateUnicodeString(
1978 IN OUT PUNICODE_STRING UniDest
,
1983 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
1984 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1985 if (UniDest
->Buffer
== NULL
)
1988 RtlCopyMemory (UniDest
->Buffer
,
1992 UniDest
->MaximumLength
= Length
;
1993 UniDest
->Length
= Length
- sizeof (WCHAR
);
2003 RtlCreateUnicodeStringFromAsciiz(
2004 OUT PUNICODE_STRING Destination
,
2007 ANSI_STRING AnsiString
;
2010 RtlInitAnsiString (&AnsiString
,
2013 Status
= RtlAnsiStringToUnicodeString (Destination
,
2017 return NT_SUCCESS(Status
);
2024 * Dest is never '\0' terminated because it may be equal to src, and src
2025 * might not be '\0' terminated.
2026 * Dest->Length is only set upon success.
2029 RtlDowncaseUnicodeString(
2030 IN OUT PUNICODE_STRING UniDest
,
2031 IN PCUNICODE_STRING UniSource
,
2032 IN BOOLEAN AllocateDestinationString
)
2037 if (AllocateDestinationString
)
2039 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2040 if (UniDest
->Buffer
== NULL
)
2041 return STATUS_NO_MEMORY
;
2043 UniDest
->MaximumLength
= UniSource
->Length
;
2045 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2047 return STATUS_BUFFER_TOO_SMALL
;
2050 UniDest
->Length
= UniSource
->Length
;
2052 Src
= UniSource
->Buffer
;
2053 Dest
= UniDest
->Buffer
;
2054 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2060 else if (*Src
<= L
'Z')
2062 *Dest
= (*Src
+ (L
'a' - L
'A'));
2066 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2073 return STATUS_SUCCESS
;
2080 * if src is NULL dest is unchanged.
2081 * dest is '\0' terminated when the MaximumLength allowes it.
2082 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2085 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2090 slen
= wcslen(Source
) * sizeof(WCHAR
);
2092 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2093 return(STATUS_BUFFER_TOO_SMALL
);
2095 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2096 Destination
->Length
+= slen
;
2097 /* append terminating '\0' if enough space */
2098 if( Destination
->MaximumLength
> Destination
->Length
)
2099 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2101 return(STATUS_SUCCESS
);
2108 * This function always writes a terminating '\0'.
2109 * If the dest buffer is too small a partial copy is NOT performed!
2113 RtlAnsiStringToUnicodeString(
2114 IN OUT PUNICODE_STRING UniDest
,
2115 IN PANSI_STRING AnsiSource
,
2116 IN BOOLEAN AllocateDestinationString
)
2119 ULONG Length
; //including nullterm
2121 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2122 if (Length
> 0xffff)
2123 return STATUS_INVALID_PARAMETER_2
;
2125 if (AllocateDestinationString
== TRUE
)
2127 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2128 if (UniDest
->Buffer
== NULL
)
2129 return STATUS_NO_MEMORY
;
2131 UniDest
->MaximumLength
= Length
;
2133 else if (Length
> UniDest
->MaximumLength
)
2135 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2136 return STATUS_BUFFER_TOO_SMALL
;
2139 UniDest
->Length
= Length
- sizeof(WCHAR
);
2141 //FIXME: We don't need this??? -Gunnar
2142 RtlZeroMemory (UniDest
->Buffer
,
2145 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2149 AnsiSource
->Length
);
2151 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2153 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
2157 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2165 * if src is NULL dest is unchanged.
2166 * dest is never '\0' terminated.
2170 RtlAppendAsciizToString(
2171 IN OUT PSTRING Destination
,
2178 return STATUS_SUCCESS
;
2180 Length
= strlen (Source
);
2181 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2182 return STATUS_BUFFER_TOO_SMALL
;
2184 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2191 Destination
->Length
+= Length
;
2193 return STATUS_SUCCESS
;
2201 RtlUpperString(PSTRING DestinationString
,
2202 PSTRING SourceString
)
2209 Length
= min(SourceString
->Length
,
2210 DestinationString
->MaximumLength
- 1);
2212 Src
= SourceString
->Buffer
;
2213 Dest
= DestinationString
->Buffer
;
2214 for (i
= 0; i
< Length
; i
++)
2216 *Dest
= RtlUpperChar(*Src
);
2222 DestinationString
->Length
= SourceString
->Length
;
2229 * See RtlpDuplicateUnicodeString
2233 RtlDuplicateUnicodeString(
2235 IN PCUNICODE_STRING SourceString
,
2236 OUT PUNICODE_STRING DestinationString
)
2238 if (SourceString
== NULL
|| DestinationString
== NULL
)
2239 return STATUS_INVALID_PARAMETER
;
2242 if ((SourceString
->Length
== 0) &&
2243 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2244 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2246 DestinationString
->Length
= 0;
2247 DestinationString
->MaximumLength
= 0;
2248 DestinationString
->Buffer
= NULL
;
2252 UINT DestMaxLength
= SourceString
->Length
;
2254 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2255 DestMaxLength
+= sizeof(UNICODE_NULL
);
2257 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2258 if (DestinationString
->Buffer
== NULL
)
2259 return STATUS_NO_MEMORY
;
2261 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2262 DestinationString
->Length
= SourceString
->Length
;
2263 DestinationString
->MaximumLength
= DestMaxLength
;
2265 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2266 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2269 return STATUS_SUCCESS
;
2276 RtlValidateUnicodeString(IN ULONG Flags
,
2277 IN PUNICODE_STRING UnicodeString
)
2279 /* currently no flags are supported! */
2283 ((UnicodeString
== NULL
) ||
2284 ((UnicodeString
->Length
!= 0) &&
2285 (UnicodeString
->Buffer
!= NULL
) &&
2286 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2287 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2288 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2290 /* a NULL pointer as a unicode string is considered to be a valid unicode
2292 return STATUS_SUCCESS
;
2296 return STATUS_INVALID_PARAMETER
;