2 * System parameters functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "wine/wingdi16.h"
43 #include "user_private.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(system
);
50 DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_GPU_LUID
, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 1);
51 DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID
, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 2);
53 /* Wine specific monitor properties */
54 DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS
, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
55 DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME
, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5);
58 static HDC display_dc
;
59 static CRITICAL_SECTION display_dc_section
;
60 static CRITICAL_SECTION_DEBUG critsect_debug
=
62 0, 0, &display_dc_section
,
63 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
64 0, 0, { (DWORD_PTR
)(__FILE__
": display_dc_section") }
66 static CRITICAL_SECTION display_dc_section
= { &critsect_debug
, -1 ,0, 0, 0, 0 };
69 /* System parameters storage */
70 static UINT system_dpi
;
72 static void SYSPARAMS_LogFont32WTo32A( const LOGFONTW
* font32W
, LPLOGFONTA font32A
)
74 font32A
->lfHeight
= font32W
->lfHeight
;
75 font32A
->lfWidth
= font32W
->lfWidth
;
76 font32A
->lfEscapement
= font32W
->lfEscapement
;
77 font32A
->lfOrientation
= font32W
->lfOrientation
;
78 font32A
->lfWeight
= font32W
->lfWeight
;
79 font32A
->lfItalic
= font32W
->lfItalic
;
80 font32A
->lfUnderline
= font32W
->lfUnderline
;
81 font32A
->lfStrikeOut
= font32W
->lfStrikeOut
;
82 font32A
->lfCharSet
= font32W
->lfCharSet
;
83 font32A
->lfOutPrecision
= font32W
->lfOutPrecision
;
84 font32A
->lfClipPrecision
= font32W
->lfClipPrecision
;
85 font32A
->lfQuality
= font32W
->lfQuality
;
86 font32A
->lfPitchAndFamily
= font32W
->lfPitchAndFamily
;
87 WideCharToMultiByte( CP_ACP
, 0, font32W
->lfFaceName
, -1, font32A
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
88 font32A
->lfFaceName
[LF_FACESIZE
-1] = 0;
91 static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA
* font32A
, LPLOGFONTW font32W
)
93 font32W
->lfHeight
= font32A
->lfHeight
;
94 font32W
->lfWidth
= font32A
->lfWidth
;
95 font32W
->lfEscapement
= font32A
->lfEscapement
;
96 font32W
->lfOrientation
= font32A
->lfOrientation
;
97 font32W
->lfWeight
= font32A
->lfWeight
;
98 font32W
->lfItalic
= font32A
->lfItalic
;
99 font32W
->lfUnderline
= font32A
->lfUnderline
;
100 font32W
->lfStrikeOut
= font32A
->lfStrikeOut
;
101 font32W
->lfCharSet
= font32A
->lfCharSet
;
102 font32W
->lfOutPrecision
= font32A
->lfOutPrecision
;
103 font32W
->lfClipPrecision
= font32A
->lfClipPrecision
;
104 font32W
->lfQuality
= font32A
->lfQuality
;
105 font32W
->lfPitchAndFamily
= font32A
->lfPitchAndFamily
;
106 MultiByteToWideChar( CP_ACP
, 0, font32A
->lfFaceName
, -1, font32W
->lfFaceName
, LF_FACESIZE
);
107 font32W
->lfFaceName
[LF_FACESIZE
-1] = 0;
110 static void SYSPARAMS_NonClientMetrics32WTo32A( const NONCLIENTMETRICSW
* lpnm32W
, LPNONCLIENTMETRICSA lpnm32A
)
112 lpnm32A
->iBorderWidth
= lpnm32W
->iBorderWidth
;
113 lpnm32A
->iScrollWidth
= lpnm32W
->iScrollWidth
;
114 lpnm32A
->iScrollHeight
= lpnm32W
->iScrollHeight
;
115 lpnm32A
->iCaptionWidth
= lpnm32W
->iCaptionWidth
;
116 lpnm32A
->iCaptionHeight
= lpnm32W
->iCaptionHeight
;
117 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfCaptionFont
, &lpnm32A
->lfCaptionFont
);
118 lpnm32A
->iSmCaptionWidth
= lpnm32W
->iSmCaptionWidth
;
119 lpnm32A
->iSmCaptionHeight
= lpnm32W
->iSmCaptionHeight
;
120 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfSmCaptionFont
, &lpnm32A
->lfSmCaptionFont
);
121 lpnm32A
->iMenuWidth
= lpnm32W
->iMenuWidth
;
122 lpnm32A
->iMenuHeight
= lpnm32W
->iMenuHeight
;
123 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfMenuFont
, &lpnm32A
->lfMenuFont
);
124 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfStatusFont
, &lpnm32A
->lfStatusFont
);
125 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfMessageFont
, &lpnm32A
->lfMessageFont
);
126 if (lpnm32A
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
))
128 if (lpnm32W
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSW
, iPaddedBorderWidth
))
129 lpnm32A
->iPaddedBorderWidth
= lpnm32W
->iPaddedBorderWidth
;
131 lpnm32A
->iPaddedBorderWidth
= 0;
135 static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA
* lpnm32A
, LPNONCLIENTMETRICSW lpnm32W
)
137 lpnm32W
->iBorderWidth
= lpnm32A
->iBorderWidth
;
138 lpnm32W
->iScrollWidth
= lpnm32A
->iScrollWidth
;
139 lpnm32W
->iScrollHeight
= lpnm32A
->iScrollHeight
;
140 lpnm32W
->iCaptionWidth
= lpnm32A
->iCaptionWidth
;
141 lpnm32W
->iCaptionHeight
= lpnm32A
->iCaptionHeight
;
142 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfCaptionFont
, &lpnm32W
->lfCaptionFont
);
143 lpnm32W
->iSmCaptionWidth
= lpnm32A
->iSmCaptionWidth
;
144 lpnm32W
->iSmCaptionHeight
= lpnm32A
->iSmCaptionHeight
;
145 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfSmCaptionFont
, &lpnm32W
->lfSmCaptionFont
);
146 lpnm32W
->iMenuWidth
= lpnm32A
->iMenuWidth
;
147 lpnm32W
->iMenuHeight
= lpnm32A
->iMenuHeight
;
148 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfMenuFont
, &lpnm32W
->lfMenuFont
);
149 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfStatusFont
, &lpnm32W
->lfStatusFont
);
150 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfMessageFont
, &lpnm32W
->lfMessageFont
);
151 if (lpnm32W
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSW
, iPaddedBorderWidth
))
153 if (lpnm32A
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
))
154 lpnm32W
->iPaddedBorderWidth
= lpnm32A
->iPaddedBorderWidth
;
156 lpnm32W
->iPaddedBorderWidth
= 0;
161 /* Helper functions to retrieve monitors info */
163 static BOOL CALLBACK
get_virtual_screen_proc( HMONITOR monitor
, HDC hdc
, LPRECT rect
, LPARAM lp
)
165 RECT
*virtual_rect
= (RECT
*)lp
;
167 UnionRect( virtual_rect
, virtual_rect
, rect
);
171 RECT
get_virtual_screen_rect(void)
175 NtUserEnumDisplayMonitors( 0, NULL
, get_virtual_screen_proc
, (LPARAM
)&rect
);
179 static BOOL CALLBACK
get_primary_monitor_proc( HMONITOR monitor
, HDC hdc
, LPRECT rect
, LPARAM lp
)
181 RECT
*primary_rect
= (RECT
*)lp
;
183 if (!rect
->top
&& !rect
->left
&& rect
->right
&& rect
->bottom
)
185 *primary_rect
= *rect
;
192 RECT
get_primary_monitor_rect(void)
196 NtUserEnumDisplayMonitors( 0, NULL
, get_primary_monitor_proc
, (LPARAM
)&rect
);
200 HDC
get_display_dc(void)
202 EnterCriticalSection( &display_dc_section
);
207 LeaveCriticalSection( &display_dc_section
);
208 dc
= CreateDCW( L
"DISPLAY", NULL
, NULL
, NULL
);
209 EnterCriticalSection( &display_dc_section
);
218 void release_display_dc( HDC hdc
)
220 LeaveCriticalSection( &display_dc_section
);
223 static HANDLE
get_display_device_init_mutex( void )
225 HANDLE mutex
= CreateMutexW( NULL
, FALSE
, L
"display_device_init" );
227 WaitForSingleObject( mutex
, INFINITE
);
231 static void release_display_device_init_mutex( HANDLE mutex
)
233 ReleaseMutex( mutex
);
234 CloseHandle( mutex
);
237 /* Wait until graphics driver is loaded by explorer */
238 void wait_graphics_driver_ready(void)
240 static BOOL ready
= FALSE
;
244 SendMessageW( GetDesktopWindow(), WM_NULL
, 0, 0 );
249 /***********************************************************************
252 void SYSPARAMS_Init(void)
254 system_dpi
= NtUserGetSystemDpiForProcess( NULL
);
257 static BOOL
update_desktop_wallpaper(void)
261 if (GetWindowThreadProcessId( GetDesktopWindow(), &pid
) && pid
== GetCurrentProcessId())
263 WCHAR wallpaper
[MAX_PATH
], pattern
[256];
265 if (NtUserSystemParametersInfo( SPI_GETDESKWALLPAPER
, ARRAYSIZE(wallpaper
), wallpaper
, 0 ) &&
266 NtUserCallOneParam( (ULONG_PTR
)pattern
, NtUserGetDeskPattern
))
268 update_wallpaper( wallpaper
, pattern
);
271 else SendMessageW( GetDesktopWindow(), WM_SETTINGCHANGE
, SPI_SETDESKWALLPAPER
, 0 );
276 /***********************************************************************
277 * SystemParametersInfoForDpi (USER32.@)
279 BOOL WINAPI
SystemParametersInfoForDpi( UINT action
, UINT val
, PVOID ptr
, UINT winini
, UINT dpi
)
281 BOOL ret
= NtUserSystemParametersInfoForDpi( action
, val
, ptr
, winini
, dpi
);
282 if (ret
&& (action
== SPI_SETDESKWALLPAPER
|| action
== SPI_SETDESKPATTERN
))
283 ret
= update_desktop_wallpaper();
288 /***********************************************************************
289 * SystemParametersInfoW (USER32.@)
291 BOOL WINAPI
SystemParametersInfoW( UINT action
, UINT val
, void *ptr
, UINT winini
)
293 BOOL ret
= NtUserSystemParametersInfo( action
, val
, ptr
, winini
);
294 if (ret
&& (action
== SPI_SETDESKWALLPAPER
|| action
== SPI_SETDESKPATTERN
))
295 ret
= update_desktop_wallpaper();
300 /***********************************************************************
301 * SystemParametersInfoA (USER32.@)
303 BOOL WINAPI
SystemParametersInfoA( UINT uiAction
, UINT uiParam
,
304 PVOID pvParam
, UINT fuWinIni
)
308 TRACE("(%u, %u, %p, %u)\n", uiAction
, uiParam
, pvParam
, fuWinIni
);
312 case SPI_SETDESKWALLPAPER
: /* 20 */
313 case SPI_SETDESKPATTERN
: /* 21 */
317 if (!MultiByteToWideChar( CP_ACP
, 0, pvParam
, -1, buffer
, ARRAY_SIZE( buffer
)))
318 buffer
[ARRAY_SIZE(buffer
)-1] = 0;
319 ret
= SystemParametersInfoW( uiAction
, uiParam
, pvParam
? buffer
: NULL
, fuWinIni
);
323 case SPI_GETICONTITLELOGFONT
: /* 31 */
326 ret
= SystemParametersInfoW( uiAction
, uiParam
, pvParam
? &tmp
: NULL
, fuWinIni
);
328 SYSPARAMS_LogFont32WTo32A( &tmp
, pvParam
);
332 case SPI_GETNONCLIENTMETRICS
: /* 41 WINVER >= 0x400 */
334 NONCLIENTMETRICSW tmp
;
335 LPNONCLIENTMETRICSA lpnmA
= pvParam
;
336 if (lpnmA
&& (lpnmA
->cbSize
== sizeof(NONCLIENTMETRICSA
) ||
337 lpnmA
->cbSize
== FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
)))
339 tmp
.cbSize
= sizeof(NONCLIENTMETRICSW
);
340 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
342 SYSPARAMS_NonClientMetrics32WTo32A( &tmp
, lpnmA
);
349 case SPI_SETNONCLIENTMETRICS
: /* 42 WINVER >= 0x400 */
351 NONCLIENTMETRICSW tmp
;
352 LPNONCLIENTMETRICSA lpnmA
= pvParam
;
353 if (lpnmA
&& (lpnmA
->cbSize
== sizeof(NONCLIENTMETRICSA
) ||
354 lpnmA
->cbSize
== FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
)))
356 tmp
.cbSize
= sizeof(NONCLIENTMETRICSW
);
357 SYSPARAMS_NonClientMetrics32ATo32W( lpnmA
, &tmp
);
358 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
365 case SPI_GETICONMETRICS
: /* 45 WINVER >= 0x400 */
368 LPICONMETRICSA lpimA
= pvParam
;
369 if (lpimA
&& lpimA
->cbSize
== sizeof(ICONMETRICSA
))
371 tmp
.cbSize
= sizeof(ICONMETRICSW
);
372 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
375 lpimA
->iHorzSpacing
= tmp
.iHorzSpacing
;
376 lpimA
->iVertSpacing
= tmp
.iVertSpacing
;
377 lpimA
->iTitleWrap
= tmp
.iTitleWrap
;
378 SYSPARAMS_LogFont32WTo32A( &tmp
.lfFont
, &lpimA
->lfFont
);
386 case SPI_SETICONMETRICS
: /* 46 WINVER >= 0x400 */
389 LPICONMETRICSA lpimA
= pvParam
;
390 if (lpimA
&& lpimA
->cbSize
== sizeof(ICONMETRICSA
))
392 tmp
.cbSize
= sizeof(ICONMETRICSW
);
393 tmp
.iHorzSpacing
= lpimA
->iHorzSpacing
;
394 tmp
.iVertSpacing
= lpimA
->iVertSpacing
;
395 tmp
.iTitleWrap
= lpimA
->iTitleWrap
;
396 SYSPARAMS_LogFont32ATo32W( &lpimA
->lfFont
, &tmp
.lfFont
);
397 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
404 case SPI_GETHIGHCONTRAST
: /* 66 WINVER >= 0x400 */
407 LPHIGHCONTRASTA lphcA
= pvParam
;
408 if (lphcA
&& lphcA
->cbSize
== sizeof(HIGHCONTRASTA
))
410 tmp
.cbSize
= sizeof(HIGHCONTRASTW
);
411 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
414 lphcA
->dwFlags
= tmp
.dwFlags
;
415 lphcA
->lpszDefaultScheme
= NULL
; /* FIXME? */
423 case SPI_GETDESKWALLPAPER
: /* 115 */
425 WCHAR buffer
[MAX_PATH
];
426 ret
= (SystemParametersInfoW( SPI_GETDESKWALLPAPER
, uiParam
, buffer
, fuWinIni
) &&
427 WideCharToMultiByte(CP_ACP
, 0, buffer
, -1, pvParam
, uiParam
, NULL
, NULL
));
432 ret
= SystemParametersInfoW( uiAction
, uiParam
, pvParam
, fuWinIni
);
439 /***********************************************************************
440 * GetSystemMetrics (USER32.@)
442 INT WINAPI
GetSystemMetrics( INT index
)
444 return NtUserGetSystemMetrics( index
);
448 /***********************************************************************
449 * GetSystemMetricsForDpi (USER32.@)
451 INT WINAPI
GetSystemMetricsForDpi( INT index
, UINT dpi
)
453 return NtUserGetSystemMetricsForDpi( index
, dpi
);
457 /***********************************************************************
458 * SwapMouseButton (USER32.@)
459 * Reverse or restore the meaning of the left and right mouse buttons
460 * fSwap [I ] TRUE - reverse, FALSE - original
464 BOOL WINAPI
SwapMouseButton( BOOL fSwap
)
466 BOOL prev
= GetSystemMetrics(SM_SWAPBUTTON
);
467 SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP
, fSwap
, 0, 0);
472 /**********************************************************************
473 * SetDoubleClickTime (USER32.@)
475 BOOL WINAPI
SetDoubleClickTime( UINT interval
)
477 return SystemParametersInfoW(SPI_SETDOUBLECLICKTIME
, interval
, 0, 0);
481 /*************************************************************************
482 * GetSysColor (USER32.@)
484 COLORREF WINAPI DECLSPEC_HOTPATCH
GetSysColor( INT index
)
486 return NtUserGetSysColor( index
);
490 /*************************************************************************
491 * SetSysColorsTemp (USER32.@)
493 DWORD_PTR WINAPI
SetSysColorsTemp( const COLORREF
*pPens
, const HBRUSH
*pBrushes
, DWORD_PTR n
)
495 FIXME( "no longer supported\n" );
500 /***********************************************************************
501 * GetSysColorBrush (USER32.@)
503 HBRUSH WINAPI DECLSPEC_HOTPATCH
GetSysColorBrush( INT index
)
505 return NtUserGetSysColorBrush( index
);
509 /***********************************************************************
512 HPEN
SYSCOLOR_GetPen( INT index
)
514 return NtUserGetSysColorPen( index
);
518 /***********************************************************************
519 * SYSCOLOR_Get55AABrush
521 HBRUSH
SYSCOLOR_Get55AABrush(void)
523 return NtUserGetSysColorBrush( COLOR_55AA_BRUSH
);
526 /***********************************************************************
527 * ChangeDisplaySettingsA (USER32.@)
529 LONG WINAPI
ChangeDisplaySettingsA( LPDEVMODEA devmode
, DWORD flags
)
531 if (devmode
) devmode
->dmDriverExtra
= 0;
533 return ChangeDisplaySettingsExA(NULL
,devmode
,NULL
,flags
,NULL
);
537 /***********************************************************************
538 * ChangeDisplaySettingsW (USER32.@)
540 LONG WINAPI
ChangeDisplaySettingsW( LPDEVMODEW devmode
, DWORD flags
)
542 if (devmode
) devmode
->dmDriverExtra
= 0;
544 return ChangeDisplaySettingsExW(NULL
,devmode
,NULL
,flags
,NULL
);
548 /***********************************************************************
549 * ChangeDisplaySettingsExA (USER32.@)
551 LONG WINAPI
ChangeDisplaySettingsExA( LPCSTR devname
, LPDEVMODEA devmode
, HWND hwnd
,
552 DWORD flags
, LPVOID lparam
)
555 UNICODE_STRING nameW
;
557 if (devname
) RtlCreateUnicodeStringFromAsciiz(&nameW
, devname
);
558 else nameW
.Buffer
= NULL
;
564 devmodeW
= GdiConvertToDevmodeW(devmode
);
567 ret
= ChangeDisplaySettingsExW(nameW
.Buffer
, devmodeW
, hwnd
, flags
, lparam
);
568 HeapFree(GetProcessHeap(), 0, devmodeW
);
571 ret
= DISP_CHANGE_SUCCESSFUL
;
575 ret
= ChangeDisplaySettingsExW(nameW
.Buffer
, NULL
, hwnd
, flags
, lparam
);
578 if (devname
) RtlFreeUnicodeString(&nameW
);
583 /***********************************************************************
584 * ChangeDisplaySettingsExW (USER32.@)
586 LONG WINAPI
ChangeDisplaySettingsExW( LPCWSTR devname
, LPDEVMODEW devmode
, HWND hwnd
,
587 DWORD flags
, LPVOID lparam
)
590 RtlInitUnicodeString( &str
, devname
);
591 return NtUserChangeDisplaySettings( &str
, devmode
, hwnd
, flags
, lparam
);
595 /***********************************************************************
596 * EnumDisplaySettingsW (USER32.@)
599 * TRUE if nth setting exists found (described in the LPDEVMODEW struct)
600 * FALSE if we do not have the nth setting
602 BOOL WINAPI
EnumDisplaySettingsW( LPCWSTR name
, DWORD n
, LPDEVMODEW devmode
)
604 return EnumDisplaySettingsExW(name
, n
, devmode
, 0);
608 /***********************************************************************
609 * EnumDisplaySettingsA (USER32.@)
611 BOOL WINAPI
EnumDisplaySettingsA(LPCSTR name
,DWORD n
,LPDEVMODEA devmode
)
613 return EnumDisplaySettingsExA(name
, n
, devmode
, 0);
617 /***********************************************************************
618 * EnumDisplaySettingsExA (USER32.@)
620 BOOL WINAPI
EnumDisplaySettingsExA(LPCSTR lpszDeviceName
, DWORD iModeNum
,
621 LPDEVMODEA lpDevMode
, DWORD dwFlags
)
625 UNICODE_STRING nameW
;
627 if (lpszDeviceName
) RtlCreateUnicodeStringFromAsciiz(&nameW
, lpszDeviceName
);
628 else nameW
.Buffer
= NULL
;
630 memset(&devmodeW
, 0, sizeof(devmodeW
));
631 devmodeW
.dmSize
= sizeof(devmodeW
);
632 ret
= EnumDisplaySettingsExW(nameW
.Buffer
,iModeNum
,&devmodeW
,dwFlags
);
635 lpDevMode
->dmSize
= FIELD_OFFSET(DEVMODEA
, dmICMMethod
);
636 lpDevMode
->dmSpecVersion
= devmodeW
.dmSpecVersion
;
637 lpDevMode
->dmDriverVersion
= devmodeW
.dmDriverVersion
;
638 WideCharToMultiByte(CP_ACP
, 0, devmodeW
.dmDeviceName
, -1,
639 (LPSTR
)lpDevMode
->dmDeviceName
, CCHDEVICENAME
, NULL
, NULL
);
640 lpDevMode
->dmDriverExtra
= 0; /* FIXME */
641 lpDevMode
->dmBitsPerPel
= devmodeW
.dmBitsPerPel
;
642 lpDevMode
->dmPelsHeight
= devmodeW
.dmPelsHeight
;
643 lpDevMode
->dmPelsWidth
= devmodeW
.dmPelsWidth
;
644 lpDevMode
->dmDisplayFlags
= devmodeW
.dmDisplayFlags
;
645 lpDevMode
->dmDisplayFrequency
= devmodeW
.dmDisplayFrequency
;
646 lpDevMode
->dmFields
= devmodeW
.dmFields
;
648 lpDevMode
->dmPosition
.x
= devmodeW
.dmPosition
.x
;
649 lpDevMode
->dmPosition
.y
= devmodeW
.dmPosition
.y
;
650 lpDevMode
->dmDisplayOrientation
= devmodeW
.dmDisplayOrientation
;
651 lpDevMode
->dmDisplayFixedOutput
= devmodeW
.dmDisplayFixedOutput
;
653 if (lpszDeviceName
) RtlFreeUnicodeString(&nameW
);
658 /***********************************************************************
659 * EnumDisplaySettingsExW (USER32.@)
661 BOOL WINAPI
EnumDisplaySettingsExW( const WCHAR
*device
, DWORD mode
,
662 DEVMODEW
*dev_mode
, DWORD flags
)
665 RtlInitUnicodeString( &str
, device
);
666 return NtUserEnumDisplaySettings( &str
, mode
, dev_mode
, flags
);
669 /**********************************************************************
670 * SetProcessDpiAwarenessContext (USER32.@)
672 BOOL WINAPI
SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
676 switch (GetAwarenessFromDpiAwarenessContext( context
))
678 case DPI_AWARENESS_UNAWARE
:
679 awareness
= NTUSER_DPI_UNAWARE
;
681 case DPI_AWARENESS_SYSTEM_AWARE
:
682 awareness
= NTUSER_DPI_SYSTEM_AWARE
;
684 case DPI_AWARENESS_PER_MONITOR_AWARE
:
685 awareness
= context
== DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
686 ? NTUSER_DPI_PER_MONITOR_AWARE_V2
: NTUSER_DPI_PER_MONITOR_AWARE
;
689 SetLastError( ERROR_INVALID_PARAMETER
);
693 if (!NtUserSetProcessDpiAwarenessContext( awareness
, 0 ))
695 SetLastError( ERROR_ACCESS_DENIED
);
699 TRACE( "set to %p\n", context
);
703 /**********************************************************************
704 * GetProcessDpiAwarenessInternal (USER32.@)
706 BOOL WINAPI
GetProcessDpiAwarenessInternal( HANDLE process
, DPI_AWARENESS
*awareness
)
708 *awareness
= NtUserGetProcessDpiAwarenessContext( process
) & 3;
712 /**********************************************************************
713 * SetProcessDpiAwarenessInternal (USER32.@)
715 BOOL WINAPI
SetProcessDpiAwarenessInternal( DPI_AWARENESS awareness
)
717 static const DPI_AWARENESS_CONTEXT contexts
[3] = { DPI_AWARENESS_CONTEXT_UNAWARE
,
718 DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
,
719 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
};
721 if (awareness
< DPI_AWARENESS_UNAWARE
|| awareness
> DPI_AWARENESS_PER_MONITOR_AWARE
)
723 SetLastError( ERROR_INVALID_PARAMETER
);
726 return SetProcessDpiAwarenessContext( contexts
[awareness
] );
729 /***********************************************************************
730 * AreDpiAwarenessContextsEqual (USER32.@)
732 BOOL WINAPI
AreDpiAwarenessContextsEqual( DPI_AWARENESS_CONTEXT ctx1
, DPI_AWARENESS_CONTEXT ctx2
)
734 DPI_AWARENESS aware1
= GetAwarenessFromDpiAwarenessContext( ctx1
);
735 DPI_AWARENESS aware2
= GetAwarenessFromDpiAwarenessContext( ctx2
);
736 return aware1
!= DPI_AWARENESS_INVALID
&& aware1
== aware2
;
739 /***********************************************************************
740 * GetAwarenessFromDpiAwarenessContext (USER32.@)
742 DPI_AWARENESS WINAPI
GetAwarenessFromDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
744 switch ((ULONG_PTR
)context
)
752 return (ULONG_PTR
)context
& 3;
753 case (ULONG_PTR
)DPI_AWARENESS_CONTEXT_UNAWARE
:
754 case (ULONG_PTR
)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
:
755 case (ULONG_PTR
)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
:
756 return ~(ULONG_PTR
)context
;
758 return DPI_AWARENESS_INVALID
;
762 /***********************************************************************
763 * IsValidDpiAwarenessContext (USER32.@)
765 BOOL WINAPI
IsValidDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
767 return GetAwarenessFromDpiAwarenessContext( context
) != DPI_AWARENESS_INVALID
;
770 /***********************************************************************
771 * SetProcessDPIAware (USER32.@)
773 BOOL WINAPI
SetProcessDPIAware(void)
776 NtUserSetProcessDpiAwarenessContext( NTUSER_DPI_SYSTEM_AWARE
, 0 );
780 /***********************************************************************
781 * IsProcessDPIAware (USER32.@)
783 BOOL WINAPI
IsProcessDPIAware(void)
785 return GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ) != DPI_AWARENESS_UNAWARE
;
788 /**********************************************************************
789 * EnableNonClientDpiScaling (USER32.@)
791 BOOL WINAPI
EnableNonClientDpiScaling( HWND hwnd
)
793 FIXME("(%p): stub\n", hwnd
);
794 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
798 /***********************************************************************
799 * GetDpiForSystem (USER32.@)
801 UINT WINAPI
GetDpiForSystem(void)
803 if (!IsProcessDPIAware()) return USER_DEFAULT_SCREEN_DPI
;
807 /**********************************************************************
808 * GetThreadDpiAwarenessContext (USER32.@)
810 DPI_AWARENESS_CONTEXT WINAPI
GetThreadDpiAwarenessContext(void)
812 struct ntuser_thread_info
*info
= NtUserGetThreadInfo();
814 if (info
->dpi_awareness
) return ULongToHandle( info
->dpi_awareness
);
815 return UlongToHandle( (NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3 ) | 0x10 );
818 /**********************************************************************
819 * SetThreadDpiAwarenessContext (USER32.@)
821 DPI_AWARENESS_CONTEXT WINAPI
SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
823 struct ntuser_thread_info
*info
= NtUserGetThreadInfo();
824 DPI_AWARENESS prev
, val
= GetAwarenessFromDpiAwarenessContext( context
);
826 if (val
== DPI_AWARENESS_INVALID
)
828 SetLastError( ERROR_INVALID_PARAMETER
);
831 if (!(prev
= info
->dpi_awareness
))
833 prev
= NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3;
834 prev
|= 0x80000010; /* restore to process default */
836 if (((ULONG_PTR
)context
& ~(ULONG_PTR
)0x13) == 0x80000000) info
->dpi_awareness
= 0;
837 else info
->dpi_awareness
= val
| 0x10;
838 return ULongToHandle( prev
);
841 /***********************************************************************
842 * MonitorFromRect (USER32.@)
844 HMONITOR WINAPI
MonitorFromRect( const RECT
*rect
, DWORD flags
)
846 return NtUserMonitorFromRect( rect
, flags
);
849 /***********************************************************************
850 * MonitorFromPoint (USER32.@)
852 HMONITOR WINAPI
MonitorFromPoint( POINT pt
, DWORD flags
)
856 SetRect( &rect
, pt
.x
, pt
.y
, pt
.x
+ 1, pt
.y
+ 1 );
857 return MonitorFromRect( &rect
, flags
);
860 /***********************************************************************
861 * MonitorFromWindow (USER32.@)
863 HMONITOR WINAPI
MonitorFromWindow( HWND hwnd
, DWORD flags
)
865 return NtUserMonitorFromWindow( hwnd
, flags
);
868 /***********************************************************************
869 * GetMonitorInfoA (USER32.@)
871 BOOL WINAPI
GetMonitorInfoA( HMONITOR monitor
, LPMONITORINFO info
)
876 if (info
->cbSize
== sizeof(MONITORINFO
)) return GetMonitorInfoW( monitor
, info
);
877 if (info
->cbSize
!= sizeof(MONITORINFOEXA
)) return FALSE
;
879 miW
.cbSize
= sizeof(miW
);
880 ret
= GetMonitorInfoW( monitor
, (MONITORINFO
*)&miW
);
883 MONITORINFOEXA
*miA
= (MONITORINFOEXA
*)info
;
884 miA
->rcMonitor
= miW
.rcMonitor
;
885 miA
->rcWork
= miW
.rcWork
;
886 miA
->dwFlags
= miW
.dwFlags
;
887 WideCharToMultiByte(CP_ACP
, 0, miW
.szDevice
, -1, miA
->szDevice
, sizeof(miA
->szDevice
), NULL
, NULL
);
892 /***********************************************************************
893 * GetMonitorInfoW (USER32.@)
895 BOOL WINAPI
GetMonitorInfoW( HMONITOR monitor
, LPMONITORINFO info
)
897 return NtUserGetMonitorInfo( monitor
, info
);
901 /* Some apps pass a non-stdcall callback to EnumDisplayMonitors,
902 * so we need a small assembly wrapper to call it.
904 extern BOOL
enum_mon_callback_wrapper( void *proc
, HMONITOR monitor
, HDC hdc
, RECT
*rect
, LPARAM lparam
);
905 __ASM_GLOBAL_FUNC( enum_mon_callback_wrapper
,
907 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
908 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
910 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
912 "pushl 24(%ebp)\n\t" /* lparam */
913 /* MJ's Help Diagnostic expects that %ecx contains the address to the rect. */
914 "movl 20(%ebp),%ecx\n\t" /* rect */
916 "pushl 16(%ebp)\n\t" /* hdc */
917 "pushl 12(%ebp)\n\t" /* monitor */
918 "movl 8(%ebp),%eax\n" /* proc */
921 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
922 __ASM_CFI(".cfi_same_value %ebp\n\t")
924 #endif /* __i386__ */
926 BOOL WINAPI
User32CallEnumDisplayMonitor( struct enum_display_monitor_params
*params
, ULONG size
)
929 return enum_mon_callback_wrapper( params
->proc
, params
->monitor
, params
->hdc
,
930 ¶ms
->rect
, params
->lparam
);
932 return params
->proc( params
->monitor
, params
->hdc
, ¶ms
->rect
, params
->lparam
);
936 /***********************************************************************
937 * EnumDisplayDevicesA (USER32.@)
939 BOOL WINAPI
EnumDisplayDevicesA( LPCSTR device
, DWORD index
, DISPLAY_DEVICEA
*info
, DWORD flags
)
941 UNICODE_STRING deviceW
;
946 RtlCreateUnicodeStringFromAsciiz( &deviceW
, device
);
948 deviceW
.Buffer
= NULL
;
950 ddW
.cb
= sizeof(ddW
);
951 ret
= EnumDisplayDevicesW( deviceW
.Buffer
, index
, &ddW
, flags
);
952 RtlFreeUnicodeString( &deviceW
);
957 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceName
, -1, info
->DeviceName
, sizeof(info
->DeviceName
), NULL
, NULL
);
958 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceString
, -1, info
->DeviceString
, sizeof(info
->DeviceString
), NULL
, NULL
);
959 info
->StateFlags
= ddW
.StateFlags
;
961 if (info
->cb
>= offsetof(DISPLAY_DEVICEA
, DeviceID
) + sizeof(info
->DeviceID
))
962 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceID
, -1, info
->DeviceID
, sizeof(info
->DeviceID
), NULL
, NULL
);
963 if (info
->cb
>= offsetof(DISPLAY_DEVICEA
, DeviceKey
) + sizeof(info
->DeviceKey
))
964 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceKey
, -1, info
->DeviceKey
, sizeof(info
->DeviceKey
), NULL
, NULL
);
969 /***********************************************************************
970 * EnumDisplayDevicesW (USER32.@)
972 BOOL WINAPI
EnumDisplayDevicesW( LPCWSTR device
, DWORD index
, DISPLAY_DEVICEW
*info
, DWORD flags
)
975 RtlInitUnicodeString( &str
, device
);
976 return NT_SUCCESS(NtUserEnumDisplayDevices( &str
, index
, info
, flags
));
979 /**********************************************************************
980 * GetAutoRotationState [USER32.@]
982 BOOL WINAPI
GetAutoRotationState( AR_STATE
*state
)
984 TRACE("(%p)\n", state
);
988 SetLastError(ERROR_INVALID_PARAMETER
);
992 *state
= AR_NOSENSOR
;
996 /**********************************************************************
997 * GetDisplayAutoRotationPreferences [USER32.@]
999 BOOL WINAPI
GetDisplayAutoRotationPreferences( ORIENTATION_PREFERENCE
*orientation
)
1001 FIXME("(%p): stub\n", orientation
);
1002 *orientation
= ORIENTATION_PREFERENCE_NONE
;
1006 /* physical<->logical mapping functions from win8 that are nops in later versions */
1008 /***********************************************************************
1009 * GetPhysicalCursorPos (USER32.@)
1011 BOOL WINAPI
GetPhysicalCursorPos( POINT
*point
)
1013 return GetCursorPos( point
);
1016 /***********************************************************************
1017 * SetPhysicalCursorPos (USER32.@)
1019 BOOL WINAPI
SetPhysicalCursorPos( INT x
, INT y
)
1021 return NtUserSetCursorPos( x
, y
);
1024 /***********************************************************************
1025 * WindowFromPhysicalPoint (USER32.@)
1027 HWND WINAPI
WindowFromPhysicalPoint( POINT pt
)
1029 return WindowFromPoint( pt
);
1032 /***********************************************************************
1033 * LogicalToPhysicalPoint (USER32.@)
1035 BOOL WINAPI
LogicalToPhysicalPoint( HWND hwnd
, POINT
*point
)
1040 /***********************************************************************
1041 * PhysicalToLogicalPoint (USER32.@)
1043 BOOL WINAPI
PhysicalToLogicalPoint( HWND hwnd
, POINT
*point
)
1048 static DISPLAYCONFIG_ROTATION
get_dc_rotation(const DEVMODEW
*devmode
)
1050 if (devmode
->dmFields
& DM_DISPLAYORIENTATION
)
1051 return devmode
->dmDisplayOrientation
+ 1;
1053 return DISPLAYCONFIG_ROTATION_IDENTITY
;
1056 static DISPLAYCONFIG_SCANLINE_ORDERING
get_dc_scanline_ordering(const DEVMODEW
*devmode
)
1058 if (!(devmode
->dmFields
& DM_DISPLAYFLAGS
))
1059 return DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED
;
1060 else if (devmode
->dmDisplayFlags
& DM_INTERLACED
)
1061 return DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED
;
1063 return DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE
;
1066 static DISPLAYCONFIG_PIXELFORMAT
get_dc_pixelformat(DWORD dmBitsPerPel
)
1068 if ((dmBitsPerPel
== 8) || (dmBitsPerPel
== 16) ||
1069 (dmBitsPerPel
== 24) || (dmBitsPerPel
== 32))
1070 return dmBitsPerPel
/ 8;
1072 return DISPLAYCONFIG_PIXELFORMAT_NONGDI
;
1075 static void set_mode_target_info(DISPLAYCONFIG_MODE_INFO
*info
, const LUID
*gpu_luid
, UINT32 target_id
,
1076 UINT32 flags
, const DEVMODEW
*devmode
)
1078 DISPLAYCONFIG_TARGET_MODE
*mode
= &info
->targetMode
;
1080 info
->infoType
= DISPLAYCONFIG_MODE_INFO_TYPE_TARGET
;
1081 info
->adapterId
= *gpu_luid
;
1082 info
->id
= target_id
;
1084 /* FIXME: Populate pixelRate/hSyncFreq/totalSize with real data */
1085 mode
->targetVideoSignalInfo
.pixelRate
= devmode
->dmDisplayFrequency
* devmode
->dmPelsWidth
* devmode
->dmPelsHeight
;
1086 mode
->targetVideoSignalInfo
.hSyncFreq
.Numerator
= devmode
->dmDisplayFrequency
* devmode
->dmPelsWidth
;
1087 mode
->targetVideoSignalInfo
.hSyncFreq
.Denominator
= 1;
1088 mode
->targetVideoSignalInfo
.vSyncFreq
.Numerator
= devmode
->dmDisplayFrequency
;
1089 mode
->targetVideoSignalInfo
.vSyncFreq
.Denominator
= 1;
1090 mode
->targetVideoSignalInfo
.activeSize
.cx
= devmode
->dmPelsWidth
;
1091 mode
->targetVideoSignalInfo
.activeSize
.cy
= devmode
->dmPelsHeight
;
1092 if (flags
& QDC_DATABASE_CURRENT
)
1094 mode
->targetVideoSignalInfo
.totalSize
.cx
= 0;
1095 mode
->targetVideoSignalInfo
.totalSize
.cy
= 0;
1099 mode
->targetVideoSignalInfo
.totalSize
.cx
= devmode
->dmPelsWidth
;
1100 mode
->targetVideoSignalInfo
.totalSize
.cy
= devmode
->dmPelsHeight
;
1102 mode
->targetVideoSignalInfo
.videoStandard
= D3DKMDT_VSS_OTHER
;
1103 mode
->targetVideoSignalInfo
.scanLineOrdering
= get_dc_scanline_ordering(devmode
);
1106 static void set_path_target_info(DISPLAYCONFIG_PATH_TARGET_INFO
*info
, const LUID
*gpu_luid
,
1107 UINT32 target_id
, UINT32 mode_index
, const DEVMODEW
*devmode
)
1109 info
->adapterId
= *gpu_luid
;
1110 info
->id
= target_id
;
1111 info
->modeInfoIdx
= mode_index
;
1112 info
->outputTechnology
= DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL
;
1113 info
->rotation
= get_dc_rotation(devmode
);
1114 info
->scaling
= DISPLAYCONFIG_SCALING_IDENTITY
;
1115 info
->refreshRate
.Numerator
= devmode
->dmDisplayFrequency
;
1116 info
->refreshRate
.Denominator
= 1;
1117 info
->scanLineOrdering
= get_dc_scanline_ordering(devmode
);
1118 info
->targetAvailable
= TRUE
;
1119 info
->statusFlags
= DISPLAYCONFIG_TARGET_IN_USE
;
1122 static void set_mode_source_info(DISPLAYCONFIG_MODE_INFO
*info
, const LUID
*gpu_luid
,
1123 UINT32 source_id
, const DEVMODEW
*devmode
)
1125 DISPLAYCONFIG_SOURCE_MODE
*mode
= &(info
->sourceMode
);
1127 info
->infoType
= DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE
;
1128 info
->adapterId
= *gpu_luid
;
1129 info
->id
= source_id
;
1131 mode
->width
= devmode
->dmPelsWidth
;
1132 mode
->height
= devmode
->dmPelsHeight
;
1133 mode
->pixelFormat
= get_dc_pixelformat(devmode
->dmBitsPerPel
);
1134 if (devmode
->dmFields
& DM_POSITION
)
1136 mode
->position
= devmode
->dmPosition
;
1140 mode
->position
.x
= 0;
1141 mode
->position
.y
= 0;
1145 static void set_path_source_info(DISPLAYCONFIG_PATH_SOURCE_INFO
*info
, const LUID
*gpu_luid
,
1146 UINT32 source_id
, UINT32 mode_index
)
1148 info
->adapterId
= *gpu_luid
;
1149 info
->id
= source_id
;
1150 info
->modeInfoIdx
= mode_index
;
1151 info
->statusFlags
= DISPLAYCONFIG_SOURCE_IN_USE
;
1154 static BOOL
source_mode_exists(const DISPLAYCONFIG_MODE_INFO
*modeinfo
, UINT32 num_modes
,
1155 UINT32 source_id
, UINT32
*found_mode_index
)
1159 for (i
= 0; i
< num_modes
; i
++)
1161 if (modeinfo
[i
].infoType
== DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE
&&
1162 modeinfo
[i
].id
== source_id
)
1164 *found_mode_index
= i
;
1171 /***********************************************************************
1172 * QueryDisplayConfig (USER32.@)
1174 LONG WINAPI
QueryDisplayConfig(UINT32 flags
, UINT32
*numpathelements
, DISPLAYCONFIG_PATH_INFO
*pathinfo
,
1175 UINT32
*numinfoelements
, DISPLAYCONFIG_MODE_INFO
*modeinfo
,
1176 DISPLAYCONFIG_TOPOLOGY_ID
*topologyid
)
1178 LONG adapter_index
, ret
;
1181 SP_DEVINFO_DATA device_data
= {sizeof(device_data
)};
1182 DWORD monitor_index
= 0, state_flags
, type
;
1183 UINT32 output_id
, source_mode_index
, path_index
= 0, mode_index
= 0;
1185 WCHAR device_name
[CCHDEVICENAME
];
1188 FIXME("(%08x %p %p %p %p %p): semi-stub\n", flags
, numpathelements
, pathinfo
, numinfoelements
, modeinfo
, topologyid
);
1190 if (!numpathelements
|| !numinfoelements
)
1191 return ERROR_INVALID_PARAMETER
;
1193 if (!*numpathelements
|| !*numinfoelements
)
1194 return ERROR_INVALID_PARAMETER
;
1196 if (flags
!= QDC_ALL_PATHS
&&
1197 flags
!= QDC_ONLY_ACTIVE_PATHS
&&
1198 flags
!= QDC_DATABASE_CURRENT
)
1199 return ERROR_INVALID_PARAMETER
;
1201 if (((flags
== QDC_DATABASE_CURRENT
) && !topologyid
) ||
1202 ((flags
!= QDC_DATABASE_CURRENT
) && topologyid
))
1203 return ERROR_INVALID_PARAMETER
;
1205 if (flags
!= QDC_ONLY_ACTIVE_PATHS
)
1206 FIXME("only returning active paths\n");
1210 FIXME("setting toplogyid to DISPLAYCONFIG_TOPOLOGY_INTERNAL\n");
1211 *topologyid
= DISPLAYCONFIG_TOPOLOGY_INTERNAL
;
1214 wait_graphics_driver_ready();
1215 mutex
= get_display_device_init_mutex();
1217 /* Iterate through "targets"/monitors.
1218 * Each target corresponds to a path, and each path corresponds to one or two unique modes.
1220 devinfo
= SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR
, L
"DISPLAY", NULL
, DIGCF_PRESENT
);
1221 if (devinfo
== INVALID_HANDLE_VALUE
)
1223 ret
= ERROR_GEN_FAILURE
;
1227 ret
= ERROR_GEN_FAILURE
;
1228 while (SetupDiEnumDeviceInfo(devinfo
, monitor_index
++, &device_data
))
1230 /* Only count active monitors */
1231 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS
,
1232 &type
, (BYTE
*)&state_flags
, sizeof(state_flags
), NULL
, 0))
1234 if (!(state_flags
& DISPLAY_DEVICE_ACTIVE
))
1237 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &DEVPROPKEY_MONITOR_GPU_LUID
,
1238 &type
, (BYTE
*)&gpu_luid
, sizeof(gpu_luid
), NULL
, 0))
1241 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &DEVPROPKEY_MONITOR_OUTPUT_ID
,
1242 &type
, (BYTE
*)&output_id
, sizeof(output_id
), NULL
, 0))
1245 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME
,
1246 &type
, (BYTE
*)device_name
, sizeof(device_name
), NULL
, 0))
1249 memset(&devmode
, 0, sizeof(devmode
));
1250 devmode
.dmSize
= sizeof(devmode
);
1251 if (!EnumDisplaySettingsW(device_name
, ENUM_CURRENT_SETTINGS
, &devmode
))
1254 /* Extract the adapter index from device_name to use as the source ID */
1255 adapter_index
= wcstol(device_name
+ lstrlenW(L
"\\\\.\\DISPLAY"), NULL
, 10);
1258 if (path_index
== *numpathelements
|| mode_index
== *numinfoelements
)
1260 ret
= ERROR_INSUFFICIENT_BUFFER
;
1264 pathinfo
[path_index
].flags
= DISPLAYCONFIG_PATH_ACTIVE
;
1265 set_mode_target_info(&modeinfo
[mode_index
], &gpu_luid
, output_id
, flags
, &devmode
);
1266 set_path_target_info(&(pathinfo
[path_index
].targetInfo
), &gpu_luid
, output_id
, mode_index
, &devmode
);
1269 if (mode_index
== *numinfoelements
)
1271 ret
= ERROR_INSUFFICIENT_BUFFER
;
1275 /* Multiple targets can be driven by the same source, ensure a mode
1276 * hasn't already been added for this source.
1278 if (!source_mode_exists(modeinfo
, mode_index
, adapter_index
, &source_mode_index
))
1280 set_mode_source_info(&modeinfo
[mode_index
], &gpu_luid
, adapter_index
, &devmode
);
1281 source_mode_index
= mode_index
;
1284 set_path_source_info(&(pathinfo
[path_index
].sourceInfo
), &gpu_luid
, adapter_index
, source_mode_index
);
1288 *numpathelements
= path_index
;
1289 *numinfoelements
= mode_index
;
1290 ret
= ERROR_SUCCESS
;
1293 SetupDiDestroyDeviceInfoList(devinfo
);
1294 release_display_device_init_mutex(mutex
);
1298 /***********************************************************************
1299 * DisplayConfigGetDeviceInfo (USER32.@)
1301 LONG WINAPI
DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER
*packet
)
1303 return RtlNtStatusToDosError(NtUserDisplayConfigGetDeviceInfo(packet
));
1306 /***********************************************************************
1307 * SetDisplayConfig (USER32.@)
1309 LONG WINAPI
SetDisplayConfig(UINT32 path_info_count
, DISPLAYCONFIG_PATH_INFO
*path_info
, UINT32 mode_info_count
,
1310 DISPLAYCONFIG_MODE_INFO
*mode_info
, UINT32 flags
)
1312 FIXME("path_info_count %u, path_info %p, mode_info_count %u, mode_info %p, flags %#x stub.\n",
1313 path_info_count
, path_info
, mode_info_count
, mode_info
, flags
);
1315 return ERROR_SUCCESS
;