Index: kmtests/rtl/RtlUnicodeString.c =================================================================== --- kmtests/rtl/RtlUnicodeString.c (revision 60823) +++ kmtests/rtl/RtlUnicodeString.c (working copy) @@ -7,6 +7,7 @@ #define KMT_EMULATE_KERNEL #include +NTSYSAPI LONG NTAPI RtlCompareString(const PSTRING String1, const PSTRING String2, BOOLEAN CaseInSensitive); static VOID @@ -173,7 +174,549 @@ #endif } +static +VOID +TestRtlAnsiStringToUnicodeSize(VOID) +{ + + ULONG Length; + ANSI_STRING Ansi; + INT i; + CHAR string[]="a"; + PCHAR stringPtr = string; + + *stringPtr = 0; + RtlInitAnsiString(&Ansi, string); + Length = RtlAnsiStringToUnicodeSize(&Ansi); + ok_eq_long(Length, 2); + ok_eq_str(Ansi.Buffer, string); + + for (i = 1; i < 256; i++){ + *stringPtr = i; + RtlInitAnsiString(&Ansi, string); + Length = RtlAnsiStringToUnicodeSize(&Ansi); + ok_eq_long(Length, 4); + //Check the Ansi string didnt change + ok_eq_str(Ansi.Buffer, string); + } + +} + +static +VOID +TestRtlAnsiStringToUnicodeString(VOID) +{ + NTSTATUS Status; + USHORT i; + + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + CHAR MaxAnsi[MAXUSHORT]; + WCHAR MaxAnsiUnicode[MAXUSHORT]; + + //Test#1 + RtlInitAnsiString(&AnsiString, "rEactOS rO#ks !!\"??"); + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(UnicodeString.Length == 38, "Expected 38, UnicodeString.Length: %u \n", UnicodeString.Length); + ok(UnicodeString.MaximumLength == 40, "Expected 40, UnicodeString.MaximumLength: %u \n", UnicodeString.MaximumLength); + ok_eq_wstr(UnicodeString.Buffer, L"rEactOS rO#ks !!\"??"); + RtlFreeUnicodeString(&UnicodeString); + + //Check if AnsiString didn't get modified + ok(AnsiString.Length == 19, "Expected 19, AnsiString.Length: %u \n", AnsiString.Length); + ok(AnsiString.MaximumLength == 20, "Expected 20, AnsiString.MaximumLength: %u \n", AnsiString.MaximumLength); + ok_eq_str(AnsiString.Buffer, "rEactOS rO#ks !!\"??"); + + //Test#2:Empty AnsiString + RtlInitAnsiString(&AnsiString, ""); + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(UnicodeString.Length == 0, "Expected 0, UnicodeString.Length: %u \n", UnicodeString.Length); + ok(UnicodeString.MaximumLength == 2, "Expected 2, UnicodeString.MaximumLength: %u \n", UnicodeString.MaximumLength); + ok_eq_wstr(UnicodeString.Buffer, L""); + RtlFreeUnicodeString(&UnicodeString); + + //Check if AnsiString didn't get modified + ok(AnsiString.Length == 0, "Expected 0, UnicodeString.Length: %u \n", AnsiString.Length); + ok(AnsiString.MaximumLength == 1, "Expected 1, UnicodeString.MaximumLength: %u \n", AnsiString.MaximumLength); + ok_eq_str(AnsiString.Buffer, ""); + + + //Test#2:NULL AnsiString. + KmtStartSeh() + Status = RtlAnsiStringToUnicodeString(&UnicodeString, NULL, TRUE); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + + //Test#3:MAXIMUN AnsiStringw + for (i = 0; i < MAXUSHORT-2; i++) + MaxAnsi[i] = 'r'; + MaxAnsi[MAXUSHORT-1] = '\0'; + + for (i = 0; i < UNICODE_STRING_MAX_CHARS-2; i++) + MaxAnsiUnicode[i] = L'r'; + MaxAnsiUnicode[UNICODE_STRING_MAX_CHARS-1] = L'\0'; + + RtlInitAnsiString(&AnsiString, MaxAnsi); + + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + ok_eq_hex(Status, STATUS_INVALID_PARAMETER_2); + ok(UnicodeString.Length == 0, "Expected UNICODE_STRING_MAX_BYTES, UnicodeString.Length: %u \n", UnicodeString.Length); + ok(UnicodeString.MaximumLength == 0, "Expected UNICODE_STRING_MAX_BYTES, UnicodeString.MaximumLength: %u \n", UnicodeString.MaximumLength); + RtlFreeUnicodeString(&UnicodeString); + + //Check if AnsiString didn't get modified + ok(AnsiString.Length == 65533, "Expected 65533, UnicodeString.Length: %u \n", AnsiString.Length); + ok(AnsiString.MaximumLength == 65534, "Expected 65534, UnicodeString.MaximumLength: %u \n", AnsiString.MaximumLength); + + //Test#4:Don't allocate. AnsiLength < UnicodeLength + RtlInitUnicodeString(&UnicodeString, L"1234567890"); + RtlInitAnsiString(&AnsiString, "abcdefg"); + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(UnicodeString.Length == 14, "Expected 14, UnicodeString.Length: %u \n", UnicodeString.Length); + ok(UnicodeString.MaximumLength == 22, "Expected 22, UnicodeString.MaximumLength: %u \n", UnicodeString.MaximumLength); + ok_eq_wstr(UnicodeString.Buffer, L"abcdefg"); + + //Check if AnsiString didn't get modified + ok(AnsiString.Length == 7, "Expected 7, UnicodeString.Length: %u \n", AnsiString.Length); + ok(AnsiString.MaximumLength == 8, "Expected 8, UnicodeString.MaximumLength: %u \n", AnsiString.MaximumLength); + ok_eq_str(AnsiString.Buffer, "abcdefg"); + + + //Test#5:Don't allocate. AnsiLength > UnicodeLength + RtlInitUnicodeString(&UnicodeString, L"abcdefg"); + RtlInitAnsiString(&AnsiString, "1234567890"); + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); + ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); + ok(UnicodeString.Length == 20, "Expected 20, UnicodeString.Length: %u \n", UnicodeString.Length); + ok(UnicodeString.MaximumLength == 16, "Expected 16, UnicodeString.MaximumLength: %u \n", UnicodeString.MaximumLength); + ok_eq_wstr(UnicodeString.Buffer, L"abcdefg"); + + //Check if AnsiString didn't get modified + ok(AnsiString.Length == 10, "Expected 10, UnicodeString.Length: %u \n", AnsiString.Length); + ok(AnsiString.MaximumLength == 11, "Expected 11, UnicodeString.MaximumLength: %u \n", AnsiString.MaximumLength); + ok_eq_str(AnsiString.Buffer, "1234567890"); + + //Test#6:Don't allocate. AnsiLength > UnicodeLength. Fake ansi length. + RtlInitUnicodeString(&UnicodeString, L"abcdefg"); + RtlInitAnsiString(&AnsiString, "1234567890"); + + //Fake Ansi Length + AnsiString.Length = 4; + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(UnicodeString.Length == 8, "Expected 8, UnicodeString.Length: %u \n", UnicodeString.Length); + ok(UnicodeString.MaximumLength == 16, "Expected 16, UnicodeString.MaximumLength: %u \n", UnicodeString.MaximumLength); + ok_eq_wstr(UnicodeString.Buffer, L"1234"); + + //Check if AnsiString didn't get modified + ok(AnsiString.Length == 4, "Expected 4, UnicodeString.Length: %u \n", AnsiString.Length); + ok(AnsiString.MaximumLength == 11, "Expected 11, UnicodeString.MaximumLength: %u \n", AnsiString.MaximumLength); + ok_eq_str(AnsiString.Buffer, "1234567890"); + +} +static +VOID +TestRtlCompareString(VOID) +{ + + ANSI_STRING String1; + ANSI_STRING String2; + LONG Length; + + //TEST #1:CASING.string vs STRING. + RtlInitAnsiString(&String1, "react\\#s"); + RtlInitAnsiString(&String2, "REACT\\#S"); + Length = RtlCompareString(&String1, &String2, TRUE); + ok_eq_long( Length, 0); + + //--- Originals shouldn't have been modified at all. + ok_eq_str(String1.Buffer, "react\\#s"); + ok_eq_str(String2.Buffer, "REACT\\#S"); + + //TEST #2:NON-CASING.string vs STRING. + RtlInitAnsiString(&String1, "re\\act\\.s"); + RtlInitAnsiString(&String2, "RE\\ACT\\.S"); + Length = RtlCompareString(&String1, &String2, FALSE); + ok( Length != 0, "Expected Length !=0, current Length is: %l", Length); + + //--- Originals shouldn't have been modified at all. + ok_eq_str(String1.Buffer, "re\\act\\.s"); + ok_eq_str(String2.Buffer, "RE\\ACT\\.S"); + + + //TEST #3: String1 is EMPTY STRING. + RtlInitAnsiString(&String1, ""); + RtlInitAnsiString(&String2, "REACT\\#S"); + Length = RtlCompareString(&String1, &String2, FALSE); + ok( Length != 0, "Expected Length !=0, current Length is: %l", Length); + + //--- Originals shouldn't have been modified at all. + ok_eq_str(String1.Buffer, ""); + ok_eq_str(String2.Buffer, "REACT\\#S"); + + + //TEST #4: String2 is EMPTY STRING. + RtlInitAnsiString(&String1, "\\/REaCTO@|S"); + RtlInitAnsiString(&String2, ""); + Length = RtlCompareString(&String1, &String2, FALSE); + ok( Length != 0, "Expected Length !=0, current Length is: %l", Length); + + //--- Originals shouldn't have been modified at all. + ok_eq_str(String1.Buffer, "\\/REaCTO@|S"); + ok_eq_str(String2.Buffer, ""); + + + //TEST #5: RtlCompareString doesn't accept String1 as NULL. + RtlInitAnsiString(&String2, "../RE\\/ac.tOS"); + KmtStartSeh() + RtlCompareString(NULL, &String2, FALSE); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + //--- Originals shouldn't have been modified at all. + ok_eq_str(String2.Buffer, "../RE\\/ac.tOS"); + + + //TEST #7: RtlCompareString doesn't accept String2 as NULL. + RtlInitAnsiString(&String1, "\\n\\t((RE\\zac.tOS"); + KmtStartSeh() + RtlCompareString(&String1, NULL, FALSE); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + //--- Originals shouldn't have been modified at all. + ok_eq_str(String1.Buffer, "\\n\\t((RE\\zac.tOS"); + +} + +static +VOID +TestRtlCompareUnicodeString(VOID) +{ + + UNICODE_STRING String1; + UNICODE_STRING String2; + LONG Length; + + //TEST #1:CASING.string vs STRING. + RtlInitUnicodeString(&String1, L"react\\#s"); + RtlInitUnicodeString(&String2, L"REACT\\#S"); + Length = RtlCompareUnicodeString(&String1, &String2, TRUE); + ok_eq_long(Length, 0); + + //--- Originals shouldn't have been modified at all. + ok_eq_wstr(String1.Buffer, L"react\\#s"); + ok_eq_wstr(String2.Buffer, L"REACT\\#S"); + + //TEST #2:NON-CASING.string vs STRING. + RtlInitUnicodeString(&String1, L"re\\act\\.s"); + RtlInitUnicodeString(&String2, L"RE\\ACT\\.S"); + Length = RtlCompareUnicodeString(&String1, &String2, FALSE); + ok(Length != 0, "Expected Length !=0, current Length is: %l", Length); + + //--- Originals shouldn't have been modified at all. + ok_eq_wstr(String1.Buffer, L"re\\act\\.s"); + ok_eq_wstr(String2.Buffer, L"RE\\ACT\\.S"); + + + //TEST #3: String1 is EMPTY STRING. + RtlInitUnicodeString(&String1, L""); + RtlInitUnicodeString(&String2, L"REACT\\#S"); + Length = RtlCompareUnicodeString(&String1, &String2, FALSE); + ok(Length != 0, "Expected Length !=0, current Length is: %l", Length); + + //--- Originals shouldn't have been modified at all. + ok_eq_wstr(String1.Buffer, L""); + ok_eq_wstr(String2.Buffer, L"REACT\\#S"); + + + //TEST #4: String2 is EMPTY STRING. + RtlInitUnicodeString(&String1, L"\\REaCTO@|S"); + RtlInitUnicodeString(&String2, L""); + Length = RtlCompareUnicodeString(&String1, &String2, FALSE); + ok(Length != 0, "Expected Length !=0, current Length is: %l", Length); + + //--- Originals shouldn't have been modified at all. + ok_eq_wstr(String1.Buffer, L"\\REaCTO@|S"); + ok_eq_wstr(String2.Buffer, L""); + + + //TEST #5: RtlCompareString doesn't accept String1 as NULL. + RtlInitUnicodeString(&String2, L"../RE\\c.tOS"); + KmtStartSeh() + RtlCompareUnicodeString(NULL, &String2, FALSE); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + //--- Originals shouldn't have been modified at all. + ok_eq_wstr(String2.Buffer, L"../RE\\c.tOS"); + + + //TEST #7: RtlCompareString doesn't accept String2 as NULL. + RtlInitUnicodeString(&String1, L"\\n\\t((RE\\/ac.tOS"); + KmtStartSeh() + RtlCompareUnicodeString(&String1, NULL, FALSE); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + //--- Originals shouldn't have been modified at all. + ok_eq_wstr(String1.Buffer, L"\\n\\t((RE\\/ac.tOS"); + +} + +static +VOID +TestRtlCopyUnicodeString(VOID) +{ + UNICODE_STRING Source; + UNICODE_STRING Destination; + + //Test #1: Simple copy, NULL source string. + RtlInitUnicodeString(&Destination, L"ReactOS-Driver"); + RtlCopyUnicodeString(&Destination, NULL); + ok_eq_uint(Destination.Length, 0); + ok_eq_uint(Destination.MaximumLength, 30); + ok_eq_wstr(Destination.Buffer, L"ReactOS-Driver"); + + //Test #1: Simple copy, Length_source < MaximunLength_Destination. + RtlInitUnicodeString(&Source, L"ReactOS-Driver"); + RtlInitUnicodeString(&Destination, L"CopyPaste"); + + RtlCopyUnicodeString(&Destination, &Source); + + ok_eq_uint(Destination.Length, 20); + ok_eq_uint(Destination.MaximumLength, 20); + + ok_eq_uint(Source.Length, 28 ); + ok_eq_uint(Source.MaximumLength, 30); + ok_eq_wstr(Source.Buffer, L"ReactOS-Driver"); + + //Test #2: Simple copy, Length_source > MaximunLength_Destination. + RtlInitUnicodeString(&Source, L"Yum-YumDeadBeef"); + RtlInitUnicodeString(&Destination, L"React#S"); + + RtlCopyUnicodeString(&Destination, &Source); + + ok_eq_uint(Destination.Length, 16); + ok_eq_uint(Destination.MaximumLength, 16); + + ok_eq_uint(Source.Length, 30 ); + ok_eq_uint(Source.MaximumLength, 32); + ok_eq_wstr(Source.Buffer, L"Yum-YumDeadBeef"); + + //Test #3: Partial copy with Length_source < MaximumLength_Destination. + RtlInitUnicodeString(&Source, L"Yum-YumDeadBeef"); + RtlInitUnicodeString(&Destination, L"React#S"); + + //--Let's fake the length of the source. The source Length is smaller than destination MaximumLength, so a partial copy is done. + Source.Length = 5 * sizeof(WCHAR); + + RtlCopyUnicodeString(&Destination, &Source); + + ok_eq_uint(Destination.Length, 10); + ok_eq_uint(Destination.MaximumLength, 16); + ok_eq_wstr(Destination.Buffer, L"Yum-Y"); + + ok_eq_uint(Source.Length, 10 ); + ok_eq_uint(Source.MaximumLength, 32); + ok_eq_wstr(Source.Buffer, L"Yum-YumDeadBeef"); + + //Test #4: Out of bounds with Length_source > MaximumLength_Destination. + RtlInitUnicodeString(&Source, L"Yum"); + RtlInitUnicodeString(&Destination, L"React#S"); + + //--Let's fake the length of the source. + Source.Length = 9 * sizeof(WCHAR); + + RtlCopyUnicodeString(&Destination, &Source); + + //--As the source Length is greater than the destination MaximumLength. Just MaximumLength is copied but goes outside "Yum" bounds. + ok_eq_uint(Destination.Length, 16); + ok_eq_uint(Destination.MaximumLength, 16); + ok_eq_wstr(Destination.Buffer, L"Yum"); + + ok_eq_uint(Source.Length, 18 ); + ok_eq_uint(Source.MaximumLength, 8); + ok_eq_wstr(Source.Buffer, L"Yum"); + + //Test #5: NULL destination. + RtlInitUnicodeString(&Source, L"Yum"); + + KmtStartSeh() + RtlCopyUnicodeString(NULL, &Source); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + ok_eq_uint(Source.Length, 6 ); + ok_eq_uint(Source.MaximumLength, 8); + ok_eq_wstr(Source.Buffer, L"Yum"); + + //Test #6: Partial copy with MaximumLength_Destination < Length_Source + RtlInitUnicodeString(&Source, L"Yum-YumDead"); + RtlInitUnicodeString(&Destination, L"React#S"); + + //--Let's fake the Maximumlength. + Destination.MaximumLength = 3 * sizeof(WCHAR); + + RtlCopyUnicodeString(&Destination, &Source); + + ok_eq_uint(Destination.Length, 6); + ok_eq_uint(Destination.MaximumLength, 6); + ok_eq_wstr(Destination.Buffer, L"Yumct#S"); + + ok_eq_uint(Source.Length, 22 ); + ok_eq_uint(Source.MaximumLength, 24); + ok_eq_wstr(Source.Buffer, L"Yum-YumDead"); + +} +static +VOID +TestRtlUpcaseUnicodeString(VOID) +{ + NTSTATUS Status; + LONG Comparison; + USHORT i; + + UNICODE_STRING StringUpcased; + UNICODE_STRING StringUpcasedRef; + UNICODE_STRING StringToUpcase; + UNICODE_STRING StringZeroed; + + WCHAR Max[UNICODE_STRING_MAX_BYTES]; + WCHAR MaxRef[UNICODE_STRING_MAX_BYTES]; + WCHAR StringBuffer[10]; + + UNICODE_STRING StringToUpcase2 = RTL_CONSTANT_STRING(L"aBcde"); + UNICODE_STRING StringUpcasedRef2 = RTL_CONSTANT_STRING(L"ABCDE0"); + +// TEST#1: Allocate buffer. + + RtlInitUnicodeString(&StringToUpcase, L" rEactOS rO#ks !!\"??"); + RtlInitUnicodeString(&StringUpcasedRef, L" REACTOS RO#KS !!\"??"); + RtlInitUnicodeString(&StringUpcased, L"ILOVETOEATDEADBEEF!!!"); + + Status = RtlUpcaseUnicodeString(&StringUpcased, &StringToUpcase, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + + /*Check the API has Upcased correctly*/ + Comparison = RtlCompareUnicodeString(&StringUpcasedRef, &StringUpcased, FALSE); + ok_eq_long(Comparison, 0); + ok(StringUpcased.Length == 40, "Expected 40, StringUpcased.Length: %u \n", StringUpcased.Length); + ok(StringUpcased.MaximumLength == 40, "Expected 40, StringUpcased.MaximumLength: %u \n", StringUpcased.MaximumLength); + + /*Check the API didn't overwrite the original */ + ok_eq_wstr(StringToUpcase.Buffer, L" rEactOS rO#ks !!\"??"); + + RtlFreeUnicodeString(&StringUpcased); + +// TEST#2: Allocate UNICODE_STRING_MAX_CHARS buffer + + for (i = 0; i < UNICODE_STRING_MAX_CHARS-2; i++) + Max[i] = L'r'; + Max[UNICODE_STRING_MAX_CHARS-1] = L'\0'; + + for (i = 0; i < UNICODE_STRING_MAX_CHARS-2; i++) + MaxRef[i]= L'R'; + MaxRef[UNICODE_STRING_MAX_CHARS-1] = L'\0'; + RtlInitUnicodeString(&StringToUpcase, Max); + RtlInitUnicodeString(&StringUpcasedRef, MaxRef); + RtlInitUnicodeString(&StringUpcased, L"ILOVETOEATDEADBEEF!!!"); + + Status = RtlUpcaseUnicodeString(&StringUpcased, &StringToUpcase, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + RtlCompareUnicodeString(&StringUpcased, &StringUpcasedRef, FALSE); + ok_eq_long(StringUpcased.Length, 65532); + ok_eq_long(StringUpcasedRef.Length, 65530); + ok(StringUpcased.Length == UNICODE_STRING_MAX_BYTES-2, "Expected %u, StringUpcased.Length: %u \n", UNICODE_STRING_MAX_BYTES-2, StringUpcased.Length); + ok(StringUpcased.MaximumLength == UNICODE_STRING_MAX_BYTES-2, "Expected %u, StringUpcased.MaximumLength: %u \n", UNICODE_STRING_MAX_BYTES-2, StringUpcased.MaximumLength); + + /*Check the API didn't overwrite the original */ + ok_eq_wstr(StringToUpcase.Buffer, Max); + + RtlFreeUnicodeString(&StringUpcased); + +// TEST#3: Allocate UNICODE_STRING_MAX_CHARS + 5 buffer + + for (i = 0; i < UNICODE_STRING_MAX_CHARS + 3; i++) + Max[i] = L'r'; + Max[UNICODE_STRING_MAX_CHARS + 4] = L'\0'; + + for (i = 0; i < UNICODE_STRING_MAX_CHARS + 3; i++) + MaxRef[i]= L'R'; + MaxRef[UNICODE_STRING_MAX_CHARS + 4] = L'\0'; + RtlInitUnicodeString(&StringToUpcase, Max); + RtlInitUnicodeString(&StringUpcasedRef, MaxRef); + RtlInitUnicodeString(&StringUpcased, L"ILOVETOEATDEADBEEF!!!"); + + Status = RtlUpcaseUnicodeString(&StringUpcased, &StringToUpcase, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + Comparison = RtlCompareUnicodeString(&StringUpcased, &StringUpcasedRef, FALSE); + ok_eq_long(Comparison, 0); + ok(StringUpcased.Length == UNICODE_STRING_MAX_BYTES - 2, "Expected %u, StringUpcased.Length: %u \n", UNICODE_STRING_MAX_BYTES - 2, StringUpcased.Length); + ok(StringUpcased.MaximumLength == UNICODE_STRING_MAX_BYTES - 2, "Expected %u, StringUpcased.MaximumLength: %u \n", UNICODE_STRING_MAX_BYTES - 2, StringUpcased.MaximumLength); + + //Check the API didn't overwrite the original + ok_eq_wstr(StringToUpcase.Buffer, Max); + + RtlFreeUnicodeString(&StringUpcased); + +// TEST#4: Allocate Buffer. RtlUpcaseUnicodeString accepts an empty UNICODE_STRING as StringToUpcase argument. + + RtlInitUnicodeString(&StringToUpcase, NULL); + RtlInitUnicodeString(&StringUpcased, L"ILOVETOEATDEADBEEF!!!"); + + Status = RtlUpcaseUnicodeString(&StringUpcased, &StringToUpcase, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(StringUpcased.Length == 0, "Expected zero, StringUpcased.Length: %u \n", StringUpcased.Length); + ok(StringUpcased.MaximumLength == 0, "Expected zero, StringUpcased.MaximumLength: %u \n", StringUpcased.MaximumLength); + + RtlFreeUnicodeString(&StringUpcased); + +// TEST#5: Don't allocate Buffer. RtlUpcaseUnicodeString accepts an empty UNICODE_STRING as StringToUpcase argument. + + + RtlInitUnicodeString(&StringToUpcase, NULL); + RtlInitUnicodeString(&StringUpcased, L"ILOVETOEATDEADBEEF!!!"); + + Status = RtlUpcaseUnicodeString(&StringUpcased, &StringToUpcase, FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + ok(StringUpcased.Length == 0, "Expected zero, StringUpcased.Length: %u \n", StringUpcased.Length); + ok(StringUpcased.MaximumLength == 44, "Expected zero, StringUpcased.MaximumLength: %u \n", StringUpcased.MaximumLength); + + RtlFreeUnicodeString(&StringUpcased); + + +// TEST#6: RtlUpcaseUnicodeString doesn't accept NULL as StringToUpcase argument. + + RtlInitUnicodeString(&StringUpcased, L"ILOVETOEATDEADBEEF!!!"); + KmtStartSeh() + Status = RtlUpcaseUnicodeString(&StringUpcased, NULL, TRUE); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + RtlFreeUnicodeString(&StringUpcased); + + +// PTEST#7: Don't allocate buffer. Also RtlUpcaseUnicodeString doesnt NULL terminate the StringUpcased + RtlInitEmptyUnicodeString(&StringZeroed, StringBuffer, sizeof(StringBuffer)); + RtlAppendUnicodeToString(&StringZeroed, L"000000"); + + Status = RtlUpcaseUnicodeString(&StringZeroed, &StringToUpcase2, FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + RtlCompareUnicodeString(&StringZeroed, &StringUpcasedRef2, FALSE); + ok_eq_long(StringZeroed.Length, 10); + ok_eq_long(StringUpcasedRef2.Length, 12); + ok_eq_wstr(StringZeroed.Buffer, StringUpcasedRef2.Buffer); + + /*Check the API didn't overwrite the original */ + ok_eq_wstr(StringToUpcase2.Buffer, L"aBcde"); + +} + START_TEST(RtlUnicodeString) { TestFindCharInUnicodeString(); + TestRtlAnsiStringToUnicodeSize(); + TestRtlAnsiStringToUnicodeString(); + TestRtlCompareString(); + TestRtlCompareUnicodeString(); + TestRtlCopyUnicodeString(); + TestRtlUpcaseUnicodeString(); }