diff options
Diffstat (limited to 'windows/nsis-plugins/src/driverlogic/context.cpp')
| -rw-r--r-- | windows/nsis-plugins/src/driverlogic/context.cpp | 212 |
1 files changed, 200 insertions, 12 deletions
diff --git a/windows/nsis-plugins/src/driverlogic/context.cpp b/windows/nsis-plugins/src/driverlogic/context.cpp index 13cb781863..4f0cb2d291 100644 --- a/windows/nsis-plugins/src/driverlogic/context.cpp +++ b/windows/nsis-plugins/src/driverlogic/context.cpp @@ -1,21 +1,33 @@ #include "stdafx.h" #include "context.h" + #include <libcommon/string.h> #include <libcommon/error.h> +#include <libcommon/memory.h> #include <log/log.h> + #include <winsock2.h> #include <ws2ipdef.h> #include <iphlpapi.h> #include <windows.h> + #include <vector> #include <list> #include <stdexcept> #include <sstream> #include <algorithm> +#include <setupapi.h> +#include <devguid.h> +#include <combaseapi.h> +#include <initguid.h> +#include <devpkey.h> + namespace { +const wchar_t TAP_HARDWARE_ID[] = L"tap0901"; + std::set<Context::NetworkAdapter> GetAllAdapters() { ULONG bufferSize = 0; @@ -89,19 +101,57 @@ void LogAdapters(const std::wstring &description, const std::set<Context::Networ PluginLogWithDetails(description, details); } -} // anonymous namespace - -Context::BaselineStatus Context::establishBaseline() +std::wstring GetNetCfgInstanceId(HDEVINFO devInfo, const SP_DEVINFO_DATA &devInfoData) { - m_baseline = GetAllAdapters(); + HKEY hNet = SetupDiOpenDevRegKey( + devInfo, + const_cast<SP_DEVINFO_DATA *>(&devInfoData), + DICS_FLAG_GLOBAL, + 0, + DIREG_DRV, + KEY_READ + ); - auto tapAdapters = GetTapAdapters(m_baseline); + if (hNet == INVALID_HANDLE_VALUE) + { + throw std::runtime_error("SetupDiOpenDevRegKey Failed"); + } - if (tapAdapters.empty()) + std::vector<wchar_t> instanceId(MAX_PATH + sizeof(L'\0')); + DWORD strSize = instanceId.size() * sizeof(wchar_t); + + const auto status = RegGetValueW( + hNet, + nullptr, + L"NetCfgInstanceId", + RRF_RT_REG_SZ, + nullptr, + instanceId.data(), + &strSize + ); + + RegCloseKey(hNet); + + if (ERROR_SUCCESS != status) { - return BaselineStatus::NO_TAP_ADAPTERS_PRESENT; + throw std::runtime_error("RegGetValue for NetCfgInstanceId failed"); } + instanceId[strSize / sizeof(wchar_t)] = L'\0'; + + return instanceId.data(); +} + +} // anonymous namespace + +//static +std::optional<Context::NetworkAdapter> Context::FindMullvadAdapter(const std::set<Context::NetworkAdapter> &tapAdapters) +{ + if (tapAdapters.empty()) + { + return std::nullopt; + } + // // Look for TAP adapter with alias "Mullvad". // @@ -113,14 +163,16 @@ Context::BaselineStatus Context::establishBaseline() return 0 == _wcsicmp(candidate.alias.c_str(), alias.c_str()); }); - return it != adapters.end(); + return it; }; static const wchar_t baseAlias[] = L"Mullvad"; - if (findByAlias(tapAdapters, baseAlias)) + const auto mullvadAdapter = findByAlias(tapAdapters, baseAlias); + + if (tapAdapters.end() != mullvadAdapter) { - return BaselineStatus::MULLVAD_ADAPTER_PRESENT; + return std::optional{ *mullvadAdapter }; } // @@ -135,12 +187,32 @@ Context::BaselineStatus Context::establishBaseline() const auto alias = ss.str(); - if (findByAlias(tapAdapters, alias)) + const auto mullvadAdapter = findByAlias(tapAdapters, alias); + + if (tapAdapters.end() != mullvadAdapter) { - return BaselineStatus::MULLVAD_ADAPTER_PRESENT; + return std::optional{ *mullvadAdapter }; } } + return std::nullopt; +} + +Context::BaselineStatus Context::establishBaseline() +{ + m_baseline = GetAllAdapters(); + const auto tapAdapters = GetTapAdapters(m_baseline); + + if (tapAdapters.empty()) + { + return BaselineStatus::NO_TAP_ADAPTERS_PRESENT; + } + + if (FindMullvadAdapter(tapAdapters).has_value()) + { + return BaselineStatus::MULLVAD_ADAPTER_PRESENT; + } + return BaselineStatus::SOME_TAP_ADAPTERS_PRESENT; } @@ -173,3 +245,119 @@ Context::NetworkAdapter Context::getNewAdapter() return *added.begin(); } + +//static +Context::DeletionResult Context::DeleteMullvadAdapter() +{ + auto tapAdapters = GetTapAdapters(GetAllAdapters()); + std::optional<NetworkAdapter> mullvadAdapter = FindMullvadAdapter(tapAdapters); + + if (!mullvadAdapter.has_value()) + { + throw std::runtime_error("Mullvad TAP adapter not found"); + } + + const auto mullvadGuid = mullvadAdapter.value().guid; + + HDEVINFO devInfo = SetupDiGetClassDevsW( + &GUID_DEVCLASS_NET, + nullptr, + nullptr, + DIGCF_PRESENT + ); + + THROW_GLE_IF(INVALID_HANDLE_VALUE, devInfo, "SetupDiGetClassDevs() failed"); + + common::memory::ScopeDestructor cleanupDevList; + cleanupDevList += [&devInfo]() + { + SetupDiDestroyDeviceInfoList(devInfo); + }; + + SP_DEVINFO_DATA devInfoData; + + std::vector<wchar_t> buffer; + DWORD nameLen; + + int numRemainingAdapters = 0; + + for (int memberIndex = 0; ; memberIndex++) + { + devInfoData = { 0 }; + devInfoData.cbSize = sizeof(devInfoData); + + if (FALSE == SetupDiEnumDeviceInfo(devInfo, memberIndex, &devInfoData)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + { + /* done */ + break; + } + THROW_GLE("Error enumerating network adapters"); + } + + if (FALSE == SetupDiGetDeviceRegistryPropertyW( + devInfo, + &devInfoData, + SPDRP_HARDWAREID, + nullptr, + nullptr, + 0, + &nameLen + )) + { + const auto status = GetLastError(); + if (ERROR_INSUFFICIENT_BUFFER != status) + { + /* ERROR_INSUFFICIENT_BUFFER is expected */ + if (ERROR_INVALID_DATA == status) + { + /* ERROR_INVALID_DATA may mean that the property does not exist */ + continue; + } + THROW_GLE("Error obtaining network adapter hardware ID length"); + } + } + + buffer.resize(nameLen / sizeof(wchar_t) + 1); + buffer[nameLen / sizeof(wchar_t)] = L'\0'; + + if (FALSE == SetupDiGetDeviceRegistryPropertyW( + devInfo, + &devInfoData, + SPDRP_HARDWAREID, + nullptr, + reinterpret_cast<PBYTE>(buffer.data()), + (buffer.size() - 1) * sizeof(wchar_t), + nullptr + )) + { + THROW_GLE("Error obtaining network adapter hardware ID"); + } + + if (wcscmp(TAP_HARDWARE_ID, buffer.data()) == 0) + { + std::wstring netCfgInstanceId = GetNetCfgInstanceId(devInfo, devInfoData); + if (netCfgInstanceId.compare(mullvadGuid) != 0) + { + numRemainingAdapters++; + continue; + } + + if (FALSE == SetupDiRemoveDevice( + devInfo, + &devInfoData + )) + { + THROW_GLE("Error removing Mullvad TAP device"); + } + } + } + + if (numRemainingAdapters > 0) + { + return DeletionResult::SOME_REMAINING_TAP_ADAPTERS; + } + + return DeletionResult::NO_REMAINING_TAP_ADAPTERS; +} |
