xref: /reactos/win32ss/drivers/videoprt/videoprt.c (revision 01a10da7)
1 /*
2  * VideoPort driver
3  *
4  * Copyright (C) 2002-2004, 2007 ReactOS Team
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21 
22 #include "videoprt.h"
23 
24 #include <stdio.h>
25 #include <ndk/exfuncs.h>
26 #include <ndk/obfuncs.h>
27 #include <ndk/rtlfuncs.h>
28 
29 #define NDEBUG
30 #include <debug.h>
31 
32 /* GLOBAL VARIABLES ***********************************************************/
33 
34 ULONG VideoDebugLevel = 0;
35 
36 BOOLEAN VpBaseVideo = FALSE;
37 BOOLEAN VpNoVesa = FALSE;
38 
39 PKPROCESS CsrProcess = NULL;
40 static ULONG VideoPortMaxObjectNumber = -1;
41 BOOLEAN VideoPortUseNewKey = FALSE;
42 KMUTEX VideoPortInt10Mutex;
43 KSPIN_LOCK HwResetAdaptersLock;
44 RTL_STATIC_LIST_HEAD(HwResetAdaptersList);
45 
46 /* PRIVATE FUNCTIONS **********************************************************/
47 
48 ULONG
49 NTAPI
DriverEntry(IN PVOID Context1,IN PVOID Context2)50 DriverEntry(
51     IN PVOID Context1,
52     IN PVOID Context2)
53 {
54     return STATUS_SUCCESS;
55 }
56 
57 static
58 NTSTATUS
IntVideoPortAddDeviceMapLink(PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)59 IntVideoPortAddDeviceMapLink(
60     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)
61 {
62     PUNICODE_STRING RegistryPath;
63     WCHAR DeviceBuffer[20];
64     UNICODE_STRING DeviceName;
65     WCHAR SymlinkBuffer[20];
66     UNICODE_STRING SymlinkName;
67     ULONG DeviceNumber;
68     NTSTATUS Status;
69 
70     /* Create a unicode device name. */
71     DeviceNumber = DeviceExtension->DeviceNumber;
72     swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
73 
74     if (VideoPortUseNewKey)
75         RegistryPath = &DeviceExtension->NewRegistryPath;
76     else
77         RegistryPath = &DeviceExtension->RegistryPath;
78 
79     /* Add entry to DEVICEMAP\VIDEO key in registry. */
80     Status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
81                                    L"VIDEO",
82                                    DeviceBuffer,
83                                    REG_SZ,
84                                    RegistryPath->Buffer,
85                                    RegistryPath->Length + sizeof(UNICODE_NULL));
86     if (!NT_SUCCESS(Status))
87     {
88         ERR_(VIDEOPRT, "Failed to create DEVICEMAP registry entry: 0x%X\n", Status);
89         return Status;
90     }
91 
92     Status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
93                                    L"VIDEO",
94                                    L"MaxObjectNumber",
95                                    REG_DWORD,
96                                    &DeviceNumber,
97                                    sizeof(DeviceNumber));
98     if (!NT_SUCCESS(Status))
99     {
100         ERR_(VIDEOPRT, "Failed to write MaxObjectNumber: 0x%X\n", Status);
101         return Status;
102     }
103 
104     /* Create symbolic link "\??\DISPLAYx" */
105     swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1);
106     RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
107     RtlInitUnicodeString(&DeviceName, DeviceBuffer);
108     Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
109     if (!NT_SUCCESS(Status))
110     {
111         ERR_(VIDEOPRT, "Failed to create symbolic link: 0x%X\n", Status);
112         return Status;
113     }
114 
115     /* Update MaxObjectNumber */
116     VideoPortMaxObjectNumber = DeviceNumber;
117 
118     return STATUS_SUCCESS;
119 }
120 
121 PVOID
122 NTAPI
IntVideoPortImageDirectoryEntryToData(PVOID BaseAddress,ULONG Directory)123 IntVideoPortImageDirectoryEntryToData(
124     PVOID BaseAddress,
125     ULONG Directory)
126 {
127     PIMAGE_NT_HEADERS NtHeader;
128     ULONG Va;
129 
130     NtHeader = RtlImageNtHeader(BaseAddress);
131     if (NtHeader == NULL)
132         return NULL;
133 
134     if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
135         return NULL;
136 
137     Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
138     if (Va == 0)
139         return NULL;
140 
141     return (PVOID)((ULONG_PTR)BaseAddress + Va);
142 }
143 
144 VOID
145 NTAPI
IntVideoPortDeferredRoutine(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)146 IntVideoPortDeferredRoutine(
147     IN PKDPC Dpc,
148     IN PVOID DeferredContext,
149     IN PVOID SystemArgument1,
150     IN PVOID SystemArgument2)
151 {
152     PVOID HwDeviceExtension =
153         &((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
154     ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
155 }
156 
157 NTSTATUS
158 NTAPI
IntVideoPortCreateAdapterDeviceObject(_In_ PDRIVER_OBJECT DriverObject,_In_ PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,_In_opt_ PDEVICE_OBJECT PhysicalDeviceObject,_In_ USHORT AdapterNumber,_In_ USHORT DisplayNumber,_Out_opt_ PDEVICE_OBJECT * DeviceObject)159 IntVideoPortCreateAdapterDeviceObject(
160    _In_ PDRIVER_OBJECT DriverObject,
161    _In_ PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
162    _In_opt_ PDEVICE_OBJECT PhysicalDeviceObject,
163    _In_ USHORT AdapterNumber,
164    _In_ USHORT DisplayNumber,
165    _Out_opt_ PDEVICE_OBJECT *DeviceObject)
166 {
167     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
168     ULONG DeviceNumber;
169     ULONG PciSlotNumber;
170     PCI_SLOT_NUMBER SlotNumber;
171     ULONG Size;
172     NTSTATUS Status;
173     WCHAR DeviceBuffer[20];
174     UNICODE_STRING DeviceName;
175     PDEVICE_OBJECT DeviceObject_;
176 
177     if (DeviceObject == NULL)
178         DeviceObject = &DeviceObject_;
179 
180     /*
181      * Find the first free device number that can be used for video device
182      * object names and symlinks.
183      */
184     DeviceNumber = VideoPortMaxObjectNumber + 1;
185     if (DeviceNumber == (ULONG)-1)
186     {
187         WARN_(VIDEOPRT, "Can't find free device number\n");
188         return STATUS_UNSUCCESSFUL;
189     }
190 
191     /*
192      * Create the device object.
193      */
194 
195     /* Create a unicode device name. */
196     swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
197     RtlInitUnicodeString(&DeviceName, DeviceBuffer);
198 
199     INFO_(VIDEOPRT, "HwDeviceExtension size is: 0x%x\n",
200           DriverExtension->InitializationData.HwDeviceExtensionSize);
201 
202     /* Create the device object. */
203     Size = sizeof(VIDEO_PORT_DEVICE_EXTENSION) +
204         DriverExtension->InitializationData.HwDeviceExtensionSize;
205     Status = IoCreateDevice(DriverObject,
206                             Size,
207                             &DeviceName,
208                             FILE_DEVICE_VIDEO,
209                             0,
210                             TRUE,
211                             DeviceObject);
212 
213     if (!NT_SUCCESS(Status))
214     {
215         WARN_(VIDEOPRT, "IoCreateDevice call failed with status 0x%08x\n", Status);
216         return Status;
217     }
218 
219     /*
220      * Set the buffering strategy here. If you change this, remember
221      * to change VidDispatchDeviceControl too.
222      */
223 
224     (*DeviceObject)->Flags |= DO_BUFFERED_IO;
225 
226     /* Initialize device extension. */
227     DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension);
228     DeviceExtension->Common.Fdo = TRUE;
229     DeviceExtension->DeviceNumber = DeviceNumber;
230     DeviceExtension->DriverObject = DriverObject;
231     DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
232     DeviceExtension->FunctionalDeviceObject = *DeviceObject;
233     DeviceExtension->DriverExtension = DriverExtension;
234     DeviceExtension->SessionId = -1;
235     DeviceExtension->AdapterNumber = AdapterNumber;
236     DeviceExtension->DisplayNumber = DisplayNumber;
237 
238     InitializeListHead(&DeviceExtension->ChildDeviceList);
239 
240     /* Get the registry path associated with this device. */
241     Status = IntCreateRegistryPath(&DriverExtension->RegistryPath,
242                                    DeviceExtension->AdapterNumber,
243                                    &DeviceExtension->RegistryPath);
244     if (!NT_SUCCESS(Status))
245     {
246         WARN_(VIDEOPRT, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status);
247         goto Failure;
248     }
249 
250     if (PhysicalDeviceObject != NULL)
251     {
252         /* Get bus number from the upper level bus driver. */
253         Size = sizeof(ULONG);
254         Status = IoGetDeviceProperty(PhysicalDeviceObject,
255                                      DevicePropertyBusNumber,
256                                      Size,
257                                      &DeviceExtension->SystemIoBusNumber,
258                                      &Size);
259         if (!NT_SUCCESS(Status))
260         {
261             WARN_(VIDEOPRT, "Couldn't get an information from bus driver. We will try to\n"
262                   "use legacy detection method, but even that doesn't mean that\n"
263                   "it will work.\n");
264             DeviceExtension->PhysicalDeviceObject = NULL;
265         }
266     }
267 
268     DeviceExtension->AdapterInterfaceType =
269         DriverExtension->InitializationData.AdapterInterfaceType;
270 
271     if (PhysicalDeviceObject != NULL)
272     {
273         /* Get bus type from the upper level bus driver. */
274         Size = sizeof(ULONG);
275         IoGetDeviceProperty(PhysicalDeviceObject,
276                             DevicePropertyLegacyBusType,
277                             Size,
278                             &DeviceExtension->AdapterInterfaceType,
279                             &Size);
280 
281         /* Get bus device address from the upper level bus driver. */
282         Size = sizeof(ULONG);
283         IoGetDeviceProperty(PhysicalDeviceObject,
284                             DevicePropertyAddress,
285                             Size,
286                             &PciSlotNumber,
287                             &Size);
288 
289         /* Convert slotnumber to PCI_SLOT_NUMBER */
290         SlotNumber.u.AsULONG = 0;
291         SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
292         SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
293         DeviceExtension->SystemIoSlotNumber = SlotNumber.u.AsULONG;
294     }
295 
296     InitializeListHead(&DeviceExtension->AddressMappingListHead);
297     InitializeListHead(&DeviceExtension->DmaAdapterList);
298 
299     KeInitializeDpc(&DeviceExtension->DpcObject,
300                     IntVideoPortDeferredRoutine,
301                     DeviceExtension);
302 
303     KeInitializeMutex(&DeviceExtension->DeviceLock, 0);
304 
305     /* Attach the device. */
306     if ((PhysicalDeviceObject != NULL) && (DisplayNumber == 0))
307         DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(
308                                                 *DeviceObject,
309                                                 PhysicalDeviceObject);
310 
311     Status = IntCreateNewRegistryPath(DeviceExtension);
312     if (!NT_SUCCESS(Status))
313     {
314         ERR_(VIDEOPRT, "IntCreateNewRegistryPath() failed with status 0x%08x\n", Status);
315         goto Failure;
316     }
317 
318     IntSetupDeviceSettingsKey(DeviceExtension);
319 
320     /* Remove the initializing flag */
321     (*DeviceObject)->Flags &= ~DO_DEVICE_INITIALIZING;
322 
323     /* Set up the VIDEO/DEVICEMAP registry keys */
324     Status = IntVideoPortAddDeviceMapLink(DeviceExtension);
325     if (!NT_SUCCESS(Status))
326     {
327         ERR_(VIDEOPRT, "IntVideoPortAddDeviceMapLink() failed with status 0x%08x\n", Status);
328         goto Failure;
329     }
330 
331     if (DisplayNumber == 0)
332     {
333         DriverExtension->InitializationData.StartingDeviceNumber++;
334     }
335 
336     return STATUS_SUCCESS;
337 
338 Failure:
339     if (DeviceExtension->NextDeviceObject)
340         IoDetachDevice(DeviceExtension->NextDeviceObject);
341     IoDeleteDevice(*DeviceObject);
342     *DeviceObject = NULL;
343     return Status;
344 }
345 
346 /**
347  * @brief
348  * A PIO_QUERY_DEVICE_ROUTINE callback for IoQueryDeviceDescription()
349  * to return success when an enumerated bus has been found.
350  **/
351 static NTSTATUS
352 NTAPI
IntVideoPortEnumBusCallback(_In_ PVOID Context,_In_ PUNICODE_STRING PathName,_In_ INTERFACE_TYPE BusType,_In_ ULONG BusNumber,_In_ PKEY_VALUE_FULL_INFORMATION * BusInformation,_In_ CONFIGURATION_TYPE ControllerType,_In_ ULONG ControllerNumber,_In_ PKEY_VALUE_FULL_INFORMATION * ControllerInformation,_In_ CONFIGURATION_TYPE PeripheralType,_In_ ULONG PeripheralNumber,_In_ PKEY_VALUE_FULL_INFORMATION * PeripheralInformation)353 IntVideoPortEnumBusCallback(
354     _In_ PVOID Context,
355     _In_ PUNICODE_STRING PathName,
356     _In_ INTERFACE_TYPE BusType,
357     _In_ ULONG BusNumber,
358     _In_ PKEY_VALUE_FULL_INFORMATION* BusInformation,
359     _In_ CONFIGURATION_TYPE ControllerType,
360     _In_ ULONG ControllerNumber,
361     _In_ PKEY_VALUE_FULL_INFORMATION* ControllerInformation,
362     _In_ CONFIGURATION_TYPE PeripheralType,
363     _In_ ULONG PeripheralNumber,
364     _In_ PKEY_VALUE_FULL_INFORMATION* PeripheralInformation)
365 {
366     UNREFERENCED_PARAMETER(Context);
367     UNREFERENCED_PARAMETER(PathName);
368     UNREFERENCED_PARAMETER(BusType);
369     UNREFERENCED_PARAMETER(BusNumber);
370     UNREFERENCED_PARAMETER(BusInformation);
371     UNREFERENCED_PARAMETER(ControllerType);
372     UNREFERENCED_PARAMETER(ControllerNumber);
373     UNREFERENCED_PARAMETER(ControllerInformation);
374     UNREFERENCED_PARAMETER(PeripheralType);
375     UNREFERENCED_PARAMETER(PeripheralNumber);
376     UNREFERENCED_PARAMETER(PeripheralInformation);
377 
378     /* The bus has been found */
379     return STATUS_SUCCESS;
380 }
381 
382 /**
383  * @brief
384  * Enumerates all supported buses on the system.
385  **/
386 static NTSTATUS
IntVideoPortEnumBuses(_In_ INTERFACE_TYPE AdapterInterfaceType,_Inout_ PULONG BusNumber)387 IntVideoPortEnumBuses(
388     _In_ INTERFACE_TYPE AdapterInterfaceType,
389     _Inout_ PULONG BusNumber)
390 {
391     // TODO: Forward-compatibility with Windows 7+:
392     // In case AdapterInterfaceType == PCIBus, check for the
393     // \Registry\HARDWARE\DESCRIPTION\System\VideoAdapterBusses
394     // key (created by pci.sys) that enumerates the PCI buses that
395     // are known to have video display adapters on them.
396     // This is a handy shortcut for videoprt, that would otherwise
397     // have to enumerate all the PCI buses (PCI_MAX_BRIDGE_NUMBER)
398     // to locate any video adapter.
399     // Otherwise, fall back to the usual method done below.
400 
401     /* Find the next bus of the given type */
402     return IoQueryDeviceDescription(&AdapterInterfaceType,
403                                     BusNumber,
404                                     NULL,
405                                     NULL,
406                                     NULL,
407                                     NULL,
408                                     IntVideoPortEnumBusCallback,
409                                     NULL);
410 }
411 
412 NTSTATUS
413 NTAPI
IntVideoPortFindAdapter(IN PDRIVER_OBJECT DriverObject,IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,IN PDEVICE_OBJECT DeviceObject)414 IntVideoPortFindAdapter(
415     IN PDRIVER_OBJECT DriverObject,
416     IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
417     IN PDEVICE_OBJECT DeviceObject)
418 {
419     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
420     NTSTATUS Status;
421     VP_STATUS vpStatus;
422     VIDEO_PORT_CONFIG_INFO ConfigInfo;
423     SYSTEM_BASIC_INFORMATION SystemBasicInfo;
424     UCHAR Again = FALSE;
425     BOOL LegacyDetection = FALSE;
426 
427     DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
428 
429     /* Setup a ConfigInfo structure that we will pass to HwFindAdapter. */
430     RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
431     ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
432     ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
433     if (ConfigInfo.AdapterInterfaceType == PCIBus)
434         ConfigInfo.InterruptMode = LevelSensitive;
435     else
436         ConfigInfo.InterruptMode = Latched;
437     ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer;
438     ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress;
439     ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
440     ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel;
441     ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector;
442 
443     Status = ZwQuerySystemInformation(SystemBasicInformation,
444                                       &SystemBasicInfo,
445                                       sizeof(SystemBasicInfo),
446                                       NULL);
447     if (NT_SUCCESS(Status))
448     {
449         ConfigInfo.SystemMemorySize = SystemBasicInfo.NumberOfPhysicalPages *
450                                       SystemBasicInfo.PageSize;
451     }
452 
453     // FIXME: Check the adapter key and update VideoDebugLevel variable.
454 
455     /*
456      * Call miniport HwVidFindAdapter entry point to detect if
457      * particular device is present. There are two possible code
458      * paths. The first one is for Legacy drivers (NT4) and cases
459      * when we don't have information about what bus we're on. The
460      * second case is the standard one for Plug & Play drivers.
461      */
462     if (DeviceExtension->PhysicalDeviceObject == NULL)
463     {
464         LegacyDetection = TRUE;
465     }
466 
467     if (LegacyDetection)
468     {
469         ULONG BusNumber;
470 
471         /* Suppose first we may not find any suitable device */
472         vpStatus = ERROR_DEV_NOT_EXIST; // ERROR_NO_MORE_DEVICES;
473 
474         /* Enumerate all buses of the given type, call HwFindAdapter for each
475          * to find whether a video adapter is recognized there. Stop when an
476          * adapter has been found. */
477         for (BusNumber = 0;
478              (BusNumber < MAXULONG) &&
479              NT_SUCCESS(IntVideoPortEnumBuses(DeviceExtension->AdapterInterfaceType,
480                                               &BusNumber));
481              ++BusNumber)
482         {
483             DPRINT("Bus Type %lu, Number %lu\n",
484                    DeviceExtension->AdapterInterfaceType, BusNumber);
485 
486             DeviceExtension->SystemIoBusNumber =
487                 ConfigInfo.SystemIoBusNumber = BusNumber;
488 
489             RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
490                           DriverExtension->InitializationData.HwDeviceExtensionSize);
491 
492             /* FIXME: Need to figure out what string to pass as param 3. */
493             // FIXME: Handle the 'Again' parameter for legacy detection.
494             vpStatus = DriverExtension->InitializationData.HwFindAdapter(
495                          &DeviceExtension->MiniPortDeviceExtension,
496                          DriverExtension->HwContext,
497                          NULL,
498                          &ConfigInfo,
499                          &Again);
500 
501             if (vpStatus == ERROR_DEV_NOT_EXIST)
502             {
503                 continue;
504             }
505             else
506             {
507                 break;
508             }
509         }
510     }
511     else
512     {
513         /* FIXME: Need to figure out what string to pass as param 3. */
514         vpStatus = DriverExtension->InitializationData.HwFindAdapter(
515                      &DeviceExtension->MiniPortDeviceExtension,
516                      DriverExtension->HwContext,
517                      NULL,
518                      &ConfigInfo,
519                      &Again);
520     }
521 
522     if (vpStatus != NO_ERROR)
523     {
524         ERR_(VIDEOPRT, "HwFindAdapter call failed with error 0x%X\n", vpStatus);
525         Status = STATUS_UNSUCCESSFUL;
526         goto Failure;
527     }
528 
529     /*
530      * Now we know the device is present, so let's do all additional tasks
531      * such as creating symlinks or setting up interrupts and timer.
532      */
533 
534     /* FIXME: Allocate hardware resources for device. */
535 
536     /* Allocate interrupt for device. */
537     if (!IntVideoPortSetupInterrupt(DeviceObject, DriverExtension, &ConfigInfo))
538     {
539         Status = STATUS_INSUFFICIENT_RESOURCES;
540         goto Failure;
541     }
542 
543     /* Allocate timer for device. */
544     if (!IntVideoPortSetupTimer(DeviceObject, DriverExtension))
545     {
546         if (DeviceExtension->InterruptObject != NULL)
547             IoDisconnectInterrupt(DeviceExtension->InterruptObject);
548         ERR_(VIDEOPRT, "IntVideoPortSetupTimer failed\n");
549         Status = STATUS_INSUFFICIENT_RESOURCES;
550         goto Failure;
551     }
552 
553     /* If the device can be reset, insert it in the list of resettable adapters */
554     InitializeListHead(&DeviceExtension->HwResetListEntry);
555     if (DriverExtension->InitializationData.HwResetHw != NULL)
556     {
557         ExInterlockedInsertTailList(&HwResetAdaptersList,
558                                     &DeviceExtension->HwResetListEntry,
559                                     &HwResetAdaptersLock);
560     }
561 
562     INFO_(VIDEOPRT, "STATUS_SUCCESS\n");
563     return STATUS_SUCCESS;
564 
565 Failure:
566     RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
567     if (DeviceExtension->NextDeviceObject)
568         IoDetachDevice(DeviceExtension->NextDeviceObject);
569     IoDeleteDevice(DeviceObject);
570     return Status;
571 }
572 
573 VOID
574 FASTCALL
IntAttachToCSRSS(PKPROCESS * CallingProcess,PKAPC_STATE ApcState)575 IntAttachToCSRSS(
576     PKPROCESS *CallingProcess,
577     PKAPC_STATE ApcState)
578 {
579     *CallingProcess = (PKPROCESS)PsGetCurrentProcess();
580     if (*CallingProcess != CsrProcess)
581     {
582         KeStackAttachProcess(CsrProcess, ApcState);
583     }
584 }
585 
586 VOID
587 FASTCALL
IntDetachFromCSRSS(PKPROCESS * CallingProcess,PKAPC_STATE ApcState)588 IntDetachFromCSRSS(
589     PKPROCESS *CallingProcess,
590     PKAPC_STATE ApcState)
591 {
592     if (*CallingProcess != CsrProcess)
593     {
594         KeUnstackDetachProcess(ApcState);
595     }
596 }
597 
598 VOID
599 FASTCALL
IntLoadRegistryParameters(VOID)600 IntLoadRegistryParameters(VOID)
601 {
602     NTSTATUS Status;
603     HANDLE KeyHandle;
604     UNICODE_STRING UseNewKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\UseNewKey");
605     UNICODE_STRING Path = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
606     UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SystemStartOptions");
607     OBJECT_ATTRIBUTES ObjectAttributes;
608     PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
609     ULONG Length, NewLength;
610 
611     /* Check if we need to use new registry */
612     InitializeObjectAttributes(&ObjectAttributes,
613                                &UseNewKeyPath,
614                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
615                                NULL,
616                                NULL);
617     Status = ZwOpenKey(&KeyHandle,
618                        GENERIC_READ | GENERIC_WRITE,
619                        &ObjectAttributes);
620     if (NT_SUCCESS(Status))
621     {
622         VideoPortUseNewKey = TRUE;
623         ZwClose(KeyHandle);
624     }
625 
626     /* Initialize object attributes with the path we want */
627     InitializeObjectAttributes(&ObjectAttributes,
628                                &Path,
629                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
630                                NULL,
631                                NULL);
632 
633     /* Open the key */
634     Status = ZwOpenKey(&KeyHandle,
635                        KEY_QUERY_VALUE,
636                        &ObjectAttributes);
637     if (!NT_SUCCESS(Status))
638     {
639         VideoPortDebugPrint(Error, "ZwOpenKey failed (0x%x)\n", Status);
640         return;
641     }
642 
643     /* Find out how large our buffer should be */
644     Status = ZwQueryValueKey(KeyHandle,
645                              &ValueName,
646                              KeyValuePartialInformation,
647                              NULL,
648                              0,
649                              &Length);
650     if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
651     {
652         VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status);
653         ObCloseHandle(KeyHandle, KernelMode);
654         return;
655     }
656 
657     /* Allocate it */
658     KeyInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_VIDEO_PORT);
659     if (!KeyInfo)
660     {
661         VideoPortDebugPrint(Error, "Out of memory\n");
662         ObCloseHandle(KeyHandle, KernelMode);
663         return;
664     }
665 
666     /* Now for real this time */
667     Status = ZwQueryValueKey(KeyHandle,
668                              &ValueName,
669                              KeyValuePartialInformation,
670                              KeyInfo,
671                              Length,
672                              &NewLength);
673     ObCloseHandle(KeyHandle, KernelMode);
674 
675     if (!NT_SUCCESS(Status))
676     {
677         VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status);
678         ExFreePoolWithTag(KeyInfo, TAG_VIDEO_PORT);
679         return;
680     }
681 
682     /* Sanity check */
683     if (KeyInfo->Type != REG_SZ)
684     {
685         VideoPortDebugPrint(Error, "Invalid type for SystemStartOptions\n");
686         ExFreePoolWithTag(KeyInfo, TAG_VIDEO_PORT);
687         return;
688     }
689 
690     /* Check if BASEVIDEO or NOVESA is present in the start options */
691     if (wcsstr((PWCHAR)KeyInfo->Data, L"BASEVIDEO"))
692         VpBaseVideo = TRUE;
693     if (wcsstr((PWCHAR)KeyInfo->Data, L"NOVESA"))
694         VpNoVesa = TRUE;
695 
696     ExFreePoolWithTag(KeyInfo, TAG_VIDEO_PORT);
697 
698     /* FIXME: Old ReactOS-compatibility... */
699     if (VpBaseVideo) VpNoVesa = TRUE;
700 
701     if (VpNoVesa)
702         VideoPortDebugPrint(Info, "VESA mode disabled\n");
703     else
704         VideoPortDebugPrint(Info, "VESA mode enabled\n");
705 
706     /* If we are in BASEVIDEO, create the volatile registry key for Win32k */
707     if (VpBaseVideo)
708     {
709         RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\BaseVideo");
710 
711         InitializeObjectAttributes(&ObjectAttributes,
712                                    &Path,
713                                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
714                                    NULL,
715                                    NULL);
716 
717         Status = ZwCreateKey(&KeyHandle,
718                              READ_CONTROL, // Non-0 placeholder: no use for this handle.
719                              &ObjectAttributes,
720                              0,
721                              NULL,
722                              REG_OPTION_VOLATILE,
723                              NULL);
724         if (NT_SUCCESS(Status))
725             ObCloseHandle(KeyHandle, KernelMode);
726         else
727             ERR_(VIDEOPRT, "Failed to create the BaseVideo key (0x%x)\n", Status);
728     }
729 
730     return;
731 }
732 
733 /* PUBLIC FUNCTIONS ***********************************************************/
734 
735 /*
736  * @implemented
737  */
738 ULONG
739 NTAPI
VideoPortInitialize(IN PVOID Context1,IN PVOID Context2,IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,IN PVOID HwContext)740 VideoPortInitialize(
741     IN PVOID Context1,
742     IN PVOID Context2,
743     IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
744     IN PVOID HwContext)
745 {
746     PDRIVER_OBJECT DriverObject = Context1;
747     PUNICODE_STRING RegistryPath = Context2;
748     NTSTATUS Status;
749     PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
750     BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE;
751     static BOOLEAN FirstInitialization;
752 
753     TRACE_(VIDEOPRT, "VideoPortInitialize\n");
754 
755     if (!FirstInitialization)
756     {
757         FirstInitialization = TRUE;
758         KeInitializeMutex(&VideoPortInt10Mutex, 0);
759         KeInitializeSpinLock(&HwResetAdaptersLock);
760         IntLoadRegistryParameters();
761     }
762 
763     /* As a first thing do parameter checks. */
764     if (HwInitializationData->HwInitDataSize > sizeof(VIDEO_HW_INITIALIZATION_DATA))
765     {
766         ERR_(VIDEOPRT, "Invalid HwInitializationData\n");
767         return STATUS_REVISION_MISMATCH;
768     }
769 
770     if ((HwInitializationData->HwFindAdapter == NULL) ||
771         (HwInitializationData->HwInitialize == NULL) ||
772         (HwInitializationData->HwStartIO == NULL))
773     {
774         ERR_(VIDEOPRT, "Invalid HwInitializationData\n");
775         return STATUS_INVALID_PARAMETER;
776     }
777 
778     switch (HwInitializationData->HwInitDataSize)
779     {
780         /*
781          * NT4 drivers are special case, because we must use legacy method
782          * of detection instead of the Plug & Play one.
783          */
784         case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA:
785             INFO_(VIDEOPRT, "We were loaded by a Windows NT miniport driver.\n");
786             break;
787 
788         case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA:
789             INFO_(VIDEOPRT, "We were loaded by a Windows 2000 miniport driver.\n");
790             break;
791 
792         case sizeof(VIDEO_HW_INITIALIZATION_DATA):
793             INFO_(VIDEOPRT, "We were loaded by a Windows XP or later miniport driver.\n");
794             break;
795 
796         default:
797             ERR_(VIDEOPRT, "Invalid HwInitializationData size %lu (expected %lu, %lu or %lu)\n",
798                  HwInitializationData->HwInitDataSize,
799                  SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA,
800                  SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA,
801                  sizeof(VIDEO_HW_INITIALIZATION_DATA));
802             return STATUS_UNSUCCESSFUL;
803     }
804 
805     /* Set dispatching routines */
806     DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen;
807     DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose;
808     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
809         IntVideoPortDispatchDeviceControl;
810     DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =
811         IntVideoPortDispatchDeviceControl;
812     DriverObject->DriverUnload = IntVideoPortUnload;
813 
814     /* Determine type of the miniport driver */
815     if ((HwInitializationData->HwInitDataSize >=
816             FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA, HwQueryInterface)) &&
817         (HwInitializationData->HwSetPowerState != NULL) &&
818         (HwInitializationData->HwGetPowerState != NULL) &&
819         (HwInitializationData->HwGetVideoChildDescriptor != NULL))
820     {
821         INFO_(VIDEOPRT, "The miniport is a PnP miniport driver\n");
822         PnpDriver = TRUE;
823     }
824 
825     /* Check if legacy detection should be applied */
826     if (!PnpDriver || HwContext)
827     {
828         INFO_(VIDEOPRT, "Legacy detection for adapter interface %d\n",
829               HwInitializationData->AdapterInterfaceType);
830 
831         /* FIXME: Move the code for legacy detection
832            to another function and call it here */
833         LegacyDetection = TRUE;
834     }
835 
836     /*
837      * NOTE:
838      * The driver extension can be already allocated in case that we were
839      * called by legacy driver and failed detecting device. Some miniport
840      * drivers in that case adjust parameters and call VideoPortInitialize
841      * again.
842      */
843     DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
844     if (DriverExtension == NULL)
845     {
846         Status = IoAllocateDriverObjectExtension(DriverObject,
847                                                  DriverObject,
848                                                  sizeof(VIDEO_PORT_DRIVER_EXTENSION),
849                                                  (PVOID *)&DriverExtension);
850         if (!NT_SUCCESS(Status))
851         {
852             ERR_(VIDEOPRT, "IoAllocateDriverObjectExtension failed 0x%x\n", Status);
853             return Status;
854         }
855 
856         /*
857          * Save the registry path. This should be done only once even if
858          * VideoPortInitialize is called multiple times.
859          */
860         if (RegistryPath->Length != 0)
861         {
862             DriverExtension->RegistryPath.Length = 0;
863             DriverExtension->RegistryPath.MaximumLength =
864                 RegistryPath->Length + sizeof(UNICODE_NULL);
865             DriverExtension->RegistryPath.Buffer =
866                 ExAllocatePoolWithTag(
867                     PagedPool,
868                     DriverExtension->RegistryPath.MaximumLength,
869                     'RTSU');
870             if (DriverExtension->RegistryPath.Buffer == NULL)
871             {
872                 RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
873                 return STATUS_INSUFFICIENT_RESOURCES;
874             }
875 
876             RtlCopyUnicodeString(&DriverExtension->RegistryPath, RegistryPath);
877 
878             /* There is a bug in Spice guest agent, which searches 'System' case-sensitively.
879              * Replace 'SYSTEM' by 'System' to fix that.
880              * Probably for similar reason, Windows also replaces 'MACHINE' by 'Machine'.
881              */
882             wcsncpy(wcsstr(DriverExtension->RegistryPath.Buffer, L"\\SYSTEM\\"), L"\\System\\", ARRAYSIZE(L"\\SYSTEM\\") - 1);
883             wcsncpy(wcsstr(DriverExtension->RegistryPath.Buffer, L"\\MACHINE\\"), L"\\Machine\\", ARRAYSIZE(L"\\MACHINE\\") - 1);
884 
885             INFO_(VIDEOPRT, "RegistryPath: %wZ\n", &DriverExtension->RegistryPath);
886         }
887         else
888         {
889             RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
890         }
891     }
892 
893     /* Copy the correct miniport initialization data to the device extension. */
894     RtlCopyMemory(&DriverExtension->InitializationData,
895                   HwInitializationData,
896                   HwInitializationData->HwInitDataSize);
897     if (HwInitializationData->HwInitDataSize <
898             sizeof(VIDEO_HW_INITIALIZATION_DATA))
899     {
900         RtlZeroMemory((PVOID)((ULONG_PTR)&DriverExtension->InitializationData +
901                               HwInitializationData->HwInitDataSize),
902                       sizeof(VIDEO_HW_INITIALIZATION_DATA) -
903                       HwInitializationData->HwInitDataSize);
904     }
905     DriverExtension->HwContext = HwContext;
906 
907     /*
908      * Plug & Play drivers registers the device in AddDevice routine.
909      * For legacy drivers we must do it now.
910      */
911     if (LegacyDetection)
912     {
913         PDEVICE_OBJECT DeviceObject;
914 
915         if (HwInitializationData->HwInitDataSize != SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA)
916         {
917             /* Power management */
918             DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
919         }
920 
921         Status = IntVideoPortCreateAdapterDeviceObject(DriverObject,
922                                                        DriverExtension,
923                                                        NULL,
924                                                        DriverExtension->InitializationData.StartingDeviceNumber,
925                                                        0,
926                                                        &DeviceObject);
927         if (!NT_SUCCESS(Status))
928         {
929             ERR_(VIDEOPRT, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status);
930             return Status;
931         }
932 
933         Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject);
934         if (!NT_SUCCESS(Status))
935             ERR_(VIDEOPRT, "IntVideoPortFindAdapter returned 0x%x\n", Status);
936 
937         return Status;
938     }
939     else
940     {
941         DriverObject->DriverExtension->AddDevice = IntVideoPortAddDevice;
942         DriverObject->MajorFunction[IRP_MJ_PNP] = IntVideoPortDispatchPnp;
943         DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
944         DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IntVideoPortDispatchSystemControl;
945 
946         return STATUS_SUCCESS;
947     }
948 }
949 
950 /*
951  * @implemented
952  */
953 VOID
VideoPortDebugPrint(IN VIDEO_DEBUG_LEVEL DebugPrintLevel,IN PCHAR DebugMessage,...)954 VideoPortDebugPrint(
955     IN VIDEO_DEBUG_LEVEL DebugPrintLevel,
956     IN PCHAR DebugMessage,
957     ...)
958 {
959     va_list ap;
960 
961     if (VideoDebugLevel >= DebugPrintLevel)
962         DebugPrintLevel = Error;
963 
964     va_start(ap, DebugMessage);
965     vDbgPrintEx(DPFLTR_IHVVIDEO_ID, DebugPrintLevel, DebugMessage, ap);
966     va_end(ap);
967 }
968 
969 /*
970  * @unimplemented
971  */
972 VOID
973 NTAPI
VideoPortLogError(IN PVOID HwDeviceExtension,IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,IN VP_STATUS ErrorCode,IN ULONG UniqueId)974 VideoPortLogError(
975     IN PVOID HwDeviceExtension,
976     IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
977     IN VP_STATUS ErrorCode,
978     IN ULONG UniqueId)
979 {
980     UNIMPLEMENTED;
981 
982     INFO_(VIDEOPRT, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
983           ErrorCode, ErrorCode, UniqueId, UniqueId);
984     if (Vrp)
985         INFO_(VIDEOPRT, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode);
986 }
987 
988 /*
989  * @implemented
990  */
991 UCHAR
992 NTAPI
VideoPortGetCurrentIrql(VOID)993 VideoPortGetCurrentIrql(VOID)
994 {
995     return KeGetCurrentIrql();
996 }
997 
998 typedef struct QueryRegistryCallbackContext
999 {
1000     PVOID HwDeviceExtension;
1001     PVOID HwContext;
1002     PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
1003 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
1004 
1005 static
1006 NTSTATUS
1007 NTAPI
QueryRegistryCallback(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)1008 QueryRegistryCallback(
1009     IN PWSTR ValueName,
1010     IN ULONG ValueType,
1011     IN PVOID ValueData,
1012     IN ULONG ValueLength,
1013     IN PVOID Context,
1014     IN PVOID EntryContext)
1015 {
1016     PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context;
1017 
1018     INFO_(VIDEOPRT, "Found registry value for name %S: type %d, length %d\n",
1019           ValueName, ValueType, ValueLength);
1020     return (*(CallbackContext->HwGetRegistryRoutine))(
1021                CallbackContext->HwDeviceExtension,
1022                CallbackContext->HwContext,
1023                ValueName,
1024                ValueData,
1025                ValueLength);
1026 }
1027 
1028 /*
1029  * @unimplemented
1030  */
1031 
1032 VP_STATUS
1033 NTAPI
VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension,IN PWSTR ParameterName,IN UCHAR IsParameterFileName,IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,IN PVOID HwContext)1034 VideoPortGetRegistryParameters(
1035     IN PVOID HwDeviceExtension,
1036     IN PWSTR ParameterName,
1037     IN UCHAR IsParameterFileName,
1038     IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
1039     IN PVOID HwContext)
1040 {
1041     RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}};
1042     QUERY_REGISTRY_CALLBACK_CONTEXT Context;
1043     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1044     NTSTATUS Status;
1045 
1046     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1047 
1048     TRACE_(VIDEOPRT, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n",
1049            ParameterName, &DeviceExtension->RegistryPath);
1050 
1051     Context.HwDeviceExtension = HwDeviceExtension;
1052     Context.HwContext = HwContext;
1053     Context.HwGetRegistryRoutine = GetRegistryRoutine;
1054 
1055     QueryTable[0].QueryRoutine = QueryRegistryCallback;
1056     QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
1057     QueryTable[0].Name = ParameterName;
1058 
1059     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1060                                     DeviceExtension->RegistryPath.Buffer,
1061                                     QueryTable,
1062                                     &Context,
1063                                     NULL);
1064     if (!NT_SUCCESS(Status))
1065     {
1066         WARN_(VIDEOPRT, "VideoPortGetRegistryParameters could not find the "
1067               "requested parameter\n");
1068         return ERROR_INVALID_PARAMETER;
1069     }
1070 
1071     if (IsParameterFileName)
1072     {
1073         /* FIXME: need to read the contents of the file */
1074         UNIMPLEMENTED;
1075     }
1076 
1077     return NO_ERROR;
1078 }
1079 
1080 /*
1081  * @implemented
1082  */
1083 VP_STATUS
1084 NTAPI
VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension,IN PWSTR ValueName,IN PVOID ValueData,IN ULONG ValueLength)1085 VideoPortSetRegistryParameters(
1086     IN PVOID HwDeviceExtension,
1087     IN PWSTR ValueName,
1088     IN PVOID ValueData,
1089     IN ULONG ValueLength)
1090 {
1091     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1092     VP_STATUS Status;
1093 
1094     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1095     TRACE_(VIDEOPRT, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n",
1096            ValueName,
1097            &DeviceExtension->RegistryPath);
1098     ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
1099     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
1100                                    DeviceExtension->RegistryPath.Buffer,
1101                                    ValueName,
1102                                    REG_BINARY,
1103                                    ValueData,
1104                                    ValueLength);
1105     if (Status != NO_ERROR)
1106         WARN_(VIDEOPRT, "VideoPortSetRegistryParameters error 0x%x\n", Status);
1107 
1108     return Status;
1109 }
1110 
1111 /*
1112  * @implemented
1113  */
1114 VP_STATUS
1115 NTAPI
VideoPortGetVgaStatus(IN PVOID HwDeviceExtension,OUT PULONG VgaStatus)1116 VideoPortGetVgaStatus(
1117     IN PVOID HwDeviceExtension,
1118     OUT PULONG VgaStatus)
1119 {
1120     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1121 
1122     TRACE_(VIDEOPRT, "VideoPortGetVgaStatus\n");
1123 
1124     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1125     if (KeGetCurrentIrql() == PASSIVE_LEVEL)
1126     {
1127         if (DeviceExtension->AdapterInterfaceType == PCIBus)
1128         {
1129             /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
1130             /* Assumed for now */
1131             *VgaStatus = 1;
1132             return NO_ERROR;
1133         }
1134     }
1135 
1136     return ERROR_INVALID_FUNCTION;
1137 }
1138 
1139 /*
1140  * @implemented
1141  */
1142 PVOID
1143 NTAPI
VideoPortGetRomImage(IN PVOID HwDeviceExtension,IN PVOID Unused1,IN ULONG Unused2,IN ULONG Length)1144 VideoPortGetRomImage(
1145     IN PVOID HwDeviceExtension,
1146     IN PVOID Unused1,
1147     IN ULONG Unused2,
1148     IN ULONG Length)
1149 {
1150     static PVOID RomImageBuffer = NULL;
1151     PKPROCESS CallingProcess;
1152     KAPC_STATE ApcState;
1153 
1154     TRACE_(VIDEOPRT, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
1155            HwDeviceExtension, Length);
1156 
1157     /* If the length is zero then free the existing buffer. */
1158     if (Length == 0)
1159     {
1160         if (RomImageBuffer != NULL)
1161         {
1162             ExFreePool(RomImageBuffer);
1163             RomImageBuffer = NULL;
1164         }
1165         return NULL;
1166     }
1167     else
1168     {
1169         /*
1170          * The DDK says we shouldn't use the legacy C0000 method but get the
1171          * rom base address from the corresponding pci or acpi register but
1172          * lets ignore that and use C0000 anyway. We have already mapped the
1173          * bios area into memory so we'll copy from there.
1174          */
1175 
1176         /* Copy the bios. */
1177         Length = min(Length, 0x10000);
1178         if (RomImageBuffer != NULL)
1179         {
1180             ExFreePool(RomImageBuffer);
1181         }
1182 
1183         RomImageBuffer = ExAllocatePool(PagedPool, Length);
1184         if (RomImageBuffer == NULL)
1185         {
1186             return NULL;
1187         }
1188 
1189         IntAttachToCSRSS(&CallingProcess, &ApcState);
1190         RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length);
1191         IntDetachFromCSRSS(&CallingProcess, &ApcState);
1192 
1193         return RomImageBuffer;
1194     }
1195 }
1196 
1197 /*
1198  * @implemented
1199  */
1200 BOOLEAN
1201 NTAPI
VideoPortScanRom(IN PVOID HwDeviceExtension,IN PUCHAR RomBase,IN ULONG RomLength,IN PUCHAR String)1202 VideoPortScanRom(
1203     IN PVOID HwDeviceExtension,
1204     IN PUCHAR RomBase,
1205     IN ULONG RomLength,
1206     IN PUCHAR String)
1207 {
1208     SIZE_T StringLength;
1209     BOOLEAN Found;
1210     PUCHAR SearchLocation;
1211 
1212     TRACE_(VIDEOPRT, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase, RomLength, String);
1213 
1214     StringLength = strlen((PCHAR)String);
1215     Found = FALSE;
1216     for (SearchLocation = RomBase;
1217             !Found && SearchLocation < RomBase + RomLength - StringLength;
1218             SearchLocation++)
1219     {
1220         Found = (RtlCompareMemory(SearchLocation, String, StringLength) == StringLength);
1221         if (Found)
1222         {
1223             INFO_(VIDEOPRT, "Match found at %p\n", SearchLocation);
1224         }
1225     }
1226 
1227     return Found;
1228 }
1229 
1230 /*
1231  * @implemented
1232  */
1233 BOOLEAN
1234 NTAPI
VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension,IN VIDEO_SYNCHRONIZE_PRIORITY Priority,IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,OUT PVOID Context)1235 VideoPortSynchronizeExecution(
1236     IN PVOID HwDeviceExtension,
1237     IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
1238     IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
1239     OUT PVOID Context)
1240 {
1241     BOOLEAN Ret;
1242     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1243     KIRQL OldIrql;
1244 
1245     switch (Priority)
1246     {
1247         case VpLowPriority:
1248             Ret = (*SynchronizeRoutine)(Context);
1249             break;
1250 
1251         case VpMediumPriority:
1252             DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1253             if (DeviceExtension->InterruptObject == NULL)
1254                 Ret = (*SynchronizeRoutine)(Context);
1255             else
1256                 Ret = KeSynchronizeExecution(
1257                           DeviceExtension->InterruptObject,
1258                           SynchronizeRoutine,
1259                           Context);
1260             break;
1261 
1262         case VpHighPriority:
1263             OldIrql = KeGetCurrentIrql();
1264             if (OldIrql < SYNCH_LEVEL)
1265                 KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
1266 
1267             Ret = (*SynchronizeRoutine)(Context);
1268 
1269             if (OldIrql < SYNCH_LEVEL)
1270                 KeLowerIrql(OldIrql);
1271             break;
1272 
1273         default:
1274             Ret = FALSE;
1275     }
1276 
1277     return Ret;
1278 }
1279 
1280 /*
1281  * @implemented
1282  */
1283 NTSTATUS NTAPI
IntVideoPortEnumerateChildren(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1284 IntVideoPortEnumerateChildren(
1285     IN PDEVICE_OBJECT DeviceObject,
1286     IN PIRP Irp)
1287 {
1288     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1289     ULONG Status;
1290     VIDEO_CHILD_ENUM_INFO ChildEnumInfo;
1291     BOOLEAN bHaveLastMonitorID = FALSE;
1292     UCHAR LastMonitorID[10];
1293     ULONG Unused;
1294     UINT i;
1295     PDEVICE_OBJECT ChildDeviceObject;
1296     PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
1297 
1298     INFO_(VIDEOPRT, "Starting child device probe\n");
1299     DeviceExtension = DeviceObject->DeviceExtension;
1300     if (DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor == NULL)
1301     {
1302         WARN_(VIDEOPRT, "Miniport's HwGetVideoChildDescriptor is NULL!\n");
1303         return STATUS_SUCCESS;
1304     }
1305 
1306     if (!IsListEmpty(&DeviceExtension->ChildDeviceList))
1307     {
1308         ERR_(VIDEOPRT, "FIXME: Support calling VideoPortEnumerateChildren again!\n");
1309         return STATUS_SUCCESS;
1310     }
1311 
1312     /* Enumerate the children */
1313     for (i = 1; ; i++)
1314     {
1315         Status = IoCreateDevice(DeviceExtension->DriverObject,
1316                                 sizeof(VIDEO_PORT_CHILD_EXTENSION) +
1317                                 DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize,
1318                                 NULL,
1319                                 FILE_DEVICE_CONTROLLER,
1320                                 FILE_DEVICE_SECURE_OPEN,
1321                                 FALSE,
1322                                 &ChildDeviceObject);
1323         if (!NT_SUCCESS(Status))
1324             return Status;
1325 
1326         ChildExtension = ChildDeviceObject->DeviceExtension;
1327 
1328         RtlZeroMemory(ChildExtension,
1329                       sizeof(VIDEO_PORT_CHILD_EXTENSION) +
1330                         DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize);
1331 
1332         ChildExtension->Common.Fdo = FALSE;
1333         ChildExtension->ChildId = i;
1334         ChildExtension->PhysicalDeviceObject = ChildDeviceObject;
1335         ChildExtension->DriverObject = DeviceExtension->DriverObject;
1336 
1337         /* Setup the ChildEnumInfo */
1338         ChildEnumInfo.Size = sizeof(ChildEnumInfo);
1339         ChildEnumInfo.ChildDescriptorSize = sizeof(ChildExtension->ChildDescriptor);
1340         ChildEnumInfo.ACPIHwId = 0;
1341 
1342         if (DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize)
1343             ChildEnumInfo.ChildHwDeviceExtension = VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension);
1344         else
1345             ChildEnumInfo.ChildHwDeviceExtension = NULL;
1346 
1347         ChildEnumInfo.ChildIndex = ChildExtension->ChildId;
1348 
1349         INFO_(VIDEOPRT, "Probing child: %d\n", ChildEnumInfo.ChildIndex);
1350         Status = DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor(
1351                      DeviceExtension->MiniPortDeviceExtension,
1352                      &ChildEnumInfo,
1353                      &ChildExtension->ChildType,
1354                      ChildExtension->ChildDescriptor,
1355                      &ChildExtension->ChildId,
1356                      &Unused);
1357         if (Status == VIDEO_ENUM_MORE_DEVICES)
1358         {
1359             if (ChildExtension->ChildType == Monitor)
1360             {
1361                 // Check if the EDID is valid
1362                 if (ChildExtension->ChildDescriptor[0] == 0x00 &&
1363                         ChildExtension->ChildDescriptor[1] == 0xFF &&
1364                         ChildExtension->ChildDescriptor[2] == 0xFF &&
1365                         ChildExtension->ChildDescriptor[3] == 0xFF &&
1366                         ChildExtension->ChildDescriptor[4] == 0xFF &&
1367                         ChildExtension->ChildDescriptor[5] == 0xFF &&
1368                         ChildExtension->ChildDescriptor[6] == 0xFF &&
1369                         ChildExtension->ChildDescriptor[7] == 0x00)
1370                 {
1371                     if (bHaveLastMonitorID)
1372                     {
1373                         // Compare the previous monitor ID with the current one, break the loop if they are identical
1374                         if (RtlCompareMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID)) == sizeof(LastMonitorID))
1375                         {
1376                             INFO_(VIDEOPRT, "Found identical Monitor ID two times, stopping enumeration\n");
1377                             IoDeleteDevice(ChildDeviceObject);
1378                             break;
1379                         }
1380                     }
1381 
1382                     // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
1383                     RtlCopyMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID));
1384                     bHaveLastMonitorID = TRUE;
1385 
1386                     /* Mark it valid */
1387                     ChildExtension->EdidValid = TRUE;
1388                 }
1389                 else
1390                 {
1391                     /* Mark it invalid */
1392                     ChildExtension->EdidValid = FALSE;
1393                 }
1394             }
1395         }
1396         else if (Status == VIDEO_ENUM_INVALID_DEVICE)
1397         {
1398             WARN_(VIDEOPRT, "Child device %d is invalid!\n", ChildEnumInfo.ChildIndex);
1399             IoDeleteDevice(ChildDeviceObject);
1400             continue;
1401         }
1402         else if (Status == VIDEO_ENUM_NO_MORE_DEVICES)
1403         {
1404             INFO_(VIDEOPRT, "End of child enumeration! (%d children enumerated)\n", i - 1);
1405             IoDeleteDevice(ChildDeviceObject);
1406             break;
1407         }
1408         else
1409         {
1410             WARN_(VIDEOPRT, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status);
1411             IoDeleteDevice(ChildDeviceObject);
1412             break;
1413         }
1414 
1415         if (ChildExtension->ChildType == Monitor)
1416         {
1417             UINT j;
1418             PUCHAR p = ChildExtension->ChildDescriptor;
1419             INFO_(VIDEOPRT, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension->ChildId);
1420             for (j = 0; j < sizeof (ChildExtension->ChildDescriptor); j += 8)
1421             {
1422                 INFO_(VIDEOPRT, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1423                       p[j + 0], p[j + 1], p[j + 2], p[j + 3],
1424                       p[j + 4], p[j + 5], p[j + 6], p[j + 7]);
1425             }
1426         }
1427         else if (ChildExtension->ChildType == Other)
1428         {
1429             INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildExtension->ChildDescriptor);
1430         }
1431         else
1432         {
1433             ERR_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension->ChildType);
1434         }
1435 
1436         /* Clear the init flag */
1437         ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1438 
1439         InsertTailList(&DeviceExtension->ChildDeviceList,
1440                        &ChildExtension->ListEntry);
1441     }
1442 
1443     return STATUS_SUCCESS;
1444 }
1445 
1446 VP_STATUS
1447 NTAPI
VideoPortEnumerateChildren(IN PVOID HwDeviceExtension,IN PVOID Reserved)1448 VideoPortEnumerateChildren(
1449     IN PVOID HwDeviceExtension,
1450     IN PVOID Reserved)
1451 {
1452     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1453 
1454     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1455     ASSERT(DeviceExtension);
1456 
1457     if (DeviceExtension->PhysicalDeviceObject)
1458     {
1459         /* Trigger reenumeration by the PnP manager */
1460         IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, BusRelations);
1461     }
1462 
1463     return NO_ERROR;
1464 }
1465 
1466 /*
1467  * @unimplemented
1468  */
1469 VP_STATUS
1470 NTAPI
VideoPortCreateSecondaryDisplay(IN PVOID HwDeviceExtension,IN OUT PVOID * SecondaryDeviceExtension,IN ULONG Flag)1471 VideoPortCreateSecondaryDisplay(
1472     IN PVOID HwDeviceExtension,
1473     IN OUT PVOID *SecondaryDeviceExtension,
1474     IN ULONG Flag)
1475 {
1476     PDEVICE_OBJECT DeviceObject;
1477     PVIDEO_PORT_DEVICE_EXTENSION FirstDeviceExtension, DeviceExtension;
1478     NTSTATUS Status;
1479 
1480     ASSERT(SecondaryDeviceExtension);
1481 
1482     if (Flag != 0)
1483     {
1484         UNIMPLEMENTED;
1485     }
1486 
1487     FirstDeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1488 
1489     if (FirstDeviceExtension->DisplayNumber != 0)
1490     {
1491         DPRINT1("Calling VideoPortCreateSecondaryDisplay for InstanceId %lu\n",
1492                 FirstDeviceExtension->DisplayNumber);
1493     }
1494 
1495     Status = IntVideoPortCreateAdapterDeviceObject(FirstDeviceExtension->DriverObject,
1496                                                    FirstDeviceExtension->DriverExtension,
1497                                                    FirstDeviceExtension->PhysicalDeviceObject,
1498                                                    FirstDeviceExtension->AdapterNumber,
1499                                                    FirstDeviceExtension->NumberOfSecondaryDisplays + 1,
1500                                                    &DeviceObject);
1501     if (!NT_SUCCESS(Status))
1502     {
1503         DPRINT1("IntVideoPortCreateAdapterDeviceObject() failed with status 0x%08x\n", Status);
1504         return ERROR_DEV_NOT_EXIST;
1505     }
1506 
1507     DeviceExtension = DeviceObject->DeviceExtension;
1508 
1509     /* Increment secondary display count */
1510     FirstDeviceExtension->NumberOfSecondaryDisplays++;
1511 
1512     *SecondaryDeviceExtension = DeviceExtension->MiniPortDeviceExtension;
1513     return NO_ERROR;
1514 }
1515 
1516 /*
1517  * @implemented
1518  */
1519 BOOLEAN
1520 NTAPI
VideoPortQueueDpc(IN PVOID HwDeviceExtension,IN PMINIPORT_DPC_ROUTINE CallbackRoutine,IN PVOID Context)1521 VideoPortQueueDpc(
1522     IN PVOID HwDeviceExtension,
1523     IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
1524     IN PVOID Context)
1525 {
1526     return KeInsertQueueDpc(
1527                &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->DpcObject,
1528                (PVOID)CallbackRoutine,
1529                (PVOID)Context);
1530 }
1531 
1532 /*
1533  * @implemented
1534  */
1535 PVOID
1536 NTAPI
VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject)1537 VideoPortGetAssociatedDeviceExtension(
1538     IN PVOID DeviceObject)
1539 {
1540     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1541 
1542     TRACE_(VIDEOPRT, "VideoPortGetAssociatedDeviceExtension\n");
1543     DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
1544     if (!DeviceExtension)
1545         return NULL;
1546     return DeviceExtension->MiniPortDeviceExtension;
1547 }
1548 
1549 /*
1550  * @implemented
1551  */
1552 VP_STATUS
1553 NTAPI
VideoPortGetVersion(IN PVOID HwDeviceExtension,IN OUT PVPOSVERSIONINFO VpOsVersionInfo)1554 VideoPortGetVersion(
1555     IN PVOID HwDeviceExtension,
1556     IN OUT PVPOSVERSIONINFO VpOsVersionInfo)
1557 {
1558     RTL_OSVERSIONINFOEXW Version;
1559 
1560     Version.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
1561     if (VpOsVersionInfo->Size >= sizeof(VPOSVERSIONINFO))
1562     {
1563 #if 1
1564         if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&Version)))
1565         {
1566             VpOsVersionInfo->MajorVersion = Version.dwMajorVersion;
1567             VpOsVersionInfo->MinorVersion = Version.dwMinorVersion;
1568             VpOsVersionInfo->BuildNumber = Version.dwBuildNumber;
1569             VpOsVersionInfo->ServicePackMajor = Version.wServicePackMajor;
1570             VpOsVersionInfo->ServicePackMinor = Version.wServicePackMinor;
1571             return NO_ERROR;
1572         }
1573         return ERROR_INVALID_PARAMETER;
1574 #else
1575         VpOsVersionInfo->MajorVersion = 5;
1576         VpOsVersionInfo->MinorVersion = 0;
1577         VpOsVersionInfo->BuildNumber = 2195;
1578         VpOsVersionInfo->ServicePackMajor = 4;
1579         VpOsVersionInfo->ServicePackMinor = 0;
1580         return NO_ERROR;
1581 #endif
1582     }
1583 
1584     return ERROR_INVALID_PARAMETER;
1585 }
1586 
1587 /*
1588  * @implemented
1589  */
1590 BOOLEAN
1591 NTAPI
VideoPortCheckForDeviceExistence(IN PVOID HwDeviceExtension,IN USHORT VendorId,IN USHORT DeviceId,IN UCHAR RevisionId,IN USHORT SubVendorId,IN USHORT SubSystemId,IN ULONG Flags)1592 VideoPortCheckForDeviceExistence(
1593     IN PVOID HwDeviceExtension,
1594     IN USHORT VendorId,
1595     IN USHORT DeviceId,
1596     IN UCHAR RevisionId,
1597     IN USHORT SubVendorId,
1598     IN USHORT SubSystemId,
1599     IN ULONG Flags)
1600 {
1601     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1602     PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1603     IO_STATUS_BLOCK IoStatusBlock;
1604     IO_STACK_LOCATION IoStack;
1605     ULONG PciFlags = 0;
1606     NTSTATUS Status;
1607     BOOL DevicePresent;
1608 
1609     TRACE_(VIDEOPRT, "VideoPortCheckForDeviceExistence\n");
1610 
1611     if (Flags & ~(CDE_USE_REVISION | CDE_USE_SUBSYSTEM_IDS))
1612     {
1613         WARN_(VIDEOPRT, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags & ~(CDE_USE_REVISION | CDE_USE_SUBSYSTEM_IDS));
1614         return FALSE;
1615     }
1616 
1617     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1618 
1619     PciDevicePresentInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1620     PciDevicePresentInterface.Version = 1;
1621     IoStack.Parameters.QueryInterface.Size = PciDevicePresentInterface.Size;
1622     IoStack.Parameters.QueryInterface.Version = PciDevicePresentInterface.Version;
1623     IoStack.Parameters.QueryInterface.Interface = (PINTERFACE)&PciDevicePresentInterface;
1624     IoStack.Parameters.QueryInterface.InterfaceType =
1625         &GUID_PCI_DEVICE_PRESENT_INTERFACE;
1626     Status = IopInitiatePnpIrp(DeviceExtension->NextDeviceObject,
1627                                &IoStatusBlock, IRP_MN_QUERY_INTERFACE, &IoStack);
1628     if (!NT_SUCCESS(Status))
1629     {
1630         WARN_(VIDEOPRT, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status);
1631         return FALSE;
1632     }
1633 
1634     if (Flags & CDE_USE_REVISION)
1635         PciFlags |= PCI_USE_REVISION;
1636     if (Flags & CDE_USE_SUBSYSTEM_IDS)
1637         PciFlags |= PCI_USE_SUBSYSTEM_IDS;
1638 
1639     DevicePresent = PciDevicePresentInterface.IsDevicePresent(
1640                         VendorId, DeviceId, RevisionId,
1641                         SubVendorId, SubSystemId, PciFlags);
1642 
1643     PciDevicePresentInterface.InterfaceDereference(PciDevicePresentInterface.Context);
1644 
1645     return DevicePresent;
1646 }
1647 
1648 /*
1649  * @unimplemented
1650  */
1651 VP_STATUS
1652 NTAPI
VideoPortRegisterBugcheckCallback(IN PVOID HwDeviceExtension,IN ULONG BugcheckCode,IN PVIDEO_BUGCHECK_CALLBACK Callback,IN ULONG BugcheckDataSize)1653 VideoPortRegisterBugcheckCallback(
1654     IN PVOID HwDeviceExtension,
1655     IN ULONG BugcheckCode,
1656     IN PVIDEO_BUGCHECK_CALLBACK Callback,
1657     IN ULONG BugcheckDataSize)
1658 {
1659     UNIMPLEMENTED;
1660     return NO_ERROR;
1661 }
1662 
1663 /*
1664  * @implemented
1665  */
1666 LONGLONG
1667 NTAPI
VideoPortQueryPerformanceCounter(IN PVOID HwDeviceExtension,OUT PLONGLONG PerformanceFrequency OPTIONAL)1668 VideoPortQueryPerformanceCounter(
1669     IN PVOID HwDeviceExtension,
1670     OUT PLONGLONG PerformanceFrequency OPTIONAL)
1671 {
1672     LARGE_INTEGER Result;
1673 
1674     TRACE_(VIDEOPRT, "VideoPortQueryPerformanceCounter\n");
1675     Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency);
1676     return Result.QuadPart;
1677 }
1678 
1679 /*
1680  * @implemented
1681  */
1682 VOID
1683 NTAPI
VideoPortAcquireDeviceLock(IN PVOID HwDeviceExtension)1684 VideoPortAcquireDeviceLock(
1685     IN PVOID  HwDeviceExtension)
1686 {
1687     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1688 
1689     TRACE_(VIDEOPRT, "VideoPortAcquireDeviceLock\n");
1690     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1691     KeWaitForMutexObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1692     // ASSERT(Status == STATUS_SUCCESS);
1693 }
1694 
1695 /*
1696  * @implemented
1697  */
1698 VOID
1699 NTAPI
VideoPortReleaseDeviceLock(IN PVOID HwDeviceExtension)1700 VideoPortReleaseDeviceLock(
1701     IN PVOID HwDeviceExtension)
1702 {
1703     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1704 
1705     TRACE_(VIDEOPRT, "VideoPortReleaseDeviceLock\n");
1706     DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1707     KeReleaseMutex(&DeviceExtension->DeviceLock, FALSE);
1708     //ASSERT(Status == STATUS_SUCCESS);
1709 }
1710 
1711 /*
1712  * @unimplemented
1713  */
1714 VOID
1715 NTAPI
VpNotifyEaData(IN PDEVICE_OBJECT DeviceObject,IN PVOID Data)1716 VpNotifyEaData(
1717     IN PDEVICE_OBJECT DeviceObject,
1718     IN PVOID Data)
1719 {
1720     UNIMPLEMENTED;
1721 }
1722 
1723 /*
1724  * @implemented
1725  */
1726 PVOID
1727 NTAPI
VideoPortAllocateContiguousMemory(IN PVOID HwDeviceExtension,IN ULONG NumberOfBytes,IN PHYSICAL_ADDRESS HighestAcceptableAddress)1728 VideoPortAllocateContiguousMemory(
1729     IN PVOID HwDeviceExtension,
1730     IN ULONG NumberOfBytes,
1731     IN PHYSICAL_ADDRESS HighestAcceptableAddress
1732 )
1733 {
1734     return MmAllocateContiguousMemory(NumberOfBytes, HighestAcceptableAddress);
1735 }
1736 
1737 /*
1738  * @implemented
1739  */
1740 BOOLEAN
1741 NTAPI
VideoPortIsNoVesa(VOID)1742 VideoPortIsNoVesa(VOID)
1743 {
1744     return VpNoVesa;
1745 }
1746