Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/win32u/font.c | 4 ++- dlls/win32u/sysparams.c | 71 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-)
On 11/25/21 09:34, Jacek Caban wrote:
Signed-off-by: Jacek Caban jacek@codeweavers.com
dlls/win32u/font.c | 4 ++- dlls/win32u/sysparams.c | 71 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-)
0004-win32u-Implement-display-adapter-registration.txt
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 1f284d775f4..40467bb82f5 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -584,9 +584,11 @@ HKEY reg_create_key( HKEY root, const WCHAR *name, ULONG name_len, if (i == len) return 0; for (;;) {
unsigned int subkey_options = options;
if (i < len) subkey_options &= ~(REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK); nameW.Buffer = (WCHAR *)name + pos; nameW.Length = (i - pos) * sizeof(WCHAR);
status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, options, disposition );
status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, subkey_options, disposition ); if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); if (!NT_SUCCESS(status)) return 0;
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d5368e96d47..e2e123e1fb1 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -125,6 +125,8 @@ static const WCHAR controlW[] = {'C','o','n','t','r','o','l'}; static const WCHAR device_parametersW[] = {'D','e','v','i','c','e',' ','P','a','r','a','m','e','t','e','r','s'}; static const WCHAR linkedW[] = {'L','i','n','k','e','d',0}; +static const WCHAR symbolic_link_valueW[] =
- {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',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 hardware_idW[] = {'H','a','r','d','w','a','r','e','I','D',0}; @@ -791,7 +793,74 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param )
static void add_adapter( const struct gdi_adapter *adapter, void *param ) {
- FIXME( "\n" );
- struct device_manager_ctx *ctx = param;
- unsigned int adapter_index, video_index, len;
- char name[64], buffer[MAX_PATH];
- WCHAR nameW[64], bufferW[MAX_PATH];
- HKEY hkey;
- TRACE( "\n" );
- if (!ctx->gpu_count)
- {
static const struct gdi_gpu default_gpu;
Maybe a name for the GPU at least?
TRACE( "adding default fake GPU\n" );
add_gpu( &default_gpu, ctx );
- }
- if (ctx->adapter_key)
- {
NtClose( ctx->adapter_key );
ctx->adapter_key = NULL;
- }
- adapter_index = ctx->adapter_count++;
- video_index = ctx->video_count++;
- ctx->monitor_count = 0;
This is making DeviceID and DeviceKey for monitors wrong. For example, a system with two monitors attached and active produces the following results with the attached test program.
master:src/wine$ wine ~/Dropbox/Stage/EnumAdapters/Release/EnumAdapters.exe #0 DeviceName: \.\DISPLAY1 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x5 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DISPLAY_DEVICE_PRIMARY_DEVICE DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0000
#0 DeviceName: \.\DISPLAY1\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
#1 DeviceName: \.\DISPLAY2 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x1 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0001
#0 DeviceName: \.\DISPLAY2\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001
After this patch series.
#0 DeviceName: \.\DISPLAY1 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x5 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DISPLAY_DEVICE_PRIMARY_DEVICE DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0000
#0 DeviceName: \.\DISPLAY1\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
#1 DeviceName: \.\DISPLAY2 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x1 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0001
#0 DeviceName: \.\DISPLAY2\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
Notice that the DeviceID and DeviceKey for both monitors are now having 0000 at the end.
I put the test program in the attachment. It can be built with Visual Studio Community 2019 and I didn't bother to create makefile for it.
- if (!video_key && !(video_key = reg_create_key( NULL, devicemap_video_keyW, sizeof(devicemap_video_keyW),
REG_OPTION_VOLATILE, NULL )))
return;
- len = asciiz_to_unicode( bufferW, "\Registry\Machine\System\CurrentControlSet\"
"Control\\Video\\" ) / sizeof(WCHAR) - 1;
- lstrcpyW( bufferW + len, ctx->gpu_guid );
- len += lstrlenW( bufferW + len );
- sprintf( buffer, "\%04x", adapter_index );
- len += asciiz_to_unicode( bufferW + len, buffer ) / sizeof(WCHAR) - 1;
- hkey = reg_create_key( NULL, bufferW, len * sizeof(WCHAR),
REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, NULL );
- if (!hkey) hkey = reg_create_key( NULL, bufferW, len * sizeof(WCHAR),
REG_OPTION_VOLATILE | REG_OPTION_OPEN_LINK, NULL );
- sprintf( name, "\Device\Video%u", video_index );
- asciiz_to_unicode( nameW, name );
- set_reg_value( video_key, nameW, REG_SZ, bufferW, (lstrlenW( bufferW ) + 1) * sizeof(WCHAR) );
- if (hkey)
- {
sprintf( buffer, "\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
"%s\\%04X", guid_devclass_displayA, ctx->gpu_count - 1 );
len = asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR);
set_reg_value( hkey, symbolic_link_valueW, REG_LINK, bufferW, len );
NtClose( hkey );
- }
- else ERR( "failed to create link key\n" );
- /* Following information is Wine specific, it doesn't really exist on Windows. */
- len = asciiz_to_unicode( bufferW, "System\CurrentControlSet\Control\Video\" )
/ sizeof(WCHAR) - 1;
- lstrcpyW( bufferW + len, ctx->gpu_guid );
- len += lstrlenW( bufferW + len );
- sprintf( buffer, "\%04x", adapter_index );
- len += asciiz_to_unicode( bufferW + len, buffer ) / sizeof(WCHAR) - 1;
- ctx->adapter_key = reg_create_key( config_key, bufferW, len * sizeof(WCHAR),
REG_OPTION_VOLATILE, NULL );
- set_reg_value( ctx->adapter_key, gpu_idW, REG_SZ, ctx->gpuid,
(lstrlenW( ctx->gpuid ) + 1) * sizeof(WCHAR) );
- set_reg_value( ctx->adapter_key, state_flagsW, REG_DWORD, &adapter->state_flags,
sizeof(adapter->state_flags) );
}
static void add_monitor( const struct gdi_monitor *monitor, void *param )
On 11/25/21 09:34, Jacek Caban wrote:
Signed-off-by: Jacek Caban jacek@codeweavers.com
dlls/win32u/font.c | 4 ++- dlls/win32u/sysparams.c | 71 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-)
0004-win32u-Implement-display-adapter-registration.txt
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 1f284d775f4..40467bb82f5 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -584,9 +584,11 @@ HKEY reg_create_key( HKEY root, const WCHAR *name, ULONG name_len, if (i == len) return 0; for (;;) {
- unsigned int subkey_options = options;
- if (i < len) subkey_options &= ~(REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK);
nameW.Buffer = (WCHAR *)name + pos; nameW.Length = (i - pos) * sizeof(WCHAR);
- status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, options, disposition );
- status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, subkey_options, disposition );
if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); if (!NT_SUCCESS(status)) return 0; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d5368e96d47..e2e123e1fb1 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -125,6 +125,8 @@ static const WCHAR controlW[] = {'C','o','n','t','r','o','l'}; static const WCHAR device_parametersW[] = {'D','e','v','i','c','e',' ','P','a','r','a','m','e','t','e','r','s'}; static const WCHAR linkedW[] = {'L','i','n','k','e','d',0}; +static const WCHAR symbolic_link_valueW[] =
- {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',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 hardware_idW[] = {'H','a','r','d','w','a','r','e','I','D',0}; @@ -791,7 +793,74 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param ) static void add_adapter( const struct gdi_adapter *adapter, void *param ) {
- FIXME( "\n" );
- struct device_manager_ctx *ctx = param;
- unsigned int adapter_index, video_index, len;
- char name[64], buffer[MAX_PATH];
- WCHAR nameW[64], bufferW[MAX_PATH];
- HKEY hkey;
- TRACE( "\n" );
- if (!ctx->gpu_count)
- {
- static const struct gdi_gpu default_gpu;
Maybe a name for the GPU at least?
- TRACE( "adding default fake GPU\n" );
- add_gpu( &default_gpu, ctx );
- }
- if (ctx->adapter_key)
- {
- NtClose( ctx->adapter_key );
- ctx->adapter_key = NULL;
- }
- adapter_index = ctx->adapter_count++;
- video_index = ctx->video_count++;
- ctx->monitor_count = 0;
This is making DeviceID and DeviceKey for monitors wrong. For example, a system with two monitors attached and active produces the following results with the attached test program.
master:src/wine$ wine ~/Dropbox/Stage/EnumAdapters/Release/EnumAdapters.exe #0 DeviceName: \.\DISPLAY1 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x5 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DISPLAY_DEVICE_PRIMARY_DEVICE DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0000
#0 DeviceName: \.\DISPLAY1\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
#1 DeviceName: \.\DISPLAY2 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x1 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0001
#0 DeviceName: \.\DISPLAY2\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001
After this patch series.
#0 DeviceName: \.\DISPLAY1 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x5 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DISPLAY_DEVICE_PRIMARY_DEVICE DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0000
#0 DeviceName: \.\DISPLAY1\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
#1 DeviceName: \.\DISPLAY2 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x1 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0001
#0 DeviceName: \.\DISPLAY2\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
Notice that the DeviceID and DeviceKey for both monitors are now having 0000 at the end.
I put the test program at https://zzhiyi.github.io/EnumAdapters.zip . It can be built with Visual Studio Community 2019 and I didn't bother to create makefile for it.
- if (!video_key && !(video_key = reg_create_key( NULL, devicemap_video_keyW, sizeof(devicemap_video_keyW),
- REG_OPTION_VOLATILE, NULL )))
- return;
- len = asciiz_to_unicode( bufferW, "\Registry\Machine\System\CurrentControlSet\"
- "Control\Video\" ) / sizeof(WCHAR) - 1;
- lstrcpyW( bufferW + len, ctx->gpu_guid );
- len += lstrlenW( bufferW + len );
- sprintf( buffer, "\%04x", adapter_index );
- len += asciiz_to_unicode( bufferW + len, buffer ) / sizeof(WCHAR) - 1;
- hkey = reg_create_key( NULL, bufferW, len * sizeof(WCHAR),
- REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, NULL );
- if (!hkey) hkey = reg_create_key( NULL, bufferW, len * sizeof(WCHAR),
- REG_OPTION_VOLATILE | REG_OPTION_OPEN_LINK, NULL );
- sprintf( name, "\Device\Video%u", video_index );
- asciiz_to_unicode( nameW, name );
- set_reg_value( video_key, nameW, REG_SZ, bufferW, (lstrlenW( bufferW ) + 1) * sizeof(WCHAR) );
- if (hkey)
- {
- sprintf( buffer, "\Registry\Machine\System\CurrentControlSet\Control\Class\"
- "%s\%04X", guid_devclass_displayA, ctx->gpu_count - 1 );
- len = asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR);
- set_reg_value( hkey, symbolic_link_valueW, REG_LINK, bufferW, len );
- NtClose( hkey );
- }
- else ERR( "failed to create link key\n" );
- /* Following information is Wine specific, it doesn't really exist on Windows. */
- len = asciiz_to_unicode( bufferW, "System\CurrentControlSet\Control\Video\" )
- / sizeof(WCHAR) - 1;
- lstrcpyW( bufferW + len, ctx->gpu_guid );
- len += lstrlenW( bufferW + len );
- sprintf( buffer, "\%04x", adapter_index );
- len += asciiz_to_unicode( bufferW + len, buffer ) / sizeof(WCHAR) - 1;
- ctx->adapter_key = reg_create_key( config_key, bufferW, len * sizeof(WCHAR),
- REG_OPTION_VOLATILE, NULL );
- set_reg_value( ctx->adapter_key, gpu_idW, REG_SZ, ctx->gpuid,
- (lstrlenW( ctx->gpuid ) + 1) * sizeof(WCHAR) );
- set_reg_value( ctx->adapter_key, state_flagsW, REG_DWORD, &adapter->state_flags,
- sizeof(adapter->state_flags) );
} static void add_monitor( const struct gdi_monitor *monitor, void *param )
Hi Zhiyi,
Thanks for the review!
On 11/25/21 9:17 AM, Zhiyi Zhang wrote:
On 11/25/21 09:34, Jacek Caban wrote:
Signed-off-by: Jacek Caban jacek@codeweavers.com
dlls/win32u/font.c | 4 ++- dlls/win32u/sysparams.c | 71 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-)
0004-win32u-Implement-display-adapter-registration.txt
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 1f284d775f4..40467bb82f5 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -584,9 +584,11 @@ HKEY reg_create_key( HKEY root, const WCHAR *name, ULONG name_len, if (i == len) return 0; for (;;) {
- unsigned int subkey_options = options;
- if (i < len) subkey_options &= ~(REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK);
nameW.Buffer = (WCHAR *)name + pos; nameW.Length = (i - pos) * sizeof(WCHAR);
- status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, options, disposition );
- status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, subkey_options, disposition );
if (attr.RootDirectory != root) NtClose( attr.RootDirectory ); if (!NT_SUCCESS(status)) return 0; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d5368e96d47..e2e123e1fb1 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -125,6 +125,8 @@ static const WCHAR controlW[] = {'C','o','n','t','r','o','l'}; static const WCHAR device_parametersW[] = {'D','e','v','i','c','e',' ','P','a','r','a','m','e','t','e','r','s'}; static const WCHAR linkedW[] = {'L','i','n','k','e','d',0}; +static const WCHAR symbolic_link_valueW[] =
- {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',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 hardware_idW[] = {'H','a','r','d','w','a','r','e','I','D',0}; @@ -791,7 +793,74 @@ static void add_gpu( const struct gdi_gpu *gpu, void *param ) static void add_adapter( const struct gdi_adapter *adapter, void *param ) {
- FIXME( "\n" );
- struct device_manager_ctx *ctx = param;
- unsigned int adapter_index, video_index, len;
- char name[64], buffer[MAX_PATH];
- WCHAR nameW[64], bufferW[MAX_PATH];
- HKEY hkey;
- TRACE( "\n" );
- if (!ctx->gpu_count)
- {
- static const struct gdi_gpu default_gpu;
Maybe a name for the GPU at least?
An empty name is replaced by a default one in add_gpu. The idea is that drivers don't need to worry about default name.
- TRACE( "adding default fake GPU\n" );
- add_gpu( &default_gpu, ctx );
- }
- if (ctx->adapter_key)
- {
- NtClose( ctx->adapter_key );
- ctx->adapter_key = NULL;
- }
- adapter_index = ctx->adapter_count++;
- video_index = ctx->video_count++;
- ctx->monitor_count = 0;
This is making DeviceID and DeviceKey for monitors wrong. For example, a system with two monitors attached and active produces the following results with the attached test program.
master:src/wine$ wine ~/Dropbox/Stage/EnumAdapters/Release/EnumAdapters.exe #0 DeviceName: \.\DISPLAY1 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x5 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DISPLAY_DEVICE_PRIMARY_DEVICE DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0000
#0 DeviceName: \.\DISPLAY1\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
#1 DeviceName: \.\DISPLAY2 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x1 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0001
#0 DeviceName: \.\DISPLAY2\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001
After this patch series.
#0 DeviceName: \.\DISPLAY1 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x5 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DISPLAY_DEVICE_PRIMARY_DEVICE DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0000
#0 DeviceName: \.\DISPLAY1\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
#1 DeviceName: \.\DISPLAY2 DeviceString: NVIDIA GeForce GTX 1650 SUPER StateFlags: 0x1 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP DeviceID: PCI\VEN_10DE&DEV_2187&SUBSYS_00000000&REV_00 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Video{b27a3cb2-1986-4fa0-9233-a457231397dc}\0001
#0 DeviceName: \.\DISPLAY2\Monitor0 DeviceString: Generic Non-PnP Monitor StateFlags: 0x3 DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICE_ATTACHED DeviceID: MONITOR\Default_Monitor{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000 DeviceKey: \Registry\Machine\System\CurrentControlSet\Control\Class{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000
Notice that the DeviceID and DeviceKey for both monitors are now having 0000 at the end.
I put the test program at https://zzhiyi.github.io/EnumAdapters.zip . It can be built with Visual Studio Community 2019 and I didn't bother to create makefile for it.
I should use output_index instead of monitor_index when setting "Driver" value in add_monitor. I will send a new version addressing this and your other comments after a bit of testing.
Thanks,
Jacek