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 #include <wine/unicode.h>
20 /* GLOBALS *******************************************************************/
22 extern BOOLEAN NlsMbCodePageTag
;
23 extern BOOLEAN NlsMbOemCodePageTag
;
24 extern PUSHORT NlsLeadByteInfo
;
26 /* FUNCTIONS *****************************************************************/
33 RtlAnsiCharToUnicodeChar(IN PUCHAR
*AnsiChar
)
37 WCHAR UnicodeChar
= L
' ';
39 Size
= (NlsLeadByteInfo
[**AnsiChar
] == 0) ? 1 : 2;
41 Status
= RtlMultiByteToUnicodeN(&UnicodeChar
,
47 if (!NT_SUCCESS(Status
))
60 * This function always writes a terminating '\0'.
61 * If the dest buffer is too small a partial copy is NOT performed!
65 RtlAnsiStringToUnicodeString(
66 IN OUT PUNICODE_STRING UniDest
,
67 IN PANSI_STRING AnsiSource
,
68 IN BOOLEAN AllocateDestinationString
)
76 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
77 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
78 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
80 if (AllocateDestinationString
)
82 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
83 UniDest
->MaximumLength
= Length
;
84 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
86 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
88 return STATUS_BUFFER_OVERFLOW
;
91 Status
= RtlMultiByteToUnicodeN(UniDest
->Buffer
,
97 if (!NT_SUCCESS(Status
))
99 if (AllocateDestinationString
)
101 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
102 UniDest
->Buffer
= NULL
;
107 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
115 * The calculated size in bytes including nullterm.
119 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString
)
123 /* Convert from Mb String to Unicode Size */
124 RtlMultiByteToUnicodeSize(&Size
,
128 /* Return the size plus the null-char */
129 return(Size
+ sizeof(WCHAR
));
136 * If src->length is zero dest is unchanged.
137 * Dest is never nullterminated.
141 RtlAppendStringToString(IN PSTRING Destination
,
144 USHORT SourceLength
= Source
->Length
;
148 if (Destination
->Length
+ SourceLength
> Destination
->MaximumLength
)
150 return STATUS_BUFFER_TOO_SMALL
;
153 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
],
157 Destination
->Length
+= SourceLength
;
160 return STATUS_SUCCESS
;
167 * If src->length is zero dest is unchanged.
168 * Dest is nullterminated when the MaximumLength allowes it.
169 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
173 RtlAppendUnicodeStringToString(
174 IN OUT PUNICODE_STRING Destination
,
175 IN PCUNICODE_STRING Source
)
177 USHORT SourceLength
= Source
->Length
;
178 PWCHAR Buffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
182 if ((SourceLength
+ Destination
->Length
) > Destination
->MaximumLength
)
184 return STATUS_BUFFER_TOO_SMALL
;
187 RtlMoveMemory(Buffer
, Source
->Buffer
, SourceLength
);
188 Destination
->Length
+= SourceLength
;
190 /* append terminating '\0' if enough space */
191 if (Destination
->MaximumLength
> Destination
->Length
)
193 Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
197 return STATUS_SUCCESS
;
200 /**************************************************************************
201 * RtlCharToInteger (NTDLL.@)
203 * Converts a character string into its integer equivalent.
206 * Success: STATUS_SUCCESS. value contains the converted number
207 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
208 * STATUS_ACCESS_VIOLATION, if value is NULL.
211 * For base 0 it uses 10 as base and the string should be in the format
212 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
213 * For other bases the string should be in the format
214 * "{whitespace} [+|-] {digits}".
215 * No check is made for value overflow, only the lower 32 bits are assigned.
216 * If str is NULL it crashes, as the native function does.
219 * This function does not read garbage behind '\0' as the native version does.
224 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
225 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
226 PULONG value
) /* [O] Destination for the converted value */
230 ULONG RunningTotal
= 0;
233 while (*str
!= '\0' && *str
<= ' ') {
239 } else if (*str
== '-') {
250 } else if (str
[1] == 'o') {
253 } else if (str
[1] == 'x') {
258 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
259 return STATUS_INVALID_PARAMETER
;
263 return STATUS_ACCESS_VIOLATION
;
266 while (*str
!= '\0') {
268 if (chCurrent
>= '0' && chCurrent
<= '9') {
269 digit
= chCurrent
- '0';
270 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
271 digit
= chCurrent
- 'A' + 10;
272 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
273 digit
= chCurrent
- 'a' + 10;
277 if (digit
< 0 || digit
>= (int)base
) {
278 *value
= bMinus
? -RunningTotal
: RunningTotal
;
279 return STATUS_SUCCESS
;
282 RunningTotal
= RunningTotal
* base
+ digit
;
286 *value
= bMinus
? -RunningTotal
: RunningTotal
;
287 return STATUS_SUCCESS
;
298 IN BOOLEAN CaseInsensitive
)
304 len
= min(s1
->Length
, s2
->Length
);
310 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
314 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
316 if (!ret
) ret
= s1
->Length
- s2
->Length
;
324 * TRUE if strings are equal.
331 IN BOOLEAN CaseInsensitive
)
333 if (s1
->Length
!= s2
->Length
) return FALSE
;
334 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
341 * TRUE if strings are equal.
345 RtlEqualUnicodeString(
346 IN CONST UNICODE_STRING
*s1
,
347 IN CONST UNICODE_STRING
*s2
,
348 IN BOOLEAN CaseInsensitive
)
350 if (s1
->Length
!= s2
->Length
) return FALSE
;
351 return !RtlCompareUnicodeString(s1
, s2
, CaseInsensitive
);
359 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
363 if (AnsiString
->Buffer
)
365 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
366 RtlZeroMemory(AnsiString
, sizeof(ANSI_STRING
));
375 RtlFreeOemString(IN POEM_STRING OemString
)
379 if (OemString
->Buffer
) RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
387 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
391 if (UnicodeString
->Buffer
)
393 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_USTR
);
394 RtlZeroMemory(UnicodeString
, sizeof(UNICODE_STRING
));
403 RtlIsValidOemCharacter(IN PWCHAR Char
)
413 * If source is NULL the length of source is assumed to be 0.
417 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
418 IN PCSZ SourceString
)
424 DestSize
= strlen(SourceString
);
425 DestinationString
->Length
= (USHORT
)DestSize
;
426 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
430 DestinationString
->Length
= 0;
431 DestinationString
->MaximumLength
= 0;
434 DestinationString
->Buffer
= (PCHAR
)SourceString
;
439 RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString
,
440 IN PCSZ SourceString
)
446 DestSize
= strlen(SourceString
);
447 if (DestSize
>= 0xFFFF) return STATUS_NAME_TOO_LONG
;
448 DestinationString
->Length
= (USHORT
)DestSize
;
449 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
453 DestinationString
->Length
= 0;
454 DestinationString
->MaximumLength
= 0;
457 DestinationString
->Buffer
= (PCHAR
)SourceString
;
458 return STATUS_SUCCESS
;
465 * If source is NULL the length of source is assumed to be 0.
470 IN OUT PSTRING DestinationString
,
471 IN PCSZ SourceString
)
473 RtlInitAnsiString(DestinationString
, SourceString
);
480 * If source is NULL the length of source is assumed to be 0.
484 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
485 IN PCWSTR SourceString
)
491 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
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
;
509 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
510 IN PCWSTR SourceString
)
516 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
517 if (DestSize
>= 0xFFFC) return STATUS_NAME_TOO_LONG
;
518 DestinationString
->Length
= (USHORT
)DestSize
;
519 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
523 DestinationString
->Length
= 0;
524 DestinationString
->MaximumLength
= 0;
527 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
528 return STATUS_SUCCESS
;
535 * Writes at most length characters to the string str.
536 * Str is nullterminated when length allowes it.
537 * When str fits exactly in length characters the nullterm is ommitted.
539 NTSTATUS NTAPI
RtlIntegerToChar(
540 ULONG value
, /* [I] Value to be converted */
541 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
542 ULONG length
, /* [I] Length of the str buffer in bytes */
543 PCHAR str
) /* [O] Destination for the converted value */
552 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
553 return STATUS_INVALID_PARAMETER
;
561 digit
= value
% base
;
562 value
= value
/ base
;
566 *pos
= 'A' + digit
- 10;
568 } while (value
!= 0L);
570 len
= &buffer
[32] - pos
;
572 return STATUS_BUFFER_OVERFLOW
;
573 } else if (str
== NULL
) {
574 return STATUS_ACCESS_VIOLATION
;
575 } else if (len
== length
) {
576 memcpy(str
, pos
, len
);
578 memcpy(str
, pos
, len
+ 1);
580 return STATUS_SUCCESS
;
590 IN ULONG Base OPTIONAL
,
591 IN ULONG Length OPTIONAL
,
606 if ((Radix
!= 2) && (Radix
!= 8) &&
607 (Radix
!= 10) && (Radix
!= 16))
609 return STATUS_INVALID_PARAMETER
;
613 while (v
|| tp
== temp
)
624 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
626 return STATUS_BUFFER_TOO_SMALL
;
634 return STATUS_SUCCESS
;
642 RtlIntegerToUnicodeString(
644 IN ULONG Base OPTIONAL
,
645 IN OUT PUNICODE_STRING String
)
647 ANSI_STRING AnsiString
;
651 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
652 if (NT_SUCCESS(Status
))
654 AnsiString
.Buffer
= Buffer
;
655 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
656 AnsiString
.MaximumLength
= sizeof(Buffer
);
658 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
669 RtlInt64ToUnicodeString (
671 IN ULONG Base OPTIONAL
,
672 IN OUT PUNICODE_STRING String
)
674 LARGE_INTEGER LargeInt
;
675 ANSI_STRING AnsiString
;
679 LargeInt
.QuadPart
= Value
;
681 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
682 if (NT_SUCCESS(Status
))
684 AnsiString
.Buffer
= Buffer
;
685 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
686 AnsiString
.MaximumLength
= sizeof(Buffer
);
688 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
698 * TRUE if String2 contains String1 as a prefix.
703 PANSI_STRING String1
,
704 PANSI_STRING String2
,
705 BOOLEAN CaseInsensitive
)
711 if (String2
->Length
< String1
->Length
)
714 Length
= String1
->Length
;
715 pc1
= String1
->Buffer
;
716 pc2
= String2
->Buffer
;
724 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
732 if (*pc1
++ != *pc2
++)
745 * TRUE if String2 contains String1 as a prefix.
749 RtlPrefixUnicodeString(
750 PCUNICODE_STRING String1
,
751 PCUNICODE_STRING String2
,
752 BOOLEAN CaseInsensitive
)
758 if (String2
->Length
< String1
->Length
)
761 Length
= String1
->Length
/ 2;
762 pc1
= String1
->Buffer
;
763 pc2
= String2
->Buffer
;
771 if (RtlUpcaseUnicodeChar (*pc1
++)
772 != RtlUpcaseUnicodeChar (*pc2
++))
780 if( *pc1
++ != *pc2
++ )
793 RtlUnicodeStringToInteger(const UNICODE_STRING
*str
, /* [I] Unicode string to be converted */
794 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
795 ULONG
*value
) /* [O] Destination for the converted value */
797 LPWSTR lpwstr
= str
->Buffer
;
798 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
801 ULONG RunningTotal
= 0;
804 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
809 if (CharsRemaining
>= 1) {
810 if (*lpwstr
== '+') {
813 } else if (*lpwstr
== '-') {
822 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
823 if (lpwstr
[1] == 'b') {
827 } else if (lpwstr
[1] == 'o') {
831 } else if (lpwstr
[1] == 'x') {
837 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
838 return STATUS_INVALID_PARAMETER
;
842 return STATUS_ACCESS_VIOLATION
;
845 while (CharsRemaining
>= 1) {
846 wchCurrent
= *lpwstr
;
847 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
848 digit
= wchCurrent
- '0';
849 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
850 digit
= wchCurrent
- 'A' + 10;
851 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
852 digit
= wchCurrent
- 'a' + 10;
856 if (digit
< 0 || digit
>= base
) {
857 *value
= bMinus
? -RunningTotal
: RunningTotal
;
858 return STATUS_SUCCESS
;
861 RunningTotal
= RunningTotal
* base
+ digit
;
866 *value
= bMinus
? -RunningTotal
: RunningTotal
;
867 return STATUS_SUCCESS
;
874 * Bytes necessary for the conversion including nullterm.
878 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
882 /* Convert the Unicode String to Mb Size */
883 RtlUnicodeToMultiByteSize(&Size
,
884 UnicodeString
->Buffer
,
885 UnicodeString
->Length
);
887 /* Return the size + the null char */
888 return (Size
+ sizeof(CHAR
));
895 * This function always writes a terminating '\0'.
896 * It performs a partial copy if ansi is too small.
900 RtlUnicodeStringToAnsiString(
901 IN OUT PANSI_STRING AnsiDest
,
902 IN PCUNICODE_STRING UniSource
,
903 IN BOOLEAN AllocateDestinationString
)
905 NTSTATUS Status
= STATUS_SUCCESS
;
912 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
913 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
915 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
917 if (AllocateDestinationString
)
919 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
920 AnsiDest
->MaximumLength
= Length
;
921 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
923 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
925 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
927 Status
= STATUS_BUFFER_OVERFLOW
;
928 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
931 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
937 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
939 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
943 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
951 * This function always writes a terminating '\0'.
952 * Does NOT perform a partial copy if unicode is too small!
956 RtlOemStringToUnicodeString(
957 IN OUT PUNICODE_STRING UniDest
,
958 IN PCOEM_STRING OemSource
,
959 IN BOOLEAN AllocateDestinationString
)
967 Length
= RtlOemStringToUnicodeSize(OemSource
);
968 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
970 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
972 if (AllocateDestinationString
)
974 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
975 UniDest
->MaximumLength
= Length
;
976 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
978 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
980 return STATUS_BUFFER_OVERFLOW
;
983 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
989 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
991 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
992 UniDest
->Buffer
= NULL
;
996 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1004 * This function always '\0' terminates the string returned.
1008 RtlUnicodeStringToOemString(
1009 IN OUT POEM_STRING OemDest
,
1010 IN PCUNICODE_STRING UniSource
,
1011 IN BOOLEAN AllocateDestinationString
)
1019 Length
= RtlUnicodeStringToOemSize(UniSource
);
1020 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1022 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1024 if (AllocateDestinationString
)
1026 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1027 OemDest
->MaximumLength
= Length
;
1028 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1030 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1032 return STATUS_BUFFER_OVERFLOW
;
1035 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1041 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1043 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1044 OemDest
->Buffer
= NULL
;
1048 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1052 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1058 * The length of the string if all tests were passed, 0 otherwise.
1062 RtlIsTextUnicode( PVOID buf
, INT len
, INT
*pf
)
1064 static const WCHAR std_control_chars
[] = {'\r','\n','\t',' ',0x3000,0};
1065 static const WCHAR byterev_control_chars
[] = {0x0d00,0x0a00,0x0900,0x2000,0};
1066 const WCHAR
*s
= buf
;
1068 unsigned int flags
= ~0U, out_flags
= 0;
1070 if (len
< sizeof(WCHAR
))
1072 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
1079 * Apply various tests to the text string. According to the
1080 * docs, each test "passed" sets the corresponding flag in
1081 * the output flags. But some of the tests are mutually
1082 * exclusive, so I don't see how you could pass all tests ...
1085 /* Check for an odd length ... pass if even. */
1086 if (len
& 1) out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1088 if (((char *)buf
)[len
- 1] == 0)
1089 len
--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
1091 len
/= sizeof(WCHAR
);
1092 /* Windows only checks the first 256 characters */
1093 if (len
> 256) len
= 256;
1095 /* Check for the special byte order unicode marks. */
1096 if (*s
== 0xFEFF) out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1097 if (*s
== 0xFFFE) out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1099 /* apply some statistical analysis */
1100 if (flags
& IS_TEXT_UNICODE_STATISTICS
)
1103 /* FIXME: checks only for ASCII characters in the unicode stream */
1104 for (i
= 0; i
< len
; i
++)
1106 if (s
[i
] <= 255) stats
++;
1108 if (stats
> len
/ 2)
1109 out_flags
|= IS_TEXT_UNICODE_STATISTICS
;
1112 /* Check for unicode NULL chars */
1113 if (flags
& IS_TEXT_UNICODE_NULL_BYTES
)
1115 for (i
= 0; i
< len
; i
++)
1117 if (!(s
[i
] & 0xff) || !(s
[i
] >> 8))
1119 out_flags
|= IS_TEXT_UNICODE_NULL_BYTES
;
1125 if (flags
& IS_TEXT_UNICODE_CONTROLS
)
1127 for (i
= 0; i
< len
; i
++)
1129 if (strchrW(std_control_chars
, s
[i
]))
1131 out_flags
|= IS_TEXT_UNICODE_CONTROLS
;
1137 if (flags
& IS_TEXT_UNICODE_REVERSE_CONTROLS
)
1139 for (i
= 0; i
< len
; i
++)
1141 if (strchrW(byterev_control_chars
, s
[i
]))
1143 out_flags
|= IS_TEXT_UNICODE_REVERSE_CONTROLS
;
1154 /* check for flags that indicate it's definitely not valid Unicode */
1155 if (out_flags
& (IS_TEXT_UNICODE_REVERSE_MASK
| IS_TEXT_UNICODE_NOT_UNICODE_MASK
)) return FALSE
;
1156 /* now check for invalid ASCII, and assume Unicode if so */
1157 if (out_flags
& IS_TEXT_UNICODE_NOT_ASCII_MASK
) return TRUE
;
1158 /* now check for Unicode flags */
1159 if (out_flags
& IS_TEXT_UNICODE_UNICODE_MASK
) return TRUE
;
1169 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1170 * A partial copy is NOT performed if the dest buffer is too small!
1174 RtlOemStringToCountedUnicodeString(
1175 IN OUT PUNICODE_STRING UniDest
,
1176 IN PCOEM_STRING OemSource
,
1177 IN BOOLEAN AllocateDestinationString
)
1185 /* Calculate size of the string */
1186 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1188 /* If it's 0 then zero out dest string and return */
1191 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1192 return STATUS_SUCCESS
;
1195 /* Check if length is a sane value */
1196 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1198 /* Store it in dest string */
1199 UniDest
->Length
= (USHORT
)Length
;
1201 /* If we're asked to alloc the string - do so */
1202 if (AllocateDestinationString
)
1204 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1205 UniDest
->MaximumLength
= Length
;
1206 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1208 else if (UniDest
->Length
> UniDest
->MaximumLength
)
1210 return STATUS_BUFFER_OVERFLOW
;
1213 /* Do the conversion */
1214 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1220 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1222 /* Conversion failed, free dest string and return status code */
1223 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1224 UniDest
->Buffer
= NULL
;
1228 return STATUS_SUCCESS
;
1235 * TRUE if the names are equal, FALSE if not
1238 * The comparison is case insensitive.
1242 RtlEqualComputerName(
1243 IN PUNICODE_STRING ComputerName1
,
1244 IN PUNICODE_STRING ComputerName2
)
1246 OEM_STRING OemString1
;
1247 OEM_STRING OemString2
;
1248 BOOLEAN Result
= FALSE
;
1250 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1254 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1258 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1259 RtlFreeOemString(&OemString2
);
1261 RtlFreeOemString(&OemString1
);
1271 * TRUE if the names are equal, FALSE if not
1274 * The comparison is case insensitive.
1278 RtlEqualDomainName (
1279 IN PUNICODE_STRING DomainName1
,
1280 IN PUNICODE_STRING DomainName2
1283 return RtlEqualComputerName(DomainName1
, DomainName2
);
1289 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1291 * Convert a string representation of a GUID into a GUID.
1294 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1295 * guid [O] Destination for the converted GUID
1298 * Success: STATUS_SUCCESS. guid contains the converted value.
1299 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1302 * See RtlStringFromGUID.
1307 IN UNICODE_STRING
*str
,
1312 const WCHAR
*lpszCLSID
= str
->Buffer
;
1313 BYTE
* lpOut
= (BYTE
*)guid
;
1315 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1317 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1318 * to memory: DWORD... WORD WORD BYTES............
1325 if (*lpszCLSID
!= '{')
1326 return STATUS_INVALID_PARAMETER
;
1333 if (*lpszCLSID
!= '-')
1334 return STATUS_INVALID_PARAMETER
;
1338 if (*lpszCLSID
!= '}')
1339 return STATUS_INVALID_PARAMETER
;
1344 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1347 /* Read two hex digits as a byte value */
1348 if (ch
>= '0' && ch
<= '9')
1350 else if (ch
>= 'a' && ch
<= 'f')
1352 else if (ch
>= 'A' && ch
<= 'F')
1355 return STATUS_INVALID_PARAMETER
;
1357 if (ch2
>= '0' && ch2
<= '9')
1359 else if (ch2
>= 'a' && ch2
<= 'f')
1360 ch2
= ch2
- 'a' + 10;
1361 else if (ch2
>= 'A' && ch2
<= 'F')
1362 ch2
= ch2
- 'A' + 10;
1364 return STATUS_INVALID_PARAMETER
;
1366 byte
= ch
<< 4 | ch2
;
1370 #ifndef WORDS_BIGENDIAN
1371 /* For Big Endian machines, we store the data such that the
1372 * dword/word members can be read as DWORDS and WORDS correctly. */
1404 lpszCLSID
++; /* Skip 2nd character of byte */
1412 return STATUS_SUCCESS
;
1420 RtlEraseUnicodeString(
1421 IN PUNICODE_STRING String
)
1423 if (String
->Buffer
&& String
->MaximumLength
)
1425 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1435 RtlHashUnicodeString(
1436 IN CONST UNICODE_STRING
*String
,
1437 IN BOOLEAN CaseInSensitive
,
1438 IN ULONG HashAlgorithm
,
1439 OUT PULONG HashValue
)
1441 if (String
!= NULL
&& HashValue
!= NULL
)
1443 switch (HashAlgorithm
)
1445 case HASH_STRING_ALGORITHM_DEFAULT
:
1446 case HASH_STRING_ALGORITHM_X65599
:
1451 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1453 if (CaseInSensitive
)
1455 for (c
= String
->Buffer
;
1459 /* only uppercase characters if they are 'a' ... 'z'! */
1460 *HashValue
= ((65599 * (*HashValue
)) +
1461 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1462 (*c
) - L
'a' + L
'A' : (*c
)));
1467 for (c
= String
->Buffer
;
1471 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1474 return STATUS_SUCCESS
;
1479 return STATUS_INVALID_PARAMETER
;
1486 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1487 * Does a partial copy if the dest buffer is too small
1491 RtlUnicodeStringToCountedOemString(
1492 IN OUT POEM_STRING OemDest
,
1493 IN PUNICODE_STRING UniSource
,
1494 IN BOOLEAN AllocateDestinationString
)
1502 /* Calculate size of the string */
1503 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1505 /* If it's 0 then zero out dest string and return */
1508 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1509 return STATUS_SUCCESS
;
1512 /* Check if length is a sane value */
1513 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1515 /* Store it in dest string */
1516 OemDest
->Length
= (USHORT
)Length
;
1518 /* If we're asked to alloc the string - do so */
1519 if (AllocateDestinationString
)
1521 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1522 OemDest
->MaximumLength
= Length
;
1523 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1525 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1527 return STATUS_BUFFER_OVERFLOW
;
1530 /* Do the conversion */
1531 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1537 /* FIXME: Check if everything mapped correctly and
1538 * return STATUS_UNMAPPABLE_CHARACTER */
1540 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1542 /* Conversion failed, free dest string and return status code */
1543 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1544 OemDest
->Buffer
= NULL
;
1556 RtlLargeIntegerToChar(
1557 IN PLARGE_INTEGER Value
,
1560 IN OUT PCHAR String
)
1562 NTSTATUS Status
= STATUS_SUCCESS
;
1565 ULONGLONG v
= Value
->QuadPart
;
1574 if ((Radix
!= 2) && (Radix
!= 8) &&
1575 (Radix
!= 10) && (Radix
!= 16))
1576 return STATUS_INVALID_PARAMETER
;
1579 while (v
|| tp
== temp
)
1590 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) > Length
)
1591 return STATUS_BUFFER_OVERFLOW
;
1599 if((ULONG
)((ULONG_PTR
)sp
- (ULONG_PTR
)String
) < Length
)
1603 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1605 /* Get the error code */
1606 Status
= _SEH2_GetExceptionCode();
1618 * dest is never '\0' terminated because it may be equal to src, and src
1619 * might not be '\0' terminated. dest->Length is only set upon success.
1623 RtlUpcaseUnicodeString(
1624 IN OUT PUNICODE_STRING UniDest
,
1625 IN PCUNICODE_STRING UniSource
,
1626 IN BOOLEAN AllocateDestinationString
)
1632 if (AllocateDestinationString
== TRUE
)
1634 UniDest
->MaximumLength
= UniSource
->Length
;
1635 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1636 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1638 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1640 return STATUS_BUFFER_OVERFLOW
;
1643 j
= UniSource
->Length
/ sizeof(WCHAR
);
1645 for (i
= 0; i
< j
; i
++)
1647 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1650 UniDest
->Length
= UniSource
->Length
;
1651 return STATUS_SUCCESS
;
1658 * This function always writes a terminating '\0'.
1659 * It performs a partial copy if ansi is too small.
1663 RtlUpcaseUnicodeStringToAnsiString(
1664 IN OUT PANSI_STRING AnsiDest
,
1665 IN PUNICODE_STRING UniSource
,
1666 IN BOOLEAN AllocateDestinationString
)
1674 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1675 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1677 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1679 if (AllocateDestinationString
)
1681 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1682 AnsiDest
->MaximumLength
= Length
;
1683 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1685 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1687 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1690 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1696 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1698 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1699 AnsiDest
->Buffer
= NULL
;
1703 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1711 * This function always writes a terminating '\0'.
1712 * It performs a partial copy if ansi is too small.
1716 RtlUpcaseUnicodeStringToCountedOemString(
1717 IN OUT POEM_STRING OemDest
,
1718 IN PCUNICODE_STRING UniSource
,
1719 IN BOOLEAN AllocateDestinationString
)
1727 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1731 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1734 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1736 OemDest
->Length
= (USHORT
)Length
;
1738 if (AllocateDestinationString
)
1740 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1741 OemDest
->MaximumLength
= Length
;
1742 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1744 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1746 return STATUS_BUFFER_OVERFLOW
;
1749 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1755 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1757 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1759 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1760 OemDest
->Buffer
= NULL
;
1770 * Oem string is allways nullterminated
1771 * It performs a partial copy if oem is too small.
1775 RtlUpcaseUnicodeStringToOemString (
1776 IN OUT POEM_STRING OemDest
,
1777 IN PCUNICODE_STRING UniSource
,
1778 IN BOOLEAN AllocateDestinationString
)
1786 Length
= RtlUnicodeStringToOemSize(UniSource
);
1787 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1789 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1791 if (AllocateDestinationString
)
1793 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1794 OemDest
->MaximumLength
= Length
;
1795 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1797 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1799 return STATUS_BUFFER_OVERFLOW
;
1802 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1808 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1810 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1812 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1813 OemDest
->Buffer
= NULL
;
1817 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1825 * Bytes calculated including nullterm
1829 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1833 /* Convert the Mb String to Unicode Size */
1834 RtlMultiByteToUnicodeSize(&Size
,
1838 /* Return the size + null-char */
1839 return (Size
+ sizeof(WCHAR
));
1847 RtlStringFromGUID (IN REFGUID Guid
,
1848 OUT PUNICODE_STRING GuidString
)
1850 /* Setup the string */
1851 GuidString
->Length
= 38 * sizeof(WCHAR
);
1852 GuidString
->MaximumLength
= GuidString
->Length
+ sizeof(UNICODE_NULL
);
1853 GuidString
->Buffer
= RtlpAllocateStringMemory(GuidString
->MaximumLength
,
1855 if (!GuidString
->Buffer
) return STATUS_NO_MEMORY
;
1857 /* Now format the GUID */
1858 swprintf(GuidString
->Buffer
,
1859 L
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1871 return STATUS_SUCCESS
;
1878 * Bytes calculated including nullterm
1882 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1886 /* Convert the Unicode String to Mb Size */
1887 RtlUnicodeToMultiByteSize(&Size
,
1888 UnicodeString
->Buffer
,
1889 UnicodeString
->Length
);
1891 /* Return the size + null-char */
1892 return (Size
+ sizeof(CHAR
));
1900 RtlCompareUnicodeString(
1901 IN PCUNICODE_STRING s1
,
1902 IN PCUNICODE_STRING s2
,
1903 IN BOOLEAN CaseInsensitive
)
1909 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1913 if (CaseInsensitive
)
1915 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1919 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1921 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1931 IN OUT PSTRING DestinationString
,
1932 IN PSTRING SourceString OPTIONAL
)
1937 /* Check if there was no source given */
1940 /* Simply return an empty string */
1941 DestinationString
->Length
= 0;
1945 /* Choose the smallest length */
1946 SourceLength
= min(DestinationString
->MaximumLength
,
1947 SourceString
->Length
);
1950 DestinationString
->Length
= (USHORT
)SourceLength
;
1952 /* Save the pointers to each buffer */
1953 p1
= DestinationString
->Buffer
;
1954 p2
= SourceString
->Buffer
;
1956 /* Loop the buffer */
1957 while (SourceLength
)
1959 /* Copy the character and move on */
1971 RtlCopyUnicodeString(
1972 IN OUT PUNICODE_STRING DestinationString
,
1973 IN PCUNICODE_STRING SourceString
)
1977 if(SourceString
== NULL
)
1979 DestinationString
->Length
= 0;
1983 SourceLength
= min(DestinationString
->MaximumLength
,
1984 SourceString
->Length
);
1985 DestinationString
->Length
= (USHORT
)SourceLength
;
1987 RtlCopyMemory(DestinationString
->Buffer
,
1988 SourceString
->Buffer
,
1991 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
1993 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2002 * Creates a nullterminated UNICODE_STRING
2006 RtlCreateUnicodeString(
2007 IN OUT PUNICODE_STRING UniDest
,
2014 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
2015 if (Length
> 0xFFFE) return FALSE
;
2017 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2019 if (UniDest
->Buffer
== NULL
) return FALSE
;
2021 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
2022 UniDest
->MaximumLength
= (USHORT
)Length
;
2023 UniDest
->Length
= Length
- sizeof (WCHAR
);
2033 RtlCreateUnicodeStringFromAsciiz(
2034 OUT PUNICODE_STRING Destination
,
2037 ANSI_STRING AnsiString
;
2040 RtlInitAnsiString(&AnsiString
, Source
);
2042 Status
= RtlAnsiStringToUnicodeString(Destination
,
2046 return NT_SUCCESS(Status
);
2053 * Dest is never '\0' terminated because it may be equal to src, and src
2054 * might not be '\0' terminated.
2055 * Dest->Length is only set upon success.
2059 RtlDowncaseUnicodeString(
2060 IN OUT PUNICODE_STRING UniDest
,
2061 IN PCUNICODE_STRING UniSource
,
2062 IN BOOLEAN AllocateDestinationString
)
2069 if (AllocateDestinationString
)
2071 UniDest
->MaximumLength
= UniSource
->Length
;
2072 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2073 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2075 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2077 return STATUS_BUFFER_OVERFLOW
;
2080 UniDest
->Length
= UniSource
->Length
;
2081 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2083 for (i
= 0 ; i
< StopGap
; i
++)
2085 if (UniSource
->Buffer
[i
] < L
'A')
2087 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2089 else if (UniSource
->Buffer
[i
] <= L
'Z')
2091 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2095 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2099 return STATUS_SUCCESS
;
2106 * if src is NULL dest is unchanged.
2107 * dest is '\0' terminated when the MaximumLength allowes it.
2108 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2112 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2120 UNICODE_STRING UnicodeSource
;
2122 RtlInitUnicodeString(&UnicodeSource
, Source
);
2123 Length
= UnicodeSource
.Length
;
2125 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2127 return STATUS_BUFFER_TOO_SMALL
;
2130 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2131 RtlMoveMemory(DestBuffer
, Source
, Length
);
2132 Destination
->Length
+= Length
;
2134 /* append terminating '\0' if enough space */
2135 if(Destination
->MaximumLength
> Destination
->Length
)
2137 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2141 return STATUS_SUCCESS
;
2148 * if src is NULL dest is unchanged.
2149 * dest is never '\0' terminated.
2153 RtlAppendAsciizToString(
2154 IN OUT PSTRING Destination
,
2161 Length
= (USHORT
)strlen(Source
);
2163 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2165 return STATUS_BUFFER_TOO_SMALL
;
2168 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2169 Destination
->Length
+= Length
;
2172 return STATUS_SUCCESS
;
2180 RtlUpperString(PSTRING DestinationString
,
2181 PSTRING SourceString
)
2186 Length
= min(SourceString
->Length
,
2187 DestinationString
->MaximumLength
);
2189 Src
= SourceString
->Buffer
;
2190 Dest
= DestinationString
->Buffer
;
2191 DestinationString
->Length
= Length
;
2194 *Dest
++ = RtlUpperChar(*Src
++);
2203 * See RtlpDuplicateUnicodeString
2207 RtlDuplicateUnicodeString(
2209 IN PCUNICODE_STRING SourceString
,
2210 OUT PUNICODE_STRING DestinationString
)
2214 if (SourceString
== NULL
|| DestinationString
== NULL
||
2215 SourceString
->Length
> SourceString
->MaximumLength
||
2216 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
2217 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4) {
2218 return STATUS_INVALID_PARAMETER
;
2222 if ((SourceString
->Length
== 0) &&
2223 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2224 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2226 DestinationString
->Length
= 0;
2227 DestinationString
->MaximumLength
= 0;
2228 DestinationString
->Buffer
= NULL
;
2232 UINT DestMaxLength
= SourceString
->Length
;
2234 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2235 DestMaxLength
+= sizeof(UNICODE_NULL
);
2237 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2238 if (DestinationString
->Buffer
== NULL
)
2239 return STATUS_NO_MEMORY
;
2241 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2242 DestinationString
->Length
= SourceString
->Length
;
2243 DestinationString
->MaximumLength
= DestMaxLength
;
2245 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2246 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2249 return STATUS_SUCCESS
;
2256 RtlValidateUnicodeString(IN ULONG Flags
,
2257 IN PCUNICODE_STRING UnicodeString
)
2259 /* currently no flags are supported! */
2263 ((UnicodeString
== NULL
) ||
2264 ((UnicodeString
->Length
!= 0) &&
2265 (UnicodeString
->Buffer
!= NULL
) &&
2266 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2267 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2268 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2270 /* a NULL pointer as a unicode string is considered to be a valid unicode
2272 return STATUS_SUCCESS
;
2276 return STATUS_INVALID_PARAMETER
;
2282 RtlFindCharInUnicodeString(IN ULONG Flags
,
2283 IN PUNICODE_STRING SearchString
,
2284 IN PCUNICODE_STRING MatchString
,
2285 OUT PUSHORT Position
)
2288 unsigned int search_idx
;
2294 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2296 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2298 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2300 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2301 return STATUS_SUCCESS
;
2306 return STATUS_NOT_FOUND
;
2311 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2313 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2315 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2317 *Position
= main_idx
* sizeof(WCHAR
);
2318 return STATUS_SUCCESS
;
2323 return STATUS_NOT_FOUND
;
2328 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2331 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2332 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2336 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2338 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2339 return STATUS_SUCCESS
;
2343 return STATUS_NOT_FOUND
;
2348 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2351 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2352 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2356 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2358 *Position
= main_idx
* sizeof(WCHAR
);
2359 return STATUS_SUCCESS
;
2363 return STATUS_NOT_FOUND
;
2367 return STATUS_NOT_FOUND
;