2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Mouse class driver
4 * FILE: drivers/mouclass/mouclass.c
5 * PURPOSE: Mouse class driver
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
17 SearchForLegacyDrivers(
18 IN PDRIVER_OBJECT DriverObject
,
19 IN PCLASS_DRIVER_EXTENSION DriverExtension
);
22 DriverUnload(IN PDRIVER_OBJECT DriverObject
)
24 // nothing to do here yet
29 IN PDEVICE_OBJECT DeviceObject
,
32 DPRINT("IRP_MJ_CREATE\n");
34 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
35 return ForwardIrpAndForget(DeviceObject
, Irp
);
37 /* FIXME: open all associated Port devices */
38 return STATUS_SUCCESS
;
43 IN PDEVICE_OBJECT DeviceObject
,
46 DPRINT("IRP_MJ_CLOSE\n");
48 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
49 return ForwardIrpAndForget(DeviceObject
, Irp
);
51 /* FIXME: close all associated Port devices */
52 return STATUS_SUCCESS
;
57 IN PDEVICE_OBJECT DeviceObject
,
60 DPRINT("IRP_MJ_CLEANUP\n");
62 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
63 return ForwardIrpAndForget(DeviceObject
, Irp
);
65 /* FIXME: cleanup all associated Port devices */
66 return STATUS_SUCCESS
;
71 IN PDEVICE_OBJECT DeviceObject
,
74 DPRINT("IRP_MJ_READ\n");
76 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
77 return ForwardIrpAndForget(DeviceObject
, Irp
);
79 if (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
< sizeof(MOUSE_INPUT_DATA
))
81 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
82 Irp
->IoStatus
.Information
= 0;
83 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
85 return STATUS_BUFFER_TOO_SMALL
;
88 IoMarkIrpPending(Irp
);
89 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
90 return STATUS_PENDING
;
95 IN PDEVICE_OBJECT DeviceObject
,
98 PCLASS_DEVICE_EXTENSION DeviceExtension
;
99 NTSTATUS Status
= Irp
->IoStatus
.Status
;
101 DPRINT("IRP_MJ_DEVICE_CONTROL\n");
103 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
104 return ForwardIrpAndForget(DeviceObject
, Irp
);
106 DeviceExtension
= (PCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
108 switch (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
)
110 case IOCTL_MOUSE_QUERY_ATTRIBUTES
:
112 /* FIXME: We hope that all devices will return the same result.
113 * Ask only the first one */
114 PLIST_ENTRY Head
= &((PCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->ListHead
;
115 if (Head
->Flink
!= Head
)
117 /* We have at least one keyboard */
118 PPORT_DEVICE_EXTENSION DevExt
= CONTAINING_RECORD(Head
->Flink
, PORT_DEVICE_EXTENSION
, ListEntry
);
119 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
120 IoSkipCurrentIrpStackLocation(Irp
);
121 return IoCallDriver(DevExt
->DeviceObject
, Irp
);
126 DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
127 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
);
132 Irp
->IoStatus
.Status
= Status
;
133 Irp
->IoStatus
.Information
= 0;
134 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
139 static NTSTATUS NTAPI
141 IN PDEVICE_OBJECT DeviceObject
,
144 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
146 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
148 /* Forward some IRPs to lower device */
149 switch (IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
)
152 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
153 return ForwardIrpAndForget(DeviceObject
, Irp
);
156 DPRINT1("Port DO stub for major function 0x%lx\n",
157 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
159 Status
= Irp
->IoStatus
.Status
;
165 DPRINT1("Class DO stub for major function 0x%lx\n",
166 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
168 Status
= Irp
->IoStatus
.Status
;
171 Irp
->IoStatus
.Status
= Status
;
172 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
178 IN PUNICODE_STRING RegistryPath
,
179 IN PCLASS_DRIVER_EXTENSION DriverExtension
)
181 UNICODE_STRING ParametersRegistryKey
;
182 RTL_QUERY_REGISTRY_TABLE Parameters
[4];
185 ULONG DefaultConnectMultiplePorts
= 1;
186 ULONG DefaultDataQueueSize
= 0x64;
187 UNICODE_STRING DefaultDeviceBaseName
= RTL_CONSTANT_STRING(L
"PointerClass");
189 ParametersRegistryKey
.Length
= 0;
190 ParametersRegistryKey
.MaximumLength
= RegistryPath
->Length
+ sizeof(L
"\\Parameters") + sizeof(UNICODE_NULL
);
191 ParametersRegistryKey
.Buffer
= ExAllocatePool(PagedPool
, ParametersRegistryKey
.MaximumLength
);
192 if (!ParametersRegistryKey
.Buffer
)
194 DPRINT("ExAllocatePool() failed\n");
195 return STATUS_INSUFFICIENT_RESOURCES
;
197 RtlCopyUnicodeString(&ParametersRegistryKey
, RegistryPath
);
198 RtlAppendUnicodeToString(&ParametersRegistryKey
, L
"\\Parameters");
199 ParametersRegistryKey
.Buffer
[ParametersRegistryKey
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
201 RtlZeroMemory(Parameters
, sizeof(Parameters
));
203 Parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
204 Parameters
[0].Name
= L
"ConnectMultiplePorts";
205 Parameters
[0].EntryContext
= &DriverExtension
->ConnectMultiplePorts
;
206 Parameters
[0].DefaultType
= REG_DWORD
;
207 Parameters
[0].DefaultData
= &DefaultConnectMultiplePorts
;
208 Parameters
[0].DefaultLength
= sizeof(ULONG
);
210 Parameters
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
211 Parameters
[1].Name
= L
"MouseDataQueueSize";
212 Parameters
[1].EntryContext
= &DriverExtension
->DataQueueSize
;
213 Parameters
[1].DefaultType
= REG_DWORD
;
214 Parameters
[1].DefaultData
= &DefaultDataQueueSize
;
215 Parameters
[1].DefaultLength
= sizeof(ULONG
);
217 Parameters
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
218 Parameters
[2].Name
= L
"PointerDeviceBaseName";
219 Parameters
[2].EntryContext
= &DriverExtension
->DeviceBaseName
;
220 Parameters
[2].DefaultType
= REG_SZ
;
221 Parameters
[2].DefaultData
= &DefaultDeviceBaseName
;
222 Parameters
[2].DefaultLength
= 0;
224 Status
= RtlQueryRegistryValues(
225 RTL_REGISTRY_ABSOLUTE
,
226 ParametersRegistryKey
.Buffer
,
231 if (NT_SUCCESS(Status
))
234 if (DriverExtension
->ConnectMultiplePorts
!= 0
235 && DriverExtension
->ConnectMultiplePorts
!= 1)
237 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
239 if (DriverExtension
->DataQueueSize
== 0)
241 DriverExtension
->DataQueueSize
= DefaultDataQueueSize
;
244 else if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
246 /* Registry path doesn't exist. Set defaults */
247 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
248 DriverExtension
->DataQueueSize
= DefaultDataQueueSize
;
249 Status
= RtlDuplicateUnicodeString(
250 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
251 &DefaultDeviceBaseName
,
252 &DriverExtension
->DeviceBaseName
);
259 CreateClassDeviceObject(
260 IN PDRIVER_OBJECT DriverObject
,
261 OUT PDEVICE_OBJECT
*ClassDO OPTIONAL
)
263 PCLASS_DRIVER_EXTENSION DriverExtension
;
266 UNICODE_STRING DeviceNameU
;
267 PWSTR DeviceIdW
= NULL
; /* Pointer into DeviceNameU.Buffer */
269 PCLASS_DEVICE_EXTENSION DeviceExtension
;
272 DPRINT("CreateClassDeviceObject(0x%p)\n", DriverObject
);
274 /* Create new device object */
275 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
276 DeviceNameU
.Length
= 0;
277 DeviceNameU
.MaximumLength
=
278 wcslen(L
"\\Device\\") * sizeof(WCHAR
) /* "\Device\" */
279 + DriverExtension
->DeviceBaseName
.Length
/* "PointerClass" */
280 + 4 * sizeof(WCHAR
) /* Id between 0 and 9999 */
281 + sizeof(UNICODE_NULL
); /* Final NULL char */
282 DeviceNameU
.Buffer
= ExAllocatePool(PagedPool
, DeviceNameU
.MaximumLength
);
283 if (!DeviceNameU
.Buffer
)
285 DPRINT("ExAllocatePool() failed\n");
286 return STATUS_INSUFFICIENT_RESOURCES
;
288 Status
= RtlAppendUnicodeToString(&DeviceNameU
, L
"\\Device\\");
289 if (!NT_SUCCESS(Status
))
291 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status
);
294 Status
= RtlAppendUnicodeStringToString(&DeviceNameU
, &DriverExtension
->DeviceBaseName
);
295 if (!NT_SUCCESS(Status
))
297 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status
);
300 PrefixLength
= DeviceNameU
.MaximumLength
- 4 * sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
301 DeviceIdW
= &DeviceNameU
.Buffer
[PrefixLength
/ sizeof(WCHAR
)];
302 while (DeviceId
< 9999)
304 DeviceNameU
.Length
= PrefixLength
+ swprintf(DeviceIdW
, L
"%lu", DeviceId
) * sizeof(WCHAR
);
305 Status
= IoCreateDevice(
307 sizeof(CLASS_DEVICE_EXTENSION
),
310 FILE_DEVICE_SECURE_OPEN
,
313 if (NT_SUCCESS(Status
))
315 else if (Status
!= STATUS_OBJECT_NAME_COLLISION
)
317 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
322 DPRINT("Too many devices starting with '\\Device\\%wZ'\n", &DriverExtension
->DeviceBaseName
);
323 Status
= STATUS_TOO_MANY_NAMES
;
325 if (!NT_SUCCESS(Status
))
327 ExFreePool(DeviceNameU
.Buffer
);
331 DeviceExtension
= (PCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
332 RtlZeroMemory(DeviceExtension
, sizeof(CLASS_DEVICE_EXTENSION
));
333 DeviceExtension
->Common
.IsClassDO
= TRUE
;
334 DeviceExtension
->DriverExtension
= DriverExtension
;
335 InitializeListHead(&DeviceExtension
->ListHead
);
336 KeInitializeSpinLock(&DeviceExtension
->ListSpinLock
);
337 KeInitializeSpinLock(&DeviceExtension
->SpinLock
);
338 DeviceExtension
->ReadIsPending
= FALSE
;
339 DeviceExtension
->InputCount
= 0;
340 DeviceExtension
->PortData
= ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->DataQueueSize
* sizeof(MOUSE_INPUT_DATA
));
341 Fdo
->Flags
|= DO_POWER_PAGABLE
;
342 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
344 /* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
345 RtlWriteRegistryValue(
346 RTL_REGISTRY_DEVICEMAP
,
347 DriverExtension
->DeviceBaseName
.Buffer
,
350 DriverExtension
->RegistryPath
.Buffer
,
351 DriverExtension
->RegistryPath
.MaximumLength
);
353 ExFreePool(DeviceNameU
.Buffer
);
358 return STATUS_SUCCESS
;
363 IN PDEVICE_OBJECT ClassDeviceObject
,
364 IN OUT PMOUSE_INPUT_DATA DataStart
,
365 IN PMOUSE_INPUT_DATA DataEnd
,
366 IN OUT PULONG ConsumedCount
)
368 PCLASS_DEVICE_EXTENSION ClassDeviceExtension
= ClassDeviceObject
->DeviceExtension
;
371 PIO_STACK_LOCATION Stack
;
372 ULONG InputCount
= DataEnd
- DataStart
;
375 ASSERT(ClassDeviceExtension
->Common
.IsClassDO
);
377 KeAcquireSpinLock(&ClassDeviceExtension
->SpinLock
, &OldIrql
);
379 DPRINT("ClassCallback()\n");
380 /* A filter driver might have consumed all the data already; I'm
381 * not sure if they are supposed to move the packets when they
382 * consume them though.
384 if (ClassDeviceExtension
->ReadIsPending
== TRUE
&& InputCount
)
386 Irp
= ClassDeviceObject
->CurrentIrp
;
387 ClassDeviceObject
->CurrentIrp
= NULL
;
388 Stack
= IoGetCurrentIrpStackLocation(Irp
);
390 /* A read request is waiting for input, so go straight to it */
393 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
395 sizeof(MOUSE_INPUT_DATA
));
397 /* Go to next packet and complete this request with STATUS_SUCCESS */
398 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
399 Irp
->IoStatus
.Information
= sizeof(MOUSE_INPUT_DATA
);
400 Stack
->Parameters
.Read
.Length
= sizeof(MOUSE_INPUT_DATA
);
402 ClassDeviceExtension
->ReadIsPending
= FALSE
;
404 /* Skip the packet we just sent away */
410 /* If we have data from the port driver and a higher service to send the data to */
413 if (ClassDeviceExtension
->InputCount
+ InputCount
> ClassDeviceExtension
->DriverExtension
->DataQueueSize
)
414 ReadSize
= ClassDeviceExtension
->DriverExtension
->DataQueueSize
- ClassDeviceExtension
->InputCount
;
416 ReadSize
= InputCount
;
419 * FIXME: If we exceed the buffer, data gets thrown away.. better
424 * Move the input data from the port data queue to our class data
428 ClassDeviceExtension
->PortData
,
430 sizeof(MOUSE_INPUT_DATA
) * ReadSize
);
432 /* Move the pointer and counter up */
433 ClassDeviceExtension
->PortData
+= ReadSize
;
434 ClassDeviceExtension
->InputCount
+= ReadSize
;
436 (*ConsumedCount
) += ReadSize
;
440 DPRINT("ClassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount
);
443 KeReleaseSpinLock(&ClassDeviceExtension
->SpinLock
, OldIrql
);
447 IoStartNextPacket(ClassDeviceObject
, FALSE
);
448 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
451 DPRINT("Leaving ClassCallback()\n");
455 /* Send IOCTL_INTERNAL_*_CONNECT to port */
458 IN PDEVICE_OBJECT PortDO
,
459 IN PDEVICE_OBJECT ClassDO
)
463 IO_STATUS_BLOCK IoStatus
;
464 CONNECT_DATA ConnectData
;
467 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
469 ConnectData
.ClassDeviceObject
= ClassDO
;
470 ConnectData
.ClassService
= ClassCallback
;
472 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT
,
474 &ConnectData
, sizeof(CONNECT_DATA
),
476 TRUE
, &Event
, &IoStatus
);
478 Status
= IoCallDriver(PortDO
, Irp
);
480 if (Status
== STATUS_PENDING
)
481 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
483 IoStatus
.Status
= Status
;
485 if (NT_SUCCESS(IoStatus
.Status
))
487 ObReferenceObject(PortDO
);
488 ExInterlockedInsertTailList(
489 &((PCLASS_DEVICE_EXTENSION
)ClassDO
->DeviceExtension
)->ListHead
,
490 &((PPORT_DEVICE_EXTENSION
)PortDO
->DeviceExtension
)->ListEntry
,
491 &((PCLASS_DEVICE_EXTENSION
)ClassDO
->DeviceExtension
)->ListSpinLock
);
492 if (ClassDO
->StackSize
<= PortDO
->StackSize
)
494 /* Increase the stack size, in case we have to
495 * forward some IRPs to the port device object
497 ClassDO
->StackSize
= PortDO
->StackSize
+ 1;
501 return IoStatus
.Status
;
504 static NTSTATUS NTAPI
506 IN PDRIVER_OBJECT DriverObject
,
507 IN PDEVICE_OBJECT Pdo
)
509 PCLASS_DRIVER_EXTENSION DriverExtension
;
510 PDEVICE_OBJECT Fdo
= NULL
;
511 PPORT_DEVICE_EXTENSION DeviceExtension
= NULL
;
514 DPRINT("ClassAddDevice called. Pdo = 0x%p\n", Pdo
);
516 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
519 /* We're getting a NULL Pdo at the first call as we're a legacy driver.
520 * Use it to search for legacy port drivers. */
521 return SearchForLegacyDrivers(DriverObject
, DriverExtension
);
523 /* Create new device object */
524 Status
= IoCreateDevice(
526 sizeof(PORT_DEVICE_EXTENSION
),
529 FILE_DEVICE_SECURE_OPEN
,
532 if (!NT_SUCCESS(Status
))
534 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
538 DeviceExtension
= (PPORT_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
539 RtlZeroMemory(DeviceExtension
, sizeof(CLASS_DEVICE_EXTENSION
));
540 DeviceExtension
->Common
.IsClassDO
= FALSE
;
541 DeviceExtension
->DeviceObject
= Fdo
;
542 DeviceExtension
->PnpState
= dsStopped
;
543 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
544 if (!NT_SUCCESS(Status
))
546 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
549 if (DeviceExtension
->LowerDevice
->Flags
& DO_POWER_PAGABLE
)
550 Fdo
->Flags
|= DO_POWER_PAGABLE
;
551 if (DeviceExtension
->LowerDevice
->Flags
& DO_BUFFERED_IO
)
552 Fdo
->Flags
|= DO_BUFFERED_IO
;
554 if (DriverExtension
->ConnectMultiplePorts
)
555 DeviceExtension
->ClassDO
= DriverExtension
->MainClassDeviceObject
;
558 /* We need a new class device object for this Fdo */
559 Status
= CreateClassDeviceObject(
561 &DeviceExtension
->ClassDO
);
562 if (!NT_SUCCESS(Status
))
564 DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status
);
568 Status
= ConnectPortDriver(Fdo
, DeviceExtension
->ClassDO
);
569 if (!NT_SUCCESS(Status
))
571 DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status
);
572 ObDereferenceObject(Fdo
);
575 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
577 /* Register interface */
578 Status
= IoRegisterDeviceInterface(
580 &GUID_DEVINTERFACE_MOUSE
,
582 &DeviceExtension
->InterfaceName
);
583 if (Status
== STATUS_INVALID_PARAMETER_1
)
585 /* The Pdo was a strange one ; maybe it is a legacy device.
586 * Ignore the error. */
587 return STATUS_SUCCESS
;
589 else if (!NT_SUCCESS(Status
))
591 DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
595 return STATUS_SUCCESS
;
600 if (DeviceExtension
->LowerDevice
)
601 IoDetachDevice(DeviceExtension
->LowerDevice
);
602 if (DriverExtension
->ConnectMultiplePorts
&& DeviceExtension
->ClassDO
)
604 PCLASS_DEVICE_EXTENSION ClassDeviceExtension
;
605 ClassDeviceExtension
= (PCLASS_DEVICE_EXTENSION
)DeviceExtension
->ClassDO
->DeviceExtension
;
606 ExFreePool(ClassDeviceExtension
->PortData
);
616 IN PDEVICE_OBJECT DeviceObject
,
619 PCLASS_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
620 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
622 ASSERT(DeviceExtension
->Common
.IsClassDO
);
624 if (DeviceExtension
->InputCount
> 0)
628 KeAcquireSpinLock(&DeviceExtension
->SpinLock
, &oldIrql
);
630 DPRINT("Mdl: %p, UserBuffer: %p, InputCount: %lu\n",
633 DeviceExtension
->InputCount
);
637 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
638 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
639 sizeof(MOUSE_INPUT_DATA
));
641 if (DeviceExtension
->InputCount
> 1)
644 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
645 DeviceExtension
->PortData
- DeviceExtension
->InputCount
+ 1,
646 (DeviceExtension
->InputCount
- 1) * sizeof(MOUSE_INPUT_DATA
));
648 DeviceExtension
->PortData
--;
649 DeviceExtension
->InputCount
--;
650 DeviceExtension
->ReadIsPending
= FALSE
;
652 /* Go to next packet and complete this request with STATUS_SUCCESS */
653 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
654 Irp
->IoStatus
.Information
= sizeof(MOUSE_INPUT_DATA
);
655 Stack
->Parameters
.Read
.Length
= sizeof(MOUSE_INPUT_DATA
);
656 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
658 IoStartNextPacket(DeviceObject
, FALSE
);
659 KeReleaseSpinLock(&DeviceExtension
->SpinLock
, oldIrql
);
663 DeviceExtension
->ReadIsPending
= TRUE
;
668 SearchForLegacyDrivers(
669 IN PDRIVER_OBJECT DriverObject
,
670 IN PCLASS_DRIVER_EXTENSION DriverExtension
)
672 UNICODE_STRING DeviceMapKeyU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
673 UNICODE_STRING PortBaseName
= {0, };
674 PKEY_VALUE_BASIC_INFORMATION KeyValueInformation
= NULL
;
675 OBJECT_ATTRIBUTES ObjectAttributes
;
676 HANDLE hDeviceMapKey
= (HANDLE
)-1;
677 HANDLE hPortKey
= (HANDLE
)-1;
679 ULONG Size
, ResultLength
;
682 /* Create port base name, by replacing Class by Port at the end of the class base name */
683 Status
= RtlDuplicateUnicodeString(
684 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
685 &DriverExtension
->DeviceBaseName
,
687 if (!NT_SUCCESS(Status
))
689 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
692 PortBaseName
.Length
-= (sizeof(L
"Class") - sizeof(UNICODE_NULL
));
693 RtlAppendUnicodeToString(&PortBaseName
, L
"Port");
695 /* Allocate memory */
696 Size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + MAX_PATH
;
697 KeyValueInformation
= ExAllocatePool(PagedPool
, Size
);
698 if (!KeyValueInformation
)
700 DPRINT("ExAllocatePool() failed\n");
701 Status
= STATUS_INSUFFICIENT_RESOURCES
;
705 /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
706 InitializeObjectAttributes(&ObjectAttributes
, &DeviceMapKeyU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
707 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
708 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
710 DPRINT("HKLM\\HARDWARE\\DEVICEMAP is non-existent\n");
711 Status
= STATUS_SUCCESS
;
714 else if (!NT_SUCCESS(Status
))
716 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
721 InitializeObjectAttributes(&ObjectAttributes
, &PortBaseName
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceMapKey
, NULL
);
722 Status
= ZwOpenKey(&hPortKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
723 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
725 DPRINT("HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName
);
726 Status
= STATUS_SUCCESS
;
729 else if (!NT_SUCCESS(Status
))
731 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
735 /* Read each value name */
736 while (ZwEnumerateValueKey(hPortKey
, Index
++, KeyValueBasicInformation
, KeyValueInformation
, Size
, &ResultLength
) == STATUS_SUCCESS
)
738 UNICODE_STRING PortName
;
739 PDEVICE_OBJECT PortDeviceObject
= NULL
;
740 PFILE_OBJECT FileObject
= NULL
;
742 PortName
.Length
= PortName
.MaximumLength
= KeyValueInformation
->NameLength
;
743 PortName
.Buffer
= KeyValueInformation
->Name
;
745 /* Open the device object pointer */
746 Status
= IoGetDeviceObjectPointer(&PortName
, FILE_READ_ATTRIBUTES
, &FileObject
, &PortDeviceObject
);
747 if (!NT_SUCCESS(Status
))
749 DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status
);
752 DPRINT("Legacy driver found: %wZ\n", &PortDeviceObject
->DriverObject
->DriverName
);
754 Status
= ClassAddDevice(DriverObject
, PortDeviceObject
);
755 if (!NT_SUCCESS(Status
))
757 /* FIXME: Log the error */
758 DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status
);
761 if (Status
== STATUS_NO_MORE_ENTRIES
)
762 Status
= STATUS_SUCCESS
;
765 if (KeyValueInformation
!= NULL
)
766 ExFreePool(KeyValueInformation
);
767 if (hDeviceMapKey
!= (HANDLE
)-1)
768 ZwClose(hDeviceMapKey
);
769 if (hPortKey
!= (HANDLE
)-1)
775 * Standard DriverEntry method.
779 IN PDRIVER_OBJECT DriverObject
,
780 IN PUNICODE_STRING RegistryPath
)
782 PCLASS_DRIVER_EXTENSION DriverExtension
;
786 Status
= IoAllocateDriverObjectExtension(
789 sizeof(CLASS_DRIVER_EXTENSION
),
790 (PVOID
*)&DriverExtension
);
791 if (!NT_SUCCESS(Status
))
793 DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status
);
796 RtlZeroMemory(DriverExtension
, sizeof(CLASS_DRIVER_EXTENSION
));
798 Status
= RtlDuplicateUnicodeString(
799 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
801 &DriverExtension
->RegistryPath
);
802 if (!NT_SUCCESS(Status
))
804 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
808 Status
= ReadRegistryEntries(RegistryPath
, DriverExtension
);
809 if (!NT_SUCCESS(Status
))
811 DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status
);
815 if (DriverExtension
->ConnectMultiplePorts
== 1)
817 Status
= CreateClassDeviceObject(
819 &DriverExtension
->MainClassDeviceObject
);
820 if (!NT_SUCCESS(Status
))
822 DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status
);
827 DriverObject
->DriverExtension
->AddDevice
= ClassAddDevice
;
828 DriverObject
->DriverUnload
= DriverUnload
;
830 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
831 DriverObject
->MajorFunction
[i
] = IrpStub
;
833 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ClassCreate
;
834 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ClassClose
;
835 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = ClassCleanup
;
836 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ClassRead
;
837 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ClassDeviceControl
;
838 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = ForwardIrpAndForget
;
839 DriverObject
->DriverStartIo
= ClassStartIo
;
841 return STATUS_SUCCESS
;