4 * Copyright (C) 2002-2004, 2007 ReactOS Team
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 /* GLOBAL VARIABLES ***********************************************************/
28 ULONG CsrssInitialized
= FALSE
;
29 PKPROCESS Csrss
= NULL
;
30 ULONG VideoPortDeviceNumber
= 0;
32 /* PRIVATE FUNCTIONS **********************************************************/
39 return STATUS_SUCCESS
;
43 IntVideoPortImageDirectoryEntryToData(
47 PIMAGE_NT_HEADERS NtHeader
;
50 NtHeader
= RtlImageNtHeader(BaseAddress
);
54 if (Directory
>= NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
)
57 Va
= NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
;
61 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
65 IntVideoPortDeferredRoutine(
67 IN PVOID DeferredContext
,
68 IN PVOID SystemArgument1
,
69 IN PVOID SystemArgument2
)
71 PVOID HwDeviceExtension
=
72 &((PVIDEO_PORT_DEVICE_EXTENSION
)DeferredContext
)->MiniPortDeviceExtension
;
73 ((PMINIPORT_DPC_ROUTINE
)SystemArgument1
)(HwDeviceExtension
, SystemArgument2
);
77 IntCreateRegistryPath(
78 IN PCUNICODE_STRING DriverRegistryPath
,
79 OUT PUNICODE_STRING DeviceRegistryPath
)
81 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
82 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
83 static WCHAR ControlSet
[] = L
"CONTROLSET";
84 static WCHAR Insert1
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
85 static WCHAR Insert2
[] = L
"\\Device0";
87 UNICODE_STRING AfterControlSet
;
89 AfterControlSet
= *DriverRegistryPath
;
90 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
91 Valid
= (DriverRegistryPath
->Length
> sizeof(RegistryMachineSystem
) &&
92 0 == _wcsnicmp(DriverRegistryPath
->Buffer
, RegistryMachineSystem
,
93 wcslen(RegistryMachineSystem
)));
96 AfterControlSet
.Buffer
+= wcslen(RegistryMachineSystem
);
97 AfterControlSet
.Length
-= sizeof(RegistryMachineSystem
) - sizeof(UNICODE_NULL
);
99 /* Check if path contains CURRENTCONTROLSET */
100 if (AfterControlSet
.Length
> sizeof(CurrentControlSet
) &&
101 0 == _wcsnicmp(AfterControlSet
.Buffer
, CurrentControlSet
, wcslen(CurrentControlSet
)))
103 AfterControlSet
.Buffer
+= wcslen(CurrentControlSet
);
104 AfterControlSet
.Length
-= sizeof(CurrentControlSet
) - sizeof(UNICODE_NULL
);
106 /* Check if path contains CONTROLSETnum */
107 else if (AfterControlSet
.Length
> sizeof(ControlSet
) &&
108 0 == _wcsnicmp(AfterControlSet
.Buffer
, ControlSet
, wcslen(ControlSet
)))
110 AfterControlSet
.Buffer
+= wcslen(ControlSet
);
111 AfterControlSet
.Length
-= sizeof(ControlSet
) - sizeof(UNICODE_NULL
);
112 while (AfterControlSet
.Length
> 0 &&
113 *AfterControlSet
.Buffer
>= L
'0' &&
114 *AfterControlSet
.Buffer
<= L
'9')
116 AfterControlSet
.Buffer
++;
117 AfterControlSet
.Length
-= sizeof(WCHAR
);
119 Valid
= (AfterControlSet
.Length
> 0 && L
'\\' == *AfterControlSet
.Buffer
);
120 AfterControlSet
.Buffer
++;
121 AfterControlSet
.Length
-= sizeof(WCHAR
);
122 AfterControlSet
.MaximumLength
= AfterControlSet
.Length
;
132 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert1
) + sizeof(Insert2
);
133 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
134 DeviceRegistryPath
->MaximumLength
,
136 if (DeviceRegistryPath
->Buffer
!= NULL
)
138 /* Build device path */
139 wcsncpy(DeviceRegistryPath
->Buffer
,
140 DriverRegistryPath
->Buffer
,
141 AfterControlSet
.Buffer
- DriverRegistryPath
->Buffer
);
142 DeviceRegistryPath
->Length
= (AfterControlSet
.Buffer
- DriverRegistryPath
->Buffer
) * sizeof(WCHAR
);
143 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert1
);
144 RtlAppendUnicodeStringToString(DeviceRegistryPath
, &AfterControlSet
);
145 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
147 /* Check if registry key exists */
148 Valid
= NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, DeviceRegistryPath
->Buffer
));
151 ExFreePoolWithTag(DeviceRegistryPath
->Buffer
, TAG_VIDEO_PORT
);
160 WARN_(VIDEOPRT
, "Unparsable registry path %wZ", DriverRegistryPath
);
163 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
166 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert2
);
167 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(
169 DeviceRegistryPath
->MaximumLength
,
172 if (!DeviceRegistryPath
->Buffer
)
173 return STATUS_NO_MEMORY
;
175 RtlCopyUnicodeString(DeviceRegistryPath
, DriverRegistryPath
);
176 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
179 return STATUS_SUCCESS
;
183 IntVideoPortCreateAdapterDeviceObject(
184 IN PDRIVER_OBJECT DriverObject
,
185 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
186 IN PDEVICE_OBJECT PhysicalDeviceObject
,
187 OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
189 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
192 PCI_SLOT_NUMBER SlotNumber
;
195 WCHAR DeviceBuffer
[20];
196 UNICODE_STRING DeviceName
;
197 PDEVICE_OBJECT DeviceObject_
;
199 if (DeviceObject
== NULL
)
200 DeviceObject
= &DeviceObject_
;
203 * Find the first free device number that can be used for video device
204 * object names and symlinks.
207 DeviceNumber
= VideoPortDeviceNumber
;
208 if (DeviceNumber
== 0xFFFFFFFF)
210 WARN_(VIDEOPRT
, "Can't find free device number\n");
211 return STATUS_UNSUCCESSFUL
;
215 * Create the device object.
218 /* Create a unicode device name. */
219 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
220 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
222 INFO_(VIDEOPRT
, "HwDeviceExtension size is: 0x%x\n",
223 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
225 /* Create the device object. */
226 Status
= IoCreateDevice(
228 sizeof(VIDEO_PORT_DEVICE_EXTENSION
) +
229 DriverExtension
->InitializationData
.HwDeviceExtensionSize
,
236 if (!NT_SUCCESS(Status
))
238 WARN_(VIDEOPRT
, "IoCreateDevice call failed with status 0x%08x\n", Status
);
243 * Set the buffering strategy here. If you change this, remember
244 * to change VidDispatchDeviceControl too.
247 (*DeviceObject
)->Flags
|= DO_BUFFERED_IO
;
250 * Initialize device extension.
253 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)((*DeviceObject
)->DeviceExtension
);
254 DeviceExtension
->DeviceNumber
= DeviceNumber
;
255 DeviceExtension
->DriverObject
= DriverObject
;
256 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
257 DeviceExtension
->FunctionalDeviceObject
= *DeviceObject
;
258 DeviceExtension
->DriverExtension
= DriverExtension
;
261 * Get the registry path associated with this driver.
264 Status
= IntCreateRegistryPath(
265 &DriverExtension
->RegistryPath
,
266 &DeviceExtension
->RegistryPath
);
267 if (!NT_SUCCESS(Status
))
269 WARN_(VIDEOPRT
, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status
);
270 IoDeleteDevice(*DeviceObject
);
271 *DeviceObject
= NULL
;
275 if (PhysicalDeviceObject
!= NULL
)
277 /* Get bus number from the upper level bus driver. */
278 Size
= sizeof(ULONG
);
279 Status
= IoGetDeviceProperty(
280 PhysicalDeviceObject
,
281 DevicePropertyBusNumber
,
283 &DeviceExtension
->SystemIoBusNumber
,
285 if (!NT_SUCCESS(Status
))
287 WARN_(VIDEOPRT
, "Couldn't get an information from bus driver. We will try to\n"
288 "use legacy detection method, but even that doesn't mean that\n"
290 DeviceExtension
->PhysicalDeviceObject
= NULL
;
294 DeviceExtension
->AdapterInterfaceType
=
295 DriverExtension
->InitializationData
.AdapterInterfaceType
;
297 if (PhysicalDeviceObject
!= NULL
)
299 /* Get bus type from the upper level bus driver. */
300 Size
= sizeof(ULONG
);
302 PhysicalDeviceObject
,
303 DevicePropertyLegacyBusType
,
305 &DeviceExtension
->AdapterInterfaceType
,
308 /* Get bus device address from the upper level bus driver. */
309 Size
= sizeof(ULONG
);
311 PhysicalDeviceObject
,
312 DevicePropertyAddress
,
317 /* Convert slotnumber to PCI_SLOT_NUMBER */
318 SlotNumber
.u
.AsULONG
= 0;
319 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
320 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
321 DeviceExtension
->SystemIoSlotNumber
= SlotNumber
.u
.AsULONG
;
324 InitializeListHead(&DeviceExtension
->AddressMappingListHead
);
325 InitializeListHead(&DeviceExtension
->DmaAdapterList
);
328 &DeviceExtension
->DpcObject
,
329 IntVideoPortDeferredRoutine
,
332 KeInitializeMutex(&DeviceExtension
->DeviceLock
, 0);
334 /* Attach the device. */
335 if (PhysicalDeviceObject
!= NULL
)
336 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(
337 *DeviceObject
, PhysicalDeviceObject
);
339 /* Remove the initailizing flag */
340 (*DeviceObject
)->Flags
&= ~DO_DEVICE_INITIALIZING
;
341 return STATUS_SUCCESS
;
346 IntVideoPortFindAdapter(
347 IN PDRIVER_OBJECT DriverObject
,
348 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
349 IN PDEVICE_OBJECT DeviceObject
)
351 WCHAR DeviceVideoBuffer
[20];
352 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
355 VIDEO_PORT_CONFIG_INFO ConfigInfo
;
356 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
358 WCHAR DeviceBuffer
[20];
359 UNICODE_STRING DeviceName
;
360 WCHAR SymlinkBuffer
[20];
361 UNICODE_STRING SymlinkName
;
362 BOOL LegacyDetection
= FALSE
;
363 ULONG DeviceNumber
, DisplayNumber
;
365 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
366 DeviceNumber
= DeviceExtension
->DeviceNumber
;
369 * Setup a ConfigInfo structure that we will pass to HwFindAdapter.
372 RtlZeroMemory(&ConfigInfo
, sizeof(VIDEO_PORT_CONFIG_INFO
));
373 ConfigInfo
.Length
= sizeof(VIDEO_PORT_CONFIG_INFO
);
374 ConfigInfo
.AdapterInterfaceType
= DeviceExtension
->AdapterInterfaceType
;
375 if (ConfigInfo
.AdapterInterfaceType
== PCIBus
)
376 ConfigInfo
.InterruptMode
= LevelSensitive
;
378 ConfigInfo
.InterruptMode
= Latched
;
379 ConfigInfo
.DriverRegistryPath
= DriverExtension
->RegistryPath
.Buffer
;
380 ConfigInfo
.VideoPortGetProcAddress
= IntVideoPortGetProcAddress
;
381 ConfigInfo
.SystemIoBusNumber
= DeviceExtension
->SystemIoBusNumber
;
382 ConfigInfo
.BusInterruptLevel
= DeviceExtension
->InterruptLevel
;
383 ConfigInfo
.BusInterruptVector
= DeviceExtension
->InterruptVector
;
385 Size
= sizeof(SystemBasicInfo
);
386 Status
= ZwQuerySystemInformation(
387 SystemBasicInformation
,
392 if (NT_SUCCESS(Status
))
394 ConfigInfo
.SystemMemorySize
=
395 SystemBasicInfo
.NumberOfPhysicalPages
*
396 SystemBasicInfo
.PageSize
;
400 * Call miniport HwVidFindAdapter entry point to detect if
401 * particular device is present. There are two possible code
402 * paths. The first one is for Legacy drivers (NT4) and cases
403 * when we don't have information about what bus we're on. The
404 * second case is the standard one for Plug & Play drivers.
406 if (DeviceExtension
->PhysicalDeviceObject
== NULL
)
408 LegacyDetection
= TRUE
;
413 ULONG BusNumber
, MaxBuses
;
415 MaxBuses
= DeviceExtension
->AdapterInterfaceType
== PCIBus
? 8 : 1;
417 for (BusNumber
= 0; BusNumber
< MaxBuses
; BusNumber
++)
419 DeviceExtension
->SystemIoBusNumber
=
420 ConfigInfo
.SystemIoBusNumber
= BusNumber
;
422 RtlZeroMemory(&DeviceExtension
->MiniPortDeviceExtension
,
423 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
425 /* FIXME: Need to figure out what string to pass as param 3. */
426 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
427 &DeviceExtension
->MiniPortDeviceExtension
,
428 DriverExtension
->HwContext
,
433 if (Status
== ERROR_DEV_NOT_EXIST
)
437 else if (Status
== NO_ERROR
)
443 WARN_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
444 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
445 if (DeviceExtension
->NextDeviceObject
)
446 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
447 IoDeleteDevice(DeviceObject
);
455 /* FIXME: Need to figure out what string to pass as param 3. */
456 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
457 &DeviceExtension
->MiniPortDeviceExtension
,
458 DriverExtension
->HwContext
,
464 if (Status
!= NO_ERROR
)
466 WARN_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
467 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
468 if (DeviceExtension
->NextDeviceObject
)
469 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
470 IoDeleteDevice(DeviceObject
);
475 * Now we know the device is present, so let's do all additional tasks
476 * such as creating symlinks or setting up interrupts and timer.
479 /* Create a unicode device name. */
480 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
481 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
483 /* Create symbolic link "\??\DISPLAYx" */
485 /* HACK: We need this to find the first available display to
486 * use. We can't use the device number because then we could
487 * end up with \Device\Video0 being non-functional because
488 * HwFindAdapter returned an error. \Device\Video1 would be
489 * the correct primary display but it would be set to DISPLAY2
490 * so it would never be used and ROS would bugcheck on boot.
491 * By doing it this way, we ensure that DISPLAY1 is always
492 * functional. Another idea would be letting the IO manager
493 * give our video devices names then getting those names
494 * somehow and creating symbolic links to \Device\VideoX
495 * and \??\DISPLAYX once we know that HwFindAdapter has succeeded.
501 swprintf(SymlinkBuffer
, L
"\\??\\DISPLAY%lu", DisplayNumber
);
502 RtlInitUnicodeString(&SymlinkName
, SymlinkBuffer
);
504 while (IoCreateSymbolicLink(&SymlinkName
, &DeviceName
) != STATUS_SUCCESS
);
506 /* Add entry to DEVICEMAP\VIDEO key in registry. */
507 swprintf(DeviceVideoBuffer
, L
"\\Device\\Video%d", DisplayNumber
- 1);
508 RtlWriteRegistryValue(
509 RTL_REGISTRY_DEVICEMAP
,
513 DeviceExtension
->RegistryPath
.Buffer
,
514 DeviceExtension
->RegistryPath
.MaximumLength
);
516 RtlWriteRegistryValue(
517 RTL_REGISTRY_DEVICEMAP
,
522 sizeof(DeviceNumber
));
524 /* FIXME: Allocate hardware resources for device. */
527 * Allocate interrupt for device.
530 if (!IntVideoPortSetupInterrupt(DeviceObject
, DriverExtension
, &ConfigInfo
))
532 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
533 if (DeviceExtension
->NextDeviceObject
)
534 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
535 IoDeleteDevice(DeviceObject
);
536 return STATUS_INSUFFICIENT_RESOURCES
;
540 * Allocate timer for device.
543 if (!IntVideoPortSetupTimer(DeviceObject
, DriverExtension
))
545 if (DeviceExtension
->InterruptObject
!= NULL
)
546 IoDisconnectInterrupt(DeviceExtension
->InterruptObject
);
547 if (DeviceExtension
->NextDeviceObject
)
548 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
549 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
550 IoDeleteDevice(DeviceObject
);
551 WARN_(VIDEOPRT
, "STATUS_INSUFFICIENT_RESOURCES\n");
552 return STATUS_INSUFFICIENT_RESOURCES
;
556 * Query children of the device.
558 VideoPortEnumerateChildren(&DeviceExtension
->MiniPortDeviceExtension
, NULL
);
560 INFO_(VIDEOPRT
, "STATUS_SUCCESS\n");
561 return STATUS_SUCCESS
;
565 IntAttachToCSRSS(PKPROCESS
*CallingProcess
, PKAPC_STATE ApcState
)
567 *CallingProcess
= (PKPROCESS
)PsGetCurrentProcess();
568 if (*CallingProcess
!= Csrss
)
570 KeStackAttachProcess(Csrss
, ApcState
);
575 IntDetachFromCSRSS(PKPROCESS
*CallingProcess
, PKAPC_STATE ApcState
)
577 if (*CallingProcess
!= Csrss
)
579 KeUnstackDetachProcess(ApcState
);
583 /* PUBLIC FUNCTIONS ***********************************************************/
593 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData
,
596 PDRIVER_OBJECT DriverObject
= Context1
;
597 PUNICODE_STRING RegistryPath
= Context2
;
599 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
600 BOOLEAN PnpDriver
= FALSE
, LegacyDetection
= FALSE
;
602 TRACE_(VIDEOPRT
, "VideoPortInitialize\n");
605 * As a first thing do parameter checks.
608 if (HwInitializationData
->HwInitDataSize
> sizeof(VIDEO_HW_INITIALIZATION_DATA
))
610 return STATUS_REVISION_MISMATCH
;
613 if (HwInitializationData
->HwFindAdapter
== NULL
||
614 HwInitializationData
->HwInitialize
== NULL
||
615 HwInitializationData
->HwStartIO
== NULL
)
617 return STATUS_INVALID_PARAMETER
;
620 switch (HwInitializationData
->HwInitDataSize
)
623 * NT4 drivers are special case, because we must use legacy method
624 * of detection instead of the Plug & Play one.
627 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
:
628 INFO_(VIDEOPRT
, "We were loaded by a Windows NT miniport driver.\n");
631 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA
:
632 INFO_(VIDEOPRT
, "We were loaded by a Windows 2000 miniport driver.\n");
635 case sizeof(VIDEO_HW_INITIALIZATION_DATA
):
636 INFO_(VIDEOPRT
, "We were loaded by a Windows XP or later miniport driver.\n");
640 WARN_(VIDEOPRT
, "Invalid HwInitializationData size.\n");
641 return STATUS_UNSUCCESSFUL
;
644 /* Set dispatching routines */
645 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = IntVideoPortDispatchOpen
;
646 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = IntVideoPortDispatchClose
;
647 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] =
648 IntVideoPortDispatchDeviceControl
;
649 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] =
650 IntVideoPortDispatchDeviceControl
;
651 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] =
652 IntVideoPortDispatchWrite
; // ReactOS-specific hack
653 DriverObject
->DriverUnload
= IntVideoPortUnload
;
655 /* Determine type of the miniport driver */
656 if ((HwInitializationData
->HwInitDataSize
>=
657 FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA
, HwQueryInterface
))
658 && HwInitializationData
->HwSetPowerState
659 && HwInitializationData
->HwGetPowerState
660 && HwInitializationData
->HwGetVideoChildDescriptor
)
662 INFO_(VIDEOPRT
, "The miniport is a PnP miniport driver\n");
666 /* Check if legacy detection should be applied */
667 if (!PnpDriver
|| HwContext
)
669 INFO_(VIDEOPRT
, "Legacy detection for adapter interface %d\n",
670 HwInitializationData
->AdapterInterfaceType
);
672 /* FIXME: Move the code for legacy detection
673 to another function and call it here */
674 LegacyDetection
= TRUE
;
679 * The driver extension can be already allocated in case that we were
680 * called by legacy driver and failed detecting device. Some miniport
681 * drivers in that case adjust parameters and call VideoPortInitialize
685 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
686 if (DriverExtension
== NULL
)
688 Status
= IoAllocateDriverObjectExtension(
691 sizeof(VIDEO_PORT_DRIVER_EXTENSION
),
692 (PVOID
*)&DriverExtension
);
694 if (!NT_SUCCESS(Status
))
700 * Save the registry path. This should be done only once even if
701 * VideoPortInitialize is called multiple times.
704 if (RegistryPath
->Length
!= 0)
706 DriverExtension
->RegistryPath
.Length
= 0;
707 DriverExtension
->RegistryPath
.MaximumLength
=
708 RegistryPath
->Length
+ sizeof(UNICODE_NULL
);
709 DriverExtension
->RegistryPath
.Buffer
=
710 ExAllocatePoolWithTag(
712 DriverExtension
->RegistryPath
.MaximumLength
,
714 if (DriverExtension
->RegistryPath
.Buffer
== NULL
)
716 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
717 return STATUS_INSUFFICIENT_RESOURCES
;
720 RtlCopyUnicodeString(&DriverExtension
->RegistryPath
, RegistryPath
);
721 INFO_(VIDEOPRT
, "RegistryPath: %wZ\n", &DriverExtension
->RegistryPath
);
725 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
730 * Copy the correct miniport initialization data to the device extension.
734 &DriverExtension
->InitializationData
,
735 HwInitializationData
,
736 HwInitializationData
->HwInitDataSize
);
737 if (HwInitializationData
->HwInitDataSize
<
738 sizeof(VIDEO_HW_INITIALIZATION_DATA
))
740 RtlZeroMemory((PVOID
)((ULONG_PTR
)&DriverExtension
->InitializationData
+
741 HwInitializationData
->HwInitDataSize
),
742 sizeof(VIDEO_HW_INITIALIZATION_DATA
) -
743 HwInitializationData
->HwInitDataSize
);
745 DriverExtension
->HwContext
= HwContext
;
748 * Plug & Play drivers registers the device in AddDevice routine. For
749 * legacy drivers we must do it now.
754 PDEVICE_OBJECT DeviceObject
;
756 if (HwInitializationData
->HwInitDataSize
!= SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
)
758 /* power management */
759 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
761 Status
= IntVideoPortCreateAdapterDeviceObject(DriverObject
, DriverExtension
,
762 NULL
, &DeviceObject
);
763 INFO_(VIDEOPRT
, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status
);
764 if (!NT_SUCCESS(Status
))
766 Status
= IntVideoPortFindAdapter(DriverObject
, DriverExtension
, DeviceObject
);
767 INFO_(VIDEOPRT
, "IntVideoPortFindAdapter returned 0x%x\n", Status
);
768 if (NT_SUCCESS(Status
))
769 VideoPortDeviceNumber
++;
774 DriverObject
->DriverExtension
->AddDevice
= IntVideoPortAddDevice
;
775 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = IntVideoPortDispatchPnp
;
776 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
777 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = IntVideoPortDispatchSystemControl
;
779 return STATUS_SUCCESS
;
789 IN VIDEO_DEBUG_LEVEL DebugPrintLevel
,
790 IN PCHAR DebugMessage
, ...)
794 va_start(ap
, DebugMessage
);
795 vDbgPrintEx(DPFLTR_IHVVIDEO_ID
, DebugPrintLevel
, DebugMessage
, ap
);
805 IN PVOID HwDeviceExtension
,
806 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL
,
807 IN VP_STATUS ErrorCode
,
812 INFO_(VIDEOPRT
, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
813 ErrorCode
, ErrorCode
, UniqueId
, UniqueId
);
815 INFO_(VIDEOPRT
, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp
->IoControlCode
, Vrp
->IoControlCode
);
823 VideoPortGetCurrentIrql(VOID
)
825 return KeGetCurrentIrql();
828 typedef struct QueryRegistryCallbackContext
830 PVOID HwDeviceExtension
;
832 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine
;
833 } QUERY_REGISTRY_CALLBACK_CONTEXT
, *PQUERY_REGISTRY_CALLBACK_CONTEXT
;
835 static NTSTATUS NTAPI
836 QueryRegistryCallback(
840 IN ULONG ValueLength
,
842 IN PVOID EntryContext
)
844 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext
= (PQUERY_REGISTRY_CALLBACK_CONTEXT
) Context
;
846 INFO_(VIDEOPRT
, "Found registry value for name %S: type %d, length %d\n",
847 ValueName
, ValueType
, ValueLength
);
848 return (*(CallbackContext
->HwGetRegistryRoutine
))(
849 CallbackContext
->HwDeviceExtension
,
850 CallbackContext
->HwContext
,
861 VideoPortGetRegistryParameters(
862 IN PVOID HwDeviceExtension
,
863 IN PWSTR ParameterName
,
864 IN UCHAR IsParameterFileName
,
865 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine
,
868 RTL_QUERY_REGISTRY_TABLE QueryTable
[2] = {{0}};
869 QUERY_REGISTRY_CALLBACK_CONTEXT Context
;
870 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
872 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
874 TRACE_(VIDEOPRT
, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n",
875 ParameterName
, &DeviceExtension
->RegistryPath
);
877 Context
.HwDeviceExtension
= HwDeviceExtension
;
878 Context
.HwContext
= HwContext
;
879 Context
.HwGetRegistryRoutine
= GetRegistryRoutine
;
881 QueryTable
[0].QueryRoutine
= QueryRegistryCallback
;
882 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
883 QueryTable
[0].Name
= ParameterName
;
885 if (!NT_SUCCESS(RtlQueryRegistryValues(
886 RTL_REGISTRY_ABSOLUTE
,
887 DeviceExtension
->RegistryPath
.Buffer
,
892 WARN_(VIDEOPRT
, "VideoPortGetRegistryParameters could not find the "
893 "requested parameter\n");
894 return ERROR_INVALID_PARAMETER
;
897 if (IsParameterFileName
)
899 /* FIXME: need to read the contents of the file */
911 VideoPortSetRegistryParameters(
912 IN PVOID HwDeviceExtension
,
915 IN ULONG ValueLength
)
919 TRACE_(VIDEOPRT
, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n",
921 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->RegistryPath
);
922 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
923 Status
= RtlWriteRegistryValue(
924 RTL_REGISTRY_ABSOLUTE
,
925 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->RegistryPath
.Buffer
,
931 if (Status
!= NO_ERROR
)
932 WARN_(VIDEOPRT
, "VideoPortSetRegistryParameters error 0x%x\n", Status
);
942 VideoPortGetVgaStatus(
943 IN PVOID HwDeviceExtension
,
944 OUT PULONG VgaStatus
)
946 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
948 TRACE_(VIDEOPRT
, "VideoPortGetVgaStatus\n");
950 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
951 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
953 if (DeviceExtension
->AdapterInterfaceType
== PCIBus
)
955 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
956 /* Assumed for now */
962 return ERROR_INVALID_FUNCTION
;
970 VideoPortGetRomImage(
971 IN PVOID HwDeviceExtension
,
976 static PVOID RomImageBuffer
= NULL
;
977 PKPROCESS CallingProcess
;
980 TRACE_(VIDEOPRT
, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
981 HwDeviceExtension
, Length
);
983 /* If the length is zero then free the existing buffer. */
986 if (RomImageBuffer
!= NULL
)
988 ExFreePool(RomImageBuffer
);
989 RomImageBuffer
= NULL
;
996 * The DDK says we shouldn't use the legacy C0000 method but get the
997 * rom base address from the corresponding pci or acpi register but
998 * lets ignore that and use C0000 anyway. We have already mapped the
999 * bios area into memory so we'll copy from there.
1002 /* Copy the bios. */
1003 Length
= min(Length
, 0x10000);
1004 if (RomImageBuffer
!= NULL
)
1006 ExFreePool(RomImageBuffer
);
1009 RomImageBuffer
= ExAllocatePool(PagedPool
, Length
);
1010 if (RomImageBuffer
== NULL
)
1015 IntAttachToCSRSS(&CallingProcess
, &ApcState
);
1016 RtlCopyMemory(RomImageBuffer
, (PUCHAR
)0xC0000, Length
);
1017 IntDetachFromCSRSS(&CallingProcess
, &ApcState
);
1019 return RomImageBuffer
;
1029 IN PVOID HwDeviceExtension
,
1036 PUCHAR SearchLocation
;
1038 TRACE_(VIDEOPRT
, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase
, RomLength
, String
);
1040 StringLength
= strlen((PCHAR
)String
);
1042 SearchLocation
= RomBase
;
1043 for (SearchLocation
= RomBase
;
1044 !Found
&& SearchLocation
< RomBase
+ RomLength
- StringLength
;
1047 Found
= (RtlCompareMemory(SearchLocation
, String
, StringLength
) == StringLength
);
1050 INFO_(VIDEOPRT
, "Match found at %p\n", SearchLocation
);
1062 VideoPortSynchronizeExecution(
1063 IN PVOID HwDeviceExtension
,
1064 IN VIDEO_SYNCHRONIZE_PRIORITY Priority
,
1065 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine
,
1069 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1075 Ret
= (*SynchronizeRoutine
)(Context
);
1078 case VpMediumPriority
:
1079 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1080 if (DeviceExtension
->InterruptObject
== NULL
)
1081 Ret
= (*SynchronizeRoutine
)(Context
);
1083 Ret
= KeSynchronizeExecution(
1084 DeviceExtension
->InterruptObject
,
1089 case VpHighPriority
:
1090 OldIrql
= KeGetCurrentIrql();
1091 if (OldIrql
< SYNCH_LEVEL
)
1092 KeRaiseIrql(SYNCH_LEVEL
, &OldIrql
);
1094 Ret
= (*SynchronizeRoutine
)(Context
);
1096 if (OldIrql
< SYNCH_LEVEL
)
1097 KeLowerIrql(OldIrql
);
1112 VideoPortEnumerateChildren(
1113 IN PVOID HwDeviceExtension
,
1116 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1118 VIDEO_CHILD_ENUM_INFO ChildEnumInfo
;
1119 VIDEO_CHILD_TYPE ChildType
;
1120 BOOLEAN bHaveLastMonitorID
= FALSE
;
1121 UCHAR LastMonitorID
[10];
1122 UCHAR ChildDescriptor
[256];
1127 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1128 if (DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor
== NULL
)
1130 WARN_(VIDEOPRT
, "Miniport's HwGetVideoChildDescriptor is NULL!\n");
1134 /* Setup the ChildEnumInfo */
1135 ChildEnumInfo
.Size
= sizeof (ChildEnumInfo
);
1136 ChildEnumInfo
.ChildDescriptorSize
= sizeof (ChildDescriptor
);
1137 ChildEnumInfo
.ACPIHwId
= 0;
1138 ChildEnumInfo
.ChildHwDeviceExtension
= NULL
; /* FIXME: must be set to
1139 ChildHwDeviceExtension... */
1141 /* Enumerate the children */
1144 ChildEnumInfo
.ChildIndex
= i
;
1145 RtlZeroMemory(ChildDescriptor
, sizeof(ChildDescriptor
));
1146 Status
= DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor(
1153 if (Status
== VIDEO_ENUM_MORE_DEVICES
)
1155 if (ChildType
== Monitor
)
1157 // Check if the EDID is valid
1158 if (ChildDescriptor
[0] == 0x00 &&
1159 ChildDescriptor
[1] == 0xFF &&
1160 ChildDescriptor
[2] == 0xFF &&
1161 ChildDescriptor
[3] == 0xFF &&
1162 ChildDescriptor
[4] == 0xFF &&
1163 ChildDescriptor
[5] == 0xFF &&
1164 ChildDescriptor
[6] == 0xFF &&
1165 ChildDescriptor
[7] == 0x00)
1167 if (bHaveLastMonitorID
)
1169 // Compare the previous monitor ID with the current one, break the loop if they are identical
1170 if (RtlCompareMemory(LastMonitorID
, &ChildDescriptor
[8], sizeof(LastMonitorID
)) == sizeof(LastMonitorID
))
1172 INFO_(VIDEOPRT
, "Found identical Monitor ID two times, stopping enumeration\n");
1177 // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
1178 RtlCopyMemory(LastMonitorID
, &ChildDescriptor
[8], sizeof(LastMonitorID
));
1179 bHaveLastMonitorID
= TRUE
;
1183 else if (Status
== VIDEO_ENUM_INVALID_DEVICE
)
1185 WARN_(VIDEOPRT
, "Child device %d is invalid!\n", ChildEnumInfo
.ChildIndex
);
1188 else if (Status
== VIDEO_ENUM_NO_MORE_DEVICES
)
1190 INFO_(VIDEOPRT
, "End of child enumeration! (%d children enumerated)\n", i
- 1);
1195 WARN_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status
);
1200 if (ChildType
== Monitor
)
1203 PUCHAR p
= ChildDescriptor
;
1204 INFO_(VIDEOPRT
, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildId
);
1205 for (j
= 0; j
< sizeof (ChildDescriptor
); j
+= 8)
1207 INFO_(VIDEOPRT
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1208 p
[j
+0], p
[j
+1], p
[j
+2], p
[j
+3],
1209 p
[j
+4], p
[j
+5], p
[j
+6], p
[j
+7]);
1212 else if (ChildType
== Other
)
1214 INFO_(VIDEOPRT
, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR
)ChildDescriptor
);
1218 WARN_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildType
);
1232 VideoPortCreateSecondaryDisplay(
1233 IN PVOID HwDeviceExtension
,
1234 IN OUT PVOID
*SecondaryDeviceExtension
,
1238 return ERROR_DEV_NOT_EXIST
;
1247 IN PVOID HwDeviceExtension
,
1248 IN PMINIPORT_DPC_ROUTINE CallbackRoutine
,
1251 return KeInsertQueueDpc(
1252 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->DpcObject
,
1253 (PVOID
)CallbackRoutine
,
1262 VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject
)
1264 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1266 TRACE_(VIDEOPRT
, "VideoPortGetAssociatedDeviceExtension\n");
1267 DeviceExtension
= ((PDEVICE_OBJECT
)DeviceObject
)->DeviceExtension
;
1268 if (!DeviceExtension
)
1270 return DeviceExtension
->MiniPortDeviceExtension
;
1278 VideoPortGetVersion(
1279 IN PVOID HwDeviceExtension
,
1280 IN OUT PVPOSVERSIONINFO VpOsVersionInfo
)
1282 RTL_OSVERSIONINFOEXW Version
;
1284 Version
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
1285 if (VpOsVersionInfo
->Size
>= sizeof(VPOSVERSIONINFO
))
1288 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&Version
)))
1290 VpOsVersionInfo
->MajorVersion
= Version
.dwMajorVersion
;
1291 VpOsVersionInfo
->MinorVersion
= Version
.dwMinorVersion
;
1292 VpOsVersionInfo
->BuildNumber
= Version
.dwBuildNumber
;
1293 VpOsVersionInfo
->ServicePackMajor
= Version
.wServicePackMajor
;
1294 VpOsVersionInfo
->ServicePackMinor
= Version
.wServicePackMinor
;
1297 return ERROR_INVALID_PARAMETER
;
1299 VpOsVersionInfo
->MajorVersion
= 5;
1300 VpOsVersionInfo
->MinorVersion
= 0;
1301 VpOsVersionInfo
->BuildNumber
= 2195;
1302 VpOsVersionInfo
->ServicePackMajor
= 4;
1303 VpOsVersionInfo
->ServicePackMinor
= 0;
1308 return ERROR_INVALID_PARAMETER
;
1316 VideoPortCheckForDeviceExistence(
1317 IN PVOID HwDeviceExtension
,
1320 IN UCHAR RevisionId
,
1321 IN USHORT SubVendorId
,
1322 IN USHORT SubSystemId
,
1325 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1326 PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface
;
1327 IO_STATUS_BLOCK IoStatusBlock
;
1328 IO_STACK_LOCATION IoStack
;
1333 TRACE_(VIDEOPRT
, "VideoPortCheckForDeviceExistence\n");
1335 if (Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
))
1337 WARN_(VIDEOPRT
, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
));
1341 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1343 PciDevicePresentInterface
.Size
= sizeof(PCI_DEVICE_PRESENT_INTERFACE
);
1344 PciDevicePresentInterface
.Version
= 1;
1345 IoStack
.Parameters
.QueryInterface
.Size
= PciDevicePresentInterface
.Size
;
1346 IoStack
.Parameters
.QueryInterface
.Version
= PciDevicePresentInterface
.Version
;
1347 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)&PciDevicePresentInterface
;
1348 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
1349 &GUID_PCI_DEVICE_PRESENT_INTERFACE
;
1350 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
1351 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
1352 if (!NT_SUCCESS(Status
))
1354 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status
);
1358 if (Flags
& CDE_USE_REVISION
)
1359 PciFlags
|= PCI_USE_REVISION
;
1360 if (Flags
& CDE_USE_SUBSYSTEM_IDS
)
1361 PciFlags
|= PCI_USE_SUBSYSTEM_IDS
;
1363 DevicePresent
= PciDevicePresentInterface
.IsDevicePresent(
1364 VendorId
, DeviceId
, RevisionId
,
1365 SubVendorId
, SubSystemId
, PciFlags
);
1367 PciDevicePresentInterface
.InterfaceDereference(PciDevicePresentInterface
.Context
);
1369 return DevicePresent
;
1377 VideoPortRegisterBugcheckCallback(
1378 IN PVOID HwDeviceExtension
,
1379 IN ULONG BugcheckCode
,
1380 IN PVIDEO_BUGCHECK_CALLBACK Callback
,
1381 IN ULONG BugcheckDataSize
)
1392 VideoPortQueryPerformanceCounter(
1393 IN PVOID HwDeviceExtension
,
1394 OUT PLONGLONG PerformanceFrequency OPTIONAL
)
1396 LARGE_INTEGER Result
;
1398 TRACE_(VIDEOPRT
, "VideoPortQueryPerformanceCounter\n");
1399 Result
= KeQueryPerformanceCounter((PLARGE_INTEGER
)PerformanceFrequency
);
1400 return Result
.QuadPart
;
1408 VideoPortAcquireDeviceLock(
1409 IN PVOID HwDeviceExtension
)
1411 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1415 TRACE_(VIDEOPRT
, "VideoPortAcquireDeviceLock\n");
1416 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1417 Status
= KeWaitForMutexObject(&DeviceExtension
->DeviceLock
, Executive
,
1418 KernelMode
, FALSE
, NULL
);
1419 // ASSERT(Status == STATUS_SUCCESS);
1427 VideoPortReleaseDeviceLock(
1428 IN PVOID HwDeviceExtension
)
1430 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1434 TRACE_(VIDEOPRT
, "VideoPortReleaseDeviceLock\n");
1435 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1436 Status
= KeReleaseMutex(&DeviceExtension
->DeviceLock
, FALSE
);
1437 //ASSERT(Status == STATUS_SUCCESS);
1446 IN PDEVICE_OBJECT DeviceObject
,
1456 VideoPortAllocateContiguousMemory(
1457 IN PVOID HwDeviceExtension
,
1458 IN ULONG NumberOfBytes
,
1459 IN PHYSICAL_ADDRESS HighestAcceptableAddress
1463 return MmAllocateContiguousMemory(NumberOfBytes
, HighestAcceptableAddress
);
1470 VideoPortIsNoVesa(VOID
)
1474 UNICODE_STRING Path
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control");
1475 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"SystemStartOptions");
1476 OBJECT_ATTRIBUTES ObjectAttributes
;
1477 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
1478 ULONG Length
, NewLength
;
1480 /* Initialize object attributes with the path we want */
1481 InitializeObjectAttributes(&ObjectAttributes
,
1483 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1488 Status
= ZwOpenKey(&KeyHandle
,
1492 if (!NT_SUCCESS(Status
))
1494 VideoPortDebugPrint(Error
, "ZwOpenKey failed (0x%x)\n", Status
);
1498 /* Find out how large our buffer should be */
1499 Status
= ZwQueryValueKey(KeyHandle
,
1501 KeyValuePartialInformation
,
1505 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
1507 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1513 KeyInfo
= ExAllocatePool(PagedPool
, Length
);
1516 VideoPortDebugPrint(Error
, "Out of memory\n");
1521 /* Now for real this time */
1522 Status
= ZwQueryValueKey(KeyHandle
,
1524 KeyValuePartialInformation
,
1531 if (!NT_SUCCESS(Status
))
1533 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1534 ExFreePool(KeyInfo
);
1539 if (KeyInfo
->Type
!= REG_SZ
)
1541 VideoPortDebugPrint(Error
, "Invalid type for SystemStartOptions\n");
1542 ExFreePool(KeyInfo
);
1546 /* Check if NOVESA or BASEVIDEO is present in the start options */
1547 if (wcsstr((PWCHAR
)KeyInfo
->Data
, L
"NOVESA") ||
1548 wcsstr((PWCHAR
)KeyInfo
->Data
, L
"BASEVIDEO"))
1550 VideoPortDebugPrint(Info
, "VESA mode disabled\n");
1551 ExFreePool(KeyInfo
);
1555 ExFreePool(KeyInfo
);
1557 VideoPortDebugPrint(Info
, "VESA mode enabled\n");