mirror of
https://github.com/reactos/reactos.git
synced 2025-07-14 20:24:24 +00:00
Rewrite mouclass, so it can now handle more than one mouse.
win32k: try to open the keyboard/mouse in a loop, as they can not be present at startup svn path=/trunk/; revision=18906
This commit is contained in:
parent
04cc754e4d
commit
aeeab7d1f4
6 changed files with 716 additions and 272 deletions
|
@ -532,7 +532,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Start",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","ConnectMultiplePorts",0x00010001,0x00000000
|
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","ConnectMultiplePorts",0x00010001,0x00000000
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","MouseDataQueueSize",0x00010001,0x00000064
|
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","MouseDataQueueSize",0x00010001,0x00000064
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDeviceBaseName",0x00000000,"PointerClass"
|
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDeviceBaseName",0x00000000,"PointerClassPnp"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"mouclass"
|
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"mouclass"
|
||||||
|
|
||||||
; Mailslot filesystem driver
|
; Mailslot filesystem driver
|
||||||
|
|
61
reactos/drivers/input/mouclass/misc.c
Normal file
61
reactos/drivers/input/mouclass/misc.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Mouse class driver
|
||||||
|
* FILE: drivers/input/mouclass/misc.c
|
||||||
|
* PURPOSE: Misceallenous operations
|
||||||
|
*
|
||||||
|
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "mouclass.h"
|
||||||
|
|
||||||
|
static NTSTATUS NTAPI
|
||||||
|
ForwardIrpAndWaitCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
if (Irp->PendingReturned)
|
||||||
|
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ForwardIrpAndWait(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT LowerDevice = ((PMOUCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||||
|
KEVENT Event;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
|
||||||
|
DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
|
||||||
|
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
Status = IoCallDriver(LowerDevice, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
ForwardIrpAndForget(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT LowerDevice = ((PMOUCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||||
|
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(LowerDevice, Irp);
|
||||||
|
}
|
|
@ -1,277 +1,599 @@
|
||||||
/*
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
** Mouse class driver 0.0.1
|
* PROJECT: ReactOS Mouse class driver
|
||||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
* FILE: drivers/mouclass/mouclass.c
|
||||||
** For ReactOS (www.reactos.com)
|
* PURPOSE: Mouse class driver
|
||||||
|
*
|
||||||
** The class driver between win32k and the various mouse port drivers
|
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
||||||
|
*/
|
||||||
** FIXME: Support IRP cancellation properly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ddk/ntddk.h>
|
|
||||||
#include <ddk/ntddmou.h>
|
|
||||||
#include <ddk/kbdmou.h>
|
|
||||||
#include "mouclass.h"
|
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
#define INITGUID
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
|
#include "mouclass.h"
|
||||||
|
|
||||||
PDEVICE_OBJECT MouclassDeviceObject;
|
static VOID NTAPI
|
||||||
|
DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
||||||
static BOOLEAN MouseClassCallBack(
|
|
||||||
PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA MouseDataStart,
|
|
||||||
PMOUSE_INPUT_DATA MouseDataEnd, PULONG ConsumedCount)
|
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
// nothing to do here yet
|
||||||
PIRP Irp = NULL;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
PIO_STACK_LOCATION Stack;
|
|
||||||
ULONG InputCount = MouseDataEnd - MouseDataStart;
|
|
||||||
ULONG ReadSize;
|
|
||||||
|
|
||||||
DPRINT("Entering MouseClassCallBack\n");
|
|
||||||
/* A filter driver might have consumed all the data already; I'm
|
|
||||||
* not sure if they are supposed to move the packets when they
|
|
||||||
* consume them though.
|
|
||||||
*/
|
|
||||||
if (ClassDeviceExtension->ReadIsPending == TRUE &&
|
|
||||||
InputCount)
|
|
||||||
{
|
|
||||||
Irp = ClassDeviceObject->CurrentIrp;
|
|
||||||
ClassDeviceObject->CurrentIrp = NULL;
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
|
|
||||||
/* A read request is waiting for input, so go straight to it */
|
|
||||||
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, MouseDataStart,
|
|
||||||
sizeof(MOUSE_INPUT_DATA));
|
|
||||||
|
|
||||||
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
|
|
||||||
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
|
|
||||||
|
|
||||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
|
||||||
|
|
||||||
/* Skip the packet we just sent away */
|
|
||||||
MouseDataStart++;
|
|
||||||
(*ConsumedCount)++;
|
|
||||||
InputCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have data from the port driver and a higher service to send the data to */
|
|
||||||
if (InputCount != 0)
|
|
||||||
{
|
|
||||||
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
|
||||||
|
|
||||||
if (ClassDeviceExtension->InputCount + InputCount > MOUSE_BUFFER_SIZE)
|
|
||||||
{
|
|
||||||
ReadSize = MOUSE_BUFFER_SIZE - ClassDeviceExtension->InputCount;
|
|
||||||
} else {
|
|
||||||
ReadSize = InputCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: If we exceed the buffer, mouse data gets thrown away.. better
|
|
||||||
* solution?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Move the mouse input data from the port data queue to our class data
|
|
||||||
* queue.
|
|
||||||
*/
|
|
||||||
RtlMoveMemory(ClassDeviceExtension->PortData, (PCHAR)MouseDataStart,
|
|
||||||
sizeof(MOUSE_INPUT_DATA) * ReadSize);
|
|
||||||
|
|
||||||
/* Move the pointer and counter up */
|
|
||||||
ClassDeviceExtension->PortData += ReadSize;
|
|
||||||
ClassDeviceExtension->InputCount += ReadSize;
|
|
||||||
|
|
||||||
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
|
||||||
(*ConsumedCount) += ReadSize;
|
|
||||||
} else {
|
|
||||||
DPRINT("MouseClassCallBack() entered, InputCount = %d - DOING NOTHING\n", InputCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Irp != NULL)
|
|
||||||
{
|
|
||||||
IoStartNextPacket(ClassDeviceObject, FALSE);
|
|
||||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Leaving MouseClassCallBack\n");
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject)
|
static NTSTATUS NTAPI
|
||||||
|
MouclassCreate(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT PortDeviceObject = NULL;
|
DPRINT("IRP_MJ_CREATE\n");
|
||||||
PFILE_OBJECT FileObject = NULL;
|
|
||||||
NTSTATUS status;
|
|
||||||
UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
|
|
||||||
IO_STATUS_BLOCK ioStatus;
|
|
||||||
KEVENT event;
|
|
||||||
PIRP irp;
|
|
||||||
CONNECT_DATA ClassInformation;
|
|
||||||
PDEVICE_EXTENSION DeviceExtension = ClassDeviceObject->DeviceExtension;
|
|
||||||
|
|
||||||
// Get the port driver's DeviceObject
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
||||||
// FIXME: The name might change.. find a way to be more dynamic?
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
|
||||||
status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
|
/* FIXME: open all associated Port devices */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
if(status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT("MOUCLASS: Could not connect to mouse port driver\n");
|
|
||||||
DPRINT("Status: %x\n", status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceExtension->PortDeviceObject = PortDeviceObject;
|
|
||||||
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, MOUSE_BUFFER_SIZE * sizeof(MOUSE_INPUT_DATA));
|
|
||||||
DeviceExtension->InputCount = 0;
|
|
||||||
DeviceExtension->ReadIsPending = FALSE;
|
|
||||||
DeviceExtension->WorkItem = NULL;
|
|
||||||
KeInitializeSpinLock(&(DeviceExtension->SpinLock));
|
|
||||||
DeviceExtension->PassiveCallbackQueued = FALSE;
|
|
||||||
|
|
||||||
// Connect our callback to the port driver
|
|
||||||
|
|
||||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
||||||
|
|
||||||
ClassInformation.ClassDeviceObject = ClassDeviceObject;
|
|
||||||
ClassInformation.ClassService = MouseClassCallBack;
|
|
||||||
|
|
||||||
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
|
|
||||||
PortDeviceObject, &ClassInformation, sizeof(CONNECT_DATA), NULL, 0, TRUE, &event, &ioStatus);
|
|
||||||
|
|
||||||
status = IoCallDriver(DeviceExtension->PortDeviceObject, irp);
|
|
||||||
|
|
||||||
if (status == STATUS_PENDING) {
|
|
||||||
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
|
|
||||||
} else {
|
|
||||||
ioStatus.Status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ioStatus.Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS STDCALL MouseClassDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
static NTSTATUS NTAPI
|
||||||
|
MouclassClose(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
DPRINT("IRP_MJ_CLOSE\n");
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
switch (Stack->MajorFunction)
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
||||||
{
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
case IRP_MJ_CREATE:
|
|
||||||
Status = ConnectMousePortDriver(MouclassDeviceObject);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IRP_MJ_CLOSE:
|
/* FIXME: close all associated Port devices */
|
||||||
Status = STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
break;
|
|
||||||
|
|
||||||
case IRP_MJ_READ:
|
|
||||||
if (Stack->Parameters.Read.Length < sizeof(MOUSE_INPUT_DATA))
|
|
||||||
{
|
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
IoMarkIrpPending(Irp);
|
|
||||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
|
||||||
return STATUS_PENDING;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINT1("NOT IMPLEMENTED\n");
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID STDCALL
|
static NTSTATUS NTAPI
|
||||||
MouseClassStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
MouclassRead(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
DPRINT("IRP_MJ_READ\n");
|
||||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
|
|
||||||
if (DeviceExtension->InputCount > 0)
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
||||||
{
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length < sizeof(MOUSE_INPUT_DATA))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
DeviceExtension->PortData - DeviceExtension->InputCount,
|
}
|
||||||
sizeof(MOUSE_INPUT_DATA));
|
|
||||||
|
|
||||||
if (DeviceExtension->InputCount > 1)
|
IoMarkIrpPending(Irp);
|
||||||
{
|
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||||
RtlMoveMemory(
|
return STATUS_PENDING;
|
||||||
DeviceExtension->PortData - DeviceExtension->InputCount,
|
|
||||||
DeviceExtension->PortData - DeviceExtension->InputCount + 1,
|
|
||||||
(DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
|
|
||||||
}
|
|
||||||
DeviceExtension->PortData--;
|
|
||||||
DeviceExtension->InputCount--;
|
|
||||||
DeviceExtension->ReadIsPending = FALSE;
|
|
||||||
|
|
||||||
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
|
|
||||||
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
|
|
||||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
|
||||||
|
|
||||||
IoStartNextPacket(DeviceObject, FALSE);
|
|
||||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
|
|
||||||
} else {
|
|
||||||
DeviceExtension->ReadIsPending = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
static NTSTATUS NTAPI
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
IrpStub(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
NTSTATUS Status = STATUS_NOT_SUPPORTED;
|
||||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Mouse");
|
|
||||||
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\Mouse");
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassDispatch;
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassDispatch;
|
{
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassDispatch;
|
/* Forward some IRPs to lower device */
|
||||||
DriverObject->DriverStartIo = MouseClassStartIo;
|
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
||||||
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
DPRINT1("Port DO stub for major function 0x%lx\n",
|
||||||
|
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) /* HACK FOR I8042PRT */
|
||||||
|
{
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("Class DO stub for major function 0x%lx\n",
|
||||||
|
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
Status = IoCreateDevice(DriverObject,
|
Irp->IoStatus.Status = Status;
|
||||||
sizeof(DEVICE_EXTENSION),
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
&DeviceName,
|
return Status;
|
||||||
FILE_DEVICE_MOUSE,
|
}
|
||||||
0,
|
|
||||||
TRUE,
|
static NTSTATUS
|
||||||
&DeviceObject);
|
ReadRegistryEntries(
|
||||||
if (!NT_SUCCESS(Status))
|
IN PUNICODE_STRING RegistryPath,
|
||||||
{
|
IN PMOUCLASS_DRIVER_EXTENSION DriverExtension)
|
||||||
return(Status);
|
{
|
||||||
}
|
RTL_QUERY_REGISTRY_TABLE Parameters[4];
|
||||||
|
NTSTATUS Status;
|
||||||
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
|
|
||||||
|
ULONG DefaultConnectMultiplePorts = 1;
|
||||||
Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
ULONG DefaultMouseDataQueueSize = 0x64;
|
||||||
if (!NT_SUCCESS(Status))
|
UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerClassPnp");
|
||||||
{
|
|
||||||
IoDeleteDevice(DeviceObject);
|
RtlZeroMemory(Parameters, sizeof(Parameters));
|
||||||
return Status;
|
|
||||||
}
|
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
|
Parameters[0].Name = L"ConnectMultiplePorts";
|
||||||
MouclassDeviceObject = DeviceObject;
|
Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts;
|
||||||
|
Parameters[0].DefaultType = REG_DWORD;
|
||||||
return STATUS_SUCCESS;
|
Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
|
||||||
|
Parameters[0].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
|
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
|
Parameters[1].Name = L"MouseDataQueueSize";
|
||||||
|
Parameters[1].EntryContext = &DriverExtension->MouseDataQueueSize;
|
||||||
|
Parameters[1].DefaultType = REG_DWORD;
|
||||||
|
Parameters[1].DefaultData = &DefaultMouseDataQueueSize;
|
||||||
|
Parameters[1].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
|
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
||||||
|
Parameters[2].Name = L"PointerDeviceBaseName";
|
||||||
|
Parameters[2].EntryContext = &DriverExtension->PointerDeviceBaseName;
|
||||||
|
Parameters[2].DefaultType = REG_SZ;
|
||||||
|
Parameters[2].DefaultData = &DefaultPointerDeviceBaseName;
|
||||||
|
Parameters[2].DefaultLength = sizeof(ULONG);
|
||||||
|
|
||||||
|
Status = RtlQueryRegistryValues(
|
||||||
|
RTL_REGISTRY_ABSOLUTE,
|
||||||
|
RegistryPath->Buffer,
|
||||||
|
Parameters,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Check values */
|
||||||
|
if (DriverExtension->ConnectMultiplePorts != 0
|
||||||
|
&& DriverExtension->ConnectMultiplePorts != 1)
|
||||||
|
{
|
||||||
|
DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
|
||||||
|
}
|
||||||
|
if (DriverExtension->MouseDataQueueSize == 0)
|
||||||
|
{
|
||||||
|
DriverExtension->MouseDataQueueSize = DefaultMouseDataQueueSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
CreatePointerClassDeviceObject(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
|
||||||
|
{
|
||||||
|
PMOUCLASS_DRIVER_EXTENSION DriverExtension;
|
||||||
|
ULONG DeviceId = 0;
|
||||||
|
ULONG PrefixLength;
|
||||||
|
UNICODE_STRING DeviceNameU;
|
||||||
|
PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
|
||||||
|
PDEVICE_OBJECT Fdo;
|
||||||
|
PMOUCLASS_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("CreatePointerClassDeviceObject(0x%p)\n", DriverObject);
|
||||||
|
|
||||||
|
/* Create new device object */
|
||||||
|
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||||
|
DeviceNameU.Length = 0;
|
||||||
|
DeviceNameU.MaximumLength =
|
||||||
|
wcslen(L"\\Device\\") * sizeof(WCHAR) /* "\Device\" */
|
||||||
|
+ DriverExtension->PointerDeviceBaseName.Length /* "PointerClass" */
|
||||||
|
+ 4 * sizeof(WCHAR) /* Id between 0 and 9999 */
|
||||||
|
+ sizeof(UNICODE_NULL); /* Final NULL char */
|
||||||
|
DeviceNameU.Buffer = ExAllocatePool(PagedPool, DeviceNameU.MaximumLength);
|
||||||
|
if (!DeviceNameU.Buffer)
|
||||||
|
{
|
||||||
|
DPRINT("ExAllocatePool() failed\n");
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->PointerDeviceBaseName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL);
|
||||||
|
DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
|
||||||
|
while (DeviceId < 9999)
|
||||||
|
{
|
||||||
|
DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW, L"%ld", DeviceId) * sizeof(WCHAR);
|
||||||
|
Status = IoCreateDevice(
|
||||||
|
DriverObject,
|
||||||
|
sizeof(MOUCLASS_DEVICE_EXTENSION),
|
||||||
|
&DeviceNameU,
|
||||||
|
FILE_DEVICE_MOUSE,
|
||||||
|
FILE_DEVICE_SECURE_OPEN,
|
||||||
|
FALSE,
|
||||||
|
&Fdo);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
goto cleanup;
|
||||||
|
else if (Status != STATUS_OBJECT_NAME_COLLISION)
|
||||||
|
{
|
||||||
|
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
DeviceId++;
|
||||||
|
}
|
||||||
|
DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->PointerDeviceBaseName);
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
cleanup:
|
||||||
|
ExFreePool(DeviceNameU.Buffer);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
||||||
|
RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION));
|
||||||
|
DeviceExtension->Common.IsClassDO = TRUE;
|
||||||
|
DeviceExtension->DriverExtension = DriverExtension;
|
||||||
|
DeviceExtension->PnpState = dsStopped;
|
||||||
|
KeInitializeSpinLock(&(DeviceExtension->SpinLock));
|
||||||
|
DeviceExtension->ReadIsPending = FALSE;
|
||||||
|
DeviceExtension->InputCount = 0;
|
||||||
|
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA));
|
||||||
|
Fdo->Flags |= DO_POWER_PAGABLE;
|
||||||
|
Fdo->Flags |= DO_BUFFERED_IO;
|
||||||
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
/* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
|
||||||
|
|
||||||
|
if (ClassDO)
|
||||||
|
*ClassDO = Fdo;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
MouclassCallback(
|
||||||
|
IN PDEVICE_OBJECT ClassDeviceObject,
|
||||||
|
IN OUT PMOUSE_INPUT_DATA MouseDataStart,
|
||||||
|
IN PMOUSE_INPUT_DATA MouseDataEnd,
|
||||||
|
IN OUT PULONG ConsumedCount)
|
||||||
|
{
|
||||||
|
PMOUCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||||
|
PIRP Irp = NULL;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
ULONG InputCount = MouseDataEnd - MouseDataStart;
|
||||||
|
ULONG ReadSize;
|
||||||
|
|
||||||
|
ASSERT(ClassDeviceExtension->Common.IsClassDO);
|
||||||
|
|
||||||
|
DPRINT("MouclassCallback()\n");
|
||||||
|
/* A filter driver might have consumed all the data already; I'm
|
||||||
|
* not sure if they are supposed to move the packets when they
|
||||||
|
* consume them though.
|
||||||
|
*/
|
||||||
|
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
|
||||||
|
{
|
||||||
|
Irp = ClassDeviceObject->CurrentIrp;
|
||||||
|
ClassDeviceObject->CurrentIrp = NULL;
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* A read request is waiting for input, so go straight to it */
|
||||||
|
RtlMoveMemory(
|
||||||
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
|
MouseDataStart,
|
||||||
|
sizeof(MOUSE_INPUT_DATA));
|
||||||
|
|
||||||
|
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
|
||||||
|
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
|
||||||
|
|
||||||
|
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||||
|
|
||||||
|
/* Skip the packet we just sent away */
|
||||||
|
MouseDataStart++;
|
||||||
|
(*ConsumedCount)++;
|
||||||
|
InputCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have data from the port driver and a higher service to send the data to */
|
||||||
|
if (InputCount != 0)
|
||||||
|
{
|
||||||
|
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
||||||
|
|
||||||
|
if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->MouseDataQueueSize)
|
||||||
|
ReadSize = ClassDeviceExtension->DriverExtension->MouseDataQueueSize - ClassDeviceExtension->InputCount;
|
||||||
|
else
|
||||||
|
ReadSize = InputCount;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: If we exceed the buffer, mouse data gets thrown away.. better
|
||||||
|
* solution?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move the mouse input data from the port data queue to our class data
|
||||||
|
* queue.
|
||||||
|
*/
|
||||||
|
RtlMoveMemory(
|
||||||
|
ClassDeviceExtension->PortData,
|
||||||
|
(PCHAR)MouseDataStart,
|
||||||
|
sizeof(MOUSE_INPUT_DATA) * ReadSize);
|
||||||
|
|
||||||
|
/* Move the pointer and counter up */
|
||||||
|
ClassDeviceExtension->PortData += ReadSize;
|
||||||
|
ClassDeviceExtension->InputCount += ReadSize;
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
||||||
|
(*ConsumedCount) += ReadSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("MouclassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Irp != NULL)
|
||||||
|
{
|
||||||
|
IoStartNextPacket(ClassDeviceObject, FALSE);
|
||||||
|
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Leaving MouclassCallback()\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send IOCTL_INTERNAL_MOUSE_CONNECT to pointer port */
|
||||||
|
static NTSTATUS
|
||||||
|
ConnectMousePortDriver(
|
||||||
|
IN PDEVICE_OBJECT PointerPortDO,
|
||||||
|
IN PDEVICE_OBJECT PointerClassDO)
|
||||||
|
{
|
||||||
|
KEVENT Event;
|
||||||
|
PIRP Irp;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
CONNECT_DATA ConnectData;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
|
ConnectData.ClassDeviceObject = PointerClassDO;
|
||||||
|
ConnectData.ClassService = MouclassCallback;
|
||||||
|
|
||||||
|
Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
|
||||||
|
PointerPortDO,
|
||||||
|
&ConnectData, sizeof(CONNECT_DATA),
|
||||||
|
NULL, 0,
|
||||||
|
TRUE, &Event, &IoStatus);
|
||||||
|
|
||||||
|
Status = IoCallDriver(PointerPortDO, Irp);
|
||||||
|
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
|
else
|
||||||
|
IoStatus.Status = Status;
|
||||||
|
|
||||||
|
return IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS NTAPI
|
||||||
|
MouclassAddDevice(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PDEVICE_OBJECT Pdo)
|
||||||
|
{
|
||||||
|
PMOUCLASS_DRIVER_EXTENSION DriverExtension;
|
||||||
|
PDEVICE_OBJECT Fdo;
|
||||||
|
PMOUCLASS_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("MouclassAddDevice called. Pdo = 0x%p\n", Pdo);
|
||||||
|
|
||||||
|
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||||
|
|
||||||
|
/* Create new device object */
|
||||||
|
Status = IoCreateDevice(
|
||||||
|
DriverObject,
|
||||||
|
sizeof(MOUCLASS_DEVICE_EXTENSION),
|
||||||
|
NULL,
|
||||||
|
Pdo->DeviceType,
|
||||||
|
FILE_DEVICE_SECURE_OPEN,
|
||||||
|
FALSE,
|
||||||
|
&Fdo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
||||||
|
RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION));
|
||||||
|
DeviceExtension->Common.IsClassDO = FALSE;
|
||||||
|
DeviceExtension->PnpState = dsStopped;
|
||||||
|
Fdo->Flags |= DO_POWER_PAGABLE;
|
||||||
|
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
|
||||||
|
IoDeleteDevice(Fdo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
Fdo->Flags |= DO_BUFFERED_IO;
|
||||||
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
if (DriverExtension->ConnectMultiplePorts)
|
||||||
|
Status = ConnectMousePortDriver(Fdo, DriverExtension->MainMouclassDeviceObject);
|
||||||
|
else
|
||||||
|
Status = ConnectMousePortDriver(Fdo, Fdo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status);
|
||||||
|
/* FIXME: why can't I cleanup without error? */
|
||||||
|
//IoDetachDevice(Fdo);
|
||||||
|
//IoDeleteDevice(Fdo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register GUID_DEVINTERFACE_MOUSE interface */
|
||||||
|
Status = IoRegisterDeviceInterface(
|
||||||
|
Pdo,
|
||||||
|
&GUID_DEVINTERFACE_MOUSE,
|
||||||
|
NULL,
|
||||||
|
&DeviceExtension->MouseInterfaceName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID NTAPI
|
||||||
|
MouclassStartIo(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PMOUCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||||
|
|
||||||
|
if (DeviceExtension->InputCount > 0)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
||||||
|
|
||||||
|
RtlMoveMemory(
|
||||||
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
|
DeviceExtension->PortData - DeviceExtension->InputCount,
|
||||||
|
sizeof(MOUSE_INPUT_DATA));
|
||||||
|
|
||||||
|
if (DeviceExtension->InputCount > 1)
|
||||||
|
{
|
||||||
|
RtlMoveMemory(
|
||||||
|
DeviceExtension->PortData - DeviceExtension->InputCount,
|
||||||
|
DeviceExtension->PortData - DeviceExtension->InputCount + 1,
|
||||||
|
(DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
|
||||||
|
}
|
||||||
|
DeviceExtension->PortData--;
|
||||||
|
DeviceExtension->InputCount--;
|
||||||
|
DeviceExtension->ReadIsPending = FALSE;
|
||||||
|
|
||||||
|
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
|
||||||
|
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
|
||||||
|
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||||
|
|
||||||
|
IoStartNextPacket(DeviceObject, FALSE);
|
||||||
|
KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeviceExtension->ReadIsPending = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
SearchForLegacyDrivers(
|
||||||
|
IN PMOUCLASS_DRIVER_EXTENSION DriverExtension)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT PortDeviceObject = NULL;
|
||||||
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* FIXME: search for more than once legacy driver */
|
||||||
|
|
||||||
|
Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
|
||||||
|
if(Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT("Could not open old device object (Status 0x%08lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DriverExtension->ConnectMultiplePorts)
|
||||||
|
Status = ConnectMousePortDriver(PortDeviceObject, DriverExtension->MainMouclassDeviceObject);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* What to do */
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard DriverEntry method.
|
||||||
|
*/
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
DriverEntry(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath)
|
||||||
|
{
|
||||||
|
PMOUCLASS_DRIVER_EXTENSION DriverExtension;
|
||||||
|
ULONG i;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = IoAllocateDriverObjectExtension(
|
||||||
|
DriverObject,
|
||||||
|
DriverObject,
|
||||||
|
sizeof(MOUCLASS_DRIVER_EXTENSION),
|
||||||
|
(PVOID*)&DriverExtension);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
RtlZeroMemory(DriverExtension, sizeof(MOUCLASS_DRIVER_EXTENSION));
|
||||||
|
|
||||||
|
Status = ReadRegistryEntries(RegistryPath, DriverExtension);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DriverExtension->ConnectMultiplePorts == 1)
|
||||||
|
{
|
||||||
|
Status = CreatePointerClassDeviceObject(
|
||||||
|
DriverObject,
|
||||||
|
&DriverExtension->MainMouclassDeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DriverObject->DriverExtension->AddDevice = MouclassAddDevice;
|
||||||
|
DriverObject->DriverUnload = DriverUnload;
|
||||||
|
|
||||||
|
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||||
|
DriverObject->MajorFunction[i] = IrpStub;
|
||||||
|
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouclassCreate;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouclassClose;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_READ] = MouclassRead;
|
||||||
|
DriverObject->DriverStartIo = MouclassStartIo;
|
||||||
|
|
||||||
|
SearchForLegacyDrivers(DriverExtension);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,65 @@
|
||||||
#define MOUSE_BUFFER_SIZE 100
|
#include <ntddk.h>
|
||||||
|
#include <kbdmou.h>
|
||||||
|
#include <ntddmou.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct _DEVICE_EXTENSION {
|
#if defined(__GNUC__)
|
||||||
PIO_WORKITEM WorkItem;
|
NTSTATUS NTAPI
|
||||||
KSPIN_LOCK SpinLock;
|
IoAttachDeviceToDeviceStackSafe(
|
||||||
BOOLEAN PassiveCallbackQueued;
|
IN PDEVICE_OBJECT SourceDevice,
|
||||||
BOOLEAN ReadIsPending;
|
IN PDEVICE_OBJECT TargetDevice,
|
||||||
ULONG InputCount;
|
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
|
||||||
PMOUSE_INPUT_DATA PortData;
|
#else
|
||||||
PDEVICE_OBJECT PortDeviceObject; // FIXME: Expand this to handle multiple port drivers (make *PortDeviceObject)
|
#error Unknown compiler!
|
||||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
dsStopped,
|
||||||
|
dsStarted,
|
||||||
|
dsPaused,
|
||||||
|
dsRemoved,
|
||||||
|
dsSurpriseRemoved
|
||||||
|
} MOUCLASS_DEVICE_STATE;
|
||||||
|
|
||||||
|
typedef struct _MOUCLASS_DRIVER_EXTENSION
|
||||||
|
{
|
||||||
|
/* Registry settings */
|
||||||
|
ULONG ConnectMultiplePorts;
|
||||||
|
ULONG MouseDataQueueSize;
|
||||||
|
UNICODE_STRING PointerDeviceBaseName;
|
||||||
|
|
||||||
|
PDEVICE_OBJECT MainMouclassDeviceObject;
|
||||||
|
} MOUCLASS_DRIVER_EXTENSION, *PMOUCLASS_DRIVER_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct _COMMON_DEVICE_EXTENSION
|
||||||
|
{
|
||||||
|
BOOLEAN IsClassDO;
|
||||||
|
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct _MOUPORT_DEVICE_EXTENSION
|
||||||
|
{
|
||||||
|
COMMON_DEVICE_EXTENSION Common;
|
||||||
|
} MOUPORT_DEVICE_EXTENSION, *PMOUPORT_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct _MOUCLASS_DEVICE_EXTENSION
|
||||||
|
{
|
||||||
|
COMMON_DEVICE_EXTENSION Common;
|
||||||
|
|
||||||
|
MOUCLASS_DEVICE_STATE PnpState;
|
||||||
|
PMOUCLASS_DRIVER_EXTENSION DriverExtension;
|
||||||
|
PDEVICE_OBJECT LowerDevice;
|
||||||
|
UNICODE_STRING MouseInterfaceName;
|
||||||
|
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
BOOLEAN ReadIsPending;
|
||||||
|
ULONG InputCount;
|
||||||
|
PMOUSE_INPUT_DATA PortData;
|
||||||
|
} MOUCLASS_DEVICE_EXTENSION, *PMOUCLASS_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
/* misc.c */
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
ForwardIrpAndForget(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<define name="__USE_W32API" />
|
<define name="__USE_W32API" />
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
|
<file>misc.c</file>
|
||||||
<file>mouclass.c</file>
|
<file>mouclass.c</file>
|
||||||
<file>mouclass.rc</file>
|
<file>mouclass.rc</file>
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -151,7 +151,7 @@ ProcessMouseInputData(PMOUSE_INPUT_DATA Data, ULONG InputCount)
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
MouseThreadMain(PVOID StartContext)
|
MouseThreadMain(PVOID StartContext)
|
||||||
{
|
{
|
||||||
UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\??\\Mouse");
|
UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClassPnp0");
|
||||||
OBJECT_ATTRIBUTES MouseObjectAttributes;
|
OBJECT_ATTRIBUTES MouseObjectAttributes;
|
||||||
IO_STATUS_BLOCK Iosb;
|
IO_STATUS_BLOCK Iosb;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -161,17 +161,20 @@ MouseThreadMain(PVOID StartContext)
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
Status = NtOpenFile(&MouseDeviceHandle,
|
do
|
||||||
|
{
|
||||||
|
LARGE_INTEGER DueTime;
|
||||||
|
KEVENT Event;
|
||||||
|
DueTime.QuadPart = (LONGLONG)(-10000000);
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
|
||||||
|
Status = NtOpenFile(&MouseDeviceHandle,
|
||||||
FILE_ALL_ACCESS,
|
FILE_ALL_ACCESS,
|
||||||
&MouseObjectAttributes,
|
&MouseObjectAttributes,
|
||||||
&Iosb,
|
&Iosb,
|
||||||
0,
|
0,
|
||||||
FILE_SYNCHRONOUS_IO_ALERT);
|
FILE_SYNCHRONOUS_IO_ALERT);
|
||||||
if(!NT_SUCCESS(Status))
|
} while (!NT_SUCCESS(Status));
|
||||||
{
|
|
||||||
DPRINT1("Win32K: Failed to open mouse.\n");
|
|
||||||
return; //(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
@ -422,17 +425,20 @@ KeyboardThreadMain(PVOID StartContext)
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
Status = NtOpenFile(&KeyboardDeviceHandle,
|
do
|
||||||
|
{
|
||||||
|
LARGE_INTEGER DueTime;
|
||||||
|
KEVENT Event;
|
||||||
|
DueTime.QuadPart = (LONGLONG)(-10000000);
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
|
||||||
|
Status = NtOpenFile(&KeyboardDeviceHandle,
|
||||||
FILE_ALL_ACCESS,
|
FILE_ALL_ACCESS,
|
||||||
&KeyboardObjectAttributes,
|
&KeyboardObjectAttributes,
|
||||||
&Iosb,
|
&Iosb,
|
||||||
0,
|
0,
|
||||||
FILE_SYNCHRONOUS_IO_ALERT);
|
FILE_SYNCHRONOUS_IO_ALERT);
|
||||||
if (!NT_SUCCESS(Status))
|
} while (!NT_SUCCESS(Status));
|
||||||
{
|
|
||||||
DPRINT1("Win32K: Failed to open keyboard.\n");
|
|
||||||
return; //(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not sure if converting this thread to a win32 thread is such
|
/* Not sure if converting this thread to a win32 thread is such
|
||||||
a great idea. Since we're posting keyboard messages to the focus
|
a great idea. Since we're posting keyboard messages to the focus
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue