[PATCH 5/9] win32u: Implement monitor registration.

Zhiyi Zhang zzhang at codeweavers.com
Thu Nov 25 02:08:14 CST 2021



On 11/25/21 09:35, Jacek Caban wrote:
> Signed-off-by: Jacek Caban <jacek at codeweavers.com>
> ---
>  dlls/win32u/sysparams.c | 143 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 142 insertions(+), 1 deletion(-)
>
>
>
> 0005-win32u-Implement-monitor-registration.txt
>
> diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
> index e2e123e1fb1..7d06c42e1f5 100644
> --- a/dlls/win32u/sysparams.c
> +++ b/dlls/win32u/sysparams.c
> @@ -96,6 +96,22 @@ static const WCHAR devpropkey_device_ispresentW[] =
>      '\\','0','0','0','5'
>  };
>  
> +static const WCHAR devpropkey_monitor_gpu_luidW[] =
> +{
> +    'P','r','o','p','e','r','t','i','e','s',
> +    '\\','{','C','A','0','8','5','8','5','3','-','1','6','C','E','-','4','8','A','A',
> +    '-','B','1','1','4','-','D','E','9','C','7','2','3','3','4','2','2','3','}',
> +    '\\','0','0','0','1'
> +};
> +
> +static const WCHAR devpropkey_monitor_output_idW[] =
> +{
> +    'P','r','o','p','e','r','t','i','e','s',
> +    '\\','{','C','A','0','8','5','8','5','3','-','1','6','C','E','-','4','8','A','A',
> +    '-','B','1','1','4','-','D','E','9','C','7','2','3','3','4','2','2','3','}',
> +    '\\','0','0','0','2'
> +};
> +
>  static const WCHAR wine_devpropkey_monitor_stateflagsW[] =
>  {
>      'P','r','o','p','e','r','t','i','e','s','\\',
> @@ -120,6 +136,14 @@ static const WCHAR wine_devpropkey_monitor_rcworkW[] =
>      '\\','0','0','0','4'
>  };
>  
> +static const WCHAR wine_devpropkey_monitor_adapternameW[] =
> +{
> +    'P','r','o','p','e','r','t','i','e','s','\\',
> +    '{','2','3','3','a','9','e','f','3','-','a','f','c','4','-','4','a','b','d',
> +    '-','b','5','6','4','-','c','3','2','f','2','1','f','1','5','3','5','b','}',
> +    '\\','0','0','0','5'
> +};
> +
>  static const WCHAR device_instanceW[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
>  static const WCHAR controlW[] = {'C','o','n','t','r','o','l'};
>  static const WCHAR device_parametersW[] =
> @@ -143,6 +167,9 @@ static const WCHAR guid_devclass_displayW[] =
>       'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
>  
>  static const char  guid_devclass_monitorA[] = "{4D36E96E-E325-11CE-BFC1-08002BE10318}";
> +static const WCHAR guid_devclass_monitorW[] =
> +    {'{','4','D','3','6','E','9','6','E','-','E','3','2','5','-','1','1','C','E','-'
> +        ,'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}'};
>  
>  static const WCHAR guid_devinterface_display_adapterW[] =
>      {'{','5','B','4','5','2','0','1','D','-','F','2','F','2','-','4','F','3','B','-',
> @@ -865,7 +892,121 @@ static void add_adapter( const struct gdi_adapter *adapter, void *param )
>  
>  static void add_monitor( const struct gdi_monitor *monitor, void *param )
>  {
> -    FIXME( "\n" );
> +    struct device_manager_ctx *ctx = param;
> +    char buffer[MAX_PATH], instance[64];
> +    unsigned int monitor_index, output_index;
> +    WCHAR bufferW[MAX_PATH];
> +    HKEY hkey, subkey;
> +
> +    static const WCHAR default_monitorW[] =
> +        {'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 monitorW[] = {'M','o','n','i','t','o','r',0};
> +
> +    TRACE( "%s %s %s\n", debugstr_w(monitor->name), wine_dbgstr_rect(&monitor->rc_monitor),
> +           wine_dbgstr_rect(&monitor->rc_work) );
> +
> +    if (!ctx->adapter_count)
> +    {
> +        static const struct gdi_adapter default_adapter =
> +        {
> +            .state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED,

DISPLAY_DEVICE_ACTIVE and DISPLAY_DEVICE_ATTACHED are for monitors. For a default GDI adapter, you probably
want DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE.

It's probably necessary. But without SetupAPI, I find the overall display device registration much harder to
understand and error-prone, mostly from these NT registry calls. I wonder if the display device registration
can be moved to somewhere that SetupAPI can be called.



Thanks,
Zhiyi

> +        };
> +        TRACE( "adding default fake adapter\n" );
> +        add_adapter( &default_adapter, ctx );
> +    }
> +
> +    monitor_index = ctx->monitor_count++;
> +    output_index = ctx->output_count++;
> +
> +    sprintf( buffer, "MonitorID%u", monitor_index );
> +    sprintf( instance, "DISPLAY\\Default_Monitor\\%04X&%04X", ctx->video_count - 1, monitor_index );
> +    set_reg_ascii_value( ctx->adapter_key, buffer, instance );
> +
> +    hkey = reg_create_key( enum_key, bufferW, asciiz_to_unicode( bufferW, instance ) - sizeof(WCHAR),
> +                          0, NULL );
> +    if (!hkey) return;
> +
> +    link_device( bufferW, guid_devinterface_monitorW );
> +
> +    lstrcpyW( bufferW, monitor->name );
> +    if (!bufferW[0]) asciiz_to_unicode( bufferW, "Generic Non-PnP Monitor" );
> +    set_reg_value( hkey, device_descW, REG_SZ, bufferW, (lstrlenW( bufferW ) + 1) * sizeof(WCHAR) );
> +
> +    set_reg_value( hkey, classW, REG_SZ, monitorW, sizeof(monitorW) );
> +    sprintf( buffer, "%s\\%04X", guid_devclass_monitorA, monitor_index );
> +    set_reg_ascii_value( hkey, "Driver", buffer );
> +    set_reg_value( hkey, class_guidW, REG_SZ, guid_devclass_monitorW, sizeof(guid_devclass_monitorW) );
> +    set_reg_value( hkey, hardware_idW, REG_MULTI_SZ, default_monitorW, sizeof(default_monitorW) );
> +
> +    if ((subkey = reg_create_key( hkey, device_parametersW, sizeof(device_parametersW), 0, NULL )))
> +    {
> +        static const WCHAR edidW[] = {'E','D','I','D',0};
> +        set_reg_value( subkey, edidW, REG_BINARY, monitor->edid, monitor->edid_len );
> +        NtClose( subkey );
> +    }
> +
> +    /* StateFlags */
> +    if ((subkey = reg_create_key( hkey, wine_devpropkey_monitor_stateflagsW,
> +                                  sizeof(wine_devpropkey_monitor_stateflagsW), 0, NULL )))
> +    {
> +        set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_UINT32, &monitor->state_flags,
> +                       sizeof(monitor->state_flags) );
> +        NtClose( subkey );
> +    }
> +
> +    /* WINE_DEVPROPKEY_MONITOR_RCMONITOR */
> +    if ((subkey = reg_create_key( hkey, wine_devpropkey_monitor_rcmonitorW,
> +                                  sizeof(wine_devpropkey_monitor_rcmonitorW), 0, NULL )))
> +    {
> +        set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_BINARY, &monitor->rc_monitor,
> +                       sizeof(monitor->rc_monitor) );
> +        NtClose( subkey );
> +    }
> +
> +    /* WINE_DEVPROPKEY_MONITOR_RCWORK */
> +    if ((subkey = reg_create_key( hkey, wine_devpropkey_monitor_rcworkW,
> +                                  sizeof(wine_devpropkey_monitor_rcworkW), 0, NULL )))
> +    {
> +        TRACE( "rc_work %s\n", wine_dbgstr_rect(&monitor->rc_work) );
> +        set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_BINARY, &monitor->rc_work,
> +                       sizeof(monitor->rc_work) );
> +        NtClose( subkey );
> +    }
> +
> +    /* WINE_DEVPROPKEY_MONITOR_ADAPTERNAME */
> +    if ((subkey = reg_create_key( hkey, wine_devpropkey_monitor_adapternameW,
> +                                  sizeof(wine_devpropkey_monitor_adapternameW), 0, NULL )))
> +    {
> +        sprintf( buffer, "\\\\.\\DISPLAY%u", ctx->video_count );
> +        set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_STRING, bufferW,
> +                       asciiz_to_unicode( bufferW, buffer ));
> +        NtClose( subkey );
> +    }
> +
> +    /* DEVPROPKEY_MONITOR_GPU_LUID */
> +    if ((subkey = reg_create_key( hkey, devpropkey_monitor_gpu_luidW,
> +                                  sizeof(devpropkey_monitor_gpu_luidW), 0, NULL )))
> +    {
> +        set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_INT64,
> +                       &ctx->gpu_luid, sizeof(ctx->gpu_luid) );
> +        NtClose( subkey );
> +    }
> +
> +    /* DEVPROPKEY_MONITOR_OUTPUT_ID */
> +    if ((subkey = reg_create_key( hkey, devpropkey_monitor_output_idW,
> +                                  sizeof(devpropkey_monitor_output_idW), 0, NULL )))
> +    {
> +        set_reg_value( subkey, NULL, 0xffff0000 | DEVPROP_TYPE_UINT32,
> +                       &output_index, sizeof(output_index) );
> +        NtClose( subkey );
> +    }
> +
> +    NtClose( hkey );
> +
> +    sprintf( buffer, "Class\\%s\\%04X", guid_devclass_monitorA, output_index );
> +    hkey = reg_create_key( control_key, bufferW,
> +                           asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR), 0, NULL );
> +    if (hkey) NtClose( hkey );
>  }
>  
>  static const struct gdi_device_manager device_manager =
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20211125/19bbc72a/attachment.htm>


More information about the wine-devel mailing list