From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/unixlib.c | 31 +++++++++++++++++- dlls/winebth.sys/unixlib.h | 9 ++++++ dlls/winebth.sys/winebluetooth.c | 17 ++++++++++ dlls/winebth.sys/winebluetooth.h | 2 ++ dlls/winebth.sys/winebth.c | 54 ++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index 826c180ea7c..2a3607046dd 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -27,7 +27,6 @@ #include <stdlib.h> #include <stdarg.h> #include <assert.h> -#include <ctype.h> #include <pthread.h>
#include <ntstatus.h> @@ -110,6 +109,35 @@ static NTSTATUS bluetooth_shutdown( void *params ) return STATUS_SUCCESS; }
+static NTSTATUS get_unique_name( const struct unix_name *name, char *buf, SIZE_T *buf_size ) +{ + SIZE_T path_len, i; + + path_len = strlen( name->str ); + if (*buf_size <= (path_len * sizeof(char))) + { + *buf_size = (path_len + 1) * sizeof(char); + return STATUS_BUFFER_TOO_SMALL; + } + + for (i = 0; i < path_len; i++) + { + if (name->str[i] == '/') buf[i] = '_'; + else + buf[i] = name->str[i]; + } + buf[path_len] = '\0'; + return STATUS_SUCCESS; +} + +static NTSTATUS bluetooth_adapter_get_unique_name( void *args ) +{ + struct bluetooth_adapter_get_unique_name_params *params = args; + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + + return get_unique_name( params->adapter, params->buf, ¶ms->buf_size ); +} + static NTSTATUS bluetooth_adapter_free( void *args ) { struct bluetooth_adapter_free_params *params = args; @@ -144,6 +172,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_init, bluetooth_shutdown,
+ bluetooth_adapter_get_unique_name, bluetooth_adapter_free,
bluetooth_watcher_init, diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index 4b6354a96e2..c3b601715db 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -47,6 +47,14 @@ struct bluetooth_adapter_free_params unix_name_t adapter; };
+struct bluetooth_adapter_get_unique_name_params +{ + unix_name_t adapter; + + char *buf; + SIZE_T buf_size; +}; + struct bluetooth_watcher_init_params { unix_handle_t unix_watcher_ctx; @@ -69,6 +77,7 @@ enum bluetoothapis_funcs unix_bluetooth_init, unix_bluetooth_shutdown,
+ unix_bluetooth_adapter_get_unique_name, unix_bluetooth_adapter_free,
unix_bluetooth_watcher_init, diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index d29b4f1f2b1..0d4053bae9c 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -36,6 +36,23 @@
WINE_DEFAULT_DEBUG_CHANNEL( winebth );
+NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name, + SIZE_T *size ) +{ + struct bluetooth_adapter_get_unique_name_params params = {0}; + NTSTATUS status; + + TRACE( "(%p, %p, %p)\n", (void *)radio.handle, name, size ); + + params.adapter = radio.handle; + params.buf = name; + params.buf_size = *size; + status = UNIX_BLUETOOTH_CALL( bluetooth_adapter_get_unique_name, ¶ms ); + if (status == STATUS_BUFFER_TOO_SMALL) + *size = params.buf_size; + return status; +} + void winebluetooth_radio_free( winebluetooth_radio_t radio ) { struct bluetooth_adapter_free_params args = { 0 }; diff --git a/dlls/winebth.sys/winebluetooth.h b/dlls/winebth.sys/winebluetooth.h index 4ecd3d31c64..f4de9594247 100644 --- a/dlls/winebth.sys/winebluetooth.h +++ b/dlls/winebth.sys/winebluetooth.h @@ -36,6 +36,8 @@ struct winebluetooth_bluetooth_version UCHAR minor; };
+NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name, + SIZE_T *size ); void winebluetooth_radio_free( winebluetooth_radio_t radio );
typedef struct diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 7e528c15bdb..c8f50541717 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -68,6 +68,7 @@ struct bluetooth_radio
DEVICE_OBJECT *device_obj; winebluetooth_radio_t radio; + WCHAR *hw_name; LIST_ENTRY irp_list; };
@@ -101,7 +102,45 @@ void WINAPIV append_id( struct string_buffer *buffer, const WCHAR *format, ... )
static HANDLE event_loop_thread; +static NTSTATUS radio_get_hw_name_w( winebluetooth_radio_t radio, WCHAR **name ) +{ + char *name_a; + SIZE_T size = sizeof( char ) * 256; + NTSTATUS status; + + name_a = malloc( size ); + if (name_a == NULL) + return STATUS_NO_MEMORY; + + status = winebluetooth_radio_get_unique_name( radio, name_a, &size ); + if (status == STATUS_BUFFER_TOO_SMALL) + { + void *ptr = realloc( name_a, size ); + if (ptr == NULL) + { + free( name_a ); + return STATUS_NO_MEMORY; + } + name_a = ptr; + status = winebluetooth_radio_get_unique_name( radio, name_a, &size ); + } + if (status != STATUS_SUCCESS) + { + free( name_a ); + return status; + }
+ *name = malloc( (mbstowcs( NULL, name_a, 0 ) + 1) * sizeof( WCHAR )); + if (*name == NULL) + { + free( name_a ); + return status; + } + + mbstowcs( *name, name_a, strlen( name_a ) + 1 ); + free( name_a ); + return STATUS_SUCCESS; +} static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added event ) { struct bluetooth_radio *device; @@ -109,11 +148,19 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added UNICODE_STRING string; NTSTATUS status; WCHAR name[256]; + WCHAR *hw_name; static unsigned int radio_index;
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 ) );
+ status = radio_get_hw_name_w(event.radio, &hw_name); + if (status != STATUS_SUCCESS) + { + ERR( "Failed to get hardware name for radio %p, status %#lx\n", (void *)event.radio.handle, status ); + return; + } + RtlInitUnicodeString( &string, name ); status = IoCreateDevice( driver_obj, sizeof( *device ), &string, FILE_DEVICE_BLUETOOTH, 0, FALSE, &device_obj ); @@ -127,6 +174,7 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added device->device_obj = device_obj; device->radio = event.radio; device->removed = FALSE; + device->hw_name = hw_name; InitializeListHead(&device->irp_list);
EnterCriticalSection( &device_list_cs ); @@ -276,9 +324,14 @@ static NTSTATUS query_id(const struct bluetooth_radio *ext, IRP *irp, BUS_QUERY_ TRACE( "(%p, %p, %s)\n", ext, irp, debugstr_BUS_QUERY_ID_TYPE( type ) ); switch (type) { + case BusQueryDeviceID: + append_id( &buf, L"WINEBTH\%s", ext->hw_name ); + break; case BusQueryInstanceID: append_id(&buf, L"%p", ext->radio); break; + case BusQueryHardwareIDs: + append_id( &buf, L"WINEBTH\%s", ext->hw_name ); case BusQueryCompatibleIDs: append_id( &buf, L"" ); break; @@ -320,6 +373,7 @@ static NTSTATUS WINAPI pdo_pnp( DEVICE_OBJECT *device_obj, IRP *irp ) case IRP_MN_REMOVE_DEVICE: assert( device->removed ); remove_pending_irps( device ); + free( device->hw_name ); winebluetooth_radio_free( device->radio ); IoDeleteDevice( device->device_obj ); ret = STATUS_SUCCESS;