user32/tests: Test EnableMouseInPointer behavior.
[wine.git] / dlls / user32 / sysparams.c
blobc7bd702726a96f05c14189dbe952450361a7e6a0
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 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 );
168 return TRUE;
171 RECT get_virtual_screen_rect(void)
173 RECT rect = {0};
175 NtUserEnumDisplayMonitors( 0, NULL, get_virtual_screen_proc, (LPARAM)&rect );
176 return 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;
186 return FALSE;
189 return TRUE;
192 RECT get_primary_monitor_rect(void)
194 RECT rect = {0};
196 NtUserEnumDisplayMonitors( 0, NULL, get_primary_monitor_proc, (LPARAM)&rect );
197 return rect;
200 HDC get_display_dc(void)
202 EnterCriticalSection( &display_dc_section );
203 if (!display_dc)
205 HDC dc;
207 LeaveCriticalSection( &display_dc_section );
208 dc = CreateDCW( L"DISPLAY", NULL, NULL, NULL );
209 EnterCriticalSection( &display_dc_section );
210 if (display_dc)
211 DeleteDC(dc);
212 else
213 display_dc = dc;
215 return display_dc;
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 );
228 return mutex;
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;
242 if (!ready)
244 SendMessageW( GetDesktopWindow(), WM_NULL, 0, 0 );
245 ready = TRUE;
249 /***********************************************************************
250 * SYSPARAMS_Init
252 void SYSPARAMS_Init(void)
254 system_dpi = NtUserGetSystemDpiForProcess( NULL );
257 static BOOL update_desktop_wallpaper(void)
259 DWORD pid;
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 );
272 return TRUE;
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();
284 return ret;
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();
296 return ret;
300 /***********************************************************************
301 * SystemParametersInfoA (USER32.@)
303 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
304 PVOID pvParam, UINT fuWinIni )
306 BOOL ret;
308 TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
310 switch (uiAction)
312 case SPI_SETDESKWALLPAPER: /* 20 */
313 case SPI_SETDESKPATTERN: /* 21 */
315 WCHAR buffer[256];
316 if (pvParam)
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 );
320 break;
323 case SPI_GETICONTITLELOGFONT: /* 31 */
325 LOGFONTW tmp;
326 ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
327 if (ret && pvParam)
328 SYSPARAMS_LogFont32WTo32A( &tmp, pvParam );
329 break;
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 );
341 if (ret)
342 SYSPARAMS_NonClientMetrics32WTo32A( &tmp, lpnmA );
344 else
345 ret = FALSE;
346 break;
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 );
360 else
361 ret = FALSE;
362 break;
365 case SPI_GETICONMETRICS: /* 45 WINVER >= 0x400 */
367 ICONMETRICSW tmp;
368 LPICONMETRICSA lpimA = pvParam;
369 if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
371 tmp.cbSize = sizeof(ICONMETRICSW);
372 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
373 if (ret)
375 lpimA->iHorzSpacing = tmp.iHorzSpacing;
376 lpimA->iVertSpacing = tmp.iVertSpacing;
377 lpimA->iTitleWrap = tmp.iTitleWrap;
378 SYSPARAMS_LogFont32WTo32A( &tmp.lfFont, &lpimA->lfFont );
381 else
382 ret = FALSE;
383 break;
386 case SPI_SETICONMETRICS: /* 46 WINVER >= 0x400 */
388 ICONMETRICSW tmp;
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 );
399 else
400 ret = FALSE;
401 break;
404 case SPI_GETHIGHCONTRAST: /* 66 WINVER >= 0x400 */
406 HIGHCONTRASTW tmp;
407 LPHIGHCONTRASTA lphcA = pvParam;
408 if (lphcA && lphcA->cbSize == sizeof(HIGHCONTRASTA))
410 tmp.cbSize = sizeof(HIGHCONTRASTW);
411 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
412 if (ret)
414 lphcA->dwFlags = tmp.dwFlags;
415 lphcA->lpszDefaultScheme = NULL; /* FIXME? */
418 else
419 ret = FALSE;
420 break;
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));
428 break;
431 default:
432 ret = SystemParametersInfoW( uiAction, uiParam, pvParam, fuWinIni );
433 break;
435 return ret;
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
461 * RETURN
462 * previous state
464 BOOL WINAPI SwapMouseButton( BOOL fSwap )
466 BOOL prev = GetSystemMetrics(SM_SWAPBUTTON);
467 SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP, fSwap, 0, 0);
468 return prev;
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" );
496 return FALSE;
500 /***********************************************************************
501 * GetSysColorBrush (USER32.@)
503 HBRUSH WINAPI DECLSPEC_HOTPATCH GetSysColorBrush( INT index )
505 return NtUserGetSysColorBrush( index );
509 /***********************************************************************
510 * SYSCOLOR_GetPen
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 )
554 LONG ret;
555 UNICODE_STRING nameW;
557 if (devname) RtlCreateUnicodeStringFromAsciiz(&nameW, devname);
558 else nameW.Buffer = NULL;
560 if (devmode)
562 DEVMODEW *devmodeW;
564 devmodeW = GdiConvertToDevmodeW(devmode);
565 if (devmodeW)
567 ret = ChangeDisplaySettingsExW(nameW.Buffer, devmodeW, hwnd, flags, lparam);
568 HeapFree(GetProcessHeap(), 0, devmodeW);
570 else
571 ret = DISP_CHANGE_SUCCESSFUL;
573 else
575 ret = ChangeDisplaySettingsExW(nameW.Buffer, NULL, hwnd, flags, lparam);
578 if (devname) RtlFreeUnicodeString(&nameW);
579 return ret;
583 /***********************************************************************
584 * ChangeDisplaySettingsExW (USER32.@)
586 LONG WINAPI ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd,
587 DWORD flags, LPVOID lparam )
589 UNICODE_STRING str;
590 RtlInitUnicodeString( &str, devname );
591 return NtUserChangeDisplaySettings( &str, devmode, hwnd, flags, lparam );
595 /***********************************************************************
596 * EnumDisplaySettingsW (USER32.@)
598 * RETURNS
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)
623 DEVMODEW devmodeW;
624 BOOL ret;
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);
633 if (ret)
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);
654 return ret;
658 /***********************************************************************
659 * EnumDisplaySettingsExW (USER32.@)
661 BOOL WINAPI EnumDisplaySettingsExW( const WCHAR *device, DWORD mode,
662 DEVMODEW *dev_mode, DWORD flags )
664 UNICODE_STRING str;
665 RtlInitUnicodeString( &str, device );
666 return NtUserEnumDisplaySettings( &str, mode, dev_mode, flags );
669 /**********************************************************************
670 * SetProcessDpiAwarenessContext (USER32.@)
672 BOOL WINAPI SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
674 ULONG awareness;
676 switch (GetAwarenessFromDpiAwarenessContext( context ))
678 case DPI_AWARENESS_UNAWARE:
679 awareness = NTUSER_DPI_UNAWARE;
680 break;
681 case DPI_AWARENESS_SYSTEM_AWARE:
682 awareness = NTUSER_DPI_SYSTEM_AWARE;
683 break;
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;
687 break;
688 default:
689 SetLastError( ERROR_INVALID_PARAMETER );
690 return FALSE;
693 if (!NtUserSetProcessDpiAwarenessContext( awareness, 0 ))
695 SetLastError( ERROR_ACCESS_DENIED );
696 return FALSE;
699 TRACE( "set to %p\n", context );
700 return TRUE;
703 /**********************************************************************
704 * GetProcessDpiAwarenessInternal (USER32.@)
706 BOOL WINAPI GetProcessDpiAwarenessInternal( HANDLE process, DPI_AWARENESS *awareness )
708 *awareness = NtUserGetProcessDpiAwarenessContext( process ) & 3;
709 return TRUE;
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 );
724 return FALSE;
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)
746 case 0x10:
747 case 0x11:
748 case 0x12:
749 case 0x80000010:
750 case 0x80000011:
751 case 0x80000012:
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;
757 default:
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)
775 TRACE("\n");
776 NtUserSetProcessDpiAwarenessContext( NTUSER_DPI_SYSTEM_AWARE, 0 );
777 return TRUE;
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 );
795 return FALSE;
798 /***********************************************************************
799 * GetDpiForSystem (USER32.@)
801 UINT WINAPI GetDpiForSystem(void)
803 if (!IsProcessDPIAware()) return USER_DEFAULT_SCREEN_DPI;
804 return system_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 );
829 return 0;
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 )
854 RECT rect;
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 )
873 MONITORINFOEXW miW;
874 BOOL ret;
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 );
881 if (ret)
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);
889 return ret;
892 /***********************************************************************
893 * GetMonitorInfoW (USER32.@)
895 BOOL WINAPI GetMonitorInfoW( HMONITOR monitor, LPMONITORINFO info )
897 return NtUserGetMonitorInfo( monitor, info );
900 #ifdef __i386__
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,
906 "pushl %ebp\n\t"
907 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
908 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
909 "movl %esp,%ebp\n\t"
910 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
911 "subl $8,%esp\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 */
915 "pushl %ecx\n\t"
916 "pushl 16(%ebp)\n\t" /* hdc */
917 "pushl 12(%ebp)\n\t" /* monitor */
918 "movl 8(%ebp),%eax\n" /* proc */
919 "call *%eax\n\t"
920 "leave\n\t"
921 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
922 __ASM_CFI(".cfi_same_value %ebp\n\t")
923 "ret" )
924 #endif /* __i386__ */
926 BOOL WINAPI User32CallEnumDisplayMonitor( struct enum_display_monitor_params *params, ULONG size )
928 #ifdef __i386__
929 return enum_mon_callback_wrapper( params->proc, params->monitor, params->hdc,
930 &params->rect, params->lparam );
931 #else
932 return params->proc( params->monitor, params->hdc, &params->rect, params->lparam );
933 #endif
936 /***********************************************************************
937 * EnumDisplayDevicesA (USER32.@)
939 BOOL WINAPI EnumDisplayDevicesA( LPCSTR device, DWORD index, DISPLAY_DEVICEA *info, DWORD flags )
941 UNICODE_STRING deviceW;
942 DISPLAY_DEVICEW ddW;
943 BOOL ret;
945 if (device)
946 RtlCreateUnicodeStringFromAsciiz( &deviceW, device );
947 else
948 deviceW.Buffer = NULL;
950 ddW.cb = sizeof(ddW);
951 ret = EnumDisplayDevicesW( deviceW.Buffer, index, &ddW, flags );
952 RtlFreeUnicodeString( &deviceW );
954 if (!ret)
955 return ret;
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 );
966 return TRUE;
969 /***********************************************************************
970 * EnumDisplayDevicesW (USER32.@)
972 BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags )
974 UNICODE_STRING str;
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);
986 if (!state)
988 SetLastError(ERROR_INVALID_PARAMETER);
989 return FALSE;
992 *state = AR_NOSENSOR;
993 return TRUE;
996 /**********************************************************************
997 * GetDisplayAutoRotationPreferences [USER32.@]
999 BOOL WINAPI GetDisplayAutoRotationPreferences( ORIENTATION_PREFERENCE *orientation )
1001 FIXME("(%p): stub\n", orientation);
1002 *orientation = ORIENTATION_PREFERENCE_NONE;
1003 return TRUE;
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 )
1037 return TRUE;
1040 /***********************************************************************
1041 * PhysicalToLogicalPoint (USER32.@)
1043 BOOL WINAPI PhysicalToLogicalPoint( HWND hwnd, POINT *point )
1045 return TRUE;
1048 static DISPLAYCONFIG_ROTATION get_dc_rotation(const DEVMODEW *devmode)
1050 if (devmode->dmFields & DM_DISPLAYORIENTATION)
1051 return devmode->dmDisplayOrientation + 1;
1052 else
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;
1062 else
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;
1071 else
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;
1097 else
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;
1138 else
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)
1157 UINT32 i;
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;
1165 return TRUE;
1168 return FALSE;
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;
1179 HANDLE mutex;
1180 HDEVINFO devinfo;
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;
1184 LUID gpu_luid;
1185 WCHAR device_name[CCHDEVICENAME];
1186 DEVMODEW devmode;
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");
1208 if (topologyid)
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;
1224 goto done;
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))
1233 goto done;
1234 if (!(state_flags & DISPLAY_DEVICE_ACTIVE))
1235 continue;
1237 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
1238 &type, (BYTE *)&gpu_luid, sizeof(gpu_luid), NULL, 0))
1239 goto done;
1241 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID,
1242 &type, (BYTE *)&output_id, sizeof(output_id), NULL, 0))
1243 goto done;
1245 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME,
1246 &type, (BYTE *)device_name, sizeof(device_name), NULL, 0))
1247 goto done;
1249 memset(&devmode, 0, sizeof(devmode));
1250 devmode.dmSize = sizeof(devmode);
1251 if (!EnumDisplaySettingsW(device_name, ENUM_CURRENT_SETTINGS, &devmode))
1252 goto done;
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);
1256 adapter_index--;
1258 if (path_index == *numpathelements || mode_index == *numinfoelements)
1260 ret = ERROR_INSUFFICIENT_BUFFER;
1261 goto done;
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);
1268 mode_index++;
1269 if (mode_index == *numinfoelements)
1271 ret = ERROR_INSUFFICIENT_BUFFER;
1272 goto done;
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;
1282 mode_index++;
1284 set_path_source_info(&(pathinfo[path_index].sourceInfo), &gpu_luid, adapter_index, source_mode_index);
1285 path_index++;
1288 *numpathelements = path_index;
1289 *numinfoelements = mode_index;
1290 ret = ERROR_SUCCESS;
1292 done:
1293 SetupDiDestroyDeviceInfoList(devinfo);
1294 release_display_device_init_mutex(mutex);
1295 return ret;
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;