This MR adds a unixlib component to wlanapi containing DBus + NetworkManager implementations for
* WlanEnumInterfaces * WlanGetAvailableNetworkList * WlanGetAvailableNetworkList * WlanGetNetworkBssList * WlanScan
-- v11: wlanapi: Add NetworkManager backed implementation for WlanGetProfileList. wlanapi/tests: Add unit tests for WlanGetProfileList. wlanapi: Add stub for WlanGetProfileList. wlanapi: Add NetworkManager backed implementation for WlanScan. wlanapi/tests: Add unit tests for WlanScan. wlanapi: Add NetworkManager backed implementation for WlanGetNetworkBssList. wlanapi/tests: Add unit test for test_WlanGetNetworkBssList. wlanapi: Add stub for WlanGetNetworkBssList.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/Makefile.in | 6 +- dlls/wlanapi/dbus.c | 101 ++++++++++++++++++++++++++++++++ dlls/wlanapi/dbus.h | 113 ++++++++++++++++++++++++++++++++++++ dlls/wlanapi/main.c | 35 +++++++++++ dlls/wlanapi/unixlib.c | 71 ++++++++++++++++++++++ dlls/wlanapi/unixlib.h | 48 +++++++++++++++ dlls/wlanapi/unixlib_priv.h | 28 +++++++++ 7 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 dlls/wlanapi/dbus.c create mode 100644 dlls/wlanapi/dbus.h create mode 100644 dlls/wlanapi/unixlib.c create mode 100644 dlls/wlanapi/unixlib.h create mode 100644 dlls/wlanapi/unixlib_priv.h
diff --git a/dlls/wlanapi/Makefile.in b/dlls/wlanapi/Makefile.in index bd2bf87d4d1..92e65dabd54 100644 --- a/dlls/wlanapi/Makefile.in +++ b/dlls/wlanapi/Makefile.in @@ -1,7 +1,11 @@ MODULE = wlanapi.dll IMPORTLIB = wlanapi +UNIXLIB = wlanapi.so +UNIX_CFLAGS = $(DBUS_CFLAGS)
EXTRADLLFLAGS = -Wb,--prefer-native
SOURCES = \ - main.c + main.c \ + dbus.c \ + unixlib.c diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c new file mode 100644 index 00000000000..8a6b5e5b5bb --- /dev/null +++ b/dlls/wlanapi/dbus.c @@ -0,0 +1,101 @@ +/* + * wlanapi DBus backed implementation + * + * 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 + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include <dlfcn.h> + +#ifdef SONAME_LIBDBUS_1 +#include <dbus/dbus.h> +#endif + +#include <ntstatus.h> +#define WIN32_NO_STATUS +#include <winternl.h> + +#include <wine/debug.h> + +#include "dbus.h" + +WINE_DEFAULT_DEBUG_CHANNEL( wlanapi ); + +#ifdef SONAME_LIBDBUS_1 + +#define DO_FUNC( f ) typeof( f ) (*p_##f) +DBUS_FUNCS; +#undef DO_FUNC + +BOOL load_dbus_functions( void ) +{ + void *handle = dlopen( SONAME_LIBDBUS_1, RTLD_NOW ); + + if (handle == NULL) goto failed; + +#define DO_FUNC( f ) \ + if (!(p_##f = dlsym( handle, #f ))) \ + { \ + ERR( "failed to load symbol %s: %s\n", #f, dlerror() ); \ + goto failed; \ + } + DBUS_FUNCS; +#undef DO_FUNC + p_dbus_threads_init_default(); + return TRUE; + +failed: + WARN( "failed to load DBus support: %s\n", dlerror() ); + return FALSE; +} + +NTSTATUS init_dbus_connection( UINT_PTR *handle ) +{ + DBusError error; + DBusConnection *connection; + NTSTATUS ret = STATUS_SUCCESS; + + p_dbus_error_init( &error ); + connection = p_dbus_bus_get_private( DBUS_BUS_SYSTEM, &error ); + if (connection == NULL) + { + ERR( "Failed to get system dbus connection: %s: %s.\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + ret = STATUS_NOT_SUPPORTED; + } + else + *handle = (UINT_PTR)connection; + p_dbus_error_free( &error ); + + return ret; +} + +void close_dbus_connection( void *c ) +{ + p_dbus_connection_close( c ); + p_dbus_connection_unref( c ); +} +#else /* SONAME_LIBDBUS_1 */ +BOOL load_dbus_functions( void ) { return FALSE; } +NTSTATUS init_dbus_connection( UINT_PTR *handle ) { return STATUS_NOT_SUPPORTED; } +void close_dbus_connection( void *c ) { return STATUS_NOT_SUPPORTED; } +#endif diff --git a/dlls/wlanapi/dbus.h b/dlls/wlanapi/dbus.h new file mode 100644 index 00000000000..86c5309d117 --- /dev/null +++ b/dlls/wlanapi/dbus.h @@ -0,0 +1,113 @@ +/* + * DBus declarations. + * + * 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 + * 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 + */ + +#ifndef __WINE_WLANAPI_UNIXLIB_DBUS_H +#define __WINE_WLANAPI_UNIXLIB_DBUS_H + +#include "config.h" + +#ifdef SONAME_LIBDBUS_1 +#include <dbus/dbus.h> +#endif + +#ifdef SONAME_LIBDBUS_1 + +#define DBUS_FUNCS \ + DO_FUNC(dbus_bus_add_match); \ + DO_FUNC(dbus_bus_get); \ + DO_FUNC(dbus_bus_get_id); \ + DO_FUNC(dbus_bus_get_private); \ + DO_FUNC(dbus_bus_remove_match); \ + DO_FUNC(dbus_connection_add_filter); \ + DO_FUNC(dbus_connection_close); \ + DO_FUNC(dbus_connection_flush); \ + DO_FUNC(dbus_connection_free_preallocated_send); \ + DO_FUNC(dbus_connection_get_is_anonymous); \ + DO_FUNC(dbus_connection_get_is_authenticated); \ + DO_FUNC(dbus_connection_get_is_connected); \ + DO_FUNC(dbus_connection_get_server_id); \ + DO_FUNC(dbus_connection_get_unix_process_id); \ + DO_FUNC(dbus_connection_get_unix_fd); \ + DO_FUNC(dbus_connection_get_unix_user); \ + DO_FUNC(dbus_connection_preallocate_send); \ + DO_FUNC(dbus_connection_read_write_dispatch); \ + DO_FUNC(dbus_connection_remove_filter); \ + DO_FUNC(dbus_connection_ref); \ + DO_FUNC(dbus_connection_send); \ + DO_FUNC(dbus_connection_send_preallocated); \ + DO_FUNC(dbus_connection_send_with_reply); \ + DO_FUNC(dbus_connection_send_with_reply_and_block); \ + DO_FUNC(dbus_connection_try_register_object_path); \ + DO_FUNC(dbus_connection_unref); \ + DO_FUNC(dbus_connection_unregister_object_path); \ + DO_FUNC(dbus_error_free); \ + DO_FUNC(dbus_error_has_name) ; \ + DO_FUNC(dbus_error_init); \ + DO_FUNC(dbus_error_is_set); \ + DO_FUNC(dbus_free); \ + DO_FUNC(dbus_free_string_array); \ + DO_FUNC(dbus_message_append_args); \ + DO_FUNC(dbus_message_get_args); \ + DO_FUNC(dbus_message_iter_get_element_count); \ + DO_FUNC(dbus_message_get_interface); \ + DO_FUNC(dbus_message_get_member); \ + DO_FUNC(dbus_message_get_path); \ + DO_FUNC(dbus_message_get_sender); \ + DO_FUNC(dbus_message_get_serial); \ + DO_FUNC(dbus_message_get_signature); \ + DO_FUNC(dbus_message_get_type); \ + DO_FUNC(dbus_message_has_signature); \ + DO_FUNC(dbus_message_iter_has_next); \ + DO_FUNC(dbus_message_is_error); \ + DO_FUNC(dbus_message_is_method_call); \ + DO_FUNC(dbus_message_is_signal); \ + DO_FUNC(dbus_message_iter_append_basic); \ + DO_FUNC(dbus_message_iter_close_container); \ + DO_FUNC(dbus_message_iter_get_arg_type); \ + DO_FUNC(dbus_message_iter_get_element_type); \ + DO_FUNC(dbus_message_iter_get_basic); \ + DO_FUNC(dbus_message_iter_get_fixed_array); \ + DO_FUNC(dbus_message_iter_get_signature); \ + DO_FUNC(dbus_message_iter_init); \ + DO_FUNC(dbus_message_iter_init_append); \ + DO_FUNC(dbus_message_iter_next); \ + DO_FUNC(dbus_message_iter_open_container); \ + DO_FUNC(dbus_message_iter_recurse); \ + DO_FUNC(dbus_message_new_error); \ + DO_FUNC(dbus_message_new_error_printf); \ + DO_FUNC(dbus_message_new_method_return); \ + DO_FUNC(dbus_message_new_method_call); \ + DO_FUNC(dbus_message_ref); \ + DO_FUNC(dbus_message_unref); \ + DO_FUNC(dbus_pending_call_block); \ + DO_FUNC(dbus_pending_call_cancel); \ + DO_FUNC(dbus_pending_call_get_completed); \ + DO_FUNC(dbus_pending_call_set_notify); \ + DO_FUNC(dbus_pending_call_steal_reply); \ + DO_FUNC(dbus_pending_call_unref); \ + DO_FUNC(dbus_set_error_from_message); \ + DO_FUNC(dbus_threads_init_default); + +#define DO_FUNC( f ) extern typeof( f ) *p_##f +DBUS_FUNCS; +#undef DO_FUNC + +#endif /* SONAME_LIBDBUS_1 */ +#endif /* __WINE_WLANAPI_UNIXLIB_DBUS_H */ diff --git a/dlls/wlanapi/main.c b/dlls/wlanapi/main.c index c3712662232..6335088973c 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -28,12 +28,18 @@
#include <stdarg.h>
+#include <ntstatus.h> +#define WIN32_NO_STATUS + #include "windef.h" #include "winbase.h" #include "wine/debug.h" +#include "wine/unixlib.h"
#include "wlanapi.h"
+#include "unixlib.h" + WINE_DEFAULT_DEBUG_CHANNEL(wlanapi);
#define WLAN_MAGIC 0x574c414e /* WLAN */ @@ -41,6 +47,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wlanapi); static struct wine_wlan { DWORD magic, cli_version; + UINT_PTR unix_handle; } handle_table[16];
static struct wine_wlan* handle_index(HANDLE handle) @@ -98,6 +105,8 @@ DWORD WINAPI WlanEnumInterfaces(HANDLE handle, void *reserved, WLAN_INTERFACE_IN DWORD WINAPI WlanCloseHandle(HANDLE handle, void *reserved) { struct wine_wlan *wlan; + struct wlan_close_handle_params params = {0}; + NTSTATUS status;
TRACE("(%p, %p)\n", handle, reserved);
@@ -108,6 +117,11 @@ DWORD WINAPI WlanCloseHandle(HANDLE handle, void *reserved) if (!wlan) return ERROR_INVALID_HANDLE;
+ params.handle = wlan->unix_handle; + status = UNIX_WLAN_CALL( wlan_close_handle, ¶ms ); + if (status != STATUS_SUCCESS && status != STATUS_NOT_SUPPORTED) + return RtlNtStatusToDosError( status ); + wlan->magic = 0; return ERROR_SUCCESS; } @@ -115,7 +129,9 @@ DWORD WINAPI WlanCloseHandle(HANDLE handle, void *reserved) DWORD WINAPI WlanOpenHandle(DWORD client_version, void *reserved, DWORD *negotiated_version, HANDLE *handle) { struct wine_wlan *wlan; + struct wlan_open_handle_params params = {0}; HANDLE ret_handle; + NTSTATUS status;
TRACE("(%lu, %p, %p, %p)\n", client_version, reserved, negotiated_version, handle);
@@ -129,6 +145,11 @@ DWORD WINAPI WlanOpenHandle(DWORD client_version, void *reserved, DWORD *negotia if (!ret_handle) return ERROR_REMOTE_SESSION_LIMIT_EXCEEDED;
+ status = UNIX_WLAN_CALL( wlan_open_handle, ¶ms ); + if (status != STATUS_SUCCESS && status != STATUS_NOT_SUPPORTED) + return RtlNtStatusToDosError( status ); + + wlan->unix_handle = params.handle; wlan->magic = WLAN_MAGIC; wlan->cli_version = *negotiated_version = client_version; *handle = ret_handle; @@ -225,3 +246,17 @@ void *WINAPI WlanAllocateMemory(DWORD size)
return ret; } + +BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved ) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( instance ); + if (__wine_init_unix_call()) return FALSE; + UNIX_WLAN_CALL( wlan_init, NULL ); + break; + } + + return TRUE; +} diff --git a/dlls/wlanapi/unixlib.c b/dlls/wlanapi/unixlib.c new file mode 100644 index 00000000000..92311ffb856 --- /dev/null +++ b/dlls/wlanapi/unixlib.c @@ -0,0 +1,71 @@ +/* + * wlanapi unixlib implementation + * + * 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 + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include <ntstatus.h> +#define WIN32_NO_STATUS +#include <winternl.h> + +#include <wine/unixlib.h> + +#include "unixlib.h" +#include "unixlib_priv.h" + +static BOOL initialized; + +NTSTATUS wlan_init( void *params ) +{ + initialized = load_dbus_functions(); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_open_handle( void *params ) +{ + struct wlan_open_handle_params *args = params; + NTSTATUS status; + if (!initialized) + return STATUS_NOT_SUPPORTED; + + status = init_dbus_connection( &args->handle ); + return status; +} + +NTSTATUS wlan_close_handle( void *params ) +{ + struct wlan_close_handle_params *args = params; + if (!initialized) + return STATUS_NOT_SUPPORTED; + + close_dbus_connection( (void *)args->handle ); + return STATUS_SUCCESS; +} + +const unixlib_entry_t __wine_unix_call_funcs[] = { + wlan_init, + wlan_open_handle, + wlan_close_handle +}; + +C_ASSERT( ARRAYSIZE( __wine_unix_call_funcs ) == unix_funcs_count ); diff --git a/dlls/wlanapi/unixlib.h b/dlls/wlanapi/unixlib.h new file mode 100644 index 00000000000..9bf2149e7c3 --- /dev/null +++ b/dlls/wlanapi/unixlib.h @@ -0,0 +1,48 @@ +/* + * Unix interface definitions + * + * 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 + * 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 + */ + +#ifndef __WINE_WLANAPI_UNIXLIB_H +#define __WINE_WLANAPI_UNIXLIB_H + +#include <windef.h> + +struct wlan_open_handle_params +{ + UINT_PTR handle; +}; + +struct wlan_close_handle_params +{ + UINT_PTR handle; +}; + +enum wlanpi_funcs +{ + unix_wlan_init, + + unix_wlan_open_handle, + unix_wlan_close_handle, + + unix_funcs_count +}; + +#define UNIX_WLAN_CALL( func, params ) WINE_UNIX_CALL( unix_##func, (params) ) + +#endif /* __WINE_WLANAPI_UNIXLIB_H */ diff --git a/dlls/wlanapi/unixlib_priv.h b/dlls/wlanapi/unixlib_priv.h new file mode 100644 index 00000000000..fa813d07844 --- /dev/null +++ b/dlls/wlanapi/unixlib_priv.h @@ -0,0 +1,28 @@ +/* + * Unix private definitions + * + * 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 + * 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 + */ + +#ifndef __WINE_WLANAPI_UNIXLIB_PRIV_H +#define __WINE_WLANAPI_UNIXLIB_PRIV_H + +extern BOOL load_dbus_functions( void ); +extern NTSTATUS init_dbus_connection( UINT_PTR *handle ); +extern void close_dbus_connection( void *c ); + +#endif /* __WINE_WLANAPI_UNIXLIB_PRIV_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/dbus.c | 290 ++++++++++++++++++++++++++++++++++++ dlls/wlanapi/main.c | 68 ++++++++- dlls/wlanapi/unixlib.c | 70 ++++++++- dlls/wlanapi/unixlib.h | 31 ++++ dlls/wlanapi/unixlib_priv.h | 7 + 5 files changed, 461 insertions(+), 5 deletions(-)
diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c index 8a6b5e5b5bb..dca8156afe5 100644 --- a/dlls/wlanapi/dbus.c +++ b/dlls/wlanapi/dbus.c @@ -24,6 +24,7 @@
#include "config.h"
+#include <stdlib.h> #include <dlfcn.h>
#ifdef SONAME_LIBDBUS_1 @@ -33,9 +34,13 @@ #include <ntstatus.h> #define WIN32_NO_STATUS #include <winternl.h> +#include <wlanapi.h>
#include <wine/debug.h> +#include <wine/list.h>
+#include "unixlib.h" +#include "unixlib_priv.h" #include "dbus.h"
WINE_DEFAULT_DEBUG_CHANNEL( wlanapi ); @@ -46,6 +51,11 @@ WINE_DEFAULT_DEBUG_CHANNEL( wlanapi ); DBUS_FUNCS; #undef DO_FUNC
+#define NETWORKMANAGER_SERVICE "org.freedesktop.NetworkManager" + +#define NETWORKMANAGER_INTERFACE_MANAGER "org.freedesktop.NetworkManager" +#define NETWORKMANAGER_INTERFACE_DEVICE "org.freedesktop.NetworkManager.Device" + BOOL load_dbus_functions( void ) { void *handle = dlopen( SONAME_LIBDBUS_1, RTLD_NOW ); @@ -94,6 +104,286 @@ void close_dbus_connection( void *c ) p_dbus_connection_close( c ); p_dbus_connection_unref( c ); } + +const static int dbus_timeout = -1; + + +static NTSTATUS dbus_error_to_ntstatus( const DBusError *error ) +{ + +#define DBUS_ERROR_CASE(n, s) if(p_dbus_error_has_name( error, (n)) ) return (s) + + DBUS_ERROR_CASE( DBUS_ERROR_UNKNOWN_OBJECT, STATUS_INVALID_PARAMETER ); + DBUS_ERROR_CASE( DBUS_ERROR_NO_MEMORY, STATUS_NO_MEMORY ); + DBUS_ERROR_CASE( DBUS_ERROR_NOT_SUPPORTED, STATUS_NOT_SUPPORTED ); + DBUS_ERROR_CASE( DBUS_ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED ); + return STATUS_INTERNAL_ERROR; +#undef DBUS_ERROR_CASE +} + +#define NM_DEVICE_TYPE_WIFI 2 + +static BOOL networkmanager_device_is_wifi( void *connection, const char *object_path ) +{ + DBusMessage *request, *reply; + DBusError error; + DBusMessageIter iter, variant; + dbus_bool_t success; + BOOL is_wifi; + const char *device_iface = NETWORKMANAGER_INTERFACE_DEVICE; + const char *devicetype_prop = "DeviceType"; + + request = p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, object_path, + DBUS_INTERFACE_PROPERTIES, "Get" ); + if (!request) return FALSE; + success = p_dbus_message_append_args( request, DBUS_TYPE_STRING, &device_iface, + DBUS_TYPE_STRING, &devicetype_prop, DBUS_TYPE_INVALID ); + if (!success) + { + p_dbus_message_unref( request ); + return FALSE; + } + + 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) + { + p_dbus_error_free( &error ); + return FALSE; + } + p_dbus_error_free( &error ); + p_dbus_error_init( &error ); + + p_dbus_message_iter_init( reply, &iter ); + p_dbus_message_iter_recurse( &iter, &variant ); + if (p_dbus_message_iter_get_arg_type( &variant) == DBUS_TYPE_UINT32) + { + dbus_uint32_t device_type; + + p_dbus_message_iter_get_basic( &variant, &device_type ); + is_wifi = device_type == NM_DEVICE_TYPE_WIFI; + } + else + { + ERR( "Unexpected signature for property DeviceType: %c\n", + p_dbus_message_iter_get_arg_type( &variant ) ); + is_wifi = FALSE; + } + + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + + return is_wifi; +} + +/* NetworkManager device objects do not have any UUID-like propertiy which we could use to + deterministically derive an interface GUID for Win32. However, all device objects have + the object path prefix "/org/freedesktop/NetworkManager/Devices/" followed by a numerical + index. We use index as the last 4 bytes of this GUID to create a Win32 WLAN interface GUID. */ +const static GUID NETWORKMANAGER_DEVICE_BASE_INTERFACE_GUID = { + 0xa53634f7, 0xc1bc, 0x4d41, { 0xbc, 0x06, 0xd3, 0xf7, 0x00, 0x00, 0x00, 0x00 } }; + +static BOOL networkmanager_device_path_to_guid( const char *object_path, GUID *guid ) +{ + const static char device_prefix[] = "/org/freedesktop/NetworkManager/Devices/"; + BOOL is_device = strncmp( object_path, device_prefix, sizeof( device_prefix ) ); + UINT32 idx; + + if (!is_device) return FALSE; + idx = atoi( object_path + sizeof(device_prefix) - 1 ); + if (!idx) /* NetworkManager doesn't seem to use 0 as an index for devices. */ + { + ERR( "Could not parse index from device path %s:\n", debugstr_a( object_path )); + return FALSE; + } + + *guid = NETWORKMANAGER_DEVICE_BASE_INTERFACE_GUID; + memcpy( &guid->Data4[4], &idx, 4 ); + + return TRUE; +} + +static const char *dbus_next_dict_entry( DBusMessageIter *iter, DBusMessageIter *variant ) +{ + DBusMessageIter sub; + const char *name; + + if (p_dbus_message_iter_get_arg_type( iter ) != DBUS_TYPE_DICT_ENTRY) + return NULL; + + p_dbus_message_iter_recurse( iter, &sub ); + p_dbus_message_iter_next( iter ); + p_dbus_message_iter_get_basic( &sub, &name ); + p_dbus_message_iter_next( &sub ); + p_dbus_message_iter_recurse( &sub, variant ); + return name; +} + +#define NM_DEVICE_STATE_UNKNOWN 0 +#define NM_DEVICE_STATE_UNMANAGED 10 +#define NM_DEVICE_STATE_UNAVAILABLE 20 +#define NM_DEVICE_STATE_DISCONNECTED 30 +#define NM_DEVICE_STATE_PREPARE 40 +#define NM_DEVICE_STATE_CONFIG 50 +#define NM_DEVICE_STATE_NEED_AUTH 60 +#define NM_DEVICE_STATE_IP_CONFIG 70 +#define NM_DEVICE_STATE_IP_CHECK 80 +#define NM_DEVICE_STATE_SECONDARIES 90 +#define NM_DEVICE_STATE_ACTIVATED 100 +#define NM_DEVICE_STATE_DEACTIVATING 110 +#define NM_DEVICE_STATE_FAILED 120 + +static BOOL networkmanager_wifi_device_get_info( void *connection, const char *object_path, + struct unix_wlan_interface_info *info ) +{ + DBusMessage *request, *reply; + DBusError error; + DBusMessageIter dict, prop_iter, variant; + const char *prop_name; + const char *device_iface = NETWORKMANAGER_INTERFACE_DEVICE; + + if (!networkmanager_device_path_to_guid( object_path, &info->guid )) return FALSE; + request = p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, object_path, + DBUS_INTERFACE_PROPERTIES, "GetAll" ); + if (!request) return FALSE; + + p_dbus_message_append_args( request, DBUS_TYPE_STRING, &device_iface, DBUS_TYPE_INVALID ); + 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) + { + ERR( "Could not get properties for %s: %s: %s.\n", debugstr_a( object_path ), error.name, + error.message ); + p_dbus_error_free( &error ); + return FALSE; + } + + p_dbus_error_free( &error ); + p_dbus_message_iter_init( reply, &dict ); + p_dbus_message_iter_recurse( &dict, &prop_iter ); + while ((prop_name = dbus_next_dict_entry( &prop_iter, &variant ))) + { + if (!strcmp( prop_name, "Interface" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_STRING) + { + const char *interface; + size_t len; + + p_dbus_message_iter_get_basic( &variant, &interface ); + len = min( strlen( interface ), sizeof( info->description ) - 1 ); + memcpy( info->description, interface, len); + info->description[len] = '\0'; + } + else if (!strcmp( prop_name, "State" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + dbus_uint32_t state; + + p_dbus_message_iter_get_basic( &variant, &state ); + switch (state) + { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_FAILED: + case NM_DEVICE_STATE_SECONDARIES: + info->state = wlan_interface_state_not_ready; + break; + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_PREPARE: + info->state = wlan_interface_state_associating; + break; + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + info->state = wlan_interface_state_discovering; + break; + case NM_DEVICE_STATE_NEED_AUTH: + info->state = wlan_interface_state_authenticating; + break; + case NM_DEVICE_STATE_ACTIVATED: + info->state = wlan_interface_state_connected; + break; + case NM_DEVICE_STATE_DEACTIVATING: + info->state = wlan_interface_state_disconnecting; + break; + case NM_DEVICE_STATE_DISCONNECTED: + info->state = wlan_interface_state_disconnected; + break; + default: + FIXME( "Unknown NMDeviceState value %d\n", (int)state ); + info->state = wlan_interface_state_not_ready; + break; + } + } + } + p_dbus_message_unref(reply); + return TRUE; +} + +NTSTATUS networkmanager_get_wifi_devices( void *connection, struct list *devices ) +{ + DBusMessage *request, *reply; + char **object_paths = NULL; + int n_objects, i; + dbus_bool_t success; + DBusError error; + + request = + p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, "/org/freedesktop/NetworkManager", + NETWORKMANAGER_INTERFACE_MANAGER, "GetDevices" ); + if (!request) return STATUS_NO_MEMORY; + + 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( "Could not get list of network devices: %s: %s.\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + return ret; + } + + p_dbus_error_free( &error ); + p_dbus_error_init( &error ); + success = p_dbus_message_get_args( reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, + &object_paths, &n_objects, DBUS_TYPE_INVALID ); + if (!success) + { + NTSTATUS ret = dbus_error_to_ntstatus( &error ); + ERR( "Could not read object paths from GetDevices reply: %s: %s.\n", + debugstr_a( error.name ), debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + return ret; + } + + p_dbus_error_free( &error ); + for (i = 0; i < n_objects; i++) + { + const char *object_path = object_paths[i]; + struct unix_wlan_interface_info info = {0}; + + if (networkmanager_device_is_wifi( connection, object_path ) && + networkmanager_device_path_to_guid( object_path, &info.guid ) && + networkmanager_wifi_device_get_info( connection, object_path, &info )) + { + struct wlan_interface *entry = malloc( sizeof(*entry) ); + if (!entry) continue; + entry->info = info; + list_add_head( devices, &entry->entry ); + } + } + + p_dbus_free_string_array( object_paths ); + 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/main.c b/dlls/wlanapi/main.c index 6335088973c..35d65efcdd1 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -27,12 +27,14 @@ */
#include <stdarg.h> +#include <stdlib.h>
#include <ntstatus.h> #define WIN32_NO_STATUS
#include "windef.h" #include "winbase.h" + #include "wine/debug.h" #include "wine/unixlib.h"
@@ -79,9 +81,12 @@ static HANDLE handle_new(struct wine_wlan **entry) DWORD WINAPI WlanEnumInterfaces(HANDLE handle, void *reserved, WLAN_INTERFACE_INFO_LIST **interface_list) { struct wine_wlan *wlan; + struct wlan_get_interfaces_params args = {0}; + SIZE_T count = 0, list_size; WLAN_INTERFACE_INFO_LIST *ret_list; + NTSTATUS status;
- FIXME("(%p, %p, %p) semi-stub\n", handle, reserved, interface_list); + TRACE( "(%p, %p, %p)\n", handle, reserved, interface_list );
if (!handle || reserved || !interface_list) return ERROR_INVALID_PARAMETER; @@ -90,12 +95,67 @@ DWORD WINAPI WlanEnumInterfaces(HANDLE handle, void *reserved, WLAN_INTERFACE_IN if (!wlan) return ERROR_INVALID_HANDLE;
- ret_list = WlanAllocateMemory(sizeof(WLAN_INTERFACE_INFO_LIST)); + args.handle = wlan->unix_handle; + status = UNIX_WLAN_CALL( wlan_get_interfaces, &args ); + if (status != STATUS_SUCCESS) + { + ERR( "Could not get list of interfaces from host: %lx.\n", status ); + return RtlNtStatusToDosError( status ); + } + else + count = args.len; + + list_size = offsetof(WLAN_INTERFACE_INFO_LIST, InterfaceInfo[count ? count : 1]); + ret_list = WlanAllocateMemory(list_size); if (!ret_list) + { + if (args.interfaces) + { + struct wlan_free_interfaces_params free_args = {0}; + + free_args.interfaces = args.interfaces; + UNIX_WLAN_CALL( wlan_free_interfaces, &free_args ); + } return ERROR_NOT_ENOUGH_MEMORY; + }
- memset(&ret_list->InterfaceInfo[0], 0, sizeof(WLAN_INTERFACE_INFO)); - ret_list->dwNumberOfItems = 0; + memset( ret_list, 0, list_size ); + if (args.interfaces) + { + struct wlan_copy_and_free_interfaces_params copy_args = {0}; + struct unix_wlan_interface_info *unix_ifaces = NULL; + SIZE_T i; + + unix_ifaces = malloc( sizeof( *unix_ifaces ) * count ); + if (!unix_ifaces) + { + struct wlan_free_interfaces_params free_args = {0}; + + free_args.interfaces = args.interfaces; + UNIX_WLAN_CALL( wlan_free_interfaces, &free_args ); + WlanFreeMemory( ret_list ); + return ERROR_NOT_ENOUGH_MEMORY; + } + + copy_args.info = unix_ifaces; + copy_args.interfaces = args.interfaces; + UNIX_WLAN_CALL( wlan_copy_and_free_interfaces, ©_args ); + + for (i = 0; i < count; i++) + { + const size_t desc_max = + sizeof( ret_list->InterfaceInfo[i].strInterfaceDescription ) / sizeof( WCHAR ); + + ret_list->InterfaceInfo[i].InterfaceGuid = unix_ifaces[i].guid; + ret_list->InterfaceInfo[i].isState = unix_ifaces[i].state; + + mbstowcs( ret_list->InterfaceInfo[i].strInterfaceDescription, + unix_ifaces[i].description, desc_max ); + ret_list->InterfaceInfo[i].strInterfaceDescription[desc_max - 1] = '\0'; + } + free( unix_ifaces ); + } + ret_list->dwNumberOfItems = args.interfaces ? count : 0; ret_list->dwIndex = 0; /* unused in this function */ *interface_list = ret_list;
diff --git a/dlls/wlanapi/unixlib.c b/dlls/wlanapi/unixlib.c index 92311ffb856..8888f620ed0 100644 --- a/dlls/wlanapi/unixlib.c +++ b/dlls/wlanapi/unixlib.c @@ -24,10 +24,14 @@
#include "config.h"
+#include <stdlib.h> + #include <ntstatus.h> #define WIN32_NO_STATUS #include <winternl.h> +#include <wlanapi.h>
+#include <wine/list.h> #include <wine/unixlib.h>
#include "unixlib.h" @@ -62,10 +66,74 @@ NTSTATUS wlan_close_handle( void *params ) return STATUS_SUCCESS; }
+NTSTATUS wlan_get_interfaces( void *params ) +{ + struct wlan_get_interfaces_params *args = params; + struct list *ifaces; + NTSTATUS status; + + if (!initialized) + return STATUS_NOT_SUPPORTED; + + ifaces = malloc( sizeof( *ifaces ) ); + if (!ifaces) return STATUS_NO_MEMORY; + + list_init( ifaces ); + status = networkmanager_get_wifi_devices( (void *)args->handle, ifaces ); + if (status != STATUS_SUCCESS) + { + free( ifaces ); + return status; + } + + args->interfaces = (UINT_PTR)ifaces; + args->len = list_count( ifaces ); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_copy_and_free_interfaces( void *params ) +{ + struct wlan_copy_and_free_interfaces_params *args = params; + struct wlan_interface *ifaces = (struct wlan_interface *)args->interfaces; + struct wlan_interface *cur, *next; + SIZE_T i = 0; + + LIST_FOR_EACH_ENTRY_SAFE(cur, next, &ifaces->entry, struct wlan_interface, entry) + { + args->info[i++] = cur->info; + list_remove( &cur->entry ); + free( cur ); + } + + free( ifaces ); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_free_interfaces( void *params ) +{ + struct wlan_free_interfaces_params *args = params; + struct wlan_interface *ifaces = (struct wlan_interface *)args->interfaces; + struct wlan_interface *cur, *next; + + LIST_FOR_EACH_ENTRY_SAFE(cur, next, &ifaces->entry, struct wlan_interface, entry) + { + list_remove( &cur->entry ); + free( cur ); + } + + free( ifaces ); + return STATUS_SUCCESS; +} + const unixlib_entry_t __wine_unix_call_funcs[] = { wlan_init, wlan_open_handle, - wlan_close_handle + wlan_close_handle, + + wlan_get_interfaces, + wlan_copy_and_free_interfaces, + + wlan_free_interfaces, };
C_ASSERT( ARRAYSIZE( __wine_unix_call_funcs ) == unix_funcs_count ); diff --git a/dlls/wlanapi/unixlib.h b/dlls/wlanapi/unixlib.h index 9bf2149e7c3..0f9f41ffb3d 100644 --- a/dlls/wlanapi/unixlib.h +++ b/dlls/wlanapi/unixlib.h @@ -33,6 +33,33 @@ struct wlan_close_handle_params UINT_PTR handle; };
+struct wlan_get_interfaces_params +{ + UINT_PTR handle; + + UINT_PTR interfaces; + SIZE_T len; +}; + +struct unix_wlan_interface_info +{ + GUID guid; + CHAR description[256]; + WLAN_INTERFACE_STATE state; +}; + +struct wlan_copy_and_free_interfaces_params +{ + UINT_PTR interfaces; + + struct unix_wlan_interface_info *info; +}; + +struct wlan_free_interfaces_params +{ + UINT_PTR interfaces; +}; + enum wlanpi_funcs { unix_wlan_init, @@ -40,6 +67,10 @@ enum wlanpi_funcs unix_wlan_open_handle, unix_wlan_close_handle,
+ unix_wlan_get_interfaces, + unix_wlan_copy_and_free_interfaces, + unix_wlan_free_interfaces, + unix_funcs_count };
diff --git a/dlls/wlanapi/unixlib_priv.h b/dlls/wlanapi/unixlib_priv.h index fa813d07844..9b6982f0e46 100644 --- a/dlls/wlanapi/unixlib_priv.h +++ b/dlls/wlanapi/unixlib_priv.h @@ -21,8 +21,15 @@ #ifndef __WINE_WLANAPI_UNIXLIB_PRIV_H #define __WINE_WLANAPI_UNIXLIB_PRIV_H
+struct wlan_interface +{ + struct list entry; + struct unix_wlan_interface_info info; +}; + extern BOOL load_dbus_functions( void ); extern NTSTATUS init_dbus_connection( UINT_PTR *handle ); extern void close_dbus_connection( void *c ); +extern NTSTATUS networkmanager_get_wifi_devices( void *connection, struct list *devices );
#endif /* __WINE_WLANAPI_UNIXLIB_PRIV_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/tests/wlanapi.c | 82 ++++++++++++++++++++++++++++++++++++ include/wlanapi.h | 2 + 2 files changed, 84 insertions(+)
diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index 5c26e6d8ba0..5b52dad7a3b 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -182,6 +182,87 @@ static void test_WlanEnumInterfaces(void) ok(ret == 0, "Expected 0, got %ld\n", ret); }
+static void test_WlanGetAvailableNetworkList( void ) +{ + HANDLE handle; + DWORD neg_version, i, ret, reserved = 0xdeadbeef; + WLAN_INTERFACE_INFO_LIST *ifaces; + + ret = WlanOpenHandle(1, NULL, &neg_version, &handle); + ok(ret == 0, "Expected 0, got %ld\n", ret); + + ret = WlanEnumInterfaces( handle, NULL, &ifaces ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!ifaces || !ifaces->dwNumberOfItems) + { + skip( "No wireless interfaces\n" ); + WlanCloseHandle( handle, NULL ); + WlanFreeMemory( ifaces ); + return; + } + + trace("Wireless interfaces: %ld\n", ifaces->dwNumberOfItems); + for (i = 0; i < ifaces->dwNumberOfItems;i ++) + { + WLAN_INTERFACE_INFO *info; + WLAN_AVAILABLE_NETWORK_LIST *bad_list = (WLAN_AVAILABLE_NETWORK_LIST *)0xdeadbeef, + *list = bad_list; + DWORD j; + + info = &ifaces->InterfaceInfo[i]; + trace( " Index[%ld] GUID: %s\n", i, debugstr_guid( &info->InterfaceGuid ) ); + + /* invalid parameters */ + ret = WlanGetAvailableNetworkList( NULL, NULL, 0, NULL, &list ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + ret = WlanGetAvailableNetworkList( handle, &info->InterfaceGuid, 0, &reserved, &list ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + ret = WlanGetAvailableNetworkList( handle, NULL, 0, NULL, &list ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + + /* valid parameters */ + ret = WlanGetAvailableNetworkList( handle, &info->InterfaceGuid, 0, NULL, &list ); + todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!list || !list->dwNumberOfItems) + { + skip( "No wireless networks\n" ); + WlanFreeMemory( list ); + continue; + } + + for (j = 0; j < list->dwNumberOfItems; j++) + { + WLAN_AVAILABLE_NETWORK *network = &list->Network[j]; + + todo_wine ok( network->dot11Ssid.uSSIDLength <= sizeof( network->dot11Ssid.ucSSID ), + "Unexpected length for uSSID, should be <= 32: %ld\n", + network->dot11Ssid.uSSIDLength ); + + trace( + " Index[%ld] SSID: %s\n", j, + debugstr_an( (char *)network->dot11Ssid.ucSSID, network->dot11Ssid.uSSIDLength ) ); + if (network->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) + { + trace(" connected\n"); + } + else + { + trace(" not connected\n"); + } + trace( " Signal Quality: %ld\n", network->wlanSignalQuality ); + } + + WlanFreeMemory( list ); + } + + WlanFreeMemory( ifaces ); + ret = WlanCloseHandle( handle, NULL ); + ok( ret == 0, "Expected 0, got %ld\n", ret ); +} + START_TEST(wlanapi) { HANDLE handle; @@ -198,4 +279,5 @@ START_TEST(wlanapi) test_WlanOpenHandle(); test_WlanAllocateFreeMemory(); test_WlanEnumInterfaces(); + test_WlanGetAvailableNetworkList(); } diff --git a/include/wlanapi.h b/include/wlanapi.h index 5150ff09f47..70cc3a45d78 100644 --- a/include/wlanapi.h +++ b/include/wlanapi.h @@ -109,6 +109,8 @@ typedef enum _DOT11_CIPHER_ALGORITHM
#define WLAN_MAX_PHY_TYPE_NUMBER 8
+#define WLAN_AVAILABLE_NETWORK_CONNECTED 0x1 + typedef struct _WLAN_AVAILABLE_NETWORK { WCHAR strProfileName[256];
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/dbus.c | 464 ++++++++++++++++++++++++++++++++++- dlls/wlanapi/main.c | 42 +++- dlls/wlanapi/tests/wlanapi.c | 16 +- dlls/wlanapi/unixlib.c | 64 ++++- dlls/wlanapi/unixlib.h | 25 ++ dlls/wlanapi/unixlib_priv.h | 31 ++- include/windot11.h | 2 + include/wlanapi.h | 5 + 8 files changed, 633 insertions(+), 16 deletions(-)
diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c index dca8156afe5..f0e3ea124e2 100644 --- a/dlls/wlanapi/dbus.c +++ b/dlls/wlanapi/dbus.c @@ -55,6 +55,9 @@ DBUS_FUNCS;
#define NETWORKMANAGER_INTERFACE_MANAGER "org.freedesktop.NetworkManager" #define NETWORKMANAGER_INTERFACE_DEVICE "org.freedesktop.NetworkManager.Device" +#define NETWORKMANAGER_INTERFACE_DEVICE_WIRELESS "org.freedesktop.NetworkManager.Device.Wireless" +#define NETWORKMANAGER_INTERFACE_ACCESS_POINT "org.freedesktop.NetworkManager.AccessPoint" +#define NETWORKMANAGER_INTERFACE_CONNECTION_ACTIVE "org.freedesktop.NetworkManager.Connection.Active"
BOOL load_dbus_functions( void ) { @@ -183,15 +186,46 @@ static BOOL networkmanager_device_is_wifi( void *connection, const char *object_ index. We use index as the last 4 bytes of this GUID to create a Win32 WLAN interface GUID. */ const static GUID NETWORKMANAGER_DEVICE_BASE_INTERFACE_GUID = { 0xa53634f7, 0xc1bc, 0x4d41, { 0xbc, 0x06, 0xd3, 0xf7, 0x00, 0x00, 0x00, 0x00 } }; +#define NETWORKMANAGER_DEVICE_PATH_PREFIX "/org/freedesktop/NetworkManager/Devices/" + +static BOOL networkmanager_valid_device_guid( const GUID *guid ) +{ + return !memcmp( &NETWORKMANAGER_DEVICE_BASE_INTERFACE_GUID, guid, offsetof( GUID, Data4[4] ) ); +} + +static __WINE_MALLOC char *networkmanager_device_guid_to_path( const GUID *guid ) +{ + char *path; + UINT32 idx = *(UINT32 *)&guid->Data4[4]; + size_t orig_size = sizeof( NETWORKMANAGER_DEVICE_PATH_PREFIX ) + 3; + size_t size; + + path = malloc( orig_size ); + if (!path) return NULL; + + size = snprintf( path, orig_size, NETWORKMANAGER_DEVICE_PATH_PREFIX "%u", idx ); + if (size >= orig_size) + { + char *ptr = realloc( path, size ); + if (!ptr) + { + free( path ); + return NULL; + } + path = ptr; + snprintf( path, size, NETWORKMANAGER_DEVICE_PATH_PREFIX "%u", idx ); + } + + return path; +}
static BOOL networkmanager_device_path_to_guid( const char *object_path, GUID *guid ) { - const static char device_prefix[] = "/org/freedesktop/NetworkManager/Devices/"; - BOOL is_device = strncmp( object_path, device_prefix, sizeof( device_prefix ) ); + BOOL is_device = strncmp( object_path, NETWORKMANAGER_DEVICE_PATH_PREFIX, sizeof( NETWORKMANAGER_DEVICE_PATH_PREFIX ) ); UINT32 idx;
if (!is_device) return FALSE; - idx = atoi( object_path + sizeof(device_prefix) - 1 ); + idx = atoi( object_path + sizeof( NETWORKMANAGER_DEVICE_PATH_PREFIX ) - 1 ); if (!idx) /* NetworkManager doesn't seem to use 0 as an index for devices. */ { ERR( "Could not parse index from device path %s:\n", debugstr_a( object_path )); @@ -384,8 +418,432 @@ NTSTATUS networkmanager_get_wifi_devices( void *connection, struct list *devices return STATUS_SUCCESS; }
+static void parse_mac_address( const char *addr_str, BYTE dest[6] ) +{ + int addr[6], i; + + sscanf( addr_str, "%x:%x:%x:%x:%x:%x", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], + &addr[5] ); + for (i = 0 ; i < 6; i++) + dest[i] = addr[i]; +} + +static BOOL networkmanager_get_access_point_info( void *connection, const char *object_path, + struct wlan_bss_info *network ) +{ + DBusMessage *request, *reply; + DBusMessageIter dict, prop_iter, variant; + DBusError error; + dbus_bool_t success; + const char *prop_name; + const char *iface_accesspoint = NETWORKMANAGER_INTERFACE_ACCESS_POINT; + + TRACE( "(%p, %s, %p)\n", connection, debugstr_a( object_path ), network ); + request = p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, object_path, + DBUS_INTERFACE_PROPERTIES, "GetAll" ); + if (!request) return FALSE; + success = p_dbus_message_append_args( request, DBUS_TYPE_STRING, &iface_accesspoint, + DBUS_TYPE_INVALID ); + if (!success) + { + p_dbus_message_unref( request ); + return FALSE; + } + + 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) + { + ERR( "Could not get proerties for access point %s: %s: %s.\n", debugstr_a( object_path ), + debugstr_a( error.name ), debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + return FALSE; + } + + + p_dbus_error_free( &error ); + p_dbus_message_iter_init( reply, &dict ); + p_dbus_message_iter_recurse( &dict, &prop_iter ); + while ((prop_name = dbus_next_dict_entry( &prop_iter, &variant ))) + { + if (!strcmp( prop_name, "Flags" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->flags ); + } + else if (!strcmp( prop_name, "WpaFlags" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->wpa_flags ); + } + else if (!strcmp( prop_name, "RsnFlags" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->rsn_flags ); + } + else if (!strcmp( prop_name, "Ssid" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_ARRAY && + p_dbus_message_iter_get_element_type( &variant ) == DBUS_TYPE_BYTE) + { + DBusMessageIter iter; + const char *ssid; + int len; + + p_dbus_message_iter_recurse( &variant, &iter ); + p_dbus_message_iter_get_fixed_array( &iter, &ssid, &len ); + if (len > sizeof( network->ssid )) + WARN( "SSID %s for %s is too long\n", debugstr_a( object_path ), + debugstr_an( ssid, len ) ); + + memcpy( network->ssid, ssid, min( len, sizeof( network->ssid ) ) ); + network->ssid_len = min( len, sizeof( network->ssid ) ); + } + else if (!strcmp( prop_name, "Frequency" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->frequency ); + } + else if (!strcmp( prop_name, "HwAddress") && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_STRING) + { + const char *addr_str; + + p_dbus_message_iter_get_basic( &variant, &addr_str ); + if (strlen( addr_str ) != 17) + ERR( "Unexpected HwAddress %s for %s\n", debugstr_a( addr_str ), + debugstr_a( object_path ) ); + + parse_mac_address( addr_str, network->hw_address ); + } + else if (!strcmp( prop_name, "Mode" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->mode ); + } + else if (!strcmp( prop_name, "MaxBitrate") && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->max_bitrate ); + } + else if (!strcmp( prop_name, "Bandwidth" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( &variant, &network->bandwidth ); + } + else if (!strcmp( prop_name, "Strength" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_BYTE) + { + p_dbus_message_iter_get_basic( &variant, &network->strength ); + } + else if (!strcmp( prop_name, "LastSeen") && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_INT32) + { + p_dbus_message_iter_get_basic( &variant, &network->last_seen ); + } + + } + + p_dbus_message_unref( reply ); + return TRUE; +} + +static char *__WINE_MALLOC networkmanager_device_get_active_ap( void *connection, + const char *device_path ) +{ + DBusMessage *request, *reply; + DBusMessageIter iter, variant; + DBusError error; + const char *str; + char *dup; + const char *device_iface = NETWORKMANAGER_INTERFACE_DEVICE, + *conn_active_iface = NETWORKMANAGER_INTERFACE_CONNECTION_ACTIVE; + const char *activeconn_prop = "ActiveConnection", *specobj_prop = "SpecificObject"; + dbus_bool_t success; + + request = p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, device_path, + DBUS_INTERFACE_PROPERTIES, + "Get" ); + if (!request) return NULL; + success = p_dbus_message_append_args( request, DBUS_TYPE_STRING, &device_iface, + DBUS_TYPE_STRING, &activeconn_prop, DBUS_TYPE_INVALID ); + if (!success) + { + p_dbus_message_unref( request ); + return NULL; + } + + 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) + { + p_dbus_error_free( &error ); + return NULL; + } + p_dbus_error_free( &error ); + + p_dbus_message_iter_init( reply, &iter ); + p_dbus_message_iter_recurse( &iter, &variant ); + if (p_dbus_message_iter_get_arg_type( &variant ) != DBUS_TYPE_OBJECT_PATH) + { + ERR( "Unexpected signature for property ActiveConnection: %c\n", + p_dbus_message_iter_get_arg_type( &variant ) ); + return NULL; + } + p_dbus_message_iter_get_basic( &variant, &str ); + + request = p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, str, + DBUS_INTERFACE_PROPERTIES, "Get" ); + p_dbus_message_unref( reply ); + + if (!request) return NULL; + success = p_dbus_message_append_args( request, DBUS_TYPE_STRING, &conn_active_iface, + DBUS_TYPE_STRING, &specobj_prop, DBUS_TYPE_INVALID ); + if (!success) + { + p_dbus_message_unref( request ); + return NULL; + } + + 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) + { + ERR( "Could not get properties for %s: %s: %s.\n", debugstr_a( device_path ), error.name, + error.message ); + p_dbus_error_free( &error ); + return NULL; + } + p_dbus_error_free( &error ); + p_dbus_message_iter_init( reply, &iter ); + p_dbus_message_iter_recurse( &iter, &variant ); + if ( p_dbus_message_iter_get_arg_type( &variant ) != DBUS_TYPE_OBJECT_PATH ) + { + ERR( "Unexpected signature for property SpecificObject: %c\n", + p_dbus_message_iter_get_arg_type( &variant ) ); + return NULL; + } + + p_dbus_message_iter_get_basic( &variant, &str ); + dup = strdup( str ); + p_dbus_message_unref( reply ); + + return dup; +} + +NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device, struct list *access_points ) +{ + DBusMessage *request, *reply; + DBusError error; + dbus_bool_t success; + char *device_path, *active_ap = NULL; + char **object_paths; + int n_objects, i; + + TRACE( "(%p, %s, %p)\n", connection, debugstr_guid( device ), access_points ); + + if (!networkmanager_valid_device_guid( device )) return STATUS_INVALID_PARAMETER; + device_path = networkmanager_device_guid_to_path( device ); + if (!device_path) return STATUS_NO_MEMORY; + + request = p_dbus_message_new_method_call( NETWORKMANAGER_SERVICE, device_path, + NETWORKMANAGER_INTERFACE_DEVICE_WIRELESS, + "GetAllAccessPoints" ); + active_ap = networkmanager_device_get_active_ap( connection, device_path ); + + free( device_path ); + if (!request) + { + free( active_ap ); + return STATUS_NO_MEMORY; + } + + 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( "Could not get list of access points: %s: %s.\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + free( active_ap ); + return ret; + } + + p_dbus_error_free( &error ); + p_dbus_error_init( &error ); + success = p_dbus_message_get_args( reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, + &object_paths, &n_objects, DBUS_TYPE_INVALID ); + if (!success) + { + NTSTATUS ret = dbus_error_to_ntstatus( &error ); + ERR( "Could not read object paths from GetDevices reply: %s: %s.\n", + debugstr_a( error.name ), debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + free( active_ap ); + return ret; + } + + p_dbus_error_free( &error ); + for (i = 0; i < n_objects; i++) + { + const char *object_path = object_paths[i]; + struct wlan_bss_info info = {0}; + + if (networkmanager_get_access_point_info( connection, object_path, &info )) + { + struct wlan_network *network = calloc( 1, sizeof( *network ) ); + + if (!network) continue; + network->info = info; + network->info.connected = active_ap && !strcmp( active_ap, object_path ); + list_add_tail( access_points, &network->entry ); + } + } + + free( active_ap ); + p_dbus_free_string_array( object_paths ); + 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; } void close_dbus_connection( void *c ) { return STATUS_NOT_SUPPORTED; } +NTSTATUS networkmanager_get_wifi_devices( void *connection, struct list *devices ) +{ + return STATUS_NOT_SUPPORTED; +} +NTSTATUS networkmanager_get_access_points( void *connection, GUID device, + struct list *access_points ) +{ + return STATUS_NOT_SUPPORTED; +} #endif + +#define NM_802_11_MODE_UNKNOWN 0 +#define NM_802_11_MODE_ADHOC 1 +#define NM_802_11_MODE_INFRA 2 +#define NM_802_11_MODE_AP 3 +#define NM_802_11_MODE_MESH 4 + +#define NM_802_11_AP_FLAGS_NONE 0x00000000 +#define NM_802_11_AP_FLAGS_PRIVACY 0x00000001 +#define NM_802_11_AP_FLAGS_WPS 0x00000002 +#define NM_802_11_AP_FLAGS_WPS_PBC 0x00000004 +#define NM_802_11_AP_FLAGS_WPS_PIN 0x00000008 + +#define NM_802_11_AP_SEC_NONE 0x00000000 +#define NM_802_11_AP_SEC_PAIR_WEP40 0x00000001 +#define NM_802_11_AP_SEC_PAIR_WEP104 0x00000002 +#define NM_802_11_AP_SEC_PAIR_TKIP 0x00000004 +#define NM_802_11_AP_SEC_PAIR_CCMP 0x00000008 +#define NM_802_11_AP_SEC_GROUP_WEP40 0x00000010 +#define NM_802_11_AP_SEC_GROUP_WEP104 0x00000020 +#define NM_802_11_AP_SEC_GROUP_TKIP 0x00000040 +#define NM_802_11_AP_SEC_GROUP_CCMP 0x00000080 +#define NM_802_11_AP_SEC_KEY_MGMT_PSK 0x00000100 +#define NM_802_11_AP_SEC_KEY_MGMT_802_1X 0x00000200 +#define NM_802_11_AP_SEC_KEY_MGMT_SAE 0x00000400 +#define NM_802_11_AP_SEC_KEY_MGMT_OWE 0x00000800 +#define NM_802_11_AP_SEC_KEY_MGMT_OWE_TM 0x00001000 +#define NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 0x00002000 + +void wlan_bss_info_to_WLAN_AVAILABLE_NETWORK( const struct wlan_bss_info *info, + WLAN_AVAILABLE_NETWORK *dest ) +{ + memset( dest, 0, sizeof( *dest ) ); + + memcpy( dest->dot11Ssid.ucSSID, info->ssid, sizeof( info->ssid ) ); + dest->dot11Ssid.uSSIDLength = info->ssid_len; + dest->dot11BssType = info->mode == NM_802_11_MODE_INFRA ? dot11_BSS_type_infrastructure + : dot11_BSS_type_independent; + dest->uNumberOfBssids = 1; + dest->bNetworkConnectable = TRUE; + dest->uNumberOfPhyTypes = 1; + /* Use dot11_phy_type_any for now, as NetworkManager AccessPoints object do not have an equivalent + * property. */ + dest->dot11PhyTypes[0] = dot11_phy_type_any; + dest->bMorePhyTypes = FALSE; + dest->wlanSignalQuality = info->strength; + dest->bSecurityEnabled = !(info->flags & NM_802_11_AP_FLAGS_PRIVACY); + + if (info->rsn_flags) + { + if (info->rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_RSNA; + if (info->rsn_flags & NM_802_11_AP_SEC_GROUP_TKIP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_TKIP; + else if (info->rsn_flags & NM_802_11_AP_SEC_PAIR_CCMP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_CCMP; + else if (info->rsn_flags & (NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP)) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_RSN_USE_GROUP; + } + if (info->rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_WPA3_ENT_192; + if (info->rsn_flags & NM_802_11_AP_SEC_GROUP_TKIP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_TKIP; + else if (info->rsn_flags & NM_802_11_AP_SEC_PAIR_CCMP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_CCMP; + else if (info->rsn_flags & (NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP)) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_RSN_USE_GROUP; + } + if (info->rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_WPA3_SAE; + dest->dot11DefaultCipherAlgorithm = info->rsn_flags & NM_802_11_AP_SEC_PAIR_TKIP + ? DOT11_CIPHER_ALGO_TKIP + : DOT11_CIPHER_ALGO_CCMP; + } + if (info->rsn_flags & (NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_OWE; + dest->dot11DefaultCipherAlgorithm = info->rsn_flags & NM_802_11_AP_SEC_PAIR_TKIP + ? DOT11_CIPHER_ALGO_TKIP + : DOT11_CIPHER_ALGO_CCMP; + } + } + else if (info->wpa_flags) + { + if (info->wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_WPA; + if (info->wpa_flags & NM_802_11_AP_SEC_GROUP_TKIP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_TKIP; + else if (info->wpa_flags & NM_802_11_AP_SEC_PAIR_CCMP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_CCMP; + else if (info->wpa_flags & (NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP)) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_WPA_USE_GROUP; + } + if (info->wpa_flags & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104)) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_80211_SHARED_KEY; + dest->dot11DefaultCipherAlgorithm = + info->wpa_flags & ( NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_GROUP_WEP40 ) + ? DOT11_CIPHER_ALGO_WEP40 + : DOT11_CIPHER_ALGO_WEP104; + } + if (info->wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + { + dest->dot11DefaultAuthAlgorithm = DOT11_AUTH_ALGO_WPA_PSK; + if (info->wpa_flags & NM_802_11_AP_SEC_GROUP_TKIP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_TKIP; + else if (info->wpa_flags & NM_802_11_AP_SEC_PAIR_CCMP) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_CCMP; + else if (info->wpa_flags & (NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP)) + dest->dot11DefaultCipherAlgorithm = DOT11_CIPHER_ALGO_WPA_USE_GROUP; + } + } + + if (info->connected) + dest->dwFlags |= WLAN_AVAILABLE_NETWORK_CONNECTED; +} diff --git a/dlls/wlanapi/main.c b/dlls/wlanapi/main.c index 35d65efcdd1..648f7433d0d 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -239,10 +239,46 @@ DWORD WINAPI WlanRegisterNotification(HANDLE handle, DWORD notify_source, BOOL i DWORD WINAPI WlanGetAvailableNetworkList(HANDLE handle, const GUID *guid, DWORD flags, void *reserved, WLAN_AVAILABLE_NETWORK_LIST **network_list) { - FIXME("(%p, %s, 0x%lx, %p, %p) stub\n", - handle, wine_dbgstr_guid(guid), flags, reserved, network_list); + struct wine_wlan *wlan; + struct wlan_network_list_get_params params = {0}; + struct wlan_network_list_move_to_avail_network_params move_params = {0}; + WLAN_AVAILABLE_NETWORK_LIST *ret_list; + NTSTATUS status;
- return ERROR_CALL_NOT_IMPLEMENTED; + TRACE( "(%p, %s, 0x%lx, %p, %p)\n", handle, wine_dbgstr_guid( guid ), flags, reserved, + network_list ); + + if (!handle || !guid || reserved || !network_list) + return ERROR_INVALID_PARAMETER; + + wlan = handle_index( handle ); + if (!wlan) + return ERROR_INVALID_HANDLE; + + params.handle = wlan->unix_handle; + params.interface = guid; + status = UNIX_WLAN_CALL( wlan_network_list_get, ¶ms ); + if (status != STATUS_SUCCESS) + return RtlNtStatusToDosError( status ); + + ret_list = WlanAllocateMemory( offsetof( WLAN_AVAILABLE_NETWORK_LIST, Network[params.len] ) ); + if (!ret_list) + { + struct wlan_network_list_free_params free_params = {0}; + free_params.networks = params.networks; + UNIX_WLAN_CALL( wlan_network_list_free, &free_params ); + return ERROR_NOT_ENOUGH_MEMORY; + } + + move_params.networks = params.networks; + move_params.dest = ret_list->Network; + UNIX_WLAN_CALL( wlan_network_list_move_to_avail_network, &move_params ); + + ret_list->dwNumberOfItems = params.len; + ret_list->dwIndex = 0; + *network_list = ret_list; + + return ERROR_SUCCESS; }
DWORD WINAPI WlanQueryInterface(HANDLE handle, const GUID *guid, WLAN_INTF_OPCODE opcode, diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index 5b52dad7a3b..647a0a8ea10 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -214,18 +214,18 @@ static void test_WlanGetAvailableNetworkList( void )
/* invalid parameters */ ret = WlanGetAvailableNetworkList( NULL, NULL, 0, NULL, &list ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" ); ret = WlanGetAvailableNetworkList( handle, &info->InterfaceGuid, 0, &reserved, &list ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" ); ret = WlanGetAvailableNetworkList( handle, NULL, 0, NULL, &list ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" );
/* valid parameters */ ret = WlanGetAvailableNetworkList( handle, &info->InterfaceGuid, 0, NULL, &list ); - todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); if (!list || !list->dwNumberOfItems) { skip( "No wireless networks\n" ); @@ -237,7 +237,7 @@ static void test_WlanGetAvailableNetworkList( void ) { WLAN_AVAILABLE_NETWORK *network = &list->Network[j];
- todo_wine ok( network->dot11Ssid.uSSIDLength <= sizeof( network->dot11Ssid.ucSSID ), + ok( network->dot11Ssid.uSSIDLength <= sizeof( network->dot11Ssid.ucSSID ), "Unexpected length for uSSID, should be <= 32: %ld\n", network->dot11Ssid.uSSIDLength );
diff --git a/dlls/wlanapi/unixlib.c b/dlls/wlanapi/unixlib.c index 8888f620ed0..3b64c55730c 100644 --- a/dlls/wlanapi/unixlib.c +++ b/dlls/wlanapi/unixlib.c @@ -125,6 +125,65 @@ NTSTATUS wlan_free_interfaces( void *params ) return STATUS_SUCCESS; }
+NTSTATUS wlan_network_list_get( void *params ) +{ + NTSTATUS status; + struct wlan_network_list_get_params *args = params; + struct list *networks; + + if (!initialized) + return STATUS_NOT_SUPPORTED; + + networks = malloc( sizeof( *networks )); + if (!networks) return STATUS_NO_MEMORY; + + list_init( networks ); + status = networkmanager_get_access_points( (void *)args->handle, args->interface, networks ); + if (status != STATUS_SUCCESS) + { + free( networks ); + return status; + } + + args->networks = (UINT_PTR)networks; + args->len = list_count( networks ); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_network_list_move_to_avail_network( void *params ) +{ + struct wlan_network_list_move_to_avail_network_params *args = params; + struct wlan_network *networks = (struct wlan_network *)args->networks; + struct wlan_network *cur, *next; + SIZE_T i = 0; + + LIST_FOR_EACH_ENTRY_SAFE( cur, next, &networks->entry, struct wlan_network, entry) + { + wlan_bss_info_to_WLAN_AVAILABLE_NETWORK( &cur->info, &args->dest[i++] ); + list_remove( &cur->entry ); + free( cur ); + } + + free( networks ); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_network_list_free( void *params ) +{ + struct wlan_network_list_free_params *args = params; + struct wlan_network *networks = (struct wlan_network *)args->networks; + struct wlan_network *cur, *next; + + LIST_FOR_EACH_ENTRY_SAFE(cur, next, &networks->entry, struct wlan_network, entry) + { + list_remove( &cur->entry ); + free( cur ); + } + + free( networks ); + return STATUS_SUCCESS; +} + const unixlib_entry_t __wine_unix_call_funcs[] = { wlan_init, wlan_open_handle, @@ -132,8 +191,11 @@ const unixlib_entry_t __wine_unix_call_funcs[] = {
wlan_get_interfaces, wlan_copy_and_free_interfaces, - wlan_free_interfaces, + + wlan_network_list_get, + wlan_network_list_move_to_avail_network, + wlan_network_list_free, };
C_ASSERT( ARRAYSIZE( __wine_unix_call_funcs ) == unix_funcs_count ); diff --git a/dlls/wlanapi/unixlib.h b/dlls/wlanapi/unixlib.h index 0f9f41ffb3d..06c961c5e36 100644 --- a/dlls/wlanapi/unixlib.h +++ b/dlls/wlanapi/unixlib.h @@ -60,6 +60,27 @@ struct wlan_free_interfaces_params UINT_PTR interfaces; };
+struct wlan_network_list_get_params +{ + UINT_PTR handle; + const GUID *interface; + + UINT_PTR networks; + SIZE_T len; +}; + +struct wlan_network_list_move_to_avail_network_params +{ + UINT_PTR networks; + + WLAN_AVAILABLE_NETWORK *dest; +}; + +struct wlan_network_list_free_params +{ + UINT_PTR networks; +}; + enum wlanpi_funcs { unix_wlan_init, @@ -71,6 +92,10 @@ enum wlanpi_funcs unix_wlan_copy_and_free_interfaces, unix_wlan_free_interfaces,
+ unix_wlan_network_list_get, + unix_wlan_network_list_move_to_avail_network, + unix_wlan_network_list_free, + unix_funcs_count };
diff --git a/dlls/wlanapi/unixlib_priv.h b/dlls/wlanapi/unixlib_priv.h index 9b6982f0e46..3868218250f 100644 --- a/dlls/wlanapi/unixlib_priv.h +++ b/dlls/wlanapi/unixlib_priv.h @@ -21,15 +21,44 @@ #ifndef __WINE_WLANAPI_UNIXLIB_PRIV_H #define __WINE_WLANAPI_UNIXLIB_PRIV_H
+struct wlan_bss_info +{ + UINT32 flags; + UINT32 wpa_flags; + UINT32 rsn_flags; + + USHORT ssid_len; + BYTE ssid[32]; + + UINT32 frequency; + BYTE hw_address[6]; + UINT32 mode; + UINT32 max_bitrate; + UINT32 bandwidth; + UINT8 strength; + INT32 last_seen; + + BOOL connected; +}; + struct wlan_interface { struct list entry; struct unix_wlan_interface_info info; };
+struct wlan_network +{ + struct list entry; + struct wlan_bss_info info; +}; + extern BOOL load_dbus_functions( void ); extern NTSTATUS init_dbus_connection( UINT_PTR *handle ); extern void close_dbus_connection( void *c ); extern NTSTATUS networkmanager_get_wifi_devices( void *connection, struct list *devices ); - +extern NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device, + struct list *access_points ); +extern void wlan_bss_info_to_WLAN_AVAILABLE_NETWORK( const struct wlan_bss_info *info, + WLAN_AVAILABLE_NETWORK *dest ); #endif /* __WINE_WLANAPI_UNIXLIB_PRIV_H */ diff --git a/include/windot11.h b/include/windot11.h index 39effeb93ec..36b962be804 100644 --- a/include/windot11.h +++ b/include/windot11.h @@ -38,4 +38,6 @@ typedef enum _DOT11_PHY_TYPE typedef UCHAR DOT11_MAC_ADDRESS[6]; typedef DOT11_MAC_ADDRESS *PDOT11_MAC_ADDRESS;
+#define DOT11_RATE_SET_MAX_LENGTH 126 + #endif /* _WINDOT11_H */ diff --git a/include/wlanapi.h b/include/wlanapi.h index 70cc3a45d78..0db5c5e8899 100644 --- a/include/wlanapi.h +++ b/include/wlanapi.h @@ -89,6 +89,11 @@ typedef enum _DOT11_AUTH_ALGORITHM DOT11_AUTH_ALGO_WPA_NONE = 0x05, DOT11_AUTH_ALGO_RSNA = 0x06, DOT11_AUTH_ALGO_RSNA_PSK = 0x07, + DOT11_AUTH_ALGO_WPA3 = 8, + DOT11_AUTH_ALGO_WPA3_ENT_192 = 8, + DOT11_AUTH_ALGO_WPA3_SAE = 9, + DOT11_AUTH_ALGO_OWE = 10, + DOT11_AUTH_ALGO_WPA3_ENT = 11, DOT11_AUTH_ALGO_IHV_START = 0x80000000, DOT11_AUTH_ALGO_IHV_END = 0xFFFFFFFF } DOT11_AUTH_ALGORITHM, *PDOT11_AUTH_ALGORITHM;
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/main.c | 10 ++++++++++ dlls/wlanapi/wlanapi.spec | 2 +- include/wlanapi.h | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/dlls/wlanapi/main.c b/dlls/wlanapi/main.c index 648f7433d0d..fcccff42fa8 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -281,6 +281,16 @@ DWORD WINAPI WlanGetAvailableNetworkList(HANDLE handle, const GUID *guid, DWORD return ERROR_SUCCESS; }
+DWORD WINAPI WlanGetNetworkBssList( HANDLE handle, const GUID *guid, const DOT11_SSID *ssid, + DOT11_BSS_TYPE bss_type, BOOL security, void *reserved, + WLAN_BSS_LIST **bss_list ) +{ + FIXME( "(%p, %s, %p, %d, %d, %p, %p) stub\n", handle, debugstr_guid( guid ), ssid, bss_type, + security, reserved, bss_list ); + + return ERROR_CALL_NOT_IMPLEMENTED; +} + DWORD WINAPI WlanQueryInterface(HANDLE handle, const GUID *guid, WLAN_INTF_OPCODE opcode, void *reserved, DWORD *data_size, void **data, WLAN_OPCODE_VALUE_TYPE *opcode_type) { diff --git a/dlls/wlanapi/wlanapi.spec b/dlls/wlanapi/wlanapi.spec index 45d83c80b0f..6b47812d017 100644 --- a/dlls/wlanapi/wlanapi.spec +++ b/dlls/wlanapi/wlanapi.spec @@ -9,7 +9,7 @@ @ stdcall WlanGetAvailableNetworkList(ptr ptr long ptr ptr) @ stub WlanGetFilterList @ stub WlanGetInterfaceCapability -@ stub WlanGetNetworkBssList +@ stdcall WlanGetNetworkBssList(ptr ptr ptr long long ptr ptr) @ stub WlanGetProfile @ stub WlanGetProfileCustomUserData @ stub WlanGetProfileList diff --git a/include/wlanapi.h b/include/wlanapi.h index 0db5c5e8899..a050752d541 100644 --- a/include/wlanapi.h +++ b/include/wlanapi.h @@ -135,6 +135,38 @@ typedef struct _WLAN_AVAILABLE_NETWORK DWORD dwReserved; } WLAN_AVAILABLE_NETWORK, *PWLAN_AVAILABLE_NETWORK;
+typedef struct _WLAN_RATE_SET { + ULONG uRateSetLength; + USHORT usRateSet[DOT11_RATE_SET_MAX_LENGTH]; +} WLAN_RATE_SET, *PWLAN_RATE_SET; + +typedef struct _WLAN_BSS_ENTRY +{ + DOT11_SSID dot11Ssid; + ULONG uPhyId; + DOT11_MAC_ADDRESS dot11Bssid; + DOT11_BSS_TYPE dot11BssType; + DOT11_PHY_TYPE dot11BssPhyType; + LONG lRssi; + ULONG uLinkQuality; + BOOLEAN bInRegDomain; + USHORT usBeaconPeriod; + ULONGLONG ullTimestamp; + ULONGLONG ullHostTimestamp; + USHORT usCapabilityInformation; + ULONG ulChCenterFrequency; + WLAN_RATE_SET wlanRateSet; + ULONG ulIeOffset; + ULONG ulIeSize; +} WLAN_BSS_ENTRY, *PWLAN_BSS_ENTRY; + +typedef struct _WLAN_BSS_LIST +{ + DWORD dwTotalSize; + DWORD dwNumberOfItems; + WLAN_BSS_ENTRY wlanBssEntries[1]; +} WLAN_BSS_LIST, *PWLAN_BSS_LIST; + typedef enum _WLAN_INTF_OPCODE { wlan_intf_opcode_autoconf_start = 0x000000000, @@ -260,5 +292,7 @@ DWORD WINAPI WlanScan(HANDLE, const GUID *, const DOT11_SSID *, const WLAN_RAW_D DWORD WINAPI WlanRegisterNotification(HANDLE, DWORD, BOOL, WLAN_NOTIFICATION_CALLBACK, void *, void *, DWORD *); DWORD WINAPI WlanGetAvailableNetworkList(HANDLE, const GUID *, DWORD, void *, WLAN_AVAILABLE_NETWORK_LIST **); DWORD WINAPI WlanQueryInterface(HANDLE, const GUID *, WLAN_INTF_OPCODE, void *, DWORD *, void **, WLAN_OPCODE_VALUE_TYPE *); +DWORD WINAPI WlanGetNetworkBssList( HANDLE, const GUID *, const DOT11_SSID *, DOT11_BSS_TYPE, BOOL, + void *, WLAN_BSS_LIST ** );
#endif /* _WLAN_WLANAPI_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/tests/wlanapi.c | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+)
diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index 647a0a8ea10..6d8d7808a26 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -263,6 +263,82 @@ static void test_WlanGetAvailableNetworkList( void ) ok( ret == 0, "Expected 0, got %ld\n", ret ); }
+static void test_WlanGetNetworkBssList( void ) +{ + HANDLE handle; + DWORD neg_version, i, ret, reserved = 0xdeadbeef; + WLAN_INTERFACE_INFO_LIST *ifaces; + + ret = WlanOpenHandle(1, NULL, &neg_version, &handle); + ok(ret == 0, "Expected 0, got %ld\n", ret); + + ret = WlanEnumInterfaces( handle, NULL, &ifaces ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!ifaces || !ifaces->dwNumberOfItems) + { + skip( "No wireless interfaces\n" ); + WlanCloseHandle( handle, NULL ); + WlanFreeMemory( ifaces ); + return; + } + + trace("Wireless interfaces: %ld\n", ifaces->dwNumberOfItems); + + for (i = 0; i < ifaces->dwNumberOfItems; i++) + { + WLAN_INTERFACE_INFO *info; + WLAN_BSS_LIST *bad_list = (WLAN_BSS_LIST *)0xdeadbeef, *list = bad_list; + DWORD j; + + info = &ifaces->InterfaceInfo[i]; + trace( " Index[%ld] GUID: %s\n", i, debugstr_guid( &info->InterfaceGuid ) ); + + /* invalid parameters */ + ret = WlanGetNetworkBssList( NULL, NULL, NULL, 0, FALSE, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + ret = + WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, &reserved, &list ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + + /* valid paramters */ + ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, NULL, &list ); + todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!list || !list->dwNumberOfItems) + { + skip( "No wireless networks\n" ); + WlanFreeMemory( list ); + continue; + } + + for (j = 0; j < list->dwNumberOfItems; j++) + { + WLAN_BSS_ENTRY *entry = &list->wlanBssEntries[j]; + + todo_wine ok( entry->dot11Ssid.uSSIDLength <= sizeof( entry->dot11Ssid.ucSSID ), + "Unexpected length for uSSID, should be <= 32: %ld\n", + entry->dot11Ssid.uSSIDLength ); + + trace( + " Index[%ld] SSID: %s\n", j, + debugstr_an( (char *)entry->dot11Ssid.ucSSID, entry->dot11Ssid.uSSIDLength ) ); + } + + WlanFreeMemory( list ); + } + + WlanFreeMemory( ifaces ); + ret = WlanCloseHandle( handle, NULL ); + ok( ret == 0, "Expected 0, got %ld\n", ret ); +} + START_TEST(wlanapi) { HANDLE handle; @@ -280,4 +356,5 @@ START_TEST(wlanapi) test_WlanAllocateFreeMemory(); test_WlanEnumInterfaces(); test_WlanGetAvailableNetworkList(); + test_WlanGetNetworkBssList(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/dbus.c | 29 +++++++++++++++-- dlls/wlanapi/main.c | 60 ++++++++++++++++++++++++++++++++++-- dlls/wlanapi/tests/wlanapi.c | 24 +++++++-------- dlls/wlanapi/unixlib.c | 22 ++++++++++++- dlls/wlanapi/unixlib.h | 10 ++++++ dlls/wlanapi/unixlib_priv.h | 7 +++-- 6 files changed, 132 insertions(+), 20 deletions(-)
diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c index f0e3ea124e2..a9b13295d54 100644 --- a/dlls/wlanapi/dbus.c +++ b/dlls/wlanapi/dbus.c @@ -634,7 +634,9 @@ static char *__WINE_MALLOC networkmanager_device_get_active_ap( void *connection return dup; }
-NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device, struct list *access_points ) +NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device, + const DOT11_SSID *ssid, BOOL security, + struct list *access_points ) { DBusMessage *request, *reply; DBusError error; @@ -698,8 +700,15 @@ NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device,
if (networkmanager_get_access_point_info( connection, object_path, &info )) { - struct wlan_network *network = calloc( 1, sizeof( *network ) ); + struct wlan_network *network; + + if (ssid && !(info.ssid_len == ssid->uSSIDLength && + !memcmp( info.ssid, ssid->ucSSID, sizeof( info.ssid ) ))) + continue; + if (security && !(info.flags & 1)) /* NM_802_11_AP_FLAGS_PRIVACY */ + continue;
+ network = calloc( 1, sizeof( *network ) ); if (!network) continue; network->info = info; network->info.connected = active_ap && !strcmp( active_ap, object_path ); @@ -847,3 +856,19 @@ void wlan_bss_info_to_WLAN_AVAILABLE_NETWORK( const struct wlan_bss_info *info, if (info->connected) dest->dwFlags |= WLAN_AVAILABLE_NETWORK_CONNECTED; } + +void wlan_bss_info_to_WLAN_BSS_ENTRY( const struct wlan_bss_info *info, WLAN_BSS_ENTRY *dest ) +{ + memset( dest, 0, sizeof( *dest )); + + FIXME( "(%p, %p) semi-stub\n", info, dest ); + memcpy( dest->dot11Ssid.ucSSID, info->ssid, sizeof( info->ssid ) ); + dest->dot11Ssid.uSSIDLength = info->ssid_len; + + memcpy( dest->dot11Bssid, info->hw_address, sizeof( info->hw_address ) ); + dest->dot11BssType = info->mode == NM_802_11_MODE_INFRA ? dot11_BSS_type_infrastructure + : dot11_BSS_type_independent; + dest->uLinkQuality = info->strength; + dest->bInRegDomain = TRUE; + dest->usBeaconPeriod = 1; +} diff --git a/dlls/wlanapi/main.c b/dlls/wlanapi/main.c index fcccff42fa8..49c05ecb381 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -285,10 +285,64 @@ DWORD WINAPI WlanGetNetworkBssList( HANDLE handle, const GUID *guid, const DOT11 DOT11_BSS_TYPE bss_type, BOOL security, void *reserved, WLAN_BSS_LIST **bss_list ) { - FIXME( "(%p, %s, %p, %d, %d, %p, %p) stub\n", handle, debugstr_guid( guid ), ssid, bss_type, - security, reserved, bss_list ); + struct wine_wlan *wlan; + struct wlan_network_list_get_params params = {0}; + struct wlan_network_list_move_to_bss_entry_params move_params = {0}; + WLAN_BSS_LIST *ret_list; + NTSTATUS status; + DWORD size;
- return ERROR_CALL_NOT_IMPLEMENTED; + TRACE( "(%p, %s, %p, %d, %d, %p, %p)\n", handle, debugstr_guid( guid ), ssid, bss_type, security, reserved, + bss_list ); + + if (!handle || !guid || reserved || !bss_list) + return ERROR_INVALID_PARAMETER; + if (ssid) + { + if (ssid->uSSIDLength > sizeof(ssid->ucSSID)) + return ERROR_INVALID_PARAMETER; + switch (bss_type) + { + case dot11_BSS_type_infrastructure: + case dot11_BSS_type_independent: + case dot11_BSS_type_any: + break; + default: + return ERROR_INVALID_PARAMETER; + } + } + + wlan = handle_index( handle ); + if (!wlan) + return ERROR_INVALID_HANDLE; + + params.handle = wlan->unix_handle; + params.interface = guid; + params.ssid_filter = ssid; + params.security = ssid && security; + status = UNIX_WLAN_CALL( wlan_network_list_get, ¶ms ); + if (status != STATUS_SUCCESS) + return RtlNtStatusToDosError( status ); + + size = offsetof( WLAN_BSS_LIST, wlanBssEntries[params.len] ); + ret_list = WlanAllocateMemory( size ); + if (!ret_list) + { + struct wlan_network_list_free_params free_params = {0}; + free_params.networks = params.networks; + UNIX_WLAN_CALL( wlan_network_list_free, &free_params ); + return ERROR_NOT_ENOUGH_MEMORY; + } + + move_params.networks = params.networks; + move_params.dest = ret_list->wlanBssEntries; + UNIX_WLAN_CALL( wlan_network_list_move_to_bss_entry, &move_params ); + + ret_list->dwTotalSize = size; + ret_list->dwNumberOfItems = params.len; + *bss_list = ret_list; + + return ERROR_SUCCESS; }
DWORD WINAPI WlanQueryInterface(HANDLE handle, const GUID *guid, WLAN_INTF_OPCODE opcode, diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index 6d8d7808a26..5aa1bcce653 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -295,22 +295,22 @@ static void test_WlanGetNetworkBssList( void )
/* invalid parameters */ ret = WlanGetNetworkBssList( NULL, NULL, NULL, 0, FALSE, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" ); ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" ); ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" ); ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, &reserved, &list ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" );
/* valid paramters */ ret = WlanGetNetworkBssList( handle, &info->InterfaceGuid, NULL, 0, FALSE, NULL, &list ); - todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); if (!list || !list->dwNumberOfItems) { skip( "No wireless networks\n" ); @@ -322,9 +322,9 @@ static void test_WlanGetNetworkBssList( void ) { WLAN_BSS_ENTRY *entry = &list->wlanBssEntries[j];
- todo_wine ok( entry->dot11Ssid.uSSIDLength <= sizeof( entry->dot11Ssid.ucSSID ), - "Unexpected length for uSSID, should be <= 32: %ld\n", - entry->dot11Ssid.uSSIDLength ); + ok( entry->dot11Ssid.uSSIDLength <= sizeof( entry->dot11Ssid.ucSSID ), + "Unexpected length for uSSID, should be <= 32: %ld\n", + entry->dot11Ssid.uSSIDLength );
trace( " Index[%ld] SSID: %s\n", j, diff --git a/dlls/wlanapi/unixlib.c b/dlls/wlanapi/unixlib.c index 3b64c55730c..02f5d077100 100644 --- a/dlls/wlanapi/unixlib.c +++ b/dlls/wlanapi/unixlib.c @@ -138,7 +138,8 @@ NTSTATUS wlan_network_list_get( void *params ) if (!networks) return STATUS_NO_MEMORY;
list_init( networks ); - status = networkmanager_get_access_points( (void *)args->handle, args->interface, networks ); + status = networkmanager_get_access_points( (void *)args->handle, args->interface, + args->ssid_filter, args->security, networks ); if (status != STATUS_SUCCESS) { free( networks ); @@ -168,6 +169,24 @@ NTSTATUS wlan_network_list_move_to_avail_network( void *params ) return STATUS_SUCCESS; }
+NTSTATUS wlan_network_list_move_to_bss_entry( void *params ) +{ + struct wlan_network_list_move_to_bss_entry_params *args = params; + struct wlan_network *networks = (struct wlan_network *)args->networks; + struct wlan_network *cur, *next; + SIZE_T i = 0; + + LIST_FOR_EACH_ENTRY_SAFE( cur, next, &networks->entry, struct wlan_network, entry) + { + wlan_bss_info_to_WLAN_BSS_ENTRY( &cur->info, &args->dest[i++] ); + list_remove( &cur->entry ); + free( cur ); + } + + free( networks ); + return STATUS_SUCCESS; +} + NTSTATUS wlan_network_list_free( void *params ) { struct wlan_network_list_free_params *args = params; @@ -195,6 +214,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = {
wlan_network_list_get, wlan_network_list_move_to_avail_network, + wlan_network_list_move_to_bss_entry, wlan_network_list_free, };
diff --git a/dlls/wlanapi/unixlib.h b/dlls/wlanapi/unixlib.h index 06c961c5e36..2776c515e96 100644 --- a/dlls/wlanapi/unixlib.h +++ b/dlls/wlanapi/unixlib.h @@ -64,6 +64,8 @@ struct wlan_network_list_get_params { UINT_PTR handle; const GUID *interface; + const DOT11_SSID *ssid_filter; + BOOL security;
UINT_PTR networks; SIZE_T len; @@ -76,6 +78,13 @@ struct wlan_network_list_move_to_avail_network_params WLAN_AVAILABLE_NETWORK *dest; };
+struct wlan_network_list_move_to_bss_entry_params +{ + UINT_PTR networks; + + WLAN_BSS_ENTRY *dest; +}; + struct wlan_network_list_free_params { UINT_PTR networks; @@ -94,6 +103,7 @@ enum wlanpi_funcs
unix_wlan_network_list_get, unix_wlan_network_list_move_to_avail_network, + unix_wlan_network_list_move_to_bss_entry, unix_wlan_network_list_free,
unix_funcs_count diff --git a/dlls/wlanapi/unixlib_priv.h b/dlls/wlanapi/unixlib_priv.h index 3868218250f..89f0a034d97 100644 --- a/dlls/wlanapi/unixlib_priv.h +++ b/dlls/wlanapi/unixlib_priv.h @@ -58,7 +58,10 @@ extern NTSTATUS init_dbus_connection( UINT_PTR *handle ); extern void close_dbus_connection( void *c ); extern NTSTATUS networkmanager_get_wifi_devices( void *connection, struct list *devices ); extern NTSTATUS networkmanager_get_access_points( void *connection, const GUID *device, - struct list *access_points ); + const DOT11_SSID *ssid, BOOL security, + struct list *access_points ); extern void wlan_bss_info_to_WLAN_AVAILABLE_NETWORK( const struct wlan_bss_info *info, - WLAN_AVAILABLE_NETWORK *dest ); + WLAN_AVAILABLE_NETWORK *dest ); +extern void wlan_bss_info_to_WLAN_BSS_ENTRY( const struct wlan_bss_info *info, + WLAN_BSS_ENTRY *dest ); #endif /* __WINE_WLANAPI_UNIXLIB_PRIV_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/tests/wlanapi.c | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index 5aa1bcce653..a80903cc6fd 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -339,6 +339,57 @@ static void test_WlanGetNetworkBssList( void ) ok( ret == 0, "Expected 0, got %ld\n", ret ); }
+static void test_WlanStartScan( void ) +{ + HANDLE handle; + DWORD neg_version, i, ret, reserved = 0xdeadbeef; + WLAN_INTERFACE_INFO_LIST *ifaces; + + ret = WlanOpenHandle(1, NULL, &neg_version, &handle); + ok(ret == 0, "Expected 0, got %ld\n", ret); + + ret = WlanEnumInterfaces( handle, NULL, &ifaces ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!ifaces || !ifaces->dwNumberOfItems) + { + skip( "No wireless interfaces\n" ); + WlanCloseHandle( handle, NULL ); + WlanFreeMemory( ifaces ); + return; + } + + trace("Wireless interfaces: %ld\n", ifaces->dwNumberOfItems); + for (i = 0; i < ifaces->dwNumberOfItems; i++) + { + WLAN_INTERFACE_INFO *info; + DOT11_SSID invalid_ssid = {.uSSIDLength = 60}, + ssid = {.uSSIDLength = 4, .ucSSID = {'t', 'e', 's', 't'}}; + + info = &ifaces->InterfaceInfo[i]; + trace( " Index[%ld] GUID: %s\n", i, debugstr_guid( &info->InterfaceGuid ) ); + + /* invalid parameters */ + ret = WlanScan( NULL, NULL, NULL, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ret = WlanScan( handle, NULL, NULL, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ret = WlanScan( handle, &info->InterfaceGuid, &invalid_ssid, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ret = WlanScan( handle, &info->InterfaceGuid, &ssid, NULL, &reserved ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + + /* valid parameters */ + ret = WlanScan( handle, &info->InterfaceGuid, NULL, NULL, NULL ); + todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret ); + ret = WlanScan( handle, &info->InterfaceGuid, &ssid, NULL, NULL ); + todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret ); + } + + WlanFreeMemory( ifaces ); + ret = WlanCloseHandle( handle, NULL ); + ok( ret == 0, "Expected 0, got %ld\n", ret ); +} + START_TEST(wlanapi) { HANDLE handle; @@ -355,6 +406,7 @@ START_TEST(wlanapi) test_WlanOpenHandle(); test_WlanAllocateFreeMemory(); test_WlanEnumInterfaces(); + test_WlanStartScan(); test_WlanGetAvailableNetworkList(); test_WlanGetNetworkBssList(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/dbus.c | 99 ++++++++++++++++++++++++++++++++++++ dlls/wlanapi/dbus.h | 2 + dlls/wlanapi/main.c | 25 +++++++-- dlls/wlanapi/tests/wlanapi.c | 14 ++--- dlls/wlanapi/unixlib.c | 9 ++++ dlls/wlanapi/unixlib.h | 9 ++++ dlls/wlanapi/unixlib_priv.h | 2 + 7 files changed, 150 insertions(+), 10 deletions(-)
diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c index a9b13295d54..f29ecd85bc9 100644 --- a/dlls/wlanapi/dbus.c +++ b/dlls/wlanapi/dbus.c @@ -26,6 +26,7 @@
#include <stdlib.h> #include <dlfcn.h> +#include <assert.h>
#ifdef SONAME_LIBDBUS_1 #include <dbus/dbus.h> @@ -722,6 +723,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 49c05ecb381..ea7b6e85b49 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 @@ -220,10 +221,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/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index a80903cc6fd..a9e204f6c65 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -370,19 +370,19 @@ static void test_WlanStartScan( void )
/* invalid parameters */ ret = WlanScan( NULL, NULL, NULL, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok (ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret); ret = WlanScan( handle, NULL, NULL, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok (ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret); ret = WlanScan( handle, &info->InterfaceGuid, &invalid_ssid, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - ret = WlanScan( handle, &info->InterfaceGuid, &ssid, NULL, &reserved ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok (ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret); + ret = WlanScan ( handle, &info->InterfaceGuid, &ssid, NULL, &reserved ); + ok (ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret);
/* valid parameters */ ret = WlanScan( handle, &info->InterfaceGuid, NULL, NULL, NULL ); - todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret ); ret = WlanScan( handle, &info->InterfaceGuid, &ssid, NULL, NULL ); - todo_wine ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret ); }
WlanFreeMemory( ifaces ); 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 */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/main.c | 8 ++++++++ dlls/wlanapi/wlanapi.spec | 2 +- include/wlanapi.h | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/dlls/wlanapi/main.c b/dlls/wlanapi/main.c index ea7b6e85b49..9d9ea91be9b 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -364,6 +364,14 @@ DWORD WINAPI WlanGetNetworkBssList( HANDLE handle, const GUID *guid, const DOT11 return ERROR_SUCCESS; }
+DWORD WINAPI WlanGetProfileList( HANDLE handle, const GUID *guid, void *reserved, + WLAN_PROFILE_INFO_LIST **list ) +{ + FIXME("(%p, %p, %p, %p) stub\n", handle, guid, reserved, list); + + return ERROR_CALL_NOT_IMPLEMENTED; +} + DWORD WINAPI WlanQueryInterface(HANDLE handle, const GUID *guid, WLAN_INTF_OPCODE opcode, void *reserved, DWORD *data_size, void **data, WLAN_OPCODE_VALUE_TYPE *opcode_type) { diff --git a/dlls/wlanapi/wlanapi.spec b/dlls/wlanapi/wlanapi.spec index 6b47812d017..5a446efc45c 100644 --- a/dlls/wlanapi/wlanapi.spec +++ b/dlls/wlanapi/wlanapi.spec @@ -12,7 +12,7 @@ @ stdcall WlanGetNetworkBssList(ptr ptr ptr long long ptr ptr) @ stub WlanGetProfile @ stub WlanGetProfileCustomUserData -@ stub WlanGetProfileList +@ stdcall WlanGetProfileList(ptr ptr ptr ptr) @ stub WlanGetSecuritySettings @ stdcall WlanHostedNetworkQueryProperty(ptr long ptr ptr ptr ptr) @ stdcall WlanHostedNetworkQuerySecondaryKey(ptr ptr ptr ptr ptr ptr ptr) diff --git a/include/wlanapi.h b/include/wlanapi.h index a050752d541..76cb79bb83e 100644 --- a/include/wlanapi.h +++ b/include/wlanapi.h @@ -283,6 +283,21 @@ typedef struct _WLAN_HOSTED_NETWORK_STATUS WLAN_HOSTED_NETWORK_PEER_STATE PeerList[1]; } WLAN_HOSTED_NETWORK_STATUS, *PWLAN_HOSTED_NETWORK_STATUS;
+#define WLAN_MAX_NAME_LENGTH 256 + +typedef struct _WLAN_PROFILE_INFO +{ + WCHAR strProfileName[WLAN_MAX_NAME_LENGTH]; + DWORD dwFlags; +} WLAN_PROFILE_INFO, *PWLAN_PROFILE_INFO; + +typedef struct _WLAN_PROFILE_INFO_LIST +{ + DWORD dwNumberOfItems; + DWORD dwIndex; + WLAN_PROFILE_INFO ProfileInfo[1]; +} WLAN_PROFILE_INFO_LIST, *PWLAN_PROFILE_INFO_LIST; + DWORD WINAPI WlanCloseHandle(HANDLE, void *); DWORD WINAPI WlanEnumInterfaces(HANDLE, void *, WLAN_INTERFACE_INFO_LIST **); DWORD WINAPI WlanOpenHandle(DWORD, void *, DWORD *, HANDLE *); @@ -294,5 +309,6 @@ DWORD WINAPI WlanGetAvailableNetworkList(HANDLE, const GUID *, DWORD, void *, WL DWORD WINAPI WlanQueryInterface(HANDLE, const GUID *, WLAN_INTF_OPCODE, void *, DWORD *, void **, WLAN_OPCODE_VALUE_TYPE *); DWORD WINAPI WlanGetNetworkBssList( HANDLE, const GUID *, const DOT11_SSID *, DOT11_BSS_TYPE, BOOL, void *, WLAN_BSS_LIST ** ); +DWORD WINAPI WlanGetProfileList( HANDLE, const GUID *, void *, WLAN_PROFILE_INFO_LIST ** );
#endif /* _WLAN_WLANAPI_H */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/tests/wlanapi.c | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index a9e204f6c65..a3017518a55 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -390,6 +390,69 @@ static void test_WlanStartScan( void ) ok( ret == 0, "Expected 0, got %ld\n", ret ); }
+static void test_WlanGetProfileList( void ) +{ + HANDLE handle; + DWORD neg_version, i, ret, reserved = 0xdeadbeef; + WLAN_INTERFACE_INFO_LIST *ifaces; + + ret = WlanOpenHandle(1, NULL, &neg_version, &handle); + ok(ret == 0, "Expected 0, got %ld\n", ret); + + ret = WlanEnumInterfaces( handle, NULL, &ifaces ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!ifaces || !ifaces->dwNumberOfItems) + { + skip( "No wireless interfaces\n" ); + WlanCloseHandle( handle, NULL ); + WlanFreeMemory( ifaces ); + return; + } + + trace("Wireless interfaces: %ld\n", ifaces->dwNumberOfItems); + for (i = 0; i < ifaces->dwNumberOfItems; i++) + { + WLAN_PROFILE_INFO_LIST *bad_list = (WLAN_PROFILE_INFO_LIST *)0xdeadbeef, *list = bad_list; + WLAN_INTERFACE_INFO *info; + DWORD j; + + info = &ifaces->InterfaceInfo[i]; + trace( " Index[%ld] GUID: %s\n", i, debugstr_guid( &info->InterfaceGuid ) ); + + ret = WlanGetProfileList( NULL, NULL, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ret = WlanGetProfileList( handle, NULL, NULL, &list ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + ret = WlanGetProfileList( handle, &info->InterfaceGuid, NULL, NULL ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ret = WlanGetProfileList( handle, &info->InterfaceGuid, &reserved, &list ); + todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + todo_wine ok( list == bad_list, "list changed\n" ); + + ret = WlanGetProfileList( handle, &info->InterfaceGuid, NULL, &list ); + ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); + if (!list || !list->dwNumberOfItems) + { + skip( "No WLAN profiles\n" ); + WlanFreeMemory( list ); + continue; + } + + for (j = 0; j < list->dwNumberOfItems; j++) + { + trace( " Index[%ld] Name: %s Flags: %#lx\n", j, + debugstr_w( list->ProfileInfo[j].strProfileName ), + list->ProfileInfo[j].dwFlags ); + } + WlanFreeMemory( list ); + } + + WlanFreeMemory( ifaces ); + ret = WlanCloseHandle( handle, NULL ); + ok( ret == 0, "Expected 0, got %ld\n", ret ); +} + START_TEST(wlanapi) { HANDLE handle; @@ -409,4 +472,5 @@ START_TEST(wlanapi) test_WlanStartScan(); test_WlanGetAvailableNetworkList(); test_WlanGetNetworkBssList(); + test_WlanGetProfileList(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wlanapi/dbus.c | 168 +++++++++++++++++++++++++++++++++++ dlls/wlanapi/main.c | 42 ++++++++- dlls/wlanapi/tests/wlanapi.c | 12 +-- dlls/wlanapi/unixlib.c | 68 ++++++++++++++ dlls/wlanapi/unixlib.h | 25 ++++++ dlls/wlanapi/unixlib_priv.h | 8 ++ include/wlanapi.h | 2 + 7 files changed, 317 insertions(+), 8 deletions(-)
diff --git a/dlls/wlanapi/dbus.c b/dlls/wlanapi/dbus.c index f29ecd85bc9..b779f40902b 100644 --- a/dlls/wlanapi/dbus.c +++ b/dlls/wlanapi/dbus.c @@ -59,6 +59,8 @@ DBUS_FUNCS; #define NETWORKMANAGER_INTERFACE_DEVICE_WIRELESS "org.freedesktop.NetworkManager.Device.Wireless" #define NETWORKMANAGER_INTERFACE_ACCESS_POINT "org.freedesktop.NetworkManager.AccessPoint" #define NETWORKMANAGER_INTERFACE_CONNECTION_ACTIVE "org.freedesktop.NetworkManager.Connection.Active" +#define NETWORKMANAGER_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" +#define NETWORKMANAGER_INTERFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManager.Settings.Connection"
BOOL load_dbus_functions( void ) { @@ -821,6 +823,172 @@ NTSTATUS networkmanager_start_scan( void *connection, const GUID *interface, return STATUS_SUCCESS; }
+struct networkmanager_settings +{ + const char *id; + dbus_bool_t autoconnect; + const char *type; + const char *interface; +}; + +static BOOL networkmanager_settings_get_section_dict( DBusMessage *getsettings_reply, + const char *name, DBusMessageIter *dict ) +{ + DBusMessageIter iter, sections; + + p_dbus_message_iter_init( getsettings_reply, &iter ); + p_dbus_message_iter_recurse( &iter, §ions ); + while (p_dbus_message_iter_has_next( §ions )) + { + DBusMessageIter section; + const char *section_name; + + p_dbus_message_iter_recurse( §ions, §ion ); + p_dbus_message_iter_get_basic( §ion, §ion_name ); + if (!strcmp( section_name, name )) + { + p_dbus_message_iter_next( §ion ); + p_dbus_message_iter_recurse( §ion, dict ); + return TRUE; + } + p_dbus_message_iter_next( §ions ); + } + + return FALSE; +} + +static BOOL networkmanager_read_settings( DBusMessage *getsettings_reply, + struct networkmanager_settings *settings, + const char *filter_id ) +{ + DBusMessageIter dict, variant; + const char *prop_name; + + if (networkmanager_settings_get_section_dict( getsettings_reply, "connection", &dict )) + { + settings->autoconnect = 1; + + while((prop_name = dbus_next_dict_entry( &dict, &variant ))) + { + if (!strcmp( prop_name, "id" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_STRING) + p_dbus_message_iter_get_basic( &variant, &settings->id ); + else if (!strcmp( prop_name, "autoconnect" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_BOOLEAN) + p_dbus_message_iter_get_basic( &variant, &settings->autoconnect ); + else if (!strcmp( prop_name, "type" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_STRING) + p_dbus_message_iter_get_basic( &variant, &settings->type ); + else if (!strcmp( prop_name, "interface-name" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_STRING) + p_dbus_message_iter_get_basic( &variant, &settings->interface ); + } + } + if (filter_id && !(settings->id && !strcmp(settings->id, filter_id))) + return FALSE; + + return TRUE; +} + +NTSTATUS networkmanager_wifi_device_get_setting_ids( void *connection, const GUID *device, + struct list *ids) +{ + DBusMessage *request, *reply; + DBusError error; + char **object_paths; + int n_objects, i; + dbus_bool_t success; + char *device_path; + struct unix_wlan_interface_info device_info = {0}; + + if (!networkmanager_valid_device_guid( device )) return STATUS_INVALID_PARAMETER; + device_path = networkmanager_device_guid_to_path( device ); + if (!device_path) return STATUS_NO_MEMORY; + if (!networkmanager_wifi_device_get_info( connection, device_path, &device_info)) + { + free( device_path ); + return STATUS_INTERNAL_ERROR; + } + free( device_path ); + + request = p_dbus_message_new_method_call( + NETWORKMANAGER_SERVICE, "/org/freedesktop/NetworkManager/Settings", + NETWORKMANAGER_INTERFACE_SETTINGS, "ListConnections" ); + if (!request) return STATUS_NO_MEMORY; + + 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( "Could not get list of connections settings: %s: %s.\n", debugstr_a( error.name ), + debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + return ret; + } + + p_dbus_error_free( &error ); + p_dbus_error_init( &error ); + success = p_dbus_message_get_args( reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, + &object_paths, &n_objects, DBUS_TYPE_INVALID ); + if (!success) + { + NTSTATUS ret = dbus_error_to_ntstatus( &error ); + ERR( "Could not read object paths from ListConnections reply: %s: %s.\n", + debugstr_a( error.name ), debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + return ret; + } + + p_dbus_error_free( &error ); + for (i = 0; i < n_objects; i++) + { + DBusMessage *getsettings_req, *getsettings_reply; + const char *object_path = object_paths[i]; + struct networkmanager_settings settings = {0}; + + getsettings_req = p_dbus_message_new_method_call( + NETWORKMANAGER_SERVICE, object_path, NETWORKMANAGER_INTERFACE_SETTINGS_CONNECTION, + "GetSettings" ); + if (!getsettings_req) continue; + p_dbus_error_init( &error ); + getsettings_reply = p_dbus_connection_send_with_reply_and_block( connection, getsettings_req, + dbus_timeout, &error ); + p_dbus_message_unref( getsettings_req ); + if (!getsettings_reply) + { + ERR( "Could not get settings for %s: %s: %s.\n", debugstr_a( object_path ), + debugstr_a( error.name ), debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + continue; + } + p_dbus_error_free( &error ); + if (networkmanager_read_settings( getsettings_reply, &settings, NULL ) && settings.id && + settings.type && !strcmp( settings.type, "802-11-wireless" ) && + settings.interface && !strcmp ( settings.interface, device_info.description )) + { + struct wlan_profile *entry; + SIZE_T len; + + entry = malloc( sizeof( *entry ) ); + if (!entry) continue; + + len = min( strlen( settings.id ), sizeof( entry->name ) - 1 ); + memcpy( entry->name, settings.id, len ); + entry->name[len] = '\0'; + list_add_tail( ids, &entry->entry ); + } + p_dbus_message_unref( getsettings_reply ); + } + + p_dbus_free_string_array( object_paths ); + 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/main.c b/dlls/wlanapi/main.c index 9d9ea91be9b..f5e70735c4f 100644 --- a/dlls/wlanapi/main.c +++ b/dlls/wlanapi/main.c @@ -367,9 +367,47 @@ DWORD WINAPI WlanGetNetworkBssList( HANDLE handle, const GUID *guid, const DOT11 DWORD WINAPI WlanGetProfileList( HANDLE handle, const GUID *guid, void *reserved, WLAN_PROFILE_INFO_LIST **list ) { - FIXME("(%p, %p, %p, %p) stub\n", handle, guid, reserved, list); + NTSTATUS status; + WLAN_PROFILE_INFO_LIST *ret_list; + struct wine_wlan *wlan; + struct wlan_get_profile_list_params params = {0}; + struct wlan_profile_list_move_to_profile_info_params move_params = {0}; + DWORD size;
- return ERROR_CALL_NOT_IMPLEMENTED; + TRACE( "(%p, %s, %p, %p)\n", handle, debugstr_guid( guid ), reserved, list ); + + if (!handle || !guid || reserved || !list) + return ERROR_INVALID_PARAMETER; + + wlan = handle_index( handle ); + if (!wlan) + return ERROR_INVALID_HANDLE; + + params.handle = wlan->unix_handle; + params.interface = guid; + status = UNIX_WLAN_CALL( wlan_get_profile_list, ¶ms ); + if (status) + return RtlNtStatusToDosError( status ); + + size = offsetof( WLAN_PROFILE_INFO_LIST, ProfileInfo[params.len] ); + ret_list = WlanAllocateMemory( size ); + if (!ret_list) + { + struct wlan_profile_list_free_params free_params = {0}; + free_params.profiles = params.list; + UNIX_WLAN_CALL( wlan_profile_list_free, &free_params ); + return ERROR_NOT_ENOUGH_MEMORY; + } + + move_params.dest = ret_list->ProfileInfo; + move_params.profiles = params.list; + UNIX_WLAN_CALL( wlan_profile_list_move_to_profile_info, &move_params ); + + ret_list->dwIndex = 0; + ret_list->dwNumberOfItems = params.len; + *list = ret_list; + + return ERROR_SUCCESS; }
DWORD WINAPI WlanQueryInterface(HANDLE handle, const GUID *guid, WLAN_INTF_OPCODE opcode, diff --git a/dlls/wlanapi/tests/wlanapi.c b/dlls/wlanapi/tests/wlanapi.c index a3017518a55..0e01567b043 100644 --- a/dlls/wlanapi/tests/wlanapi.c +++ b/dlls/wlanapi/tests/wlanapi.c @@ -420,15 +420,15 @@ static void test_WlanGetProfileList( void ) trace( " Index[%ld] GUID: %s\n", i, debugstr_guid( &info->InterfaceGuid ) );
ret = WlanGetProfileList( NULL, NULL, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); ret = WlanGetProfileList( handle, NULL, NULL, &list ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" ); ret = WlanGetProfileList( handle, &info->InterfaceGuid, NULL, NULL ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); ret = WlanGetProfileList( handle, &info->InterfaceGuid, &reserved, &list ); - todo_wine ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); - todo_wine ok( list == bad_list, "list changed\n" ); + ok( ret == ERROR_INVALID_PARAMETER, "Expected 87, got %ld\n", ret ); + ok( list == bad_list, "list changed\n" );
ret = WlanGetProfileList( handle, &info->InterfaceGuid, NULL, &list ); ok( ret == ERROR_SUCCESS, "Expected 0, got %ld\n", ret); diff --git a/dlls/wlanapi/unixlib.c b/dlls/wlanapi/unixlib.c index 3b101263f3c..0b38594fbe2 100644 --- a/dlls/wlanapi/unixlib.c +++ b/dlls/wlanapi/unixlib.c @@ -210,6 +210,70 @@ NTSTATUS wlan_start_scan( void *params ) return networkmanager_start_scan( (void *) args->handle, args->interface, args->ssid ); }
+NTSTATUS wlan_get_profile_list( void *params ) +{ + NTSTATUS status; + struct wlan_get_profile_list_params *args = params; + struct list *profiles; + + if (!initialized) + return STATUS_NOT_SUPPORTED; + + profiles = malloc( sizeof( *profiles )); + if (!profiles) return STATUS_NO_MEMORY; + + list_init( profiles ); + status = networkmanager_wifi_device_get_setting_ids( (void *)args->handle, args->interface, + profiles ); + if (status) + { + free( profiles ); + return status; + } + + args->list = (UINT_PTR)profiles; + args->len = list_count( profiles ); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_profile_list_move_to_profile_info( void *params ) +{ + struct wlan_profile_list_move_to_profile_info_params *args = params; + struct list *profiles = (struct list *)args->profiles; + struct wlan_profile *cur, *next; + SIZE_T i = 0; + + LIST_FOR_EACH_ENTRY_SAFE( cur, next, profiles, struct wlan_profile, entry) + { + WCHAR *dst = args->dest[i].strProfileName; + + args->dest[i++].dwFlags = WLAN_PROFILE_USER; + ntdll_umbstowcs( cur->name, strlen( cur->name ) + 1, dst, + ARRAY_SIZE( args->dest[0].strProfileName ) ); + list_remove( &cur->entry ); + free( cur ); + } + + free( profiles ); + return STATUS_SUCCESS; +} + +NTSTATUS wlan_profile_list_free( void *params ) +{ + struct wlan_profile_list_free_params *args = params; + struct list *profiles = (struct list *)args->profiles; + struct wlan_profile *cur, *next; + + LIST_FOR_EACH_ENTRY_SAFE( cur, next, profiles, struct wlan_profile, entry) + { + list_remove( &cur->entry ); + free( cur ); + } + + free( profiles ); + return STATUS_SUCCESS; +} + const unixlib_entry_t __wine_unix_call_funcs[] = { wlan_init, wlan_open_handle, @@ -225,6 +289,10 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { wlan_network_list_free,
wlan_start_scan, + + wlan_get_profile_list, + wlan_profile_list_move_to_profile_info, + wlan_profile_list_free };
C_ASSERT( ARRAYSIZE( __wine_unix_call_funcs ) == unix_funcs_count ); diff --git a/dlls/wlanapi/unixlib.h b/dlls/wlanapi/unixlib.h index 1a39149018b..56f85f99c82 100644 --- a/dlls/wlanapi/unixlib.h +++ b/dlls/wlanapi/unixlib.h @@ -97,6 +97,27 @@ struct wlan_start_scan const DOT11_SSID *ssid; };
+struct wlan_get_profile_list_params +{ + UINT_PTR handle; + const GUID *interface; + + UINT_PTR list; + SIZE_T len; +}; + +struct wlan_profile_list_move_to_profile_info_params +{ + UINT_PTR profiles; + + WLAN_PROFILE_INFO *dest; +}; + +struct wlan_profile_list_free_params +{ + UINT_PTR profiles; +}; + enum wlanpi_funcs { unix_wlan_init, @@ -115,6 +136,10 @@ enum wlanpi_funcs
unix_wlan_start_scan,
+ unix_wlan_get_profile_list, + unix_wlan_profile_list_move_to_profile_info, + unix_wlan_profile_list_free, + unix_funcs_count };
diff --git a/dlls/wlanapi/unixlib_priv.h b/dlls/wlanapi/unixlib_priv.h index da51fcdf66d..9171a5dafc5 100644 --- a/dlls/wlanapi/unixlib_priv.h +++ b/dlls/wlanapi/unixlib_priv.h @@ -53,6 +53,12 @@ struct wlan_network struct wlan_bss_info info; };
+struct wlan_profile +{ + struct list entry; + CHAR name[WLAN_MAX_NAME_LENGTH]; +}; + extern BOOL load_dbus_functions( void ); extern NTSTATUS init_dbus_connection( UINT_PTR *handle ); extern void close_dbus_connection( void *c ); @@ -66,4 +72,6 @@ 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 ); +extern NTSTATUS networkmanager_wifi_device_get_setting_ids( void *connection, const GUID *device, + struct list *ids ); #endif /* __WINE_WLANAPI_UNIXLIB_PRIV_H */ diff --git a/include/wlanapi.h b/include/wlanapi.h index 76cb79bb83e..c8864c09c70 100644 --- a/include/wlanapi.h +++ b/include/wlanapi.h @@ -285,6 +285,8 @@ typedef struct _WLAN_HOSTED_NETWORK_STATUS
#define WLAN_MAX_NAME_LENGTH 256
+#define WLAN_PROFILE_USER 0x00000002 + typedef struct _WLAN_PROFILE_INFO { WCHAR strProfileName[WLAN_MAX_NAME_LENGTH];
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148587
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/wlanapi/dbus.c:26 error: patch failed: dlls/wlanapi/dbus.h:78 error: patch failed: dlls/wlanapi/main.c:1 error: patch failed: dlls/wlanapi/tests/wlanapi.c:370 error: patch failed: dlls/wlanapi/unixlib.c:203 error: patch failed: dlls/wlanapi/unixlib.h:90 error: patch failed: dlls/wlanapi/unixlib_priv.h:64 error: patch failed: dlls/wlanapi/unixlib.c:210 error: patch failed: dlls/wlanapi/unixlib.h:97 error: patch failed: dlls/wlanapi/unixlib_priv.h:66 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/wlanapi/dbus.c:26 error: patch failed: dlls/wlanapi/dbus.h:78 error: patch failed: dlls/wlanapi/main.c:1 error: patch failed: dlls/wlanapi/tests/wlanapi.c:370 error: patch failed: dlls/wlanapi/unixlib.c:203 error: patch failed: dlls/wlanapi/unixlib.h:90 error: patch failed: dlls/wlanapi/unixlib_priv.h:64 error: patch failed: dlls/wlanapi/unixlib.c:210 error: patch failed: dlls/wlanapi/unixlib.h:97 error: patch failed: dlls/wlanapi/unixlib_priv.h:66 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/wlanapi/dbus.c:26 error: patch failed: dlls/wlanapi/dbus.h:78 error: patch failed: dlls/wlanapi/main.c:1 error: patch failed: dlls/wlanapi/tests/wlanapi.c:370 error: patch failed: dlls/wlanapi/unixlib.c:203 error: patch failed: dlls/wlanapi/unixlib.h:90 error: patch failed: dlls/wlanapi/unixlib_priv.h:64 error: patch failed: dlls/wlanapi/unixlib.c:210 error: patch failed: dlls/wlanapi/unixlib.h:97 error: patch failed: dlls/wlanapi/unixlib_priv.h:66 Task: Patch failed to apply
Fwiw it's not very useful to rebase every day. You don't need to update a MR unless there's actual changes to be made, and when you do it's also better to avoid rebasing unless there's conflicts, so that Gitlab diff can be used to compare the changes (otherwise it's pretty much unusable).
If you want to get some feedback it'll be more effective to look for someone (ask here or in IRC, or figure who could be knowledgeable) who's happy to review your changes, and assign them as reviewer.
Regarding this MR specifically, the issue might be that nobody's knowledgeable enough about WLAN APIs to give relevant feedback.
Then a general feedback I can give already, is that bridging DLLs directly to the unix side is the easiest way, but not always the right way to do things. It's unclear to me (because I know nothing about these APIs) how the handles/objects returned by the APIs here can be used on Windows, and whether we're going to get stuck in a dead end or not if we go that way.
For instance, are these handles related in any way to some underlying devices or are they truly wlanapi private handles? "Should/can/what about" we expose the WLAN devices as NT devices instead?
For instance, are these handles related in any way to some underlying devices or are they truly wlanapi private handles? "Should/can/what about" we expose the WLAN devices as NT devices instead?
All the testing I've done seems to indicate they're private handles. `CloseHandle` and `NtQueryObject` fails on them. There's also this bug report in win32metadata (and its associated commit) that seems to indicate that Microsoft does intend that: https://github.com/microsoft/win32metadata/issues/1656
It's unclear to me (because I know nothing about these APIs) how the handles/objects returned by the APIs here can be used on Windows, and whether we're going to get stuck in a dead end or not if we go that way.
`wlanapi` handles, being strictly private, seem to be only used within `wlanapi`. I imagine on Windows they likely contain the connection to the WLAN service.