From 8d77737ce9f480da6e6422f7c6c7b994b7afacbb Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sat, 29 Oct 2016 11:39:07 +0000 Subject: [PATCH] [NTDLL_APITEST] - Add tests for NtWriteFile with buffer sizes larger than an MDL can describe. CORE-12132 svn path=/trunk/; revision=73059 --- rostests/apitests/ntdll/CMakeLists.txt | 1 + rostests/apitests/ntdll/NtWriteFile.c | 223 +++++++++++++++++++++++++ rostests/apitests/ntdll/testlist.c | 2 + 3 files changed, 226 insertions(+) create mode 100644 rostests/apitests/ntdll/NtWriteFile.c diff --git a/rostests/apitests/ntdll/CMakeLists.txt b/rostests/apitests/ntdll/CMakeLists.txt index 9f2498dfc2d..2cddf33ac91 100644 --- a/rostests/apitests/ntdll/CMakeLists.txt +++ b/rostests/apitests/ntdll/CMakeLists.txt @@ -20,6 +20,7 @@ list(APPEND SOURCE NtQueryVolumeInformationFile.c NtSaveKey.c NtSetValueKey.c + NtWriteFile.c RtlAllocateHeap.c RtlBitmap.c RtlCopyMappedMemory.c diff --git a/rostests/apitests/ntdll/NtWriteFile.c b/rostests/apitests/ntdll/NtWriteFile.c new file mode 100644 index 00000000000..c6f13c7b39a --- /dev/null +++ b/rostests/apitests/ntdll/NtWriteFile.c @@ -0,0 +1,223 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test for NtWriteFile + * PROGRAMMER: Thomas Faber + */ + +#include + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include +#include +#include + +static +BOOL +Is64BitSystem(VOID) +{ +#ifdef _WIN64 + return TRUE; +#else + NTSTATUS Status; + ULONG_PTR IsWow64; + + Status = NtQueryInformationProcess(NtCurrentProcess(), + ProcessWow64Information, + &IsWow64, + sizeof(IsWow64), + NULL); + if (NT_SUCCESS(Status)) + { + return IsWow64 != 0; + } + + return FALSE; +#endif +} + +static +ULONG +SizeOfMdl(VOID) +{ + return Is64BitSystem() ? 48 : 28; +} + +START_TEST(NtWriteFile) +{ + NTSTATUS Status; + HANDLE FileHandle; + UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\ntdll-apitest-NtWriteFile-test.bin"); + PVOID Buffer; + SIZE_T BufferSize; + LARGE_INTEGER ByteOffset; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatus; + FILE_DISPOSITION_INFORMATION DispositionInfo; + ULONG TooLargeDataSize = (MAXUSHORT + 1 - SizeOfMdl()) / sizeof(ULONG_PTR) * PAGE_SIZE; // 0x3FF9000 on x86 + ULONG LargeMdlMaxDataSize = TooLargeDataSize - PAGE_SIZE; + + trace("System is %d bits, Size of MDL: %lu\n", Is64BitSystem() ? 64 : 32, SizeOfMdl()); + trace("Max MDL data size: 0x%lx bytes\n", LargeMdlMaxDataSize); + + ByteOffset.QuadPart = 0; + + Buffer = NULL; + BufferSize = TooLargeDataSize; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &Buffer, + 0, + &BufferSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READONLY); + if (!NT_SUCCESS(Status)) + { + skip("Failed to allocate memory, status %lx\n", Status); + return; + } + + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtCreateFile(&FileHandle, + FILE_WRITE_DATA | DELETE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatus, + NULL, + 0, + 0, + FILE_SUPERSEDE, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | + FILE_NO_INTERMEDIATE_BUFFERING, + NULL, + 0); + ok_hex(Status, STATUS_SUCCESS); + + /* non-cached, max size -- succeeds */ + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + LargeMdlMaxDataSize - PAGE_SIZE, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + /* non-cached, max size -- succeeds */ + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + LargeMdlMaxDataSize, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + /* non-cached, too large -- fails to allocate MDL + * Note: this returns STATUS_SUCCESS on Win7 -- higher MDL size limit */ + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + LargeMdlMaxDataSize + PAGE_SIZE, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_INSUFFICIENT_RESOURCES); + + /* non-cached, unaligned -- fails with invalid parameter */ + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + LargeMdlMaxDataSize + 1, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_INVALID_PARAMETER); + + DispositionInfo.DeleteFile = TRUE; + Status = NtSetInformationFile(FileHandle, + &IoStatus, + &DispositionInfo, + sizeof(DispositionInfo), + FileDispositionInformation); + ok_hex(Status, STATUS_SUCCESS); + Status = NtClose(FileHandle); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtCreateFile(&FileHandle, + FILE_WRITE_DATA | DELETE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatus, + NULL, + 0, + 0, + FILE_SUPERSEDE, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + ok_hex(Status, STATUS_SUCCESS); + + /* cached: succeeds with arbitrary length */ + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + LargeMdlMaxDataSize, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + LargeMdlMaxDataSize + 1, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + Buffer, + TooLargeDataSize, + &ByteOffset, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + DispositionInfo.DeleteFile = TRUE; + Status = NtSetInformationFile(FileHandle, + &IoStatus, + &DispositionInfo, + sizeof(DispositionInfo), + FileDispositionInformation); + ok_hex(Status, STATUS_SUCCESS); + Status = NtClose(FileHandle); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtFreeVirtualMemory(NtCurrentProcess(), + &Buffer, + &BufferSize, + MEM_RELEASE); + ok_hex(Status, STATUS_SUCCESS); +} diff --git a/rostests/apitests/ntdll/testlist.c b/rostests/apitests/ntdll/testlist.c index a3e17a6fa3e..895335c946d 100644 --- a/rostests/apitests/ntdll/testlist.c +++ b/rostests/apitests/ntdll/testlist.c @@ -24,6 +24,7 @@ extern void func_NtQueryVolumeInformationFile(void); extern void func_NtSaveKey(void); extern void func_NtSetValueKey(void); extern void func_NtSystemInformation(void); +extern void func_NtWriteFile(void); extern void func_RtlAllocateHeap(void); extern void func_RtlBitmap(void); extern void func_RtlCopyMappedMemory(void); @@ -70,6 +71,7 @@ const struct test winetest_testlist[] = { "NtSaveKey", func_NtSaveKey}, { "NtSetValueKey", func_NtSetValueKey}, { "NtSystemInformation", func_NtSystemInformation }, + { "NtWriteFile", func_NtWriteFile }, { "RtlAllocateHeap", func_RtlAllocateHeap }, { "RtlBitmapApi", func_RtlBitmap }, { "RtlCopyMappedMemory", func_RtlCopyMappedMemory }, -- 2.17.1