#define INITGUID
#include "mouclass.h"
+static NTSTATUS
+SearchForLegacyDrivers(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PCLASS_DRIVER_EXTENSION DriverExtension);
+
static VOID NTAPI
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
}
static NTSTATUS NTAPI
-MouclassCreate(
+ClassCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: open all associated Port devices */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI
-MouclassClose(
+ClassClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: close all associated Port devices */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS NTAPI
+ClassCleanup(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("IRP_MJ_CLEANUP\n");
+
+ if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ return ForwardIrpAndForget(DeviceObject, Irp);
+
+ /* FIXME: cleanup all associated Port devices */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI
-MouclassRead(
+ClassRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return STATUS_PENDING;
}
+static NTSTATUS NTAPI
+ClassDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PCLASS_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status = Irp->IoStatus.Status;
+
+ DPRINT("IRP_MJ_DEVICE_CONTROL\n");
+
+ if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ return ForwardIrpAndForget(DeviceObject, Irp);
+
+ DeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_MOUSE_QUERY_ATTRIBUTES:
+ {
+ /* FIXME: We hope that all devices will return the same result.
+ * Ask only the first one */
+ PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
+ if (Head->Flink != Head)
+ {
+ /* We have at least one mouse */
+ PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
+ IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(DevExt->DeviceObject, Irp);
+ }
+ break;
+ }
+ default:
+ DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
+ IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
+ ASSERT(FALSE);
+ break;
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return Status;
+}
+
static NTSTATUS NTAPI
IrpStub(
IN PDEVICE_OBJECT DeviceObject,
/* Forward some IRPs to lower device */
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
{
+ case IRP_MJ_PNP:
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
return ForwardIrpAndForget(DeviceObject, Irp);
default:
static NTSTATUS
ReadRegistryEntries(
IN PUNICODE_STRING RegistryPath,
- IN PMOUCLASS_DRIVER_EXTENSION DriverExtension)
+ IN PCLASS_DRIVER_EXTENSION DriverExtension)
{
+ UNICODE_STRING ParametersRegistryKey;
RTL_QUERY_REGISTRY_TABLE Parameters[4];
NTSTATUS Status;
ULONG DefaultConnectMultiplePorts = 1;
- ULONG DefaultMouseDataQueueSize = 0x64;
- UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerClass");
+ ULONG DefaultDataQueueSize = 0x64;
+ UNICODE_STRING DefaultDeviceBaseName = RTL_CONSTANT_STRING(L"PointerClass");
+
+ ParametersRegistryKey.Length = 0;
+ ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
+ ParametersRegistryKey.Buffer = ExAllocatePool(PagedPool, ParametersRegistryKey.MaximumLength);
+ if (!ParametersRegistryKey.Buffer)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
+ RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
+ ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;
RtlZeroMemory(Parameters, sizeof(Parameters));
Parameters[0].DefaultType = REG_DWORD;
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].EntryContext = &DriverExtension->DataQueueSize;
Parameters[1].DefaultType = REG_DWORD;
- Parameters[1].DefaultData = &DefaultMouseDataQueueSize;
+ Parameters[1].DefaultData = &DefaultDataQueueSize;
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].EntryContext = &DriverExtension->DeviceBaseName;
Parameters[2].DefaultType = REG_SZ;
- Parameters[2].DefaultData = &DefaultPointerDeviceBaseName;
- Parameters[2].DefaultLength = sizeof(ULONG);
+ Parameters[2].DefaultData = &DefaultDeviceBaseName;
+ Parameters[2].DefaultLength = 0;
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
- RegistryPath->Buffer,
+ ParametersRegistryKey.Buffer,
Parameters,
NULL,
NULL);
{
DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
}
- if (DriverExtension->MouseDataQueueSize == 0)
+ if (DriverExtension->DataQueueSize == 0)
{
- DriverExtension->MouseDataQueueSize = DefaultMouseDataQueueSize;
+ DriverExtension->DataQueueSize = DefaultDataQueueSize;
}
}
+ else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ /* Registry path doesn't exist. Set defaults */
+ DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
+ DriverExtension->DataQueueSize = DefaultDataQueueSize;
+ Status = RtlDuplicateUnicodeString(
+ RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &DefaultDeviceBaseName,
+ &DriverExtension->DeviceBaseName);
+ }
return Status;
}
static NTSTATUS
-CreatePointerClassDeviceObject(
+CreateClassDeviceObject(
IN PDRIVER_OBJECT DriverObject,
OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
{
- PMOUCLASS_DRIVER_EXTENSION DriverExtension;
+ PCLASS_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;
+ PCLASS_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
- DPRINT("CreatePointerClassDeviceObject(0x%p)\n", DriverObject);
+ DPRINT("CreateClassDeviceObject(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 */
+ wcslen(L"\\Device\\") * sizeof(WCHAR) /* "\Device\" */
+ + DriverExtension->DeviceBaseName.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("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
goto cleanup;
}
- Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->PointerDeviceBaseName);
+ Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->DeviceBaseName);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW, L"%lu", DeviceId) * sizeof(WCHAR);
Status = IoCreateDevice(
DriverObject,
- sizeof(MOUCLASS_DEVICE_EXTENSION),
+ sizeof(CLASS_DEVICE_EXTENSION),
&DeviceNameU,
FILE_DEVICE_MOUSE,
FILE_DEVICE_SECURE_OPEN,
- FALSE,
+ TRUE,
&Fdo);
if (NT_SUCCESS(Status))
goto cleanup;
}
DeviceId++;
}
- DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->PointerDeviceBaseName);
- Status = STATUS_UNSUCCESSFUL;
+ DPRINT("Too many devices starting with '\\Device\\%wZ'\n", &DriverExtension->DeviceBaseName);
+ Status = STATUS_TOO_MANY_NAMES;
cleanup:
- ExFreePool(DeviceNameU.Buffer);
if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(DeviceNameU.Buffer);
return Status;
+ }
- DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
- RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION));
+ DeviceExtension = (PCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
+ RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
DeviceExtension->Common.IsClassDO = TRUE;
DeviceExtension->DriverExtension = DriverExtension;
- DeviceExtension->PnpState = dsStopped;
- KeInitializeSpinLock(&(DeviceExtension->SpinLock));
+ InitializeListHead(&DeviceExtension->ListHead);
+ KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
+ KeInitializeSpinLock(&DeviceExtension->SpinLock);
DeviceExtension->ReadIsPending = FALSE;
DeviceExtension->InputCount = 0;
- DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA));
+ DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(MOUSE_INPUT_DATA));
Fdo->Flags |= DO_POWER_PAGABLE;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
+ /* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
+ RtlWriteRegistryValue(
+ RTL_REGISTRY_DEVICEMAP,
+ DriverExtension->DeviceBaseName.Buffer,
+ DeviceNameU.Buffer,
+ REG_SZ,
+ DriverExtension->RegistryPath.Buffer,
+ DriverExtension->RegistryPath.MaximumLength);
+
+ ExFreePool(DeviceNameU.Buffer);
if (ClassDO)
*ClassDO = Fdo;
return STATUS_SUCCESS;
}
+static NTSTATUS
+FillOneEntry(
+ IN PDEVICE_OBJECT ClassDeviceObject,
+ IN PIRP Irp,
+ IN PMOUSE_INPUT_DATA DataStart)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (ClassDeviceObject->Flags & DO_BUFFERED_IO)
+ {
+ RtlCopyMemory(
+ Irp->AssociatedIrp.SystemBuffer,
+ DataStart,
+ sizeof(MOUSE_INPUT_DATA));
+ }
+ else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
+ {
+ PVOID DestAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+ if (DestAddress)
+ {
+ RtlCopyMemory(
+ DestAddress,
+ DataStart,
+ sizeof(MOUSE_INPUT_DATA));
+ }
+ else
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ _SEH_TRY
+ {
+ RtlCopyMemory(
+ Irp->UserBuffer,
+ DataStart,
+ sizeof(MOUSE_INPUT_DATA));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ return Status;
+}
+
static BOOLEAN
-MouclassCallback(
+ClassCallback(
IN PDEVICE_OBJECT ClassDeviceObject,
- IN OUT PMOUSE_INPUT_DATA MouseDataStart,
- IN PMOUSE_INPUT_DATA MouseDataEnd,
+ IN OUT PMOUSE_INPUT_DATA DataStart,
+ IN PMOUSE_INPUT_DATA DataEnd,
IN OUT PULONG ConsumedCount)
{
- PMOUCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
+ PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
PIRP Irp = NULL;
KIRQL OldIrql;
PIO_STACK_LOCATION Stack;
- ULONG InputCount = MouseDataEnd - MouseDataStart;
+ ULONG InputCount = DataEnd - DataStart;
ULONG ReadSize;
ASSERT(ClassDeviceExtension->Common.IsClassDO);
- DPRINT("MouclassCallback()\n");
+ KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
+
+ DPRINT("ClassCallback()\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)
{
+ NTSTATUS Status;
+
Irp = ClassDeviceObject->CurrentIrp;
ClassDeviceObject->CurrentIrp = NULL;
Stack = IoGetCurrentIrpStackLocation(Irp);
/* A read request is waiting for input, so go straight to it */
- /* FIXME: use SEH */
- RtlCopyMemory(
- Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->UserBuffer,
- MouseDataStart,
- sizeof(MOUSE_INPUT_DATA));
+ Status = FillOneEntry(
+ ClassDeviceObject,
+ Irp,
+ DataStart);
- /* 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);
+ if (NT_SUCCESS(Status))
+ {
+ /* 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;
+ ClassDeviceExtension->ReadIsPending = FALSE;
- /* Skip the packet we just sent away */
- MouseDataStart++;
- (*ConsumedCount)++;
- InputCount--;
+ /* Skip the packet we just sent away */
+ DataStart++;
+ (*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;
+ if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->DataQueueSize)
+ {
+ /*
+ * We're exceeding the buffer, and data will be thrown away...
+ * FIXME: What could we do, as we are at DISPATCH_LEVEL?
+ */
+ ReadSize = ClassDeviceExtension->DriverExtension->DataQueueSize - 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
+ * Move the input data from the port data queue to our class data
* queue.
*/
RtlMoveMemory(
ClassDeviceExtension->PortData,
- (PCHAR)MouseDataStart,
+ (PCHAR)DataStart,
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);
+ DPRINT("ClassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount);
}
+ KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
+
if (Irp != NULL)
{
IoStartNextPacket(ClassDeviceObject, FALSE);
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
}
- DPRINT("Leaving MouclassCallback()\n");
+ DPRINT("Leaving ClassCallback()\n");
return TRUE;
}
-/* Send IOCTL_INTERNAL_MOUSE_CONNECT to pointer port */
+/* Send IOCTL_INTERNAL_*_CONNECT to port */
static NTSTATUS
-ConnectMousePortDriver(
- IN PDEVICE_OBJECT PointerPortDO,
- IN PDEVICE_OBJECT PointerClassDO)
+ConnectPortDriver(
+ IN PDEVICE_OBJECT PortDO,
+ IN PDEVICE_OBJECT ClassDO)
{
KEVENT Event;
PIRP Irp;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
- ConnectData.ClassDeviceObject = PointerClassDO;
- ConnectData.ClassService = MouclassCallback;
+ ConnectData.ClassDeviceObject = ClassDO;
+ ConnectData.ClassService = ClassCallback;
Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
- PointerPortDO,
+ PortDO,
&ConnectData, sizeof(CONNECT_DATA),
NULL, 0,
TRUE, &Event, &IoStatus);
- Status = IoCallDriver(PointerPortDO, Irp);
+ Status = IoCallDriver(PortDO, Irp);
if (Status == STATUS_PENDING)
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
else
IoStatus.Status = Status;
+ if (NT_SUCCESS(IoStatus.Status))
+ {
+ ObReferenceObject(PortDO);
+ ExInterlockedInsertTailList(
+ &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListHead,
+ &((PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension)->ListEntry,
+ &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListSpinLock);
+ if (ClassDO->StackSize <= PortDO->StackSize)
+ {
+ /* Increase the stack size, in case we have to
+ * forward some IRPs to the port device object
+ */
+ ClassDO->StackSize = PortDO->StackSize + 1;
+ }
+ }
+
return IoStatus.Status;
}
static NTSTATUS NTAPI
-MouclassAddDevice(
+ClassAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
- PMOUCLASS_DRIVER_EXTENSION DriverExtension;
- PDEVICE_OBJECT Fdo;
- PMOUCLASS_DEVICE_EXTENSION DeviceExtension;
+ PCLASS_DRIVER_EXTENSION DriverExtension;
+ PDEVICE_OBJECT Fdo = NULL;
+ PPORT_DEVICE_EXTENSION DeviceExtension = NULL;
NTSTATUS Status;
- DPRINT("MouclassAddDevice called. Pdo = 0x%p\n", Pdo);
+ DPRINT("ClassAddDevice called. Pdo = 0x%p\n", Pdo);
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
+ if (Pdo == NULL)
+ /* We're getting a NULL Pdo at the first call as we're a legacy driver.
+ * Use it to search for legacy port drivers. */
+ return SearchForLegacyDrivers(DriverObject, DriverExtension);
+
/* Create new device object */
Status = IoCreateDevice(
DriverObject,
- sizeof(MOUCLASS_DEVICE_EXTENSION),
+ sizeof(PORT_DEVICE_EXTENSION),
NULL,
Pdo->DeviceType,
- FILE_DEVICE_SECURE_OPEN,
- FALSE,
+ Pdo->Characteristics & FILE_DEVICE_SECURE_OPEN ? FILE_DEVICE_SECURE_OPEN : 0,
+ TRUE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
- return Status;
+ goto cleanup;
}
- DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
- RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION));
+ DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
+ RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
DeviceExtension->Common.IsClassDO = FALSE;
+ DeviceExtension->DeviceObject = Fdo;
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;
+ goto cleanup;
}
- Fdo->Flags |= DO_BUFFERED_IO;
- Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+ if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE)
+ Fdo->Flags |= DO_POWER_PAGABLE;
+ if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
+ Fdo->Flags |= DO_BUFFERED_IO;
+ if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
+ Fdo->Flags |= DO_DIRECT_IO;
if (DriverExtension->ConnectMultiplePorts)
- Status = ConnectMousePortDriver(Fdo, DriverExtension->MainMouclassDeviceObject);
+ DeviceExtension->ClassDO = DriverExtension->MainClassDeviceObject;
else
- Status = ConnectMousePortDriver(Fdo, Fdo);
+ {
+ /* We need a new class device object for this Fdo */
+ Status = CreateClassDeviceObject(
+ DriverObject,
+ &DeviceExtension->ClassDO);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status);
+ goto cleanup;
+ }
+ }
+ Status = ConnectPortDriver(Fdo, DeviceExtension->ClassDO);
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;
+ DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
+ goto cleanup;
}
+ Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- /* Register GUID_DEVINTERFACE_MOUSE interface */
+ /* Register interface */
Status = IoRegisterDeviceInterface(
Pdo,
&GUID_DEVINTERFACE_MOUSE,
NULL,
- &DeviceExtension->MouseInterfaceName);
- if (!NT_SUCCESS(Status))
+ &DeviceExtension->InterfaceName);
+ if (Status == STATUS_INVALID_PARAMETER_1)
+ {
+ /* The Pdo was a strange one ; maybe it is a legacy device.
+ * Ignore the error. */
+ return STATUS_SUCCESS;
+ }
+ else if (!NT_SUCCESS(Status))
{
DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
- return Status;
+ goto cleanup;
}
return STATUS_SUCCESS;
+
+cleanup:
+ if (DeviceExtension)
+ {
+ if (DeviceExtension->LowerDevice)
+ IoDetachDevice(DeviceExtension->LowerDevice);
+ if (DriverExtension->ConnectMultiplePorts && DeviceExtension->ClassDO)
+ {
+ PCLASS_DEVICE_EXTENSION ClassDeviceExtension;
+ ClassDeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceExtension->ClassDO->DeviceExtension;
+ ExFreePool(ClassDeviceExtension->PortData);
+ }
+ }
+ if (Fdo)
+ IoDeleteDevice(Fdo);
+ return Status;
}
static VOID NTAPI
-MouclassStartIo(
+ClassStartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- PMOUCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(DeviceExtension->Common.IsClassDO);
if (DeviceExtension->InputCount > 0)
{
KIRQL oldIrql;
+ NTSTATUS Status;
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
- /* FIXME: use SEH */
- RtlCopyMemory(
- Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->UserBuffer,
- DeviceExtension->PortData - DeviceExtension->InputCount,
- sizeof(MOUSE_INPUT_DATA));
+ Status = FillOneEntry(
+ DeviceObject,
+ Irp,
+ DeviceExtension->PortData - DeviceExtension->InputCount);
- if (DeviceExtension->InputCount > 1)
+ if (NT_SUCCESS(Status))
{
- RtlMoveMemory(
- DeviceExtension->PortData - DeviceExtension->InputCount,
- DeviceExtension->PortData - DeviceExtension->InputCount + 1,
- (DeviceExtension->InputCount - 1) * 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;
+
+ Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
+ Stack->Parameters.Read.Length = 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);
+
+ /* Go to next packet and complete this request */
+ Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
IoStartNextPacket(DeviceObject, FALSE);
static NTSTATUS
SearchForLegacyDrivers(
IN PDRIVER_OBJECT DriverObject,
- IN PMOUCLASS_DRIVER_EXTENSION DriverExtension)
+ IN PCLASS_DRIVER_EXTENSION DriverExtension)
{
UNICODE_STRING DeviceMapKeyU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
UNICODE_STRING PortBaseName = {0, };
/* Create port base name, by replacing Class by Port at the end of the class base name */
Status = RtlDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
- &DriverExtension->PointerDeviceBaseName,
+ &DriverExtension->DeviceBaseName,
&PortBaseName);
if (!NT_SUCCESS(Status))
{
/* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
InitializeObjectAttributes(&ObjectAttributes, &DeviceMapKeyU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
- if (!NT_SUCCESS(Status))
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ DPRINT("HKLM\\HARDWARE\\DEVICEMAP is non-existent\n");
+ Status = STATUS_SUCCESS;
+ goto cleanup;
+ }
+ else if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
goto cleanup;
/* Open sub key */
InitializeObjectAttributes(&ObjectAttributes, &PortBaseName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceMapKey, NULL);
Status = ZwOpenKey(&hPortKey, KEY_QUERY_VALUE, &ObjectAttributes);
- if (!NT_SUCCESS(Status))
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ DPRINT("HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName);
+ Status = STATUS_SUCCESS;
+ goto cleanup;
+ }
+ else if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
- DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
goto cleanup;
}
if (!NT_SUCCESS(Status))
{
DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status);
+ continue;
}
+ DPRINT("Legacy driver found: %wZ\n", &PortDeviceObject->DriverObject->DriverName);
- /* Connect the port device object */
- if (DriverExtension->ConnectMultiplePorts)
+ Status = ClassAddDevice(DriverObject, PortDeviceObject);
+ if (!NT_SUCCESS(Status))
{
- Status = ConnectMousePortDriver(PortDeviceObject, DriverExtension->MainMouclassDeviceObject);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: Log the error */
- DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status);
- /* FIXME: cleanup */
- }
- }
- else
- {
- PDEVICE_OBJECT ClassDO;
- Status = CreatePointerClassDeviceObject(DriverObject, &ClassDO);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: Log the error */
- DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
- /* FIXME: cleanup */
- continue;
- }
- Status = ConnectMousePortDriver(PortDeviceObject, ClassDO);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: Log the error */
- DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status);
- /* FIXME: cleanup */
- }
+ /* FIXME: Log the error */
+ DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status);
}
}
if (Status == STATUS_NO_MORE_ENTRIES)
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
- PMOUCLASS_DRIVER_EXTENSION DriverExtension;
+ PCLASS_DRIVER_EXTENSION DriverExtension;
ULONG i;
NTSTATUS Status;
Status = IoAllocateDriverObjectExtension(
DriverObject,
DriverObject,
- sizeof(MOUCLASS_DRIVER_EXTENSION),
+ sizeof(CLASS_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));
+ RtlZeroMemory(DriverExtension, sizeof(CLASS_DRIVER_EXTENSION));
+
+ Status = RtlDuplicateUnicodeString(
+ RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ RegistryPath,
+ &DriverExtension->RegistryPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status);
+ return Status;
+ }
Status = ReadRegistryEntries(RegistryPath, DriverExtension);
if (!NT_SUCCESS(Status))
if (DriverExtension->ConnectMultiplePorts == 1)
{
- Status = CreatePointerClassDeviceObject(
+ Status = CreateClassDeviceObject(
DriverObject,
- &DriverExtension->MainMouclassDeviceObject);
+ &DriverExtension->MainClassDeviceObject);
if (!NT_SUCCESS(Status))
{
- DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
+ DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status);
return Status;
}
}
- DriverObject->DriverExtension->AddDevice = MouclassAddDevice;
+ DriverObject->DriverExtension->AddDevice = ClassAddDevice;
DriverObject->DriverUnload = DriverUnload;
- for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+ 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;
-
- Status = SearchForLegacyDrivers(DriverObject, DriverExtension);
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = ClassCreate;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = ClassClose;
+ DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup;
+ DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
+ DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
+ DriverObject->DriverStartIo = ClassStartIo;
- return Status;
+ return STATUS_SUCCESS;
}