xref: /reactos/win32ss/user/user32/misc/display.c (revision 3d93998d)
1 /*
2  * PROJECT:         ReactOS user32.dll
3  * FILE:            win32ss/user/user32/misc/display.c
4  * PURPOSE:         DDE
5  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
6  */
7 
8 #include <user32.h>
9 
10 WINE_DEFAULT_DEBUG_CHANNEL(user32);
11 
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
18 
19 /*
20  * @implemented
21  */
22 BOOL WINAPI
EnumDisplayDevicesA(LPCSTR lpDevice,DWORD iDevNum,PDISPLAY_DEVICEA lpDisplayDevice,DWORD dwFlags)23 EnumDisplayDevicesA(
24     LPCSTR lpDevice,
25     DWORD iDevNum,
26     PDISPLAY_DEVICEA lpDisplayDevice,
27     DWORD dwFlags)
28 {
29     BOOL rc;
30     UNICODE_STRING Device;
31     DISPLAY_DEVICEW DisplayDeviceW;
32 
33     if (!RtlCreateUnicodeStringFromAsciiz(&Device, (PCSZ)lpDevice))
34     {
35         SetLastError(ERROR_OUTOFMEMORY);
36         return FALSE;
37     }
38 
39     RtlZeroMemory(&DisplayDeviceW, sizeof(DISPLAY_DEVICEW));
40     DisplayDeviceW.cb = sizeof(DISPLAY_DEVICEW);
41     rc = NtUserEnumDisplayDevices(&Device,
42                                   iDevNum,
43                                   &DisplayDeviceW,
44                                   dwFlags);
45     if (rc)
46     {
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]),
52                             NULL, NULL);
53         WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceString, -1,
54                             lpDisplayDevice->DeviceString,
55                             sizeof(lpDisplayDevice->DeviceString) / sizeof(lpDisplayDevice->DeviceString[0]),
56                             NULL, NULL);
57         WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceID, -1,
58                             lpDisplayDevice->DeviceID,
59                             sizeof(lpDisplayDevice->DeviceID) / sizeof(lpDisplayDevice->DeviceID[0]),
60                             NULL, NULL);
61         WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceKey, -1,
62                             lpDisplayDevice->DeviceKey,
63                             sizeof(lpDisplayDevice->DeviceKey) / sizeof(lpDisplayDevice->DeviceKey[0]),
64                             NULL, NULL);
65     }
66 
67     RtlFreeUnicodeString(&Device);
68 
69     return rc;
70 }
71 
72 
73 /*
74  * @implemented
75  */
76 BOOL
77 WINAPI
EnumDisplayDevicesW(LPCWSTR lpDevice,DWORD iDevNum,PDISPLAY_DEVICEW lpDisplayDevice,DWORD dwFlags)78 EnumDisplayDevicesW(
79     LPCWSTR lpDevice,
80     DWORD iDevNum,
81     PDISPLAY_DEVICEW lpDisplayDevice,
82     DWORD dwFlags)
83 {
84     UNICODE_STRING Device;
85     BOOL rc;
86 
87     RtlInitUnicodeString(&Device, lpDevice);
88 
89     rc = NtUserEnumDisplayDevices(
90              &Device,
91              iDevNum,
92              lpDisplayDevice,
93              dwFlags);
94 
95     return rc;
96 }
97 
98 
99 /*
100  * @implemented
101  */
102 BOOL
103 WINAPI
EnumDisplayMonitors(HDC hdc,LPCRECT lprcClip,MONITORENUMPROC lpfnEnum,LPARAM dwData)104 EnumDisplayMonitors(
105     HDC hdc,
106     LPCRECT lprcClip,
107     MONITORENUMPROC lpfnEnum,
108     LPARAM dwData)
109 {
110     INT iCount, i;
111     HMONITOR *hMonitorList;
112     LPRECT pRectList;
113     HANDLE hHeap;
114     BOOL ret = FALSE;
115 
116     /* get list of monitors/rects */
117     iCount = NtUserEnumDisplayMonitors(hdc, lprcClip, NULL, NULL, 0);
118     if (iCount < 0)
119     {
120         /* FIXME: SetLastError() */
121         return FALSE;
122     }
123     if (iCount == 0)
124     {
125         return TRUE;
126     }
127 
128     hHeap = GetProcessHeap();
129     hMonitorList = HeapAlloc(hHeap, 0, sizeof (HMONITOR) * iCount);
130     if (hMonitorList == NULL)
131     {
132         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
133         return FALSE;
134     }
135     pRectList = HeapAlloc(hHeap, 0, sizeof (RECT) * iCount);
136     if (pRectList == NULL)
137     {
138         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
139         goto cleanup;
140     }
141 
142     iCount = NtUserEnumDisplayMonitors(hdc, lprcClip, hMonitorList, pRectList, iCount);
143     if (iCount <= 0)
144     {
145         /* FIXME: SetLastError() */
146         goto cleanup;
147     }
148 
149     /* enumerate list */
150     for (i = 0; i < iCount; i++)
151     {
152         HMONITOR hMonitor = hMonitorList[i];
153         LPRECT pMonitorRect = pRectList + i;
154         HDC hMonitorDC = NULL;
155 
156         if (hdc != NULL)
157         {
158             /* make monitor DC */
159             hMonitorDC = hdc;
160         }
161 
162         if (!lpfnEnum(hMonitor, hMonitorDC, pMonitorRect, dwData))
163             goto cleanup; /* return FALSE */
164     }
165 
166     ret = TRUE;
167 
168 cleanup:
169     if(hMonitorList)
170         HeapFree(hHeap, 0, hMonitorList);
171     if(pRectList)
172         HeapFree(hHeap, 0, pRectList);
173     return ret;
174 }
175 
176 
177 /*
178  * @implemented
179  */
180 BOOL
181 WINAPI
EnumDisplaySettingsExA(LPCSTR lpszDeviceName,DWORD iModeNum,LPDEVMODEA lpDevMode,DWORD dwFlags)182 EnumDisplaySettingsExA(
183     LPCSTR lpszDeviceName,
184     DWORD iModeNum,
185     LPDEVMODEA lpDevMode,
186     DWORD dwFlags)
187 {
188     NTSTATUS Status;
189     UNICODE_STRING usDeviceName;
190     PUNICODE_STRING pusDeviceName = NULL;
191     LPDEVMODEW lpExtendedDevMode;
192     BOOL Result = FALSE;
193 
194     if (lpszDeviceName)
195     {
196         if (!RtlCreateUnicodeStringFromAsciiz(&usDeviceName, (PCSZ)lpszDeviceName))
197         {
198             SetLastError(ERROR_OUTOFMEMORY);
199             return FALSE;
200         }
201         pusDeviceName = &usDeviceName;
202     }
203 
204     /* Allocate memory for DEVMODEW and extra data */
205     lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(),
206                                         HEAP_ZERO_MEMORY,
207                                         sizeof(DEVMODEW) + lpDevMode->dmDriverExtra);
208     if (!lpExtendedDevMode)
209     {
210         if (pusDeviceName)
211             RtlFreeUnicodeString(&usDeviceName);
212 
213         return FALSE;
214     }
215 
216     /* Initialize structure fields */
217     lpExtendedDevMode->dmSize = sizeof(DEVMODEW);
218     lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra;
219 
220     Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags);
221 
222     if (pusDeviceName)
223         RtlFreeUnicodeString(&usDeviceName);
224 
225     if (NT_SUCCESS(Status))
226     {
227         /* Store old structure size */
228         WORD OldSize = lpDevMode->dmSize;
229 
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
232 
233         COPYS(dmDeviceName, CCHDEVICENAME);
234         COPYN(dmSpecVersion);
235         COPYN(dmDriverVersion);
236         COPYN(dmFields);
237         COPYN(dmPosition.x);
238         COPYN(dmPosition.y);
239         COPYN(dmScale);
240         COPYN(dmCopies);
241         COPYN(dmDefaultSource);
242         COPYN(dmPrintQuality);
243         COPYN(dmColor);
244         COPYN(dmDuplex);
245         COPYN(dmYResolution);
246         COPYN(dmTTOption);
247         COPYN(dmCollate);
248         COPYS(dmFormName,CCHFORMNAME);
249         COPYN(dmLogPixels);
250         COPYN(dmBitsPerPel);
251         COPYN(dmPelsWidth);
252         COPYN(dmPelsHeight);
253         COPYN(dmDisplayFlags); // aka dmNup
254         COPYN(dmDisplayFrequency);
255 
256         /* we're done with 0x300 fields */
257         if (OldSize > SIZEOF_DEVMODEA_300)
258         {
259             COPYN(dmICMMethod);
260             COPYN(dmICMIntent);
261             COPYN(dmMediaType);
262             COPYN(dmDitherType);
263             COPYN(dmReserved1);
264             COPYN(dmReserved2);
265 
266             /* we're done with 0x400 fields */
267             if (OldSize > SIZEOF_DEVMODEA_400)
268             {
269                 COPYN(dmPanningWidth);
270                 COPYN(dmPanningHeight);
271             }
272         }
273 
274         /* Restore old size */
275         lpDevMode->dmSize = OldSize;
276 
277         /* Extra data presented? */
278         if (lpDevMode->dmDriverExtra && lpExtendedDevMode->dmDriverExtra)
279         {
280             /* We choose the smallest size */
281             if (lpDevMode->dmDriverExtra > lpExtendedDevMode->dmDriverExtra)
282                 lpDevMode->dmDriverExtra = lpExtendedDevMode->dmDriverExtra;
283 
284             /* Copy extra data */
285             RtlCopyMemory((PUCHAR)lpDevMode + OldSize,
286                           lpExtendedDevMode + 1,
287                           lpDevMode->dmDriverExtra);
288         }
289 
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;
293 
294         if (OldSize < FIELD_OFFSET(DEVMODEA, dmPanningWidth))
295             lpDevMode->dmFields &= ~DM_PANNINGWIDTH;
296 
297         Result = TRUE;
298     }
299 
300     /* Free memory */
301     RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode);
302 
303     return Result;
304 }
305 
306 
307 /*
308  * @implemented
309  */
310 BOOL
311 WINAPI
EnumDisplaySettingsA(LPCSTR lpszDeviceName,DWORD iModeNum,LPDEVMODEA lpDevMode)312 EnumDisplaySettingsA(
313     LPCSTR lpszDeviceName,
314     DWORD iModeNum,
315     LPDEVMODEA lpDevMode)
316 {
317     /* Fixup sizes */
318     lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod);
319     lpDevMode->dmDriverExtra = 0;
320 
321     return EnumDisplaySettingsExA(lpszDeviceName, iModeNum, lpDevMode, 0);
322 }
323 
324 
325 /*
326  * @implemented
327  */
328 BOOL
329 WINAPI
EnumDisplaySettingsExW(LPCWSTR lpszDeviceName,DWORD iModeNum,LPDEVMODEW lpDevMode,DWORD dwFlags)330 EnumDisplaySettingsExW(
331     LPCWSTR lpszDeviceName,
332     DWORD iModeNum,
333     LPDEVMODEW lpDevMode,
334     DWORD dwFlags)
335 {
336     NTSTATUS Status;
337     UNICODE_STRING usDeviceName;
338     PUNICODE_STRING pusDeviceName = NULL;
339     LPDEVMODEW lpExtendedDevMode;
340     BOOL Result = FALSE;
341 
342     if (lpszDeviceName)
343     {
344         RtlInitUnicodeString(&usDeviceName, lpszDeviceName);
345         pusDeviceName = &usDeviceName;
346     }
347 
348     /* Allocate memory for DEVMODEW and extra data */
349     lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(),
350                                         HEAP_ZERO_MEMORY,
351                                         sizeof(DEVMODEW) + lpDevMode->dmDriverExtra);
352     if (!lpExtendedDevMode)
353         return FALSE;
354 
355     /* Initialize structure fields */
356     lpExtendedDevMode->dmSize = sizeof(DEVMODEW);
357     lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra;
358 
359     Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags);
360     if (NT_SUCCESS(Status))
361     {
362         /* Store old structure sizes */
363         WORD OldSize = lpDevMode->dmSize;
364         WORD OldDriverExtra = lpDevMode->dmDriverExtra;
365 
366         /* Copy general data */
367         RtlCopyMemory(lpDevMode, lpExtendedDevMode, OldSize);
368 
369         /* Restore old sizes */
370         lpDevMode->dmSize = OldSize;
371         lpDevMode->dmDriverExtra = OldDriverExtra;
372 
373         /* Extra data presented? */
374         if (lpDevMode->dmDriverExtra && lpExtendedDevMode->dmDriverExtra)
375         {
376             /* We choose the smallest size */
377             if (lpDevMode->dmDriverExtra > lpExtendedDevMode->dmDriverExtra)
378                 lpDevMode->dmDriverExtra = lpExtendedDevMode->dmDriverExtra;
379 
380             /* Copy extra data */
381             RtlCopyMemory((PUCHAR)lpDevMode + OldSize,
382                           lpExtendedDevMode + 1,
383                           lpDevMode->dmDriverExtra);
384         }
385 
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;
389 
390         if (OldSize < FIELD_OFFSET(DEVMODEW, dmPanningWidth))
391             lpDevMode->dmFields &= ~DM_PANNINGWIDTH;
392 
393         Result = TRUE;
394     }
395 
396     /* Free memory */
397     RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode);
398 
399     return Result;
400 }
401 
402 
403 /*
404  * @implemented
405  */
406 BOOL
407 WINAPI
EnumDisplaySettingsW(LPCWSTR lpszDeviceName,DWORD iModeNum,LPDEVMODEW lpDevMode)408 EnumDisplaySettingsW(
409     LPCWSTR lpszDeviceName,
410     DWORD iModeNum,
411     LPDEVMODEW lpDevMode)
412 {
413     /* Fixup sizes */
414     lpDevMode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
415     lpDevMode->dmDriverExtra = 0;
416 
417     return EnumDisplaySettingsExW(lpszDeviceName, iModeNum, lpDevMode, 0);
418 }
419 
420 
421 /*
422  * @implemented
423  */
424 BOOL
425 WINAPI
GetMonitorInfoA(HMONITOR hMonitor,LPMONITORINFO lpmi)426 GetMonitorInfoA(
427     HMONITOR hMonitor,
428     LPMONITORINFO lpmi)
429 {
430     if (lpmi->cbSize == sizeof (MONITORINFO))
431     {
432         return NtUserGetMonitorInfo(hMonitor, lpmi);
433     }
434     else if (lpmi->cbSize != sizeof (MONITORINFOEXA))
435     {
436         SetLastError(ERROR_INVALID_PARAMETER);
437         return FALSE;
438     }
439     else
440     {
441         MONITORINFOEXW miExW;
442         INT res;
443 
444         miExW.cbSize = sizeof (MONITORINFOEXW);
445         if (!NtUserGetMonitorInfo(hMonitor, (LPMONITORINFO)&miExW))
446         {
447             return FALSE;
448         }
449         memcpy(lpmi, &miExW, sizeof (MONITORINFO));
450         res = WideCharToMultiByte(CP_THREAD_ACP, 0, miExW.szDevice, -1,
451                                   ((LPMONITORINFOEXA)lpmi)->szDevice, CCHDEVICENAME,
452                                   NULL, NULL);
453         if (res == 0)
454         {
455             WARN("WideCharToMultiByte() failed!\n");
456             return FALSE;
457         }
458     }
459 
460     return TRUE;
461 }
462 
463 
464 /*
465  * @implemented
466  */
467 BOOL
468 WINAPI
GetMonitorInfoW(HMONITOR hMonitor,LPMONITORINFO lpmi)469 GetMonitorInfoW(
470     HMONITOR hMonitor,
471     LPMONITORINFO lpmi)
472 {
473     return NtUserGetMonitorInfo(hMonitor, lpmi);
474 }
475 
476 
477 /*
478  * @implemented
479  */
480 HMONITOR
481 WINAPI
MonitorFromPoint(IN POINT ptPoint,IN DWORD dwFlags)482 MonitorFromPoint(
483     IN POINT ptPoint,
484     IN DWORD dwFlags )
485 {
486     return NtUserMonitorFromPoint(ptPoint, dwFlags);
487 }
488 
489 
490 /*
491  * @implemented
492  */
493 HMONITOR
494 WINAPI
MonitorFromRect(IN LPCRECT lpcRect,IN DWORD dwFlags)495 MonitorFromRect(
496     IN LPCRECT lpcRect,
497     IN DWORD dwFlags )
498 {
499     return NtUserMonitorFromRect(lpcRect, dwFlags);
500 }
501 
502 
503 /*
504  * @implemented
505  */
506 HMONITOR
507 WINAPI
MonitorFromWindow(IN HWND hWnd,IN DWORD dwFlags)508 MonitorFromWindow(
509     IN HWND hWnd,
510     IN DWORD dwFlags )
511 {
512     return NtUserMonitorFromWindow(hWnd, dwFlags);
513 }
514 
515 
516 /*
517  * @implemented
518  */
519 LONG
520 WINAPI
ChangeDisplaySettingsExA(LPCSTR lpszDeviceName,LPDEVMODEA lpDevMode,HWND hwnd,DWORD dwflags,LPVOID lParam)521 ChangeDisplaySettingsExA(
522     LPCSTR lpszDeviceName,
523     LPDEVMODEA lpDevMode,
524     HWND hwnd,
525     DWORD dwflags,
526     LPVOID lParam)
527 {
528     LONG rc;
529     UNICODE_STRING DeviceName;
530     PUNICODE_STRING pDeviceName = &DeviceName;
531 
532     if (lpszDeviceName != NULL)
533     {
534         if (!RtlCreateUnicodeStringFromAsciiz(pDeviceName, (PCSZ)lpszDeviceName))
535         {
536             SetLastError(ERROR_OUTOFMEMORY);
537             return DISP_CHANGE_BADPARAM; /* FIXME what to return? */
538         }
539     }
540     else
541         pDeviceName = NULL;
542 
543     if (lpDevMode != NULL)
544     {
545         LPDEVMODEW pDevModeW;
546         pDevModeW = GdiConvertToDevmodeW(lpDevMode);
547         if(pDevModeW)
548         {
549             rc = NtUserChangeDisplaySettings(pDeviceName, pDevModeW, dwflags, lParam);
550             RtlFreeHeap(GetProcessHeap(), 0, pDevModeW);
551         }
552         else
553             rc = DISP_CHANGE_SUCCESSFUL;
554     }
555     else
556         rc = NtUserChangeDisplaySettings(pDeviceName, NULL, dwflags, lParam);
557 
558     if (lpszDeviceName != NULL)
559         RtlFreeUnicodeString(&DeviceName);
560 
561     return rc;
562 }
563 
564 
565 /*
566  * @implemented
567  */
568 LONG
569 WINAPI
ChangeDisplaySettingsA(LPDEVMODEA lpDevMode,DWORD dwflags)570 ChangeDisplaySettingsA(
571     LPDEVMODEA lpDevMode,
572     DWORD dwflags)
573 {
574     if(lpDevMode)
575         lpDevMode->dmDriverExtra = 0;
576     return ChangeDisplaySettingsExA ( NULL, lpDevMode, NULL, dwflags, 0 );
577 }
578 
579 
580 /*
581  * @implemented
582  */
583 LONG
584 WINAPI
ChangeDisplaySettingsExW(LPCWSTR lpszDeviceName,LPDEVMODEW lpDevMode,HWND hwnd,DWORD dwflags,LPVOID lParam)585 ChangeDisplaySettingsExW(
586     LPCWSTR lpszDeviceName,
587     LPDEVMODEW lpDevMode,
588     HWND hwnd,
589     DWORD dwflags,
590     LPVOID lParam)
591 {
592     LONG rc;
593     UNICODE_STRING DeviceName;
594     PUNICODE_STRING pDeviceName = &DeviceName;
595 
596     if (lpszDeviceName != NULL)
597         RtlInitUnicodeString(pDeviceName, lpszDeviceName);
598     else
599         pDeviceName = NULL;
600 
601     rc = NtUserChangeDisplaySettings(pDeviceName, lpDevMode, dwflags, lParam);
602 
603     return rc;
604 }
605 
606 
607 /*
608  * @implemented
609  */
610 LONG
611 WINAPI
ChangeDisplaySettingsW(LPDEVMODEW lpDevMode,DWORD dwflags)612 ChangeDisplaySettingsW(
613     LPDEVMODEW lpDevMode,
614     DWORD dwflags)
615 {
616     if(lpDevMode)
617         lpDevMode->dmDriverExtra = 0;
618     return ChangeDisplaySettingsExW(NULL, lpDevMode, NULL, dwflags, 0);
619 }
620