Index: win32ss/gdi/eng/device.h =================================================================== --- win32ss/gdi/eng/device.h (revision 65544) +++ win32ss/gdi/eng/device.h (working copy) @@ -44,5 +44,10 @@ PPDEVOBJ ppdev, PDEVMODEW pdm); +VOID +NTAPI +PDEVOBJ_vRefreshModeList( + PPDEVOBJ ppdev); + extern PGRAPHICS_DEVICE gpPrimaryGraphicsDevice; extern PGRAPHICS_DEVICE gpVgaGraphicsDevice; Index: win32ss/gdi/eng/pdevobj.c =================================================================== --- win32ss/gdi/eng/pdevobj.c (revision 65544) +++ win32ss/gdi/eng/pdevobj.c (working copy) @@ -7,9 +7,11 @@ */ #include -#define NDEBUG +//#define NDEBUG #include +DBG_DEFAULT_CHANNEL(UserDisplay); + PPDEVOBJ gppdevPrimary = NULL; static PPDEVOBJ gppdevList = NULL; @@ -225,10 +227,111 @@ /* Increment reference count */ GDIOBJ_vReferenceObjectByPointer(&ppdev->pSurface->BaseObject); - DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface); + TRACE("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface); return ppdev->pSurface; } +VOID +NTAPI +PDEVOBJ_vRefreshModeList( + PPDEVOBJ ppdev) +{ + PGRAPHICS_DEVICE pGraphicsDevice; + PDEVMODEENTRY pTmpDevModeList, pOldDevModeList; + PDEVMODEINFO pdminfo; + PDEVMODEW pdm, pdmEnd; + UINT cModes = 0; + UINT j = 0; + + /* Lock the PDEV */ + EngAcquireSemaphore(ppdev->hsemDevLock); + + pGraphicsDevice = ppdev->pGraphicsDevice; + + TRACE("Enter PDEVOBJ_vRefreshModeList('%ws'/'%ws')\n", + pGraphicsDevice->szNtDeviceName, + pGraphicsDevice->szWinDeviceName); + + pdminfo = LDEVOBJ_pdmiGetModes(ppdev->pldev, pGraphicsDevice->DeviceObject); + + if (!pdminfo || pdminfo->cbdevmode == 0) + { + ERR("Could not get an updated mode list for '%ls'\n", pGraphicsDevice->szWinDeviceName); + } + else + { + TRACE("Bingo! We've just got some (%lu) new modes for '%ls'.\n", pdminfo->cbdevmode/sizeof(DEVMODEW), pGraphicsDevice->szWinDeviceName); + + /* 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)) + { + TRACE("mode %lu -- %lux%lux%lu (%lu hz)\n", cModes, pdminfo->adevmode[cModes].dmPelsWidth, + pdminfo->adevmode[cModes].dmPelsHeight, + pdminfo->adevmode[cModes].dmBitsPerPel, + pdminfo->adevmode[cModes].dmDisplayFrequency); + + /* Some drivers like the VBox driver don't fill the dmDeviceName + with the name of the display driver. So fix that here. */ + wcsncpy(pdminfo->adevmode[cModes].dmDeviceName, pGraphicsDevice->pDiplayDrivers, CCHDEVICENAME); + pdminfo->adevmode[cModes].dmDeviceName[CCHDEVICENAME - 1] = 0; + + /* Count this DEVMODE */ + cModes++; + } + + if (cModes == 0) + { + ERR("No valid devmodes returned by the driver on mode list refresh!\n"); + ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE); + return; + } + + /* Allocate an index buffer early on, even before trying to change the graphics device struct */ + pTmpDevModeList = ExAllocatePoolWithTag(PagedPool, + cModes * sizeof(DEVMODEENTRY), + GDITAG_GDEVICE); + + if (!pTmpDevModeList) + { + ERR("Bummer! Not enough memory to alloc a new DevModeList\n"); + return; + } + + /* Save a reference to the old thing */ + pOldDevModeList = pGraphicsDevice->pDevModeList; + + /* Attach the new mode info and company to the device, + the GraphicsDevice could potentially use additional synchonisation mechanisms */ + pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo; + pGraphicsDevice->pdevmodeInfo = pdminfo; + + pGraphicsDevice->cDevModes = cModes; + pGraphicsDevice->pDevModeList = pTmpDevModeList; + + /* Don't leak the previous DevModeList, please! */ + ExFreePoolWithTag(pOldDevModeList, GDITAG_GDEVICE); + + /* Loop through the DEVMODEs */ + for (pdm = pdminfo->adevmode; + (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); + pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) + { + /* Initialize the entry */ + pGraphicsDevice->pDevModeList[j].dwFlags = 0; + pGraphicsDevice->pDevModeList[j].pdm = &pdminfo->adevmode[j]; + + j++; + } + + } + + /* Unlock PDEV */ + EngReleaseSemaphore(ppdev->hsemDevLock); +} + PDEVMODEW NTAPI PDEVOBJ_pdmMatchDevMode( @@ -242,13 +345,32 @@ pGraphicsDevice = ppdev->pGraphicsDevice; + DPRINT("looking for mode -- %lux%lux%lu (%lu hz) (%ls)\n", pdm->dmPelsWidth, + pdm->dmPelsHeight, + pdm->dmBitsPerPel, + pdm->dmDisplayFrequency, + pdm->dmDeviceName); + for (i = 0; i < pGraphicsDevice->cDevModes; i++) { pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm; + DPRINT("mode %lu -- %lux%lux%lu (%lu hz) (%ls)\n", i, pdmCurrent->dmPelsWidth, + pdmCurrent->dmPelsHeight, + pdmCurrent->dmBitsPerPel, + pdmCurrent->dmDisplayFrequency, + pdmCurrent->dmDeviceName); + } + + DPRINT("---\n"); + + 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 ; + dwFields = pdmCurrent->dmFields & pdm->dmFields; /* For now, we only need those */ if ((dwFields & DM_BITSPERPEL) && @@ -260,6 +382,12 @@ if ((dwFields & DM_DISPLAYFREQUENCY) && (pdmCurrent->dmDisplayFrequency != pdm->dmDisplayFrequency)) continue; + DPRINT("chosen mode %lu -- %lux%lux%lu (%lu hz) (%ls)\n", i, pdmCurrent->dmPelsWidth, + pdmCurrent->dmPelsHeight, + pdmCurrent->dmBitsPerPel, + pdmCurrent->dmDisplayFrequency, + pdmCurrent->dmDeviceName); + /* Match! Return the DEVMODE */ return pdmCurrent; } @@ -331,7 +459,7 @@ ppdev->pGraphicsDevice = pGraphicsDevice; ppdev->hsemDevLock = EngCreateSemaphore(); - // Should we change the ative mode of pGraphicsDevice ? + // Should we change the active mode of pGraphicsDevice ? ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm) ; /* FIXME! */ Index: win32ss/user/ntuser/display.c =================================================================== --- win32ss/user/ntuser/display.c (revision 65544) +++ win32ss/user/ntuser/display.c (working copy) @@ -7,6 +7,8 @@ */ #include +#include + DBG_DEFAULT_CHANNEL(UserDisplay); BOOL gbBaseVideo = 0; @@ -462,22 +464,34 @@ PGRAPHICS_DEVICE pGraphicsDevice; PDEVMODEENTRY pdmentry; ULONG i, iFoundMode; + PPDEVOBJ ppdev; - TRACE("Enter UserEnumDisplaySettings('%wZ', %lu)\n", + DPRINT("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"); + DPRINT("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) + { + DPRINT("STATUS_NO_MORE_ENTRIES!\n"); return STATUS_NO_MORE_ENTRIES; + } iFoundMode = 0; for (i = 0; i < pGraphicsDevice->cDevModes; i++) @@ -568,7 +582,7 @@ ULONG cbSize, cbExtra; DEVMODEW dmReg, *pdm; - TRACE("Enter NtUserEnumDisplaySettings(%wZ, %lu, %p, 0x%lx)\n", + DPRINT("Enter NtUserEnumDisplaySettings(%wZ, %lu, %p, 0x%lx)\n", pustrDevice, iModeNum, lpDevMode, dwFlags); if (pustrDevice)