[NTDLL_APITEST]
authorThomas Faber <thomas.faber@reactos.org>
Sat, 29 Oct 2016 11:39:07 +0000 (11:39 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sat, 29 Oct 2016 11:39:07 +0000 (11:39 +0000)
- 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
rostests/apitests/ntdll/NtWriteFile.c [new file with mode: 0644]
rostests/apitests/ntdll/testlist.c

index 9f2498d..2cddf33 100644 (file)
@@ -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 (file)
index 0000000..c6f13c7
--- /dev/null
@@ -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 <thomas.faber@reactos.org>
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <winreg.h>
+#include <ndk/cmfuncs.h>
+#include <ndk/iofuncs.h>
+#include <ndk/mmfuncs.h>
+#include <ndk/obfuncs.h>
+#include <ndk/psfuncs.h>
+#include <ndk/rtlfuncs.h>
+
+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);
+}
index a3e17a6..895335c 100644 (file)
@@ -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 },