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_READ\n");
57 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
58 return ForwardIrpAndForget(DeviceObject
, Irp
);
60 if (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
< sizeof(KEYBOARD_INPUT_DATA
))
62 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
63 Irp
->IoStatus
.Information
= 0;
64 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
66 return STATUS_BUFFER_TOO_SMALL
;
69 IoMarkIrpPending(Irp
);
70 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
71 return STATUS_PENDING
;
75 KbdclassDeviceControl(
76 IN PDEVICE_OBJECT DeviceObject
,
81 DPRINT("IRP_MJ_DEVICE_CONTROL\n");
83 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
84 return ForwardIrpAndForget(DeviceObject
, Irp
);
86 switch (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
)
88 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES
:
89 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
:
90 case IOCTL_KEYBOARD_QUERY_INDICATORS
:
91 case IOCTL_KEYBOARD_QUERY_TYPEMATIC
:
92 case IOCTL_KEYBOARD_SET_INDICATORS
:
93 case IOCTL_KEYBOARD_SET_TYPEMATIC
: /* not in MSDN, would seem logical */
94 /* FIXME: send it to all associated Port devices */
95 Status
= STATUS_NOT_SUPPORTED
;
98 DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
99 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
);
100 Status
= STATUS_NOT_SUPPORTED
;
103 Irp
->IoStatus
.Status
= Status
;
104 Irp
->IoStatus
.Information
= 0;
105 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
110 static NTSTATUS NTAPI
112 IN PDEVICE_OBJECT DeviceObject
,
115 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
117 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
119 /* Forward some IRPs to lower device */
120 switch (IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
)
122 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
123 return ForwardIrpAndForget(DeviceObject
, Irp
);
126 DPRINT1("Port DO stub for major function 0x%lx\n",
127 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
129 Status
= Irp
->IoStatus
.Status
;
135 DPRINT1("Class DO stub for major function 0x%lx\n",
136 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
138 Status
= Irp
->IoStatus
.Status
;
141 Irp
->IoStatus
.Status
= Status
;
142 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
148 IN PUNICODE_STRING RegistryPath
,
149 IN PKBDCLASS_DRIVER_EXTENSION DriverExtension
)
151 RTL_QUERY_REGISTRY_TABLE Parameters
[4];
154 ULONG DefaultConnectMultiplePorts
= 1;
155 ULONG DefaultKeyboardDataQueueSize
= 0x64;
156 UNICODE_STRING DefaultKeyboardDeviceBaseName
= RTL_CONSTANT_STRING(L
"KeyboardClass");
158 RtlZeroMemory(Parameters
, sizeof(Parameters
));
160 Parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
161 Parameters
[0].Name
= L
"ConnectMultiplePorts";
162 Parameters
[0].EntryContext
= &DriverExtension
->ConnectMultiplePorts
;
163 Parameters
[0].DefaultType
= REG_DWORD
;
164 Parameters
[0].DefaultData
= &DefaultConnectMultiplePorts
;
165 Parameters
[0].DefaultLength
= sizeof(ULONG
);
167 Parameters
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
168 Parameters
[1].Name
= L
"KeyboardDataQueueSize";
169 Parameters
[1].EntryContext
= &DriverExtension
->KeyboardDataQueueSize
;
170 Parameters
[1].DefaultType
= REG_DWORD
;
171 Parameters
[1].DefaultData
= &DefaultKeyboardDataQueueSize
;
172 Parameters
[1].DefaultLength
= sizeof(ULONG
);
174 Parameters
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
175 Parameters
[2].Name
= L
"KeyboardDeviceBaseName";
176 Parameters
[2].EntryContext
= &DriverExtension
->KeyboardDeviceBaseName
;
177 Parameters
[2].DefaultType
= REG_SZ
;
178 Parameters
[2].DefaultData
= &DefaultKeyboardDeviceBaseName
;
179 Parameters
[2].DefaultLength
= sizeof(ULONG
);
181 Status
= RtlQueryRegistryValues(
182 RTL_REGISTRY_ABSOLUTE
,
183 RegistryPath
->Buffer
,
188 if (NT_SUCCESS(Status
))
191 if (DriverExtension
->ConnectMultiplePorts
!= 0
192 && DriverExtension
->ConnectMultiplePorts
!= 1)
194 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
196 if (DriverExtension
->KeyboardDataQueueSize
== 0)
198 DriverExtension
->KeyboardDataQueueSize
= DefaultKeyboardDataQueueSize
;
206 CreateKeyboardClassDeviceObject(
207 IN PDRIVER_OBJECT DriverObject
,
208 OUT PDEVICE_OBJECT
*ClassDO OPTIONAL
)
210 PKBDCLASS_DRIVER_EXTENSION DriverExtension
;
213 UNICODE_STRING DeviceNameU
;
214 PWSTR DeviceIdW
= NULL
; /* Pointer into DeviceNameU.Buffer */
216 PKBDCLASS_DEVICE_EXTENSION DeviceExtension
;
219 DPRINT("CreateKeyboardClassDeviceObject(0x%p)\n", DriverObject
);
221 /* Create new device object */
222 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
223 DeviceNameU
.Length
= 0;
224 DeviceNameU
.MaximumLength
=
225 wcslen(L
"\\Device\\") * sizeof(WCHAR
) /* "\Device\" */
226 + DriverExtension
->KeyboardDeviceBaseName
.Length
/* "KeyboardClass" */
227 + 4 * sizeof(WCHAR
) /* Id between 0 and 9999 */
228 + sizeof(UNICODE_NULL
); /* Final NULL char */
229 DeviceNameU
.Buffer
= ExAllocatePool(PagedPool
, DeviceNameU
.MaximumLength
);
230 if (!DeviceNameU
.Buffer
)
232 DPRINT("ExAllocatePool() failed\n");
233 return STATUS_INSUFFICIENT_RESOURCES
;
235 Status
= RtlAppendUnicodeToString(&DeviceNameU
, L
"\\Device\\");
236 if (!NT_SUCCESS(Status
))
238 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status
);
241 Status
= RtlAppendUnicodeStringToString(&DeviceNameU
, &DriverExtension
->KeyboardDeviceBaseName
);
242 if (!NT_SUCCESS(Status
))
244 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status
);
247 PrefixLength
= DeviceNameU
.MaximumLength
- 4 * sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
248 DeviceIdW
= &DeviceNameU
.Buffer
[PrefixLength
/ sizeof(WCHAR
)];
249 while (DeviceId
< 9999)
251 DeviceNameU
.Length
= PrefixLength
+ swprintf(DeviceIdW
, L
"%lu", DeviceId
) * sizeof(WCHAR
);
252 Status
= IoCreateDevice(
254 sizeof(KBDCLASS_DEVICE_EXTENSION
),
256 FILE_DEVICE_KEYBOARD
,
257 FILE_DEVICE_SECURE_OPEN
,
260 if (NT_SUCCESS(Status
))
262 else if (Status
!= STATUS_OBJECT_NAME_COLLISION
)
264 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
269 DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension
->KeyboardDeviceBaseName
);
270 Status
= STATUS_UNSUCCESSFUL
;
272 ExFreePool(DeviceNameU
.Buffer
);
273 if (!NT_SUCCESS(Status
))
276 DeviceExtension
= (PKBDCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
277 RtlZeroMemory(DeviceExtension
, sizeof(KBDCLASS_DEVICE_EXTENSION
));
278 DeviceExtension
->Common
.IsClassDO
= TRUE
;
279 DeviceExtension
->DriverExtension
= DriverExtension
;
280 DeviceExtension
->PnpState
= dsStopped
;
281 KeInitializeSpinLock(&(DeviceExtension
->SpinLock
));
282 DeviceExtension
->ReadIsPending
= FALSE
;
283 DeviceExtension
->InputCount
= 0;
284 DeviceExtension
->PortData
= ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->KeyboardDataQueueSize
* sizeof(KEYBOARD_INPUT_DATA
));
285 Fdo
->Flags
|= DO_POWER_PAGABLE
;
286 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
288 /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
293 return STATUS_SUCCESS
;
298 IN PDEVICE_OBJECT ClassDeviceObject
,
299 IN OUT PKEYBOARD_INPUT_DATA KeyboardDataStart
,
300 IN PKEYBOARD_INPUT_DATA KeyboardDataEnd
,
301 IN OUT PULONG ConsumedCount
)
303 PKBDCLASS_DEVICE_EXTENSION ClassDeviceExtension
= ClassDeviceObject
->DeviceExtension
;
306 PIO_STACK_LOCATION Stack
;
307 ULONG InputCount
= KeyboardDataEnd
- KeyboardDataStart
;
310 ASSERT(ClassDeviceExtension
->Common
.IsClassDO
);
312 DPRINT("KbdclassCallback()\n");
313 /* A filter driver might have consumed all the data already; I'm
314 * not sure if they are supposed to move the packets when they
315 * consume them though.
317 if (ClassDeviceExtension
->ReadIsPending
== TRUE
&& InputCount
)
319 Irp
= ClassDeviceObject
->CurrentIrp
;
320 ClassDeviceObject
->CurrentIrp
= NULL
;
321 Stack
= IoGetCurrentIrpStackLocation(Irp
);
323 /* A read request is waiting for input, so go straight to it */
326 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
328 sizeof(KEYBOARD_INPUT_DATA
));
330 /* Go to next packet and complete this request with STATUS_SUCCESS */
331 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
332 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INPUT_DATA
);
333 Stack
->Parameters
.Read
.Length
= sizeof(KEYBOARD_INPUT_DATA
);
335 ClassDeviceExtension
->ReadIsPending
= FALSE
;
337 /* Skip the packet we just sent away */
343 /* If we have data from the port driver and a higher service to send the data to */
346 KeAcquireSpinLock(&ClassDeviceExtension
->SpinLock
, &OldIrql
);
348 if (ClassDeviceExtension
->InputCount
+ InputCount
> ClassDeviceExtension
->DriverExtension
->KeyboardDataQueueSize
)
349 ReadSize
= ClassDeviceExtension
->DriverExtension
->KeyboardDataQueueSize
- ClassDeviceExtension
->InputCount
;
351 ReadSize
= InputCount
;
354 * FIXME: If we exceed the buffer, keyboard data gets thrown away.. better
359 * Move the keyboard input data from the port data queue to our class data
363 ClassDeviceExtension
->PortData
,
364 (PCHAR
)KeyboardDataStart
,
365 sizeof(KEYBOARD_INPUT_DATA
) * ReadSize
);
367 /* Move the pointer and counter up */
368 ClassDeviceExtension
->PortData
+= ReadSize
;
369 ClassDeviceExtension
->InputCount
+= ReadSize
;
371 KeReleaseSpinLock(&ClassDeviceExtension
->SpinLock
, OldIrql
);
372 (*ConsumedCount
) += ReadSize
;
376 DPRINT("KbdclassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount
);
381 IoStartNextPacket(ClassDeviceObject
, FALSE
);
382 IoCompleteRequest(Irp
, IO_KEYBOARD_INCREMENT
);
385 DPRINT("Leaving KbdclassCallback()\n");
389 /* Send IOCTL_INTERNAL_KEYBOARD_CONNECT to keyboard port */
391 ConnectKeyboardPortDriver(
392 IN PDEVICE_OBJECT KeyboardPortDO
,
393 IN PDEVICE_OBJECT KeyboardClassDO
)
397 IO_STATUS_BLOCK IoStatus
;
398 CONNECT_DATA ConnectData
;
401 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
403 ConnectData
.ClassDeviceObject
= KeyboardClassDO
;
404 ConnectData
.ClassService
= KbdclassCallback
;
406 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_KEYBOARD_CONNECT
,
408 &ConnectData
, sizeof(CONNECT_DATA
),
410 TRUE
, &Event
, &IoStatus
);
412 Status
= IoCallDriver(KeyboardPortDO
, Irp
);
414 if (Status
== STATUS_PENDING
)
415 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
417 IoStatus
.Status
= Status
;
419 return IoStatus
.Status
;
422 static NTSTATUS NTAPI
424 IN PDRIVER_OBJECT DriverObject
,
425 IN PDEVICE_OBJECT Pdo
)
427 PKBDCLASS_DRIVER_EXTENSION DriverExtension
;
429 PKBDCLASS_DEVICE_EXTENSION DeviceExtension
;
432 DPRINT("KbdclassAddDevice called. Pdo = 0x%p\n", Pdo
);
434 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
436 /* Create new device object */
437 Status
= IoCreateDevice(
439 sizeof(KBDCLASS_DEVICE_EXTENSION
),
442 FILE_DEVICE_SECURE_OPEN
,
445 if (!NT_SUCCESS(Status
))
447 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
451 DeviceExtension
= (PKBDCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
452 RtlZeroMemory(DeviceExtension
, sizeof(KBDCLASS_DEVICE_EXTENSION
));
453 DeviceExtension
->Common
.IsClassDO
= FALSE
;
454 DeviceExtension
->PnpState
= dsStopped
;
455 Fdo
->Flags
|= DO_POWER_PAGABLE
;
456 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
457 if (!NT_SUCCESS(Status
))
459 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
463 Fdo
->Flags
|= DO_BUFFERED_IO
;
464 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
466 if (DriverExtension
->ConnectMultiplePorts
)
467 Status
= ConnectKeyboardPortDriver(Fdo
, DriverExtension
->MainKbdclassDeviceObject
);
469 Status
= ConnectKeyboardPortDriver(Fdo
, Fdo
);
470 if (!NT_SUCCESS(Status
))
472 DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status
);
473 /* FIXME: why can't I cleanup without error? */
474 //IoDetachDevice(Fdo);
475 //IoDeleteDevice(Fdo);
479 /* Register GUID_DEVINTERFACE_KEYBOARD interface */
480 Status
= IoRegisterDeviceInterface(
482 &GUID_DEVINTERFACE_KEYBOARD
,
484 &DeviceExtension
->KeyboardInterfaceName
);
485 if (!NT_SUCCESS(Status
))
487 DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
491 return STATUS_SUCCESS
;
496 IN PDEVICE_OBJECT DeviceObject
,
499 PKBDCLASS_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
500 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
502 ASSERT(DeviceExtension
->Common
.IsClassDO
);
504 if (DeviceExtension
->InputCount
> 0)
508 KeAcquireSpinLock(&DeviceExtension
->SpinLock
, &oldIrql
);
512 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
513 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
514 sizeof(KEYBOARD_INPUT_DATA
));
516 if (DeviceExtension
->InputCount
> 1)
519 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
520 DeviceExtension
->PortData
- DeviceExtension
->InputCount
+ 1,
521 (DeviceExtension
->InputCount
- 1) * sizeof(KEYBOARD_INPUT_DATA
));
523 DeviceExtension
->PortData
--;
524 DeviceExtension
->InputCount
--;
525 DeviceExtension
->ReadIsPending
= FALSE
;
527 /* Go to next packet and complete this request with STATUS_SUCCESS */
528 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
529 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INPUT_DATA
);
530 Stack
->Parameters
.Read
.Length
= sizeof(KEYBOARD_INPUT_DATA
);
531 IoCompleteRequest(Irp
, IO_KEYBOARD_INCREMENT
);
533 IoStartNextPacket(DeviceObject
, FALSE
);
534 KeReleaseSpinLock(&DeviceExtension
->SpinLock
, oldIrql
);
538 DeviceExtension
->ReadIsPending
= TRUE
;
543 SearchForLegacyDrivers(
544 IN PDRIVER_OBJECT DriverObject
,
545 IN PKBDCLASS_DRIVER_EXTENSION DriverExtension
)
547 UNICODE_STRING DeviceMapKeyU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
548 UNICODE_STRING PortBaseName
= {0, };
549 PKEY_VALUE_BASIC_INFORMATION KeyValueInformation
= NULL
;
550 OBJECT_ATTRIBUTES ObjectAttributes
;
551 HANDLE hDeviceMapKey
= (HANDLE
)-1;
552 HANDLE hPortKey
= (HANDLE
)-1;
554 ULONG Size
, ResultLength
;
557 /* Create port base name, by replacing Class by Port at the end of the class base name */
558 Status
= RtlDuplicateUnicodeString(
559 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
560 &DriverExtension
->KeyboardDeviceBaseName
,
562 if (!NT_SUCCESS(Status
))
564 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
567 PortBaseName
.Length
-= (sizeof(L
"Class") - sizeof(UNICODE_NULL
));
568 RtlAppendUnicodeToString(&PortBaseName
, L
"Port");
570 /* Allocate memory */
571 Size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + MAX_PATH
;
572 KeyValueInformation
= ExAllocatePool(PagedPool
, Size
);
573 if (!KeyValueInformation
)
575 DPRINT("ExAllocatePool() failed\n");
576 Status
= STATUS_INSUFFICIENT_RESOURCES
;
580 /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
581 InitializeObjectAttributes(&ObjectAttributes
, &DeviceMapKeyU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
582 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
583 if (!NT_SUCCESS(Status
))
585 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
590 InitializeObjectAttributes(&ObjectAttributes
, &PortBaseName
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceMapKey
, NULL
);
591 Status
= ZwOpenKey(&hPortKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
592 if (!NT_SUCCESS(Status
))
594 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
595 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
599 /* Read each value name */
600 while (ZwEnumerateValueKey(hPortKey
, Index
++, KeyValueBasicInformation
, KeyValueInformation
, Size
, &ResultLength
) == STATUS_SUCCESS
)
602 UNICODE_STRING PortName
;
603 PDEVICE_OBJECT PortDeviceObject
= NULL
;
604 PFILE_OBJECT FileObject
= NULL
;
606 PortName
.Length
= PortName
.MaximumLength
= KeyValueInformation
->NameLength
;
607 PortName
.Buffer
= KeyValueInformation
->Name
;
609 /* Open the device object pointer */
610 Status
= IoGetDeviceObjectPointer(&PortName
, FILE_READ_ATTRIBUTES
, &FileObject
, &PortDeviceObject
);
611 if (!NT_SUCCESS(Status
))
613 DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status
);
616 /* Connect the port device object */
617 if (DriverExtension
->ConnectMultiplePorts
)
619 Status
= ConnectKeyboardPortDriver(PortDeviceObject
, DriverExtension
->MainKbdclassDeviceObject
);
620 if (!NT_SUCCESS(Status
))
622 /* FIXME: Log the error */
623 DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status
);
629 PDEVICE_OBJECT ClassDO
;
630 Status
= CreateKeyboardClassDeviceObject(DriverObject
, &ClassDO
);
631 if (!NT_SUCCESS(Status
))
633 /* FIXME: Log the error */
634 DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status
);
638 Status
= ConnectKeyboardPortDriver(PortDeviceObject
, ClassDO
);
639 if (!NT_SUCCESS(Status
))
641 /* FIXME: Log the error */
642 DPRINT("ConnectKeyboardPortDriver() failed with status 0x%08lx\n", Status
);
647 if (Status
== STATUS_NO_MORE_ENTRIES
)
648 Status
= STATUS_SUCCESS
;
651 if (KeyValueInformation
!= NULL
)
652 ExFreePool(KeyValueInformation
);
653 if (hDeviceMapKey
!= (HANDLE
)-1)
654 ZwClose(hDeviceMapKey
);
655 if (hPortKey
!= (HANDLE
)-1)
661 * Standard DriverEntry method.
665 IN PDRIVER_OBJECT DriverObject
,
666 IN PUNICODE_STRING RegistryPath
)
668 PKBDCLASS_DRIVER_EXTENSION DriverExtension
;
672 Status
= IoAllocateDriverObjectExtension(
675 sizeof(KBDCLASS_DRIVER_EXTENSION
),
676 (PVOID
*)&DriverExtension
);
677 if (!NT_SUCCESS(Status
))
679 DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status
);
682 RtlZeroMemory(DriverExtension
, sizeof(KBDCLASS_DRIVER_EXTENSION
));
684 Status
= ReadRegistryEntries(RegistryPath
, DriverExtension
);
685 if (!NT_SUCCESS(Status
))
687 DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status
);
691 if (DriverExtension
->ConnectMultiplePorts
== 1)
693 Status
= CreateKeyboardClassDeviceObject(
695 &DriverExtension
->MainKbdclassDeviceObject
);
696 if (!NT_SUCCESS(Status
))
698 DPRINT("CreateKeyboardClassDeviceObject() failed with status 0x%08lx\n", Status
);
703 DriverObject
->DriverExtension
->AddDevice
= KbdclassAddDevice
;
704 DriverObject
->DriverUnload
= DriverUnload
;
706 for (i
= 0; i
< IRP_MJ_MAXIMUM_FUNCTION
; i
++)
707 DriverObject
->MajorFunction
[i
] = IrpStub
;
709 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdclassCreate
;
710 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdclassClose
;
711 DriverObject
->MajorFunction
[IRP_MJ_READ
] = KbdclassRead
;
712 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdclassDeviceControl
;
713 DriverObject
->DriverStartIo
= KbdclassStartIo
;
715 Status
= SearchForLegacyDrivers(DriverObject
, DriverExtension
);