Implement `BluetoothSendAuthenticationResponseEx` over the `IOCTL_WINEBTH_RADIO_SEND_AUTH_RESPONSE` command in winebth.sys.
From: Vibhav Pant vibhavp@gmail.com
If BlueZ calls the "Cancel" method on the pairing agent object registered by the driver, mark the currently active authentication request as canceled. --- dlls/winebth.sys/dbus.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index a1d27c32ac0..fae5394a1e2 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -956,6 +956,21 @@ static DBusHandlerResult bluez_auth_agent_vtable_message_handler( DBusConnection
return DBUS_HANDLER_RESULT_HANDLED; } + if (p_dbus_message_is_method_call( message, BLUEZ_INTERFACE_AGENT, "Cancel" )) + { + pthread_mutex_lock( &ctx->lock ); + if (ctx->status == BLUEZ_PAIRING_SESSION_INCOMING || ctx->status == BLUEZ_PAIRING_SESSION_PENDING_REPLY) + { + TRACE( "Cancelling authentication request from device %s\n", debugstr_a( ctx->device->str ) ); + ctx->status = BLUEZ_PAIRING_SESSION_CANCELLED; + unix_name_free( ctx->device ); + p_dbus_message_unref( ctx->auth_request ); + p_dbus_connection_free_preallocated_send( ctx->connection, ctx->preallocate_send ); + p_dbus_connection_unref( ctx->connection ); + } + pthread_mutex_unlock( &ctx->lock ); + reply = p_dbus_message_new_method_return( message ); + } else { FIXME( "Unsupported method call: %s\n", debugstr_a( p_dbus_message_get_member( message ) ) );
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 58 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 10 ++++++ dlls/winebth.sys/unixlib.h | 10 ++++++ dlls/winebth.sys/unixlib_priv.h | 3 ++ dlls/winebth.sys/winebluetooth.c | 15 +++++++++ dlls/winebth.sys/winebth.c | 45 +++++++++++++++++++++++++ dlls/winebth.sys/winebth_priv.h | 3 ++ include/wine/winebth.h | 21 +++++++++--- 8 files changed, 160 insertions(+), 5 deletions(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index fae5394a1e2..4a86cb4cbb4 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -1138,6 +1138,58 @@ NTSTATUS bluez_auth_agent_request_default( void *connection ) return STATUS_SUCCESS; }
+NTSTATUS bluez_auth_agent_send_response( void *auth_agent, struct unix_name *device, + BLUETOOTH_AUTHENTICATION_METHOD method, UINT32 numeric_or_passkey, + BOOL negative, BOOL *authenticated ) +{ + struct bluez_auth_agent_ctx *ctx = auth_agent; + NTSTATUS ret; + + TRACE( "auth_agent=%p device=%s negative=%d\n", auth_agent, debugstr_a( device->str ), negative ); + + pthread_mutex_lock( &ctx->lock ); + switch (ctx->status) + { + case BLUEZ_PAIRING_SESSION_PENDING_REPLY: + { + DBusMessage *reply; + if (device != ctx->device) + { + ret = STATUS_DEVICE_NOT_CONNECTED; + goto done; + } + if (numeric_or_passkey != ctx->passkey || method != ctx->method) + negative = TRUE; + + reply = negative ? p_dbus_message_new_error( ctx->auth_request, "org.bluez.Rejected", "" ) + : p_dbus_message_new_method_return( ctx->auth_request ); + if (!reply) + { + ret = STATUS_NO_MEMORY; + goto done; + } + p_dbus_connection_send_preallocated( ctx->connection, ctx->preallocate_send, reply, NULL ); + + unix_name_free( ctx->device ); + p_dbus_message_unref( ctx->auth_request ); + p_dbus_connection_unref( ctx->connection ); + ctx->status = BLUEZ_PAIRING_SESSION_NONE; + *authenticated = !negative; + ret = STATUS_SUCCESS; + break; + } + case BLUEZ_PAIRING_SESSION_CANCELLED: + ret = STATUS_CANCELLED; + break; + default: + ret = STATUS_DEVICE_NOT_READY; + break; + } +done: + pthread_mutex_unlock( &ctx->lock ); + return ret; +} + struct bluez_watcher_event { struct list entry; @@ -2052,5 +2104,11 @@ NTSTATUS bluez_adapter_stop_discovery( void *connection, const char *adapter_pat NTSTATUS bluez_auth_agent_start( void *connection, void **ctx ) { return STATUS_NOT_SUPPORTED; } NTSTATUS bluez_auth_agent_stop( void *connection, void *ctx ) { return STATUS_NOT_SUPPORTED; } NTSTATUS bluez_auth_agent_request_default( void *connection ) { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_auth_agent_send_response( void *auth_agent, struct unix_name *device, + BLUETOOTH_AUTHENTICATION_METHOD method, UINT32 numeric_or_passkey, + BOOL negative, BOOL *authenticated ) +{ + return STATUS_NOT_SUPPORTED; +}
#endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index 7b3edaad61a..e9c4010b047 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -214,6 +214,15 @@ static NTSTATUS bluetooth_auth_agent_enable_incoming( void *args ) return bluez_auth_agent_request_default( dbus_connection ); }
+static NTSTATUS bluetooth_auth_send_response( void *args ) +{ + struct bluetooth_auth_send_response_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + return bluez_auth_agent_send_response( bluetooth_auth_agent, params->device, params->method, + params->numeric_or_passkey, params->negative, params->authenticated ); +} + static NTSTATUS bluetooth_get_event( void *args ) { struct bluetooth_get_event_params *params = args; @@ -236,6 +245,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_device_free,
bluetooth_auth_agent_enable_incoming, + bluetooth_auth_send_response,
bluetooth_get_event, }; diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index c9630fe6676..bc963f48c98 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -80,6 +80,15 @@ struct bluetooth_adapter_stop_discovery_params unix_name_t adapter; };
+struct bluetooth_auth_send_response_params +{ + unix_name_t device; + BLUETOOTH_AUTHENTICATION_METHOD method; + UINT32 numeric_or_passkey; + BOOL negative; + BOOL *authenticated; +}; + struct bluetooth_get_event_params { struct winebluetooth_event result; @@ -99,6 +108,7 @@ enum bluetoothapis_funcs unix_bluetooth_device_free,
unix_bluetooth_auth_agent_enable_incoming, + unix_bluetooth_auth_send_response,
unix_bluetooth_get_event,
diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 29b789ab025..7aff1386986 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -57,6 +57,9 @@ extern NTSTATUS bluez_adapter_stop_discovery( void *connection, const char *adap extern NTSTATUS bluez_auth_agent_request_default( void *connection ); extern NTSTATUS bluez_auth_agent_start( void *connection, void **ctx ); extern NTSTATUS bluez_auth_agent_stop( void *connection, void *ctx ); +extern NTSTATUS bluez_auth_agent_send_response( void *auth_agent, struct unix_name *device, + BLUETOOTH_AUTHENTICATION_METHOD method, UINT32 numeric_or_passkey, + BOOL negative, BOOL *authenticated ); 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 0f421a87828..f9ec589e0de 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -143,6 +143,21 @@ void winebluetooth_device_properties_to_info( winebluetooth_device_props_mask_t } }
+NTSTATUS winebluetooth_auth_send_response( winebluetooth_device_t device, BLUETOOTH_AUTHENTICATION_METHOD method, + UINT32 numeric_or_passkey, BOOL negative, BOOL *authenticated ) +{ + struct bluetooth_auth_send_response_params args = {0}; + + TRACE( "device=%p method=%d negative=%d authenticated=%p\n", (void *)device.handle, method, negative, authenticated ); + + args.device = device.handle; + args.method = method; + args.numeric_or_passkey = numeric_or_passkey; + args.negative = negative; + args.authenticated = authenticated; + return UNIX_BLUETOOTH_CALL( bluetooth_auth_send_response, &args ); +} + NTSTATUS winebluetooth_get_event( struct winebluetooth_event *result ) { struct bluetooth_get_event_params params = {0}; diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 8c885cde2fa..44d8c3f90d4 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -251,6 +251,51 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) case IOCTL_WINEBTH_RADIO_STOP_DISCOVERY: status = winebluetooth_radio_stop_discovery( ext->radio ); break; + case IOCTL_WINEBTH_RADIO_SEND_AUTH_RESPONSE: + { + struct winebth_radio_send_auth_response_params *params = irp->AssociatedIrp.SystemBuffer; + struct bluetooth_remote_device *device; + + if (!params) + { + status = STATUS_INVALID_PARAMETER; + break; + } + if (insize < sizeof( *params )) + { + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + if (outsize < sizeof( *params )) + { + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + status = STATUS_DEVICE_NOT_CONNECTED; + EnterCriticalSection( &ext->remote_devices_cs ); + LIST_FOR_EACH_ENTRY( device, &ext->remote_devices, struct bluetooth_remote_device, entry ) + { + BOOL matches; + EnterCriticalSection( &device->props_cs ); + matches = device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS && + device->props.address.ullLong == params->address; + LeaveCriticalSection( &device->props_cs ); + if (matches) + { + BOOL authenticated = FALSE; + status = winebluetooth_auth_send_response( device->device, params->method, + params->numeric_value_or_passkey, params->negative, + &authenticated ); + params->authenticated = !!authenticated; + break; + } + } + if (!status) + irp->IoStatus.Information = sizeof( *params ); + LeaveCriticalSection( &ext->remote_devices_cs ); + 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 47ae3b03b15..13e234a0da8 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -210,6 +210,9 @@ void winebluetooth_device_properties_to_info( winebluetooth_device_props_mask_t const struct winebluetooth_device_properties *props, BTH_DEVICE_INFO *info );
+NTSTATUS winebluetooth_auth_send_response( winebluetooth_device_t device, BLUETOOTH_AUTHENTICATION_METHOD method, + UINT32 numeric_or_passkey, BOOL negative, BOOL *authenticated ); + enum winebluetooth_watcher_event_type { BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_ADDED, diff --git a/include/wine/winebth.h b/include/wine/winebth.h index 5fa702726a7..d8ff41a6a61 100644 --- a/include/wine/winebth.h +++ b/include/wine/winebth.h @@ -24,14 +24,14 @@
/* 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) +#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) +#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) +#define IOCTL_WINEBTH_RADIO_STOP_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa7, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Ask the system's Bluetooth service to send all incoming authentication requests to Wine. */ -#define IOCTL_WINEBTH_AUTH_REGISTER CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa8, METHOD_BUFFERED, FILE_ANY_ACCESS) - +#define IOCTL_WINEBTH_AUTH_REGISTER CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINEBTH_RADIO_SEND_AUTH_RESPONSE CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa9, METHOD_BUFFERED, FILE_ANY_ACCESS)
DEFINE_GUID( GUID_WINEBTH_AUTHENTICATION_REQUEST, 0xca67235f, 0xf621, 0x4c27, 0x85, 0x65, 0xa4, 0xd5, 0x5e, 0xa1, 0x26, 0xe8 ); @@ -56,6 +56,17 @@ struct winebth_authentication_request BLUETOOTH_AUTHENTICATION_METHOD auth_method; ULONG numeric_value_or_passkey; }; + +struct winebth_radio_send_auth_response_params +{ + BTH_ADDR address; + BLUETOOTH_AUTHENTICATION_METHOD method; + UINT32 numeric_value_or_passkey; + unsigned int negative : 1; + + unsigned int authenticated : 1; +}; + #include <poppack.h>
#endif /* __WINEBTH_H__ */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/bluetoothapis.spec | 2 +- dlls/bluetoothapis/main.c | 14 +++++++++++ dlls/bthprops.cpl/bthprops.cpl.spec | 2 +- include/bluetoothapis.h | 34 +++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/dlls/bluetoothapis/bluetoothapis.spec b/dlls/bluetoothapis/bluetoothapis.spec index 2a2a657fabe..b028c29146f 100644 --- a/dlls/bluetoothapis/bluetoothapis.spec +++ b/dlls/bluetoothapis/bluetoothapis.spec @@ -59,7 +59,7 @@ @ stdcall BluetoothSdpGetElementData(ptr long ptr) @ stub BluetoothSdpGetString @ stub BluetoothSendAuthenticationResponse -@ stub BluetoothSendAuthenticationResponseEx +@ stdcall BluetoothSendAuthenticationResponseEx(ptr ptr) @ stub BluetoothSetLocalServiceInfo @ stub BluetoothSetServiceState @ stub BluetoothSetServiceStateEx diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index 2c496088e98..061f4208f64 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -867,3 +867,17 @@ BOOL WINAPI BluetoothUnregisterAuthentication( HBLUETOOTH_AUTHENTICATION_REGISTR SetLastError( ret ); return !ret; } + +static const char *debugstr_BLUETOOTH_AUTHENTICATE_RESPONSE( const BLUETOOTH_AUTHENTICATE_RESPONSE *resp ) +{ + if (!resp) + return wine_dbg_sprintf("(null)"); + return wine_dbg_sprintf("{ bthAddressRemote: %s, authMethod: %d, negativeResponse: %d }", + debugstr_addr( resp->bthAddressRemote.rgBytes ), resp->authMethod, resp->negativeResponse ); +} + +DWORD WINAPI BluetoothSendAuthenticationResponseEx( HANDLE handle_radio, BLUETOOTH_AUTHENTICATE_RESPONSE *auth_response ) +{ + FIXME( "(%p, %s): stub!\n", handle_radio, debugstr_BLUETOOTH_AUTHENTICATE_RESPONSE( auth_response ) ); + return ERROR_CALL_NOT_IMPLEMENTED; +} diff --git a/dlls/bthprops.cpl/bthprops.cpl.spec b/dlls/bthprops.cpl/bthprops.cpl.spec index 2b263c7627e..4c6ad724792 100644 --- a/dlls/bthprops.cpl/bthprops.cpl.spec +++ b/dlls/bthprops.cpl/bthprops.cpl.spec @@ -52,7 +52,7 @@ @ stub BluetoothSelectDevices @ stub BluetoothSelectDevicesFree @ stub BluetoothSendAuthenticationResponse -@ stub BluetoothSendAuthenticationResponseEx +@ stdcall -import BluetoothSendAuthenticationResponseEx(ptr ptr) @ stub BluetoothSetLocalServiceInfo @ stub BluetoothSetServiceState @ stdcall -import BluetoothUnregisterAuthentication(long) diff --git a/include/bluetoothapis.h b/include/bluetoothapis.h index d3b5c941b7c..b97967ec81f 100644 --- a/include/bluetoothapis.h +++ b/include/bluetoothapis.h @@ -153,6 +153,39 @@ typedef struct _BLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS {
typedef BOOL (CALLBACK *PFN_AUTHENTICATION_CALLBACK_EX)(void *, BLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS *);
+#define BTH_MAX_PIN_SIZE 16 + +typedef struct _BLUETOOTH_PIN_INFO { + UCHAR pin[BTH_MAX_PIN_SIZE]; + UCHAR pinLength; +} BLUETOOTH_PIN_INFO, *PBLUETOOTH_PIN_INFO; + +typedef struct _BLUETOOTH_OOB_DATA_INFO { + UCHAR C[16]; + UCHAR R[16]; +} BLUETOOTH_OOB_DATA_INFO, *PBLUETOOTH_OOB_DATA_INFO; + +typedef struct _BLUETOOTH_NUMERIC_COMPARISON_INFO { + ULONG NumericValue; +} BLUETOOTH_NUMERIC_COMPARISON_INFO, *PBLUETOOTH_NUMERIC_COMPARISON_INFO; + +typedef struct _BLUETOOTH_PASSKEY_INFO { + ULONG passkey; +} BLUETOOTH_PASSKEY_INFO, *PBLUETOOTH_PASSKEY_INFO; + +typedef struct _BLUETOOTH_AUTHENTICATE_RESPONSE { + BLUETOOTH_ADDRESS bthAddressRemote; + BLUETOOTH_AUTHENTICATION_METHOD authMethod; + union + { + BLUETOOTH_PIN_INFO pinInfo; + BLUETOOTH_OOB_DATA_INFO oobInfo; + BLUETOOTH_NUMERIC_COMPARISON_INFO numericCompInfo; + BLUETOOTH_PASSKEY_INFO passkeyInfo; + }; + UCHAR negativeResponse; +} BLUETOOTH_AUTHENTICATE_RESPONSE, *PBLUETOOTH_AUTHENTICATE_RESPONSE; + typedef struct _SDP_ELEMENT_DATA { SDP_TYPE type; SDP_SPECIFICTYPE specificType; @@ -237,6 +270,7 @@ DWORD WINAPI BluetoothSdpGetString(BYTE *, ULONG, PSDP_STRING_TYPE_DATA, USHORT, BOOL WINAPI BluetoothSelectDevices(BLUETOOTH_SELECT_DEVICE_PARAMS *); BOOL WINAPI BluetoothSelectDevicesFree(BLUETOOTH_SELECT_DEVICE_PARAMS *); DWORD WINAPI BluetoothSendAuthenticationResponse(HANDLE, BLUETOOTH_DEVICE_INFO *, WCHAR *); +DWORD WINAPI BluetoothSendAuthenticationResponseEx(HANDLE, BLUETOOTH_AUTHENTICATE_RESPONSE *); DWORD WINAPI BluetoothSetServiceState(HANDLE, BLUETOOTH_DEVICE_INFO *, GUID *, DWORD); BOOL WINAPI BluetoothUnregisterAuthentication(HBLUETOOTH_AUTHENTICATION_REGISTRATION); DWORD WINAPI BluetoothUpdateDeviceRecord(BLUETOOTH_DEVICE_INFO *);
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/main.c | 70 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-)
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index 061f4208f64..5341db0d295 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -878,6 +878,72 @@ static const char *debugstr_BLUETOOTH_AUTHENTICATE_RESPONSE( const BLUETOOTH_AUT
DWORD WINAPI BluetoothSendAuthenticationResponseEx( HANDLE handle_radio, BLUETOOTH_AUTHENTICATE_RESPONSE *auth_response ) { - FIXME( "(%p, %s): stub!\n", handle_radio, debugstr_BLUETOOTH_AUTHENTICATE_RESPONSE( auth_response ) ); - return ERROR_CALL_NOT_IMPLEMENTED; + struct winebth_radio_send_auth_response_params params = {0}; + DWORD ret, bytes; + + TRACE( "(%p, %s)\n", handle_radio, debugstr_BLUETOOTH_AUTHENTICATE_RESPONSE( auth_response ) ); + + if (!auth_response) + return ERROR_INVALID_PARAMETER; + switch (auth_response->authMethod) + { + case BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON: + break; + case BLUETOOTH_AUTHENTICATION_METHOD_LEGACY: + case BLUETOOTH_AUTHENTICATION_METHOD_OOB: + case BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY_NOTIFICATION: + case BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY: + FIXME( "Unsupported authMethod: %d\n", auth_response->authMethod ); + return ERROR_CALL_NOT_IMPLEMENTED; + default: + return ERROR_INVALID_PARAMETER; + } + if (!handle_radio) + { + HBLUETOOTH_RADIO_FIND radio_find; + BLUETOOTH_FIND_RADIO_PARAMS find_params = {.dwSize = sizeof( find_params ) }; + + radio_find = BluetoothFindFirstRadio( &find_params, &handle_radio ); + if (!radio_find) + return GetLastError(); + for(;;) + { + ret = BluetoothSendAuthenticationResponseEx( handle_radio, auth_response ); + CloseHandle( handle_radio ); + if (!ret) + { + BluetoothFindRadioClose( radio_find ); + return ERROR_SUCCESS; + } + + if (!BluetoothFindNextRadio( radio_find, &handle_radio )) + { + BluetoothFindRadioClose( radio_find ); + return ret; + } + } + } + + AcquireSRWLockShared( &bluetooth_auth_lock ); + if (list_empty( &bluetooth_auth_listeners )) + { + ret = ERROR_INVALID_PARAMETER; + goto done; + } + params.address = RtlUlonglongByteSwap( auth_response->bthAddressRemote.ullLong ) >> 16; + params.method = auth_response->authMethod; + params.numeric_value_or_passkey = auth_response->numericCompInfo.NumericValue; + params.negative = !!auth_response->negativeResponse; + + if (!DeviceIoControl( handle_radio, IOCTL_WINEBTH_RADIO_SEND_AUTH_RESPONSE, ¶ms, sizeof( params ), + ¶ms, sizeof( params ), &bytes, NULL )) + { + ret = GetLastError(); + goto done; + } + ret = params.authenticated ? ERROR_SUCCESS : ERROR_NOT_AUTHENTICATED; + + done: + ReleaseSRWLockShared( &bluetooth_auth_lock ); + return ret; }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/tests/Makefile.in | 2 +- dlls/bluetoothapis/tests/device.c | 79 +++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/dlls/bluetoothapis/tests/Makefile.in b/dlls/bluetoothapis/tests/Makefile.in index 5d01bf3a809..601d70b9636 100644 --- a/dlls/bluetoothapis/tests/Makefile.in +++ b/dlls/bluetoothapis/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = bluetoothapis.dll -IMPORTS = bluetoothapis +IMPORTS = bluetoothapis user32
SOURCES = \ device.c \ diff --git a/dlls/bluetoothapis/tests/device.c b/dlls/bluetoothapis/tests/device.c index ef79913f558..16eb1a6ecfc 100644 --- a/dlls/bluetoothapis/tests/device.c +++ b/dlls/bluetoothapis/tests/device.c @@ -23,6 +23,7 @@ #include <windef.h> #include <winbase.h> #include <winnls.h> +#include <winuser.h>
#include <bthsdpdef.h> #include <bluetoothapis.h> @@ -234,7 +235,54 @@ static void test_auth_callback_params( int line, const BLUETOOTH_AUTHENTICATION_
static CALLBACK BOOL auth_ex_callback( void *data, BLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS *auth_params ) { + char msg[400]; + test_auth_callback_params( __LINE__, auth_params ); + if (auth_params) + { + DWORD ret, exp; + BLUETOOTH_AUTHENTICATE_RESPONSE resp = {0}; + + /* Invalid parameters with an active registration */ + ret = BluetoothSendAuthenticationResponseEx( NULL, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER ); + + resp.bthAddressRemote.ullLong = 0xdeadbeefcafe; + ret = BluetoothSendAuthenticationResponseEx( NULL, &resp ); + ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER ); + + /* Non-existent device. */ + resp.authMethod = auth_params->authenticationMethod; + ret = BluetoothSendAuthenticationResponseEx( NULL, &resp ); + ok( ret == ERROR_DEVICE_NOT_CONNECTED, "%lu != %d\n", ret, ERROR_DEVICE_NOT_CONNECTED ); + + /* Invalid auth method */ + resp.bthAddressRemote = auth_params->deviceInfo.Address; + resp.authMethod = 0xdeadbeef; + ret = BluetoothSendAuthenticationResponseEx( NULL, &resp ); + ok( ret == ERROR_INVALID_PARAMETER, "%lu != %d\n", ret, ERROR_INVALID_PARAMETER ); + + resp.authMethod = auth_params->authenticationMethod; + resp.numericCompInfo.NumericValue = auth_params->Numeric_Value; + + snprintf( msg, ARRAY_SIZE( msg ), "Accept auth request from %s (address %s, method %d, passkey %lu)?", + debugstr_w( auth_params->deviceInfo.szName ), + debugstr_bluetooth_address( auth_params->deviceInfo.Address.rgBytes ), + auth_params->authenticationMethod, auth_params->Numeric_Value ); + ret = MessageBoxA( NULL, msg, __FILE__, MB_YESNO ); + ok( ret, "MessageBoxA failed: %lu\n", GetLastError() ); + + resp.negativeResponse = ret != IDYES; + + ret = BluetoothSendAuthenticationResponseEx( NULL, &resp ); + exp = resp.negativeResponse ? ERROR_NOT_AUTHENTICATED : ERROR_SUCCESS; + todo_wine_if( auth_params->authenticationMethod != BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON ) + ok( ret == exp, "%lu != %lu\n", ret, exp ); + + ret = BluetoothSendAuthenticationResponseEx( NULL, &resp ); + todo_wine_if( auth_params->authenticationMethod != BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON ) + ok( ret == ERROR_NOT_READY, "%lu != %d\n", ret, ERROR_NOT_READY ); + } SetEvent( auth_events[0] ); return TRUE; } @@ -280,12 +328,40 @@ static void test_BluetoothRegisterForAuthenticationEx( void )
success = BluetoothUnregisterAuthentication( hreg ); ok( success, "BluetoothUnregisterAuthentication failed: %lu\n", GetLastError() ); - success = BluetoothUnregisterAuthentication( hreg ); + success = BluetoothUnregisterAuthentication( hreg2 ); ok( success, "BluetoothUnregisterAuthentication failed: %lu\n", GetLastError() );
BluetoothEnableDiscovery( NULL, FALSE ); }
+ +static void test_radio_BluetoothSendAuthenticationResponseEx( HANDLE radio , void *data ) +{ + BLUETOOTH_AUTHENTICATE_RESPONSE resp = {0}; + DWORD ret; + + ret = BluetoothSendAuthenticationResponseEx( radio, NULL ); + + ok( ret == ERROR_INVALID_PARAMETER || (!radio && ret == ERROR_NO_MORE_ITEMS), + "%lu != %d\n", ret, ERROR_INVALID_PARAMETER ); + + ret = BluetoothSendAuthenticationResponseEx( radio, &resp ); + ok( ret == ERROR_INVALID_PARAMETER || (!radio && ret == ERROR_NO_MORE_ITEMS), + "%lu != %d\n", ret, ERROR_INVALID_PARAMETER ); + + resp.bthAddressRemote.ullLong = 0xdeadbeefcafe; + ret = BluetoothSendAuthenticationResponseEx( radio, &resp ); + ok( ret == ERROR_INVALID_PARAMETER || (!radio && ret == ERROR_NO_MORE_ITEMS), + "%lu != %d\n", ret, ERROR_INVALID_PARAMETER ); +} + +/* Test BluetoothSendAuthenticationResponseEx when no authentication registrations exist. */ +static void test_BluetoothSendAuthenticationResponseEx( void ) +{ + test_radio_BluetoothSendAuthenticationResponseEx( NULL, (void *)__LINE__ ); + test_for_all_radios( __FILE__, __LINE__, test_radio_BluetoothSendAuthenticationResponseEx, NULL ); +} + START_TEST( device ) { test_BluetoothFindFirstDevice(); @@ -294,4 +370,5 @@ START_TEST( device )
if (winetest_interactive) test_BluetoothRegisterForAuthenticationEx(); + test_BluetoothSendAuthenticationResponseEx(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 4a86cb4cbb4..25352d5e271 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -956,7 +956,11 @@ static DBusHandlerResult bluez_auth_agent_vtable_message_handler( DBusConnection
return DBUS_HANDLER_RESULT_HANDLED; } - if (p_dbus_message_is_method_call( message, BLUEZ_INTERFACE_AGENT, "Cancel" )) + if (p_dbus_message_is_method_call( message, BLUEZ_INTERFACE_AGENT, "AuthorizeService" )) + /* Services are handled by BlueZ and other services, so we can just allow them here, as + * this method only gets called for authenticated devices. */ + reply = p_dbus_message_new_method_return( message ); + else if (p_dbus_message_is_method_call( message, BLUEZ_INTERFACE_AGENT, "Cancel" )) { pthread_mutex_lock( &ctx->lock ); if (ctx->status == BLUEZ_PAIRING_SESSION_INCOMING || ctx->status == BLUEZ_PAIRING_SESSION_PENDING_REPLY)
This merge request was approved by Elizabeth Figura.