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
25 /* GLOBAL VARIABLES ***********************************************************/
27 ULONG CsrssInitialized
= FALSE
;
28 PKPROCESS Csrss
= NULL
;
29 ULONG VideoPortDeviceNumber
= 0;
31 /* PRIVATE FUNCTIONS **********************************************************/
38 return STATUS_SUCCESS
;
42 IntVideoPortImageDirectoryEntryToData(
46 PIMAGE_NT_HEADERS NtHeader
;
49 NtHeader
= RtlImageNtHeader(BaseAddress
);
53 if (Directory
>= NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
)
56 Va
= NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
;
60 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
64 IntVideoPortDeferredRoutine(
66 IN PVOID DeferredContext
,
67 IN PVOID SystemArgument1
,
68 IN PVOID SystemArgument2
)
70 PVOID HwDeviceExtension
=
71 &((PVIDEO_PORT_DEVICE_EXTENSION
)DeferredContext
)->MiniPortDeviceExtension
;
72 ((PMINIPORT_DPC_ROUTINE
)SystemArgument1
)(HwDeviceExtension
, SystemArgument2
);
76 IntCreateRegistryPath(
77 IN PCUNICODE_STRING DriverRegistryPath
,
78 OUT PUNICODE_STRING DeviceRegistryPath
)
80 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
81 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
82 static WCHAR ControlSet
[] = L
"CONTROLSET";
83 static WCHAR Insert1
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
84 static WCHAR Insert2
[] = L
"\\Device0";
86 UNICODE_STRING AfterControlSet
;
88 AfterControlSet
= *DriverRegistryPath
;
89 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
90 Valid
= (DriverRegistryPath
->Length
> sizeof(RegistryMachineSystem
) &&
91 0 == _wcsnicmp(DriverRegistryPath
->Buffer
, RegistryMachineSystem
,
92 wcslen(RegistryMachineSystem
)));
95 AfterControlSet
.Buffer
+= wcslen(RegistryMachineSystem
);
96 AfterControlSet
.Length
-= sizeof(RegistryMachineSystem
) - sizeof(UNICODE_NULL
);
98 /* Check if path contains CURRENTCONTROLSET */
99 if (AfterControlSet
.Length
> sizeof(CurrentControlSet
) &&
100 0 == _wcsnicmp(AfterControlSet
.Buffer
, CurrentControlSet
, wcslen(CurrentControlSet
)))
102 AfterControlSet
.Buffer
+= wcslen(CurrentControlSet
);
103 AfterControlSet
.Length
-= sizeof(CurrentControlSet
) - sizeof(UNICODE_NULL
);
105 /* Check if path contains CONTROLSETnum */
106 else if (AfterControlSet
.Length
> sizeof(ControlSet
) &&
107 0 == _wcsnicmp(AfterControlSet
.Buffer
, ControlSet
, wcslen(ControlSet
)))
109 AfterControlSet
.Buffer
+= wcslen(ControlSet
);
110 AfterControlSet
.Length
-= sizeof(ControlSet
) - sizeof(UNICODE_NULL
);
111 while (AfterControlSet
.Length
> 0 &&
112 *AfterControlSet
.Buffer
>= L
'0' &&
113 *AfterControlSet
.Buffer
<= L
'9')
115 AfterControlSet
.Buffer
++;
116 AfterControlSet
.Length
-= sizeof(WCHAR
);
118 Valid
= (AfterControlSet
.Length
> 0 && L
'\\' == *AfterControlSet
.Buffer
);
119 AfterControlSet
.Buffer
++;
120 AfterControlSet
.Length
-= sizeof(WCHAR
);
121 AfterControlSet
.MaximumLength
= AfterControlSet
.Length
;
131 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert1
) + sizeof(Insert2
);
132 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
133 DeviceRegistryPath
->MaximumLength
,
135 if (DeviceRegistryPath
->Buffer
!= NULL
)
137 /* Build device path */
138 wcsncpy(DeviceRegistryPath
->Buffer
,
139 DriverRegistryPath
->Buffer
,
140 AfterControlSet
.Buffer
- DriverRegistryPath
->Buffer
);
141 DeviceRegistryPath
->Length
= (AfterControlSet
.Buffer
- DriverRegistryPath
->Buffer
) * sizeof(WCHAR
);
142 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert1
);
143 RtlAppendUnicodeStringToString(DeviceRegistryPath
, &AfterControlSet
);
144 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
146 /* Check if registry key exists */
147 Valid
= NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, DeviceRegistryPath
->Buffer
));
150 ExFreePoolWithTag(DeviceRegistryPath
->Buffer
, TAG_VIDEO_PORT
);
159 WARN_(VIDEOPRT
, "Unparsable registry path %wZ", DriverRegistryPath
);
162 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
165 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert2
);
166 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(
168 DeviceRegistryPath
->MaximumLength
,
171 if (!DeviceRegistryPath
->Buffer
)
172 return STATUS_NO_MEMORY
;
174 RtlCopyUnicodeString(DeviceRegistryPath
, DriverRegistryPath
);
175 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
178 return STATUS_SUCCESS
;
182 IntVideoPortCreateAdapterDeviceObject(
183 IN PDRIVER_OBJECT DriverObject
,
184 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
185 IN PDEVICE_OBJECT PhysicalDeviceObject
,
186 OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
188 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
191 PCI_SLOT_NUMBER SlotNumber
;
194 WCHAR DeviceBuffer
[20];
195 UNICODE_STRING DeviceName
;
196 PDEVICE_OBJECT DeviceObject_
;
198 if (DeviceObject
== NULL
)
199 DeviceObject
= &DeviceObject_
;
202 * Find the first free device number that can be used for video device
203 * object names and symlinks.
206 DeviceNumber
= VideoPortDeviceNumber
;
207 if (DeviceNumber
== 0xFFFFFFFF)
209 WARN_(VIDEOPRT
, "Can't find free device number\n");
210 return STATUS_UNSUCCESSFUL
;
214 * Create the device object.
217 /* Create a unicode device name. */
218 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
219 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
221 INFO_(VIDEOPRT
, "HwDeviceExtension size is: 0x%x\n",
222 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
224 /* Create the device object. */
225 Status
= IoCreateDevice(
227 sizeof(VIDEO_PORT_DEVICE_EXTENSION
) +
228 DriverExtension
->InitializationData
.HwDeviceExtensionSize
,
235 if (!NT_SUCCESS(Status
))
237 WARN_(VIDEOPRT
, "IoCreateDevice call failed with status 0x%08x\n", Status
);
242 * Set the buffering strategy here. If you change this, remember
243 * to change VidDispatchDeviceControl too.
246 (*DeviceObject
)->Flags
|= DO_BUFFERED_IO
;
249 * Initialize device extension.
252 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)((*DeviceObject
)->DeviceExtension
);
253 DeviceExtension
->Common
.Fdo
= TRUE
;
254 DeviceExtension
->DeviceNumber
= DeviceNumber
;
255 DeviceExtension
->DriverObject
= DriverObject
;
256 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
257 DeviceExtension
->FunctionalDeviceObject
= *DeviceObject
;
258 DeviceExtension
->DriverExtension
= DriverExtension
;
260 InitializeListHead(&DeviceExtension
->ChildDeviceList
);
263 * Get the registry path associated with this driver.
266 Status
= IntCreateRegistryPath(
267 &DriverExtension
->RegistryPath
,
268 &DeviceExtension
->RegistryPath
);
269 if (!NT_SUCCESS(Status
))
271 WARN_(VIDEOPRT
, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status
);
272 IoDeleteDevice(*DeviceObject
);
273 *DeviceObject
= NULL
;
277 if (PhysicalDeviceObject
!= NULL
)
279 /* Get bus number from the upper level bus driver. */
280 Size
= sizeof(ULONG
);
281 Status
= IoGetDeviceProperty(
282 PhysicalDeviceObject
,
283 DevicePropertyBusNumber
,
285 &DeviceExtension
->SystemIoBusNumber
,
287 if (!NT_SUCCESS(Status
))
289 WARN_(VIDEOPRT
, "Couldn't get an information from bus driver. We will try to\n"
290 "use legacy detection method, but even that doesn't mean that\n"
292 DeviceExtension
->PhysicalDeviceObject
= NULL
;
296 DeviceExtension
->AdapterInterfaceType
=
297 DriverExtension
->InitializationData
.AdapterInterfaceType
;
299 if (PhysicalDeviceObject
!= NULL
)
301 /* Get bus type from the upper level bus driver. */
302 Size
= sizeof(ULONG
);
304 PhysicalDeviceObject
,
305 DevicePropertyLegacyBusType
,
307 &DeviceExtension
->AdapterInterfaceType
,
310 /* Get bus device address from the upper level bus driver. */
311 Size
= sizeof(ULONG
);
313 PhysicalDeviceObject
,
314 DevicePropertyAddress
,
319 /* Convert slotnumber to PCI_SLOT_NUMBER */
320 SlotNumber
.u
.AsULONG
= 0;
321 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
322 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
323 DeviceExtension
->SystemIoSlotNumber
= SlotNumber
.u
.AsULONG
;
326 InitializeListHead(&DeviceExtension
->AddressMappingListHead
);
327 InitializeListHead(&DeviceExtension
->DmaAdapterList
);
330 &DeviceExtension
->DpcObject
,
331 IntVideoPortDeferredRoutine
,
334 KeInitializeMutex(&DeviceExtension
->DeviceLock
, 0);
336 /* Attach the device. */
337 if (PhysicalDeviceObject
!= NULL
)
338 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(
339 *DeviceObject
, PhysicalDeviceObject
);
341 /* Remove the initailizing flag */
342 (*DeviceObject
)->Flags
&= ~DO_DEVICE_INITIALIZING
;
343 return STATUS_SUCCESS
;
348 IntVideoPortFindAdapter(
349 IN PDRIVER_OBJECT DriverObject
,
350 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
351 IN PDEVICE_OBJECT DeviceObject
)
353 WCHAR DeviceVideoBuffer
[20];
354 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
357 VIDEO_PORT_CONFIG_INFO ConfigInfo
;
358 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
360 WCHAR DeviceBuffer
[20];
361 UNICODE_STRING DeviceName
;
362 WCHAR SymlinkBuffer
[20];
363 UNICODE_STRING SymlinkName
;
364 BOOL LegacyDetection
= FALSE
;
367 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
368 DeviceNumber
= DeviceExtension
->DeviceNumber
;
371 * Setup a ConfigInfo structure that we will pass to HwFindAdapter.
374 RtlZeroMemory(&ConfigInfo
, sizeof(VIDEO_PORT_CONFIG_INFO
));
375 ConfigInfo
.Length
= sizeof(VIDEO_PORT_CONFIG_INFO
);
376 ConfigInfo
.AdapterInterfaceType
= DeviceExtension
->AdapterInterfaceType
;
377 if (ConfigInfo
.AdapterInterfaceType
== PCIBus
)
378 ConfigInfo
.InterruptMode
= LevelSensitive
;
380 ConfigInfo
.InterruptMode
= Latched
;
381 ConfigInfo
.DriverRegistryPath
= DriverExtension
->RegistryPath
.Buffer
;
382 ConfigInfo
.VideoPortGetProcAddress
= IntVideoPortGetProcAddress
;
383 ConfigInfo
.SystemIoBusNumber
= DeviceExtension
->SystemIoBusNumber
;
384 ConfigInfo
.BusInterruptLevel
= DeviceExtension
->InterruptLevel
;
385 ConfigInfo
.BusInterruptVector
= DeviceExtension
->InterruptVector
;
387 Size
= sizeof(SystemBasicInfo
);
388 Status
= ZwQuerySystemInformation(
389 SystemBasicInformation
,
394 if (NT_SUCCESS(Status
))
396 ConfigInfo
.SystemMemorySize
=
397 SystemBasicInfo
.NumberOfPhysicalPages
*
398 SystemBasicInfo
.PageSize
;
402 * Call miniport HwVidFindAdapter entry point to detect if
403 * particular device is present. There are two possible code
404 * paths. The first one is for Legacy drivers (NT4) and cases
405 * when we don't have information about what bus we're on. The
406 * second case is the standard one for Plug & Play drivers.
408 if (DeviceExtension
->PhysicalDeviceObject
== NULL
)
410 LegacyDetection
= TRUE
;
415 ULONG BusNumber
, MaxBuses
;
417 MaxBuses
= DeviceExtension
->AdapterInterfaceType
== PCIBus
? PCI_MAX_BRIDGE_NUMBER
: 1;
419 for (BusNumber
= 0; BusNumber
< MaxBuses
; BusNumber
++)
421 DeviceExtension
->SystemIoBusNumber
=
422 ConfigInfo
.SystemIoBusNumber
= BusNumber
;
424 RtlZeroMemory(&DeviceExtension
->MiniPortDeviceExtension
,
425 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
427 /* FIXME: Need to figure out what string to pass as param 3. */
428 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
429 &DeviceExtension
->MiniPortDeviceExtension
,
430 DriverExtension
->HwContext
,
435 if (Status
== ERROR_DEV_NOT_EXIST
)
439 else if (Status
== NO_ERROR
)
445 WARN_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
446 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
447 if (DeviceExtension
->NextDeviceObject
)
448 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
449 IoDeleteDevice(DeviceObject
);
457 /* FIXME: Need to figure out what string to pass as param 3. */
458 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
459 &DeviceExtension
->MiniPortDeviceExtension
,
460 DriverExtension
->HwContext
,
466 if (Status
!= NO_ERROR
)
468 WARN_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
469 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
470 if (DeviceExtension
->NextDeviceObject
)
471 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
472 IoDeleteDevice(DeviceObject
);
477 * Now we know the device is present, so let's do all additional tasks
478 * such as creating symlinks or setting up interrupts and timer.
481 /* Create a unicode device name. */
482 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
483 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
485 /* Create symbolic link "\??\DISPLAYx" */
486 swprintf(SymlinkBuffer
, L
"\\??\\DISPLAY%lu", DeviceNumber
+ 1);
487 RtlInitUnicodeString(&SymlinkName
, SymlinkBuffer
);
488 IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
490 /* Add entry to DEVICEMAP\VIDEO key in registry. */
491 swprintf(DeviceVideoBuffer
, L
"\\Device\\Video%d", DeviceNumber
);
492 RtlWriteRegistryValue(
493 RTL_REGISTRY_DEVICEMAP
,
497 DeviceExtension
->RegistryPath
.Buffer
,
498 DeviceExtension
->RegistryPath
.Length
+ sizeof(UNICODE_NULL
));
500 RtlWriteRegistryValue(
501 RTL_REGISTRY_DEVICEMAP
,
506 sizeof(DeviceNumber
));
508 /* FIXME: Allocate hardware resources for device. */
511 * Allocate interrupt for device.
514 if (!IntVideoPortSetupInterrupt(DeviceObject
, DriverExtension
, &ConfigInfo
))
516 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
517 if (DeviceExtension
->NextDeviceObject
)
518 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
519 IoDeleteDevice(DeviceObject
);
520 return STATUS_INSUFFICIENT_RESOURCES
;
524 * Allocate timer for device.
527 if (!IntVideoPortSetupTimer(DeviceObject
, DriverExtension
))
529 if (DeviceExtension
->InterruptObject
!= NULL
)
530 IoDisconnectInterrupt(DeviceExtension
->InterruptObject
);
531 if (DeviceExtension
->NextDeviceObject
)
532 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
533 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
534 IoDeleteDevice(DeviceObject
);
535 WARN_(VIDEOPRT
, "STATUS_INSUFFICIENT_RESOURCES\n");
536 return STATUS_INSUFFICIENT_RESOURCES
;
540 * Query children of the device.
542 VideoPortEnumerateChildren(&DeviceExtension
->MiniPortDeviceExtension
, NULL
);
544 INFO_(VIDEOPRT
, "STATUS_SUCCESS\n");
545 return STATUS_SUCCESS
;
549 IntAttachToCSRSS(PKPROCESS
*CallingProcess
, PKAPC_STATE ApcState
)
551 *CallingProcess
= (PKPROCESS
)PsGetCurrentProcess();
552 if (*CallingProcess
!= Csrss
)
554 KeStackAttachProcess(Csrss
, ApcState
);
559 IntDetachFromCSRSS(PKPROCESS
*CallingProcess
, PKAPC_STATE ApcState
)
561 if (*CallingProcess
!= Csrss
)
563 KeUnstackDetachProcess(ApcState
);
567 /* PUBLIC FUNCTIONS ***********************************************************/
577 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData
,
580 PDRIVER_OBJECT DriverObject
= Context1
;
581 PUNICODE_STRING RegistryPath
= Context2
;
583 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
584 BOOLEAN PnpDriver
= FALSE
, LegacyDetection
= FALSE
;
586 TRACE_(VIDEOPRT
, "VideoPortInitialize\n");
589 * As a first thing do parameter checks.
592 if (HwInitializationData
->HwInitDataSize
> sizeof(VIDEO_HW_INITIALIZATION_DATA
))
594 return STATUS_REVISION_MISMATCH
;
597 if (HwInitializationData
->HwFindAdapter
== NULL
||
598 HwInitializationData
->HwInitialize
== NULL
||
599 HwInitializationData
->HwStartIO
== NULL
)
601 return STATUS_INVALID_PARAMETER
;
604 switch (HwInitializationData
->HwInitDataSize
)
607 * NT4 drivers are special case, because we must use legacy method
608 * of detection instead of the Plug & Play one.
611 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
:
612 INFO_(VIDEOPRT
, "We were loaded by a Windows NT miniport driver.\n");
615 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA
:
616 INFO_(VIDEOPRT
, "We were loaded by a Windows 2000 miniport driver.\n");
619 case sizeof(VIDEO_HW_INITIALIZATION_DATA
):
620 INFO_(VIDEOPRT
, "We were loaded by a Windows XP or later miniport driver.\n");
624 WARN_(VIDEOPRT
, "Invalid HwInitializationData size.\n");
625 return STATUS_UNSUCCESSFUL
;
628 /* Set dispatching routines */
629 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = IntVideoPortDispatchOpen
;
630 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = IntVideoPortDispatchClose
;
631 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] =
632 IntVideoPortDispatchDeviceControl
;
633 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] =
634 IntVideoPortDispatchDeviceControl
;
635 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] =
636 IntVideoPortDispatchWrite
; // ReactOS-specific hack
637 DriverObject
->DriverUnload
= IntVideoPortUnload
;
639 /* Determine type of the miniport driver */
640 if ((HwInitializationData
->HwInitDataSize
>=
641 FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA
, HwQueryInterface
))
642 && HwInitializationData
->HwSetPowerState
643 && HwInitializationData
->HwGetPowerState
644 && HwInitializationData
->HwGetVideoChildDescriptor
)
646 INFO_(VIDEOPRT
, "The miniport is a PnP miniport driver\n");
650 /* Check if legacy detection should be applied */
651 if (!PnpDriver
|| HwContext
)
653 INFO_(VIDEOPRT
, "Legacy detection for adapter interface %d\n",
654 HwInitializationData
->AdapterInterfaceType
);
656 /* FIXME: Move the code for legacy detection
657 to another function and call it here */
658 LegacyDetection
= TRUE
;
663 * The driver extension can be already allocated in case that we were
664 * called by legacy driver and failed detecting device. Some miniport
665 * drivers in that case adjust parameters and call VideoPortInitialize
669 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
670 if (DriverExtension
== NULL
)
672 Status
= IoAllocateDriverObjectExtension(
675 sizeof(VIDEO_PORT_DRIVER_EXTENSION
),
676 (PVOID
*)&DriverExtension
);
678 if (!NT_SUCCESS(Status
))
684 * Save the registry path. This should be done only once even if
685 * VideoPortInitialize is called multiple times.
688 if (RegistryPath
->Length
!= 0)
690 DriverExtension
->RegistryPath
.Length
= 0;
691 DriverExtension
->RegistryPath
.MaximumLength
=
692 RegistryPath
->Length
+ sizeof(UNICODE_NULL
);
693 DriverExtension
->RegistryPath
.Buffer
=
694 ExAllocatePoolWithTag(
696 DriverExtension
->RegistryPath
.MaximumLength
,
698 if (DriverExtension
->RegistryPath
.Buffer
== NULL
)
700 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
701 return STATUS_INSUFFICIENT_RESOURCES
;
704 RtlCopyUnicodeString(&DriverExtension
->RegistryPath
, RegistryPath
);
705 INFO_(VIDEOPRT
, "RegistryPath: %wZ\n", &DriverExtension
->RegistryPath
);
709 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
714 * Copy the correct miniport initialization data to the device extension.
718 &DriverExtension
->InitializationData
,
719 HwInitializationData
,
720 HwInitializationData
->HwInitDataSize
);
721 if (HwInitializationData
->HwInitDataSize
<
722 sizeof(VIDEO_HW_INITIALIZATION_DATA
))
724 RtlZeroMemory((PVOID
)((ULONG_PTR
)&DriverExtension
->InitializationData
+
725 HwInitializationData
->HwInitDataSize
),
726 sizeof(VIDEO_HW_INITIALIZATION_DATA
) -
727 HwInitializationData
->HwInitDataSize
);
729 DriverExtension
->HwContext
= HwContext
;
732 * Plug & Play drivers registers the device in AddDevice routine. For
733 * legacy drivers we must do it now.
738 PDEVICE_OBJECT DeviceObject
;
740 if (HwInitializationData
->HwInitDataSize
!= SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
)
742 /* power management */
743 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
745 Status
= IntVideoPortCreateAdapterDeviceObject(DriverObject
, DriverExtension
,
746 NULL
, &DeviceObject
);
747 INFO_(VIDEOPRT
, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status
);
748 if (!NT_SUCCESS(Status
))
750 Status
= IntVideoPortFindAdapter(DriverObject
, DriverExtension
, DeviceObject
);
751 INFO_(VIDEOPRT
, "IntVideoPortFindAdapter returned 0x%x\n", Status
);
752 if (NT_SUCCESS(Status
))
753 VideoPortDeviceNumber
++;
758 DriverObject
->DriverExtension
->AddDevice
= IntVideoPortAddDevice
;
759 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = IntVideoPortDispatchPnp
;
760 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
761 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = IntVideoPortDispatchSystemControl
;
763 return STATUS_SUCCESS
;
773 IN VIDEO_DEBUG_LEVEL DebugPrintLevel
,
774 IN PCHAR DebugMessage
, ...)
778 va_start(ap
, DebugMessage
);
779 vDbgPrintEx(DPFLTR_IHVVIDEO_ID
, DebugPrintLevel
, DebugMessage
, ap
);
789 IN PVOID HwDeviceExtension
,
790 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL
,
791 IN VP_STATUS ErrorCode
,
796 INFO_(VIDEOPRT
, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
797 ErrorCode
, ErrorCode
, UniqueId
, UniqueId
);
799 INFO_(VIDEOPRT
, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp
->IoControlCode
, Vrp
->IoControlCode
);
807 VideoPortGetCurrentIrql(VOID
)
809 return KeGetCurrentIrql();
812 typedef struct QueryRegistryCallbackContext
814 PVOID HwDeviceExtension
;
816 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine
;
817 } QUERY_REGISTRY_CALLBACK_CONTEXT
, *PQUERY_REGISTRY_CALLBACK_CONTEXT
;
819 static NTSTATUS NTAPI
820 QueryRegistryCallback(
824 IN ULONG ValueLength
,
826 IN PVOID EntryContext
)
828 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext
= (PQUERY_REGISTRY_CALLBACK_CONTEXT
) Context
;
830 INFO_(VIDEOPRT
, "Found registry value for name %S: type %d, length %d\n",
831 ValueName
, ValueType
, ValueLength
);
832 return (*(CallbackContext
->HwGetRegistryRoutine
))(
833 CallbackContext
->HwDeviceExtension
,
834 CallbackContext
->HwContext
,
845 VideoPortGetRegistryParameters(
846 IN PVOID HwDeviceExtension
,
847 IN PWSTR ParameterName
,
848 IN UCHAR IsParameterFileName
,
849 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine
,
852 RTL_QUERY_REGISTRY_TABLE QueryTable
[2] = {{0}};
853 QUERY_REGISTRY_CALLBACK_CONTEXT Context
;
854 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
856 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
858 TRACE_(VIDEOPRT
, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n",
859 ParameterName
, &DeviceExtension
->RegistryPath
);
861 Context
.HwDeviceExtension
= HwDeviceExtension
;
862 Context
.HwContext
= HwContext
;
863 Context
.HwGetRegistryRoutine
= GetRegistryRoutine
;
865 QueryTable
[0].QueryRoutine
= QueryRegistryCallback
;
866 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
867 QueryTable
[0].Name
= ParameterName
;
869 if (!NT_SUCCESS(RtlQueryRegistryValues(
870 RTL_REGISTRY_ABSOLUTE
,
871 DeviceExtension
->RegistryPath
.Buffer
,
876 WARN_(VIDEOPRT
, "VideoPortGetRegistryParameters could not find the "
877 "requested parameter\n");
878 return ERROR_INVALID_PARAMETER
;
881 if (IsParameterFileName
)
883 /* FIXME: need to read the contents of the file */
895 VideoPortSetRegistryParameters(
896 IN PVOID HwDeviceExtension
,
899 IN ULONG ValueLength
)
903 TRACE_(VIDEOPRT
, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n",
905 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->RegistryPath
);
906 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
907 Status
= RtlWriteRegistryValue(
908 RTL_REGISTRY_ABSOLUTE
,
909 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->RegistryPath
.Buffer
,
915 if (Status
!= NO_ERROR
)
916 WARN_(VIDEOPRT
, "VideoPortSetRegistryParameters error 0x%x\n", Status
);
926 VideoPortGetVgaStatus(
927 IN PVOID HwDeviceExtension
,
928 OUT PULONG VgaStatus
)
930 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
932 TRACE_(VIDEOPRT
, "VideoPortGetVgaStatus\n");
934 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
935 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
937 if (DeviceExtension
->AdapterInterfaceType
== PCIBus
)
939 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
940 /* Assumed for now */
946 return ERROR_INVALID_FUNCTION
;
954 VideoPortGetRomImage(
955 IN PVOID HwDeviceExtension
,
960 static PVOID RomImageBuffer
= NULL
;
961 PKPROCESS CallingProcess
;
964 TRACE_(VIDEOPRT
, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
965 HwDeviceExtension
, Length
);
967 /* If the length is zero then free the existing buffer. */
970 if (RomImageBuffer
!= NULL
)
972 ExFreePool(RomImageBuffer
);
973 RomImageBuffer
= NULL
;
980 * The DDK says we shouldn't use the legacy C0000 method but get the
981 * rom base address from the corresponding pci or acpi register but
982 * lets ignore that and use C0000 anyway. We have already mapped the
983 * bios area into memory so we'll copy from there.
987 Length
= min(Length
, 0x10000);
988 if (RomImageBuffer
!= NULL
)
990 ExFreePool(RomImageBuffer
);
993 RomImageBuffer
= ExAllocatePool(PagedPool
, Length
);
994 if (RomImageBuffer
== NULL
)
999 IntAttachToCSRSS(&CallingProcess
, &ApcState
);
1000 RtlCopyMemory(RomImageBuffer
, (PUCHAR
)0xC0000, Length
);
1001 IntDetachFromCSRSS(&CallingProcess
, &ApcState
);
1003 return RomImageBuffer
;
1013 IN PVOID HwDeviceExtension
,
1020 PUCHAR SearchLocation
;
1022 TRACE_(VIDEOPRT
, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase
, RomLength
, String
);
1024 StringLength
= strlen((PCHAR
)String
);
1026 SearchLocation
= RomBase
;
1027 for (SearchLocation
= RomBase
;
1028 !Found
&& SearchLocation
< RomBase
+ RomLength
- StringLength
;
1031 Found
= (RtlCompareMemory(SearchLocation
, String
, StringLength
) == StringLength
);
1034 INFO_(VIDEOPRT
, "Match found at %p\n", SearchLocation
);
1046 VideoPortSynchronizeExecution(
1047 IN PVOID HwDeviceExtension
,
1048 IN VIDEO_SYNCHRONIZE_PRIORITY Priority
,
1049 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine
,
1053 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1059 Ret
= (*SynchronizeRoutine
)(Context
);
1062 case VpMediumPriority
:
1063 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1064 if (DeviceExtension
->InterruptObject
== NULL
)
1065 Ret
= (*SynchronizeRoutine
)(Context
);
1067 Ret
= KeSynchronizeExecution(
1068 DeviceExtension
->InterruptObject
,
1073 case VpHighPriority
:
1074 OldIrql
= KeGetCurrentIrql();
1075 if (OldIrql
< SYNCH_LEVEL
)
1076 KeRaiseIrql(SYNCH_LEVEL
, &OldIrql
);
1078 Ret
= (*SynchronizeRoutine
)(Context
);
1080 if (OldIrql
< SYNCH_LEVEL
)
1081 KeLowerIrql(OldIrql
);
1096 VideoPortEnumerateChildren(
1097 IN PVOID HwDeviceExtension
,
1100 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1102 VIDEO_CHILD_ENUM_INFO ChildEnumInfo
;
1103 BOOLEAN bHaveLastMonitorID
= FALSE
;
1104 UCHAR LastMonitorID
[10];
1107 PDEVICE_OBJECT ChildDeviceObject
;
1108 PVIDEO_PORT_CHILD_EXTENSION ChildExtension
;
1110 INFO_(VIDEOPRT
, "Starting child device probe\n");
1111 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1112 if (DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor
== NULL
)
1114 WARN_(VIDEOPRT
, "Miniport's HwGetVideoChildDescriptor is NULL!\n");
1118 if (!IsListEmpty(&DeviceExtension
->ChildDeviceList
))
1120 ERR_(VIDEOPRT
, "FIXME: Support calling VideoPortEnumerateChildren again!\n");
1124 /* Enumerate the children */
1127 Status
= IoCreateDevice(DeviceExtension
->DriverObject
,
1128 sizeof(VIDEO_PORT_CHILD_EXTENSION
) +
1129 DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
,
1131 FILE_DEVICE_CONTROLLER
,
1132 FILE_DEVICE_SECURE_OPEN
,
1134 &ChildDeviceObject
);
1135 if (!NT_SUCCESS(Status
))
1138 ChildExtension
= ChildDeviceObject
->DeviceExtension
;
1140 RtlZeroMemory(ChildExtension
, sizeof(VIDEO_PORT_CHILD_EXTENSION
) +
1141 DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
);
1143 ChildExtension
->Common
.Fdo
= FALSE
;
1144 ChildExtension
->ChildId
= i
;
1145 ChildExtension
->PhysicalDeviceObject
= ChildDeviceObject
;
1146 ChildExtension
->DriverObject
= DeviceExtension
->DriverObject
;
1148 /* Setup the ChildEnumInfo */
1149 ChildEnumInfo
.Size
= sizeof(ChildEnumInfo
);
1150 ChildEnumInfo
.ChildDescriptorSize
= sizeof(ChildExtension
->ChildDescriptor
);
1151 ChildEnumInfo
.ACPIHwId
= 0;
1153 if (DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
)
1154 ChildEnumInfo
.ChildHwDeviceExtension
= VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension
);
1156 ChildEnumInfo
.ChildHwDeviceExtension
= NULL
;
1158 ChildEnumInfo
.ChildIndex
= ChildExtension
->ChildId
;
1160 INFO_(VIDEOPRT
, "Probing child: %d\n", ChildEnumInfo
.ChildIndex
);
1161 Status
= DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor(
1164 &ChildExtension
->ChildType
,
1165 ChildExtension
->ChildDescriptor
,
1166 &ChildExtension
->ChildId
,
1168 if (Status
== VIDEO_ENUM_MORE_DEVICES
)
1170 if (ChildExtension
->ChildType
== Monitor
)
1172 // Check if the EDID is valid
1173 if (ChildExtension
->ChildDescriptor
[0] == 0x00 &&
1174 ChildExtension
->ChildDescriptor
[1] == 0xFF &&
1175 ChildExtension
->ChildDescriptor
[2] == 0xFF &&
1176 ChildExtension
->ChildDescriptor
[3] == 0xFF &&
1177 ChildExtension
->ChildDescriptor
[4] == 0xFF &&
1178 ChildExtension
->ChildDescriptor
[5] == 0xFF &&
1179 ChildExtension
->ChildDescriptor
[6] == 0xFF &&
1180 ChildExtension
->ChildDescriptor
[7] == 0x00)
1182 if (bHaveLastMonitorID
)
1184 // Compare the previous monitor ID with the current one, break the loop if they are identical
1185 if (RtlCompareMemory(LastMonitorID
, &ChildExtension
->ChildDescriptor
[8], sizeof(LastMonitorID
)) == sizeof(LastMonitorID
))
1187 INFO_(VIDEOPRT
, "Found identical Monitor ID two times, stopping enumeration\n");
1188 IoDeleteDevice(ChildDeviceObject
);
1193 // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
1194 RtlCopyMemory(LastMonitorID
, &ChildExtension
->ChildDescriptor
[8], sizeof(LastMonitorID
));
1195 bHaveLastMonitorID
= TRUE
;
1198 ChildExtension
->EdidValid
= TRUE
;
1202 /* Mark it invalid */
1203 ChildExtension
->EdidValid
= FALSE
;
1207 else if (Status
== VIDEO_ENUM_INVALID_DEVICE
)
1209 WARN_(VIDEOPRT
, "Child device %d is invalid!\n", ChildEnumInfo
.ChildIndex
);
1210 IoDeleteDevice(ChildDeviceObject
);
1213 else if (Status
== VIDEO_ENUM_NO_MORE_DEVICES
)
1215 INFO_(VIDEOPRT
, "End of child enumeration! (%d children enumerated)\n", i
- 1);
1216 IoDeleteDevice(ChildDeviceObject
);
1221 WARN_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status
);
1222 IoDeleteDevice(ChildDeviceObject
);
1226 if (ChildExtension
->ChildType
== Monitor
)
1229 PUCHAR p
= ChildExtension
->ChildDescriptor
;
1230 INFO_(VIDEOPRT
, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension
->ChildId
);
1231 for (j
= 0; j
< sizeof (ChildExtension
->ChildDescriptor
); j
+= 8)
1233 INFO_(VIDEOPRT
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1234 p
[j
+0], p
[j
+1], p
[j
+2], p
[j
+3],
1235 p
[j
+4], p
[j
+5], p
[j
+6], p
[j
+7]);
1238 else if (ChildExtension
->ChildType
== Other
)
1240 INFO_(VIDEOPRT
, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR
)ChildExtension
->ChildDescriptor
);
1244 ERR_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension
->ChildType
);
1247 /* Clear the init flag */
1248 ChildDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1250 InsertTailList(&DeviceExtension
->ChildDeviceList
,
1251 &ChildExtension
->ListEntry
);
1254 /* Trigger reenumeration by the PnP manager */
1255 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1265 VideoPortCreateSecondaryDisplay(
1266 IN PVOID HwDeviceExtension
,
1267 IN OUT PVOID
*SecondaryDeviceExtension
,
1271 return ERROR_DEV_NOT_EXIST
;
1280 IN PVOID HwDeviceExtension
,
1281 IN PMINIPORT_DPC_ROUTINE CallbackRoutine
,
1284 return KeInsertQueueDpc(
1285 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->DpcObject
,
1286 (PVOID
)CallbackRoutine
,
1295 VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject
)
1297 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1299 TRACE_(VIDEOPRT
, "VideoPortGetAssociatedDeviceExtension\n");
1300 DeviceExtension
= ((PDEVICE_OBJECT
)DeviceObject
)->DeviceExtension
;
1301 if (!DeviceExtension
)
1303 return DeviceExtension
->MiniPortDeviceExtension
;
1311 VideoPortGetVersion(
1312 IN PVOID HwDeviceExtension
,
1313 IN OUT PVPOSVERSIONINFO VpOsVersionInfo
)
1315 RTL_OSVERSIONINFOEXW Version
;
1317 Version
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
1318 if (VpOsVersionInfo
->Size
>= sizeof(VPOSVERSIONINFO
))
1321 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&Version
)))
1323 VpOsVersionInfo
->MajorVersion
= Version
.dwMajorVersion
;
1324 VpOsVersionInfo
->MinorVersion
= Version
.dwMinorVersion
;
1325 VpOsVersionInfo
->BuildNumber
= Version
.dwBuildNumber
;
1326 VpOsVersionInfo
->ServicePackMajor
= Version
.wServicePackMajor
;
1327 VpOsVersionInfo
->ServicePackMinor
= Version
.wServicePackMinor
;
1330 return ERROR_INVALID_PARAMETER
;
1332 VpOsVersionInfo
->MajorVersion
= 5;
1333 VpOsVersionInfo
->MinorVersion
= 0;
1334 VpOsVersionInfo
->BuildNumber
= 2195;
1335 VpOsVersionInfo
->ServicePackMajor
= 4;
1336 VpOsVersionInfo
->ServicePackMinor
= 0;
1341 return ERROR_INVALID_PARAMETER
;
1349 VideoPortCheckForDeviceExistence(
1350 IN PVOID HwDeviceExtension
,
1353 IN UCHAR RevisionId
,
1354 IN USHORT SubVendorId
,
1355 IN USHORT SubSystemId
,
1358 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1359 PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface
;
1360 IO_STATUS_BLOCK IoStatusBlock
;
1361 IO_STACK_LOCATION IoStack
;
1366 TRACE_(VIDEOPRT
, "VideoPortCheckForDeviceExistence\n");
1368 if (Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
))
1370 WARN_(VIDEOPRT
, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
));
1374 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1376 PciDevicePresentInterface
.Size
= sizeof(PCI_DEVICE_PRESENT_INTERFACE
);
1377 PciDevicePresentInterface
.Version
= 1;
1378 IoStack
.Parameters
.QueryInterface
.Size
= PciDevicePresentInterface
.Size
;
1379 IoStack
.Parameters
.QueryInterface
.Version
= PciDevicePresentInterface
.Version
;
1380 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)&PciDevicePresentInterface
;
1381 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
1382 &GUID_PCI_DEVICE_PRESENT_INTERFACE
;
1383 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
1384 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
1385 if (!NT_SUCCESS(Status
))
1387 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status
);
1391 if (Flags
& CDE_USE_REVISION
)
1392 PciFlags
|= PCI_USE_REVISION
;
1393 if (Flags
& CDE_USE_SUBSYSTEM_IDS
)
1394 PciFlags
|= PCI_USE_SUBSYSTEM_IDS
;
1396 DevicePresent
= PciDevicePresentInterface
.IsDevicePresent(
1397 VendorId
, DeviceId
, RevisionId
,
1398 SubVendorId
, SubSystemId
, PciFlags
);
1400 PciDevicePresentInterface
.InterfaceDereference(PciDevicePresentInterface
.Context
);
1402 return DevicePresent
;
1410 VideoPortRegisterBugcheckCallback(
1411 IN PVOID HwDeviceExtension
,
1412 IN ULONG BugcheckCode
,
1413 IN PVIDEO_BUGCHECK_CALLBACK Callback
,
1414 IN ULONG BugcheckDataSize
)
1425 VideoPortQueryPerformanceCounter(
1426 IN PVOID HwDeviceExtension
,
1427 OUT PLONGLONG PerformanceFrequency OPTIONAL
)
1429 LARGE_INTEGER Result
;
1431 TRACE_(VIDEOPRT
, "VideoPortQueryPerformanceCounter\n");
1432 Result
= KeQueryPerformanceCounter((PLARGE_INTEGER
)PerformanceFrequency
);
1433 return Result
.QuadPart
;
1441 VideoPortAcquireDeviceLock(
1442 IN PVOID HwDeviceExtension
)
1444 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1448 TRACE_(VIDEOPRT
, "VideoPortAcquireDeviceLock\n");
1449 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1450 Status
= KeWaitForMutexObject(&DeviceExtension
->DeviceLock
, Executive
,
1451 KernelMode
, FALSE
, NULL
);
1452 // ASSERT(Status == STATUS_SUCCESS);
1460 VideoPortReleaseDeviceLock(
1461 IN PVOID HwDeviceExtension
)
1463 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1467 TRACE_(VIDEOPRT
, "VideoPortReleaseDeviceLock\n");
1468 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1469 Status
= KeReleaseMutex(&DeviceExtension
->DeviceLock
, FALSE
);
1470 //ASSERT(Status == STATUS_SUCCESS);
1479 IN PDEVICE_OBJECT DeviceObject
,
1489 VideoPortAllocateContiguousMemory(
1490 IN PVOID HwDeviceExtension
,
1491 IN ULONG NumberOfBytes
,
1492 IN PHYSICAL_ADDRESS HighestAcceptableAddress
1496 return MmAllocateContiguousMemory(NumberOfBytes
, HighestAcceptableAddress
);
1503 VideoPortIsNoVesa(VOID
)
1507 UNICODE_STRING Path
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control");
1508 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"SystemStartOptions");
1509 OBJECT_ATTRIBUTES ObjectAttributes
;
1510 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
1511 ULONG Length
, NewLength
;
1513 /* Initialize object attributes with the path we want */
1514 InitializeObjectAttributes(&ObjectAttributes
,
1516 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1521 Status
= ZwOpenKey(&KeyHandle
,
1525 if (!NT_SUCCESS(Status
))
1527 VideoPortDebugPrint(Error
, "ZwOpenKey failed (0x%x)\n", Status
);
1531 /* Find out how large our buffer should be */
1532 Status
= ZwQueryValueKey(KeyHandle
,
1534 KeyValuePartialInformation
,
1538 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
1540 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1546 KeyInfo
= ExAllocatePool(PagedPool
, Length
);
1549 VideoPortDebugPrint(Error
, "Out of memory\n");
1554 /* Now for real this time */
1555 Status
= ZwQueryValueKey(KeyHandle
,
1557 KeyValuePartialInformation
,
1564 if (!NT_SUCCESS(Status
))
1566 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1567 ExFreePool(KeyInfo
);
1572 if (KeyInfo
->Type
!= REG_SZ
)
1574 VideoPortDebugPrint(Error
, "Invalid type for SystemStartOptions\n");
1575 ExFreePool(KeyInfo
);
1579 /* Check if NOVESA or BASEVIDEO is present in the start options */
1580 if (wcsstr((PWCHAR
)KeyInfo
->Data
, L
"NOVESA") ||
1581 wcsstr((PWCHAR
)KeyInfo
->Data
, L
"BASEVIDEO"))
1583 VideoPortDebugPrint(Info
, "VESA mode disabled\n");
1584 ExFreePool(KeyInfo
);
1588 ExFreePool(KeyInfo
);
1590 VideoPortDebugPrint(Info
, "VESA mode enabled\n");