鼠标过滤驱动程序启动后获取IRP_MJ_CLOSE

问题描述 投票:0回答:1

我有以下适用于 Windows 的自定义鼠标驱动程序,但无法在 Windows 内核中正确加载

#include <ntddk.h>
#include <ntstrsafe.h>

#pragma warning(disable : 4201)

typedef struct
{
    PDEVICE_OBJECT LowerKbdDevice;
} DEVICE_EXTENSION, * PDEVICE_EXTENSION;

PDEVICE_OBJECT myKbdDevice = NULL;
ULONG pendingkey = 0;
int first_time = TRUE;

typedef struct _MOUSE_INPUT_DATA {
    USHORT UnitId;
    USHORT Flags;
    union {
        ULONG Buttons;
        struct {
            USHORT ButtonFlags;
            USHORT ButtonData;
        };
    };
    ULONG  RawButtons;
    LONG   LastX;
    LONG   LastY;
    ULONG  ExtraInformation;
} MOUSE_INPUT_DATA, * PMOUSE_INPUT_DATA;

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{

    LARGE_INTEGER interval = { 0 };
    interval.QuadPart = -10 * 1000 * 1000; // 1 second

    PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
    IoDetachDevice(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice);

    while (pendingkey)
    {
        KeDelayExecutionThread(KernelMode, FALSE, &interval);
    }

    IoDeleteDevice(myKbdDevice);

    DbgPrintEx(0, 0, "Mouse filter unloaded\n");
}

NTSTATUS DispatchPass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{

    PIO_STACK_LOCATION sl = IoGetCurrentIrpStackLocation(Irp);
    DbgPrintEx(0, 0, "DispatchPass: %d\n", sl->MajorFunction);
    UNREFERENCED_PARAMETER(DeviceObject);

    IoCopyCurrentIrpStackLocationToNext(Irp);

    NTSTATUS status = IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice, Irp);

    return status;
}



NTSTATUS ReadComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Context);

    PMOUSE_INPUT_DATA Keys = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
    int structnum = (ULONG)Irp->IoStatus.Information / sizeof(PMOUSE_INPUT_DATA);

    if (structnum == 0) {
        Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }

    if (Irp->IoStatus.Status == STATUS_SUCCESS) {
        for (int i = 0; i < structnum; i++)
        {

            DbgPrintEx(0, 0, "The button state is %x\n", Keys->ButtonFlags);
        }
    }
    else {
        DbgPrintEx(0, 0, "Complete status not success: %d\n", Irp->IoStatus.Status);
    }

    if (Irp->PendingReturned) {
        IoMarkIrpPending(Irp);
    }


    pendingkey--;
    return STATUS_CONTINUE_COMPLETION;
}

NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);

    IoCopyCurrentIrpStackLocationToNext(Irp);

    pendingkey++;

    IoSetCompletionRoutineEx(DeviceObject, Irp, ReadComplete, NULL, TRUE, TRUE, TRUE);
    NTSTATUS status = IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice, Irp);
    DbgPrintEx(0, 0, "DispatchRead: IoCallDriver status is %d\n", status);

    return status;
}


NTSTATUS MyAttachDevice(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING TargetDevice = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");

    PAGED_CODE();

    NTSTATUS status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &myKbdDevice);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "IoCreateDevice failed\n");
        return status;
    }

    RtlZeroMemory(myKbdDevice->DeviceExtension, sizeof(DEVICE_EXTENSION));

    myKbdDevice->Flags |= DO_BUFFERED_IO;
    myKbdDevice->Flags &= ~DO_DEVICE_INITIALIZING;

    status = IoAttachDevice(myKbdDevice,&TargetDevice,&((PDEVICE_EXTENSION)myKbdDevice->DeviceExtension)->LowerKbdDevice);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "IoAttachDevice failed with status %d\n", status);
        IoDeleteDevice(myKbdDevice);
        return status;
    }

    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    UNREFERENCED_PARAMETER(RegistryPath);

    DriverObject->DriverUnload = DriverUnload;

    for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction[i] = DispatchPass;
    }

    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
    NTSTATUS status = MyAttachDevice(DriverObject);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "MyAttachDevice failed\n");
        return status;
    }


    return STATUS_SUCCESS;
}

通过 OSR Loader 启动驱动程序后,我立即收到 IRP_MJ_CLOSE IRP 并且无法理解为什么。我使用带有内置触摸板的笔记本电脑。据我所知,在这种情况下,PointerClass0设备应该代表笔记本电脑的触摸板(鼠标)。也许我需要使用其他类而不是 PointerClass0?我也有 PointerClass1 和 PointerClass2,但对于此类,IoAttachDevice 总是失败。有人可以有想法吗?

c windows driver windows-kernel
1个回答
0
投票

解决了。我像这样更改了 MyAttachDevice 函数:

NTSTATUS MyAttachDevice(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING MCName = RTL_CONSTANT_STRING(L"\\Driver\\Mouclass");
    PDRIVER_OBJECT TargetDriverObject;
    PDEVICE_OBJECT CurrentDeviceObject;
    PDEVICE_OBJECT myDeviceObject = NULL;

    DbgPrintEx(0, 0, "Before ObReferenceObjectByName\n");
    NTSTATUS status = ObReferenceObjectByName(&MCName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, (PVOID*)&TargetDriverObject);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "ObReferenceObjectByName failed\n");
        return status;
    }

    CurrentDeviceObject = TargetDriverObject->DeviceObject;
    ObDereferenceObject(TargetDriverObject);

    while (CurrentDeviceObject)
    {
        status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &myDeviceObject);
        if (!NT_SUCCESS(status)) {
            DbgPrintEx(0, 0, "IoCreateDevice failed\n");
            return status;
        }

        RtlZeroMemory(myDeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
        DbgPrintEx(0, 0, "Before IoAttachDeviceToDeviceStackSafe\n");
        status = IoAttachDeviceToDeviceStackSafe(myDeviceObject, CurrentDeviceObject, &((PDEVICE_EXTENSION)myDeviceObject->DeviceExtension)->LowerKbdDevice);

        if (!NT_SUCCESS(status)) {
            IoDeleteDevice(myDeviceObject);
            DbgPrintEx(0, 0, "IoAttachDeviceToDeviceStackSafe failed\n");
            return status;
        }

        myDeviceObject->Flags |= DO_BUFFERED_IO;
        myDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

        CurrentDeviceObject = CurrentDeviceObject->NextDevice;
    }

    return STATUS_SUCCESS;
}

简而言之:我们需要将设备绑定到“\Driver\Mouclass”而不是“\Device\PointerClass0”中的设备

© www.soinside.com 2019 - 2024. All rights reserved.