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

svn path=/trunk/; revision=18943
This commit is contained in:
Gé van Geldorp 2005-11-01 23:39:12 +00:00
parent f9d8fe961d
commit baee1b54eb

View file

@ -47,6 +47,20 @@ KbdclassClose(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
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 static NTSTATUS NTAPI
KbdclassRead( KbdclassRead(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
@ -79,7 +93,7 @@ KbdclassDeviceControl(
NTSTATUS Status; NTSTATUS Status;
DPRINT("IRP_MJ_DEVICE_CONTROL\n"); DPRINT("IRP_MJ_DEVICE_CONTROL\n");
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
return ForwardIrpAndForget(DeviceObject, Irp); return ForwardIrpAndForget(DeviceObject, Irp);
@ -148,6 +162,7 @@ ReadRegistryEntries(
IN PUNICODE_STRING RegistryPath, IN PUNICODE_STRING RegistryPath,
IN PKBDCLASS_DRIVER_EXTENSION DriverExtension) IN PKBDCLASS_DRIVER_EXTENSION DriverExtension)
{ {
UNICODE_STRING ParametersRegistryKey;
RTL_QUERY_REGISTRY_TABLE Parameters[4]; RTL_QUERY_REGISTRY_TABLE Parameters[4];
NTSTATUS Status; NTSTATUS Status;
@ -155,6 +170,18 @@ ReadRegistryEntries(
ULONG DefaultKeyboardDataQueueSize = 0x64; ULONG DefaultKeyboardDataQueueSize = 0x64;
UNICODE_STRING DefaultKeyboardDeviceBaseName = RTL_CONSTANT_STRING(L"KeyboardClass"); 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)); RtlZeroMemory(Parameters, sizeof(Parameters));
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
@ -163,14 +190,14 @@ ReadRegistryEntries(
Parameters[0].DefaultType = REG_DWORD; Parameters[0].DefaultType = REG_DWORD;
Parameters[0].DefaultData = &DefaultConnectMultiplePorts; Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
Parameters[0].DefaultLength = sizeof(ULONG); Parameters[0].DefaultLength = sizeof(ULONG);
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[1].Name = L"KeyboardDataQueueSize"; Parameters[1].Name = L"KeyboardDataQueueSize";
Parameters[1].EntryContext = &DriverExtension->KeyboardDataQueueSize; Parameters[1].EntryContext = &DriverExtension->KeyboardDataQueueSize;
Parameters[1].DefaultType = REG_DWORD; Parameters[1].DefaultType = REG_DWORD;
Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize; Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize;
Parameters[1].DefaultLength = sizeof(ULONG); Parameters[1].DefaultLength = sizeof(ULONG);
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[2].Name = L"KeyboardDeviceBaseName"; Parameters[2].Name = L"KeyboardDeviceBaseName";
Parameters[2].EntryContext = &DriverExtension->KeyboardDeviceBaseName; Parameters[2].EntryContext = &DriverExtension->KeyboardDeviceBaseName;
@ -180,7 +207,7 @@ ReadRegistryEntries(
Status = RtlQueryRegistryValues( Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE, RTL_REGISTRY_ABSOLUTE,
RegistryPath->Buffer, ParametersRegistryKey.Buffer,
Parameters, Parameters,
NULL, NULL,
NULL); NULL);
@ -198,6 +225,16 @@ ReadRegistryEntries(
DriverExtension->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize; 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; return Status;
} }
@ -208,6 +245,7 @@ CreateKeyboardClassDeviceObject(
OUT PDEVICE_OBJECT *ClassDO OPTIONAL) OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
{ {
PKBDCLASS_DRIVER_EXTENSION DriverExtension; PKBDCLASS_DRIVER_EXTENSION DriverExtension;
UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\Keyboard");
ULONG DeviceId = 0; ULONG DeviceId = 0;
ULONG PrefixLength; ULONG PrefixLength;
UNICODE_STRING DeviceNameU; UNICODE_STRING DeviceNameU;
@ -255,7 +293,7 @@ CreateKeyboardClassDeviceObject(
&DeviceNameU, &DeviceNameU,
FILE_DEVICE_KEYBOARD, FILE_DEVICE_KEYBOARD,
FILE_DEVICE_SECURE_OPEN, FILE_DEVICE_SECURE_OPEN,
FALSE, TRUE,
&Fdo); &Fdo);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
goto cleanup; goto cleanup;
@ -269,9 +307,11 @@ CreateKeyboardClassDeviceObject(
DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->KeyboardDeviceBaseName); DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->KeyboardDeviceBaseName);
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
cleanup: cleanup:
ExFreePool(DeviceNameU.Buffer);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
ExFreePool(DeviceNameU.Buffer);
return Status; return Status;
}
DeviceExtension = (PKBDCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension; DeviceExtension = (PKBDCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(KBDCLASS_DEVICE_EXTENSION)); RtlZeroMemory(DeviceExtension, sizeof(KBDCLASS_DEVICE_EXTENSION));
@ -282,11 +322,17 @@ cleanup:
DeviceExtension->ReadIsPending = FALSE; DeviceExtension->ReadIsPending = FALSE;
DeviceExtension->InputCount = 0; DeviceExtension->InputCount = 0;
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->KeyboardDataQueueSize * sizeof(KEYBOARD_INPUT_DATA)); 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; Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */ /* 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) if (ClassDO)
*ClassDO = Fdo; *ClassDO = Fdo;
@ -323,7 +369,7 @@ KbdclassCallback(
/* A read request is waiting for input, so go straight to it */ /* A read request is waiting for input, so go straight to it */
/* FIXME: use SEH */ /* FIXME: use SEH */
RtlCopyMemory( RtlCopyMemory(
Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->UserBuffer, Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->AssociatedIrp.SystemBuffer,
KeyboardDataStart, KeyboardDataStart,
sizeof(KEYBOARD_INPUT_DATA)); sizeof(KEYBOARD_INPUT_DATA));
@ -416,6 +462,9 @@ ConnectKeyboardPortDriver(
else else
IoStatus.Status = Status; IoStatus.Status = Status;
if (NT_SUCCESS(Status))
ObReferenceObject(KeyboardPortDO);
return IoStatus.Status; return IoStatus.Status;
} }
@ -440,7 +489,7 @@ KbdclassAddDevice(
NULL, NULL,
Pdo->DeviceType, Pdo->DeviceType,
FILE_DEVICE_SECURE_OPEN, FILE_DEVICE_SECURE_OPEN,
FALSE, TRUE,
&Fdo); &Fdo);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -461,7 +510,6 @@ KbdclassAddDevice(
return Status; return Status;
} }
Fdo->Flags |= DO_BUFFERED_IO; Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
if (DriverExtension->ConnectMultiplePorts) if (DriverExtension->ConnectMultiplePorts)
Status = ConnectKeyboardPortDriver(Fdo, DriverExtension->MainKbdclassDeviceObject); Status = ConnectKeyboardPortDriver(Fdo, DriverExtension->MainKbdclassDeviceObject);
@ -470,11 +518,12 @@ KbdclassAddDevice(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status); DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status);
IoDetachDevice(DeviceExtension->LowerDevice);
/* FIXME: why can't I cleanup without error? */ /* FIXME: why can't I cleanup without error? */
//IoDetachDevice(Fdo);
//IoDeleteDevice(Fdo); //IoDeleteDevice(Fdo);
return Status; return Status;
} }
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* Register GUID_DEVINTERFACE_KEYBOARD interface */ /* Register GUID_DEVINTERFACE_KEYBOARD interface */
Status = IoRegisterDeviceInterface( Status = IoRegisterDeviceInterface(
@ -621,7 +670,7 @@ SearchForLegacyDrivers(
{ {
/* FIXME: Log the error */ /* FIXME: Log the error */
DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status); DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status);
/* FIXME: cleanup */ ObReferenceObject(PortDeviceObject);
} }
} }
else else
@ -632,7 +681,7 @@ SearchForLegacyDrivers(
{ {
/* FIXME: Log the error */ /* FIXME: Log the error */
DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status); DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
/* FIXME: cleanup */ ObReferenceObject(PortDeviceObject);
continue; continue;
} }
Status = ConnectKeyboardPortDriver(PortDeviceObject, ClassDO); Status = ConnectKeyboardPortDriver(PortDeviceObject, ClassDO);
@ -640,7 +689,8 @@ SearchForLegacyDrivers(
{ {
/* FIXME: Log the error */ /* FIXME: Log the error */
DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status); DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status);
/* FIXME: cleanup */ ObReferenceObject(PortDeviceObject);
IoDeleteDevice(ClassDO);
} }
} }
} }
@ -708,6 +758,7 @@ DriverEntry(
DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdclassCreate; DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdclassCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdclassClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdclassClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = KbdclassCleanup;
DriverObject->MajorFunction[IRP_MJ_READ] = KbdclassRead; DriverObject->MajorFunction[IRP_MJ_READ] = KbdclassRead;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdclassDeviceControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdclassDeviceControl;
DriverObject->DriverStartIo = KbdclassStartIo; DriverObject->DriverStartIo = KbdclassStartIo;