|
8 | 8 | #include <shlobj.h> |
9 | 9 | #include <versionhelpers.h> |
10 | 10 | #include <WbemIdl.h> |
| 11 | +#include <wlanapi.h> |
11 | 12 |
|
12 | 13 | #include <cwctype> |
13 | 14 |
|
14 | 15 | #include "logger.h" |
15 | 16 | #include "utils/executable_signature/executable_signature.h" |
16 | 17 | #include "utils/win32handle.h" |
| 18 | +#include "utils/wsscopeguard.h" |
17 | 19 |
|
18 | 20 | #pragma comment(lib, "wbemuuid.lib") |
19 | 21 |
|
@@ -567,4 +569,85 @@ bool isMacAddress(const std::wstring &value) |
567 | 569 | return valid; |
568 | 570 | } |
569 | 571 |
|
| 572 | +std::string ssidFromInterfaceGUID(const std::wstring &interfaceGUID) |
| 573 | +{ |
| 574 | + // This DLL is not available on default installs of Windows Server. Dynamically load it so |
| 575 | + // the app doesn't fail to launch with a "DLL not found" error. App profiling was performed |
| 576 | + // and indicated no performance degradation when dynamically loading and unloading the DLL. |
| 577 | + const std::wstring dll = getSystemDir() + L"\\wlanapi.dll"; |
| 578 | + auto wlanDll = ::LoadLibraryEx(dll.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); |
| 579 | + if (wlanDll == NULL) { |
| 580 | + throw std::system_error(::GetLastError(), std::generic_category(), "wlanapi.dll could not be loaded"); |
| 581 | + } |
| 582 | + |
| 583 | + auto freeDLL = wsl::wsScopeGuard([&] { |
| 584 | + ::FreeLibrary(wlanDll); |
| 585 | + }); |
| 586 | + |
| 587 | + typedef DWORD (WINAPI * WlanOpenHandleFunc)(DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle); |
| 588 | + typedef DWORD (WINAPI * WlanCloseHandleFunc)(HANDLE hClientHandle, PVOID pReserved); |
| 589 | + typedef VOID (WINAPI * WlanFreeMemoryFunc)(PVOID pMemory); |
| 590 | + typedef DWORD (WINAPI * WlanQueryInterfaceFunc)(HANDLE hClientHandle, CONST GUID *pInterfaceGuid, WLAN_INTF_OPCODE OpCode, PVOID pReserved, |
| 591 | + PDWORD pdwDataSize, PVOID *ppData, PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType); |
| 592 | + |
| 593 | + WlanOpenHandleFunc pfnWlanOpenHandle = (WlanOpenHandleFunc)::GetProcAddress(wlanDll, "WlanOpenHandle"); |
| 594 | + if (pfnWlanOpenHandle == NULL) { |
| 595 | + throw std::system_error(::GetLastError(), std::generic_category(), "Failed to load WlanOpenHandle"); |
| 596 | + } |
| 597 | + |
| 598 | + WlanCloseHandleFunc pfnWlanCloseHandle = (WlanCloseHandleFunc)::GetProcAddress(wlanDll, "WlanCloseHandle"); |
| 599 | + if (pfnWlanCloseHandle == NULL) { |
| 600 | + throw std::system_error(::GetLastError(), std::generic_category(), "Failed to load WlanCloseHandle"); |
| 601 | + } |
| 602 | + |
| 603 | + WlanFreeMemoryFunc pfnWlanFreeMemory = (WlanFreeMemoryFunc)::GetProcAddress(wlanDll, "WlanFreeMemory"); |
| 604 | + if (pfnWlanFreeMemory == NULL) { |
| 605 | + throw std::system_error(::GetLastError(), std::generic_category(), "Failed to load WlanFreeMemory"); |
| 606 | + } |
| 607 | + |
| 608 | + WlanQueryInterfaceFunc pfnWlanQueryInterface = (WlanQueryInterfaceFunc)::GetProcAddress(wlanDll, "WlanQueryInterface"); |
| 609 | + if (pfnWlanQueryInterface == NULL) { |
| 610 | + throw std::system_error(::GetLastError(), std::generic_category(), "Failed to load WlanQueryInterface"); |
| 611 | + } |
| 612 | + |
| 613 | + DWORD dwCurVersion = 0; |
| 614 | + HANDLE hClient = NULL; |
| 615 | + auto result = pfnWlanOpenHandle(2, NULL, &dwCurVersion, &hClient); |
| 616 | + if (result != ERROR_SUCCESS) { |
| 617 | + throw std::system_error(::GetLastError(), std::generic_category(), "WlanOpenHandle failed"); |
| 618 | + } |
| 619 | + |
| 620 | + PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL; |
| 621 | + |
| 622 | + auto freeWlanResources = wsl::wsScopeGuard([&] { |
| 623 | + if (pConnectInfo != NULL) { |
| 624 | + pfnWlanFreeMemory(pConnectInfo); |
| 625 | + } |
| 626 | + |
| 627 | + pfnWlanCloseHandle(hClient, NULL); |
| 628 | + }); |
| 629 | + |
| 630 | + GUID actualGUID = guidFromString(interfaceGUID); |
| 631 | + |
| 632 | + DWORD connectInfoSize = sizeof(WLAN_CONNECTION_ATTRIBUTES); |
| 633 | + WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid; |
| 634 | + |
| 635 | + result = pfnWlanQueryInterface(hClient, &actualGUID, wlan_intf_opcode_current_connection, NULL, |
| 636 | + &connectInfoSize, (PVOID *) &pConnectInfo, &opCode); |
| 637 | + if (result != ERROR_SUCCESS) { |
| 638 | + throw std::system_error(::GetLastError(), std::generic_category(), "WlanQueryInterface failed"); |
| 639 | + } |
| 640 | + |
| 641 | + std::string ssid; |
| 642 | + const auto &dot11Ssid = pConnectInfo->wlanAssociationAttributes.dot11Ssid; |
| 643 | + if (dot11Ssid.uSSIDLength > 0) { |
| 644 | + ssid.reserve(dot11Ssid.uSSIDLength); |
| 645 | + for (ULONG k = 0; k < dot11Ssid.uSSIDLength; k++) { |
| 646 | + ssid.push_back(static_cast<char>(dot11Ssid.ucSSID[k])); |
| 647 | + } |
| 648 | + } |
| 649 | + |
| 650 | + return ssid; |
| 651 | +} |
| 652 | + |
570 | 653 | } |
0 commit comments