4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
6 * Copyright (C) 2003 Thomas Mertes
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 /* GLOBALS *******************************************************************/
30 #define TAG_USTR TAG('U', 'S', 'T', 'R')
31 #define TAG_ASTR TAG('A', 'S', 'T', 'R')
32 #define TAG_OSTR TAG('O', 'S', 'T', 'R')
35 extern BOOLEAN NlsMbCodePageTag
;
36 extern BOOLEAN NlsMbOemCodePageTag
;
38 /* FUNCTIONS *****************************************************************/
45 RtlAnsiCharToUnicodeChar (IN CHAR AnsiChar
)
53 Size
= (NlsLeadByteInfo
[AnsiChar
] == 0) ? 1 : 2;
56 RtlMultiByteToUnicodeN (&UnicodeChar
,
70 * The calculated size in bytes including nullterm.
74 RtlAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
78 RtlMultiByteToUnicodeSize(&Size
,
91 * If src->length is zero dest is unchanged.
92 * Dest is never nullterminated.
96 RtlAppendStringToString(IN OUT PSTRING Destination
,
101 if (Source
->Length
== 0)
102 return(STATUS_SUCCESS
);
104 if (Destination
->Length
+ Source
->Length
>= Destination
->MaximumLength
)
105 return(STATUS_BUFFER_TOO_SMALL
);
107 Ptr
= Destination
->Buffer
+ Destination
->Length
;
111 Ptr
+= Source
->Length
;
114 Destination
->Length
+= Source
->Length
;
116 return(STATUS_SUCCESS
);
125 * If src->length is zero dest is unchanged.
126 * Dest is nullterminated when the MaximumLength allowes it.
127 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
131 RtlAppendUnicodeStringToString(
132 IN OUT PUNICODE_STRING Destination
,
133 IN PUNICODE_STRING Source
)
136 if ((Source
->Length
+ Destination
->Length
) > Destination
->MaximumLength
)
137 return STATUS_BUFFER_TOO_SMALL
;
139 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
->Buffer
, Source
->Length
);
140 Destination
->Length
+= Source
->Length
;
141 /* append terminating '\0' if enough space */
142 if( Destination
->MaximumLength
> Destination
->Length
)
143 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
145 return STATUS_SUCCESS
;
149 /**************************************************************************
150 * RtlCharToInteger (NTDLL.@)
152 * Converts a character string into its integer equivalent.
155 * Success: STATUS_SUCCESS. value contains the converted number
156 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
157 * STATUS_ACCESS_VIOLATION, if value is NULL.
160 * For base 0 it uses 10 as base and the string should be in the format
161 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
162 * For other bases the string should be in the format
163 * "{whitespace} [+|-] {digits}".
164 * No check is made for value overflow, only the lower 32 bits are assigned.
165 * If str is NULL it crashes, as the native function does.
168 * This function does not read garbage behind '\0' as the native version does.
173 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
174 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
175 PULONG value
) /* [O] Destination for the converted value */
179 ULONG RunningTotal
= 0;
182 while (*str
!= '\0' && *str
<= ' ') {
188 } else if (*str
== '-') {
199 } else if (str
[1] == 'o') {
202 } else if (str
[1] == 'x') {
207 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
208 return STATUS_INVALID_PARAMETER
;
212 return STATUS_ACCESS_VIOLATION
;
215 while (*str
!= '\0') {
217 if (chCurrent
>= '0' && chCurrent
<= '9') {
218 digit
= chCurrent
- '0';
219 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
220 digit
= chCurrent
- 'A' + 10;
221 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
222 digit
= chCurrent
- 'a' + 10;
226 if (digit
< 0 || digit
>= (int)base
) {
227 *value
= bMinus
? -RunningTotal
: RunningTotal
;
228 return STATUS_SUCCESS
;
231 RunningTotal
= RunningTotal
* base
+ digit
;
235 *value
= bMinus
? -RunningTotal
: RunningTotal
;
236 return STATUS_SUCCESS
;
247 IN BOOLEAN CaseInsensitive
)
253 if (String1
&& String2
)
255 len1
= String1
->Length
;
256 len2
= String2
->Length
;
257 s1
= String1
->Buffer
;
258 s2
= String2
->Buffer
;
266 c1
= len1
-- ? RtlUpperChar (*s1
++) : 0;
267 c2
= len2
-- ? RtlUpperChar (*s2
++) : 0;
268 if (!c1
|| !c2
|| c1
!= c2
)
276 c1
= len1
-- ? *s1
++ : 0;
277 c2
= len2
-- ? *s2
++ : 0;
278 if (!c1
|| !c2
|| c1
!= c2
)
293 * TRUE if strings are equal.
300 IN BOOLEAN CaseInsensitive
)
306 if (String1
->Length
!= String2
->Length
)
309 p1
= String1
->Buffer
;
310 p2
= String2
->Buffer
;
311 for (i
= 0; i
< String1
->Length
; i
++)
313 if (CaseInsensitive
== TRUE
)
315 c1
= RtlUpperChar (*p1
);
316 c2
= RtlUpperChar (*p2
);
339 * TRUE if strings are equal.
343 RtlEqualUnicodeString(
344 IN CONST UNICODE_STRING
*String1
,
345 IN CONST UNICODE_STRING
*String2
,
346 IN BOOLEAN CaseInsensitive
)
352 if (String1
->Length
!= String2
->Length
)
355 pw1
= String1
->Buffer
;
356 pw2
= String2
->Buffer
;
358 for (i
= 0; i
< String1
->Length
/ sizeof(WCHAR
); i
++)
360 if (CaseInsensitive
== TRUE
)
362 wc1
= RtlUpcaseUnicodeChar (*pw1
);
363 wc2
= RtlUpcaseUnicodeChar (*pw2
);
387 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
389 if (AnsiString
->Buffer
== NULL
)
392 ExFreePoolWithTag(AnsiString
->Buffer
, TAG_ASTR
);
394 AnsiString
->Buffer
= NULL
;
395 AnsiString
->Length
= 0;
396 AnsiString
->MaximumLength
= 0;
405 RtlFreeOemString(IN POEM_STRING OemString
)
407 if (OemString
->Buffer
== NULL
)
410 ExFreePoolWithTag(OemString
->Buffer
, TAG_OSTR
);
412 OemString
->Buffer
= NULL
;
413 OemString
->Length
= 0;
414 OemString
->MaximumLength
= 0;
423 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
425 if (UnicodeString
->Buffer
== NULL
)
428 ExFreePoolWithTag(UnicodeString
->Buffer
, TAG_USTR
);
430 UnicodeString
->Buffer
= NULL
;
431 UnicodeString
->Length
= 0;
432 UnicodeString
->MaximumLength
= 0;
440 RtlIsValidOemCharacter (
452 * If source is NULL the length of source is assumed to be 0.
456 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
457 IN PCSZ SourceString
)
461 if (SourceString
== NULL
)
463 DestinationString
->Length
= 0;
464 DestinationString
->MaximumLength
= 0;
468 DestSize
= strlen ((const char *)SourceString
);
469 DestinationString
->Length
= DestSize
;
470 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
472 DestinationString
->Buffer
= (PCHAR
)SourceString
;
481 * If source is NULL the length of source is assumed to be 0.
486 IN OUT PSTRING DestinationString
,
487 IN PCSZ SourceString
)
491 if (SourceString
== NULL
)
493 DestinationString
->Length
= 0;
494 DestinationString
->MaximumLength
= 0;
498 DestSize
= strlen((const char *)SourceString
);
499 DestinationString
->Length
= DestSize
;
500 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
502 DestinationString
->Buffer
= (PCHAR
)SourceString
;
510 * If source is NULL the length of source is assumed to be 0.
514 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
515 IN PCWSTR SourceString
)
519 DPRINT("RtlInitUnicodeString(DestinationString 0x%p, SourceString 0x%p)\n",
523 if (SourceString
== NULL
)
525 DestinationString
->Length
= 0;
526 DestinationString
->MaximumLength
= 0;
530 DestSize
= wcslen((PWSTR
)SourceString
) * sizeof(WCHAR
);
531 DestinationString
->Length
= DestSize
;
532 DestinationString
->MaximumLength
= DestSize
+ sizeof(WCHAR
);
534 DestinationString
->Buffer
= (PWSTR
)SourceString
;
541 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
542 IN PCWSTR SourceString
)
546 if (SourceString
!= NULL
)
548 Length
= wcslen(SourceString
) * sizeof(WCHAR
);
550 return STATUS_NAME_TOO_LONG
;
552 DestinationString
->Length
= Length
;
553 DestinationString
->MaximumLength
= Length
+ sizeof(WCHAR
);
554 DestinationString
->Buffer
= (PWSTR
)SourceString
;
558 DestinationString
->Length
= 0;
559 DestinationString
->MaximumLength
= 0;
560 DestinationString
->Buffer
= NULL
;
563 return STATUS_SUCCESS
;
570 * Writes at most length characters to the string str.
571 * Str is nullterminated when length allowes it.
572 * When str fits exactly in length characters the nullterm is ommitted.
593 if ((Radix
!= 2) && (Radix
!= 8) &&
594 (Radix
!= 10) && (Radix
!= 16))
596 return STATUS_INVALID_PARAMETER
;
600 while (v
|| tp
== temp
)
611 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
613 return STATUS_BUFFER_TOO_SMALL
;
621 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
;
686 RtlIntegerToUnicodeString(
688 IN ULONG Base
, /* optional */
689 IN OUT PUNICODE_STRING String
)
691 ANSI_STRING AnsiString
;
695 Status
= RtlIntegerToChar (Value
,
699 if (!NT_SUCCESS(Status
))
702 AnsiString
.Buffer
= Buffer
;
703 AnsiString
.Length
= strlen (Buffer
);
704 AnsiString
.MaximumLength
= sizeof(Buffer
);
706 Status
= RtlAnsiStringToUnicodeString (String
,
719 RtlInt64ToUnicodeString (
721 IN ULONG Base OPTIONAL
,
722 IN OUT PUNICODE_STRING String
725 LARGE_INTEGER LargeInt
;
726 ANSI_STRING AnsiString
;
730 LargeInt
.QuadPart
= Value
;
732 Status
= RtlLargeIntegerToChar (&LargeInt
,
736 if (!NT_SUCCESS(Status
))
739 AnsiString
.Buffer
= Buffer
;
740 AnsiString
.Length
= strlen (Buffer
);
741 AnsiString
.MaximumLength
= sizeof(Buffer
);
743 Status
= RtlAnsiStringToUnicodeString (String
,
755 * TRUE if String2 contains String1 as a prefix.
760 PANSI_STRING String1
,
761 PANSI_STRING String2
,
762 BOOLEAN CaseInsensitive
)
768 if (String2
->Length
< String1
->Length
)
771 Length
= String1
->Length
;
772 pc1
= String1
->Buffer
;
773 pc2
= String2
->Buffer
;
781 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
789 if (*pc1
++ != *pc2
++)
803 * TRUE if String2 contains String1 as a prefix.
807 RtlPrefixUnicodeString(
808 PUNICODE_STRING String1
,
809 PUNICODE_STRING String2
,
810 BOOLEAN CaseInsensitive
)
816 if (String2
->Length
< String1
->Length
)
819 Length
= String1
->Length
/ 2;
820 pc1
= String1
->Buffer
;
821 pc2
= String2
->Buffer
;
829 if (RtlUpcaseUnicodeChar (*pc1
++)
830 != RtlUpcaseUnicodeChar (*pc2
++))
838 if( *pc1
++ != *pc2
++ )
847 /**************************************************************************
848 * RtlUnicodeStringToInteger (NTDLL.@)
850 * Converts an unicode string into its integer equivalent.
853 * Success: STATUS_SUCCESS. value contains the converted number
854 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
855 * STATUS_ACCESS_VIOLATION, if value is NULL.
858 * For base 0 it uses 10 as base and the string should be in the format
859 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
860 * For other bases the string should be in the format
861 * "{whitespace} [+|-] {digits}".
862 * No check is made for value overflow, only the lower 32 bits are assigned.
863 * If str is NULL it crashes, as the native function does.
865 * Note that regardless of success or failure status, we should leave the
866 * partial value in Value. An error is never returned based on the chars
870 * This function does not read garbage on string length 0 as the native
875 RtlUnicodeStringToInteger(
876 PUNICODE_STRING str
, /* [I] Unicode string to be converted */
877 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
878 PULONG value
) /* [O] Destination for the converted value */
880 LPWSTR lpwstr
= str
->Buffer
;
881 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
884 ULONG RunningTotal
= 0;
887 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
892 if (CharsRemaining
>= 1) {
893 if (*lpwstr
== '+') {
896 } else if (*lpwstr
== '-') {
905 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
906 if (lpwstr
[1] == 'b') {
910 } else if (lpwstr
[1] == 'o') {
914 } else if (lpwstr
[1] == 'x') {
920 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
921 return STATUS_INVALID_PARAMETER
;
925 return STATUS_ACCESS_VIOLATION
;
928 while (CharsRemaining
>= 1) {
929 wchCurrent
= *lpwstr
;
930 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
931 digit
= wchCurrent
- '0';
932 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
933 digit
= wchCurrent
- 'A' + 10;
934 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
935 digit
= wchCurrent
- 'a' + 10;
939 if (digit
< 0 || digit
>= (int)base
) {
940 *value
= bMinus
? -RunningTotal
: RunningTotal
;
941 return STATUS_SUCCESS
;
944 RunningTotal
= RunningTotal
* base
+ digit
;
949 *value
= bMinus
? -RunningTotal
: RunningTotal
;
950 return STATUS_SUCCESS
;
958 * Bytes necessary for the conversion including nullterm.
962 RtlUnicodeStringToOemSize(
963 IN PUNICODE_STRING UnicodeString
)
967 RtlUnicodeToMultiByteSize (&Size
,
968 UnicodeString
->Buffer
,
969 UnicodeString
->Length
);
971 return Size
+1; //NB: incl. nullterm
978 * This function always writes a terminating '\0'.
979 * It performs a partial copy if ansi is too small.
983 RtlpUnicodeStringToAnsiString(
984 IN OUT PANSI_STRING AnsiDest
,
985 IN PUNICODE_STRING UniSource
,
986 IN BOOLEAN AllocateDestinationString
,
987 IN POOL_TYPE PoolType
)
989 NTSTATUS Status
= STATUS_SUCCESS
;
990 ULONG Length
; //including nullterm
992 if (NlsMbCodePageTag
== TRUE
)
994 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
997 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
999 AnsiDest
->Length
= Length
- sizeof(CHAR
);
1001 if (AllocateDestinationString
)
1003 AnsiDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_ASTR
);
1004 if (AnsiDest
->Buffer
== NULL
)
1005 return STATUS_NO_MEMORY
;
1007 AnsiDest
->MaximumLength
= Length
;
1009 else if (AnsiDest
->MaximumLength
== 0)
1011 return STATUS_BUFFER_TOO_SMALL
;
1013 else if (Length
> AnsiDest
->MaximumLength
)
1015 //make room for nullterm
1016 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1019 Status
= RtlUnicodeToMultiByteN (AnsiDest
->Buffer
,
1025 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1027 ExFreePoolWithTag(AnsiDest
->Buffer
, TAG_ASTR
);
1031 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1040 * See RtlpUnicodeStringToAnsiString
1044 RtlUnicodeStringToAnsiString(
1045 IN OUT PANSI_STRING AnsiDest
,
1046 IN PUNICODE_STRING UniSource
,
1047 IN BOOLEAN AllocateDestinationString
)
1049 return RtlpUnicodeStringToAnsiString(
1052 AllocateDestinationString
,
1060 * This function always writes a terminating '\0'.
1061 * Does NOT perform a partial copy if unicode is too small!
1065 RtlpOemStringToUnicodeString(
1066 IN OUT PUNICODE_STRING UniDest
,
1067 IN POEM_STRING OemSource
,
1068 IN BOOLEAN AllocateDestinationString
,
1069 IN POOL_TYPE PoolType
)
1072 ULONG Length
; //including nullterm
1074 if (NlsMbOemCodePageTag
== TRUE
)
1075 Length
= RtlOemStringToUnicodeSize(OemSource
);
1077 Length
= (OemSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
1079 if (Length
> 0xffff)
1080 return STATUS_INVALID_PARAMETER_2
;
1082 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
1084 if (AllocateDestinationString
)
1086 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_USTR
);
1087 if (UniDest
->Buffer
== NULL
)
1088 return STATUS_NO_MEMORY
;
1090 UniDest
->MaximumLength
= Length
;
1092 else if (Length
> UniDest
->MaximumLength
)
1094 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
1095 return STATUS_BUFFER_TOO_SMALL
;
1098 //FIXME: Do we need this????? -Gunnar
1099 RtlZeroMemory (UniDest
->Buffer
,
1102 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1108 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1110 ExFreePoolWithTag(UniDest
->Buffer
, TAG_USTR
);
1114 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1115 return STATUS_SUCCESS
;
1123 * See RtlpOemStringToUnicodeString
1127 RtlOemStringToUnicodeString(
1128 IN OUT PUNICODE_STRING UniDest
,
1129 IN POEM_STRING OemSource
,
1130 IN BOOLEAN AllocateDestinationString
)
1132 return RtlpOemStringToUnicodeString(
1135 AllocateDestinationString
,
1143 * This function always '\0' terminates the string returned.
1147 RtlpUnicodeStringToOemString(
1148 IN OUT POEM_STRING OemDest
,
1149 IN PUNICODE_STRING UniSource
,
1150 IN BOOLEAN AllocateDestinationString
,
1151 IN POOL_TYPE PoolType
)
1153 NTSTATUS Status
= STATUS_SUCCESS
;
1154 ULONG Length
; //including nullterm
1156 if (NlsMbOemCodePageTag
== TRUE
)
1157 Length
= RtlUnicodeStringToAnsiSize (UniSource
);
1159 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1161 if (Length
> 0x0000FFFF)
1162 return STATUS_INVALID_PARAMETER_2
;
1164 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1166 if (AllocateDestinationString
)
1168 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
1169 if (OemDest
->Buffer
== NULL
)
1170 return STATUS_NO_MEMORY
;
1172 OemDest
->MaximumLength
= Length
;
1174 else if (OemDest
->MaximumLength
== 0)
1176 return STATUS_BUFFER_TOO_SMALL
;
1178 else if (Length
> OemDest
->MaximumLength
)
1180 //make room for nullterm
1181 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1184 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1190 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1192 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
1196 OemDest
->Buffer
[OemDest
->Length
] = 0;
1204 * See RtlpUnicodeStringToOemString.
1208 RtlUnicodeStringToOemString(
1209 IN OUT POEM_STRING OemDest
,
1210 IN PUNICODE_STRING UniSource
,
1211 IN BOOLEAN AllocateDestinationString
)
1213 return RtlpUnicodeStringToOemString(
1216 AllocateDestinationString
,
1220 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1227 * The length of the string if all tests were passed, 0 otherwise.
1230 RtlIsTextUnicode (PVOID Buffer
,
1235 ULONG in_flags
= (ULONG
)-1;
1236 ULONG out_flags
= 0;
1245 * Apply various tests to the text string. According to the
1246 * docs, each test "passed" sets the corresponding flag in
1247 * the output flags. But some of the tests are mutually
1248 * exclusive, so I don't see how you could pass all tests ...
1251 /* Check for an odd length ... pass if even. */
1253 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1255 /* Check for the BOM (byte order mark). */
1257 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1260 /* Check for the reverse BOM (byte order mark). */
1262 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1265 /* FIXME: Add more tests */
1268 * Check whether the string passed all of the tests.
1270 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1271 if ((out_flags
& in_flags
) != in_flags
)
1285 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1286 * A partial copy is NOT performed if the dest buffer is too small!
1290 RtlpOemStringToCountedUnicodeString(
1291 IN OUT PUNICODE_STRING UniDest
,
1292 IN POEM_STRING OemSource
,
1293 IN BOOLEAN AllocateDestinationString
,
1294 IN POOL_TYPE PoolType
)
1297 ULONG Length
; //excluding nullterm
1299 if (NlsMbCodePageTag
== TRUE
)
1300 Length
= RtlOemStringToUnicodeSize(OemSource
) - sizeof(WCHAR
);
1302 Length
= OemSource
->Length
* sizeof(WCHAR
);
1305 return STATUS_INVALID_PARAMETER_2
;
1307 if (AllocateDestinationString
== TRUE
)
1309 UniDest
->Buffer
= ExAllocatePoolWithTag (PoolType
, Length
, TAG_USTR
);
1310 if (UniDest
->Buffer
== NULL
)
1311 return STATUS_NO_MEMORY
;
1313 UniDest
->MaximumLength
= Length
;
1315 else if (Length
> UniDest
->MaximumLength
)
1317 return STATUS_BUFFER_TOO_SMALL
;
1320 UniDest
->Length
= Length
;
1322 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1328 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1330 ExFreePoolWithTag(UniDest
->Buffer
, TAG_USTR
);
1341 * See RtlpOemStringToCountedUnicodeString
1345 RtlOemStringToCountedUnicodeString(
1346 IN OUT PUNICODE_STRING UniDest
,
1347 IN POEM_STRING OemSource
,
1348 IN BOOLEAN AllocateDestinationString
)
1350 return RtlpOemStringToCountedUnicodeString(
1353 AllocateDestinationString
,
1361 * TRUE if the names are equal, FALSE if not
1364 * The comparison is case insensitive.
1368 RtlEqualComputerName(
1369 IN PUNICODE_STRING ComputerName1
,
1370 IN PUNICODE_STRING ComputerName2
)
1372 OEM_STRING OemString1
;
1373 OEM_STRING OemString2
;
1374 BOOLEAN Result
= FALSE
;
1376 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1378 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1380 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1381 RtlFreeOemString( &OemString2
);
1383 RtlFreeOemString( &OemString1
);
1393 * TRUE if the names are equal, FALSE if not
1396 * The comparison is case insensitive.
1400 RtlEqualDomainName (
1401 IN PUNICODE_STRING DomainName1
,
1402 IN PUNICODE_STRING DomainName2
1405 return RtlEqualComputerName(DomainName1
, DomainName2
);
1415 RtlEqualDomainName (
1416 IN PUNICODE_STRING DomainName1,
1417 IN PUNICODE_STRING DomainName2
1420 OEM_STRING OemString1;
1421 OEM_STRING OemString2;
1424 RtlUpcaseUnicodeStringToOemString (&OemString1,
1427 RtlUpcaseUnicodeStringToOemString (&OemString2,
1431 Result = RtlEqualString (&OemString1,
1435 RtlFreeOemString (&OemString1);
1436 RtlFreeOemString (&OemString2);
1446 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1448 * Convert a string representation of a GUID into a GUID.
1451 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1452 * guid [O] Destination for the converted GUID
1455 * Success: STATUS_SUCCESS. guid contains the converted value.
1456 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1459 * See RtlStringFromGUID.
1464 IN UNICODE_STRING
*str
,
1469 const WCHAR
*lpszCLSID
= str
->Buffer
;
1470 BYTE
* lpOut
= (BYTE
*)guid
;
1472 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1474 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1475 * to memory: DWORD... WORD WORD BYTES............
1482 if (*lpszCLSID
!= '{')
1483 return STATUS_INVALID_PARAMETER
;
1490 if (*lpszCLSID
!= '-')
1491 return STATUS_INVALID_PARAMETER
;
1495 if (*lpszCLSID
!= '}')
1496 return STATUS_INVALID_PARAMETER
;
1501 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1504 /* Read two hex digits as a byte value */
1505 if (ch
>= '0' && ch
<= '9')
1507 else if (ch
>= 'a' && ch
<= 'f')
1509 else if (ch
>= 'A' && ch
<= 'F')
1512 return STATUS_INVALID_PARAMETER
;
1514 if (ch2
>= '0' && ch2
<= '9')
1516 else if (ch2
>= 'a' && ch2
<= 'f')
1517 ch2
= ch2
- 'a' + 10;
1518 else if (ch2
>= 'A' && ch2
<= 'F')
1519 ch2
= ch2
- 'A' + 10;
1521 return STATUS_INVALID_PARAMETER
;
1523 byte
= ch
<< 4 | ch2
;
1527 #ifndef WORDS_BIGENDIAN
1528 /* For Big Endian machines, we store the data such that the
1529 * dword/word members can be read as DWORDS and WORDS correctly. */
1561 lpszCLSID
++; /* Skip 2nd character of byte */
1569 return STATUS_SUCCESS
;
1577 RtlEraseUnicodeString(
1578 IN PUNICODE_STRING String
)
1580 if (String
->Buffer
== NULL
)
1583 if (String
->MaximumLength
== 0)
1586 memset (String
->Buffer
,
1588 String
->MaximumLength
);
1598 RtlHashUnicodeString(
1599 IN CONST UNICODE_STRING
*String
,
1600 IN BOOLEAN CaseInSensitive
,
1601 IN ULONG HashAlgorithm
,
1602 OUT PULONG HashValue
)
1604 if (String
!= NULL
&& HashValue
!= NULL
)
1606 switch (HashAlgorithm
)
1608 case HASH_STRING_ALGORITHM_DEFAULT
:
1609 case HASH_STRING_ALGORITHM_X65599
:
1614 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1616 if (CaseInSensitive
)
1618 for (c
= String
->Buffer
;
1622 /* only uppercase characters if they are 'a' ... 'z'! */
1623 *HashValue
= ((65599 * (*HashValue
)) +
1624 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1625 (*c
) - L
'a' + L
'A' : (*c
)));
1630 for (c
= String
->Buffer
;
1634 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1637 return STATUS_SUCCESS
;
1642 return STATUS_INVALID_PARAMETER
;
1649 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1650 * Does a partial copy if the dest buffer is too small
1654 RtlpUnicodeStringToCountedOemString(
1655 IN OUT POEM_STRING OemDest
,
1656 IN PUNICODE_STRING UniSource
,
1657 IN BOOLEAN AllocateDestinationString
,
1658 IN POOL_TYPE PoolType
)
1661 ULONG Length
; //excluding nullterm
1663 if (NlsMbOemCodePageTag
== TRUE
)
1664 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1666 Length
= (UniSource
->Length
/ sizeof(WCHAR
));
1668 if (Length
> 0x0000FFFF)
1669 return STATUS_INVALID_PARAMETER_2
;
1671 OemDest
->Length
= (WORD
)(Length
);
1673 if (AllocateDestinationString
)
1675 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
1676 if (OemDest
->Buffer
== NULL
)
1677 return STATUS_NO_MEMORY
;
1679 OemDest
->MaximumLength
= Length
;
1681 else if (OemDest
->MaximumLength
== 0)
1683 return STATUS_BUFFER_TOO_SMALL
;
1685 else if (Length
> OemDest
->MaximumLength
)
1687 OemDest
->Length
= OemDest
->MaximumLength
;
1690 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1696 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1698 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
1708 * See RtlpUnicodeStringToCountedOemString.
1712 RtlUnicodeStringToCountedOemString(
1713 IN OUT POEM_STRING OemDest
,
1714 IN PUNICODE_STRING UniSource
,
1715 IN BOOLEAN AllocateDestinationString
)
1717 return RtlpUnicodeStringToCountedOemString(
1720 AllocateDestinationString
,
1729 RtlLargeIntegerToChar(
1730 IN PLARGE_INTEGER Value
,
1733 IN OUT PCHAR String
)
1737 ULONGLONG v
= Value
->QuadPart
;
1746 if ((Radix
!= 2) && (Radix
!= 8) &&
1747 (Radix
!= 10) && (Radix
!= 16))
1748 return STATUS_INVALID_PARAMETER
;
1751 while (v
|| tp
== temp
)
1762 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1763 return STATUS_BUFFER_TOO_SMALL
;
1770 return STATUS_SUCCESS
;
1777 * dest is never '\0' terminated because it may be equal to src, and src
1778 * might not be '\0' terminated. dest->Length is only set upon success.
1782 RtlpUpcaseUnicodeString(
1783 IN OUT PUNICODE_STRING UniDest
,
1784 IN PCUNICODE_STRING UniSource
,
1785 IN BOOLEAN AllocateDestinationString
,
1786 IN POOL_TYPE PoolType
)
1791 if (AllocateDestinationString
== TRUE
)
1793 UniDest
->MaximumLength
= UniSource
->Length
;
1794 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, UniDest
->MaximumLength
, TAG_USTR
);
1795 if (UniDest
->Buffer
== NULL
)
1796 return STATUS_NO_MEMORY
;
1798 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1800 return STATUS_BUFFER_TOO_SMALL
;
1803 UniDest
->Length
= UniSource
->Length
;
1805 Src
= UniSource
->Buffer
;
1806 Dest
= UniDest
->Buffer
;
1807 for (i
= 0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
1809 *Dest
= RtlUpcaseUnicodeChar (*Src
);
1814 return STATUS_SUCCESS
;
1821 * See RtlpUpcaseUnicodeString
1825 RtlUpcaseUnicodeString(
1826 IN OUT PUNICODE_STRING UniDest
,
1827 IN PCUNICODE_STRING UniSource
,
1828 IN BOOLEAN AllocateDestinationString
)
1831 return RtlpUpcaseUnicodeString(
1834 AllocateDestinationString
,
1842 * This function always writes a terminating '\0'.
1843 * It performs a partial copy if ansi is too small.
1847 RtlpUpcaseUnicodeStringToAnsiString(
1848 IN OUT PANSI_STRING AnsiDest
,
1849 IN PUNICODE_STRING UniSource
,
1850 IN BOOLEAN AllocateDestinationString
,
1851 IN POOL_TYPE PoolType
)
1854 ULONG Length
; //including nullterm
1856 if (NlsMbCodePageTag
== TRUE
)
1857 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1859 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1861 if (Length
> 0x0000FFFF)
1862 return STATUS_INVALID_PARAMETER_2
;
1864 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1866 if (AllocateDestinationString
)
1868 AnsiDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_ASTR
);
1869 if (AnsiDest
->Buffer
== NULL
)
1870 return STATUS_NO_MEMORY
;
1872 AnsiDest
->MaximumLength
= Length
;
1874 else if (AnsiDest
->MaximumLength
== 0)
1876 return STATUS_BUFFER_TOO_SMALL
;
1878 else if (Length
> AnsiDest
->MaximumLength
)
1880 //make room for nullterm
1881 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1884 //FIXME: do we need this??????? -Gunnar
1885 RtlZeroMemory (AnsiDest
->Buffer
,
1888 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1894 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1896 ExFreePoolWithTag(AnsiDest
->Buffer
, TAG_ASTR
);
1900 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1908 * See RtlpUpcaseUnicodeStringToAnsiString
1912 RtlUpcaseUnicodeStringToAnsiString(
1913 IN OUT PANSI_STRING AnsiDest
,
1914 IN PUNICODE_STRING UniSource
,
1915 IN BOOLEAN AllocateDestinationString
)
1917 return RtlpUpcaseUnicodeStringToAnsiString(
1920 AllocateDestinationString
,
1928 * Same as RtlUpcaseUnicodeStringToOemString but doesn't write terminating null
1929 * It performs a partial copy if oem is too small.
1933 RtlpUpcaseUnicodeStringToCountedOemString(
1934 IN OUT POEM_STRING OemDest
,
1935 IN PUNICODE_STRING UniSource
,
1936 IN BOOLEAN AllocateDestinationString
,
1937 IN POOL_TYPE PoolType
)
1940 ULONG Length
; //excluding nullterm
1942 if (NlsMbCodePageTag
== TRUE
)
1943 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1945 Length
= UniSource
->Length
/ sizeof(WCHAR
);
1947 if (Length
> 0x0000FFFF)
1948 return(STATUS_INVALID_PARAMETER_2
);
1950 OemDest
->Length
= (WORD
)(Length
);
1952 if (AllocateDestinationString
)
1954 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
1955 if (OemDest
->Buffer
== NULL
)
1956 return(STATUS_NO_MEMORY
);
1958 //FIXME: Do we need this?????
1959 RtlZeroMemory (OemDest
->Buffer
, Length
);
1961 OemDest
->MaximumLength
= (WORD
)Length
;
1963 else if (OemDest
->MaximumLength
== 0)
1965 return(STATUS_BUFFER_TOO_SMALL
);
1967 else if (Length
> OemDest
->MaximumLength
)
1969 OemDest
->Length
= OemDest
->MaximumLength
;
1972 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1978 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1980 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
1991 * See RtlpUpcaseUnicodeStringToCountedOemString
1995 RtlUpcaseUnicodeStringToCountedOemString(
1996 IN OUT POEM_STRING OemDest
,
1997 IN PUNICODE_STRING UniSource
,
1998 IN BOOLEAN AllocateDestinationString
)
2000 return RtlpUpcaseUnicodeStringToCountedOemString(
2003 AllocateDestinationString
,
2011 * Oem string is allways nullterminated
2012 * It performs a partial copy if oem is too small.
2016 RtlpUpcaseUnicodeStringToOemString (
2017 IN OUT POEM_STRING OemDest
,
2018 IN PUNICODE_STRING UniSource
,
2019 IN BOOLEAN AllocateDestinationString
,
2020 IN POOL_TYPE PoolType
2024 ULONG Length
; //including nullterm
2026 if (NlsMbOemCodePageTag
== TRUE
)
2027 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
2029 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
2031 if (Length
> 0x0000FFFF)
2032 return STATUS_INVALID_PARAMETER_2
;
2034 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
2036 if (AllocateDestinationString
)
2038 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
2039 if (OemDest
->Buffer
== NULL
)
2040 return STATUS_NO_MEMORY
;
2042 //FIXME: Do we need this????
2043 RtlZeroMemory (OemDest
->Buffer
, Length
);
2045 OemDest
->MaximumLength
= (WORD
)Length
;
2047 else if (OemDest
->MaximumLength
== 0)
2049 return STATUS_BUFFER_OVERFLOW
;
2051 else if (Length
> OemDest
->MaximumLength
)
2053 //make room for nullterm
2054 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
2057 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
2063 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2065 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
2069 OemDest
->Buffer
[OemDest
->Length
] = 0;
2076 * See RtlpUpcaseUnicodeStringToOemString
2080 RtlUpcaseUnicodeStringToOemString (
2081 IN OUT POEM_STRING OemDest
,
2082 IN PUNICODE_STRING UniSource
,
2083 IN BOOLEAN AllocateDestinationString
2086 return RtlpUpcaseUnicodeStringToOemString(
2089 AllocateDestinationString
,
2097 * Bytes calculated including nullterm
2101 RtlOemStringToUnicodeSize(IN POEM_STRING OemString
)
2105 //this function returns size including nullterm
2106 RtlMultiByteToUnicodeSize(&Size
,
2120 RtlStringFromGUID (IN REFGUID Guid
,
2121 OUT PUNICODE_STRING GuidString
)
2123 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
2130 return STATUS_INVALID_PARAMETER
;
2134 L
"{%08lX-%04X-%04X-%02X%02X-",
2140 BufferPtr
= Buffer
+ 25;
2143 for (i
= 2; i
< 8; i
++)
2145 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
2146 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
2149 *BufferPtr
++ = L
'}';
2150 *BufferPtr
++ = L
'\0';
2152 return RtlCreateUnicodeString (GuidString
, Buffer
);
2160 * Bytes calculated including nullterm
2164 RtlUnicodeStringToAnsiSize(
2165 IN PUNICODE_STRING UnicodeString
)
2169 //this function return size without nullterm!
2170 RtlUnicodeToMultiByteSize (&Size
,
2171 UnicodeString
->Buffer
,
2172 UnicodeString
->Length
);
2174 return Size
+ sizeof(CHAR
); //NB: incl. nullterm
2185 RtlCompareUnicodeString(
2186 IN PUNICODE_STRING String1
,
2187 IN PUNICODE_STRING String2
,
2188 IN BOOLEAN CaseInsensitive
)
2194 if (String1
&& String2
)
2196 len1
= String1
->Length
/ sizeof(WCHAR
);
2197 len2
= String2
->Length
/ sizeof(WCHAR
);
2198 s1
= String1
->Buffer
;
2199 s2
= String2
->Buffer
;
2203 if (CaseInsensitive
)
2207 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
2208 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
2209 if (!c1
|| !c2
|| c1
!= c2
)
2217 c1
= len1
-- ? *s1
++ : 0;
2218 c2
= len2
-- ? *s2
++ : 0;
2219 if (!c1
|| !c2
|| c1
!= c2
)
2236 IN OUT PSTRING DestinationString
,
2237 IN PSTRING SourceString
)
2241 if(SourceString
== NULL
)
2243 DestinationString
->Length
= 0;
2247 copylen
= min (DestinationString
->MaximumLength
,
2248 SourceString
->Length
);
2250 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2251 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
2253 DestinationString
->Buffer
[copylen
] = 0;
2255 DestinationString
->Length
= copylen
;
2265 RtlCopyUnicodeString(
2266 IN OUT PUNICODE_STRING DestinationString
,
2267 IN PUNICODE_STRING SourceString
)
2271 if (SourceString
== NULL
)
2273 DestinationString
->Length
= 0;
2277 copylen
= min (DestinationString
->MaximumLength
,
2278 SourceString
->Length
);
2279 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2280 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
2282 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
2284 DestinationString
->Length
= copylen
;
2290 * Creates a nullterminated UNICODE_STRING
2294 RtlpCreateUnicodeString(
2295 IN OUT PUNICODE_STRING UniDest
,
2297 IN POOL_TYPE PoolType
)
2301 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
2302 PoolType
= PagedPool
;
2303 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_USTR
);
2304 if (UniDest
->Buffer
== NULL
)
2307 memmove (UniDest
->Buffer
,
2311 UniDest
->MaximumLength
= Length
;
2312 UniDest
->Length
= Length
- sizeof (WCHAR
);
2321 * See RtlpCreateUnicodeString
2325 RtlCreateUnicodeString(
2326 IN OUT PUNICODE_STRING UniDest
,
2330 DPRINT("RtlCreateUnicodeString\n");
2331 return RtlpCreateUnicodeString(UniDest
, Source
, PagedPool
);
2339 RtlCreateUnicodeStringFromAsciiz(
2340 OUT PUNICODE_STRING Destination
,
2343 ANSI_STRING AnsiString
;
2346 RtlInitAnsiString (&AnsiString
,
2349 Status
= RtlAnsiStringToUnicodeString (Destination
,
2353 return NT_SUCCESS(Status
);
2360 * Dest is never '\0' terminated because it may be equal to src, and src
2361 * might not be '\0' terminated.
2362 * Dest->Length is only set upon success.
2366 RtlpDowncaseUnicodeString(
2367 IN OUT PUNICODE_STRING UniDest
,
2368 IN PUNICODE_STRING UniSource
,
2369 IN BOOLEAN AllocateDestinationString
,
2370 IN POOL_TYPE PoolType
)
2375 if (AllocateDestinationString
)
2377 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, UniSource
->Length
, TAG_USTR
);
2378 if (UniDest
->Buffer
== NULL
)
2379 return STATUS_NO_MEMORY
;
2381 UniDest
->MaximumLength
= UniSource
->Length
;
2383 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2385 return STATUS_BUFFER_TOO_SMALL
;
2388 UniDest
->Length
= UniSource
->Length
;
2390 Src
= UniSource
->Buffer
;
2391 Dest
= UniDest
->Buffer
;
2392 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2398 else if (*Src
<= L
'Z')
2400 *Dest
= (*Src
+ (L
'a' - L
'A'));
2404 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2411 return STATUS_SUCCESS
;
2418 * See RtlpDowncaseUnicodeString
2421 RtlDowncaseUnicodeString(
2422 IN OUT PUNICODE_STRING UniDest
,
2423 IN PUNICODE_STRING UniSource
,
2424 IN BOOLEAN AllocateDestinationString
)
2426 return RtlpDowncaseUnicodeString(
2429 AllocateDestinationString
,
2437 * if src is NULL dest is unchanged.
2438 * dest is '\0' terminated when the MaximumLength allowes it.
2439 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2442 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2447 slen
= wcslen(Source
) * sizeof(WCHAR
);
2449 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2450 return(STATUS_BUFFER_TOO_SMALL
);
2452 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2453 Destination
->Length
+= slen
;
2454 /* append terminating '\0' if enough space */
2455 if( Destination
->MaximumLength
> Destination
->Length
)
2456 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2458 return(STATUS_SUCCESS
);
2465 * This function always writes a terminating '\0'.
2466 * If the dest buffer is too small a partial copy is NOT performed!
2470 RtlpAnsiStringToUnicodeString(
2471 IN OUT PUNICODE_STRING UniDest
,
2472 IN PANSI_STRING AnsiSource
,
2473 IN BOOLEAN AllocateDestinationString
,
2474 IN POOL_TYPE PoolType
)
2477 ULONG Length
; //including nullterm
2479 if (NlsMbCodePageTag
== TRUE
)
2480 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2482 Length
= (AnsiSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
2484 if (Length
> 0xffff)
2485 return STATUS_INVALID_PARAMETER_2
;
2487 if (AllocateDestinationString
== TRUE
)
2489 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_USTR
);
2490 if (UniDest
->Buffer
== NULL
)
2491 return STATUS_NO_MEMORY
;
2493 UniDest
->MaximumLength
= Length
;
2495 else if (Length
> UniDest
->MaximumLength
)
2497 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2498 return STATUS_BUFFER_TOO_SMALL
;
2501 UniDest
->Length
= Length
- sizeof(WCHAR
);
2503 //FIXME: We don't need this??? -Gunnar
2504 RtlZeroMemory (UniDest
->Buffer
,
2507 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2511 AnsiSource
->Length
);
2513 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2515 ExFreePoolWithTag(UniDest
->Buffer
, TAG_USTR
);
2519 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2527 * See RtlpAnsiStringToUnicodeString
2531 RtlAnsiStringToUnicodeString(
2532 IN OUT PUNICODE_STRING UniDest
,
2533 IN PANSI_STRING AnsiSource
,
2534 IN BOOLEAN AllocateDestinationString
)
2536 return RtlpAnsiStringToUnicodeString(
2539 AllocateDestinationString
,
2547 * if src is NULL dest is unchanged.
2548 * dest is never '\0' terminated.
2552 RtlAppendAsciizToString(
2553 IN OUT PSTRING Destination
,
2560 return STATUS_SUCCESS
;
2562 Length
= strlen (Source
);
2563 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2564 return STATUS_BUFFER_TOO_SMALL
;
2566 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2573 Destination
->Length
+= Length
;
2575 return STATUS_SUCCESS
;
2583 RtlUpperString(PSTRING DestinationString
,
2584 PSTRING SourceString
)
2591 Length
= min(SourceString
->Length
,
2592 DestinationString
->MaximumLength
- 1);
2594 Src
= SourceString
->Buffer
;
2595 Dest
= DestinationString
->Buffer
;
2596 for (i
= 0; i
< Length
; i
++)
2598 *Dest
= RtlUpperChar(*Src
);
2604 DestinationString
->Length
= SourceString
->Length
;
2612 RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
2614 return RtlAnsiStringToUnicodeSize(AnsiString
);
2622 RtlxOemStringToUnicodeSize(IN POEM_STRING OemString
)
2624 return RtlOemStringToUnicodeSize((PANSI_STRING
)OemString
);
2633 RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString
)
2635 return RtlUnicodeStringToAnsiSize(UnicodeString
);
2643 RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString
)
2645 return RtlUnicodeStringToOemSize(UnicodeString
);
2652 RtlpDuplicateUnicodeString(
2654 IN PUNICODE_STRING SourceString
,
2655 PUNICODE_STRING DestinationString
,
2658 if (SourceString
== NULL
|| DestinationString
== NULL
)
2659 return STATUS_INVALID_PARAMETER
;
2662 if (SourceString
->Length
== 0 && AddNull
!= 3)
2664 DestinationString
->Length
= 0;
2665 DestinationString
->MaximumLength
= 0;
2666 DestinationString
->Buffer
= NULL
;
2670 unsigned int DestMaxLength
= SourceString
->Length
;
2673 DestMaxLength
+= sizeof(UNICODE_NULL
);
2675 DestinationString
->Buffer
= ExAllocatePool(PoolType
, DestMaxLength
);
2676 if (DestinationString
->Buffer
== NULL
)
2677 return STATUS_NO_MEMORY
;
2679 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2680 DestinationString
->Length
= SourceString
->Length
;
2681 DestinationString
->MaximumLength
= DestMaxLength
;
2684 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2687 return STATUS_SUCCESS
;
2694 * See RtlpDuplicateUnicodeString
2697 RtlDuplicateUnicodeString(
2699 IN PUNICODE_STRING SourceString
,
2700 PUNICODE_STRING DestinationString
)
2702 return RtlpDuplicateUnicodeString(
2713 RtlValidateUnicodeString(IN ULONG Flags
,
2714 IN PUNICODE_STRING UnicodeString
)
2716 /* currently no flags are supported! */
2720 ((UnicodeString
== NULL
) ||
2721 ((UnicodeString
->Length
!= 0) &&
2722 (UnicodeString
->Buffer
!= NULL
) &&
2723 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2724 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2725 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2727 /* a NULL pointer as a unicode string is considered to be a valid unicode
2729 return STATUS_SUCCESS
;
2733 return STATUS_INVALID_PARAMETER
;