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_USTR
);
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
;
437 RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString
,
438 IN PCSZ SourceString
)
444 DestSize
= strlen(SourceString
);
445 if (DestSize
>= 0xFFFF) return STATUS_NAME_TOO_LONG
;
446 DestinationString
->Length
= (USHORT
)DestSize
;
447 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
451 DestinationString
->Length
= 0;
452 DestinationString
->MaximumLength
= 0;
455 DestinationString
->Buffer
= (PCHAR
)SourceString
;
456 return STATUS_SUCCESS
;
463 * If source is NULL the length of source is assumed to be 0.
468 IN OUT PSTRING DestinationString
,
469 IN PCSZ SourceString
)
471 RtlInitAnsiString(DestinationString
, SourceString
);
478 * If source is NULL the length of source is assumed to be 0.
482 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
483 IN PCWSTR SourceString
)
489 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
490 DestinationString
->Length
= (USHORT
)DestSize
;
491 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
495 DestinationString
->Length
= 0;
496 DestinationString
->MaximumLength
= 0;
499 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
507 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
508 IN PCWSTR SourceString
)
514 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
515 if (DestSize
>= 0xFFFC) return STATUS_NAME_TOO_LONG
;
516 DestinationString
->Length
= (USHORT
)DestSize
;
517 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
521 DestinationString
->Length
= 0;
522 DestinationString
->MaximumLength
= 0;
525 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
526 return STATUS_SUCCESS
;
533 * Writes at most length characters to the string str.
534 * Str is nullterminated when length allowes it.
535 * When str fits exactly in length characters the nullterm is ommitted.
537 NTSTATUS NTAPI
RtlIntegerToChar(
538 ULONG value
, /* [I] Value to be converted */
539 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
540 ULONG length
, /* [I] Length of the str buffer in bytes */
541 PCHAR str
) /* [O] Destination for the converted value */
550 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
551 return STATUS_INVALID_PARAMETER
;
559 digit
= value
% base
;
560 value
= value
/ base
;
564 *pos
= 'A' + digit
- 10;
566 } while (value
!= 0L);
568 len
= &buffer
[32] - pos
;
570 return STATUS_BUFFER_OVERFLOW
;
571 } else if (str
== NULL
) {
572 return STATUS_ACCESS_VIOLATION
;
573 } else if (len
== length
) {
574 memcpy(str
, pos
, len
);
576 memcpy(str
, pos
, len
+ 1);
578 return STATUS_SUCCESS
;
588 IN ULONG Base OPTIONAL
,
589 IN ULONG Length OPTIONAL
,
604 if ((Radix
!= 2) && (Radix
!= 8) &&
605 (Radix
!= 10) && (Radix
!= 16))
607 return STATUS_INVALID_PARAMETER
;
611 while (v
|| tp
== temp
)
622 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
624 return STATUS_BUFFER_TOO_SMALL
;
632 return STATUS_SUCCESS
;
640 RtlIntegerToUnicodeString(
642 IN ULONG Base OPTIONAL
,
643 IN OUT PUNICODE_STRING String
)
645 ANSI_STRING AnsiString
;
649 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
650 if (NT_SUCCESS(Status
))
652 AnsiString
.Buffer
= Buffer
;
653 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
654 AnsiString
.MaximumLength
= sizeof(Buffer
);
656 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
667 RtlInt64ToUnicodeString (
669 IN ULONG Base OPTIONAL
,
670 IN OUT PUNICODE_STRING String
)
672 LARGE_INTEGER LargeInt
;
673 ANSI_STRING AnsiString
;
677 LargeInt
.QuadPart
= Value
;
679 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
680 if (NT_SUCCESS(Status
))
682 AnsiString
.Buffer
= Buffer
;
683 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
684 AnsiString
.MaximumLength
= sizeof(Buffer
);
686 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
696 * TRUE if String2 contains String1 as a prefix.
701 PANSI_STRING String1
,
702 PANSI_STRING String2
,
703 BOOLEAN CaseInsensitive
)
709 if (String2
->Length
< String1
->Length
)
712 Length
= String1
->Length
;
713 pc1
= String1
->Buffer
;
714 pc2
= String2
->Buffer
;
722 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
730 if (*pc1
++ != *pc2
++)
743 * TRUE if String2 contains String1 as a prefix.
747 RtlPrefixUnicodeString(
748 PCUNICODE_STRING String1
,
749 PCUNICODE_STRING String2
,
750 BOOLEAN CaseInsensitive
)
756 if (String2
->Length
< String1
->Length
)
759 Length
= String1
->Length
/ 2;
760 pc1
= String1
->Buffer
;
761 pc2
= String2
->Buffer
;
769 if (RtlUpcaseUnicodeChar (*pc1
++)
770 != RtlUpcaseUnicodeChar (*pc2
++))
778 if( *pc1
++ != *pc2
++ )
791 RtlUnicodeStringToInteger(const UNICODE_STRING
*str
, /* [I] Unicode string to be converted */
792 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
793 ULONG
*value
) /* [O] Destination for the converted value */
795 LPWSTR lpwstr
= str
->Buffer
;
796 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
799 ULONG RunningTotal
= 0;
802 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
807 if (CharsRemaining
>= 1) {
808 if (*lpwstr
== '+') {
811 } else if (*lpwstr
== '-') {
820 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
821 if (lpwstr
[1] == 'b') {
825 } else if (lpwstr
[1] == 'o') {
829 } else if (lpwstr
[1] == 'x') {
835 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
836 return STATUS_INVALID_PARAMETER
;
840 return STATUS_ACCESS_VIOLATION
;
843 while (CharsRemaining
>= 1) {
844 wchCurrent
= *lpwstr
;
845 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
846 digit
= wchCurrent
- '0';
847 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
848 digit
= wchCurrent
- 'A' + 10;
849 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
850 digit
= wchCurrent
- 'a' + 10;
854 if (digit
< 0 || digit
>= base
) {
855 *value
= bMinus
? -RunningTotal
: RunningTotal
;
856 return STATUS_SUCCESS
;
859 RunningTotal
= RunningTotal
* base
+ digit
;
864 *value
= bMinus
? -RunningTotal
: RunningTotal
;
865 return STATUS_SUCCESS
;
872 * Bytes necessary for the conversion including nullterm.
876 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
880 /* Convert the Unicode String to Mb Size */
881 RtlUnicodeToMultiByteSize(&Size
,
882 UnicodeString
->Buffer
,
883 UnicodeString
->Length
);
885 /* Return the size + the null char */
886 return (Size
+ sizeof(CHAR
));
893 * This function always writes a terminating '\0'.
894 * It performs a partial copy if ansi is too small.
898 RtlUnicodeStringToAnsiString(
899 IN OUT PANSI_STRING AnsiDest
,
900 IN PCUNICODE_STRING UniSource
,
901 IN BOOLEAN AllocateDestinationString
)
903 NTSTATUS Status
= STATUS_SUCCESS
;
910 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
911 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
913 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
915 if (AllocateDestinationString
)
917 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
918 AnsiDest
->MaximumLength
= Length
;
919 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
921 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
923 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
925 Status
= STATUS_BUFFER_OVERFLOW
;
926 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
929 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
935 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
937 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
941 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
949 * This function always writes a terminating '\0'.
950 * Does NOT perform a partial copy if unicode is too small!
954 RtlOemStringToUnicodeString(
955 IN OUT PUNICODE_STRING UniDest
,
956 IN PCOEM_STRING OemSource
,
957 IN BOOLEAN AllocateDestinationString
)
965 Length
= RtlOemStringToUnicodeSize(OemSource
);
966 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
968 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
970 if (AllocateDestinationString
)
972 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
973 UniDest
->MaximumLength
= Length
;
974 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
976 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
978 return STATUS_BUFFER_OVERFLOW
;
981 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
987 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
989 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
990 UniDest
->Buffer
= NULL
;
994 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1002 * This function always '\0' terminates the string returned.
1006 RtlUnicodeStringToOemString(
1007 IN OUT POEM_STRING OemDest
,
1008 IN PCUNICODE_STRING UniSource
,
1009 IN BOOLEAN AllocateDestinationString
)
1017 Length
= RtlUnicodeStringToOemSize(UniSource
);
1018 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1020 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1022 if (AllocateDestinationString
)
1024 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1025 OemDest
->MaximumLength
= Length
;
1026 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1028 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1030 return STATUS_BUFFER_OVERFLOW
;
1033 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1039 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1041 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1042 OemDest
->Buffer
= NULL
;
1046 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1050 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1056 * The length of the string if all tests were passed, 0 otherwise.
1060 RtlIsTextUnicode( LPCVOID buf
, INT len
, INT
*pf
)
1062 const WCHAR
*s
= buf
;
1064 unsigned int flags
= ~0U, out_flags
= 0;
1066 if (len
< sizeof(WCHAR
))
1068 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
1075 * Apply various tests to the text string. According to the
1076 * docs, each test "passed" sets the corresponding flag in
1077 * the output flags. But some of the tests are mutually
1078 * exclusive, so I don't see how you could pass all tests ...
1081 /* Check for an odd length ... pass if even. */
1082 if (len
& 1) out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1084 if (((char *)buf
)[len
- 1] == 0)
1085 len
--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
1087 len
/= sizeof(WCHAR
);
1088 /* Windows only checks the first 256 characters */
1089 if (len
> 256) len
= 256;
1091 /* Check for the special byte order unicode marks. */
1092 if (*s
== 0xFEFF) out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1093 if (*s
== 0xFFFE) out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1095 /* apply some statistical analysis */
1096 if (flags
& IS_TEXT_UNICODE_STATISTICS
)
1099 /* FIXME: checks only for ASCII characters in the unicode stream */
1100 for (i
= 0; i
< len
; i
++)
1102 if (s
[i
] <= 255) stats
++;
1104 if (stats
> len
/ 2)
1105 out_flags
|= IS_TEXT_UNICODE_STATISTICS
;
1108 /* Check for unicode NULL chars */
1109 if (flags
& IS_TEXT_UNICODE_NULL_BYTES
)
1111 for (i
= 0; i
< len
; i
++)
1113 if (!(s
[i
] & 0xff) || !(s
[i
] >> 8))
1115 out_flags
|= IS_TEXT_UNICODE_NULL_BYTES
;
1126 /* check for flags that indicate it's definitely not valid Unicode */
1127 if (out_flags
& (IS_TEXT_UNICODE_REVERSE_MASK
| IS_TEXT_UNICODE_NOT_UNICODE_MASK
)) return FALSE
;
1128 /* now check for invalid ASCII, and assume Unicode if so */
1129 if (out_flags
& IS_TEXT_UNICODE_NOT_ASCII_MASK
) return TRUE
;
1130 /* now check for Unicode flags */
1131 if (out_flags
& IS_TEXT_UNICODE_UNICODE_MASK
) return TRUE
;
1141 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1142 * A partial copy is NOT performed if the dest buffer is too small!
1146 RtlOemStringToCountedUnicodeString(
1147 IN OUT PUNICODE_STRING UniDest
,
1148 IN PCOEM_STRING OemSource
,
1149 IN BOOLEAN AllocateDestinationString
)
1157 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1161 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1162 return STATUS_SUCCESS
;
1165 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1167 UniDest
->Length
= (USHORT
)Length
;
1169 if (AllocateDestinationString
)
1171 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1172 UniDest
->MaximumLength
= Length
;
1173 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1175 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1177 return STATUS_BUFFER_OVERFLOW
;
1180 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1186 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1188 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1189 UniDest
->Buffer
= NULL
;
1193 return STATUS_SUCCESS
;
1200 * TRUE if the names are equal, FALSE if not
1203 * The comparison is case insensitive.
1207 RtlEqualComputerName(
1208 IN PUNICODE_STRING ComputerName1
,
1209 IN PUNICODE_STRING ComputerName2
)
1211 OEM_STRING OemString1
;
1212 OEM_STRING OemString2
;
1213 BOOLEAN Result
= FALSE
;
1215 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1219 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1223 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1224 RtlFreeOemString(&OemString2
);
1226 RtlFreeOemString(&OemString1
);
1236 * TRUE if the names are equal, FALSE if not
1239 * The comparison is case insensitive.
1243 RtlEqualDomainName (
1244 IN PUNICODE_STRING DomainName1
,
1245 IN PUNICODE_STRING DomainName2
1248 return RtlEqualComputerName(DomainName1
, DomainName2
);
1254 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1256 * Convert a string representation of a GUID into a GUID.
1259 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1260 * guid [O] Destination for the converted GUID
1263 * Success: STATUS_SUCCESS. guid contains the converted value.
1264 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1267 * See RtlStringFromGUID.
1272 IN UNICODE_STRING
*str
,
1277 const WCHAR
*lpszCLSID
= str
->Buffer
;
1278 BYTE
* lpOut
= (BYTE
*)guid
;
1280 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1282 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1283 * to memory: DWORD... WORD WORD BYTES............
1290 if (*lpszCLSID
!= '{')
1291 return STATUS_INVALID_PARAMETER
;
1298 if (*lpszCLSID
!= '-')
1299 return STATUS_INVALID_PARAMETER
;
1303 if (*lpszCLSID
!= '}')
1304 return STATUS_INVALID_PARAMETER
;
1309 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1312 /* Read two hex digits as a byte value */
1313 if (ch
>= '0' && ch
<= '9')
1315 else if (ch
>= 'a' && ch
<= 'f')
1317 else if (ch
>= 'A' && ch
<= 'F')
1320 return STATUS_INVALID_PARAMETER
;
1322 if (ch2
>= '0' && ch2
<= '9')
1324 else if (ch2
>= 'a' && ch2
<= 'f')
1325 ch2
= ch2
- 'a' + 10;
1326 else if (ch2
>= 'A' && ch2
<= 'F')
1327 ch2
= ch2
- 'A' + 10;
1329 return STATUS_INVALID_PARAMETER
;
1331 byte
= ch
<< 4 | ch2
;
1335 #ifndef WORDS_BIGENDIAN
1336 /* For Big Endian machines, we store the data such that the
1337 * dword/word members can be read as DWORDS and WORDS correctly. */
1369 lpszCLSID
++; /* Skip 2nd character of byte */
1377 return STATUS_SUCCESS
;
1385 RtlEraseUnicodeString(
1386 IN PUNICODE_STRING String
)
1388 if (String
->Buffer
&& String
->MaximumLength
)
1390 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1400 RtlHashUnicodeString(
1401 IN CONST UNICODE_STRING
*String
,
1402 IN BOOLEAN CaseInSensitive
,
1403 IN ULONG HashAlgorithm
,
1404 OUT PULONG HashValue
)
1406 if (String
!= NULL
&& HashValue
!= NULL
)
1408 switch (HashAlgorithm
)
1410 case HASH_STRING_ALGORITHM_DEFAULT
:
1411 case HASH_STRING_ALGORITHM_X65599
:
1416 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1418 if (CaseInSensitive
)
1420 for (c
= String
->Buffer
;
1424 /* only uppercase characters if they are 'a' ... 'z'! */
1425 *HashValue
= ((65599 * (*HashValue
)) +
1426 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1427 (*c
) - L
'a' + L
'A' : (*c
)));
1432 for (c
= String
->Buffer
;
1436 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1439 return STATUS_SUCCESS
;
1444 return STATUS_INVALID_PARAMETER
;
1451 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1452 * Does a partial copy if the dest buffer is too small
1456 RtlUnicodeStringToCountedOemString(
1457 IN OUT POEM_STRING OemDest
,
1458 IN PUNICODE_STRING UniSource
,
1459 IN BOOLEAN AllocateDestinationString
)
1467 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1471 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1474 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1476 OemDest
->Length
= (USHORT
)Length
;
1478 if (AllocateDestinationString
)
1480 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1481 OemDest
->MaximumLength
= Length
;
1482 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1484 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1486 return STATUS_BUFFER_OVERFLOW
;
1489 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1495 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1497 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1499 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1500 OemDest
->Buffer
= NULL
;
1512 RtlLargeIntegerToChar(
1513 IN PLARGE_INTEGER Value
,
1516 IN OUT PCHAR String
)
1518 NTSTATUS Status
= STATUS_SUCCESS
;
1521 ULONGLONG v
= Value
->QuadPart
;
1530 if ((Radix
!= 2) && (Radix
!= 8) &&
1531 (Radix
!= 10) && (Radix
!= 16))
1532 return STATUS_INVALID_PARAMETER
;
1535 while (v
|| tp
== temp
)
1546 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) > Length
)
1547 return STATUS_BUFFER_OVERFLOW
;
1555 if((ULONG
)((ULONG_PTR
)sp
- (ULONG_PTR
)String
) < Length
)
1561 /* Get the error code */
1562 Status
= _SEH_GetExceptionCode();
1574 * dest is never '\0' terminated because it may be equal to src, and src
1575 * might not be '\0' terminated. dest->Length is only set upon success.
1579 RtlUpcaseUnicodeString(
1580 IN OUT PUNICODE_STRING UniDest
,
1581 IN PCUNICODE_STRING UniSource
,
1582 IN BOOLEAN AllocateDestinationString
)
1588 if (AllocateDestinationString
== TRUE
)
1590 UniDest
->MaximumLength
= UniSource
->Length
;
1591 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1592 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1594 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1596 return STATUS_BUFFER_OVERFLOW
;
1599 j
= UniSource
->Length
/ sizeof(WCHAR
);
1601 for (i
= 0; i
< j
; i
++)
1603 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1606 UniDest
->Length
= UniSource
->Length
;
1607 return STATUS_SUCCESS
;
1614 * This function always writes a terminating '\0'.
1615 * It performs a partial copy if ansi is too small.
1619 RtlUpcaseUnicodeStringToAnsiString(
1620 IN OUT PANSI_STRING AnsiDest
,
1621 IN PUNICODE_STRING UniSource
,
1622 IN BOOLEAN AllocateDestinationString
)
1630 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1631 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1633 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1635 if (AllocateDestinationString
)
1637 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1638 AnsiDest
->MaximumLength
= Length
;
1639 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1641 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1643 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1646 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1652 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1654 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1655 AnsiDest
->Buffer
= NULL
;
1659 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1667 * This function always writes a terminating '\0'.
1668 * It performs a partial copy if ansi is too small.
1672 RtlUpcaseUnicodeStringToCountedOemString(
1673 IN OUT POEM_STRING OemDest
,
1674 IN PCUNICODE_STRING UniSource
,
1675 IN BOOLEAN AllocateDestinationString
)
1683 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1687 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1690 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1692 OemDest
->Length
= (USHORT
)Length
;
1694 if (AllocateDestinationString
)
1696 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1697 OemDest
->MaximumLength
= Length
;
1698 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1700 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1702 return STATUS_BUFFER_OVERFLOW
;
1705 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1711 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1713 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1715 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1716 OemDest
->Buffer
= NULL
;
1726 * Oem string is allways nullterminated
1727 * It performs a partial copy if oem is too small.
1731 RtlUpcaseUnicodeStringToOemString (
1732 IN OUT POEM_STRING OemDest
,
1733 IN PCUNICODE_STRING UniSource
,
1734 IN BOOLEAN AllocateDestinationString
)
1742 Length
= RtlUnicodeStringToOemSize(UniSource
);
1743 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1745 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1747 if (AllocateDestinationString
)
1749 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1750 OemDest
->MaximumLength
= Length
;
1751 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1753 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1755 return STATUS_BUFFER_OVERFLOW
;
1758 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1764 /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
1766 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1768 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1769 OemDest
->Buffer
= NULL
;
1773 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1781 * Bytes calculated including nullterm
1785 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1789 /* Convert the Mb String to Unicode Size */
1790 RtlMultiByteToUnicodeSize(&Size
,
1794 /* Return the size + null-char */
1795 return (Size
+ sizeof(WCHAR
));
1803 RtlStringFromGUID (IN REFGUID Guid
,
1804 OUT PUNICODE_STRING GuidString
)
1806 /* Setup the string */
1807 GuidString
->Length
= 38 * sizeof(WCHAR
);
1808 GuidString
->MaximumLength
= GuidString
->Length
+ sizeof(UNICODE_NULL
);
1809 GuidString
->Buffer
= RtlpAllocateStringMemory(GuidString
->MaximumLength
,
1811 if (!GuidString
->Buffer
) return STATUS_NO_MEMORY
;
1813 /* Now format the GUID */
1814 swprintf(GuidString
->Buffer
,
1815 L
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1827 return STATUS_SUCCESS
;
1834 * Bytes calculated including nullterm
1838 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1842 /* Convert the Unicode String to Mb Size */
1843 RtlUnicodeToMultiByteSize(&Size
,
1844 UnicodeString
->Buffer
,
1845 UnicodeString
->Length
);
1847 /* Return the size + null-char */
1848 return (Size
+ sizeof(CHAR
));
1856 RtlCompareUnicodeString(
1857 IN PCUNICODE_STRING s1
,
1858 IN PCUNICODE_STRING s2
,
1859 IN BOOLEAN CaseInsensitive
)
1865 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1869 if (CaseInsensitive
)
1871 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1875 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1877 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1887 IN OUT PSTRING DestinationString
,
1888 IN PSTRING SourceString OPTIONAL
)
1893 /* Check if there was no source given */
1896 /* Simply return an empty string */
1897 DestinationString
->Length
= 0;
1901 /* Choose the smallest length */
1902 SourceLength
= min(DestinationString
->MaximumLength
,
1903 SourceString
->Length
);
1906 DestinationString
->Length
= (USHORT
)SourceLength
;
1908 /* Save the pointers to each buffer */
1909 p1
= DestinationString
->Buffer
;
1910 p2
= SourceString
->Buffer
;
1912 /* Loop the buffer */
1913 while (SourceLength
)
1915 /* Copy the character and move on */
1927 RtlCopyUnicodeString(
1928 IN OUT PUNICODE_STRING DestinationString
,
1929 IN PCUNICODE_STRING SourceString
)
1933 if(SourceString
== NULL
)
1935 DestinationString
->Length
= 0;
1939 SourceLength
= min(DestinationString
->MaximumLength
,
1940 SourceString
->Length
);
1941 DestinationString
->Length
= (USHORT
)SourceLength
;
1943 RtlCopyMemory(DestinationString
->Buffer
,
1944 SourceString
->Buffer
,
1947 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
1949 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1958 * Creates a nullterminated UNICODE_STRING
1962 RtlCreateUnicodeString(
1963 IN OUT PUNICODE_STRING UniDest
,
1970 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
1971 if (Length
> 0xFFFE) return FALSE
;
1973 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1975 if (UniDest
->Buffer
== NULL
) return FALSE
;
1977 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
1978 UniDest
->MaximumLength
= (USHORT
)Length
;
1979 UniDest
->Length
= Length
- sizeof (WCHAR
);
1989 RtlCreateUnicodeStringFromAsciiz(
1990 OUT PUNICODE_STRING Destination
,
1993 ANSI_STRING AnsiString
;
1996 RtlInitAnsiString(&AnsiString
, Source
);
1998 Status
= RtlAnsiStringToUnicodeString(Destination
,
2002 return NT_SUCCESS(Status
);
2009 * Dest is never '\0' terminated because it may be equal to src, and src
2010 * might not be '\0' terminated.
2011 * Dest->Length is only set upon success.
2015 RtlDowncaseUnicodeString(
2016 IN OUT PUNICODE_STRING UniDest
,
2017 IN PCUNICODE_STRING UniSource
,
2018 IN BOOLEAN AllocateDestinationString
)
2025 if (AllocateDestinationString
)
2027 UniDest
->MaximumLength
= UniSource
->Length
;
2028 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2029 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2031 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2033 return STATUS_BUFFER_OVERFLOW
;
2036 UniDest
->Length
= UniSource
->Length
;
2037 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2039 for (i
= 0 ; i
< StopGap
; i
++)
2041 if (UniSource
->Buffer
[i
] < L
'A')
2043 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2045 else if (UniSource
->Buffer
[i
] <= L
'Z')
2047 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2051 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2055 return STATUS_SUCCESS
;
2062 * if src is NULL dest is unchanged.
2063 * dest is '\0' terminated when the MaximumLength allowes it.
2064 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2068 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2076 UNICODE_STRING UnicodeSource
;
2078 RtlInitUnicodeString(&UnicodeSource
, Source
);
2079 Length
= UnicodeSource
.Length
;
2081 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2083 return STATUS_BUFFER_TOO_SMALL
;
2086 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2087 RtlMoveMemory(DestBuffer
, Source
, Length
);
2088 Destination
->Length
+= Length
;
2090 /* append terminating '\0' if enough space */
2091 if(Destination
->MaximumLength
> Destination
->Length
)
2093 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2097 return STATUS_SUCCESS
;
2104 * if src is NULL dest is unchanged.
2105 * dest is never '\0' terminated.
2109 RtlAppendAsciizToString(
2110 IN OUT PSTRING Destination
,
2117 Length
= (USHORT
)strlen(Source
);
2119 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2121 return STATUS_BUFFER_TOO_SMALL
;
2124 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2125 Destination
->Length
+= Length
;
2128 return STATUS_SUCCESS
;
2136 RtlUpperString(PSTRING DestinationString
,
2137 PSTRING SourceString
)
2142 Length
= min(SourceString
->Length
,
2143 DestinationString
->MaximumLength
);
2145 Src
= SourceString
->Buffer
;
2146 Dest
= DestinationString
->Buffer
;
2147 DestinationString
->Length
= Length
;
2150 *Dest
++ = RtlUpperChar(*Src
++);
2159 * See RtlpDuplicateUnicodeString
2163 RtlDuplicateUnicodeString(
2165 IN PCUNICODE_STRING SourceString
,
2166 OUT PUNICODE_STRING DestinationString
)
2170 if (SourceString
== NULL
|| DestinationString
== NULL
||
2171 SourceString
->Length
> SourceString
->MaximumLength
||
2172 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
2173 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4) {
2174 return STATUS_INVALID_PARAMETER
;
2178 if ((SourceString
->Length
== 0) &&
2179 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2180 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2182 DestinationString
->Length
= 0;
2183 DestinationString
->MaximumLength
= 0;
2184 DestinationString
->Buffer
= NULL
;
2188 UINT DestMaxLength
= SourceString
->Length
;
2190 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2191 DestMaxLength
+= sizeof(UNICODE_NULL
);
2193 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2194 if (DestinationString
->Buffer
== NULL
)
2195 return STATUS_NO_MEMORY
;
2197 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2198 DestinationString
->Length
= SourceString
->Length
;
2199 DestinationString
->MaximumLength
= DestMaxLength
;
2201 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2202 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2205 return STATUS_SUCCESS
;
2212 RtlValidateUnicodeString(IN ULONG Flags
,
2213 IN PCUNICODE_STRING UnicodeString
)
2215 /* currently no flags are supported! */
2219 ((UnicodeString
== NULL
) ||
2220 ((UnicodeString
->Length
!= 0) &&
2221 (UnicodeString
->Buffer
!= NULL
) &&
2222 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2223 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2224 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2226 /* a NULL pointer as a unicode string is considered to be a valid unicode
2228 return STATUS_SUCCESS
;
2232 return STATUS_INVALID_PARAMETER
;
2238 RtlFindCharInUnicodeString(IN ULONG Flags
,
2239 IN PUNICODE_STRING SearchString
,
2240 IN PCUNICODE_STRING MatchString
,
2241 OUT PUSHORT Position
)
2244 unsigned int search_idx
;
2250 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2252 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2254 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2256 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2257 return STATUS_SUCCESS
;
2262 return STATUS_NOT_FOUND
;
2267 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2269 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2271 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2273 *Position
= main_idx
* sizeof(WCHAR
);
2274 return STATUS_SUCCESS
;
2279 return STATUS_NOT_FOUND
;
2284 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2287 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2288 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2292 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2294 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2295 return STATUS_SUCCESS
;
2299 return STATUS_NOT_FOUND
;
2304 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2307 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2308 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2312 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2314 *Position
= main_idx
* sizeof(WCHAR
);
2315 return STATUS_SUCCESS
;
2319 return STATUS_NOT_FOUND
;
2323 return STATUS_NOT_FOUND
;