If user driver didn't initialize the display device registry data, create
some fallback data to at least make EnumDisplayDevice report a primary
adapter and a monitor. 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(a)codeweavers.com>
---
dlls/user32/desktop.c | 11 +-
dlls/user32/tests/monitor.c | 6 +-
programs/explorer/Makefile.in | 2 +-
programs/explorer/desktop.c | 205 +++++++++++++++++++++++++++++-----
4 files changed, 181 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..119c99d800 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"
@@ -39,6 +44,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(explorer);
static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0};
+/* Wine specific monitor properties */
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
+
static BOOL using_root;
struct launcher
@@ -748,24 +756,178 @@ 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 monitor_instanceW[] = {
+ 'D','I','S','P','L','A','Y','\\',
+ 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r','\\',
+ '0','0','0','0','&','0','0','0','0',0};
+ static const WCHAR monitor_hardware_idW[] = {
+ 'M','O','N','I','T','O','R','\\',
+ 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r',0,0};
+ static const WCHAR generic_nonpnp_monitorW[] = {
+ 'G','e','n','e','r','i','c',' ',
+ 'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',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 WCHAR gpu_idW[] = {'G','P','U','I','D',0};
+ static const WCHAR monitor_id0W[] = {'M','o','n','i','t','o','r','I','D','0',0};
+ static const DWORD adapter_state_flags = DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
+ static const DWORD monitor_state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE;
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HDEVINFO devinfo = INVALID_HANDLE_VALUE;
+ WCHAR adapter_keyW[MAX_PATH];
+ WCHAR bufferW[MAX_PATH];
+ DWORD disposition = 0;
+ HKEY hkey = NULL;
+ BOOL ret = FALSE;
+ DWORD size;
+ GUID guid;
+
+ /* 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 and a monitor */
+
+ /* Init GPU */
+ devinfo = SetupDiCreateDeviceInfoList( &GUID_DEVCLASS_DISPLAY, NULL );
+ if (!SetupDiOpenDeviceInfoW( devinfo, gpu_instanceW, NULL, 0, &device_data ))
+ {
+ SetupDiCreateDeviceInfoW( devinfo, gpu_instanceW, &GUID_DEVCLASS_DISPLAY, wine_gpuW, NULL, 0, &device_data );
+ if (!SetupDiRegisterDeviceInfo( devinfo, &device_data, 0, NULL, NULL, NULL ))
+ goto fail;
+ }
+ if (!SetupDiSetDeviceRegistryPropertyW( devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)gpu_hardware_idW,
+ sizeof(gpu_hardware_idW) ))
+ goto fail;
+ SetupDiDestroyDeviceInfoList( devinfo );
+ devinfo = INVALID_HANDLE_VALUE;
+
+ /* Init 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 );
+
+ if (RegSetValueExW( hkey, device_video0W, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW( bufferW ) + 1) * sizeof(WCHAR) ))
+ goto fail;
+ RegCloseKey( hkey );
+ hkey = NULL;
+
+ 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;
+ if (RegSetValueExW( hkey, driver_descW, 0, REG_SZ, (const BYTE *)wine_gpuW, (lstrlenW( wine_gpuW ) + 1) * sizeof(WCHAR) ))
+ goto fail;
+ RegCloseKey( hkey );
+ hkey = NULL;
+ /* Wine specific */
+ RegCreateKeyExW( HKEY_CURRENT_CONFIG, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL );
+ if (RegSetValueExW( hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter_state_flags,
+ sizeof(adapter_state_flags) ))
+ goto fail;
+ if (RegSetValueExW( hkey, gpu_idW, 0, REG_SZ, (const BYTE *)gpu_instanceW,
+ (lstrlenW( gpu_instanceW ) + 1) * sizeof(WCHAR)) )
+ goto fail;
+ if (RegSetValueExW( hkey, monitor_id0W, 0, REG_SZ, (const BYTE *)monitor_instanceW,
+ (lstrlenW( monitor_instanceW ) + 1) * sizeof(WCHAR)) )
+ goto fail;
+ RegCloseKey( hkey );
+ hkey = NULL;
+
+ /* Init monitor */
+ devinfo = SetupDiCreateDeviceInfoList( &GUID_DEVCLASS_MONITOR, NULL );
+ if (!SetupDiOpenDeviceInfoW( devinfo, monitor_instanceW, NULL, 0, &device_data ))
+ {
+ SetupDiCreateDeviceInfoW( devinfo, monitor_instanceW, &GUID_DEVCLASS_MONITOR, generic_nonpnp_monitorW, NULL, 0,
+ &device_data );
+ if (!SetupDiRegisterDeviceInfo( devinfo, &device_data, 0, NULL, NULL, NULL ))
+ goto fail;
+ }
+ hkey = SetupDiCreateDevRegKeyW( devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL );
+
+ if (!SetupDiSetDeviceRegistryPropertyW( devinfo, &device_data, SPDRP_HARDWAREID,
+ (const BYTE *)monitor_hardware_idW, sizeof(monitor_hardware_idW)) )
+ goto fail;
+ /* Wine specific */
+ if (!SetupDiSetDevicePropertyW( devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, DEVPROP_TYPE_UINT32,
+ (const BYTE *)&monitor_state_flags, sizeof(monitor_state_flags), 0) )
+ goto fail;
+
+ ret = TRUE;
+fail:
+ RegCloseKey( hkey );
+ SetupDiDestroyDeviceInfoList( devinfo );
+ if (!ret)
+ ERR("Failed to initialize fallback display device\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 +970,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 +1034,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 +1086,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)
{
--
2.20.1