mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
- kbdclass/mouclass should be able to return more than one keystroke/mouse move during a IRP_MJ_READ.
- Better cleanup in case of error in ClassAddDevice - Registering the interface is optional. Don't fail in case of error. svn path=/trunk/; revision=23129
This commit is contained in:
parent
de3f42794a
commit
2c59aa9330
4 changed files with 205 additions and 127 deletions
|
@ -126,7 +126,7 @@ ClassDeviceControl(
|
|||
PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
|
||||
if (Head->Flink != Head)
|
||||
{
|
||||
/* We have at least one keyboard */
|
||||
/* We have at least one device */
|
||||
PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
|
||||
IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
@ -375,6 +375,7 @@ cleanup:
|
|||
ExFreePool(DeviceNameU.Buffer);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
DeviceExtension->DeviceName = DeviceNameU.Buffer;
|
||||
Fdo->Flags |= DO_POWER_PAGABLE;
|
||||
Fdo->Flags |= DO_BUFFERED_IO; /* FIXME: Why is it needed for 1st stage setup? */
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
@ -383,13 +384,11 @@ cleanup:
|
|||
RtlWriteRegistryValue(
|
||||
RTL_REGISTRY_DEVICEMAP,
|
||||
DriverExtension->DeviceBaseName.Buffer,
|
||||
DeviceNameU.Buffer,
|
||||
DeviceExtension->DeviceName,
|
||||
REG_SZ,
|
||||
DriverExtension->RegistryPath.Buffer,
|
||||
DriverExtension->RegistryPath.MaximumLength);
|
||||
|
||||
ExFreePool(DeviceNameU.Buffer);
|
||||
|
||||
if (ClassDO)
|
||||
*ClassDO = Fdo;
|
||||
|
||||
|
@ -397,10 +396,11 @@ cleanup:
|
|||
}
|
||||
|
||||
static NTSTATUS
|
||||
FillOneEntry(
|
||||
FillEntries(
|
||||
IN PDEVICE_OBJECT ClassDeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PKEYBOARD_INPUT_DATA DataStart)
|
||||
IN PKEYBOARD_INPUT_DATA DataStart,
|
||||
IN SIZE_T NumberOfEntries)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
|
@ -409,7 +409,7 @@ FillOneEntry(
|
|||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
DataStart,
|
||||
sizeof(KEYBOARD_INPUT_DATA));
|
||||
NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
|
||||
}
|
||||
else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
|
||||
{
|
||||
|
@ -419,7 +419,7 @@ FillOneEntry(
|
|||
RtlCopyMemory(
|
||||
DestAddress,
|
||||
DataStart,
|
||||
sizeof(KEYBOARD_INPUT_DATA));
|
||||
NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
|
||||
}
|
||||
else
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
|
@ -431,7 +431,7 @@ FillOneEntry(
|
|||
RtlCopyMemory(
|
||||
Irp->UserBuffer,
|
||||
DataStart,
|
||||
sizeof(KEYBOARD_INPUT_DATA));
|
||||
NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
|
@ -453,7 +453,6 @@ ClassCallback(
|
|||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
PIRP Irp = NULL;
|
||||
KIRQL OldIrql;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
ULONG InputCount = DataEnd - DataStart;
|
||||
ULONG ReadSize;
|
||||
|
||||
|
@ -468,31 +467,35 @@ ClassCallback(
|
|||
*/
|
||||
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
|
||||
{
|
||||
/* A read request is waiting for input, so go straight to it */
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
Irp = ClassDeviceObject->CurrentIrp;
|
||||
ClassDeviceObject->CurrentIrp = NULL;
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* A read request is waiting for input, so go straight to it */
|
||||
Status = FillOneEntry(
|
||||
NumberOfEntries = MIN(
|
||||
InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
|
||||
|
||||
Status = FillEntries(
|
||||
ClassDeviceObject,
|
||||
Irp,
|
||||
DataStart);
|
||||
DataStart,
|
||||
NumberOfEntries);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
|
||||
Stack->Parameters.Read.Length = sizeof(KEYBOARD_INPUT_DATA);
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
|
||||
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
/* Skip the packet we just sent away */
|
||||
DataStart++;
|
||||
(*ConsumedCount)++;
|
||||
InputCount--;
|
||||
DataStart += NumberOfEntries;
|
||||
(*ConsumedCount) += NumberOfEntries;
|
||||
InputCount -= NumberOfEntries;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,11 +564,14 @@ ConnectPortDriver(
|
|||
ConnectData.ClassDeviceObject = ClassDO;
|
||||
ConnectData.ClassService = ClassCallback;
|
||||
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_KEYBOARD_CONNECT,
|
||||
Irp = IoBuildDeviceIoControlRequest(
|
||||
IOCTL_INTERNAL_KEYBOARD_CONNECT,
|
||||
PortDO,
|
||||
&ConnectData, sizeof(CONNECT_DATA),
|
||||
NULL, 0,
|
||||
TRUE, &Event, &IoStatus);
|
||||
if (!Irp)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
Status = IoCallDriver(PortDO, Irp);
|
||||
|
||||
|
@ -593,16 +599,65 @@ ConnectPortDriver(
|
|||
return IoStatus.Status;
|
||||
}
|
||||
|
||||
/* Send IOCTL_INTERNAL_*_DISCONNECT to port */
|
||||
static NTSTATUS
|
||||
DisconnectPortDriver(
|
||||
/* Send IOCTL_INTERNAL_*_DISCONNECT to port + destroy the Port DO */
|
||||
static VOID
|
||||
DestroyPortDriver(
|
||||
IN PDEVICE_OBJECT PortDO)
|
||||
{
|
||||
DPRINT("Disconnecting PortDO %p [%wZ]\n",
|
||||
PPORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension;
|
||||
PCLASS_DRIVER_EXTENSION DriverExtension;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("Destroying PortDO %p [%wZ]\n",
|
||||
PortDO, &PortDO->DriverObject->DriverName);
|
||||
|
||||
DPRINT1("FIXME: Need to send IOCTL_INTERNAL_*_DISCONNECT\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
DeviceExtension = (PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension;
|
||||
ClassDeviceExtension = DeviceExtension->ClassDO->DeviceExtension;
|
||||
DriverExtension = IoGetDriverObjectExtension(PortDO->DriverObject, PortDO->DriverObject);
|
||||
|
||||
/* Send IOCTL_INTERNAL_*_DISCONNECT */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(
|
||||
IOCTL_INTERNAL_KEYBOARD_DISCONNECT,
|
||||
PortDO,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
TRUE, &Event, &IoStatus);
|
||||
if (Irp)
|
||||
{
|
||||
Status = IoCallDriver(PortDO, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
/* Remove from ClassDeviceExtension->ListHead list */
|
||||
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
|
||||
RemoveHeadList(DeviceExtension->ListEntry.Blink);
|
||||
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
|
||||
|
||||
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
|
||||
RtlDeleteRegistryValue(
|
||||
RTL_REGISTRY_DEVICEMAP,
|
||||
DriverExtension->DeviceBaseName.Buffer,
|
||||
ClassDeviceExtension->DeviceName);
|
||||
|
||||
if (DeviceExtension->LowerDevice)
|
||||
IoDetachDevice(DeviceExtension->LowerDevice);
|
||||
ObDereferenceObject(PortDO);
|
||||
|
||||
if (!DriverExtension->ConnectMultiplePorts && DeviceExtension->ClassDO)
|
||||
{
|
||||
ExFreePool(ClassDeviceExtension->PortData);
|
||||
ExFreePool((PVOID)ClassDeviceExtension->DeviceName);
|
||||
IoDeleteDevice(DeviceExtension->ClassDO);
|
||||
}
|
||||
|
||||
IoDeleteDevice(PortDO);
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
|
@ -679,44 +734,21 @@ ClassAddDevice(
|
|||
}
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
/* Register interface */
|
||||
/* Register interface ; ignore the error (if any) as having
|
||||
* a registred interface is not so important... */
|
||||
Status = IoRegisterDeviceInterface(
|
||||
Pdo,
|
||||
&GUID_DEVINTERFACE_KEYBOARD,
|
||||
NULL,
|
||||
&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);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!NT_SUCCESS(Status))
|
||||
DeviceExtension->InterfaceName.Length = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (!(Fdo->Flags & DO_DEVICE_INITIALIZING))
|
||||
DisconnectPortDriver(Fdo);
|
||||
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);
|
||||
/* FIXME BSOD for second boot when u press on finsih buttom or wait timeout */
|
||||
//IoDeleteDevice(DeviceExtension->ClassDO);
|
||||
}
|
||||
}
|
||||
if (Fdo)
|
||||
IoDeleteDevice(Fdo);
|
||||
DestroyPortDriver(Fdo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -726,7 +758,6 @@ ClassStartIo(
|
|||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
|
@ -734,29 +765,34 @@ ClassStartIo(
|
|||
{
|
||||
KIRQL oldIrql;
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
NumberOfEntries = MIN(
|
||||
DeviceExtension->InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
|
||||
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
||||
|
||||
Status = FillOneEntry(
|
||||
Status = FillEntries(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
&DeviceExtension->PortData[DeviceExtension->InputCount - 1]);
|
||||
DeviceExtension->PortData,
|
||||
NumberOfEntries);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (DeviceExtension->InputCount > 1)
|
||||
if (DeviceExtension->InputCount > NumberOfEntries)
|
||||
{
|
||||
RtlMoveMemory(
|
||||
&DeviceExtension->PortData[1],
|
||||
&DeviceExtension->PortData[0],
|
||||
(DeviceExtension->InputCount - 1) * sizeof(KEYBOARD_INPUT_DATA));
|
||||
&DeviceExtension->PortData[NumberOfEntries],
|
||||
(DeviceExtension->InputCount - NumberOfEntries) * sizeof(KEYBOARD_INPUT_DATA));
|
||||
}
|
||||
|
||||
DeviceExtension->InputCount--;
|
||||
DeviceExtension->InputCount -= NumberOfEntries;
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
|
||||
Stack->Parameters.Read.Length = sizeof(KEYBOARD_INPUT_DATA);
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
|
||||
}
|
||||
|
||||
/* Go to next packet and complete this request */
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#define MAX_PATH 260
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dsStopped,
|
||||
|
@ -56,6 +58,7 @@ typedef struct _CLASS_DEVICE_EXTENSION
|
|||
BOOLEAN ReadIsPending;
|
||||
ULONG InputCount;
|
||||
PKEYBOARD_INPUT_DATA PortData;
|
||||
LPCWSTR DeviceName;
|
||||
} CLASS_DEVICE_EXTENSION, *PCLASS_DEVICE_EXTENSION;
|
||||
|
||||
/* misc.c */
|
||||
|
|
|
@ -123,7 +123,7 @@ ClassDeviceControl(
|
|||
PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
|
||||
if (Head->Flink != Head)
|
||||
{
|
||||
/* We have at least one mouse */
|
||||
/* We have at least one device */
|
||||
PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
|
||||
IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
@ -352,6 +352,7 @@ cleanup:
|
|||
ExFreePool(DeviceNameU.Buffer);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
DeviceExtension->DeviceName = DeviceNameU.Buffer;
|
||||
Fdo->Flags |= DO_POWER_PAGABLE;
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
|
@ -359,13 +360,11 @@ cleanup:
|
|||
RtlWriteRegistryValue(
|
||||
RTL_REGISTRY_DEVICEMAP,
|
||||
DriverExtension->DeviceBaseName.Buffer,
|
||||
DeviceNameU.Buffer,
|
||||
DeviceExtension->DeviceName,
|
||||
REG_SZ,
|
||||
DriverExtension->RegistryPath.Buffer,
|
||||
DriverExtension->RegistryPath.MaximumLength);
|
||||
|
||||
ExFreePool(DeviceNameU.Buffer);
|
||||
|
||||
if (ClassDO)
|
||||
*ClassDO = Fdo;
|
||||
|
||||
|
@ -373,10 +372,11 @@ cleanup:
|
|||
}
|
||||
|
||||
static NTSTATUS
|
||||
FillOneEntry(
|
||||
FillEntries(
|
||||
IN PDEVICE_OBJECT ClassDeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PMOUSE_INPUT_DATA DataStart)
|
||||
IN PMOUSE_INPUT_DATA DataStart,
|
||||
IN SIZE_T NumberOfEntries)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
|
@ -385,7 +385,7 @@ FillOneEntry(
|
|||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
DataStart,
|
||||
sizeof(MOUSE_INPUT_DATA));
|
||||
NumberOfEntries * sizeof(MOUSE_INPUT_DATA));
|
||||
}
|
||||
else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
|
||||
{
|
||||
|
@ -395,7 +395,7 @@ FillOneEntry(
|
|||
RtlCopyMemory(
|
||||
DestAddress,
|
||||
DataStart,
|
||||
sizeof(MOUSE_INPUT_DATA));
|
||||
NumberOfEntries * sizeof(MOUSE_INPUT_DATA));
|
||||
}
|
||||
else
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
|
@ -407,7 +407,7 @@ FillOneEntry(
|
|||
RtlCopyMemory(
|
||||
Irp->UserBuffer,
|
||||
DataStart,
|
||||
sizeof(MOUSE_INPUT_DATA));
|
||||
NumberOfEntries * sizeof(MOUSE_INPUT_DATA));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
|
@ -429,7 +429,6 @@ ClassCallback(
|
|||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
PIRP Irp = NULL;
|
||||
KIRQL OldIrql;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
ULONG InputCount = DataEnd - DataStart;
|
||||
ULONG ReadSize;
|
||||
|
||||
|
@ -444,31 +443,35 @@ ClassCallback(
|
|||
*/
|
||||
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
|
||||
{
|
||||
/* A read request is waiting for input, so go straight to it */
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
Irp = ClassDeviceObject->CurrentIrp;
|
||||
ClassDeviceObject->CurrentIrp = NULL;
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* A read request is waiting for input, so go straight to it */
|
||||
Status = FillOneEntry(
|
||||
NumberOfEntries = MIN(
|
||||
InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(MOUSE_INPUT_DATA));
|
||||
|
||||
Status = FillEntries(
|
||||
ClassDeviceObject,
|
||||
Irp,
|
||||
DataStart);
|
||||
DataStart,
|
||||
NumberOfEntries);
|
||||
|
||||
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);
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(MOUSE_INPUT_DATA);
|
||||
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
/* Skip the packet we just sent away */
|
||||
DataStart++;
|
||||
(*ConsumedCount)++;
|
||||
InputCount--;
|
||||
DataStart += NumberOfEntries;
|
||||
(*ConsumedCount) += NumberOfEntries;
|
||||
InputCount -= NumberOfEntries;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,11 +540,14 @@ ConnectPortDriver(
|
|||
ConnectData.ClassDeviceObject = ClassDO;
|
||||
ConnectData.ClassService = ClassCallback;
|
||||
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
|
||||
Irp = IoBuildDeviceIoControlRequest(
|
||||
IOCTL_INTERNAL_MOUSE_CONNECT,
|
||||
PortDO,
|
||||
&ConnectData, sizeof(CONNECT_DATA),
|
||||
NULL, 0,
|
||||
TRUE, &Event, &IoStatus);
|
||||
if (!Irp)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
Status = IoCallDriver(PortDO, Irp);
|
||||
|
||||
|
@ -569,16 +575,65 @@ ConnectPortDriver(
|
|||
return IoStatus.Status;
|
||||
}
|
||||
|
||||
/* Send IOCTL_INTERNAL_*_DISCONNECT to port */
|
||||
static NTSTATUS
|
||||
DisconnectPortDriver(
|
||||
/* Send IOCTL_INTERNAL_*_DISCONNECT to port + destroy the Port DO */
|
||||
static VOID
|
||||
DestroyPortDriver(
|
||||
IN PDEVICE_OBJECT PortDO)
|
||||
{
|
||||
DPRINT("Disconnecting PortDO %p [%wZ]\n",
|
||||
PPORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension;
|
||||
PCLASS_DRIVER_EXTENSION DriverExtension;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("Destroying PortDO %p [%wZ]\n",
|
||||
PortDO, &PortDO->DriverObject->DriverName);
|
||||
|
||||
DPRINT1("FIXME: Need to send IOCTL_INTERNAL_*_DISCONNECT\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
DeviceExtension = (PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension;
|
||||
ClassDeviceExtension = DeviceExtension->ClassDO->DeviceExtension;
|
||||
DriverExtension = IoGetDriverObjectExtension(PortDO->DriverObject, PortDO->DriverObject);
|
||||
|
||||
/* Send IOCTL_INTERNAL_*_DISCONNECT */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(
|
||||
IOCTL_INTERNAL_MOUSE_DISCONNECT,
|
||||
PortDO,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
TRUE, &Event, &IoStatus);
|
||||
if (Irp)
|
||||
{
|
||||
Status = IoCallDriver(PortDO, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
/* Remove from ClassDeviceExtension->ListHead list */
|
||||
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
|
||||
RemoveHeadList(DeviceExtension->ListEntry.Blink);
|
||||
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
|
||||
|
||||
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
|
||||
RtlDeleteRegistryValue(
|
||||
RTL_REGISTRY_DEVICEMAP,
|
||||
DriverExtension->DeviceBaseName.Buffer,
|
||||
ClassDeviceExtension->DeviceName);
|
||||
|
||||
if (DeviceExtension->LowerDevice)
|
||||
IoDetachDevice(DeviceExtension->LowerDevice);
|
||||
ObDereferenceObject(PortDO);
|
||||
|
||||
if (!DriverExtension->ConnectMultiplePorts && DeviceExtension->ClassDO)
|
||||
{
|
||||
ExFreePool(ClassDeviceExtension->PortData);
|
||||
ExFreePool((PVOID)ClassDeviceExtension->DeviceName);
|
||||
IoDeleteDevice(DeviceExtension->ClassDO);
|
||||
}
|
||||
|
||||
IoDeleteDevice(PortDO);
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
|
@ -655,44 +710,21 @@ ClassAddDevice(
|
|||
}
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
/* Register interface */
|
||||
Status = IoRegisterDeviceInterface(
|
||||
/* Register interface ; ignore the error (if any) as having
|
||||
* a registred interface is not so important... */
|
||||
IoRegisterDeviceInterface(
|
||||
Pdo,
|
||||
&GUID_DEVINTERFACE_MOUSE,
|
||||
NULL,
|
||||
&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);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!NT_SUCCESS(Status))
|
||||
DeviceExtension->InterfaceName.Length = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (!(Fdo->Flags & DO_DEVICE_INITIALIZING))
|
||||
DisconnectPortDriver(Fdo);
|
||||
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);
|
||||
/* FIXME BSOD for second boot when u press on finsih buttom or wait timeout */
|
||||
// IoDeleteDevice(DeviceExtension->ClassDO);
|
||||
}
|
||||
}
|
||||
if (Fdo)
|
||||
IoDeleteDevice(Fdo);
|
||||
DestroyPortDriver(Fdo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -702,7 +734,6 @@ ClassStartIo(
|
|||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
|
@ -710,29 +741,34 @@ ClassStartIo(
|
|||
{
|
||||
KIRQL oldIrql;
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
NumberOfEntries = MIN(
|
||||
DeviceExtension->InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(MOUSE_INPUT_DATA));
|
||||
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
||||
|
||||
Status = FillOneEntry(
|
||||
Status = FillEntries(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
&DeviceExtension->PortData[DeviceExtension->InputCount - 1]);
|
||||
DeviceExtension->PortData,
|
||||
NumberOfEntries);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (DeviceExtension->InputCount > 1)
|
||||
if (DeviceExtension->InputCount > NumberOfEntries)
|
||||
{
|
||||
RtlMoveMemory(
|
||||
&DeviceExtension->PortData[1],
|
||||
&DeviceExtension->PortData[0],
|
||||
(DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
|
||||
&DeviceExtension->PortData[NumberOfEntries],
|
||||
(DeviceExtension->InputCount - NumberOfEntries) * sizeof(MOUSE_INPUT_DATA));
|
||||
}
|
||||
|
||||
DeviceExtension->InputCount--;
|
||||
DeviceExtension->InputCount -= NumberOfEntries;
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
|
||||
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(MOUSE_INPUT_DATA);
|
||||
}
|
||||
|
||||
/* Go to next packet and complete this request */
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#define MAX_PATH 260
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dsStopped,
|
||||
|
@ -56,6 +58,7 @@ typedef struct _CLASS_DEVICE_EXTENSION
|
|||
BOOLEAN ReadIsPending;
|
||||
ULONG InputCount;
|
||||
PMOUSE_INPUT_DATA PortData;
|
||||
LPCWSTR DeviceName;
|
||||
} CLASS_DEVICE_EXTENSION, *PCLASS_DEVICE_EXTENSION;
|
||||
|
||||
/* misc.c */
|
||||
|
|
Loading…
Reference in a new issue