mshtml: Implement onprogress for XMLHttpRequest.
[wine.git] / dlls / user32 / sysparams.c
blobec83a1822a53a5f7e5de7db968c9e0c0cf3bf118
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 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "wingdi.h"
36 #include "winuser.h"
37 #include "winreg.h"
38 #include "wine/wingdi16.h"
39 #include "winerror.h"
41 #include "initguid.h"
42 #include "d3dkmdt.h"
43 #include "devguid.h"
44 #include "setupapi.h"
45 #include "controls.h"
46 #include "user_private.h"
47 #include "wine/asm.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(system);
53 DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_GPU_LUID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 1);
54 DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 2);
56 /* Wine specific monitor properties */
57 DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
58 DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5);
61 static HDC display_dc;
62 static CRITICAL_SECTION display_dc_section;
63 static CRITICAL_SECTION_DEBUG critsect_debug =
65 0, 0, &display_dc_section,
66 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
67 0, 0, { (DWORD_PTR)(__FILE__ ": display_dc_section") }
69 static CRITICAL_SECTION display_dc_section = { &critsect_debug, -1 ,0, 0, 0, 0 };
72 /* System parameters storage */
73 static UINT system_dpi;
75 static void SYSPARAMS_LogFont32WTo32A( const LOGFONTW* font32W, LPLOGFONTA font32A )
77 font32A->lfHeight = font32W->lfHeight;
78 font32A->lfWidth = font32W->lfWidth;
79 font32A->lfEscapement = font32W->lfEscapement;
80 font32A->lfOrientation = font32W->lfOrientation;
81 font32A->lfWeight = font32W->lfWeight;
82 font32A->lfItalic = font32W->lfItalic;
83 font32A->lfUnderline = font32W->lfUnderline;
84 font32A->lfStrikeOut = font32W->lfStrikeOut;
85 font32A->lfCharSet = font32W->lfCharSet;
86 font32A->lfOutPrecision = font32W->lfOutPrecision;
87 font32A->lfClipPrecision = font32W->lfClipPrecision;
88 font32A->lfQuality = font32W->lfQuality;
89 font32A->lfPitchAndFamily = font32W->lfPitchAndFamily;
90 WideCharToMultiByte( CP_ACP, 0, font32W->lfFaceName, -1, font32A->lfFaceName, LF_FACESIZE, NULL, NULL );
91 font32A->lfFaceName[LF_FACESIZE-1] = 0;
94 static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA* font32A, LPLOGFONTW font32W )
96 font32W->lfHeight = font32A->lfHeight;
97 font32W->lfWidth = font32A->lfWidth;
98 font32W->lfEscapement = font32A->lfEscapement;
99 font32W->lfOrientation = font32A->lfOrientation;
100 font32W->lfWeight = font32A->lfWeight;
101 font32W->lfItalic = font32A->lfItalic;
102 font32W->lfUnderline = font32A->lfUnderline;
103 font32W->lfStrikeOut = font32A->lfStrikeOut;
104 font32W->lfCharSet = font32A->lfCharSet;
105 font32W->lfOutPrecision = font32A->lfOutPrecision;
106 font32W->lfClipPrecision = font32A->lfClipPrecision;
107 font32W->lfQuality = font32A->lfQuality;
108 font32W->lfPitchAndFamily = font32A->lfPitchAndFamily;
109 MultiByteToWideChar( CP_ACP, 0, font32A->lfFaceName, -1, font32W->lfFaceName, LF_FACESIZE );
110 font32W->lfFaceName[LF_FACESIZE-1] = 0;
113 static void SYSPARAMS_NonClientMetrics32WTo32A( const NONCLIENTMETRICSW* lpnm32W, LPNONCLIENTMETRICSA lpnm32A )
115 lpnm32A->iBorderWidth = lpnm32W->iBorderWidth;
116 lpnm32A->iScrollWidth = lpnm32W->iScrollWidth;
117 lpnm32A->iScrollHeight = lpnm32W->iScrollHeight;
118 lpnm32A->iCaptionWidth = lpnm32W->iCaptionWidth;
119 lpnm32A->iCaptionHeight = lpnm32W->iCaptionHeight;
120 SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfCaptionFont, &lpnm32A->lfCaptionFont );
121 lpnm32A->iSmCaptionWidth = lpnm32W->iSmCaptionWidth;
122 lpnm32A->iSmCaptionHeight = lpnm32W->iSmCaptionHeight;
123 SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfSmCaptionFont, &lpnm32A->lfSmCaptionFont );
124 lpnm32A->iMenuWidth = lpnm32W->iMenuWidth;
125 lpnm32A->iMenuHeight = lpnm32W->iMenuHeight;
126 SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfMenuFont, &lpnm32A->lfMenuFont );
127 SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfStatusFont, &lpnm32A->lfStatusFont );
128 SYSPARAMS_LogFont32WTo32A( &lpnm32W->lfMessageFont, &lpnm32A->lfMessageFont );
129 if (lpnm32A->cbSize > FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth))
131 if (lpnm32W->cbSize > FIELD_OFFSET(NONCLIENTMETRICSW, iPaddedBorderWidth))
132 lpnm32A->iPaddedBorderWidth = lpnm32W->iPaddedBorderWidth;
133 else
134 lpnm32A->iPaddedBorderWidth = 0;
138 static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA* lpnm32A, LPNONCLIENTMETRICSW lpnm32W )
140 lpnm32W->iBorderWidth = lpnm32A->iBorderWidth;
141 lpnm32W->iScrollWidth = lpnm32A->iScrollWidth;
142 lpnm32W->iScrollHeight = lpnm32A->iScrollHeight;
143 lpnm32W->iCaptionWidth = lpnm32A->iCaptionWidth;
144 lpnm32W->iCaptionHeight = lpnm32A->iCaptionHeight;
145 SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfCaptionFont, &lpnm32W->lfCaptionFont );
146 lpnm32W->iSmCaptionWidth = lpnm32A->iSmCaptionWidth;
147 lpnm32W->iSmCaptionHeight = lpnm32A->iSmCaptionHeight;
148 SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfSmCaptionFont, &lpnm32W->lfSmCaptionFont );
149 lpnm32W->iMenuWidth = lpnm32A->iMenuWidth;
150 lpnm32W->iMenuHeight = lpnm32A->iMenuHeight;
151 SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMenuFont, &lpnm32W->lfMenuFont );
152 SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfStatusFont, &lpnm32W->lfStatusFont );
153 SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMessageFont, &lpnm32W->lfMessageFont );
154 if (lpnm32W->cbSize > FIELD_OFFSET(NONCLIENTMETRICSW, iPaddedBorderWidth))
156 if (lpnm32A->cbSize > FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth))
157 lpnm32W->iPaddedBorderWidth = lpnm32A->iPaddedBorderWidth;
158 else
159 lpnm32W->iPaddedBorderWidth = 0;
164 /* Helper functions to retrieve monitors info */
166 static BOOL CALLBACK get_virtual_screen_proc( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
168 RECT *virtual_rect = (RECT *)lp;
170 UnionRect( virtual_rect, virtual_rect, rect );
171 return TRUE;
174 RECT get_virtual_screen_rect(void)
176 RECT rect = {0};
178 NtUserEnumDisplayMonitors( 0, NULL, get_virtual_screen_proc, (LPARAM)&rect );
179 return rect;
182 static BOOL CALLBACK get_primary_monitor_proc( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
184 RECT *primary_rect = (RECT *)lp;
186 if (!rect->top && !rect->left && rect->right && rect->bottom)
188 *primary_rect = *rect;
189 return FALSE;
192 return TRUE;
195 RECT get_primary_monitor_rect(void)
197 RECT rect = {0};
199 NtUserEnumDisplayMonitors( 0, NULL, get_primary_monitor_proc, (LPARAM)&rect );
200 return rect;
203 HDC get_display_dc(void)
205 EnterCriticalSection( &display_dc_section );
206 if (!display_dc)
208 HDC dc;
210 LeaveCriticalSection( &display_dc_section );
211 dc = CreateDCW( L"DISPLAY", NULL, NULL, NULL );
212 EnterCriticalSection( &display_dc_section );
213 if (display_dc)
214 DeleteDC(dc);
215 else
216 display_dc = dc;
218 return display_dc;
221 void release_display_dc( HDC hdc )
223 LeaveCriticalSection( &display_dc_section );
226 static HANDLE get_display_device_init_mutex( void )
228 HANDLE mutex = CreateMutexW( NULL, FALSE, L"display_device_init" );
230 WaitForSingleObject( mutex, INFINITE );
231 return mutex;
234 static void release_display_device_init_mutex( HANDLE mutex )
236 ReleaseMutex( mutex );
237 CloseHandle( mutex );
240 /* Wait until graphics driver is loaded by explorer */
241 void wait_graphics_driver_ready(void)
243 static BOOL ready = FALSE;
245 if (!ready)
247 SendMessageW( GetDesktopWindow(), WM_NULL, 0, 0 );
248 ready = TRUE;
252 /***********************************************************************
253 * SYSPARAMS_Init
255 void SYSPARAMS_Init(void)
257 system_dpi = NtUserGetSystemDpiForProcess( NULL );
260 static BOOL update_desktop_wallpaper(void)
262 DWORD pid;
264 if (GetWindowThreadProcessId( GetDesktopWindow(), &pid ) && pid == GetCurrentProcessId())
266 WCHAR wallpaper[MAX_PATH], pattern[256];
268 if (NtUserSystemParametersInfo( SPI_GETDESKWALLPAPER, ARRAYSIZE(wallpaper), wallpaper, 0 ) &&
269 NtUserCallOneParam( (ULONG_PTR)pattern, NtUserGetDeskPattern ))
271 update_wallpaper( wallpaper, pattern );
274 else SendMessageW( GetDesktopWindow(), WM_SETTINGCHANGE, SPI_SETDESKWALLPAPER, 0 );
275 return TRUE;
279 /***********************************************************************
280 * SystemParametersInfoForDpi (USER32.@)
282 BOOL WINAPI SystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi )
284 BOOL ret = NtUserSystemParametersInfoForDpi( action, val, ptr, winini, dpi );
285 if (ret && (action == SPI_SETDESKWALLPAPER || action == SPI_SETDESKPATTERN))
286 ret = update_desktop_wallpaper();
287 return ret;
291 /***********************************************************************
292 * SystemParametersInfoW (USER32.@)
294 BOOL WINAPI SystemParametersInfoW( UINT action, UINT val, void *ptr, UINT winini )
296 BOOL ret = NtUserSystemParametersInfo( action, val, ptr, winini );
297 if (ret && (action == SPI_SETDESKWALLPAPER || action == SPI_SETDESKPATTERN))
298 ret = update_desktop_wallpaper();
299 return ret;
303 /***********************************************************************
304 * SystemParametersInfoA (USER32.@)
306 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
307 PVOID pvParam, UINT fuWinIni )
309 BOOL ret;
311 TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
313 switch (uiAction)
315 case SPI_SETDESKWALLPAPER: /* 20 */
316 case SPI_SETDESKPATTERN: /* 21 */
318 WCHAR buffer[256];
319 if (pvParam)
320 if (!MultiByteToWideChar( CP_ACP, 0, pvParam, -1, buffer, ARRAY_SIZE( buffer )))
321 buffer[ARRAY_SIZE(buffer)-1] = 0;
322 ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
323 break;
326 case SPI_GETICONTITLELOGFONT: /* 31 */
328 LOGFONTW tmp;
329 ret = SystemParametersInfoW( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
330 if (ret && pvParam)
331 SYSPARAMS_LogFont32WTo32A( &tmp, pvParam );
332 break;
335 case SPI_GETNONCLIENTMETRICS: /* 41 WINVER >= 0x400 */
337 NONCLIENTMETRICSW tmp;
338 LPNONCLIENTMETRICSA lpnmA = pvParam;
339 if (lpnmA && (lpnmA->cbSize == sizeof(NONCLIENTMETRICSA) ||
340 lpnmA->cbSize == FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth)))
342 tmp.cbSize = sizeof(NONCLIENTMETRICSW);
343 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
344 if (ret)
345 SYSPARAMS_NonClientMetrics32WTo32A( &tmp, lpnmA );
347 else
348 ret = FALSE;
349 break;
352 case SPI_SETNONCLIENTMETRICS: /* 42 WINVER >= 0x400 */
354 NONCLIENTMETRICSW tmp;
355 LPNONCLIENTMETRICSA lpnmA = pvParam;
356 if (lpnmA && (lpnmA->cbSize == sizeof(NONCLIENTMETRICSA) ||
357 lpnmA->cbSize == FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth)))
359 tmp.cbSize = sizeof(NONCLIENTMETRICSW);
360 SYSPARAMS_NonClientMetrics32ATo32W( lpnmA, &tmp );
361 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
363 else
364 ret = FALSE;
365 break;
368 case SPI_GETICONMETRICS: /* 45 WINVER >= 0x400 */
370 ICONMETRICSW tmp;
371 LPICONMETRICSA lpimA = pvParam;
372 if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
374 tmp.cbSize = sizeof(ICONMETRICSW);
375 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
376 if (ret)
378 lpimA->iHorzSpacing = tmp.iHorzSpacing;
379 lpimA->iVertSpacing = tmp.iVertSpacing;
380 lpimA->iTitleWrap = tmp.iTitleWrap;
381 SYSPARAMS_LogFont32WTo32A( &tmp.lfFont, &lpimA->lfFont );
384 else
385 ret = FALSE;
386 break;
389 case SPI_SETICONMETRICS: /* 46 WINVER >= 0x400 */
391 ICONMETRICSW tmp;
392 LPICONMETRICSA lpimA = pvParam;
393 if (lpimA && lpimA->cbSize == sizeof(ICONMETRICSA))
395 tmp.cbSize = sizeof(ICONMETRICSW);
396 tmp.iHorzSpacing = lpimA->iHorzSpacing;
397 tmp.iVertSpacing = lpimA->iVertSpacing;
398 tmp.iTitleWrap = lpimA->iTitleWrap;
399 SYSPARAMS_LogFont32ATo32W( &lpimA->lfFont, &tmp.lfFont);
400 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
402 else
403 ret = FALSE;
404 break;
407 case SPI_GETHIGHCONTRAST: /* 66 WINVER >= 0x400 */
409 HIGHCONTRASTW tmp;
410 LPHIGHCONTRASTA lphcA = pvParam;
411 if (lphcA && lphcA->cbSize == sizeof(HIGHCONTRASTA))
413 tmp.cbSize = sizeof(HIGHCONTRASTW);
414 ret = SystemParametersInfoW( uiAction, uiParam, &tmp, fuWinIni );
415 if (ret)
417 lphcA->dwFlags = tmp.dwFlags;
418 lphcA->lpszDefaultScheme = NULL; /* FIXME? */
421 else
422 ret = FALSE;
423 break;
426 case SPI_GETDESKWALLPAPER: /* 115 */
428 WCHAR buffer[MAX_PATH];
429 ret = (SystemParametersInfoW( SPI_GETDESKWALLPAPER, uiParam, buffer, fuWinIni ) &&
430 WideCharToMultiByte(CP_ACP, 0, buffer, -1, pvParam, uiParam, NULL, NULL));
431 break;
434 default:
435 ret = SystemParametersInfoW( uiAction, uiParam, pvParam, fuWinIni );
436 break;
438 return ret;
442 /***********************************************************************
443 * GetSystemMetrics (USER32.@)
445 INT WINAPI GetSystemMetrics( INT index )
447 return NtUserGetSystemMetrics( index );
451 /***********************************************************************
452 * GetSystemMetricsForDpi (USER32.@)
454 INT WINAPI GetSystemMetricsForDpi( INT index, UINT dpi )
456 return NtUserGetSystemMetricsForDpi( index, dpi );
460 /***********************************************************************
461 * SwapMouseButton (USER32.@)
462 * Reverse or restore the meaning of the left and right mouse buttons
463 * fSwap [I ] TRUE - reverse, FALSE - original
464 * RETURN
465 * previous state
467 BOOL WINAPI SwapMouseButton( BOOL fSwap )
469 BOOL prev = GetSystemMetrics(SM_SWAPBUTTON);
470 SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP, fSwap, 0, 0);
471 return prev;
475 /**********************************************************************
476 * SetDoubleClickTime (USER32.@)
478 BOOL WINAPI SetDoubleClickTime( UINT interval )
480 return SystemParametersInfoW(SPI_SETDOUBLECLICKTIME, interval, 0, 0);
484 /*************************************************************************
485 * GetSysColor (USER32.@)
487 COLORREF WINAPI DECLSPEC_HOTPATCH GetSysColor( INT index )
489 return NtUserGetSysColor( index );
493 /*************************************************************************
494 * SetSysColorsTemp (USER32.@)
496 DWORD_PTR WINAPI SetSysColorsTemp( const COLORREF *pPens, const HBRUSH *pBrushes, DWORD_PTR n)
498 FIXME( "no longer supported\n" );
499 return FALSE;
503 /***********************************************************************
504 * GetSysColorBrush (USER32.@)
506 HBRUSH WINAPI DECLSPEC_HOTPATCH GetSysColorBrush( INT index )
508 return NtUserGetSysColorBrush( index );
512 /***********************************************************************
513 * SYSCOLOR_GetPen
515 HPEN SYSCOLOR_GetPen( INT index )
517 return NtUserGetSysColorPen( index );
521 /***********************************************************************
522 * SYSCOLOR_Get55AABrush
524 HBRUSH SYSCOLOR_Get55AABrush(void)
526 return NtUserGetSysColorBrush( COLOR_55AA_BRUSH );
529 /***********************************************************************
530 * ChangeDisplaySettingsA (USER32.@)
532 LONG WINAPI ChangeDisplaySettingsA( LPDEVMODEA devmode, DWORD flags )
534 if (devmode) devmode->dmDriverExtra = 0;
536 return ChangeDisplaySettingsExA(NULL,devmode,NULL,flags,NULL);
540 /***********************************************************************
541 * ChangeDisplaySettingsW (USER32.@)
543 LONG WINAPI ChangeDisplaySettingsW( LPDEVMODEW devmode, DWORD flags )
545 if (devmode) devmode->dmDriverExtra = 0;
547 return ChangeDisplaySettingsExW(NULL,devmode,NULL,flags,NULL);
551 /***********************************************************************
552 * ChangeDisplaySettingsExA (USER32.@)
554 LONG WINAPI ChangeDisplaySettingsExA( LPCSTR devname, LPDEVMODEA devmode, HWND hwnd,
555 DWORD flags, LPVOID lparam )
557 LONG ret;
558 UNICODE_STRING nameW;
560 if (devname) RtlCreateUnicodeStringFromAsciiz(&nameW, devname);
561 else nameW.Buffer = NULL;
563 if (devmode)
565 DEVMODEW *devmodeW;
567 devmodeW = GdiConvertToDevmodeW(devmode);
568 if (devmodeW)
570 ret = ChangeDisplaySettingsExW(nameW.Buffer, devmodeW, hwnd, flags, lparam);
571 HeapFree(GetProcessHeap(), 0, devmodeW);
573 else
574 ret = DISP_CHANGE_SUCCESSFUL;
576 else
578 ret = ChangeDisplaySettingsExW(nameW.Buffer, NULL, hwnd, flags, lparam);
581 if (devname) RtlFreeUnicodeString(&nameW);
582 return ret;
586 /***********************************************************************
587 * ChangeDisplaySettingsExW (USER32.@)
589 LONG WINAPI ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd,
590 DWORD flags, LPVOID lparam )
592 UNICODE_STRING str;
593 RtlInitUnicodeString( &str, devname );
594 return NtUserChangeDisplaySettings( &str, devmode, hwnd, flags, lparam );
598 /***********************************************************************
599 * EnumDisplaySettingsW (USER32.@)
601 * RETURNS
602 * TRUE if nth setting exists found (described in the LPDEVMODEW struct)
603 * FALSE if we do not have the nth setting
605 BOOL WINAPI EnumDisplaySettingsW( LPCWSTR name, DWORD n, LPDEVMODEW devmode )
607 return EnumDisplaySettingsExW(name, n, devmode, 0);
611 /***********************************************************************
612 * EnumDisplaySettingsA (USER32.@)
614 BOOL WINAPI EnumDisplaySettingsA(LPCSTR name,DWORD n,LPDEVMODEA devmode)
616 return EnumDisplaySettingsExA(name, n, devmode, 0);
620 /***********************************************************************
621 * EnumDisplaySettingsExA (USER32.@)
623 BOOL WINAPI EnumDisplaySettingsExA(LPCSTR lpszDeviceName, DWORD iModeNum,
624 LPDEVMODEA lpDevMode, DWORD dwFlags)
626 DEVMODEW devmodeW;
627 BOOL ret;
628 UNICODE_STRING nameW;
630 if (lpszDeviceName) RtlCreateUnicodeStringFromAsciiz(&nameW, lpszDeviceName);
631 else nameW.Buffer = NULL;
633 memset(&devmodeW, 0, sizeof(devmodeW));
634 devmodeW.dmSize = sizeof(devmodeW);
635 ret = EnumDisplaySettingsExW(nameW.Buffer,iModeNum,&devmodeW,dwFlags);
636 if (ret)
638 lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod);
639 lpDevMode->dmSpecVersion = devmodeW.dmSpecVersion;
640 lpDevMode->dmDriverVersion = devmodeW.dmDriverVersion;
641 WideCharToMultiByte(CP_ACP, 0, devmodeW.dmDeviceName, -1,
642 (LPSTR)lpDevMode->dmDeviceName, CCHDEVICENAME, NULL, NULL);
643 lpDevMode->dmDriverExtra = 0; /* FIXME */
644 lpDevMode->dmBitsPerPel = devmodeW.dmBitsPerPel;
645 lpDevMode->dmPelsHeight = devmodeW.dmPelsHeight;
646 lpDevMode->dmPelsWidth = devmodeW.dmPelsWidth;
647 lpDevMode->u2.dmDisplayFlags = devmodeW.u2.dmDisplayFlags;
648 lpDevMode->dmDisplayFrequency = devmodeW.dmDisplayFrequency;
649 lpDevMode->dmFields = devmodeW.dmFields;
651 lpDevMode->u1.s2.dmPosition.x = devmodeW.u1.s2.dmPosition.x;
652 lpDevMode->u1.s2.dmPosition.y = devmodeW.u1.s2.dmPosition.y;
653 lpDevMode->u1.s2.dmDisplayOrientation = devmodeW.u1.s2.dmDisplayOrientation;
654 lpDevMode->u1.s2.dmDisplayFixedOutput = devmodeW.u1.s2.dmDisplayFixedOutput;
656 if (lpszDeviceName) RtlFreeUnicodeString(&nameW);
657 return ret;
661 /***********************************************************************
662 * EnumDisplaySettingsExW (USER32.@)
664 BOOL WINAPI EnumDisplaySettingsExW( const WCHAR *device, DWORD mode,
665 DEVMODEW *dev_mode, DWORD flags )
667 UNICODE_STRING str;
668 RtlInitUnicodeString( &str, device );
669 return NtUserEnumDisplaySettings( &str, mode, dev_mode, flags );
672 /**********************************************************************
673 * get_monitor_dpi
675 UINT get_monitor_dpi( HMONITOR monitor )
677 /* FIXME: use the monitor DPI instead */
678 return system_dpi;
681 /**********************************************************************
682 * get_win_monitor_dpi
684 UINT get_win_monitor_dpi( HWND hwnd )
686 /* FIXME: use the monitor DPI instead */
687 return system_dpi;
690 /**********************************************************************
691 * get_thread_dpi
693 UINT get_thread_dpi(void)
695 switch (GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ))
697 case DPI_AWARENESS_UNAWARE: return USER_DEFAULT_SCREEN_DPI;
698 case DPI_AWARENESS_SYSTEM_AWARE: return system_dpi;
699 default: return 0; /* no scaling */
703 /**********************************************************************
704 * map_dpi_point
706 POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to )
708 if (dpi_from && dpi_to && dpi_from != dpi_to)
710 pt.x = MulDiv( pt.x, dpi_to, dpi_from );
711 pt.y = MulDiv( pt.y, dpi_to, dpi_from );
713 return pt;
716 /**********************************************************************
717 * point_win_to_phys_dpi
719 POINT point_win_to_phys_dpi( HWND hwnd, POINT pt )
721 return map_dpi_point( pt, GetDpiForWindow( hwnd ), get_win_monitor_dpi( hwnd ) );
724 /**********************************************************************
725 * point_phys_to_win_dpi
727 POINT point_phys_to_win_dpi( HWND hwnd, POINT pt )
729 return map_dpi_point( pt, get_win_monitor_dpi( hwnd ), GetDpiForWindow( hwnd ));
732 /**********************************************************************
733 * point_win_to_thread_dpi
735 POINT point_win_to_thread_dpi( HWND hwnd, POINT pt )
737 UINT dpi = get_thread_dpi();
738 if (!dpi) dpi = get_win_monitor_dpi( hwnd );
739 return map_dpi_point( pt, GetDpiForWindow( hwnd ), dpi );
742 /**********************************************************************
743 * map_dpi_rect
745 RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to )
747 if (dpi_from && dpi_to && dpi_from != dpi_to)
749 rect.left = MulDiv( rect.left, dpi_to, dpi_from );
750 rect.top = MulDiv( rect.top, dpi_to, dpi_from );
751 rect.right = MulDiv( rect.right, dpi_to, dpi_from );
752 rect.bottom = MulDiv( rect.bottom, dpi_to, dpi_from );
754 return rect;
757 /**********************************************************************
758 * rect_win_to_thread_dpi
760 RECT rect_win_to_thread_dpi( HWND hwnd, RECT rect )
762 UINT dpi = get_thread_dpi();
763 if (!dpi) dpi = get_win_monitor_dpi( hwnd );
764 return map_dpi_rect( rect, GetDpiForWindow( hwnd ), dpi );
767 /**********************************************************************
768 * SetProcessDpiAwarenessContext (USER32.@)
770 BOOL WINAPI SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
772 ULONG awareness;
774 switch (GetAwarenessFromDpiAwarenessContext( context ))
776 case DPI_AWARENESS_UNAWARE:
777 awareness = NTUSER_DPI_UNAWARE;
778 break;
779 case DPI_AWARENESS_SYSTEM_AWARE:
780 awareness = NTUSER_DPI_SYSTEM_AWARE;
781 break;
782 case DPI_AWARENESS_PER_MONITOR_AWARE:
783 awareness = context == DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
784 ? NTUSER_DPI_PER_MONITOR_AWARE_V2 : NTUSER_DPI_PER_MONITOR_AWARE;
785 break;
786 default:
787 SetLastError( ERROR_INVALID_PARAMETER );
788 return FALSE;
791 if (!NtUserSetProcessDpiAwarenessContext( awareness, 0 ))
793 SetLastError( ERROR_ACCESS_DENIED );
794 return FALSE;
797 TRACE( "set to %p\n", context );
798 return TRUE;
801 /**********************************************************************
802 * GetProcessDpiAwarenessInternal (USER32.@)
804 BOOL WINAPI GetProcessDpiAwarenessInternal( HANDLE process, DPI_AWARENESS *awareness )
806 *awareness = NtUserGetProcessDpiAwarenessContext( process ) & 3;
807 return TRUE;
810 /**********************************************************************
811 * SetProcessDpiAwarenessInternal (USER32.@)
813 BOOL WINAPI SetProcessDpiAwarenessInternal( DPI_AWARENESS awareness )
815 static const DPI_AWARENESS_CONTEXT contexts[3] = { DPI_AWARENESS_CONTEXT_UNAWARE,
816 DPI_AWARENESS_CONTEXT_SYSTEM_AWARE,
817 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE };
819 if (awareness < DPI_AWARENESS_UNAWARE || awareness > DPI_AWARENESS_PER_MONITOR_AWARE)
821 SetLastError( ERROR_INVALID_PARAMETER );
822 return FALSE;
824 return SetProcessDpiAwarenessContext( contexts[awareness] );
827 /***********************************************************************
828 * AreDpiAwarenessContextsEqual (USER32.@)
830 BOOL WINAPI AreDpiAwarenessContextsEqual( DPI_AWARENESS_CONTEXT ctx1, DPI_AWARENESS_CONTEXT ctx2 )
832 DPI_AWARENESS aware1 = GetAwarenessFromDpiAwarenessContext( ctx1 );
833 DPI_AWARENESS aware2 = GetAwarenessFromDpiAwarenessContext( ctx2 );
834 return aware1 != DPI_AWARENESS_INVALID && aware1 == aware2;
837 /***********************************************************************
838 * GetAwarenessFromDpiAwarenessContext (USER32.@)
840 DPI_AWARENESS WINAPI GetAwarenessFromDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
842 switch ((ULONG_PTR)context)
844 case 0x10:
845 case 0x11:
846 case 0x12:
847 case 0x80000010:
848 case 0x80000011:
849 case 0x80000012:
850 return (ULONG_PTR)context & 3;
851 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
852 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
853 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
854 return ~(ULONG_PTR)context;
855 default:
856 return DPI_AWARENESS_INVALID;
860 /***********************************************************************
861 * IsValidDpiAwarenessContext (USER32.@)
863 BOOL WINAPI IsValidDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
865 return GetAwarenessFromDpiAwarenessContext( context ) != DPI_AWARENESS_INVALID;
868 /***********************************************************************
869 * SetProcessDPIAware (USER32.@)
871 BOOL WINAPI SetProcessDPIAware(void)
873 TRACE("\n");
874 NtUserSetProcessDpiAwarenessContext( NTUSER_DPI_SYSTEM_AWARE, 0 );
875 return TRUE;
878 /***********************************************************************
879 * IsProcessDPIAware (USER32.@)
881 BOOL WINAPI IsProcessDPIAware(void)
883 return GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ) != DPI_AWARENESS_UNAWARE;
886 /**********************************************************************
887 * EnableNonClientDpiScaling (USER32.@)
889 BOOL WINAPI EnableNonClientDpiScaling( HWND hwnd )
891 FIXME("(%p): stub\n", hwnd);
892 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
893 return FALSE;
896 /***********************************************************************
897 * GetDpiForSystem (USER32.@)
899 UINT WINAPI GetDpiForSystem(void)
901 if (!IsProcessDPIAware()) return USER_DEFAULT_SCREEN_DPI;
902 return system_dpi;
905 /**********************************************************************
906 * GetThreadDpiAwarenessContext (USER32.@)
908 DPI_AWARENESS_CONTEXT WINAPI GetThreadDpiAwarenessContext(void)
910 struct user_thread_info *info = get_user_thread_info();
912 if (info->dpi_awareness) return ULongToHandle( info->dpi_awareness );
913 return UlongToHandle( (NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3 ) | 0x10 );
916 /**********************************************************************
917 * SetThreadDpiAwarenessContext (USER32.@)
919 DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
921 struct user_thread_info *info = get_user_thread_info();
922 DPI_AWARENESS prev, val = GetAwarenessFromDpiAwarenessContext( context );
924 if (val == DPI_AWARENESS_INVALID)
926 SetLastError( ERROR_INVALID_PARAMETER );
927 return 0;
929 if (!(prev = info->dpi_awareness))
931 prev = NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3;
932 prev |= 0x80000010; /* restore to process default */
934 if (((ULONG_PTR)context & ~(ULONG_PTR)0x13) == 0x80000000) info->dpi_awareness = 0;
935 else info->dpi_awareness = val | 0x10;
936 return ULongToHandle( prev );
939 /**********************************************************************
940 * LogicalToPhysicalPointForPerMonitorDPI (USER32.@)
942 BOOL WINAPI LogicalToPhysicalPointForPerMonitorDPI( HWND hwnd, POINT *pt )
944 RECT rect;
946 if (!GetWindowRect( hwnd, &rect )) return FALSE;
947 if (pt->x < rect.left || pt->y < rect.top || pt->x > rect.right || pt->y > rect.bottom) return FALSE;
948 *pt = point_win_to_phys_dpi( hwnd, *pt );
949 return TRUE;
952 /**********************************************************************
953 * PhysicalToLogicalPointForPerMonitorDPI (USER32.@)
955 BOOL WINAPI PhysicalToLogicalPointForPerMonitorDPI( HWND hwnd, POINT *pt )
957 DPI_AWARENESS_CONTEXT context;
958 RECT rect;
959 BOOL ret = FALSE;
961 context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
962 if (GetWindowRect( hwnd, &rect ) &&
963 pt->x >= rect.left && pt->y >= rect.top && pt->x <= rect.right && pt->y <= rect.bottom)
965 *pt = point_phys_to_win_dpi( hwnd, *pt );
966 ret = TRUE;
968 SetThreadDpiAwarenessContext( context );
969 return ret;
972 /***********************************************************************
973 * MonitorFromRect (USER32.@)
975 HMONITOR WINAPI MonitorFromRect( const RECT *rect, DWORD flags )
977 return NtUserMonitorFromRect( rect, flags );
980 /***********************************************************************
981 * MonitorFromPoint (USER32.@)
983 HMONITOR WINAPI MonitorFromPoint( POINT pt, DWORD flags )
985 RECT rect;
987 SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 );
988 return MonitorFromRect( &rect, flags );
991 /***********************************************************************
992 * MonitorFromWindow (USER32.@)
994 HMONITOR WINAPI MonitorFromWindow( HWND hwnd, DWORD flags )
996 return NtUserMonitorFromWindow( hwnd, flags );
999 /***********************************************************************
1000 * GetMonitorInfoA (USER32.@)
1002 BOOL WINAPI GetMonitorInfoA( HMONITOR monitor, LPMONITORINFO info )
1004 MONITORINFOEXW miW;
1005 BOOL ret;
1007 if (info->cbSize == sizeof(MONITORINFO)) return GetMonitorInfoW( monitor, info );
1008 if (info->cbSize != sizeof(MONITORINFOEXA)) return FALSE;
1010 miW.cbSize = sizeof(miW);
1011 ret = GetMonitorInfoW( monitor, (MONITORINFO *)&miW );
1012 if (ret)
1014 MONITORINFOEXA *miA = (MONITORINFOEXA *)info;
1015 miA->rcMonitor = miW.rcMonitor;
1016 miA->rcWork = miW.rcWork;
1017 miA->dwFlags = miW.dwFlags;
1018 WideCharToMultiByte(CP_ACP, 0, miW.szDevice, -1, miA->szDevice, sizeof(miA->szDevice), NULL, NULL);
1020 return ret;
1023 /***********************************************************************
1024 * GetMonitorInfoW (USER32.@)
1026 BOOL WINAPI GetMonitorInfoW( HMONITOR monitor, LPMONITORINFO info )
1028 return NtUserGetMonitorInfo( monitor, info );
1031 #ifdef __i386__
1032 /* Some apps pass a non-stdcall callback to EnumDisplayMonitors,
1033 * so we need a small assembly wrapper to call it.
1035 extern BOOL enum_mon_callback_wrapper( void *proc, HMONITOR monitor, HDC hdc, RECT *rect, LPARAM lparam );
1036 __ASM_GLOBAL_FUNC( enum_mon_callback_wrapper,
1037 "pushl %ebp\n\t"
1038 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
1039 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
1040 "movl %esp,%ebp\n\t"
1041 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
1042 "subl $8,%esp\n\t"
1043 "pushl 24(%ebp)\n\t" /* lparam */
1044 /* MJ's Help Diagnostic expects that %ecx contains the address to the rect. */
1045 "movl 20(%ebp),%ecx\n\t" /* rect */
1046 "pushl %ecx\n\t"
1047 "pushl 16(%ebp)\n\t" /* hdc */
1048 "pushl 12(%ebp)\n\t" /* monitor */
1049 "movl 8(%ebp),%eax\n" /* proc */
1050 "call *%eax\n\t"
1051 "leave\n\t"
1052 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
1053 __ASM_CFI(".cfi_same_value %ebp\n\t")
1054 "ret" )
1055 #endif /* __i386__ */
1057 BOOL WINAPI User32CallEnumDisplayMonitor( struct enum_display_monitor_params *params, ULONG size )
1059 #ifdef __i386__
1060 return enum_mon_callback_wrapper( params->proc, params->monitor, params->hdc,
1061 &params->rect, params->lparam );
1062 #else
1063 return params->proc( params->monitor, params->hdc, &params->rect, params->lparam );
1064 #endif
1067 /***********************************************************************
1068 * EnumDisplayDevicesA (USER32.@)
1070 BOOL WINAPI EnumDisplayDevicesA( LPCSTR device, DWORD index, DISPLAY_DEVICEA *info, DWORD flags )
1072 UNICODE_STRING deviceW;
1073 DISPLAY_DEVICEW ddW;
1074 BOOL ret;
1076 if (device)
1077 RtlCreateUnicodeStringFromAsciiz( &deviceW, device );
1078 else
1079 deviceW.Buffer = NULL;
1081 ddW.cb = sizeof(ddW);
1082 ret = EnumDisplayDevicesW( deviceW.Buffer, index, &ddW, flags );
1083 RtlFreeUnicodeString( &deviceW );
1085 if (!ret)
1086 return ret;
1088 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceName, -1, info->DeviceName, sizeof(info->DeviceName), NULL, NULL );
1089 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceString, -1, info->DeviceString, sizeof(info->DeviceString), NULL, NULL );
1090 info->StateFlags = ddW.StateFlags;
1092 if (info->cb >= offsetof(DISPLAY_DEVICEA, DeviceID) + sizeof(info->DeviceID))
1093 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceID, -1, info->DeviceID, sizeof(info->DeviceID), NULL, NULL );
1094 if (info->cb >= offsetof(DISPLAY_DEVICEA, DeviceKey) + sizeof(info->DeviceKey))
1095 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceKey, -1, info->DeviceKey, sizeof(info->DeviceKey), NULL, NULL );
1097 return TRUE;
1100 /***********************************************************************
1101 * EnumDisplayDevicesW (USER32.@)
1103 BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags )
1105 UNICODE_STRING str;
1106 RtlInitUnicodeString( &str, device );
1107 return NT_SUCCESS(NtUserEnumDisplayDevices( &str, index, info, flags ));
1110 /**********************************************************************
1111 * GetAutoRotationState [USER32.@]
1113 BOOL WINAPI GetAutoRotationState( AR_STATE *state )
1115 TRACE("(%p)\n", state);
1117 if (!state)
1119 SetLastError(ERROR_INVALID_PARAMETER);
1120 return FALSE;
1123 *state = AR_NOSENSOR;
1124 return TRUE;
1127 /**********************************************************************
1128 * GetDisplayAutoRotationPreferences [USER32.@]
1130 BOOL WINAPI GetDisplayAutoRotationPreferences( ORIENTATION_PREFERENCE *orientation )
1132 FIXME("(%p): stub\n", orientation);
1133 *orientation = ORIENTATION_PREFERENCE_NONE;
1134 return TRUE;
1137 /* physical<->logical mapping functions from win8 that are nops in later versions */
1139 /***********************************************************************
1140 * GetPhysicalCursorPos (USER32.@)
1142 BOOL WINAPI GetPhysicalCursorPos( POINT *point )
1144 return GetCursorPos( point );
1147 /***********************************************************************
1148 * SetPhysicalCursorPos (USER32.@)
1150 BOOL WINAPI SetPhysicalCursorPos( INT x, INT y )
1152 return NtUserSetCursorPos( x, y );
1155 /***********************************************************************
1156 * WindowFromPhysicalPoint (USER32.@)
1158 HWND WINAPI WindowFromPhysicalPoint( POINT pt )
1160 return WindowFromPoint( pt );
1163 /***********************************************************************
1164 * LogicalToPhysicalPoint (USER32.@)
1166 BOOL WINAPI LogicalToPhysicalPoint( HWND hwnd, POINT *point )
1168 return TRUE;
1171 /***********************************************************************
1172 * PhysicalToLogicalPoint (USER32.@)
1174 BOOL WINAPI PhysicalToLogicalPoint( HWND hwnd, POINT *point )
1176 return TRUE;
1179 static DISPLAYCONFIG_ROTATION get_dc_rotation(const DEVMODEW *devmode)
1181 if (devmode->dmFields & DM_DISPLAYORIENTATION)
1182 return devmode->u1.s2.dmDisplayOrientation + 1;
1183 else
1184 return DISPLAYCONFIG_ROTATION_IDENTITY;
1187 static DISPLAYCONFIG_SCANLINE_ORDERING get_dc_scanline_ordering(const DEVMODEW *devmode)
1189 if (!(devmode->dmFields & DM_DISPLAYFLAGS))
1190 return DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED;
1191 else if (devmode->u2.dmDisplayFlags & DM_INTERLACED)
1192 return DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED;
1193 else
1194 return DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
1197 static DISPLAYCONFIG_PIXELFORMAT get_dc_pixelformat(DWORD dmBitsPerPel)
1199 if ((dmBitsPerPel == 8) || (dmBitsPerPel == 16) ||
1200 (dmBitsPerPel == 24) || (dmBitsPerPel == 32))
1201 return dmBitsPerPel / 8;
1202 else
1203 return DISPLAYCONFIG_PIXELFORMAT_NONGDI;
1206 static void set_mode_target_info(DISPLAYCONFIG_MODE_INFO *info, const LUID *gpu_luid, UINT32 target_id,
1207 UINT32 flags, const DEVMODEW *devmode)
1209 DISPLAYCONFIG_TARGET_MODE *mode = &(info->u.targetMode);
1211 info->infoType = DISPLAYCONFIG_MODE_INFO_TYPE_TARGET;
1212 info->adapterId = *gpu_luid;
1213 info->id = target_id;
1215 /* FIXME: Populate pixelRate/hSyncFreq/totalSize with real data */
1216 mode->targetVideoSignalInfo.pixelRate = devmode->dmDisplayFrequency * devmode->dmPelsWidth * devmode->dmPelsHeight;
1217 mode->targetVideoSignalInfo.hSyncFreq.Numerator = devmode->dmDisplayFrequency * devmode->dmPelsWidth;
1218 mode->targetVideoSignalInfo.hSyncFreq.Denominator = 1;
1219 mode->targetVideoSignalInfo.vSyncFreq.Numerator = devmode->dmDisplayFrequency;
1220 mode->targetVideoSignalInfo.vSyncFreq.Denominator = 1;
1221 mode->targetVideoSignalInfo.activeSize.cx = devmode->dmPelsWidth;
1222 mode->targetVideoSignalInfo.activeSize.cy = devmode->dmPelsHeight;
1223 if (flags & QDC_DATABASE_CURRENT)
1225 mode->targetVideoSignalInfo.totalSize.cx = 0;
1226 mode->targetVideoSignalInfo.totalSize.cy = 0;
1228 else
1230 mode->targetVideoSignalInfo.totalSize.cx = devmode->dmPelsWidth;
1231 mode->targetVideoSignalInfo.totalSize.cy = devmode->dmPelsHeight;
1233 mode->targetVideoSignalInfo.u.videoStandard = D3DKMDT_VSS_OTHER;
1234 mode->targetVideoSignalInfo.scanLineOrdering = get_dc_scanline_ordering(devmode);
1237 static void set_path_target_info(DISPLAYCONFIG_PATH_TARGET_INFO *info, const LUID *gpu_luid,
1238 UINT32 target_id, UINT32 mode_index, const DEVMODEW *devmode)
1240 info->adapterId = *gpu_luid;
1241 info->id = target_id;
1242 info->u.modeInfoIdx = mode_index;
1243 info->outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL;
1244 info->rotation = get_dc_rotation(devmode);
1245 info->scaling = DISPLAYCONFIG_SCALING_IDENTITY;
1246 info->refreshRate.Numerator = devmode->dmDisplayFrequency;
1247 info->refreshRate.Denominator = 1;
1248 info->scanLineOrdering = get_dc_scanline_ordering(devmode);
1249 info->targetAvailable = TRUE;
1250 info->statusFlags = DISPLAYCONFIG_TARGET_IN_USE;
1253 static void set_mode_source_info(DISPLAYCONFIG_MODE_INFO *info, const LUID *gpu_luid,
1254 UINT32 source_id, const DEVMODEW *devmode)
1256 DISPLAYCONFIG_SOURCE_MODE *mode = &(info->u.sourceMode);
1258 info->infoType = DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE;
1259 info->adapterId = *gpu_luid;
1260 info->id = source_id;
1262 mode->width = devmode->dmPelsWidth;
1263 mode->height = devmode->dmPelsHeight;
1264 mode->pixelFormat = get_dc_pixelformat(devmode->dmBitsPerPel);
1265 if (devmode->dmFields & DM_POSITION)
1267 mode->position = devmode->u1.s2.dmPosition;
1269 else
1271 mode->position.x = 0;
1272 mode->position.y = 0;
1276 static void set_path_source_info(DISPLAYCONFIG_PATH_SOURCE_INFO *info, const LUID *gpu_luid,
1277 UINT32 source_id, UINT32 mode_index)
1279 info->adapterId = *gpu_luid;
1280 info->id = source_id;
1281 info->u.modeInfoIdx = mode_index;
1282 info->statusFlags = DISPLAYCONFIG_SOURCE_IN_USE;
1285 static BOOL source_mode_exists(const DISPLAYCONFIG_MODE_INFO *modeinfo, UINT32 num_modes,
1286 UINT32 source_id, UINT32 *found_mode_index)
1288 UINT32 i;
1290 for (i = 0; i < num_modes; i++)
1292 if (modeinfo[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE &&
1293 modeinfo[i].id == source_id)
1295 *found_mode_index = i;
1296 return TRUE;
1299 return FALSE;
1302 /***********************************************************************
1303 * QueryDisplayConfig (USER32.@)
1305 LONG WINAPI QueryDisplayConfig(UINT32 flags, UINT32 *numpathelements, DISPLAYCONFIG_PATH_INFO *pathinfo,
1306 UINT32 *numinfoelements, DISPLAYCONFIG_MODE_INFO *modeinfo,
1307 DISPLAYCONFIG_TOPOLOGY_ID *topologyid)
1309 LONG adapter_index, ret;
1310 HANDLE mutex;
1311 HDEVINFO devinfo;
1312 SP_DEVINFO_DATA device_data = {sizeof(device_data)};
1313 DWORD monitor_index = 0, state_flags, type;
1314 UINT32 output_id, source_mode_index, path_index = 0, mode_index = 0;
1315 LUID gpu_luid;
1316 WCHAR device_name[CCHDEVICENAME];
1317 DEVMODEW devmode;
1319 FIXME("(%08x %p %p %p %p %p): semi-stub\n", flags, numpathelements, pathinfo, numinfoelements, modeinfo, topologyid);
1321 if (!numpathelements || !numinfoelements)
1322 return ERROR_INVALID_PARAMETER;
1324 if (!*numpathelements || !*numinfoelements)
1325 return ERROR_INVALID_PARAMETER;
1327 if (flags != QDC_ALL_PATHS &&
1328 flags != QDC_ONLY_ACTIVE_PATHS &&
1329 flags != QDC_DATABASE_CURRENT)
1330 return ERROR_INVALID_PARAMETER;
1332 if (((flags == QDC_DATABASE_CURRENT) && !topologyid) ||
1333 ((flags != QDC_DATABASE_CURRENT) && topologyid))
1334 return ERROR_INVALID_PARAMETER;
1336 if (flags != QDC_ONLY_ACTIVE_PATHS)
1337 FIXME("only returning active paths\n");
1339 if (topologyid)
1341 FIXME("setting toplogyid to DISPLAYCONFIG_TOPOLOGY_INTERNAL\n");
1342 *topologyid = DISPLAYCONFIG_TOPOLOGY_INTERNAL;
1345 wait_graphics_driver_ready();
1346 mutex = get_display_device_init_mutex();
1348 /* Iterate through "targets"/monitors.
1349 * Each target corresponds to a path, and each path corresponds to one or two unique modes.
1351 devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, L"DISPLAY", NULL, DIGCF_PRESENT);
1352 if (devinfo == INVALID_HANDLE_VALUE)
1354 ret = ERROR_GEN_FAILURE;
1355 goto done;
1358 ret = ERROR_GEN_FAILURE;
1359 while (SetupDiEnumDeviceInfo(devinfo, monitor_index++, &device_data))
1361 /* Only count active monitors */
1362 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS,
1363 &type, (BYTE *)&state_flags, sizeof(state_flags), NULL, 0))
1364 goto done;
1365 if (!(state_flags & DISPLAY_DEVICE_ACTIVE))
1366 continue;
1368 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
1369 &type, (BYTE *)&gpu_luid, sizeof(gpu_luid), NULL, 0))
1370 goto done;
1372 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID,
1373 &type, (BYTE *)&output_id, sizeof(output_id), NULL, 0))
1374 goto done;
1376 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME,
1377 &type, (BYTE *)device_name, sizeof(device_name), NULL, 0))
1378 goto done;
1380 memset(&devmode, 0, sizeof(devmode));
1381 devmode.dmSize = sizeof(devmode);
1382 if (!EnumDisplaySettingsW(device_name, ENUM_CURRENT_SETTINGS, &devmode))
1383 goto done;
1385 /* Extract the adapter index from device_name to use as the source ID */
1386 adapter_index = wcstol(device_name + lstrlenW(L"\\\\.\\DISPLAY"), NULL, 10);
1387 adapter_index--;
1389 if (path_index == *numpathelements || mode_index == *numinfoelements)
1391 ret = ERROR_INSUFFICIENT_BUFFER;
1392 goto done;
1395 pathinfo[path_index].flags = DISPLAYCONFIG_PATH_ACTIVE;
1396 set_mode_target_info(&modeinfo[mode_index], &gpu_luid, output_id, flags, &devmode);
1397 set_path_target_info(&(pathinfo[path_index].targetInfo), &gpu_luid, output_id, mode_index, &devmode);
1399 mode_index++;
1400 if (mode_index == *numinfoelements)
1402 ret = ERROR_INSUFFICIENT_BUFFER;
1403 goto done;
1406 /* Multiple targets can be driven by the same source, ensure a mode
1407 * hasn't already been added for this source.
1409 if (!source_mode_exists(modeinfo, mode_index, adapter_index, &source_mode_index))
1411 set_mode_source_info(&modeinfo[mode_index], &gpu_luid, adapter_index, &devmode);
1412 source_mode_index = mode_index;
1413 mode_index++;
1415 set_path_source_info(&(pathinfo[path_index].sourceInfo), &gpu_luid, adapter_index, source_mode_index);
1416 path_index++;
1419 *numpathelements = path_index;
1420 *numinfoelements = mode_index;
1421 ret = ERROR_SUCCESS;
1423 done:
1424 SetupDiDestroyDeviceInfoList(devinfo);
1425 release_display_device_init_mutex(mutex);
1426 return ret;
1429 /***********************************************************************
1430 * DisplayConfigGetDeviceInfo (USER32.@)
1432 LONG WINAPI DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER *packet)
1434 LONG ret = ERROR_GEN_FAILURE;
1435 HANDLE mutex;
1436 HDEVINFO devinfo;
1437 SP_DEVINFO_DATA device_data = {sizeof(device_data)};
1438 DWORD index = 0, type;
1439 LUID gpu_luid;
1441 TRACE("(%p)\n", packet);
1443 if (!packet || packet->size < sizeof(*packet))
1444 return ERROR_GEN_FAILURE;
1445 wait_graphics_driver_ready();
1447 switch (packet->type)
1449 case DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME:
1451 DISPLAYCONFIG_SOURCE_DEVICE_NAME *source_name = (DISPLAYCONFIG_SOURCE_DEVICE_NAME *)packet;
1452 WCHAR device_name[CCHDEVICENAME];
1453 LONG source_id;
1455 TRACE("DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME\n");
1457 if (packet->size < sizeof(*source_name))
1458 return ERROR_INVALID_PARAMETER;
1460 mutex = get_display_device_init_mutex();
1461 devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, L"DISPLAY", NULL, DIGCF_PRESENT);
1462 if (devinfo == INVALID_HANDLE_VALUE)
1464 release_display_device_init_mutex(mutex);
1465 return ret;
1468 while (SetupDiEnumDeviceInfo(devinfo, index++, &device_data))
1470 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
1471 &type, (BYTE *)&gpu_luid, sizeof(gpu_luid), NULL, 0))
1472 continue;
1474 if ((source_name->header.adapterId.LowPart != gpu_luid.LowPart) ||
1475 (source_name->header.adapterId.HighPart != gpu_luid.HighPart))
1476 continue;
1478 /* QueryDisplayConfig() derives the source ID from the adapter name. */
1479 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME,
1480 &type, (BYTE *)device_name, sizeof(device_name), NULL, 0))
1481 continue;
1483 source_id = wcstol(device_name + lstrlenW(L"\\\\.\\DISPLAY"), NULL, 10);
1484 source_id--;
1485 if (source_name->header.id != source_id)
1486 continue;
1488 lstrcpyW(source_name->viewGdiDeviceName, device_name);
1489 ret = ERROR_SUCCESS;
1490 break;
1492 SetupDiDestroyDeviceInfoList(devinfo);
1493 release_display_device_init_mutex(mutex);
1494 return ret;
1496 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME:
1498 DISPLAYCONFIG_TARGET_DEVICE_NAME *target_name = (DISPLAYCONFIG_TARGET_DEVICE_NAME *)packet;
1500 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME: stub\n");
1502 if (packet->size < sizeof(*target_name))
1503 return ERROR_INVALID_PARAMETER;
1505 return ERROR_NOT_SUPPORTED;
1507 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE:
1509 DISPLAYCONFIG_TARGET_PREFERRED_MODE *preferred_mode = (DISPLAYCONFIG_TARGET_PREFERRED_MODE *)packet;
1511 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE: stub\n");
1513 if (packet->size < sizeof(*preferred_mode))
1514 return ERROR_INVALID_PARAMETER;
1516 return ERROR_NOT_SUPPORTED;
1518 case DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME:
1520 DISPLAYCONFIG_ADAPTER_NAME *adapter_name = (DISPLAYCONFIG_ADAPTER_NAME *)packet;
1522 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME: stub\n");
1524 if (packet->size < sizeof(*adapter_name))
1525 return ERROR_INVALID_PARAMETER;
1527 return ERROR_NOT_SUPPORTED;
1529 case DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE:
1530 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE:
1531 case DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION:
1532 case DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION:
1533 case DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO:
1534 case DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE:
1535 case DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL:
1536 default:
1537 FIXME("Unimplemented packet type: %u\n", packet->type);
1538 return ERROR_INVALID_PARAMETER;
1542 /***********************************************************************
1543 * SetDisplayConfig (USER32.@)
1545 LONG WINAPI SetDisplayConfig(UINT32 path_info_count, DISPLAYCONFIG_PATH_INFO *path_info, UINT32 mode_info_count,
1546 DISPLAYCONFIG_MODE_INFO *mode_info, UINT32 flags)
1548 FIXME("path_info_count %u, path_info %p, mode_info_count %u, mode_info %p, flags %#x stub.\n",
1549 path_info_count, path_info, mode_info_count, mode_info, flags);
1551 return ERROR_SUCCESS;