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 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
39 Irp
->IoStatus
.Information
= 0;
40 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
41 return STATUS_SUCCESS
;
46 IN PDEVICE_OBJECT DeviceObject
,
49 DPRINT("IRP_MJ_CLOSE\n");
51 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
52 return ForwardIrpAndForget(DeviceObject
, Irp
);
54 /* FIXME: close all associated Port devices */
55 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
56 Irp
->IoStatus
.Information
= 0;
57 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
58 return STATUS_SUCCESS
;
63 IN PDEVICE_OBJECT DeviceObject
,
66 DPRINT("IRP_MJ_CLEANUP\n");
68 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
69 return ForwardIrpAndForget(DeviceObject
, Irp
);
71 /* FIXME: cleanup all associated Port devices */
72 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
73 Irp
->IoStatus
.Information
= 0;
74 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
75 return STATUS_SUCCESS
;
80 IN PDEVICE_OBJECT DeviceObject
,
83 DPRINT("IRP_MJ_READ\n");
85 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
86 return ForwardIrpAndForget(DeviceObject
, Irp
);
88 if (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
< sizeof(MOUSE_INPUT_DATA
))
90 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
91 Irp
->IoStatus
.Information
= 0;
92 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
94 return STATUS_BUFFER_TOO_SMALL
;
97 IoMarkIrpPending(Irp
);
98 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
99 return STATUS_PENDING
;
102 static NTSTATUS NTAPI
104 IN PDEVICE_OBJECT DeviceObject
,
107 PCLASS_DEVICE_EXTENSION DeviceExtension
;
108 NTSTATUS Status
= Irp
->IoStatus
.Status
;
110 DPRINT("IRP_MJ_DEVICE_CONTROL\n");
112 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
113 return ForwardIrpAndForget(DeviceObject
, Irp
);
115 DeviceExtension
= (PCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
117 switch (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
)
119 case IOCTL_MOUSE_QUERY_ATTRIBUTES
:
121 /* FIXME: We hope that all devices will return the same result.
122 * Ask only the first one */
123 PLIST_ENTRY Head
= &((PCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->ListHead
;
124 if (Head
->Flink
!= Head
)
126 /* We have at least one mouse */
127 PPORT_DEVICE_EXTENSION DevExt
= CONTAINING_RECORD(Head
->Flink
, PORT_DEVICE_EXTENSION
, ListEntry
);
128 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
129 IoSkipCurrentIrpStackLocation(Irp
);
130 return IoCallDriver(DevExt
->DeviceObject
, Irp
);
135 DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
136 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
);
141 Irp
->IoStatus
.Status
= Status
;
142 Irp
->IoStatus
.Information
= 0;
143 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
148 static NTSTATUS NTAPI
150 IN PDEVICE_OBJECT DeviceObject
,
153 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
155 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
157 /* Forward some IRPs to lower device */
158 switch (IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
)
161 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
162 return ForwardIrpAndForget(DeviceObject
, Irp
);
165 DPRINT1("Port DO stub for major function 0x%lx\n",
166 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
168 Status
= Irp
->IoStatus
.Status
;
174 DPRINT1("Class DO stub for major function 0x%lx\n",
175 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
177 Status
= Irp
->IoStatus
.Status
;
180 Irp
->IoStatus
.Status
= Status
;
181 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
187 IN PUNICODE_STRING RegistryPath
,
188 IN PCLASS_DRIVER_EXTENSION DriverExtension
)
190 UNICODE_STRING ParametersRegistryKey
;
191 RTL_QUERY_REGISTRY_TABLE Parameters
[4];
194 ULONG DefaultConnectMultiplePorts
= 1;
195 ULONG DefaultDataQueueSize
= 0x64;
196 UNICODE_STRING DefaultDeviceBaseName
= RTL_CONSTANT_STRING(L
"PointerClass");
198 ParametersRegistryKey
.Length
= 0;
199 ParametersRegistryKey
.MaximumLength
= RegistryPath
->Length
+ sizeof(L
"\\Parameters") + sizeof(UNICODE_NULL
);
200 ParametersRegistryKey
.Buffer
= ExAllocatePool(PagedPool
, ParametersRegistryKey
.MaximumLength
);
201 if (!ParametersRegistryKey
.Buffer
)
203 DPRINT("ExAllocatePool() failed\n");
204 return STATUS_INSUFFICIENT_RESOURCES
;
206 RtlCopyUnicodeString(&ParametersRegistryKey
, RegistryPath
);
207 RtlAppendUnicodeToString(&ParametersRegistryKey
, L
"\\Parameters");
208 ParametersRegistryKey
.Buffer
[ParametersRegistryKey
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
210 RtlZeroMemory(Parameters
, sizeof(Parameters
));
212 Parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
213 Parameters
[0].Name
= L
"ConnectMultiplePorts";
214 Parameters
[0].EntryContext
= &DriverExtension
->ConnectMultiplePorts
;
215 Parameters
[0].DefaultType
= REG_DWORD
;
216 Parameters
[0].DefaultData
= &DefaultConnectMultiplePorts
;
217 Parameters
[0].DefaultLength
= sizeof(ULONG
);
219 Parameters
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
220 Parameters
[1].Name
= L
"MouseDataQueueSize";
221 Parameters
[1].EntryContext
= &DriverExtension
->DataQueueSize
;
222 Parameters
[1].DefaultType
= REG_DWORD
;
223 Parameters
[1].DefaultData
= &DefaultDataQueueSize
;
224 Parameters
[1].DefaultLength
= sizeof(ULONG
);
226 Parameters
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
227 Parameters
[2].Name
= L
"PointerDeviceBaseName";
228 Parameters
[2].EntryContext
= &DriverExtension
->DeviceBaseName
;
229 Parameters
[2].DefaultType
= REG_SZ
;
230 Parameters
[2].DefaultData
= &DefaultDeviceBaseName
;
231 Parameters
[2].DefaultLength
= 0;
233 Status
= RtlQueryRegistryValues(
234 RTL_REGISTRY_ABSOLUTE
,
235 ParametersRegistryKey
.Buffer
,
240 if (NT_SUCCESS(Status
))
243 if (DriverExtension
->ConnectMultiplePorts
!= 0
244 && DriverExtension
->ConnectMultiplePorts
!= 1)
246 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
248 if (DriverExtension
->DataQueueSize
== 0)
250 DriverExtension
->DataQueueSize
= DefaultDataQueueSize
;
253 else if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
255 /* Registry path doesn't exist. Set defaults */
256 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
257 DriverExtension
->DataQueueSize
= DefaultDataQueueSize
;
258 Status
= RtlDuplicateUnicodeString(
259 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
260 &DefaultDeviceBaseName
,
261 &DriverExtension
->DeviceBaseName
);
268 CreateClassDeviceObject(
269 IN PDRIVER_OBJECT DriverObject
,
270 OUT PDEVICE_OBJECT
*ClassDO OPTIONAL
)
272 PCLASS_DRIVER_EXTENSION DriverExtension
;
275 UNICODE_STRING DeviceNameU
;
276 PWSTR DeviceIdW
= NULL
; /* Pointer into DeviceNameU.Buffer */
278 PCLASS_DEVICE_EXTENSION DeviceExtension
;
281 DPRINT("CreateClassDeviceObject(0x%p)\n", DriverObject
);
283 /* Create new device object */
284 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
285 DeviceNameU
.Length
= 0;
286 DeviceNameU
.MaximumLength
=
287 wcslen(L
"\\Device\\") * sizeof(WCHAR
) /* "\Device\" */
288 + DriverExtension
->DeviceBaseName
.Length
/* "PointerClass" */
289 + 4 * sizeof(WCHAR
) /* Id between 0 and 9999 */
290 + sizeof(UNICODE_NULL
); /* Final NULL char */
291 DeviceNameU
.Buffer
= ExAllocatePool(PagedPool
, DeviceNameU
.MaximumLength
);
292 if (!DeviceNameU
.Buffer
)
294 DPRINT("ExAllocatePool() failed\n");
295 return STATUS_INSUFFICIENT_RESOURCES
;
297 Status
= RtlAppendUnicodeToString(&DeviceNameU
, L
"\\Device\\");
298 if (!NT_SUCCESS(Status
))
300 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status
);
303 Status
= RtlAppendUnicodeStringToString(&DeviceNameU
, &DriverExtension
->DeviceBaseName
);
304 if (!NT_SUCCESS(Status
))
306 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status
);
309 PrefixLength
= DeviceNameU
.MaximumLength
- 4 * sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
310 DeviceIdW
= &DeviceNameU
.Buffer
[PrefixLength
/ sizeof(WCHAR
)];
311 while (DeviceId
< 9999)
313 DeviceNameU
.Length
= PrefixLength
+ swprintf(DeviceIdW
, L
"%lu", DeviceId
) * sizeof(WCHAR
);
314 Status
= IoCreateDevice(
316 sizeof(CLASS_DEVICE_EXTENSION
),
319 FILE_DEVICE_SECURE_OPEN
,
322 if (NT_SUCCESS(Status
))
324 else if (Status
!= STATUS_OBJECT_NAME_COLLISION
)
326 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
331 DPRINT("Too many devices starting with '\\Device\\%wZ'\n", &DriverExtension
->DeviceBaseName
);
332 Status
= STATUS_TOO_MANY_NAMES
;
334 if (!NT_SUCCESS(Status
))
336 ExFreePool(DeviceNameU
.Buffer
);
340 DeviceExtension
= (PCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
341 RtlZeroMemory(DeviceExtension
, sizeof(CLASS_DEVICE_EXTENSION
));
342 DeviceExtension
->Common
.IsClassDO
= TRUE
;
343 DeviceExtension
->DriverExtension
= DriverExtension
;
344 InitializeListHead(&DeviceExtension
->ListHead
);
345 KeInitializeSpinLock(&DeviceExtension
->ListSpinLock
);
346 KeInitializeSpinLock(&DeviceExtension
->SpinLock
);
347 DeviceExtension
->ReadIsPending
= FALSE
;
348 DeviceExtension
->InputCount
= 0;
349 DeviceExtension
->PortData
= ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->DataQueueSize
* sizeof(MOUSE_INPUT_DATA
));
350 Fdo
->Flags
|= DO_POWER_PAGABLE
;
351 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
353 /* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
354 RtlWriteRegistryValue(
355 RTL_REGISTRY_DEVICEMAP
,
356 DriverExtension
->DeviceBaseName
.Buffer
,
359 DriverExtension
->RegistryPath
.Buffer
,
360 DriverExtension
->RegistryPath
.MaximumLength
);
362 ExFreePool(DeviceNameU
.Buffer
);
367 return STATUS_SUCCESS
;
372 IN PDEVICE_OBJECT ClassDeviceObject
,
374 IN PMOUSE_INPUT_DATA DataStart
)
376 NTSTATUS Status
= STATUS_SUCCESS
;
378 if (ClassDeviceObject
->Flags
& DO_BUFFERED_IO
)
381 Irp
->AssociatedIrp
.SystemBuffer
,
383 sizeof(MOUSE_INPUT_DATA
));
385 else if (ClassDeviceObject
->Flags
& DO_DIRECT_IO
)
387 PVOID DestAddress
= MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
393 sizeof(MOUSE_INPUT_DATA
));
396 Status
= STATUS_UNSUCCESSFUL
;
405 sizeof(MOUSE_INPUT_DATA
));
409 Status
= _SEH_GetExceptionCode();
419 IN PDEVICE_OBJECT ClassDeviceObject
,
420 IN OUT PMOUSE_INPUT_DATA DataStart
,
421 IN PMOUSE_INPUT_DATA DataEnd
,
422 IN OUT PULONG ConsumedCount
)
424 PCLASS_DEVICE_EXTENSION ClassDeviceExtension
= ClassDeviceObject
->DeviceExtension
;
427 PIO_STACK_LOCATION Stack
;
428 ULONG InputCount
= DataEnd
- DataStart
;
431 ASSERT(ClassDeviceExtension
->Common
.IsClassDO
);
433 KeAcquireSpinLock(&ClassDeviceExtension
->SpinLock
, &OldIrql
);
435 DPRINT("ClassCallback()\n");
436 /* A filter driver might have consumed all the data already; I'm
437 * not sure if they are supposed to move the packets when they
438 * consume them though.
440 if (ClassDeviceExtension
->ReadIsPending
== TRUE
&& InputCount
)
444 Irp
= ClassDeviceObject
->CurrentIrp
;
445 ClassDeviceObject
->CurrentIrp
= NULL
;
446 Stack
= IoGetCurrentIrpStackLocation(Irp
);
448 /* A read request is waiting for input, so go straight to it */
449 Status
= FillOneEntry(
454 if (NT_SUCCESS(Status
))
456 /* Go to next packet and complete this request with STATUS_SUCCESS */
457 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
458 Irp
->IoStatus
.Information
= sizeof(MOUSE_INPUT_DATA
);
459 Stack
->Parameters
.Read
.Length
= sizeof(MOUSE_INPUT_DATA
);
461 ClassDeviceExtension
->ReadIsPending
= FALSE
;
463 /* Skip the packet we just sent away */
470 /* If we have data from the port driver and a higher service to send the data to */
473 if (ClassDeviceExtension
->InputCount
+ InputCount
> ClassDeviceExtension
->DriverExtension
->DataQueueSize
)
474 ReadSize
= ClassDeviceExtension
->DriverExtension
->DataQueueSize
- ClassDeviceExtension
->InputCount
;
476 ReadSize
= InputCount
;
479 * If we exceed the buffer, data gets thrown away...
480 * Try at least to display a dialog
483 IoRaiseHardError(Irp
, NULL
, ClassDeviceObject
);
486 * Move the input data from the port data queue to our class data
490 ClassDeviceExtension
->PortData
,
492 sizeof(MOUSE_INPUT_DATA
) * ReadSize
);
494 /* Move the pointer and counter up */
495 ClassDeviceExtension
->PortData
+= ReadSize
;
496 ClassDeviceExtension
->InputCount
+= ReadSize
;
498 (*ConsumedCount
) += ReadSize
;
502 DPRINT("ClassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount
);
505 KeReleaseSpinLock(&ClassDeviceExtension
->SpinLock
, OldIrql
);
509 IoStartNextPacket(ClassDeviceObject
, FALSE
);
510 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
513 DPRINT("Leaving ClassCallback()\n");
517 /* Send IOCTL_INTERNAL_*_CONNECT to port */
520 IN PDEVICE_OBJECT PortDO
,
521 IN PDEVICE_OBJECT ClassDO
)
525 IO_STATUS_BLOCK IoStatus
;
526 CONNECT_DATA ConnectData
;
529 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
531 ConnectData
.ClassDeviceObject
= ClassDO
;
532 ConnectData
.ClassService
= ClassCallback
;
534 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT
,
536 &ConnectData
, sizeof(CONNECT_DATA
),
538 TRUE
, &Event
, &IoStatus
);
540 Status
= IoCallDriver(PortDO
, Irp
);
542 if (Status
== STATUS_PENDING
)
543 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
545 IoStatus
.Status
= Status
;
547 if (NT_SUCCESS(IoStatus
.Status
))
549 ObReferenceObject(PortDO
);
550 ExInterlockedInsertTailList(
551 &((PCLASS_DEVICE_EXTENSION
)ClassDO
->DeviceExtension
)->ListHead
,
552 &((PPORT_DEVICE_EXTENSION
)PortDO
->DeviceExtension
)->ListEntry
,
553 &((PCLASS_DEVICE_EXTENSION
)ClassDO
->DeviceExtension
)->ListSpinLock
);
554 if (ClassDO
->StackSize
<= PortDO
->StackSize
)
556 /* Increase the stack size, in case we have to
557 * forward some IRPs to the port device object
559 ClassDO
->StackSize
= PortDO
->StackSize
+ 1;
563 return IoStatus
.Status
;
566 static NTSTATUS NTAPI
568 IN PDRIVER_OBJECT DriverObject
,
569 IN PDEVICE_OBJECT Pdo
)
571 PCLASS_DRIVER_EXTENSION DriverExtension
;
572 PDEVICE_OBJECT Fdo
= NULL
;
573 PPORT_DEVICE_EXTENSION DeviceExtension
= NULL
;
576 DPRINT("ClassAddDevice called. Pdo = 0x%p\n", Pdo
);
578 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
581 /* We're getting a NULL Pdo at the first call as we're a legacy driver.
582 * Use it to search for legacy port drivers. */
583 return SearchForLegacyDrivers(DriverObject
, DriverExtension
);
585 /* Create new device object */
586 Status
= IoCreateDevice(
588 sizeof(PORT_DEVICE_EXTENSION
),
591 Pdo
->Characteristics
& FILE_DEVICE_SECURE_OPEN
? FILE_DEVICE_SECURE_OPEN
: 0,
594 if (!NT_SUCCESS(Status
))
596 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
600 DeviceExtension
= (PPORT_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
601 RtlZeroMemory(DeviceExtension
, sizeof(CLASS_DEVICE_EXTENSION
));
602 DeviceExtension
->Common
.IsClassDO
= FALSE
;
603 DeviceExtension
->DeviceObject
= Fdo
;
604 DeviceExtension
->PnpState
= dsStopped
;
605 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
606 if (!NT_SUCCESS(Status
))
608 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
611 if (DeviceExtension
->LowerDevice
->Flags
& DO_POWER_PAGABLE
)
612 Fdo
->Flags
|= DO_POWER_PAGABLE
;
613 if (DeviceExtension
->LowerDevice
->Flags
& DO_BUFFERED_IO
)
614 Fdo
->Flags
|= DO_BUFFERED_IO
;
615 if (DeviceExtension
->LowerDevice
->Flags
& DO_DIRECT_IO
)
616 Fdo
->Flags
|= DO_DIRECT_IO
;
618 if (DriverExtension
->ConnectMultiplePorts
)
619 DeviceExtension
->ClassDO
= DriverExtension
->MainClassDeviceObject
;
622 /* We need a new class device object for this Fdo */
623 Status
= CreateClassDeviceObject(
625 &DeviceExtension
->ClassDO
);
626 if (!NT_SUCCESS(Status
))
628 DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status
);
632 Status
= ConnectPortDriver(Fdo
, DeviceExtension
->ClassDO
);
633 if (!NT_SUCCESS(Status
))
635 DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status
);
638 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
640 /* Register interface */
641 Status
= IoRegisterDeviceInterface(
643 &GUID_DEVINTERFACE_MOUSE
,
645 &DeviceExtension
->InterfaceName
);
646 if (Status
== STATUS_INVALID_PARAMETER_1
)
648 /* The Pdo was a strange one ; maybe it is a legacy device.
649 * Ignore the error. */
650 return STATUS_SUCCESS
;
652 else if (!NT_SUCCESS(Status
))
654 DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
658 return STATUS_SUCCESS
;
663 if (DeviceExtension
->LowerDevice
)
664 IoDetachDevice(DeviceExtension
->LowerDevice
);
665 if (DriverExtension
->ConnectMultiplePorts
&& DeviceExtension
->ClassDO
)
667 PCLASS_DEVICE_EXTENSION ClassDeviceExtension
;
668 ClassDeviceExtension
= (PCLASS_DEVICE_EXTENSION
)DeviceExtension
->ClassDO
->DeviceExtension
;
669 ExFreePool(ClassDeviceExtension
->PortData
);
679 IN PDEVICE_OBJECT DeviceObject
,
682 PCLASS_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
683 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
685 ASSERT(DeviceExtension
->Common
.IsClassDO
);
687 if (DeviceExtension
->InputCount
> 0)
692 KeAcquireSpinLock(&DeviceExtension
->SpinLock
, &oldIrql
);
694 Status
= FillOneEntry(
697 DeviceExtension
->PortData
- DeviceExtension
->InputCount
);
699 if (NT_SUCCESS(Status
))
701 if (DeviceExtension
->InputCount
> 1)
704 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
705 DeviceExtension
->PortData
- DeviceExtension
->InputCount
+ 1,
706 (DeviceExtension
->InputCount
- 1) * sizeof(MOUSE_INPUT_DATA
));
709 DeviceExtension
->PortData
--;
710 DeviceExtension
->InputCount
--;
711 DeviceExtension
->ReadIsPending
= FALSE
;
713 Irp
->IoStatus
.Information
= sizeof(MOUSE_INPUT_DATA
);
714 Stack
->Parameters
.Read
.Length
= sizeof(MOUSE_INPUT_DATA
);
717 /* Go to next packet and complete this request */
718 Irp
->IoStatus
.Status
= Status
;
719 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
721 IoStartNextPacket(DeviceObject
, FALSE
);
722 KeReleaseSpinLock(&DeviceExtension
->SpinLock
, oldIrql
);
726 DeviceExtension
->ReadIsPending
= TRUE
;
731 SearchForLegacyDrivers(
732 IN PDRIVER_OBJECT DriverObject
,
733 IN PCLASS_DRIVER_EXTENSION DriverExtension
)
735 UNICODE_STRING DeviceMapKeyU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
736 UNICODE_STRING PortBaseName
= {0, };
737 PKEY_VALUE_BASIC_INFORMATION KeyValueInformation
= NULL
;
738 OBJECT_ATTRIBUTES ObjectAttributes
;
739 HANDLE hDeviceMapKey
= (HANDLE
)-1;
740 HANDLE hPortKey
= (HANDLE
)-1;
742 ULONG Size
, ResultLength
;
745 /* Create port base name, by replacing Class by Port at the end of the class base name */
746 Status
= RtlDuplicateUnicodeString(
747 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
748 &DriverExtension
->DeviceBaseName
,
750 if (!NT_SUCCESS(Status
))
752 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
755 PortBaseName
.Length
-= (sizeof(L
"Class") - sizeof(UNICODE_NULL
));
756 RtlAppendUnicodeToString(&PortBaseName
, L
"Port");
758 /* Allocate memory */
759 Size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + MAX_PATH
;
760 KeyValueInformation
= ExAllocatePool(PagedPool
, Size
);
761 if (!KeyValueInformation
)
763 DPRINT("ExAllocatePool() failed\n");
764 Status
= STATUS_INSUFFICIENT_RESOURCES
;
768 /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
769 InitializeObjectAttributes(&ObjectAttributes
, &DeviceMapKeyU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
770 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
771 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
773 DPRINT("HKLM\\HARDWARE\\DEVICEMAP is non-existent\n");
774 Status
= STATUS_SUCCESS
;
777 else if (!NT_SUCCESS(Status
))
779 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
784 InitializeObjectAttributes(&ObjectAttributes
, &PortBaseName
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceMapKey
, NULL
);
785 Status
= ZwOpenKey(&hPortKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
786 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
788 DPRINT("HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName
);
789 Status
= STATUS_SUCCESS
;
792 else if (!NT_SUCCESS(Status
))
794 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
798 /* Read each value name */
799 while (ZwEnumerateValueKey(hPortKey
, Index
++, KeyValueBasicInformation
, KeyValueInformation
, Size
, &ResultLength
) == STATUS_SUCCESS
)
801 UNICODE_STRING PortName
;
802 PDEVICE_OBJECT PortDeviceObject
= NULL
;
803 PFILE_OBJECT FileObject
= NULL
;
805 PortName
.Length
= PortName
.MaximumLength
= KeyValueInformation
->NameLength
;
806 PortName
.Buffer
= KeyValueInformation
->Name
;
808 /* Open the device object pointer */
809 Status
= IoGetDeviceObjectPointer(&PortName
, FILE_READ_ATTRIBUTES
, &FileObject
, &PortDeviceObject
);
810 if (!NT_SUCCESS(Status
))
812 DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status
);
815 DPRINT("Legacy driver found: %wZ\n", &PortDeviceObject
->DriverObject
->DriverName
);
817 Status
= ClassAddDevice(DriverObject
, PortDeviceObject
);
818 if (!NT_SUCCESS(Status
))
820 /* FIXME: Log the error */
821 DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status
);
824 if (Status
== STATUS_NO_MORE_ENTRIES
)
825 Status
= STATUS_SUCCESS
;
828 if (KeyValueInformation
!= NULL
)
829 ExFreePool(KeyValueInformation
);
830 if (hDeviceMapKey
!= (HANDLE
)-1)
831 ZwClose(hDeviceMapKey
);
832 if (hPortKey
!= (HANDLE
)-1)
838 * Standard DriverEntry method.
842 IN PDRIVER_OBJECT DriverObject
,
843 IN PUNICODE_STRING RegistryPath
)
845 PCLASS_DRIVER_EXTENSION DriverExtension
;
849 Status
= IoAllocateDriverObjectExtension(
852 sizeof(CLASS_DRIVER_EXTENSION
),
853 (PVOID
*)&DriverExtension
);
854 if (!NT_SUCCESS(Status
))
856 DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status
);
859 RtlZeroMemory(DriverExtension
, sizeof(CLASS_DRIVER_EXTENSION
));
861 Status
= RtlDuplicateUnicodeString(
862 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
864 &DriverExtension
->RegistryPath
);
865 if (!NT_SUCCESS(Status
))
867 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
871 Status
= ReadRegistryEntries(RegistryPath
, DriverExtension
);
872 if (!NT_SUCCESS(Status
))
874 DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status
);
878 if (DriverExtension
->ConnectMultiplePorts
== 1)
880 Status
= CreateClassDeviceObject(
882 &DriverExtension
->MainClassDeviceObject
);
883 if (!NT_SUCCESS(Status
))
885 DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status
);
890 DriverObject
->DriverExtension
->AddDevice
= ClassAddDevice
;
891 DriverObject
->DriverUnload
= DriverUnload
;
893 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
894 DriverObject
->MajorFunction
[i
] = IrpStub
;
896 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ClassCreate
;
897 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ClassClose
;
898 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = ClassCleanup
;
899 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ClassRead
;
900 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ClassDeviceControl
;
901 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = ForwardIrpAndForget
;
902 DriverObject
->DriverStartIo
= ClassStartIo
;
904 return STATUS_SUCCESS
;