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 ULONGLONG Val
= Value
->QuadPart
;
1563 NTSTATUS Status
= STATUS_SUCCESS
;
1569 if (Base
== 0) Base
= 10;
1571 if ((Base
!= 2) && (Base
!= 8) &&
1572 (Base
!= 10) && (Base
!= 16))
1574 return STATUS_INVALID_PARAMETER
;
1588 *Pos
= 'A' + Digit
- 10;
1592 Len
= &Buffer
[64] - Pos
;
1595 return STATUS_BUFFER_OVERFLOW
;
1597 #if 1 /* It needs to be removed, when will probably use SEH in rtl */
1600 return STATUS_ACCESS_VIOLATION
;
1609 RtlCopyMemory(String
, Pos
, Len
);
1611 RtlCopyMemory(String
, Pos
, Len
+ 1);
1614 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1616 /* Get the error code */
1617 Status
= _SEH2_GetExceptionCode();
1629 * dest is never '\0' terminated because it may be equal to src, and src
1630 * might not be '\0' terminated. dest->Length is only set upon success.
1634 RtlUpcaseUnicodeString(
1635 IN OUT PUNICODE_STRING UniDest
,
1636 IN PCUNICODE_STRING UniSource
,
1637 IN BOOLEAN AllocateDestinationString
)
1643 if (AllocateDestinationString
== TRUE
)
1645 UniDest
->MaximumLength
= UniSource
->Length
;
1646 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1647 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1649 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1651 return STATUS_BUFFER_OVERFLOW
;
1654 j
= UniSource
->Length
/ sizeof(WCHAR
);
1656 for (i
= 0; i
< j
; i
++)
1658 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1661 UniDest
->Length
= UniSource
->Length
;
1662 return STATUS_SUCCESS
;
1669 * This function always writes a terminating '\0'.
1670 * It performs a partial copy if ansi is too small.
1674 RtlUpcaseUnicodeStringToAnsiString(
1675 IN OUT PANSI_STRING AnsiDest
,
1676 IN PUNICODE_STRING UniSource
,
1677 IN BOOLEAN AllocateDestinationString
)
1685 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1686 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1688 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1690 if (AllocateDestinationString
)
1692 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1693 AnsiDest
->MaximumLength
= Length
;
1694 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1696 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1698 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1701 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1707 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1709 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1710 AnsiDest
->Buffer
= NULL
;
1714 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1722 * This function always writes a terminating '\0'.
1723 * It performs a partial copy if ansi is too small.
1727 RtlUpcaseUnicodeStringToCountedOemString(
1728 IN OUT POEM_STRING OemDest
,
1729 IN PCUNICODE_STRING UniSource
,
1730 IN BOOLEAN AllocateDestinationString
)
1738 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1742 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1745 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1747 OemDest
->Length
= (USHORT
)Length
;
1749 if (AllocateDestinationString
)
1751 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1752 OemDest
->MaximumLength
= Length
;
1753 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1755 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1757 return STATUS_BUFFER_OVERFLOW
;
1760 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1766 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1768 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1770 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1771 OemDest
->Buffer
= NULL
;
1781 * Oem string is allways nullterminated
1782 * It performs a partial copy if oem is too small.
1786 RtlUpcaseUnicodeStringToOemString (
1787 IN OUT POEM_STRING OemDest
,
1788 IN PCUNICODE_STRING UniSource
,
1789 IN BOOLEAN AllocateDestinationString
)
1797 Length
= RtlUnicodeStringToOemSize(UniSource
);
1798 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1800 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1802 if (AllocateDestinationString
)
1804 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1805 OemDest
->MaximumLength
= Length
;
1806 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1808 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1810 return STATUS_BUFFER_OVERFLOW
;
1813 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1819 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1821 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1823 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1824 OemDest
->Buffer
= NULL
;
1828 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1836 * Bytes calculated including nullterm
1840 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1844 /* Convert the Mb String to Unicode Size */
1845 RtlMultiByteToUnicodeSize(&Size
,
1849 /* Return the size + null-char */
1850 return (Size
+ sizeof(WCHAR
));
1858 RtlStringFromGUID (IN REFGUID Guid
,
1859 OUT PUNICODE_STRING GuidString
)
1861 /* Setup the string */
1862 GuidString
->Length
= 38 * sizeof(WCHAR
);
1863 GuidString
->MaximumLength
= GuidString
->Length
+ sizeof(UNICODE_NULL
);
1864 GuidString
->Buffer
= RtlpAllocateStringMemory(GuidString
->MaximumLength
,
1866 if (!GuidString
->Buffer
) return STATUS_NO_MEMORY
;
1868 /* Now format the GUID */
1869 swprintf(GuidString
->Buffer
,
1870 L
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1882 return STATUS_SUCCESS
;
1889 * Bytes calculated including nullterm
1893 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1897 /* Convert the Unicode String to Mb Size */
1898 RtlUnicodeToMultiByteSize(&Size
,
1899 UnicodeString
->Buffer
,
1900 UnicodeString
->Length
);
1902 /* Return the size + null-char */
1903 return (Size
+ sizeof(CHAR
));
1911 RtlCompareUnicodeString(
1912 IN PCUNICODE_STRING s1
,
1913 IN PCUNICODE_STRING s2
,
1914 IN BOOLEAN CaseInsensitive
)
1920 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1924 if (CaseInsensitive
)
1926 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1930 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1932 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1942 IN OUT PSTRING DestinationString
,
1943 IN PSTRING SourceString OPTIONAL
)
1948 /* Check if there was no source given */
1951 /* Simply return an empty string */
1952 DestinationString
->Length
= 0;
1956 /* Choose the smallest length */
1957 SourceLength
= min(DestinationString
->MaximumLength
,
1958 SourceString
->Length
);
1961 DestinationString
->Length
= (USHORT
)SourceLength
;
1963 /* Save the pointers to each buffer */
1964 p1
= DestinationString
->Buffer
;
1965 p2
= SourceString
->Buffer
;
1967 /* Loop the buffer */
1968 while (SourceLength
)
1970 /* Copy the character and move on */
1982 RtlCopyUnicodeString(
1983 IN OUT PUNICODE_STRING DestinationString
,
1984 IN PCUNICODE_STRING SourceString
)
1988 if(SourceString
== NULL
)
1990 DestinationString
->Length
= 0;
1994 SourceLength
= min(DestinationString
->MaximumLength
,
1995 SourceString
->Length
);
1996 DestinationString
->Length
= (USHORT
)SourceLength
;
1998 RtlCopyMemory(DestinationString
->Buffer
,
1999 SourceString
->Buffer
,
2002 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
2004 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2013 * Creates a nullterminated UNICODE_STRING
2017 RtlCreateUnicodeString(
2018 IN OUT PUNICODE_STRING UniDest
,
2025 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
2026 if (Length
> 0xFFFE) return FALSE
;
2028 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2030 if (UniDest
->Buffer
== NULL
) return FALSE
;
2032 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
2033 UniDest
->MaximumLength
= (USHORT
)Length
;
2034 UniDest
->Length
= Length
- sizeof (WCHAR
);
2044 RtlCreateUnicodeStringFromAsciiz(
2045 OUT PUNICODE_STRING Destination
,
2048 ANSI_STRING AnsiString
;
2051 RtlInitAnsiString(&AnsiString
, Source
);
2053 Status
= RtlAnsiStringToUnicodeString(Destination
,
2057 return NT_SUCCESS(Status
);
2064 * Dest is never '\0' terminated because it may be equal to src, and src
2065 * might not be '\0' terminated.
2066 * Dest->Length is only set upon success.
2070 RtlDowncaseUnicodeString(
2071 IN OUT PUNICODE_STRING UniDest
,
2072 IN PCUNICODE_STRING UniSource
,
2073 IN BOOLEAN AllocateDestinationString
)
2080 if (AllocateDestinationString
)
2082 UniDest
->MaximumLength
= UniSource
->Length
;
2083 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2084 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2086 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2088 return STATUS_BUFFER_OVERFLOW
;
2091 UniDest
->Length
= UniSource
->Length
;
2092 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2094 for (i
= 0 ; i
< StopGap
; i
++)
2096 if (UniSource
->Buffer
[i
] < L
'A')
2098 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2100 else if (UniSource
->Buffer
[i
] <= L
'Z')
2102 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2106 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2110 return STATUS_SUCCESS
;
2117 * if src is NULL dest is unchanged.
2118 * dest is '\0' terminated when the MaximumLength allowes it.
2119 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2123 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2131 UNICODE_STRING UnicodeSource
;
2133 RtlInitUnicodeString(&UnicodeSource
, Source
);
2134 Length
= UnicodeSource
.Length
;
2136 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2138 return STATUS_BUFFER_TOO_SMALL
;
2141 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2142 RtlMoveMemory(DestBuffer
, Source
, Length
);
2143 Destination
->Length
+= Length
;
2145 /* append terminating '\0' if enough space */
2146 if(Destination
->MaximumLength
> Destination
->Length
)
2148 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2152 return STATUS_SUCCESS
;
2159 * if src is NULL dest is unchanged.
2160 * dest is never '\0' terminated.
2164 RtlAppendAsciizToString(
2165 IN OUT PSTRING Destination
,
2172 Length
= (USHORT
)strlen(Source
);
2174 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2176 return STATUS_BUFFER_TOO_SMALL
;
2179 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2180 Destination
->Length
+= Length
;
2183 return STATUS_SUCCESS
;
2191 RtlUpperString(PSTRING DestinationString
,
2192 PSTRING SourceString
)
2197 Length
= min(SourceString
->Length
,
2198 DestinationString
->MaximumLength
);
2200 Src
= SourceString
->Buffer
;
2201 Dest
= DestinationString
->Buffer
;
2202 DestinationString
->Length
= Length
;
2205 *Dest
++ = RtlUpperChar(*Src
++);
2214 * See RtlpDuplicateUnicodeString
2218 RtlDuplicateUnicodeString(
2220 IN PCUNICODE_STRING SourceString
,
2221 OUT PUNICODE_STRING DestinationString
)
2225 if (SourceString
== NULL
|| DestinationString
== NULL
||
2226 SourceString
->Length
> SourceString
->MaximumLength
||
2227 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
2228 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4) {
2229 return STATUS_INVALID_PARAMETER
;
2233 if ((SourceString
->Length
== 0) &&
2234 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2235 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2237 DestinationString
->Length
= 0;
2238 DestinationString
->MaximumLength
= 0;
2239 DestinationString
->Buffer
= NULL
;
2243 UINT DestMaxLength
= SourceString
->Length
;
2245 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2246 DestMaxLength
+= sizeof(UNICODE_NULL
);
2248 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2249 if (DestinationString
->Buffer
== NULL
)
2250 return STATUS_NO_MEMORY
;
2252 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2253 DestinationString
->Length
= SourceString
->Length
;
2254 DestinationString
->MaximumLength
= DestMaxLength
;
2256 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2257 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2260 return STATUS_SUCCESS
;
2267 RtlValidateUnicodeString(IN ULONG Flags
,
2268 IN PCUNICODE_STRING UnicodeString
)
2270 /* currently no flags are supported! */
2274 ((UnicodeString
== NULL
) ||
2275 ((UnicodeString
->Length
!= 0) &&
2276 (UnicodeString
->Buffer
!= NULL
) &&
2277 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2278 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2279 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2281 /* a NULL pointer as a unicode string is considered to be a valid unicode
2283 return STATUS_SUCCESS
;
2287 return STATUS_INVALID_PARAMETER
;
2293 RtlFindCharInUnicodeString(IN ULONG Flags
,
2294 IN PUNICODE_STRING SearchString
,
2295 IN PCUNICODE_STRING MatchString
,
2296 OUT PUSHORT Position
)
2299 unsigned int search_idx
;
2305 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2307 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2309 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2311 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2312 return STATUS_SUCCESS
;
2317 return STATUS_NOT_FOUND
;
2322 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2324 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2326 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2328 *Position
= main_idx
* sizeof(WCHAR
);
2329 return STATUS_SUCCESS
;
2334 return STATUS_NOT_FOUND
;
2339 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2342 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2343 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2347 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2349 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2350 return STATUS_SUCCESS
;
2354 return STATUS_NOT_FOUND
;
2359 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2362 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2363 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2367 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2369 *Position
= main_idx
* sizeof(WCHAR
);
2370 return STATUS_SUCCESS
;
2374 return STATUS_NOT_FOUND
;
2378 return STATUS_NOT_FOUND
;