[KMTESTS:MM]
authorPierre Schweitzer <pierre@reactos.org>
Fri, 2 Jun 2017 19:19:32 +0000 (19:19 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Fri, 2 Jun 2017 19:19:32 +0000 (19:19 +0000)
Add tests for MmMapLockedPagesSpecifyCache() functions, and more specifically for usermode mapping.
This was designed/tested under W2K3.

CORE-8204

svn path=/trunk/; revision=74751

rostests/kmtests/CMakeLists.txt
rostests/kmtests/kmtest/testlist.c
rostests/kmtests/ntos_mm/CMakeLists.txt
rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h [new file with mode: 0644]
rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c [new file with mode: 0644]
rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c [new file with mode: 0644]

index 6291fcd..1db3ccc 100644 (file)
@@ -128,6 +128,7 @@ list(APPEND KMTEST_SOURCE
     ntos_io/IoCreateFile_user.c
     ntos_io/IoDeviceObject_user.c
     ntos_io/IoReadWrite_user.c
+    ntos_mm/MmMapLockedPagesSpecifyCache_user.c
     ntos_mm/NtCreateSection_user.c
     ntos_po/PoIrp_user.c
     tcpip/TcpIp_user.c
@@ -157,6 +158,7 @@ add_dependencies(kmtest_drivers
     iodeviceobject_drv
     iohelper_drv
     ioreadwrite_drv
+    mmmaplockedpagesspecifycache_drv
     ntcreatesection_drv
     poirp_drv
     tcpip_drv
index 74e525c..4d8ba68 100644 (file)
@@ -13,6 +13,7 @@ KMT_TESTFUNC Test_FindFile;
 KMT_TESTFUNC Test_IoCreateFile;
 KMT_TESTFUNC Test_IoDeviceObject;
 KMT_TESTFUNC Test_IoReadWrite;
+KMT_TESTFUNC Test_MmMapLockedPagesSpecifyCache;
 KMT_TESTFUNC Test_NtCreateSection;
 KMT_TESTFUNC Test_PoIrp;
 KMT_TESTFUNC Test_RtlAvlTree;
@@ -30,23 +31,24 @@ KMT_TESTFUNC Test_TcpIpConnect;
 /* tests with a leading '-' will not be listed */
 const KMT_TEST TestList[] =
 {
-    { "CcCopyRead",         Test_CcCopyRead },
-    { "-Example",           Test_Example },
-    { "FindFile",           Test_FindFile },
-    { "IoCreateFile",       Test_IoCreateFile },
-    { "IoDeviceObject",     Test_IoDeviceObject },
-    { "IoReadWrite",        Test_IoReadWrite },
-    { "NtCreateSection",    Test_NtCreateSection },
-    { "PoIrp",              Test_PoIrp },
-    { "RtlAvlTree",         Test_RtlAvlTree },
-    { "RtlException",       Test_RtlException },
-    { "RtlIntSafe",         Test_RtlIntSafe },
-    { "RtlMemory",          Test_RtlMemory },
-    { "RtlRegistry",        Test_RtlRegistry },
-    { "RtlSplayTree",       Test_RtlSplayTree },
-    { "RtlStack",           Test_RtlStack },
-    { "RtlUnicodeString",   Test_RtlUnicodeString },
-    { "TcpIpTdi",           Test_TcpIpTdi },
-    { "TcpIpConnect",       Test_TcpIpConnect },
-    { NULL,                 NULL },
+    { "CcCopyRead",                   Test_CcCopyRead },
+    { "-Example",                     Test_Example },
+    { "FindFile",                     Test_FindFile },
+    { "IoCreateFile",                 Test_IoCreateFile },
+    { "IoDeviceObject",               Test_IoDeviceObject },
+    { "IoReadWrite",                  Test_IoReadWrite },
+    { "MmMapLockedPagesSpecifyCache", Test_MmMapLockedPagesSpecifyCache },
+    { "NtCreateSection",              Test_NtCreateSection },
+    { "PoIrp",                        Test_PoIrp },
+    { "RtlAvlTree",                   Test_RtlAvlTree },
+    { "RtlException",                 Test_RtlException },
+    { "RtlIntSafe",                   Test_RtlIntSafe },
+    { "RtlMemory",                    Test_RtlMemory },
+    { "RtlRegistry",                  Test_RtlRegistry },
+    { "RtlSplayTree",                 Test_RtlSplayTree },
+    { "RtlStack",                     Test_RtlStack },
+    { "RtlUnicodeString",             Test_RtlUnicodeString },
+    { "TcpIpTdi",                     Test_TcpIpTdi },
+    { "TcpIpConnect",                 Test_TcpIpConnect },
+    { NULL,                           NULL },
 };
index b0356e6..f83bdee 100644 (file)
@@ -15,3 +15,18 @@ add_importlibs(ntcreatesection_drv ntoskrnl hal)
 add_target_compile_definitions(ntcreatesection_drv KMT_STANDALONE_DRIVER)
 #add_pch(ntcreatesection_drv ../include/kmt_test.h)
 add_rostests_file(TARGET ntcreatesection_drv)
+
+#
+# MmMapLockedPagesSpecifyCache
+#
+list(APPEND MMMAPLOCKEDPAGESSPECIFYCACHE_DRV_SOURCE
+    ../kmtest_drv/kmtest_standalone.c
+    MmMapLockedPagesSpecifyCache_drv.c)
+
+add_library(mmmaplockedpagesspecifycache_drv SHARED ${MMMAPLOCKEDPAGESSPECIFYCACHE_DRV_SOURCE})
+set_module_type(mmmaplockedpagesspecifycache_drv kernelmodedriver)
+target_link_libraries(mmmaplockedpagesspecifycache_drv kmtest_printf ${PSEH_LIB})
+add_importlibs(mmmaplockedpagesspecifycache_drv ntoskrnl hal)
+add_target_compile_definitions(mmmaplockedpagesspecifycache_drv KMT_STANDALONE_DRIVER)
+#add_pch(mmmaplockedpagesspecifycache_drv ../include/kmt_test.h)
+add_rostests_file(TARGET mmmaplockedpagesspecifycache_drv)
diff --git a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h
new file mode 100644 (file)
index 0000000..195703f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * PROJECT:         ReactOS kernel-mode tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Kernel-Mode Test Suite MmMapLockedPagesSpecifyCache test declarations
+ * PROGRAMMER:      Pierre Schweitzer <pierre@reactos.org>
+ */
+
+#ifndef _KMTEST_MMMAPLOCKEDPAGESSPECIFYCACHE_H_
+#define _KMTEST_MMMAPLOCKEDPAGESSPECIFYCACHE_H_
+
+typedef struct _QUERY_BUFFER
+{
+    USHORT Length;
+    PVOID Buffer;
+    BOOLEAN Cached;
+} QUERY_BUFFER, *PQUERY_BUFFER;
+
+typedef struct _READ_BUFFER
+{
+    USHORT Length;
+    PVOID Buffer;
+    USHORT Pattern;
+} READ_BUFFER, *PREAD_BUFFER;
+
+#define IOCTL_QUERY_BUFFER 1
+#define IOCTL_READ_BUFFER  2
+
+#endif /* !defined _KMTEST_MMMAPLOCKEDPAGESSPECIFYCACHE_H_ */
diff --git a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c
new file mode 100644 (file)
index 0000000..69c387d
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * PROJECT:         ReactOS kernel-mode tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Test driver for MmMapLockedPagesSpecifyCache function
+ * PROGRAMMER:      Pierre Schweitzer <pierre@reactos.org>
+ */
+
+#include <kmt_test.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#include "MmMapLockedPagesSpecifyCache.h"
+
+static KMT_IRP_HANDLER TestIrpHandler;
+static KMT_MESSAGE_HANDLER TestMessageHandler;
+
+static PVOID CurrentBuffer;
+static PMDL CurrentMdl;
+static PVOID CurrentUser;
+
+NTSTATUS
+TestEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PCUNICODE_STRING RegistryPath,
+    OUT PCWSTR *DeviceName,
+    IN OUT INT *Flags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    PAGED_CODE();
+
+    UNREFERENCED_PARAMETER(RegistryPath);
+    UNREFERENCED_PARAMETER(Flags);
+
+    *DeviceName = L"MmMapLockedPagesSpecifyCache";
+
+    KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
+    KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
+
+    return Status;
+}
+
+VOID
+TestUnload(
+    IN PDRIVER_OBJECT DriverObject)
+{
+    PAGED_CODE();
+}
+
+VOID
+TestCleanEverything(VOID)
+{
+    NTSTATUS SehStatus;
+
+    if (CurrentMdl == NULL)
+    {
+        return;
+    }
+
+    if (CurrentUser != NULL)
+    {
+        SehStatus = STATUS_SUCCESS;
+        _SEH2_TRY
+        {
+            MmUnmapLockedPages(CurrentUser, CurrentMdl);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            SehStatus = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+        ok_eq_hex(SehStatus, STATUS_SUCCESS);
+        CurrentUser = NULL;
+    }
+
+    SehStatus = STATUS_SUCCESS;
+    _SEH2_TRY
+    {
+        MmUnlockPages(CurrentMdl);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SehStatus = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+    ok_eq_hex(SehStatus, STATUS_SUCCESS);
+    IoFreeMdl(CurrentMdl);
+    ExFreePoolWithTag(CurrentBuffer, 'MLPC');
+    CurrentMdl = NULL;
+}
+
+static
+NTSTATUS
+TestMessageHandler(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN ULONG ControlCode,
+    IN PVOID Buffer OPTIONAL,
+    IN SIZE_T InLength,
+    IN OUT PSIZE_T OutLength)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS SehStatus;
+
+    switch (ControlCode)
+    {
+        case IOCTL_QUERY_BUFFER:
+        {
+            ok(Buffer != NULL, "Buffer is NULL\n");
+            ok_eq_size(InLength, sizeof(QUERY_BUFFER));
+            ok_eq_size(*OutLength, sizeof(QUERY_BUFFER));
+            ok_eq_pointer(CurrentMdl, NULL);
+            ok(ExGetPreviousMode() == UserMode, "Not comming from umode!\n");
+            if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER) && *OutLength >= sizeof(QUERY_BUFFER), "Cannot read/write from/to buffer!\n"))
+            {
+                PQUERY_BUFFER QueryBuffer;
+                USHORT Length;
+                MEMORY_CACHING_TYPE CacheType;
+
+                QueryBuffer = Buffer;
+                CacheType = (QueryBuffer->Cached ? MmCached : MmNonCached);
+                Length = QueryBuffer->Length;
+                ok(Length > 0, "Null size!\n");
+
+                CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, Length + 0x8, 'MLPC');
+                ok(CurrentBuffer != NULL, "ExAllocatePool failed!\n");
+                CurrentUser = NULL;
+                if (!skip(CurrentBuffer != NULL, "ExAllocatePool failed!\n"))
+                {
+                    CurrentMdl = IoAllocateMdl(CurrentBuffer, Length, FALSE, FALSE, NULL);
+                    ok(CurrentMdl != NULL, "IoAllocateMdl failed!\n");
+                    if (CurrentMdl)
+                    {
+                        KIRQL Irql;
+
+                        SehStatus = STATUS_SUCCESS;
+                        _SEH2_TRY
+                        {
+                            MmProbeAndLockPages(CurrentMdl, KernelMode, IoWriteAccess);
+                        }
+                        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                        {
+                            SehStatus = _SEH2_GetExceptionCode();
+                        }
+                        _SEH2_END;
+                        ok_eq_hex(SehStatus, STATUS_SUCCESS);
+
+                        Irql = KeGetCurrentIrql();
+                        ok(Irql <= APC_LEVEL, "IRQL > APC_LEVEL: %d\n", Irql);
+
+                        SehStatus = STATUS_SUCCESS;
+                        _SEH2_TRY
+                        {
+                            CurrentUser = MmMapLockedPagesSpecifyCache(CurrentMdl, UserMode, CacheType, NULL, FALSE, NormalPagePriority);
+                        }
+                        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                        {
+                            SehStatus = _SEH2_GetExceptionCode();
+                        }
+                        _SEH2_END;
+
+                        if (QueryBuffer->Cached)
+                        {
+                            ok_eq_hex(SehStatus, STATUS_SUCCESS);
+                            ok(CurrentUser != NULL, "MmMapLockedPagesSpecifyCache failed!\n");
+                        }
+                        else
+                        {
+                            ok_eq_hex(SehStatus, STATUS_INVALID_ADDRESS);
+                            ok_eq_pointer(CurrentUser, NULL);
+                        }
+                    }
+                }
+                QueryBuffer->Buffer = CurrentUser;
+
+                *OutLength = sizeof(QUERY_BUFFER);
+            }
+
+            break;
+        }
+        case IOCTL_READ_BUFFER:
+        {
+            ok(Buffer != NULL, "Buffer is NULL\n");
+            ok_eq_size(InLength, sizeof(READ_BUFFER));
+            ok_eq_size(*OutLength, 0);
+            ok(CurrentMdl != NULL, "MDL is not in use!\n");
+
+            if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER), "Cannot read from buffer!\n"))
+            {
+                PREAD_BUFFER ReadBuffer;
+
+                ReadBuffer = Buffer;
+                if (!skip(ReadBuffer && ReadBuffer->Buffer == CurrentUser, "Cannot find matching MDL\n"))
+                {
+                    if (ReadBuffer->Buffer != NULL)
+                    {
+                        USHORT i;
+                        PUSHORT KBuffer = MmGetSystemAddressForMdlSafe(CurrentMdl, NormalPagePriority);
+                        ok(KBuffer != NULL, "Failed to get kmode ptr\n");
+
+                        if (!skip(Buffer != NULL, "Failed to get kmode ptr\n"))
+                        {
+                            for (i = 0; i < ReadBuffer->Length / sizeof(USHORT); ++i)
+                            {
+                                ok_eq_ulong((ULONG)KBuffer[i], (ULONG)ReadBuffer->Pattern);
+                            }
+                        }
+                    }
+                }
+
+                TestCleanEverything();
+            }
+
+            break;
+        }
+        default:
+            ok(0, "Got an unknown message! DeviceObject=%p, ControlCode=%lu, Buffer=%p, In=%lu, Out=%lu bytes\n",
+                    DeviceObject, ControlCode, Buffer, InLength, *OutLength);
+            break;
+    }
+
+    return Status;
+}
+
+static
+NTSTATUS
+TestIrpHandler(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp,
+    _In_ PIO_STACK_LOCATION IoStack)
+{
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
+    ASSERT(IoStack->MajorFunction == IRP_MJ_CLEANUP);
+
+    Status = STATUS_NOT_SUPPORTED;
+    Irp->IoStatus.Information = 0;
+
+    if (IoStack->MajorFunction == IRP_MJ_CLEANUP)
+    {
+        TestCleanEverything();
+        Status = STATUS_SUCCESS;
+    }
+
+    if (Status == STATUS_PENDING)
+    {
+        IoMarkIrpPending(Irp);
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        Status = STATUS_PENDING;
+    }
+    else
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+
+    return Status;
+}
diff --git a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c
new file mode 100644 (file)
index 0000000..d67e8e4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * PROJECT:         ReactOS kernel-mode tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Kernel-Mode Test Suite MmMapLockedPagesSpecifyCache test user-mode part
+ * PROGRAMMER:      Pierre Schweitzer <pierre@reactos.org>
+ */
+
+#include <kmt_test.h>
+
+#include "MmMapLockedPagesSpecifyCache.h"
+
+START_TEST(MmMapLockedPagesSpecifyCache)
+{
+    QUERY_BUFFER QueryBuffer;
+    READ_BUFFER ReadBuffer;
+    DWORD Length;
+    USHORT i;
+    PUSHORT Buffer;
+
+    KmtLoadDriver(L"MmMapLockedPagesSpecifyCache", FALSE);
+    KmtOpenDriver();
+
+    QueryBuffer.Length = 0x100;
+    QueryBuffer.Buffer = NULL;
+    QueryBuffer.Cached = FALSE;
+    Length = sizeof(QUERY_BUFFER);
+    ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+    ok_eq_int(QueryBuffer.Length, 0x100);
+    ok_eq_pointer(QueryBuffer.Buffer, NULL);
+
+    ReadBuffer.Buffer = QueryBuffer.Buffer;
+    Length = 0;
+    ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+
+    QueryBuffer.Length = 0x100;
+    QueryBuffer.Buffer = NULL;
+    QueryBuffer.Cached = TRUE;
+    Length = sizeof(QUERY_BUFFER);
+    ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+    ok_eq_int(QueryBuffer.Length, 0x100);
+    ok(QueryBuffer.Buffer != NULL, "Buffer is NULL\n");
+
+    ReadBuffer.Buffer = QueryBuffer.Buffer;
+    if (!skip(QueryBuffer.Buffer != NULL, "Buffer is NULL\n"))
+    {
+        ReadBuffer.Pattern = 0xA7;
+        ReadBuffer.Length = QueryBuffer.Length;
+        Buffer = QueryBuffer.Buffer;
+        for (i = 0; i < ReadBuffer.Length / sizeof(USHORT); ++i)
+        {
+            Buffer[i] = ReadBuffer.Pattern;
+        }
+    }
+
+    Length = 0;
+    ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+
+    KmtCloseDriver();
+    KmtUnloadDriver();
+}