summaryrefslogtreecommitdiffhomepage
path: root/windows/nsis-plugins/src/driverlogic/context.cpp
diff options
context:
space:
mode:
authorOdd Stranne <odd@mullvad.net>2018-07-06 09:21:54 +0200
committerOdd Stranne <odd@mullvad.net>2018-07-10 11:32:02 +0200
commit0dbc1839e335362596564e504c4ad17fa022876c (patch)
treefd27715ba42cc9fa879d0313ee3c16890ea484cb /windows/nsis-plugins/src/driverlogic/context.cpp
parentb8ebecb5119cd0bf2ffbffaeca5f9b452db0475d (diff)
downloadmullvadvpn-0dbc1839e335362596564e504c4ad17fa022876c.tar.xz
mullvadvpn-0dbc1839e335362596564e504c4ad17fa022876c.zip
Add NSIS plugin for aiding in driver installation
Diffstat (limited to 'windows/nsis-plugins/src/driverlogic/context.cpp')
-rw-r--r--windows/nsis-plugins/src/driverlogic/context.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/windows/nsis-plugins/src/driverlogic/context.cpp b/windows/nsis-plugins/src/driverlogic/context.cpp
new file mode 100644
index 0000000000..d2481e3e67
--- /dev/null
+++ b/windows/nsis-plugins/src/driverlogic/context.cpp
@@ -0,0 +1,132 @@
+#include "stdafx.h"
+#include "context.h"
+#include <libcommon/string.h>
+#include <libcommon/wmi/connection.h>
+#include <libcommon/wmi/resultset.h>
+#include <libcommon/wmi/wmi.h>
+#include <vector>
+#include <stdexcept>
+#include <algorithm>
+#include <memory>
+#include <sstream>
+
+using namespace common;
+
+namespace
+{
+
+std::vector<std::wstring> BlockToRows(const std::wstring &textBlock)
+{
+ //
+ // This is such a hack :-(
+ //
+ // It only works because the tokenizer is greedy and because we don't care about
+ // empty lines for this usage.
+ //
+ return common::string::Tokenize(textBlock, L"\r\n");
+}
+
+} // anonymous namespace
+
+Context::BaselineStatus Context::establishBaseline(const std::wstring &textBlock)
+{
+ m_baseline = ParseVirtualNics(textBlock);
+
+ if (m_baseline.empty())
+ {
+ return BaselineStatus::NO_INTERFACES_PRESENT;
+ }
+
+ for (const auto &nic : m_baseline)
+ {
+ if (0 == _wcsicmp(nic.alias.c_str(), L"mullvad"))
+ {
+ return BaselineStatus::MULLVAD_INTERFACE_PRESENT;
+ }
+ }
+
+ return BaselineStatus::SOME_INTERFACES_PRESENT;
+}
+
+void Context::recordCurrentState(const std::wstring &textBlock)
+{
+ m_currentState = ParseVirtualNics(textBlock);
+}
+
+Context::VirtualNic Context::getNewAdapter()
+{
+ std::vector<VirtualNic> added;
+
+ for (const auto &nic : m_currentState)
+ {
+ if (m_baseline.end() == m_baseline.find(nic))
+ {
+ added.push_back(nic);
+ }
+ }
+
+ if (added.size() != 1)
+ {
+ throw std::runtime_error("Unable to identify newly added virtual adapter");
+ }
+
+ return added[0];
+}
+
+//static
+std::set<Context::VirtualNic> Context::ParseVirtualNics(const std::wstring &textBlock)
+{
+ // ROOT\NET\0000
+ // Name: TAP - Windows Adapter V9
+ // Hardware IDs :
+ // tap0901
+ // 1 matching device(s) found.
+
+ std::set<VirtualNic> nics;
+
+ auto text = BlockToRows(textBlock);
+
+ size_t line = 0;
+
+ while (nullptr != wcschr(text.at(line).c_str(), L'\\'))
+ {
+ auto nameDelimiter = wcschr(text.at(line + 1).c_str(), L':');
+
+ if (nullptr == nameDelimiter)
+ {
+ throw std::runtime_error("Unexpected formatting in input data");
+ }
+
+ VirtualNic nic;
+
+ nic.node = text.at(line);
+ nic.name = std::wstring(nameDelimiter + 2);
+ nic.alias = GetNicAlias(nic.name);
+
+ nics.emplace(std::move(nic));
+ line += 4;
+ }
+
+ return nics;
+}
+
+//static
+std::wstring Context::GetNicAlias(const std::wstring &name)
+{
+ static wmi::Connection connection(wmi::Connection::Namespace::Cimv2);
+
+ std::wstringstream ss;
+
+ ss << L"SELECT * from Win32_NetworkAdapter WHERE Name = \"" << name << L"\"";
+
+ auto resultset = connection.query(ss.str().c_str());
+
+ if (false == resultset.advance())
+ {
+ throw std::runtime_error("Unable to look up virtual adapter using WMI");
+ }
+
+ auto alias = wmi::WmiGetPropertyAlways(resultset.result(), L"NetConnectionID");
+
+ return V_BSTR(&alias);
+}