From 35d777891f3e072f1bbb8d628edff9d3d1cbb3c0 Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Sun, 11 Sep 2016 19:05:27 +0000 Subject: [PATCH] [USER32] We have to use the copy of DEVMODEW structure (having size expanded on dmDriverExtra) for support of extra data of the driver * Fixes 16 tests for EnumDisplaySettings svn path=/trunk/; revision=72657 --- reactos/win32ss/user/ntuser/display.c | 4 +- reactos/win32ss/user/user32/misc/display.c | 60 ++++++++++++++++++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/reactos/win32ss/user/ntuser/display.c b/reactos/win32ss/user/ntuser/display.c index 149df74cce6..e63f38a51a2 100644 --- a/reactos/win32ss/user/ntuser/display.c +++ b/reactos/win32ss/user/ntuser/display.c @@ -571,12 +571,12 @@ NtUserEnumDisplaySettings( _SEH2_TRY { - ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1); + ProbeForRead(lpDevMode, sizeof(DEVMODEW), sizeof(UCHAR)); cbSize = lpDevMode->dmSize; cbExtra = lpDevMode->dmDriverExtra; - ProbeForWrite(lpDevMode, cbSize + cbExtra, 1); + ProbeForWrite(lpDevMode, cbSize + cbExtra, sizeof(UCHAR)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { diff --git a/reactos/win32ss/user/user32/misc/display.c b/reactos/win32ss/user/user32/misc/display.c index 7da315a2150..631ffe661ab 100644 --- a/reactos/win32ss/user/user32/misc/display.c +++ b/reactos/win32ss/user/user32/misc/display.c @@ -301,7 +301,10 @@ EnumDisplaySettingsExW( DWORD dwFlags) { NTSTATUS Status; - UNICODE_STRING usDeviceName, *pusDeviceName = NULL; + UNICODE_STRING usDeviceName; + PUNICODE_STRING pusDeviceName = NULL; + LPDEVMODEW lpExtendedDevMode; + BOOL Result = FALSE; if (lpszDeviceName) { @@ -309,9 +312,54 @@ EnumDisplaySettingsExW( pusDeviceName = &usDeviceName; } - Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpDevMode, dwFlags); + /* Allocate memory for DEVMODEW and extra data */ + lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(DEVMODEW) + lpDevMode->dmDriverExtra); + if (!lpExtendedDevMode) + return FALSE; - return NT_SUCCESS(Status); + /* Initialize structure fields */ + lpExtendedDevMode->dmSize = sizeof(DEVMODEW); + lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra; + + Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags); + if (NT_SUCCESS(Status)) + { + /* Store old structure size */ + WORD OldSize = lpDevMode->dmSize; + + /* Copy general data */ + RtlCopyMemory(lpDevMode, lpExtendedDevMode, OldSize); + + /* 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(DEVMODEW, dmPanningHeight)) + lpDevMode->dmFields &= ~DM_PANNINGHEIGHT; + + if (OldSize < FIELD_OFFSET(DEVMODEW, dmPanningWidth)) + lpDevMode->dmFields &= ~DM_PANNINGWIDTH; + + Result = TRUE; + } + + /* Free memory */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode); + + return Result; } @@ -325,7 +373,11 @@ EnumDisplaySettingsW( DWORD iModeNum, LPDEVMODEW lpDevMode) { - return EnumDisplaySettingsExW ( lpszDeviceName, iModeNum, lpDevMode, 0 ); + /* Fixup sizes */ + lpDevMode->dmSize = FIELD_OFFSET(DEVMODE, dmICMMethod); + lpDevMode->dmDriverExtra = 0; + + return EnumDisplaySettingsExW(lpszDeviceName, iModeNum, lpDevMode, 0); }