user32: Remove now unused virtual screen helpers.
[wine.git] / dlls / user32 / sysparams.c
blobe7c7ce350e43bde6820d49e37e65342df1ed72c8
1 /*
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
21 #include <assert.h>
22 #include <limits.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <wchar.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "winreg.h"
35 #include "wine/wingdi16.h"
36 #include "winerror.h"
38 #include "initguid.h"
39 #include "d3dkmdt.h"
40 #include "devguid.h"
41 #include "setupapi.h"
42 #include "controls.h"
43 #include "user_private.h"
44 #include "wine/asm.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;
130 else
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;
155 else
156 lpnm32W->iPaddedBorderWidth = 0;
161 /* Helper functions to retrieve monitors info */
163 HDC get_display_dc(void)
165 EnterCriticalSection( &display_dc_section );
166 if (!display_dc)
168 HDC dc;
170 LeaveCriticalSection( &display_dc_section );
171 dc = CreateDCW( L"DISPLAY", NULL, NULL, NULL );
172 EnterCriticalSection( &display_dc_section );
173 if (display_dc)
174 DeleteDC(dc);
175 else
176 display_dc = dc;
178 return display_dc;
181 void release_display_dc( HDC hdc )
183 LeaveCriticalSection( &display_dc_section );
186 static HANDLE get_display_device_init_mutex( void )
188 HANDLE mutex = CreateMutexW( NULL, FALSE, L"display_device_init" );
190 WaitForSingleObject( mutex, INFINITE );
191 return mutex;
194 static void release_display_device_init_mutex( HANDLE mutex )
196 ReleaseMutex( mutex );
197 CloseHandle( mutex );
200 /* Wait until graphics driver is loaded by explorer */
201 static void wait_graphics_driver_ready(void)
203 static BOOL ready = FALSE;
205 if (!ready)
207 SendMessageW( GetDesktopWindow(), WM_NULL, 0, 0 );
208 ready = TRUE;
212 /***********************************************************************
213 * SYSPARAMS_Init
215 void SYSPARAMS_Init(void)
217 system_dpi = NtUserGetSystemDpiForProcess( NULL );
220 static BOOL update_desktop_wallpaper(void)
222 DWORD pid;
224 if (GetWindowThreadProcessId( GetDesktopWindow(), &pid ) && pid == GetCurrentProcessId())
226 WCHAR wallpaper[MAX_PATH], pattern[256];
228 if (NtUserSystemParametersInfo( SPI_GETDESKWALLPAPER, ARRAYSIZE(wallpaper), wallpaper, 0 ) &&
229 NtUserCallOneParam( (ULONG_PTR)pattern, NtUserGetDeskPattern ))
231 update_wallpaper( wallpaper, pattern );
234 else SendMessageW( GetDesktopWindow(), WM_SETTINGCHANGE, SPI_SETDESKWALLPAPER, 0 );
235 return TRUE;
239 /***********************************************************************
240 * SystemParametersInfoForDpi (USER32.@)
242 BOOL WINAPI SystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi )
244 BOOL ret = NtUserSystemParametersInfoForDpi( action, val, ptr, winini, dpi );
245 if (ret && (action == SPI_SETDESKWALLPAPER || action == SPI_SETDESKPATTERN))
246 ret = update_desktop_wallpaper();
247 return ret;
251 /***********************************************************************
252 * SystemParametersInfoW (USER32.@)
254 BOOL WINAPI SystemParametersInfoW( UINT action, UINT val, void *ptr, UINT winini )
256 BOOL ret = NtUserSystemParametersInfo( action, val, ptr, winini );
257 if (ret && (action == SPI_SETDESKWALLPAPER || action == SPI_SETDESKPATTERN))
258 ret = update_desktop_wallpaper();
259 return ret;
263 /***********************************************************************
264 * SystemParametersInfoA (USER32.@)
266 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
267 PVOID pvParam, UINT fuWinIni )
269 BOOL ret;
271 TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
273 switch (uiAction)
275 case SPI_SETDESKWALLPAPER: /* 20 */
276 case SPI_SETDESKPATTERN: /* 21 */
278 WCHAR buffer[256];
279 if (pvParam)
280 if (!MultiByteToWideChar( CP_ACP, 0, pvParam, -1, buffer, ARRAY_SIZE( buffer )))
281 buffer[ARRAY_SIZE(buffer)-1] = 0;
282 ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
283 break;
286 case SPI_GETICONTITLELOGFONT: /* 31 */
288 LOGFONTW tmp;
289 ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
290 if (ret && pvParam)
291 SYSPARAMS_LogFont32WTo32A( &tmp, pvParam );
292 break;
295 case SPI_GETNONCLIENTMETRICS: /* 41 WINVER >= 0x400 */
297 NONCLIENTMETRICSW tmp;
298 LPNONCLIENTMETRICSA lpnmA = pvParam;
299 if (lpnmA && (lpnmA->cbSize == sizeof(NONCLIENTMETRICSA) ||
300 lpnmA->cbSize == FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth)))
302 tmp.cbSize = sizeof(NONCLIENTMETRICSW);
303 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
304 if (ret)
305 SYSPARAMS_NonClientMetrics32WTo32A( &tmp, lpnmA );
307 else
308 ret = FALSE;
309 break;
312 case SPI_SETNONCLIENTMETRICS: /* 42 WINVER >= 0x400 */
314 NONCLIENTMETRICSW tmp;
315 LPNONCLIENTMETRICSA lpnmA = pvParam;
316 if (lpnmA && (lpnmA->cbSize == sizeof(NONCLIENTMETRICSA) ||
317 lpnmA->cbSize == FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth)))
319 tmp.cbSize = sizeof(NONCLIENTMETRICSW);
320 SYSPARAMS_NonClientMetrics32ATo32W( lpnmA, &tmp );
321 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
323 else
324 ret = FALSE;
325 break;
328 case SPI_GETICONMETRICS: /* 45 WINVER >= 0x400 */
330 ICONMETRICSW tmp;
331 LPICONMETRICSA lpimA = pvParam;
332 if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
334 tmp.cbSize = sizeof(ICONMETRICSW);
335 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
336 if (ret)
338 lpimA->iHorzSpacing = tmp.iHorzSpacing;
339 lpimA->iVertSpacing = tmp.iVertSpacing;
340 lpimA->iTitleWrap = tmp.iTitleWrap;
341 SYSPARAMS_LogFont32WTo32A( &tmp.lfFont, &lpimA->lfFont );
344 else
345 ret = FALSE;
346 break;
349 case SPI_SETICONMETRICS: /* 46 WINVER >= 0x400 */
351 ICONMETRICSW tmp;
352 LPICONMETRICSA lpimA = pvParam;
353 if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
355 tmp.cbSize = sizeof(ICONMETRICSW);
356 tmp.iHorzSpacing = lpimA->iHorzSpacing;
357 tmp.iVertSpacing = lpimA->iVertSpacing;
358 tmp.iTitleWrap = lpimA->iTitleWrap;
359 SYSPARAMS_LogFont32ATo32W( &lpimA->lfFont, &tmp.lfFont);
360 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
362 else
363 ret = FALSE;
364 break;
367 case SPI_GETHIGHCONTRAST: /* 66 WINVER >= 0x400 */
369 HIGHCONTRASTW tmp;
370 LPHIGHCONTRASTA lphcA = pvParam;
371 if (lphcA && lphcA->cbSize == sizeof(HIGHCONTRASTA))
373 tmp.cbSize = sizeof(HIGHCONTRASTW);
374 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
375 if (ret)
377 lphcA->dwFlags = tmp.dwFlags;
378 lphcA->lpszDefaultScheme = NULL; /* FIXME? */
381 else
382 ret = FALSE;
383 break;
386 case SPI_GETDESKWALLPAPER: /* 115 */
388 WCHAR buffer[MAX_PATH];
389 ret = (SystemParametersInfoW( SPI_GETDESKWALLPAPER, uiParam, buffer, fuWinIni ) &&
390 WideCharToMultiByte(CP_ACP, 0, buffer, -1, pvParam, uiParam, NULL, NULL));
391 break;
394 default:
395 ret = SystemParametersInfoW( uiAction, uiParam, pvParam, fuWinIni );
396 break;
398 return ret;
402 /***********************************************************************
403 * GetSystemMetrics (USER32.@)
405 INT WINAPI GetSystemMetrics( INT index )
407 return NtUserGetSystemMetrics( index );
411 /***********************************************************************
412 * GetSystemMetricsForDpi (USER32.@)
414 INT WINAPI GetSystemMetricsForDpi( INT index, UINT dpi )
416 return NtUserGetSystemMetricsForDpi( index, dpi );
420 /***********************************************************************
421 * SwapMouseButton (USER32.@)
422 * Reverse or restore the meaning of the left and right mouse buttons
423 * fSwap [I ] TRUE - reverse, FALSE - original
424 * RETURN
425 * previous state
427 BOOL WINAPI SwapMouseButton( BOOL fSwap )
429 BOOL prev = GetSystemMetrics(SM_SWAPBUTTON);
430 SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP, fSwap, 0, 0);
431 return prev;
435 /**********************************************************************
436 * SetDoubleClickTime (USER32.@)
438 BOOL WINAPI SetDoubleClickTime( UINT interval )
440 return SystemParametersInfoW(SPI_SETDOUBLECLICKTIME, interval, 0, 0);
444 /*************************************************************************
445 * GetSysColor (USER32.@)
447 COLORREF WINAPI DECLSPEC_HOTPATCH GetSysColor( INT index )
449 return NtUserGetSysColor( index );
453 /*************************************************************************
454 * SetSysColorsTemp (USER32.@)
456 DWORD_PTR WINAPI SetSysColorsTemp( const COLORREF *pPens, const HBRUSH *pBrushes, DWORD_PTR n)
458 FIXME( "no longer supported\n" );
459 return FALSE;
463 /***********************************************************************
464 * GetSysColorBrush (USER32.@)
466 HBRUSH WINAPI DECLSPEC_HOTPATCH GetSysColorBrush( INT index )
468 return NtUserGetSysColorBrush( index );
472 /***********************************************************************
473 * SYSCOLOR_GetPen
475 HPEN SYSCOLOR_GetPen( INT index )
477 return NtUserGetSysColorPen( index );
481 /***********************************************************************
482 * SYSCOLOR_Get55AABrush
484 HBRUSH SYSCOLOR_Get55AABrush(void)
486 return NtUserGetSysColorBrush( COLOR_55AA_BRUSH );
489 /***********************************************************************
490 * ChangeDisplaySettingsA (USER32.@)
492 LONG WINAPI ChangeDisplaySettingsA( LPDEVMODEA devmode, DWORD flags )
494 if (devmode) devmode->dmDriverExtra = 0;
496 return ChangeDisplaySettingsExA(NULL,devmode,NULL,flags,NULL);
500 /***********************************************************************
501 * ChangeDisplaySettingsW (USER32.@)
503 LONG WINAPI ChangeDisplaySettingsW( LPDEVMODEW devmode, DWORD flags )
505 if (devmode) devmode->dmDriverExtra = 0;
507 return ChangeDisplaySettingsExW(NULL,devmode,NULL,flags,NULL);
511 /***********************************************************************
512 * ChangeDisplaySettingsExA (USER32.@)
514 LONG WINAPI ChangeDisplaySettingsExA( LPCSTR devname, LPDEVMODEA devmode, HWND hwnd,
515 DWORD flags, LPVOID lparam )
517 LONG ret;
518 UNICODE_STRING nameW;
520 if (devname) RtlCreateUnicodeStringFromAsciiz(&nameW, devname);
521 else nameW.Buffer = NULL;
523 if (devmode)
525 DEVMODEW *devmodeW;
527 devmodeW = GdiConvertToDevmodeW(devmode);
528 if (devmodeW)
530 ret = ChangeDisplaySettingsExW(nameW.Buffer, devmodeW, hwnd, flags, lparam);
531 HeapFree(GetProcessHeap(), 0, devmodeW);
533 else
534 ret = DISP_CHANGE_SUCCESSFUL;
536 else
538 ret = ChangeDisplaySettingsExW(nameW.Buffer, NULL, hwnd, flags, lparam);
541 if (devname) RtlFreeUnicodeString(&nameW);
542 return ret;
546 /***********************************************************************
547 * ChangeDisplaySettingsExW (USER32.@)
549 LONG WINAPI ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd,
550 DWORD flags, LPVOID lparam )
552 UNICODE_STRING str;
553 RtlInitUnicodeString( &str, devname );
554 return NtUserChangeDisplaySettings( &str, devmode, hwnd, flags, lparam );
558 /***********************************************************************
559 * EnumDisplaySettingsW (USER32.@)
561 * RETURNS
562 * TRUE if nth setting exists found (described in the LPDEVMODEW struct)
563 * FALSE if we do not have the nth setting
565 BOOL WINAPI EnumDisplaySettingsW( LPCWSTR name, DWORD n, LPDEVMODEW devmode )
567 return EnumDisplaySettingsExW(name, n, devmode, 0);
571 /***********************************************************************
572 * EnumDisplaySettingsA (USER32.@)
574 BOOL WINAPI EnumDisplaySettingsA(LPCSTR name,DWORD n,LPDEVMODEA devmode)
576 return EnumDisplaySettingsExA(name, n, devmode, 0);
580 /***********************************************************************
581 * EnumDisplaySettingsExA (USER32.@)
583 BOOL WINAPI EnumDisplaySettingsExA(LPCSTR lpszDeviceName, DWORD iModeNum,
584 LPDEVMODEA lpDevMode, DWORD dwFlags)
586 DEVMODEW devmodeW;
587 BOOL ret;
588 UNICODE_STRING nameW;
590 if (lpszDeviceName) RtlCreateUnicodeStringFromAsciiz(&nameW, lpszDeviceName);
591 else nameW.Buffer = NULL;
593 memset(&devmodeW, 0, sizeof(devmodeW));
594 devmodeW.dmSize = sizeof(devmodeW);
595 ret = EnumDisplaySettingsExW(nameW.Buffer,iModeNum,&devmodeW,dwFlags);
596 if (ret)
598 lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod);
599 lpDevMode->dmSpecVersion = devmodeW.dmSpecVersion;
600 lpDevMode->dmDriverVersion = devmodeW.dmDriverVersion;
601 WideCharToMultiByte(CP_ACP, 0, devmodeW.dmDeviceName, -1,
602 (LPSTR)lpDevMode->dmDeviceName, CCHDEVICENAME, NULL, NULL);
603 lpDevMode->dmDriverExtra = 0; /* FIXME */
604 lpDevMode->dmBitsPerPel = devmodeW.dmBitsPerPel;
605 lpDevMode->dmPelsHeight = devmodeW.dmPelsHeight;
606 lpDevMode->dmPelsWidth = devmodeW.dmPelsWidth;
607 lpDevMode->dmDisplayFlags = devmodeW.dmDisplayFlags;
608 lpDevMode->dmDisplayFrequency = devmodeW.dmDisplayFrequency;
609 lpDevMode->dmFields = devmodeW.dmFields;
611 lpDevMode->dmPosition.x = devmodeW.dmPosition.x;
612 lpDevMode->dmPosition.y = devmodeW.dmPosition.y;
613 lpDevMode->dmDisplayOrientation = devmodeW.dmDisplayOrientation;
614 lpDevMode->dmDisplayFixedOutput = devmodeW.dmDisplayFixedOutput;
616 if (lpszDeviceName) RtlFreeUnicodeString(&nameW);
617 return ret;
621 /***********************************************************************
622 * EnumDisplaySettingsExW (USER32.@)
624 BOOL WINAPI EnumDisplaySettingsExW( const WCHAR *device, DWORD mode,
625 DEVMODEW *dev_mode, DWORD flags )
627 UNICODE_STRING str;
628 RtlInitUnicodeString( &str, device );
629 return NtUserEnumDisplaySettings( &str, mode, dev_mode, flags );
632 /**********************************************************************
633 * SetProcessDpiAwarenessContext (USER32.@)
635 BOOL WINAPI SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
637 ULONG awareness;
639 switch (GetAwarenessFromDpiAwarenessContext( context ))
641 case DPI_AWARENESS_UNAWARE:
642 awareness = NTUSER_DPI_UNAWARE;
643 break;
644 case DPI_AWARENESS_SYSTEM_AWARE:
645 awareness = NTUSER_DPI_SYSTEM_AWARE;
646 break;
647 case DPI_AWARENESS_PER_MONITOR_AWARE:
648 awareness = context == DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
649 ? NTUSER_DPI_PER_MONITOR_AWARE_V2 : NTUSER_DPI_PER_MONITOR_AWARE;
650 break;
651 default:
652 SetLastError( ERROR_INVALID_PARAMETER );
653 return FALSE;
656 if (!NtUserSetProcessDpiAwarenessContext( awareness, 0 ))
658 SetLastError( ERROR_ACCESS_DENIED );
659 return FALSE;
662 TRACE( "set to %p\n", context );
663 return TRUE;
666 /**********************************************************************
667 * GetProcessDpiAwarenessInternal (USER32.@)
669 BOOL WINAPI GetProcessDpiAwarenessInternal( HANDLE process, DPI_AWARENESS *awareness )
671 *awareness = NtUserGetProcessDpiAwarenessContext( process ) & 3;
672 return TRUE;
675 /**********************************************************************
676 * SetProcessDpiAwarenessInternal (USER32.@)
678 BOOL WINAPI SetProcessDpiAwarenessInternal( DPI_AWARENESS awareness )
680 static const DPI_AWARENESS_CONTEXT contexts[3] = { DPI_AWARENESS_CONTEXT_UNAWARE,
681 DPI_AWARENESS_CONTEXT_SYSTEM_AWARE,
682 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE };
684 if (awareness < DPI_AWARENESS_UNAWARE || awareness > DPI_AWARENESS_PER_MONITOR_AWARE)
686 SetLastError( ERROR_INVALID_PARAMETER );
687 return FALSE;
689 return SetProcessDpiAwarenessContext( contexts[awareness] );
692 /***********************************************************************
693 * AreDpiAwarenessContextsEqual (USER32.@)
695 BOOL WINAPI AreDpiAwarenessContextsEqual( DPI_AWARENESS_CONTEXT ctx1, DPI_AWARENESS_CONTEXT ctx2 )
697 DPI_AWARENESS aware1 = GetAwarenessFromDpiAwarenessContext( ctx1 );
698 DPI_AWARENESS aware2 = GetAwarenessFromDpiAwarenessContext( ctx2 );
699 return aware1 != DPI_AWARENESS_INVALID && aware1 == aware2;
702 /***********************************************************************
703 * GetAwarenessFromDpiAwarenessContext (USER32.@)
705 DPI_AWARENESS WINAPI GetAwarenessFromDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
707 switch ((ULONG_PTR)context)
709 case 0x10:
710 case 0x11:
711 case 0x12:
712 case 0x80000010:
713 case 0x80000011:
714 case 0x80000012:
715 return (ULONG_PTR)context & 3;
716 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
717 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
718 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
719 return ~(ULONG_PTR)context;
720 default:
721 return DPI_AWARENESS_INVALID;
725 /***********************************************************************
726 * IsValidDpiAwarenessContext (USER32.@)
728 BOOL WINAPI IsValidDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
730 return GetAwarenessFromDpiAwarenessContext( context ) != DPI_AWARENESS_INVALID;
733 /***********************************************************************
734 * SetProcessDPIAware (USER32.@)
736 BOOL WINAPI SetProcessDPIAware(void)
738 TRACE("\n");
739 NtUserSetProcessDpiAwarenessContext( NTUSER_DPI_SYSTEM_AWARE, 0 );
740 return TRUE;
743 /***********************************************************************
744 * IsProcessDPIAware (USER32.@)
746 BOOL WINAPI IsProcessDPIAware(void)
748 return GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ) != DPI_AWARENESS_UNAWARE;
751 /**********************************************************************
752 * EnableNonClientDpiScaling (USER32.@)
754 BOOL WINAPI EnableNonClientDpiScaling( HWND hwnd )
756 FIXME("(%p): stub\n", hwnd);
757 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
758 return FALSE;
761 /***********************************************************************
762 * GetDpiForSystem (USER32.@)
764 UINT WINAPI GetDpiForSystem(void)
766 if (!IsProcessDPIAware()) return USER_DEFAULT_SCREEN_DPI;
767 return system_dpi;
770 /**********************************************************************
771 * GetThreadDpiAwarenessContext (USER32.@)
773 DPI_AWARENESS_CONTEXT WINAPI GetThreadDpiAwarenessContext(void)
775 struct ntuser_thread_info *info = NtUserGetThreadInfo();
777 if (info->dpi_awareness) return ULongToHandle( info->dpi_awareness );
778 return UlongToHandle( (NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3 ) | 0x10 );
781 /**********************************************************************
782 * SetThreadDpiAwarenessContext (USER32.@)
784 DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
786 struct ntuser_thread_info *info = NtUserGetThreadInfo();
787 DPI_AWARENESS prev, val = GetAwarenessFromDpiAwarenessContext( context );
789 if (val == DPI_AWARENESS_INVALID)
791 SetLastError( ERROR_INVALID_PARAMETER );
792 return 0;
794 if (!(prev = info->dpi_awareness))
796 prev = NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3;
797 prev |= 0x80000010; /* restore to process default */
799 if (((ULONG_PTR)context & ~(ULONG_PTR)0x13) == 0x80000000) info->dpi_awareness = 0;
800 else info->dpi_awareness = val | 0x10;
801 return ULongToHandle( prev );
804 /***********************************************************************
805 * MonitorFromRect (USER32.@)
807 HMONITOR WINAPI MonitorFromRect( const RECT *rect, DWORD flags )
809 return NtUserMonitorFromRect( rect, flags );
812 /***********************************************************************
813 * MonitorFromPoint (USER32.@)
815 HMONITOR WINAPI MonitorFromPoint( POINT pt, DWORD flags )
817 RECT rect;
819 SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 );
820 return MonitorFromRect( &rect, flags );
823 /***********************************************************************
824 * MonitorFromWindow (USER32.@)
826 HMONITOR WINAPI MonitorFromWindow( HWND hwnd, DWORD flags )
828 return NtUserMonitorFromWindow( hwnd, flags );
831 /***********************************************************************
832 * GetMonitorInfoA (USER32.@)
834 BOOL WINAPI GetMonitorInfoA( HMONITOR monitor, LPMONITORINFO info )
836 MONITORINFOEXW miW;
837 BOOL ret;
839 if (info->cbSize == sizeof(MONITORINFO)) return GetMonitorInfoW( monitor, info );
840 if (info->cbSize != sizeof(MONITORINFOEXA)) return FALSE;
842 miW.cbSize = sizeof(miW);
843 ret = GetMonitorInfoW( monitor, (MONITORINFO *)&miW );
844 if (ret)
846 MONITORINFOEXA *miA = (MONITORINFOEXA *)info;
847 miA->rcMonitor = miW.rcMonitor;
848 miA->rcWork = miW.rcWork;
849 miA->dwFlags = miW.dwFlags;
850 WideCharToMultiByte(CP_ACP, 0, miW.szDevice, -1, miA->szDevice, sizeof(miA->szDevice), NULL, NULL);
852 return ret;
855 /***********************************************************************
856 * GetMonitorInfoW (USER32.@)
858 BOOL WINAPI GetMonitorInfoW( HMONITOR monitor, LPMONITORINFO info )
860 return NtUserGetMonitorInfo( monitor, info );
863 #ifdef __i386__
864 /* Some apps pass a non-stdcall callback to EnumDisplayMonitors,
865 * so we need a small assembly wrapper to call it.
867 extern BOOL enum_mon_callback_wrapper( void *proc, HMONITOR monitor, HDC hdc, RECT *rect, LPARAM lparam );
868 __ASM_GLOBAL_FUNC( enum_mon_callback_wrapper,
869 "pushl %ebp\n\t"
870 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
871 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
872 "movl %esp,%ebp\n\t"
873 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
874 "subl $8,%esp\n\t"
875 "pushl 24(%ebp)\n\t" /* lparam */
876 /* MJ's Help Diagnostic expects that %ecx contains the address to the rect. */
877 "movl 20(%ebp),%ecx\n\t" /* rect */
878 "pushl %ecx\n\t"
879 "pushl 16(%ebp)\n\t" /* hdc */
880 "pushl 12(%ebp)\n\t" /* monitor */
881 "movl 8(%ebp),%eax\n" /* proc */
882 "call *%eax\n\t"
883 "leave\n\t"
884 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
885 __ASM_CFI(".cfi_same_value %ebp\n\t")
886 "ret" )
887 #endif /* __i386__ */
889 BOOL WINAPI User32CallEnumDisplayMonitor( struct enum_display_monitor_params *params, ULONG size )
891 #ifdef __i386__
892 return enum_mon_callback_wrapper( params->proc, params->monitor, params->hdc,
893 &params->rect, params->lparam );
894 #else
895 return params->proc( params->monitor, params->hdc, &params->rect, params->lparam );
896 #endif
899 /***********************************************************************
900 * EnumDisplayDevicesA (USER32.@)
902 BOOL WINAPI EnumDisplayDevicesA( LPCSTR device, DWORD index, DISPLAY_DEVICEA *info, DWORD flags )
904 UNICODE_STRING deviceW;
905 DISPLAY_DEVICEW ddW;
906 BOOL ret;
908 if (device)
909 RtlCreateUnicodeStringFromAsciiz( &deviceW, device );
910 else
911 deviceW.Buffer = NULL;
913 ddW.cb = sizeof(ddW);
914 ret = EnumDisplayDevicesW( deviceW.Buffer, index, &ddW, flags );
915 RtlFreeUnicodeString( &deviceW );
917 if (!ret)
918 return ret;
920 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceName, -1, info->DeviceName, sizeof(info->DeviceName), NULL, NULL );
921 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceString, -1, info->DeviceString, sizeof(info->DeviceString), NULL, NULL );
922 info->StateFlags = ddW.StateFlags;
924 if (info->cb >= offsetof(DISPLAY_DEVICEA, DeviceID) + sizeof(info->DeviceID))
925 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceID, -1, info->DeviceID, sizeof(info->DeviceID), NULL, NULL );
926 if (info->cb >= offsetof(DISPLAY_DEVICEA, DeviceKey) + sizeof(info->DeviceKey))
927 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceKey, -1, info->DeviceKey, sizeof(info->DeviceKey), NULL, NULL );
929 return TRUE;
932 /***********************************************************************
933 * EnumDisplayDevicesW (USER32.@)
935 BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags )
937 UNICODE_STRING str;
938 RtlInitUnicodeString( &str, device );
939 return NT_SUCCESS(NtUserEnumDisplayDevices( &str, index, info, flags ));
942 /**********************************************************************
943 * GetAutoRotationState [USER32.@]
945 BOOL WINAPI GetAutoRotationState( AR_STATE *state )
947 TRACE("(%p)\n", state);
949 if (!state)
951 SetLastError(ERROR_INVALID_PARAMETER);
952 return FALSE;
955 *state = AR_NOSENSOR;
956 return TRUE;
959 /**********************************************************************
960 * GetDisplayAutoRotationPreferences [USER32.@]
962 BOOL WINAPI GetDisplayAutoRotationPreferences( ORIENTATION_PREFERENCE *orientation )
964 FIXME("(%p): stub\n", orientation);
965 *orientation = ORIENTATION_PREFERENCE_NONE;
966 return TRUE;
969 /* physical<->logical mapping functions from win8 that are nops in later versions */
971 /***********************************************************************
972 * GetPhysicalCursorPos (USER32.@)
974 BOOL WINAPI GetPhysicalCursorPos( POINT *point )
976 return GetCursorPos( point );
979 /***********************************************************************
980 * SetPhysicalCursorPos (USER32.@)
982 BOOL WINAPI SetPhysicalCursorPos( INT x, INT y )
984 return NtUserSetCursorPos( x, y );
987 /***********************************************************************
988 * WindowFromPhysicalPoint (USER32.@)
990 HWND WINAPI WindowFromPhysicalPoint( POINT pt )
992 return WindowFromPoint( pt );
995 /***********************************************************************
996 * LogicalToPhysicalPoint (USER32.@)
998 BOOL WINAPI LogicalToPhysicalPoint( HWND hwnd, POINT *point )
1000 return TRUE;
1003 /***********************************************************************
1004 * PhysicalToLogicalPoint (USER32.@)
1006 BOOL WINAPI PhysicalToLogicalPoint( HWND hwnd, POINT *point )
1008 return TRUE;
1011 static DISPLAYCONFIG_ROTATION get_dc_rotation(const DEVMODEW *devmode)
1013 if (devmode->dmFields & DM_DISPLAYORIENTATION)
1014 return devmode->dmDisplayOrientation + 1;
1015 else
1016 return DISPLAYCONFIG_ROTATION_IDENTITY;
1019 static DISPLAYCONFIG_SCANLINE_ORDERING get_dc_scanline_ordering(const DEVMODEW *devmode)
1021 if (!(devmode->dmFields & DM_DISPLAYFLAGS))
1022 return DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED;
1023 else if (devmode->dmDisplayFlags & DM_INTERLACED)
1024 return DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED;
1025 else
1026 return DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
1029 static DISPLAYCONFIG_PIXELFORMAT get_dc_pixelformat(DWORD dmBitsPerPel)
1031 if ((dmBitsPerPel == 8) || (dmBitsPerPel == 16) ||
1032 (dmBitsPerPel == 24) || (dmBitsPerPel == 32))
1033 return dmBitsPerPel / 8;
1034 else
1035 return DISPLAYCONFIG_PIXELFORMAT_NONGDI;
1038 static void set_mode_target_info(DISPLAYCONFIG_MODE_INFO *info, const LUID *gpu_luid, UINT32 target_id,
1039 UINT32 flags, const DEVMODEW *devmode)
1041 DISPLAYCONFIG_TARGET_MODE *mode = &info->targetMode;
1043 info->infoType = DISPLAYCONFIG_MODE_INFO_TYPE_TARGET;
1044 info->adapterId = *gpu_luid;
1045 info->id = target_id;
1047 /* FIXME: Populate pixelRate/hSyncFreq/totalSize with real data */
1048 mode->targetVideoSignalInfo.pixelRate = devmode->dmDisplayFrequency * devmode->dmPelsWidth * devmode->dmPelsHeight;
1049 mode->targetVideoSignalInfo.hSyncFreq.Numerator = devmode->dmDisplayFrequency * devmode->dmPelsWidth;
1050 mode->targetVideoSignalInfo.hSyncFreq.Denominator = 1;
1051 mode->targetVideoSignalInfo.vSyncFreq.Numerator = devmode->dmDisplayFrequency;
1052 mode->targetVideoSignalInfo.vSyncFreq.Denominator = 1;
1053 mode->targetVideoSignalInfo.activeSize.cx = devmode->dmPelsWidth;
1054 mode->targetVideoSignalInfo.activeSize.cy = devmode->dmPelsHeight;
1055 if (flags & QDC_DATABASE_CURRENT)
1057 mode->targetVideoSignalInfo.totalSize.cx = 0;
1058 mode->targetVideoSignalInfo.totalSize.cy = 0;
1060 else
1062 mode->targetVideoSignalInfo.totalSize.cx = devmode->dmPelsWidth;
1063 mode->targetVideoSignalInfo.totalSize.cy = devmode->dmPelsHeight;
1065 mode->targetVideoSignalInfo.videoStandard = D3DKMDT_VSS_OTHER;
1066 mode->targetVideoSignalInfo.scanLineOrdering = get_dc_scanline_ordering(devmode);
1069 static void set_path_target_info(DISPLAYCONFIG_PATH_TARGET_INFO *info, const LUID *gpu_luid,
1070 UINT32 target_id, UINT32 mode_index, const DEVMODEW *devmode)
1072 info->adapterId = *gpu_luid;
1073 info->id = target_id;
1074 info->modeInfoIdx = mode_index;
1075 info->outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL;
1076 info->rotation = get_dc_rotation(devmode);
1077 info->scaling = DISPLAYCONFIG_SCALING_IDENTITY;
1078 info->refreshRate.Numerator = devmode->dmDisplayFrequency;
1079 info->refreshRate.Denominator = 1;
1080 info->scanLineOrdering = get_dc_scanline_ordering(devmode);
1081 info->targetAvailable = TRUE;
1082 info->statusFlags = DISPLAYCONFIG_TARGET_IN_USE;
1085 static void set_mode_source_info(DISPLAYCONFIG_MODE_INFO *info, const LUID *gpu_luid,
1086 UINT32 source_id, const DEVMODEW *devmode)
1088 DISPLAYCONFIG_SOURCE_MODE *mode = &(info->sourceMode);
1090 info->infoType = DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE;
1091 info->adapterId = *gpu_luid;
1092 info->id = source_id;
1094 mode->width = devmode->dmPelsWidth;
1095 mode->height = devmode->dmPelsHeight;
1096 mode->pixelFormat = get_dc_pixelformat(devmode->dmBitsPerPel);
1097 if (devmode->dmFields & DM_POSITION)
1099 mode->position = devmode->dmPosition;
1101 else
1103 mode->position.x = 0;
1104 mode->position.y = 0;
1108 static void set_path_source_info(DISPLAYCONFIG_PATH_SOURCE_INFO *info, const LUID *gpu_luid,
1109 UINT32 source_id, UINT32 mode_index)
1111 info->adapterId = *gpu_luid;
1112 info->id = source_id;
1113 info->modeInfoIdx = mode_index;
1114 info->statusFlags = DISPLAYCONFIG_SOURCE_IN_USE;
1117 static BOOL source_mode_exists(const DISPLAYCONFIG_MODE_INFO *modeinfo, UINT32 num_modes,
1118 UINT32 source_id, UINT32 *found_mode_index)
1120 UINT32 i;
1122 for (i = 0; i < num_modes; i++)
1124 if (modeinfo[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE &&
1125 modeinfo[i].id == source_id)
1127 *found_mode_index = i;
1128 return TRUE;
1131 return FALSE;
1134 /***********************************************************************
1135 * QueryDisplayConfig (USER32.@)
1137 LONG WINAPI QueryDisplayConfig(UINT32 flags, UINT32 *numpathelements, DISPLAYCONFIG_PATH_INFO *pathinfo,
1138 UINT32 *numinfoelements, DISPLAYCONFIG_MODE_INFO *modeinfo,
1139 DISPLAYCONFIG_TOPOLOGY_ID *topologyid)
1141 LONG adapter_index, ret;
1142 HANDLE mutex;
1143 HDEVINFO devinfo;
1144 SP_DEVINFO_DATA device_data = {sizeof(device_data)};
1145 DWORD monitor_index = 0, state_flags, type;
1146 UINT32 output_id, source_mode_index, path_index = 0, mode_index = 0;
1147 LUID gpu_luid;
1148 WCHAR device_name[CCHDEVICENAME];
1149 DEVMODEW devmode;
1151 FIXME("(%08x %p %p %p %p %p): semi-stub\n", flags, numpathelements, pathinfo, numinfoelements, modeinfo, topologyid);
1153 if (!numpathelements || !numinfoelements)
1154 return ERROR_INVALID_PARAMETER;
1156 if (!*numpathelements || !*numinfoelements)
1157 return ERROR_INVALID_PARAMETER;
1159 if (flags != QDC_ALL_PATHS &&
1160 flags != QDC_ONLY_ACTIVE_PATHS &&
1161 flags != QDC_DATABASE_CURRENT)
1162 return ERROR_INVALID_PARAMETER;
1164 if (((flags == QDC_DATABASE_CURRENT) && !topologyid) ||
1165 ((flags != QDC_DATABASE_CURRENT) && topologyid))
1166 return ERROR_INVALID_PARAMETER;
1168 if (flags != QDC_ONLY_ACTIVE_PATHS)
1169 FIXME("only returning active paths\n");
1171 if (topologyid)
1173 FIXME("setting toplogyid to DISPLAYCONFIG_TOPOLOGY_INTERNAL\n");
1174 *topologyid = DISPLAYCONFIG_TOPOLOGY_INTERNAL;
1177 wait_graphics_driver_ready();
1178 mutex = get_display_device_init_mutex();
1180 /* Iterate through "targets"/monitors.
1181 * Each target corresponds to a path, and each path corresponds to one or two unique modes.
1183 devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, L"DISPLAY", NULL, DIGCF_PRESENT);
1184 if (devinfo == INVALID_HANDLE_VALUE)
1186 ret = ERROR_GEN_FAILURE;
1187 goto done;
1190 ret = ERROR_GEN_FAILURE;
1191 while (SetupDiEnumDeviceInfo(devinfo, monitor_index++, &device_data))
1193 /* Only count active monitors */
1194 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS,
1195 &type, (BYTE *)&state_flags, sizeof(state_flags), NULL, 0))
1196 goto done;
1197 if (!(state_flags & DISPLAY_DEVICE_ACTIVE))
1198 continue;
1200 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
1201 &type, (BYTE *)&gpu_luid, sizeof(gpu_luid), NULL, 0))
1202 goto done;
1204 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID,
1205 &type, (BYTE *)&output_id, sizeof(output_id), NULL, 0))
1206 goto done;
1208 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME,
1209 &type, (BYTE *)device_name, sizeof(device_name), NULL, 0))
1210 goto done;
1212 memset(&devmode, 0, sizeof(devmode));
1213 devmode.dmSize = sizeof(devmode);
1214 if (!EnumDisplaySettingsW(device_name, ENUM_CURRENT_SETTINGS, &devmode))
1215 goto done;
1217 /* Extract the adapter index from device_name to use as the source ID */
1218 adapter_index = wcstol(device_name + lstrlenW(L"\\\\.\\DISPLAY"), NULL, 10);
1219 adapter_index--;
1221 if (path_index == *numpathelements || mode_index == *numinfoelements)
1223 ret = ERROR_INSUFFICIENT_BUFFER;
1224 goto done;
1227 pathinfo[path_index].flags = DISPLAYCONFIG_PATH_ACTIVE;
1228 set_mode_target_info(&modeinfo[mode_index], &gpu_luid, output_id, flags, &devmode);
1229 set_path_target_info(&(pathinfo[path_index].targetInfo), &gpu_luid, output_id, mode_index, &devmode);
1231 mode_index++;
1232 if (mode_index == *numinfoelements)
1234 ret = ERROR_INSUFFICIENT_BUFFER;
1235 goto done;
1238 /* Multiple targets can be driven by the same source, ensure a mode
1239 * hasn't already been added for this source.
1241 if (!source_mode_exists(modeinfo, mode_index, adapter_index, &source_mode_index))
1243 set_mode_source_info(&modeinfo[mode_index], &gpu_luid, adapter_index, &devmode);
1244 source_mode_index = mode_index;
1245 mode_index++;
1247 set_path_source_info(&(pathinfo[path_index].sourceInfo), &gpu_luid, adapter_index, source_mode_index);
1248 path_index++;
1251 *numpathelements = path_index;
1252 *numinfoelements = mode_index;
1253 ret = ERROR_SUCCESS;
1255 done:
1256 SetupDiDestroyDeviceInfoList(devinfo);
1257 release_display_device_init_mutex(mutex);
1258 return ret;
1261 /***********************************************************************
1262 * DisplayConfigGetDeviceInfo (USER32.@)
1264 LONG WINAPI DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER *packet)
1266 return RtlNtStatusToDosError(NtUserDisplayConfigGetDeviceInfo(packet));
1269 /***********************************************************************
1270 * SetDisplayConfig (USER32.@)
1272 LONG WINAPI SetDisplayConfig(UINT32 path_info_count, DISPLAYCONFIG_PATH_INFO *path_info, UINT32 mode_info_count,
1273 DISPLAYCONFIG_MODE_INFO *mode_info, UINT32 flags)
1275 FIXME("path_info_count %u, path_info %p, mode_info_count %u, mode_info %p, flags %#x stub.\n",
1276 path_info_count, path_info, mode_info_count, mode_info, flags);
1278 return ERROR_SUCCESS;