Patch by hpoussin/GvG - Read parameters in the right registry key - Force exclusive opening on device object - Add hack for first stage setup (link main device object to ??\Keyboard) - Use buffered IO - Reference pointer port DOs when they are linked to pointer class DO Modified: trunk/reactos/drivers/input/kbdclass/kbdclass.c _____
Modified: trunk/reactos/drivers/input/kbdclass/kbdclass.c --- trunk/reactos/drivers/input/kbdclass/kbdclass.c 2005-11-01 23:37:26 UTC (rev 18942) +++ trunk/reactos/drivers/input/kbdclass/kbdclass.c 2005-11-01 23:39:12 UTC (rev 18943) @@ -48,6 +48,20 @@
}
static NTSTATUS NTAPI +KbdclassCleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("IRP_MJ_CLEANUP\n"); + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + /* FIXME: close all associated Port devices */ + return STATUS_SUCCESS; +} + +static NTSTATUS NTAPI KbdclassRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) @@ -79,7 +93,7 @@ NTSTATUS Status;
DPRINT("IRP_MJ_DEVICE_CONTROL\n"); - + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) return ForwardIrpAndForget(DeviceObject, Irp);
@@ -148,6 +162,7 @@ IN PUNICODE_STRING RegistryPath, IN PKBDCLASS_DRIVER_EXTENSION DriverExtension) { + UNICODE_STRING ParametersRegistryKey; RTL_QUERY_REGISTRY_TABLE Parameters[4]; NTSTATUS Status;
@@ -155,6 +170,18 @@ ULONG DefaultKeyboardDataQueueSize = 0x64; UNICODE_STRING DefaultKeyboardDeviceBaseName = RTL_CONSTANT_STRING(L"KeyboardClass");
+ 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].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; @@ -163,14 +190,14 @@ 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"KeyboardDataQueueSize"; Parameters[1].EntryContext = &DriverExtension->KeyboardDataQueueSize; Parameters[1].DefaultType = REG_DWORD; Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize; Parameters[1].DefaultLength = sizeof(ULONG); - + Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; Parameters[2].Name = L"KeyboardDeviceBaseName"; Parameters[2].EntryContext = &DriverExtension->KeyboardDeviceBaseName; @@ -180,7 +207,7 @@
Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, - RegistryPath->Buffer, + ParametersRegistryKey.Buffer, Parameters, NULL, NULL); @@ -198,6 +225,16 @@ DriverExtension->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize; } } + else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + /* Registry path doesn't exist. Set defaults */ + DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts; + DriverExtension->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize; + Status = RtlDuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &DefaultKeyboardDeviceBaseName, + &DriverExtension->KeyboardDeviceBaseName); + }
return Status; } @@ -208,6 +245,7 @@ OUT PDEVICE_OBJECT *ClassDO OPTIONAL) { PKBDCLASS_DRIVER_EXTENSION DriverExtension; + UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\??\Keyboard"); ULONG DeviceId = 0; ULONG PrefixLength; UNICODE_STRING DeviceNameU; @@ -255,7 +293,7 @@ &DeviceNameU, FILE_DEVICE_KEYBOARD, FILE_DEVICE_SECURE_OPEN, - FALSE, + TRUE, &Fdo); if (NT_SUCCESS(Status)) goto cleanup; @@ -269,9 +307,11 @@ DPRINT("Too much devices starting with '\Device\%wZ'\n", &DriverExtension->KeyboardDeviceBaseName); Status = STATUS_UNSUCCESSFUL; cleanup: - ExFreePool(DeviceNameU.Buffer); if (!NT_SUCCESS(Status)) + { + ExFreePool(DeviceNameU.Buffer); return Status; + }
DeviceExtension = (PKBDCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension; RtlZeroMemory(DeviceExtension, sizeof(KBDCLASS_DEVICE_EXTENSION)); @@ -282,11 +322,17 @@ DeviceExtension->ReadIsPending = FALSE; DeviceExtension->InputCount = 0; DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->KeyboardDataQueueSize * sizeof(KEYBOARD_INPUT_DATA)); - Fdo->Flags |= DO_POWER_PAGABLE; + Fdo->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO; Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
+ /* HACK: 1st stage setup needs a keyboard to open it in user-mode + * Create a link to user space... */ + IoCreateSymbolicLink(&SymbolicLinkName, &DeviceNameU); + + ExFreePool(DeviceNameU.Buffer); + if (ClassDO) *ClassDO = Fdo;
@@ -323,7 +369,7 @@ /* A read request is waiting for input, so go straight to it */ /* FIXME: use SEH */ RtlCopyMemory( - Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->UserBuffer, + Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->AssociatedIrp.SystemBuffer, KeyboardDataStart, sizeof(KEYBOARD_INPUT_DATA));
@@ -416,6 +462,9 @@ else IoStatus.Status = Status;
+ if (NT_SUCCESS(Status)) + ObReferenceObject(KeyboardPortDO); + return IoStatus.Status; }
@@ -440,7 +489,7 @@ NULL, Pdo->DeviceType, FILE_DEVICE_SECURE_OPEN, - FALSE, + TRUE, &Fdo); if (!NT_SUCCESS(Status)) { @@ -461,7 +510,6 @@ return Status; } Fdo->Flags |= DO_BUFFERED_IO; - Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
if (DriverExtension->ConnectMultiplePorts) Status = ConnectKeyboardPortDriver(Fdo, DriverExtension->MainKbdclassDeviceObject); @@ -470,11 +518,12 @@ if (!NT_SUCCESS(Status)) { DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status); + IoDetachDevice(DeviceExtension->LowerDevice); /* FIXME: why can't I cleanup without error? */ - //IoDetachDevice(Fdo); //IoDeleteDevice(Fdo); return Status; } + Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* Register GUID_DEVINTERFACE_KEYBOARD interface */ Status = IoRegisterDeviceInterface( @@ -621,7 +670,7 @@ { /* FIXME: Log the error */ DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status); - /* FIXME: cleanup */ + ObReferenceObject(PortDeviceObject); } } else @@ -632,7 +681,7 @@ { /* FIXME: Log the error */ DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status); - /* FIXME: cleanup */ + ObReferenceObject(PortDeviceObject); continue; } Status = ConnectKeyboardPortDriver(PortDeviceObject, ClassDO); @@ -640,7 +689,8 @@ { /* FIXME: Log the error */ DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status); - /* FIXME: cleanup */ + ObReferenceObject(PortDeviceObject); + IoDeleteDevice(ClassDO); } } } @@ -708,6 +758,7 @@
DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdclassCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdclassClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = KbdclassCleanup; DriverObject->MajorFunction[IRP_MJ_READ] = KbdclassRead; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdclassDeviceControl; DriverObject->DriverStartIo = KbdclassStartIo;