From 6dd9ac5dc5eb32f7bfe351177142c4950a52c79d Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Sun, 11 Sep 2016 20:11:35 +0000 Subject: [PATCH] [USER32] We have to use the copy of DEVMODEA structure (having size expanded on dmDriverExtra) for support of extra data of the driver svn path=/trunk/; revision=72659 --- reactos/win32ss/user/user32/misc/display.c | 163 +++++++++++++-------- 1 file changed, 100 insertions(+), 63 deletions(-) diff --git a/reactos/win32ss/user/user32/misc/display.c b/reactos/win32ss/user/user32/misc/display.c index 631ffe661ab..a596ef3627f 100644 --- a/reactos/win32ss/user/user32/misc/display.c +++ b/reactos/win32ss/user/user32/misc/display.c @@ -191,8 +191,10 @@ EnumDisplaySettingsExA( DWORD dwFlags) { NTSTATUS Status; - UNICODE_STRING usDeviceName, *pusDeviceName = NULL; - DEVMODEW DevModeW; + UNICODE_STRING usDeviceName; + PUNICODE_STRING pusDeviceName = NULL; + LPDEVMODEW lpExtendedDevMode; + BOOL Result = FALSE; if (lpszDeviceName) { @@ -204,74 +206,105 @@ EnumDisplaySettingsExA( pusDeviceName = &usDeviceName; } - memset(&DevModeW,0, sizeof(DEVMODEW)); - DevModeW.dmSize = sizeof(DEVMODEW); - - Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, &DevModeW, dwFlags); - - if (pusDeviceName) + /* Allocate memory for DEVMODEW and extra data */ + lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(DEVMODEW) + lpDevMode->dmDriverExtra); + if (!lpExtendedDevMode) { - RtlFreeUnicodeString (&usDeviceName); - } + if (pusDeviceName) + RtlFreeUnicodeString(&usDeviceName); - if (!NT_SUCCESS(Status)) - { return FALSE; } -#define COPYS(f,len) WideCharToMultiByte( CP_THREAD_ACP, 0, DevModeW.f, len, (LPSTR)lpDevMode->f, len, NULL, NULL ) -#define COPYN(f) lpDevMode->f = DevModeW.f - COPYS(dmDeviceName, CCHDEVICENAME ); - COPYN(dmSpecVersion); - COPYN(dmDriverVersion); - switch (lpDevMode->dmSize) + /* Initialize structure fields */ + lpExtendedDevMode->dmSize = sizeof(DEVMODEW); + lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra; + + Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags); + + if (pusDeviceName) + RtlFreeUnicodeString(&usDeviceName); + + if (NT_SUCCESS(Status)) { - case SIZEOF_DEVMODEA_300: - case SIZEOF_DEVMODEA_400: - case SIZEOF_DEVMODEA_500: - break; - default: - lpDevMode->dmSize = SIZEOF_DEVMODEA_300; - break; + /* Store old structure size */ + WORD OldSize = lpDevMode->dmSize; + +#define COPYS(f,len) WideCharToMultiByte(CP_THREAD_ACP, 0, lpExtendedDevMode->f, len, (LPSTR)lpDevMode->f, len, NULL, NULL) +#define COPYN(f) lpDevMode->f = lpExtendedDevMode->f + + COPYS(dmDeviceName, CCHDEVICENAME); + COPYN(dmSpecVersion); + COPYN(dmDriverVersion); + COPYN(dmDriverExtra); + COPYN(dmFields); + COPYN(dmPosition.x); + COPYN(dmPosition.y); + COPYN(dmScale); + COPYN(dmCopies); + COPYN(dmDefaultSource); + COPYN(dmPrintQuality); + COPYN(dmColor); + COPYN(dmDuplex); + COPYN(dmYResolution); + COPYN(dmTTOption); + COPYN(dmCollate); + COPYS(dmFormName,CCHFORMNAME); + COPYN(dmLogPixels); + COPYN(dmBitsPerPel); + COPYN(dmPelsWidth); + COPYN(dmPelsHeight); + COPYN(dmDisplayFlags); // aka dmNup + COPYN(dmDisplayFrequency); + + /* we're done with 0x300 fields */ + if (OldSize > SIZEOF_DEVMODEA_300) + { + COPYN(dmICMMethod); + COPYN(dmICMIntent); + COPYN(dmMediaType); + COPYN(dmDitherType); + COPYN(dmReserved1); + COPYN(dmReserved2); + + /* we're done with 0x400 fields */ + if (OldSize > SIZEOF_DEVMODEA_400) + { + COPYN(dmPanningWidth); + COPYN(dmPanningHeight); + } + } + + /* Restore old size */ + lpDevMode->dmSize = OldSize; + + /* Extra data presented? */ + if (lpDevMode->dmDriverExtra && lpExtendedDevMode->dmDriverExtra) + { + /* We choose the smallest size */ + if (lpDevMode->dmDriverExtra > lpExtendedDevMode->dmDriverExtra) + lpDevMode->dmDriverExtra = lpExtendedDevMode->dmDriverExtra; + + /* Copy extra data */ + RtlCopyMemory(lpDevMode + OldSize, lpExtendedDevMode + 1, lpDevMode->dmDriverExtra); + } + + /* If the size of source structure is less, than used, we clean unsupported flags */ + if (OldSize < FIELD_OFFSET(DEVMODEA, dmPanningHeight)) + lpDevMode->dmFields &= ~DM_PANNINGHEIGHT; + + if (OldSize < FIELD_OFFSET(DEVMODEA, dmPanningWidth)) + lpDevMode->dmFields &= ~DM_PANNINGWIDTH; + + Result = TRUE; } - COPYN(dmDriverExtra); - COPYN(dmFields); - COPYN(dmPosition.x); - COPYN(dmPosition.y); - COPYN(dmScale); - COPYN(dmCopies); - COPYN(dmDefaultSource); - COPYN(dmPrintQuality); - COPYN(dmColor); - COPYN(dmDuplex); - COPYN(dmYResolution); - COPYN(dmTTOption); - COPYN(dmCollate); - COPYS(dmFormName,CCHFORMNAME); - COPYN(dmLogPixels); - COPYN(dmBitsPerPel); - COPYN(dmPelsWidth); - COPYN(dmPelsHeight); - COPYN(dmDisplayFlags); // aka dmNup - COPYN(dmDisplayFrequency); - if (lpDevMode->dmSize <= SIZEOF_DEVMODEW_300) - return TRUE; // we're done with 0x300 fields + /* Free memory */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode); - COPYN(dmICMMethod); - COPYN(dmICMIntent); - COPYN(dmMediaType); - COPYN(dmDitherType); - COPYN(dmReserved1); - COPYN(dmReserved2); - - if (lpDevMode->dmSize <= SIZEOF_DEVMODEW_400) - return TRUE; // we're done with 0x400 fields - - COPYN(dmPanningWidth); - COPYN(dmPanningHeight); - - return TRUE; + return Result; } @@ -285,7 +318,11 @@ EnumDisplaySettingsA( DWORD iModeNum, LPDEVMODEA lpDevMode) { - return EnumDisplaySettingsExA ( lpszDeviceName, iModeNum, lpDevMode, 0 ); + /* Fixup sizes */ + lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod); + lpDevMode->dmDriverExtra = 0; + + return EnumDisplaySettingsExA(lpszDeviceName, iModeNum, lpDevMode, 0); } @@ -374,7 +411,7 @@ EnumDisplaySettingsW( LPDEVMODEW lpDevMode) { /* Fixup sizes */ - lpDevMode->dmSize = FIELD_OFFSET(DEVMODE, dmICMMethod); + lpDevMode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod); lpDevMode->dmDriverExtra = 0; return EnumDisplaySettingsExW(lpszDeviceName, iModeNum, lpDevMode, 0);