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 Unicode string.
408 * Functions which convert Unicode strings to OEM strings will set a
409 * DefaultChar from the OEM codepage when the characters are unknown.
410 * So check it against the Unicode string and return false when the
411 * Unicode string does not contain a TransDefaultChar.
415 RtlpDidUnicodeToOemWork(IN PCUNICODE_STRING UnicodeString
,
416 IN POEM_STRING OemString
)
420 if (NlsMbOemCodePageTag
== FALSE
)
422 /* single-byte code page */
423 /* Go through all characters of a string */
424 while (i
< OemString
->Length
)
426 /* Check if it got translated into a default char,
427 * but source char wasn't a default char equivalent
429 if ((OemString
->Buffer
[i
] == NlsOemDefaultChar
) &&
430 (UnicodeString
->Buffer
[i
] != NlsUnicodeDefaultChar
))
432 /* Yes, it means unmappable characters were found */
436 /* Move to the next char */
440 /* All chars were translated successfuly */
445 /* multibyte code page */
457 RtlIsValidOemCharacter(IN PWCHAR Char
)
467 * If source is NULL the length of source is assumed to be 0.
471 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
472 IN PCSZ SourceString
)
478 DestSize
= strlen(SourceString
);
479 DestinationString
->Length
= (USHORT
)DestSize
;
480 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
484 DestinationString
->Length
= 0;
485 DestinationString
->MaximumLength
= 0;
488 DestinationString
->Buffer
= (PCHAR
)SourceString
;
493 RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString
,
494 IN PCSZ SourceString
)
500 DestSize
= strlen(SourceString
);
501 if (DestSize
>= 0xFFFF) return STATUS_NAME_TOO_LONG
;
502 DestinationString
->Length
= (USHORT
)DestSize
;
503 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(CHAR
);
507 DestinationString
->Length
= 0;
508 DestinationString
->MaximumLength
= 0;
511 DestinationString
->Buffer
= (PCHAR
)SourceString
;
512 return STATUS_SUCCESS
;
519 * If source is NULL the length of source is assumed to be 0.
524 IN OUT PSTRING DestinationString
,
525 IN PCSZ SourceString
)
527 RtlInitAnsiString(DestinationString
, SourceString
);
534 * If source is NULL the length of source is assumed to be 0.
538 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
539 IN PCWSTR SourceString
)
545 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
546 DestinationString
->Length
= (USHORT
)DestSize
;
547 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
551 DestinationString
->Length
= 0;
552 DestinationString
->MaximumLength
= 0;
555 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
563 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
564 IN PCWSTR SourceString
)
570 DestSize
= wcslen(SourceString
) * sizeof(WCHAR
);
571 if (DestSize
>= 0xFFFC) return STATUS_NAME_TOO_LONG
;
572 DestinationString
->Length
= (USHORT
)DestSize
;
573 DestinationString
->MaximumLength
= (USHORT
)DestSize
+ sizeof(WCHAR
);
577 DestinationString
->Length
= 0;
578 DestinationString
->MaximumLength
= 0;
581 DestinationString
->Buffer
= (PWCHAR
)SourceString
;
582 return STATUS_SUCCESS
;
589 * Writes at most length characters to the string str.
590 * Str is nullterminated when length allowes it.
591 * When str fits exactly in length characters the nullterm is ommitted.
593 NTSTATUS NTAPI
RtlIntegerToChar(
594 ULONG value
, /* [I] Value to be converted */
595 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
596 ULONG length
, /* [I] Length of the str buffer in bytes */
597 PCHAR str
) /* [O] Destination for the converted value */
606 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
607 return STATUS_INVALID_PARAMETER
;
615 digit
= value
% base
;
616 value
= value
/ base
;
620 *pos
= 'A' + digit
- 10;
622 } while (value
!= 0L);
624 len
= &buffer
[32] - pos
;
626 return STATUS_BUFFER_OVERFLOW
;
627 } else if (str
== NULL
) {
628 return STATUS_ACCESS_VIOLATION
;
629 } else if (len
== length
) {
630 memcpy(str
, pos
, len
);
632 memcpy(str
, pos
, len
+ 1);
634 return STATUS_SUCCESS
;
644 IN ULONG Base OPTIONAL
,
645 IN ULONG Length OPTIONAL
,
660 if ((Radix
!= 2) && (Radix
!= 8) &&
661 (Radix
!= 10) && (Radix
!= 16))
663 return STATUS_INVALID_PARAMETER
;
667 while (v
|| tp
== temp
)
678 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
680 return STATUS_BUFFER_TOO_SMALL
;
688 return STATUS_SUCCESS
;
696 RtlIntegerToUnicodeString(
698 IN ULONG Base OPTIONAL
,
699 IN OUT PUNICODE_STRING String
)
701 ANSI_STRING AnsiString
;
705 Status
= RtlIntegerToChar(Value
, Base
, sizeof(Buffer
), Buffer
);
706 if (NT_SUCCESS(Status
))
708 AnsiString
.Buffer
= Buffer
;
709 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
710 AnsiString
.MaximumLength
= sizeof(Buffer
);
712 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
723 RtlInt64ToUnicodeString (
725 IN ULONG Base OPTIONAL
,
726 IN OUT PUNICODE_STRING String
)
728 LARGE_INTEGER LargeInt
;
729 ANSI_STRING AnsiString
;
733 LargeInt
.QuadPart
= Value
;
735 Status
= RtlLargeIntegerToChar(&LargeInt
, Base
, sizeof(Buffer
), Buffer
);
736 if (NT_SUCCESS(Status
))
738 AnsiString
.Buffer
= Buffer
;
739 AnsiString
.Length
= (USHORT
)strlen(Buffer
);
740 AnsiString
.MaximumLength
= sizeof(Buffer
);
742 Status
= RtlAnsiStringToUnicodeString(String
, &AnsiString
, FALSE
);
752 * TRUE if String2 contains String1 as a prefix.
757 PANSI_STRING String1
,
758 PANSI_STRING String2
,
759 BOOLEAN CaseInsensitive
)
765 if (String2
->Length
< String1
->Length
)
768 Length
= String1
->Length
;
769 pc1
= String1
->Buffer
;
770 pc2
= String2
->Buffer
;
778 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
786 if (*pc1
++ != *pc2
++)
799 * TRUE if String2 contains String1 as a prefix.
803 RtlPrefixUnicodeString(
804 PCUNICODE_STRING String1
,
805 PCUNICODE_STRING String2
,
806 BOOLEAN CaseInsensitive
)
812 if (String2
->Length
< String1
->Length
)
815 Length
= String1
->Length
/ 2;
816 pc1
= String1
->Buffer
;
817 pc2
= String2
->Buffer
;
825 if (RtlUpcaseUnicodeChar (*pc1
++)
826 != RtlUpcaseUnicodeChar (*pc2
++))
834 if( *pc1
++ != *pc2
++ )
847 RtlUnicodeStringToInteger(const UNICODE_STRING
*str
, /* [I] Unicode string to be converted */
848 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
849 ULONG
*value
) /* [O] Destination for the converted value */
851 LPWSTR lpwstr
= str
->Buffer
;
852 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
855 ULONG RunningTotal
= 0;
858 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
863 if (CharsRemaining
>= 1) {
864 if (*lpwstr
== '+') {
867 } else if (*lpwstr
== '-') {
876 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
877 if (lpwstr
[1] == 'b') {
881 } else if (lpwstr
[1] == 'o') {
885 } else if (lpwstr
[1] == 'x') {
891 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
892 return STATUS_INVALID_PARAMETER
;
896 return STATUS_ACCESS_VIOLATION
;
899 while (CharsRemaining
>= 1) {
900 wchCurrent
= *lpwstr
;
901 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
902 digit
= wchCurrent
- '0';
903 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
904 digit
= wchCurrent
- 'A' + 10;
905 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
906 digit
= wchCurrent
- 'a' + 10;
910 if (digit
< 0 || digit
>= base
) {
911 *value
= bMinus
? -RunningTotal
: RunningTotal
;
912 return STATUS_SUCCESS
;
915 RunningTotal
= RunningTotal
* base
+ digit
;
920 *value
= bMinus
? -RunningTotal
: RunningTotal
;
921 return STATUS_SUCCESS
;
928 * Bytes necessary for the conversion including nullterm.
932 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString
)
936 /* Convert the Unicode String to Mb Size */
937 RtlUnicodeToMultiByteSize(&Size
,
938 UnicodeString
->Buffer
,
939 UnicodeString
->Length
);
941 /* Return the size + the null char */
942 return (Size
+ sizeof(CHAR
));
949 * This function always writes a terminating '\0'.
950 * It performs a partial copy if ansi is too small.
954 RtlUnicodeStringToAnsiString(
955 IN OUT PANSI_STRING AnsiDest
,
956 IN PCUNICODE_STRING UniSource
,
957 IN BOOLEAN AllocateDestinationString
)
959 NTSTATUS Status
= STATUS_SUCCESS
;
966 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
967 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
969 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
971 if (AllocateDestinationString
)
973 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
974 AnsiDest
->MaximumLength
= Length
;
975 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
977 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
979 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
981 Status
= STATUS_BUFFER_OVERFLOW
;
982 AnsiDest
->Length
= AnsiDest
->MaximumLength
- 1;
985 RealStatus
= RtlUnicodeToMultiByteN(AnsiDest
->Buffer
,
991 if (!NT_SUCCESS(RealStatus
) && AllocateDestinationString
)
993 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
997 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1005 * This function always writes a terminating '\0'.
1006 * Does NOT perform a partial copy if unicode is too small!
1010 RtlOemStringToUnicodeString(
1011 IN OUT PUNICODE_STRING UniDest
,
1012 IN PCOEM_STRING OemSource
,
1013 IN BOOLEAN AllocateDestinationString
)
1021 Length
= RtlOemStringToUnicodeSize(OemSource
);
1022 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1024 UniDest
->Length
= (USHORT
)Length
- sizeof(WCHAR
);
1026 if (AllocateDestinationString
)
1028 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1029 UniDest
->MaximumLength
= Length
;
1030 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1032 else if (UniDest
->Length
>= UniDest
->MaximumLength
)
1034 return STATUS_BUFFER_OVERFLOW
;
1037 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1043 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1045 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1046 UniDest
->Buffer
= NULL
;
1050 UniDest
->Buffer
[Index
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1058 * This function always '\0' terminates the string returned.
1062 RtlUnicodeStringToOemString(
1063 IN OUT POEM_STRING OemDest
,
1064 IN PCUNICODE_STRING UniSource
,
1065 IN BOOLEAN AllocateDestinationString
)
1073 Length
= RtlUnicodeStringToOemSize(UniSource
);
1074 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1076 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1078 if (AllocateDestinationString
)
1080 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1081 OemDest
->MaximumLength
= Length
;
1082 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1084 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1086 return STATUS_BUFFER_OVERFLOW
;
1089 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1095 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1097 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1098 OemDest
->Buffer
= NULL
;
1102 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1106 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1112 * The length of the string if all tests were passed, 0 otherwise.
1116 RtlIsTextUnicode( PVOID buf
, INT len
, INT
*pf
)
1118 static const WCHAR std_control_chars
[] = {'\r','\n','\t',' ',0x3000,0};
1119 static const WCHAR byterev_control_chars
[] = {0x0d00,0x0a00,0x0900,0x2000,0};
1120 const WCHAR
*s
= buf
;
1122 unsigned int flags
= MAXULONG
, out_flags
= 0;
1124 if (len
< sizeof(WCHAR
))
1126 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
1133 * Apply various tests to the text string. According to the
1134 * docs, each test "passed" sets the corresponding flag in
1135 * the output flags. But some of the tests are mutually
1136 * exclusive, so I don't see how you could pass all tests ...
1139 /* Check for an odd length ... pass if even. */
1140 if (len
& 1) out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1142 if (((char *)buf
)[len
- 1] == 0)
1143 len
--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
1145 len
/= sizeof(WCHAR
);
1146 /* Windows only checks the first 256 characters */
1147 if (len
> 256) len
= 256;
1149 /* Check for the special byte order unicode marks. */
1150 if (*s
== 0xFEFF) out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1151 if (*s
== 0xFFFE) out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1153 /* apply some statistical analysis */
1154 if (flags
& IS_TEXT_UNICODE_STATISTICS
)
1157 /* FIXME: checks only for ASCII characters in the unicode stream */
1158 for (i
= 0; i
< len
; i
++)
1160 if (s
[i
] <= 255) stats
++;
1162 if (stats
> len
/ 2)
1163 out_flags
|= IS_TEXT_UNICODE_STATISTICS
;
1166 /* Check for unicode NULL chars */
1167 if (flags
& IS_TEXT_UNICODE_NULL_BYTES
)
1169 for (i
= 0; i
< len
; i
++)
1171 if (!(s
[i
] & 0xff) || !(s
[i
] >> 8))
1173 out_flags
|= IS_TEXT_UNICODE_NULL_BYTES
;
1179 if (flags
& IS_TEXT_UNICODE_CONTROLS
)
1181 for (i
= 0; i
< len
; i
++)
1183 if (strchrW(std_control_chars
, s
[i
]))
1185 out_flags
|= IS_TEXT_UNICODE_CONTROLS
;
1191 if (flags
& IS_TEXT_UNICODE_REVERSE_CONTROLS
)
1193 for (i
= 0; i
< len
; i
++)
1195 if (strchrW(byterev_control_chars
, s
[i
]))
1197 out_flags
|= IS_TEXT_UNICODE_REVERSE_CONTROLS
;
1208 /* check for flags that indicate it's definitely not valid Unicode */
1209 if (out_flags
& (IS_TEXT_UNICODE_REVERSE_MASK
| IS_TEXT_UNICODE_NOT_UNICODE_MASK
)) return FALSE
;
1210 /* now check for invalid ASCII, and assume Unicode if so */
1211 if (out_flags
& IS_TEXT_UNICODE_NOT_ASCII_MASK
) return TRUE
;
1212 /* now check for Unicode flags */
1213 if (out_flags
& IS_TEXT_UNICODE_UNICODE_MASK
) return TRUE
;
1223 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1224 * A partial copy is NOT performed if the dest buffer is too small!
1228 RtlOemStringToCountedUnicodeString(
1229 IN OUT PUNICODE_STRING UniDest
,
1230 IN PCOEM_STRING OemSource
,
1231 IN BOOLEAN AllocateDestinationString
)
1239 /* Calculate size of the string */
1240 Length
= RtlOemStringToCountedUnicodeSize(OemSource
);
1242 /* If it's 0 then zero out dest string and return */
1245 RtlZeroMemory(UniDest
, sizeof(UNICODE_STRING
));
1246 return STATUS_SUCCESS
;
1249 /* Check if length is a sane value */
1250 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1252 /* Store it in dest string */
1253 UniDest
->Length
= (USHORT
)Length
;
1255 /* If we're asked to alloc the string - do so */
1256 if (AllocateDestinationString
)
1258 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1259 UniDest
->MaximumLength
= Length
;
1260 if (!UniDest
->Buffer
) return STATUS_NO_MEMORY
;
1262 else if (UniDest
->Length
> UniDest
->MaximumLength
)
1264 return STATUS_BUFFER_OVERFLOW
;
1267 /* Do the conversion */
1268 Status
= RtlOemToUnicodeN(UniDest
->Buffer
,
1274 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1276 /* Conversion failed, free dest string and return status code */
1277 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1278 UniDest
->Buffer
= NULL
;
1282 return STATUS_SUCCESS
;
1289 * TRUE if the names are equal, FALSE if not
1292 * The comparison is case insensitive.
1296 RtlEqualComputerName(
1297 IN PUNICODE_STRING ComputerName1
,
1298 IN PUNICODE_STRING ComputerName2
)
1300 OEM_STRING OemString1
;
1301 OEM_STRING OemString2
;
1302 BOOLEAN Result
= FALSE
;
1304 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1
,
1308 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2
,
1312 Result
= RtlEqualString(&OemString1
, &OemString2
, FALSE
);
1313 RtlFreeOemString(&OemString2
);
1315 RtlFreeOemString(&OemString1
);
1325 * TRUE if the names are equal, FALSE if not
1328 * The comparison is case insensitive.
1332 RtlEqualDomainName (
1333 IN PUNICODE_STRING DomainName1
,
1334 IN PUNICODE_STRING DomainName2
1337 return RtlEqualComputerName(DomainName1
, DomainName2
);
1343 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1345 * Convert a string representation of a GUID into a GUID.
1348 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1349 * guid [O] Destination for the converted GUID
1352 * Success: STATUS_SUCCESS. guid contains the converted value.
1353 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1356 * See RtlStringFromGUID.
1361 IN UNICODE_STRING
*str
,
1366 const WCHAR
*lpszCLSID
= str
->Buffer
;
1367 BYTE
* lpOut
= (BYTE
*)guid
;
1369 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1371 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1372 * to memory: DWORD... WORD WORD BYTES............
1379 if (*lpszCLSID
!= '{')
1380 return STATUS_INVALID_PARAMETER
;
1387 if (*lpszCLSID
!= '-')
1388 return STATUS_INVALID_PARAMETER
;
1392 if (*lpszCLSID
!= '}')
1393 return STATUS_INVALID_PARAMETER
;
1398 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1401 /* Read two hex digits as a byte value */
1402 if (ch
>= '0' && ch
<= '9')
1404 else if (ch
>= 'a' && ch
<= 'f')
1406 else if (ch
>= 'A' && ch
<= 'F')
1409 return STATUS_INVALID_PARAMETER
;
1411 if (ch2
>= '0' && ch2
<= '9')
1413 else if (ch2
>= 'a' && ch2
<= 'f')
1414 ch2
= ch2
- 'a' + 10;
1415 else if (ch2
>= 'A' && ch2
<= 'F')
1416 ch2
= ch2
- 'A' + 10;
1418 return STATUS_INVALID_PARAMETER
;
1420 byte
= ch
<< 4 | ch2
;
1424 #ifndef WORDS_BIGENDIAN
1425 /* For Big Endian machines, we store the data such that the
1426 * dword/word members can be read as DWORDS and WORDS correctly. */
1458 lpszCLSID
++; /* Skip 2nd character of byte */
1466 return STATUS_SUCCESS
;
1474 RtlEraseUnicodeString(
1475 IN PUNICODE_STRING String
)
1477 if (String
->Buffer
&& String
->MaximumLength
)
1479 RtlZeroMemory(String
->Buffer
, String
->MaximumLength
);
1489 RtlHashUnicodeString(
1490 IN CONST UNICODE_STRING
*String
,
1491 IN BOOLEAN CaseInSensitive
,
1492 IN ULONG HashAlgorithm
,
1493 OUT PULONG HashValue
)
1495 if (String
!= NULL
&& HashValue
!= NULL
)
1497 switch (HashAlgorithm
)
1499 case HASH_STRING_ALGORITHM_DEFAULT
:
1500 case HASH_STRING_ALGORITHM_X65599
:
1505 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1507 if (CaseInSensitive
)
1509 for (c
= String
->Buffer
;
1513 /* only uppercase characters if they are 'a' ... 'z'! */
1514 *HashValue
= ((65599 * (*HashValue
)) +
1515 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1516 (*c
) - L
'a' + L
'A' : (*c
)));
1521 for (c
= String
->Buffer
;
1525 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1528 return STATUS_SUCCESS
;
1533 return STATUS_INVALID_PARAMETER
;
1540 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1541 * Does a partial copy if the dest buffer is too small
1545 RtlUnicodeStringToCountedOemString(
1546 IN OUT POEM_STRING OemDest
,
1547 IN PUNICODE_STRING UniSource
,
1548 IN BOOLEAN AllocateDestinationString
)
1556 /* Calculate size of the string */
1557 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1559 /* If it's 0 then zero out dest string and return */
1562 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1563 return STATUS_SUCCESS
;
1566 /* Check if length is a sane value */
1567 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1569 /* Store it in dest string */
1570 OemDest
->Length
= (USHORT
)Length
;
1572 /* If we're asked to alloc the string - do so */
1573 if (AllocateDestinationString
)
1575 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1576 OemDest
->MaximumLength
= Length
;
1577 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1579 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1581 return STATUS_BUFFER_OVERFLOW
;
1584 /* Do the conversion */
1585 Status
= RtlUnicodeToOemN(OemDest
->Buffer
,
1591 /* Check for unmapped character */
1592 if (NT_SUCCESS(Status
) && !RtlpDidUnicodeToOemWork(UniSource
, OemDest
))
1593 Status
= STATUS_UNMAPPABLE_CHARACTER
;
1595 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1597 /* Conversion failed, free dest string and return status code */
1598 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1599 OemDest
->Buffer
= NULL
;
1611 RtlLargeIntegerToChar(
1612 IN PLARGE_INTEGER Value
,
1615 IN OUT PCHAR String
)
1617 ULONGLONG Val
= Value
->QuadPart
;
1618 NTSTATUS Status
= STATUS_SUCCESS
;
1624 if (Base
== 0) Base
= 10;
1626 if ((Base
!= 2) && (Base
!= 8) &&
1627 (Base
!= 10) && (Base
!= 16))
1629 return STATUS_INVALID_PARAMETER
;
1643 *Pos
= 'A' + Digit
- 10;
1647 Len
= &Buffer
[64] - Pos
;
1650 return STATUS_BUFFER_OVERFLOW
;
1652 #if 1 /* It needs to be removed, when will probably use SEH in rtl */
1655 return STATUS_ACCESS_VIOLATION
;
1664 RtlCopyMemory(String
, Pos
, Len
);
1666 RtlCopyMemory(String
, Pos
, Len
+ 1);
1669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1671 /* Get the error code */
1672 Status
= _SEH2_GetExceptionCode();
1684 * dest is never '\0' terminated because it may be equal to src, and src
1685 * might not be '\0' terminated. dest->Length is only set upon success.
1689 RtlUpcaseUnicodeString(
1690 IN OUT PUNICODE_STRING UniDest
,
1691 IN PCUNICODE_STRING UniSource
,
1692 IN BOOLEAN AllocateDestinationString
)
1698 if (AllocateDestinationString
== TRUE
)
1700 UniDest
->MaximumLength
= UniSource
->Length
;
1701 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1702 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
1704 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1706 return STATUS_BUFFER_OVERFLOW
;
1709 j
= UniSource
->Length
/ sizeof(WCHAR
);
1711 for (i
= 0; i
< j
; i
++)
1713 UniDest
->Buffer
[i
] = RtlUpcaseUnicodeChar(UniSource
->Buffer
[i
]);
1716 UniDest
->Length
= UniSource
->Length
;
1717 return STATUS_SUCCESS
;
1724 * This function always writes a terminating '\0'.
1725 * It performs a partial copy if ansi is too small.
1729 RtlUpcaseUnicodeStringToAnsiString(
1730 IN OUT PANSI_STRING AnsiDest
,
1731 IN PUNICODE_STRING UniSource
,
1732 IN BOOLEAN AllocateDestinationString
)
1740 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1741 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1743 AnsiDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1745 if (AllocateDestinationString
)
1747 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1748 AnsiDest
->MaximumLength
= Length
;
1749 if (!AnsiDest
->Buffer
) return STATUS_NO_MEMORY
;
1751 else if (AnsiDest
->Length
>= AnsiDest
->MaximumLength
)
1753 if (!AnsiDest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1756 Status
= RtlUpcaseUnicodeToMultiByteN(AnsiDest
->Buffer
,
1762 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1764 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1765 AnsiDest
->Buffer
= NULL
;
1769 AnsiDest
->Buffer
[Index
] = ANSI_NULL
;
1777 * This function always writes a terminating '\0'.
1778 * It performs a partial copy if ansi is too small.
1782 RtlUpcaseUnicodeStringToCountedOemString(
1783 IN OUT POEM_STRING OemDest
,
1784 IN PCUNICODE_STRING UniSource
,
1785 IN BOOLEAN AllocateDestinationString
)
1793 Length
= RtlUnicodeStringToCountedOemSize(UniSource
);
1797 RtlZeroMemory(OemDest
, sizeof(OEM_STRING
));
1800 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1802 OemDest
->Length
= (USHORT
)Length
;
1804 if (AllocateDestinationString
)
1806 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1807 OemDest
->MaximumLength
= Length
;
1808 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1810 else if (OemDest
->Length
> OemDest
->MaximumLength
)
1812 return STATUS_BUFFER_OVERFLOW
;
1815 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1821 /* Check for unmapped characters */
1822 if (NT_SUCCESS(Status
) && !RtlpDidUnicodeToOemWork(UniSource
, OemDest
))
1823 Status
= STATUS_UNMAPPABLE_CHARACTER
;
1825 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1827 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1828 OemDest
->Buffer
= NULL
;
1838 * Oem string is allways nullterminated
1839 * It performs a partial copy if oem is too small.
1843 RtlUpcaseUnicodeStringToOemString (
1844 IN OUT POEM_STRING OemDest
,
1845 IN PCUNICODE_STRING UniSource
,
1846 IN BOOLEAN AllocateDestinationString
)
1854 Length
= RtlUnicodeStringToOemSize(UniSource
);
1855 if (Length
> MAXUSHORT
) return STATUS_INVALID_PARAMETER_2
;
1857 OemDest
->Length
= (USHORT
)Length
- sizeof(CHAR
);
1859 if (AllocateDestinationString
)
1861 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1862 OemDest
->MaximumLength
= Length
;
1863 if (!OemDest
->Buffer
) return STATUS_NO_MEMORY
;
1865 else if (OemDest
->Length
>= OemDest
->MaximumLength
)
1867 return STATUS_BUFFER_OVERFLOW
;
1870 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1876 /* Check for unmapped characters */
1877 if (NT_SUCCESS(Status
) && !RtlpDidUnicodeToOemWork(UniSource
, OemDest
))
1878 Status
= STATUS_UNMAPPABLE_CHARACTER
;
1880 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1882 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1883 OemDest
->Buffer
= NULL
;
1887 OemDest
->Buffer
[Index
] = ANSI_NULL
;
1895 * Bytes calculated including nullterm
1899 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString
)
1903 /* Convert the Mb String to Unicode Size */
1904 RtlMultiByteToUnicodeSize(&Size
,
1908 /* Return the size + null-char */
1909 return (Size
+ sizeof(WCHAR
));
1917 RtlStringFromGUID (IN REFGUID Guid
,
1918 OUT PUNICODE_STRING GuidString
)
1920 /* Setup the string */
1921 GuidString
->Length
= 38 * sizeof(WCHAR
);
1922 GuidString
->MaximumLength
= GuidString
->Length
+ sizeof(UNICODE_NULL
);
1923 GuidString
->Buffer
= RtlpAllocateStringMemory(GuidString
->MaximumLength
,
1925 if (!GuidString
->Buffer
) return STATUS_NO_MEMORY
;
1927 /* Now format the GUID */
1928 swprintf(GuidString
->Buffer
,
1929 L
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1941 return STATUS_SUCCESS
;
1948 * Bytes calculated including nullterm
1952 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString
)
1956 /* Convert the Unicode String to Mb Size */
1957 RtlUnicodeToMultiByteSize(&Size
,
1958 UnicodeString
->Buffer
,
1959 UnicodeString
->Length
);
1961 /* Return the size + null-char */
1962 return (Size
+ sizeof(CHAR
));
1970 RtlCompareUnicodeString(
1971 IN PCUNICODE_STRING s1
,
1972 IN PCUNICODE_STRING s2
,
1973 IN BOOLEAN CaseInsensitive
)
1979 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
1983 if (CaseInsensitive
)
1985 while (!ret
&& len
--) ret
= RtlUpcaseUnicodeChar(*p1
++) - RtlUpcaseUnicodeChar(*p2
++);
1989 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
1991 if (!ret
) ret
= s1
->Length
- s2
->Length
;
2001 IN OUT PSTRING DestinationString
,
2002 IN PSTRING SourceString OPTIONAL
)
2007 /* Check if there was no source given */
2010 /* Simply return an empty string */
2011 DestinationString
->Length
= 0;
2015 /* Choose the smallest length */
2016 SourceLength
= min(DestinationString
->MaximumLength
,
2017 SourceString
->Length
);
2020 DestinationString
->Length
= (USHORT
)SourceLength
;
2022 /* Save the pointers to each buffer */
2023 p1
= DestinationString
->Buffer
;
2024 p2
= SourceString
->Buffer
;
2026 /* Loop the buffer */
2027 while (SourceLength
)
2029 /* Copy the character and move on */
2041 RtlCopyUnicodeString(
2042 IN OUT PUNICODE_STRING DestinationString
,
2043 IN PCUNICODE_STRING SourceString
)
2047 if(SourceString
== NULL
)
2049 DestinationString
->Length
= 0;
2053 SourceLength
= min(DestinationString
->MaximumLength
,
2054 SourceString
->Length
);
2055 DestinationString
->Length
= (USHORT
)SourceLength
;
2057 RtlCopyMemory(DestinationString
->Buffer
,
2058 SourceString
->Buffer
,
2061 if (DestinationString
->Length
< DestinationString
->MaximumLength
)
2063 DestinationString
->Buffer
[SourceLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2072 * Creates a nullterminated UNICODE_STRING
2076 RtlCreateUnicodeString(
2077 IN OUT PUNICODE_STRING UniDest
,
2084 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
2085 if (Length
> 0xFFFE) return FALSE
;
2087 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2089 if (UniDest
->Buffer
== NULL
) return FALSE
;
2091 RtlCopyMemory(UniDest
->Buffer
, Source
, Length
);
2092 UniDest
->MaximumLength
= (USHORT
)Length
;
2093 UniDest
->Length
= Length
- sizeof (WCHAR
);
2103 RtlCreateUnicodeStringFromAsciiz(
2104 OUT PUNICODE_STRING Destination
,
2107 ANSI_STRING AnsiString
;
2110 RtlInitAnsiString(&AnsiString
, Source
);
2112 Status
= RtlAnsiStringToUnicodeString(Destination
,
2116 return NT_SUCCESS(Status
);
2123 * Dest is never '\0' terminated because it may be equal to src, and src
2124 * might not be '\0' terminated.
2125 * Dest->Length is only set upon success.
2129 RtlDowncaseUnicodeString(
2130 IN OUT PUNICODE_STRING UniDest
,
2131 IN PCUNICODE_STRING UniSource
,
2132 IN BOOLEAN AllocateDestinationString
)
2139 if (AllocateDestinationString
)
2141 UniDest
->MaximumLength
= UniSource
->Length
;
2142 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2143 if (UniDest
->Buffer
== NULL
) return STATUS_NO_MEMORY
;
2145 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2147 return STATUS_BUFFER_OVERFLOW
;
2150 UniDest
->Length
= UniSource
->Length
;
2151 StopGap
= UniSource
->Length
/ sizeof(WCHAR
);
2153 for (i
= 0 ; i
< StopGap
; i
++)
2155 if (UniSource
->Buffer
[i
] < L
'A')
2157 UniDest
->Buffer
[i
] = UniSource
->Buffer
[i
];
2159 else if (UniSource
->Buffer
[i
] <= L
'Z')
2161 UniDest
->Buffer
[i
] = (UniSource
->Buffer
[i
] + (L
'a' - L
'A'));
2165 UniDest
->Buffer
[i
] = RtlDowncaseUnicodeChar(UniSource
->Buffer
[i
]);
2169 return STATUS_SUCCESS
;
2176 * if src is NULL dest is unchanged.
2177 * dest is '\0' terminated when the MaximumLength allowes it.
2178 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2182 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2190 UNICODE_STRING UnicodeSource
;
2192 RtlInitUnicodeString(&UnicodeSource
, Source
);
2193 Length
= UnicodeSource
.Length
;
2195 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2197 return STATUS_BUFFER_TOO_SMALL
;
2200 DestBuffer
= &Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)];
2201 RtlMoveMemory(DestBuffer
, Source
, Length
);
2202 Destination
->Length
+= Length
;
2204 /* append terminating '\0' if enough space */
2205 if(Destination
->MaximumLength
> Destination
->Length
)
2207 DestBuffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2211 return STATUS_SUCCESS
;
2218 * if src is NULL dest is unchanged.
2219 * dest is never '\0' terminated.
2223 RtlAppendAsciizToString(
2224 IN OUT PSTRING Destination
,
2231 Length
= (USHORT
)strlen(Source
);
2233 if (Destination
->Length
+ Length
> Destination
->MaximumLength
)
2235 return STATUS_BUFFER_TOO_SMALL
;
2238 RtlMoveMemory(&Destination
->Buffer
[Destination
->Length
], Source
, Length
);
2239 Destination
->Length
+= Length
;
2242 return STATUS_SUCCESS
;
2250 RtlUpperString(PSTRING DestinationString
,
2251 PSTRING SourceString
)
2256 Length
= min(SourceString
->Length
,
2257 DestinationString
->MaximumLength
);
2259 Src
= SourceString
->Buffer
;
2260 Dest
= DestinationString
->Buffer
;
2261 DestinationString
->Length
= Length
;
2264 *Dest
++ = RtlUpperChar(*Src
++);
2273 * See RtlpDuplicateUnicodeString
2277 RtlDuplicateUnicodeString(
2279 IN PCUNICODE_STRING SourceString
,
2280 OUT PUNICODE_STRING DestinationString
)
2284 if (SourceString
== NULL
|| DestinationString
== NULL
||
2285 SourceString
->Length
> SourceString
->MaximumLength
||
2286 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
2287 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4) {
2288 return STATUS_INVALID_PARAMETER
;
2292 if ((SourceString
->Length
== 0) &&
2293 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
2294 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
2296 DestinationString
->Length
= 0;
2297 DestinationString
->MaximumLength
= 0;
2298 DestinationString
->Buffer
= NULL
;
2302 UINT DestMaxLength
= SourceString
->Length
;
2304 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2305 DestMaxLength
+= sizeof(UNICODE_NULL
);
2307 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2308 if (DestinationString
->Buffer
== NULL
)
2309 return STATUS_NO_MEMORY
;
2311 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2312 DestinationString
->Length
= SourceString
->Length
;
2313 DestinationString
->MaximumLength
= DestMaxLength
;
2315 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
2316 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2319 return STATUS_SUCCESS
;
2326 RtlValidateUnicodeString(IN ULONG Flags
,
2327 IN PCUNICODE_STRING UnicodeString
)
2329 /* currently no flags are supported! */
2333 ((UnicodeString
== NULL
) ||
2334 ((UnicodeString
->Length
!= 0) &&
2335 (UnicodeString
->Buffer
!= NULL
) &&
2336 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2337 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2338 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2340 /* a NULL pointer as a unicode string is considered to be a valid unicode
2342 return STATUS_SUCCESS
;
2346 return STATUS_INVALID_PARAMETER
;
2352 RtlFindCharInUnicodeString(IN ULONG Flags
,
2353 IN PUNICODE_STRING SearchString
,
2354 IN PCUNICODE_STRING MatchString
,
2355 OUT PUSHORT Position
)
2358 unsigned int search_idx
;
2364 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2366 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2368 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2370 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2371 return STATUS_SUCCESS
;
2376 return STATUS_NOT_FOUND
;
2381 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2383 for (search_idx
= 0; search_idx
< MatchString
->Length
/ sizeof(WCHAR
); search_idx
++)
2385 if (SearchString
->Buffer
[main_idx
] == MatchString
->Buffer
[search_idx
])
2387 *Position
= main_idx
* sizeof(WCHAR
);
2388 return STATUS_SUCCESS
;
2393 return STATUS_NOT_FOUND
;
2398 for (main_idx
= 0; main_idx
< SearchString
->Length
/ sizeof(WCHAR
); main_idx
++)
2401 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2402 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2406 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2408 *Position
= (main_idx
+ 1) * sizeof(WCHAR
);
2409 return STATUS_SUCCESS
;
2413 return STATUS_NOT_FOUND
;
2418 for (main_idx
= SearchString
->Length
/ sizeof(WCHAR
) - 1; main_idx
>= 0; main_idx
--)
2421 while (search_idx
< MatchString
->Length
/ sizeof(WCHAR
) &&
2422 SearchString
->Buffer
[main_idx
] != MatchString
->Buffer
[search_idx
])
2426 if (search_idx
>= MatchString
->Length
/ sizeof(WCHAR
))
2428 *Position
= main_idx
* sizeof(WCHAR
);
2429 return STATUS_SUCCESS
;
2433 return STATUS_NOT_FOUND
;
2437 return STATUS_NOT_FOUND
;
2444 * Get the maximum of MAX_COMPUTERNAME_LENGTH characters from the dns.host name until the dot is found.
2445 * Convert is to an uppercase oem string and check for unmapped characters.
2446 * Then convert the oem string back to an unicode string.
2450 RtlDnsHostNameToComputerName(PUNICODE_STRING ComputerName
,PUNICODE_STRING DnsHostName
,BOOLEAN AllocateComputerNameString
)
2454 ULONG ComputerNameLength
;
2455 ULONG ComputerNameOemNLength
;
2456 OEM_STRING ComputerNameOem
;
2457 CHAR ComputerNameOemN
[MAX_COMPUTERNAME_LENGTH
+ 1];
2459 Status
= STATUS_INVALID_COMPUTER_NAME
;
2460 ComputerNameLength
= DnsHostName
->Length
;
2462 /* find the first dot in the dns host name */
2463 for (Length
= 0;Length
< DnsHostName
->Length
/sizeof(WCHAR
);Length
++)
2465 if (DnsHostName
->Buffer
[Length
] == L
'.')
2467 /* dot found, so set the length for the oem translation */
2468 ComputerNameLength
= Length
*sizeof(WCHAR
);
2473 /* the computername must have one character */
2474 if (ComputerNameLength
> 0)
2476 ComputerNameOemNLength
= 0;
2477 /* convert to oem string and use uppercase letters */
2478 Status
= RtlUpcaseUnicodeToOemN(ComputerNameOemN
,
2479 MAX_COMPUTERNAME_LENGTH
,
2480 &ComputerNameOemNLength
,
2481 DnsHostName
->Buffer
,
2482 ComputerNameLength
);
2483 /* status STATUS_BUFFER_OVERFLOW is not a problem since the computername shoud only
2484 have MAX_COMPUTERNAME_LENGTH characters */
2485 if ((Status
== STATUS_SUCCESS
) ||
2486 (Status
== STATUS_BUFFER_OVERFLOW
))
2488 /* set the termination for the oem string */
2489 ComputerNameOemN
[MAX_COMPUTERNAME_LENGTH
] = 0;
2490 /* set status for the case the next function failed */
2491 Status
= STATUS_INVALID_COMPUTER_NAME
;
2492 /* fillup the oem string structure with the converted computername
2493 and check it for unmapped characters */
2494 ComputerNameOem
.Buffer
= ComputerNameOemN
;
2495 ComputerNameOem
.Length
= (USHORT
)ComputerNameOemNLength
;
2496 ComputerNameOem
.MaximumLength
= (USHORT
)(MAX_COMPUTERNAME_LENGTH
+ 1);
2497 if (RtlpDidUnicodeToOemWork(DnsHostName
, &ComputerNameOem
) == TRUE
)
2499 /* no unmapped character so convert it back to an unicode string */
2500 Status
= RtlOemStringToUnicodeString(ComputerName
,
2502 AllocateComputerNameString
);