From: Vibhav Pant vibhavp@gmail.com
The agent receives authentication requests from BlueZ, and will relay them to the PE driver. --- dlls/winebth.sys/dbus.c | 133 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 11 +++ dlls/winebth.sys/unixlib_priv.h | 2 + dlls/winebth.sys/winebth.c | 2 + 4 files changed, 148 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 383fd74187d..39e5a1e4a89 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -116,6 +116,8 @@ const int bluez_timeout = -1; #define BLUEZ_DEST "org.bluez" #define BLUEZ_INTERFACE_ADAPTER "org.bluez.Adapter1" #define BLUEZ_INTERFACE_DEVICE "org.bluez.Device1" +#define BLUEZ_INTERFACE_AGENT_MANAGER "org.bluez.AgentManager1" +#define BLUEZ_INTERFACE_AGENT "org.bluez.Agent1"
#define DO_FUNC( f ) typeof( f ) (*p_##f) DBUS_FUNCS; @@ -848,6 +850,135 @@ void bluez_dbus_free( void *connection ) p_dbus_connection_unref( connection ); }
+static DBusHandlerResult bluez_auth_agent_vtable_message_handler( DBusConnection *connection, DBusMessage *message, + void *data ) +{ + DBusMessage *reply; + dbus_bool_t success; + + FIXME_(dbus)( "(%s, %s, %p): stub!\n", dbgstr_dbus_connection( connection ), dbgstr_dbus_message( message ), + data ); + + reply = p_dbus_message_new_error( message, "org.bluez.Error.Rejected", "" ); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + success = p_dbus_connection_send( connection, reply, NULL ); + p_dbus_message_unref( reply ); + return success ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +const static struct DBusObjectPathVTable bluez_auth_agent_object_vtable = { + .message_function = bluez_auth_agent_vtable_message_handler }; + +#define WINE_BLUEZ_AUTH_AGENT_PATH "/org/winehq/wine/winebth/AuthAgent" + +NTSTATUS bluez_auth_agent_start( void *connection ) +{ + static const char *wine_bluez_auth_agent_path = WINE_BLUEZ_AUTH_AGENT_PATH; + static const char *capability = "KeyboardDisplay"; + DBusMessage *request, *reply; + dbus_bool_t success; + DBusError error; + NTSTATUS status; + + TRACE( "(%s)\n", dbgstr_dbus_connection( connection ) ); + + p_dbus_error_init( &error ); + TRACE_(dbus)( "Registering an org.bluez.Agent1 object at %s\n", WINE_BLUEZ_AUTH_AGENT_PATH ); + success = p_dbus_connection_try_register_object_path( connection, WINE_BLUEZ_AUTH_AGENT_PATH, + &bluez_auth_agent_object_vtable, NULL, &error ); + if (!success) + { + ERR_(dbus)( "Failed to register object: %s: %s\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + goto done; + } + + request = p_dbus_message_new_method_call( BLUEZ_DEST, "/org/bluez", BLUEZ_INTERFACE_AGENT_MANAGER, + "RegisterAgent" ); + if (!request) + { + status = STATUS_NO_MEMORY; + goto failure; + } + + success = p_dbus_message_append_args( request, DBUS_TYPE_OBJECT_PATH, &wine_bluez_auth_agent_path, DBUS_TYPE_STRING, + &capability, DBUS_TYPE_INVALID ); + if (!success) + { + status = STATUS_NO_MEMORY; + goto failure; + } + + /* This is called before the bluez_dbus_loop, so we need to use send_with_reply_and_block. */ + reply = p_dbus_connection_send_with_reply_and_block( connection, request, -1, &error ); + p_dbus_message_unref( request ); + if (!reply) + { + ERR( "Failed to register authentication agent with BlueZ: %s: %s\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + status = bluez_dbus_error_to_ntstatus( &error ); + goto failure; + } + p_dbus_message_unref( reply ); + status = STATUS_SUCCESS; + goto done; + +failure: + p_dbus_connection_unregister_object_path( connection, WINE_BLUEZ_AUTH_AGENT_PATH ); +done: + p_dbus_error_free( &error ); + return status; +} + +NTSTATUS bluez_auth_agent_stop( void *connection ) +{ + static const char *wine_bluez_auth_agent_path = WINE_BLUEZ_AUTH_AGENT_PATH; + DBusMessage *request, *reply; + dbus_bool_t success; + NTSTATUS status; + DBusError error; + + TRACE( "(%s)\n", dbgstr_dbus_connection( connection ) ); + + request = p_dbus_message_new_method_call( BLUEZ_DEST, "/org/bluez", BLUEZ_INTERFACE_AGENT_MANAGER, + "UnregisterAgent" ); + if (!request) + return STATUS_NO_MEMORY; + + success = p_dbus_message_append_args( request, DBUS_TYPE_OBJECT_PATH, &wine_bluez_auth_agent_path, + DBUS_TYPE_INVALID ); + if (!success) + { + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + + p_dbus_error_init( &error ); + status = bluez_dbus_send_and_wait_for_reply( connection, request, &reply, &error ); + if (status) + { + p_dbus_message_unref( request ); + p_dbus_error_free( &error ); + return status; + } + if (!reply) + { + status = bluez_dbus_error_to_ntstatus( &error ); + ERR( "Could not unregister authentication agent with BlueZ: %s: %s\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + return status; + } + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + + success = p_dbus_connection_unregister_object_path( connection, WINE_BLUEZ_AUTH_AGENT_PATH ); + return success ? STATUS_SUCCESS : STATUS_NO_MEMORY; +} + struct bluez_watcher_event { struct list entry; @@ -1727,5 +1858,7 @@ NTSTATUS bluez_adapter_stop_discovery( void *connection, const char *adapter_pat { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_auth_agent_start( void *connection ) { return STATUS_NOT_SUPPORTED; } +NTSTATUS bluez_auth_agent_stop( void *connection ) { return STATUS_NOT_SUPPORTED; }
#endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index 88f6c6164d3..ebbbe2f8fcb 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -102,9 +102,19 @@ static NTSTATUS bluetooth_init ( void *params ) if (!dbus_connection) return STATUS_INTERNAL_ERROR;
+ status = bluez_auth_agent_start( dbus_connection ); + if (status) + { + bluez_dbus_close( dbus_connection ); + return status; + } + status = bluez_watcher_init( dbus_connection, &bluetooth_watcher ); if (status) + { + bluez_auth_agent_stop( dbus_connection ); bluez_dbus_close( dbus_connection ); + } else TRACE( "dbus_connection=%p bluetooth_watcher=%p\n", dbus_connection, bluetooth_watcher ); return status; @@ -114,6 +124,7 @@ static NTSTATUS bluetooth_shutdown( void *params ) { if (!dbus_connection) return STATUS_NOT_SUPPORTED;
+ bluez_auth_agent_stop( dbus_connection ); bluez_dbus_close( dbus_connection ); bluez_watcher_close( dbus_connection, bluetooth_watcher ); bluez_dbus_free( dbus_connection ); diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 60570a2413a..61656e0cf80 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -52,6 +52,8 @@ 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_auth_agent_start( void *connection ); +extern NTSTATUS bluez_auth_agent_stop( void *connection ); 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/winebth.c b/dlls/winebth.sys/winebth.c index 94aa2869b72..5fe6339d9c5 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -659,6 +659,7 @@ static NTSTATUS WINAPI fdo_pnp( DEVICE_OBJECT *device_obj, IRP *irp ) CreateThread( NULL, 0, bluetooth_event_loop_thread_proc, NULL, 0, NULL ); irp->IoStatus.Status = STATUS_SUCCESS; break; + case IRP_MN_SURPRISE_REMOVAL: irp->IoStatus.Status = STATUS_SUCCESS; break; @@ -666,6 +667,7 @@ static NTSTATUS WINAPI fdo_pnp( DEVICE_OBJECT *device_obj, IRP *irp ) { struct bluetooth_radio *device, *cur; NTSTATUS ret; + winebluetooth_shutdown(); WaitForSingleObject( event_loop_thread, INFINITE ); CloseHandle( event_loop_thread );