If user driver didn't initialize the display device registry data, create some fallback data to at least make EnumDisplayDevice report a primary adapter. Otherwise, report back the primary adapter GUID to store in the desktop HWND atom, instead of creating a new one.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/user32/desktop.c | 11 +-- dlls/user32/tests/monitor.c | 6 +- programs/explorer/Makefile.in | 2 +- programs/explorer/desktop.c | 167 ++++++++++++++++++++++++++++------ 4 files changed, 143 insertions(+), 43 deletions(-)
diff --git a/dlls/user32/desktop.c b/dlls/user32/desktop.c index fe6649446e..3662a68976 100644 --- a/dlls/user32/desktop.c +++ b/dlls/user32/desktop.c @@ -101,28 +101,21 @@ LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lP static const WCHAR display_device_guid_propW[] = { '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_', 'd','e','v','i','c','e','_','g','u','i','d',0 }; - static const WCHAR guid_formatW[] = { - '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-', - '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0};
switch (message) { case WM_NCCREATE: { CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam; - const GUID *guid = cs->lpCreateParams; + WCHAR *guid = cs->lpCreateParams;
if (guid) { ATOM atom; - WCHAR buffer[37];
if (GetAncestor( hwnd, GA_PARENT )) return FALSE; /* refuse to create non-desktop window */
- sprintfW( buffer, guid_formatW, guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); - atom = GlobalAddAtomW( buffer ); + atom = GlobalAddAtomW( guid ); SetPropW( hwnd, display_device_guid_propW, ULongToHandle( atom ) ); } return TRUE; diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index c5e6745322..bee1085a14 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -81,7 +81,7 @@ static int monitor_count = 0;
static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *device, DWORD flags) { - char video_name[16]; + char video_name[32]; char video_value[128]; char buffer[128]; int number; @@ -107,7 +107,7 @@ static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *de { sprintf(video_name, "\Device\Video%d", index); ls = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\DEVICEMAP\VIDEO", 0, KEY_READ, &hkey); - todo_wine ok(!ls, "#%d: failed to open registry, error: %#x\n", index, ls); + ok(!ls, "#%d: failed to open registry, error: %#x\n", index, ls); if (!ls) { memset(video_value, 0, sizeof(video_value)); @@ -115,7 +115,7 @@ static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *de ls = RegQueryValueExA(hkey, video_name, NULL, NULL, (unsigned char *)video_value, &size); ok(!ls, "#%d: failed to get registry value, error: %#x\n", index, ls); RegCloseKey(hkey); - ok(!strcmp(video_value, device->DeviceKey), "#%d: wrong DeviceKey: %s\n", index, device->DeviceKey); + todo_wine ok(!strcmp(video_value, device->DeviceKey), "#%d: wrong DeviceKey: %s\n", index, device->DeviceKey); } } else diff --git a/programs/explorer/Makefile.in b/programs/explorer/Makefile.in index 374c6aaebe..13b0ed3dfa 100644 --- a/programs/explorer/Makefile.in +++ b/programs/explorer/Makefile.in @@ -1,5 +1,5 @@ MODULE = explorer.exe -IMPORTS = rpcrt4 user32 gdi32 advapi32 +IMPORTS = rpcrt4 user32 gdi32 advapi32 setupapi DELAYIMPORTS = comctl32 shell32 oleaut32 ole32 shlwapi
EXTRADLLFLAGS = -mwindows -municode -mno-cygwin diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index d4925f7c5b..48b97cb137 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -27,6 +27,11 @@ #include <rpc.h> #include <shlobj.h> #include <shellapi.h> +#include <wingdi.h> +#include <initguid.h> +#include <devguid.h> +#include <devpkey.h> +#include <setupapi.h> #include "exdisp.h"
#include "wine/debug.h" @@ -748,24 +753,143 @@ static BOOL get_default_enable_shell( const WCHAR *name ) return result; }
-static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid ) -{ - static const WCHAR device_keyW[] = { +/* Initialize the display device registry if user driver didn't do it, + * and report the primary adapter guid in paramter guid_string. */ +static BOOL initialize_fallback_display_devices( const WCHAR *driver_path, WCHAR *guid_string ) +{ + static const WCHAR video_keyW[] = { + 'H','A','R','D','W','A','R','E','\', + 'D','E','V','I','C','E','M','A','P','\', + 'V','I','D','E','O',0}; + static const WCHAR device_video0W[] = { + '\','D','e','v','i','c','e','\', + 'V','i','d','e','o','0',0}; + static const WCHAR device_video_prefixW[] = { + '\','R','e','g','i','s','t','r','y','\', + 'M','a','c','h','i','n','e','\',0}; + static const WCHAR gpu_instanceW[] = { + 'P','C','I','\', + 'V','E','N','_','0','0','0','0','&', + 'D','E','V','_','0','0','0','0','&', + 'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&', + 'R','E','V','_','0','0','\', + '0','0','0','0','0','0','0','0',0}; + static const WCHAR gpu_hardware_idW[] = { + 'P','C','I','\', + 'V','E','N','_','0','0','0','0','&', + 'D','E','V','_','0','0','0','0','&', + 'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&', + 'R','E','V','_','0','0',0,0}; + static const WCHAR device_key_fmtW[] = { 'S','y','s','t','e','m','\', 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\', 'C','o','n','t','r','o','l','\', 'V','i','d','e','o','\', - '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-', - '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x','%','0','2','x', - '%','0','2','x','%','0','2','x','%','0','2','x','}','\','0','0','0','0',0}; + '{','%','s','}','\', + '0','0','0','0',0}; + static const WCHAR guid_formatW[] = { + '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-', + '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0}; static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0}; + static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0}; + static const WCHAR wine_gpuW[] = {'W','i','n','e',' ','G','P','U',0}; + static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0}; + static const DWORD primary_state_flags = DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP; + HDEVINFO devinfo; + SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + WCHAR adapter_keyW[MAX_PATH]; + WCHAR bufferW[MAX_PATH]; + DWORD disposition = 0; + DWORD size; + GUID guid; + HKEY hkey = NULL; + BOOL ret = FALSE; + + /* Create HKLM\HARDWARE\DEVICEMAP\VIDEO key if user drivers didn't do it */ + RegCreateKeyExW( HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &disposition ); + + /* User driver did create it. Report back primary adapter guid */ + if (disposition != REG_CREATED_NEW_KEY) + { + size = sizeof(bufferW); + if (!RegQueryValueExW( hkey, device_video0W, NULL, NULL, (BYTE *)bufferW, &size )) + { + /* Skip over \Registry\Machine\System\CurrentControlSet\Control\Video{ to get guid string */ + memcpy( guid_string, bufferW + 58, 36 * sizeof(WCHAR) ); + guid_string[36] = 0; + RegCloseKey( hkey ); + return TRUE; + } + /* Falling through */ + } + + /* Create basic display device registry data so that functions like EnumDisplayDevice can at least report + * a primary adapter */ + /* Init GPU */ + devinfo = SetupDiCreateDeviceInfoList( &GUID_DEVCLASS_DISPLAY, NULL ); + if (!SetupDiOpenDeviceInfoW( devinfo, gpu_instanceW, NULL, 0, &device_data )) + { + SetupDiCreateDeviceInfoW( devinfo, gpu_instanceW, &GUID_DEVCLASS_DISPLAY, NULL, NULL, 0, &device_data ); + if (!SetupDiRegisterDeviceInfo( devinfo, &device_data, 0, NULL, NULL, NULL )) + goto fail; + } + + /* Write HardwareID */ + if (!SetupDiSetDeviceRegistryPropertyW( devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)(gpu_hardware_idW), + sizeof(gpu_hardware_idW) )) + goto fail; + + /* Init primary adapter */ + UuidCreate( &guid ); + swprintf( guid_string, 37, guid_formatW, guid.Data1, guid.Data2, guid.Data3, + guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], + guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] ); + swprintf( adapter_keyW, ARRAY_SIZE(adapter_keyW), device_key_fmtW, guid_string ); + lstrcpyW( bufferW, device_video_prefixW ); + lstrcatW( bufferW, adapter_keyW ); + + /* Write value of \Device\Video0 in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */ + if (RegSetValueExW( hkey, device_video0W, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW( bufferW ) + 1) * sizeof(WCHAR) )) + goto fail; + RegCloseKey( hkey ); + hkey = NULL; + + /* Write GraphicsDriver */ + RegCreateKeyExW( HKEY_LOCAL_MACHINE, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL ); + if (RegSetValueExW( hkey, graphics_driverW, 0, REG_SZ, (const BYTE *)driver_path, (lstrlenW( driver_path ) + 1) * sizeof(WCHAR) )) + goto fail; + + /* Write DriverDesc */ + if (RegSetValueExW( hkey, driver_descW, 0, REG_SZ, (const BYTE *)wine_gpuW, (lstrlenW( wine_gpuW ) + 1) * sizeof(WCHAR) )) + goto fail; + + RegCloseKey( hkey ); + hkey = NULL; + + RegCreateKeyExW( HKEY_CURRENT_CONFIG, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL ); + /* Write StateFlags */ + if (RegSetValueExW( hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&primary_state_flags, + sizeof(primary_state_flags) )) + goto fail; + + ret = TRUE; +fail: + RegCloseKey( hkey ); + SetupDiDestroyDeviceInfoList( devinfo ); + if (!ret) + ERR("Failed to initialize fallback display device registry data\n"); + return ret; +} + +/* Load graphics driver, return its module handle in hmodule and report primary adapter guid in guid */ +static void load_graphics_driver( const WCHAR *driver, HMODULE *hmodule, WCHAR *guid ) +{ static const WCHAR driversW[] = {'S','o','f','t','w','a','r','e','\', 'W','i','n','e','\','D','r','i','v','e','r','s',0}; static const WCHAR graphicsW[] = {'G','r','a','p','h','i','c','s',0}; static const WCHAR drv_formatW[] = {'w','i','n','e','%','s','.','d','r','v',0};
WCHAR buffer[MAX_PATH], libname[32], *name, *next; - WCHAR key[ARRAY_SIZE( device_keyW ) + 39]; HMODULE module = 0; HKEY hkey; char error[80]; @@ -808,27 +932,12 @@ static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid ) }
if (module) - { GetModuleFileNameW( module, buffer, MAX_PATH ); - TRACE( "display %s driver %s\n", debugstr_guid(guid), debugstr_w(buffer) ); - }
- swprintf( key, ARRAY_SIZE(key), device_keyW, guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); + initialize_fallback_display_devices( buffer, guid ); + TRACE( "display %s driver %s\n", debugstr_w(guid), debugstr_w(buffer) );
- if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, key, 0, NULL, - REG_OPTION_VOLATILE, KEY_SET_VALUE, NULL, &hkey, NULL )) - { - if (module) - RegSetValueExW( hkey, graphics_driverW, 0, REG_SZ, - (BYTE *)buffer, (lstrlenW(buffer) + 1) * sizeof(WCHAR) ); - else - RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 ); - RegCloseKey( hkey ); - } - - return module; + *hmodule = module; }
static void initialize_display_settings(void) @@ -887,7 +996,7 @@ void manage_desktop( WCHAR *arg ) { static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0}; HDESK desktop = 0; - GUID guid; + WCHAR guid[37] = {0}; MSG msg; HWND hwnd; HMODULE graphics_driver; @@ -939,13 +1048,11 @@ void manage_desktop( WCHAR *arg ) SetThreadDesktop( desktop ); }
- UuidCreate( &guid ); - TRACE( "display guid %s\n", debugstr_guid(&guid) ); - graphics_driver = load_graphics_driver( driver, &guid ); + load_graphics_driver( driver, &graphics_driver, guid );
/* create the desktop window */ hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL, - WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, &guid ); + WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, guid );
if (hwnd) {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=52682
Your paranoid android.
=== debian9 (32 bit Chinese:China report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000