Send IOCTL_* to the port device objects. Keyboard LEDs should now work

Simplify code in SearchForLegacyDrivers

svn path=/trunk/; revision=21188
This commit is contained in:
Hervé Poussineau 2006-02-24 13:38:14 +00:00
parent 5b247bc560
commit 2c5b094ca5
4 changed files with 118 additions and 66 deletions

View file

@ -96,7 +96,7 @@ ClassDeviceControl(
IN PIRP Irp) IN PIRP Irp)
{ {
PCLASS_DEVICE_EXTENSION DeviceExtension; PCLASS_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status; NTSTATUS Status = Irp->IoStatus.Status;
DPRINT("IRP_MJ_DEVICE_CONTROL\n"); DPRINT("IRP_MJ_DEVICE_CONTROL\n");
@ -111,15 +111,44 @@ ClassDeviceControl(
case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
case IOCTL_KEYBOARD_QUERY_INDICATORS: case IOCTL_KEYBOARD_QUERY_INDICATORS:
case IOCTL_KEYBOARD_QUERY_TYPEMATIC: case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
{
/* 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 keyboard */
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;
}
case IOCTL_KEYBOARD_SET_INDICATORS: case IOCTL_KEYBOARD_SET_INDICATORS:
case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */ case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */
/* FIXME: send it to all associated Port devices */ {
Status = STATUS_NOT_SUPPORTED; /* Send it to all associated Port devices */
PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
PLIST_ENTRY Entry = Head->Flink;
Status = STATUS_SUCCESS;
while (Entry != Head)
{
PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry);
NTSTATUS IntermediateStatus;
IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp);
if (!NT_SUCCESS(IntermediateStatus))
Status = IntermediateStatus;
Entry = Entry->Flink;
}
break; break;
}
default: default:
DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n", DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode); IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_NOT_SUPPORTED; break;
} }
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
@ -141,6 +170,7 @@ IrpStub(
/* Forward some IRPs to lower device */ /* Forward some IRPs to lower device */
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
{ {
case IRP_MJ_PNP:
case IRP_MJ_INTERNAL_DEVICE_CONTROL: case IRP_MJ_INTERNAL_DEVICE_CONTROL:
return ForwardIrpAndForget(DeviceObject, Irp); return ForwardIrpAndForget(DeviceObject, Irp);
default: default:
@ -325,7 +355,9 @@ cleanup:
RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION)); RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
DeviceExtension->Common.IsClassDO = TRUE; DeviceExtension->Common.IsClassDO = TRUE;
DeviceExtension->DriverExtension = DriverExtension; DeviceExtension->DriverExtension = DriverExtension;
KeInitializeSpinLock(&(DeviceExtension->SpinLock)); InitializeListHead(&DeviceExtension->ListHead);
KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
KeInitializeSpinLock(&DeviceExtension->SpinLock);
DeviceExtension->ReadIsPending = FALSE; DeviceExtension->ReadIsPending = FALSE;
DeviceExtension->InputCount = 0; DeviceExtension->InputCount = 0;
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA)); DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA));
@ -478,7 +510,20 @@ ConnectPortDriver(
IoStatus.Status = Status; IoStatus.Status = Status;
if (NT_SUCCESS(IoStatus.Status)) if (NT_SUCCESS(IoStatus.Status))
{
ObReferenceObject(PortDO); 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; return IoStatus.Status;
} }
@ -520,6 +565,7 @@ ClassAddDevice(
DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension; DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION)); RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
DeviceExtension->Common.IsClassDO = FALSE; DeviceExtension->Common.IsClassDO = FALSE;
DeviceExtension->DeviceObject = Fdo;
DeviceExtension->PnpState = dsStopped; DeviceExtension->PnpState = dsStopped;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -541,8 +587,8 @@ ClassAddDevice(
{ {
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status); DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
IoDetachDevice(DeviceExtension->LowerDevice); IoDetachDevice(DeviceExtension->LowerDevice);
/* FIXME: why can't I cleanup without error? */ ObDereferenceObject(Fdo);
//IoDeleteDevice(Fdo); IoDeleteDevice(Fdo);
return Status; return Status;
} }
Fdo->Flags &= ~DO_DEVICE_INITIALIZING; Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
@ -698,35 +744,14 @@ SearchForLegacyDrivers(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status); DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status);
continue;
} }
/* Connect the port device object */ Status = ClassAddDevice(DriverObject, PortDeviceObject);
if (DriverExtension->ConnectMultiplePorts) if (!NT_SUCCESS(Status))
{ {
Status = ConnectPortDriver(PortDeviceObject, DriverExtension->MainClassDeviceObject); /* FIXME: Log the error */
if (!NT_SUCCESS(Status)) DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status);
{
/* FIXME: Log the error */
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
}
}
else
{
PDEVICE_OBJECT ClassDO;
Status = CreateClassDeviceObject(DriverObject, &ClassDO);
if (!NT_SUCCESS(Status))
{
/* FIXME: Log the error */
DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
continue;
}
Status = ConnectPortDriver(PortDeviceObject, ClassDO);
if (!NT_SUCCESS(Status))
{
/* FIXME: Log the error */
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
IoDeleteDevice(ClassDO);
}
} }
} }
if (Status == STATUS_NO_MORE_ENTRIES) if (Status == STATUS_NO_MORE_ENTRIES)
@ -806,6 +831,7 @@ DriverEntry(
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup;
DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead; DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
DriverObject->DriverStartIo = ClassStartIo; DriverObject->DriverStartIo = ClassStartIo;
return STATUS_SUCCESS; return STATUS_SUCCESS;

View file

@ -35,6 +35,8 @@ typedef struct _PORT_DEVICE_EXTENSION
{ {
COMMON_DEVICE_EXTENSION Common; COMMON_DEVICE_EXTENSION Common;
LIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
PORT_DEVICE_STATE PnpState; PORT_DEVICE_STATE PnpState;
PDEVICE_OBJECT LowerDevice; PDEVICE_OBJECT LowerDevice;
UNICODE_STRING InterfaceName; UNICODE_STRING InterfaceName;
@ -46,6 +48,8 @@ typedef struct _CLASS_DEVICE_EXTENSION
PCLASS_DRIVER_EXTENSION DriverExtension; PCLASS_DRIVER_EXTENSION DriverExtension;
LIST_ENTRY ListHead;
KSPIN_LOCK ListSpinLock;
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock;
BOOLEAN ReadIsPending; BOOLEAN ReadIsPending;
ULONG InputCount; ULONG InputCount;
@ -54,6 +58,11 @@ typedef struct _CLASS_DEVICE_EXTENSION
/* misc.c */ /* misc.c */
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS NTAPI NTSTATUS NTAPI
ForwardIrpAndForget( ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,

View file

@ -96,7 +96,7 @@ ClassDeviceControl(
IN PIRP Irp) IN PIRP Irp)
{ {
PCLASS_DEVICE_EXTENSION DeviceExtension; PCLASS_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status; NTSTATUS Status = Irp->IoStatus.Status;
DPRINT("IRP_MJ_DEVICE_CONTROL\n"); DPRINT("IRP_MJ_DEVICE_CONTROL\n");
@ -108,13 +108,24 @@ ClassDeviceControl(
switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode) switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)
{ {
case IOCTL_MOUSE_QUERY_ATTRIBUTES: case IOCTL_MOUSE_QUERY_ATTRIBUTES:
/* FIXME */ {
Status = STATUS_NOT_SUPPORTED; /* 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 keyboard */
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; break;
}
default: default:
DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n", DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode); IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_NOT_SUPPORTED; break;
} }
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
@ -320,7 +331,9 @@ cleanup:
RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION)); RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
DeviceExtension->Common.IsClassDO = TRUE; DeviceExtension->Common.IsClassDO = TRUE;
DeviceExtension->DriverExtension = DriverExtension; DeviceExtension->DriverExtension = DriverExtension;
KeInitializeSpinLock(&(DeviceExtension->SpinLock)); InitializeListHead(&DeviceExtension->ListHead);
KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
KeInitializeSpinLock(&DeviceExtension->SpinLock);
DeviceExtension->ReadIsPending = FALSE; DeviceExtension->ReadIsPending = FALSE;
DeviceExtension->InputCount = 0; DeviceExtension->InputCount = 0;
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(MOUSE_INPUT_DATA)); DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(MOUSE_INPUT_DATA));
@ -469,7 +482,20 @@ ConnectPortDriver(
IoStatus.Status = Status; IoStatus.Status = Status;
if (NT_SUCCESS(IoStatus.Status)) if (NT_SUCCESS(IoStatus.Status))
{
ObReferenceObject(PortDO); 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; return IoStatus.Status;
} }
@ -511,6 +537,7 @@ ClassAddDevice(
DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension; DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION)); RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
DeviceExtension->Common.IsClassDO = FALSE; DeviceExtension->Common.IsClassDO = FALSE;
DeviceExtension->DeviceObject = Fdo;
DeviceExtension->PnpState = dsStopped; DeviceExtension->PnpState = dsStopped;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -532,8 +559,8 @@ ClassAddDevice(
{ {
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status); DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
IoDetachDevice(DeviceExtension->LowerDevice); IoDetachDevice(DeviceExtension->LowerDevice);
/* FIXME: why can't I cleanup without error? */ ObDereferenceObject(Fdo);
//IoDeleteDevice(Fdo); IoDeleteDevice(Fdo);
return Status; return Status;
} }
Fdo->Flags &= ~DO_DEVICE_INITIALIZING; Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
@ -689,35 +716,14 @@ SearchForLegacyDrivers(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status); DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status);
continue;
} }
/* Connect the port device object */ Status = ClassAddDevice(DriverObject, PortDeviceObject);
if (DriverExtension->ConnectMultiplePorts) if (!NT_SUCCESS(Status))
{ {
Status = ConnectPortDriver(PortDeviceObject, DriverExtension->MainClassDeviceObject); /* FIXME: Log the error */
if (!NT_SUCCESS(Status)) DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status);
{
/* FIXME: Log the error */
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
}
}
else
{
PDEVICE_OBJECT ClassDO;
Status = CreateClassDeviceObject(DriverObject, &ClassDO);
if (!NT_SUCCESS(Status))
{
/* FIXME: Log the error */
DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
continue;
}
Status = ConnectPortDriver(PortDeviceObject, ClassDO);
if (!NT_SUCCESS(Status))
{
/* FIXME: Log the error */
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
IoDeleteDevice(ClassDO);
}
} }
} }
if (Status == STATUS_NO_MORE_ENTRIES) if (Status == STATUS_NO_MORE_ENTRIES)
@ -797,6 +803,7 @@ DriverEntry(
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup;
DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead; DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
DriverObject->DriverStartIo = ClassStartIo; DriverObject->DriverStartIo = ClassStartIo;
return STATUS_SUCCESS; return STATUS_SUCCESS;

View file

@ -4,6 +4,7 @@
#include <stdio.h> #include <stdio.h>
#define MAX_PATH 260 #define MAX_PATH 260
typedef enum typedef enum
{ {
dsStopped, dsStopped,
@ -34,6 +35,8 @@ typedef struct _PORT_DEVICE_EXTENSION
{ {
COMMON_DEVICE_EXTENSION Common; COMMON_DEVICE_EXTENSION Common;
LIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
PORT_DEVICE_STATE PnpState; PORT_DEVICE_STATE PnpState;
PDEVICE_OBJECT LowerDevice; PDEVICE_OBJECT LowerDevice;
UNICODE_STRING InterfaceName; UNICODE_STRING InterfaceName;
@ -45,6 +48,8 @@ typedef struct _CLASS_DEVICE_EXTENSION
PCLASS_DRIVER_EXTENSION DriverExtension; PCLASS_DRIVER_EXTENSION DriverExtension;
LIST_ENTRY ListHead;
KSPIN_LOCK ListSpinLock;
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock;
BOOLEAN ReadIsPending; BOOLEAN ReadIsPending;
ULONG InputCount; ULONG InputCount;
@ -53,6 +58,11 @@ typedef struct _CLASS_DEVICE_EXTENSION
/* misc.c */ /* misc.c */
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS NTAPI NTSTATUS NTAPI
ForwardIrpAndForget( ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,