[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
This commit is contained in:
Dmitry Chapyshev 2016-09-11 20:11:35 +00:00
parent 5e9b9699a6
commit 6dd9ac5dc5

View file

@ -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);