From: Vibhav Pant <vibhavp@gmail.com> --- dlls/winebth.sys/winebth.c | 75 ++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 1c13edd29fc..13a190ec2cd 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -825,6 +825,7 @@ static NTSTATUS radio_get_hw_name_w( winebluetooth_radio_t radio, WCHAR **name ) static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added event ) { struct bluetooth_pdo_ext *ext; + struct bluetooth_radio *radio; DEVICE_OBJECT *device_obj; UNICODE_STRING string; NTSTATUS status; @@ -832,6 +833,18 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added WCHAR *hw_name; static unsigned int radio_index; + EnterCriticalSection( &device_list_cs ); + LIST_FOR_EACH_ENTRY( radio, &device_list, struct bluetooth_radio, entry ) + { + if (winebluetooth_radio_equal( radio->radio, event.radio )) + { + WARN( "Radio %#Ix already exists, skipping.\n", event.radio.handle ); + LeaveCriticalSection( &device_list_cs ); + winebluetooth_radio_free( event.radio ); + return; + } + } + swprintf( name, ARRAY_SIZE( name ), L"\\Device\\WINEBTH-RADIO-%d", radio_index++ ); TRACE( "Adding new bluetooth radio %p: %s\n", (void *)event.radio.handle, debugstr_w( name ) ); @@ -839,6 +852,8 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added if (status) { ERR( "Failed to get hardware name for radio %p, status %#lx\n", (void *)event.radio.handle, status ); + LeaveCriticalSection( &device_list_cs ); + winebluetooth_radio_free( event.radio ); return; } @@ -848,6 +863,8 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added if (status) { ERR( "Failed to create device, status %#lx\n", status ); + LeaveCriticalSection( &device_list_cs ); + winebluetooth_radio_free( event.radio ); return; } @@ -864,7 +881,6 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added InitializeListHead( &ext->radio.irp_list ); - EnterCriticalSection( &device_list_cs ); list_add_tail( &device_list, &ext->radio.entry ); LeaveCriticalSection( &device_list_cs ); @@ -975,10 +991,21 @@ static void bluetooth_radio_add_remote_device( struct winebluetooth_watcher_even { if (winebluetooth_radio_equal( event.radio, radio->radio )) { + struct bluetooth_remote_device *device; struct bluetooth_pdo_ext *ext; DEVICE_OBJECT *device_obj; NTSTATUS status; + LIST_FOR_EACH_ENTRY( device, &radio->remote_devices, struct bluetooth_remote_device, entry ) + { + if (winebluetooth_device_equal( device->device, event.device )) + { + WARN( "Remote device %#Ix already exists, skipping.\n", event.device.handle ); + winebluetooth_device_free( event.device ); + goto done; + } + } + status = IoCreateDevice( driver_obj, sizeof( *ext ), NULL, FILE_DEVICE_BLUETOOTH, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &device_obj ); if (status) @@ -1016,6 +1043,7 @@ static void bluetooth_radio_add_remote_device( struct winebluetooth_watcher_even break; } } +done: LeaveCriticalSection( &device_list_cs ); winebluetooth_radio_free( event.radio ); @@ -1250,28 +1278,20 @@ static void complete_irp( IRP *irp, NTSTATUS result ) IoCompleteRequest( irp, IO_NO_INCREMENT ); } +/* Enables the low energy interface for this device if it hasn't been already. Caller should hold device->props_cs. */ static void bluetooth_device_enable_le_iface( struct bluetooth_remote_device *device ) { - EnterCriticalSection( &device->props_cs ); /* The device hasn't been started by the PnP manager yet. Set le, and let remote_device_pdo_pnp enable the * interface. */ if (!device->started) - { device->le = TRUE; - LeaveCriticalSection( &device->props_cs ); - return; - } - - if (device->le) + else if (!device->le) { - LeaveCriticalSection( &device->props_cs ); - return; - } - device->le = TRUE; - if (!IoRegisterDeviceInterface( device->device_obj, &GUID_BLUETOOTHLE_DEVICE_INTERFACE, NULL, - &device->bthle_symlink_name )) + device->le = TRUE; + if (!IoRegisterDeviceInterface( device->device_obj, &GUID_BLUETOOTHLE_DEVICE_INTERFACE, NULL, + &device->bthle_symlink_name )) IoSetDeviceInterfaceState( &device->bthle_symlink_name, TRUE ); - LeaveCriticalSection( &device->props_cs ); + } } static void bluetooth_device_add_gatt_service( struct winebluetooth_watcher_event_gatt_service_added event ) @@ -1287,10 +1307,22 @@ static void bluetooth_device_add_gatt_service( struct winebluetooth_watcher_even { if (winebluetooth_device_equal( event.device, device->device ) && !device->removed) { + struct bluetooth_gatt_service *service; struct bluetooth_pdo_ext *ext; DEVICE_OBJECT *device_obj; NTSTATUS status; + EnterCriticalSection( &device->props_cs ); + LIST_FOR_EACH_ENTRY( service, &device->gatt_services, struct bluetooth_gatt_service, entry ) + { + if (winebluetooth_gatt_service_equal( service->service, event.service )) + { + WARN( "GATT service %#Ix already exists, skipping.\n", event.device.handle ); + LeaveCriticalSection( &device->props_cs ); + goto failed; + } + } + TRACE( "Adding GATT service %s for remote device %p\n", debugstr_guid( &event.uuid ), (void *)event.device.handle ); @@ -1299,6 +1331,7 @@ static void bluetooth_device_add_gatt_service( struct winebluetooth_watcher_even if (status) { ERR( "Failed to create GATT service PDO, status %#lx\n", status ); + LeaveCriticalSection( &device->props_cs ); goto failed; } @@ -1317,7 +1350,6 @@ static void bluetooth_device_add_gatt_service( struct winebluetooth_watcher_even ext->gatt_service.chars_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": bluetooth_gatt_service.chars_cs"); bluetooth_device_enable_le_iface( device ); - EnterCriticalSection( &device->props_cs ); list_add_tail( &device->gatt_services, &ext->gatt_service.entry ); LeaveCriticalSection( &device->props_cs ); @@ -1400,6 +1432,17 @@ bluetooth_gatt_service_add_characteristic( struct winebluetooth_watcher_event_ga { struct bluetooth_gatt_characteristic *entry; + LIST_FOR_EACH_ENTRY( entry, &svc->characteristics, struct bluetooth_gatt_characteristic, entry ) + { + if (winebluetooth_gatt_characteristic_equal( entry->characteristic, characteristic.characteristic )) + { + WARN( "GATT characteristic %#Ix already exists, skipping.\n", + entry->characteristic.handle ); + LeaveCriticalSection( &device->props_cs ); + goto failed; + } + } + if (!(entry = calloc( 1, sizeof( *entry ) ))) { LeaveCriticalSection( &device->props_cs ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10417