From d419e5b6956c9a37982cba6e2a038bd6537a13c0 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Fri, 24 Aug 2007 12:10:10 +0000 Subject: [PATCH] Bug Fix from Gregor Brunmar (gregor dot brunmar at home dot se), IRC nick ALiENiD we getting change display working again with this bugfix. details * Added missing info from PrimarySurface.DMW when display driver defaults back to the video drivers standard mode * Fixed caching system in IntEnumDisplaySettings when run more than once * Hacked a way around the bug in FindDDIDriver svn path=/trunk/; revision=28514 --- .../subsystems/win32/win32k/include/driver.h | 2 + reactos/subsystems/win32/win32k/misc/driver.c | 15 ++ reactos/subsystems/win32/win32k/objects/dc.c | 215 +++++++++++++----- 3 files changed, 181 insertions(+), 51 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/driver.h b/reactos/subsystems/win32/win32k/include/driver.h index eff9cc9b1d0..0a3e64332f1 100644 --- a/reactos/subsystems/win32/win32k/include/driver.h +++ b/reactos/subsystems/win32/win32k/include/driver.h @@ -176,6 +176,7 @@ typedef struct _DRIVER_FUNCTIONS } DRIVER_FUNCTIONS, *PDRIVER_FUNCTIONS; BOOL DRIVER_RegisterDriver(LPCWSTR Name, PGD_ENABLEDRIVER EnableDriver); +PGD_ENABLEDRIVER DRIVER_FindExistingDDIDriver(LPCWSTR Name); PGD_ENABLEDRIVER DRIVER_FindDDIDriver(LPCWSTR Name); PFILE_OBJECT DRIVER_FindMPDriver(ULONG DisplayNumber); BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED, @@ -186,3 +187,4 @@ INT DRIVER_UnreferenceDriver (LPCWSTR Name); #endif + diff --git a/reactos/subsystems/win32/win32k/misc/driver.c b/reactos/subsystems/win32/win32k/misc/driver.c index f363706df72..c11366b4e2a 100644 --- a/reactos/subsystems/win32/win32k/misc/driver.c +++ b/reactos/subsystems/win32/win32k/misc/driver.c @@ -77,6 +77,21 @@ BOOL DRIVER_RegisterDriver(LPCWSTR Name, PGD_ENABLEDRIVER EnableDriver) return TRUE; } +PGD_ENABLEDRIVER DRIVER_FindExistingDDIDriver(LPCWSTR Name) +{ + GRAPHICS_DRIVER *Driver = DriverList; + while (Driver && Name) + { + if (!_wcsicmp(Driver->Name, Name)) + { + return Driver->EnableDriver; + } + Driver = Driver->Next; + } + + return NULL; +} + PGD_ENABLEDRIVER DRIVER_FindDDIDriver(LPCWSTR Name) { static WCHAR DefaultPath[] = L"\\SystemRoot\\System32\\"; diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/dc.c index 13e4d6d6c0e..212bf3dda84 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/dc.c @@ -600,6 +600,12 @@ IntPrepareDriver() DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n"); continue; } + + // Update the primary surface with what we really got + PrimarySurface.DMW.dmPelsWidth = PrimarySurface.GDIInfo.ulHorzRes; + PrimarySurface.DMW.dmPelsHeight = PrimarySurface.GDIInfo.ulVertRes; + PrimarySurface.DMW.dmBitsPerPel = PrimarySurface.GDIInfo.cBitsPixel; + PrimarySurface.DMW.dmDisplayFrequency = PrimarySurface.GDIInfo.ulVRefresh; } if (0 == PrimarySurface.GDIInfo.ulLogPixelsX) @@ -2640,6 +2646,68 @@ IntSetDCColor(HDC hDC, ULONG Object, COLORREF Color) #define SIZEOF_DEVMODEW_400 212 #define SIZEOF_DEVMODEW_500 220 +static NTSTATUS FASTCALL +GetDisplayNumberFromDeviceName( + IN PUNICODE_STRING pDeviceName OPTIONAL, + OUT ULONG *DisplayNumber) +{ + UNICODE_STRING DisplayString = RTL_CONSTANT_STRING(L"\\\\.\\DISPLAY"); + NTSTATUS Status = STATUS_SUCCESS; + ULONG Length; + ULONG Number; + ULONG i; + + if (DisplayNumber == NULL) + return STATUS_INVALID_PARAMETER_2; + + if (pDeviceName && pDeviceName->Length <= DisplayString.Length) + return STATUS_OBJECT_NAME_INVALID; + + if (pDeviceName == NULL || pDeviceName->Length == 0) + { + PWINDOW_OBJECT DesktopObject; + HDC DesktopHDC; + PDC pDC; + + DesktopObject = UserGetDesktopWindow(); + DesktopHDC = (HDC)UserGetWindowDC(DesktopObject); + pDC = DC_LockDc(DesktopHDC); + + *DisplayNumber = ((GDIDEVICE *)pDC->GDIDevice)->DisplayNumber; + + DC_UnlockDc(DesktopHDC); + UserReleaseDC(DesktopObject, DesktopHDC, FALSE); + + return STATUS_SUCCESS; + } + + /* Hack to check if the first parts are equal, by faking the device name length */ + Length = pDeviceName->Length; + pDeviceName->Length = DisplayString.Length; + if (RtlEqualUnicodeString(&DisplayString, pDeviceName, FALSE) == FALSE) + Status = STATUS_OBJECT_NAME_INVALID; + pDeviceName->Length = Length; + + if (NT_SUCCESS(Status)) + { + /* Convert the last part of pDeviceName to a number */ + Number = 0; + Length = pDeviceName->Length / sizeof(WCHAR); + for (i = DisplayString.Length / sizeof(WCHAR); i < Length; i++) + { + WCHAR Char = pDeviceName->Buffer[i]; + if (Char >= L'0' && Char <= L'9') + Number = Number * 10 + Char - L'0'; + else if (Char != L'\0') + return STATUS_OBJECT_NAME_INVALID; + } + + *DisplayNumber = Number - 1; + } + + return Status; +} + /*! \brief Enumerate possible display settings for the given display... * * \todo Make thread safe!? @@ -2655,10 +2723,17 @@ IntEnumDisplaySettings( { static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL; static DWORD SizeOfCachedDevModes = 0; + static UNICODE_STRING CachedDeviceName; PDEVMODEW CachedMode = NULL; DEVMODEW DevMode; INT Size, OldSize; - ULONG DisplayNumber = 0; /* only default display supported */ + ULONG DisplayNumber; + + if (!NT_SUCCESS(GetDisplayNumberFromDeviceName(pDeviceName, &DisplayNumber))) + { + SetLastWin32Error(STATUS_NO_SUCH_DEVICE); + return FALSE; + } DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize); DPRINT("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra); @@ -2693,12 +2768,28 @@ IntEnumDisplaySettings( } else { - if (iModeNum == 0 || CachedDevModes == NULL) /* query modes from drivers */ + BOOL IsCachedDevice = (CachedDevModes != NULL); + + if (CachedDevModes && + ((pDeviceName == NULL && CachedDeviceName.Length > 0) || + (pDeviceName != NULL && pDeviceName->Buffer != NULL && CachedDeviceName.Length == 0) || + (pDeviceName != NULL && pDeviceName->Buffer != NULL && CachedDeviceName.Length > 0 && RtlEqualUnicodeString(pDeviceName, &CachedDeviceName, TRUE) == FALSE))) + { + IsCachedDevice = FALSE; + } + + if (iModeNum == 0 || IsCachedDevice == FALSE) /* query modes from drivers */ { UNICODE_STRING DriverFileNames; LPWSTR CurrentName; DRVENABLEDATA DrvEnableData; + /* Free resources from last driver cache */ + if (IsCachedDevice == FALSE && CachedDeviceName.Buffer != NULL) + { + RtlFreeUnicodeString(&CachedDeviceName); + } + /* Retrieve DDI driver names from registry */ RtlInitUnicodeString(&DriverFileNames, NULL); if (!FindDriverFileNames(&DriverFileNames, DisplayNumber)) @@ -2719,9 +2810,12 @@ IntEnumDisplaySettings( { INT i; PGD_ENABLEDRIVER GDEnableDriver; + PGD_GETMODES GetModes = NULL; + INT SizeNeeded, SizeUsed; /* Get the DDI driver's entry point */ - GDEnableDriver = DRIVER_FindDDIDriver(CurrentName); + //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName); + GDEnableDriver = DRIVER_FindExistingDDIDriver(L"DISPLAY"); if (NULL == GDEnableDriver) { DPRINT("FindDDIDriver failed for %S\n", CurrentName); @@ -2743,62 +2837,81 @@ IntEnumDisplaySettings( for (i = 0; i < DrvEnableData.c; i++) { PDRVFN DrvFn = DrvEnableData.pdrvfn + i; - PGD_GETMODES GetModes; - INT SizeNeeded, SizeUsed; - if (DrvFn->iFunc != INDEX_DrvGetModes) - continue; - - GetModes = (PGD_GETMODES)DrvFn->pfn; - - /* make sure we have enough memory to hold the modes */ - SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL); - if (SizeNeeded <= 0) + if (DrvFn->iFunc == INDEX_DrvGetModes) { - DPRINT("DrvGetModes failed for %S\n", CurrentName); + GetModes = (PGD_GETMODES)DrvFn->pfn; break; } + } - SizeUsed = CachedDevModesEnd - CachedDevModes; - if (SizeOfCachedDevModes - SizeUsed < SizeNeeded) - { - PVOID NewBuffer; + if (GetModes == NULL) + { + DPRINT("DrvGetModes doesn't exist for %S\n", CurrentName); + continue; + } - SizeOfCachedDevModes += SizeNeeded; - NewBuffer = ExAllocatePool(PagedPool, SizeOfCachedDevModes); - if (NewBuffer == NULL) - { - /* clean up */ - ExFreePool(CachedDevModes); - SizeOfCachedDevModes = 0; - CachedDevModes = NULL; - CachedDevModesEnd = NULL; - SetLastWin32Error(STATUS_NO_MEMORY); - return FALSE; - } - if (CachedDevModes != NULL) - { - RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed); - ExFreePool(CachedDevModes); - } - CachedDevModes = NewBuffer; - CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed); - } - - /* query modes */ - SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), - SizeOfCachedDevModes - SizeUsed, - CachedDevModesEnd); - if (SizeNeeded <= 0) - { - DPRINT("DrvGetModes failed for %S\n", CurrentName); - } - else - { - CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd + SizeNeeded); - } + /* make sure we have enough memory to hold the modes */ + SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL); + if (SizeNeeded <= 0) + { + DPRINT("DrvGetModes failed for %S\n", CurrentName); break; } + + SizeUsed = (PCHAR)CachedDevModesEnd - (PCHAR)CachedDevModes; + if (SizeOfCachedDevModes < SizeUsed + SizeNeeded) + { + PVOID NewBuffer; + + SizeOfCachedDevModes += SizeNeeded; + NewBuffer = ExAllocatePool(PagedPool, SizeOfCachedDevModes); + if (NewBuffer == NULL) + { + /* clean up */ + ExFreePool(CachedDevModes); + CachedDevModes = NULL; + CachedDevModesEnd = NULL; + SizeOfCachedDevModes = 0; + + if (CachedDeviceName.Buffer != NULL) + RtlFreeUnicodeString(&CachedDeviceName); + + SetLastWin32Error(STATUS_NO_MEMORY); + return FALSE; + } + if (CachedDevModes != NULL) + { + RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed); + ExFreePool(CachedDevModes); + } + CachedDevModes = NewBuffer; + CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed); + } + + if (!IsCachedDevice) + { + if (CachedDeviceName.Buffer != NULL) + RtlFreeUnicodeString(&CachedDeviceName); + + if (pDeviceName) + IntSafeCopyUnicodeString(&CachedDeviceName, pDeviceName); + + IsCachedDevice = TRUE; + } + + /* query modes */ + SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), + SizeNeeded, + CachedDevModesEnd); + if (SizeNeeded <= 0) + { + DPRINT("DrvGetModes failed for %S\n", CurrentName); + } + else + { + CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd + SizeNeeded); + } } RtlFreeUnicodeString(&DriverFileNames);