[KMTESTS:IO]
authorThomas Faber <thomas.faber@reactos.org>
Fri, 1 May 2015 12:50:12 +0000 (12:50 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Fri, 1 May 2015 12:50:12 +0000 (12:50 +0000)
- Also test write operations in IoReadWrite
- Add some nonzero success statuses
CORE-9624

svn path=/trunk/; revision=67493

rostests/kmtests/ntos_io/IoReadWrite.h
rostests/kmtests/ntos_io/IoReadWrite_drv.c
rostests/kmtests/ntos_io/IoReadWrite_user.c

index 28001c7..a306c85 100644 (file)
 #define TEST_FILE_SIZE 17
 
 #define KEY_SUCCEED                 0x00
+#define KEY_SUCCESS_WAIT1           0x01
+
+#define KEY_INFO_EXISTS             0x41
+
 #define KEY_FAIL_MISALIGNED         0x81
 #define KEY_FAIL_OVERFLOW           0x82
 #define KEY_FAIL_PARTIAL            0x83
@@ -28,7 +32,8 @@
 
 #define KEY_NEXT(key) ( (key) == KEY_FAIL_MISALIGNED_ERROR ? 0xff :                 \
                         (key) == KEY_FAIL_VERIFY_REQUIRED ? KEY_FAIL_UNSUCCESSFUL : \
-                        (key) == KEY_SUCCEED ? KEY_FAIL_MISALIGNED :                \
+                        (key) == KEY_INFO_EXISTS ? KEY_FAIL_MISALIGNED :            \
+                        (key) == KEY_SUCCESS_WAIT1 ? KEY_INFO_EXISTS :              \
                         (key) + 1 )
 #define KEY_ERROR(key) (((key) & 0xc0) == 0xc0)
 static
@@ -40,6 +45,11 @@ TestGetReturnStatus(
     {
         case KEY_SUCCEED:
             return STATUS_SUCCESS;
+        case KEY_SUCCESS_WAIT1:
+            return STATUS_WAIT_1;
+
+        case KEY_INFO_EXISTS:
+            return STATUS_OBJECT_NAME_EXISTS;
 
         case KEY_FAIL_MISALIGNED:
             return STATUS_DATATYPE_MISALIGNMENT;
index 0c03068..89bdf91 100644 (file)
@@ -43,7 +43,9 @@ TestEntry(
     UNREFERENCED_PARAMETER(RegistryPath);
 
     *DeviceName = L"IoReadWrite";
-    *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE | TESTENTRY_BUFFERED_IO_DEVICE;
+    *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE |
+             TESTENTRY_BUFFERED_IO_DEVICE |
+             TESTENTRY_NO_READONLY_DEVICE;
 
     TestFastIoDispatch.FastIoRead = TestFastIoRead;
     TestFastIoDispatch.FastIoWrite = TestFastIoWrite;
@@ -52,7 +54,7 @@ TestEntry(
     KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler);
     KmtRegisterIrpHandler(IRP_MJ_CLEANUP, NULL, TestIrpHandler);
     KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
-    //KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
+    KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
 
     return Status;
 }
@@ -187,6 +189,28 @@ TestFastIoRead(
         return FALSE;
 }
 
+static
+NTSTATUS
+TestCommonWrite(
+    _In_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ LONGLONG FileOffset,
+    _In_ ULONG LockKey,
+    _Out_ PIO_STATUS_BLOCK IoStatus)
+{
+    ULONG i;
+    PUCHAR BufferBytes = Buffer;
+
+    for (i = 0; i < Length; i++)
+        ok(BufferBytes[i] == KEY_GET_DATA(LockKey), "Buffer[%lu] = 0x%x, expected 0x%x\n", i, BufferBytes[i], KEY_GET_DATA(LockKey));
+    IoStatus->Status = TestGetReturnStatus(LockKey);
+    IoStatus->Information = Length;
+
+    if (LockKey & KEY_RETURN_PENDING)
+        return STATUS_PENDING;
+    return IoStatus->Status;
+}
+
 static
 BOOLEAN
 NTAPI
@@ -200,9 +224,38 @@ TestFastIoWrite(
     _Out_ PIO_STATUS_BLOCK IoStatus,
     _In_ PDEVICE_OBJECT DeviceObject)
 {
+    PTEST_FCB Fcb;
+    NTSTATUS Status;
+
+    //trace("FastIoWrite: %p %lx %p -> %I64d+%lu\n", FileObject, LockKey, Buffer, FileOffset->QuadPart, Length);
+    ok_eq_pointer(FileObject, TestFileObject);
+    ok_bool_true(Wait, "Wait is");
+    ok_eq_pointer(DeviceObject, TestDeviceObject);
+    Fcb = FileObject->FsContext;
+    ok_bool_true(Fcb->Cached, "Cached is");
+
     TestLastFastWriteKey = LockKey;
-    UNIMPLEMENTED;
-    return FALSE;
+    ok((ULONG_PTR)Buffer < MM_USER_PROBE_ADDRESS, "Buffer is %p\n", Buffer);
+    ok((ULONG_PTR)FileOffset > MM_USER_PROBE_ADDRESS, "FileOffset is %p\n", FileOffset);
+    ok((ULONG_PTR)IoStatus > MM_USER_PROBE_ADDRESS, "IoStatus is %p\n", IoStatus);
+    _SEH2_TRY
+    {
+        Status = TestCommonWrite(Buffer, Length, FileOffset->QuadPart, LockKey, IoStatus);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        IoStatus->Status = _SEH2_GetExceptionCode();
+        return FALSE;
+    }
+    _SEH2_END;
+
+    if (Status == STATUS_PENDING)
+        return FALSE;
+
+    if (LockKey & KEY_USE_FASTIO)
+        return TRUE;
+    else
+        return FALSE;
 }
 
 static
@@ -291,10 +344,21 @@ TestIrpHandler(
     }
     else if (IoStack->MajorFunction == IRP_MJ_WRITE)
     {
+        //trace("IRP_MJ_WRITE: %p %lx %I64d+%lu -> %p\n", IoStack->FileObject, IoStack->Parameters.Write.Key, IoStack->Parameters.Write.ByteOffset.QuadPart, IoStack->Parameters.Write.Length, Irp->AssociatedIrp.SystemBuffer);
         ok_eq_pointer(DeviceObject, TestDeviceObject);
         ok_eq_pointer(IoStack->FileObject, TestFileObject);
-        UNIMPLEMENTED;
-        Status = STATUS_NOT_IMPLEMENTED;
+        Fcb = IoStack->FileObject->FsContext;
+        if (Fcb->Cached)
+            ok_eq_hex(IoStack->Parameters.Write.Key, TestLastFastWriteKey);
+        ok(Irp->AssociatedIrp.SystemBuffer == NULL ||
+           (ULONG_PTR)Irp->AssociatedIrp.SystemBuffer > MM_USER_PROBE_ADDRESS,
+           "Buffer is %p\n",
+           Irp->AssociatedIrp.SystemBuffer);
+        Status = TestCommonWrite(Irp->AssociatedIrp.SystemBuffer,
+                                 IoStack->Parameters.Write.Length,
+                                 IoStack->Parameters.Write.ByteOffset.QuadPart,
+                                 IoStack->Parameters.Write.Key,
+                                 &Irp->IoStatus);
     }
 
     if (Status == STATUS_PENDING)
index 429dbc2..e04119b 100644 (file)
@@ -32,7 +32,7 @@ TestRead(
 
     for (StatusKey = KEY_SUCCEED ; StatusKey != 0xff; StatusKey = KEY_NEXT(StatusKey))
     {
-        trace("\tSTATUS KEY: %lx\n", StatusKey);
+        //trace("\tSTATUS KEY: %lx\n", StatusKey);
         ResetEvent(EventHandle);
         RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
         Key = BaseKey | StatusKey | KEY_DATA(0x11);
@@ -162,6 +162,140 @@ TestRead(
     }
 }
 
+static
+VOID
+TestWrite(
+    _In_ HANDLE FileHandle,
+    _In_ BOOLEAN Cached,
+    _In_ BOOLEAN UseFastIo,
+    _In_ BOOLEAN ReturnPending)
+{
+    NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatus;
+    HANDLE EventHandle;
+    UCHAR Buffer[32];
+    LARGE_INTEGER Offset;
+    ULONG BaseKey, StatusKey, Key;
+    DWORD WaitStatus;
+
+    BaseKey = (UseFastIo ? KEY_USE_FASTIO : 0) |
+              (ReturnPending ? KEY_RETURN_PENDING : 0);
+
+    EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
+    ok(EventHandle != NULL, "CreateEvent failed with %lu\n", GetLastError());
+
+    for (StatusKey = KEY_SUCCEED ; StatusKey != 0xff; StatusKey = KEY_NEXT(StatusKey))
+    {
+        //trace("\tSTATUS KEY: %lx\n", StatusKey);
+        ResetEvent(EventHandle);
+        RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
+        Key = BaseKey | StatusKey | KEY_DATA(0x11);
+        Offset.QuadPart = 0;
+        Status = NtWriteFile(FileHandle,
+                             EventHandle,
+                             NULL,
+                             NULL,
+                             &IoStatus,
+                             NULL,
+                             0,
+                             &Offset,
+                             &Key);
+        WaitStatus = WaitForSingleObject(EventHandle, 0);
+        ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
+        if (!KEY_ERROR(StatusKey))
+        {
+            ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
+            ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
+            ok_eq_ulongptr(IoStatus.Information, 0);
+        }
+        else
+        {
+            ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
+            ok_eq_hex(IoStatus.Status, 0x55555555);
+            ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
+        }
+
+        KmtStartSeh()
+        ResetEvent(EventHandle);
+        RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
+        Key = BaseKey | StatusKey | KEY_DATA(0x22);
+        Offset.QuadPart = 0;
+        Status = NtWriteFile(FileHandle,
+                             EventHandle,
+                             NULL,
+                             NULL,
+                             &IoStatus,
+                             NULL,
+                             sizeof(Buffer),
+                             &Offset,
+                             &Key);
+        WaitStatus = WaitForSingleObject(EventHandle, 0);
+        ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
+        ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
+        ok_eq_hex(IoStatus.Status, 0x55555555);
+        ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
+        KmtEndSeh(STATUS_SUCCESS);
+
+        ResetEvent(EventHandle);
+        RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
+        RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
+        Key = BaseKey | StatusKey | KEY_DATA(0x33);
+        Offset.QuadPart = 0;
+        Status = NtWriteFile(FileHandle,
+                             EventHandle,
+                             NULL,
+                             NULL,
+                             &IoStatus,
+                             Buffer,
+                             0,
+                             &Offset,
+                             &Key);
+        WaitStatus = WaitForSingleObject(EventHandle, 0);
+        ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
+        if (!KEY_ERROR(StatusKey))
+        {
+            ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
+            ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
+            ok_eq_ulongptr(IoStatus.Information, 0);
+        }
+        else
+        {
+            ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
+            ok_eq_hex(IoStatus.Status, 0x55555555);
+            ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
+        }
+
+        ResetEvent(EventHandle);
+        RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
+        RtlFillMemory(Buffer, sizeof(Buffer), 0x44);
+        Key = BaseKey | StatusKey | KEY_DATA(0x44);
+        Offset.QuadPart = 0;
+        Status = NtWriteFile(FileHandle,
+                             EventHandle,
+                             NULL,
+                             NULL,
+                             &IoStatus,
+                             Buffer,
+                             sizeof(Buffer),
+                             &Offset,
+                             &Key);
+        WaitStatus = WaitForSingleObject(EventHandle, 0);
+        ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
+        if (!KEY_ERROR(StatusKey))
+        {
+            ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
+            ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
+            ok_eq_ulongptr(IoStatus.Information, sizeof(Buffer));
+        }
+        else
+        {
+            ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
+            ok_eq_hex(IoStatus.Status, 0x55555555);
+            ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
+        }
+    }
+}
+
 START_TEST(IoReadWrite)
 {
     HANDLE FileHandle;
@@ -192,14 +326,23 @@ START_TEST(IoReadWrite)
     {
         ok_eq_hex(IoStatus.Status, STATUS_SUCCESS);
         ok_eq_ulongptr(IoStatus.Information, FILE_OPENED);
-        trace("Non-Cached, no FastIo, direct return\n");
+        trace("Non-Cached read, no FastIo, direct return\n");
         TestRead(FileHandle, FALSE, FALSE, FALSE);
-        trace("Non-Cached, allow FastIo, direct return\n");
+        trace("Non-Cached read, allow FastIo, direct return\n");
         TestRead(FileHandle, FALSE, TRUE, FALSE);
-        trace("Non-Cached, no FastIo, pending return\n");
+        trace("Non-Cached read, no FastIo, pending return\n");
         TestRead(FileHandle, FALSE, FALSE, TRUE);
-        trace("Non-Cached, allow FastIo, pending return\n");
+        trace("Non-Cached read, allow FastIo, pending return\n");
         TestRead(FileHandle, FALSE, TRUE, TRUE);
+
+        trace("Non-Cached write, no FastIo, direct return\n");
+        TestWrite(FileHandle, FALSE, FALSE, FALSE);
+        trace("Non-Cached write, allow FastIo, direct return\n");
+        TestWrite(FileHandle, FALSE, TRUE, FALSE);
+        trace("Non-Cached write, no FastIo, pending return\n");
+        TestWrite(FileHandle, FALSE, FALSE, TRUE);
+        trace("Non-Cached write, allow FastIo, pending return\n");
+        TestWrite(FileHandle, FALSE, TRUE, TRUE);
         NtClose(FileHandle);
     }
 
@@ -221,14 +364,23 @@ START_TEST(IoReadWrite)
     {
         ok_eq_hex(IoStatus.Status, STATUS_SUCCESS);
         ok_eq_ulongptr(IoStatus.Information, FILE_OPENED);
-        trace("Cached, no FastIo, direct return\n");
+        trace("Cached read, no FastIo, direct return\n");
         TestRead(FileHandle, TRUE, FALSE, FALSE);
-        trace("Cached, allow FastIo, direct return\n");
+        trace("Cached read, allow FastIo, direct return\n");
         TestRead(FileHandle, TRUE, TRUE, FALSE);
-        trace("Cached, no FastIo, pending return\n");
+        trace("Cached read, no FastIo, pending return\n");
         TestRead(FileHandle, TRUE, FALSE, TRUE);
-        trace("Cached, allow FastIo, pending return\n");
+        trace("Cached read, allow FastIo, pending return\n");
         TestRead(FileHandle, TRUE, TRUE, TRUE);
+
+        trace("Cached write, no FastIo, direct return\n");
+        TestWrite(FileHandle, TRUE, FALSE, FALSE);
+        trace("Cached write, allow FastIo, direct return\n");
+        TestWrite(FileHandle, TRUE, TRUE, FALSE);
+        trace("Cached write, no FastIo, pending return\n");
+        TestWrite(FileHandle, TRUE, FALSE, TRUE);
+        trace("Cached write, allow FastIo, pending return\n");
+        TestWrite(FileHandle, TRUE, TRUE, TRUE);
         NtClose(FileHandle);
     }