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') {
914 if (base
== 0 && newbase
== 0) {
916 } else if (base
== 0 && newbase
!= 0) {
918 } else if ((newbase
!= 0 && base
!= newbase
) ||
919 (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16)) {
920 return STATUS_INVALID_PARAMETER
;
925 return STATUS_ACCESS_VIOLATION
;
928 while (CharsRemaining
>= 1) {
929 wchCurrent
= *lpwstr
;
930 if (wchCurrent
>= L
'0' && wchCurrent
<= L
'9') {
931 digit
= wchCurrent
- L
'0';
932 } else if (wchCurrent
>= L
'A' && wchCurrent
<= L
'Z') {
933 digit
= wchCurrent
- L
'A' + 10;
934 } else if (wchCurrent
>= L
'a' && wchCurrent
<= L
'z') {
935 digit
= wchCurrent
- L
'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
979 * This function always writes a terminating '\0'.
980 * It performs a partial copy if ansi is too small.
984 RtlUnicodeStringToAnsiString(
985 IN OUT PANSI_STRING AnsiDest
,
986 IN PUNICODE_STRING UniSource
,
987 IN BOOLEAN AllocateDestinationString
)
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
= RtlpAllocateStringMemory(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 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1031 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1040 * This function always writes a terminating '\0'.
1041 * Does NOT perform a partial copy if unicode is too small!
1045 RtlOemStringToUnicodeString(
1046 IN OUT PUNICODE_STRING UniDest
,
1047 IN POEM_STRING OemSource
,
1048 IN BOOLEAN AllocateDestinationString
)
1051 ULONG Length
; /* including nullterm */
1053 if (NlsMbOemCodePageTag
== TRUE
)
1054 Length
= RtlOemStringToUnicodeSize(OemSource
);
1056 Length
= (OemSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
1058 if (Length
> 0xffff)
1059 return STATUS_INVALID_PARAMETER_2
;
1061 UniDest
->Length
= (WORD
)(Length
- sizeof(WCHAR
));
1063 if (AllocateDestinationString
)
1065 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
1066 if (UniDest
->Buffer
== NULL
)
1067 return STATUS_NO_MEMORY
;
1069 UniDest
->MaximumLength
= Length
;
1071 else if (Length
> UniDest
->MaximumLength
)
1073 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
1074 return STATUS_BUFFER_TOO_SMALL
;
1077 /* FIXME: Do we need this????? -Gunnar */
1078 RtlZeroMemory (UniDest
->Buffer
,
1081 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1087 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1089 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1093 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
1094 return STATUS_SUCCESS
;
1102 * This function always '\0' terminates the string returned.
1106 RtlUnicodeStringToOemString(
1107 IN OUT POEM_STRING OemDest
,
1108 IN PUNICODE_STRING UniSource
,
1109 IN BOOLEAN AllocateDestinationString
)
1111 NTSTATUS Status
= STATUS_SUCCESS
;
1112 ULONG Length
; //including nullterm
1114 if (NlsMbOemCodePageTag
== TRUE
)
1115 Length
= RtlUnicodeStringToAnsiSize (UniSource
);
1117 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1119 if (Length
> 0x0000FFFF)
1120 return STATUS_INVALID_PARAMETER_2
;
1122 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1124 if (AllocateDestinationString
)
1126 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1127 if (OemDest
->Buffer
== NULL
)
1128 return STATUS_NO_MEMORY
;
1130 OemDest
->MaximumLength
= Length
;
1132 else if (OemDest
->MaximumLength
== 0)
1134 return STATUS_BUFFER_TOO_SMALL
;
1136 else if (Length
> OemDest
->MaximumLength
)
1138 //make room for nullterm
1139 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1142 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1148 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1150 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1154 OemDest
->Buffer
[OemDest
->Length
] = 0;
1158 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
1165 * The length of the string if all tests were passed, 0 otherwise.
1168 RtlIsTextUnicode (PVOID Buffer
,
1173 ULONG in_flags
= (ULONG
)-1;
1174 ULONG out_flags
= 0;
1183 * Apply various tests to the text string. According to the
1184 * docs, each test "passed" sets the corresponding flag in
1185 * the output flags. But some of the tests are mutually
1186 * exclusive, so I don't see how you could pass all tests ...
1189 /* Check for an odd length ... pass if even. */
1191 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1193 /* Check for the BOM (byte order mark). */
1195 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1198 /* Check for the reverse BOM (byte order mark). */
1200 out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1203 /* FIXME: Add more tests */
1206 * Check whether the string passed all of the tests.
1208 in_flags
&= ITU_IMPLEMENTED_TESTS
;
1209 if ((out_flags
& in_flags
) != in_flags
)
1224 * Same as RtlOemStringToUnicodeString but doesn't write terminating null
1225 * A partial copy is NOT performed if the dest buffer is too small!
1229 RtlOemStringToCountedUnicodeString(
1230 IN OUT PUNICODE_STRING UniDest
,
1231 IN POEM_STRING OemSource
,
1232 IN BOOLEAN AllocateDestinationString
)
1235 ULONG Length
; /* excluding nullterm */
1237 if (NlsMbCodePageTag
== TRUE
)
1238 Length
= RtlOemStringToUnicodeSize(OemSource
) - sizeof(WCHAR
);
1240 Length
= OemSource
->Length
* sizeof(WCHAR
);
1243 return STATUS_INVALID_PARAMETER_2
;
1245 if (AllocateDestinationString
== TRUE
)
1247 UniDest
->Buffer
= RtlpAllocateStringMemory (Length
, TAG_USTR
);
1248 if (UniDest
->Buffer
== NULL
)
1249 return STATUS_NO_MEMORY
;
1251 UniDest
->MaximumLength
= Length
;
1253 else if (Length
> UniDest
->MaximumLength
)
1255 return STATUS_BUFFER_TOO_SMALL
;
1258 UniDest
->Length
= Length
;
1260 Status
= RtlOemToUnicodeN (UniDest
->Buffer
,
1266 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1268 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
1279 * TRUE if the names are equal, FALSE if not
1282 * The comparison is case insensitive.
1286 RtlEqualComputerName(
1287 IN PUNICODE_STRING ComputerName1
,
1288 IN PUNICODE_STRING ComputerName2
)
1290 OEM_STRING OemString1
;
1291 OEM_STRING OemString2
;
1292 BOOLEAN Result
= FALSE
;
1294 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1
, ComputerName1
, TRUE
)))
1296 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2
, ComputerName2
, TRUE
)))
1298 Result
= RtlEqualString( &OemString1
, &OemString2
, TRUE
);
1299 RtlFreeOemString( &OemString2
);
1301 RtlFreeOemString( &OemString1
);
1311 * TRUE if the names are equal, FALSE if not
1314 * The comparison is case insensitive.
1318 RtlEqualDomainName (
1319 IN PUNICODE_STRING DomainName1
,
1320 IN PUNICODE_STRING DomainName2
1323 return RtlEqualComputerName(DomainName1
, DomainName2
);
1333 RtlEqualDomainName (
1334 IN PUNICODE_STRING DomainName1,
1335 IN PUNICODE_STRING DomainName2
1338 OEM_STRING OemString1;
1339 OEM_STRING OemString2;
1342 RtlUpcaseUnicodeStringToOemString (&OemString1,
1345 RtlUpcaseUnicodeStringToOemString (&OemString2,
1349 Result = RtlEqualString (&OemString1,
1353 RtlFreeOemString (&OemString1);
1354 RtlFreeOemString (&OemString2);
1364 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45
1366 * Convert a string representation of a GUID into a GUID.
1369 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1370 * guid [O] Destination for the converted GUID
1373 * Success: STATUS_SUCCESS. guid contains the converted value.
1374 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1377 * See RtlStringFromGUID.
1382 IN UNICODE_STRING
*str
,
1387 const WCHAR
*lpszCLSID
= str
->Buffer
;
1388 BYTE
* lpOut
= (BYTE
*)guid
;
1390 //TRACE("(%s,%p)\n", debugstr_us(str), guid);
1392 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1393 * to memory: DWORD... WORD WORD BYTES............
1400 if (*lpszCLSID
!= '{')
1401 return STATUS_INVALID_PARAMETER
;
1408 if (*lpszCLSID
!= '-')
1409 return STATUS_INVALID_PARAMETER
;
1413 if (*lpszCLSID
!= '}')
1414 return STATUS_INVALID_PARAMETER
;
1419 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1422 /* Read two hex digits as a byte value */
1423 if (ch
>= '0' && ch
<= '9')
1425 else if (ch
>= 'a' && ch
<= 'f')
1427 else if (ch
>= 'A' && ch
<= 'F')
1430 return STATUS_INVALID_PARAMETER
;
1432 if (ch2
>= '0' && ch2
<= '9')
1434 else if (ch2
>= 'a' && ch2
<= 'f')
1435 ch2
= ch2
- 'a' + 10;
1436 else if (ch2
>= 'A' && ch2
<= 'F')
1437 ch2
= ch2
- 'A' + 10;
1439 return STATUS_INVALID_PARAMETER
;
1441 byte
= ch
<< 4 | ch2
;
1445 #ifndef WORDS_BIGENDIAN
1446 /* For Big Endian machines, we store the data such that the
1447 * dword/word members can be read as DWORDS and WORDS correctly. */
1479 lpszCLSID
++; /* Skip 2nd character of byte */
1487 return STATUS_SUCCESS
;
1495 RtlEraseUnicodeString(
1496 IN PUNICODE_STRING String
)
1498 if (String
->Buffer
!= NULL
&&
1499 String
->MaximumLength
!= 0)
1501 RtlZeroMemory (String
->Buffer
,
1502 String
->MaximumLength
);
1513 RtlHashUnicodeString(
1514 IN CONST UNICODE_STRING
*String
,
1515 IN BOOLEAN CaseInSensitive
,
1516 IN ULONG HashAlgorithm
,
1517 OUT PULONG HashValue
)
1519 if (String
!= NULL
&& HashValue
!= NULL
)
1521 switch (HashAlgorithm
)
1523 case HASH_STRING_ALGORITHM_DEFAULT
:
1524 case HASH_STRING_ALGORITHM_X65599
:
1529 end
= String
->Buffer
+ (String
->Length
/ sizeof(WCHAR
));
1531 if (CaseInSensitive
)
1533 for (c
= String
->Buffer
;
1537 /* only uppercase characters if they are 'a' ... 'z'! */
1538 *HashValue
= ((65599 * (*HashValue
)) +
1539 (ULONG
)(((*c
) >= L
'a' && (*c
) <= L
'z') ?
1540 (*c
) - L
'a' + L
'A' : (*c
)));
1545 for (c
= String
->Buffer
;
1549 *HashValue
= ((65599 * (*HashValue
)) + (ULONG
)(*c
));
1552 return STATUS_SUCCESS
;
1557 return STATUS_INVALID_PARAMETER
;
1564 * Same as RtlUnicodeStringToOemString but doesn't write terminating null
1565 * Does a partial copy if the dest buffer is too small
1569 RtlUnicodeStringToCountedOemString(
1570 IN OUT POEM_STRING OemDest
,
1571 IN PUNICODE_STRING UniSource
,
1572 IN BOOLEAN AllocateDestinationString
)
1575 ULONG Length
; //excluding nullterm
1577 if (NlsMbOemCodePageTag
== TRUE
)
1578 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1580 Length
= (UniSource
->Length
/ sizeof(WCHAR
));
1582 if (Length
> 0x0000FFFF)
1583 return STATUS_INVALID_PARAMETER_2
;
1585 OemDest
->Length
= (WORD
)(Length
);
1587 if (AllocateDestinationString
)
1589 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1590 if (OemDest
->Buffer
== NULL
)
1591 return STATUS_NO_MEMORY
;
1593 OemDest
->MaximumLength
= Length
;
1595 else if (OemDest
->MaximumLength
== 0)
1597 return STATUS_BUFFER_TOO_SMALL
;
1599 else if (Length
> OemDest
->MaximumLength
)
1601 OemDest
->Length
= OemDest
->MaximumLength
;
1604 Status
= RtlUnicodeToOemN (OemDest
->Buffer
,
1610 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1612 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1623 RtlLargeIntegerToChar(
1624 IN PLARGE_INTEGER Value
,
1627 IN OUT PCHAR String
)
1631 ULONGLONG v
= Value
->QuadPart
;
1640 if ((Radix
!= 2) && (Radix
!= 8) &&
1641 (Radix
!= 10) && (Radix
!= 16))
1642 return STATUS_INVALID_PARAMETER
;
1645 while (v
|| tp
== temp
)
1656 if ((ULONG
)((ULONG_PTR
)tp
- (ULONG_PTR
)temp
) >= Length
)
1657 return STATUS_BUFFER_TOO_SMALL
;
1664 return STATUS_SUCCESS
;
1671 * dest is never '\0' terminated because it may be equal to src, and src
1672 * might not be '\0' terminated. dest->Length is only set upon success.
1676 RtlUpcaseUnicodeString(
1677 IN OUT PUNICODE_STRING UniDest
,
1678 IN PCUNICODE_STRING UniSource
,
1679 IN BOOLEAN AllocateDestinationString
)
1684 if (AllocateDestinationString
== TRUE
)
1686 UniDest
->MaximumLength
= UniSource
->Length
;
1687 UniDest
->Buffer
= RtlpAllocateStringMemory(UniDest
->MaximumLength
, TAG_USTR
);
1688 if (UniDest
->Buffer
== NULL
)
1689 return STATUS_NO_MEMORY
;
1691 else if (UniSource
->Length
> UniDest
->MaximumLength
)
1693 return STATUS_BUFFER_TOO_SMALL
;
1696 UniDest
->Length
= UniSource
->Length
;
1698 Src
= UniSource
->Buffer
;
1699 Dest
= UniDest
->Buffer
;
1700 for (i
= 0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
1702 *Dest
= RtlUpcaseUnicodeChar (*Src
);
1707 return STATUS_SUCCESS
;
1714 * This function always writes a terminating '\0'.
1715 * It performs a partial copy if ansi is too small.
1719 RtlUpcaseUnicodeStringToAnsiString(
1720 IN OUT PANSI_STRING AnsiDest
,
1721 IN PUNICODE_STRING UniSource
,
1722 IN BOOLEAN AllocateDestinationString
)
1725 ULONG Length
; /* including nullterm */
1727 if (NlsMbCodePageTag
== TRUE
)
1728 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1730 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1732 if (Length
> 0x0000FFFF)
1733 return STATUS_INVALID_PARAMETER_2
;
1735 AnsiDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1737 if (AllocateDestinationString
)
1739 AnsiDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_ASTR
);
1740 if (AnsiDest
->Buffer
== NULL
)
1741 return STATUS_NO_MEMORY
;
1743 AnsiDest
->MaximumLength
= Length
;
1745 else if (AnsiDest
->MaximumLength
== 0)
1747 return STATUS_BUFFER_TOO_SMALL
;
1749 else if (Length
> AnsiDest
->MaximumLength
)
1751 /* make room for nullterm */
1752 AnsiDest
->Length
= AnsiDest
->MaximumLength
- sizeof(CHAR
);
1755 /* FIXME: do we need this??????? -Gunnar */
1756 RtlZeroMemory (AnsiDest
->Buffer
,
1759 Status
= RtlUpcaseUnicodeToMultiByteN (AnsiDest
->Buffer
,
1765 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1767 RtlpFreeStringMemory(AnsiDest
->Buffer
, TAG_ASTR
);
1771 AnsiDest
->Buffer
[AnsiDest
->Length
] = 0;
1779 * This function always writes a terminating '\0'.
1780 * It performs a partial copy if ansi is too small.
1784 RtlUpcaseUnicodeStringToCountedOemString(
1785 IN OUT POEM_STRING OemDest
,
1786 IN PUNICODE_STRING UniSource
,
1787 IN BOOLEAN AllocateDestinationString
)
1790 ULONG Length
; /* excluding nullterm */
1792 if (NlsMbCodePageTag
== TRUE
)
1793 Length
= RtlUnicodeStringToAnsiSize(UniSource
) - sizeof(CHAR
);
1795 Length
= UniSource
->Length
/ sizeof(WCHAR
);
1797 if (Length
> 0x0000FFFF)
1798 return(STATUS_INVALID_PARAMETER_2
);
1800 OemDest
->Length
= (WORD
)(Length
);
1802 if (AllocateDestinationString
)
1804 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1805 if (OemDest
->Buffer
== NULL
)
1806 return(STATUS_NO_MEMORY
);
1808 /* FIXME: Do we need this????? */
1809 RtlZeroMemory (OemDest
->Buffer
, Length
);
1811 OemDest
->MaximumLength
= (WORD
)Length
;
1813 else if (OemDest
->MaximumLength
== 0)
1815 return(STATUS_BUFFER_TOO_SMALL
);
1817 else if (Length
> OemDest
->MaximumLength
)
1819 OemDest
->Length
= OemDest
->MaximumLength
;
1822 Status
= RtlUpcaseUnicodeToOemN(OemDest
->Buffer
,
1828 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1830 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1840 * Oem string is allways nullterminated
1841 * It performs a partial copy if oem is too small.
1845 RtlUpcaseUnicodeStringToOemString (
1846 IN OUT POEM_STRING OemDest
,
1847 IN PUNICODE_STRING UniSource
,
1848 IN BOOLEAN AllocateDestinationString
1852 ULONG Length
; /* including nullterm */
1854 if (NlsMbOemCodePageTag
== TRUE
)
1855 Length
= RtlUnicodeStringToAnsiSize(UniSource
);
1857 Length
= (UniSource
->Length
/ sizeof(WCHAR
)) + sizeof(CHAR
);
1859 if (Length
> 0x0000FFFF)
1860 return STATUS_INVALID_PARAMETER_2
;
1862 OemDest
->Length
= (WORD
)(Length
- sizeof(CHAR
));
1864 if (AllocateDestinationString
)
1866 OemDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_OSTR
);
1867 if (OemDest
->Buffer
== NULL
)
1868 return STATUS_NO_MEMORY
;
1870 /* FIXME: Do we need this???? */
1871 RtlZeroMemory (OemDest
->Buffer
, Length
);
1873 OemDest
->MaximumLength
= (WORD
)Length
;
1875 else if (OemDest
->MaximumLength
== 0)
1877 return STATUS_BUFFER_OVERFLOW
;
1879 else if (Length
> OemDest
->MaximumLength
)
1881 /* make room for nullterm */
1882 OemDest
->Length
= OemDest
->MaximumLength
- sizeof(CHAR
);
1885 Status
= RtlUpcaseUnicodeToOemN (OemDest
->Buffer
,
1891 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
1893 RtlpFreeStringMemory(OemDest
->Buffer
, TAG_OSTR
);
1897 OemDest
->Buffer
[OemDest
->Length
] = 0;
1905 * Bytes calculated including nullterm
1909 RtlOemStringToUnicodeSize(IN POEM_STRING OemString
)
1913 //this function returns size including nullterm
1914 RtlMultiByteToUnicodeSize(&Size
,
1928 RtlStringFromGUID (IN REFGUID Guid
,
1929 OUT PUNICODE_STRING GuidString
)
1931 STATIC CONST PWCHAR Hex
= L
"0123456789ABCDEF";
1938 return STATUS_INVALID_PARAMETER
;
1942 L
"{%08lX-%04X-%04X-%02X%02X-",
1948 BufferPtr
= Buffer
+ 25;
1951 for (i
= 2; i
< 8; i
++)
1953 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] >> 4];
1954 *BufferPtr
++ = Hex
[Guid
->Data4
[i
] & 0xf];
1957 *BufferPtr
++ = L
'}';
1958 *BufferPtr
++ = L
'\0';
1960 return RtlCreateUnicodeString (GuidString
, Buffer
);
1968 * Bytes calculated including nullterm
1972 RtlUnicodeStringToAnsiSize(
1973 IN PUNICODE_STRING UnicodeString
)
1977 //this function return size without nullterm!
1978 RtlUnicodeToMultiByteSize (&Size
,
1979 UnicodeString
->Buffer
,
1980 UnicodeString
->Length
);
1982 return Size
+ sizeof(CHAR
); //NB: incl. nullterm
1993 RtlCompareUnicodeString(
1994 IN PUNICODE_STRING String1
,
1995 IN PUNICODE_STRING String2
,
1996 IN BOOLEAN CaseInsensitive
)
2002 if (String1
&& String2
)
2004 len1
= String1
->Length
/ sizeof(WCHAR
);
2005 len2
= String2
->Length
/ sizeof(WCHAR
);
2006 s1
= String1
->Buffer
;
2007 s2
= String2
->Buffer
;
2011 if (CaseInsensitive
)
2015 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
2016 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
2017 if (!c1
|| !c2
|| c1
!= c2
)
2025 c1
= len1
-- ? *s1
++ : 0;
2026 c2
= len2
-- ? *s2
++ : 0;
2027 if (!c1
|| !c2
|| c1
!= c2
)
2044 IN OUT PSTRING DestinationString
,
2045 IN PSTRING SourceString
)
2049 if(SourceString
== NULL
)
2051 DestinationString
->Length
= 0;
2055 copylen
= min (DestinationString
->MaximumLength
,
2056 SourceString
->Length
);
2058 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2059 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(CHAR
))
2061 DestinationString
->Buffer
[copylen
] = 0;
2063 DestinationString
->Length
= copylen
;
2073 RtlCopyUnicodeString(
2074 IN OUT PUNICODE_STRING DestinationString
,
2075 IN PUNICODE_STRING SourceString
)
2079 if (SourceString
== NULL
)
2081 DestinationString
->Length
= 0;
2085 copylen
= min (DestinationString
->MaximumLength
,
2086 SourceString
->Length
);
2087 memcpy(DestinationString
->Buffer
, SourceString
->Buffer
, copylen
);
2088 if (DestinationString
->MaximumLength
>= copylen
+ sizeof(WCHAR
))
2090 DestinationString
->Buffer
[copylen
/ sizeof(WCHAR
)] = 0;
2092 DestinationString
->Length
= copylen
;
2099 * Creates a nullterminated UNICODE_STRING
2103 RtlCreateUnicodeString(
2104 IN OUT PUNICODE_STRING UniDest
,
2109 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
2110 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2111 if (UniDest
->Buffer
== NULL
)
2114 RtlCopyMemory (UniDest
->Buffer
,
2118 UniDest
->MaximumLength
= Length
;
2119 UniDest
->Length
= Length
- sizeof (WCHAR
);
2129 RtlCreateUnicodeStringFromAsciiz(
2130 OUT PUNICODE_STRING Destination
,
2133 ANSI_STRING AnsiString
;
2136 RtlInitAnsiString (&AnsiString
,
2139 Status
= RtlAnsiStringToUnicodeString (Destination
,
2143 return NT_SUCCESS(Status
);
2150 * Dest is never '\0' terminated because it may be equal to src, and src
2151 * might not be '\0' terminated.
2152 * Dest->Length is only set upon success.
2155 RtlDowncaseUnicodeString(
2156 IN OUT PUNICODE_STRING UniDest
,
2157 IN PUNICODE_STRING UniSource
,
2158 IN BOOLEAN AllocateDestinationString
)
2163 if (AllocateDestinationString
)
2165 UniDest
->Buffer
= RtlpAllocateStringMemory(UniSource
->Length
, TAG_USTR
);
2166 if (UniDest
->Buffer
== NULL
)
2167 return STATUS_NO_MEMORY
;
2169 UniDest
->MaximumLength
= UniSource
->Length
;
2171 else if (UniSource
->Length
> UniDest
->MaximumLength
)
2173 return STATUS_BUFFER_TOO_SMALL
;
2176 UniDest
->Length
= UniSource
->Length
;
2178 Src
= UniSource
->Buffer
;
2179 Dest
= UniDest
->Buffer
;
2180 for (i
=0; i
< UniSource
->Length
/ sizeof(WCHAR
); i
++)
2186 else if (*Src
<= L
'Z')
2188 *Dest
= (*Src
+ (L
'a' - L
'A'));
2192 *Dest
= RtlDowncaseUnicodeChar(*Src
);
2199 return STATUS_SUCCESS
;
2206 * if src is NULL dest is unchanged.
2207 * dest is '\0' terminated when the MaximumLength allowes it.
2208 * When dest fits exactly in MaximumLength characters the '\0' is ommitted.
2211 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination
,
2216 slen
= wcslen(Source
) * sizeof(WCHAR
);
2218 if (Destination
->Length
+ slen
> Destination
->MaximumLength
)
2219 return(STATUS_BUFFER_TOO_SMALL
);
2221 memcpy((char*)Destination
->Buffer
+ Destination
->Length
, Source
, slen
);
2222 Destination
->Length
+= slen
;
2223 /* append terminating '\0' if enough space */
2224 if( Destination
->MaximumLength
> Destination
->Length
)
2225 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = 0;
2227 return(STATUS_SUCCESS
);
2234 * This function always writes a terminating '\0'.
2235 * If the dest buffer is too small a partial copy is NOT performed!
2239 RtlAnsiStringToUnicodeString(
2240 IN OUT PUNICODE_STRING UniDest
,
2241 IN PANSI_STRING AnsiSource
,
2242 IN BOOLEAN AllocateDestinationString
)
2245 ULONG Length
; //including nullterm
2247 if (NlsMbCodePageTag
== TRUE
)
2248 Length
= RtlAnsiStringToUnicodeSize(AnsiSource
);
2250 Length
= (AnsiSource
->Length
* sizeof(WCHAR
)) + sizeof(WCHAR
);
2252 if (Length
> 0xffff)
2253 return STATUS_INVALID_PARAMETER_2
;
2255 if (AllocateDestinationString
== TRUE
)
2257 UniDest
->Buffer
= RtlpAllocateStringMemory(Length
, TAG_USTR
);
2258 if (UniDest
->Buffer
== NULL
)
2259 return STATUS_NO_MEMORY
;
2261 UniDest
->MaximumLength
= Length
;
2263 else if (Length
> UniDest
->MaximumLength
)
2265 DPRINT("STATUS_BUFFER_TOO_SMALL\n");
2266 return STATUS_BUFFER_TOO_SMALL
;
2269 UniDest
->Length
= Length
- sizeof(WCHAR
);
2271 //FIXME: We don't need this??? -Gunnar
2272 RtlZeroMemory (UniDest
->Buffer
,
2275 Status
= RtlMultiByteToUnicodeN (UniDest
->Buffer
,
2279 AnsiSource
->Length
);
2281 if (!NT_SUCCESS(Status
) && AllocateDestinationString
)
2283 RtlpFreeStringMemory(UniDest
->Buffer
, TAG_USTR
);
2287 UniDest
->Buffer
[UniDest
->Length
/ sizeof(WCHAR
)] = 0;
2295 * if src is NULL dest is unchanged.
2296 * dest is never '\0' terminated.
2300 RtlAppendAsciizToString(
2301 IN OUT PSTRING Destination
,
2308 return STATUS_SUCCESS
;
2310 Length
= strlen (Source
);
2311 if (Destination
->Length
+ Length
>= Destination
->MaximumLength
)
2312 return STATUS_BUFFER_TOO_SMALL
;
2314 Ptr
= Destination
->Buffer
+ Destination
->Length
;
2321 Destination
->Length
+= Length
;
2323 return STATUS_SUCCESS
;
2331 RtlUpperString(PSTRING DestinationString
,
2332 PSTRING SourceString
)
2339 Length
= min(SourceString
->Length
,
2340 DestinationString
->MaximumLength
- 1);
2342 Src
= SourceString
->Buffer
;
2343 Dest
= DestinationString
->Buffer
;
2344 for (i
= 0; i
< Length
; i
++)
2346 *Dest
= RtlUpperChar(*Src
);
2352 DestinationString
->Length
= SourceString
->Length
;
2360 RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString
)
2362 return RtlAnsiStringToUnicodeSize(AnsiString
);
2370 RtlxOemStringToUnicodeSize(IN POEM_STRING OemString
)
2372 return RtlOemStringToUnicodeSize(OemString
);
2381 RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString
)
2383 return RtlUnicodeStringToAnsiSize(UnicodeString
);
2391 RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString
)
2393 return RtlUnicodeStringToOemSize(UnicodeString
);
2400 * See RtlpDuplicateUnicodeString
2403 RtlDuplicateUnicodeString(
2405 IN PUNICODE_STRING SourceString
,
2406 PUNICODE_STRING DestinationString
)
2408 if (SourceString
== NULL
|| DestinationString
== NULL
)
2409 return STATUS_INVALID_PARAMETER
;
2412 if (SourceString
->Length
== 0 && AddNull
!= 3)
2414 DestinationString
->Length
= 0;
2415 DestinationString
->MaximumLength
= 0;
2416 DestinationString
->Buffer
= NULL
;
2420 UINT DestMaxLength
= SourceString
->Length
;
2423 DestMaxLength
+= sizeof(UNICODE_NULL
);
2425 DestinationString
->Buffer
= RtlpAllocateStringMemory(DestMaxLength
, TAG_USTR
);
2426 if (DestinationString
->Buffer
== NULL
)
2427 return STATUS_NO_MEMORY
;
2429 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
2430 DestinationString
->Length
= SourceString
->Length
;
2431 DestinationString
->MaximumLength
= DestMaxLength
;
2434 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
2437 return STATUS_SUCCESS
;
2444 RtlValidateUnicodeString(IN ULONG Flags
,
2445 IN PUNICODE_STRING UnicodeString
)
2447 /* currently no flags are supported! */
2451 ((UnicodeString
== NULL
) ||
2452 ((UnicodeString
->Length
!= 0) &&
2453 (UnicodeString
->Buffer
!= NULL
) &&
2454 ((UnicodeString
->Length
% sizeof(WCHAR
)) == 0) &&
2455 ((UnicodeString
->MaximumLength
% sizeof(WCHAR
)) == 0) &&
2456 (UnicodeString
->MaximumLength
>= UnicodeString
->Length
))))
2458 /* a NULL pointer as a unicode string is considered to be a valid unicode
2460 return STATUS_SUCCESS
;
2464 return STATUS_INVALID_PARAMETER
;