From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/dbus.c | 100 ++++++++++++++++++++++++++++++++++++ dlls/wlanapi/dbus.h | 2 + dlls/wlanapi/main.c | 25 +++++++-- dlls/wlanapi/unixlib.c | 9 ++++ dlls/wlanapi/unixlib.h | 9 ++++ dlls/wlanapi/unixlib_priv.h | 2 + 6 files changed, 144 insertions(+), 3 deletions(-)
diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c index a9b13295d54..ee3d63c9fa0 100644 --- a/dlls/wlanapi/dbus.c +++ b/dlls/wlanapi/dbus.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "dbus/dbus-protocol.h" #if 0 #pragma makedep unix #endif @@ -26,6 +27,7 @@
#include <stdlib.h> #include <dlfcn.h> +#include <assert.h>
#ifdef SONAME_LIBDBUS_1 #include <dbus/dbus.h> @@ -722,6 +724,104 @@ NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device, return STATUS_SUCCESS; }
+static BOOL networkmanager_requestscan_call_set_ssid( DBusMessageIter *dict, const DOT11_SSID *ssid ) +{ + DBusMessageIter entry, variant = DBUS_MESSAGE_ITER_INIT_CLOSED, + ssids = DBUS_MESSAGE_ITER_INIT_CLOSED, + ssid_bytes = DBUS_MESSAGE_ITER_INIT_CLOSED; + const char *ssids_key = "ssids"; + unsigned char ssid_copy[32]; + INT i; + dbus_bool_t success; + + memcpy( ssid_copy, ssid->ucSSID, sizeof( ssid->ucSSID ) ); + + success = p_dbus_message_iter_open_container( dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry ); + if (!success) return FALSE; + + success = p_dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING, &ssids_key ); + if (!success) goto failed; + success = p_dbus_message_iter_open_container( &entry, DBUS_TYPE_VARIANT, "aay", &variant ); + if (!success) goto failed; + + success = p_dbus_message_iter_open_container( &variant, DBUS_TYPE_ARRAY, "ay", &ssids ); + if (!success) goto failed; + success = p_dbus_message_iter_open_container( &ssids, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, + &ssid_bytes ); + if (!success) goto failed; + for (i = 0; i < ssid->uSSIDLength; i++) + { + success = p_dbus_message_iter_append_basic( &ssid_bytes, DBUS_TYPE_BYTE, &ssid_copy[i] ); + if (!success) goto failed; + } + + p_dbus_message_iter_close_container( &ssids, &ssid_bytes ); + p_dbus_message_iter_close_container( &variant, &ssids ); + p_dbus_message_iter_close_container( &entry, &variant ); + p_dbus_message_iter_close_container( dict, &entry ); + return TRUE; + + failed: + p_dbus_message_iter_abandon_container_if_open( &ssids, &ssid_bytes ); + p_dbus_message_iter_abandon_container_if_open( &variant, &ssids ); + p_dbus_message_iter_abandon_container_if_open( &entry, &variant ); + p_dbus_message_iter_abandon_container_if_open( dict, &entry ); + return FALSE; +} + +NTSTATUS networkmanager_start_scan( void *connection, const GUID *interface, + const DOT11_SSID *ssid ) +{ + DBusMessage *request, *reply; + DBusMessageIter iter, options; + DBusError error; + dbus_bool_t success; + char *device_path; + + TRACE( "(%p, %p, %p)\n", connection, debugstr_guid( interface ), ssid ); + + if (!networkmanager_valid_device_guid( interface )) return STATUS_INVALID_PARAMETER; + device_path = networkmanager_device_guid_to_path( interface ); + if (!device_path) return STATUS_NO_MEMORY; + + request = + p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, device_path, + NETWORKMANAGER_INTERFACE_DEVICE_WIRELESS, "RequestScan" ); + free( device_path ); + if (!request) return STATUS_NO_MEMORY; + + p_dbus_message_iter_init_append( request, &iter ); + success = p_dbus_message_iter_open_container( &iter, DBUS_TYPE_ARRAY, "{sv}", &options ); + if (!success) + { + p_dbus_message_unref( request ); + return STATUS_NO_MEMORY; + } + + if (ssid) + { + assert( ssid->uSSIDLength <= sizeof( ssid->ucSSID ) ); + networkmanager_requestscan_call_set_ssid( &options, ssid ); + } + p_dbus_message_iter_close_container( &iter, &options ); + + p_dbus_error_init( &error ); + reply = + p_dbus_connection_send_with_reply_and_block( connection, request, dbus_timeout, &error ); + p_dbus_message_unref( request ); + if (!reply) + { + NTSTATUS ret = dbus_error_to_ntstatus( &error ); + ERR( "Error calling RequestScan on interface %s: %s: %s.\n", debugstr_guid( interface ), + debugstr_a( error.name ), debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + return ret; + } + p_dbus_message_unref( reply ); + + return STATUS_SUCCESS; +} + #else /* SONAME_LIBDBUS_1 */ BOOL load_dbus_functions( void ) { return FALSE; } NTSTATUS init_dbus_connection( UINT_PTR *handle ) { return STATUS_NOT_SUPPORTED; } diff --git a/dlls/wlanapi/dbus.h b/dlls/wlanapi/dbus.h index 86c5309d117..a8c914222a6 100644 --- a/dlls/wlanapi/dbus.h +++ b/dlls/wlanapi/dbus.h @@ -78,7 +78,9 @@ DO_FUNC(dbus_message_is_error); \ DO_FUNC(dbus_message_is_method_call); \ DO_FUNC(dbus_message_is_signal); \ + DO_FUNC(dbus_message_iter_abandon_container_if_open); \ DO_FUNC(dbus_message_iter_append_basic); \ + DO_FUNC(dbus_message_iter_append_fixed_array); \ DO_FUNC(dbus_message_iter_close_container); \ DO_FUNC(dbus_message_iter_get_arg_type); \ DO_FUNC(dbus_message_iter_get_element_type); \ diff --git a/dlls/wlanapi/main.c b/dlls/wlanapi/main.c index e46646eddf9..de5eb229726 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -1,5 +1,6 @@ /* * Copyright 2010 Ričardas Barkauskas + * Copyright 2024 Vibhav Pant * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -224,10 +225,28 @@ DWORD WINAPI WlanOpenHandle(DWORD client_version, void *reserved, DWORD *negotia DWORD WINAPI WlanScan(HANDLE handle, const GUID *guid, const DOT11_SSID *ssid, const WLAN_RAW_DATA *raw, void *reserved) { - FIXME("(%p, %s, %p, %p, %p) stub\n", - handle, wine_dbgstr_guid(guid), ssid, raw, reserved); + struct wine_wlan *wlan; + struct wlan_start_scan params = {0}; + NTSTATUS status;
- return ERROR_CALL_NOT_IMPLEMENTED; + TRACE( "(%p, %s, %p, %p, %p)\n", handle, wine_dbgstr_guid( guid ), ssid, raw, reserved ); + + if (!handle || !guid || reserved) + return ERROR_INVALID_PARAMETER; + + if (ssid && ssid->uSSIDLength > sizeof( ssid->ucSSID )) + return ERROR_INVALID_PARAMETER; + + wlan = handle_index( handle ); + if (!wlan) + return ERROR_INVALID_HANDLE; + + params.handle = wlan->unix_handle; + params.interface = guid; + params.ssid = ssid; + status = UNIX_WLAN_CALL( wlan_start_scan, ¶ms ); + + return RtlNtStatusToDosError( status ); }
DWORD WINAPI WlanRegisterNotification(HANDLE handle, DWORD notify_source, BOOL ignore_dup, diff --git a/dlls/wlanapi/unixlib.c b/dlls/wlanapi/unixlib.c index 02f5d077100..3b101263f3c 100644 --- a/dlls/wlanapi/unixlib.c +++ b/dlls/wlanapi/unixlib.c @@ -203,6 +203,13 @@ NTSTATUS wlan_network_list_free( void *params ) return STATUS_SUCCESS; }
+NTSTATUS wlan_start_scan( void *params ) +{ + struct wlan_start_scan *args = params; + + return networkmanager_start_scan( (void *) args->handle, args->interface, args->ssid ); +} + const unixlib_entry_t __wine_unix_call_funcs[] = { wlan_init, wlan_open_handle, @@ -216,6 +223,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { wlan_network_list_move_to_avail_network, wlan_network_list_move_to_bss_entry, wlan_network_list_free, + + wlan_start_scan, };
C_ASSERT( ARRAYSIZE( __wine_unix_call_funcs ) == unix_funcs_count ); diff --git a/dlls/wlanapi/unixlib.h b/dlls/wlanapi/unixlib.h index 2776c515e96..1a39149018b 100644 --- a/dlls/wlanapi/unixlib.h +++ b/dlls/wlanapi/unixlib.h @@ -90,6 +90,13 @@ struct wlan_network_list_free_params UINT_PTR networks; };
+struct wlan_start_scan +{ + UINT_PTR handle; + const GUID *interface; + const DOT11_SSID *ssid; +}; + enum wlanpi_funcs { unix_wlan_init, @@ -106,6 +113,8 @@ enum wlanpi_funcs unix_wlan_network_list_move_to_bss_entry, unix_wlan_network_list_free,
+ unix_wlan_start_scan, + unix_funcs_count };
diff --git a/dlls/wlanapi/unixlib_priv.h b/dlls/wlanapi/unixlib_priv.h index 89f0a034d97..da51fcdf66d 100644 --- a/dlls/wlanapi/unixlib_priv.h +++ b/dlls/wlanapi/unixlib_priv.h @@ -64,4 +64,6 @@ extern void wlan_bss_info_to_WLAN_AVAILABLE_NETWORK( const struct wlan_bss_info WLAN_AVAILABLE_NETWORK *dest ); extern void wlan_bss_info_to_WLAN_BSS_ENTRY( const struct wlan_bss_info *info, WLAN_BSS_ENTRY *dest ); +extern NTSTATUS networkmanager_start_scan( void *connection, const GUID *interface, + const DOT11_SSID *ssid ); #endif /* __WINE_WLANAPI_UNIXLIB_PRIV_H */