2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Keyboard class driver
4 * FILE: drivers/kbdclass/kbdclass.c
5 * PURPOSE: Keyboard class driver
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
17 DriverUnload(IN PDRIVER_OBJECT DriverObject
)
19 // nothing to do here yet
24 IN PDEVICE_OBJECT DeviceObject
,
27 DPRINT("IRP_MJ_CREATE\n");
29 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
30 return ForwardIrpAndForget(DeviceObject
, Irp
);
32 /* FIXME: open all associated Port devices */
33 return STATUS_SUCCESS
;
38 IN PDEVICE_OBJECT DeviceObject
,
41 DPRINT("IRP_MJ_CLOSE\n");
43 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
44 return ForwardIrpAndForget(DeviceObject
, Irp
);
46 /* FIXME: close all associated Port devices */
47 return STATUS_SUCCESS
;
52 IN PDEVICE_OBJECT DeviceObject
,
55 DPRINT("IRP_MJ_CLEANUP\n");
57 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
58 return ForwardIrpAndForget(DeviceObject
, Irp
);
60 /* FIXME: close all associated Port devices */
61 return STATUS_SUCCESS
;
66 IN PDEVICE_OBJECT DeviceObject
,
69 DPRINT("IRP_MJ_READ\n");
71 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
72 return ForwardIrpAndForget(DeviceObject
, Irp
);
74 if (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
< sizeof(KEYBOARD_INPUT_DATA
))
76 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
77 Irp
->IoStatus
.Information
= 0;
78 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
80 return STATUS_BUFFER_TOO_SMALL
;
83 IoMarkIrpPending(Irp
);
84 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
85 return STATUS_PENDING
;
89 KbdclassDeviceControl(
90 IN PDEVICE_OBJECT DeviceObject
,
95 DPRINT("IRP_MJ_DEVICE_CONTROL\n");
97 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
98 return ForwardIrpAndForget(DeviceObject
, Irp
);
100 switch (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
)
102 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES
:
103 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
:
104 case IOCTL_KEYBOARD_QUERY_INDICATORS
:
105 case IOCTL_KEYBOARD_QUERY_TYPEMATIC
:
106 case IOCTL_KEYBOARD_SET_INDICATORS
:
107 case IOCTL_KEYBOARD_SET_TYPEMATIC
: /* not in MSDN, would seem logical */
108 /* FIXME: send it to all associated Port devices */
109 Status
= STATUS_NOT_SUPPORTED
;
112 DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
113 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
);
114 Status
= STATUS_NOT_SUPPORTED
;
117 Irp
->IoStatus
.Status
= Status
;
118 Irp
->IoStatus
.Information
= 0;
119 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
124 static NTSTATUS NTAPI
126 IN PDEVICE_OBJECT DeviceObject
,
129 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
131 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
133 /* Forward some IRPs to lower device */
134 switch (IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
)
136 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
137 return ForwardIrpAndForget(DeviceObject
, Irp
);
140 DPRINT1("Port DO stub for major function 0x%lx\n",
141 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
143 Status
= Irp
->IoStatus
.Status
;
149 DPRINT1("Class DO stub for major function 0x%lx\n",
150 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
152 Status
= Irp
->IoStatus
.Status
;
155 Irp
->IoStatus
.Status
= Status
;
156 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
162 IN PUNICODE_STRING RegistryPath
,
163 IN PKBDCLASS_DRIVER_EXTENSION DriverExtension
)
165 UNICODE_STRING ParametersRegistryKey
;
166 RTL_QUERY_REGISTRY_TABLE Parameters
[4];
169 ULONG DefaultConnectMultiplePorts
= 1;
170 ULONG DefaultKeyboardDataQueueSize
= 0x64;
171 UNICODE_STRING DefaultKeyboardDeviceBaseName
= RTL_CONSTANT_STRING(L
"KeyboardClass");
173 ParametersRegistryKey
.Length
= 0;
174 ParametersRegistryKey
.MaximumLength
= RegistryPath
->Length
+ sizeof(L
"\\Parameters") + sizeof(UNICODE_NULL
);
175 ParametersRegistryKey
.Buffer
= ExAllocatePool(PagedPool
, ParametersRegistryKey
.MaximumLength
);
176 if (!ParametersRegistryKey
.Buffer
)
178 DPRINT("ExAllocatePool() failed\n");
179 return STATUS_INSUFFICIENT_RESOURCES
;
181 RtlCopyUnicodeString(&ParametersRegistryKey
, RegistryPath
);
182 RtlAppendUnicodeToString(&ParametersRegistryKey
, L
"\\Parameters");
183 ParametersRegistryKey
.Buffer
[ParametersRegistryKey
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
185 RtlZeroMemory(Parameters
, sizeof(Parameters
));
187 Parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
188 Parameters
[0].Name
= L
"ConnectMultiplePorts";
189 Parameters
[0].EntryContext
= &DriverExtension
->ConnectMultiplePorts
;
190 Parameters
[0].DefaultType
= REG_DWORD
;
191 Parameters
[0].DefaultData
= &DefaultConnectMultiplePorts
;
192 Parameters
[0].DefaultLength
= sizeof(ULONG
);
194 Parameters
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
195 Parameters
[1].Name
= L
"KeyboardDataQueueSize";
196 Parameters
[1].EntryContext
= &DriverExtension
->KeyboardDataQueueSize
;
197 Parameters
[1].DefaultType
= REG_DWORD
;
198 Parameters
[1].DefaultData
= &DefaultKeyboardDataQueueSize
;
199 Parameters
[1].DefaultLength
= sizeof(ULONG
);
201 Parameters
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
202 Parameters
[2].Name
= L
"KeyboardDeviceBaseName";
203 Parameters
[2].EntryContext
= &DriverExtension
->KeyboardDeviceBaseName
;
204 Parameters
[2].DefaultType
= REG_SZ
;
205 Parameters
[2].DefaultData
= &DefaultKeyboardDeviceBaseName
;
206 Parameters
[2].DefaultLength
= sizeof(ULONG
);
208 Status
= RtlQueryRegistryValues(
209 RTL_REGISTRY_ABSOLUTE
,
210 ParametersRegistryKey
.Buffer
,
215 if (NT_SUCCESS(Status
))
218 if (DriverExtension
->ConnectMultiplePorts
!= 0
219 && DriverExtension
->ConnectMultiplePorts
!= 1)
221 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
223 if (DriverExtension
->KeyboardDataQueueSize
== 0)
225 DriverExtension
->KeyboardDataQueueSize
= DefaultKeyboardDataQueueSize
;
228 else if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
230 /* Registry path doesn't exist. Set defaults */
231 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
232 DriverExtension
->KeyboardDataQueueSize
= DefaultKeyboardDataQueueSize
;
233 Status
= RtlDuplicateUnicodeString(
234 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
235 &DefaultKeyboardDeviceBaseName
,
236 &DriverExtension
->KeyboardDeviceBaseName
);
243 CreateKeyboardClassDeviceObject(
244 IN PDRIVER_OBJECT DriverObject
,
245 OUT PDEVICE_OBJECT
*ClassDO OPTIONAL
)
247 PKBDCLASS_DRIVER_EXTENSION DriverExtension
;
248 UNICODE_STRING SymbolicLinkName
= RTL_CONSTANT_STRING(L
"\\??\\Keyboard");
251 UNICODE_STRING DeviceNameU
;
252 PWSTR DeviceIdW
= NULL
; /* Pointer into DeviceNameU.Buffer */
254 PKBDCLASS_DEVICE_EXTENSION DeviceExtension
;
257 DPRINT("CreateKeyboardClassDeviceObject(0x%p)\n", DriverObject
);
259 /* Create new device object */
260 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
261 DeviceNameU
.Length
= 0;
262 DeviceNameU
.MaximumLength
=
263 wcslen(L
"\\Device\\") * sizeof(WCHAR
) /* "\Device\" */
264 + DriverExtension
->KeyboardDeviceBaseName
.Length
/* "KeyboardClass" */
265 + 4 * sizeof(WCHAR
) /* Id between 0 and 9999 */
266 + sizeof(UNICODE_NULL
); /* Final NULL char */
267 DeviceNameU
.Buffer
= ExAllocatePool(PagedPool
, DeviceNameU
.MaximumLength
);
268 if (!DeviceNameU
.Buffer
)
270 DPRINT("ExAllocatePool() failed\n");
271 return STATUS_INSUFFICIENT_RESOURCES
;
273 Status
= RtlAppendUnicodeToString(&DeviceNameU
, L
"\\Device\\");
274 if (!NT_SUCCESS(Status
))
276 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status
);
279 Status
= RtlAppendUnicodeStringToString(&DeviceNameU
, &DriverExtension
->KeyboardDeviceBaseName
);
280 if (!NT_SUCCESS(Status
))
282 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status
);
285 PrefixLength
= DeviceNameU
.MaximumLength
- 4 * sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
286 DeviceIdW
= &DeviceNameU
.Buffer
[PrefixLength
/ sizeof(WCHAR
)];
287 while (DeviceId
< 9999)
289 DeviceNameU
.Length
= PrefixLength
+ swprintf(DeviceIdW
, L
"%lu", DeviceId
) * sizeof(WCHAR
);
290 Status
= IoCreateDevice(
292 sizeof(KBDCLASS_DEVICE_EXTENSION
),
294 FILE_DEVICE_KEYBOARD
,
295 FILE_DEVICE_SECURE_OPEN
,
298 if (NT_SUCCESS(Status
))
300 else if (Status
!= STATUS_OBJECT_NAME_COLLISION
)
302 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
307 DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension
->KeyboardDeviceBaseName
);
308 Status
= STATUS_UNSUCCESSFUL
;
310 if (!NT_SUCCESS(Status
))
312 ExFreePool(DeviceNameU
.Buffer
);
316 DeviceExtension
= (PKBDCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
317 RtlZeroMemory(DeviceExtension
, sizeof(KBDCLASS_DEVICE_EXTENSION
));
318 DeviceExtension
->Common
.IsClassDO
= TRUE
;
319 DeviceExtension
->DriverExtension
= DriverExtension
;
320 DeviceExtension
->PnpState
= dsStopped
;
321 KeInitializeSpinLock(&(DeviceExtension
->SpinLock
));
322 DeviceExtension
->ReadIsPending
= FALSE
;
323 DeviceExtension
->InputCount
= 0;
324 DeviceExtension
->PortData
= ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->KeyboardDataQueueSize
* sizeof(KEYBOARD_INPUT_DATA
));
325 Fdo
->Flags
|= DO_POWER_PAGABLE
| DO_BUFFERED_IO
;
326 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
328 /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
330 /* HACK: 1st stage setup needs a keyboard to open it in user-mode
331 * Create a link to user space... */
332 IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceNameU
);
334 ExFreePool(DeviceNameU
.Buffer
);
339 return STATUS_SUCCESS
;
344 IN PDEVICE_OBJECT ClassDeviceObject
,
345 IN OUT PKEYBOARD_INPUT_DATA KeyboardDataStart
,
346 IN PKEYBOARD_INPUT_DATA KeyboardDataEnd
,
347 IN OUT PULONG ConsumedCount
)
349 PKBDCLASS_DEVICE_EXTENSION ClassDeviceExtension
= ClassDeviceObject
->DeviceExtension
;
352 PIO_STACK_LOCATION Stack
;
353 ULONG InputCount
= KeyboardDataEnd
- KeyboardDataStart
;
356 ASSERT(ClassDeviceExtension
->Common
.IsClassDO
);
358 DPRINT("KbdclassCallback()\n");
359 /* A filter driver might have consumed all the data already; I'm
360 * not sure if they are supposed to move the packets when they
361 * consume them though.
363 if (ClassDeviceExtension
->ReadIsPending
== TRUE
&& InputCount
)
365 Irp
= ClassDeviceObject
->CurrentIrp
;
366 ClassDeviceObject
->CurrentIrp
= NULL
;
367 Stack
= IoGetCurrentIrpStackLocation(Irp
);
369 /* A read request is waiting for input, so go straight to it */
372 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->AssociatedIrp
.SystemBuffer
,
374 sizeof(KEYBOARD_INPUT_DATA
));
376 /* Go to next packet and complete this request with STATUS_SUCCESS */
377 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
378 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INPUT_DATA
);
379 Stack
->Parameters
.Read
.Length
= sizeof(KEYBOARD_INPUT_DATA
);
381 ClassDeviceExtension
->ReadIsPending
= FALSE
;
383 /* Skip the packet we just sent away */
389 /* If we have data from the port driver and a higher service to send the data to */
392 KeAcquireSpinLock(&ClassDeviceExtension
->SpinLock
, &OldIrql
);
394 if (ClassDeviceExtension
->InputCount
+ InputCount
> ClassDeviceExtension
->DriverExtension
->KeyboardDataQueueSize
)
395 ReadSize
= ClassDeviceExtension
->DriverExtension
->KeyboardDataQueueSize
- ClassDeviceExtension
->InputCount
;
397 ReadSize
= InputCount
;
400 * FIXME: If we exceed the buffer, keyboard data gets thrown away.. better
405 * Move the keyboard input data from the port data queue to our class data
409 ClassDeviceExtension
->PortData
,
410 (PCHAR
)KeyboardDataStart
,
411 sizeof(KEYBOARD_INPUT_DATA
) * ReadSize
);
413 /* Move the pointer and counter up */
414 ClassDeviceExtension
->PortData
+= ReadSize
;
415 ClassDeviceExtension
->InputCount
+= ReadSize
;
417 KeReleaseSpinLock(&ClassDeviceExtension
->SpinLock
, OldIrql
);
418 (*ConsumedCount
) += ReadSize
;
422 DPRINT("KbdclassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount
);
427 IoStartNextPacket(ClassDeviceObject
, FALSE
);
428 IoCompleteRequest(Irp
, IO_KEYBOARD_INCREMENT
);
431 DPRINT("Leaving KbdclassCallback()\n");
435 /* Send IOCTL_INTERNAL_KEYBOARD_CONNECT to keyboard port */
437 ConnectKeyboardPortDriver(
438 IN PDEVICE_OBJECT KeyboardPortDO
,
439 IN PDEVICE_OBJECT KeyboardClassDO
)
443 IO_STATUS_BLOCK IoStatus
;
444 CONNECT_DATA ConnectData
;
447 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
449 ConnectData
.ClassDeviceObject
= KeyboardClassDO
;
450 ConnectData
.ClassService
= KbdclassCallback
;
452 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_KEYBOARD_CONNECT
,
454 &ConnectData
, sizeof(CONNECT_DATA
),
456 TRUE
, &Event
, &IoStatus
);
458 Status
= IoCallDriver(KeyboardPortDO
, Irp
);
460 if (Status
== STATUS_PENDING
)
461 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
463 IoStatus
.Status
= Status
;
465 if (NT_SUCCESS(Status
))
466 ObReferenceObject(KeyboardPortDO
);
468 return IoStatus
.Status
;
471 static NTSTATUS NTAPI
473 IN PDRIVER_OBJECT DriverObject
,
474 IN PDEVICE_OBJECT Pdo
)
476 PKBDCLASS_DRIVER_EXTENSION DriverExtension
;
478 PKBDCLASS_DEVICE_EXTENSION DeviceExtension
;
481 DPRINT("KbdclassAddDevice called. Pdo = 0x%p\n", Pdo
);
483 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
485 /* Create new device object */
486 Status
= IoCreateDevice(
488 sizeof(KBDCLASS_DEVICE_EXTENSION
),
491 FILE_DEVICE_SECURE_OPEN
,
494 if (!NT_SUCCESS(Status
))
496 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
500 DeviceExtension
= (PKBDCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
501 RtlZeroMemory(DeviceExtension
, sizeof(KBDCLASS_DEVICE_EXTENSION
));
502 DeviceExtension
->Common
.IsClassDO
= FALSE
;
503 DeviceExtension
->PnpState
= dsStopped
;
504 Fdo
->Flags
|= DO_POWER_PAGABLE
;
505 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
506 if (!NT_SUCCESS(Status
))
508 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
512 Fdo
->Flags
|= DO_BUFFERED_IO
;
514 if (DriverExtension
->ConnectMultiplePorts
)
515 Status
= ConnectKeyboardPortDriver(Fdo
, DriverExtension
->MainKbdclassDeviceObject
);
517 Status
= ConnectKeyboardPortDriver(Fdo
, Fdo
);
518 if (!NT_SUCCESS(Status
))
520 DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status
);
521 IoDetachDevice(DeviceExtension
->LowerDevice
);
522 /* FIXME: why can't I cleanup without error? */
523 //IoDeleteDevice(Fdo);
526 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
528 /* Register GUID_DEVINTERFACE_KEYBOARD interface */
529 Status
= IoRegisterDeviceInterface(
531 &GUID_DEVINTERFACE_KEYBOARD
,
533 &DeviceExtension
->KeyboardInterfaceName
);
534 if (!NT_SUCCESS(Status
))
536 DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
540 return STATUS_SUCCESS
;
545 IN PDEVICE_OBJECT DeviceObject
,
548 PKBDCLASS_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
549 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
551 ASSERT(DeviceExtension
->Common
.IsClassDO
);
553 if (DeviceExtension
->InputCount
> 0)
557 KeAcquireSpinLock(&DeviceExtension
->SpinLock
, &oldIrql
);
561 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
562 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
563 sizeof(KEYBOARD_INPUT_DATA
));
565 if (DeviceExtension
->InputCount
> 1)
568 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
569 DeviceExtension
->PortData
- DeviceExtension
->InputCount
+ 1,
570 (DeviceExtension
->InputCount
- 1) * sizeof(KEYBOARD_INPUT_DATA
));
572 DeviceExtension
->PortData
--;
573 DeviceExtension
->InputCount
--;
574 DeviceExtension
->ReadIsPending
= FALSE
;
576 /* Go to next packet and complete this request with STATUS_SUCCESS */
577 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
578 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INPUT_DATA
);
579 Stack
->Parameters
.Read
.Length
= sizeof(KEYBOARD_INPUT_DATA
);
580 IoCompleteRequest(Irp
, IO_KEYBOARD_INCREMENT
);
582 IoStartNextPacket(DeviceObject
, FALSE
);
583 KeReleaseSpinLock(&DeviceExtension
->SpinLock
, oldIrql
);
587 DeviceExtension
->ReadIsPending
= TRUE
;
592 SearchForLegacyDrivers(
593 IN PDRIVER_OBJECT DriverObject
,
594 IN PKBDCLASS_DRIVER_EXTENSION DriverExtension
)
596 UNICODE_STRING DeviceMapKeyU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
597 UNICODE_STRING PortBaseName
= {0, };
598 PKEY_VALUE_BASIC_INFORMATION KeyValueInformation
= NULL
;
599 OBJECT_ATTRIBUTES ObjectAttributes
;
600 HANDLE hDeviceMapKey
= (HANDLE
)-1;
601 HANDLE hPortKey
= (HANDLE
)-1;
603 ULONG Size
, ResultLength
;
606 /* Create port base name, by replacing Class by Port at the end of the class base name */
607 Status
= RtlDuplicateUnicodeString(
608 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
609 &DriverExtension
->KeyboardDeviceBaseName
,
611 if (!NT_SUCCESS(Status
))
613 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
616 PortBaseName
.Length
-= (sizeof(L
"Class") - sizeof(UNICODE_NULL
));
617 RtlAppendUnicodeToString(&PortBaseName
, L
"Port");
619 /* Allocate memory */
620 Size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + MAX_PATH
;
621 KeyValueInformation
= ExAllocatePool(PagedPool
, Size
);
622 if (!KeyValueInformation
)
624 DPRINT("ExAllocatePool() failed\n");
625 Status
= STATUS_INSUFFICIENT_RESOURCES
;
629 /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
630 InitializeObjectAttributes(&ObjectAttributes
, &DeviceMapKeyU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
631 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
632 if (!NT_SUCCESS(Status
))
634 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
639 InitializeObjectAttributes(&ObjectAttributes
, &PortBaseName
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceMapKey
, NULL
);
640 Status
= ZwOpenKey(&hPortKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
641 if (!NT_SUCCESS(Status
))
643 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
644 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
648 /* Read each value name */
649 while (ZwEnumerateValueKey(hPortKey
, Index
++, KeyValueBasicInformation
, KeyValueInformation
, Size
, &ResultLength
) == STATUS_SUCCESS
)
651 UNICODE_STRING PortName
;
652 PDEVICE_OBJECT PortDeviceObject
= NULL
;
653 PFILE_OBJECT FileObject
= NULL
;
655 PortName
.Length
= PortName
.MaximumLength
= KeyValueInformation
->NameLength
;
656 PortName
.Buffer
= KeyValueInformation
->Name
;
658 /* Open the device object pointer */
659 Status
= IoGetDeviceObjectPointer(&PortName
, FILE_READ_ATTRIBUTES
, &FileObject
, &PortDeviceObject
);
660 if (!NT_SUCCESS(Status
))
662 DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status
);
665 /* Connect the port device object */
666 if (DriverExtension
->ConnectMultiplePorts
)
668 Status
= ConnectKeyboardPortDriver(PortDeviceObject
, DriverExtension
->MainKbdclassDeviceObject
);
669 if (!NT_SUCCESS(Status
))
671 /* FIXME: Log the error */
672 DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status
);
673 ObReferenceObject(PortDeviceObject
);
678 PDEVICE_OBJECT ClassDO
;
679 Status
= CreateKeyboardClassDeviceObject(DriverObject
, &ClassDO
);
680 if (!NT_SUCCESS(Status
))
682 /* FIXME: Log the error */
683 DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status
);
684 ObReferenceObject(PortDeviceObject
);
687 Status
= ConnectKeyboardPortDriver(PortDeviceObject
, ClassDO
);
688 if (!NT_SUCCESS(Status
))
690 /* FIXME: Log the error */
691 DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status
);
692 ObReferenceObject(PortDeviceObject
);
693 IoDeleteDevice(ClassDO
);
697 if (Status
== STATUS_NO_MORE_ENTRIES
)
698 Status
= STATUS_SUCCESS
;
701 if (KeyValueInformation
!= NULL
)
702 ExFreePool(KeyValueInformation
);
703 if (hDeviceMapKey
!= (HANDLE
)-1)
704 ZwClose(hDeviceMapKey
);
705 if (hPortKey
!= (HANDLE
)-1)
711 * Standard DriverEntry method.
715 IN PDRIVER_OBJECT DriverObject
,
716 IN PUNICODE_STRING RegistryPath
)
718 PKBDCLASS_DRIVER_EXTENSION DriverExtension
;
722 Status
= IoAllocateDriverObjectExtension(
725 sizeof(KBDCLASS_DRIVER_EXTENSION
),
726 (PVOID
*)&DriverExtension
);
727 if (!NT_SUCCESS(Status
))
729 DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status
);
732 RtlZeroMemory(DriverExtension
, sizeof(KBDCLASS_DRIVER_EXTENSION
));
734 Status
= ReadRegistryEntries(RegistryPath
, DriverExtension
);
735 if (!NT_SUCCESS(Status
))
737 DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status
);
741 if (DriverExtension
->ConnectMultiplePorts
== 1)
743 Status
= CreateKeyboardClassDeviceObject(
745 &DriverExtension
->MainKbdclassDeviceObject
);
746 if (!NT_SUCCESS(Status
))
748 DPRINT("CreateKeyboardClassDeviceObject() failed with status 0x%08lx\n", Status
);
753 DriverObject
->DriverExtension
->AddDevice
= KbdclassAddDevice
;
754 DriverObject
->DriverUnload
= DriverUnload
;
756 for (i
= 0; i
< IRP_MJ_MAXIMUM_FUNCTION
; i
++)
757 DriverObject
->MajorFunction
[i
] = IrpStub
;
759 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdclassCreate
;
760 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdclassClose
;
761 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = KbdclassCleanup
;
762 DriverObject
->MajorFunction
[IRP_MJ_READ
] = KbdclassRead
;
763 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdclassDeviceControl
;
764 DriverObject
->DriverStartIo
= KbdclassStartIo
;
766 Status
= SearchForLegacyDrivers(DriverObject
, DriverExtension
);