Inform HAL about the switch to graphics mode as late as possible. Fixes bug 880.
[reactos.git] / reactos / drivers / video / videoprt / videoprt.c
index 7384b5b..6c1dbac 100644 (file)
  */
 
 #include "videoprt.h"
-#include "internal/ps.h"
 
 /* GLOBAL VARIABLES ***********************************************************/
 
 ULONG CsrssInitialized = FALSE;
-PEPROCESS Csrss = NULL;
+PKPROCESS Csrss = NULL;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath)
@@ -39,34 +38,34 @@ DriverEntry(
    return STATUS_SUCCESS;
 }
 
-PVOID STDCALL
+PVOID NTAPI
 IntVideoPortImageDirectoryEntryToData(
    PVOID BaseAddress,
    ULONG Directory)
 {
    PIMAGE_NT_HEADERS NtHeader;
    ULONG Va;
-  
+
    NtHeader = RtlImageNtHeader(BaseAddress);
    if (NtHeader == NULL)
       return NULL;
-  
+
    if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
       return NULL;
-  
+
    Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
    if (Va == 0)
       return NULL;
-  
-   return (PVOID)(BaseAddress + Va);
+
+   return (PVOID)((ULONG_PTR)BaseAddress + Va);
 }
 
-PVOID STDCALL
+PVOID NTAPI
 IntVideoPortGetProcAddress(
    IN PVOID HwDeviceExtension,
    IN PUCHAR FunctionName)
 {
-   SYSTEM_LOAD_IMAGE GdiDriverInfo;
+   SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
    PVOID BaseAddress;
    PIMAGE_EXPORT_DIRECTORY ExportDir;
    PUSHORT OrdinalPtr;
@@ -77,18 +76,18 @@ IntVideoPortGetProcAddress(
 
    DPRINT("VideoPortGetProcAddress(%s)\n", FunctionName);
 
-   RtlInitUnicodeString(&GdiDriverInfo.ModuleName, L"videoprt");
+   RtlInitUnicodeString(&GdiDriverInfo.DriverName, L"videoprt");
    Status = ZwSetSystemInformation(
-      SystemLoadImage,
-      &GdiDriverInfo, 
-      sizeof(SYSTEM_LOAD_IMAGE));
+      SystemLoadGdiDriverInformation,
+      &GdiDriverInfo,
+      sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
    if (!NT_SUCCESS(Status))
    {
       DPRINT("Couldn't get our own module handle?\n");
       return NULL;
    }
 
-   BaseAddress = GdiDriverInfo.ModuleBase;
+   BaseAddress = GdiDriverInfo.ImageAddress;
 
    /* Get the pointer to the export directory */
    ExportDir = (PIMAGE_EXPORT_DIRECTORY)IntVideoPortImageDirectoryEntryToData(
@@ -104,11 +103,11 @@ IntVideoPortGetProcAddress(
       ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
    for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
    {
-      if (!_strnicmp((PCHAR)FunctionName, (PCHAR)(BaseAddress + *NamePtr),
+      if (!_strnicmp((PCHAR)FunctionName, (PCHAR)((ULONG_PTR)BaseAddress + *NamePtr),
                      strlen((PCHAR)FunctionName)))
       {
-         return (PVOID)((ULONG_PTR)BaseAddress + 
-                        (ULONG_PTR)AddressPtr[*OrdinalPtr]);     
+         return (PVOID)((ULONG_PTR)BaseAddress +
+                        (ULONG_PTR)AddressPtr[*OrdinalPtr]);
       }
    }
 
@@ -117,19 +116,19 @@ IntVideoPortGetProcAddress(
    return NULL;
 }
 
-VOID STDCALL
+VOID NTAPI
 IntVideoPortDeferredRoutine(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2)
 {
-   PVOID HwDeviceExtension = 
+   PVOID HwDeviceExtension =
       &((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
    ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
 }
 
-ULONG STDCALL
+ULONG NTAPI
 IntVideoPortAllocateDeviceNumber(VOID)
 {
    NTSTATUS Status;
@@ -152,35 +151,35 @@ IntVideoPortAllocateDeviceNumber(VOID)
          DeviceNumber++;
          continue;
       }
-      else if (Status == STATUS_NOT_FOUND || Status == STATUS_UNSUCCESSFUL)
+      else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
          break;
       else
+      {
+         DPRINT1("ZwOpenSymbolicLinkObject() returned unexpected status: 0x%08lx\n", Status);
          return 0xFFFFFFFF;
+      }
    }
 
    return DeviceNumber;
 }
 
-NTSTATUS STDCALL
-IntVideoPortFindAdapter(
+NTSTATUS NTAPI
+IntVideoPortCreateAdapterDeviceObject(
    IN PDRIVER_OBJECT DriverObject,
    IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
-   IN PDEVICE_OBJECT PhysicalDeviceObject)
+   IN PDEVICE_OBJECT PhysicalDeviceObject,
+   OUT PDEVICE_OBJECT *DeviceObject  OPTIONAL)
 {
-   WCHAR DeviceVideoBuffer[20];
    PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
    ULONG DeviceNumber;
    ULONG Size;
    NTSTATUS Status;
-   VIDEO_PORT_CONFIG_INFO ConfigInfo;
-   SYSTEM_BASIC_INFORMATION SystemBasicInfo;
-   UCHAR Again = FALSE;
    WCHAR DeviceBuffer[20];
    UNICODE_STRING DeviceName;
-   WCHAR SymlinkBuffer[20];
-   UNICODE_STRING SymlinkName;
-   PDEVICE_OBJECT DeviceObject;
-   BOOL LegacyDetection = FALSE;
+   PDEVICE_OBJECT DeviceObject_;
+
+   if (DeviceObject == NULL)
+      DeviceObject = &DeviceObject_;
 
    /*
     * Find the first free device number that can be used for video device
@@ -195,7 +194,7 @@ IntVideoPortFindAdapter(
    }
 
    /*
-    * Create the device object, we need it even for calling HwFindAdapter :(
+    * Create the device object.
     */
 
    /* Create a unicode device name. */
@@ -211,7 +210,7 @@ IntVideoPortFindAdapter(
       FILE_DEVICE_VIDEO,
       0,
       TRUE,
-      &DeviceObject);
+      DeviceObject);
 
    if (!NT_SUCCESS(Status))
    {
@@ -219,38 +218,36 @@ IntVideoPortFindAdapter(
       return Status;
    }
 
-   /* 
+   /*
     * Set the buffering strategy here. If you change this, remember
     * to change VidDispatchDeviceControl too.
     */
 
-   DeviceObject->Flags |= DO_BUFFERED_IO;
+   (*DeviceObject)->Flags |= DO_BUFFERED_IO;
 
    /*
     * Initialize device extension.
     */
 
-   DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+   DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension);
+   DeviceExtension->DeviceNumber = DeviceNumber;
+   DeviceExtension->DriverObject = DriverObject;
    DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
-   DeviceExtension->FunctionalDeviceObject = DeviceObject;
+   DeviceExtension->FunctionalDeviceObject = *DeviceObject;
    DeviceExtension->DriverExtension = DriverExtension;
 
-   DeviceExtension->RegistryPath.Length = 
-   DeviceExtension->RegistryPath.MaximumLength = 
+   DeviceExtension->RegistryPath.Length =
+   DeviceExtension->RegistryPath.MaximumLength =
       DriverExtension->RegistryPath.Length + (9 * sizeof(WCHAR));
    DeviceExtension->RegistryPath.Length -= sizeof(WCHAR);
    DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(
       NonPagedPool,
       DeviceExtension->RegistryPath.MaximumLength,
-      TAG_VIDEO_PORT);      
+      TAG_VIDEO_PORT);
    swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0",
       DriverExtension->RegistryPath.Buffer);
 
-   if (PhysicalDeviceObject == NULL)
-   {
-      LegacyDetection = TRUE;
-   }
-   else
+   if (PhysicalDeviceObject != NULL)
    {
       /* Get bus number from the upper level bus driver. */
       Size = sizeof(ULONG);
@@ -266,11 +263,10 @@ IntVideoPortFindAdapter(
                 "use legacy detection method, but even that doesn't mean that\n"
                 "it will work.\n");
          DeviceExtension->PhysicalDeviceObject = NULL;
-         LegacyDetection = TRUE;
       }
    }
 
-   DeviceExtension->AdapterInterfaceType = 
+   DeviceExtension->AdapterInterfaceType =
       DriverExtension->InitializationData.AdapterInterfaceType;
 
    if (PhysicalDeviceObject != NULL)
@@ -291,7 +287,7 @@ IntVideoPortFindAdapter(
          DevicePropertyAddress,
          Size,
          &DeviceExtension->SystemIoSlotNumber,
-         &Size);   
+         &Size);
    }
 
    InitializeListHead(&DeviceExtension->AddressMappingListHead);
@@ -300,9 +296,43 @@ IntVideoPortFindAdapter(
       IntVideoPortDeferredRoutine,
       DeviceExtension);
 
+   KeInitializeMutex(&DeviceExtension->DeviceLock, 0);
+
+   /* Attach the device. */
+   if (PhysicalDeviceObject != NULL)
+      DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(
+         *DeviceObject, PhysicalDeviceObject);
+
+   return STATUS_SUCCESS;
+}
+
+
+/* FIXME: we have to detach the device object in IntVideoPortFindAdapter if it fails */
+NTSTATUS NTAPI
+IntVideoPortFindAdapter(
+   IN PDRIVER_OBJECT DriverObject,
+   IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
+   IN PDEVICE_OBJECT DeviceObject)
+{
+   WCHAR DeviceVideoBuffer[20];
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   ULONG Size;
+   NTSTATUS Status;
+   VIDEO_PORT_CONFIG_INFO ConfigInfo;
+   SYSTEM_BASIC_INFORMATION SystemBasicInfo;
+   UCHAR Again = FALSE;
+   WCHAR DeviceBuffer[20];
+   UNICODE_STRING DeviceName;
+   WCHAR SymlinkBuffer[20];
+   UNICODE_STRING SymlinkName;
+   BOOL LegacyDetection = FALSE;
+   ULONG DeviceNumber;
+
+   DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+   DeviceNumber = DeviceExtension->DeviceNumber;
+
    /*
-    * Uff, the DeviceExtension is setup. Now it's needed to setup
-    * a ConfigInfo structure that we will pass to HwFindAdapter.
+    * Setup a ConfigInfo structure that we will pass to HwFindAdapter.
     */
 
    RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
@@ -315,6 +345,8 @@ IntVideoPortFindAdapter(
    ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer;
    ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress;
    ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
+   ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel;
+   ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector;
 
    Size = sizeof(SystemBasicInfo);
    Status = ZwQuerySystemInformation(
@@ -326,8 +358,8 @@ IntVideoPortFindAdapter(
    if (NT_SUCCESS(Status))
    {
       ConfigInfo.SystemMemorySize =
-         SystemBasicInfo.NumberOfPhysicalPages * 
-         SystemBasicInfo.PhysicalPageSize;
+         SystemBasicInfo.NumberOfPhysicalPages *
+         SystemBasicInfo.PageSize;
    }
 
    /*
@@ -337,7 +369,11 @@ IntVideoPortFindAdapter(
     * when we don't have information about what bus we're on. The
     * second case is the standard one for Plug & Play drivers.
     */
-    
+   if (DeviceExtension->PhysicalDeviceObject == NULL)
+   {
+      LegacyDetection = TRUE;
+   }
+
    if (LegacyDetection)
    {
       ULONG BusNumber, MaxBuses;
@@ -349,9 +385,9 @@ IntVideoPortFindAdapter(
          DeviceExtension->SystemIoBusNumber =
          ConfigInfo.SystemIoBusNumber = BusNumber;
 
-         RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension, 
+         RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
                        DriverExtension->InitializationData.HwDeviceExtensionSize);
-   
+
          /* FIXME: Need to figure out what string to pass as param 3. */
          Status = DriverExtension->InitializationData.HwFindAdapter(
             &DeviceExtension->MiniPortDeviceExtension,
@@ -370,7 +406,7 @@ IntVideoPortFindAdapter(
          }
          else
          {
-            DPRINT("HwFindAdapter call failed with error %X\n", Status);
+            DPRINT("HwFindAdapter call failed with error 0x%X\n", Status);
             RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
             IoDeleteDevice(DeviceObject);
 
@@ -391,7 +427,7 @@ IntVideoPortFindAdapter(
 
    if (Status != NO_ERROR)
    {
-      DPRINT("HwFindAdapter call failed with error %X\n", Status);
+      DPRINT("HwFindAdapter call failed with error 0x%X\n", Status);
       RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
       IoDeleteDevice(DeviceObject);
       return Status;
@@ -402,6 +438,10 @@ IntVideoPortFindAdapter(
     * such as creating symlinks or setting up interrupts and timer.
     */
 
+   /* Create a unicode device name. */
+   swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
+   RtlInitUnicodeString(&DeviceName, DeviceBuffer);
+
    /* Create symbolic link "\??\DISPLAYx" */
    swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1);
    RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
@@ -444,45 +484,33 @@ IntVideoPortFindAdapter(
       return STATUS_INSUFFICIENT_RESOURCES;
    }
 
-   if (PhysicalDeviceObject != NULL)
-      DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(
-         DeviceObject, PhysicalDeviceObject);
+   /*
+    * Query children of the device.
+    */
+   VideoPortEnumerateChildren(&DeviceExtension->MiniPortDeviceExtension, NULL);
 
    DPRINT("STATUS_SUCCESS\n");
    return STATUS_SUCCESS;
 }
 
-VOID FASTCALL 
-IntAttachToCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess) 
-{ 
-   *CallingProcess = PsGetCurrentProcess(); 
-   if (*CallingProcess != Csrss) 
-   { 
-      if (PsGetCurrentThread()->ThreadsProcess != *CallingProcess)
-      { 
-         *PrevAttachedProcess = *CallingProcess; 
-         KeDetachProcess(); 
-      } 
-      else 
-      { 
-         *PrevAttachedProcess = NULL; 
-      } 
-      KeAttachProcess(Csrss); 
-   } 
-} 
-VOID FASTCALL 
-IntDetachFromCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess) 
-{ 
-   if (*CallingProcess != Csrss) 
-   { 
-      KeDetachProcess(); 
-      if (NULL != *PrevAttachedProcess) 
-      { 
-         KeAttachProcess(*PrevAttachedProcess); 
-      } 
-   } 
-} 
+VOID FASTCALL
+IntAttachToCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState)
+{
+   *CallingProcess = (PKPROCESS)PsGetCurrentProcess();
+   if (*CallingProcess != Csrss)
+   {
+      KeStackAttachProcess(Csrss, ApcState);
+   }
+}
+
+VOID FASTCALL
+IntDetachFromCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState)
+{
+   if (*CallingProcess != Csrss)
+   {
+      KeUnstackDetachProcess(ApcState);
+   }
+}
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
@@ -490,7 +518,7 @@ IntDetachFromCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess)
  * @implemented
  */
 
-ULONG STDCALL
+ULONG NTAPI
 VideoPortInitialize(
    IN PVOID Context1,
    IN PVOID Context2,
@@ -505,11 +533,27 @@ VideoPortInitialize(
 
    DPRINT("VideoPortInitialize\n");
 
+   /*
+    * As a first thing do parameter checks.
+    */
+
+   if (HwInitializationData->HwInitDataSize > sizeof(VIDEO_HW_INITIALIZATION_DATA))
+   {
+      return STATUS_REVISION_MISMATCH;
+   }
+
+   if (HwInitializationData->HwFindAdapter == NULL ||
+       HwInitializationData->HwInitialize == NULL ||
+       HwInitializationData->HwStartIO == NULL)
+   {
+      return STATUS_INVALID_PARAMETER;
+   }
+
    /*
     * NOTE:
     * The driver extension can be already allocated in case that we were
     * called by legacy driver and failed detecting device. Some miniport
-    * drivers in that case adjust parameters and calls VideoPortInitialize
+    * drivers in that case adjust parameters and call VideoPortInitialize
     * again.
     */
 
@@ -526,6 +570,34 @@ VideoPortInitialize(
       {
          return Status;
       }
+
+      /*
+       * Save the registry path. This should be done only once even if
+       * VideoPortInitialize is called multiple times.
+       */
+
+      if (RegistryPath->Length != 0)
+      {
+         DriverExtension->RegistryPath.Length = 0;
+         DriverExtension->RegistryPath.MaximumLength =
+            RegistryPath->Length + sizeof(UNICODE_NULL);
+         DriverExtension->RegistryPath.Buffer =
+            ExAllocatePoolWithTag(
+               PagedPool,
+               DriverExtension->RegistryPath.MaximumLength,
+               TAG('U', 'S', 'T', 'R'));
+         if (DriverExtension->RegistryPath.Buffer == NULL)
+         {
+            RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
+            return STATUS_INSUFFICIENT_RESOURCES;
+         }
+
+         RtlCopyUnicodeString(&DriverExtension->RegistryPath, RegistryPath);
+      }
+      else
+      {
+         RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
+      }
    }
 
    /*
@@ -535,12 +607,17 @@ VideoPortInitialize(
    RtlCopyMemory(
       &DriverExtension->InitializationData,
       HwInitializationData,
-      min(sizeof(VIDEO_HW_INITIALIZATION_DATA),
-          HwInitializationData->HwInitDataSize));
+      HwInitializationData->HwInitDataSize);
+   if (HwInitializationData->HwInitDataSize <
+       sizeof(VIDEO_HW_INITIALIZATION_DATA))
+   {
+      RtlZeroMemory((PVOID)((ULONG_PTR)&DriverExtension->InitializationData +
+                                       HwInitializationData->HwInitDataSize),
+                    sizeof(VIDEO_HW_INITIALIZATION_DATA) -
+                    HwInitializationData->HwInitDataSize);
+   }
    DriverExtension->HwContext = HwContext;
 
-   RtlCopyMemory(&DriverExtension->RegistryPath, RegistryPath, sizeof(UNICODE_STRING));
-
    switch (HwInitializationData->HwInitDataSize)
    {
       /*
@@ -569,6 +646,7 @@ VideoPortInitialize(
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IntVideoPortDispatchDeviceControl;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = IntVideoPortDispatchWrite;
    DriverObject->DriverUnload = IntVideoPortUnload;
 
    /*
@@ -578,7 +656,13 @@ VideoPortInitialize(
 
    if (LegacyDetection)
    {
-      Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, NULL);
+      PDEVICE_OBJECT DeviceObject;
+      Status = IntVideoPortCreateAdapterDeviceObject(DriverObject, DriverExtension,
+                                                     NULL, &DeviceObject);
+      DPRINT("IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status);
+      if (!NT_SUCCESS(Status))
+         return Status;
+      Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject);
       DPRINT("IntVideoPortFindAdapter returned 0x%x\n", Status);
       return Status;
    }
@@ -615,7 +699,7 @@ VideoPortDebugPrint(
  * @unimplemented
  */
 
-VOID STDCALL
+VOID NTAPI
 VideoPortLogError(
    IN PVOID HwDeviceExtension,
    IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
@@ -634,7 +718,7 @@ VideoPortLogError(
  * @implemented
  */
 
-UCHAR STDCALL
+UCHAR NTAPI
 VideoPortGetCurrentIrql(VOID)
 {
    return KeGetCurrentIrql();
@@ -647,7 +731,7 @@ typedef struct QueryRegistryCallbackContext
    PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 QueryRegistryCallback(
    IN PWSTR ValueName,
    IN ULONG ValueType,
@@ -672,7 +756,7 @@ QueryRegistryCallback(
  * @unimplemented
  */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortGetRegistryParameters(
    IN PVOID HwDeviceExtension,
    IN PWSTR ParameterName,
@@ -720,7 +804,7 @@ VideoPortGetRegistryParameters(
  * @implemented
  */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortSetRegistryParameters(
    IN PVOID HwDeviceExtension,
    IN PWSTR ValueName,
@@ -740,9 +824,9 @@ VideoPortSetRegistryParameters(
 
 /*
  * @implemented
- */ 
+ */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortGetVgaStatus(
    IN PVOID HwDeviceExtension,
    OUT PULONG VgaStatus)
@@ -763,14 +847,14 @@ VideoPortGetVgaStatus(
       }
    }
 
-   return ERROR_INVALID_FUNCTION;    
+   return ERROR_INVALID_FUNCTION;
 }
 
 /*
  * @implemented
  */
 
-PVOID STDCALL
+PVOID NTAPI
 VideoPortGetRomImage(
    IN PVOID HwDeviceExtension,
    IN PVOID Unused1,
@@ -778,8 +862,8 @@ VideoPortGetRomImage(
    IN ULONG Length)
 {
    static PVOID RomImageBuffer = NULL;
-   PEPROCESS CallingProcess; 
-   PEPROCESS PrevAttachedProcess; 
+   PKPROCESS CallingProcess;
+   KAPC_STATE ApcState;
 
    DPRINT("VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
           HwDeviceExtension, Length);
@@ -797,10 +881,10 @@ VideoPortGetRomImage(
    else
    {
       /*
-       * The DDK says we shouldn't use the legacy C0000 method but get the  
-       * rom base address from the corresponding pci or acpi register but  
+       * The DDK says we shouldn't use the legacy C0000 method but get the
+       * rom base address from the corresponding pci or acpi register but
        * lets ignore that and use C0000 anyway. We have already mapped the
-       * bios area into memory so we'll copy from there.                   
+       * bios area into memory so we'll copy from there.
        */
 
       /* Copy the bios. */
@@ -816,9 +900,9 @@ VideoPortGetRomImage(
          return NULL;
       }
 
-      IntAttachToCSRSS(&CallingProcess, &PrevAttachedProcess);
+      IntAttachToCSRSS(&CallingProcess, &ApcState);
       RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length);
-      IntDetachFromCSRSS(&CallingProcess, &PrevAttachedProcess);
+      IntDetachFromCSRSS(&CallingProcess, &ApcState);
 
       return RomImageBuffer;
    }
@@ -828,9 +912,9 @@ VideoPortGetRomImage(
  * @implemented
  */
 
-BOOLEAN STDCALL
+BOOLEAN NTAPI
 VideoPortScanRom(
-   IN PVOID HwDeviceExtension, 
+   IN PVOID HwDeviceExtension,
    IN PUCHAR RomBase,
    IN ULONG RomLength,
    IN PUCHAR String)
@@ -862,7 +946,7 @@ VideoPortScanRom(
  * @implemented
  */
 
-BOOLEAN STDCALL
+BOOLEAN NTAPI
 VideoPortSynchronizeExecution(
    IN PVOID HwDeviceExtension,
    IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
@@ -878,7 +962,7 @@ VideoPortSynchronizeExecution(
       case VpLowPriority:
          Ret = (*SynchronizeRoutine)(Context);
          break;
-   
+
       case VpMediumPriority:
          DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
          if (DeviceExtension->InterruptObject == NULL)
@@ -909,31 +993,90 @@ VideoPortSynchronizeExecution(
 }
 
 /*
- * @unimplemented
- */
-
-BOOLEAN STDCALL
-VideoPortDDCMonitorHelper(
-   PVOID HwDeviceExtension,
-   /*PI2C_FNC_TABLE*/PVOID I2CFunctions,
-   PUCHAR pEdidBuffer,
-   ULONG EdidBufferSize
-   )
-{
-   DPRINT1("VideoPortDDCMonitorHelper() - Unimplemented.\n");
-   return FALSE;
-}
-
-/*
- * @unimplemented
+ * @implemented
  */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortEnumerateChildren(
    IN PVOID HwDeviceExtension,
    IN PVOID Reserved)
 {
-   DPRINT1("VideoPortEnumerateChildren(): Unimplemented.\n");
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   ULONG Status;
+   VIDEO_CHILD_ENUM_INFO ChildEnumInfo;
+   VIDEO_CHILD_TYPE ChildType;
+   UCHAR ChildDescriptor[256];
+   ULONG ChildId;
+   ULONG Unused;
+   INT i;
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   if (DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor == NULL)
+   {
+      DPRINT("Miniport's HwGetVideoChildDescriptor is NULL!\n");
+      return NO_ERROR;
+   }
+
+   /* Setup the ChildEnumInfo */
+   ChildEnumInfo.Size = sizeof (ChildEnumInfo);
+   ChildEnumInfo.ChildDescriptorSize = sizeof (ChildDescriptor);
+   ChildEnumInfo.ACPIHwId = 0;
+   ChildEnumInfo.ChildHwDeviceExtension = NULL; /* FIXME: must be set to
+                                                   ChildHwDeviceExtension... */
+
+   /* Enumerate the children */
+   for (i = 1; ; i++)
+   {
+      ChildEnumInfo.ChildIndex = i;
+      RtlZeroMemory(ChildDescriptor, sizeof(ChildDescriptor));
+      Status = DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor(
+                  HwDeviceExtension,
+                  &ChildEnumInfo,
+                  &ChildType,
+                  ChildDescriptor,
+                  &ChildId,
+                  &Unused);
+      if (Status == VIDEO_ENUM_INVALID_DEVICE)
+      {
+         DPRINT("Child device %d is invalid!\n", ChildEnumInfo.ChildIndex);
+         continue;
+      }
+      else if (Status == VIDEO_ENUM_NO_MORE_DEVICES)
+      {
+         DPRINT("End of child enumeration! (%d children enumerated)\n", i - 1);
+         break;
+      }
+      else if (Status != VIDEO_ENUM_MORE_DEVICES)
+      {
+         DPRINT("HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status);
+         break;
+      }
+
+#ifndef NDEBUG
+      if (ChildType == Monitor)
+      {
+         INT j;
+         PUCHAR p = ChildDescriptor;
+         DPRINT("Monitor device enumerated! (ChildId = 0x%x)\n", ChildId);
+         for (j = 0; j < sizeof (ChildDescriptor); j += 8)
+         {
+            DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+                   p[j+0], p[j+1], p[j+2], p[j+3],
+                   p[j+4], p[j+5], p[j+6], p[j+7]);
+         }
+      }
+      else if (ChildType == Other)
+      {
+         DPRINT("\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildDescriptor);
+      }
+      else
+      {
+         DPRINT("HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildType);
+      }
+#endif /* NDEBUG */
+
+   }
+
    return NO_ERROR;
 }
 
@@ -941,7 +1084,7 @@ VideoPortEnumerateChildren(
  * @unimplemented
  */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortCreateSecondaryDisplay(
    IN PVOID HwDeviceExtension,
    IN OUT PVOID *SecondaryDeviceExtension,
@@ -955,14 +1098,14 @@ VideoPortCreateSecondaryDisplay(
  * @implemented
  */
 
-BOOLEAN STDCALL
+BOOLEAN NTAPI
 VideoPortQueueDpc(
    IN PVOID HwDeviceExtension,
    IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
    IN PVOID Context)
 {
    return KeInsertQueueDpc(
-      &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->DpcObject, 
+      &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->DpcObject,
       (PVOID)CallbackRoutine,
       (PVOID)Context);
 }
@@ -971,7 +1114,7 @@ VideoPortQueueDpc(
  * @unimplemented
  */
 
-PVOID STDCALL
+PVOID NTAPI
 VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject)
 {
    DPRINT1("VideoPortGetAssociatedDeviceExtension: Unimplemented.\n");
@@ -982,7 +1125,7 @@ VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject)
  * @implemented
  */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortGetVersion(
    IN PVOID HwDeviceExtension,
    IN OUT PVPOSVERSIONINFO VpOsVersionInfo)
@@ -1020,7 +1163,7 @@ VideoPortGetVersion(
  * @unimplemented
  */
 
-BOOLEAN STDCALL
+BOOLEAN NTAPI
 VideoPortCheckForDeviceExistence(
    IN PVOID HwDeviceExtension,
    IN USHORT VendorId,
@@ -1038,7 +1181,7 @@ VideoPortCheckForDeviceExistence(
  * @unimplemented
  */
 
-VP_STATUS STDCALL
+VP_STATUS NTAPI
 VideoPortRegisterBugcheckCallback(
    IN PVOID HwDeviceExtension,
    IN ULONG BugcheckCode,
@@ -1053,7 +1196,7 @@ VideoPortRegisterBugcheckCallback(
  * @implemented
  */
 
-LONGLONG STDCALL
+LONGLONG NTAPI
 VideoPortQueryPerformanceCounter(
    IN PVOID HwDeviceExtension,
    OUT PLONGLONG PerformanceFrequency OPTIONAL)
@@ -1064,3 +1207,51 @@ VideoPortQueryPerformanceCounter(
    Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency);
    return Result.QuadPart;
 }
+
+/*
+ * @implemented
+ */
+
+VOID NTAPI
+VideoPortAcquireDeviceLock(
+   IN PVOID  HwDeviceExtension)
+{
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   NTSTATUS Status;
+   (void)Status;
+
+   DPRINT("VideoPortAcquireDeviceLock\n");
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   Status = KeWaitForMutexObject(&DeviceExtension->DeviceLock, Executive,
+                                 KernelMode, FALSE, NULL);
+   ASSERT(Status == STATUS_SUCCESS);
+}
+
+/*
+ * @implemented
+ */
+
+VOID NTAPI
+VideoPortReleaseDeviceLock(
+   IN PVOID  HwDeviceExtension)
+{
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   LONG Status;
+   (void)Status;
+
+   DPRINT("VideoPortReleaseDeviceLock\n");
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   Status = KeReleaseMutex(&DeviceExtension->DeviceLock, FALSE);
+   ASSERT(Status == 0);
+}
+
+/*
+ * @unimplemented
+ */
+
+VOID NTAPI
+VpNotifyEaData(
+   IN PDEVICE_OBJECT DeviceObject,
+   IN PVOID Data)
+{
+}