[6/6] ntoskrnl.exe/tests: Add tests for some functions working with IRP

Alexander Morozov amorozov at etersoft.ru
Tue Jul 22 03:58:56 CDT 2008


Add tests for some functions working with IRP.
These tests pass on Win XP and Server 2003.
On Win 98 they are skipped.
-------------- next part --------------
From a9476cccb5a9ab75666dcfc2a886bf982fb32401 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov at etersoft.ru>
Date: Tue, 22 Jul 2008 11:46:14 +0400
Subject: [PATCH] ntoskrnl.exe/tests: Add tests for some functions working with IRP

---
 dlls/ntoskrnl.exe/tests/driver.c        |  354 +++++++++++++++++++++++++++++++
 dlls/ntoskrnl.exe/tests/ntoskrnl.c      |   27 +++
 dlls/ntoskrnl.exe/tests/ntoskrnl_test.h |   24 ++
 3 files changed, 405 insertions(+), 0 deletions(-)
 create mode 100644 dlls/ntoskrnl.exe/tests/ntoskrnl_test.h

diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 278c8f7..9e58b48 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -18,20 +18,374 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#ifndef WIN32
+#include "config.h"
+#endif
+
 #include <stdarg.h>
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
 #include "winternl.h"
+#include "winioctl.h"
 #include "ddk/ntddk.h"
+#include "ntoskrnl_test.h"
+
+#ifdef WIN32
+#define IoCompleteRequest IofCompleteRequest
+#define IoCallDriver IofCallDriver
+extern void __fastcall IofCompleteRequest(IRP*, UCHAR);
+extern NTSTATUS __fastcall IofCallDriver(DEVICE_OBJECT*, IRP*);
+#else
+void WINAPI IoCompleteRequest(IRP *irp, UCHAR priority_boost)
+{
+    #ifdef __i386__
+    __asm__("movl %1,%%edx\n\t"
+            "movl %0,%%ecx\n\t"
+            "call " __ASM_NAME("IofCompleteRequest")
+            : : "g" (irp), "g" (priority_boost));
+    #else
+    IofCompleteRequest(irp, priority_boost);
+    #endif
+}
+
+NTSTATUS WINAPI IoCallDriver(DEVICE_OBJECT *device, IRP *irp)
+{
+    #ifdef __i386__
+    NTSTATUS status;
+    __asm__("movl %2,%%edx\n\t"
+            "movl %1,%%ecx\n\t"
+            "call " __ASM_NAME("IofCallDriver") "\n\t"
+            "movl %%eax,%0"
+            : "=g" (status) : "g" (device), "g" (irp));
+    return status;
+    #else
+    return IofCallDriver(device, irp);
+    #endif
+}
+#endif
+
+typedef struct
+{
+    UNICODE_STRING slinkname;
+} devext;
 
 void WINAPI unload(DRIVER_OBJECT *driver)
 {
+    DEVICE_OBJECT *device = driver->DeviceObject;
+
+    if (device)
+    {
+        devext *dx = device->DeviceExtension;
+
+        IoDeleteSymbolicLink(&dx->slinkname);
+        IoDeleteDevice(device);
+    }
+}
+
+NTSTATUS WINAPI complete_request(DEVICE_OBJECT *device, IRP *irp)
+{
+    irp->IoStatus.u.Status = STATUS_SUCCESS;
+    irp->IoStatus.Information = 0;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS WINAPI completion_routine(DEVICE_OBJECT *device, IRP *irp, PVOID context)
+{
+    if ((void *)0x99999999 == context && 2 == irp->CurrentLocation &&
+            sizeof(IRP) + sizeof(IO_STACK_LOCATION) ==
+            (ULONG)irp->Tail.Overlay.s.u.CurrentStackLocation - (ULONG)irp)
+    {
+        irp->IoStatus.Information = 0x66666666;
+        irp->UserIosb->u.Status = STATUS_SUCCESS;
+        irp->UserIosb->Information = 0x11111111;
+    }
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS WINAPI completion_routine_2(DEVICE_OBJECT *device, IRP *irp, PVOID event)
+{
+    if (3 == irp->CurrentLocation && sizeof(IRP) + 2 * sizeof(IO_STACK_LOCATION) ==
+            (ULONG)irp->Tail.Overlay.s.u.CurrentStackLocation - (ULONG)irp)
+    {
+        irp->UserIosb->u.Status = STATUS_SUCCESS;
+        irp->UserIosb->Information = 0xaaaaaaaa;
+    }
+    IoFreeIrp(irp);
+    KeSetEvent(event, IO_NO_INCREMENT, FALSE);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS WINAPI completion_routine_3(DEVICE_OBJECT *device, IRP *irp, PVOID event)
+{
+    if (2 == irp->CurrentLocation && sizeof(IRP) + sizeof(IO_STACK_LOCATION) ==
+            (ULONG)irp->Tail.Overlay.s.u.CurrentStackLocation - (ULONG)irp)
+        irp->IoStatus.Information = 0x22222222;
+    KeSetEvent(event, IO_NO_INCREMENT, FALSE);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS WINAPI device_control(DEVICE_OBJECT *device, IRP *irp)
+{
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+    ULONG info = 0;
+    IO_STACK_LOCATION *irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
+    ULONG ioctl_code = irpsp->Parameters.DeviceIoControl.IoControlCode;
+
+    switch (ioctl_code)
+    {
+    case IOCTL_IRPTEST(1):
+    {
+        USHORT size = sizeof(IRP) + 5 * sizeof(IO_STACK_LOCATION);
+        IRP *iorp = ExAllocatePool(NonPagedPool, size);
+
+        if (NULL != iorp)
+        {
+            IoInitializeIrp(iorp, size, 5);
+            if (6 == iorp->Type && iorp->Size == size &&
+                    5 == iorp->StackCount && 6 == iorp->CurrentLocation &&
+                    IsListEmpty(&iorp->ThreadListEntry) &&
+                    (PIO_STACK_LOCATION)(iorp + 1) + 5 ==
+                    iorp->Tail.Overlay.s.u.CurrentStackLocation)
+                status = STATUS_SUCCESS;
+            ExFreePool(iorp);
+        }
+        break;
+    }
+    case IOCTL_IRPTEST(2):
+    {
+        USHORT size = sizeof(IRP) + 2 * sizeof(IO_STACK_LOCATION);
+        IRP *iorp = IoAllocateIrp(2, FALSE);
+
+        if (NULL != iorp)
+        {
+            if (6 == iorp->Type && iorp->Size >= size &&
+                    2 == iorp->StackCount && 3 == iorp->CurrentLocation &&
+                    IsListEmpty(&iorp->ThreadListEntry) &&
+                    (PIO_STACK_LOCATION)(iorp + 1) + 2 ==
+                    iorp->Tail.Overlay.s.u.CurrentStackLocation &&
+                    (IRP_ALLOCATED_FIXED_SIZE & iorp->AllocationFlags) &&
+                    !(IRP_LOOKASIDE_ALLOCATION & iorp->AllocationFlags))
+                status = STATUS_SUCCESS;
+            IoFreeIrp(iorp);
+        }
+        break;
+    }
+    case IOCTL_IRPTEST(3):
+    {
+        USHORT size = sizeof(IRP) + 2 * sizeof(IO_STACK_LOCATION);
+        IRP *iorp = IoAllocateIrp(2, TRUE);
+
+        if (NULL != iorp)
+        {
+            if (6 == iorp->Type && iorp->Size >= size &&
+                    2 == iorp->StackCount && 3 == iorp->CurrentLocation &&
+                    IsListEmpty(&iorp->ThreadListEntry) &&
+                    (PIO_STACK_LOCATION)(iorp + 1) + 2 ==
+                    iorp->Tail.Overlay.s.u.CurrentStackLocation &&
+                    (IRP_ALLOCATED_FIXED_SIZE & iorp->AllocationFlags) &&
+                    (IRP_LOOKASIDE_ALLOCATION & iorp->AllocationFlags))
+                status = STATUS_SUCCESS;
+            IoFreeIrp(iorp);
+        }
+        break;
+    }
+    case IOCTL_IRPTEST(4):
+    {
+        NTSTATUS stat;
+        IO_STATUS_BLOCK iosb;
+        KEVENT event;
+        IRP *iorp;
+
+        iorp = IoBuildDeviceIoControlRequest(INTERNAL_IOCTL(1), device, NULL, 0,
+                NULL, 0, TRUE, &event, &iosb);
+        if (NULL == iorp)
+            break;
+
+        stat = IoCallDriver(device, iorp);
+        if (STATUS_PENDING == stat)
+            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        if ((STATUS_SUCCESS == stat || STATUS_PENDING == stat) &&
+                STATUS_SUCCESS == iosb.u.Status && 0x33333333 == iosb.Information)
+            status = STATUS_SUCCESS;
+        break;
+    }
+    case IOCTL_IRPTEST(5):
+    {
+        NTSTATUS stat;
+        IO_STATUS_BLOCK iosb;
+        KEVENT event;
+        IRP *iorp;
+
+        iorp = IoBuildDeviceIoControlRequest(INTERNAL_IOCTL(1), device, NULL, 0,
+                NULL, 0, TRUE, &event, &iosb);
+        if (NULL == iorp)
+            break;
+
+        irpsp = iorp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+        irpsp->Control = SL_INVOKE_ON_SUCCESS;
+        irpsp->CompletionRoutine = completion_routine;
+        irpsp->Context = (void *)0x99999999;
+
+        stat = IoCallDriver(device, iorp);
+        if (STATUS_PENDING == stat)
+            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        if ((STATUS_SUCCESS == stat || STATUS_PENDING == stat) &&
+                STATUS_SUCCESS == iosb.u.Status && 0x66666666 == iosb.Information)
+            status = STATUS_SUCCESS;
+        break;
+    }
+    case IOCTL_IRPTEST(6):
+    {
+        NTSTATUS stat;
+        IO_STATUS_BLOCK iosb;
+        KEVENT event;
+        IRP *iorp;
+
+        iorp = IoBuildDeviceIoControlRequest(INTERNAL_IOCTL(1), device, NULL, 0,
+                NULL, 0, TRUE, &event, &iosb);
+        if (NULL == iorp)
+            break;
+
+        irpsp = iorp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+        irpsp->Control = SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL;
+        irpsp->CompletionRoutine = completion_routine;
+        irpsp->Context = (void *)0x99999999;
+
+        stat = IoCallDriver(device, iorp);
+        if (STATUS_PENDING == stat)
+            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        if ((STATUS_SUCCESS == stat || STATUS_PENDING == stat) &&
+                STATUS_SUCCESS == iosb.u.Status && 0x33333333 == iosb.Information)
+            status = STATUS_SUCCESS;
+        break;
+    }
+    case IOCTL_IRPTEST(7):
+    {
+        NTSTATUS stat;
+        IO_STATUS_BLOCK iosb;
+        KEVENT event;
+        IRP *iorp;
+
+        iorp = IoBuildDeviceIoControlRequest(INTERNAL_IOCTL(2), device, NULL, 0,
+                NULL, 0, TRUE, &event, &iosb);
+        if (NULL == iorp)
+            break;
+
+        irpsp = iorp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+        irpsp->Control = SL_INVOKE_ON_ERROR;
+        irpsp->CompletionRoutine = completion_routine;
+        irpsp->Context = (void *)0x99999999;
+
+        stat = IoCallDriver(device, iorp);
+        if (STATUS_PENDING == stat)
+            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        if ((STATUS_UNSUCCESSFUL == stat || STATUS_PENDING == stat) &&
+                STATUS_SUCCESS == iosb.u.Status && 0x11111111 == iosb.Information)
+            status = STATUS_SUCCESS;
+        break;
+    }
+    case IOCTL_IRPTEST(8):
+    {
+        NTSTATUS stat;
+        IO_STATUS_BLOCK iosb;
+        KEVENT event;
+        IRP *iorp;
+
+        iorp = IoAllocateIrp(2, TRUE);
+        if (NULL == iorp)
+            break;
+
+        iorp->UserIosb = &iosb;
+        irpsp = iorp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+        irpsp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
+        irpsp->CompletionRoutine = completion_routine_2;
+        irpsp->Context = &event;
+        irpsp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+        irpsp->Parameters.DeviceIoControl.IoControlCode = INTERNAL_IOCTL(3);
+        KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+        stat = IoCallDriver(device, iorp);
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        if ((STATUS_SUCCESS == stat || STATUS_PENDING == stat) &&
+                STATUS_SUCCESS == iosb.u.Status && 0xaaaaaaaa == iosb.Information)
+            status = STATUS_SUCCESS;
+        break;
+    }
+    case INTERNAL_IOCTL(1):
+        status = STATUS_SUCCESS;
+        info = 0x33333333;
+        irp->UserIosb->u.Status = 0xdeadbeef;
+        irp->UserIosb->Information = 0xdeadbeef;
+        break;
+    case INTERNAL_IOCTL(2):
+        status = STATUS_UNSUCCESSFUL;
+        info = 0x33333333;
+        irp->UserIosb->u.Status = 0xdeadbeef;
+        irp->UserIosb->Information = 0xdeadbeef;
+        break;
+    case INTERNAL_IOCTL(3):
+    {
+        NTSTATUS stat;
+        KEVENT event;
+
+        irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+        irpsp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
+        irpsp->CompletionRoutine = completion_routine_3;
+        irpsp->Context = &event;
+        irpsp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+        irpsp->Parameters.DeviceIoControl.IoControlCode = INTERNAL_IOCTL(1);
+        KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+        stat = IoCallDriver(device, irp);
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        if ((STATUS_SUCCESS == stat || STATUS_PENDING == stat) &&
+                0xdeadbeef == irp->UserIosb->u.Status &&
+                0xdeadbeef == irp->UserIosb->Information &&
+                STATUS_SUCCESS == irp->IoStatus.u.Status &&
+                0x22222222 == irp->IoStatus.Information)
+            status = STATUS_SUCCESS;
+    }
+    }
+
+    irp->IoStatus.u.Status = status;
+    irp->IoStatus.Information = info;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+    return status;
 }
 
 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *regpath)
 {
+    static const WCHAR devnameW[] = {'\\','D','e','v','i','c','e','\\',
+                                     'w','i','n','e','t','e','s','t',0};
+    static const WCHAR slinknameW[] = {'\\','D','o','s','D','e','v','i','c','e','s',
+                                       '\\','w','i','n','e','t','e','s','t',0};
+    UNICODE_STRING devname;
+    NTSTATUS status;
+    DEVICE_OBJECT *device;
+    devext *dx;
+
     driver->DriverUnload = unload;
+    driver->MajorFunction[IRP_MJ_CREATE] = complete_request;
+    driver->MajorFunction[IRP_MJ_CLOSE] = complete_request;
+    driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = device_control;
+    driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = device_control;
+
+    RtlInitUnicodeString(&devname, devnameW);
+    status = IoCreateDevice(driver, sizeof(devext), &devname,
+            FILE_DEVICE_UNKNOWN, 0, FALSE, &device);
+    if (STATUS_SUCCESS != status)
+        return status;
+    dx = device->DeviceExtension;
+    RtlInitUnicodeString(&dx->slinkname, slinknameW);
+    IoCreateSymbolicLink(&dx->slinkname, &devname);
+    device->Flags &= ~DO_DEVICE_INITIALIZING;
 
     return STATUS_SUCCESS;
 }
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index 3da3100..5af264c 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -19,7 +19,9 @@
  */
 
 #include "windows.h"
+#include "winioctl.h"
 #include "wine/test.h"
+#include "ntoskrnl_test.h"
 #include "rc.h"
 
 #define DRVNAME "winetest"
@@ -118,6 +120,30 @@ void stop_service(SC_HANDLE scm)
     CloseServiceHandle(service);
 }
 
+void irp_test(void)
+{
+    HANDLE hfile;
+    BOOL ret;
+    ULONG k;
+    DWORD bytes;
+
+    SetLastError(0xdeadbeef);
+    hfile = CreateFileA("\\\\.\\" DRVNAME, GENERIC_READ | GENERIC_WRITE,
+            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+            FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(INVALID_HANDLE_VALUE != hfile, "CreateFileA failed: %u\n", GetLastError());
+
+    for (k = 1; k <= 8; ++k)
+    {
+        SetLastError(0xdeadbeef);
+        ret = DeviceIoControl(hfile, IOCTL_IRPTEST(k), NULL, 0, NULL, 0, &bytes, NULL);
+        todo_wine
+        ok(ret, "IRP test %u failed\n", k);
+    }
+
+    CloseHandle(hfile);
+}
+
 START_TEST(ntoskrnl)
 {
     CHAR destpath[MAX_PATH + 1];
@@ -139,6 +165,7 @@ START_TEST(ntoskrnl)
 
     create_service(scm);
     start_service(scm);
+    irp_test();
     stop_service(scm);
     delete_service(scm);
 
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl_test.h b/dlls/ntoskrnl.exe/tests/ntoskrnl_test.h
new file mode 100644
index 0000000..8d4f652
--- /dev/null
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl_test.h
@@ -0,0 +1,24 @@
+/*
+ * Tests for ntoskrnl.exe
+ *
+ * Copyright 2008 Etersoft (Alexander Morozov)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define IOCTL_IRPTEST(n) CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80f + n, \
+        METHOD_NEITHER, FILE_ANY_ACCESS)
+#define INTERNAL_IOCTL(n) CTL_CODE(FILE_DEVICE_UNKNOWN, 0x8ff + n, \
+        METHOD_NEITHER, FILE_ANY_ACCESS)
-- 
1.5.4.5.GIT



More information about the wine-patches mailing list