From 05312cacf7e2f76ea34c8359abeb68ef0d64b9b0 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 18 Jan 2024 22:20:40 +0100 Subject: [PATCH 1/2] Fix of #11790: missing wlanapi.dll on Win Server 2019 --- src/slic3r/Utils/WifiScanner.cpp | 61 ++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/src/slic3r/Utils/WifiScanner.cpp b/src/slic3r/Utils/WifiScanner.cpp index aa4c8f4e9f..40b4c98038 100644 --- a/src/slic3r/Utils/WifiScanner.cpp +++ b/src/slic3r/Utils/WifiScanner.cpp @@ -12,9 +12,8 @@ #include #include -// Need to link with Wlanapi.lib and Ole32.lib -#pragma comment(lib, "wlanapi.lib") -#pragma comment(lib, "ole32.lib") +#include "libslic3r//Utils.hpp" + #elif __APPLE_ #include "WifiScannerMac.h" #endif @@ -49,17 +48,49 @@ bool ptree_get_value(const boost::property_tree::ptree& pt, const std::string& t // https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlangetavailablenetworklist void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid) { + HINSTANCE hWlanApi = LoadLibrary(L"wlanapi.dll"); + if (hWlanApi == NULL) + return; + Slic3r::ScopeGuard guard([&hWlanApi] { FreeLibrary(hWlanApi); }); + + using WlanOpenHandleFunc = DWORD(WINAPI*)(DWORD, PVOID, PDWORD, PHANDLE); + using WlanEnumInterfacesFunc = DWORD(WINAPI*)(HANDLE, PVOID, PWLAN_INTERFACE_INFO_LIST*); + using WlanQueryInterfaceFunc = DWORD(WINAPI*)(HANDLE, const GUID*, WLAN_INTF_OPCODE, PVOID, PDWORD, PVOID*, PWLAN_OPCODE_VALUE_TYPE); + using WlanFreeMemoryFunc = VOID(WINAPI* )(PVOID); + using WlanGetProfileFunc = DWORD(WINAPI*)(HANDLE, const GUID*, LPCWSTR, PVOID, LPWSTR*, DWORD*, DWORD*); + using WlanGetProfileListFunc = DWORD(WINAPI*)(HANDLE, const GUID*, PVOID, PWLAN_PROFILE_INFO_LIST*); + using WlanGetAvailableNetworkListFunc = DWORD(WINAPI*)(HANDLE, const GUID*, DWORD, PVOID, PWLAN_AVAILABLE_NETWORK_LIST*); + using WlanCloseHandleFunc = DWORD(WINAPI*)(HANDLE, PVOID); + + WlanOpenHandleFunc wlanOpenHandleFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanOpenHandle")); + WlanEnumInterfacesFunc wlanEnumInterfacesFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanEnumInterfaces")); + WlanQueryInterfaceFunc wlanQueryInterfaceFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanQueryInterface")); + WlanFreeMemoryFunc wlanFreeMemoryFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanFreeMemory")); + WlanGetProfileFunc wlanGetProfileFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanGetProfile")); + WlanGetProfileListFunc wlanGetProfileListFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanGetProfileList")); + WlanGetAvailableNetworkListFunc wlanGetAvailableNetworkListFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanGetAvailableNetworkList")); + WlanCloseHandleFunc wlanCloseHandleFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanCloseHandle")); + + if (! wlanOpenHandleFunc || ! wlanEnumInterfacesFunc || ! wlanQueryInterfaceFunc || ! wlanFreeMemoryFunc + || ! wlanGetProfileFunc || ! wlanGetProfileListFunc || ! wlanGetAvailableNetworkListFunc || ! wlanCloseHandleFunc) + return; + + HANDLE handle; DWORD supported_version = 0; DWORD client_version = 2; PWLAN_INTERFACE_INFO_LIST interface_list = NULL; - - if (WlanOpenHandle(client_version, NULL, &supported_version, &handle) != ERROR_SUCCESS) + + if (wlanOpenHandleFunc(client_version, NULL, &supported_version, &handle) != ERROR_SUCCESS) return; - if (WlanEnumInterfaces(handle, NULL, &interface_list) != ERROR_SUCCESS) + if (wlanEnumInterfacesFunc(handle, NULL, &interface_list) != ERROR_SUCCESS) { + // Touhle cestou funkce vrati bez toho, aby zavolala WlanCloseHandleFunc. + // I tady by stalo za uvahu pouziti ScopeGuard, ktery podobnou chybu vylouci + // a kod bude exception-safe (coz je tady asi jedno, ale obecne to jedno neni). return; + } for (DWORD i = 0; i < interface_list->dwNumberOfItems; i++) { @@ -69,7 +100,7 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid DWORD connectInfoSize = sizeof(WLAN_CONNECTION_ATTRIBUTES); WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid; - if (WlanQueryInterface(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, + if (wlanQueryInterfaceFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, wlan_intf_opcode_current_connection, NULL, &connectInfoSize, (PVOID*)&pConnectInfo, &opCode) == ERROR_SUCCESS && pConnectInfo && pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength) { @@ -77,7 +108,7 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength); } - WlanFreeMemory(pConnectInfo); + wlanFreeMemoryFunc(pConnectInfo); } PWLAN_PROFILE_INFO_LIST profile_list = NULL; @@ -90,7 +121,7 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid int iRet = StringFromGUID2(interface_info_entry->InterfaceGuid, (LPOLESTR)&guid, sizeof(guid) / sizeof(*guid)); - if (WlanGetAvailableNetworkList(handle, + if (wlanGetAvailableNetworkListFunc(handle, &interface_info_entry->InterfaceGuid, 0, NULL, @@ -121,7 +152,7 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid wifi_map[ssid] = std::string(); - if (WlanGetProfileList(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, + if (wlanGetProfileListFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, NULL, &profile_list) != ERROR_SUCCESS) { continue; @@ -140,7 +171,7 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid if (s != ssid) continue; - if ((ret = WlanGetProfile(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, profile_list->ProfileInfo[k].strProfileName, + if ((ret = wlanGetProfileFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, profile_list->ProfileInfo[k].strProfileName, NULL, &xmlstr, &flags, &access)) == ERROR_SUCCESS && xmlstr) { wxString xml(xmlstr); @@ -160,20 +191,20 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid if (ptree_get_value(pt, "keyMaterial", password)) wifi_map[ssid] = password; - WlanFreeMemory(xmlstr); + wlanFreeMemoryFunc(xmlstr); break; } } if (profile_list) { - WlanFreeMemory(profile_list); + wlanFreeMemoryFunc(profile_list); } } } if (interface_list) - WlanFreeMemory(interface_list); - WlanCloseHandle(handle, NULL); + wlanFreeMemoryFunc(interface_list); + wlanCloseHandleFunc(handle, NULL); } #elif __APPLE__ void get_connected_ssid(std::string& connected_ssid) From e0e1afd6400bf2c23df5baa3d4e948f50ac2c880 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 19 Jan 2024 15:19:41 +0100 Subject: [PATCH 2/2] Error message when wlanapi.dll is missing Code improvements due to @lukasmatena code review. --- src/slic3r/GUI/WifiConfigDialog.cpp | 16 ++ src/slic3r/Utils/WifiScanner.cpp | 333 ++++++++++++++-------------- src/slic3r/Utils/WifiScanner.hpp | 34 ++- 3 files changed, 214 insertions(+), 169 deletions(-) diff --git a/src/slic3r/GUI/WifiConfigDialog.cpp b/src/slic3r/GUI/WifiConfigDialog.cpp index e5be758be5..9e535337fc 100644 --- a/src/slic3r/GUI/WifiConfigDialog.cpp +++ b/src/slic3r/GUI/WifiConfigDialog.cpp @@ -29,6 +29,19 @@ WifiConfigDialog::WifiConfigDialog(wxWindow* parent, std::string& file_path, Rem , out_file_path(file_path) , m_removable_manager(removable_manager) { + // Propagation of error in wifi scanner construtor + if (!m_wifi_scanner->is_init()) { + // TRN Error dialog of configuration -> wifi configuration file + wxString msg = format_wxstr(L"%1%\n\n%2%", _L("Failed to scan wireless networks. Please fill SSID manually."), +#ifdef _WIN32 + // TRN Windows specific second line of error dialog of configuration -> wifi configuration file + _L("Library wlanapi.dll was not loaded.") +#else + "" +#endif // _WIN32 + ); + show_error(this, msg); + } wxPanel* panel = new wxPanel(this); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); panel->SetSizer(vsizer); @@ -188,6 +201,9 @@ void WifiConfigDialog::on_rescan_networks(wxCommandEvent& e) void WifiConfigDialog::rescan_networks(bool select) { assert(m_ssid_combo && m_wifi_scanner); + // Do not do anything if scanner is in faulty state (which should has been propageted in constructor call) + if (!m_wifi_scanner->is_init()) + return; m_wifi_scanner->scan(); std::string current = m_wifi_scanner->get_current_ssid(); const auto& map = m_wifi_scanner->get_map(); diff --git a/src/slic3r/Utils/WifiScanner.cpp b/src/slic3r/Utils/WifiScanner.cpp index 40b4c98038..390a6b2e04 100644 --- a/src/slic3r/Utils/WifiScanner.cpp +++ b/src/slic3r/Utils/WifiScanner.cpp @@ -8,7 +8,6 @@ #ifdef _WIN32 #include -#include #include #include @@ -42,170 +41,6 @@ bool ptree_get_value(const boost::property_tree::ptree& pt, const std::string& t return false; // Element not found in this subtree } - -// Fill SSID map. Implementation from Raspberry Pi imager and Win32 Api examples. -// https://github.com/raspberrypi/rpi-imager/blob/qml/src/windows/winwlancredentials.cpp -// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlangetavailablenetworklist -void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid) -{ - HINSTANCE hWlanApi = LoadLibrary(L"wlanapi.dll"); - if (hWlanApi == NULL) - return; - Slic3r::ScopeGuard guard([&hWlanApi] { FreeLibrary(hWlanApi); }); - - using WlanOpenHandleFunc = DWORD(WINAPI*)(DWORD, PVOID, PDWORD, PHANDLE); - using WlanEnumInterfacesFunc = DWORD(WINAPI*)(HANDLE, PVOID, PWLAN_INTERFACE_INFO_LIST*); - using WlanQueryInterfaceFunc = DWORD(WINAPI*)(HANDLE, const GUID*, WLAN_INTF_OPCODE, PVOID, PDWORD, PVOID*, PWLAN_OPCODE_VALUE_TYPE); - using WlanFreeMemoryFunc = VOID(WINAPI* )(PVOID); - using WlanGetProfileFunc = DWORD(WINAPI*)(HANDLE, const GUID*, LPCWSTR, PVOID, LPWSTR*, DWORD*, DWORD*); - using WlanGetProfileListFunc = DWORD(WINAPI*)(HANDLE, const GUID*, PVOID, PWLAN_PROFILE_INFO_LIST*); - using WlanGetAvailableNetworkListFunc = DWORD(WINAPI*)(HANDLE, const GUID*, DWORD, PVOID, PWLAN_AVAILABLE_NETWORK_LIST*); - using WlanCloseHandleFunc = DWORD(WINAPI*)(HANDLE, PVOID); - - WlanOpenHandleFunc wlanOpenHandleFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanOpenHandle")); - WlanEnumInterfacesFunc wlanEnumInterfacesFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanEnumInterfaces")); - WlanQueryInterfaceFunc wlanQueryInterfaceFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanQueryInterface")); - WlanFreeMemoryFunc wlanFreeMemoryFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanFreeMemory")); - WlanGetProfileFunc wlanGetProfileFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanGetProfile")); - WlanGetProfileListFunc wlanGetProfileListFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanGetProfileList")); - WlanGetAvailableNetworkListFunc wlanGetAvailableNetworkListFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanGetAvailableNetworkList")); - WlanCloseHandleFunc wlanCloseHandleFunc = reinterpret_cast(GetProcAddress(hWlanApi, "WlanCloseHandle")); - - if (! wlanOpenHandleFunc || ! wlanEnumInterfacesFunc || ! wlanQueryInterfaceFunc || ! wlanFreeMemoryFunc - || ! wlanGetProfileFunc || ! wlanGetProfileListFunc || ! wlanGetAvailableNetworkListFunc || ! wlanCloseHandleFunc) - return; - - - HANDLE handle; - DWORD supported_version = 0; - DWORD client_version = 2; - PWLAN_INTERFACE_INFO_LIST interface_list = NULL; - - - if (wlanOpenHandleFunc(client_version, NULL, &supported_version, &handle) != ERROR_SUCCESS) - return; - - if (wlanEnumInterfacesFunc(handle, NULL, &interface_list) != ERROR_SUCCESS) { - // Touhle cestou funkce vrati bez toho, aby zavolala WlanCloseHandleFunc. - // I tady by stalo za uvahu pouziti ScopeGuard, ktery podobnou chybu vylouci - // a kod bude exception-safe (coz je tady asi jedno, ale obecne to jedno neni). - return; - } - - for (DWORD i = 0; i < interface_list->dwNumberOfItems; i++) - { - if (interface_list->InterfaceInfo[i].isState == wlan_interface_state_connected) - { - PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL; - DWORD connectInfoSize = sizeof(WLAN_CONNECTION_ATTRIBUTES); - WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid; - - if (wlanQueryInterfaceFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, - wlan_intf_opcode_current_connection, NULL, - &connectInfoSize, (PVOID*)&pConnectInfo, &opCode) == ERROR_SUCCESS && pConnectInfo && pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength) - { - connected_ssid = std::string((const char*)pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID, - pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength); - } - - wlanFreeMemoryFunc(pConnectInfo); - } - - PWLAN_PROFILE_INFO_LIST profile_list = NULL; - PWLAN_INTERFACE_INFO interface_info_entry = NULL; - PWLAN_AVAILABLE_NETWORK_LIST available_network_list = NULL; - WCHAR guid[39] = { 0 }; - - // Get all available networks. - interface_info_entry = (WLAN_INTERFACE_INFO*)&interface_list->InterfaceInfo[i]; - int iRet = StringFromGUID2(interface_info_entry->InterfaceGuid, (LPOLESTR)&guid, - sizeof(guid) / sizeof(*guid)); - - if (wlanGetAvailableNetworkListFunc(handle, - &interface_info_entry->InterfaceGuid, - 0, - NULL, - &available_network_list) - != ERROR_SUCCESS) - { - continue; - } - - for (unsigned int j = 0; j < available_network_list->dwNumberOfItems; j++) - { - PWLAN_AVAILABLE_NETWORK available_network_entry = NULL; - wxString ssid; - - // Store SSID into the map. - available_network_entry = - (WLAN_AVAILABLE_NETWORK*)&available_network_list->Network[j]; - - if (available_network_entry->dot11Ssid.uSSIDLength != 0) - ssid = wxString(available_network_entry->dot11Ssid.ucSSID, - available_network_entry->dot11Ssid.uSSIDLength); - - if (ssid.empty()) - continue; - - if (wifi_map.find(ssid) != wifi_map.end()) - continue; - - wifi_map[ssid] = std::string(); - - if (wlanGetProfileListFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, - NULL, &profile_list) != ERROR_SUCCESS) - { - continue; - } - // enmurate all stored profiles, take password from matching one. - for (DWORD k = 0; k < profile_list->dwNumberOfItems; k++) - { - DWORD flags = WLAN_PROFILE_GET_PLAINTEXT_KEY; - DWORD access = 0; - DWORD ret = 0; - LPWSTR xmlstr = NULL; - wxString s(profile_list->ProfileInfo[k].strProfileName); - - BOOST_LOG_TRIVIAL(debug) << "Enumerating wlan profiles, SSID found:" << s << " looking for:" << ssid; - - if (s != ssid) - continue; - - if ((ret = wlanGetProfileFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, profile_list->ProfileInfo[k].strProfileName, - NULL, &xmlstr, &flags, &access)) == ERROR_SUCCESS && xmlstr) - { - wxString xml(xmlstr); - boost::property_tree::ptree pt; - std::stringstream ss(boost::nowide::narrow(xml)); - boost::property_tree::read_xml(ss, pt); - std::string password; - std::string psk_protected; - - BOOST_LOG_TRIVIAL(debug) << "XML wlan profile:" << xml; - - // break if password is not readable - // TODO: what if there is other line "protected" in the XML? - if (ptree_get_value(pt, "protected", psk_protected) && psk_protected != "false") - break; - - if (ptree_get_value(pt, "keyMaterial", password)) - wifi_map[ssid] = password; - - wlanFreeMemoryFunc(xmlstr); - break; - } - } - - if (profile_list) { - wlanFreeMemoryFunc(profile_list); - } - } - } - - if (interface_list) - wlanFreeMemoryFunc(interface_list); - wlanCloseHandleFunc(handle, NULL); -} #elif __APPLE__ void get_connected_ssid(std::string& connected_ssid) { @@ -426,11 +261,39 @@ void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map) namespace Slic3r { WifiScanner::WifiScanner() -{} +{ +#ifdef _WIN32 + m_wlanapi_handle = LoadLibrary(L"wlanapi.dll"); + if (m_wlanapi_handle == NULL) + return; + + wlanOpenHandleFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanOpenHandle")); + wlanEnumInterfacesFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanEnumInterfaces")); + wlanQueryInterfaceFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanQueryInterface")); + wlanFreeMemoryFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanFreeMemory")); + wlanGetProfileFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanGetProfile")); + wlanGetProfileListFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanGetProfileList")); + wlanGetAvailableNetworkListFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanGetAvailableNetworkList")); + wlanCloseHandleFunc = reinterpret_cast(GetProcAddress(m_wlanapi_handle, "WlanCloseHandle")); + + if (!wlanOpenHandleFunc || !wlanEnumInterfacesFunc || !wlanQueryInterfaceFunc || !wlanFreeMemoryFunc + || !wlanGetProfileFunc || !wlanGetProfileListFunc || !wlanGetAvailableNetworkListFunc || !wlanCloseHandleFunc) + return; +#endif // _WIN32 + m_init = true; +} WifiScanner::~WifiScanner() -{} +{ +#ifdef _WIN32 + if (m_wlanapi_handle) + FreeLibrary(m_wlanapi_handle); +#endif // _WIN32 + +} void WifiScanner::scan() { + if (!m_init) + return; m_map.clear(); #ifdef _WIN32 fill_wifi_map(m_map, m_current_ssid); @@ -490,4 +353,140 @@ std::string WifiScanner::get_psk(const std::string& ssid) } return {}; } + +#ifdef _WIN32 +// Fill SSID map. Implementation from Raspberry Pi imager and Win32 Api examples. +// https://github.com/raspberrypi/rpi-imager/blob/qml/src/windows/winwlancredentials.cpp +// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlangetavailablenetworklist +void WifiScanner::fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid) +{ + HANDLE handle; + DWORD supported_version = 0; + DWORD client_version = 2; + PWLAN_INTERFACE_INFO_LIST interface_list = NULL; + + if (!m_init) + return; + + if (wlanOpenHandleFunc(client_version, NULL, &supported_version, &handle) != ERROR_SUCCESS) + return; + + Slic3r::ScopeGuard guard([this, &handle] { wlanCloseHandleFunc(handle, NULL); }); + + if (wlanEnumInterfacesFunc(handle, NULL, &interface_list) != ERROR_SUCCESS) + return; + + for (DWORD i = 0; i < interface_list->dwNumberOfItems; i++) + { + if (interface_list->InterfaceInfo[i].isState == wlan_interface_state_connected) + { + PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL; + DWORD connectInfoSize = sizeof(WLAN_CONNECTION_ATTRIBUTES); + WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid; + + if (wlanQueryInterfaceFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, + wlan_intf_opcode_current_connection, NULL, + &connectInfoSize, (PVOID*)&pConnectInfo, &opCode) == ERROR_SUCCESS && pConnectInfo && pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength) + { + connected_ssid = std::string((const char*)pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID, + pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength); + wlanFreeMemoryFunc(pConnectInfo); + } + } + + PWLAN_PROFILE_INFO_LIST profile_list = NULL; + PWLAN_INTERFACE_INFO interface_info_entry = NULL; + PWLAN_AVAILABLE_NETWORK_LIST available_network_list = NULL; + WCHAR guid[39] = { 0 }; + + // Get all available networks. + interface_info_entry = (WLAN_INTERFACE_INFO*)&interface_list->InterfaceInfo[i]; + int iRet = StringFromGUID2(interface_info_entry->InterfaceGuid, (LPOLESTR)&guid, + sizeof(guid) / sizeof(*guid)); + + if (wlanGetAvailableNetworkListFunc(handle, + &interface_info_entry->InterfaceGuid, + 0, + NULL, + &available_network_list) + != ERROR_SUCCESS) + { + continue; + } + + for (unsigned int j = 0; j < available_network_list->dwNumberOfItems; j++) + { + PWLAN_AVAILABLE_NETWORK available_network_entry = NULL; + wxString ssid; + + // Store SSID into the map. + available_network_entry = + (WLAN_AVAILABLE_NETWORK*)&available_network_list->Network[j]; + + if (available_network_entry->dot11Ssid.uSSIDLength != 0) + ssid = wxString(available_network_entry->dot11Ssid.ucSSID, + available_network_entry->dot11Ssid.uSSIDLength); + + if (ssid.empty()) + continue; + + if (wifi_map.find(ssid) != wifi_map.end()) + continue; + + wifi_map[ssid] = std::string(); + + if (wlanGetProfileListFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, + NULL, &profile_list) != ERROR_SUCCESS) + { + continue; + } + // enmurate all stored profiles, take password from matching one. + for (DWORD k = 0; k < profile_list->dwNumberOfItems; k++) + { + DWORD flags = WLAN_PROFILE_GET_PLAINTEXT_KEY; + DWORD access = 0; + DWORD ret = 0; + LPWSTR xmlstr = NULL; + wxString s(profile_list->ProfileInfo[k].strProfileName); + + BOOST_LOG_TRIVIAL(debug) << "Enumerating wlan profiles, SSID found:" << s << " looking for:" << ssid; + + if (s != ssid) + continue; + + if ((ret = wlanGetProfileFunc(handle, &interface_list->InterfaceInfo[i].InterfaceGuid, profile_list->ProfileInfo[k].strProfileName, + NULL, &xmlstr, &flags, &access)) == ERROR_SUCCESS && xmlstr) + { + wxString xml(xmlstr); + boost::property_tree::ptree pt; + std::stringstream ss(boost::nowide::narrow(xml)); + boost::property_tree::read_xml(ss, pt); + std::string password; + std::string psk_protected; + + BOOST_LOG_TRIVIAL(debug) << "XML wlan profile:" << xml; + + // break if password is not readable + // TODO: what if there is other line "protected" in the XML? + if (ptree_get_value(pt, "protected", psk_protected) && psk_protected != "false") + break; + + if (ptree_get_value(pt, "keyMaterial", password)) + wifi_map[ssid] = password; + + wlanFreeMemoryFunc(xmlstr); + break; + } + } + + if (profile_list) { + wlanFreeMemoryFunc(profile_list); + } + } + } + + if (interface_list) + wlanFreeMemoryFunc(interface_list); +} +#endif // _WIN32 } // Slic3r \ No newline at end of file diff --git a/src/slic3r/Utils/WifiScanner.hpp b/src/slic3r/Utils/WifiScanner.hpp index 96befa5e65..0223e2d8dc 100644 --- a/src/slic3r/Utils/WifiScanner.hpp +++ b/src/slic3r/Utils/WifiScanner.hpp @@ -6,9 +6,13 @@ #include #include +#ifdef _WIN32 +#include +#endif //_WIN32 + namespace Slic3r { -typedef std::map WifiSsidPskMap; +using WifiSsidPskMap = std::map; class WifiScanner { @@ -16,6 +20,8 @@ public: WifiScanner(); ~WifiScanner(); + bool is_init() const { return m_init; } + const WifiSsidPskMap& get_map() const { return m_map; } // returns psk for given ssid // used on APPLE where each psk query requires user to give their password @@ -27,7 +33,31 @@ public: private: WifiSsidPskMap m_map; std::string m_current_ssid; -#if __APPLE__ + + bool m_init { false }; + +#ifdef _WIN32 + void fill_wifi_map(Slic3r::WifiSsidPskMap& wifi_map, std::string& connected_ssid); + HINSTANCE m_wlanapi_handle; + // Functions of wlanapi used by fill_wifi_map + using WlanOpenHandleFunc = DWORD(WINAPI*)(DWORD, PVOID, PDWORD, PHANDLE); + using WlanEnumInterfacesFunc = DWORD(WINAPI*)(HANDLE, PVOID, PWLAN_INTERFACE_INFO_LIST*); + using WlanQueryInterfaceFunc = DWORD(WINAPI*)(HANDLE, const GUID*, WLAN_INTF_OPCODE, PVOID, PDWORD, PVOID*, PWLAN_OPCODE_VALUE_TYPE); + using WlanFreeMemoryFunc = VOID(WINAPI*)(PVOID); + using WlanGetProfileFunc = DWORD(WINAPI*)(HANDLE, const GUID*, LPCWSTR, PVOID, LPWSTR*, DWORD*, DWORD*); + using WlanGetProfileListFunc = DWORD(WINAPI*)(HANDLE, const GUID*, PVOID, PWLAN_PROFILE_INFO_LIST*); + using WlanGetAvailableNetworkListFunc = DWORD(WINAPI*)(HANDLE, const GUID*, DWORD, PVOID, PWLAN_AVAILABLE_NETWORK_LIST*); + using WlanCloseHandleFunc = DWORD(WINAPI*)(HANDLE, PVOID); + + WlanOpenHandleFunc wlanOpenHandleFunc; + WlanEnumInterfacesFunc wlanEnumInterfacesFunc; + WlanQueryInterfaceFunc wlanQueryInterfaceFunc; + WlanFreeMemoryFunc wlanFreeMemoryFunc; + WlanGetProfileFunc wlanGetProfileFunc; + WlanGetProfileListFunc wlanGetProfileListFunc; + WlanGetAvailableNetworkListFunc wlanGetAvailableNetworkListFunc; + WlanCloseHandleFunc wlanCloseHandleFunc; +#elif __APPLE__ void get_ssids_mac(std::vector& ssids); std::string get_psk_mac(const std::string& ssid); std::string get_current_ssid_mac();