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 extern USHORT NlsOemDefaultChar
;
27 extern USHORT NlsUnicodeDefaultChar
;
29 /* FUNCTIONS *****************************************************************/
36 RtlAnsiCharToUnicodeChar(IN PUCHAR
*AnsiChar
)
40 WCHAR UnicodeChar
= L
' ';
42 Size
= (NlsLeadByteInfo
[**AnsiChar
] == 0) ? 1 : 2;
44 Status
= RtlMultiByteToUnicodeN(&UnicodeChar
,
50 if (!NT_SUCCESS(Status
))
63 * This function always writes a terminating '\0'.
64 * If the dest buffer is too small a partial copy is NOT performed!
68 RtlAnsiStringToUnicodeString(
69 IN OUT PUNICODE_STRING UniDest
,
70 IN PANSI_STRING AnsiSource
,
71 IN BOOLEAN AllocateDestinationString
)
79 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
80 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
81 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
83 if (AllocateDestinationString
)
85 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
86 UniDest
->MaximumLength
= Length
;
87 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
89 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
91 return STATUS_BUFFER_OVERFLOW
;
94 Status
= RtlMultiByteToUnicodeN(UniDest
->Buffer
,
100 if (!NT_SUCCESS(Status
))
102 if (AllocateDestinationString
)
104 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
105 UniDest
->Buffer
= NULL
;
110 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
118 * The calculated size in bytes including nullterm.
122 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString
)
126 /* Convert from Mb String to Unicode Size */
127 RtlMultiByteToUnicodeSize(&Size
,
131 /* Return the size plus the null-char */
132 return(Size
+ sizeof(WCHAR
));
139 * If src->length is zero dest is unchanged.
140 * Dest is never nullterminated.
144 RtlAppendStringToString(IN PSTRING Destination
,
147 USHORT SourceLength
= Source
->Length
;
151 if (Destination
->Length
+ SourceLength
> Destination
->MaximumLength
)
153 return STATUS_BUFFER_TOO_SMALL
;
156 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
],
160 Destination
->Length
+= SourceLength
;
163 return STATUS_SUCCESS
;
170 * If src->length is zero dest is unchanged.
171 * Dest is nullterminated when the MaximumLength allowes it.
172 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
176 RtlAppendUnicodeStringToString(
177 IN OUT PUNICODE_STRING Destination
,
178 IN PCUNICODE_STRING Source
)
180 USHORT SourceLength
= Source
->Length
;
181 PWCHAR Buffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
185 if ((SourceLength
+ Destination
->Length
) > Destination
->MaximumLength
)
187 return STATUS_BUFFER_TOO_SMALL
;
190 RtlMoveMemory(Buffer
, Source
->Buffer
, SourceLength
);
191 Destination
->Length
+= SourceLength
;
193 /* append terminating '\0' if enough space */
194 if (Destination
->MaximumLength
> Destination
->Length
)
196 Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
200 return STATUS_SUCCESS
;
203 /**************************************************************************
204 * RtlCharToInteger (NTDLL.@)
206 * Converts a character string into its integer equivalent.
209 * Success: STATUS_SUCCESS. value contains the converted number
210 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
211 * STATUS_ACCESS_VIOLATION, if value is NULL.
214 * For base 0 it uses 10 as base and the string should be in the format
215 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
216 * For other bases the string should be in the format
217 * "{whitespace} [+|-] {digits}".
218 * No check is made for value overflow, only the lower 32 bits are assigned.
219 * If str is NULL it crashes, as the native function does.
222 * This function does not read garbage behind '\0' as the native version does.
227 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
228 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
229 PULONG value
) /* [O] Destination for the converted value */
233 ULONG RunningTotal
= 0;
236 while (*str
!= '\0' && *str
<= ' ') {
242 } else if (*str
== '-') {
253 } else if (str
[1] == 'o') {
256 } else if (str
[1] == 'x') {
261 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
262 return STATUS_INVALID_PARAMETER
;
266 return STATUS_ACCESS_VIOLATION
;
269 while (*str
!= '\0') {
271 if (chCurrent
>= '0' && chCurrent
<= '9') {
272 digit
= chCurrent
- '0';
273 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
274 digit
= chCurrent
- 'A' + 10;
275 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
276 digit
= chCurrent
- 'a' + 10;
280 if (digit
< 0 || digit
>= (int)base
) {
281 *value
= bMinus
? -RunningTotal
: RunningTotal
;
282 return STATUS_SUCCESS
;
285 RunningTotal
= RunningTotal
* base
+ digit
;
289 *value
= bMinus
? -RunningTotal
: RunningTotal
;
290 return STATUS_SUCCESS
;
301 IN BOOLEAN CaseInsensitive
)
307 len
= min(s1
->Length
, s2
->Length
);
313 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
317 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
319 if (!ret
) ret
= s1
->Length
- s2
->Length
;
327 * TRUE if strings are equal.
334 IN BOOLEAN CaseInsensitive
)
336 if (s1
->Length
!= s2
->Length
) return FALSE
;
337 return !RtlCompareString(s1
, s2
, CaseInsensitive
);
344 * TRUE if strings are equal.
348 RtlEqualUnicodeString(
349 IN CONST UNICODE_STRING
*s1
,
350 IN CONST UNICODE_STRING
*s2
,
351 IN BOOLEAN CaseInsensitive
)
353 if (s1
->Length
!= s2
->Length
) return FALSE
;
354 return !RtlCompareUnicodeString(s1
, s2
, CaseInsensitive
);
362 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
366 if (AnsiString
->Buffer
)
368 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
369 RtlZeroMemory(AnsiString
, sizeof(ANSI_STRING
));
378 RtlFreeOemString(IN POEM_STRING OemString
)
382 if (OemString
->Buffer
) RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
390 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
394 if (UnicodeString
->Buffer
)
396 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_USTR
);
397 RtlZeroMemory(UnicodeString
, sizeof(UNICODE_STRING
));
406 * Check the oem-string to match the uincoded-string.
408 * Functions who convert unicode strings to oem strings will set a DefaultChar from
409 * the OemCodepage when the character are unknown. So check it against the unicode string
410 * and return false when the unicode string not contain an TransDefaultChar.
414 RtlpDidUnicodeToOemWork(IN PCUNICODE_STRING UnicodeString
,
415 IN POEM_STRING OemString
)
419 /* Go through all characters of a string */
420 while ((OemString
->Buffer
[i
] != 0) &&
421 (i
< OemString
->Length
))
423 /* Check if it got translated into '?', but source char
424 wasn't '?' equivalent */
425 if ((OemString
->Buffer
[i
] == NlsOemDefaultChar
) &&
426 (UnicodeString
->Buffer
[i
] != NlsUnicodeDefaultChar
))
428 /* Yes, it means unmappable characters were found */
432 /* Move to the next char */
436 /* All chars were translated successfuly */
445 RtlIsValidOemCharacter(IN PWCHAR Char
)
455 * If source is NULL the length of source is assumed to be 0.
459 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
460 IN PCSZ SourceString
)
466 DestSize
= strlen(SourceString
);
467 DestinationString
->Length
= (USHORT
)DestSize
;
468 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
472 DestinationString
->Length
= 0;
473 DestinationString
->MaximumLength
= 0;
476 DestinationString
->Buffer
= (PCHAR
)SourceString
;
481 RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString
,
482 IN PCSZ SourceString
)
488 DestSize
= strlen(SourceString
);
489 if (DestSize
>= 0xFFFF) return STATUS_NAME_TOO_LONG
;
490 DestinationString
->Length
= (USHORT
)DestSize
;
491 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
495 DestinationString
->Length
= 0;
496 DestinationString
->MaximumLength
= 0;
499 DestinationString
->Buffer
= (PCHAR
)SourceString
;
500 return STATUS_SUCCESS
;
507 * If source is NULL the length of source is assumed to be 0.
512 IN OUT PSTRING DestinationString
,
513 IN PCSZ SourceString
)
515 RtlInitAnsiString(DestinationString
, SourceString
);
522 * If source is NULL the length of source is assumed to be 0.
526 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
527 IN PCWSTR SourceString
)
533 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
534 DestinationString
->Length
= (USHORT
)DestSize
;
535 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
539 DestinationString
->Length
= 0;
540 DestinationString
->MaximumLength
= 0;
543 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
551 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
552 IN PCWSTR SourceString
)
558 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
559 if (DestSize
>= 0xFFFC) return STATUS_NAME_TOO_LONG
;
560 DestinationString
->Length
= (USHORT
)DestSize
;
561 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
565 DestinationString
->Length
= 0;
566 DestinationString
->MaximumLength
= 0;
569 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
570 return STATUS_SUCCESS
;
577 * Writes at most length characters to the string str.
578 * Str is nullterminated when length allowes it.
579 * When str fits exactly in length characters the nullterm is ommitted.
581 NTSTATUS NTAPI
RtlIntegerToChar(
582 ULONG value
, /* [I] Value to be converted */
583 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
584 ULONG length
, /* [I] Length of the str buffer in bytes */
585 PCHAR str
) /* [O] Destination for the converted value */
594 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
595 return STATUS_INVALID_PARAMETER
;
603 digit
= value
% base
;
604 value
= value
/ base
;
608 *pos
= 'A' + digit
- 10;
610 } while (value
!= 0L);
612 len
= &buffer
[32] - pos
;
614 return STATUS_BUFFER_OVERFLOW
;
615 } else if (str
== NULL
) {
616 return STATUS_ACCESS_VIOLATION
;
617 } else if (len
== length
) {
618 memcpy(str
, pos
, len
);
620 memcpy(str
, pos
, len
+ 1);
622 return STATUS_SUCCESS
;
632 IN ULONG Base OPTIONAL
,
633 IN ULONG Length OPTIONAL
,
648 if ((Radix
!= 2) && (Radix
!= 8) &&
649 (Radix
!= 10) && (Radix
!= 16))
651 return STATUS_INVALID_PARAMETER
;
655 while (v
|| tp
== temp
)
666 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
668 return STATUS_BUFFER_TOO_SMALL
;
676 return STATUS_SUCCESS
;
684 RtlIntegerToUnicodeString(
686 IN ULONG Base OPTIONAL
,
687 IN OUT PUNICODE_STRING String
)
689 ANSI_STRING AnsiString
;
693 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
694 if (NT_SUCCESS(Status
))
696 AnsiString
.Buffer
= Buffer
;
697 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
698 AnsiString
.MaximumLength
= sizeof(Buffer
);
700 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
711 RtlInt64ToUnicodeString (
713 IN ULONG Base OPTIONAL
,
714 IN OUT PUNICODE_STRING String
)
716 LARGE_INTEGER LargeInt
;
717 ANSI_STRING AnsiString
;
721 LargeInt
.QuadPart
= Value
;
723 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
724 if (NT_SUCCESS(Status
))
726 AnsiString
.Buffer
= Buffer
;
727 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
728 AnsiString
.MaximumLength
= sizeof(Buffer
);
730 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
740 * TRUE if String2 contains String1 as a prefix.
745 PANSI_STRING String1
,
746 PANSI_STRING String2
,
747 BOOLEAN CaseInsensitive
)
753 if (String2
->Length
< String1
->Length
)
756 Length
= String1
->Length
;
757 pc1
= String1
->Buffer
;
758 pc2
= String2
->Buffer
;
766 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
774 if (*pc1
++ != *pc2
++)
787 * TRUE if String2 contains String1 as a prefix.
791 RtlPrefixUnicodeString(
792 PCUNICODE_STRING String1
,
793 PCUNICODE_STRING String2
,
794 BOOLEAN CaseInsensitive
)
800 if (String2
->Length
< String1
->Length
)
803 Length
= String1
->Length
/ 2;
804 pc1
= String1
->Buffer
;
805 pc2
= String2
->Buffer
;
813 if (RtlUpcaseUnicodeChar (*pc1
++)
814 != RtlUpcaseUnicodeChar (*pc2
++))
822 if( *pc1
++ != *pc2
++ )
835 RtlUnicodeStringToInteger(const UNICODE_STRING
*str
, /* [I] Unicode string to be converted */
836 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
837 ULONG
*value
) /* [O] Destination for the converted value */
839 LPWSTR lpwstr
= str
->Buffer
;
840 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
843 ULONG RunningTotal
= 0;
846 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
851 if (CharsRemaining
>= 1) {
852 if (*lpwstr
== '+') {
855 } else if (*lpwstr
== '-') {
864 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
865 if (lpwstr
[1] == 'b') {
869 } else if (lpwstr
[1] == 'o') {
873 } else if (lpwstr
[1] == 'x') {
879 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
880 return STATUS_INVALID_PARAMETER
;
884 return STATUS_ACCESS_VIOLATION
;
887 while (CharsRemaining
>= 1) {
888 wchCurrent
= *lpwstr
;
889 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
890 digit
= wchCurrent
- '0';
891 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
892 digit
= wchCurrent
- 'A' + 10;
893 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
894 digit
= wchCurrent
- 'a' + 10;
898 if (digit
< 0 || digit
>= base
) {
899 *value
= bMinus
? -RunningTotal
: RunningTotal
;
900 return STATUS_SUCCESS
;
903 RunningTotal
= RunningTotal
* base
+ digit
;
908 *value
= bMinus
? -RunningTotal
: RunningTotal
;
909 return STATUS_SUCCESS
;
916 * Bytes necessary for the conversion including nullterm.
920 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
924 /* Convert the Unicode String to Mb Size */
925 RtlUnicodeToMultiByteSize(&Size
,
926 UnicodeString
->Buffer
,
927 UnicodeString
->Length
);
929 /* Return the size + the null char */
930 return (Size
+ sizeof(CHAR
));
937 * This function always writes a terminating '\0'.
938 * It performs a partial copy if ansi is too small.
942 RtlUnicodeStringToAnsiString(
943 IN OUT PANSI_STRING AnsiDest
,
944 IN PCUNICODE_STRING UniSource
,
945 IN BOOLEAN AllocateDestinationString
)
947 NTSTATUS Status
= STATUS_SUCCESS
;
954 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
955 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
957 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
959 if (AllocateDestinationString
)
961 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
962 AnsiDest
->MaximumLength
= Length
;
963 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
965 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
967 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
969 Status
= STATUS_BUFFER_OVERFLOW
;
970 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
973 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
979 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
981 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
985 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
993 * This function always writes a terminating '\0'.
994 * Does NOT perform a partial copy if unicode is too small!
998 RtlOemStringToUnicodeString(
999 IN OUT PUNICODE_STRING UniDest
,
1000 IN PCOEM_STRING OemSource
,
1001 IN BOOLEAN AllocateDestinationString
)
1009 Length
= RtlOemStringToUnicodeSize(OemSource
);
1010 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1012 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
1014 if (AllocateDestinationString
)
1016 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1017 UniDest
->MaximumLength
= Length
;
1018 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1020 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1022 return STATUS_BUFFER_OVERFLOW
;
1025 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1031 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1033 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1034 UniDest
->Buffer
= NULL
;
1038 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1046 * This function always '\0' terminates the string returned.
1050 RtlUnicodeStringToOemString(
1051 IN OUT POEM_STRING OemDest
,
1052 IN PCUNICODE_STRING UniSource
,
1053 IN BOOLEAN AllocateDestinationString
)
1061 Length
= RtlUnicodeStringToOemSize(UniSource
);
1062 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1064 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1066 if (AllocateDestinationString
)
1068 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1069 OemDest
->MaximumLength
= Length
;
1070 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1072 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1074 return STATUS_BUFFER_OVERFLOW
;
1077 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1083 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1085 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1086 OemDest
->Buffer
= NULL
;
1090 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1094 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1100 * The length of the string if all tests were passed, 0 otherwise.
1104 RtlIsTextUnicode( PVOID buf
, INT len
, INT
*pf
)
1106 static const WCHAR std_control_chars
[] = {'\r','\n','\t',' ',0x3000,0};
1107 static const WCHAR byterev_control_chars
[] = {0x0d00,0x0a00,0x0900,0x2000,0};
1108 const WCHAR
*s
= buf
;
1110 unsigned int flags
= MAXULONG
, out_flags
= 0;
1112 if (len
< sizeof(WCHAR
))
1114 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
1121 * Apply various tests to the text string. According to the
1122 * docs, each test "passed" sets the corresponding flag in
1123 * the output flags. But some of the tests are mutually
1124 * exclusive, so I don't see how you could pass all tests ...
1127 /* Check for an odd length ... pass if even. */
1128 if (len
& 1) out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1130 if (((char *)buf
)[len
- 1] == 0)
1131 len
--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
1133 len
/= sizeof(WCHAR
);
1134 /* Windows only checks the first 256 characters */
1135 if (len
> 256) len
= 256;
1137 /* Check for the special byte order unicode marks. */
1138 if (*s
== 0xFEFF) out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1139 if (*s
== 0xFFFE) out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1141 /* apply some statistical analysis */
1142 if (flags
& IS_TEXT_UNICODE_STATISTICS
)
1145 /* FIXME: checks only for ASCII characters in the unicode stream */
1146 for (i
= 0; i
< len
; i
++)
1148 if (s
[i
] <= 255) stats
++;
1150 if (stats
> len
/ 2)
1151 out_flags
|= IS_TEXT_UNICODE_STATISTICS
;
1154 /* Check for unicode NULL chars */
1155 if (flags
& IS_TEXT_UNICODE_NULL_BYTES
)
1157 for (i
= 0; i
< len
; i
++)
1159 if (!(s
[i
] & 0xff) || !(s
[i
] >> 8))
1161 out_flags
|= IS_TEXT_UNICODE_NULL_BYTES
;
1167 if (flags
& IS_TEXT_UNICODE_CONTROLS
)
1169 for (i
= 0; i
< len
; i
++)
1171 if (strchrW(std_control_chars
, s
[i
]))
1173 out_flags
|= IS_TEXT_UNICODE_CONTROLS
;
1179 if (flags
& IS_TEXT_UNICODE_REVERSE_CONTROLS
)
1181 for (i
= 0; i
< len
; i
++)
1183 if (strchrW(byterev_control_chars
, s
[i
]))
1185 out_flags
|= IS_TEXT_UNICODE_REVERSE_CONTROLS
;
1196 /* check for flags that indicate it's definitely not valid Unicode */
1197 if (out_flags
& (IS_TEXT_UNICODE_REVERSE_MASK
| IS_TEXT_UNICODE_NOT_UNICODE_MASK
)) return FALSE
;
1198 /* now check for invalid ASCII, and assume Unicode if so */
1199 if (out_flags
& IS_TEXT_UNICODE_NOT_ASCII_MASK
) return TRUE
;
1200 /* now check for Unicode flags */
1201 if (out_flags
& IS_TEXT_UNICODE_UNICODE_MASK
) return TRUE
;
1211 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1212 * A partial copy is NOT performed if the dest buffer is too small!
1216 RtlOemStringToCountedUnicodeString(
1217 IN OUT PUNICODE_STRING UniDest
,
1218 IN PCOEM_STRING OemSource
,
1219 IN BOOLEAN AllocateDestinationString
)
1227 /* Calculate size of the string */
1228 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1230 /* If it's 0 then zero out dest string and return */
1233 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1234 return STATUS_SUCCESS
;
1237 /* Check if length is a sane value */
1238 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1240 /* Store it in dest string */
1241 UniDest
->Length
= (USHORT
)Length
;
1243 /* If we're asked to alloc the string - do so */
1244 if (AllocateDestinationString
)
1246 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1247 UniDest
->MaximumLength
= Length
;
1248 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1250 else if (UniDest
->Length
> UniDest
->MaximumLength
)
1252 return STATUS_BUFFER_OVERFLOW
;
1255 /* Do the conversion */
1256 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1262 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1264 /* Conversion failed, free dest string and return status code */
1265 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1266 UniDest
->Buffer
= NULL
;
1270 return STATUS_SUCCESS
;
1277 * TRUE if the names are equal, FALSE if not
1280 * The comparison is case insensitive.
1284 RtlEqualComputerName(
1285 IN PUNICODE_STRING ComputerName1
,
1286 IN PUNICODE_STRING ComputerName2
)
1288 OEM_STRING OemString1
;
1289 OEM_STRING OemString2
;
1290 BOOLEAN Result
= FALSE
;
1292 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1296 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1300 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1301 RtlFreeOemString(&OemString2
);
1303 RtlFreeOemString(&OemString1
);
1313 * TRUE if the names are equal, FALSE if not
1316 * The comparison is case insensitive.
1320 RtlEqualDomainName (
1321 IN PUNICODE_STRING DomainName1
,
1322 IN PUNICODE_STRING DomainName2
1325 return RtlEqualComputerName(DomainName1
, DomainName2
);
1331 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1333 * Convert a string representation of a GUID into a GUID.
1336 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1337 * guid [O] Destination for the converted GUID
1340 * Success: STATUS_SUCCESS. guid contains the converted value.
1341 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1344 * See RtlStringFromGUID.
1349 IN UNICODE_STRING
*str
,
1354 const WCHAR
*lpszCLSID
= str
->Buffer
;
1355 BYTE
* lpOut
= (BYTE
*)guid
;
1357 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1359 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1360 * to memory: DWORD... WORD WORD BYTES............
1367 if (*lpszCLSID
!= '{')
1368 return STATUS_INVALID_PARAMETER
;
1375 if (*lpszCLSID
!= '-')
1376 return STATUS_INVALID_PARAMETER
;
1380 if (*lpszCLSID
!= '}')
1381 return STATUS_INVALID_PARAMETER
;
1386 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1389 /* Read two hex digits as a byte value */
1390 if (ch
>= '0' && ch
<= '9')
1392 else if (ch
>= 'a' && ch
<= 'f')
1394 else if (ch
>= 'A' && ch
<= 'F')
1397 return STATUS_INVALID_PARAMETER
;
1399 if (ch2
>= '0' && ch2
<= '9')
1401 else if (ch2
>= 'a' && ch2
<= 'f')
1402 ch2
= ch2
- 'a' + 10;
1403 else if (ch2
>= 'A' && ch2
<= 'F')
1404 ch2
= ch2
- 'A' + 10;
1406 return STATUS_INVALID_PARAMETER
;
1408 byte
= ch
<< 4 | ch2
;
1412 #ifndef WORDS_BIGENDIAN
1413 /* For Big Endian machines, we store the data such that the
1414 * dword/word members can be read as DWORDS and WORDS correctly. */
1446 lpszCLSID
++; /* Skip 2nd character of byte */
1454 return STATUS_SUCCESS
;
1462 RtlEraseUnicodeString(
1463 IN PUNICODE_STRING String
)
1465 if (String
->Buffer
&& String
->MaximumLength
)
1467 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1477 RtlHashUnicodeString(
1478 IN CONST UNICODE_STRING
*String
,
1479 IN BOOLEAN CaseInSensitive
,
1480 IN ULONG HashAlgorithm
,
1481 OUT PULONG HashValue
)
1483 if (String
!= NULL
&& HashValue
!= NULL
)
1485 switch (HashAlgorithm
)
1487 case HASH_STRING_ALGORITHM_DEFAULT
:
1488 case HASH_STRING_ALGORITHM_X65599
:
1493 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1495 if (CaseInSensitive
)
1497 for (c
= String
->Buffer
;
1501 /* only uppercase characters if they are 'a' ... 'z'! */
1502 *HashValue
= ((65599 * (*HashValue
)) +
1503 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1504 (*c
) - L
'a' + L
'A' : (*c
)));
1509 for (c
= String
->Buffer
;
1513 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1516 return STATUS_SUCCESS
;
1521 return STATUS_INVALID_PARAMETER
;
1528 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1529 * Does a partial copy if the dest buffer is too small
1533 RtlUnicodeStringToCountedOemString(
1534 IN OUT POEM_STRING OemDest
,
1535 IN PUNICODE_STRING UniSource
,
1536 IN BOOLEAN AllocateDestinationString
)
1544 /* Calculate size of the string */
1545 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1547 /* If it's 0 then zero out dest string and return */
1550 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1551 return STATUS_SUCCESS
;
1554 /* Check if length is a sane value */
1555 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1557 /* Store it in dest string */
1558 OemDest
->Length
= (USHORT
)Length
;
1560 /* If we're asked to alloc the string - do so */
1561 if (AllocateDestinationString
)
1563 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1564 OemDest
->MaximumLength
= Length
;
1565 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1567 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1569 return STATUS_BUFFER_OVERFLOW
;
1572 /* Do the conversion */
1573 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1579 /* Check for unmapped character */
1580 if (NT_SUCCESS(Status
) && !RtlpDidUnicodeToOemWork(UniSource
, OemDest
))
1581 Status
= STATUS_UNMAPPABLE_CHARACTER
;
1583 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1585 /* Conversion failed, free dest string and return status code */
1586 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1587 OemDest
->Buffer
= NULL
;
1599 RtlLargeIntegerToChar(
1600 IN PLARGE_INTEGER Value
,
1603 IN OUT PCHAR String
)
1605 ULONGLONG Val
= Value
->QuadPart
;
1606 NTSTATUS Status
= STATUS_SUCCESS
;
1612 if (Base
== 0) Base
= 10;
1614 if ((Base
!= 2) && (Base
!= 8) &&
1615 (Base
!= 10) && (Base
!= 16))
1617 return STATUS_INVALID_PARAMETER
;
1631 *Pos
= 'A' + Digit
- 10;
1635 Len
= &Buffer
[64] - Pos
;
1638 return STATUS_BUFFER_OVERFLOW
;
1640 #if 1 /* It needs to be removed, when will probably use SEH in rtl */
1643 return STATUS_ACCESS_VIOLATION
;
1652 RtlCopyMemory(String
, Pos
, Len
);
1654 RtlCopyMemory(String
, Pos
, Len
+ 1);
1657 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1659 /* Get the error code */
1660 Status
= _SEH2_GetExceptionCode();
1672 * dest is never '\0' terminated because it may be equal to src, and src
1673 * might not be '\0' terminated. dest->Length is only set upon success.
1677 RtlUpcaseUnicodeString(
1678 IN OUT PUNICODE_STRING UniDest
,
1679 IN PCUNICODE_STRING UniSource
,
1680 IN BOOLEAN AllocateDestinationString
)
1686 if (AllocateDestinationString
== TRUE
)
1688 UniDest
->MaximumLength
= UniSource
->Length
;
1689 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1690 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1692 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1694 return STATUS_BUFFER_OVERFLOW
;
1697 j
= UniSource
->Length
/ sizeof(WCHAR
);
1699 for (i
= 0; i
< j
; i
++)
1701 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1704 UniDest
->Length
= UniSource
->Length
;
1705 return STATUS_SUCCESS
;
1712 * This function always writes a terminating '\0'.
1713 * It performs a partial copy if ansi is too small.
1717 RtlUpcaseUnicodeStringToAnsiString(
1718 IN OUT PANSI_STRING AnsiDest
,
1719 IN PUNICODE_STRING UniSource
,
1720 IN BOOLEAN AllocateDestinationString
)
1728 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1729 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1731 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1733 if (AllocateDestinationString
)
1735 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1736 AnsiDest
->MaximumLength
= Length
;
1737 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1739 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1741 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1744 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1750 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1752 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1753 AnsiDest
->Buffer
= NULL
;
1757 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1765 * This function always writes a terminating '\0'.
1766 * It performs a partial copy if ansi is too small.
1770 RtlUpcaseUnicodeStringToCountedOemString(
1771 IN OUT POEM_STRING OemDest
,
1772 IN PCUNICODE_STRING UniSource
,
1773 IN BOOLEAN AllocateDestinationString
)
1781 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1785 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1788 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1790 OemDest
->Length
= (USHORT
)Length
;
1792 if (AllocateDestinationString
)
1794 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1795 OemDest
->MaximumLength
= Length
;
1796 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1798 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1800 return STATUS_BUFFER_OVERFLOW
;
1803 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1809 /* Check for unmapped characters */
1810 if (NT_SUCCESS(Status
) && !RtlpDidUnicodeToOemWork(UniSource
, OemDest
))
1811 Status
= STATUS_UNMAPPABLE_CHARACTER
;
1813 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1815 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1816 OemDest
->Buffer
= NULL
;
1826 * Oem string is allways nullterminated
1827 * It performs a partial copy if oem is too small.
1831 RtlUpcaseUnicodeStringToOemString (
1832 IN OUT POEM_STRING OemDest
,
1833 IN PCUNICODE_STRING UniSource
,
1834 IN BOOLEAN AllocateDestinationString
)
1842 Length
= RtlUnicodeStringToOemSize(UniSource
);
1843 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1845 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1847 if (AllocateDestinationString
)
1849 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1850 OemDest
->MaximumLength
= Length
;
1851 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1853 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1855 return STATUS_BUFFER_OVERFLOW
;
1858 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1864 /* Check for unmapped characters */
1865 if (NT_SUCCESS(Status
) && !RtlpDidUnicodeToOemWork(UniSource
, OemDest
))
1866 Status
= STATUS_UNMAPPABLE_CHARACTER
;
1868 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1870 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1871 OemDest
->Buffer
= NULL
;
1875 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1883 * Bytes calculated including nullterm
1887 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1891 /* Convert the Mb String to Unicode Size */
1892 RtlMultiByteToUnicodeSize(&Size
,
1896 /* Return the size + null-char */
1897 return (Size
+ sizeof(WCHAR
));
1905 RtlStringFromGUID (IN REFGUID Guid
,
1906 OUT PUNICODE_STRING GuidString
)
1908 /* Setup the string */
1909 GuidString
->Length
= 38 * sizeof(WCHAR
);
1910 GuidString
->MaximumLength
= GuidString
->Length
+ sizeof(UNICODE_NULL
);
1911 GuidString
->Buffer
= RtlpAllocateStringMemory(GuidString
->MaximumLength
,
1913 if (!GuidString
->Buffer
) return STATUS_NO_MEMORY
;
1915 /* Now format the GUID */
1916 swprintf(GuidString
->Buffer
,
1917 L
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1929 return STATUS_SUCCESS
;
1936 * Bytes calculated including nullterm
1940 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1944 /* Convert the Unicode String to Mb Size */
1945 RtlUnicodeToMultiByteSize(&Size
,
1946 UnicodeString
->Buffer
,
1947 UnicodeString
->Length
);
1949 /* Return the size + null-char */
1950 return (Size
+ sizeof(CHAR
));
1958 RtlCompareUnicodeString(
1959 IN PCUNICODE_STRING s1
,
1960 IN PCUNICODE_STRING s2
,
1961 IN BOOLEAN CaseInsensitive
)
1967 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1971 if (CaseInsensitive
)
1973 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1977 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1979 if (!ret
) ret
= s1
->Length
- s2
->Length
;
1989 IN OUT PSTRING DestinationString
,
1990 IN PSTRING SourceString OPTIONAL
)
1995 /* Check if there was no source given */
1998 /* Simply return an empty string */
1999 DestinationString
->Length
= 0;
2003 /* Choose the smallest length */
2004 SourceLength
= min(DestinationString
->MaximumLength
,
2005 SourceString
->Length
);
2008 DestinationString
->Length
= (USHORT
)SourceLength
;
2010 /* Save the pointers to each buffer */
2011 p1
= DestinationString
->Buffer
;
2012 p2
= SourceString
->Buffer
;
2014 /* Loop the buffer */
2015 while (SourceLength
)
2017 /* Copy the character and move on */
2029 RtlCopyUnicodeString(
2030 IN OUT PUNICODE_STRING DestinationString
,
2031 IN PCUNICODE_STRING SourceString
)
2035 if(SourceString
== NULL
)
2037 DestinationString
->Length
= 0;
2041 SourceLength
= min(DestinationString
->MaximumLength
,
2042 SourceString
->Length
);
2043 DestinationString
->Length
= (USHORT
)SourceLength
;
2045 RtlCopyMemory(DestinationString
->Buffer
,
2046 SourceString
->Buffer
,
2049 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
2051 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2060 * Creates a nullterminated UNICODE_STRING
2064 RtlCreateUnicodeString(
2065 IN OUT PUNICODE_STRING UniDest
,
2072 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
2073 if (Length
> 0xFFFE) return FALSE
;
2075 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2077 if (UniDest
->Buffer
== NULL
) return FALSE
;
2079 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
2080 UniDest
->MaximumLength
= (USHORT
)Length
;
2081 UniDest
->Length
= Length
- sizeof (WCHAR
);
2091 RtlCreateUnicodeStringFromAsciiz(
2092 OUT PUNICODE_STRING Destination
,
2095 ANSI_STRING AnsiString
;
2098 RtlInitAnsiString(&AnsiString
, Source
);
2100 Status
= RtlAnsiStringToUnicodeString(Destination
,
2104 return NT_SUCCESS(Status
);
2111 * Dest is never '\0' terminated because it may be equal to src, and src
2112 * might not be '\0' terminated.
2113 * Dest->Length is only set upon success.
2117 RtlDowncaseUnicodeString(
2118 IN OUT PUNICODE_STRING UniDest
,
2119 IN PCUNICODE_STRING UniSource
,
2120 IN BOOLEAN AllocateDestinationString
)
2127 if (AllocateDestinationString
)
2129 UniDest
->MaximumLength
= UniSource
->Length
;
2130 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2131 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2133 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2135 return STATUS_BUFFER_OVERFLOW
;
2138 UniDest
->Length
= UniSource
->Length
;
2139 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2141 for (i
= 0 ; i
< StopGap
; i
++)
2143 if (UniSource
->Buffer
[i
] < L
'A')
2145 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2147 else if (UniSource
->Buffer
[i
] <= L
'Z')
2149 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2153 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2157 return STATUS_SUCCESS
;
2164 * if src is NULL dest is unchanged.
2165 * dest is '\0' terminated when the MaximumLength allowes it.
2166 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2170 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2178 UNICODE_STRING UnicodeSource
;
2180 RtlInitUnicodeString(&UnicodeSource
, Source
);
2181 Length
= UnicodeSource
.Length
;
2183 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2185 return STATUS_BUFFER_TOO_SMALL
;
2188 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2189 RtlMoveMemory(DestBuffer
, Source
, Length
);
2190 Destination
->Length
+= Length
;
2192 /* append terminating '\0' if enough space */
2193 if(Destination
->MaximumLength
> Destination
->Length
)
2195 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2199 return STATUS_SUCCESS
;
2206 * if src is NULL dest is unchanged.
2207 * dest is never '\0' terminated.
2211 RtlAppendAsciizToString(
2212 IN OUT PSTRING Destination
,
2219 Length
= (USHORT
)strlen(Source
);
2221 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2223 return STATUS_BUFFER_TOO_SMALL
;
2226 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2227 Destination
->Length
+= Length
;
2230 return STATUS_SUCCESS
;
2238 RtlUpperString(PSTRING DestinationString
,
2239 PSTRING SourceString
)
2244 Length
= min(SourceString
->Length
,
2245 DestinationString
->MaximumLength
);
2247 Src
= SourceString
->Buffer
;
2248 Dest
= DestinationString
->Buffer
;
2249 DestinationString
->Length
= Length
;
2252 *Dest
++ = RtlUpperChar(*Src
++);
2261 * See RtlpDuplicateUnicodeString
2265 RtlDuplicateUnicodeString(
2267 IN PCUNICODE_STRING SourceString
,
2268 OUT PUNICODE_STRING DestinationString
)
2272 if (SourceString
== NULL
|| DestinationString
== NULL
||
2273 SourceString
->Length
> SourceString
->MaximumLength
||
2274 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
2275 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4) {
2276 return STATUS_INVALID_PARAMETER
;
2280 if ((SourceString
->Length
== 0) &&
2281 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2282 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2284 DestinationString
->Length
= 0;
2285 DestinationString
->MaximumLength
= 0;
2286 DestinationString
->Buffer
= NULL
;
2290 UINT DestMaxLength
= SourceString
->Length
;
2292 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2293 DestMaxLength
+= sizeof(UNICODE_NULL
);
2295 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2296 if (DestinationString
->Buffer
== NULL
)
2297 return STATUS_NO_MEMORY
;
2299 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2300 DestinationString
->Length
= SourceString
->Length
;
2301 DestinationString
->MaximumLength
= DestMaxLength
;
2303 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2304 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2307 return STATUS_SUCCESS
;
2314 RtlValidateUnicodeString(IN ULONG Flags
,
2315 IN PCUNICODE_STRING UnicodeString
)
2317 /* currently no flags are supported! */
2321 ((UnicodeString
== NULL
) ||
2322 ((UnicodeString
->Length
!= 0) &&
2323 (UnicodeString
->Buffer
!= NULL
) &&
2324 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2325 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2326 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2328 /* a NULL pointer as a unicode string is considered to be a valid unicode
2330 return STATUS_SUCCESS
;
2334 return STATUS_INVALID_PARAMETER
;
2340 RtlFindCharInUnicodeString(IN ULONG Flags
,
2341 IN PUNICODE_STRING SearchString
,
2342 IN PCUNICODE_STRING MatchString
,
2343 OUT PUSHORT Position
)
2346 unsigned int search_idx
;
2352 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2354 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2356 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2358 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2359 return STATUS_SUCCESS
;
2364 return STATUS_NOT_FOUND
;
2369 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2371 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2373 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2375 *Position
= main_idx
* sizeof(WCHAR
);
2376 return STATUS_SUCCESS
;
2381 return STATUS_NOT_FOUND
;
2386 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2389 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2390 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2394 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2396 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2397 return STATUS_SUCCESS
;
2401 return STATUS_NOT_FOUND
;
2406 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2409 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2410 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2414 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2416 *Position
= main_idx
* sizeof(WCHAR
);
2417 return STATUS_SUCCESS
;
2421 return STATUS_NOT_FOUND
;
2425 return STATUS_NOT_FOUND
;