1/**
2 * This file is part of the mingw-w64 runtime package.
3 * No warranty is given; refer to the file DISCLAIMER within this package.
4 */
5
6#include <winapifamily.h>
7
8#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
9
10#ifdef __cplusplus
11extern "C" {
12#endif
13
14#ifndef SM_CMONITORS
15
16#define SM_XVIRTUALSCREEN 76
17#define SM_YVIRTUALSCREEN 77
18#define SM_CXVIRTUALSCREEN 78
19#define SM_CYVIRTUALSCREEN 79
20#define SM_CMONITORS 80
21#define SM_SAMEDISPLAYFORMAT 81
22
23#define MONITOR_DEFAULTTONULL 0x00000000
24#define MONITOR_DEFAULTTOPRIMARY 0x00000001
25#define MONITOR_DEFAULTTONEAREST 0x00000002
26
27#define MONITORINFOF_PRIMARY 0x00000001
28
29  typedef struct tagMONITORINFO {
30    DWORD cbSize;
31    RECT rcMonitor;
32    RECT rcWork;
33    DWORD dwFlags;
34  } MONITORINFO,*LPMONITORINFO;
35
36#ifndef CCHDEVICENAME
37#define CCHDEVICENAME 32
38#endif
39
40#ifdef __cplusplus
41  typedef struct tagMONITORINFOEXA : public tagMONITORINFO {
42    CHAR szDevice[CCHDEVICENAME];
43  } MONITORINFOEXA,*LPMONITORINFOEXA;
44
45  typedef struct tagMONITORINFOEXW : public tagMONITORINFO {
46    WCHAR szDevice[CCHDEVICENAME];
47  } MONITORINFOEXW,*LPMONITORINFOEXW;
48#else
49  typedef struct tagMONITORINFOEXA {
50    __C89_NAMELESS struct {
51      DWORD cbSize;
52      RECT rcMonitor;
53      RECT rcWork;
54      DWORD dwFlags;
55    }; /* MONITORINFO */;
56    CHAR szDevice[CCHDEVICENAME];
57  } MONITORINFOEXA,*LPMONITORINFOEXA;
58
59  typedef struct tagMONITORINFOEXW {
60    __C89_NAMELESS struct {
61      DWORD cbSize;
62      RECT rcMonitor;
63      RECT rcWork;
64      DWORD dwFlags;
65    }; /* MONITORINFO */;
66    WCHAR szDevice[CCHDEVICENAME];
67  } MONITORINFOEXW,*LPMONITORINFOEXW;
68#endif
69  __MINGW_TYPEDEF_AW(MONITORINFOEX)
70  __MINGW_TYPEDEF_AW(LPMONITORINFOEX)
71
72  typedef WINBOOL (CALLBACK *MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);
73
74#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
75  typedef struct _DISPLAY_DEVICEA {
76    DWORD cb;
77    CHAR DeviceName[32];
78    CHAR DeviceString[128];
79    DWORD StateFlags;
80    CHAR DeviceID[128];
81    CHAR DeviceKey[128];
82  } DISPLAY_DEVICEA,*PDISPLAY_DEVICEA,*LPDISPLAY_DEVICEA;
83
84  typedef struct _DISPLAY_DEVICEW {
85    DWORD cb;
86    WCHAR DeviceName[32];
87    WCHAR DeviceString[128];
88    DWORD StateFlags;
89    WCHAR DeviceID[128];
90    WCHAR DeviceKey[128];
91  } DISPLAY_DEVICEW,*PDISPLAY_DEVICEW,*LPDISPLAY_DEVICEW;
92
93  __MINGW_TYPEDEF_AW(DISPLAY_DEVICE)
94  __MINGW_TYPEDEF_AW(PDISPLAY_DEVICE)
95  __MINGW_TYPEDEF_AW(LPDISPLAY_DEVICE)
96
97#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
98#define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
99#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
100#define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008
101#define DISPLAY_DEVICE_VGA_COMPATIBLE 0x00000010
102#endif
103#endif
104
105#undef GetMonitorInfo
106#undef GetSystemMetrics
107#undef MonitorFromWindow
108#undef MonitorFromRect
109#undef MonitorFromPoint
110#undef EnumDisplayMonitors
111#undef EnumDisplayDevices
112
113#ifdef COMPILE_MULTIMON_STUBS
114
115#ifndef MULTIMON_FNS_DEFINED
116  int (WINAPI *g_pfnGetSystemMetrics)(int) = NULL;
117  HMONITOR (WINAPI *g_pfnMonitorFromWindow)(HWND, DWORD) = NULL;
118  HMONITOR (WINAPI *g_pfnMonitorFromRect)(LPCRECT, DWORD) = NULL;
119  HMONITOR (WINAPI *g_pfnMonitorFromPoint)(POINT, DWORD) = NULL;
120  WINBOOL (WINAPI *g_pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO) = NULL;
121  WINBOOL (WINAPI *g_pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM) = NULL;
122  WINBOOL (WINAPI *g_pfnEnumDisplayDevices)(PVOID, DWORD, PDISPLAY_DEVICE, DWORD) = NULL;
123  WINBOOL g_fMultiMonInitDone = FALSE;
124  WINBOOL g_fMultimonPlatformNT = FALSE;
125#endif
126
127  WINBOOL IsPlatformNT() {
128    OSVERSIONINFOA oi = { 0 };
129
130    oi.dwOSVersionInfoSize = sizeof (osvi);
131    GetVersionExA ((OSVERSIONINFOA *) &oi);
132    return (oi.dwPlatformId == VER_PLATFORM_WIN32_NT);
133  }
134
135  WINBOOL InitMultipleMonitorStubs(void) {
136    HMODULE h;
137
138    if (g_fMultiMonInitDone)
139      return g_pfnGetMonitorInfo != NULL;
140
141    g_fMultimonPlatformNT = IsPlatformNT ();
142    h = GetModuleHandle (TEXT ("USER32"));
143
144    if (h
145        && (*((FARPROC *) &g_pfnGetSystemMetrics) = GetProcAddress (h, "GetSystemMetrics")) != NULL
146	&& (*((FARPROC *) &g_pfnMonitorFromWindow) = GetProcAddress (h, "MonitorFromWindow")) != NULL
147	&& (*((FARPROC *) &g_pfnMonitorFromRect) = GetProcAddress (h, "MonitorFromRect")) != NULL
148	&& (*((FARPROC *) &g_pfnMonitorFromPoint) = GetProcAddress (h, "MonitorFromPoint")) != NULL
149	&& (*((FARPROC *) &g_pfnEnumDisplayMonitors) = GetProcAddress (h, "EnumDisplayMonitors")) != NULL
150#ifdef UNICODE
151        && (*((FARPROC *) &g_pfnEnumDisplayDevices) = GetProcAddress (h, "EnumDisplayDevicesW")) != NULL
152	&& (*((FARPROC *) &g_pfnGetMonitorInfo) = (g_fMultimonPlatformNT ? GetProcAddress (h, "GetMonitorInfoW") : GetProcAddress (h, "GetMonitorInfoA"))) != NULL
153#else
154        && (*((FARPROC *) &g_pfnGetMonitorInfo) = GetProcAddress (h, "GetMonitorInfoA")) != NULL
155	&& (*((FARPROC *) &g_pfnEnumDisplayDevices) = GetProcAddress (h, "EnumDisplayDevicesA")) != NULL
156#endif
157    ) {
158      g_fMultiMonInitDone = TRUE;
159      return TRUE;
160    }
161
162    g_pfnGetSystemMetrics = NULL;
163    g_pfnMonitorFromWindow = NULL;
164    g_pfnMonitorFromRect = NULL;
165    g_pfnMonitorFromPoint = NULL;
166    g_pfnGetMonitorInfo = NULL;
167    g_pfnEnumDisplayMonitors = NULL;
168    g_pfnEnumDisplayDevices = NULL;
169    g_fMultiMonInitDone = TRUE;
170    return FALSE;
171  }
172
173  int WINAPI xGetSystemMetrics(int n) {
174    if (InitMultipleMonitorStubs ())
175      return g_pfnGetSystemMetrics (n);
176
177    switch (n) {
178    case SM_CMONITORS:
179    case SM_SAMEDISPLAYFORMAT:
180      return 1;
181    case SM_XVIRTUALSCREEN:
182    case SM_YVIRTUALSCREEN:
183      return 0;
184    case SM_CXVIRTUALSCREEN:
185      return GetSystemMetrics (SM_CXSCREEN);
186    case SM_CYVIRTUALSCREEN:
187      return GetSystemMetrics (SM_CYSCREEN);
188    default:
189      break;
190    }
191
192    return GetSystemMetrics (n);
193  }
194
195#define xPRIMARY_MONITOR ((HMONITOR)0x12340042)
196
197  HMONITOR WINAPI xMonitorFromPoint (POINT pt, DWORD flags) {
198    if (InitMultipleMonitorStubs ())
199      return g_pfnMonitorFromPoint (pt, flags);
200
201    if ((flags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) != 0
202        || (pt.x >= 0 && pt.y >= 0 && pt.x < GetSystemMetrics (SM_CXSCREEN) && pt.y < GetSystemMetrics (SM_CYSCREEN)))
203      return xPRIMARY_MONITOR;
204
205    return NULL;
206  }
207
208  HMONITOR WINAPI xMonitorFromRect (LPCRECT pr, DWORD flags) {
209    if (InitMultipleMonitorStubs ())
210      return g_pfnMonitorFromRect (pr, flags);
211
212    if ((flags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) != 0
213        || (pr->right > 0 && pr->bottom > 0 && pr->left < GetSystemMetrics (SM_CXSCREEN) && pr->top < GetSystemMetrics (SM_CYSCREEN)))
214      return xPRIMARY_MONITOR;
215
216    return NULL;
217  }
218
219  HMONITOR WINAPI xMonitorFromWindow (HWND hw, DWORD flags) {
220    WINDOWPLACEMENT wp;
221
222    if (InitMultipleMonitorStubs ())
223      return g_pfnMonitorFromWindow (hw, flags);
224
225    if ((flags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) != 0)
226      return xPRIMARY_MONITOR;
227
228    if ((IsIconic (hw) ? GetWindowPlacement (hw, &wp) : GetWindowRect (hw, &wp.rcNormalPosition)) != 0)
229      return xMonitorFromRect (&wp.rcNormalPosition, flags);
230
231    return NULL;
232  }
233
234  WINBOOL WINAPI xGetMonitorInfo (HMONITOR hmon, LPMONITORINFO pmi) {
235    RECT r;
236    WINBOOL f;
237    union { LPMONITORINFO mi; MONITORINFOEX ex; } c;
238
239    c.mi = pmi;
240    if (InitMultipleMonitorStubs ()) {
241      f = g_pfnGetMonitorInfo (hmon, pmi);
242#ifdef UNICODE
243      if (f && !g_fMultimonPlatformNT && pmi->cbSize >= sizeof (MONITORINFOEX))
244	MultiByteToWideChar (CP_ACP, 0, (LPSTR) c.ex->szDevice, -1, c.ex->szDevice, (sizeof (c.ex->szDevice) / 2));
245#endif
246      return f;
247    }
248
249    if ((hmon == xPRIMARY_MONITOR) && pmi &&(pmi->cbSize >= sizeof (MONITORINFO)) && SystemParametersInfoA (SPI_GETWORKAREA, 0,&r, 0)) {
250      pmi->rcMonitor.left = 0;
251      pmi->rcMonitor.top = 0;
252      pmi->rcMonitor.right = GetSystemMetrics (SM_CXSCREEN);
253      pmi->rcMonitor.bottom = GetSystemMetrics (SM_CYSCREEN);
254      pmi->rcWork = r;
255      pmi->dwFlags = MONITORINFOF_PRIMARY;
256      if (pmi->cbSize >= sizeof (MONITORINFOEX)) {
257#ifdef UNICODE
258	MultiByteToWideChar (CP_ACP, 0, "DISPLAY", -1, c.ex->szDevice, (sizeof (c.ex->szDevice) / 2));
259#else
260	lstrcpyn (c.ex->szDevice, "DISPLAY", sizeof (c.ex->szDevice));
261#endif
262      }
263
264      return TRUE;
265    }
266
267    return FALSE;
268  }
269
270  WINBOOL WINAPI xEnumDisplayMonitors (HDC hdcOptionalForPainting, LPCRECT lprcEnumMonitorsThatIntersect, MONITORENUMPROC lpfnEnumProc, LPARAM dwData) {
271    RECT rcLimit, rcClip;
272    POINT ptOrg;
273
274    if (InitMultipleMonitorStubs ())
275      return g_pfnEnumDisplayMonitors (hdcOptionalForPainting, lprcEnumMonitorsThatIntersect, lpfnEnumProc, dwData);
276
277    if (!lpfnEnumProc)
278      return FALSE;
279
280    rcLimit.left = rcLimit.top = 0;
281    rcLimit.right = GetSystemMetrics (SM_CXSCREEN);
282    rcLimit.bottom = GetSystemMetrics (SM_CYSCREEN);
283
284    if (hdcOptionalForPainting) {
285      switch (GetClipBox (hdcOptionalForPainting,&rcClip)) {
286      default:
287	if (!GetDCOrgEx (hdcOptionalForPainting,&ptOrg))
288	  return FALSE;
289
290	OffsetRect (&rcLimit, -ptOrg.x, -ptOrg.y);
291
292	if (IntersectRect (&rcLimit, &rcLimit, &rcClip)
293	    && (!lprcEnumMonitorsThatIntersect || IntersectRect (&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect)))
294	  break;
295
296      case NULLREGION:
297	return TRUE;
298      case ERROR:
299	return FALSE;
300      }
301    } else if (lprcEnumMonitorsThatIntersect && !IntersectRect (&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect))
302      return TRUE;
303
304    return lpfnEnumProc (xPRIMARY_MONITOR, hdcOptionalForPainting, &rcLimit, dwData);
305  }
306
307  WINBOOL WINAPI xEnumDisplayDevices (PVOID Unused, DWORD iDevNum, PDISPLAY_DEVICE lpDisplayDevice, DWORD flags) {
308    if (InitMultipleMonitorStubs ())
309      return g_pfnEnumDisplayDevices (Unused, iDevNum, lpDisplayDevice, flags);
310    if (Unused || iDevNum || lpDisplayDevice == NULL || lpDisplayDevice->cb < sizeof (DISPLAY_DEVICE))
311      return FALSE;
312#ifdef UNICODE
313    MultiByteToWideChar (CP_ACP, 0, "DISPLAY", -1, lpDisplayDevice->DeviceName, (sizeof (lpDisplayDevice->DeviceName) / 2));
314    MultiByteToWideChar (CP_ACP, 0, "DISPLAY", -1, lpDisplayDevice->DeviceString, (sizeof (lpDisplayDevice->DeviceString) / 2));
315#else
316    lstrcpyn ((LPTSTR)lpDisplayDevice->DeviceName, "DISPLAY", sizeof (lpDisplayDevice->DeviceName));
317    lstrcpyn ((LPTSTR)lpDisplayDevice->DeviceString, "DISPLAY", sizeof (lpDisplayDevice->DeviceString));
318#endif
319    lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE;
320
321    return TRUE;
322  }
323
324#undef xPRIMARY_MONITOR
325#undef COMPILE_MULTIMON_STUBS
326#else
327  extern int WINAPI xGetSystemMetrics (int);
328  extern HMONITOR WINAPI xMonitorFromWindow (HWND, DWORD);
329  extern HMONITOR WINAPI xMonitorFromRect (LPCRECT, DWORD);
330  extern HMONITOR WINAPI xMonitorFromPoint (POINT, DWORD);
331  extern WINBOOL WINAPI xGetMonitorInfo (HMONITOR, LPMONITORINFO);
332  extern WINBOOL WINAPI xEnumDisplayMonitors (HDC, LPCRECT, MONITORENUMPROC, LPARAM);
333  extern WINBOOL WINAPI xEnumDisplayDevices (PVOID, DWORD, PDISPLAY_DEVICE, DWORD);
334#endif
335
336#define GetSystemMetrics xGetSystemMetrics
337#define MonitorFromWindow xMonitorFromWindow
338#define MonitorFromRect xMonitorFromRect
339#define MonitorFromPoint xMonitorFromPoint
340#define GetMonitorInfo xGetMonitorInfo
341#define EnumDisplayMonitors xEnumDisplayMonitors
342#define EnumDisplayDevices xEnumDisplayDevices
343
344#ifdef __cplusplus
345}
346#endif
347
348#endif
349