https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3cb1dd8ab20c8b29ed497518b5abb8656ac8354e

commit 3cb1dd8ab20c8b29ed497518b5abb8656ac8354e
Author:     Hervé Poussineau <[email protected]>
AuthorDate: Sun Jan 9 10:44:53 2022 +0100
Commit:     hpoussin <[email protected]>
CommitDate: Fri Apr 15 23:09:16 2022 +0200

    [WIN32SS] Rewrite PDEVOBJ_pdmMatchDevMode to LDEVOBJ_bProbeAndCaptureDevmode
    
    - make it return a new allocated PDEVMODEW instead of a pointer into
      existing PGRAPHICS_DEVICE (usefull when available display modes can
      dynamically change: VirtualBox, RDP, ...)
    - update all callers
---
 win32ss/gdi/eng/device.c      | 27 +++++-----------
 win32ss/gdi/eng/ldevobj.c     | 71 +++++++++++++++++++++++++++++++++++++++++++
 win32ss/gdi/eng/ldevobj.h     |  8 +++++
 win32ss/gdi/eng/pdevobj.c     | 68 ++++++++++-------------------------------
 win32ss/gdi/eng/pdevobj.h     |  6 ----
 win32ss/user/ntuser/display.c | 17 ++++++++---
 6 files changed, 114 insertions(+), 83 deletions(-)

diff --git a/win32ss/gdi/eng/device.c b/win32ss/gdi/eng/device.c
index 8ad49ed5fd1..4f2284fa1e6 100644
--- a/win32ss/gdi/eng/device.c
+++ b/win32ss/gdi/eng/device.c
@@ -130,25 +130,18 @@ EngpPopulateDeviceModeList(
     _In_ PDEVMODEW pdmDefault)
 {
     PDEVMODEINFO pdminfo;
-    PDEVMODEW pdm;
+    PDEVMODEW pdm, pdmSelected;
     ULONG i;
-    BOOLEAN bModeMatch = FALSE;
 
     ASSERT(pGraphicsDevice->pdevmodeInfo == NULL);
     ASSERT(pGraphicsDevice->pDevModeList == NULL);
 
-    if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
+    if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdmDefault, 
&pdmSelected, TRUE))
     {
-        ERR("LDEVOBJ_bBuildDevmodeList() failed\n");
+        ERR("LDEVOBJ_bProbeAndCaptureDevmode() failed\n");
         return FALSE;
     }
 
-    TRACE("Looking for mode %lux%lux%lu(%lu Hz)\n",
-        pdmDefault->dmPelsWidth,
-        pdmDefault->dmPelsHeight,
-        pdmDefault->dmBitsPerPel,
-        pdmDefault->dmDisplayFrequency);
-
     /* Loop through all DEVMODEINFOs */
     for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
          pdminfo;
@@ -159,20 +152,14 @@ EngpPopulateDeviceModeList(
         {
             pdm = pGraphicsDevice->pDevModeList[i].pdm;
 
-            /* Compare with the default entry */
-            if (!bModeMatch &&
-                pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel &&
-                pdm->dmPelsWidth == pdmDefault->dmPelsWidth &&
-                pdm->dmPelsHeight == pdmDefault->dmPelsHeight)
+            /* Compare with the selected entry */
+            if (pdm->dmSize == pdmSelected->dmSize &&
+                RtlCompareMemory(pdm, pdmSelected, pdm->dmSize) == pdm->dmSize)
             {
                 pGraphicsDevice->iDefaultMode = i;
                 pGraphicsDevice->iCurrentMode = i;
                 TRACE("Found default entry: %lu '%ls'\n", i, 
pdm->dmDeviceName);
-                if (pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency)
-                {
-                    /* Uh oh, even the display frequency matches. */
-                    bModeMatch = TRUE;
-                }
+                break;
             }
         }
     }
diff --git a/win32ss/gdi/eng/ldevobj.c b/win32ss/gdi/eng/ldevobj.c
index e2079da8178..db46a0dfbb6 100644
--- a/win32ss/gdi/eng/ldevobj.c
+++ b/win32ss/gdi/eng/ldevobj.c
@@ -558,6 +558,77 @@ LDEVOBJ_bBuildDevmodeList(
     return TRUE;
 }
 
+BOOL
+LDEVOBJ_bProbeAndCaptureDevmode(
+    _Inout_ PGRAPHICS_DEVICE pGraphicsDevice,
+    _In_ PDEVMODEW RequestedMode,
+    _Out_ PDEVMODEW *pSelectedMode,
+    _In_ BOOL bSearchClosestMode)
+{
+    PDEVMODEW pdmCurrent, pdm, pdmSelected = NULL;
+    ULONG i;
+    DWORD dwFields;
+
+    if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
+        return FALSE;
+
+    /* Search if requested mode exists */
+    for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+    {
+        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;
+    }
+
+    if (!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);
+        if (!bSearchClosestMode || pGraphicsDevice->cDevModes == 0)
+            return FALSE;
+
+        /* FIXME: need to search the closest mode instead of taking the first 
one */
+        pdmSelected = pGraphicsDevice->pDevModeList[0].pdm;
+        WARN("Replacing it by %dx%dx%d %d Hz\n",
+            pdmSelected->dmFields & DM_PELSWIDTH ? pdmSelected->dmPelsWidth : 
0,
+            pdmSelected->dmFields & DM_PELSHEIGHT ? pdmSelected->dmPelsHeight 
: 0,
+            pdmSelected->dmFields & DM_BITSPERPEL ? pdmSelected->dmBitsPerPel 
: 0,
+            pdmSelected->dmFields & DM_DISPLAYFREQUENCY ? 
pdmSelected->dmDisplayFrequency : 0);
+    }
+
+    /* Allocate memory for output */
+    pdm = ExAllocatePoolZero(PagedPool, pdmSelected->dmSize + 
pdmSelected->dmDriverExtra, GDITAG_DEVMODE);
+    if (!pdm)
+        return FALSE;
+
+    /* Copy selected mode */
+    RtlCopyMemory(pdm, pdmSelected, pdmSelected->dmSize);
+    RtlCopyMemory((PVOID)((ULONG_PTR)pdm + pdm->dmSize),
+                  (PVOID)((ULONG_PTR)pdmSelected + pdmSelected->dmSize),
+                  pdmSelected->dmDriverExtra);
+
+    *pSelectedMode = pdm;
+    return TRUE;
+}
+
 /** Exported functions 
********************************************************/
 
 HANDLE
diff --git a/win32ss/gdi/eng/ldevobj.h b/win32ss/gdi/eng/ldevobj.h
index cac2ec8f5e0..7b2fc2065ee 100644
--- a/win32ss/gdi/eng/ldevobj.h
+++ b/win32ss/gdi/eng/ldevobj.h
@@ -56,6 +56,14 @@ BOOL
 LDEVOBJ_bBuildDevmodeList(
     _Inout_ PGRAPHICS_DEVICE pGraphicsDevice);
 
+/* This function selects the best available mode corresponding to requested 
mode */
+BOOL
+LDEVOBJ_bProbeAndCaptureDevmode(
+    _Inout_ PGRAPHICS_DEVICE pGraphicsDevice,
+    _In_ PDEVMODEW RequestedMode,
+    _Out_ PDEVMODEW *pSelectedMode,
+    _In_ BOOL bSearchClosestMode);
+
 PLDEVOBJ
 NTAPI
 EngGetLDEV(
diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c
index e764dea384c..77b9a9fafc3 100644
--- a/win32ss/gdi/eng/pdevobj.c
+++ b/win32ss/gdi/eng/pdevobj.c
@@ -83,6 +83,8 @@ PDEVOBJ_vDeletePDEV(
     PPDEVOBJ ppdev)
 {
     EngDeleteSemaphore(ppdev->hsemDevLock);
+    if (ppdev->pdmwDev)
+        ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE);
     if (ppdev->pEDDgpl)
         ExFreePoolWithTag(ppdev->pEDDgpl, GDITAG_PDEV);
     ExFreePoolWithTag(ppdev, GDITAG_PDEV);
@@ -266,18 +268,13 @@ PDEVOBJ_vRefreshModeList(
 {
     PGRAPHICS_DEVICE pGraphicsDevice;
     PDEVMODEINFO pdminfo, pdmiNext;
-    DEVMODEW dmDefault;
-    DEVMODEW dmCurrent;
+    PDEVMODEW newDevMode;
 
     /* Lock the PDEV */
     EngAcquireSemaphore(ppdev->hsemDevLock);
 
     pGraphicsDevice = ppdev->pGraphicsDevice;
 
-    /* Remember our default mode */
-    dmDefault = 
*pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm;
-    dmCurrent = *ppdev->pdmwDev;
-
     /* Clear out the modes */
     for (pdminfo = pGraphicsDevice->pdevmodeInfo;
          pdminfo;
@@ -290,57 +287,17 @@ PDEVOBJ_vRefreshModeList(
     ExFreePoolWithTag(pGraphicsDevice->pDevModeList, GDITAG_GDEVICE);
     pGraphicsDevice->pDevModeList = NULL;
 
-    /* Now re-populate the list */
-    if (!EngpPopulateDeviceModeList(pGraphicsDevice, &dmDefault))
+    /* Search an available display mode */
+    if (LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, ppdev->pdmwDev, 
&newDevMode, TRUE))
     {
-        DPRINT1("FIXME: EngpPopulateDeviceModeList failed, we just destroyed a 
perfectly good mode list\n");
+        ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE);
+        ppdev->pdmwDev = newDevMode;
     }
 
-    ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, &dmCurrent);
-
     /* Unlock PDEV */
     EngReleaseSemaphore(ppdev->hsemDevLock);
 }
 
-PDEVMODEW
-NTAPI
-PDEVOBJ_pdmMatchDevMode(
-    PPDEVOBJ ppdev,
-    PDEVMODEW pdm)
-{
-    PGRAPHICS_DEVICE pGraphicsDevice;
-    PDEVMODEW pdmCurrent;
-    ULONG i;
-    DWORD dwFields;
-
-    pGraphicsDevice = ppdev->pGraphicsDevice;
-
-    for (i = 0; i < pGraphicsDevice->cDevModes; i++)
-    {
-        pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
-
-        /* Compare asked DEVMODE fields
-         * Only compare those that are valid in both DEVMODE structs */
-        dwFields = pdmCurrent->dmFields & pdm->dmFields;
-
-        /* For now, we only need those */
-        if ((dwFields & DM_BITSPERPEL) &&
-            (pdmCurrent->dmBitsPerPel != pdm->dmBitsPerPel)) continue;
-        if ((dwFields & DM_PELSWIDTH) &&
-            (pdmCurrent->dmPelsWidth != pdm->dmPelsWidth)) continue;
-        if ((dwFields & DM_PELSHEIGHT) &&
-            (pdmCurrent->dmPelsHeight != pdm->dmPelsHeight)) continue;
-        if ((dwFields & DM_DISPLAYFREQUENCY) &&
-            (pdmCurrent->dmDisplayFrequency != pdm->dmDisplayFrequency)) 
continue;
-
-        /* Match! Return the DEVMODE */
-        return pdmCurrent;
-    }
-
-    /* Nothing found */
-    return NULL;
-}
-
 static
 PPDEVOBJ
 EngpCreatePDEV(
@@ -349,6 +306,7 @@ EngpCreatePDEV(
 {
     PGRAPHICS_DEVICE pGraphicsDevice;
     PPDEVOBJ ppdev;
+    PDEVMODEW newDevMode;
 
     DPRINT("EngpCreatePDEV(%wZ, %p)\n", pustrDeviceName, pdm);
 
@@ -410,7 +368,13 @@ EngpCreatePDEV(
     ppdev->hSpooler = ppdev->pGraphicsDevice->DeviceObject;
 
     // Should we change the ative mode of pGraphicsDevice ?
-    ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
+    if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdm, &newDevMode, 
TRUE))
+    {
+        DPRINT1("LDEVOBJ_bProbeAndCaptureDevmode() failed\n");
+        PDEVOBJ_vRelease(ppdev);
+        return NULL;
+    }
+    ppdev->pdmwDev = newDevMode;
 
     /* FIXME! */
     ppdev->flFlags = PDEV_DISPLAY;
@@ -525,7 +489,7 @@ PDEVOBJ_bSwitchMode(
     DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, 
ppdev->pSurface);
 
     // Lookup the GraphicsDevice + select DEVMODE
-    // pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
+    // pdm = LDEVOBJ_bProbeAndCaptureDevmode(ppdev, pdm);
 
     /* 1. Temporarily disable the current PDEV and reset video to its default 
mode */
     if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE))
diff --git a/win32ss/gdi/eng/pdevobj.h b/win32ss/gdi/eng/pdevobj.h
index 4d22c270aa7..af4973b60f6 100644
--- a/win32ss/gdi/eng/pdevobj.h
+++ b/win32ss/gdi/eng/pdevobj.h
@@ -213,10 +213,4 @@ PDEVOBJ_bSwitchMode(
     PPDEVOBJ ppdev,
     PDEVMODEW pdm);
 
-PDEVMODEW
-NTAPI
-PDEVOBJ_pdmMatchDevMode(
-    PPDEVOBJ ppdev,
-    PDEVMODEW pdm);
-
 #endif /* !__WIN32K_PDEVOBJ_H */
diff --git a/win32ss/user/ntuser/display.c b/win32ss/user/ntuser/display.c
index df00c0e3974..81ed1bdb402 100644
--- a/win32ss/user/ntuser/display.c
+++ b/win32ss/user/ntuser/display.c
@@ -657,6 +657,7 @@ UserChangeDisplaySettings(
     PPDEVOBJ ppdev;
     WORD OrigBC;
     //PDESKTOP pdesk;
+    PDEVMODEW newDevMode = NULL;
 
     /* If no DEVMODE is given, use registry settings */
     if (!pdm)
@@ -707,8 +708,7 @@ UserChangeDisplaySettings(
         dm.dmDisplayFrequency = ppdev->pdmwDev->dmDisplayFrequency;
 
     /* Look for the requested DEVMODE */
-    pdm = PDEVOBJ_pdmMatchDevMode(ppdev, &dm);
-    if (!pdm)
+    if (!LDEVOBJ_bProbeAndCaptureDevmode(ppdev->pGraphicsDevice, &dm, 
&newDevMode, FALSE))
     {
         ERR("Could not find a matching DEVMODE\n");
         lResult = DISP_CHANGE_BADMODE;
@@ -729,7 +729,7 @@ UserChangeDisplaySettings(
         if (NT_SUCCESS(Status))
         {
             /* Store the settings */
-            RegWriteDisplaySettings(hkey, pdm);
+            RegWriteDisplaySettings(hkey, newDevMode);
 
             /* Close the registry key */
             ZwClose(hkey);
@@ -742,7 +742,9 @@ UserChangeDisplaySettings(
     }
 
     /* Check if DEVMODE matches the current mode */
-    if (pdm == ppdev->pdmwDev && !(flags & CDS_RESET))
+    if (newDevMode->dmSize == ppdev->pdmwDev->dmSize &&
+        RtlCompareMemory(newDevMode, ppdev->pdmwDev, newDevMode->dmSize) == 
newDevMode->dmSize &&
+        !(flags & CDS_RESET))
     {
         ERR("DEVMODE matches, nothing to do\n");
         goto leave;
@@ -759,7 +761,7 @@ UserChangeDisplaySettings(
         pvOldCursor = UserSetCursor(NULL, TRUE);
 
         /* Do the mode switch */
-        ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
+        ulResult = PDEVOBJ_bSwitchMode(ppdev, newDevMode);
 
         /* Restore mouse pointer, no hooks called */
         pvOldCursor = UserSetCursor(pvOldCursor, TRUE);
@@ -781,6 +783,8 @@ UserChangeDisplaySettings(
         {
             /* Setting mode succeeded */
             lResult = DISP_CHANGE_SUCCESSFUL;
+            ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE);
+            ppdev->pdmwDev = newDevMode;
 
             UserUpdateFullscreen(flags);
 
@@ -847,6 +851,9 @@ UserChangeDisplaySettings(
     }
 
 leave:
+    if (newDevMode && newDevMode != ppdev->pdmwDev)
+        ExFreePoolWithTag(newDevMode, GDITAG_DEVMODE);
+
     /* Release the PDEV */
     PDEVOBJ_vRelease(ppdev);
 

Reply via email to