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
= 0x20;
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
)
72 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
73 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
74 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
76 if (AllocateDestinationString
== TRUE
)
78 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
79 UniDest
->MaximumLength
= Length
;
80 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
82 else if (Length
>= UniDest
->MaximumLength
)
84 return STATUS_BUFFER_TOO_SMALL
;
87 Status
= RtlMultiByteToUnicodeN(UniDest
->Buffer
,
93 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
95 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
99 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
107 * The calculated size in bytes including nullterm.
111 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString
)
115 /* Convert from Mb String to Unicode Size */
116 RtlMultiByteToUnicodeSize(&Size
,
120 /* Return the size plus the null-char */
121 return(Size
+ sizeof(WCHAR
));
128 * If src->length is zero dest is unchanged.
129 * Dest is never nullterminated.
133 RtlAppendStringToString(IN PSTRING Destination
,
136 USHORT SourceLength
= Source
->Length
;
140 if (Destination
->Length
+ SourceLength
> Destination
->MaximumLength
)
142 return STATUS_BUFFER_TOO_SMALL
;
145 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
],
149 Destination
->Length
+= SourceLength
;
152 return STATUS_SUCCESS
;
159 * If src->length is zero dest is unchanged.
160 * Dest is nullterminated when the MaximumLength allowes it.
161 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
165 RtlAppendUnicodeStringToString(
166 IN OUT PUNICODE_STRING Destination
,
167 IN PCUNICODE_STRING Source
)
169 USHORT SourceLength
= Source
->Length
;
170 PWCHAR Buffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
174 if ((SourceLength
+ Destination
->Length
) > Destination
->MaximumLength
)
176 return STATUS_BUFFER_TOO_SMALL
;
179 RtlMoveMemory(Buffer
, Source
->Buffer
, SourceLength
);
180 Destination
->Length
+= SourceLength
;
182 /* append terminating '\0' if enough space */
183 if (Destination
->MaximumLength
> Destination
->Length
)
185 Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
189 return STATUS_SUCCESS
;
192 /**************************************************************************
193 * RtlCharToInteger (NTDLL.@)
195 * Converts a character string into its integer equivalent.
198 * Success: STATUS_SUCCESS. value contains the converted number
199 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
200 * STATUS_ACCESS_VIOLATION, if value is NULL.
203 * For base 0 it uses 10 as base and the string should be in the format
204 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
205 * For other bases the string should be in the format
206 * "{whitespace} [+|-] {digits}".
207 * No check is made for value overflow, only the lower 32 bits are assigned.
208 * If str is NULL it crashes, as the native function does.
211 * This function does not read garbage behind '\0' as the native version does.
216 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
217 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
218 PULONG value
) /* [O] Destination for the converted value */
222 ULONG RunningTotal
= 0;
225 while (*str
!= '\0' && *str
<= ' ') {
231 } else if (*str
== '-') {
242 } else if (str
[1] == 'o') {
245 } else if (str
[1] == 'x') {
250 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
251 return STATUS_INVALID_PARAMETER
;
255 return STATUS_ACCESS_VIOLATION
;
258 while (*str
!= '\0') {
260 if (chCurrent
>= '0' && chCurrent
<= '9') {
261 digit
= chCurrent
- '0';
262 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
263 digit
= chCurrent
- 'A' + 10;
264 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
265 digit
= chCurrent
- 'a' + 10;
269 if (digit
< 0 || digit
>= (int)base
) {
270 *value
= bMinus
? -RunningTotal
: RunningTotal
;
271 return STATUS_SUCCESS
;
274 RunningTotal
= RunningTotal
* base
+ digit
;
278 *value
= bMinus
? -RunningTotal
: RunningTotal
;
279 return STATUS_SUCCESS
;
290 IN BOOLEAN CaseInsensitive
)
296 len
= min(s1
->Length
, s2
->Length
);
302 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
306 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
308 if (!ret
) ret
= s1
->Length
- s2
->Length
;
316 * TRUE if strings are equal.
323 IN BOOLEAN CaseInsensitive
)
325 if (s1
->Length
!= s2
->Length
) return FALSE
;
326 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
333 * TRUE if strings are equal.
337 RtlEqualUnicodeString(
338 IN CONST UNICODE_STRING
*s1
,
339 IN CONST UNICODE_STRING
*s2
,
340 IN BOOLEAN CaseInsensitive
)
342 if (s1
->Length
!= s2
->Length
) return FALSE
;
343 return !RtlCompareUnicodeString(s1
, s2
, CaseInsensitive
);
351 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
353 if (AnsiString
->Buffer
)
355 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
356 RtlZeroMemory(AnsiString
, sizeof(ANSI_STRING
));
365 RtlFreeOemString(IN POEM_STRING OemString
)
367 if (OemString
->Buffer
) RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
375 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
377 if (UnicodeString
->Buffer
)
379 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_ASTR
);
380 RtlZeroMemory(UnicodeString
, sizeof(UNICODE_STRING
));
389 RtlIsValidOemCharacter(IN PWCHAR Char
)
399 * If source is NULL the length of source is assumed to be 0.
403 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
404 IN PCSZ SourceString
)
410 DestSize
= strlen(SourceString
);
411 DestinationString
->Length
= (USHORT
)DestSize
;
412 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
416 DestinationString
->Length
= 0;
417 DestinationString
->MaximumLength
= 0;
420 DestinationString
->Buffer
= (PCHAR
)SourceString
;
427 * If source is NULL the length of source is assumed to be 0.
432 IN OUT PSTRING DestinationString
,
433 IN PCSZ SourceString
)
435 RtlInitAnsiString(DestinationString
, SourceString
);
442 * If source is NULL the length of source is assumed to be 0.
446 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
447 IN PCWSTR SourceString
)
453 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
454 DestinationString
->Length
= (USHORT
)DestSize
;
455 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
459 DestinationString
->Length
= 0;
460 DestinationString
->MaximumLength
= 0;
463 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
471 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
472 IN PCWSTR SourceString
)
478 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
479 if (DestSize
> 0xFFFC) return STATUS_NAME_TOO_LONG
;
480 DestinationString
->Length
= (USHORT
)DestSize
;
481 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
485 DestinationString
->Length
= 0;
486 DestinationString
->MaximumLength
= 0;
489 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
490 return STATUS_SUCCESS
;
497 * Writes at most length characters to the string str.
498 * Str is nullterminated when length allowes it.
499 * When str fits exactly in length characters the nullterm is ommitted.
520 if ((Radix
!= 2) && (Radix
!= 8) &&
521 (Radix
!= 10) && (Radix
!= 16))
523 return STATUS_INVALID_PARAMETER
;
527 while (v
|| tp
== temp
)
538 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
540 return STATUS_BUFFER_TOO_SMALL
;
548 return STATUS_SUCCESS
;
558 IN ULONG Base OPTIONAL
,
559 IN ULONG Length OPTIONAL
,
574 if ((Radix
!= 2) && (Radix
!= 8) &&
575 (Radix
!= 10) && (Radix
!= 16))
577 return STATUS_INVALID_PARAMETER
;
581 while (v
|| tp
== temp
)
592 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
594 return STATUS_BUFFER_TOO_SMALL
;
602 return STATUS_SUCCESS
;
610 RtlIntegerToUnicodeString(
612 IN ULONG Base OPTIONAL
,
613 IN OUT PUNICODE_STRING String
)
615 ANSI_STRING AnsiString
;
619 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
620 if (NT_SUCCESS(Status
))
622 AnsiString
.Buffer
= Buffer
;
623 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
624 AnsiString
.MaximumLength
= sizeof(Buffer
);
626 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
637 RtlInt64ToUnicodeString (
639 IN ULONG Base OPTIONAL
,
640 IN OUT PUNICODE_STRING String
)
642 LARGE_INTEGER LargeInt
;
643 ANSI_STRING AnsiString
;
647 LargeInt
.QuadPart
= Value
;
649 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
650 if (NT_SUCCESS(Status
))
652 AnsiString
.Buffer
= Buffer
;
653 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
654 AnsiString
.MaximumLength
= sizeof(Buffer
);
656 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
666 * TRUE if String2 contains String1 as a prefix.
671 PANSI_STRING String1
,
672 PANSI_STRING String2
,
673 BOOLEAN CaseInsensitive
)
679 if (String2
->Length
< String1
->Length
)
682 Length
= String1
->Length
;
683 pc1
= String1
->Buffer
;
684 pc2
= String2
->Buffer
;
692 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
700 if (*pc1
++ != *pc2
++)
713 * TRUE if String2 contains String1 as a prefix.
717 RtlPrefixUnicodeString(
718 PCUNICODE_STRING String1
,
719 PCUNICODE_STRING String2
,
720 BOOLEAN CaseInsensitive
)
726 if (String2
->Length
< String1
->Length
)
729 Length
= String1
->Length
/ 2;
730 pc1
= String1
->Buffer
;
731 pc2
= String2
->Buffer
;
739 if (RtlUpcaseUnicodeChar (*pc1
++)
740 != RtlUpcaseUnicodeChar (*pc2
++))
748 if( *pc1
++ != *pc2
++ )
757 /**************************************************************************
758 * RtlUnicodeStringToInteger (NTDLL.@)
760 * Converts an unicode string into its integer equivalent.
763 * Success: STATUS_SUCCESS. value contains the converted number
764 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
765 * STATUS_ACCESS_VIOLATION, if value is NULL.
768 * For base 0 it uses 10 as base and the string should be in the format
769 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
770 * For other bases the string should be in the format
771 * "{whitespace} [+|-] {digits}".
772 * No check is made for value overflow, only the lower 32 bits are assigned.
773 * If str is NULL it crashes, as the native function does.
775 * Note that regardless of success or failure status, we should leave the
776 * partial value in Value. An error is never returned based on the chars
780 * This function does not read garbage on string length 0 as the native
785 RtlUnicodeStringToInteger(
786 PCUNICODE_STRING str
, /* [I] Unicode string to be converted */
787 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
788 PULONG value
) /* [O] Destination for the converted value */
790 LPWSTR lpwstr
= str
->Buffer
;
791 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
795 ULONG RunningTotal
= 0;
798 while (CharsRemaining
>= 1 && *lpwstr
<= L
' ') {
803 if (CharsRemaining
>= 1) {
804 if (*lpwstr
== L
'+') {
807 } else if (*lpwstr
== L
'-') {
814 if (CharsRemaining
>= 2 && lpwstr
[0] == L
'0') {
815 if (lpwstr
[1] == L
'b' || lpwstr
[1] == L
'B') {
819 } else if (lpwstr
[1] == L
'o' || lpwstr
[1] == L
'O') {
823 } else if (lpwstr
[1] == L
'x' || lpwstr
[1] == L
'X') {
829 if (base
== 0 && newbase
== 0) {
831 } else if (base
== 0 && newbase
!= 0) {
833 } else if ((newbase
!= 0 && base
!= newbase
) ||
834 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
835 return STATUS_INVALID_PARAMETER
;
840 return STATUS_ACCESS_VIOLATION
;
843 while (CharsRemaining
>= 1) {
844 wchCurrent
= *lpwstr
;
845 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
846 digit
= wchCurrent
- L
'0';
847 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
848 digit
= wchCurrent
- L
'A' + 10;
849 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
850 digit
= wchCurrent
- L
'a' + 10;
854 if (digit
< 0 || digit
>= (int)base
) {
855 *value
= bMinus
? -RunningTotal
: RunningTotal
;
856 return STATUS_SUCCESS
;
859 RunningTotal
= RunningTotal
* base
+ digit
;
864 *value
= bMinus
? -RunningTotal
: RunningTotal
;
865 return STATUS_SUCCESS
;
872 * Bytes necessary for the conversion including nullterm.
876 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
880 /* Convert the Unicode String to Mb Size */
881 RtlUnicodeToMultiByteSize(&Size
,
882 UnicodeString
->Buffer
,
883 UnicodeString
->Length
);
885 /* Return the size + the null char */
886 return (Size
+ sizeof(CHAR
));
893 * This function always writes a terminating '\0'.
894 * It performs a partial copy if ansi is too small.
898 RtlUnicodeStringToAnsiString(
899 IN OUT PANSI_STRING AnsiDest
,
900 IN PCUNICODE_STRING UniSource
,
901 IN BOOLEAN AllocateDestinationString
)
903 NTSTATUS Status
= STATUS_SUCCESS
;
908 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
909 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
911 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
913 if (AllocateDestinationString
)
915 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
916 AnsiDest
->MaximumLength
= Length
;
917 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
919 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
921 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
923 Status
= STATUS_BUFFER_OVERFLOW
;
924 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
927 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
933 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
935 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
939 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
947 * This function always writes a terminating '\0'.
948 * Does NOT perform a partial copy if unicode is too small!
952 RtlOemStringToUnicodeString(
953 IN OUT PUNICODE_STRING UniDest
,
954 IN PCOEM_STRING OemSource
,
955 IN BOOLEAN AllocateDestinationString
)
961 Length
= RtlOemStringToUnicodeSize(OemSource
);
962 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
964 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
966 if (AllocateDestinationString
)
968 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
969 UniDest
->MaximumLength
= Length
;
970 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
972 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
974 return STATUS_BUFFER_OVERFLOW
;
977 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
983 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
985 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
986 UniDest
->Buffer
= NULL
;
990 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
998 * This function always '\0' terminates the string returned.
1002 RtlUnicodeStringToOemString(
1003 IN OUT POEM_STRING OemDest
,
1004 IN PCUNICODE_STRING UniSource
,
1005 IN BOOLEAN AllocateDestinationString
)
1011 Length
= RtlUnicodeStringToOemSize(UniSource
);
1012 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1014 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1016 if (AllocateDestinationString
)
1018 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1019 OemDest
->MaximumLength
= Length
;
1020 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1022 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1024 return STATUS_BUFFER_OVERFLOW
;
1027 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1033 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1035 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1036 OemDest
->Buffer
= NULL
;
1040 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1044 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1050 * The length of the string if all tests were passed, 0 otherwise.
1053 RtlIsTextUnicode (PVOID Buffer
,
1058 ULONG in_flags
= (ULONG
)-1;
1059 ULONG out_flags
= 0;
1068 * Apply various tests to the text string. According to the
1069 * docs, each test "passed" sets the corresponding flag in
1070 * the output flags. But some of the tests are mutually
1071 * exclusive, so I don't see how you could pass all tests ...
1074 /* Check for an odd length ... pass if even. */
1076 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1078 /* Check for the BOM (byte order mark). */
1080 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1083 /* Check for the reverse BOM (byte order mark). */
1085 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1088 /* FIXME: Add more tests */
1091 * Check whether the string passed all of the tests.
1093 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1094 if ((out_flags
& in_flags
) != in_flags
)
1108 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1109 * A partial copy is NOT performed if the dest buffer is too small!
1113 RtlOemStringToCountedUnicodeString(
1114 IN OUT PUNICODE_STRING UniDest
,
1115 IN PCOEM_STRING OemSource
,
1116 IN BOOLEAN AllocateDestinationString
)
1122 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1126 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1127 return STATUS_SUCCESS
;
1130 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1132 UniDest
->Length
= (USHORT
)Length
;
1134 if (AllocateDestinationString
)
1136 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1137 UniDest
->MaximumLength
= Length
;
1138 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1140 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1142 return STATUS_BUFFER_OVERFLOW
;
1145 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1151 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1153 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1154 UniDest
->Buffer
= NULL
;
1158 return STATUS_SUCCESS
;
1165 * TRUE if the names are equal, FALSE if not
1168 * The comparison is case insensitive.
1172 RtlEqualComputerName(
1173 IN PUNICODE_STRING ComputerName1
,
1174 IN PUNICODE_STRING ComputerName2
)
1176 OEM_STRING OemString1
;
1177 OEM_STRING OemString2
;
1178 BOOLEAN Result
= FALSE
;
1180 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1184 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1188 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1189 RtlFreeOemString(&OemString2
);
1191 RtlFreeOemString(&OemString1
);
1201 * TRUE if the names are equal, FALSE if not
1204 * The comparison is case insensitive.
1208 RtlEqualDomainName (
1209 IN PUNICODE_STRING DomainName1
,
1210 IN PUNICODE_STRING DomainName2
1213 return RtlEqualComputerName(DomainName1
, DomainName2
);
1219 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1221 * Convert a string representation of a GUID into a GUID.
1224 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1225 * guid [O] Destination for the converted GUID
1228 * Success: STATUS_SUCCESS. guid contains the converted value.
1229 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1232 * See RtlStringFromGUID.
1237 IN UNICODE_STRING
*str
,
1242 const WCHAR
*lpszCLSID
= str
->Buffer
;
1243 BYTE
* lpOut
= (BYTE
*)guid
;
1245 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1247 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1248 * to memory: DWORD... WORD WORD BYTES............
1255 if (*lpszCLSID
!= '{')
1256 return STATUS_INVALID_PARAMETER
;
1263 if (*lpszCLSID
!= '-')
1264 return STATUS_INVALID_PARAMETER
;
1268 if (*lpszCLSID
!= '}')
1269 return STATUS_INVALID_PARAMETER
;
1274 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1277 /* Read two hex digits as a byte value */
1278 if (ch
>= '0' && ch
<= '9')
1280 else if (ch
>= 'a' && ch
<= 'f')
1282 else if (ch
>= 'A' && ch
<= 'F')
1285 return STATUS_INVALID_PARAMETER
;
1287 if (ch2
>= '0' && ch2
<= '9')
1289 else if (ch2
>= 'a' && ch2
<= 'f')
1290 ch2
= ch2
- 'a' + 10;
1291 else if (ch2
>= 'A' && ch2
<= 'F')
1292 ch2
= ch2
- 'A' + 10;
1294 return STATUS_INVALID_PARAMETER
;
1296 byte
= ch
<< 4 | ch2
;
1300 #ifndef WORDS_BIGENDIAN
1301 /* For Big Endian machines, we store the data such that the
1302 * dword/word members can be read as DWORDS and WORDS correctly. */
1334 lpszCLSID
++; /* Skip 2nd character of byte */
1342 return STATUS_SUCCESS
;
1350 RtlEraseUnicodeString(
1351 IN PUNICODE_STRING String
)
1353 if (String
->Buffer
&& String
->MaximumLength
)
1355 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1365 RtlHashUnicodeString(
1366 IN CONST UNICODE_STRING
*String
,
1367 IN BOOLEAN CaseInSensitive
,
1368 IN ULONG HashAlgorithm
,
1369 OUT PULONG HashValue
)
1371 if (String
!= NULL
&& HashValue
!= NULL
)
1373 switch (HashAlgorithm
)
1375 case HASH_STRING_ALGORITHM_DEFAULT
:
1376 case HASH_STRING_ALGORITHM_X65599
:
1381 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1383 if (CaseInSensitive
)
1385 for (c
= String
->Buffer
;
1389 /* only uppercase characters if they are 'a' ... 'z'! */
1390 *HashValue
= ((65599 * (*HashValue
)) +
1391 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1392 (*c
) - L
'a' + L
'A' : (*c
)));
1397 for (c
= String
->Buffer
;
1401 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1404 return STATUS_SUCCESS
;
1409 return STATUS_INVALID_PARAMETER
;
1416 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1417 * Does a partial copy if the dest buffer is too small
1421 RtlUnicodeStringToCountedOemString(
1422 IN OUT POEM_STRING OemDest
,
1423 IN PUNICODE_STRING UniSource
,
1424 IN BOOLEAN AllocateDestinationString
)
1430 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1434 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1437 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1439 OemDest
->Length
= (USHORT
)Length
;
1441 if (AllocateDestinationString
)
1443 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1444 OemDest
->MaximumLength
= Length
;
1445 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1447 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1449 return STATUS_BUFFER_OVERFLOW
;
1452 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1458 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1460 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1462 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1463 OemDest
->Buffer
= NULL
;
1475 RtlLargeIntegerToChar(
1476 IN PLARGE_INTEGER Value
,
1479 IN OUT PCHAR String
)
1483 ULONGLONG v
= Value
->QuadPart
;
1492 if ((Radix
!= 2) && (Radix
!= 8) &&
1493 (Radix
!= 10) && (Radix
!= 16))
1494 return STATUS_INVALID_PARAMETER
;
1497 while (v
|| tp
== temp
)
1508 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1509 return STATUS_BUFFER_TOO_SMALL
;
1516 return STATUS_SUCCESS
;
1523 * dest is never '\0' terminated because it may be equal to src, and src
1524 * might not be '\0' terminated. dest->Length is only set upon success.
1528 RtlUpcaseUnicodeString(
1529 IN OUT PUNICODE_STRING UniDest
,
1530 IN PCUNICODE_STRING UniSource
,
1531 IN BOOLEAN AllocateDestinationString
)
1535 if (AllocateDestinationString
== TRUE
)
1537 UniDest
->MaximumLength
= UniSource
->Length
;
1538 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1539 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1541 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1543 return STATUS_BUFFER_OVERFLOW
;
1546 j
= UniSource
->Length
/ sizeof(WCHAR
);
1548 for (i
= 0; i
< j
; i
++)
1550 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1553 UniDest
->Length
= UniSource
->Length
;
1554 return STATUS_SUCCESS
;
1561 * This function always writes a terminating '\0'.
1562 * It performs a partial copy if ansi is too small.
1566 RtlUpcaseUnicodeStringToAnsiString(
1567 IN OUT PANSI_STRING AnsiDest
,
1568 IN PUNICODE_STRING UniSource
,
1569 IN BOOLEAN AllocateDestinationString
)
1575 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1576 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1578 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1580 if (AllocateDestinationString
)
1582 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1583 AnsiDest
->MaximumLength
= Length
;
1584 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1586 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1588 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1591 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1597 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1599 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1600 AnsiDest
->Buffer
= NULL
;
1604 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1612 * This function always writes a terminating '\0'.
1613 * It performs a partial copy if ansi is too small.
1617 RtlUpcaseUnicodeStringToCountedOemString(
1618 IN OUT POEM_STRING OemDest
,
1619 IN PCUNICODE_STRING UniSource
,
1620 IN BOOLEAN AllocateDestinationString
)
1626 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1630 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1633 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1635 OemDest
->Length
= (USHORT
)Length
;
1637 if (AllocateDestinationString
)
1639 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1640 OemDest
->MaximumLength
= Length
;
1641 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1643 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1645 return STATUS_BUFFER_OVERFLOW
;
1648 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1654 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1656 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1658 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1659 OemDest
->Buffer
= NULL
;
1669 * Oem string is allways nullterminated
1670 * It performs a partial copy if oem is too small.
1674 RtlUpcaseUnicodeStringToOemString (
1675 IN OUT POEM_STRING OemDest
,
1676 IN PCUNICODE_STRING UniSource
,
1677 IN BOOLEAN AllocateDestinationString
)
1683 Length
= RtlUnicodeStringToOemSize(UniSource
);
1684 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1686 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1688 if (AllocateDestinationString
)
1690 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1691 OemDest
->MaximumLength
= Length
;
1692 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1694 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1696 return STATUS_BUFFER_OVERFLOW
;
1699 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1705 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1707 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1709 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1710 OemDest
->Buffer
= NULL
;
1714 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1722 * Bytes calculated including nullterm
1726 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1730 /* Convert the Mb String to Unicode Size */
1731 RtlMultiByteToUnicodeSize(&Size
,
1735 /* Return the size + null-char */
1736 return (Size
+ sizeof(WCHAR
));
1744 RtlStringFromGUID (IN REFGUID Guid
,
1745 OUT PUNICODE_STRING GuidString
)
1747 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1754 return STATUS_INVALID_PARAMETER
;
1758 L
"{%08lX-%04X-%04X-%02X%02X-",
1764 BufferPtr
= Buffer
+ 25;
1767 for (i
= 2; i
< 8; i
++)
1769 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1770 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1773 *BufferPtr
++ = L
'}';
1774 *BufferPtr
++ = L
'\0';
1776 return RtlCreateUnicodeString (GuidString
, Buffer
);
1783 * Bytes calculated including nullterm
1787 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1791 /* Convert the Unicode String to Mb Size */
1792 RtlUnicodeToMultiByteSize(&Size
,
1793 UnicodeString
->Buffer
,
1794 UnicodeString
->Length
);
1796 /* Return the size + null-char */
1797 return (Size
+ sizeof(CHAR
));
1805 RtlCompareUnicodeString(
1806 IN PCUNICODE_STRING s1
,
1807 IN PCUNICODE_STRING s2
,
1808 IN BOOLEAN CaseInsensitive
)
1814 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1818 if (CaseInsensitive
)
1820 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1824 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1826 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1836 IN OUT PSTRING DestinationString
,
1837 IN PSTRING SourceString OPTIONAL
)
1842 /* Check if there was no source given */
1845 /* Simply return an empty string */
1846 DestinationString
->Length
= 0;
1850 /* Choose the smallest length */
1851 SourceLength
= min(DestinationString
->MaximumLength
,
1852 SourceString
->Length
);
1855 DestinationString
->Length
= (USHORT
)SourceLength
;
1857 /* Save the pointers to each buffer */
1858 p1
= DestinationString
->Buffer
;
1859 p2
= SourceString
->Buffer
;
1861 /* Loop the buffer */
1862 while (SourceLength
)
1864 /* Copy the character and move on */
1876 RtlCopyUnicodeString(
1877 IN OUT PUNICODE_STRING DestinationString
,
1878 IN PCUNICODE_STRING SourceString
)
1882 if(SourceString
== NULL
)
1884 DestinationString
->Length
= 0;
1888 SourceLength
= min(DestinationString
->MaximumLength
,
1889 SourceString
->Length
);
1890 DestinationString
->Length
= (USHORT
)SourceLength
;
1892 RtlCopyMemory(DestinationString
->Buffer
,
1893 SourceString
->Buffer
,
1896 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
1898 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1907 * Creates a nullterminated UNICODE_STRING
1911 RtlCreateUnicodeString(
1912 IN OUT PUNICODE_STRING UniDest
,
1917 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
1918 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1920 if (UniDest
->Buffer
== NULL
) return FALSE
;
1922 RtlMoveMemory(UniDest
->Buffer
, Source
, Length
);
1923 UniDest
->MaximumLength
= (USHORT
)Length
;
1924 UniDest
->Length
= Length
- sizeof (WCHAR
);
1934 RtlCreateUnicodeStringFromAsciiz(
1935 OUT PUNICODE_STRING Destination
,
1938 ANSI_STRING AnsiString
;
1941 RtlInitAnsiString(&AnsiString
, Source
);
1943 Status
= RtlAnsiStringToUnicodeString(Destination
,
1947 return NT_SUCCESS(Status
);
1954 * Dest is never '\0' terminated because it may be equal to src, and src
1955 * might not be '\0' terminated.
1956 * Dest->Length is only set upon success.
1960 RtlDowncaseUnicodeString(
1961 IN OUT PUNICODE_STRING UniDest
,
1962 IN PCUNICODE_STRING UniSource
,
1963 IN BOOLEAN AllocateDestinationString
)
1968 if (AllocateDestinationString
)
1970 UniDest
->MaximumLength
= UniSource
->Length
;
1971 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
1972 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1974 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1976 return STATUS_BUFFER_OVERFLOW
;
1979 UniDest
->Length
= UniSource
->Length
;
1980 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
1982 for (i
= 0 ; i
< StopGap
; i
++)
1984 if (UniSource
->Buffer
[i
] < L
'A')
1986 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
1988 else if (UniSource
->Buffer
[i
] <= L
'Z')
1990 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
1994 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
1998 return STATUS_SUCCESS
;
2005 * if src is NULL dest is unchanged.
2006 * dest is '\0' terminated when the MaximumLength allowes it.
2007 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2011 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2019 UNICODE_STRING UnicodeSource
;
2021 RtlInitUnicodeString(&UnicodeSource
, Source
);
2022 Length
= UnicodeSource
.Length
;
2024 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2026 return STATUS_BUFFER_TOO_SMALL
;
2029 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2030 RtlMoveMemory(DestBuffer
, Source
, Length
);
2031 Destination
->Length
+= Length
;
2033 /* append terminating '\0' if enough space */
2034 if(Destination
->MaximumLength
> Destination
->Length
)
2036 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2040 return STATUS_SUCCESS
;
2047 * if src is NULL dest is unchanged.
2048 * dest is never '\0' terminated.
2052 RtlAppendAsciizToString(
2053 IN OUT PSTRING Destination
,
2060 Length
= (USHORT
)strlen(Source
);
2062 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2064 return STATUS_BUFFER_TOO_SMALL
;
2067 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2068 Destination
->Length
+= Length
;
2071 return STATUS_SUCCESS
;
2079 RtlUpperString(PSTRING DestinationString
,
2080 PSTRING SourceString
)
2085 Length
= min(SourceString
->Length
,
2086 DestinationString
->MaximumLength
- 1);
2088 Src
= SourceString
->Buffer
;
2089 Dest
= DestinationString
->Buffer
;
2090 DestinationString
->Length
= Length
;
2093 *Dest
++ = RtlUpperChar(*Src
++);
2102 * See RtlpDuplicateUnicodeString
2106 RtlDuplicateUnicodeString(
2108 IN PCUNICODE_STRING SourceString
,
2109 OUT PUNICODE_STRING DestinationString
)
2111 if (SourceString
== NULL
|| DestinationString
== NULL
)
2112 return STATUS_INVALID_PARAMETER
;
2115 if ((SourceString
->Length
== 0) &&
2116 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2117 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2119 DestinationString
->Length
= 0;
2120 DestinationString
->MaximumLength
= 0;
2121 DestinationString
->Buffer
= NULL
;
2125 UINT DestMaxLength
= SourceString
->Length
;
2127 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2128 DestMaxLength
+= sizeof(UNICODE_NULL
);
2130 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2131 if (DestinationString
->Buffer
== NULL
)
2132 return STATUS_NO_MEMORY
;
2134 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2135 DestinationString
->Length
= SourceString
->Length
;
2136 DestinationString
->MaximumLength
= DestMaxLength
;
2138 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2139 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2142 return STATUS_SUCCESS
;
2149 RtlValidateUnicodeString(IN ULONG Flags
,
2150 IN PUNICODE_STRING UnicodeString
)
2152 /* currently no flags are supported! */
2156 ((UnicodeString
== NULL
) ||
2157 ((UnicodeString
->Length
!= 0) &&
2158 (UnicodeString
->Buffer
!= NULL
) &&
2159 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2160 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2161 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2163 /* a NULL pointer as a unicode string is considered to be a valid unicode
2165 return STATUS_SUCCESS
;
2169 return STATUS_INVALID_PARAMETER
;