2 * PROJECT: ReactOS user32.dll
3 * FILE: win32ss/user/user32/misc/display.c
5 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
12 #define SIZEOF_DEVMODEA_300 124
13 #define SIZEOF_DEVMODEA_400 148
14 #define SIZEOF_DEVMODEA_500 156
15 #define SIZEOF_DEVMODEW_300 188
16 #define SIZEOF_DEVMODEW_400 212
17 #define SIZEOF_DEVMODEW_500 220
26 PDISPLAY_DEVICEA lpDisplayDevice
,
30 UNICODE_STRING Device
;
31 DISPLAY_DEVICEW DisplayDeviceW
;
33 if (!RtlCreateUnicodeStringFromAsciiz(&Device
, (PCSZ
)lpDevice
))
35 SetLastError(ERROR_OUTOFMEMORY
);
39 RtlZeroMemory(&DisplayDeviceW
, sizeof(DISPLAY_DEVICEW
));
40 DisplayDeviceW
.cb
= sizeof(DISPLAY_DEVICEW
);
41 rc
= NtUserEnumDisplayDevices(&Device
,
47 /* Copy result from DisplayDeviceW to lpDisplayDevice. Buffers have the same size so result is always NULL terminated. */
48 lpDisplayDevice
->StateFlags
= DisplayDeviceW
.StateFlags
;
49 WideCharToMultiByte(CP_ACP
, 0, DisplayDeviceW
.DeviceName
, -1,
50 lpDisplayDevice
->DeviceName
,
51 sizeof(lpDisplayDevice
->DeviceName
) / sizeof(lpDisplayDevice
->DeviceName
[0]),
53 WideCharToMultiByte(CP_ACP
, 0, DisplayDeviceW
.DeviceString
, -1,
54 lpDisplayDevice
->DeviceString
,
55 sizeof(lpDisplayDevice
->DeviceString
) / sizeof(lpDisplayDevice
->DeviceString
[0]),
57 WideCharToMultiByte(CP_ACP
, 0, DisplayDeviceW
.DeviceID
, -1,
58 lpDisplayDevice
->DeviceID
,
59 sizeof(lpDisplayDevice
->DeviceID
) / sizeof(lpDisplayDevice
->DeviceID
[0]),
61 WideCharToMultiByte(CP_ACP
, 0, DisplayDeviceW
.DeviceKey
, -1,
62 lpDisplayDevice
->DeviceKey
,
63 sizeof(lpDisplayDevice
->DeviceKey
) / sizeof(lpDisplayDevice
->DeviceKey
[0]),
67 RtlFreeUnicodeString(&Device
);
81 PDISPLAY_DEVICEW lpDisplayDevice
,
84 UNICODE_STRING Device
;
87 RtlInitUnicodeString(&Device
, lpDevice
);
89 rc
= NtUserEnumDisplayDevices(
107 MONITORENUMPROC lpfnEnum
,
111 HMONITOR
*hMonitorList
;
116 /* get list of monitors/rects */
117 iCount
= NtUserEnumDisplayMonitors(hdc
, lprcClip
, NULL
, NULL
, 0);
120 /* FIXME: SetLastError() */
128 hHeap
= GetProcessHeap();
129 hMonitorList
= HeapAlloc(hHeap
, 0, sizeof (HMONITOR
) * iCount
);
130 if (hMonitorList
== NULL
)
132 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
135 pRectList
= HeapAlloc(hHeap
, 0, sizeof (RECT
) * iCount
);
136 if (pRectList
== NULL
)
138 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
142 iCount
= NtUserEnumDisplayMonitors(hdc
, lprcClip
, hMonitorList
, pRectList
, iCount
);
145 /* FIXME: SetLastError() */
150 for (i
= 0; i
< iCount
; i
++)
152 HMONITOR hMonitor
= hMonitorList
[i
];
153 LPRECT pMonitorRect
= pRectList
+ i
;
154 HDC hMonitorDC
= NULL
;
158 /* make monitor DC */
162 if (!lpfnEnum(hMonitor
, hMonitorDC
, pMonitorRect
, dwData
))
163 goto cleanup
; /* return FALSE */
170 HeapFree(hHeap
, 0, hMonitorList
);
172 HeapFree(hHeap
, 0, pRectList
);
182 EnumDisplaySettingsExA(
183 LPCSTR lpszDeviceName
,
185 LPDEVMODEA lpDevMode
,
189 UNICODE_STRING usDeviceName
;
190 PUNICODE_STRING pusDeviceName
= NULL
;
191 LPDEVMODEW lpExtendedDevMode
;
196 if (!RtlCreateUnicodeStringFromAsciiz(&usDeviceName
, (PCSZ
)lpszDeviceName
))
198 SetLastError(ERROR_OUTOFMEMORY
);
201 pusDeviceName
= &usDeviceName
;
204 /* Allocate memory for DEVMODEW and extra data */
205 lpExtendedDevMode
= RtlAllocateHeap(RtlGetProcessHeap(),
207 sizeof(DEVMODEW
) + lpDevMode
->dmDriverExtra
);
208 if (!lpExtendedDevMode
)
211 RtlFreeUnicodeString(&usDeviceName
);
216 /* Initialize structure fields */
217 lpExtendedDevMode
->dmSize
= sizeof(DEVMODEW
);
218 lpExtendedDevMode
->dmDriverExtra
= lpDevMode
->dmDriverExtra
;
220 Status
= NtUserEnumDisplaySettings(pusDeviceName
, iModeNum
, lpExtendedDevMode
, dwFlags
);
223 RtlFreeUnicodeString(&usDeviceName
);
225 if (NT_SUCCESS(Status
))
227 /* Store old structure size */
228 WORD OldSize
= lpDevMode
->dmSize
;
230 #define COPYS(f,len) WideCharToMultiByte(CP_THREAD_ACP, 0, lpExtendedDevMode->f, len, (LPSTR)lpDevMode->f, len, NULL, NULL)
231 #define COPYN(f) lpDevMode->f = lpExtendedDevMode->f
233 COPYS(dmDeviceName
, CCHDEVICENAME
);
234 COPYN(dmSpecVersion
);
235 COPYN(dmDriverVersion
);
241 COPYN(dmDefaultSource
);
242 COPYN(dmPrintQuality
);
245 COPYN(dmYResolution
);
248 COPYS(dmFormName
,CCHFORMNAME
);
253 COPYN(dmDisplayFlags
); // aka dmNup
254 COPYN(dmDisplayFrequency
);
256 /* we're done with 0x300 fields */
257 if (OldSize
> SIZEOF_DEVMODEA_300
)
266 /* we're done with 0x400 fields */
267 if (OldSize
> SIZEOF_DEVMODEA_400
)
269 COPYN(dmPanningWidth
);
270 COPYN(dmPanningHeight
);
274 /* Restore old size */
275 lpDevMode
->dmSize
= OldSize
;
277 /* Extra data presented? */
278 if (lpDevMode
->dmDriverExtra
&& lpExtendedDevMode
->dmDriverExtra
)
280 /* We choose the smallest size */
281 if (lpDevMode
->dmDriverExtra
> lpExtendedDevMode
->dmDriverExtra
)
282 lpDevMode
->dmDriverExtra
= lpExtendedDevMode
->dmDriverExtra
;
284 /* Copy extra data */
285 RtlCopyMemory((PUCHAR
)lpDevMode
+ OldSize
,
286 lpExtendedDevMode
+ 1,
287 lpDevMode
->dmDriverExtra
);
290 /* If the size of source structure is less, than used, we clean unsupported flags */
291 if (OldSize
< FIELD_OFFSET(DEVMODEA
, dmPanningHeight
))
292 lpDevMode
->dmFields
&= ~DM_PANNINGHEIGHT
;
294 if (OldSize
< FIELD_OFFSET(DEVMODEA
, dmPanningWidth
))
295 lpDevMode
->dmFields
&= ~DM_PANNINGWIDTH
;
301 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode
);
312 EnumDisplaySettingsA(
313 LPCSTR lpszDeviceName
,
315 LPDEVMODEA lpDevMode
)
318 lpDevMode
->dmSize
= FIELD_OFFSET(DEVMODEA
, dmICMMethod
);
319 lpDevMode
->dmDriverExtra
= 0;
321 return EnumDisplaySettingsExA(lpszDeviceName
, iModeNum
, lpDevMode
, 0);
330 EnumDisplaySettingsExW(
331 LPCWSTR lpszDeviceName
,
333 LPDEVMODEW lpDevMode
,
337 UNICODE_STRING usDeviceName
;
338 PUNICODE_STRING pusDeviceName
= NULL
;
339 LPDEVMODEW lpExtendedDevMode
;
344 RtlInitUnicodeString(&usDeviceName
, lpszDeviceName
);
345 pusDeviceName
= &usDeviceName
;
348 /* Allocate memory for DEVMODEW and extra data */
349 lpExtendedDevMode
= RtlAllocateHeap(RtlGetProcessHeap(),
351 sizeof(DEVMODEW
) + lpDevMode
->dmDriverExtra
);
352 if (!lpExtendedDevMode
)
355 /* Initialize structure fields */
356 lpExtendedDevMode
->dmSize
= sizeof(DEVMODEW
);
357 lpExtendedDevMode
->dmDriverExtra
= lpDevMode
->dmDriverExtra
;
359 Status
= NtUserEnumDisplaySettings(pusDeviceName
, iModeNum
, lpExtendedDevMode
, dwFlags
);
360 if (NT_SUCCESS(Status
))
362 /* Store old structure sizes */
363 WORD OldSize
= lpDevMode
->dmSize
;
364 WORD OldDriverExtra
= lpDevMode
->dmDriverExtra
;
366 /* Copy general data */
367 RtlCopyMemory(lpDevMode
, lpExtendedDevMode
, OldSize
);
369 /* Restore old sizes */
370 lpDevMode
->dmSize
= OldSize
;
371 lpDevMode
->dmDriverExtra
= OldDriverExtra
;
373 /* Extra data presented? */
374 if (lpDevMode
->dmDriverExtra
&& lpExtendedDevMode
->dmDriverExtra
)
376 /* We choose the smallest size */
377 if (lpDevMode
->dmDriverExtra
> lpExtendedDevMode
->dmDriverExtra
)
378 lpDevMode
->dmDriverExtra
= lpExtendedDevMode
->dmDriverExtra
;
380 /* Copy extra data */
381 RtlCopyMemory((PUCHAR
)lpDevMode
+ OldSize
,
382 lpExtendedDevMode
+ 1,
383 lpDevMode
->dmDriverExtra
);
386 /* If the size of source structure is less, than used, we clean unsupported flags */
387 if (OldSize
< FIELD_OFFSET(DEVMODEW
, dmPanningHeight
))
388 lpDevMode
->dmFields
&= ~DM_PANNINGHEIGHT
;
390 if (OldSize
< FIELD_OFFSET(DEVMODEW
, dmPanningWidth
))
391 lpDevMode
->dmFields
&= ~DM_PANNINGWIDTH
;
397 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode
);
408 EnumDisplaySettingsW(
409 LPCWSTR lpszDeviceName
,
411 LPDEVMODEW lpDevMode
)
414 lpDevMode
->dmSize
= FIELD_OFFSET(DEVMODEW
, dmICMMethod
);
415 lpDevMode
->dmDriverExtra
= 0;
417 return EnumDisplaySettingsExW(lpszDeviceName
, iModeNum
, lpDevMode
, 0);
430 if (lpmi
->cbSize
== sizeof (MONITORINFO
))
432 return NtUserGetMonitorInfo(hMonitor
, lpmi
);
434 else if (lpmi
->cbSize
!= sizeof (MONITORINFOEXA
))
436 SetLastError(ERROR_INVALID_PARAMETER
);
441 MONITORINFOEXW miExW
;
444 miExW
.cbSize
= sizeof (MONITORINFOEXW
);
445 if (!NtUserGetMonitorInfo(hMonitor
, (LPMONITORINFO
)&miExW
))
449 memcpy(lpmi
, &miExW
, sizeof (MONITORINFO
));
450 res
= WideCharToMultiByte(CP_THREAD_ACP
, 0, miExW
.szDevice
, -1,
451 ((LPMONITORINFOEXA
)lpmi
)->szDevice
, CCHDEVICENAME
,
455 WARN("WideCharToMultiByte() failed!\n");
473 return NtUserGetMonitorInfo(hMonitor
, lpmi
);
486 return NtUserMonitorFromPoint(ptPoint
, dwFlags
);
499 return NtUserMonitorFromRect(lpcRect
, dwFlags
);
512 return NtUserMonitorFromWindow(hWnd
, dwFlags
);
521 ChangeDisplaySettingsExA(
522 LPCSTR lpszDeviceName
,
523 LPDEVMODEA lpDevMode
,
529 UNICODE_STRING DeviceName
;
530 PUNICODE_STRING pDeviceName
= &DeviceName
;
532 if (lpszDeviceName
!= NULL
)
534 if (!RtlCreateUnicodeStringFromAsciiz(pDeviceName
, (PCSZ
)lpszDeviceName
))
536 SetLastError(ERROR_OUTOFMEMORY
);
537 return DISP_CHANGE_BADPARAM
; /* FIXME what to return? */
543 if (lpDevMode
!= NULL
)
545 LPDEVMODEW pDevModeW
;
546 pDevModeW
= GdiConvertToDevmodeW(lpDevMode
);
549 rc
= NtUserChangeDisplaySettings(pDeviceName
, pDevModeW
, dwflags
, lParam
);
550 RtlFreeHeap(GetProcessHeap(), 0, pDevModeW
);
553 rc
= DISP_CHANGE_SUCCESSFUL
;
556 rc
= NtUserChangeDisplaySettings(pDeviceName
, NULL
, dwflags
, lParam
);
558 if (lpszDeviceName
!= NULL
)
559 RtlFreeUnicodeString(&DeviceName
);
570 ChangeDisplaySettingsA(
571 LPDEVMODEA lpDevMode
,
575 lpDevMode
->dmDriverExtra
= 0;
576 return ChangeDisplaySettingsExA ( NULL
, lpDevMode
, NULL
, dwflags
, 0 );
585 ChangeDisplaySettingsExW(
586 LPCWSTR lpszDeviceName
,
587 LPDEVMODEW lpDevMode
,
593 UNICODE_STRING DeviceName
;
594 PUNICODE_STRING pDeviceName
= &DeviceName
;
596 if (lpszDeviceName
!= NULL
)
597 RtlInitUnicodeString(pDeviceName
, lpszDeviceName
);
601 rc
= NtUserChangeDisplaySettings(pDeviceName
, lpDevMode
, dwflags
, lParam
);
612 ChangeDisplaySettingsW(
613 LPDEVMODEW lpDevMode
,
617 lpDevMode
->dmDriverExtra
= 0;
618 return ChangeDisplaySettingsExW(NULL
, lpDevMode
, NULL
, dwflags
, 0);