diff options
| author | Odd Stranne <odd@mullvad.net> | 2018-11-09 13:44:43 +0100 |
|---|---|---|
| committer | Odd Stranne <odd@mullvad.net> | 2018-11-09 13:44:43 +0100 |
| commit | 4df87e526518eeeb462eefa4f9937ea42016ca66 (patch) | |
| tree | 997954b0b788850ae8dd50da6803d27971ed0d40 | |
| parent | 900833dedc44c99aa235a11d6daf62feeddd7c0f (diff) | |
| parent | 928944cbdf49db36ebd6fb830d9a61280b598d49 (diff) | |
| download | mullvadvpn-4df87e526518eeeb462eefa4f9937ea42016ca66.tar.xz mullvadvpn-4df87e526518eeeb462eefa4f9937ea42016ca66.zip | |
Merge branch 'fix-com-deinit'
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | dist-assets/windows/installer.nsh | 29 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/driverlogic/context.cpp | 17 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/driverlogic/context.h | 9 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/driverlogic/driverlogic.cpp | 158 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/driverlogic/driverlogic.def | 2 | ||||
| m--------- | windows/windows-libraries | 0 |
7 files changed, 178 insertions, 38 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cd4059435..7c5c3ddf23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ Line wrap the file at 100 chars. Th #### Windows - Use proper app id in the registry. This avoids false-positives with certain anti-virus software. +- Fix crash on Windows 7 when closing installer. ### Security #### Linux diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh index 1de27c2b14..2eff75e688 100644 --- a/dist-assets/windows/installer.nsh +++ b/dist-assets/windows/installer.nsh @@ -29,6 +29,10 @@ !define INI_GENERAL_ERROR 0 !define INI_SUCCESS 1 +#Return codes from driverlogic::Initialize/Deinitialize +!define DRIVERLOGIC_GENERAL_ERROR 0 +!define DRIVERLOGIC_SUCCESS 1 + # # BreakInstallation # @@ -83,6 +87,17 @@ Push $0 Push $1 + driverlogic::Initialize + + Pop $0 + Pop $1 + + ${If} $0 != ${DRIVERLOGIC_SUCCESS} + StrCpy $R0 "Failed to initialize plugin 'driverlogic': $1" + log::Log $R0 + Goto InstallDriver_return_only + ${EndIf} + log::Log "Listing virtual adapters" nsExec::ExecToStack '"$TEMP\driver\tapinstall.exe" hwids ${TAP_HARDWARE_ID}' @@ -96,7 +111,7 @@ ${EndIf} log::LogWithDetails "Virtual adapters listing" $1 - + log::Log "Calling on plugin to parse adapter data" driverlogic::EstablishBaseline $1 @@ -202,6 +217,18 @@ InstallDriver_return: + driverlogic::Deinitialize + + Pop $0 + Pop $1 + + ${If} $0 != ${DRIVERLOGIC_SUCCESS} + # Do not update $R0 + log::Log "Failed to deinitialize plugin 'driverlogic': $1" + ${EndIf} + + InstallDriver_return_only: + Pop $1 Pop $0 diff --git a/windows/nsis-plugins/src/driverlogic/context.cpp b/windows/nsis-plugins/src/driverlogic/context.cpp index 178cc337d1..a01fd29bac 100644 --- a/windows/nsis-plugins/src/driverlogic/context.cpp +++ b/windows/nsis-plugins/src/driverlogic/context.cpp @@ -122,6 +122,11 @@ std::wstring DoubleBackslashes(const std::wstring &str) } // anonymous namespace +Context::Context() + : m_connection(wmi::Connection::Namespace::Cimv2) +{ +} + Context::BaselineStatus Context::establishBaseline(const std::wstring &textBlock) { m_baseline = ParseVirtualNics(textBlock); @@ -167,7 +172,6 @@ Context::VirtualNic Context::getNewAdapter() return added[0]; } -//static std::set<Context::VirtualNic> Context::ParseVirtualNics(const std::wstring &textBlock) { // ROOT\NET\0000 @@ -204,13 +208,8 @@ std::set<Context::VirtualNic> Context::ParseVirtualNics(const std::wstring &text return nics; } -//static std::wstring Context::GetNicAlias(const std::wstring &node, const std::wstring &name) { - static wmi::Connection connection(wmi::Connection::Namespace::Cimv2); - - std::wstringstream ss; - // // The name cannot be used when querying WMI, because WMI sometimes normalizes the // names in its dataset, thereby destroying their uniqueness. @@ -224,14 +223,16 @@ std::wstring Context::GetNicAlias(const std::wstring &node, const std::wstring & const auto formattedNode = DoubleBackslashes(node); + std::wstringstream ss; + ss << L"SELECT * FROM Win32_NetworkAdapter WHERE PNPDeviceID = \"" << formattedNode << L"\""; - auto resultset = connection.query(ss.str().c_str()); + auto resultset = m_connection.query(ss.str().c_str()); if (false == resultset.advance()) { PluginLog(std::wstring(L"WMI query failed for adapter: ").append(name)); - LogAllAdapters(connection); + LogAllAdapters(m_connection); throw std::runtime_error("Unable to look up virtual adapter using WMI"); } diff --git a/windows/nsis-plugins/src/driverlogic/context.h b/windows/nsis-plugins/src/driverlogic/context.h index b9d34f68d5..1340d561fe 100644 --- a/windows/nsis-plugins/src/driverlogic/context.h +++ b/windows/nsis-plugins/src/driverlogic/context.h @@ -1,5 +1,6 @@ #pragma once +#include <libcommon/wmi/connection.h> #include <set> #include <string> @@ -7,6 +8,8 @@ class Context { public: + Context(); + struct VirtualNic { std::wstring node; @@ -43,8 +46,10 @@ public: private: - static std::set<VirtualNic> ParseVirtualNics(const std::wstring &textBlock); - static std::wstring GetNicAlias(const std::wstring &node, const std::wstring &name); + common::wmi::Connection m_connection; + + std::set<VirtualNic> ParseVirtualNics(const std::wstring &textBlock); + std::wstring GetNicAlias(const std::wstring &node, const std::wstring &name); std::set<VirtualNic> m_baseline; std::set<VirtualNic> m_currentState; diff --git a/windows/nsis-plugins/src/driverlogic/driverlogic.cpp b/windows/nsis-plugins/src/driverlogic/driverlogic.cpp index 4a8911572c..2aedaf41ee 100644 --- a/windows/nsis-plugins/src/driverlogic/driverlogic.cpp +++ b/windows/nsis-plugins/src/driverlogic/driverlogic.cpp @@ -1,12 +1,19 @@ #include <stdafx.h> #include "context.h" #include <libcommon/string.h> +#include <libcommon/valuemapper.h> #include <windows.h> + +// Suppress warnings caused by broken legacy code +#pragma warning (push) +#pragma warning (disable: 4005) #include <nsis/pluginapi.h> +#pragma warning (pop) + #include <string> #include <vector> -Context g_context; +Context *g_context = nullptr; namespace { @@ -66,6 +73,53 @@ void PinDll() } // anonymous namespace // +// Initialize +// +// Call this function once during startup. +// +enum class InitializeStatus +{ + GENERAL_ERROR = 0, + SUCCESS, +}; + +void __declspec(dllexport) NSISCALL Initialize +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + if (nullptr == g_context) + { + g_context = new Context; + + PinDll(); + } + + pushstring(L""); + pushint(InitializeStatus::SUCCESS); + } + catch (std::exception &err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(InitializeStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(InitializeStatus::GENERAL_ERROR); + } +} + +// // EstablishBaseline // // Invoke with the output from "tapinstall hwids tap0901" @@ -91,34 +145,24 @@ void __declspec(dllexport) NSISCALL EstablishBaseline { EXDLL_INIT(); - try + if (nullptr == g_context) { - PinDll(); + pushstring(L"Initialize() function was not called or was not successful"); + pushint(EstablishBaselineStatus::GENERAL_ERROR); + } - auto status = EstablishBaselineStatus::GENERAL_ERROR; + try + { + using value_type = common::ValueMapper<Context::BaselineStatus, EstablishBaselineStatus>::value_type; - switch (g_context.establishBaseline(PopString())) + const common::ValueMapper<Context::BaselineStatus, EstablishBaselineStatus> mapper = { - case Context::BaselineStatus::NO_INTERFACES_PRESENT: - { - status = EstablishBaselineStatus::NO_INTERFACES_PRESENT; - break; - } - case Context::BaselineStatus::SOME_INTERFACES_PRESENT: - { - status = EstablishBaselineStatus::SOME_INTERFACES_PRESENT; - break; - } - case Context::BaselineStatus::MULLVAD_INTERFACE_PRESENT: - { - status = EstablishBaselineStatus::MULLVAD_INTERFACE_PRESENT; - break; - } - default: - { - throw std::runtime_error("Missing case handler in switch clause"); - } - } + value_type(Context::BaselineStatus::NO_INTERFACES_PRESENT, EstablishBaselineStatus::NO_INTERFACES_PRESENT), + value_type(Context::BaselineStatus::SOME_INTERFACES_PRESENT, EstablishBaselineStatus::SOME_INTERFACES_PRESENT), + value_type(Context::BaselineStatus::MULLVAD_INTERFACE_PRESENT, EstablishBaselineStatus::MULLVAD_INTERFACE_PRESENT) + }; + + const auto status = mapper.map(g_context->establishBaseline(PopString())); pushstring(L""); pushint(status); @@ -128,6 +172,11 @@ void __declspec(dllexport) NSISCALL EstablishBaseline pushstring(common::string::ToWide(err.what()).c_str()); pushint(EstablishBaselineStatus::GENERAL_ERROR); } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(EstablishBaselineStatus::GENERAL_ERROR); + } } // @@ -154,11 +203,17 @@ void __declspec(dllexport) NSISCALL IdentifyNewInterface { EXDLL_INIT(); + if (nullptr == g_context) + { + pushstring(L"Initialize() function was not called or was not successful"); + pushint(EstablishBaselineStatus::GENERAL_ERROR); + } + try { - g_context.recordCurrentState(PopString()); + g_context->recordCurrentState(PopString()); - auto nic = g_context.getNewAdapter(); + auto nic = g_context->getNewAdapter(); pushstring(nic.alias.c_str()); pushint(IdentifyNewInterfaceStatus::SUCCESS); @@ -168,4 +223,53 @@ void __declspec(dllexport) NSISCALL IdentifyNewInterface pushstring(common::string::ToWide(err.what()).c_str()); pushint(IdentifyNewInterfaceStatus::GENERAL_ERROR); } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(IdentifyNewInterfaceStatus::GENERAL_ERROR); + } +} + +// +// Deinitialize +// +// Call this function once during shutdown. +// +enum class DeinitializeStatus +{ + GENERAL_ERROR = 0, + SUCCESS, +}; + +void __declspec(dllexport) NSISCALL Deinitialize +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + delete g_context; + + pushstring(L""); + pushint(InitializeStatus::SUCCESS); + } + catch (std::exception &err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(DeinitializeStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(DeinitializeStatus::GENERAL_ERROR); + } + + g_context = nullptr; } diff --git a/windows/nsis-plugins/src/driverlogic/driverlogic.def b/windows/nsis-plugins/src/driverlogic/driverlogic.def index f65de5b6a7..3bd78e1eea 100644 --- a/windows/nsis-plugins/src/driverlogic/driverlogic.def +++ b/windows/nsis-plugins/src/driverlogic/driverlogic.def @@ -2,5 +2,7 @@ LIBRARY driverlogic EXPORTS +Initialize EstablishBaseline IdentifyNewInterface +Deinitialize diff --git a/windows/windows-libraries b/windows/windows-libraries -Subproject a1128567944fbb6472c953d39b35b2d700fe1c0 +Subproject 791fdc37245039ddf2a10aac3212d347e2d11ac |
