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 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: cleanup 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(MOUSE_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
;
90 IN PDEVICE_OBJECT DeviceObject
,
93 PCLASS_DEVICE_EXTENSION DeviceExtension
;
96 DPRINT("IRP_MJ_DEVICE_CONTROL\n");
98 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
99 return ForwardIrpAndForget(DeviceObject
, Irp
);
101 DeviceExtension
= (PCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
103 switch (IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
)
105 case IOCTL_MOUSE_QUERY_ATTRIBUTES
:
107 Status
= STATUS_NOT_SUPPORTED
;
110 DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
111 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
);
112 Status
= STATUS_NOT_SUPPORTED
;
115 Irp
->IoStatus
.Status
= Status
;
116 Irp
->IoStatus
.Information
= 0;
117 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
122 static NTSTATUS NTAPI
124 IN PDEVICE_OBJECT DeviceObject
,
127 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
129 if (!((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsClassDO
)
131 /* Forward some IRPs to lower device */
132 switch (IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
)
134 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
135 return ForwardIrpAndForget(DeviceObject
, Irp
);
138 DPRINT1("Port DO stub for major function 0x%lx\n",
139 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
141 Status
= Irp
->IoStatus
.Status
;
147 DPRINT1("Class DO stub for major function 0x%lx\n",
148 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
150 Status
= Irp
->IoStatus
.Status
;
153 Irp
->IoStatus
.Status
= Status
;
154 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
160 IN PUNICODE_STRING RegistryPath
,
161 IN PCLASS_DRIVER_EXTENSION DriverExtension
)
163 UNICODE_STRING ParametersRegistryKey
;
164 RTL_QUERY_REGISTRY_TABLE Parameters
[4];
167 ULONG DefaultConnectMultiplePorts
= 1;
168 ULONG DefaultDataQueueSize
= 0x64;
169 UNICODE_STRING DefaultDeviceBaseName
= RTL_CONSTANT_STRING(L
"PointerClass");
171 ParametersRegistryKey
.Length
= 0;
172 ParametersRegistryKey
.MaximumLength
= RegistryPath
->Length
+ sizeof(L
"\\Parameters") + sizeof(UNICODE_NULL
);
173 ParametersRegistryKey
.Buffer
= ExAllocatePool(PagedPool
, ParametersRegistryKey
.MaximumLength
);
174 if (!ParametersRegistryKey
.Buffer
)
176 DPRINT("ExAllocatePool() failed\n");
177 return STATUS_INSUFFICIENT_RESOURCES
;
179 RtlCopyUnicodeString(&ParametersRegistryKey
, RegistryPath
);
180 RtlAppendUnicodeToString(&ParametersRegistryKey
, L
"\\Parameters");
181 ParametersRegistryKey
.Buffer
[ParametersRegistryKey
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
183 RtlZeroMemory(Parameters
, sizeof(Parameters
));
185 Parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
186 Parameters
[0].Name
= L
"ConnectMultiplePorts";
187 Parameters
[0].EntryContext
= &DriverExtension
->ConnectMultiplePorts
;
188 Parameters
[0].DefaultType
= REG_DWORD
;
189 Parameters
[0].DefaultData
= &DefaultConnectMultiplePorts
;
190 Parameters
[0].DefaultLength
= sizeof(ULONG
);
192 Parameters
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
193 Parameters
[1].Name
= L
"MouseDataQueueSize";
194 Parameters
[1].EntryContext
= &DriverExtension
->DataQueueSize
;
195 Parameters
[1].DefaultType
= REG_DWORD
;
196 Parameters
[1].DefaultData
= &DefaultDataQueueSize
;
197 Parameters
[1].DefaultLength
= sizeof(ULONG
);
199 Parameters
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_REGISTRY_OPTIONAL
;
200 Parameters
[2].Name
= L
"PointerDeviceBaseName";
201 Parameters
[2].EntryContext
= &DriverExtension
->DeviceBaseName
;
202 Parameters
[2].DefaultType
= REG_SZ
;
203 Parameters
[2].DefaultData
= &DefaultDeviceBaseName
;
204 Parameters
[2].DefaultLength
= sizeof(ULONG
);
206 Status
= RtlQueryRegistryValues(
207 RTL_REGISTRY_ABSOLUTE
,
208 ParametersRegistryKey
.Buffer
,
213 if (NT_SUCCESS(Status
))
216 if (DriverExtension
->ConnectMultiplePorts
!= 0
217 && DriverExtension
->ConnectMultiplePorts
!= 1)
219 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
221 if (DriverExtension
->DataQueueSize
== 0)
223 DriverExtension
->DataQueueSize
= DefaultDataQueueSize
;
226 else if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
228 /* Registry path doesn't exist. Set defaults */
229 DriverExtension
->ConnectMultiplePorts
= DefaultConnectMultiplePorts
;
230 DriverExtension
->DataQueueSize
= DefaultDataQueueSize
;
231 Status
= RtlDuplicateUnicodeString(
232 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
233 &DefaultDeviceBaseName
,
234 &DriverExtension
->DeviceBaseName
);
241 CreateClassDeviceObject(
242 IN PDRIVER_OBJECT DriverObject
,
243 OUT PDEVICE_OBJECT
*ClassDO OPTIONAL
)
245 PCLASS_DRIVER_EXTENSION DriverExtension
;
248 UNICODE_STRING DeviceNameU
;
249 PWSTR DeviceIdW
= NULL
; /* Pointer into DeviceNameU.Buffer */
251 PCLASS_DEVICE_EXTENSION DeviceExtension
;
254 DPRINT("CreateClassDeviceObject(0x%p)\n", DriverObject
);
256 /* Create new device object */
257 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
258 DeviceNameU
.Length
= 0;
259 DeviceNameU
.MaximumLength
=
260 wcslen(L
"\\Device\\") * sizeof(WCHAR
) /* "\Device\" */
261 + DriverExtension
->DeviceBaseName
.Length
/* "PointerClass" */
262 + 4 * sizeof(WCHAR
) /* Id between 0 and 9999 */
263 + sizeof(UNICODE_NULL
); /* Final NULL char */
264 DeviceNameU
.Buffer
= ExAllocatePool(PagedPool
, DeviceNameU
.MaximumLength
);
265 if (!DeviceNameU
.Buffer
)
267 DPRINT("ExAllocatePool() failed\n");
268 return STATUS_INSUFFICIENT_RESOURCES
;
270 Status
= RtlAppendUnicodeToString(&DeviceNameU
, L
"\\Device\\");
271 if (!NT_SUCCESS(Status
))
273 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status
);
276 Status
= RtlAppendUnicodeStringToString(&DeviceNameU
, &DriverExtension
->DeviceBaseName
);
277 if (!NT_SUCCESS(Status
))
279 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status
);
282 PrefixLength
= DeviceNameU
.MaximumLength
- 4 * sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
283 DeviceIdW
= &DeviceNameU
.Buffer
[PrefixLength
/ sizeof(WCHAR
)];
284 while (DeviceId
< 9999)
286 DeviceNameU
.Length
= PrefixLength
+ swprintf(DeviceIdW
, L
"%lu", DeviceId
) * sizeof(WCHAR
);
287 Status
= IoCreateDevice(
289 sizeof(CLASS_DEVICE_EXTENSION
),
292 FILE_DEVICE_SECURE_OPEN
,
295 if (NT_SUCCESS(Status
))
297 else if (Status
!= STATUS_OBJECT_NAME_COLLISION
)
299 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
304 DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension
->DeviceBaseName
);
305 Status
= STATUS_UNSUCCESSFUL
;
307 if (!NT_SUCCESS(Status
))
309 ExFreePool(DeviceNameU
.Buffer
);
313 DeviceExtension
= (PCLASS_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
314 RtlZeroMemory(DeviceExtension
, sizeof(CLASS_DEVICE_EXTENSION
));
315 DeviceExtension
->Common
.IsClassDO
= TRUE
;
316 DeviceExtension
->DriverExtension
= DriverExtension
;
317 KeInitializeSpinLock(&(DeviceExtension
->SpinLock
));
318 DeviceExtension
->ReadIsPending
= FALSE
;
319 DeviceExtension
->InputCount
= 0;
320 DeviceExtension
->PortData
= ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->DataQueueSize
* sizeof(MOUSE_INPUT_DATA
));
321 Fdo
->Flags
|= DO_POWER_PAGABLE
;
322 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
324 /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
326 ExFreePool(DeviceNameU
.Buffer
);
331 return STATUS_SUCCESS
;
336 IN PDEVICE_OBJECT ClassDeviceObject
,
337 IN OUT PMOUSE_INPUT_DATA DataStart
,
338 IN PMOUSE_INPUT_DATA DataEnd
,
339 IN OUT PULONG ConsumedCount
)
341 PCLASS_DEVICE_EXTENSION ClassDeviceExtension
= ClassDeviceObject
->DeviceExtension
;
344 PIO_STACK_LOCATION Stack
;
345 ULONG InputCount
= DataEnd
- DataStart
;
348 ASSERT(ClassDeviceExtension
->Common
.IsClassDO
);
350 DPRINT("ClassCallback()\n");
351 /* A filter driver might have consumed all the data already; I'm
352 * not sure if they are supposed to move the packets when they
353 * consume them though.
355 if (ClassDeviceExtension
->ReadIsPending
== TRUE
&& InputCount
)
357 Irp
= ClassDeviceObject
->CurrentIrp
;
358 ClassDeviceObject
->CurrentIrp
= NULL
;
359 Stack
= IoGetCurrentIrpStackLocation(Irp
);
361 /* A read request is waiting for input, so go straight to it */
364 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
366 sizeof(MOUSE_INPUT_DATA
));
368 /* Go to next packet and complete this request with STATUS_SUCCESS */
369 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
370 Irp
->IoStatus
.Information
= sizeof(MOUSE_INPUT_DATA
);
371 Stack
->Parameters
.Read
.Length
= sizeof(MOUSE_INPUT_DATA
);
373 ClassDeviceExtension
->ReadIsPending
= FALSE
;
375 /* Skip the packet we just sent away */
381 /* If we have data from the port driver and a higher service to send the data to */
384 KeAcquireSpinLock(&ClassDeviceExtension
->SpinLock
, &OldIrql
);
386 if (ClassDeviceExtension
->InputCount
+ InputCount
> ClassDeviceExtension
->DriverExtension
->DataQueueSize
)
387 ReadSize
= ClassDeviceExtension
->DriverExtension
->DataQueueSize
- ClassDeviceExtension
->InputCount
;
389 ReadSize
= InputCount
;
392 * FIXME: If we exceed the buffer, data gets thrown away.. better
397 * Move the input data from the port data queue to our class data
401 ClassDeviceExtension
->PortData
,
403 sizeof(MOUSE_INPUT_DATA
) * ReadSize
);
405 /* Move the pointer and counter up */
406 ClassDeviceExtension
->PortData
+= ReadSize
;
407 ClassDeviceExtension
->InputCount
+= ReadSize
;
409 KeReleaseSpinLock(&ClassDeviceExtension
->SpinLock
, OldIrql
);
410 (*ConsumedCount
) += ReadSize
;
414 DPRINT("ClassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount
);
419 IoStartNextPacket(ClassDeviceObject
, FALSE
);
420 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
423 DPRINT("Leaving ClassCallback()\n");
427 /* Send IOCTL_INTERNAL_*_CONNECT to port */
430 IN PDEVICE_OBJECT PortDO
,
431 IN PDEVICE_OBJECT ClassDO
)
435 IO_STATUS_BLOCK IoStatus
;
436 CONNECT_DATA ConnectData
;
439 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
441 ConnectData
.ClassDeviceObject
= ClassDO
;
442 ConnectData
.ClassService
= ClassCallback
;
444 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT
,
446 &ConnectData
, sizeof(CONNECT_DATA
),
448 TRUE
, &Event
, &IoStatus
);
450 Status
= IoCallDriver(PortDO
, Irp
);
452 if (Status
== STATUS_PENDING
)
453 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
455 IoStatus
.Status
= Status
;
457 if (NT_SUCCESS(IoStatus
.Status
))
458 ObReferenceObject(PortDO
);
460 return IoStatus
.Status
;
463 static NTSTATUS NTAPI
465 IN PDRIVER_OBJECT DriverObject
,
466 IN PDEVICE_OBJECT Pdo
)
468 PCLASS_DRIVER_EXTENSION DriverExtension
;
470 PPORT_DEVICE_EXTENSION DeviceExtension
;
473 DPRINT("ClassAddDevice called. Pdo = 0x%p\n", Pdo
);
476 return STATUS_SUCCESS
;
478 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
480 /* Create new device object */
481 Status
= IoCreateDevice(
483 sizeof(PORT_DEVICE_EXTENSION
),
486 FILE_DEVICE_SECURE_OPEN
,
489 if (!NT_SUCCESS(Status
))
491 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
495 DeviceExtension
= (PPORT_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
496 RtlZeroMemory(DeviceExtension
, sizeof(CLASS_DEVICE_EXTENSION
));
497 DeviceExtension
->Common
.IsClassDO
= FALSE
;
498 DeviceExtension
->PnpState
= dsStopped
;
499 Fdo
->Flags
|= DO_POWER_PAGABLE
;
500 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
501 if (!NT_SUCCESS(Status
))
503 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
507 Fdo
->Flags
|= DO_BUFFERED_IO
;
509 if (DriverExtension
->ConnectMultiplePorts
)
510 Status
= ConnectPortDriver(Fdo
, DriverExtension
->MainClassDeviceObject
);
512 Status
= ConnectPortDriver(Fdo
, Fdo
);
513 if (!NT_SUCCESS(Status
))
515 DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status
);
516 IoDetachDevice(DeviceExtension
->LowerDevice
);
517 /* FIXME: why can't I cleanup without error? */
518 //IoDeleteDevice(Fdo);
521 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
523 /* Register interface */
524 Status
= IoRegisterDeviceInterface(
526 &GUID_DEVINTERFACE_MOUSE
,
528 &DeviceExtension
->InterfaceName
);
529 if (!NT_SUCCESS(Status
))
531 DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
535 return STATUS_SUCCESS
;
540 IN PDEVICE_OBJECT DeviceObject
,
543 PCLASS_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
544 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
546 ASSERT(DeviceExtension
->Common
.IsClassDO
);
548 if (DeviceExtension
->InputCount
> 0)
552 KeAcquireSpinLock(&DeviceExtension
->SpinLock
, &oldIrql
);
556 Irp
->MdlAddress
? MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
) : Irp
->UserBuffer
,
557 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
558 sizeof(MOUSE_INPUT_DATA
));
560 if (DeviceExtension
->InputCount
> 1)
563 DeviceExtension
->PortData
- DeviceExtension
->InputCount
,
564 DeviceExtension
->PortData
- DeviceExtension
->InputCount
+ 1,
565 (DeviceExtension
->InputCount
- 1) * sizeof(MOUSE_INPUT_DATA
));
567 DeviceExtension
->PortData
--;
568 DeviceExtension
->InputCount
--;
569 DeviceExtension
->ReadIsPending
= FALSE
;
571 /* Go to next packet and complete this request with STATUS_SUCCESS */
572 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
573 Irp
->IoStatus
.Information
= sizeof(MOUSE_INPUT_DATA
);
574 Stack
->Parameters
.Read
.Length
= sizeof(MOUSE_INPUT_DATA
);
575 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
577 IoStartNextPacket(DeviceObject
, FALSE
);
578 KeReleaseSpinLock(&DeviceExtension
->SpinLock
, oldIrql
);
582 DeviceExtension
->ReadIsPending
= TRUE
;
587 SearchForLegacyDrivers(
588 IN PDRIVER_OBJECT DriverObject
,
589 IN PCLASS_DRIVER_EXTENSION DriverExtension
)
591 UNICODE_STRING DeviceMapKeyU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
592 UNICODE_STRING PortBaseName
= {0, };
593 PKEY_VALUE_BASIC_INFORMATION KeyValueInformation
= NULL
;
594 OBJECT_ATTRIBUTES ObjectAttributes
;
595 HANDLE hDeviceMapKey
= (HANDLE
)-1;
596 HANDLE hPortKey
= (HANDLE
)-1;
598 ULONG Size
, ResultLength
;
601 /* Create port base name, by replacing Class by Port at the end of the class base name */
602 Status
= RtlDuplicateUnicodeString(
603 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
604 &DriverExtension
->DeviceBaseName
,
606 if (!NT_SUCCESS(Status
))
608 DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status
);
611 PortBaseName
.Length
-= (sizeof(L
"Class") - sizeof(UNICODE_NULL
));
612 RtlAppendUnicodeToString(&PortBaseName
, L
"Port");
614 /* Allocate memory */
615 Size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + MAX_PATH
;
616 KeyValueInformation
= ExAllocatePool(PagedPool
, Size
);
617 if (!KeyValueInformation
)
619 DPRINT("ExAllocatePool() failed\n");
620 Status
= STATUS_INSUFFICIENT_RESOURCES
;
624 /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
625 InitializeObjectAttributes(&ObjectAttributes
, &DeviceMapKeyU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
626 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
627 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
629 DPRINT("HKLM\\HARDWARE\\DEVICEMAP is non-existent\n");
630 Status
= STATUS_SUCCESS
;
633 else if (!NT_SUCCESS(Status
))
635 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
640 InitializeObjectAttributes(&ObjectAttributes
, &PortBaseName
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceMapKey
, NULL
);
641 Status
= ZwOpenKey(&hPortKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
642 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
644 DPRINT("HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName
);
645 Status
= STATUS_SUCCESS
;
648 else if (!NT_SUCCESS(Status
))
650 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
654 /* Read each value name */
655 while (ZwEnumerateValueKey(hPortKey
, Index
++, KeyValueBasicInformation
, KeyValueInformation
, Size
, &ResultLength
) == STATUS_SUCCESS
)
657 UNICODE_STRING PortName
;
658 PDEVICE_OBJECT PortDeviceObject
= NULL
;
659 PFILE_OBJECT FileObject
= NULL
;
661 PortName
.Length
= PortName
.MaximumLength
= KeyValueInformation
->NameLength
;
662 PortName
.Buffer
= KeyValueInformation
->Name
;
664 /* Open the device object pointer */
665 Status
= IoGetDeviceObjectPointer(&PortName
, FILE_READ_ATTRIBUTES
, &FileObject
, &PortDeviceObject
);
666 if (!NT_SUCCESS(Status
))
668 DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status
);
671 /* Connect the port device object */
672 if (DriverExtension
->ConnectMultiplePorts
)
674 Status
= ConnectPortDriver(PortDeviceObject
, DriverExtension
->MainClassDeviceObject
);
675 if (!NT_SUCCESS(Status
))
677 /* FIXME: Log the error */
678 DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status
);
683 PDEVICE_OBJECT ClassDO
;
684 Status
= CreateClassDeviceObject(DriverObject
, &ClassDO
);
685 if (!NT_SUCCESS(Status
))
687 /* FIXME: Log the error */
688 DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status
);
691 Status
= ConnectPortDriver(PortDeviceObject
, ClassDO
);
692 if (!NT_SUCCESS(Status
))
694 /* FIXME: Log the error */
695 DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status
);
696 IoDeleteDevice(ClassDO
);
700 if (Status
== STATUS_NO_MORE_ENTRIES
)
701 Status
= STATUS_SUCCESS
;
704 if (KeyValueInformation
!= NULL
)
705 ExFreePool(KeyValueInformation
);
706 if (hDeviceMapKey
!= (HANDLE
)-1)
707 ZwClose(hDeviceMapKey
);
708 if (hPortKey
!= (HANDLE
)-1)
714 * Standard DriverEntry method.
718 IN PDRIVER_OBJECT DriverObject
,
719 IN PUNICODE_STRING RegistryPath
)
721 PCLASS_DRIVER_EXTENSION DriverExtension
;
725 Status
= IoAllocateDriverObjectExtension(
728 sizeof(CLASS_DRIVER_EXTENSION
),
729 (PVOID
*)&DriverExtension
);
730 if (!NT_SUCCESS(Status
))
732 DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status
);
735 RtlZeroMemory(DriverExtension
, sizeof(CLASS_DRIVER_EXTENSION
));
737 Status
= ReadRegistryEntries(RegistryPath
, DriverExtension
);
738 if (!NT_SUCCESS(Status
))
740 DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status
);
744 if (DriverExtension
->ConnectMultiplePorts
== 1)
746 Status
= CreateClassDeviceObject(
748 &DriverExtension
->MainClassDeviceObject
);
749 if (!NT_SUCCESS(Status
))
751 DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status
);
756 DriverObject
->DriverExtension
->AddDevice
= ClassAddDevice
;
757 DriverObject
->DriverUnload
= DriverUnload
;
759 for (i
= 0; i
< IRP_MJ_MAXIMUM_FUNCTION
; i
++)
760 DriverObject
->MajorFunction
[i
] = IrpStub
;
762 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ClassCreate
;
763 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ClassClose
;
764 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = ClassCleanup
;
765 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ClassRead
;
766 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ClassDeviceControl
;
767 DriverObject
->DriverStartIo
= ClassStartIo
;
769 Status
= SearchForLegacyDrivers(DriverObject
, DriverExtension
);