From 976b50cf4da34e6046bbe0bdcc8fa60f8e7d7b8b Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 27 Jul 2016 10:34:01 +0000 Subject: [PATCH] [0.4.2] * Apply the patch that allows us to dynamically change the resolution by resizing in VirtualBox. CORE-6742 svn path=/branches/ros-branch-0_4_2/; revision=72012 --- reactos/win32ss/gdi/eng/device.c | 242 ++++++++++++++------------ reactos/win32ss/gdi/eng/device.h | 10 ++ reactos/win32ss/gdi/eng/pdevobj.c | 39 +++++ reactos/win32ss/user/ntuser/display.c | 14 +- 4 files changed, 193 insertions(+), 112 deletions(-) diff --git a/reactos/win32ss/gdi/eng/device.c b/reactos/win32ss/gdi/eng/device.c index e1d6363e5b0..0123a2713c9 100644 --- a/reactos/win32ss/gdi/eng/device.c +++ b/reactos/win32ss/gdi/eng/device.c @@ -30,6 +30,132 @@ InitDeviceImpl(VOID) return STATUS_SUCCESS; } +BOOLEAN +EngpPopulateDeviceModeList( + _Inout_ PGRAPHICS_DEVICE pGraphicsDevice, + _In_ PDEVMODEW pdmDefault) +{ + PWSTR pwsz; + PLDEVOBJ pldev; + PDEVMODEINFO pdminfo; + PDEVMODEW pdm, pdmEnd; + ULONG i, cModes = 0; + BOOLEAN bModeMatch = FALSE; + + ASSERT(pGraphicsDevice->pdevmodeInfo == NULL); + ASSERT(pGraphicsDevice->pDevModeList == NULL); + + pwsz = pGraphicsDevice->pDiplayDrivers; + + /* Loop through the driver names + * This is a REG_MULTI_SZ string */ + for (; *pwsz; pwsz += wcslen(pwsz) + 1) + { + TRACE("trying driver: %ls\n", pwsz); + /* Try to load the display driver */ + pldev = EngLoadImageEx(pwsz, LDEV_DEVICE_DISPLAY); + if (!pldev) + { + ERR("Could not load driver: '%ls'\n", pwsz); + continue; + } + + /* Get the mode list from the driver */ + pdminfo = LDEVOBJ_pdmiGetModes(pldev, pGraphicsDevice->DeviceObject); + if (!pdminfo) + { + ERR("Could not get mode list for '%ls'\n", pwsz); + continue; + } + + /* Attach the mode info to the device */ + pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo; + pGraphicsDevice->pdevmodeInfo = pdminfo; + + /* Loop all DEVMODEs */ + pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode); + for (pdm = pdminfo->adevmode; + (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); + pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) + { + /* Count this DEVMODE */ + cModes++; + + /* Some drivers like the VBox driver don't fill the dmDeviceName + with the name of the display driver. So fix that here. */ + wcsncpy(pdm->dmDeviceName, pwsz, CCHDEVICENAME); + pdm->dmDeviceName[CCHDEVICENAME - 1] = 0; + } + + // FIXME: release the driver again until it's used? + } + + if (!pGraphicsDevice->pdevmodeInfo || cModes == 0) + { + ERR("No devmodes\n"); + return FALSE; + } + + /* Allocate an index buffer */ + pGraphicsDevice->cDevModes = cModes; + pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool, + cModes * sizeof(DEVMODEENTRY), + GDITAG_GDEVICE); + if (!pGraphicsDevice->pDevModeList) + { + ERR("No devmode list\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; + pdminfo = pdminfo->pdmiNext) + { + /* Calculate End of the DEVMODEs */ + pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode); + + /* Loop through the DEVMODEs */ + for (pdm = pdminfo->adevmode; + (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); + pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) + { + TRACE(" %S has mode %lux%lux%lu(%lu Hz)\n", + pdm->dmDeviceName, + pdm->dmPelsWidth, + pdm->dmPelsHeight, + pdm->dmBitsPerPel, + pdm->dmDisplayFrequency); + /* Compare with the default entry */ + if (!bModeMatch && + pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel && + pdm->dmPelsWidth == pdmDefault->dmPelsWidth && + pdm->dmPelsHeight == pdmDefault->dmPelsHeight) + { + 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; + } + } + + /* Initialize the entry */ + pGraphicsDevice->pDevModeList[i].dwFlags = 0; + pGraphicsDevice->pDevModeList[i].pdm = pdm; + i++; + } + } + return TRUE; +} PGRAPHICS_DEVICE NTAPI @@ -44,13 +170,9 @@ EngpRegisterGraphicsDevice( PFILE_OBJECT pFileObject; NTSTATUS Status; PWSTR pwsz; - ULONG i, cj, cModes = 0; + ULONG cj; SIZE_T cjWritten; BOOL bEnable = TRUE; - PDEVMODEINFO pdminfo; - PDEVMODEW pdm, pdmEnd; - PLDEVOBJ pldev; - BOOLEAN bModeMatch = FALSE; TRACE("EngpRegisterGraphicsDevice(%wZ)\n", pustrDeviceName); @@ -124,116 +246,14 @@ EngpRegisterGraphicsDevice( // FIXME: initialize state flags pGraphicsDevice->StateFlags = 0; - /* Loop through the driver names - * This is a REG_MULTI_SZ string */ - for (; *pwsz; pwsz += wcslen(pwsz) + 1) + /* Create the mode list */ + pGraphicsDevice->pDevModeList = NULL; + if (!EngpPopulateDeviceModeList(pGraphicsDevice, pdmDefault)) { - TRACE("trying driver: %ls\n", pwsz); - /* Try to load the display driver */ - pldev = EngLoadImageEx(pwsz, LDEV_DEVICE_DISPLAY); - if (!pldev) - { - ERR("Could not load driver: '%ls'\n", pwsz); - continue; - } - - /* Get the mode list from the driver */ - pdminfo = LDEVOBJ_pdmiGetModes(pldev, pDeviceObject); - if (!pdminfo) - { - ERR("Could not get mode list for '%ls'\n", pwsz); - continue; - } - - /* Attach the mode info to the device */ - pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo; - pGraphicsDevice->pdevmodeInfo = pdminfo; - - /* Loop all DEVMODEs */ - pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode); - for (pdm = pdminfo->adevmode; - (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); - pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) - { - /* Count this DEVMODE */ - cModes++; - - /* Some drivers like the VBox driver don't fill the dmDeviceName - with the name of the display driver. So fix that here. */ - wcsncpy(pdm->dmDeviceName, pwsz, CCHDEVICENAME); - pdm->dmDeviceName[CCHDEVICENAME - 1] = 0; - } - - // FIXME: release the driver again until it's used? - } - - if (!pGraphicsDevice->pdevmodeInfo || cModes == 0) - { - ERR("No devmodes\n"); ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } - /* Allocate an index buffer */ - pGraphicsDevice->cDevModes = cModes; - pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool, - cModes * sizeof(DEVMODEENTRY), - GDITAG_GDEVICE); - if (!pGraphicsDevice->pDevModeList) - { - ERR("No devmode list\n"); - ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); - return NULL; - } - - 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; - pdminfo = pdminfo->pdmiNext) - { - /* Calculate End of the DEVMODEs */ - pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode); - - /* Loop through the DEVMODEs */ - for (pdm = pdminfo->adevmode; - (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); - pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) - { - TRACE(" %S has mode %lux%lux%lu(%lu Hz)\n", - pdm->dmDeviceName, - pdm->dmPelsWidth, - pdm->dmPelsHeight, - pdm->dmBitsPerPel, - pdm->dmDisplayFrequency); - /* Compare with the default entry */ - if (!bModeMatch && - pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel && - pdm->dmPelsWidth == pdmDefault->dmPelsWidth && - pdm->dmPelsHeight == pdmDefault->dmPelsHeight) - { - 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; - } - } - - /* Initialize the entry */ - pGraphicsDevice->pDevModeList[i].dwFlags = 0; - pGraphicsDevice->pDevModeList[i].pdm = pdm; - i++; - } - } - /* Lock loader */ EngAcquireSemaphore(ghsemGraphicsDeviceList); @@ -250,7 +270,7 @@ EngpRegisterGraphicsDevice( /* Unlock loader */ EngReleaseSemaphore(ghsemGraphicsDeviceList); - TRACE("Prepared %lu modes for %ls\n", cModes, pGraphicsDevice->pwszDescription); + TRACE("Prepared %lu modes for %ls\n", pGraphicsDevice->cDevModes, pGraphicsDevice->pwszDescription); return pGraphicsDevice; } diff --git a/reactos/win32ss/gdi/eng/device.h b/reactos/win32ss/gdi/eng/device.h index e194456544f..c035441c995 100644 --- a/reactos/win32ss/gdi/eng/device.h +++ b/reactos/win32ss/gdi/eng/device.h @@ -3,6 +3,11 @@ #define TAG_GDEV 'gdev' +VOID +NTAPI +PDEVOBJ_vRefreshModeList( + PPDEVOBJ ppdev); + extern PGRAPHICS_DEVICE gpPrimaryGraphicsDevice; extern PGRAPHICS_DEVICE gpVgaGraphicsDevice; @@ -29,6 +34,11 @@ EngpRegisterGraphicsDevice( _In_ PUNICODE_STRING pustrDescription, _In_ PDEVMODEW pdmDefault); +BOOLEAN +EngpPopulateDeviceModeList( + _Inout_ PGRAPHICS_DEVICE pGraphicsDevice, + _In_ PDEVMODEW pdmDefault); + INIT_FUNCTION NTSTATUS NTAPI diff --git a/reactos/win32ss/gdi/eng/pdevobj.c b/reactos/win32ss/gdi/eng/pdevobj.c index cc724715f50..ce31df3d7a4 100644 --- a/reactos/win32ss/gdi/eng/pdevobj.c +++ b/reactos/win32ss/gdi/eng/pdevobj.c @@ -251,6 +251,45 @@ PDEVOBJ_pSurface( return ppdev->pSurface; } +VOID +NTAPI +PDEVOBJ_vRefreshModeList( + PPDEVOBJ ppdev) +{ + PGRAPHICS_DEVICE pGraphicsDevice; + PDEVMODEINFO pdminfo, pdmiNext; + DEVMODEW dmDefault; + + /* Lock the PDEV */ + EngAcquireSemaphore(ppdev->hsemDevLock); + + pGraphicsDevice = ppdev->pGraphicsDevice; + + /* Remember our default mode */ + dmDefault = *pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm; + + /* Clear out the modes */ + for (pdminfo = pGraphicsDevice->pdevmodeInfo; + pdminfo; + pdminfo = pdmiNext) + { + pdmiNext = pdminfo->pdmiNext; + ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE); + } + pGraphicsDevice->pdevmodeInfo = NULL; + ExFreePoolWithTag(pGraphicsDevice->pDevModeList, GDITAG_GDEVICE); + pGraphicsDevice->pDevModeList = NULL; + + /* Now re-populate the list */ + if (!EngpPopulateDeviceModeList(pGraphicsDevice, &dmDefault)) + { + DPRINT1("FIXME: EngpPopulateDeviceModeList failed, we just destroyed a perfectly good mode list\n"); + } + + /* Unlock PDEV */ + EngReleaseSemaphore(ppdev->hsemDevLock); +} + PDEVMODEW NTAPI PDEVOBJ_pdmMatchDevMode( diff --git a/reactos/win32ss/user/ntuser/display.c b/reactos/win32ss/user/ntuser/display.c index 5c44f2a1205..c7bc9566f8c 100644 --- a/reactos/win32ss/user/ntuser/display.c +++ b/reactos/win32ss/user/ntuser/display.c @@ -463,22 +463,34 @@ UserEnumDisplaySettings( PGRAPHICS_DEVICE pGraphicsDevice; PDEVMODEENTRY pdmentry; ULONG i, iFoundMode; + PPDEVOBJ ppdev; TRACE("Enter UserEnumDisplaySettings('%wZ', %lu)\n", pustrDevice, iModeNum); /* Ask GDI for the GRAPHICS_DEVICE */ pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, 0, 0); + ppdev = EngpGetPDEV(pustrDevice); - if (!pGraphicsDevice) + if (!pGraphicsDevice || !ppdev) { /* No device found */ ERR("No device found!\n"); return STATUS_UNSUCCESSFUL; } + /* let's politely ask the driver for an updated mode list, + just in case there's something new in there (vbox) */ + + PDEVOBJ_vRefreshModeList(ppdev); + PDEVOBJ_vRelease(ppdev); + + /* FIXME: maybe only refresh when iModeNum is bigger than cDevModes? */ if (iModeNum >= pGraphicsDevice->cDevModes) + { + ERR("STATUS_NO_MORE_ENTRIES!\n"); return STATUS_NO_MORE_ENTRIES; + } iFoundMode = 0; for (i = 0; i < pGraphicsDevice->cDevModes; i++)