win32u: Introduce reference counting to struct adapter.

This commit is contained in:
Rémi Bernon 2022-09-09 11:24:45 +02:00 committed by Alexandre Julliard
parent b197bd3bf8
commit 75e62eb720

View file

@ -217,6 +217,7 @@ struct display_device
struct adapter struct adapter
{ {
LONG refcount;
struct list entry; struct list entry;
struct display_device dev; struct display_device dev;
unsigned int id; unsigned int id;
@ -425,6 +426,21 @@ static void release_display_device_init_mutex( HANDLE mutex )
NtClose( mutex ); NtClose( mutex );
} }
static struct adapter *adapter_acquire( struct adapter *adapter )
{
InterlockedIncrement( &adapter->refcount );
return adapter;
}
static void adapter_release( struct adapter *adapter )
{
if (!InterlockedDecrement( &adapter->refcount ))
{
free( adapter->modes );
free( adapter );
}
}
static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *mode ) static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *mode )
{ {
WCHAR bufferW[MAX_PATH]; WCHAR bufferW[MAX_PATH];
@ -1450,6 +1466,7 @@ static void clear_display_devices(void)
while (!list_empty( &monitors )) while (!list_empty( &monitors ))
{ {
monitor = LIST_ENTRY( list_head( &monitors ), struct monitor, entry ); monitor = LIST_ENTRY( list_head( &monitors ), struct monitor, entry );
adapter_release( monitor->adapter );
list_remove( &monitor->entry ); list_remove( &monitor->entry );
free( monitor ); free( monitor );
} }
@ -1458,8 +1475,7 @@ static void clear_display_devices(void)
{ {
adapter = LIST_ENTRY( list_head( &adapters ), struct adapter, entry ); adapter = LIST_ENTRY( list_head( &adapters ), struct adapter, entry );
list_remove( &adapter->entry ); list_remove( &adapter->entry );
free( adapter->modes ); adapter_release( adapter );
free( adapter );
} }
} }
@ -1493,12 +1509,12 @@ static BOOL update_display_cache_from_registry(void)
for (adapter_id = 0;; adapter_id++) for (adapter_id = 0;; adapter_id++)
{ {
if (!(adapter = calloc( 1, sizeof(*adapter) ))) break; if (!(adapter = calloc( 1, sizeof(*adapter) ))) break;
adapter->refcount = 1;
adapter->id = adapter_id; adapter->id = adapter_id;
if (!read_display_adapter_settings( adapter_id, adapter )) if (!read_display_adapter_settings( adapter_id, adapter ))
{ {
free( adapter->modes ); adapter_release( adapter );
free( adapter );
break; break;
} }
@ -1506,15 +1522,15 @@ static BOOL update_display_cache_from_registry(void)
for (monitor_id = 0;; monitor_id++) for (monitor_id = 0;; monitor_id++)
{ {
if (!(monitor = calloc( 1, sizeof(*monitor) ))) break; if (!(monitor = calloc( 1, sizeof(*monitor) ))) break;
monitor->id = monitor_id;
monitor->adapter = adapter;
if (!read_monitor_settings( adapter, monitor_id, monitor )) if (!read_monitor_settings( adapter, monitor_id, monitor ))
{ {
free( monitor ); free( monitor );
break; break;
} }
monitor->id = monitor_id;
monitor->adapter = adapter_acquire( adapter );
LIST_FOR_EACH_ENTRY(monitor2, &monitors, struct monitor, entry) LIST_FOR_EACH_ENTRY(monitor2, &monitors, struct monitor, entry)
{ {
if (EqualRect(&monitor2->rc_monitor, &monitor->rc_monitor)) if (EqualRect(&monitor2->rc_monitor, &monitor->rc_monitor))
@ -1957,16 +1973,19 @@ LONG WINAPI NtUserGetDisplayConfigBufferSizes( UINT32 flags, UINT32 *num_path_in
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
/* Find and acquire the adapter matching name, or primary adapter if name is NULL.
* If not NULL, the returned adapter needs to be released with adapter_release.
*/
static struct adapter *find_adapter( UNICODE_STRING *name ) static struct adapter *find_adapter( UNICODE_STRING *name )
{ {
struct adapter *adapter; struct adapter *adapter;
LIST_FOR_EACH_ENTRY(adapter, &adapters, struct adapter, entry) LIST_FOR_EACH_ENTRY(adapter, &adapters, struct adapter, entry)
{ {
if (!name || !name->Length) return adapter; /* use primary adapter */ if (!name || !name->Length) return adapter_acquire( adapter ); /* use primary adapter */
if (!wcsnicmp( name->Buffer, adapter->dev.device_name, name->Length / sizeof(WCHAR) ) && if (!wcsnicmp( name->Buffer, adapter->dev.device_name, name->Length / sizeof(WCHAR) ) &&
!adapter->dev.device_name[name->Length / sizeof(WCHAR)]) !adapter->dev.device_name[name->Length / sizeof(WCHAR)])
return adapter; return adapter_acquire( adapter );
} }
return NULL; return NULL;
} }
@ -2010,6 +2029,7 @@ NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index,
break; break;
} }
} }
adapter_release( adapter );
} }
if (found) if (found)
@ -2472,6 +2492,7 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm
if (!adapter || !modes) if (!adapter || !modes)
{ {
WARN( "Invalid device name %s.\n", debugstr_us(devname) ); WARN( "Invalid device name %s.\n", debugstr_us(devname) );
if (adapter) adapter_release( adapter );
return DISP_CHANGE_BADPARAM; return DISP_CHANGE_BADPARAM;
} }
@ -2480,6 +2501,7 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm
else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL;
else ret = apply_display_settings( device_name, &full_mode, hwnd, flags, lparam ); else ret = apply_display_settings( device_name, &full_mode, hwnd, flags, lparam );
free( modes ); free( modes );
adapter_release( adapter );
if (ret) ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret ); if (ret) ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret );
return ret; return ret;
@ -2519,6 +2541,7 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD index, DEVM
if (index == ENUM_REGISTRY_SETTINGS) ret = read_registry_settings( adapter_path, devmode ); if (index == ENUM_REGISTRY_SETTINGS) ret = read_registry_settings( adapter_path, devmode );
else if (index != ENUM_CURRENT_SETTINGS) ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags ); else if (index != ENUM_CURRENT_SETTINGS) ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags );
else ret = user_driver->pGetCurrentDisplaySettings( device_name, devmode ); else ret = user_driver->pGetCurrentDisplaySettings( device_name, devmode );
adapter_release( adapter );
if (!ret) WARN( "Failed to query %s display settings.\n", debugstr_w(device_name) ); if (!ret) WARN( "Failed to query %s display settings.\n", debugstr_w(device_name) );
else TRACE( "position %dx%d, resolution %ux%u, frequency %u, depth %u, orientation %#x.\n", else TRACE( "position %dx%d, resolution %ux%u, frequency %u, depth %u, orientation %#x.\n",