2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Unicode Conversion Routines
5 * FILE: lib/rtl/unicode.c
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
11 /* INCLUDES *****************************************************************/
18 /* GLOBALS *******************************************************************/
20 extern BOOLEAN NlsMbCodePageTag
;
21 extern BOOLEAN NlsMbOemCodePageTag
;
22 extern PUSHORT NlsLeadByteInfo
;
24 /* FUNCTIONS *****************************************************************/
31 RtlAnsiCharToUnicodeChar(IN PUCHAR
*AnsiChar
)
35 WCHAR UnicodeChar
= L
' ';
37 Size
= (NlsLeadByteInfo
[**AnsiChar
] == 0) ? 1 : 2;
39 Status
= RtlMultiByteToUnicodeN(&UnicodeChar
,
45 if (!NT_SUCCESS(Status
))
58 * This function always writes a terminating '\0'.
59 * If the dest buffer is too small a partial copy is NOT performed!
63 RtlAnsiStringToUnicodeString(
64 IN OUT PUNICODE_STRING UniDest
,
65 IN PANSI_STRING AnsiSource
,
66 IN BOOLEAN AllocateDestinationString
)
74 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
75 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
76 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
78 if (AllocateDestinationString
== TRUE
)
80 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
81 UniDest
->MaximumLength
= Length
;
82 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
84 else if (Length
>= UniDest
->MaximumLength
)
86 return STATUS_BUFFER_TOO_SMALL
;
89 Status
= RtlMultiByteToUnicodeN(UniDest
->Buffer
,
95 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
97 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
101 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
109 * The calculated size in bytes including nullterm.
113 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString
)
117 /* Convert from Mb String to Unicode Size */
118 RtlMultiByteToUnicodeSize(&Size
,
122 /* Return the size plus the null-char */
123 return(Size
+ sizeof(WCHAR
));
130 * If src->length is zero dest is unchanged.
131 * Dest is never nullterminated.
135 RtlAppendStringToString(IN PSTRING Destination
,
138 USHORT SourceLength
= Source
->Length
;
142 if (Destination
->Length
+ SourceLength
> Destination
->MaximumLength
)
144 return STATUS_BUFFER_TOO_SMALL
;
147 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
],
151 Destination
->Length
+= SourceLength
;
154 return STATUS_SUCCESS
;
161 * If src->length is zero dest is unchanged.
162 * Dest is nullterminated when the MaximumLength allowes it.
163 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
167 RtlAppendUnicodeStringToString(
168 IN OUT PUNICODE_STRING Destination
,
169 IN PCUNICODE_STRING Source
)
171 USHORT SourceLength
= Source
->Length
;
172 PWCHAR Buffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
176 if ((SourceLength
+ Destination
->Length
) > Destination
->MaximumLength
)
178 return STATUS_BUFFER_TOO_SMALL
;
181 RtlMoveMemory(Buffer
, Source
->Buffer
, SourceLength
);
182 Destination
->Length
+= SourceLength
;
184 /* append terminating '\0' if enough space */
185 if (Destination
->MaximumLength
> Destination
->Length
)
187 Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
191 return STATUS_SUCCESS
;
194 /**************************************************************************
195 * RtlCharToInteger (NTDLL.@)
197 * Converts a character string into its integer equivalent.
200 * Success: STATUS_SUCCESS. value contains the converted number
201 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
202 * STATUS_ACCESS_VIOLATION, if value is NULL.
205 * For base 0 it uses 10 as base and the string should be in the format
206 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
207 * For other bases the string should be in the format
208 * "{whitespace} [+|-] {digits}".
209 * No check is made for value overflow, only the lower 32 bits are assigned.
210 * If str is NULL it crashes, as the native function does.
213 * This function does not read garbage behind '\0' as the native version does.
218 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
219 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
220 PULONG value
) /* [O] Destination for the converted value */
224 ULONG RunningTotal
= 0;
227 while (*str
!= '\0' && *str
<= ' ') {
233 } else if (*str
== '-') {
244 } else if (str
[1] == 'o') {
247 } else if (str
[1] == 'x') {
252 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
253 return STATUS_INVALID_PARAMETER
;
257 return STATUS_ACCESS_VIOLATION
;
260 while (*str
!= '\0') {
262 if (chCurrent
>= '0' && chCurrent
<= '9') {
263 digit
= chCurrent
- '0';
264 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
265 digit
= chCurrent
- 'A' + 10;
266 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
267 digit
= chCurrent
- 'a' + 10;
271 if (digit
< 0 || digit
>= (int)base
) {
272 *value
= bMinus
? -RunningTotal
: RunningTotal
;
273 return STATUS_SUCCESS
;
276 RunningTotal
= RunningTotal
* base
+ digit
;
280 *value
= bMinus
? -RunningTotal
: RunningTotal
;
281 return STATUS_SUCCESS
;
292 IN BOOLEAN CaseInsensitive
)
298 len
= min(s1
->Length
, s2
->Length
);
304 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
308 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
310 if (!ret
) ret
= s1
->Length
- s2
->Length
;
318 * TRUE if strings are equal.
325 IN BOOLEAN CaseInsensitive
)
327 if (s1
->Length
!= s2
->Length
) return FALSE
;
328 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
335 * TRUE if strings are equal.
339 RtlEqualUnicodeString(
340 IN CONST UNICODE_STRING
*s1
,
341 IN CONST UNICODE_STRING
*s2
,
342 IN BOOLEAN CaseInsensitive
)
344 if (s1
->Length
!= s2
->Length
) return FALSE
;
345 return !RtlCompareUnicodeString(s1
, s2
, CaseInsensitive
);
353 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
357 if (AnsiString
->Buffer
)
359 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
360 RtlZeroMemory(AnsiString
, sizeof(ANSI_STRING
));
369 RtlFreeOemString(IN POEM_STRING OemString
)
373 if (OemString
->Buffer
) RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
381 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
385 if (UnicodeString
->Buffer
)
387 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_ASTR
);
388 RtlZeroMemory(UnicodeString
, sizeof(UNICODE_STRING
));
397 RtlIsValidOemCharacter(IN PWCHAR Char
)
407 * If source is NULL the length of source is assumed to be 0.
411 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
412 IN PCSZ SourceString
)
418 DestSize
= strlen(SourceString
);
419 DestinationString
->Length
= (USHORT
)DestSize
;
420 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
424 DestinationString
->Length
= 0;
425 DestinationString
->MaximumLength
= 0;
428 DestinationString
->Buffer
= (PCHAR
)SourceString
;
435 * If source is NULL the length of source is assumed to be 0.
440 IN OUT PSTRING DestinationString
,
441 IN PCSZ SourceString
)
443 RtlInitAnsiString(DestinationString
, SourceString
);
450 * If source is NULL the length of source is assumed to be 0.
454 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
455 IN PCWSTR SourceString
)
461 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
462 DestinationString
->Length
= (USHORT
)DestSize
;
463 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
467 DestinationString
->Length
= 0;
468 DestinationString
->MaximumLength
= 0;
471 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
479 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
480 IN PCWSTR SourceString
)
486 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
487 if (DestSize
>= 0xFFFC) return STATUS_NAME_TOO_LONG
;
488 DestinationString
->Length
= (USHORT
)DestSize
;
489 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
493 DestinationString
->Length
= 0;
494 DestinationString
->MaximumLength
= 0;
497 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
498 return STATUS_SUCCESS
;
505 * Writes at most length characters to the string str.
506 * Str is nullterminated when length allowes it.
507 * When str fits exactly in length characters the nullterm is ommitted.
528 if ((Radix
!= 2) && (Radix
!= 8) &&
529 (Radix
!= 10) && (Radix
!= 16))
531 return STATUS_INVALID_PARAMETER
;
535 while (v
|| tp
== temp
)
546 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
548 return STATUS_BUFFER_TOO_SMALL
;
556 return STATUS_SUCCESS
;
566 IN ULONG Base OPTIONAL
,
567 IN ULONG Length OPTIONAL
,
582 if ((Radix
!= 2) && (Radix
!= 8) &&
583 (Radix
!= 10) && (Radix
!= 16))
585 return STATUS_INVALID_PARAMETER
;
589 while (v
|| tp
== temp
)
600 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
602 return STATUS_BUFFER_TOO_SMALL
;
610 return STATUS_SUCCESS
;
618 RtlIntegerToUnicodeString(
620 IN ULONG Base OPTIONAL
,
621 IN OUT PUNICODE_STRING String
)
623 ANSI_STRING AnsiString
;
627 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
628 if (NT_SUCCESS(Status
))
630 AnsiString
.Buffer
= Buffer
;
631 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
632 AnsiString
.MaximumLength
= sizeof(Buffer
);
634 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
645 RtlInt64ToUnicodeString (
647 IN ULONG Base OPTIONAL
,
648 IN OUT PUNICODE_STRING String
)
650 LARGE_INTEGER LargeInt
;
651 ANSI_STRING AnsiString
;
655 LargeInt
.QuadPart
= Value
;
657 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
658 if (NT_SUCCESS(Status
))
660 AnsiString
.Buffer
= Buffer
;
661 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
662 AnsiString
.MaximumLength
= sizeof(Buffer
);
664 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
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
++)
721 * TRUE if String2 contains String1 as a prefix.
725 RtlPrefixUnicodeString(
726 PCUNICODE_STRING String1
,
727 PCUNICODE_STRING String2
,
728 BOOLEAN CaseInsensitive
)
734 if (String2
->Length
< String1
->Length
)
737 Length
= String1
->Length
/ 2;
738 pc1
= String1
->Buffer
;
739 pc2
= String2
->Buffer
;
747 if (RtlUpcaseUnicodeChar (*pc1
++)
748 != RtlUpcaseUnicodeChar (*pc2
++))
756 if( *pc1
++ != *pc2
++ )
765 /**************************************************************************
766 * RtlUnicodeStringToInteger (NTDLL.@)
768 * Converts an unicode string into its integer equivalent.
771 * Success: STATUS_SUCCESS. value contains the converted number
772 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
773 * STATUS_ACCESS_VIOLATION, if value is NULL.
776 * For base 0 it uses 10 as base and the string should be in the format
777 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
778 * For other bases the string should be in the format
779 * "{whitespace} [+|-] {digits}".
780 * No check is made for value overflow, only the lower 32 bits are assigned.
781 * If str is NULL it crashes, as the native function does.
783 * Note that regardless of success or failure status, we should leave the
784 * partial value in Value. An error is never returned based on the chars
788 * This function does not read garbage on string length 0 as the native
793 RtlUnicodeStringToInteger(
794 PCUNICODE_STRING str
, /* [I] Unicode string to be converted */
795 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
796 PULONG value
) /* [O] Destination for the converted value */
798 LPWSTR lpwstr
= str
->Buffer
;
799 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
803 ULONG RunningTotal
= 0;
806 while (CharsRemaining
>= 1 && *lpwstr
<= L
' ') {
811 if (CharsRemaining
>= 1) {
812 if (*lpwstr
== L
'+') {
815 } else if (*lpwstr
== L
'-') {
822 if (CharsRemaining
>= 2 && lpwstr
[0] == L
'0') {
823 if (lpwstr
[1] == L
'b' || lpwstr
[1] == L
'B') {
827 } else if (lpwstr
[1] == L
'o' || lpwstr
[1] == L
'O') {
831 } else if (lpwstr
[1] == L
'x' || lpwstr
[1] == L
'X') {
837 if (base
== 0 && newbase
== 0) {
839 } else if (base
== 0 && newbase
!= 0) {
841 } else if ((newbase
!= 0 && base
!= newbase
) ||
842 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
843 return STATUS_INVALID_PARAMETER
;
848 return STATUS_ACCESS_VIOLATION
;
851 while (CharsRemaining
>= 1) {
852 wchCurrent
= *lpwstr
;
853 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
854 digit
= wchCurrent
- L
'0';
855 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
856 digit
= wchCurrent
- L
'A' + 10;
857 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
858 digit
= wchCurrent
- L
'a' + 10;
862 if (digit
< 0 || digit
>= (int)base
) {
863 *value
= bMinus
? -RunningTotal
: RunningTotal
;
864 return STATUS_SUCCESS
;
867 RunningTotal
= RunningTotal
* base
+ digit
;
872 *value
= bMinus
? -RunningTotal
: RunningTotal
;
873 return STATUS_SUCCESS
;
880 * Bytes necessary for the conversion including nullterm.
884 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
888 /* Convert the Unicode String to Mb Size */
889 RtlUnicodeToMultiByteSize(&Size
,
890 UnicodeString
->Buffer
,
891 UnicodeString
->Length
);
893 /* Return the size + the null char */
894 return (Size
+ sizeof(CHAR
));
901 * This function always writes a terminating '\0'.
902 * It performs a partial copy if ansi is too small.
906 RtlUnicodeStringToAnsiString(
907 IN OUT PANSI_STRING AnsiDest
,
908 IN PCUNICODE_STRING UniSource
,
909 IN BOOLEAN AllocateDestinationString
)
911 NTSTATUS Status
= STATUS_SUCCESS
;
918 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
919 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
921 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
923 if (AllocateDestinationString
)
925 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
926 AnsiDest
->MaximumLength
= Length
;
927 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
929 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
931 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
933 Status
= STATUS_BUFFER_OVERFLOW
;
934 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
937 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
943 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
945 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
949 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
957 * This function always writes a terminating '\0'.
958 * Does NOT perform a partial copy if unicode is too small!
962 RtlOemStringToUnicodeString(
963 IN OUT PUNICODE_STRING UniDest
,
964 IN PCOEM_STRING OemSource
,
965 IN BOOLEAN AllocateDestinationString
)
973 Length
= RtlOemStringToUnicodeSize(OemSource
);
974 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
976 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
978 if (AllocateDestinationString
)
980 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
981 UniDest
->MaximumLength
= Length
;
982 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
984 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
986 return STATUS_BUFFER_OVERFLOW
;
989 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
995 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
997 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
998 UniDest
->Buffer
= NULL
;
1002 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1010 * This function always '\0' terminates the string returned.
1014 RtlUnicodeStringToOemString(
1015 IN OUT POEM_STRING OemDest
,
1016 IN PCUNICODE_STRING UniSource
,
1017 IN BOOLEAN AllocateDestinationString
)
1025 Length
= RtlUnicodeStringToOemSize(UniSource
);
1026 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1028 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1030 if (AllocateDestinationString
)
1032 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1033 OemDest
->MaximumLength
= Length
;
1034 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1036 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1038 return STATUS_BUFFER_OVERFLOW
;
1041 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1047 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1049 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1050 OemDest
->Buffer
= NULL
;
1054 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1058 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1064 * The length of the string if all tests were passed, 0 otherwise.
1067 RtlIsTextUnicode (PVOID Buffer
,
1072 ULONG in_flags
= (ULONG
)-1;
1073 ULONG out_flags
= 0;
1082 * Apply various tests to the text string. According to the
1083 * docs, each test "passed" sets the corresponding flag in
1084 * the output flags. But some of the tests are mutually
1085 * exclusive, so I don't see how you could pass all tests ...
1088 /* Check for an odd length ... pass if even. */
1090 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1092 /* Check for the BOM (byte order mark). */
1094 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1097 /* Check for the reverse BOM (byte order mark). */
1099 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1102 /* FIXME: Add more tests */
1105 * Check whether the string passed all of the tests.
1107 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1108 if ((out_flags
& in_flags
) != in_flags
)
1122 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1123 * A partial copy is NOT performed if the dest buffer is too small!
1127 RtlOemStringToCountedUnicodeString(
1128 IN OUT PUNICODE_STRING UniDest
,
1129 IN PCOEM_STRING OemSource
,
1130 IN BOOLEAN AllocateDestinationString
)
1138 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1142 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1143 return STATUS_SUCCESS
;
1146 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1148 UniDest
->Length
= (USHORT
)Length
;
1150 if (AllocateDestinationString
)
1152 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1153 UniDest
->MaximumLength
= Length
;
1154 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1156 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1158 return STATUS_BUFFER_OVERFLOW
;
1161 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1167 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1169 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1170 UniDest
->Buffer
= NULL
;
1174 return STATUS_SUCCESS
;
1181 * TRUE if the names are equal, FALSE if not
1184 * The comparison is case insensitive.
1188 RtlEqualComputerName(
1189 IN PUNICODE_STRING ComputerName1
,
1190 IN PUNICODE_STRING ComputerName2
)
1192 OEM_STRING OemString1
;
1193 OEM_STRING OemString2
;
1194 BOOLEAN Result
= FALSE
;
1196 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1200 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1204 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
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
);
1235 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1237 * Convert a string representation of a GUID into a GUID.
1240 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1241 * guid [O] Destination for the converted GUID
1244 * Success: STATUS_SUCCESS. guid contains the converted value.
1245 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1248 * See RtlStringFromGUID.
1253 IN UNICODE_STRING
*str
,
1258 const WCHAR
*lpszCLSID
= str
->Buffer
;
1259 BYTE
* lpOut
= (BYTE
*)guid
;
1261 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1263 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1264 * to memory: DWORD... WORD WORD BYTES............
1271 if (*lpszCLSID
!= '{')
1272 return STATUS_INVALID_PARAMETER
;
1279 if (*lpszCLSID
!= '-')
1280 return STATUS_INVALID_PARAMETER
;
1284 if (*lpszCLSID
!= '}')
1285 return STATUS_INVALID_PARAMETER
;
1290 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1293 /* Read two hex digits as a byte value */
1294 if (ch
>= '0' && ch
<= '9')
1296 else if (ch
>= 'a' && ch
<= 'f')
1298 else if (ch
>= 'A' && ch
<= 'F')
1301 return STATUS_INVALID_PARAMETER
;
1303 if (ch2
>= '0' && ch2
<= '9')
1305 else if (ch2
>= 'a' && ch2
<= 'f')
1306 ch2
= ch2
- 'a' + 10;
1307 else if (ch2
>= 'A' && ch2
<= 'F')
1308 ch2
= ch2
- 'A' + 10;
1310 return STATUS_INVALID_PARAMETER
;
1312 byte
= ch
<< 4 | ch2
;
1316 #ifndef WORDS_BIGENDIAN
1317 /* For Big Endian machines, we store the data such that the
1318 * dword/word members can be read as DWORDS and WORDS correctly. */
1350 lpszCLSID
++; /* Skip 2nd character of byte */
1358 return STATUS_SUCCESS
;
1366 RtlEraseUnicodeString(
1367 IN PUNICODE_STRING String
)
1369 if (String
->Buffer
&& String
->MaximumLength
)
1371 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1381 RtlHashUnicodeString(
1382 IN CONST UNICODE_STRING
*String
,
1383 IN BOOLEAN CaseInSensitive
,
1384 IN ULONG HashAlgorithm
,
1385 OUT PULONG HashValue
)
1387 if (String
!= NULL
&& HashValue
!= NULL
)
1389 switch (HashAlgorithm
)
1391 case HASH_STRING_ALGORITHM_DEFAULT
:
1392 case HASH_STRING_ALGORITHM_X65599
:
1397 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1399 if (CaseInSensitive
)
1401 for (c
= String
->Buffer
;
1405 /* only uppercase characters if they are 'a' ... 'z'! */
1406 *HashValue
= ((65599 * (*HashValue
)) +
1407 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1408 (*c
) - L
'a' + L
'A' : (*c
)));
1413 for (c
= String
->Buffer
;
1417 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1420 return STATUS_SUCCESS
;
1425 return STATUS_INVALID_PARAMETER
;
1432 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1433 * Does a partial copy if the dest buffer is too small
1437 RtlUnicodeStringToCountedOemString(
1438 IN OUT POEM_STRING OemDest
,
1439 IN PUNICODE_STRING UniSource
,
1440 IN BOOLEAN AllocateDestinationString
)
1448 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1452 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1455 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1457 OemDest
->Length
= (USHORT
)Length
;
1459 if (AllocateDestinationString
)
1461 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1462 OemDest
->MaximumLength
= Length
;
1463 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1465 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1467 return STATUS_BUFFER_OVERFLOW
;
1470 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1476 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1478 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1480 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1481 OemDest
->Buffer
= NULL
;
1493 RtlLargeIntegerToChar(
1494 IN PLARGE_INTEGER Value
,
1497 IN OUT PCHAR String
)
1501 ULONGLONG v
= Value
->QuadPart
;
1510 if ((Radix
!= 2) && (Radix
!= 8) &&
1511 (Radix
!= 10) && (Radix
!= 16))
1512 return STATUS_INVALID_PARAMETER
;
1515 while (v
|| tp
== temp
)
1526 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1527 return STATUS_BUFFER_TOO_SMALL
;
1534 return STATUS_SUCCESS
;
1541 * dest is never '\0' terminated because it may be equal to src, and src
1542 * might not be '\0' terminated. dest->Length is only set upon success.
1546 RtlUpcaseUnicodeString(
1547 IN OUT PUNICODE_STRING UniDest
,
1548 IN PCUNICODE_STRING UniSource
,
1549 IN BOOLEAN AllocateDestinationString
)
1555 if (AllocateDestinationString
== TRUE
)
1557 UniDest
->MaximumLength
= UniSource
->Length
;
1558 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1559 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1561 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1563 return STATUS_BUFFER_OVERFLOW
;
1566 j
= UniSource
->Length
/ sizeof(WCHAR
);
1568 for (i
= 0; i
< j
; i
++)
1570 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1573 UniDest
->Length
= UniSource
->Length
;
1574 return STATUS_SUCCESS
;
1581 * This function always writes a terminating '\0'.
1582 * It performs a partial copy if ansi is too small.
1586 RtlUpcaseUnicodeStringToAnsiString(
1587 IN OUT PANSI_STRING AnsiDest
,
1588 IN PUNICODE_STRING UniSource
,
1589 IN BOOLEAN AllocateDestinationString
)
1597 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1598 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1600 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1602 if (AllocateDestinationString
)
1604 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1605 AnsiDest
->MaximumLength
= Length
;
1606 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1608 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1610 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1613 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1619 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1621 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1622 AnsiDest
->Buffer
= NULL
;
1626 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1634 * This function always writes a terminating '\0'.
1635 * It performs a partial copy if ansi is too small.
1639 RtlUpcaseUnicodeStringToCountedOemString(
1640 IN OUT POEM_STRING OemDest
,
1641 IN PCUNICODE_STRING UniSource
,
1642 IN BOOLEAN AllocateDestinationString
)
1650 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1654 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1657 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1659 OemDest
->Length
= (USHORT
)Length
;
1661 if (AllocateDestinationString
)
1663 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1664 OemDest
->MaximumLength
= Length
;
1665 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1667 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1669 return STATUS_BUFFER_OVERFLOW
;
1672 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1678 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1680 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1682 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1683 OemDest
->Buffer
= NULL
;
1693 * Oem string is allways nullterminated
1694 * It performs a partial copy if oem is too small.
1698 RtlUpcaseUnicodeStringToOemString (
1699 IN OUT POEM_STRING OemDest
,
1700 IN PCUNICODE_STRING UniSource
,
1701 IN BOOLEAN AllocateDestinationString
)
1709 Length
= RtlUnicodeStringToOemSize(UniSource
);
1710 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1712 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1714 if (AllocateDestinationString
)
1716 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1717 OemDest
->MaximumLength
= Length
;
1718 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1720 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1722 return STATUS_BUFFER_OVERFLOW
;
1725 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1731 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1733 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1735 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1736 OemDest
->Buffer
= NULL
;
1740 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1748 * Bytes calculated including nullterm
1752 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1756 /* Convert the Mb String to Unicode Size */
1757 RtlMultiByteToUnicodeSize(&Size
,
1761 /* Return the size + null-char */
1762 return (Size
+ sizeof(WCHAR
));
1770 RtlStringFromGUID (IN REFGUID Guid
,
1771 OUT PUNICODE_STRING GuidString
)
1773 static CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1780 return STATUS_INVALID_PARAMETER
;
1784 L
"{%08lX-%04X-%04X-%02X%02X-",
1790 BufferPtr
= Buffer
+ 25;
1793 for (i
= 2; i
< 8; i
++)
1795 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1796 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1799 *BufferPtr
++ = L
'}';
1800 *BufferPtr
++ = L
'\0';
1802 return RtlCreateUnicodeString (GuidString
, Buffer
);
1809 * Bytes calculated including nullterm
1813 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1817 /* Convert the Unicode String to Mb Size */
1818 RtlUnicodeToMultiByteSize(&Size
,
1819 UnicodeString
->Buffer
,
1820 UnicodeString
->Length
);
1822 /* Return the size + null-char */
1823 return (Size
+ sizeof(CHAR
));
1831 RtlCompareUnicodeString(
1832 IN PCUNICODE_STRING s1
,
1833 IN PCUNICODE_STRING s2
,
1834 IN BOOLEAN CaseInsensitive
)
1840 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1844 if (CaseInsensitive
)
1846 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1850 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1852 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1862 IN OUT PSTRING DestinationString
,
1863 IN PSTRING SourceString OPTIONAL
)
1868 /* Check if there was no source given */
1871 /* Simply return an empty string */
1872 DestinationString
->Length
= 0;
1876 /* Choose the smallest length */
1877 SourceLength
= min(DestinationString
->MaximumLength
,
1878 SourceString
->Length
);
1881 DestinationString
->Length
= (USHORT
)SourceLength
;
1883 /* Save the pointers to each buffer */
1884 p1
= DestinationString
->Buffer
;
1885 p2
= SourceString
->Buffer
;
1887 /* Loop the buffer */
1888 while (SourceLength
)
1890 /* Copy the character and move on */
1902 RtlCopyUnicodeString(
1903 IN OUT PUNICODE_STRING DestinationString
,
1904 IN PCUNICODE_STRING SourceString
)
1908 if(SourceString
== NULL
)
1910 DestinationString
->Length
= 0;
1914 SourceLength
= min(DestinationString
->MaximumLength
,
1915 SourceString
->Length
);
1916 DestinationString
->Length
= (USHORT
)SourceLength
;
1918 RtlCopyMemory(DestinationString
->Buffer
,
1919 SourceString
->Buffer
,
1922 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
1924 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1933 * Creates a nullterminated UNICODE_STRING
1937 RtlCreateUnicodeString(
1938 IN OUT PUNICODE_STRING UniDest
,
1945 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
1946 if (Length
> 0xFFFE) return FALSE
;
1948 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1950 if (UniDest
->Buffer
== NULL
) return FALSE
;
1952 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
1953 UniDest
->MaximumLength
= (USHORT
)Length
;
1954 UniDest
->Length
= Length
- sizeof (WCHAR
);
1964 RtlCreateUnicodeStringFromAsciiz(
1965 OUT PUNICODE_STRING Destination
,
1968 ANSI_STRING AnsiString
;
1971 RtlInitAnsiString(&AnsiString
, Source
);
1973 Status
= RtlAnsiStringToUnicodeString(Destination
,
1977 return NT_SUCCESS(Status
);
1984 * Dest is never '\0' terminated because it may be equal to src, and src
1985 * might not be '\0' terminated.
1986 * Dest->Length is only set upon success.
1990 RtlDowncaseUnicodeString(
1991 IN OUT PUNICODE_STRING UniDest
,
1992 IN PCUNICODE_STRING UniSource
,
1993 IN BOOLEAN AllocateDestinationString
)
2000 if (AllocateDestinationString
)
2002 UniDest
->MaximumLength
= UniSource
->Length
;
2003 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2004 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2006 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2008 return STATUS_BUFFER_OVERFLOW
;
2011 UniDest
->Length
= UniSource
->Length
;
2012 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2014 for (i
= 0 ; i
< StopGap
; i
++)
2016 if (UniSource
->Buffer
[i
] < L
'A')
2018 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2020 else if (UniSource
->Buffer
[i
] <= L
'Z')
2022 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2026 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2030 return STATUS_SUCCESS
;
2037 * if src is NULL dest is unchanged.
2038 * dest is '\0' terminated when the MaximumLength allowes it.
2039 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2043 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2051 UNICODE_STRING UnicodeSource
;
2053 RtlInitUnicodeString(&UnicodeSource
, Source
);
2054 Length
= UnicodeSource
.Length
;
2056 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2058 return STATUS_BUFFER_TOO_SMALL
;
2061 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2062 RtlMoveMemory(DestBuffer
, Source
, Length
);
2063 Destination
->Length
+= Length
;
2065 /* append terminating '\0' if enough space */
2066 if(Destination
->MaximumLength
> Destination
->Length
)
2068 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2072 return STATUS_SUCCESS
;
2079 * if src is NULL dest is unchanged.
2080 * dest is never '\0' terminated.
2084 RtlAppendAsciizToString(
2085 IN OUT PSTRING Destination
,
2092 Length
= (USHORT
)strlen(Source
);
2094 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2096 return STATUS_BUFFER_TOO_SMALL
;
2099 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2100 Destination
->Length
+= Length
;
2103 return STATUS_SUCCESS
;
2111 RtlUpperString(PSTRING DestinationString
,
2112 PSTRING SourceString
)
2117 Length
= min(SourceString
->Length
,
2118 DestinationString
->MaximumLength
- 1);
2120 Src
= SourceString
->Buffer
;
2121 Dest
= DestinationString
->Buffer
;
2122 DestinationString
->Length
= Length
;
2125 *Dest
++ = RtlUpperChar(*Src
++);
2134 * See RtlpDuplicateUnicodeString
2138 RtlDuplicateUnicodeString(
2140 IN PCUNICODE_STRING SourceString
,
2141 OUT PUNICODE_STRING DestinationString
)
2145 if (SourceString
== NULL
|| DestinationString
== NULL
)
2146 return STATUS_INVALID_PARAMETER
;
2149 if ((SourceString
->Length
== 0) &&
2150 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2151 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2153 DestinationString
->Length
= 0;
2154 DestinationString
->MaximumLength
= 0;
2155 DestinationString
->Buffer
= NULL
;
2159 UINT DestMaxLength
= SourceString
->Length
;
2161 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2162 DestMaxLength
+= sizeof(UNICODE_NULL
);
2164 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2165 if (DestinationString
->Buffer
== NULL
)
2166 return STATUS_NO_MEMORY
;
2168 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2169 DestinationString
->Length
= SourceString
->Length
;
2170 DestinationString
->MaximumLength
= DestMaxLength
;
2172 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2173 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2176 return STATUS_SUCCESS
;
2183 RtlValidateUnicodeString(IN ULONG Flags
,
2184 IN PUNICODE_STRING UnicodeString
)
2186 /* currently no flags are supported! */
2190 ((UnicodeString
== NULL
) ||
2191 ((UnicodeString
->Length
!= 0) &&
2192 (UnicodeString
->Buffer
!= NULL
) &&
2193 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2194 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2195 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2197 /* a NULL pointer as a unicode string is considered to be a valid unicode
2199 return STATUS_SUCCESS
;
2203 return STATUS_INVALID_PARAMETER
;