[WIN32SS] Change LDEVOBJ_bProbeAndCaptureDevmode to load missing settings from registry CORE-18189
authorHervé Poussineau <hpoussin@reactos.org>
Sun, 22 May 2022 12:23:26 +0000 (14:23 +0200)
committerHervé Poussineau <hpoussin@reactos.org>
Sun, 22 May 2022 15:32:44 +0000 (17:32 +0200)
- use EngpGetDisplayDriverParameters to get display settings from registry
- update searched display settings with the provided ones (+ add missing SEH2)
- then, search exact mode

User can now change only one display setting, without specifying other ones.

win32ss/gdi/eng/ldevobj.c
win32ss/gdi/eng/mdevobj.c

index 4a929ec..bd6d282 100644 (file)
@@ -710,56 +710,113 @@ LDEVOBJ_bProbeAndCaptureDevmode(
     _Out_ PDEVMODEW *pSelectedMode,
     _In_ BOOL bSearchClosestMode)
 {
+    DEVMODEW dmSearch;
     PDEVMODEW pdmCurrent, pdm, pdmSelected = NULL;
     ULONG i;
-    DWORD dwFields;
+    ULONG ulVirtualWidth = 0, ulVirtualHeight = 0;
+    BOOL bResult = TRUE;
+    NTSTATUS Status;
 
     if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
         return FALSE;
 
-    if (bSearchClosestMode)
+    /* At first, load information from registry */
+    RtlZeroMemory(&dmSearch, sizeof(dmSearch));
+    Status = EngpGetDisplayDriverParameters(pGraphicsDevice, &dmSearch, NULL);
+    if (!NT_SUCCESS(Status))
     {
-        /* Search the closest mode */
-        if (!LDEVOBJ_bGetClosestMode(pGraphicsDevice, RequestedMode, &pdmSelected))
-            return FALSE;
-        ASSERT(pdmSelected);
+        ERR("EngpGetDisplayDriverParameters() failed with status 0x%08x\n", Status);
+        return FALSE;
     }
-    else
+
+    /* Override values with the new ones provided */
+
+    _SEH2_TRY
     {
-        /* Search if requested mode exists */
-        for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+        bSearchClosestMode |= RequestedMode->dmFields == 0;
+
+        /* Copy standard fields (if provided) */
+        if (RequestedMode->dmFields & DM_BITSPERPEL && RequestedMode->dmBitsPerPel != 0)
+            dmSearch.dmBitsPerPel = RequestedMode->dmBitsPerPel;
+        if (RequestedMode->dmFields & DM_PELSWIDTH && RequestedMode->dmPelsWidth != 0)
+            dmSearch.dmPelsWidth = RequestedMode->dmPelsWidth;
+        if (RequestedMode->dmFields & DM_PELSHEIGHT && RequestedMode->dmPelsHeight != 0)
+            dmSearch.dmPelsHeight = RequestedMode->dmPelsHeight;
+        if (RequestedMode->dmFields & DM_DISPLAYFREQUENCY && RequestedMode->dmDisplayFrequency != 0)
+            dmSearch.dmDisplayFrequency = RequestedMode->dmDisplayFrequency;
+
+        if ((RequestedMode->dmFields & (DM_PANNINGWIDTH | DM_PANNINGHEIGHT)) == (DM_PANNINGWIDTH | DM_PANNINGHEIGHT) &&
+            RequestedMode->dmPanningWidth != 0 && RequestedMode->dmPanningHeight != 0 &&
+            RequestedMode->dmPanningWidth < dmSearch.dmPelsWidth &&
+            RequestedMode->dmPanningHeight < dmSearch.dmPelsHeight)
         {
-            pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
-
-            /* Compare asked DEVMODE fields
-             * Only compare those that are valid in both DEVMODE structs */
-            dwFields = pdmCurrent->dmFields & RequestedMode->dmFields;
-
-            /* For now, we only need those */
-            if ((dwFields & DM_BITSPERPEL) &&
-                (pdmCurrent->dmBitsPerPel != RequestedMode->dmBitsPerPel)) continue;
-            if ((dwFields & DM_PELSWIDTH) &&
-                (pdmCurrent->dmPelsWidth != RequestedMode->dmPelsWidth)) continue;
-            if ((dwFields & DM_PELSHEIGHT) &&
-                (pdmCurrent->dmPelsHeight != RequestedMode->dmPelsHeight)) continue;
-            if ((dwFields & DM_DISPLAYFREQUENCY) &&
-                (pdmCurrent->dmDisplayFrequency != RequestedMode->dmDisplayFrequency)) continue;
-
-            pdmSelected = pdmCurrent;
-            break;
+            /* Get new panning values */
+            ulVirtualWidth = RequestedMode->dmPelsWidth;
+            ulVirtualHeight = RequestedMode->dmPelsHeight;
+            dmSearch.dmPelsWidth = RequestedMode->dmPanningWidth;
+            dmSearch.dmPelsHeight = RequestedMode->dmPanningHeight;
+        }
+        else if (dmSearch.dmPanningWidth != 0 && dmSearch.dmPanningHeight != 0 &&
+                 dmSearch.dmPanningWidth < dmSearch.dmPelsWidth &&
+                 dmSearch.dmPanningHeight < dmSearch.dmPelsHeight)
+        {
+            /* Keep existing panning values */
+            ulVirtualWidth = dmSearch.dmPelsWidth;
+            ulVirtualHeight = dmSearch.dmPelsHeight;
+            dmSearch.dmPelsWidth = dmSearch.dmPanningWidth;
+            dmSearch.dmPelsHeight = dmSearch.dmPanningHeight;
         }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        bResult = FALSE;
+    }
+    _SEH2_END;
+
+    if (!bResult)
+        return FALSE;
 
-        if (!pdmSelected)
+    if (bSearchClosestMode)
+    {
+        if (LDEVOBJ_bGetClosestMode(pGraphicsDevice, &dmSearch, &pdmSelected))
         {
-            WARN("Requested mode not found (%dx%dx%d %d Hz)\n",
-                RequestedMode->dmFields & DM_PELSWIDTH ? RequestedMode->dmPelsWidth : 0,
-                RequestedMode->dmFields & DM_PELSHEIGHT ? RequestedMode->dmPelsHeight : 0,
-                RequestedMode->dmFields & DM_BITSPERPEL ? RequestedMode->dmBitsPerPel : 0,
-                RequestedMode->dmFields & DM_DISPLAYFREQUENCY ? RequestedMode->dmDisplayFrequency : 0);
-            return FALSE;
+            /* Ok, found a closest mode. Update search */
+            dmSearch.dmBitsPerPel = pdmSelected->dmBitsPerPel;
+            dmSearch.dmPelsWidth = pdmSelected->dmPelsWidth;
+            dmSearch.dmPelsHeight = pdmSelected->dmPelsHeight;
+            dmSearch.dmDisplayFrequency = pdmSelected->dmDisplayFrequency;
         }
     }
 
+    /* Now, search the exact mode to return to caller */
+    for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+    {
+        pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
+
+        /* For now, we only need those */
+        if (pdmCurrent->dmBitsPerPel != dmSearch.dmBitsPerPel)
+            continue;
+        if (pdmCurrent->dmPelsWidth != dmSearch.dmPelsWidth)
+            continue;
+        if (pdmCurrent->dmPelsHeight != dmSearch.dmPelsHeight)
+            continue;
+        if (pdmCurrent->dmDisplayFrequency != dmSearch.dmDisplayFrequency)
+            continue;
+
+        pdmSelected = pdmCurrent;
+        break;
+    }
+
+    if (!pdmSelected)
+    {
+        ERR("Requested mode not found (%dx%dx%d %d Hz)\n",
+            dmSearch.dmPelsWidth,
+            dmSearch.dmPelsHeight,
+            dmSearch.dmBitsPerPel,
+            dmSearch.dmDisplayFrequency);
+        return FALSE;
+    }
+
     /* Allocate memory for output */
     pdm = ExAllocatePoolZero(PagedPool, pdmSelected->dmSize + pdmSelected->dmDriverExtra, GDITAG_DEVMODE);
     if (!pdm)
@@ -771,6 +828,18 @@ LDEVOBJ_bProbeAndCaptureDevmode(
                   (PVOID)((ULONG_PTR)pdmSelected + pdmSelected->dmSize),
                   pdmSelected->dmDriverExtra);
 
+    /* Add back panning */
+    if (ulVirtualWidth != 0 && ulVirtualHeight != 0 &&
+        pdm->dmPelsWidth < ulVirtualWidth &&
+        pdm->dmPelsHeight < ulVirtualHeight)
+    {
+        pdm->dmFields |= DM_PANNINGWIDTH | DM_PANNINGHEIGHT;
+        pdm->dmPanningWidth = pdm->dmPelsWidth;
+        pdm->dmPanningHeight = pdm->dmPelsHeight;
+        pdm->dmPelsWidth = ulVirtualWidth;
+        pdm->dmPelsHeight = ulVirtualHeight;
+    }
+
     *pSelectedMode = pdm;
     return TRUE;
 }
index 2b6ce26..620e545 100644 (file)
@@ -99,62 +99,10 @@ MDEVOBJ_Create(
 
         if (!pdm)
         {
-            /* No settings requested. Read default settings from registry to dmDefault */
-            HKEY hKey;
-            WCHAR DeviceKey[128];
-            ULONG cbSize;
-            NTSTATUS Status;
-            DWORD dwValue;
-
+            /* No settings requested. Provide nothing and LDEVOBJ_bProbeAndCaptureDevmode
+             * will read default settings from registry */
             RtlZeroMemory(&dmDefault, sizeof(dmDefault));
             dmDefault.dmSize = sizeof(dmDefault);
-
-            Status = RegOpenKey(L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO", &hKey);
-            if (!NT_SUCCESS(Status))
-            {
-                /* Ignore this device and continue */
-                ERR("Failed to open VIDEO key: status 0x%08x\n", Status);
-                continue;
-            }
-            cbSize = sizeof(DeviceKey);
-            Status = RegQueryValue(hKey,
-                                   pGraphicsDevice->szNtDeviceName,
-                                   REG_SZ,
-                                   DeviceKey,
-                                   &cbSize);
-            ZwClose(hKey);
-            if (!NT_SUCCESS(Status))
-            {
-                /* Ignore this device and continue */
-                ERR("Failed to open get device key for '%S': status 0x%08x\n", pGraphicsDevice->szNtDeviceName, Status);
-                continue;
-            }
-            Status = RegOpenKey(DeviceKey, &hKey);
-            if (!NT_SUCCESS(Status))
-            {
-                /* Ignore this device and continue */
-                ERR("Failed to open open device key '%S' for '%S': status 0x%08x\n", DeviceKey, pGraphicsDevice->szNtDeviceName, Status);
-                continue;
-            }
-#define READ(field, str, flag) \
-    if (RegReadDWORD(hKey, L##str, &dwValue)) \
-    { \
-        dmDefault.field = dwValue; \
-        dmDefault.dmFields |= flag; \
-    }
-            READ(dmBitsPerPel, "DefaultSettings.BitsPerPel", DM_BITSPERPEL);
-            READ(dmPelsWidth, "DefaultSettings.XResolution", DM_PELSWIDTH);
-            READ(dmPelsHeight, "DefaultSettings.YResolution", DM_PELSHEIGHT);
-            READ(dmDisplayFlags, "DefaultSettings.Flags", DM_DISPLAYFLAGS);
-            READ(dmDisplayFrequency, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY);
-            READ(dmPanningWidth, "DefaultSettings.XPanning", DM_PANNINGWIDTH);
-            READ(dmPanningHeight, "DefaultSettings.YPanning", DM_PANNINGHEIGHT);
-            READ(dmDisplayOrientation, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION);
-            READ(dmDisplayFixedOutput, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT);
-            READ(dmPosition.x, "Attach.RelativeX", DM_POSITION);
-            READ(dmPosition.y, "Attach.RelativeY", DM_POSITION);
-            RegReadDWORD(hKey, L"Acceleration.Level", &dwAccelerationLevel);
-            ZwClose(hKey);
         }
 
         /* Get or create a PDEV for these settings */