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
>= 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 PUNICODE_STRING String1
,
345 IN PUNICODE_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 %x, SourceString %x)\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 (tp
- 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 (tp
- 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
>= 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
980 * See RtlpUnicodeStringToAnsiString
984 RtlUnicodeStringToAnsiString(
985 IN OUT PANSI_STRING AnsiDest
,
986 IN PUNICODE_STRING UniSource
,
987 IN BOOLEAN AllocateDestinationString
)
989 return RtlpUnicodeStringToAnsiString(
992 AllocateDestinationString
,
1001 * This function always writes a terminating '\0'.
1002 * It performs a partial copy if ansi is too small.
1006 RtlpUnicodeStringToAnsiString(
1007 IN OUT PANSI_STRING AnsiDest
,
1008 IN PUNICODE_STRING UniSource
,
1009 IN BOOLEAN AllocateDestinationString
,
1010 IN POOL_TYPE PoolType
)
1012 NTSTATUS Status
= STATUS_SUCCESS
;
1013 ULONG Length
; //including nullterm
1015 if (NlsMbCodePageTag
== TRUE
)
1017 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1020 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1022 AnsiDest
->Length
= Length
- sizeof(CHAR
);
1024 if (AllocateDestinationString
)
1026 AnsiDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_ASTR
);
1027 if (AnsiDest
->Buffer
== NULL
)
1028 return STATUS_NO_MEMORY
;
1030 AnsiDest
->MaximumLength
= Length
;
1032 else if (AnsiDest
->MaximumLength
== 0)
1034 return STATUS_BUFFER_TOO_SMALL
;
1036 else if (Length
> AnsiDest
->MaximumLength
)
1038 //make room for nullterm
1039 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1042 Status
= RtlUnicodeToMultiByteN (AnsiDest
->Buffer
,
1048 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1050 ExFreePoolWithTag(AnsiDest
->Buffer
, TAG_ASTR
);
1054 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1063 * See RtlpOemStringToUnicodeString
1067 RtlOemStringToUnicodeString(
1068 IN OUT PUNICODE_STRING UniDest
,
1069 IN POEM_STRING OemSource
,
1070 IN BOOLEAN AllocateDestinationString
)
1072 return RtlpOemStringToUnicodeString(
1075 AllocateDestinationString
,
1084 * This function always writes a terminating '\0'.
1085 * Does NOT perform a partial copy if unicode is too small!
1089 RtlpOemStringToUnicodeString(
1090 IN OUT PUNICODE_STRING UniDest
,
1091 IN POEM_STRING OemSource
,
1092 IN BOOLEAN AllocateDestinationString
,
1093 IN POOL_TYPE PoolType
)
1096 ULONG Length
; //including nullterm
1098 if (NlsMbOemCodePageTag
== TRUE
)
1099 Length
= RtlOemStringToUnicodeSize(OemSource
);
1101 Length
= (OemSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
1103 if (Length
> 0xffff)
1104 return STATUS_INVALID_PARAMETER_2
;
1106 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
1108 if (AllocateDestinationString
)
1110 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_USTR
);
1111 if (UniDest
->Buffer
== NULL
)
1112 return STATUS_NO_MEMORY
;
1114 UniDest
->MaximumLength
= Length
;
1116 else if (Length
> UniDest
->MaximumLength
)
1118 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
1119 return STATUS_BUFFER_TOO_SMALL
;
1122 //FIXME: Do we need this????? -Gunnar
1123 RtlZeroMemory (UniDest
->Buffer
,
1126 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1132 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1134 ExFreePoolWithTag(UniDest
->Buffer
, TAG_USTR
);
1138 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1139 return STATUS_SUCCESS
;
1147 * See RtlpUnicodeStringToOemString.
1151 RtlUnicodeStringToOemString(
1152 IN OUT POEM_STRING OemDest
,
1153 IN PUNICODE_STRING UniSource
,
1154 IN BOOLEAN AllocateDestinationString
)
1156 return RtlpUnicodeStringToOemString(
1159 AllocateDestinationString
,
1169 * This function always '\0' terminates the string returned.
1173 RtlpUnicodeStringToOemString(
1174 IN OUT POEM_STRING OemDest
,
1175 IN PUNICODE_STRING UniSource
,
1176 IN BOOLEAN AllocateDestinationString
,
1177 IN POOL_TYPE PoolType
)
1179 NTSTATUS Status
= STATUS_SUCCESS
;
1180 ULONG Length
; //including nullterm
1182 if (NlsMbOemCodePageTag
== TRUE
)
1183 Length
= RtlUnicodeStringToAnsiSize (UniSource
);
1185 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1187 if (Length
> 0x0000FFFF)
1188 return STATUS_INVALID_PARAMETER_2
;
1190 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1192 if (AllocateDestinationString
)
1194 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
1195 if (OemDest
->Buffer
== NULL
)
1196 return STATUS_NO_MEMORY
;
1198 OemDest
->MaximumLength
= Length
;
1200 else if (OemDest
->MaximumLength
== 0)
1202 return STATUS_BUFFER_TOO_SMALL
;
1204 else if (Length
> OemDest
->MaximumLength
)
1206 //make room for nullterm
1207 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1210 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1216 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1218 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
1222 OemDest
->Buffer
[OemDest
->Length
] = 0;
1228 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1235 * The length of the string if all tests were passed, 0 otherwise.
1238 RtlIsTextUnicode (PVOID Buffer
,
1243 ULONG in_flags
= (ULONG
)-1;
1244 ULONG out_flags
= 0;
1253 * Apply various tests to the text string. According to the
1254 * docs, each test "passed" sets the corresponding flag in
1255 * the output flags. But some of the tests are mutually
1256 * exclusive, so I don't see how you could pass all tests ...
1259 /* Check for an odd length ... pass if even. */
1261 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1263 /* Check for the BOM (byte order mark). */
1265 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1268 /* Check for the reverse BOM (byte order mark). */
1270 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1273 /* FIXME: Add more tests */
1276 * Check whether the string passed all of the tests.
1278 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1279 if ((out_flags
& in_flags
) != in_flags
)
1294 * See RtlpOemStringToCountedUnicodeString
1298 RtlOemStringToCountedUnicodeString(
1299 IN OUT PUNICODE_STRING UniDest
,
1300 IN POEM_STRING OemSource
,
1301 IN BOOLEAN AllocateDestinationString
)
1303 return RtlpOemStringToCountedUnicodeString(
1306 AllocateDestinationString
,
1315 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1316 * A partial copy is NOT performed if the dest buffer is too small!
1320 RtlpOemStringToCountedUnicodeString(
1321 IN OUT PUNICODE_STRING UniDest
,
1322 IN POEM_STRING OemSource
,
1323 IN BOOLEAN AllocateDestinationString
,
1324 IN POOL_TYPE PoolType
)
1327 ULONG Length
; //excluding nullterm
1329 if (NlsMbCodePageTag
== TRUE
)
1330 Length
= RtlOemStringToUnicodeSize(OemSource
) - sizeof(WCHAR
);
1332 Length
= OemSource
->Length
* sizeof(WCHAR
);
1335 return STATUS_INVALID_PARAMETER_2
;
1337 if (AllocateDestinationString
== TRUE
)
1339 UniDest
->Buffer
= ExAllocatePoolWithTag (PoolType
, Length
, TAG_USTR
);
1340 if (UniDest
->Buffer
== NULL
)
1341 return STATUS_NO_MEMORY
;
1343 UniDest
->MaximumLength
= Length
;
1345 else if (Length
> UniDest
->MaximumLength
)
1347 return STATUS_BUFFER_TOO_SMALL
;
1350 UniDest
->Length
= Length
;
1352 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1358 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1360 ExFreePoolWithTag(UniDest
->Buffer
, TAG_USTR
);
1372 * TRUE if the names are equal, FALSE if not
1375 * The comparison is case insensitive.
1379 RtlEqualComputerName(
1380 IN PUNICODE_STRING ComputerName1
,
1381 IN PUNICODE_STRING ComputerName2
)
1383 OEM_STRING OemString1
;
1384 OEM_STRING OemString2
;
1385 BOOLEAN Result
= FALSE
;
1387 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1389 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1391 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1392 RtlFreeOemString( &OemString2
);
1394 RtlFreeOemString( &OemString1
);
1404 * TRUE if the names are equal, FALSE if not
1407 * The comparison is case insensitive.
1411 RtlEqualDomainName (
1412 IN PUNICODE_STRING DomainName1
,
1413 IN PUNICODE_STRING DomainName2
1416 return RtlEqualComputerName(DomainName1
, DomainName2
);
1426 RtlEqualDomainName (
1427 IN PUNICODE_STRING DomainName1,
1428 IN PUNICODE_STRING DomainName2
1431 OEM_STRING OemString1;
1432 OEM_STRING OemString2;
1435 RtlUpcaseUnicodeStringToOemString (&OemString1,
1438 RtlUpcaseUnicodeStringToOemString (&OemString2,
1442 Result = RtlEqualString (&OemString1,
1446 RtlFreeOemString (&OemString1);
1447 RtlFreeOemString (&OemString2);
1457 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1459 * Convert a string representation of a GUID into a GUID.
1462 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1463 * guid [O] Destination for the converted GUID
1466 * Success: STATUS_SUCCESS. guid contains the converted value.
1467 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1470 * See RtlStringFromGUID.
1475 IN UNICODE_STRING
*str
,
1480 const WCHAR
*lpszCLSID
= str
->Buffer
;
1481 BYTE
* lpOut
= (BYTE
*)guid
;
1483 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1485 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1486 * to memory: DWORD... WORD WORD BYTES............
1493 if (*lpszCLSID
!= '{')
1494 return STATUS_INVALID_PARAMETER
;
1501 if (*lpszCLSID
!= '-')
1502 return STATUS_INVALID_PARAMETER
;
1506 if (*lpszCLSID
!= '}')
1507 return STATUS_INVALID_PARAMETER
;
1512 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1515 /* Read two hex digits as a byte value */
1516 if (ch
>= '0' && ch
<= '9')
1518 else if (ch
>= 'a' && ch
<= 'f')
1520 else if (ch
>= 'A' && ch
<= 'F')
1523 return STATUS_INVALID_PARAMETER
;
1525 if (ch2
>= '0' && ch2
<= '9')
1527 else if (ch2
>= 'a' && ch2
<= 'f')
1528 ch2
= ch2
- 'a' + 10;
1529 else if (ch2
>= 'A' && ch2
<= 'F')
1530 ch2
= ch2
- 'A' + 10;
1532 return STATUS_INVALID_PARAMETER
;
1534 byte
= ch
<< 4 | ch2
;
1538 #ifndef WORDS_BIGENDIAN
1539 /* For Big Endian machines, we store the data such that the
1540 * dword/word members can be read as DWORDS and WORDS correctly. */
1572 lpszCLSID
++; /* Skip 2nd character of byte */
1580 return STATUS_SUCCESS
;
1588 RtlEraseUnicodeString(
1589 IN PUNICODE_STRING String
)
1591 if (String
->Buffer
== NULL
)
1594 if (String
->MaximumLength
== 0)
1597 memset (String
->Buffer
,
1599 String
->MaximumLength
);
1609 RtlHashUnicodeString(
1610 IN
const UNICODE_STRING
*String
,
1611 IN BOOLEAN CaseInSensitive
,
1612 IN ULONG HashAlgorithm
,
1613 OUT PULONG HashValue
1617 return STATUS_NOT_IMPLEMENTED
;
1624 * See RtlpUnicodeStringToCountedOemString.
1628 RtlUnicodeStringToCountedOemString(
1629 IN OUT POEM_STRING OemDest
,
1630 IN PUNICODE_STRING UniSource
,
1631 IN BOOLEAN AllocateDestinationString
)
1633 return RtlpUnicodeStringToCountedOemString(
1636 AllocateDestinationString
,
1644 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1645 * Does a partial copy if the dest buffer is too small
1649 RtlpUnicodeStringToCountedOemString(
1650 IN OUT POEM_STRING OemDest
,
1651 IN PUNICODE_STRING UniSource
,
1652 IN BOOLEAN AllocateDestinationString
,
1653 IN POOL_TYPE PoolType
)
1656 ULONG Length
; //excluding nullterm
1658 if (NlsMbOemCodePageTag
== TRUE
)
1659 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1661 Length
= (UniSource
->Length
/ sizeof(WCHAR
));
1663 if (Length
> 0x0000FFFF)
1664 return STATUS_INVALID_PARAMETER_2
;
1666 OemDest
->Length
= (WORD
)(Length
);
1668 if (AllocateDestinationString
)
1670 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
1671 if (OemDest
->Buffer
== NULL
)
1672 return STATUS_NO_MEMORY
;
1674 OemDest
->MaximumLength
= Length
;
1676 else if (OemDest
->MaximumLength
== 0)
1678 return STATUS_BUFFER_TOO_SMALL
;
1680 else if (Length
> OemDest
->MaximumLength
)
1682 OemDest
->Length
= OemDest
->MaximumLength
;
1685 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1691 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1693 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
1705 RtlLargeIntegerToChar(
1706 IN PLARGE_INTEGER Value
,
1709 IN OUT PCHAR String
)
1713 ULONGLONG v
= Value
->QuadPart
;
1722 if ((Radix
!= 2) && (Radix
!= 8) &&
1723 (Radix
!= 10) && (Radix
!= 16))
1724 return STATUS_INVALID_PARAMETER
;
1727 while (v
|| tp
== temp
)
1738 if (tp
- temp
>= Length
)
1739 return STATUS_BUFFER_TOO_SMALL
;
1746 return STATUS_SUCCESS
;
1755 * See RtlpUpcaseUnicodeString
1759 RtlUpcaseUnicodeString(
1760 IN OUT PUNICODE_STRING UniDest
,
1761 IN PCUNICODE_STRING UniSource
,
1762 IN BOOLEAN AllocateDestinationString
)
1765 return RtlpUpcaseUnicodeString(
1768 AllocateDestinationString
,
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
;
1823 * See RtlpUpcaseUnicodeStringToAnsiString
1827 RtlUpcaseUnicodeStringToAnsiString(
1828 IN OUT PANSI_STRING AnsiDest
,
1829 IN PUNICODE_STRING UniSource
,
1830 IN BOOLEAN AllocateDestinationString
)
1832 return RtlpUpcaseUnicodeStringToAnsiString(
1835 AllocateDestinationString
,
1843 * This function always writes a terminating '\0'.
1844 * It performs a partial copy if ansi is too small.
1848 RtlpUpcaseUnicodeStringToAnsiString(
1849 IN OUT PANSI_STRING AnsiDest
,
1850 IN PUNICODE_STRING UniSource
,
1851 IN BOOLEAN AllocateDestinationString
,
1852 IN POOL_TYPE PoolType
)
1855 ULONG Length
; //including nullterm
1857 if (NlsMbCodePageTag
== TRUE
)
1858 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1860 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1862 if (Length
> 0x0000FFFF)
1863 return STATUS_INVALID_PARAMETER_2
;
1865 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1867 if (AllocateDestinationString
)
1869 AnsiDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_ASTR
);
1870 if (AnsiDest
->Buffer
== NULL
)
1871 return STATUS_NO_MEMORY
;
1873 AnsiDest
->MaximumLength
= Length
;
1875 else if (AnsiDest
->MaximumLength
== 0)
1877 return STATUS_BUFFER_TOO_SMALL
;
1879 else if (Length
> AnsiDest
->MaximumLength
)
1881 //make room for nullterm
1882 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1885 //FIXME: do we need this??????? -Gunnar
1886 RtlZeroMemory (AnsiDest
->Buffer
,
1889 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1895 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1897 ExFreePoolWithTag(AnsiDest
->Buffer
, TAG_ASTR
);
1901 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1911 * See RtlpUpcaseUnicodeStringToCountedOemString
1915 RtlUpcaseUnicodeStringToCountedOemString(
1916 IN OUT POEM_STRING OemDest
,
1917 IN PUNICODE_STRING UniSource
,
1918 IN BOOLEAN AllocateDestinationString
)
1920 return RtlpUpcaseUnicodeStringToCountedOemString(
1923 AllocateDestinationString
,
1933 * Same as RtlUpcaseUnicodeStringToOemString but doesn't write terminating null
1934 * It performs a partial copy if oem is too small.
1938 RtlpUpcaseUnicodeStringToCountedOemString(
1939 IN OUT POEM_STRING OemDest
,
1940 IN PUNICODE_STRING UniSource
,
1941 IN BOOLEAN AllocateDestinationString
,
1942 IN POOL_TYPE PoolType
)
1945 ULONG Length
; //excluding nullterm
1947 if (NlsMbCodePageTag
== TRUE
)
1948 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1950 Length
= UniSource
->Length
/ sizeof(WCHAR
);
1952 if (Length
> 0x0000FFFF)
1953 return(STATUS_INVALID_PARAMETER_2
);
1955 OemDest
->Length
= (WORD
)(Length
);
1957 if (AllocateDestinationString
)
1959 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
1960 if (OemDest
->Buffer
== NULL
)
1961 return(STATUS_NO_MEMORY
);
1963 //FIXME: Do we need this?????
1964 RtlZeroMemory (OemDest
->Buffer
, Length
);
1966 OemDest
->MaximumLength
= (WORD
)Length
;
1968 else if (OemDest
->MaximumLength
== 0)
1970 return(STATUS_BUFFER_TOO_SMALL
);
1972 else if (Length
> OemDest
->MaximumLength
)
1974 OemDest
->Length
= OemDest
->MaximumLength
;
1977 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1983 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1985 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
1996 * See RtlpUpcaseUnicodeStringToOemString
2000 RtlUpcaseUnicodeStringToOemString (
2001 IN OUT POEM_STRING OemDest
,
2002 IN PUNICODE_STRING UniSource
,
2003 IN BOOLEAN AllocateDestinationString
2006 return RtlpUpcaseUnicodeStringToOemString(
2009 AllocateDestinationString
,
2018 * Oem string is allways nullterminated
2019 * It performs a partial copy if oem is too small.
2023 RtlpUpcaseUnicodeStringToOemString (
2024 IN OUT POEM_STRING OemDest
,
2025 IN PUNICODE_STRING UniSource
,
2026 IN BOOLEAN AllocateDestinationString
,
2027 IN POOL_TYPE PoolType
2031 ULONG Length
; //including nullterm
2033 if (NlsMbOemCodePageTag
== TRUE
)
2034 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
2036 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
2038 if (Length
> 0x0000FFFF)
2039 return STATUS_INVALID_PARAMETER_2
;
2041 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
2043 if (AllocateDestinationString
)
2045 OemDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_OSTR
);
2046 if (OemDest
->Buffer
== NULL
)
2047 return STATUS_NO_MEMORY
;
2049 //FIXME: Do we need this????
2050 RtlZeroMemory (OemDest
->Buffer
, Length
);
2052 OemDest
->MaximumLength
= (WORD
)Length
;
2054 else if (OemDest
->MaximumLength
== 0)
2056 return STATUS_BUFFER_OVERFLOW
;
2058 else if (Length
> OemDest
->MaximumLength
)
2060 //make room for nullterm
2061 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
2064 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
2070 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2072 ExFreePoolWithTag(OemDest
->Buffer
, TAG_OSTR
);
2076 OemDest
->Buffer
[OemDest
->Length
] = 0;
2085 * Bytes calculated including nullterm
2089 RtlOemStringToUnicodeSize(IN POEM_STRING OemString
)
2093 //this function returns size including nullterm
2094 RtlMultiByteToUnicodeSize(&Size
,
2108 RtlStringFromGUID (IN REFGUID Guid
,
2109 OUT PUNICODE_STRING GuidString
)
2111 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
2118 return STATUS_INVALID_PARAMETER
;
2122 L
"{%08lX-%04X-%04X-%02X%02X-",
2128 BufferPtr
= Buffer
+ 25;
2131 for (i
= 2; i
< 8; i
++)
2133 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
2134 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
2137 *BufferPtr
++ = L
'}';
2138 *BufferPtr
++ = L
'\0';
2140 return RtlCreateUnicodeString (GuidString
, Buffer
);
2148 * Bytes calculated including nullterm
2152 RtlUnicodeStringToAnsiSize(
2153 IN PUNICODE_STRING UnicodeString
)
2157 //this function return size without nullterm!
2158 RtlUnicodeToMultiByteSize (&Size
,
2159 UnicodeString
->Buffer
,
2160 UnicodeString
->Length
);
2162 return Size
+ sizeof(CHAR
); //NB: incl. nullterm
2173 RtlCompareUnicodeString(
2174 IN PUNICODE_STRING String1
,
2175 IN PUNICODE_STRING String2
,
2176 IN BOOLEAN CaseInsensitive
)
2182 if (String1
&& String2
)
2184 len1
= String1
->Length
/ sizeof(WCHAR
);
2185 len2
= String2
->Length
/ sizeof(WCHAR
);
2186 s1
= String1
->Buffer
;
2187 s2
= String2
->Buffer
;
2191 if (CaseInsensitive
)
2195 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
2196 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
2197 if (!c1
|| !c2
|| c1
!= c2
)
2205 c1
= len1
-- ? *s1
++ : 0;
2206 c2
= len2
-- ? *s2
++ : 0;
2207 if (!c1
|| !c2
|| c1
!= c2
)
2224 IN OUT PSTRING DestinationString
,
2225 IN PSTRING SourceString
)
2229 if(SourceString
== NULL
)
2231 DestinationString
->Length
= 0;
2235 copylen
= min (DestinationString
->MaximumLength
,
2236 SourceString
->Length
);
2238 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2239 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
2241 DestinationString
->Buffer
[copylen
] = 0;
2243 DestinationString
->Length
= copylen
;
2253 RtlCopyUnicodeString(
2254 IN OUT PUNICODE_STRING DestinationString
,
2255 IN PUNICODE_STRING SourceString
)
2259 if (SourceString
== NULL
)
2261 DestinationString
->Length
= 0;
2265 copylen
= min (DestinationString
->MaximumLength
,
2266 SourceString
->Length
);
2267 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2268 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
2270 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
2272 DestinationString
->Length
= copylen
;
2280 * See RtlpCreateUnicodeString
2284 RtlCreateUnicodeString(
2285 IN OUT PUNICODE_STRING UniDest
,
2289 DPRINT("RtlCreateUnicodeString\n");
2290 return RtlpCreateUnicodeString(UniDest
, Source
, PagedPool
);
2297 * Creates a nullterminated UNICODE_STRING
2301 RtlpCreateUnicodeString(
2302 IN OUT PUNICODE_STRING UniDest
,
2304 IN POOL_TYPE PoolType
)
2308 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
2309 PoolType
= PagedPool
;
2310 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_USTR
);
2311 if (UniDest
->Buffer
== NULL
)
2314 memmove (UniDest
->Buffer
,
2318 UniDest
->MaximumLength
= Length
;
2319 UniDest
->Length
= Length
- sizeof (WCHAR
);
2331 RtlCreateUnicodeStringFromAsciiz(
2332 OUT PUNICODE_STRING Destination
,
2335 ANSI_STRING AnsiString
;
2338 RtlInitAnsiString (&AnsiString
,
2341 Status
= RtlAnsiStringToUnicodeString (Destination
,
2345 return NT_SUCCESS(Status
);
2354 * See RtlpDowncaseUnicodeString
2357 RtlDowncaseUnicodeString(
2358 IN OUT PUNICODE_STRING UniDest
,
2359 IN PUNICODE_STRING UniSource
,
2360 IN BOOLEAN AllocateDestinationString
)
2362 return RtlpDowncaseUnicodeString(
2365 AllocateDestinationString
,
2374 * Dest is never '\0' terminated because it may be equal to src, and src
2375 * might not be '\0' terminated.
2376 * Dest->Length is only set upon success.
2380 RtlpDowncaseUnicodeString(
2381 IN OUT PUNICODE_STRING UniDest
,
2382 IN PUNICODE_STRING UniSource
,
2383 IN BOOLEAN AllocateDestinationString
,
2384 IN POOL_TYPE PoolType
)
2389 if (AllocateDestinationString
)
2391 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, UniSource
->Length
, TAG_USTR
);
2392 if (UniDest
->Buffer
== NULL
)
2393 return STATUS_NO_MEMORY
;
2395 UniDest
->MaximumLength
= UniSource
->Length
;
2397 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2399 return STATUS_BUFFER_TOO_SMALL
;
2402 UniDest
->Length
= UniSource
->Length
;
2404 Src
= UniSource
->Buffer
;
2405 Dest
= UniDest
->Buffer
;
2406 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2412 else if (*Src
<= L
'Z')
2414 *Dest
= (*Src
+ (L
'a' - L
'A'));
2418 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2425 return STATUS_SUCCESS
;
2434 * if src is NULL dest is unchanged.
2435 * dest is '\0' terminated when the MaximumLength allowes it.
2436 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2439 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2444 slen
= wcslen(Source
) * sizeof(WCHAR
);
2446 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2447 return(STATUS_BUFFER_TOO_SMALL
);
2449 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2450 Destination
->Length
+= slen
;
2451 /* append terminating '\0' if enough space */
2452 if( Destination
->MaximumLength
> Destination
->Length
)
2453 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2455 return(STATUS_SUCCESS
);
2463 * See RtlpAnsiStringToUnicodeString
2467 RtlAnsiStringToUnicodeString(
2468 IN OUT PUNICODE_STRING UniDest
,
2469 IN PANSI_STRING AnsiSource
,
2470 IN BOOLEAN AllocateDestinationString
)
2472 return RtlpAnsiStringToUnicodeString(
2475 AllocateDestinationString
,
2485 * This function always writes a terminating '\0'.
2486 * If the dest buffer is too small a partial copy is NOT performed!
2490 RtlpAnsiStringToUnicodeString(
2491 IN OUT PUNICODE_STRING UniDest
,
2492 IN PANSI_STRING AnsiSource
,
2493 IN BOOLEAN AllocateDestinationString
,
2494 IN POOL_TYPE PoolType
)
2497 ULONG Length
; //including nullterm
2499 if (NlsMbCodePageTag
== TRUE
)
2500 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2502 Length
= (AnsiSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
2504 if (Length
> 0xffff)
2505 return STATUS_INVALID_PARAMETER_2
;
2507 if (AllocateDestinationString
== TRUE
)
2509 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG_USTR
);
2510 if (UniDest
->Buffer
== NULL
)
2511 return STATUS_NO_MEMORY
;
2513 UniDest
->MaximumLength
= Length
;
2515 else if (Length
> UniDest
->MaximumLength
)
2517 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2518 return STATUS_BUFFER_TOO_SMALL
;
2521 UniDest
->Length
= Length
- sizeof(WCHAR
);
2523 //FIXME: We don't need this??? -Gunnar
2524 RtlZeroMemory (UniDest
->Buffer
,
2527 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2531 AnsiSource
->Length
);
2533 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2535 ExFreePoolWithTag(UniDest
->Buffer
, TAG_USTR
);
2539 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2549 * if src is NULL dest is unchanged.
2550 * dest is never '\0' terminated.
2554 RtlAppendAsciizToString(
2555 IN OUT PSTRING Destination
,
2562 return STATUS_SUCCESS
;
2564 Length
= strlen (Source
);
2565 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2566 return STATUS_BUFFER_TOO_SMALL
;
2568 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2575 Destination
->Length
+= Length
;
2577 return STATUS_SUCCESS
;
2585 RtlUpperString(PSTRING DestinationString
,
2586 PSTRING SourceString
)
2593 Length
= min(SourceString
->Length
,
2594 DestinationString
->MaximumLength
- 1);
2596 Src
= SourceString
->Buffer
;
2597 Dest
= DestinationString
->Buffer
;
2598 for (i
= 0; i
< Length
; i
++)
2600 *Dest
= RtlUpperChar(*Src
);
2606 DestinationString
->Length
= SourceString
->Length
;
2614 RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
2616 return RtlAnsiStringToUnicodeSize(AnsiString
);
2624 RtlxOemStringToUnicodeSize(IN POEM_STRING OemString
)
2626 return RtlOemStringToUnicodeSize((PANSI_STRING
)OemString
);
2635 RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString
)
2637 return RtlUnicodeStringToAnsiSize(UnicodeString
);
2645 RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString
)
2647 return RtlUnicodeStringToOemSize(UnicodeString
);
2655 * See RtlpDuplicateUnicodeString
2658 RtlDuplicateUnicodeString(
2660 IN PUNICODE_STRING SourceString
,
2661 PUNICODE_STRING DestinationString
)
2663 return RtlpDuplicateUnicodeString(
2675 RtlpDuplicateUnicodeString(
2677 IN PUNICODE_STRING SourceString
,
2678 PUNICODE_STRING DestinationString
,
2681 if (SourceString
== NULL
|| DestinationString
== NULL
)
2682 return STATUS_INVALID_PARAMETER
;
2685 if (SourceString
->Length
== 0 && AddNull
!= 3)
2687 DestinationString
->Length
= 0;
2688 DestinationString
->MaximumLength
= 0;
2689 DestinationString
->Buffer
= NULL
;
2693 unsigned int DestMaxLength
= SourceString
->Length
;
2696 DestMaxLength
+= sizeof(UNICODE_NULL
);
2698 DestinationString
->Buffer
= ExAllocatePool(PoolType
, DestMaxLength
);
2699 if (DestinationString
->Buffer
== NULL
)
2700 return STATUS_NO_MEMORY
;
2702 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2703 DestinationString
->Length
= SourceString
->Length
;
2704 DestinationString
->MaximumLength
= DestMaxLength
;
2707 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2710 return STATUS_SUCCESS
;
2718 RtlValidateUnicodeString(IN ULONG Flags
,
2719 IN PUNICODE_STRING UnicodeString
)
2721 /* currently no flags are supported! */
2725 ((UnicodeString
== NULL
) ||
2726 ((UnicodeString
->Length
!= 0) &&
2727 (UnicodeString
->Buffer
!= NULL
) &&
2728 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2729 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2730 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2732 /* a NULL pointer as a unicode string is considered to be a valid unicode
2734 return STATUS_SUCCESS
;
2738 return STATUS_INVALID_PARAMETER
;