mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 12:54:51 +00:00
620 lines
15 KiB
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);
|
|
}
|