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.
513 NTSTATUS NTAPI
RtlIntegerToChar(
514 ULONG value
, /* [I] Value to be converted */
515 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
516 ULONG length
, /* [I] Length of the str buffer in bytes */
517 PCHAR str
) /* [O] Destination for the converted value */
526 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
527 return STATUS_INVALID_PARAMETER
;
535 digit
= value
% base
;
536 value
= value
/ base
;
540 *pos
= 'A' + digit
- 10;
542 } while (value
!= 0L);
544 len
= &buffer
[32] - pos
;
546 return STATUS_BUFFER_OVERFLOW
;
547 } else if (str
== NULL
) {
548 return STATUS_ACCESS_VIOLATION
;
549 } else if (len
== length
) {
550 memcpy(str
, pos
, len
);
552 memcpy(str
, pos
, len
+ 1);
554 return STATUS_SUCCESS
;
564 IN ULONG Base OPTIONAL
,
565 IN ULONG Length OPTIONAL
,
580 if ((Radix
!= 2) && (Radix
!= 8) &&
581 (Radix
!= 10) && (Radix
!= 16))
583 return STATUS_INVALID_PARAMETER
;
587 while (v
|| tp
== temp
)
598 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
600 return STATUS_BUFFER_TOO_SMALL
;
608 return STATUS_SUCCESS
;
616 RtlIntegerToUnicodeString(
618 IN ULONG Base OPTIONAL
,
619 IN OUT PUNICODE_STRING String
)
621 ANSI_STRING AnsiString
;
625 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
626 if (NT_SUCCESS(Status
))
628 AnsiString
.Buffer
= Buffer
;
629 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
630 AnsiString
.MaximumLength
= sizeof(Buffer
);
632 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
643 RtlInt64ToUnicodeString (
645 IN ULONG Base OPTIONAL
,
646 IN OUT PUNICODE_STRING String
)
648 LARGE_INTEGER LargeInt
;
649 ANSI_STRING AnsiString
;
653 LargeInt
.QuadPart
= Value
;
655 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
656 if (NT_SUCCESS(Status
))
658 AnsiString
.Buffer
= Buffer
;
659 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
660 AnsiString
.MaximumLength
= sizeof(Buffer
);
662 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
672 * TRUE if String2 contains String1 as a prefix.
677 PANSI_STRING String1
,
678 PANSI_STRING String2
,
679 BOOLEAN CaseInsensitive
)
685 if (String2
->Length
< String1
->Length
)
688 Length
= String1
->Length
;
689 pc1
= String1
->Buffer
;
690 pc2
= String2
->Buffer
;
698 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
706 if (*pc1
++ != *pc2
++)
719 * TRUE if String2 contains String1 as a prefix.
723 RtlPrefixUnicodeString(
724 PCUNICODE_STRING String1
,
725 PCUNICODE_STRING String2
,
726 BOOLEAN CaseInsensitive
)
732 if (String2
->Length
< String1
->Length
)
735 Length
= String1
->Length
/ 2;
736 pc1
= String1
->Buffer
;
737 pc2
= String2
->Buffer
;
745 if (RtlUpcaseUnicodeChar (*pc1
++)
746 != RtlUpcaseUnicodeChar (*pc2
++))
754 if( *pc1
++ != *pc2
++ )
767 RtlUnicodeStringToInteger(const UNICODE_STRING
*str
, /* [I] Unicode string to be converted */
768 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
769 ULONG
*value
) /* [O] Destination for the converted value */
771 LPWSTR lpwstr
= str
->Buffer
;
772 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
775 ULONG RunningTotal
= 0;
778 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
783 if (CharsRemaining
>= 1) {
784 if (*lpwstr
== '+') {
787 } else if (*lpwstr
== '-') {
796 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
797 if (lpwstr
[1] == 'b') {
801 } else if (lpwstr
[1] == 'o') {
805 } else if (lpwstr
[1] == 'x') {
811 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
812 return STATUS_INVALID_PARAMETER
;
816 return STATUS_ACCESS_VIOLATION
;
819 while (CharsRemaining
>= 1) {
820 wchCurrent
= *lpwstr
;
821 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
822 digit
= wchCurrent
- '0';
823 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
824 digit
= wchCurrent
- 'A' + 10;
825 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
826 digit
= wchCurrent
- 'a' + 10;
830 if (digit
< 0 || digit
>= base
) {
831 *value
= bMinus
? -RunningTotal
: RunningTotal
;
832 return STATUS_SUCCESS
;
835 RunningTotal
= RunningTotal
* base
+ digit
;
840 *value
= bMinus
? -RunningTotal
: RunningTotal
;
841 return STATUS_SUCCESS
;
848 * Bytes necessary for the conversion including nullterm.
852 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
856 /* Convert the Unicode String to Mb Size */
857 RtlUnicodeToMultiByteSize(&Size
,
858 UnicodeString
->Buffer
,
859 UnicodeString
->Length
);
861 /* Return the size + the null char */
862 return (Size
+ sizeof(CHAR
));
869 * This function always writes a terminating '\0'.
870 * It performs a partial copy if ansi is too small.
874 RtlUnicodeStringToAnsiString(
875 IN OUT PANSI_STRING AnsiDest
,
876 IN PCUNICODE_STRING UniSource
,
877 IN BOOLEAN AllocateDestinationString
)
879 NTSTATUS Status
= STATUS_SUCCESS
;
886 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
887 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
889 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
891 if (AllocateDestinationString
)
893 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
894 AnsiDest
->MaximumLength
= Length
;
895 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
897 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
899 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
901 Status
= STATUS_BUFFER_OVERFLOW
;
902 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
905 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
911 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
913 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
917 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
925 * This function always writes a terminating '\0'.
926 * Does NOT perform a partial copy if unicode is too small!
930 RtlOemStringToUnicodeString(
931 IN OUT PUNICODE_STRING UniDest
,
932 IN PCOEM_STRING OemSource
,
933 IN BOOLEAN AllocateDestinationString
)
941 Length
= RtlOemStringToUnicodeSize(OemSource
);
942 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
944 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
946 if (AllocateDestinationString
)
948 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
949 UniDest
->MaximumLength
= Length
;
950 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
952 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
954 return STATUS_BUFFER_OVERFLOW
;
957 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
963 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
965 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
966 UniDest
->Buffer
= NULL
;
970 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
978 * This function always '\0' terminates the string returned.
982 RtlUnicodeStringToOemString(
983 IN OUT POEM_STRING OemDest
,
984 IN PCUNICODE_STRING UniSource
,
985 IN BOOLEAN AllocateDestinationString
)
993 Length
= RtlUnicodeStringToOemSize(UniSource
);
994 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
996 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
998 if (AllocateDestinationString
)
1000 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1001 OemDest
->MaximumLength
= Length
;
1002 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1004 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1006 return STATUS_BUFFER_OVERFLOW
;
1009 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1015 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1017 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1018 OemDest
->Buffer
= NULL
;
1022 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1026 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1032 * The length of the string if all tests were passed, 0 otherwise.
1035 RtlIsTextUnicode (PVOID Buffer
,
1040 ULONG in_flags
= (ULONG
)-1;
1041 ULONG out_flags
= 0;
1050 * Apply various tests to the text string. According to the
1051 * docs, each test "passed" sets the corresponding flag in
1052 * the output flags. But some of the tests are mutually
1053 * exclusive, so I don't see how you could pass all tests ...
1056 /* Check for an odd length ... pass if even. */
1058 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1060 /* Check for the BOM (byte order mark). */
1062 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1065 /* Check for the reverse BOM (byte order mark). */
1067 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1070 /* FIXME: Add more tests */
1073 * Check whether the string passed all of the tests.
1075 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1076 if ((out_flags
& in_flags
) != in_flags
)
1090 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1091 * A partial copy is NOT performed if the dest buffer is too small!
1095 RtlOemStringToCountedUnicodeString(
1096 IN OUT PUNICODE_STRING UniDest
,
1097 IN PCOEM_STRING OemSource
,
1098 IN BOOLEAN AllocateDestinationString
)
1106 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1110 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1111 return STATUS_SUCCESS
;
1114 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1116 UniDest
->Length
= (USHORT
)Length
;
1118 if (AllocateDestinationString
)
1120 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1121 UniDest
->MaximumLength
= Length
;
1122 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1124 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1126 return STATUS_BUFFER_OVERFLOW
;
1129 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1135 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1137 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1138 UniDest
->Buffer
= NULL
;
1142 return STATUS_SUCCESS
;
1149 * TRUE if the names are equal, FALSE if not
1152 * The comparison is case insensitive.
1156 RtlEqualComputerName(
1157 IN PUNICODE_STRING ComputerName1
,
1158 IN PUNICODE_STRING ComputerName2
)
1160 OEM_STRING OemString1
;
1161 OEM_STRING OemString2
;
1162 BOOLEAN Result
= FALSE
;
1164 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1168 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1172 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1173 RtlFreeOemString(&OemString2
);
1175 RtlFreeOemString(&OemString1
);
1185 * TRUE if the names are equal, FALSE if not
1188 * The comparison is case insensitive.
1192 RtlEqualDomainName (
1193 IN PUNICODE_STRING DomainName1
,
1194 IN PUNICODE_STRING DomainName2
1197 return RtlEqualComputerName(DomainName1
, DomainName2
);
1203 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1205 * Convert a string representation of a GUID into a GUID.
1208 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1209 * guid [O] Destination for the converted GUID
1212 * Success: STATUS_SUCCESS. guid contains the converted value.
1213 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1216 * See RtlStringFromGUID.
1221 IN UNICODE_STRING
*str
,
1226 const WCHAR
*lpszCLSID
= str
->Buffer
;
1227 BYTE
* lpOut
= (BYTE
*)guid
;
1229 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1231 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1232 * to memory: DWORD... WORD WORD BYTES............
1239 if (*lpszCLSID
!= '{')
1240 return STATUS_INVALID_PARAMETER
;
1247 if (*lpszCLSID
!= '-')
1248 return STATUS_INVALID_PARAMETER
;
1252 if (*lpszCLSID
!= '}')
1253 return STATUS_INVALID_PARAMETER
;
1258 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1261 /* Read two hex digits as a byte value */
1262 if (ch
>= '0' && ch
<= '9')
1264 else if (ch
>= 'a' && ch
<= 'f')
1266 else if (ch
>= 'A' && ch
<= 'F')
1269 return STATUS_INVALID_PARAMETER
;
1271 if (ch2
>= '0' && ch2
<= '9')
1273 else if (ch2
>= 'a' && ch2
<= 'f')
1274 ch2
= ch2
- 'a' + 10;
1275 else if (ch2
>= 'A' && ch2
<= 'F')
1276 ch2
= ch2
- 'A' + 10;
1278 return STATUS_INVALID_PARAMETER
;
1280 byte
= ch
<< 4 | ch2
;
1284 #ifndef WORDS_BIGENDIAN
1285 /* For Big Endian machines, we store the data such that the
1286 * dword/word members can be read as DWORDS and WORDS correctly. */
1318 lpszCLSID
++; /* Skip 2nd character of byte */
1326 return STATUS_SUCCESS
;
1334 RtlEraseUnicodeString(
1335 IN PUNICODE_STRING String
)
1337 if (String
->Buffer
&& String
->MaximumLength
)
1339 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1349 RtlHashUnicodeString(
1350 IN CONST UNICODE_STRING
*String
,
1351 IN BOOLEAN CaseInSensitive
,
1352 IN ULONG HashAlgorithm
,
1353 OUT PULONG HashValue
)
1355 if (String
!= NULL
&& HashValue
!= NULL
)
1357 switch (HashAlgorithm
)
1359 case HASH_STRING_ALGORITHM_DEFAULT
:
1360 case HASH_STRING_ALGORITHM_X65599
:
1365 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1367 if (CaseInSensitive
)
1369 for (c
= String
->Buffer
;
1373 /* only uppercase characters if they are 'a' ... 'z'! */
1374 *HashValue
= ((65599 * (*HashValue
)) +
1375 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1376 (*c
) - L
'a' + L
'A' : (*c
)));
1381 for (c
= String
->Buffer
;
1385 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1388 return STATUS_SUCCESS
;
1393 return STATUS_INVALID_PARAMETER
;
1400 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1401 * Does a partial copy if the dest buffer is too small
1405 RtlUnicodeStringToCountedOemString(
1406 IN OUT POEM_STRING OemDest
,
1407 IN PUNICODE_STRING UniSource
,
1408 IN BOOLEAN AllocateDestinationString
)
1416 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1420 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1423 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1425 OemDest
->Length
= (USHORT
)Length
;
1427 if (AllocateDestinationString
)
1429 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1430 OemDest
->MaximumLength
= Length
;
1431 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1433 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1435 return STATUS_BUFFER_OVERFLOW
;
1438 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1444 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1446 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1448 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1449 OemDest
->Buffer
= NULL
;
1461 RtlLargeIntegerToChar(
1462 IN PLARGE_INTEGER Value
,
1465 IN OUT PCHAR String
)
1469 ULONGLONG v
= Value
->QuadPart
;
1478 if ((Radix
!= 2) && (Radix
!= 8) &&
1479 (Radix
!= 10) && (Radix
!= 16))
1480 return STATUS_INVALID_PARAMETER
;
1483 while (v
|| tp
== temp
)
1494 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1495 return STATUS_BUFFER_TOO_SMALL
;
1502 return STATUS_SUCCESS
;
1509 * dest is never '\0' terminated because it may be equal to src, and src
1510 * might not be '\0' terminated. dest->Length is only set upon success.
1514 RtlUpcaseUnicodeString(
1515 IN OUT PUNICODE_STRING UniDest
,
1516 IN PCUNICODE_STRING UniSource
,
1517 IN BOOLEAN AllocateDestinationString
)
1523 if (AllocateDestinationString
== TRUE
)
1525 UniDest
->MaximumLength
= UniSource
->Length
;
1526 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1527 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1529 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1531 return STATUS_BUFFER_OVERFLOW
;
1534 j
= UniSource
->Length
/ sizeof(WCHAR
);
1536 for (i
= 0; i
< j
; i
++)
1538 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1541 UniDest
->Length
= UniSource
->Length
;
1542 return STATUS_SUCCESS
;
1549 * This function always writes a terminating '\0'.
1550 * It performs a partial copy if ansi is too small.
1554 RtlUpcaseUnicodeStringToAnsiString(
1555 IN OUT PANSI_STRING AnsiDest
,
1556 IN PUNICODE_STRING UniSource
,
1557 IN BOOLEAN AllocateDestinationString
)
1565 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1566 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1568 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1570 if (AllocateDestinationString
)
1572 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1573 AnsiDest
->MaximumLength
= Length
;
1574 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1576 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1578 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1581 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1587 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1589 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1590 AnsiDest
->Buffer
= NULL
;
1594 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1602 * This function always writes a terminating '\0'.
1603 * It performs a partial copy if ansi is too small.
1607 RtlUpcaseUnicodeStringToCountedOemString(
1608 IN OUT POEM_STRING OemDest
,
1609 IN PCUNICODE_STRING UniSource
,
1610 IN BOOLEAN AllocateDestinationString
)
1618 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1622 RtlZeroMemory(OemDest
, sizeof(UNICODE_STRING
));
1625 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1627 OemDest
->Length
= (USHORT
)Length
;
1629 if (AllocateDestinationString
)
1631 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1632 OemDest
->MaximumLength
= Length
;
1633 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1635 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1637 return STATUS_BUFFER_OVERFLOW
;
1640 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1646 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1648 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1650 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1651 OemDest
->Buffer
= NULL
;
1661 * Oem string is allways nullterminated
1662 * It performs a partial copy if oem is too small.
1666 RtlUpcaseUnicodeStringToOemString (
1667 IN OUT POEM_STRING OemDest
,
1668 IN PCUNICODE_STRING UniSource
,
1669 IN BOOLEAN AllocateDestinationString
)
1677 Length
= RtlUnicodeStringToOemSize(UniSource
);
1678 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1680 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1682 if (AllocateDestinationString
)
1684 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1685 OemDest
->MaximumLength
= Length
;
1686 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1688 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1690 return STATUS_BUFFER_OVERFLOW
;
1693 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1699 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1701 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1703 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1704 OemDest
->Buffer
= NULL
;
1708 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1716 * Bytes calculated including nullterm
1720 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1724 /* Convert the Mb String to Unicode Size */
1725 RtlMultiByteToUnicodeSize(&Size
,
1729 /* Return the size + null-char */
1730 return (Size
+ sizeof(WCHAR
));
1738 RtlStringFromGUID (IN REFGUID Guid
,
1739 OUT PUNICODE_STRING GuidString
)
1741 /* Setup the string */
1742 GuidString
->Length
= 38 * sizeof(WCHAR
);
1743 GuidString
->MaximumLength
= GuidString
->Length
+ sizeof(UNICODE_NULL
);
1744 GuidString
->Buffer
= RtlpAllocateStringMemory(GuidString
->MaximumLength
,
1746 if (!GuidString
->Buffer
) return STATUS_NO_MEMORY
;
1748 /* Now format the GUID */
1749 swprintf(GuidString
->Buffer
,
1750 L
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1762 return STATUS_SUCCESS
;
1769 * Bytes calculated including nullterm
1773 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1777 /* Convert the Unicode String to Mb Size */
1778 RtlUnicodeToMultiByteSize(&Size
,
1779 UnicodeString
->Buffer
,
1780 UnicodeString
->Length
);
1782 /* Return the size + null-char */
1783 return (Size
+ sizeof(CHAR
));
1791 RtlCompareUnicodeString(
1792 IN PCUNICODE_STRING s1
,
1793 IN PCUNICODE_STRING s2
,
1794 IN BOOLEAN CaseInsensitive
)
1800 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1804 if (CaseInsensitive
)
1806 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1810 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1812 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1822 IN OUT PSTRING DestinationString
,
1823 IN PSTRING SourceString OPTIONAL
)
1828 /* Check if there was no source given */
1831 /* Simply return an empty string */
1832 DestinationString
->Length
= 0;
1836 /* Choose the smallest length */
1837 SourceLength
= min(DestinationString
->MaximumLength
,
1838 SourceString
->Length
);
1841 DestinationString
->Length
= (USHORT
)SourceLength
;
1843 /* Save the pointers to each buffer */
1844 p1
= DestinationString
->Buffer
;
1845 p2
= SourceString
->Buffer
;
1847 /* Loop the buffer */
1848 while (SourceLength
)
1850 /* Copy the character and move on */
1862 RtlCopyUnicodeString(
1863 IN OUT PUNICODE_STRING DestinationString
,
1864 IN PCUNICODE_STRING SourceString
)
1868 if(SourceString
== NULL
)
1870 DestinationString
->Length
= 0;
1874 SourceLength
= min(DestinationString
->MaximumLength
,
1875 SourceString
->Length
);
1876 DestinationString
->Length
= (USHORT
)SourceLength
;
1878 RtlCopyMemory(DestinationString
->Buffer
,
1879 SourceString
->Buffer
,
1882 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
1884 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1893 * Creates a nullterminated UNICODE_STRING
1897 RtlCreateUnicodeString(
1898 IN OUT PUNICODE_STRING UniDest
,
1905 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
1906 if (Length
> 0xFFFE) return FALSE
;
1908 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1910 if (UniDest
->Buffer
== NULL
) return FALSE
;
1912 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
1913 UniDest
->MaximumLength
= (USHORT
)Length
;
1914 UniDest
->Length
= Length
- sizeof (WCHAR
);
1924 RtlCreateUnicodeStringFromAsciiz(
1925 OUT PUNICODE_STRING Destination
,
1928 ANSI_STRING AnsiString
;
1931 RtlInitAnsiString(&AnsiString
, Source
);
1933 Status
= RtlAnsiStringToUnicodeString(Destination
,
1937 return NT_SUCCESS(Status
);
1944 * Dest is never '\0' terminated because it may be equal to src, and src
1945 * might not be '\0' terminated.
1946 * Dest->Length is only set upon success.
1950 RtlDowncaseUnicodeString(
1951 IN OUT PUNICODE_STRING UniDest
,
1952 IN PCUNICODE_STRING UniSource
,
1953 IN BOOLEAN AllocateDestinationString
)
1960 if (AllocateDestinationString
)
1962 UniDest
->MaximumLength
= UniSource
->Length
;
1963 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
1964 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1966 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1968 return STATUS_BUFFER_OVERFLOW
;
1971 UniDest
->Length
= UniSource
->Length
;
1972 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
1974 for (i
= 0 ; i
< StopGap
; i
++)
1976 if (UniSource
->Buffer
[i
] < L
'A')
1978 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
1980 else if (UniSource
->Buffer
[i
] <= L
'Z')
1982 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
1986 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
1990 return STATUS_SUCCESS
;
1997 * if src is NULL dest is unchanged.
1998 * dest is '\0' terminated when the MaximumLength allowes it.
1999 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2003 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2011 UNICODE_STRING UnicodeSource
;
2013 RtlInitUnicodeString(&UnicodeSource
, Source
);
2014 Length
= UnicodeSource
.Length
;
2016 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2018 return STATUS_BUFFER_TOO_SMALL
;
2021 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2022 RtlMoveMemory(DestBuffer
, Source
, Length
);
2023 Destination
->Length
+= Length
;
2025 /* append terminating '\0' if enough space */
2026 if(Destination
->MaximumLength
> Destination
->Length
)
2028 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2032 return STATUS_SUCCESS
;
2039 * if src is NULL dest is unchanged.
2040 * dest is never '\0' terminated.
2044 RtlAppendAsciizToString(
2045 IN OUT PSTRING Destination
,
2052 Length
= (USHORT
)strlen(Source
);
2054 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2056 return STATUS_BUFFER_TOO_SMALL
;
2059 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2060 Destination
->Length
+= Length
;
2063 return STATUS_SUCCESS
;
2071 RtlUpperString(PSTRING DestinationString
,
2072 PSTRING SourceString
)
2077 Length
= min(SourceString
->Length
,
2078 DestinationString
->MaximumLength
);
2080 Src
= SourceString
->Buffer
;
2081 Dest
= DestinationString
->Buffer
;
2082 DestinationString
->Length
= Length
;
2085 *Dest
++ = RtlUpperChar(*Src
++);
2094 * See RtlpDuplicateUnicodeString
2098 RtlDuplicateUnicodeString(
2100 IN PCUNICODE_STRING SourceString
,
2101 OUT PUNICODE_STRING DestinationString
)
2105 if (SourceString
== NULL
|| DestinationString
== NULL
||
2106 SourceString
->Length
> SourceString
->MaximumLength
||
2107 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
2108 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4) {
2109 return STATUS_INVALID_PARAMETER
;
2113 if ((SourceString
->Length
== 0) &&
2114 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2115 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2117 DestinationString
->Length
= 0;
2118 DestinationString
->MaximumLength
= 0;
2119 DestinationString
->Buffer
= NULL
;
2123 UINT DestMaxLength
= SourceString
->Length
;
2125 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2126 DestMaxLength
+= sizeof(UNICODE_NULL
);
2128 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2129 if (DestinationString
->Buffer
== NULL
)
2130 return STATUS_NO_MEMORY
;
2132 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2133 DestinationString
->Length
= SourceString
->Length
;
2134 DestinationString
->MaximumLength
= DestMaxLength
;
2136 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2137 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2140 return STATUS_SUCCESS
;
2147 RtlValidateUnicodeString(IN ULONG Flags
,
2148 IN PCUNICODE_STRING UnicodeString
)
2150 /* currently no flags are supported! */
2154 ((UnicodeString
== NULL
) ||
2155 ((UnicodeString
->Length
!= 0) &&
2156 (UnicodeString
->Buffer
!= NULL
) &&
2157 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2158 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2159 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2161 /* a NULL pointer as a unicode string is considered to be a valid unicode
2163 return STATUS_SUCCESS
;
2167 return STATUS_INVALID_PARAMETER
;