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 extern BOOLEAN NlsMbCodePageTag
;
31 extern BOOLEAN NlsMbOemCodePageTag
;
33 /* FUNCTIONS *****************************************************************/
40 RtlAnsiCharToUnicodeChar (IN CHAR AnsiChar
)
48 Size
= (NlsLeadByteInfo
[AnsiChar
] == 0) ? 1 : 2;
51 RtlMultiByteToUnicodeN (&UnicodeChar
,
65 * The calculated size in bytes including nullterm.
69 RtlAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
73 RtlMultiByteToUnicodeSize(&Size
,
86 * If src->length is zero dest is unchanged.
87 * Dest is never nullterminated.
91 RtlAppendStringToString(IN OUT PSTRING Destination
,
96 if (Source
->Length
== 0)
97 return(STATUS_SUCCESS
);
99 if (Destination
->Length
+ Source
->Length
>= Destination
->MaximumLength
)
100 return(STATUS_BUFFER_TOO_SMALL
);
102 Ptr
= Destination
->Buffer
+ Destination
->Length
;
106 Ptr
+= Source
->Length
;
109 Destination
->Length
+= Source
->Length
;
111 return(STATUS_SUCCESS
);
120 * If src->length is zero dest is unchanged.
121 * Dest is nullterminated when the MaximumLength allowes it.
122 * When dest fits exactly in MaximumLength characters the nullterm is ommitted.
126 RtlAppendUnicodeStringToString(
127 IN OUT PUNICODE_STRING Destination
,
128 IN PUNICODE_STRING Source
)
131 if ((Source
->Length
+ Destination
->Length
) > Destination
->MaximumLength
)
132 return STATUS_BUFFER_TOO_SMALL
;
134 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
->Buffer
, Source
->Length
);
135 Destination
->Length
+= Source
->Length
;
136 /* append terminating '\0' if enough space */
137 if( Destination
->MaximumLength
> Destination
->Length
)
138 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
140 return STATUS_SUCCESS
;
144 /**************************************************************************
145 * RtlCharToInteger (NTDLL.@)
147 * Converts a character string into its integer equivalent.
150 * Success: STATUS_SUCCESS. value contains the converted number
151 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
152 * STATUS_ACCESS_VIOLATION, if value is NULL.
155 * For base 0 it uses 10 as base and the string should be in the format
156 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
157 * For other bases the string should be in the format
158 * "{whitespace} [+|-] {digits}".
159 * No check is made for value overflow, only the lower 32 bits are assigned.
160 * If str is NULL it crashes, as the native function does.
163 * This function does not read garbage behind '\0' as the native version does.
168 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
169 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
170 PULONG value
) /* [O] Destination for the converted value */
174 ULONG RunningTotal
= 0;
177 while (*str
!= '\0' && *str
<= ' ') {
183 } else if (*str
== '-') {
194 } else if (str
[1] == 'o') {
197 } else if (str
[1] == 'x') {
202 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
203 return STATUS_INVALID_PARAMETER
;
207 return STATUS_ACCESS_VIOLATION
;
210 while (*str
!= '\0') {
212 if (chCurrent
>= '0' && chCurrent
<= '9') {
213 digit
= chCurrent
- '0';
214 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
215 digit
= chCurrent
- 'A' + 10;
216 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
217 digit
= chCurrent
- 'a' + 10;
221 if (digit
< 0 || digit
>= (int)base
) {
222 *value
= bMinus
? -RunningTotal
: RunningTotal
;
223 return STATUS_SUCCESS
;
226 RunningTotal
= RunningTotal
* base
+ digit
;
230 *value
= bMinus
? -RunningTotal
: RunningTotal
;
231 return STATUS_SUCCESS
;
242 IN BOOLEAN CaseInsensitive
)
248 if (String1
&& String2
)
250 len1
= String1
->Length
;
251 len2
= String2
->Length
;
252 s1
= String1
->Buffer
;
253 s2
= String2
->Buffer
;
261 c1
= len1
-- ? RtlUpperChar (*s1
++) : 0;
262 c2
= len2
-- ? RtlUpperChar (*s2
++) : 0;
263 if (!c1
|| !c2
|| c1
!= c2
)
271 c1
= len1
-- ? *s1
++ : 0;
272 c2
= len2
-- ? *s2
++ : 0;
273 if (!c1
|| !c2
|| c1
!= c2
)
288 * TRUE if strings are equal.
295 IN BOOLEAN CaseInsensitive
)
301 if (String1
->Length
!= String2
->Length
)
304 p1
= String1
->Buffer
;
305 p2
= String2
->Buffer
;
306 for (i
= 0; i
< String1
->Length
; i
++)
308 if (CaseInsensitive
== TRUE
)
310 c1
= RtlUpperChar (*p1
);
311 c2
= RtlUpperChar (*p2
);
334 * TRUE if strings are equal.
338 RtlEqualUnicodeString(
339 IN CONST UNICODE_STRING
*String1
,
340 IN CONST UNICODE_STRING
*String2
,
341 IN BOOLEAN CaseInsensitive
)
347 if (String1
->Length
!= String2
->Length
)
350 pw1
= String1
->Buffer
;
351 pw2
= String2
->Buffer
;
353 for (i
= 0; i
< String1
->Length
/ sizeof(WCHAR
); i
++)
355 if (CaseInsensitive
== TRUE
)
357 wc1
= RtlUpcaseUnicodeChar (*pw1
);
358 wc2
= RtlUpcaseUnicodeChar (*pw2
);
382 RtlFreeAnsiString(IN PANSI_STRING AnsiString
)
384 if (AnsiString
->Buffer
!= NULL
)
386 RtlpFreeStringMemory(AnsiString
->Buffer
, TAG_ASTR
);
388 AnsiString
->Buffer
= NULL
;
389 AnsiString
->Length
= 0;
390 AnsiString
->MaximumLength
= 0;
400 RtlFreeOemString(IN POEM_STRING OemString
)
402 if (OemString
->Buffer
!= NULL
)
404 RtlpFreeStringMemory(OemString
->Buffer
, TAG_OSTR
);
406 OemString
->Buffer
= NULL
;
407 OemString
->Length
= 0;
408 OemString
->MaximumLength
= 0;
418 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
420 if (UnicodeString
->Buffer
!= NULL
)
422 RtlpFreeStringMemory(UnicodeString
->Buffer
, TAG_USTR
);
424 UnicodeString
->Buffer
= NULL
;
425 UnicodeString
->Length
= 0;
426 UnicodeString
->MaximumLength
= 0;
435 RtlIsValidOemCharacter (
447 * If source is NULL the length of source is assumed to be 0.
451 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString
,
452 IN PCSZ SourceString
)
456 if (SourceString
== NULL
)
458 DestinationString
->Length
= 0;
459 DestinationString
->MaximumLength
= 0;
463 DestSize
= strlen ((const char *)SourceString
);
464 DestinationString
->Length
= DestSize
;
465 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
467 DestinationString
->Buffer
= (PCHAR
)SourceString
;
476 * If source is NULL the length of source is assumed to be 0.
481 IN OUT PSTRING DestinationString
,
482 IN PCSZ SourceString
)
486 if (SourceString
== NULL
)
488 DestinationString
->Length
= 0;
489 DestinationString
->MaximumLength
= 0;
493 DestSize
= strlen((const char *)SourceString
);
494 DestinationString
->Length
= DestSize
;
495 DestinationString
->MaximumLength
= DestSize
+ sizeof(CHAR
);
497 DestinationString
->Buffer
= (PCHAR
)SourceString
;
505 * If source is NULL the length of source is assumed to be 0.
509 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString
,
510 IN PCWSTR SourceString
)
514 DPRINT("RtlInitUnicodeString(DestinationString 0x%p, SourceString 0x%p)\n",
518 if (SourceString
== NULL
)
520 DestinationString
->Length
= 0;
521 DestinationString
->MaximumLength
= 0;
525 DestSize
= wcslen((PWSTR
)SourceString
) * sizeof(WCHAR
);
526 DestinationString
->Length
= DestSize
;
527 DestinationString
->MaximumLength
= DestSize
+ sizeof(WCHAR
);
529 DestinationString
->Buffer
= (PWSTR
)SourceString
;
536 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString
,
537 IN PCWSTR SourceString
)
541 if (SourceString
!= NULL
)
543 Length
= wcslen(SourceString
) * sizeof(WCHAR
);
545 return STATUS_NAME_TOO_LONG
;
547 DestinationString
->Length
= Length
;
548 DestinationString
->MaximumLength
= Length
+ sizeof(WCHAR
);
549 DestinationString
->Buffer
= (PWSTR
)SourceString
;
553 DestinationString
->Length
= 0;
554 DestinationString
->MaximumLength
= 0;
555 DestinationString
->Buffer
= NULL
;
558 return STATUS_SUCCESS
;
565 * Writes at most length characters to the string str.
566 * Str is nullterminated when length allowes it.
567 * When str fits exactly in length characters the nullterm is ommitted.
588 if ((Radix
!= 2) && (Radix
!= 8) &&
589 (Radix
!= 10) && (Radix
!= 16))
591 return STATUS_INVALID_PARAMETER
;
595 while (v
|| tp
== temp
)
606 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
608 return STATUS_BUFFER_TOO_SMALL
;
616 return STATUS_SUCCESS
;
627 IN ULONG Base OPTIONAL
,
628 IN ULONG Length OPTIONAL
,
643 if ((Radix
!= 2) && (Radix
!= 8) &&
644 (Radix
!= 10) && (Radix
!= 16))
646 return STATUS_INVALID_PARAMETER
;
650 while (v
|| tp
== temp
)
661 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
663 return STATUS_BUFFER_TOO_SMALL
;
671 return STATUS_SUCCESS
;
681 RtlIntegerToUnicodeString(
683 IN ULONG Base
, /* optional */
684 IN OUT PUNICODE_STRING String
)
686 ANSI_STRING AnsiString
;
690 Status
= RtlIntegerToChar (Value
,
694 if (NT_SUCCESS(Status
))
696 AnsiString
.Buffer
= Buffer
;
697 AnsiString
.Length
= strlen (Buffer
);
698 AnsiString
.MaximumLength
= sizeof(Buffer
);
700 Status
= RtlAnsiStringToUnicodeString (String
,
714 RtlInt64ToUnicodeString (
716 IN ULONG Base OPTIONAL
,
717 IN OUT PUNICODE_STRING String
720 LARGE_INTEGER LargeInt
;
721 ANSI_STRING AnsiString
;
725 LargeInt
.QuadPart
= Value
;
727 Status
= RtlLargeIntegerToChar (&LargeInt
,
731 if (NT_SUCCESS(Status
))
733 AnsiString
.Buffer
= Buffer
;
734 AnsiString
.Length
= strlen (Buffer
);
735 AnsiString
.MaximumLength
= sizeof(Buffer
);
737 Status
= RtlAnsiStringToUnicodeString (String
,
750 * TRUE if String2 contains String1 as a prefix.
755 PANSI_STRING String1
,
756 PANSI_STRING String2
,
757 BOOLEAN CaseInsensitive
)
763 if (String2
->Length
< String1
->Length
)
766 Length
= String1
->Length
;
767 pc1
= String1
->Buffer
;
768 pc2
= String2
->Buffer
;
776 if (RtlUpperChar (*pc1
++) != RtlUpperChar (*pc2
++))
784 if (*pc1
++ != *pc2
++)
798 * TRUE if String2 contains String1 as a prefix.
802 RtlPrefixUnicodeString(
803 PUNICODE_STRING String1
,
804 PUNICODE_STRING String2
,
805 BOOLEAN CaseInsensitive
)
811 if (String2
->Length
< String1
->Length
)
814 Length
= String1
->Length
/ 2;
815 pc1
= String1
->Buffer
;
816 pc2
= String2
->Buffer
;
824 if (RtlUpcaseUnicodeChar (*pc1
++)
825 != RtlUpcaseUnicodeChar (*pc2
++))
833 if( *pc1
++ != *pc2
++ )
842 /**************************************************************************
843 * RtlUnicodeStringToInteger (NTDLL.@)
845 * Converts an unicode string into its integer equivalent.
848 * Success: STATUS_SUCCESS. value contains the converted number
849 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
850 * STATUS_ACCESS_VIOLATION, if value is NULL.
853 * For base 0 it uses 10 as base and the string should be in the format
854 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
855 * For other bases the string should be in the format
856 * "{whitespace} [+|-] {digits}".
857 * No check is made for value overflow, only the lower 32 bits are assigned.
858 * If str is NULL it crashes, as the native function does.
860 * Note that regardless of success or failure status, we should leave the
861 * partial value in Value. An error is never returned based on the chars
865 * This function does not read garbage on string length 0 as the native
870 RtlUnicodeStringToInteger(
871 PUNICODE_STRING str
, /* [I] Unicode string to be converted */
872 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
873 PULONG value
) /* [O] Destination for the converted value */
875 LPWSTR lpwstr
= str
->Buffer
;
876 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
880 ULONG RunningTotal
= 0;
883 while (CharsRemaining
>= 1 && *lpwstr
<= L
' ') {
888 if (CharsRemaining
>= 1) {
889 if (*lpwstr
== L
'+') {
892 } else if (*lpwstr
== L
'-') {
899 if (CharsRemaining
>= 2 && lpwstr
[0] == L
'0') {
900 if (lpwstr
[1] == L
'b' || lpwstr
[1] == L
'B') {
904 } else if (lpwstr
[1] == L
'o' || lpwstr
[1] == L
'O') {
908 } else if (lpwstr
[1] == L
'x' || lpwstr
[1] == L
'X') {
916 } else if ((base
!= newbase
) ||
917 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
918 return STATUS_INVALID_PARAMETER
;
923 return STATUS_ACCESS_VIOLATION
;
926 while (CharsRemaining
>= 1) {
927 wchCurrent
= *lpwstr
;
928 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
929 digit
= wchCurrent
- L
'0';
930 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
931 digit
= wchCurrent
- L
'A' + 10;
932 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
933 digit
= wchCurrent
- L
'a' + 10;
937 if (digit
< 0 || digit
>= (int)base
) {
938 *value
= bMinus
? -RunningTotal
: RunningTotal
;
939 return STATUS_SUCCESS
;
942 RunningTotal
= RunningTotal
* base
+ digit
;
947 *value
= bMinus
? -RunningTotal
: RunningTotal
;
948 return STATUS_SUCCESS
;
956 * Bytes necessary for the conversion including nullterm.
960 RtlUnicodeStringToOemSize(
961 IN PUNICODE_STRING UnicodeString
)
965 RtlUnicodeToMultiByteSize (&Size
,
966 UnicodeString
->Buffer
,
967 UnicodeString
->Length
);
969 return Size
+1; //NB: incl. nullterm
977 * This function always writes a terminating '\0'.
978 * It performs a partial copy if ansi is too small.
982 RtlUnicodeStringToAnsiString(
983 IN OUT PANSI_STRING AnsiDest
,
984 IN PUNICODE_STRING UniSource
,
985 IN BOOLEAN AllocateDestinationString
)
987 NTSTATUS Status
= STATUS_SUCCESS
;
988 ULONG Length
; /* including nullterm */
990 if (NlsMbCodePageTag
== TRUE
)
992 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
995 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
997 AnsiDest
->Length
= Length
- sizeof(CHAR
);
999 if (AllocateDestinationString
)
1001 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1002 if (AnsiDest
->Buffer
== NULL
)
1003 return STATUS_NO_MEMORY
;
1005 AnsiDest
->MaximumLength
= Length
;
1007 else if (AnsiDest
->MaximumLength
== 0)
1009 return STATUS_BUFFER_TOO_SMALL
;
1011 else if (Length
> AnsiDest
->MaximumLength
)
1013 /* make room for nullterm */
1014 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1017 Status
= RtlUnicodeToMultiByteN (AnsiDest
->Buffer
,
1023 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1025 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1029 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1038 * This function always writes a terminating '\0'.
1039 * Does NOT perform a partial copy if unicode is too small!
1043 RtlOemStringToUnicodeString(
1044 IN OUT PUNICODE_STRING UniDest
,
1045 IN POEM_STRING OemSource
,
1046 IN BOOLEAN AllocateDestinationString
)
1049 ULONG Length
; /* including nullterm */
1051 if (NlsMbOemCodePageTag
== TRUE
)
1052 Length
= RtlOemStringToUnicodeSize(OemSource
);
1054 Length
= (OemSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
1056 if (Length
> 0xffff)
1057 return STATUS_INVALID_PARAMETER_2
;
1059 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
1061 if (AllocateDestinationString
)
1063 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1064 if (UniDest
->Buffer
== NULL
)
1065 return STATUS_NO_MEMORY
;
1067 UniDest
->MaximumLength
= Length
;
1069 else if (Length
> UniDest
->MaximumLength
)
1071 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
1072 return STATUS_BUFFER_TOO_SMALL
;
1075 /* FIXME: Do we need this????? -Gunnar */
1076 RtlZeroMemory (UniDest
->Buffer
,
1079 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1085 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1087 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1091 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1092 return STATUS_SUCCESS
;
1100 * This function always '\0' terminates the string returned.
1104 RtlUnicodeStringToOemString(
1105 IN OUT POEM_STRING OemDest
,
1106 IN PUNICODE_STRING UniSource
,
1107 IN BOOLEAN AllocateDestinationString
)
1109 NTSTATUS Status
= STATUS_SUCCESS
;
1110 ULONG Length
; //including nullterm
1112 if (NlsMbOemCodePageTag
== TRUE
)
1113 Length
= RtlUnicodeStringToAnsiSize (UniSource
);
1115 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1117 if (Length
> 0x0000FFFF)
1118 return STATUS_INVALID_PARAMETER_2
;
1120 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1122 if (AllocateDestinationString
)
1124 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1125 if (OemDest
->Buffer
== NULL
)
1126 return STATUS_NO_MEMORY
;
1128 OemDest
->MaximumLength
= Length
;
1130 else if (OemDest
->MaximumLength
== 0)
1132 return STATUS_BUFFER_TOO_SMALL
;
1134 else if (Length
> OemDest
->MaximumLength
)
1136 //make room for nullterm
1137 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1140 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1146 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1148 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1152 OemDest
->Buffer
[OemDest
->Length
] = 0;
1156 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1163 * The length of the string if all tests were passed, 0 otherwise.
1166 RtlIsTextUnicode (PVOID Buffer
,
1171 ULONG in_flags
= (ULONG
)-1;
1172 ULONG out_flags
= 0;
1181 * Apply various tests to the text string. According to the
1182 * docs, each test "passed" sets the corresponding flag in
1183 * the output flags. But some of the tests are mutually
1184 * exclusive, so I don't see how you could pass all tests ...
1187 /* Check for an odd length ... pass if even. */
1189 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1191 /* Check for the BOM (byte order mark). */
1193 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1196 /* Check for the reverse BOM (byte order mark). */
1198 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1201 /* FIXME: Add more tests */
1204 * Check whether the string passed all of the tests.
1206 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1207 if ((out_flags
& in_flags
) != in_flags
)
1222 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1223 * A partial copy is NOT performed if the dest buffer is too small!
1227 RtlOemStringToCountedUnicodeString(
1228 IN OUT PUNICODE_STRING UniDest
,
1229 IN POEM_STRING OemSource
,
1230 IN BOOLEAN AllocateDestinationString
)
1233 ULONG Length
; /* excluding nullterm */
1235 if (NlsMbCodePageTag
== TRUE
)
1236 Length
= RtlOemStringToUnicodeSize(OemSource
) - sizeof(WCHAR
);
1238 Length
= OemSource
->Length
* sizeof(WCHAR
);
1241 return STATUS_INVALID_PARAMETER_2
;
1243 if (AllocateDestinationString
== TRUE
)
1245 UniDest
->Buffer
= RtlpAllocateStringMemory (Length
, TAG_USTR
);
1246 if (UniDest
->Buffer
== NULL
)
1247 return STATUS_NO_MEMORY
;
1249 UniDest
->MaximumLength
= Length
;
1251 else if (Length
> UniDest
->MaximumLength
)
1253 return STATUS_BUFFER_TOO_SMALL
;
1256 UniDest
->Length
= Length
;
1258 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1264 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1266 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1277 * TRUE if the names are equal, FALSE if not
1280 * The comparison is case insensitive.
1284 RtlEqualComputerName(
1285 IN PUNICODE_STRING ComputerName1
,
1286 IN PUNICODE_STRING ComputerName2
)
1288 OEM_STRING OemString1
;
1289 OEM_STRING OemString2
;
1290 BOOLEAN Result
= FALSE
;
1292 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1294 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1296 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1297 RtlFreeOemString( &OemString2
);
1299 RtlFreeOemString( &OemString1
);
1309 * TRUE if the names are equal, FALSE if not
1312 * The comparison is case insensitive.
1316 RtlEqualDomainName (
1317 IN PUNICODE_STRING DomainName1
,
1318 IN PUNICODE_STRING DomainName2
1321 return RtlEqualComputerName(DomainName1
, DomainName2
);
1331 RtlEqualDomainName (
1332 IN PUNICODE_STRING DomainName1,
1333 IN PUNICODE_STRING DomainName2
1336 OEM_STRING OemString1;
1337 OEM_STRING OemString2;
1340 RtlUpcaseUnicodeStringToOemString (&OemString1,
1343 RtlUpcaseUnicodeStringToOemString (&OemString2,
1347 Result = RtlEqualString (&OemString1,
1351 RtlFreeOemString (&OemString1);
1352 RtlFreeOemString (&OemString2);
1362 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1364 * Convert a string representation of a GUID into a GUID.
1367 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1368 * guid [O] Destination for the converted GUID
1371 * Success: STATUS_SUCCESS. guid contains the converted value.
1372 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1375 * See RtlStringFromGUID.
1380 IN UNICODE_STRING
*str
,
1385 const WCHAR
*lpszCLSID
= str
->Buffer
;
1386 BYTE
* lpOut
= (BYTE
*)guid
;
1388 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1390 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1391 * to memory: DWORD... WORD WORD BYTES............
1398 if (*lpszCLSID
!= '{')
1399 return STATUS_INVALID_PARAMETER
;
1406 if (*lpszCLSID
!= '-')
1407 return STATUS_INVALID_PARAMETER
;
1411 if (*lpszCLSID
!= '}')
1412 return STATUS_INVALID_PARAMETER
;
1417 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1420 /* Read two hex digits as a byte value */
1421 if (ch
>= '0' && ch
<= '9')
1423 else if (ch
>= 'a' && ch
<= 'f')
1425 else if (ch
>= 'A' && ch
<= 'F')
1428 return STATUS_INVALID_PARAMETER
;
1430 if (ch2
>= '0' && ch2
<= '9')
1432 else if (ch2
>= 'a' && ch2
<= 'f')
1433 ch2
= ch2
- 'a' + 10;
1434 else if (ch2
>= 'A' && ch2
<= 'F')
1435 ch2
= ch2
- 'A' + 10;
1437 return STATUS_INVALID_PARAMETER
;
1439 byte
= ch
<< 4 | ch2
;
1443 #ifndef WORDS_BIGENDIAN
1444 /* For Big Endian machines, we store the data such that the
1445 * dword/word members can be read as DWORDS and WORDS correctly. */
1477 lpszCLSID
++; /* Skip 2nd character of byte */
1485 return STATUS_SUCCESS
;
1493 RtlEraseUnicodeString(
1494 IN PUNICODE_STRING String
)
1496 if (String
->Buffer
!= NULL
&&
1497 String
->MaximumLength
!= 0)
1499 RtlZeroMemory (String
->Buffer
,
1500 String
->MaximumLength
);
1511 RtlHashUnicodeString(
1512 IN CONST UNICODE_STRING
*String
,
1513 IN BOOLEAN CaseInSensitive
,
1514 IN ULONG HashAlgorithm
,
1515 OUT PULONG HashValue
)
1517 if (String
!= NULL
&& HashValue
!= NULL
)
1519 switch (HashAlgorithm
)
1521 case HASH_STRING_ALGORITHM_DEFAULT
:
1522 case HASH_STRING_ALGORITHM_X65599
:
1527 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1529 if (CaseInSensitive
)
1531 for (c
= String
->Buffer
;
1535 /* only uppercase characters if they are 'a' ... 'z'! */
1536 *HashValue
= ((65599 * (*HashValue
)) +
1537 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1538 (*c
) - L
'a' + L
'A' : (*c
)));
1543 for (c
= String
->Buffer
;
1547 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1550 return STATUS_SUCCESS
;
1555 return STATUS_INVALID_PARAMETER
;
1562 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1563 * Does a partial copy if the dest buffer is too small
1567 RtlUnicodeStringToCountedOemString(
1568 IN OUT POEM_STRING OemDest
,
1569 IN PUNICODE_STRING UniSource
,
1570 IN BOOLEAN AllocateDestinationString
)
1573 ULONG Length
; //excluding nullterm
1575 if (NlsMbOemCodePageTag
== TRUE
)
1576 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1578 Length
= (UniSource
->Length
/ sizeof(WCHAR
));
1580 if (Length
> 0x0000FFFF)
1581 return STATUS_INVALID_PARAMETER_2
;
1583 OemDest
->Length
= (WORD
)(Length
);
1585 if (AllocateDestinationString
)
1587 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1588 if (OemDest
->Buffer
== NULL
)
1589 return STATUS_NO_MEMORY
;
1591 OemDest
->MaximumLength
= Length
;
1593 else if (OemDest
->MaximumLength
== 0)
1595 return STATUS_BUFFER_TOO_SMALL
;
1597 else if (Length
> OemDest
->MaximumLength
)
1599 OemDest
->Length
= OemDest
->MaximumLength
;
1602 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1608 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1610 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1621 RtlLargeIntegerToChar(
1622 IN PLARGE_INTEGER Value
,
1625 IN OUT PCHAR String
)
1629 ULONGLONG v
= Value
->QuadPart
;
1638 if ((Radix
!= 2) && (Radix
!= 8) &&
1639 (Radix
!= 10) && (Radix
!= 16))
1640 return STATUS_INVALID_PARAMETER
;
1643 while (v
|| tp
== temp
)
1654 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1655 return STATUS_BUFFER_TOO_SMALL
;
1662 return STATUS_SUCCESS
;
1669 * dest is never '\0' terminated because it may be equal to src, and src
1670 * might not be '\0' terminated. dest->Length is only set upon success.
1674 RtlUpcaseUnicodeString(
1675 IN OUT PUNICODE_STRING UniDest
,
1676 IN PCUNICODE_STRING UniSource
,
1677 IN BOOLEAN AllocateDestinationString
)
1682 if (AllocateDestinationString
== TRUE
)
1684 UniDest
->MaximumLength
= UniSource
->Length
;
1685 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1686 if (UniDest
->Buffer
== NULL
)
1687 return STATUS_NO_MEMORY
;
1689 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1691 return STATUS_BUFFER_TOO_SMALL
;
1694 UniDest
->Length
= UniSource
->Length
;
1696 Src
= UniSource
->Buffer
;
1697 Dest
= UniDest
->Buffer
;
1698 for (i
= 0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
1700 *Dest
= RtlUpcaseUnicodeChar (*Src
);
1705 return STATUS_SUCCESS
;
1712 * This function always writes a terminating '\0'.
1713 * It performs a partial copy if ansi is too small.
1717 RtlUpcaseUnicodeStringToAnsiString(
1718 IN OUT PANSI_STRING AnsiDest
,
1719 IN PUNICODE_STRING UniSource
,
1720 IN BOOLEAN AllocateDestinationString
)
1723 ULONG Length
; /* including nullterm */
1725 if (NlsMbCodePageTag
== TRUE
)
1726 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1728 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1730 if (Length
> 0x0000FFFF)
1731 return STATUS_INVALID_PARAMETER_2
;
1733 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1735 if (AllocateDestinationString
)
1737 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1738 if (AnsiDest
->Buffer
== NULL
)
1739 return STATUS_NO_MEMORY
;
1741 AnsiDest
->MaximumLength
= Length
;
1743 else if (AnsiDest
->MaximumLength
== 0)
1745 return STATUS_BUFFER_TOO_SMALL
;
1747 else if (Length
> AnsiDest
->MaximumLength
)
1749 /* make room for nullterm */
1750 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1753 /* FIXME: do we need this??????? -Gunnar */
1754 RtlZeroMemory (AnsiDest
->Buffer
,
1757 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1763 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1765 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1769 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
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 PUNICODE_STRING UniSource
,
1785 IN BOOLEAN AllocateDestinationString
)
1788 ULONG Length
; /* excluding nullterm */
1790 if (NlsMbCodePageTag
== TRUE
)
1791 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1793 Length
= UniSource
->Length
/ sizeof(WCHAR
);
1795 if (Length
> 0x0000FFFF)
1796 return(STATUS_INVALID_PARAMETER_2
);
1798 OemDest
->Length
= (WORD
)(Length
);
1800 if (AllocateDestinationString
)
1802 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1803 if (OemDest
->Buffer
== NULL
)
1804 return(STATUS_NO_MEMORY
);
1806 /* FIXME: Do we need this????? */
1807 RtlZeroMemory (OemDest
->Buffer
, Length
);
1809 OemDest
->MaximumLength
= (WORD
)Length
;
1811 else if (OemDest
->MaximumLength
== 0)
1813 return(STATUS_BUFFER_TOO_SMALL
);
1815 else if (Length
> OemDest
->MaximumLength
)
1817 OemDest
->Length
= OemDest
->MaximumLength
;
1820 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1826 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1828 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
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 PUNICODE_STRING UniSource
,
1846 IN BOOLEAN AllocateDestinationString
1850 ULONG Length
; /* including nullterm */
1852 if (NlsMbOemCodePageTag
== TRUE
)
1853 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1855 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1857 if (Length
> 0x0000FFFF)
1858 return STATUS_INVALID_PARAMETER_2
;
1860 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1862 if (AllocateDestinationString
)
1864 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1865 if (OemDest
->Buffer
== NULL
)
1866 return STATUS_NO_MEMORY
;
1868 /* FIXME: Do we need this???? */
1869 RtlZeroMemory (OemDest
->Buffer
, Length
);
1871 OemDest
->MaximumLength
= (WORD
)Length
;
1873 else if (OemDest
->MaximumLength
== 0)
1875 return STATUS_BUFFER_OVERFLOW
;
1877 else if (Length
> OemDest
->MaximumLength
)
1879 /* make room for nullterm */
1880 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1883 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
1889 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1891 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1895 OemDest
->Buffer
[OemDest
->Length
] = 0;
1903 * Bytes calculated including nullterm
1907 RtlOemStringToUnicodeSize(IN POEM_STRING OemString
)
1911 //this function returns size including nullterm
1912 RtlMultiByteToUnicodeSize(&Size
,
1926 RtlStringFromGUID (IN REFGUID Guid
,
1927 OUT PUNICODE_STRING GuidString
)
1929 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1936 return STATUS_INVALID_PARAMETER
;
1940 L
"{%08lX-%04X-%04X-%02X%02X-",
1946 BufferPtr
= Buffer
+ 25;
1949 for (i
= 2; i
< 8; i
++)
1951 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1952 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1955 *BufferPtr
++ = L
'}';
1956 *BufferPtr
++ = L
'\0';
1958 return RtlCreateUnicodeString (GuidString
, Buffer
);
1966 * Bytes calculated including nullterm
1970 RtlUnicodeStringToAnsiSize(
1971 IN PUNICODE_STRING UnicodeString
)
1975 //this function return size without nullterm!
1976 RtlUnicodeToMultiByteSize (&Size
,
1977 UnicodeString
->Buffer
,
1978 UnicodeString
->Length
);
1980 return Size
+ sizeof(CHAR
); //NB: incl. nullterm
1991 RtlCompareUnicodeString(
1992 IN PUNICODE_STRING String1
,
1993 IN PUNICODE_STRING String2
,
1994 IN BOOLEAN CaseInsensitive
)
2000 if (String1
&& String2
)
2002 len1
= String1
->Length
/ sizeof(WCHAR
);
2003 len2
= String2
->Length
/ sizeof(WCHAR
);
2004 s1
= String1
->Buffer
;
2005 s2
= String2
->Buffer
;
2009 if (CaseInsensitive
)
2013 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
2014 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
2015 if (!c1
|| !c2
|| c1
!= c2
)
2023 c1
= len1
-- ? *s1
++ : 0;
2024 c2
= len2
-- ? *s2
++ : 0;
2025 if (!c1
|| !c2
|| c1
!= c2
)
2042 IN OUT PSTRING DestinationString
,
2043 IN PSTRING SourceString
)
2047 if(SourceString
== NULL
)
2049 DestinationString
->Length
= 0;
2053 copylen
= min (DestinationString
->MaximumLength
,
2054 SourceString
->Length
);
2056 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2057 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
2059 DestinationString
->Buffer
[copylen
] = 0;
2061 DestinationString
->Length
= copylen
;
2071 RtlCopyUnicodeString(
2072 IN OUT PUNICODE_STRING DestinationString
,
2073 IN PUNICODE_STRING SourceString
)
2077 if (SourceString
== NULL
)
2079 DestinationString
->Length
= 0;
2083 copylen
= min (DestinationString
->MaximumLength
,
2084 SourceString
->Length
);
2085 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2086 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
2088 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
2090 DestinationString
->Length
= copylen
;
2097 * Creates a nullterminated UNICODE_STRING
2101 RtlCreateUnicodeString(
2102 IN OUT PUNICODE_STRING UniDest
,
2107 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
2108 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2109 if (UniDest
->Buffer
== NULL
)
2112 RtlCopyMemory (UniDest
->Buffer
,
2116 UniDest
->MaximumLength
= Length
;
2117 UniDest
->Length
= Length
- sizeof (WCHAR
);
2127 RtlCreateUnicodeStringFromAsciiz(
2128 OUT PUNICODE_STRING Destination
,
2131 ANSI_STRING AnsiString
;
2134 RtlInitAnsiString (&AnsiString
,
2137 Status
= RtlAnsiStringToUnicodeString (Destination
,
2141 return NT_SUCCESS(Status
);
2148 * Dest is never '\0' terminated because it may be equal to src, and src
2149 * might not be '\0' terminated.
2150 * Dest->Length is only set upon success.
2153 RtlDowncaseUnicodeString(
2154 IN OUT PUNICODE_STRING UniDest
,
2155 IN PUNICODE_STRING UniSource
,
2156 IN BOOLEAN AllocateDestinationString
)
2161 if (AllocateDestinationString
)
2163 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2164 if (UniDest
->Buffer
== NULL
)
2165 return STATUS_NO_MEMORY
;
2167 UniDest
->MaximumLength
= UniSource
->Length
;
2169 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2171 return STATUS_BUFFER_TOO_SMALL
;
2174 UniDest
->Length
= UniSource
->Length
;
2176 Src
= UniSource
->Buffer
;
2177 Dest
= UniDest
->Buffer
;
2178 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2184 else if (*Src
<= L
'Z')
2186 *Dest
= (*Src
+ (L
'a' - L
'A'));
2190 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2197 return STATUS_SUCCESS
;
2204 * if src is NULL dest is unchanged.
2205 * dest is '\0' terminated when the MaximumLength allowes it.
2206 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2209 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2214 slen
= wcslen(Source
) * sizeof(WCHAR
);
2216 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2217 return(STATUS_BUFFER_TOO_SMALL
);
2219 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2220 Destination
->Length
+= slen
;
2221 /* append terminating '\0' if enough space */
2222 if( Destination
->MaximumLength
> Destination
->Length
)
2223 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2225 return(STATUS_SUCCESS
);
2232 * This function always writes a terminating '\0'.
2233 * If the dest buffer is too small a partial copy is NOT performed!
2237 RtlAnsiStringToUnicodeString(
2238 IN OUT PUNICODE_STRING UniDest
,
2239 IN PANSI_STRING AnsiSource
,
2240 IN BOOLEAN AllocateDestinationString
)
2243 ULONG Length
; //including nullterm
2245 if (NlsMbCodePageTag
== TRUE
)
2246 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2248 Length
= (AnsiSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
2250 if (Length
> 0xffff)
2251 return STATUS_INVALID_PARAMETER_2
;
2253 if (AllocateDestinationString
== TRUE
)
2255 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2256 if (UniDest
->Buffer
== NULL
)
2257 return STATUS_NO_MEMORY
;
2259 UniDest
->MaximumLength
= Length
;
2261 else if (Length
> UniDest
->MaximumLength
)
2263 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2264 return STATUS_BUFFER_TOO_SMALL
;
2267 UniDest
->Length
= Length
- sizeof(WCHAR
);
2269 //FIXME: We don't need this??? -Gunnar
2270 RtlZeroMemory (UniDest
->Buffer
,
2273 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2277 AnsiSource
->Length
);
2279 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2281 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
2285 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2293 * if src is NULL dest is unchanged.
2294 * dest is never '\0' terminated.
2298 RtlAppendAsciizToString(
2299 IN OUT PSTRING Destination
,
2306 return STATUS_SUCCESS
;
2308 Length
= strlen (Source
);
2309 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2310 return STATUS_BUFFER_TOO_SMALL
;
2312 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2319 Destination
->Length
+= Length
;
2321 return STATUS_SUCCESS
;
2329 RtlUpperString(PSTRING DestinationString
,
2330 PSTRING SourceString
)
2337 Length
= min(SourceString
->Length
,
2338 DestinationString
->MaximumLength
- 1);
2340 Src
= SourceString
->Buffer
;
2341 Dest
= DestinationString
->Buffer
;
2342 for (i
= 0; i
< Length
; i
++)
2344 *Dest
= RtlUpperChar(*Src
);
2350 DestinationString
->Length
= SourceString
->Length
;
2358 RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
2360 return RtlAnsiStringToUnicodeSize(AnsiString
);
2368 RtlxOemStringToUnicodeSize(IN POEM_STRING OemString
)
2370 return RtlOemStringToUnicodeSize(OemString
);
2379 RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString
)
2381 return RtlUnicodeStringToAnsiSize(UnicodeString
);
2389 RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString
)
2391 return RtlUnicodeStringToOemSize(UnicodeString
);
2398 * See RtlpDuplicateUnicodeString
2401 RtlDuplicateUnicodeString(
2403 IN PUNICODE_STRING SourceString
,
2404 PUNICODE_STRING DestinationString
)
2406 if (SourceString
== NULL
|| DestinationString
== NULL
)
2407 return STATUS_INVALID_PARAMETER
;
2410 if (SourceString
->Length
== 0 && AddNull
!= 3)
2412 DestinationString
->Length
= 0;
2413 DestinationString
->MaximumLength
= 0;
2414 DestinationString
->Buffer
= NULL
;
2418 UINT DestMaxLength
= SourceString
->Length
;
2421 DestMaxLength
+= sizeof(UNICODE_NULL
);
2423 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2424 if (DestinationString
->Buffer
== NULL
)
2425 return STATUS_NO_MEMORY
;
2427 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2428 DestinationString
->Length
= SourceString
->Length
;
2429 DestinationString
->MaximumLength
= DestMaxLength
;
2432 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2435 return STATUS_SUCCESS
;
2442 RtlValidateUnicodeString(IN ULONG Flags
,
2443 IN PUNICODE_STRING UnicodeString
)
2445 /* currently no flags are supported! */
2449 ((UnicodeString
== NULL
) ||
2450 ((UnicodeString
->Length
!= 0) &&
2451 (UnicodeString
->Buffer
!= NULL
) &&
2452 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2453 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2454 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2456 /* a NULL pointer as a unicode string is considered to be a valid unicode
2458 return STATUS_SUCCESS
;
2462 return STATUS_INVALID_PARAMETER
;