NtUserEnumDisplaySettings returns NTSTATUS not BOOL, it doesn't set LastError value. Fix parameter validation and return value, based on tests in w32knapi.Move NtUserEnumDisplayMonitors and NtUserEnumDisplaySettings from windc to a new file display.c (Int functions should go there, too). adapt user32 functions accordingly. As a result w32knapi test doesn't crash anymore.

svn path=/trunk/; revision=33458
This commit is contained in:
Timo Kreuzer 2008-05-11 23:51:55 +00:00
parent fcaf6d5aef
commit da0b3935d7
7 changed files with 293 additions and 268 deletions

View file

@ -199,89 +199,96 @@ EnumDisplayMonitors(
BOOL
STDCALL
EnumDisplaySettingsExA(
LPCSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEA lpDevMode,
DWORD dwFlags)
LPCSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEA lpDevMode,
DWORD dwFlags)
{
BOOL rc;
UNICODE_STRING DeviceName;
DEVMODEW lpDevModeW;
NTSTATUS Status;
UNICODE_STRING usDeviceName, *pusDeviceName = NULL;
DEVMODEW DevModeW;
if ( !RtlCreateUnicodeStringFromAsciiz ( &DeviceName, (PCSZ)lpszDeviceName ) )
if (lpszDeviceName)
{
SetLastError ( ERROR_OUTOFMEMORY );
return FALSE;
if (!RtlCreateUnicodeStringFromAsciiz(&usDeviceName, (PCSZ)lpszDeviceName))
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
pusDeviceName = &usDeviceName;
}
memset(&lpDevModeW,0,sizeof(DEVMODEW));
lpDevModeW.dmSize = sizeof(DEVMODEW);
memset(&DevModeW,0, sizeof(DEVMODEW));
DevModeW.dmSize = sizeof(DEVMODEW);
rc = NtUserEnumDisplaySettings ( &DeviceName, iModeNum, &lpDevModeW,
dwFlags );
if (!rc)
goto done;
Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, &DevModeW, dwFlags);
#define COPYS(f,len) WideCharToMultiByte( CP_THREAD_ACP, 0, lpDevModeW.f, len, (LPSTR)lpDevMode->f, len, NULL, NULL )
#define COPYN(f) lpDevMode->f = lpDevModeW.f
COPYS(dmDeviceName, CCHDEVICENAME );
COPYN(dmSpecVersion);
COPYN(dmDriverVersion);
switch ( lpDevModeW.dmSize )
if (pusDeviceName)
{
case SIZEOF_DEVMODEW_300:
lpDevMode->dmSize = SIZEOF_DEVMODEA_300;
break;
case SIZEOF_DEVMODEW_400:
lpDevMode->dmSize = SIZEOF_DEVMODEA_400;
break;
case SIZEOF_DEVMODEW_500:
default: /* FIXME what to do??? */
lpDevMode->dmSize = SIZEOF_DEVMODEA_500;
break;
RtlFreeUnicodeString (&usDeviceName);
}
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 ( lpDevModeW.dmSize <= SIZEOF_DEVMODEW_300 )
goto done; // we're done with 0x300 fields
if (!NT_SUCCESS(Status))
{
return FALSE;
}
COPYN(dmICMMethod);
COPYN(dmICMIntent);
COPYN(dmMediaType);
COPYN(dmDitherType);
COPYN(dmReserved1);
COPYN(dmReserved2);
#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 (DevModeW.dmSize)
{
case SIZEOF_DEVMODEW_300:
lpDevMode->dmSize = SIZEOF_DEVMODEA_300;
break;
case SIZEOF_DEVMODEW_400:
lpDevMode->dmSize = SIZEOF_DEVMODEA_400;
break;
case SIZEOF_DEVMODEW_500:
default: /* FIXME what to do??? */
lpDevMode->dmSize = SIZEOF_DEVMODEA_500;
break;
}
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 ( lpDevModeW.dmSize <= SIZEOF_DEVMODEW_400 )
goto done; // we're done with 0x400 fields
if (DevModeW.dmSize <= SIZEOF_DEVMODEW_300)
return TRUE; // we're done with 0x300 fields
COPYN(dmPanningWidth);
COPYN(dmPanningHeight);
COPYN(dmICMMethod);
COPYN(dmICMIntent);
COPYN(dmMediaType);
COPYN(dmDitherType);
COPYN(dmReserved1);
COPYN(dmReserved2);
done:
RtlFreeUnicodeString ( &DeviceName );
if (DevModeW.dmSize <= SIZEOF_DEVMODEW_400)
return TRUE; // we're done with 0x400 fields
COPYN(dmPanningWidth);
COPYN(dmPanningHeight);
return rc;
return TRUE;
}
@ -305,19 +312,23 @@ EnumDisplaySettingsA(
BOOL
STDCALL
EnumDisplaySettingsExW(
LPCWSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEW lpDevMode,
DWORD dwFlags)
LPCWSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEW lpDevMode,
DWORD dwFlags)
{
BOOL rc;
UNICODE_STRING DeviceName;
NTSTATUS Status;
UNICODE_STRING usDeviceName, *pusDeviceName = NULL;
RtlInitUnicodeString ( &DeviceName, lpszDeviceName );
if (lpszDeviceName)
{
RtlInitUnicodeString(&usDeviceName, lpszDeviceName);
pusDeviceName = &usDeviceName;
}
rc = NtUserEnumDisplaySettings ( &DeviceName, iModeNum, lpDevMode, dwFlags );
Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpDevMode, dwFlags);
return rc;
return NT_SUCCESS(Status);
}

View file

@ -1064,7 +1064,7 @@ NtUserEnumDisplayMonitors(
OPTIONAL IN DWORD listSize );
BOOL
NTSTATUS
NTAPI
NtUserEnumDisplaySettings(
PUNICODE_STRING lpszDeviceName,

View file

@ -201,7 +201,7 @@ IntGdiEscape(PDC dc,
LPCSTR InData,
LPVOID OutData);
BOOL
NTSTATUS
FASTCALL
IntEnumDisplaySettings(
IN PUNICODE_STRING pDeviceName OPTIONAL,

View file

@ -0,0 +1,189 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: subsystems/win32/win32k/ntuser/display.c
* PURPOSE: display settings
* COPYRIGHT: Copyright 2007 ReactOS
*
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
#define SIZEOF_DEVMODEW_300 188
#define SIZEOF_DEVMODEW_400 212
#define SIZEOF_DEVMODEW_500 220
/* PUBLIC FUNCTIONS ***********************************************************/
NTSTATUS
NTAPI
NtUserEnumDisplaySettings(
PUNICODE_STRING pusDeviceName,
DWORD iModeNum,
LPDEVMODEW lpDevMode, /* FIXME is this correct? */
DWORD dwFlags )
{
NTSTATUS Status;
LPDEVMODEW pSafeDevMode;
PUNICODE_STRING pusSafeDeviceName = NULL;
UNICODE_STRING usSafeDeviceName;
USHORT Size = 0, ExtraSize = 0;
/* Copy the devmode */
_SEH_TRY
{
ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
Size = lpDevMode->dmSize;
ExtraSize = lpDevMode->dmDriverExtra;
}
_SEH_HANDLE
{
DPRINT("FIXME ? : Out of range of DEVMODEW size \n");
_SEH_YIELD(return _SEH_GetExceptionCode());
}
_SEH_END;
if (Size != sizeof(DEVMODEW))
{
return STATUS_BUFFER_TOO_SMALL;
}
pSafeDevMode = ExAllocatePool(PagedPool, Size + ExtraSize);
if (pSafeDevMode == NULL)
{
return STATUS_NO_MEMORY;
}
pSafeDevMode->dmSize = Size;
pSafeDevMode->dmDriverExtra = ExtraSize;
/* Copy the device name */
if (pusDeviceName != NULL)
{
Status = IntSafeCopyUnicodeString(&usSafeDeviceName, pusDeviceName);
if (!NT_SUCCESS(Status))
{
ExFreePool(pSafeDevMode);
return Status;
}
pusSafeDeviceName = &usSafeDeviceName;
}
/* Call internal function */
Status = IntEnumDisplaySettings(pusSafeDeviceName, iModeNum, pSafeDevMode, dwFlags);
if (pusSafeDeviceName != NULL)
RtlFreeUnicodeString(pusSafeDeviceName);
if (!NT_SUCCESS(Status))
{
ExFreePool(pSafeDevMode);
return Status;
}
/* Copy some information back */
_SEH_TRY
{
ProbeForWrite(lpDevMode,Size + ExtraSize, 1);
lpDevMode->dmPelsWidth = pSafeDevMode->dmPelsWidth;
lpDevMode->dmPelsHeight = pSafeDevMode->dmPelsHeight;
lpDevMode->dmBitsPerPel = pSafeDevMode->dmBitsPerPel;
lpDevMode->dmDisplayFrequency = pSafeDevMode->dmDisplayFrequency;
lpDevMode->dmDisplayFlags = pSafeDevMode->dmDisplayFlags;
/* output private/extra driver data */
if (ExtraSize > 0)
{
memcpy((PCHAR)lpDevMode + Size, (PCHAR)pSafeDevMode + Size, ExtraSize);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
ExFreePool(pSafeDevMode);
return Status;
}
LONG
NTAPI
NtUserChangeDisplaySettings(
PUNICODE_STRING lpszDeviceName,
LPDEVMODEW lpDevMode,
HWND hwnd,
DWORD dwflags,
LPVOID lParam)
{
NTSTATUS Status;
DEVMODEW DevMode;
PUNICODE_STRING pSafeDeviceName = NULL;
UNICODE_STRING SafeDeviceName;
LONG Ret;
/* Check arguments */
#ifdef CDS_VIDEOPARAMETERS
if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
#else
if (lParam != NULL)
#endif
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return DISP_CHANGE_BADPARAM;
}
if (hwnd != NULL)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return DISP_CHANGE_BADPARAM;
}
/* Copy devmode */
Status = MmCopyFromCaller(&DevMode.dmSize, &lpDevMode->dmSize, sizeof (DevMode.dmSize));
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return DISP_CHANGE_BADPARAM;
}
DevMode.dmSize = min(sizeof (DevMode), DevMode.dmSize);
Status = MmCopyFromCaller(&DevMode, lpDevMode, DevMode.dmSize);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return DISP_CHANGE_BADPARAM;
}
if (DevMode.dmDriverExtra > 0)
{
DbgPrint("(%s:%i) WIN32K: %s lpDevMode->dmDriverExtra is IGNORED!\n", __FILE__, __LINE__, __FUNCTION__);
DevMode.dmDriverExtra = 0;
}
/* Copy the device name */
if (lpszDeviceName != NULL)
{
Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return DISP_CHANGE_BADPARAM;
}
pSafeDeviceName = &SafeDeviceName;
}
/* Call internal function */
Ret = IntChangeDisplaySettings(pSafeDeviceName, &DevMode, dwflags, lParam);
if (pSafeDeviceName != NULL)
RtlFreeUnicodeString(pSafeDeviceName);
return Ret;
}

View file

@ -890,179 +890,6 @@ NtUserGetDC(HWND hWnd)
return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
}
BOOL
STDCALL
NtUserEnumDisplaySettings(
PUNICODE_STRING lpszDeviceName,
DWORD iModeNum,
LPDEVMODEW lpDevMode, /* FIXME is this correct? */
DWORD dwFlags )
{
NTSTATUS Status;
LPDEVMODEW pSafeDevMode;
PUNICODE_STRING pSafeDeviceName = NULL;
UNICODE_STRING SafeDeviceName;
USHORT Size = 0, ExtraSize = 0;
/* Copy the devmode */
_SEH_TRY
{
ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
Size = lpDevMode->dmSize;
ExtraSize = lpDevMode->dmDriverExtra;
}
_SEH_HANDLE
{
DPRINT1("FIXME ? : Out of range of DEVMODEW size \n");
SetLastNtError(_SEH_GetExceptionCode());
_SEH_YIELD(return FALSE);
}
_SEH_END;
pSafeDevMode = ExAllocatePool(PagedPool, Size + ExtraSize);
if (pSafeDevMode == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
pSafeDevMode->dmSize = Size;
pSafeDevMode->dmDriverExtra = ExtraSize;
/* Copy the device name */
if (lpszDeviceName != NULL)
{
Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
if (!NT_SUCCESS(Status))
{
ExFreePool(pSafeDevMode);
SetLastNtError(Status);
return FALSE;
}
pSafeDeviceName = &SafeDeviceName;
}
/* Call internal function */
if (!IntEnumDisplaySettings(pSafeDeviceName, iModeNum, pSafeDevMode, dwFlags))
{
if (pSafeDeviceName != NULL)
RtlFreeUnicodeString(pSafeDeviceName);
ExFreePool(pSafeDevMode);
return FALSE;
}
if (pSafeDeviceName != NULL)
RtlFreeUnicodeString(pSafeDeviceName);
/* Copy some information back */
_SEH_TRY
{
ProbeForWrite(lpDevMode,Size, 1);
lpDevMode->dmPelsWidth = pSafeDevMode->dmPelsWidth;
lpDevMode->dmPelsHeight = pSafeDevMode->dmPelsHeight;
lpDevMode->dmBitsPerPel = pSafeDevMode->dmBitsPerPel;
lpDevMode->dmDisplayFrequency = pSafeDevMode->dmDisplayFrequency;
lpDevMode->dmDisplayFlags = pSafeDevMode->dmDisplayFlags;
}
_SEH_HANDLE
{
DPRINT1("Warning crash here \n");
SetLastNtError(_SEH_GetExceptionCode());
_SEH_YIELD(return FALSE);
}
_SEH_END;
/* output private/extra driver data */
if (ExtraSize > 0)
{
Status = MmCopyToCaller((PCHAR)lpDevMode + Size, (PCHAR)pSafeDevMode + Size, ExtraSize);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
ExFreePool(pSafeDevMode);
return FALSE;
}
}
ExFreePool(pSafeDevMode);
return TRUE;
}
LONG
STDCALL
NtUserChangeDisplaySettings(
PUNICODE_STRING lpszDeviceName,
LPDEVMODEW lpDevMode,
HWND hwnd,
DWORD dwflags,
LPVOID lParam)
{
NTSTATUS Status;
DEVMODEW DevMode;
PUNICODE_STRING pSafeDeviceName = NULL;
UNICODE_STRING SafeDeviceName;
LONG Ret;
/* Check arguments */
#ifdef CDS_VIDEOPARAMETERS
if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
#else
if (lParam != NULL)
#endif
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return DISP_CHANGE_BADPARAM;
}
if (hwnd != NULL)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return DISP_CHANGE_BADPARAM;
}
/* Copy devmode */
Status = MmCopyFromCaller(&DevMode.dmSize, &lpDevMode->dmSize, sizeof (DevMode.dmSize));
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return DISP_CHANGE_BADPARAM;
}
DevMode.dmSize = min(sizeof (DevMode), DevMode.dmSize);
Status = MmCopyFromCaller(&DevMode, lpDevMode, DevMode.dmSize);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return DISP_CHANGE_BADPARAM;
}
if (DevMode.dmDriverExtra > 0)
{
DbgPrint("(%s:%i) WIN32K: %s lpDevMode->dmDriverExtra is IGNORED!\n", __FILE__, __LINE__, __FUNCTION__);
DevMode.dmDriverExtra = 0;
}
/* Copy the device name */
if (lpszDeviceName != NULL)
{
Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return DISP_CHANGE_BADPARAM;
}
pSafeDeviceName = &SafeDeviceName;
}
/* Call internal function */
Ret = IntChangeDisplaySettings(pSafeDeviceName, &DevMode, dwflags, lParam);
if (pSafeDeviceName != NULL)
RtlFreeUnicodeString(pSafeDeviceName);
return Ret;
}
/*!
* Select logical palette into device context.
* \param hDC handle to the device context

View file

@ -2843,7 +2843,8 @@ GetDisplayNumberFromDeviceName(
* \todo Don't ignore pDeviceName
* \todo Implement non-raw mode (only return settings valid for driver and monitor)
*/
BOOL FASTCALL
NTSTATUS
FASTCALL
IntEnumDisplaySettings(
IN PUNICODE_STRING pDeviceName OPTIONAL,
IN DWORD iModeNum,
@ -2856,11 +2857,12 @@ IntEnumDisplaySettings(
PDEVMODEW CachedMode = NULL;
DEVMODEW DevMode;
ULONG DisplayNumber;
NTSTATUS Status;
if (!NT_SUCCESS(GetDisplayNumberFromDeviceName(pDeviceName, &DisplayNumber)))
Status = GetDisplayNumberFromDeviceName(pDeviceName, &DisplayNumber);
if (!NT_SUCCESS(Status))
{
SetLastWin32Error(STATUS_NO_SUCH_DEVICE);
return FALSE;
return Status;
}
DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize);
@ -2869,8 +2871,7 @@ IntEnumDisplaySettings(
pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
pDevMode->dmSize != SIZEOF_DEVMODEW_500)
{
SetLastWin32Error(STATUS_INVALID_PARAMETER);
return FALSE;
return STATUS_BUFFER_TOO_SMALL;
}
if (iModeNum == ENUM_CURRENT_SETTINGS)
@ -2887,8 +2888,7 @@ IntEnumDisplaySettings(
CachedMode = &DevMode;
else
{
SetLastWin32Error(0); /* FIXME: use error code */
return FALSE;
return STATUS_UNSUCCESSFUL; // FIXME: what status?
}
/* FIXME: Maybe look for the matching devmode supplied by the
* driver so we can provide driver private/extra data?
@ -2923,13 +2923,13 @@ IntEnumDisplaySettings(
if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
{
DPRINT1("FindDriverFileNames failed\n");
return FALSE;
return STATUS_UNSUCCESSFUL;
}
if (!IntPrepareDriverIfNeeded())
{
DPRINT1("IntPrepareDriverIfNeeded failed\n");
return FALSE;
return STATUS_UNSUCCESSFUL;
}
/*
@ -3009,8 +3009,7 @@ IntEnumDisplaySettings(
if (CachedDeviceName.Buffer != NULL)
RtlFreeUnicodeString(&CachedDeviceName);
SetLastWin32Error(STATUS_NO_MEMORY);
return FALSE;
return STATUS_NO_MEMORY;
}
if (CachedDevModes != NULL)
{
@ -3053,8 +3052,7 @@ IntEnumDisplaySettings(
CachedMode = CachedDevModes;
if (CachedMode >= CachedDevModesEnd)
{
SetLastWin32Error(STATUS_NO_MORE_ENTRIES);
return FALSE;
return STATUS_NO_MORE_ENTRIES;
}
while (iModeNum-- > 0 && CachedMode < CachedDevModesEnd)
{
@ -3063,8 +3061,7 @@ IntEnumDisplaySettings(
}
if (CachedMode >= CachedDevModesEnd)
{
SetLastWin32Error(STATUS_NO_MORE_ENTRIES);
return FALSE;
return STATUS_NO_MORE_ENTRIES;
}
}
@ -3074,7 +3071,7 @@ IntEnumDisplaySettings(
RtlZeroMemory(pDevMode + pDevMode->dmSize, pDevMode->dmDriverExtra);
RtlCopyMemory(pDevMode + min(pDevMode->dmSize, CachedMode->dmSize), CachedMode + CachedMode->dmSize, min(pDevMode->dmDriverExtra, CachedMode->dmDriverExtra));
return TRUE;
return STATUS_SUCCESS;
}
static NTSTATUS FASTCALL

View file

@ -111,6 +111,7 @@
<file>csr.c</file>
<file>cursoricon.c</file>
<file>desktop.c</file>
<file>display.c</file>
<file>event.c</file>
<file>focus.c</file>
<file>guicheck.c</file>