reactos/win32ss/user/user32/misc/display.c

620 lines
15 KiB
C

/*
* PROJECT: ReactOS user32.dll
* FILE: win32ss/user/user32/misc/display.c
* PURPOSE: DDE
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
#include <user32.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
#define SIZEOF_DEVMODEA_300 124
#define SIZEOF_DEVMODEA_400 148
#define SIZEOF_DEVMODEA_500 156
#define SIZEOF_DEVMODEW_300 188
#define SIZEOF_DEVMODEW_400 212
#define SIZEOF_DEVMODEW_500 220
/*
* @implemented
*/
BOOL WINAPI
EnumDisplayDevicesA(
LPCSTR lpDevice,
DWORD iDevNum,
PDISPLAY_DEVICEA lpDisplayDevice,
DWORD dwFlags)
{
BOOL rc;
UNICODE_STRING Device;
DISPLAY_DEVICEW DisplayDeviceW;
if (!RtlCreateUnicodeStringFromAsciiz(&Device, (PCSZ)lpDevice))
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
RtlZeroMemory(&DisplayDeviceW, sizeof(DISPLAY_DEVICEW));
DisplayDeviceW.cb = sizeof(DISPLAY_DEVICEW);
rc = NtUserEnumDisplayDevices(&Device,
iDevNum,
&DisplayDeviceW,
dwFlags);
if (rc)
{
/* Copy result from DisplayDeviceW to lpDisplayDevice. Buffers have the same size so result is always NULL terminated. */
lpDisplayDevice->StateFlags = DisplayDeviceW.StateFlags;
WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceName, -1,
lpDisplayDevice->DeviceName,
sizeof(lpDisplayDevice->DeviceName) / sizeof(lpDisplayDevice->DeviceName[0]),
NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceString, -1,
lpDisplayDevice->DeviceString,
sizeof(lpDisplayDevice->DeviceString) / sizeof(lpDisplayDevice->DeviceString[0]),
NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceID, -1,
lpDisplayDevice->DeviceID,
sizeof(lpDisplayDevice->DeviceID) / sizeof(lpDisplayDevice->DeviceID[0]),
NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceKey, -1,
lpDisplayDevice->DeviceKey,
sizeof(lpDisplayDevice->DeviceKey) / sizeof(lpDisplayDevice->DeviceKey[0]),
NULL, NULL);
}
RtlFreeUnicodeString(&Device);
return rc;
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDisplayDevicesW(
LPCWSTR lpDevice,
DWORD iDevNum,
PDISPLAY_DEVICEW lpDisplayDevice,
DWORD dwFlags)
{
UNICODE_STRING Device;
BOOL rc;
RtlInitUnicodeString(&Device, lpDevice);
rc = NtUserEnumDisplayDevices(
&Device,
iDevNum,
lpDisplayDevice,
dwFlags);
return rc;
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDisplayMonitors(
HDC hdc,
LPCRECT lprcClip,
MONITORENUMPROC lpfnEnum,
LPARAM dwData)
{
INT iCount, i;
HMONITOR *hMonitorList;
LPRECT pRectList;
HANDLE hHeap;
BOOL ret = FALSE;
/* get list of monitors/rects */
iCount = NtUserEnumDisplayMonitors(hdc, lprcClip, NULL, NULL, 0);
if (iCount < 0)
{
/* FIXME: SetLastError() */
return FALSE;
}
if (iCount == 0)
{
return TRUE;
}
hHeap = GetProcessHeap();
hMonitorList = HeapAlloc(hHeap, 0, sizeof (HMONITOR) * iCount);
if (hMonitorList == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
pRectList = HeapAlloc(hHeap, 0, sizeof (RECT) * iCount);
if (pRectList == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
iCount = NtUserEnumDisplayMonitors(hdc, lprcClip, hMonitorList, pRectList, iCount);
if (iCount <= 0)
{
/* FIXME: SetLastError() */
goto cleanup;
}
/* enumerate list */
for (i = 0; i < iCount; i++)
{
HMONITOR hMonitor = hMonitorList[i];
LPRECT pMonitorRect = pRectList + i;
HDC hMonitorDC = NULL;
if (hdc != NULL)
{
/* make monitor DC */
hMonitorDC = hdc;
}
if (!lpfnEnum(hMonitor, hMonitorDC, pMonitorRect, dwData))
goto cleanup; /* return FALSE */
}
ret = TRUE;
cleanup:
if(hMonitorList)
HeapFree(hHeap, 0, hMonitorList);
if(pRectList)
HeapFree(hHeap, 0, pRectList);
return ret;
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDisplaySettingsExA(
LPCSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEA lpDevMode,
DWORD dwFlags)
{
NTSTATUS Status;
UNICODE_STRING usDeviceName;
PUNICODE_STRING pusDeviceName = NULL;
LPDEVMODEW lpExtendedDevMode;
BOOL Result = FALSE;
if (lpszDeviceName)
{
if (!RtlCreateUnicodeStringFromAsciiz(&usDeviceName, (PCSZ)lpszDeviceName))
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
pusDeviceName = &usDeviceName;
}
/* Allocate memory for DEVMODEW and extra data */
lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(DEVMODEW) + lpDevMode->dmDriverExtra);
if (!lpExtendedDevMode)
{
if (pusDeviceName)
RtlFreeUnicodeString(&usDeviceName);
return FALSE;
}
/* 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))
{
/* 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(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((PUCHAR)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;
}
/* Free memory */
RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode);
return Result;
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDisplaySettingsA(
LPCSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEA lpDevMode)
{
/* Fixup sizes */
lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod);
lpDevMode->dmDriverExtra = 0;
return EnumDisplaySettingsExA(lpszDeviceName, iModeNum, lpDevMode, 0);
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDisplaySettingsExW(
LPCWSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEW lpDevMode,
DWORD dwFlags)
{
NTSTATUS Status;
UNICODE_STRING usDeviceName;
PUNICODE_STRING pusDeviceName = NULL;
LPDEVMODEW lpExtendedDevMode;
BOOL Result = FALSE;
if (lpszDeviceName)
{
RtlInitUnicodeString(&usDeviceName, lpszDeviceName);
pusDeviceName = &usDeviceName;
}
/* Allocate memory for DEVMODEW and extra data */
lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(DEVMODEW) + lpDevMode->dmDriverExtra);
if (!lpExtendedDevMode)
return FALSE;
/* Initialize structure fields */
lpExtendedDevMode->dmSize = sizeof(DEVMODEW);
lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra;
Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags);
if (NT_SUCCESS(Status))
{
/* Store old structure sizes */
WORD OldSize = lpDevMode->dmSize;
WORD OldDriverExtra = lpDevMode->dmDriverExtra;
/* Copy general data */
RtlCopyMemory(lpDevMode, lpExtendedDevMode, OldSize);
/* Restore old sizes */
lpDevMode->dmSize = OldSize;
lpDevMode->dmDriverExtra = OldDriverExtra;
/* 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((PUCHAR)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;
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDisplaySettingsW(
LPCWSTR lpszDeviceName,
DWORD iModeNum,
LPDEVMODEW lpDevMode)
{
/* Fixup sizes */
lpDevMode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
lpDevMode->dmDriverExtra = 0;
return EnumDisplaySettingsExW(lpszDeviceName, iModeNum, lpDevMode, 0);
}
/*
* @implemented
*/
BOOL
WINAPI
GetMonitorInfoA(
HMONITOR hMonitor,
LPMONITORINFO lpmi)
{
if (lpmi->cbSize == sizeof (MONITORINFO))
{
return NtUserGetMonitorInfo(hMonitor, lpmi);
}
else if (lpmi->cbSize != sizeof (MONITORINFOEXA))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
else
{
MONITORINFOEXW miExW;
INT res;
miExW.cbSize = sizeof (MONITORINFOEXW);
if (!NtUserGetMonitorInfo(hMonitor, (LPMONITORINFO)&miExW))
{
return FALSE;
}
memcpy(lpmi, &miExW, sizeof (MONITORINFO));
res = WideCharToMultiByte(CP_THREAD_ACP, 0, miExW.szDevice, -1,
((LPMONITORINFOEXA)lpmi)->szDevice, CCHDEVICENAME,
NULL, NULL);
if (res == 0)
{
WARN("WideCharToMultiByte() failed!\n");
return FALSE;
}
}
return TRUE;
}
/*
* @implemented
*/
BOOL
WINAPI
GetMonitorInfoW(
HMONITOR hMonitor,
LPMONITORINFO lpmi)
{
return NtUserGetMonitorInfo(hMonitor, lpmi);
}
/*
* @implemented
*/
HMONITOR
WINAPI
MonitorFromPoint(
IN POINT ptPoint,
IN DWORD dwFlags )
{
return NtUserMonitorFromPoint(ptPoint, dwFlags);
}
/*
* @implemented
*/
HMONITOR
WINAPI
MonitorFromRect(
IN LPCRECT lpcRect,
IN DWORD dwFlags )
{
return NtUserMonitorFromRect(lpcRect, dwFlags);
}
/*
* @implemented
*/
HMONITOR
WINAPI
MonitorFromWindow(
IN HWND hWnd,
IN DWORD dwFlags )
{
return NtUserMonitorFromWindow(hWnd, dwFlags);
}
/*
* @implemented
*/
LONG
WINAPI
ChangeDisplaySettingsExA(
LPCSTR lpszDeviceName,
LPDEVMODEA lpDevMode,
HWND hwnd,
DWORD dwflags,
LPVOID lParam)
{
LONG rc;
UNICODE_STRING DeviceName;
PUNICODE_STRING pDeviceName = &DeviceName;
if (lpszDeviceName != NULL)
{
if (!RtlCreateUnicodeStringFromAsciiz(pDeviceName, (PCSZ)lpszDeviceName))
{
SetLastError(ERROR_OUTOFMEMORY);
return DISP_CHANGE_BADPARAM; /* FIXME what to return? */
}
}
else
pDeviceName = NULL;
if (lpDevMode != NULL)
{
LPDEVMODEW pDevModeW;
pDevModeW = GdiConvertToDevmodeW(lpDevMode);
if(pDevModeW)
{
rc = NtUserChangeDisplaySettings(pDeviceName, pDevModeW, dwflags, lParam);
RtlFreeHeap(GetProcessHeap(), 0, pDevModeW);
}
else
rc = DISP_CHANGE_SUCCESSFUL;
}
else
rc = NtUserChangeDisplaySettings(pDeviceName, NULL, dwflags, lParam);
if (lpszDeviceName != NULL)
RtlFreeUnicodeString(&DeviceName);
return rc;
}
/*
* @implemented
*/
LONG
WINAPI
ChangeDisplaySettingsA(
LPDEVMODEA lpDevMode,
DWORD dwflags)
{
if(lpDevMode)
lpDevMode->dmDriverExtra = 0;
return ChangeDisplaySettingsExA ( NULL, lpDevMode, NULL, dwflags, 0 );
}
/*
* @implemented
*/
LONG
WINAPI
ChangeDisplaySettingsExW(
LPCWSTR lpszDeviceName,
LPDEVMODEW lpDevMode,
HWND hwnd,
DWORD dwflags,
LPVOID lParam)
{
LONG rc;
UNICODE_STRING DeviceName;
PUNICODE_STRING pDeviceName = &DeviceName;
if (lpszDeviceName != NULL)
RtlInitUnicodeString(pDeviceName, lpszDeviceName);
else
pDeviceName = NULL;
rc = NtUserChangeDisplaySettings(pDeviceName, lpDevMode, dwflags, lParam);
return rc;
}
/*
* @implemented
*/
LONG
WINAPI
ChangeDisplaySettingsW(
LPDEVMODEW lpDevMode,
DWORD dwflags)
{
if(lpDevMode)
lpDevMode->dmDriverExtra = 0;
return ChangeDisplaySettingsExW(NULL, lpDevMode, NULL, dwflags, 0);
}