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
)
80 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
81 UniDest
->MaximumLength
= Length
;
82 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
84 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
86 return STATUS_BUFFER_OVERFLOW
;
89 Status
= RtlMultiByteToUnicodeN(UniDest
->Buffer
,
95 if (!NT_SUCCESS(Status
))
97 if (AllocateDestinationString
)
99 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
100 UniDest
->Buffer
= NULL
;
105 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
113 * The calculated size in bytes including nullterm.
117 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString
)
121 /* Convert from Mb String to Unicode Size */
122 RtlMultiByteToUnicodeSize(&Size
,
126 /* Return the size plus the null-char */
127 return(Size
+ sizeof(WCHAR
));
134 * If src->length is zero dest is unchanged.
135 * Dest is never nullterminated.
139 RtlAppendStringToString(IN PSTRING Destination
,
142 USHORT SourceLength
= Source
->Length
;
146 if (Destination
->Length
+ SourceLength
> Destination
->MaximumLength
)
148 return STATUS_BUFFER_TOO_SMALL
;
151 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
],
155 Destination
->Length
+= SourceLength
;
158 return STATUS_SUCCESS
;
165 * If src->length is zero dest is unchanged.
166 * Dest is nullterminated when the MaximumLength allowes it.
167 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
171 RtlAppendUnicodeStringToString(
172 IN OUT PUNICODE_STRING Destination
,
173 IN PCUNICODE_STRING Source
)
175 USHORT SourceLength
= Source
->Length
;
176 PWCHAR Buffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
180 if ((SourceLength
+ Destination
->Length
) > Destination
->MaximumLength
)
182 return STATUS_BUFFER_TOO_SMALL
;
185 RtlMoveMemory(Buffer
, Source
->Buffer
, SourceLength
);
186 Destination
->Length
+= SourceLength
;
188 /* append terminating '\0' if enough space */
189 if (Destination
->MaximumLength
> Destination
->Length
)
191 Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
195 return STATUS_SUCCESS
;
198 /**************************************************************************
199 * RtlCharToInteger (NTDLL.@)
201 * Converts a character string into its integer equivalent.
204 * Success: STATUS_SUCCESS. value contains the converted number
205 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
206 * STATUS_ACCESS_VIOLATION, if value is NULL.
209 * For base 0 it uses 10 as base and the string should be in the format
210 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
211 * For other bases the string should be in the format
212 * "{whitespace} [+|-] {digits}".
213 * No check is made for value overflow, only the lower 32 bits are assigned.
214 * If str is NULL it crashes, as the native function does.
217 * This function does not read garbage behind '\0' as the native version does.
222 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
223 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
224 PULONG value
) /* [O] Destination for the converted value */
228 ULONG RunningTotal
= 0;
231 while (*str
!= '\0' && *str
<= ' ') {
237 } else if (*str
== '-') {
248 } else if (str
[1] == 'o') {
251 } else if (str
[1] == 'x') {
256 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
257 return STATUS_INVALID_PARAMETER
;
261 return STATUS_ACCESS_VIOLATION
;
264 while (*str
!= '\0') {
266 if (chCurrent
>= '0' && chCurrent
<= '9') {
267 digit
= chCurrent
- '0';
268 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
269 digit
= chCurrent
- 'A' + 10;
270 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
271 digit
= chCurrent
- 'a' + 10;
275 if (digit
< 0 || digit
>= (int)base
) {
276 *value
= bMinus
? -RunningTotal
: RunningTotal
;
277 return STATUS_SUCCESS
;
280 RunningTotal
= RunningTotal
* base
+ digit
;
284 *value
= bMinus
? -RunningTotal
: RunningTotal
;
285 return STATUS_SUCCESS
;
296 IN BOOLEAN CaseInsensitive
)
302 len
= min(s1
->Length
, s2
->Length
);
308 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
312 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
314 if (!ret
) ret
= s1
->Length
- s2
->Length
;
322 * TRUE if strings are equal.
329 IN BOOLEAN CaseInsensitive
)
331 if (s1
->Length
!= s2
->Length
) return FALSE
;
332 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
339 * TRUE if strings are equal.
343 RtlEqualUnicodeString(
344 IN CONST UNICODE_STRING
*s1
,
345 IN CONST UNICODE_STRING
*s2
,
346 IN BOOLEAN CaseInsensitive
)
348 if (s1
->Length
!= s2
->Length
) return FALSE
;
349 return !RtlCompareUnicodeString(s1
, s2
, CaseInsensitive
);
357 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
361 if (AnsiString
->Buffer
)
363 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
364 RtlZeroMemory(AnsiString
, sizeof(ANSI_STRING
));
373 RtlFreeOemString(IN POEM_STRING OemString
)
377 if (OemString
->Buffer
) RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
385 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
389 if (UnicodeString
->Buffer
)
391 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_ASTR
);
392 RtlZeroMemory(UnicodeString
, sizeof(UNICODE_STRING
));
401 RtlIsValidOemCharacter(IN PWCHAR Char
)
411 * If source is NULL the length of source is assumed to be 0.
415 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
416 IN PCSZ SourceString
)
422 DestSize
= strlen(SourceString
);
423 DestinationString
->Length
= (USHORT
)DestSize
;
424 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
428 DestinationString
->Length
= 0;
429 DestinationString
->MaximumLength
= 0;
432 DestinationString
->Buffer
= (PCHAR
)SourceString
;
439 * If source is NULL the length of source is assumed to be 0.
444 IN OUT PSTRING DestinationString
,
445 IN PCSZ SourceString
)
447 RtlInitAnsiString(DestinationString
, SourceString
);
454 * If source is NULL the length of source is assumed to be 0.
458 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
459 IN PCWSTR SourceString
)
465 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
466 DestinationString
->Length
= (USHORT
)DestSize
;
467 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
471 DestinationString
->Length
= 0;
472 DestinationString
->MaximumLength
= 0;
475 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
483 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
484 IN PCWSTR SourceString
)
490 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
491 if (DestSize
>= 0xFFFC) return STATUS_NAME_TOO_LONG
;
492 DestinationString
->Length
= (USHORT
)DestSize
;
493 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
497 DestinationString
->Length
= 0;
498 DestinationString
->MaximumLength
= 0;
501 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
502 return STATUS_SUCCESS
;
509 * Writes at most length characters to the string str.
510 * Str is nullterminated when length allowes it.
511 * When str fits exactly in length characters the nullterm is ommitted.
532 if ((Radix
!= 2) && (Radix
!= 8) &&
533 (Radix
!= 10) && (Radix
!= 16))
535 return STATUS_INVALID_PARAMETER
;
539 while (v
|| tp
== temp
)
550 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
552 return STATUS_BUFFER_TOO_SMALL
;
560 return STATUS_SUCCESS
;
570 IN ULONG Base OPTIONAL
,
571 IN ULONG Length OPTIONAL
,
586 if ((Radix
!= 2) && (Radix
!= 8) &&
587 (Radix
!= 10) && (Radix
!= 16))
589 return STATUS_INVALID_PARAMETER
;
593 while (v
|| tp
== temp
)
604 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
606 return STATUS_BUFFER_TOO_SMALL
;
614 return STATUS_SUCCESS
;
622 RtlIntegerToUnicodeString(
624 IN ULONG Base OPTIONAL
,
625 IN OUT PUNICODE_STRING String
)
627 ANSI_STRING AnsiString
;
631 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
632 if (NT_SUCCESS(Status
))
634 AnsiString
.Buffer
= Buffer
;
635 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
636 AnsiString
.MaximumLength
= sizeof(Buffer
);
638 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
649 RtlInt64ToUnicodeString (
651 IN ULONG Base OPTIONAL
,
652 IN OUT PUNICODE_STRING String
)
654 LARGE_INTEGER LargeInt
;
655 ANSI_STRING AnsiString
;
659 LargeInt
.QuadPart
= Value
;
661 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
662 if (NT_SUCCESS(Status
))
664 AnsiString
.Buffer
= Buffer
;
665 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
666 AnsiString
.MaximumLength
= sizeof(Buffer
);
668 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
678 * TRUE if String2 contains String1 as a prefix.
683 PANSI_STRING String1
,
684 PANSI_STRING String2
,
685 BOOLEAN CaseInsensitive
)
691 if (String2
->Length
< String1
->Length
)
694 Length
= String1
->Length
;
695 pc1
= String1
->Buffer
;
696 pc2
= String2
->Buffer
;
704 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
712 if (*pc1
++ != *pc2
++)
725 * TRUE if String2 contains String1 as a prefix.
729 RtlPrefixUnicodeString(
730 PCUNICODE_STRING String1
,
731 PCUNICODE_STRING String2
,
732 BOOLEAN CaseInsensitive
)
738 if (String2
->Length
< String1
->Length
)
741 Length
= String1
->Length
/ 2;
742 pc1
= String1
->Buffer
;
743 pc2
= String2
->Buffer
;
751 if (RtlUpcaseUnicodeChar (*pc1
++)
752 != RtlUpcaseUnicodeChar (*pc2
++))
760 if( *pc1
++ != *pc2
++ )
769 /**************************************************************************
770 * RtlUnicodeStringToInteger (NTDLL.@)
772 * Converts an unicode string into its integer equivalent.
775 * Success: STATUS_SUCCESS. value contains the converted number
776 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
777 * STATUS_ACCESS_VIOLATION, if value is NULL.
780 * For base 0 it uses 10 as base and the string should be in the format
781 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
782 * For other bases the string should be in the format
783 * "{whitespace} [+|-] {digits}".
784 * No check is made for value overflow, only the lower 32 bits are assigned.
785 * If str is NULL it crashes, as the native function does.
787 * Note that regardless of success or failure status, we should leave the
788 * partial value in Value. An error is never returned based on the chars
792 * This function does not read garbage on string length 0 as the native
797 RtlUnicodeStringToInteger(
798 PCUNICODE_STRING str
, /* [I] Unicode string to be converted */
799 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
800 PULONG value
) /* [O] Destination for the converted value */
802 LPWSTR lpwstr
= str
->Buffer
;
803 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
807 ULONG RunningTotal
= 0;
810 while (CharsRemaining
>= 1 && *lpwstr
<= L
' ') {
815 if (CharsRemaining
>= 1) {
816 if (*lpwstr
== L
'+') {
819 } else if (*lpwstr
== L
'-') {
826 if (CharsRemaining
>= 2 && lpwstr
[0] == L
'0') {
827 if (lpwstr
[1] == L
'b' || lpwstr
[1] == L
'B') {
831 } else if (lpwstr
[1] == L
'o' || lpwstr
[1] == L
'O') {
835 } else if (lpwstr
[1] == L
'x' || lpwstr
[1] == L
'X') {
841 if (base
== 0 && newbase
== 0) {
843 } else if (base
== 0 && newbase
!= 0) {
845 } else if ((newbase
!= 0 && base
!= newbase
) ||
846 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
847 return STATUS_INVALID_PARAMETER
;
852 return STATUS_ACCESS_VIOLATION
;
855 while (CharsRemaining
>= 1) {
856 wchCurrent
= *lpwstr
;
857 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
858 digit
= wchCurrent
- L
'0';
859 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
860 digit
= wchCurrent
- L
'A' + 10;
861 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
862 digit
= wchCurrent
- L
'a' + 10;
866 if (digit
< 0 || digit
>= (int)base
) {
867 *value
= bMinus
? -RunningTotal
: RunningTotal
;
868 return STATUS_SUCCESS
;
871 RunningTotal
= RunningTotal
* base
+ digit
;
876 *value
= bMinus
? -RunningTotal
: RunningTotal
;
877 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
));
905 * This function always writes a terminating '\0'.
906 * It performs a partial copy if ansi is too small.
910 RtlUnicodeStringToAnsiString(
911 IN OUT PANSI_STRING AnsiDest
,
912 IN PCUNICODE_STRING UniSource
,
913 IN BOOLEAN AllocateDestinationString
)
915 NTSTATUS Status
= STATUS_SUCCESS
;
922 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
923 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
925 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
927 if (AllocateDestinationString
)
929 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
930 AnsiDest
->MaximumLength
= Length
;
931 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
933 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
935 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
937 Status
= STATUS_BUFFER_OVERFLOW
;
938 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
941 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
947 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
949 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
953 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
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
)
977 Length
= RtlOemStringToUnicodeSize(OemSource
);
978 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
980 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
982 if (AllocateDestinationString
)
984 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
985 UniDest
->MaximumLength
= Length
;
986 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
988 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
990 return STATUS_BUFFER_OVERFLOW
;
993 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
999 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1001 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1002 UniDest
->Buffer
= NULL
;
1006 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1014 * This function always '\0' terminates the string returned.
1018 RtlUnicodeStringToOemString(
1019 IN OUT POEM_STRING OemDest
,
1020 IN PCUNICODE_STRING UniSource
,
1021 IN BOOLEAN AllocateDestinationString
)
1029 Length
= RtlUnicodeStringToOemSize(UniSource
);
1030 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1032 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1034 if (AllocateDestinationString
)
1036 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1037 OemDest
->MaximumLength
= Length
;
1038 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1040 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1042 return STATUS_BUFFER_OVERFLOW
;
1045 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1051 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1053 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1054 OemDest
->Buffer
= NULL
;
1058 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1062 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1068 * The length of the string if all tests were passed, 0 otherwise.
1071 RtlIsTextUnicode (PVOID Buffer
,
1076 ULONG in_flags
= (ULONG
)-1;
1077 ULONG out_flags
= 0;
1086 * Apply various tests to the text string. According to the
1087 * docs, each test "passed" sets the corresponding flag in
1088 * the output flags. But some of the tests are mutually
1089 * exclusive, so I don't see how you could pass all tests ...
1092 /* Check for an odd length ... pass if even. */
1094 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1096 /* Check for the BOM (byte order mark). */
1098 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1101 /* Check for the reverse BOM (byte order mark). */
1103 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1106 /* FIXME: Add more tests */
1109 * Check whether the string passed all of the tests.
1111 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1112 if ((out_flags
& in_flags
) != in_flags
)
1126 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1127 * A partial copy is NOT performed if the dest buffer is too small!
1131 RtlOemStringToCountedUnicodeString(
1132 IN OUT PUNICODE_STRING UniDest
,
1133 IN PCOEM_STRING OemSource
,
1134 IN BOOLEAN AllocateDestinationString
)
1142 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1146 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1147 return STATUS_SUCCESS
;
1150 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1152 UniDest
->Length
= (USHORT
)Length
;
1154 if (AllocateDestinationString
)
1156 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1157 UniDest
->MaximumLength
= Length
;
1158 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1160 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1162 return STATUS_BUFFER_OVERFLOW
;
1165 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1171 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1173 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1174 UniDest
->Buffer
= NULL
;
1178 return STATUS_SUCCESS
;
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
,
1204 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1208 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1209 RtlFreeOemString(&OemString2
);
1211 RtlFreeOemString(&OemString1
);
1221 * TRUE if the names are equal, FALSE if not
1224 * The comparison is case insensitive.
1228 RtlEqualDomainName (
1229 IN PUNICODE_STRING DomainName1
,
1230 IN PUNICODE_STRING DomainName2
1233 return RtlEqualComputerName(DomainName1
, DomainName2
);
1239 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1241 * Convert a string representation of a GUID into a GUID.
1244 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1245 * guid [O] Destination for the converted GUID
1248 * Success: STATUS_SUCCESS. guid contains the converted value.
1249 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1252 * See RtlStringFromGUID.
1257 IN UNICODE_STRING
*str
,
1262 const WCHAR
*lpszCLSID
= str
->Buffer
;
1263 BYTE
* lpOut
= (BYTE
*)guid
;
1265 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1267 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1268 * to memory: DWORD... WORD WORD BYTES............
1275 if (*lpszCLSID
!= '{')
1276 return STATUS_INVALID_PARAMETER
;
1283 if (*lpszCLSID
!= '-')
1284 return STATUS_INVALID_PARAMETER
;
1288 if (*lpszCLSID
!= '}')
1289 return STATUS_INVALID_PARAMETER
;
1294 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1297 /* Read two hex digits as a byte value */
1298 if (ch
>= '0' && ch
<= '9')
1300 else if (ch
>= 'a' && ch
<= 'f')
1302 else if (ch
>= 'A' && ch
<= 'F')
1305 return STATUS_INVALID_PARAMETER
;
1307 if (ch2
>= '0' && ch2
<= '9')
1309 else if (ch2
>= 'a' && ch2
<= 'f')
1310 ch2
= ch2
- 'a' + 10;
1311 else if (ch2
>= 'A' && ch2
<= 'F')
1312 ch2
= ch2
- 'A' + 10;
1314 return STATUS_INVALID_PARAMETER
;
1316 byte
= ch
<< 4 | ch2
;
1320 #ifndef WORDS_BIGENDIAN
1321 /* For Big Endian machines, we store the data such that the
1322 * dword/word members can be read as DWORDS and WORDS correctly. */
1354 lpszCLSID
++; /* Skip 2nd character of byte */
1362 return STATUS_SUCCESS
;
1370 RtlEraseUnicodeString(
1371 IN PUNICODE_STRING String
)
1373 if (String
->Buffer
&& String
->MaximumLength
)
1375 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1385 RtlHashUnicodeString(
1386 IN CONST UNICODE_STRING
*String
,
1387 IN BOOLEAN CaseInSensitive
,
1388 IN ULONG HashAlgorithm
,
1389 OUT PULONG HashValue
)
1391 if (String
!= NULL
&& HashValue
!= NULL
)
1393 switch (HashAlgorithm
)
1395 case HASH_STRING_ALGORITHM_DEFAULT
:
1396 case HASH_STRING_ALGORITHM_X65599
:
1401 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1403 if (CaseInSensitive
)
1405 for (c
= String
->Buffer
;
1409 /* only uppercase characters if they are 'a' ... 'z'! */
1410 *HashValue
= ((65599 * (*HashValue
)) +
1411 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1412 (*c
) - L
'a' + L
'A' : (*c
)));
1417 for (c
= String
->Buffer
;
1421 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1424 return STATUS_SUCCESS
;
1429 return STATUS_INVALID_PARAMETER
;
1436 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1437 * Does a partial copy if the dest buffer is too small
1441 RtlUnicodeStringToCountedOemString(
1442 IN OUT POEM_STRING OemDest
,
1443 IN PUNICODE_STRING UniSource
,
1444 IN BOOLEAN AllocateDestinationString
)
1452 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1456 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1459 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1461 OemDest
->Length
= (USHORT
)Length
;
1463 if (AllocateDestinationString
)
1465 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1466 OemDest
->MaximumLength
= Length
;
1467 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1469 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1471 return STATUS_BUFFER_OVERFLOW
;
1474 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1480 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1482 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1484 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1485 OemDest
->Buffer
= NULL
;
1497 RtlLargeIntegerToChar(
1498 IN PLARGE_INTEGER Value
,
1501 IN OUT PCHAR String
)
1505 ULONGLONG v
= Value
->QuadPart
;
1514 if ((Radix
!= 2) && (Radix
!= 8) &&
1515 (Radix
!= 10) && (Radix
!= 16))
1516 return STATUS_INVALID_PARAMETER
;
1519 while (v
|| tp
== temp
)
1530 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1531 return STATUS_BUFFER_TOO_SMALL
;
1538 return STATUS_SUCCESS
;
1545 * dest is never '\0' terminated because it may be equal to src, and src
1546 * might not be '\0' terminated. dest->Length is only set upon success.
1550 RtlUpcaseUnicodeString(
1551 IN OUT PUNICODE_STRING UniDest
,
1552 IN PCUNICODE_STRING UniSource
,
1553 IN BOOLEAN AllocateDestinationString
)
1559 if (AllocateDestinationString
== TRUE
)
1561 UniDest
->MaximumLength
= UniSource
->Length
;
1562 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1563 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1565 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1567 return STATUS_BUFFER_OVERFLOW
;
1570 j
= UniSource
->Length
/ sizeof(WCHAR
);
1572 for (i
= 0; i
< j
; i
++)
1574 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1577 UniDest
->Length
= UniSource
->Length
;
1578 return STATUS_SUCCESS
;
1585 * This function always writes a terminating '\0'.
1586 * It performs a partial copy if ansi is too small.
1590 RtlUpcaseUnicodeStringToAnsiString(
1591 IN OUT PANSI_STRING AnsiDest
,
1592 IN PUNICODE_STRING UniSource
,
1593 IN BOOLEAN AllocateDestinationString
)
1601 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1602 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1604 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1606 if (AllocateDestinationString
)
1608 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1609 AnsiDest
->MaximumLength
= Length
;
1610 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1612 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1614 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1617 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1623 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1625 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1626 AnsiDest
->Buffer
= NULL
;
1630 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1638 * This function always writes a terminating '\0'.
1639 * It performs a partial copy if ansi is too small.
1643 RtlUpcaseUnicodeStringToCountedOemString(
1644 IN OUT POEM_STRING OemDest
,
1645 IN PCUNICODE_STRING UniSource
,
1646 IN BOOLEAN AllocateDestinationString
)
1654 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1658 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1661 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1663 OemDest
->Length
= (USHORT
)Length
;
1665 if (AllocateDestinationString
)
1667 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1668 OemDest
->MaximumLength
= Length
;
1669 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1671 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1673 return STATUS_BUFFER_OVERFLOW
;
1676 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1682 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1684 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1686 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1687 OemDest
->Buffer
= NULL
;
1697 * Oem string is allways nullterminated
1698 * It performs a partial copy if oem is too small.
1702 RtlUpcaseUnicodeStringToOemString (
1703 IN OUT POEM_STRING OemDest
,
1704 IN PCUNICODE_STRING UniSource
,
1705 IN BOOLEAN AllocateDestinationString
)
1713 Length
= RtlUnicodeStringToOemSize(UniSource
);
1714 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1716 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1718 if (AllocateDestinationString
)
1720 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1721 OemDest
->MaximumLength
= Length
;
1722 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1724 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1726 return STATUS_BUFFER_OVERFLOW
;
1729 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1735 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1737 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1739 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1740 OemDest
->Buffer
= NULL
;
1744 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1752 * Bytes calculated including nullterm
1756 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1760 /* Convert the Mb String to Unicode Size */
1761 RtlMultiByteToUnicodeSize(&Size
,
1765 /* Return the size + null-char */
1766 return (Size
+ sizeof(WCHAR
));
1774 RtlStringFromGUID (IN REFGUID Guid
,
1775 OUT PUNICODE_STRING GuidString
)
1777 static CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1784 return STATUS_INVALID_PARAMETER
;
1788 L
"{%08lX-%04X-%04X-%02X%02X-",
1794 BufferPtr
= Buffer
+ 25;
1797 for (i
= 2; i
< 8; i
++)
1799 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1800 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1803 *BufferPtr
++ = L
'}';
1804 *BufferPtr
++ = L
'\0';
1806 return RtlCreateUnicodeString (GuidString
, Buffer
);
1813 * Bytes calculated including nullterm
1817 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1821 /* Convert the Unicode String to Mb Size */
1822 RtlUnicodeToMultiByteSize(&Size
,
1823 UnicodeString
->Buffer
,
1824 UnicodeString
->Length
);
1826 /* Return the size + null-char */
1827 return (Size
+ sizeof(CHAR
));
1835 RtlCompareUnicodeString(
1836 IN PCUNICODE_STRING s1
,
1837 IN PCUNICODE_STRING s2
,
1838 IN BOOLEAN CaseInsensitive
)
1844 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1848 if (CaseInsensitive
)
1850 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1854 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1856 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1866 IN OUT PSTRING DestinationString
,
1867 IN PSTRING SourceString OPTIONAL
)
1872 /* Check if there was no source given */
1875 /* Simply return an empty string */
1876 DestinationString
->Length
= 0;
1880 /* Choose the smallest length */
1881 SourceLength
= min(DestinationString
->MaximumLength
,
1882 SourceString
->Length
);
1885 DestinationString
->Length
= (USHORT
)SourceLength
;
1887 /* Save the pointers to each buffer */
1888 p1
= DestinationString
->Buffer
;
1889 p2
= SourceString
->Buffer
;
1891 /* Loop the buffer */
1892 while (SourceLength
)
1894 /* Copy the character and move on */
1906 RtlCopyUnicodeString(
1907 IN OUT PUNICODE_STRING DestinationString
,
1908 IN PCUNICODE_STRING SourceString
)
1912 if(SourceString
== NULL
)
1914 DestinationString
->Length
= 0;
1918 SourceLength
= min(DestinationString
->MaximumLength
,
1919 SourceString
->Length
);
1920 DestinationString
->Length
= (USHORT
)SourceLength
;
1922 RtlCopyMemory(DestinationString
->Buffer
,
1923 SourceString
->Buffer
,
1926 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
1928 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1937 * Creates a nullterminated UNICODE_STRING
1941 RtlCreateUnicodeString(
1942 IN OUT PUNICODE_STRING UniDest
,
1949 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
1950 if (Length
> 0xFFFE) return FALSE
;
1952 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1954 if (UniDest
->Buffer
== NULL
) return FALSE
;
1956 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
1957 UniDest
->MaximumLength
= (USHORT
)Length
;
1958 UniDest
->Length
= Length
- sizeof (WCHAR
);
1968 RtlCreateUnicodeStringFromAsciiz(
1969 OUT PUNICODE_STRING Destination
,
1972 ANSI_STRING AnsiString
;
1975 RtlInitAnsiString(&AnsiString
, Source
);
1977 Status
= RtlAnsiStringToUnicodeString(Destination
,
1981 return NT_SUCCESS(Status
);
1988 * Dest is never '\0' terminated because it may be equal to src, and src
1989 * might not be '\0' terminated.
1990 * Dest->Length is only set upon success.
1994 RtlDowncaseUnicodeString(
1995 IN OUT PUNICODE_STRING UniDest
,
1996 IN PCUNICODE_STRING UniSource
,
1997 IN BOOLEAN AllocateDestinationString
)
2004 if (AllocateDestinationString
)
2006 UniDest
->MaximumLength
= UniSource
->Length
;
2007 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2008 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2010 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2012 return STATUS_BUFFER_OVERFLOW
;
2015 UniDest
->Length
= UniSource
->Length
;
2016 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2018 for (i
= 0 ; i
< StopGap
; i
++)
2020 if (UniSource
->Buffer
[i
] < L
'A')
2022 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2024 else if (UniSource
->Buffer
[i
] <= L
'Z')
2026 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2030 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2034 return STATUS_SUCCESS
;
2041 * if src is NULL dest is unchanged.
2042 * dest is '\0' terminated when the MaximumLength allowes it.
2043 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2047 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2055 UNICODE_STRING UnicodeSource
;
2057 RtlInitUnicodeString(&UnicodeSource
, Source
);
2058 Length
= UnicodeSource
.Length
;
2060 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2062 return STATUS_BUFFER_TOO_SMALL
;
2065 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2066 RtlMoveMemory(DestBuffer
, Source
, Length
);
2067 Destination
->Length
+= Length
;
2069 /* append terminating '\0' if enough space */
2070 if(Destination
->MaximumLength
> Destination
->Length
)
2072 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2076 return STATUS_SUCCESS
;
2083 * if src is NULL dest is unchanged.
2084 * dest is never '\0' terminated.
2088 RtlAppendAsciizToString(
2089 IN OUT PSTRING Destination
,
2096 Length
= (USHORT
)strlen(Source
);
2098 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2100 return STATUS_BUFFER_TOO_SMALL
;
2103 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2104 Destination
->Length
+= Length
;
2107 return STATUS_SUCCESS
;
2115 RtlUpperString(PSTRING DestinationString
,
2116 PSTRING SourceString
)
2121 Length
= min(SourceString
->Length
,
2122 DestinationString
->MaximumLength
- 1);
2124 Src
= SourceString
->Buffer
;
2125 Dest
= DestinationString
->Buffer
;
2126 DestinationString
->Length
= Length
;
2129 *Dest
++ = RtlUpperChar(*Src
++);
2138 * See RtlpDuplicateUnicodeString
2142 RtlDuplicateUnicodeString(
2144 IN PCUNICODE_STRING SourceString
,
2145 OUT PUNICODE_STRING DestinationString
)
2149 if (SourceString
== NULL
|| DestinationString
== NULL
)
2150 return STATUS_INVALID_PARAMETER
;
2153 if ((SourceString
->Length
== 0) &&
2154 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2155 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2157 DestinationString
->Length
= 0;
2158 DestinationString
->MaximumLength
= 0;
2159 DestinationString
->Buffer
= NULL
;
2163 UINT DestMaxLength
= SourceString
->Length
;
2165 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2166 DestMaxLength
+= sizeof(UNICODE_NULL
);
2168 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2169 if (DestinationString
->Buffer
== NULL
)
2170 return STATUS_NO_MEMORY
;
2172 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2173 DestinationString
->Length
= SourceString
->Length
;
2174 DestinationString
->MaximumLength
= DestMaxLength
;
2176 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2177 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2180 return STATUS_SUCCESS
;
2187 RtlValidateUnicodeString(IN ULONG Flags
,
2188 IN PUNICODE_STRING UnicodeString
)
2190 /* currently no flags are supported! */
2194 ((UnicodeString
== NULL
) ||
2195 ((UnicodeString
->Length
!= 0) &&
2196 (UnicodeString
->Buffer
!= NULL
) &&
2197 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2198 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2199 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2201 /* a NULL pointer as a unicode string is considered to be a valid unicode
2203 return STATUS_SUCCESS
;
2207 return STATUS_INVALID_PARAMETER
;