d3d10: Return the read value from read_dword().
[wine.git] / dlls / user32 / sysparams.c
blob9d553d7dfff7416b10a22df1adfcf21cb719c885
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 NtUserCallOneParam( index, NtUserGetSystemMetrics );
451 /***********************************************************************
452 * GetSystemMetricsForDpi (USER32.@)
454 INT WINAPI GetSystemMetricsForDpi( INT index, UINT dpi )
456 return NtUserCallTwoParam( index, dpi, NtUserGetSystemMetricsForDpi );
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 NtUserCallOneParam( index, NtUserGetSysColor );
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 UlongToHandle( NtUserCallOneParam( index, NtUserGetSysColorBrush ));
512 /***********************************************************************
513 * SYSCOLOR_GetPen
515 HPEN SYSCOLOR_GetPen( INT index )
517 return UlongToHandle( NtUserCallOneParam( index, NtUserGetSysColorPen ));
521 /***********************************************************************
522 * SYSCOLOR_Get55AABrush
524 HBRUSH SYSCOLOR_Get55AABrush(void)
526 return UlongToHandle( NtUserCallOneParam( COLOR_55AA_BRUSH, NtUserGetSysColorBrush ));
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 * point_thread_to_win_dpi
745 POINT point_thread_to_win_dpi( HWND hwnd, POINT pt )
747 UINT dpi = get_thread_dpi();
748 if (!dpi) dpi = get_win_monitor_dpi( hwnd );
749 return map_dpi_point( pt, dpi, GetDpiForWindow( hwnd ));
752 /**********************************************************************
753 * map_dpi_rect
755 RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to )
757 if (dpi_from && dpi_to && dpi_from != dpi_to)
759 rect.left = MulDiv( rect.left, dpi_to, dpi_from );
760 rect.top = MulDiv( rect.top, dpi_to, dpi_from );
761 rect.right = MulDiv( rect.right, dpi_to, dpi_from );
762 rect.bottom = MulDiv( rect.bottom, dpi_to, dpi_from );
764 return rect;
767 /**********************************************************************
768 * rect_win_to_thread_dpi
770 RECT rect_win_to_thread_dpi( HWND hwnd, RECT rect )
772 UINT dpi = get_thread_dpi();
773 if (!dpi) dpi = get_win_monitor_dpi( hwnd );
774 return map_dpi_rect( rect, GetDpiForWindow( hwnd ), dpi );
777 /**********************************************************************
778 * rect_thread_to_win_dpi
780 RECT rect_thread_to_win_dpi( HWND hwnd, RECT rect )
782 UINT dpi = get_thread_dpi();
783 if (!dpi) dpi = get_win_monitor_dpi( hwnd );
784 return map_dpi_rect( rect, dpi, GetDpiForWindow( hwnd ) );
787 /**********************************************************************
788 * SetProcessDpiAwarenessContext (USER32.@)
790 BOOL WINAPI SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
792 ULONG awareness;
794 switch (GetAwarenessFromDpiAwarenessContext( context ))
796 case DPI_AWARENESS_UNAWARE:
797 awareness = NTUSER_DPI_UNAWARE;
798 break;
799 case DPI_AWARENESS_SYSTEM_AWARE:
800 awareness = NTUSER_DPI_SYSTEM_AWARE;
801 break;
802 case DPI_AWARENESS_PER_MONITOR_AWARE:
803 awareness = context == DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
804 ? NTUSER_DPI_PER_MONITOR_AWARE_V2 : NTUSER_DPI_PER_MONITOR_AWARE;
805 break;
806 default:
807 SetLastError( ERROR_INVALID_PARAMETER );
808 return FALSE;
811 if (!NtUserSetProcessDpiAwarenessContext( awareness, 0 ))
813 SetLastError( ERROR_ACCESS_DENIED );
814 return FALSE;
817 TRACE( "set to %p\n", context );
818 return TRUE;
821 /**********************************************************************
822 * GetProcessDpiAwarenessInternal (USER32.@)
824 BOOL WINAPI GetProcessDpiAwarenessInternal( HANDLE process, DPI_AWARENESS *awareness )
826 *awareness = NtUserGetProcessDpiAwarenessContext( process ) & 3;
827 return TRUE;
830 /**********************************************************************
831 * SetProcessDpiAwarenessInternal (USER32.@)
833 BOOL WINAPI SetProcessDpiAwarenessInternal( DPI_AWARENESS awareness )
835 static const DPI_AWARENESS_CONTEXT contexts[3] = { DPI_AWARENESS_CONTEXT_UNAWARE,
836 DPI_AWARENESS_CONTEXT_SYSTEM_AWARE,
837 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE };
839 if (awareness < DPI_AWARENESS_UNAWARE || awareness > DPI_AWARENESS_PER_MONITOR_AWARE)
841 SetLastError( ERROR_INVALID_PARAMETER );
842 return FALSE;
844 return SetProcessDpiAwarenessContext( contexts[awareness] );
847 /***********************************************************************
848 * AreDpiAwarenessContextsEqual (USER32.@)
850 BOOL WINAPI AreDpiAwarenessContextsEqual( DPI_AWARENESS_CONTEXT ctx1, DPI_AWARENESS_CONTEXT ctx2 )
852 DPI_AWARENESS aware1 = GetAwarenessFromDpiAwarenessContext( ctx1 );
853 DPI_AWARENESS aware2 = GetAwarenessFromDpiAwarenessContext( ctx2 );
854 return aware1 != DPI_AWARENESS_INVALID && aware1 == aware2;
857 /***********************************************************************
858 * GetAwarenessFromDpiAwarenessContext (USER32.@)
860 DPI_AWARENESS WINAPI GetAwarenessFromDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
862 switch ((ULONG_PTR)context)
864 case 0x10:
865 case 0x11:
866 case 0x12:
867 case 0x80000010:
868 case 0x80000011:
869 case 0x80000012:
870 return (ULONG_PTR)context & 3;
871 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
872 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
873 case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
874 return ~(ULONG_PTR)context;
875 default:
876 return DPI_AWARENESS_INVALID;
880 /***********************************************************************
881 * IsValidDpiAwarenessContext (USER32.@)
883 BOOL WINAPI IsValidDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
885 return GetAwarenessFromDpiAwarenessContext( context ) != DPI_AWARENESS_INVALID;
888 /***********************************************************************
889 * SetProcessDPIAware (USER32.@)
891 BOOL WINAPI SetProcessDPIAware(void)
893 TRACE("\n");
894 NtUserSetProcessDpiAwarenessContext( NTUSER_DPI_SYSTEM_AWARE, 0 );
895 return TRUE;
898 /***********************************************************************
899 * IsProcessDPIAware (USER32.@)
901 BOOL WINAPI IsProcessDPIAware(void)
903 return GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ) != DPI_AWARENESS_UNAWARE;
906 /**********************************************************************
907 * EnableNonClientDpiScaling (USER32.@)
909 BOOL WINAPI EnableNonClientDpiScaling( HWND hwnd )
911 FIXME("(%p): stub\n", hwnd);
912 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
913 return FALSE;
916 /***********************************************************************
917 * GetDpiForSystem (USER32.@)
919 UINT WINAPI GetDpiForSystem(void)
921 if (!IsProcessDPIAware()) return USER_DEFAULT_SCREEN_DPI;
922 return system_dpi;
925 /**********************************************************************
926 * GetThreadDpiAwarenessContext (USER32.@)
928 DPI_AWARENESS_CONTEXT WINAPI GetThreadDpiAwarenessContext(void)
930 struct user_thread_info *info = get_user_thread_info();
932 if (info->dpi_awareness) return ULongToHandle( info->dpi_awareness );
933 return UlongToHandle( (NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3 ) | 0x10 );
936 /**********************************************************************
937 * SetThreadDpiAwarenessContext (USER32.@)
939 DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT context )
941 struct user_thread_info *info = get_user_thread_info();
942 DPI_AWARENESS prev, val = GetAwarenessFromDpiAwarenessContext( context );
944 if (val == DPI_AWARENESS_INVALID)
946 SetLastError( ERROR_INVALID_PARAMETER );
947 return 0;
949 if (!(prev = info->dpi_awareness))
951 prev = NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3;
952 prev |= 0x80000010; /* restore to process default */
954 if (((ULONG_PTR)context & ~(ULONG_PTR)0x13) == 0x80000000) info->dpi_awareness = 0;
955 else info->dpi_awareness = val | 0x10;
956 return ULongToHandle( prev );
959 /**********************************************************************
960 * LogicalToPhysicalPointForPerMonitorDPI (USER32.@)
962 BOOL WINAPI LogicalToPhysicalPointForPerMonitorDPI( HWND hwnd, POINT *pt )
964 RECT rect;
966 if (!GetWindowRect( hwnd, &rect )) return FALSE;
967 if (pt->x < rect.left || pt->y < rect.top || pt->x > rect.right || pt->y > rect.bottom) return FALSE;
968 *pt = point_win_to_phys_dpi( hwnd, *pt );
969 return TRUE;
972 /**********************************************************************
973 * PhysicalToLogicalPointForPerMonitorDPI (USER32.@)
975 BOOL WINAPI PhysicalToLogicalPointForPerMonitorDPI( HWND hwnd, POINT *pt )
977 DPI_AWARENESS_CONTEXT context;
978 RECT rect;
979 BOOL ret = FALSE;
981 context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
982 if (GetWindowRect( hwnd, &rect ) &&
983 pt->x >= rect.left && pt->y >= rect.top && pt->x <= rect.right && pt->y <= rect.bottom)
985 *pt = point_phys_to_win_dpi( hwnd, *pt );
986 ret = TRUE;
988 SetThreadDpiAwarenessContext( context );
989 return ret;
992 struct monitor_enum_info
994 RECT rect;
995 UINT max_area;
996 UINT min_distance;
997 HMONITOR primary;
998 HMONITOR nearest;
999 HMONITOR ret;
1002 /* helper callback for MonitorFromRect */
1003 static BOOL CALLBACK monitor_enum( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
1005 struct monitor_enum_info *info = (struct monitor_enum_info *)lp;
1006 RECT intersect;
1008 if (IntersectRect( &intersect, rect, &info->rect ))
1010 /* check for larger intersecting area */
1011 UINT area = (intersect.right - intersect.left) * (intersect.bottom - intersect.top);
1012 if (area > info->max_area)
1014 info->max_area = area;
1015 info->ret = monitor;
1018 else if (!info->max_area) /* if not intersecting, check for min distance */
1020 UINT distance;
1021 UINT x, y;
1023 if (info->rect.right <= rect->left) x = rect->left - info->rect.right;
1024 else if (rect->right <= info->rect.left) x = info->rect.left - rect->right;
1025 else x = 0;
1026 if (info->rect.bottom <= rect->top) y = rect->top - info->rect.bottom;
1027 else if (rect->bottom <= info->rect.top) y = info->rect.top - rect->bottom;
1028 else y = 0;
1029 distance = x * x + y * y;
1030 if (distance < info->min_distance)
1032 info->min_distance = distance;
1033 info->nearest = monitor;
1036 if (!info->primary)
1038 MONITORINFO mon_info;
1039 mon_info.cbSize = sizeof(mon_info);
1040 GetMonitorInfoW( monitor, &mon_info );
1041 if (mon_info.dwFlags & MONITORINFOF_PRIMARY) info->primary = monitor;
1043 return TRUE;
1046 /***********************************************************************
1047 * MonitorFromRect (USER32.@)
1049 HMONITOR WINAPI MonitorFromRect( const RECT *rect, DWORD flags )
1051 struct monitor_enum_info info;
1053 info.rect = *rect;
1054 info.max_area = 0;
1055 info.min_distance = ~0u;
1056 info.primary = 0;
1057 info.nearest = 0;
1058 info.ret = 0;
1060 if (IsRectEmpty(&info.rect))
1062 info.rect.right = info.rect.left + 1;
1063 info.rect.bottom = info.rect.top + 1;
1066 if (!NtUserEnumDisplayMonitors( 0, NULL, monitor_enum, (LPARAM)&info )) return 0;
1067 if (!info.ret)
1069 if (flags & MONITOR_DEFAULTTOPRIMARY) info.ret = info.primary;
1070 else if (flags & MONITOR_DEFAULTTONEAREST) info.ret = info.nearest;
1073 TRACE( "%s flags %x returning %p\n", wine_dbgstr_rect(rect), flags, info.ret );
1074 return info.ret;
1077 /***********************************************************************
1078 * MonitorFromPoint (USER32.@)
1080 HMONITOR WINAPI MonitorFromPoint( POINT pt, DWORD flags )
1082 RECT rect;
1084 SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 );
1085 return MonitorFromRect( &rect, flags );
1088 /***********************************************************************
1089 * MonitorFromWindow (USER32.@)
1091 HMONITOR WINAPI MonitorFromWindow(HWND hWnd, DWORD dwFlags)
1093 RECT rect;
1094 WINDOWPLACEMENT wp;
1096 TRACE("(%p, 0x%08x)\n", hWnd, dwFlags);
1098 wp.length = sizeof(wp);
1099 if (IsIconic(hWnd) && GetWindowPlacement(hWnd, &wp))
1100 return MonitorFromRect( &wp.rcNormalPosition, dwFlags );
1102 if (GetWindowRect( hWnd, &rect ))
1103 return MonitorFromRect( &rect, dwFlags );
1105 if (!(dwFlags & (MONITOR_DEFAULTTOPRIMARY|MONITOR_DEFAULTTONEAREST))) return 0;
1106 /* retrieve the primary */
1107 SetRect( &rect, 0, 0, 1, 1 );
1108 return MonitorFromRect( &rect, dwFlags );
1111 /***********************************************************************
1112 * GetMonitorInfoA (USER32.@)
1114 BOOL WINAPI GetMonitorInfoA( HMONITOR monitor, LPMONITORINFO info )
1116 MONITORINFOEXW miW;
1117 BOOL ret;
1119 if (info->cbSize == sizeof(MONITORINFO)) return GetMonitorInfoW( monitor, info );
1120 if (info->cbSize != sizeof(MONITORINFOEXA)) return FALSE;
1122 miW.cbSize = sizeof(miW);
1123 ret = GetMonitorInfoW( monitor, (MONITORINFO *)&miW );
1124 if (ret)
1126 MONITORINFOEXA *miA = (MONITORINFOEXA *)info;
1127 miA->rcMonitor = miW.rcMonitor;
1128 miA->rcWork = miW.rcWork;
1129 miA->dwFlags = miW.dwFlags;
1130 WideCharToMultiByte(CP_ACP, 0, miW.szDevice, -1, miA->szDevice, sizeof(miA->szDevice), NULL, NULL);
1132 return ret;
1135 /***********************************************************************
1136 * GetMonitorInfoW (USER32.@)
1138 BOOL WINAPI GetMonitorInfoW( HMONITOR monitor, LPMONITORINFO info )
1140 return NtUserCallTwoParam( HandleToUlong(monitor), (ULONG_PTR)info, NtUserGetMonitorInfo );
1143 #ifdef __i386__
1144 /* Some apps pass a non-stdcall callback to EnumDisplayMonitors,
1145 * so we need a small assembly wrapper to call it.
1147 extern BOOL enum_mon_callback_wrapper( void *proc, HMONITOR monitor, HDC hdc, RECT *rect, LPARAM lparam );
1148 __ASM_GLOBAL_FUNC( enum_mon_callback_wrapper,
1149 "pushl %ebp\n\t"
1150 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
1151 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
1152 "movl %esp,%ebp\n\t"
1153 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
1154 "subl $8,%esp\n\t"
1155 "pushl 24(%ebp)\n\t" /* lparam */
1156 /* MJ's Help Diagnostic expects that %ecx contains the address to the rect. */
1157 "movl 20(%ebp),%ecx\n\t" /* rect */
1158 "pushl %ecx\n\t"
1159 "pushl 16(%ebp)\n\t" /* hdc */
1160 "pushl 12(%ebp)\n\t" /* monitor */
1161 "movl 8(%ebp),%eax\n" /* proc */
1162 "call *%eax\n\t"
1163 "leave\n\t"
1164 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
1165 __ASM_CFI(".cfi_same_value %ebp\n\t")
1166 "ret" )
1167 #endif /* __i386__ */
1169 BOOL WINAPI User32CallEnumDisplayMonitor( struct enum_display_monitor_params *params, ULONG size )
1171 #ifdef __i386__
1172 return enum_mon_callback_wrapper( params->proc, params->monitor, params->hdc,
1173 &params->rect, params->lparam );
1174 #else
1175 return params->proc( params->monitor, params->hdc, &params->rect, params->lparam );
1176 #endif
1179 /***********************************************************************
1180 * EnumDisplayDevicesA (USER32.@)
1182 BOOL WINAPI EnumDisplayDevicesA( LPCSTR device, DWORD index, DISPLAY_DEVICEA *info, DWORD flags )
1184 UNICODE_STRING deviceW;
1185 DISPLAY_DEVICEW ddW;
1186 BOOL ret;
1188 if (device)
1189 RtlCreateUnicodeStringFromAsciiz( &deviceW, device );
1190 else
1191 deviceW.Buffer = NULL;
1193 ddW.cb = sizeof(ddW);
1194 ret = EnumDisplayDevicesW( deviceW.Buffer, index, &ddW, flags );
1195 RtlFreeUnicodeString( &deviceW );
1197 if (!ret)
1198 return ret;
1200 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceName, -1, info->DeviceName, sizeof(info->DeviceName), NULL, NULL );
1201 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceString, -1, info->DeviceString, sizeof(info->DeviceString), NULL, NULL );
1202 info->StateFlags = ddW.StateFlags;
1204 if (info->cb >= offsetof(DISPLAY_DEVICEA, DeviceID) + sizeof(info->DeviceID))
1205 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceID, -1, info->DeviceID, sizeof(info->DeviceID), NULL, NULL );
1206 if (info->cb >= offsetof(DISPLAY_DEVICEA, DeviceKey) + sizeof(info->DeviceKey))
1207 WideCharToMultiByte( CP_ACP, 0, ddW.DeviceKey, -1, info->DeviceKey, sizeof(info->DeviceKey), NULL, NULL );
1209 return TRUE;
1212 /***********************************************************************
1213 * EnumDisplayDevicesW (USER32.@)
1215 BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags )
1217 UNICODE_STRING str;
1218 RtlInitUnicodeString( &str, device );
1219 return NT_SUCCESS(NtUserEnumDisplayDevices( &str, index, info, flags ));
1222 /**********************************************************************
1223 * GetAutoRotationState [USER32.@]
1225 BOOL WINAPI GetAutoRotationState( AR_STATE *state )
1227 TRACE("(%p)\n", state);
1229 if (!state)
1231 SetLastError(ERROR_INVALID_PARAMETER);
1232 return FALSE;
1235 *state = AR_NOSENSOR;
1236 return TRUE;
1239 /**********************************************************************
1240 * GetDisplayAutoRotationPreferences [USER32.@]
1242 BOOL WINAPI GetDisplayAutoRotationPreferences( ORIENTATION_PREFERENCE *orientation )
1244 FIXME("(%p): stub\n", orientation);
1245 *orientation = ORIENTATION_PREFERENCE_NONE;
1246 return TRUE;
1249 /* physical<->logical mapping functions from win8 that are nops in later versions */
1251 /***********************************************************************
1252 * GetPhysicalCursorPos (USER32.@)
1254 BOOL WINAPI GetPhysicalCursorPos( POINT *point )
1256 return GetCursorPos( point );
1259 /***********************************************************************
1260 * SetPhysicalCursorPos (USER32.@)
1262 BOOL WINAPI SetPhysicalCursorPos( INT x, INT y )
1264 return SetCursorPos( x, y );
1267 /***********************************************************************
1268 * WindowFromPhysicalPoint (USER32.@)
1270 HWND WINAPI WindowFromPhysicalPoint( POINT pt )
1272 return WindowFromPoint( pt );
1275 /***********************************************************************
1276 * LogicalToPhysicalPoint (USER32.@)
1278 BOOL WINAPI LogicalToPhysicalPoint( HWND hwnd, POINT *point )
1280 return TRUE;
1283 /***********************************************************************
1284 * PhysicalToLogicalPoint (USER32.@)
1286 BOOL WINAPI PhysicalToLogicalPoint( HWND hwnd, POINT *point )
1288 return TRUE;
1291 static DISPLAYCONFIG_ROTATION get_dc_rotation(const DEVMODEW *devmode)
1293 if (devmode->dmFields & DM_DISPLAYORIENTATION)
1294 return devmode->u1.s2.dmDisplayOrientation + 1;
1295 else
1296 return DISPLAYCONFIG_ROTATION_IDENTITY;
1299 static DISPLAYCONFIG_SCANLINE_ORDERING get_dc_scanline_ordering(const DEVMODEW *devmode)
1301 if (!(devmode->dmFields & DM_DISPLAYFLAGS))
1302 return DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED;
1303 else if (devmode->u2.dmDisplayFlags & DM_INTERLACED)
1304 return DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED;
1305 else
1306 return DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
1309 static DISPLAYCONFIG_PIXELFORMAT get_dc_pixelformat(DWORD dmBitsPerPel)
1311 if ((dmBitsPerPel == 8) || (dmBitsPerPel == 16) ||
1312 (dmBitsPerPel == 24) || (dmBitsPerPel == 32))
1313 return dmBitsPerPel / 8;
1314 else
1315 return DISPLAYCONFIG_PIXELFORMAT_NONGDI;
1318 static void set_mode_target_info(DISPLAYCONFIG_MODE_INFO *info, const LUID *gpu_luid, UINT32 target_id,
1319 UINT32 flags, const DEVMODEW *devmode)
1321 DISPLAYCONFIG_TARGET_MODE *mode = &(info->u.targetMode);
1323 info->infoType = DISPLAYCONFIG_MODE_INFO_TYPE_TARGET;
1324 info->adapterId = *gpu_luid;
1325 info->id = target_id;
1327 /* FIXME: Populate pixelRate/hSyncFreq/totalSize with real data */
1328 mode->targetVideoSignalInfo.pixelRate = devmode->dmDisplayFrequency * devmode->dmPelsWidth * devmode->dmPelsHeight;
1329 mode->targetVideoSignalInfo.hSyncFreq.Numerator = devmode->dmDisplayFrequency * devmode->dmPelsWidth;
1330 mode->targetVideoSignalInfo.hSyncFreq.Denominator = 1;
1331 mode->targetVideoSignalInfo.vSyncFreq.Numerator = devmode->dmDisplayFrequency;
1332 mode->targetVideoSignalInfo.vSyncFreq.Denominator = 1;
1333 mode->targetVideoSignalInfo.activeSize.cx = devmode->dmPelsWidth;
1334 mode->targetVideoSignalInfo.activeSize.cy = devmode->dmPelsHeight;
1335 if (flags & QDC_DATABASE_CURRENT)
1337 mode->targetVideoSignalInfo.totalSize.cx = 0;
1338 mode->targetVideoSignalInfo.totalSize.cy = 0;
1340 else
1342 mode->targetVideoSignalInfo.totalSize.cx = devmode->dmPelsWidth;
1343 mode->targetVideoSignalInfo.totalSize.cy = devmode->dmPelsHeight;
1345 mode->targetVideoSignalInfo.u.videoStandard = D3DKMDT_VSS_OTHER;
1346 mode->targetVideoSignalInfo.scanLineOrdering = get_dc_scanline_ordering(devmode);
1349 static void set_path_target_info(DISPLAYCONFIG_PATH_TARGET_INFO *info, const LUID *gpu_luid,
1350 UINT32 target_id, UINT32 mode_index, const DEVMODEW *devmode)
1352 info->adapterId = *gpu_luid;
1353 info->id = target_id;
1354 info->u.modeInfoIdx = mode_index;
1355 info->outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL;
1356 info->rotation = get_dc_rotation(devmode);
1357 info->scaling = DISPLAYCONFIG_SCALING_IDENTITY;
1358 info->refreshRate.Numerator = devmode->dmDisplayFrequency;
1359 info->refreshRate.Denominator = 1;
1360 info->scanLineOrdering = get_dc_scanline_ordering(devmode);
1361 info->targetAvailable = TRUE;
1362 info->statusFlags = DISPLAYCONFIG_TARGET_IN_USE;
1365 static void set_mode_source_info(DISPLAYCONFIG_MODE_INFO *info, const LUID *gpu_luid,
1366 UINT32 source_id, const DEVMODEW *devmode)
1368 DISPLAYCONFIG_SOURCE_MODE *mode = &(info->u.sourceMode);
1370 info->infoType = DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE;
1371 info->adapterId = *gpu_luid;
1372 info->id = source_id;
1374 mode->width = devmode->dmPelsWidth;
1375 mode->height = devmode->dmPelsHeight;
1376 mode->pixelFormat = get_dc_pixelformat(devmode->dmBitsPerPel);
1377 if (devmode->dmFields & DM_POSITION)
1379 mode->position = devmode->u1.s2.dmPosition;
1381 else
1383 mode->position.x = 0;
1384 mode->position.y = 0;
1388 static void set_path_source_info(DISPLAYCONFIG_PATH_SOURCE_INFO *info, const LUID *gpu_luid,
1389 UINT32 source_id, UINT32 mode_index)
1391 info->adapterId = *gpu_luid;
1392 info->id = source_id;
1393 info->u.modeInfoIdx = mode_index;
1394 info->statusFlags = DISPLAYCONFIG_SOURCE_IN_USE;
1397 static BOOL source_mode_exists(const DISPLAYCONFIG_MODE_INFO *modeinfo, UINT32 num_modes,
1398 UINT32 source_id, UINT32 *found_mode_index)
1400 UINT32 i;
1402 for (i = 0; i < num_modes; i++)
1404 if (modeinfo[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE &&
1405 modeinfo[i].id == source_id)
1407 *found_mode_index = i;
1408 return TRUE;
1411 return FALSE;
1414 /***********************************************************************
1415 * QueryDisplayConfig (USER32.@)
1417 LONG WINAPI QueryDisplayConfig(UINT32 flags, UINT32 *numpathelements, DISPLAYCONFIG_PATH_INFO *pathinfo,
1418 UINT32 *numinfoelements, DISPLAYCONFIG_MODE_INFO *modeinfo,
1419 DISPLAYCONFIG_TOPOLOGY_ID *topologyid)
1421 LONG adapter_index, ret;
1422 HANDLE mutex;
1423 HDEVINFO devinfo;
1424 SP_DEVINFO_DATA device_data = {sizeof(device_data)};
1425 DWORD monitor_index = 0, state_flags, type;
1426 UINT32 output_id, source_mode_index, path_index = 0, mode_index = 0;
1427 LUID gpu_luid;
1428 WCHAR device_name[CCHDEVICENAME];
1429 DEVMODEW devmode;
1431 FIXME("(%08x %p %p %p %p %p): semi-stub\n", flags, numpathelements, pathinfo, numinfoelements, modeinfo, topologyid);
1433 if (!numpathelements || !numinfoelements)
1434 return ERROR_INVALID_PARAMETER;
1436 if (!*numpathelements || !*numinfoelements)
1437 return ERROR_INVALID_PARAMETER;
1439 if (flags != QDC_ALL_PATHS &&
1440 flags != QDC_ONLY_ACTIVE_PATHS &&
1441 flags != QDC_DATABASE_CURRENT)
1442 return ERROR_INVALID_PARAMETER;
1444 if (((flags == QDC_DATABASE_CURRENT) && !topologyid) ||
1445 ((flags != QDC_DATABASE_CURRENT) && topologyid))
1446 return ERROR_INVALID_PARAMETER;
1448 if (flags != QDC_ONLY_ACTIVE_PATHS)
1449 FIXME("only returning active paths\n");
1451 if (topologyid)
1453 FIXME("setting toplogyid to DISPLAYCONFIG_TOPOLOGY_INTERNAL\n");
1454 *topologyid = DISPLAYCONFIG_TOPOLOGY_INTERNAL;
1457 wait_graphics_driver_ready();
1458 mutex = get_display_device_init_mutex();
1460 /* Iterate through "targets"/monitors.
1461 * Each target corresponds to a path, and each path corresponds to one or two unique modes.
1463 devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, L"DISPLAY", NULL, DIGCF_PRESENT);
1464 if (devinfo == INVALID_HANDLE_VALUE)
1466 ret = ERROR_GEN_FAILURE;
1467 goto done;
1470 ret = ERROR_GEN_FAILURE;
1471 while (SetupDiEnumDeviceInfo(devinfo, monitor_index++, &device_data))
1473 /* Only count active monitors */
1474 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS,
1475 &type, (BYTE *)&state_flags, sizeof(state_flags), NULL, 0))
1476 goto done;
1477 if (!(state_flags & DISPLAY_DEVICE_ACTIVE))
1478 continue;
1480 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
1481 &type, (BYTE *)&gpu_luid, sizeof(gpu_luid), NULL, 0))
1482 goto done;
1484 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID,
1485 &type, (BYTE *)&output_id, sizeof(output_id), NULL, 0))
1486 goto done;
1488 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME,
1489 &type, (BYTE *)device_name, sizeof(device_name), NULL, 0))
1490 goto done;
1492 memset(&devmode, 0, sizeof(devmode));
1493 devmode.dmSize = sizeof(devmode);
1494 if (!EnumDisplaySettingsW(device_name, ENUM_CURRENT_SETTINGS, &devmode))
1495 goto done;
1497 /* Extract the adapter index from device_name to use as the source ID */
1498 adapter_index = wcstol(device_name + lstrlenW(L"\\\\.\\DISPLAY"), NULL, 10);
1499 adapter_index--;
1501 if (path_index == *numpathelements || mode_index == *numinfoelements)
1503 ret = ERROR_INSUFFICIENT_BUFFER;
1504 goto done;
1507 pathinfo[path_index].flags = DISPLAYCONFIG_PATH_ACTIVE;
1508 set_mode_target_info(&modeinfo[mode_index], &gpu_luid, output_id, flags, &devmode);
1509 set_path_target_info(&(pathinfo[path_index].targetInfo), &gpu_luid, output_id, mode_index, &devmode);
1511 mode_index++;
1512 if (mode_index == *numinfoelements)
1514 ret = ERROR_INSUFFICIENT_BUFFER;
1515 goto done;
1518 /* Multiple targets can be driven by the same source, ensure a mode
1519 * hasn't already been added for this source.
1521 if (!source_mode_exists(modeinfo, mode_index, adapter_index, &source_mode_index))
1523 set_mode_source_info(&modeinfo[mode_index], &gpu_luid, adapter_index, &devmode);
1524 source_mode_index = mode_index;
1525 mode_index++;
1527 set_path_source_info(&(pathinfo[path_index].sourceInfo), &gpu_luid, adapter_index, source_mode_index);
1528 path_index++;
1531 *numpathelements = path_index;
1532 *numinfoelements = mode_index;
1533 ret = ERROR_SUCCESS;
1535 done:
1536 SetupDiDestroyDeviceInfoList(devinfo);
1537 release_display_device_init_mutex(mutex);
1538 return ret;
1541 /***********************************************************************
1542 * DisplayConfigGetDeviceInfo (USER32.@)
1544 LONG WINAPI DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER *packet)
1546 LONG ret = ERROR_GEN_FAILURE;
1547 HANDLE mutex;
1548 HDEVINFO devinfo;
1549 SP_DEVINFO_DATA device_data = {sizeof(device_data)};
1550 DWORD index = 0, type;
1551 LUID gpu_luid;
1553 TRACE("(%p)\n", packet);
1555 if (!packet || packet->size < sizeof(*packet))
1556 return ERROR_GEN_FAILURE;
1557 wait_graphics_driver_ready();
1559 switch (packet->type)
1561 case DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME:
1563 DISPLAYCONFIG_SOURCE_DEVICE_NAME *source_name = (DISPLAYCONFIG_SOURCE_DEVICE_NAME *)packet;
1564 WCHAR device_name[CCHDEVICENAME];
1565 LONG source_id;
1567 TRACE("DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME\n");
1569 if (packet->size < sizeof(*source_name))
1570 return ERROR_INVALID_PARAMETER;
1572 mutex = get_display_device_init_mutex();
1573 devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, L"DISPLAY", NULL, DIGCF_PRESENT);
1574 if (devinfo == INVALID_HANDLE_VALUE)
1576 release_display_device_init_mutex(mutex);
1577 return ret;
1580 while (SetupDiEnumDeviceInfo(devinfo, index++, &device_data))
1582 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
1583 &type, (BYTE *)&gpu_luid, sizeof(gpu_luid), NULL, 0))
1584 continue;
1586 if ((source_name->header.adapterId.LowPart != gpu_luid.LowPart) ||
1587 (source_name->header.adapterId.HighPart != gpu_luid.HighPart))
1588 continue;
1590 /* QueryDisplayConfig() derives the source ID from the adapter name. */
1591 if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME,
1592 &type, (BYTE *)device_name, sizeof(device_name), NULL, 0))
1593 continue;
1595 source_id = wcstol(device_name + lstrlenW(L"\\\\.\\DISPLAY"), NULL, 10);
1596 source_id--;
1597 if (source_name->header.id != source_id)
1598 continue;
1600 lstrcpyW(source_name->viewGdiDeviceName, device_name);
1601 ret = ERROR_SUCCESS;
1602 break;
1604 SetupDiDestroyDeviceInfoList(devinfo);
1605 release_display_device_init_mutex(mutex);
1606 return ret;
1608 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME:
1610 DISPLAYCONFIG_TARGET_DEVICE_NAME *target_name = (DISPLAYCONFIG_TARGET_DEVICE_NAME *)packet;
1612 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME: stub\n");
1614 if (packet->size < sizeof(*target_name))
1615 return ERROR_INVALID_PARAMETER;
1617 return ERROR_NOT_SUPPORTED;
1619 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE:
1621 DISPLAYCONFIG_TARGET_PREFERRED_MODE *preferred_mode = (DISPLAYCONFIG_TARGET_PREFERRED_MODE *)packet;
1623 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE: stub\n");
1625 if (packet->size < sizeof(*preferred_mode))
1626 return ERROR_INVALID_PARAMETER;
1628 return ERROR_NOT_SUPPORTED;
1630 case DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME:
1632 DISPLAYCONFIG_ADAPTER_NAME *adapter_name = (DISPLAYCONFIG_ADAPTER_NAME *)packet;
1634 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME: stub\n");
1636 if (packet->size < sizeof(*adapter_name))
1637 return ERROR_INVALID_PARAMETER;
1639 return ERROR_NOT_SUPPORTED;
1641 case DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE:
1642 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE:
1643 case DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION:
1644 case DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION:
1645 case DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO:
1646 case DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE:
1647 case DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL:
1648 default:
1649 FIXME("Unimplemented packet type: %u\n", packet->type);
1650 return ERROR_INVALID_PARAMETER;
1654 /***********************************************************************
1655 * SetDisplayConfig (USER32.@)
1657 LONG WINAPI SetDisplayConfig(UINT32 path_info_count, DISPLAYCONFIG_PATH_INFO *path_info, UINT32 mode_info_count,
1658 DISPLAYCONFIG_MODE_INFO *mode_info, UINT32 flags)
1660 FIXME("path_info_count %u, path_info %p, mode_info_count %u, mode_info %p, flags %#x stub.\n",
1661 path_info_count, path_info, mode_info_count, mode_info, flags);
1663 return ERROR_SUCCESS;