-- v7: bluetoothapis/tests: Add tests for BluetoothFindNextDevice. bluetoothapis: Implement BluetoothFindNextDevice. bluetoothapis/tests: Add tests for BluetoothFindFirstDevice, BluetoothFindDeviceClose. bluetoothapis: Implement BluetoothFindFirstDevice and BluetoothFindDeviceClose.
From: Vibhav Pant vibhavp@gmail.com
A Bluetooth address consists of 6 bytes, while a BTH_ADDR is 8 bytes. --- dlls/bluetoothapis/main.c | 2 +- dlls/winebth.sys/winebth.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index 6cdc84f6b6f..87d530c846e 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -202,7 +202,7 @@ DWORD WINAPI BluetoothGetRadioInfo( HANDLE radio, PBLUETOOTH_RADIO_INFO info ) return GetLastError();
if (radio_info.localInfo.flags & BDIF_ADDRESS) - info->address.ullLong = RtlUlonglongByteSwap( radio_info.localInfo.address ); + info->address.ullLong = RtlUlonglongByteSwap( radio_info.localInfo.address ) >> 16; if (radio_info.localInfo.flags & BDIF_COD) info->ulClassofDevice = radio_info.localInfo.classOfDevice; if (radio_info.localInfo.flags & BDIF_NAME) diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index b47806de077..c3af6f9b95f 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -122,7 +122,7 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) if (ext->props_mask & WINEBLUETOOTH_RADIO_PROPERTY_ADDRESS) { info->localInfo.flags |= BDIF_ADDRESS; - info->localInfo.address = RtlUlonglongByteSwap( ext->props.address.ullLong ); + info->localInfo.address = RtlUlonglongByteSwap( ext->props.address.ullLong ) >> 16; } if (ext->props_mask & WINEBLUETOOTH_RADIO_PROPERTY_NAME) { @@ -190,7 +190,7 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS) { info->flags |= BDIF_ADDRESS; - info->address = RtlUlonglongByteSwap( device->props.address.ullLong ); + info->address = RtlUlonglongByteSwap( device->props.address.ullLong ) >> 16; } if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED && device->props.connected) @@ -421,7 +421,7 @@ static void update_bluetooth_radio_properties( struct winebluetooth_watcher_even if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_NAME) memcpy( device->props.name, event.props.name, sizeof( event.props.name )); if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_ADDRESS) - device->props.address.ullLong = RtlUlonglongByteSwap( event.props.address.ullLong ); + device->props.address.ullLong = event.props.address.ullLong; if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERABLE) device->props.discoverable = event.props.discoverable; if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_CONNECTABLE) @@ -721,7 +721,7 @@ static void bluetooth_radio_set_properties( DEVICE_OBJECT *obj, { if (mask & WINEBLUETOOTH_RADIO_PROPERTY_ADDRESS) { - BTH_ADDR addr = RtlUlonglongByteSwap( props->address.ullLong ); + BTH_ADDR addr = RtlUlonglongByteSwap( props->address.ullLong ) >> 16; IoSetDevicePropertyData( obj, &DEVPKEY_BluetoothRadio_Address, LOCALE_NEUTRAL, 0, DEVPROP_TYPE_UINT64, sizeof( addr ), &addr ); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 130 +++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 9 +++ dlls/winebth.sys/unixlib.h | 6 ++ dlls/winebth.sys/unixlib_priv.h | 1 + dlls/winebth.sys/winebluetooth.c | 10 +++ dlls/winebth.sys/winebth.c | 3 + dlls/winebth.sys/winebth_priv.h | 1 + include/wine/winebth.h | 2 + 8 files changed, 162 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 153c4e60ad1..6bd90008735 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -183,6 +183,39 @@ static const char *bluez_next_dict_entry( DBusMessageIter *iter, DBusMessageIter return name; }
+/* Adds an entry to a dict iterator of type {sv} */ +static BOOL bluez_variant_dict_add_entry( DBusMessageIter *dict, const char *key, int value_type, + const char *value_type_str, const void *value ) +{ + DBusMessageIter entry, variant; + + if (!p_dbus_message_iter_open_container( dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry )) return FALSE; + if (!p_dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING, &key )) + { + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + + if (!p_dbus_message_iter_open_container( &entry, DBUS_TYPE_VARIANT, value_type_str, &variant )) + { + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + if (!p_dbus_message_iter_append_basic( &variant, value_type, value )) + { + p_dbus_message_iter_abandon_container( &entry, &variant ); + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + if (!p_dbus_message_iter_close_container( &entry, &variant )) + { + p_dbus_message_iter_abandon_container( dict, &entry ); + return FALSE; + } + + return !!p_dbus_message_iter_close_container( dict, &entry ); +} + static const char *dbgstr_dbus_message( DBusMessage *message ) { const char *interface; @@ -329,6 +362,99 @@ static NTSTATUS bluez_dbus_send_and_wait_for_reply( DBusConnection *connection, return bluez_dbus_pending_call_wait( pending_call, reply, error ); }
+static NTSTATUS bluez_adapter_set_discovery_filter( void *connection, const char *adapter_path, + const char *transport_str ) +{ + DBusMessage *request, *reply; + DBusMessageIter iter, dict_iter; + DBusError error; + NTSTATUS status; + + TRACE( "(%p, %s, %s)\n", connection, debugstr_a( adapter_path ), debugstr_a( transport_str ) ); + + request = p_dbus_message_new_method_call( BLUEZ_DEST, adapter_path, BLUEZ_INTERFACE_ADAPTER, + "SetDiscoveryFilter" ); + if (!request) return STATUS_NO_MEMORY; + + p_dbus_message_iter_init_append( request, &iter ); + if (!p_dbus_message_iter_open_container( &iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter )) + { + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + if (!bluez_variant_dict_add_entry( &dict_iter, "Transport", DBUS_TYPE_STRING, + DBUS_TYPE_STRING_AS_STRING, &transport_str )) + { + p_dbus_message_iter_abandon_container( &iter, &dict_iter ); + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + if (!p_dbus_message_iter_close_container( &iter, &dict_iter )) + { + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + + p_dbus_error_init ( &error ); + + TRACE( "Setting discovery filter on %s to use transport %s\n", debugstr_a( adapter_path ), + debugstr_a( transport_str ) ); + status = bluez_dbus_send_and_wait_for_reply( connection, request, &reply, &error ); + if (status) + { + p_dbus_error_free( &error ); + return status; + } + if (!reply) + { + WARN( "Failed to set discovery filter: %s: %s\n", debugstr_a( error.name ), debugstr_a( error.message ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + p_dbus_error_free( &error ); + return status; + } + p_dbus_message_unref( reply ); + p_dbus_error_free( &error ); + + return STATUS_SUCCESS; + +} + +NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ) +{ + DBusMessage *request, *reply; + DBusError error; + NTSTATUS status; + + TRACE( "(%p, %s)\n", connection, debugstr_a( adapter_path ) ); + + status = bluez_adapter_set_discovery_filter( connection, adapter_path, "bredr" ); + if (status != STATUS_SUCCESS) return status; + + request = p_dbus_message_new_method_call( BLUEZ_DEST, adapter_path, BLUEZ_INTERFACE_ADAPTER, + "StartDiscovery" ); + if (!request) return STATUS_NO_MEMORY; + + TRACE( "Starting discovery on %s\n", debugstr_a( adapter_path ) ); + p_dbus_error_init( &error ); + status = bluez_dbus_send_and_wait_for_reply( connection, request, &reply, &error ); + if (status) + { + p_dbus_error_free( &error ); + return status; + } + if (!reply) + { + ERR( "Failed to start discovery on adapter %s: %s: %s", debugstr_a( adapter_path ), + debugstr_a( error.message ), debugstr_a( error.name ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + p_dbus_error_free( &error ); + return status; + } + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + return STATUS_SUCCESS; +} + NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ) { DBusMessage *request, *reply; @@ -1560,5 +1686,9 @@ NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_ { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ) +{ + return STATUS_NOT_SUPPORTED; +}
#endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index a80a51d9cf1..9ae1bf4022b 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -171,6 +171,14 @@ static NTSTATUS bluetooth_device_free( void *args ) return STATUS_SUCCESS; }
+static NTSTATUS bluetooth_adapter_start_discovery( void *args ) +{ + struct bluetooth_adapter_start_discovery_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_adapter_start_discovery( dbus_connection, params->adapter->str ); +} + static NTSTATUS bluetooth_get_event( void *args ) { struct bluetooth_get_event_params *params = args; @@ -186,6 +194,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = {
bluetooth_adapter_set_prop, bluetooth_adapter_get_unique_name, + bluetooth_adapter_start_discovery, bluetooth_adapter_free,
bluetooth_device_free, diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index 002cc2cc3aa..7de32fd38f0 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -70,6 +70,11 @@ struct bluetooth_adapter_set_prop_params union winebluetooth_property *prop; };
+struct bluetooth_adapter_start_discovery_params +{ + unix_name_t adapter; +}; + struct bluetooth_get_event_params { struct winebluetooth_event result; @@ -82,6 +87,7 @@ enum bluetoothapis_funcs
unix_bluetooth_adapter_set_prop, unix_bluetooth_adapter_get_unique_name, + unix_bluetooth_adapter_start_discovery, unix_bluetooth_adapter_free,
unix_bluetooth_device_free, diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 5146799e705..3dc7b956293 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -50,6 +50,7 @@ extern void bluez_dbus_free( void *connection ); extern NTSTATUS bluez_dbus_loop( void *connection, void *watcher_ctx, struct winebluetooth_event *result ); extern NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ); +extern NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ); extern NTSTATUS bluez_watcher_init( void *connection, void **ctx ); extern void bluez_watcher_close( void *connection, void *ctx ); #endif /* __WINE_WINEBTH_UNIXLIB_PRIV_H */ diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index 6ebfe55ac28..62ae685f55d 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -68,6 +68,16 @@ NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, return UNIX_BLUETOOTH_CALL( bluetooth_adapter_set_prop, ¶ms ); }
+NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio ) +{ + struct bluetooth_adapter_start_discovery_params params = {0}; + + TRACE( "(%p)\n", (void *)radio.handle ); + + params.adapter = radio.handle; + return UNIX_BLUETOOTH_CALL( bluetooth_adapter_start_discovery, ¶ms ); +} + void winebluetooth_radio_free( winebluetooth_radio_t radio ) { struct bluetooth_adapter_free_params args = { 0 }; diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index c3af6f9b95f..2dab1614644 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -251,6 +251,9 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) status = winebluetooth_radio_set_property( ext->radio, params->flag, &prop_value ); break; } + case IOCTL_WINEBTH_RADIO_START_DISCOVERY: + status = winebluetooth_radio_start_discovery( ext->radio ); + break; default: FIXME( "Unimplemented IOCTL code: %#lx\n", code ); break; diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index b50935c091c..a0d4e689e90 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -196,6 +196,7 @@ static inline BOOL winebluetooth_radio_equal( winebluetooth_radio_t r1, wineblue NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, ULONG prop_flag, union winebluetooth_property *property ); +NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio );
void winebluetooth_device_free( winebluetooth_device_t device ); static inline BOOL winebluetooth_device_equal( winebluetooth_device_t d1, winebluetooth_device_t d2 ) diff --git a/include/wine/winebth.h b/include/wine/winebth.h index c26a2100fb9..222d780e10d 100644 --- a/include/wine/winebth.h +++ b/include/wine/winebth.h @@ -25,6 +25,8 @@ /* Set the discoverability or connectable flag for a local radio. Enabling discoverability will also enable incoming * connections, while disabling incoming connections disables discoverability as well. */ #define IOCTL_WINEBTH_RADIO_SET_FLAG CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa3, METHOD_BUFFERED, FILE_ANY_ACCESS) +/* Start device inquiry for a local radio. */ +#define IOCTL_WINEBTH_RADIO_START_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa6, METHOD_BUFFERED, FILE_ANY_ACCESS)
#include <pshpack1.h>
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 37 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 9 ++++++++ dlls/winebth.sys/unixlib.h | 6 ++++++ dlls/winebth.sys/unixlib_priv.h | 1 + dlls/winebth.sys/winebluetooth.c | 9 ++++++++ dlls/winebth.sys/winebth.c | 3 +++ dlls/winebth.sys/winebth_priv.h | 1 + include/wine/winebth.h | 2 ++ 8 files changed, 68 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 6bd90008735..383fd74187d 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -455,6 +455,39 @@ NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_pa return STATUS_SUCCESS; }
+NTSTATUS bluez_adapter_stop_discovery( void *connection, const char *adapter_path ) +{ + DBusMessage *request, *reply; + DBusError error; + NTSTATUS status; + + TRACE( "(%p, %s)\n", connection, debugstr_a( adapter_path ) ); + + request = p_dbus_message_new_method_call( BLUEZ_DEST, adapter_path, BLUEZ_INTERFACE_ADAPTER, + "StopDiscovery" ); + if (!request) return STATUS_NO_MEMORY; + + TRACE( "Stopping discovery on %s\n", debugstr_a( adapter_path ) ); + p_dbus_error_init( &error ); + status = bluez_dbus_send_and_wait_for_reply( connection, request, &reply, &error ); + if (status) + { + p_dbus_error_free( &error ); + return status; + } + if (!reply) + { + ERR( "Failed to stop discovery on adapter %s: %s: %s", debugstr_a( adapter_path ), + debugstr_a( error.message ), debugstr_a( error.name ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + p_dbus_error_free( &error ); + return status; + } + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + return STATUS_SUCCESS; +} + NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ) { DBusMessage *request, *reply; @@ -1690,5 +1723,9 @@ NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_pa { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_adapter_stop_discovery( void *connection, const char *adapter_path ) +{ + return STATUS_NOT_SUPPORTED; +}
#endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index 9ae1bf4022b..88f6c6164d3 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -179,6 +179,14 @@ static NTSTATUS bluetooth_adapter_start_discovery( void *args ) return bluez_adapter_start_discovery( dbus_connection, params->adapter->str ); }
+static NTSTATUS bluetooth_adapter_stop_discovery( void *args ) +{ + struct bluetooth_adapter_stop_discovery_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_adapter_stop_discovery( dbus_connection, params->adapter->str ); +} + static NTSTATUS bluetooth_get_event( void *args ) { struct bluetooth_get_event_params *params = args; @@ -195,6 +203,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_adapter_set_prop, bluetooth_adapter_get_unique_name, bluetooth_adapter_start_discovery, + bluetooth_adapter_stop_discovery, bluetooth_adapter_free,
bluetooth_device_free, diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index 7de32fd38f0..732c76f7d64 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -75,6 +75,11 @@ struct bluetooth_adapter_start_discovery_params unix_name_t adapter; };
+struct bluetooth_adapter_stop_discovery_params +{ + unix_name_t adapter; +}; + struct bluetooth_get_event_params { struct winebluetooth_event result; @@ -88,6 +93,7 @@ enum bluetoothapis_funcs unix_bluetooth_adapter_set_prop, unix_bluetooth_adapter_get_unique_name, unix_bluetooth_adapter_start_discovery, + unix_bluetooth_adapter_stop_discovery, unix_bluetooth_adapter_free,
unix_bluetooth_device_free, diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 3dc7b956293..60570a2413a 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -51,6 +51,7 @@ extern NTSTATUS bluez_dbus_loop( void *connection, void *watcher_ctx, struct win extern NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_prop_params *params ); extern NTSTATUS bluez_adapter_start_discovery( void *connection, const char *adapter_path ); +extern NTSTATUS bluez_adapter_stop_discovery( void *connection, const char *adapter_path ); extern NTSTATUS bluez_watcher_init( void *connection, void **ctx ); extern void bluez_watcher_close( void *connection, void *ctx ); #endif /* __WINE_WINEBTH_UNIXLIB_PRIV_H */ diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index 62ae685f55d..370f102d6f3 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -78,6 +78,15 @@ NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio ) return UNIX_BLUETOOTH_CALL( bluetooth_adapter_start_discovery, ¶ms ); }
+NTSTATUS winebluetooth_radio_stop_discovery( winebluetooth_radio_t radio ) +{ + struct bluetooth_adapter_stop_discovery_params params = {0}; + + TRACE( "(%p)\n", (void *)radio.handle ); + params.adapter = radio.handle; + return UNIX_BLUETOOTH_CALL(bluetooth_adapter_stop_discovery, ¶ms); +} + void winebluetooth_radio_free( winebluetooth_radio_t radio ) { struct bluetooth_adapter_free_params args = { 0 }; diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 2dab1614644..94aa2869b72 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -254,6 +254,9 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) case IOCTL_WINEBTH_RADIO_START_DISCOVERY: status = winebluetooth_radio_start_discovery( ext->radio ); break; + case IOCTL_WINEBTH_RADIO_STOP_DISCOVERY: + status = winebluetooth_radio_stop_discovery( ext->radio ); + break; default: FIXME( "Unimplemented IOCTL code: %#lx\n", code ); break; diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index a0d4e689e90..e664043eb63 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -197,6 +197,7 @@ NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, ULONG prop_flag, union winebluetooth_property *property ); NTSTATUS winebluetooth_radio_start_discovery( winebluetooth_radio_t radio ); +NTSTATUS winebluetooth_radio_stop_discovery( winebluetooth_radio_t radio );
void winebluetooth_device_free( winebluetooth_device_t device ); static inline BOOL winebluetooth_device_equal( winebluetooth_device_t d1, winebluetooth_device_t d2 ) diff --git a/include/wine/winebth.h b/include/wine/winebth.h index 222d780e10d..d05e4cad529 100644 --- a/include/wine/winebth.h +++ b/include/wine/winebth.h @@ -27,6 +27,8 @@ #define IOCTL_WINEBTH_RADIO_SET_FLAG CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa3, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Start device inquiry for a local radio. */ #define IOCTL_WINEBTH_RADIO_START_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa6, METHOD_BUFFERED, FILE_ANY_ACCESS) +/* Stop device inquiry for a local radio. */ +#define IOCTL_WINEBTH_RADIO_STOP_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa7, METHOD_BUFFERED, FILE_ANY_ACCESS)
#include <pshpack1.h>
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/main.c | 207 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 198 insertions(+), 9 deletions(-)
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index 87d530c846e..aea03c023ca 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -48,15 +48,193 @@ struct bluetooth_find_radio_handle DWORD idx; };
+struct bluetooth_find_device_handle +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS params; + BTH_DEVICE_INFO_LIST *device_list; + SIZE_T idx; +}; + +static const char *debugstr_BLUETOOTH_DEVICE_SEARCH_PARAMS( const BLUETOOTH_DEVICE_SEARCH_PARAMS *params ) +{ + if (!params || params->dwSize != sizeof( *params )) + return wine_dbg_sprintf("%p", params ); + + return wine_dbg_sprintf( "{ %ld %d %d %d %d %d %u %p }", params->dwSize, params->fReturnAuthenticated, + params->fReturnRemembered, params->fReturnUnknown, params->fReturnConnected, + params->fIssueInquiry, (UINT)params->cTimeoutMultiplier, params->hRadio ); +} + +static BOOL radio_set_inquiry( HANDLE radio, BOOL enable ) +{ + DWORD bytes; + + return DeviceIoControl( radio, enable ? IOCTL_WINEBTH_RADIO_START_DISCOVERY : IOCTL_WINEBTH_RADIO_STOP_DISCOVERY, + NULL, 0, NULL, 0, &bytes, NULL ); +} + +static BOOL radio_get_devices( HANDLE radio, BTH_DEVICE_INFO_LIST **devices ) +{ + BTH_DEVICE_INFO_LIST *list; + BOOL success; + DWORD bytes, size; + void *ptr; + + list = malloc( sizeof( *list ) ); + if (!list) + { + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + + success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, sizeof( *list ), &bytes, + NULL ); + if (!success) + { + free( list ); + return FALSE; + } + if (!list->numOfDevices) + { + free( list ); + SetLastError( ERROR_NO_MORE_ITEMS ); + return FALSE; + } + if (list->numOfDevices == 1) + { + *devices = list; + return TRUE; + } + + size = sizeof( *list ) + (list->numOfDevices - 1) * sizeof( list->deviceList[0] ); + ptr = realloc( list, size ); + if (!ptr) + { + free( list ); + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + list = ptr; + success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, size, &bytes, NULL ); + if (!success) + { + free( list ); + return FALSE; + } + *devices = list; + return TRUE; +} + +static void device_info_from_bth_info( BLUETOOTH_DEVICE_INFO *info, const BTH_DEVICE_INFO *bth_info ) +{ + memset( info, 0, sizeof( *info )); + info->dwSize = sizeof( *info ); + + if (bth_info->flags & BDIF_ADDRESS) + info->Address.ullLong = bth_info->address; + info->ulClassofDevice = bth_info->classOfDevice; + info->fConnected = !!(bth_info->flags & BDIF_CONNECTED); + info->fRemembered = !!(bth_info->flags & BDIF_PERSONAL); + info->fAuthenticated = !!(bth_info->flags & BDIF_PAIRED); + + if (bth_info->flags & BDIF_NAME) + MultiByteToWideChar( CP_ACP, 0, bth_info->name, -1, info->szName, ARRAY_SIZE( info->szName ) ); +} + +static BOOL device_find_set_next( struct bluetooth_find_device_handle *find, BLUETOOTH_DEVICE_INFO *info ) +{ + while (find->idx < find->device_list->numOfDevices) + { + const BTH_DEVICE_INFO *bth_info; + BOOL matches; + + bth_info = &find->device_list->deviceList[find->idx++]; + matches = (find->params.fReturnAuthenticated && bth_info->flags & BDIF_PAIRED) || + (find->params.fReturnRemembered && bth_info->flags & BDIF_PERSONAL) || + (find->params.fReturnUnknown && !(bth_info->flags & BDIF_PERSONAL)) || + (find->params.fReturnConnected && bth_info->flags & BDIF_CONNECTED); + + if (!matches) + continue; + + device_info_from_bth_info( info, bth_info ); + /* If the user is looking for unknown devices as part of device inquiry, or wants connected devices, + * we can set stLastSeen to the current UTC time. */ + if ((find->params.fIssueInquiry && find->params.fReturnUnknown && !info->fRemembered) + || (find->params.fReturnConnected && info->fConnected)) + GetSystemTime( &info->stLastSeen ); + else + FIXME( "semi-stub!\n" ); + return TRUE; + } + + return FALSE; +} + /********************************************************************* * BluetoothFindFirstDevice */ -HBLUETOOTH_DEVICE_FIND WINAPI BluetoothFindFirstDevice(BLUETOOTH_DEVICE_SEARCH_PARAMS *params, - BLUETOOTH_DEVICE_INFO *info) +HBLUETOOTH_DEVICE_FIND WINAPI BluetoothFindFirstDevice( BLUETOOTH_DEVICE_SEARCH_PARAMS *params, + BLUETOOTH_DEVICE_INFO *info ) { - FIXME("(%p %p): stub!\n", params, info); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return NULL; + struct bluetooth_find_device_handle *hfind; + BTH_DEVICE_INFO_LIST *device_list; + BOOL success; + + TRACE( "(%s %p)\n", debugstr_BLUETOOTH_DEVICE_SEARCH_PARAMS( params ), info ); + + if (!params || !info) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + if (params->dwSize != sizeof( *params ) || info->dwSize != sizeof( *info )) + { + SetLastError( ERROR_REVISION_MISMATCH ); + return NULL; + } + if (params->fIssueInquiry && params->cTimeoutMultiplier > 48) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + if (!params->hRadio) + { + /* TODO: Perform device inquiry on all local radios */ + FIXME( "semi-stub!\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + + if (!radio_set_inquiry( params->hRadio, TRUE )) + return NULL; + Sleep( params->cTimeoutMultiplier * 1280 ); + radio_set_inquiry( params->hRadio, FALSE ); + + success = radio_get_devices( params->hRadio, &device_list ); + if (!success) + return NULL; + + hfind = malloc( sizeof( *hfind ) ); + if (!hfind) + { + free( device_list ); + SetLastError( ERROR_OUTOFMEMORY ); + return NULL; + } + + memcpy( hfind, params, sizeof( *params ) ); + hfind->device_list = device_list; + hfind->idx = 0; + if (!device_find_set_next( hfind, info )) + { + free( hfind->device_list ); + free( hfind ); + SetLastError( ERROR_NO_MORE_ITEMS ); + return NULL; + } + SetLastError( ERROR_SUCCESS ); + return hfind; }
/********************************************************************* @@ -130,11 +308,22 @@ BOOL WINAPI BluetoothFindRadioClose( HBLUETOOTH_RADIO_FIND find_handle ) /********************************************************************* * BluetoothFindDeviceClose */ -BOOL WINAPI BluetoothFindDeviceClose(HBLUETOOTH_DEVICE_FIND find) +BOOL WINAPI BluetoothFindDeviceClose( HBLUETOOTH_DEVICE_FIND find_handle ) { - FIXME("(%p): stub!\n", find); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct bluetooth_find_device_handle *find = find_handle; + + TRACE( "(%p)\n", find_handle ); + + if (!find_handle) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + + free( find->device_list ); + free( find ); + SetLastError( ERROR_SUCCESS ); + return TRUE; }
/*********************************************************************
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/Makefile.in | 1 + dlls/bluetoothapis/tests/device.c | 109 +++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 dlls/bluetoothapis/tests/device.c
diff --git a/dlls/bluetoothapis/tests/Makefile.in b/dlls/bluetoothapis/tests/Makefile.in index c7d6567f578..5d01bf3a809 100644 --- a/dlls/bluetoothapis/tests/Makefile.in +++ b/dlls/bluetoothapis/tests/Makefile.in @@ -2,5 +2,6 @@ TESTDLL = bluetoothapis.dll IMPORTS = bluetoothapis
SOURCES = \ + device.c \ radio.c \ sdp.c diff --git a/dlls/bluetoothapis/tests/device.c b/dlls/bluetoothapis/tests/device.c new file mode 100644 index 00000000000..31f25953c78 --- /dev/null +++ b/dlls/bluetoothapis/tests/device.c @@ -0,0 +1,109 @@ +/* + * Tests for Bluetooth device methods + * + * Copyright 2025 Vibhav Pant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#include <windef.h> +#include <winbase.h> + +#include <bthsdpdef.h> +#include <bluetoothapis.h> + +#include <wine/test.h> + +extern void test_for_all_radios( void (*test)( HANDLE radio, void *data ), void *data ); + +void test_radio_BluetoothFindFirstDevice( HANDLE radio, void *data ) +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS search_params; + BLUETOOTH_DEVICE_INFO device_info; + HBLUETOOTH_DEVICE_FIND hfind; + DWORD err, exp; + BOOL success; + + search_params.dwSize = sizeof( search_params ); + search_params.cTimeoutMultiplier = 200; + search_params.fIssueInquiry = TRUE; + search_params.fReturnUnknown = TRUE; + search_params.hRadio = radio; + device_info.dwSize = sizeof( device_info ); + SetLastError( 0xdeadbeef ); + hfind = BluetoothFindFirstDevice( &search_params, &device_info ); + ok( !hfind, "Expected %p to be NULL\n", hfind ); + err = GetLastError(); + ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER ); + + search_params.cTimeoutMultiplier = 5; + SetLastError( 0xdeadbeef ); + hfind = BluetoothFindFirstDevice( &search_params, &device_info ); + err = GetLastError(); + exp = hfind ? ERROR_SUCCESS : ERROR_NO_MORE_ITEMS; + todo_wine_if( !radio ) ok( err == exp, "%lu != %lu\n", err, exp ); + + if (hfind) + { + success = BluetoothFindDeviceClose( hfind ); + ok( success, "BluetoothFindDeviceClose failed: %lu\n", GetLastError() ); + } +} + +void test_BluetoothFindFirstDevice( void ) +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS search_params = {0}; + BLUETOOTH_DEVICE_INFO device_info = {0}; + HBLUETOOTH_DEVICE_FIND hfind; + DWORD err; + + SetLastError( 0xdeadbeef ); + hfind = BluetoothFindFirstDevice( NULL, NULL ); + ok( !hfind, "Expected %p to be NULL\n", hfind ); + err = GetLastError(); + ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER ); + + SetLastError( 0xdeadbeef ); + hfind = BluetoothFindFirstDevice( &search_params, NULL ); + ok( !hfind, "Expected %p to be NULL\n", hfind ); + err = GetLastError(); + ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER ); + + SetLastError( 0xdeadbeef ); + hfind = BluetoothFindFirstDevice( &search_params, &device_info ); + ok( !hfind, "Expected %p to be NULL\n", hfind ); + err = GetLastError(); + ok( err == ERROR_REVISION_MISMATCH, "%lu != %d\n", err, ERROR_REVISION_MISMATCH ); + + test_for_all_radios( test_radio_BluetoothFindFirstDevice, NULL ); +} + +void test_BluetoothFindDeviceClose( void ) +{ + DWORD err; + + SetLastError( 0xdeadbeef ); + ok( !BluetoothFindDeviceClose( NULL ), "Expected BluetoothFindDeviceClose to return FALSE\n" ); + err = GetLastError(); + ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); +} + +START_TEST( device ) +{ + test_BluetoothFindFirstDevice(); + test_BluetoothFindDeviceClose(); +}
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/main.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index aea03c023ca..aaf55ae88fb 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -598,11 +598,24 @@ BOOL WINAPI BluetoothEnableDiscovery( HANDLE radio, BOOL enabled ) /********************************************************************* * BluetoothFindNextDevice */ -BOOL WINAPI BluetoothFindNextDevice(HBLUETOOTH_DEVICE_FIND find, BLUETOOTH_DEVICE_INFO *info) +BOOL WINAPI BluetoothFindNextDevice( HBLUETOOTH_DEVICE_FIND find, BLUETOOTH_DEVICE_INFO *info ) { - FIXME("(%p, %p): stub!\n", find, info); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + BOOL success; + + TRACE( "(%p, %p)\n", find, info ); + + /* This method doesn't perform any validation for info, for some reason. */ + if (!find) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + + success = device_find_set_next( find, info ); + if (!success) + SetLastError( ERROR_NO_MORE_ITEMS ); + + return success; }
/*********************************************************************
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/device.c | 76 +++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)
diff --git a/dlls/bluetoothapis/tests/device.c b/dlls/bluetoothapis/tests/device.c index 31f25953c78..7f3fbcd6f14 100644 --- a/dlls/bluetoothapis/tests/device.c +++ b/dlls/bluetoothapis/tests/device.c @@ -22,6 +22,7 @@
#include <windef.h> #include <winbase.h> +#include <winnls.h>
#include <bthsdpdef.h> #include <bluetoothapis.h> @@ -92,6 +93,80 @@ void test_BluetoothFindFirstDevice( void ) test_for_all_radios( test_radio_BluetoothFindFirstDevice, NULL ); }
+void test_radio_BluetoothFindNextDevice( HANDLE radio, void *data ) +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS search_params = *(BLUETOOTH_DEVICE_SEARCH_PARAMS *)data; + BLUETOOTH_DEVICE_INFO info = {0}; + HBLUETOOTH_DEVICE_FIND hfind; + BOOL success; + DWORD err, i = 0; + + search_params.hRadio = radio; + info.dwSize = sizeof( info ); + + SetLastError( 0xdeadbeef ); + hfind = BluetoothFindFirstDevice( &search_params, &info ); + err = GetLastError(); + ok( !!hfind || err == ERROR_NO_MORE_ITEMS, "BluetoothFindFirstDevice failed: %lu\n", GetLastError() ); + if (!hfind) + { + skip( "No devices found.\n" ); + return; + } + + for (;;) + { + const BYTE *addr = info.Address.rgBytes; + WCHAR buf[256]; + + ok( info.fConnected == search_params.fReturnConnected, "%d != %d\n", info.fConnected, + search_params.fReturnConnected ); + ok( info.fAuthenticated == search_params.fReturnAuthenticated, "%d != %d\n", info.fAuthenticated, + search_params.fReturnAuthenticated ); + ok( info.fRemembered == search_params.fReturnRemembered, "%d != %d\n", + info.fRemembered, search_params.fReturnRemembered ); + + trace( "device %lu: %02x:%02x:%02x:%02x:%02x:%02x\n", i, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] ); + trace( " name: %s\n", debugstr_w( info.szName ) ); + trace( " class: %#lx\n", info.ulClassofDevice ); + trace( " connected: %d, authenticated: %d, remembered: %d\n", info.fConnected, info.fAuthenticated, + info.fRemembered ); + if (GetTimeFormatEx( NULL, TIME_FORCE24HOURFORMAT, &info.stLastSeen, NULL, buf, ARRAY_SIZE( buf ) )) + trace( " last seen: %s UTC\n", debugstr_w( buf ) ); + + memset( &info, 0, sizeof( info )); + info.dwSize = sizeof( info ); + SetLastError( 0xdeadbeef ); + success = BluetoothFindNextDevice( hfind, &info ); + err = GetLastError(); + ok( success || err == ERROR_NO_MORE_ITEMS, "BluetoothFindNextDevice failed: %lu\n", GetLastError() ); + if (!success) + break; + } + + ok( BluetoothFindDeviceClose( hfind ), "BluetoothFindDeviceClose failed: %lu\n", GetLastError() ); +} + +void test_BluetoothFindNextDevice( void ) +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS params = {0}; + DWORD err; + BOOL ret; + + SetLastError( 0xdeadbeef ); + ret = BluetoothFindNextDevice( NULL, NULL ); + ok( !ret, "Expected BluetoothFindNextDevice to return FALSE\n" ); + err = GetLastError(); + ok( err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE ); + + params.dwSize = sizeof( params ); + params.fIssueInquiry = TRUE; + params.fReturnUnknown = TRUE; + params.cTimeoutMultiplier = 5; + + test_for_all_radios( test_radio_BluetoothFindNextDevice, ¶ms ); +} + void test_BluetoothFindDeviceClose( void ) { DWORD err; @@ -106,4 +181,5 @@ START_TEST( device ) { test_BluetoothFindFirstDevice(); test_BluetoothFindDeviceClose(); + test_BluetoothFindNextDevice(); }
v3: Correctly match enumerated devices against `BLUETOOTH_DEVICE_SEARCH_PARAMS` flags.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/tests/device.c:
- DWORD err, exp;
- BOOL success;
- search_params.dwSize = sizeof( search_params );
- search_params.cTimeoutMultiplier = 200;
- search_params.fIssueInquiry = TRUE;
- search_params.fReturnUnknown = TRUE;
- search_params.hRadio = radio;
- device_info.dwSize = sizeof( device_info );
- SetLastError( 0xdeadbeef );
- hfind = BluetoothFindFirstDevice( &search_params, &device_info );
- ok( !hfind, "Expected %p to be NULL\n", hfind );
- err = GetLastError();
- ok( err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER );
- search_params.cTimeoutMultiplier = 5;
Isn't this going to always wait for 6 seconds? Maybe we should guard this behind winetest_interactive or something.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
DWORD idx;
};
+struct bluetooth_find_device_handle
Calling this a "handle" seems odd when it *is* the thing the handle points to.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
- Sleep( params->cTimeoutMultiplier * 1280 );
- radio_set_inquiry( params->hRadio, FALSE );
- success = radio_get_devices( params->hRadio, &device_list );
- if (!success)
return NULL;
- hfind = malloc( sizeof( *hfind ) );
- if (!hfind)
- {
free( device_list );
SetLastError( ERROR_OUTOFMEMORY );
return NULL;
- }
- memcpy( hfind, params, sizeof( *params ) );
Don't memcpy between two structures of different types when you can memcpy to the member ("&hfind->params"), that's unnecessarily fragile and opaque. Better yet, don't memcpy at all but just perform a structure assignment.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
+{
- memset( info, 0, sizeof( *info ));
- info->dwSize = sizeof( *info );
- if (bth_info->flags & BDIF_ADDRESS)
info->Address.ullLong = bth_info->address;
- info->ulClassofDevice = bth_info->classOfDevice;
- info->fConnected = !!(bth_info->flags & BDIF_CONNECTED);
- info->fRemembered = !!(bth_info->flags & BDIF_PERSONAL);
- info->fAuthenticated = !!(bth_info->flags & BDIF_PAIRED);
- if (bth_info->flags & BDIF_NAME)
MultiByteToWideChar( CP_ACP, 0, bth_info->name, -1, info->szName, ARRAY_SIZE( info->szName ) );
+}
+static BOOL device_find_set_next( struct bluetooth_find_device_handle *find, BLUETOOTH_DEVICE_INFO *info )
I'm having a bit of trouble parsing this name, perhaps just "find_next"?
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
- hfind = malloc( sizeof( *hfind ) );
- if (!hfind)
- {
free( device_list );
SetLastError( ERROR_OUTOFMEMORY );
return NULL;
- }
- memcpy( hfind, params, sizeof( *params ) );
- hfind->device_list = device_list;
- hfind->idx = 0;
- if (!device_find_set_next( hfind, info ))
- {
free( hfind->device_list );
free( hfind );
SetLastError( ERROR_NO_MORE_ITEMS );
Since BluetoothFindNextDevice() returns the same error we could just factor this in.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
return wine_dbg_sprintf("%p", params );
- return wine_dbg_sprintf( "{ %ld %d %d %d %d %d %u %p }", params->dwSize, params->fReturnAuthenticated,
params->fReturnRemembered, params->fReturnUnknown, params->fReturnConnected,
params->fIssueInquiry, (UINT)params->cTimeoutMultiplier, params->hRadio );
+}
+static BOOL radio_set_inquiry( HANDLE radio, BOOL enable ) +{
- DWORD bytes;
- return DeviceIoControl( radio, enable ? IOCTL_WINEBTH_RADIO_START_DISCOVERY : IOCTL_WINEBTH_RADIO_STOP_DISCOVERY,
NULL, 0, NULL, 0, &bytes, NULL );
+}
+static BOOL radio_get_devices( HANDLE radio, BTH_DEVICE_INFO_LIST **devices )
We could return the list here instead of a boolean, making this function a little tighter.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
+struct bluetooth_find_device_handle +{
- BLUETOOTH_DEVICE_SEARCH_PARAMS params;
- BTH_DEVICE_INFO_LIST *device_list;
- SIZE_T idx;
+};
+static const char *debugstr_BLUETOOTH_DEVICE_SEARCH_PARAMS( const BLUETOOTH_DEVICE_SEARCH_PARAMS *params ) +{
- if (!params || params->dwSize != sizeof( *params ))
return wine_dbg_sprintf("%p", params );
- return wine_dbg_sprintf( "{ %ld %d %d %d %d %d %u %p }", params->dwSize, params->fReturnAuthenticated,
params->fReturnRemembered, params->fReturnUnknown, params->fReturnConnected,
params->fIssueInquiry, (UINT)params->cTimeoutMultiplier, params->hRadio );
You shouldn't need to cast any format strings. %u works for UCHAR without the cast here.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
- if (list->numOfDevices == 1)
- {
*devices = list;
return TRUE;
- }
- size = sizeof( *list ) + (list->numOfDevices - 1) * sizeof( list->deviceList[0] );
- ptr = realloc( list, size );
- if (!ptr)
- {
free( list );
SetLastError( ERROR_OUTOFMEMORY );
return FALSE;
- }
- list = ptr;
- success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, size, &bytes, NULL );
Can't the number of devices change between the two calls? I would assume we don't want to fail in that case; we should probably be performing a loop.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
+{
- BTH_DEVICE_INFO_LIST *list;
- BOOL success;
- DWORD bytes, size;
- void *ptr;
- list = malloc( sizeof( *list ) );
- if (!list)
- {
SetLastError( ERROR_OUTOFMEMORY );
return FALSE;
- }
- success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, sizeof( *list ), &bytes,
NULL );
- if (!success)
As usual I'm going to go no further than a recommendation made when bikeshedding, but the way this line is wrapped seems unnecessarily ugly. Also, the use of a temporary boolean variable (as well as very frequently in other places in the code) instead of just putting the expression inside the if strikes me as wasting space.
Also, do we actually need to pass input here? It looks wrong, and Microsoft's bthioctl.h suggests we don't. The MSDN documentation for this suggests otherwise, but I think that's a side effect of it being written for drivers, where buffered ioctls basically overload the same pointer to refer to the input and output length.
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
return FALSE;
- }
- success = DeviceIoControl( radio, IOCTL_BTH_GET_DEVICE_INFO, list, sizeof( *list ), list, sizeof( *list ), &bytes,
NULL );
- if (!success)
- {
free( list );
return FALSE;
- }
- if (!list->numOfDevices)
- {
free( list );
SetLastError( ERROR_NO_MORE_ITEMS );
return FALSE;
- }
Do we even need this special case? If we changed the next line to "<= 1" wouldn't it work as-is?
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
- {
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
- }
- if (!params->hRadio)
- {
/* TODO: Perform device inquiry on all local radios */
FIXME( "semi-stub!\n" );
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
- }
- if (!radio_set_inquiry( params->hRadio, TRUE ))
return NULL;
- Sleep( params->cTimeoutMultiplier * 1280 );
- radio_set_inquiry( params->hRadio, FALSE );
Not familiar with the implementation, but is this part not supposed to be guarded out by fIssueInquiry?
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/main.c:
- BOOL success;
- TRACE( "(%p, %p)\n", find, info );
- /* This method doesn't perform any validation for info, for some reason. */
- if (!find)
- {
SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
- }
- success = device_find_set_next( find, info );
- if (!success)
SetLastError( ERROR_NO_MORE_ITEMS );
- return success;
Other functions seem to explicitly SetLastError( ERROR_SUCCESS ), should we be doing that here too?
Elizabeth Figura (@zfigura) commented about dlls/bluetoothapis/tests/device.c:
test_for_all_radios( test_radio_BluetoothFindFirstDevice, NULL );
}
+void test_radio_BluetoothFindNextDevice( HANDLE radio, void *data )
Why do this with a separate function instead of inside test_radio_BluetoothFindFirstDevice()?