mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-01 18:58:29 +00:00
gdi32: Use an internal NtUser call for D3DKMTOpenAdapterFromGdiDisplayName.
Fixes a deadlock with display_device_init mutex and display_lock when trying to open the D3DKMT adapter while holding the mutex in the caller. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56764
This commit is contained in:
parent
0da33d5493
commit
6b8cdda502
|
@ -2,7 +2,7 @@ EXTRADEFS = -D_GDI32_
|
|||
MODULE = gdi32.dll
|
||||
IMPORTLIB = gdi32
|
||||
IMPORTS = user32 advapi32 win32u
|
||||
DELAYIMPORTS = setupapi winspool
|
||||
DELAYIMPORTS = winspool
|
||||
|
||||
SOURCES = \
|
||||
dc.c \
|
||||
|
|
|
@ -886,89 +886,15 @@ UINT WINAPI SetDIBColorTable( HDC hdc, UINT start, UINT count, const RGBQUAD *co
|
|||
return NtGdiDoPalette( hdc, start, count, (void *)colors, NtGdiSetDIBColorTable, FALSE );
|
||||
}
|
||||
|
||||
static HANDLE get_display_device_init_mutex( void )
|
||||
{
|
||||
HANDLE mutex = CreateMutexW( NULL, FALSE, L"display_device_init" );
|
||||
|
||||
WaitForSingleObject( mutex, INFINITE );
|
||||
return mutex;
|
||||
}
|
||||
|
||||
static void release_display_device_init_mutex( HANDLE mutex )
|
||||
{
|
||||
ReleaseMutex( mutex );
|
||||
CloseHandle( mutex );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* D3DKMTOpenAdapterFromGdiDisplayName (GDI32.@)
|
||||
*/
|
||||
NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc )
|
||||
{
|
||||
WCHAR *end, key_nameW[MAX_PATH], bufferW[MAX_PATH];
|
||||
HDEVINFO devinfo = INVALID_HANDLE_VALUE;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
D3DKMT_OPENADAPTERFROMLUID luid_desc;
|
||||
SP_DEVINFO_DATA device_data;
|
||||
DWORD size, state_flags;
|
||||
DEVPROPTYPE type;
|
||||
HANDLE mutex;
|
||||
int index;
|
||||
|
||||
TRACE("(%p)\n", desc);
|
||||
|
||||
if (!desc)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
TRACE("DeviceName: %s\n", wine_dbgstr_w( desc->DeviceName ));
|
||||
if (wcsnicmp( desc->DeviceName, L"\\\\.\\DISPLAY", lstrlenW(L"\\\\.\\DISPLAY") ))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
index = wcstol( desc->DeviceName + lstrlenW(L"\\\\.\\DISPLAY"), &end, 10 ) - 1;
|
||||
if (*end)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* Get adapter LUID from SetupAPI */
|
||||
mutex = get_display_device_init_mutex();
|
||||
|
||||
size = sizeof( bufferW );
|
||||
swprintf( key_nameW, MAX_PATH, L"\\Device\\Video%d", index );
|
||||
if (RegGetValueW( HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\VIDEO", key_nameW,
|
||||
RRF_RT_REG_SZ, NULL, bufferW, &size ))
|
||||
goto done;
|
||||
|
||||
/* Strip \Registry\Machine\ prefix and retrieve Wine specific data set by the display driver */
|
||||
lstrcpyW( key_nameW, bufferW + 18 );
|
||||
size = sizeof( state_flags );
|
||||
if (RegGetValueW( HKEY_CURRENT_CONFIG, key_nameW, L"StateFlags", RRF_RT_REG_DWORD, NULL,
|
||||
&state_flags, &size ))
|
||||
goto done;
|
||||
|
||||
if (!(state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
||||
goto done;
|
||||
|
||||
size = sizeof( bufferW );
|
||||
if (RegGetValueW( HKEY_CURRENT_CONFIG, key_nameW, L"GPUID", RRF_RT_REG_SZ, NULL, bufferW, &size ))
|
||||
goto done;
|
||||
|
||||
devinfo = SetupDiCreateDeviceInfoList( &GUID_DEVCLASS_DISPLAY, NULL );
|
||||
device_data.cbSize = sizeof( device_data );
|
||||
SetupDiOpenDeviceInfoW( devinfo, bufferW, NULL, 0, &device_data );
|
||||
if (!SetupDiGetDevicePropertyW( devinfo, &device_data, &DEVPROPKEY_GPU_LUID, &type,
|
||||
(BYTE *)&luid_desc.AdapterLuid, sizeof( luid_desc.AdapterLuid ),
|
||||
NULL, 0))
|
||||
goto done;
|
||||
|
||||
if ((status = NtGdiDdDDIOpenAdapterFromLuid( &luid_desc ))) goto done;
|
||||
|
||||
desc->hAdapter = luid_desc.hAdapter;
|
||||
desc->AdapterLuid = luid_desc.AdapterLuid;
|
||||
desc->VidPnSourceId = index;
|
||||
|
||||
done:
|
||||
SetupDiDestroyDeviceInfoList( devinfo );
|
||||
release_display_device_init_mutex( mutex );
|
||||
return status;
|
||||
if (!desc) return STATUS_UNSUCCESSFUL;
|
||||
return NtUserD3DKMTOpenAdapterFromGdiDisplayName( desc );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -2730,6 +2730,34 @@ static void monitor_get_interface_name( struct monitor *monitor, WCHAR *interfac
|
|||
asciiz_to_unicode( interface_name, buffer );
|
||||
}
|
||||
|
||||
/* see D3DKMTOpenAdapterFromGdiDisplayName */
|
||||
static NTSTATUS d3dkmt_open_adapter_from_gdi_display_name( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc )
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
D3DKMT_OPENADAPTERFROMLUID luid_desc;
|
||||
struct source *source;
|
||||
UNICODE_STRING name;
|
||||
|
||||
TRACE( "desc %p, name %s\n", desc, debugstr_w( desc->DeviceName ) );
|
||||
|
||||
RtlInitUnicodeString( &name, desc->DeviceName );
|
||||
if (!name.Length) return STATUS_UNSUCCESSFUL;
|
||||
if (!(source = find_source( &name ))) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
luid_desc.AdapterLuid = source->gpu->luid;
|
||||
if ((source->state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) &&
|
||||
!(status = NtGdiDdDDIOpenAdapterFromLuid( &luid_desc )))
|
||||
{
|
||||
desc->hAdapter = luid_desc.hAdapter;
|
||||
desc->AdapterLuid = luid_desc.AdapterLuid;
|
||||
desc->VidPnSourceId = source->id + 1;
|
||||
}
|
||||
|
||||
source_release( source );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* NtUserEnumDisplayDevices (win32u.@)
|
||||
*/
|
||||
|
@ -6433,6 +6461,9 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
|
|||
case NtUserCallOneParam_SetThreadDpiAwarenessContext:
|
||||
return set_thread_dpi_awareness_context( arg );
|
||||
|
||||
case NtUserCallOneParam_D3DKMTOpenAdapterFromGdiDisplayName:
|
||||
return d3dkmt_open_adapter_from_gdi_display_name( (void *)arg );
|
||||
|
||||
/* temporary exports */
|
||||
case NtUserGetDeskPattern:
|
||||
return get_entry( &entry_DESKPATTERN, 256, (WCHAR *)arg );
|
||||
|
|
|
@ -912,6 +912,7 @@ enum
|
|||
NtUserCallOneParam_SetProcessDefaultLayout,
|
||||
NtUserCallOneParam_SetKeyboardAutoRepeat,
|
||||
NtUserCallOneParam_SetThreadDpiAwarenessContext,
|
||||
NtUserCallOneParam_D3DKMTOpenAdapterFromGdiDisplayName,
|
||||
/* temporary exports */
|
||||
NtUserGetDeskPattern,
|
||||
};
|
||||
|
@ -1035,6 +1036,13 @@ static inline UINT NtUserSetThreadDpiAwarenessContext( UINT context )
|
|||
return NtUserCallOneParam( context, NtUserCallOneParam_SetThreadDpiAwarenessContext );
|
||||
}
|
||||
|
||||
typedef struct _D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME;
|
||||
|
||||
static inline NTSTATUS NtUserD3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc )
|
||||
{
|
||||
return NtUserCallOneParam( (UINT_PTR)desc, NtUserCallOneParam_D3DKMTOpenAdapterFromGdiDisplayName );
|
||||
}
|
||||
|
||||
/* NtUserCallTwoParam codes, not compatible with Windows */
|
||||
enum
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue