[NTDLL_APITEST]
authorThomas Faber <thomas.faber@reactos.org>
Sat, 29 Oct 2016 20:14:16 +0000 (20:14 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sat, 29 Oct 2016 20:14:16 +0000 (20:14 +0000)
- Add a test for NtReadFile, also covering buffer size too large for an MDL
CORE-12132

svn path=/trunk/; revision=73071

rostests/apitests/ntdll/CMakeLists.txt
rostests/apitests/ntdll/NtReadFile.c [new file with mode: 0644]
rostests/apitests/ntdll/testlist.c

index 2cddf33..4eab1e6 100644 (file)
@@ -18,6 +18,7 @@ list(APPEND SOURCE
     NtQueryKey.c
     NtQuerySystemEnvironmentValue.c
     NtQueryVolumeInformationFile.c
     NtQueryKey.c
     NtQuerySystemEnvironmentValue.c
     NtQueryVolumeInformationFile.c
+    NtReadFile.c
     NtSaveKey.c
     NtSetValueKey.c
     NtWriteFile.c
     NtSaveKey.c
     NtSetValueKey.c
     NtWriteFile.c
diff --git a/rostests/apitests/ntdll/NtReadFile.c b/rostests/apitests/ntdll/NtReadFile.c
new file mode 100644 (file)
index 0000000..0d6ceae
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * PROJECT:         ReactOS API tests
+ * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
+ * PURPOSE:         Test for NtReadFile
+ * 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(NtReadFile)
+{
+    NTSTATUS Status;
+    HANDLE FileHandle;
+    UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\ntdll-apitest-NtReadFile-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_READWRITE);
+    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_READ_DATA | 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);
+
+    ByteOffset.QuadPart = 0x10000;
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatus,
+                         Buffer,
+                         BufferSize - 0x10000,
+                         &ByteOffset,
+                         NULL);
+    ok_hex(Status, STATUS_SUCCESS);
+    ByteOffset.QuadPart = 0;
+
+    /* non-cached, max size -- succeeds */
+    Status = NtReadFile(FileHandle,
+                        NULL,
+                        NULL,
+                        NULL,
+                        &IoStatus,
+                        Buffer,
+                        LargeMdlMaxDataSize - PAGE_SIZE,
+                        &ByteOffset,
+                        NULL);
+    ok_hex(Status, STATUS_SUCCESS);
+
+    /* non-cached, max size -- succeeds */
+    Status = NtReadFile(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 = NtReadFile(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 = NtReadFile(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_READ_DATA | 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);
+
+    ByteOffset.QuadPart = 0x10000;
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatus,
+                         Buffer,
+                         BufferSize - 0x10000,
+                         &ByteOffset,
+                         NULL);
+    ok_hex(Status, STATUS_SUCCESS);
+    ByteOffset.QuadPart = 0;
+
+    /* cached: succeeds with arbitrary length */
+    Status = NtReadFile(FileHandle,
+                        NULL,
+                        NULL,
+                        NULL,
+                        &IoStatus,
+                        Buffer,
+                        LargeMdlMaxDataSize,
+                        &ByteOffset,
+                        NULL);
+    ok_hex(Status, STATUS_SUCCESS);
+
+    Status = NtReadFile(FileHandle,
+                        NULL,
+                        NULL,
+                        NULL,
+                        &IoStatus,
+                        Buffer,
+                        LargeMdlMaxDataSize + 1,
+                        &ByteOffset,
+                        NULL);
+    ok_hex(Status, STATUS_SUCCESS);
+
+    Status = NtReadFile(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 895335c..9a5f955 100644 (file)
@@ -21,6 +21,7 @@ extern void func_NtQueryInformationProcess(void);
 extern void func_NtQueryKey(void);
 extern void func_NtQuerySystemEnvironmentValue(void);
 extern void func_NtQueryVolumeInformationFile(void);
 extern void func_NtQueryKey(void);
 extern void func_NtQuerySystemEnvironmentValue(void);
 extern void func_NtQueryVolumeInformationFile(void);
+extern void func_NtReadFile(void);
 extern void func_NtSaveKey(void);
 extern void func_NtSetValueKey(void);
 extern void func_NtSystemInformation(void);
 extern void func_NtSaveKey(void);
 extern void func_NtSetValueKey(void);
 extern void func_NtSystemInformation(void);
@@ -68,6 +69,7 @@ const struct test winetest_testlist[] =
     { "NtQueryKey",                     func_NtQueryKey },
     { "NtQuerySystemEnvironmentValue",  func_NtQuerySystemEnvironmentValue },
     { "NtQueryVolumeInformationFile",   func_NtQueryVolumeInformationFile },
     { "NtQueryKey",                     func_NtQueryKey },
     { "NtQuerySystemEnvironmentValue",  func_NtQuerySystemEnvironmentValue },
     { "NtQueryVolumeInformationFile",   func_NtQueryVolumeInformationFile },
+    { "NtReadFile",                     func_NtReadFile },
     { "NtSaveKey",                      func_NtSaveKey},
     { "NtSetValueKey",                  func_NtSetValueKey},
     { "NtSystemInformation",            func_NtSystemInformation },
     { "NtSaveKey",                      func_NtSaveKey},
     { "NtSetValueKey",                  func_NtSetValueKey},
     { "NtSystemInformation",            func_NtSystemInformation },