[PATCH 4/4] gdi32: Support LUID in D3DKMTOpenAdapterFromGdiDisplayName().

Zhiyi Zhang zzhang at codeweavers.com
Tue Apr 21 07:13:13 CDT 2020


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/gdi32/Makefile.in    |   2 +-
 dlls/gdi32/driver.c       | 100 ++++++++++++++++++++++++++++++++++++--
 dlls/gdi32/tests/driver.c |   2 +
 3 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in
index e1ac922ce52..32b2e6959c1 100644
--- a/dlls/gdi32/Makefile.in
+++ b/dlls/gdi32/Makefile.in
@@ -4,7 +4,7 @@ IMPORTLIB = gdi32
 IMPORTS   = advapi32
 EXTRAINCL = $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS)
 EXTRALIBS = $(CARBON_LIBS) $(APPKIT_LIBS)
-DELAYIMPORTS = usp10
+DELAYIMPORTS = usp10 setupapi
 
 C_SRCS = \
 	bidi.c \
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 90977383a58..8eedc821146 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -31,10 +31,14 @@
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
+#include "winreg.h"
 #include "ddrawgdi.h"
 #include "wine/winbase16.h"
 #include "winuser.h"
 #include "winternl.h"
+#include "initguid.h"
+#include "devguid.h"
+#include "setupapi.h"
 #include "ddk/d3dkmthk.h"
 
 #include "gdi_private.h"
@@ -45,6 +49,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(driver);
 
+DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+
 struct graphics_driver
 {
     struct list                entry;
@@ -84,6 +90,7 @@ static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 };
 static HWND (WINAPI *pGetDesktopWindow)(void);
 static INT (WINAPI *pGetSystemMetrics)(INT);
 static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+static BOOL (WINAPI *pEnumDisplayDevicesW)(LPCWSTR, DWORD, DISPLAY_DEVICEW *, DWORD);
 
 /**********************************************************************
  *	     create_driver
@@ -159,6 +166,20 @@ static BOOL is_display_device( LPCWSTR name )
     return TRUE;
 }
 
+static HANDLE get_display_device_init_mutex( void )
+{
+    static const WCHAR init_mutex[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
+    HANDLE mutex = CreateMutexW( NULL, FALSE, init_mutex );
+
+    WaitForSingleObject( mutex, INFINITE );
+    return mutex;
+}
+
+static void release_display_device_init_mutex( HANDLE mutex )
+{
+    ReleaseMutex( mutex );
+    CloseHandle( mutex );
+}
 
 /**********************************************************************
  *	     DRIVER_load_driver
@@ -1351,16 +1372,89 @@ NTSTATUS WINAPI D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
 NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc )
 {
     static const WCHAR displayW[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'};
+    static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
+    static const WCHAR pciW[] = {'P','C','I',0};
     static D3DKMT_HANDLE handle_start = 0;
+    DWORD size, type, device_index = 0;
+    DISPLAY_DEVICEW display_device;
     struct d3dkmt_adapter *adapter;
+    SP_DEVINFO_DATA device_data;
+    WCHAR buffer[MAX_PATH];
+    BOOL found = FALSE;
+    HDEVINFO devinfo;
+    HMODULE user32;
+    HANDLE mutex;
+    LSTATUS ls;
     WCHAR *end;
+    HKEY hkey;
+    LUID luid;
     int id;
 
     TRACE("(%p) semi-stub\n", desc);
 
-    if (!desc || strncmpiW( desc->DeviceName, displayW, ARRAY_SIZE(displayW) ))
+    if (!desc)
         return STATUS_UNSUCCESSFUL;
 
+    if (!pEnumDisplayDevicesW)
+    {
+        user32 = LoadLibraryA( "user32.dll" );
+        pEnumDisplayDevicesW = (void *)GetProcAddress( user32, "EnumDisplayDevicesW" );
+    }
+
+    display_device.cb = sizeof( display_device );
+    while (pEnumDisplayDevicesW( NULL, device_index++, &display_device, 0 ))
+    {
+        if (lstrcmpiW( display_device.DeviceName, desc->DeviceName ))
+            continue;
+
+        if (display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
+        {
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (!found)
+        return STATUS_UNSUCCESSFUL;
+
+    /* Get the GPU LUID from SetupAPI */
+    mutex = get_display_device_init_mutex();
+    devinfo = SetupDiGetClassDevsW( &GUID_DEVCLASS_DISPLAY, pciW, NULL, 0 );
+
+    found = FALSE;
+    device_index = 0;
+    device_data.cbSize = sizeof(device_data);
+    while (SetupDiEnumDeviceInfo( devinfo, device_index++, &device_data ))
+    {
+        hkey = SetupDiOpenDevRegKey( devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ );
+        if (hkey == INVALID_HANDLE_VALUE)
+            continue;
+
+        size = sizeof(buffer);
+        ls = RegQueryValueExW( hkey, video_idW, 0, NULL, (BYTE *)buffer, &size );
+        RegCloseKey( hkey );
+        if (ls)
+            continue;
+
+        /* Compare GPU UUID. DeviceKey from EnumDisplayDevices is of form
+         * \Registry\Machine\System\CurrentControlSet\Control\Video\{GPU UUID}\0000 */
+        if (strncmpiW( buffer, display_device.DeviceKey + 57, 38 ))
+            continue;
+
+        if (SetupDiGetDevicePropertyW( devinfo, &device_data, &DEVPROPKEY_GPU_LUID,
+                                       &type, (BYTE *)&luid, sizeof(luid), NULL, 0) )
+        {
+            found = TRUE;
+            break;
+        }
+    }
+    SetupDiDestroyDeviceInfoList( devinfo );
+    release_display_device_init_mutex( mutex );
+
+    if (!found)
+        return STATUS_UNSUCCESSFUL;
+
+    /* FIXME: Using display index as VidPnSourceId */
     id = strtolW( desc->DeviceName + ARRAY_SIZE(displayW), &end, 10 ) - 1;
     if (*end)
         return STATUS_UNSUCCESSFUL;
@@ -1376,9 +1470,7 @@ NTSTATUS WINAPI D3DKMTOpenAdapterFromGdiDisplayName( D3DKMT_OPENADAPTERFROMGDIDI
     LeaveCriticalSection( &driver_section );
 
     desc->hAdapter = handle_start;
-    /* FIXME: Support AdapterLuid */
-    desc->AdapterLuid.LowPart = 0;
-    desc->AdapterLuid.HighPart = 0;
+    desc->AdapterLuid = luid;
     desc->VidPnSourceId = id;
     return STATUS_SUCCESS;
 }
diff --git a/dlls/gdi32/tests/driver.c b/dlls/gdi32/tests/driver.c
index 6172d4a7983..c656eb4245a 100644
--- a/dlls/gdi32/tests/driver.c
+++ b/dlls/gdi32/tests/driver.c
@@ -86,6 +86,8 @@ static void test_D3DKMTOpenAdapterFromGdiDisplayName(void)
         }
 
         ok(open_adapter_gdi_desc.hAdapter, "Expect not null.\n");
+        ok(open_adapter_gdi_desc.AdapterLuid.LowPart || open_adapter_gdi_desc.AdapterLuid.HighPart,
+           "Expect LUID not zero.\n");
 
         close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
         status = pD3DKMTCloseAdapter(&close_adapter_desc);
-- 
2.20.1



More information about the wine-devel mailing list