summaryrefslogtreecommitdiffhomepage
path: root/windows/nsis-plugins/src/driverlogic/context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'windows/nsis-plugins/src/driverlogic/context.cpp')
-rw-r--r--windows/nsis-plugins/src/driverlogic/context.cpp212
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;
+}