summaryrefslogtreecommitdiffhomepage
path: root/windows/libshared/src
diff options
context:
space:
mode:
authorOdd Stranne <odd@mullvad.net>2019-12-03 10:07:20 +0100
committerOdd Stranne <odd@mullvad.net>2019-12-04 13:07:57 +0100
commit877f34593b857e3f1d81d9acce003e2ededbda1d (patch)
tree6b0f78b1c6e9b0b0dc437434a37bd8fd8af969e6 /windows/libshared/src
parent80ce050ad2eee528ded8d5c1d2211534fe7485ae (diff)
downloadmullvadvpn-877f34593b857e3f1d81d9acce003e2ededbda1d.tar.xz
mullvadvpn-877f34593b857e3f1d81d9acce003e2ededbda1d.zip
Update shared logging in C++
Diffstat (limited to 'windows/libshared/src')
-rw-r--r--windows/libshared/src/libshared/libshared.vcxproj202
-rw-r--r--windows/libshared/src/libshared/libshared.vcxproj.filters45
-rw-r--r--windows/libshared/src/libshared/logging/logsink.h27
-rw-r--r--windows/libshared/src/libshared/logging/logsinkadapter.cpp49
-rw-r--r--windows/libshared/src/libshared/logging/logsinkadapter.h24
-rw-r--r--windows/libshared/src/libshared/logging/stdoutlogger.cpp33
-rw-r--r--windows/libshared/src/libshared/logging/stdoutlogger.h10
-rw-r--r--windows/libshared/src/libshared/logging/unwind.cpp21
-rw-r--r--windows/libshared/src/libshared/logging/unwind.h11
-rw-r--r--windows/libshared/src/libshared/network/interfaceutils.cpp177
-rw-r--r--windows/libshared/src/libshared/network/interfaceutils.h79
-rw-r--r--windows/libshared/src/libshared/stdafx.cpp8
-rw-r--r--windows/libshared/src/libshared/stdafx.h15
-rw-r--r--windows/libshared/src/libshared/targetver.h12
14 files changed, 713 insertions, 0 deletions
diff --git a/windows/libshared/src/libshared/libshared.vcxproj b/windows/libshared/src/libshared/libshared.vcxproj
new file mode 100644
index 0000000000..88a2ac5140
--- /dev/null
+++ b/windows/libshared/src/libshared/libshared.vcxproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <ProjectGuid>{EE69EA4A-CF71-4B88-866B-957F60C4CE0D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>libshared</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+ <ProjectName>libshared</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../../windows-libraries/src/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)-$(Configuration)\</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="network\interfaceutils.h" />
+ <ClInclude Include="logging\logsink.h" />
+ <ClInclude Include="logging\logsinkadapter.h" />
+ <ClInclude Include="logging\stdoutlogger.h" />
+ <ClInclude Include="logging\unwind.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="network\interfaceutils.cpp" />
+ <ClCompile Include="logging\logsinkadapter.cpp" />
+ <ClCompile Include="logging\stdoutlogger.cpp" />
+ <ClCompile Include="logging\unwind.cpp" />
+ <ClCompile Include="stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/windows/libshared/src/libshared/libshared.vcxproj.filters b/windows/libshared/src/libshared/libshared.vcxproj.filters
new file mode 100644
index 0000000000..ef4f0330d2
--- /dev/null
+++ b/windows/libshared/src/libshared/libshared.vcxproj.filters
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ <ClInclude Include="logging\logsink.h">
+ <Filter>logging</Filter>
+ </ClInclude>
+ <ClInclude Include="logging\logsinkadapter.h">
+ <Filter>logging</Filter>
+ </ClInclude>
+ <ClInclude Include="logging\stdoutlogger.h">
+ <Filter>logging</Filter>
+ </ClInclude>
+ <ClInclude Include="logging\unwind.h">
+ <Filter>logging</Filter>
+ </ClInclude>
+ <ClInclude Include="network\interfaceutils.h">
+ <Filter>network</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="stdafx.cpp" />
+ <ClCompile Include="logging\logsinkadapter.cpp">
+ <Filter>logging</Filter>
+ </ClCompile>
+ <ClCompile Include="logging\stdoutlogger.cpp">
+ <Filter>logging</Filter>
+ </ClCompile>
+ <ClCompile Include="logging\unwind.cpp">
+ <Filter>logging</Filter>
+ </ClCompile>
+ <ClCompile Include="network\interfaceutils.cpp">
+ <Filter>network</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="logging">
+ <UniqueIdentifier>{8d3be7e9-117c-44d3-a799-0bc6e2712776}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="network">
+ <UniqueIdentifier>{c36884fc-7afc-42a8-b852-c0aafcfcc1c2}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/windows/libshared/src/libshared/logging/logsink.h b/windows/libshared/src/libshared/logging/logsink.h
new file mode 100644
index 0000000000..e24c69ac32
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/logsink.h
@@ -0,0 +1,27 @@
+#pragma once
+
+//
+// This file is shared between DLL modules to help define their public interface.
+// It should always be C-compatible.
+//
+
+enum MULLVAD_LOG_LEVEL
+{
+ MULLVAD_LOG_LEVEL_ERROR = 0,
+ MULLVAD_LOG_LEVEL_WARNING,
+ MULLVAD_LOG_LEVEL_INFO,
+ MULLVAD_LOG_LEVEL_DEBUG,
+ MULLVAD_LOG_LEVEL_TRACE
+};
+
+//
+// The log sink is registered with a DLL during e.g. initialization.
+// It may later be activated as a direct or indirect result of calling into the DLL.
+//
+// The parameters are:
+//
+// `MULLVAD_LOG_LEVEL` - Severity of the message.
+// `const char *` - The message itself.
+// `void *` - The sink context that was registered along with the sink.
+//
+typedef void (__stdcall *MullvadLogSink)(MULLVAD_LOG_LEVEL, const char *, void *);
diff --git a/windows/libshared/src/libshared/logging/logsinkadapter.cpp b/windows/libshared/src/libshared/logging/logsinkadapter.cpp
new file mode 100644
index 0000000000..f506aba096
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/logsinkadapter.cpp
@@ -0,0 +1,49 @@
+#include "stdafx.h"
+#include "logsinkadapter.h"
+
+namespace shared::logging
+{
+
+LogSinkAdapter::LogSinkAdapter(MullvadLogSink target, void *context)
+ : LogSink(MakeAdapter(target, context))
+{
+}
+
+//static
+common::logging::LogTarget LogSinkAdapter::MakeAdapter(MullvadLogSink target, void *context)
+{
+ return [target, context](common::logging::LogLevel level, const char* msg)
+ {
+ if (nullptr == target)
+ {
+ return;
+ }
+
+ //
+ // TODO: Replace manual mapping with ValueMapper once the updated
+ // ValueMapper reaches libcommon.
+ //
+
+ const MULLVAD_LOG_LEVEL translatedLevel = [level]()
+ {
+ switch (level)
+ {
+ case common::logging::LogLevel::Warning:
+ return MULLVAD_LOG_LEVEL_WARNING;
+ case common::logging::LogLevel::Info:
+ return MULLVAD_LOG_LEVEL_INFO;
+ case common::logging::LogLevel::Trace:
+ return MULLVAD_LOG_LEVEL_TRACE;
+ case common::logging::LogLevel::Debug:
+ return MULLVAD_LOG_LEVEL_DEBUG;
+ case common::logging::LogLevel::Error:
+ default:
+ return MULLVAD_LOG_LEVEL_ERROR;
+ }
+ }();
+
+ target(translatedLevel, msg, context);
+ };
+}
+
+}
diff --git a/windows/libshared/src/libshared/logging/logsinkadapter.h b/windows/libshared/src/libshared/logging/logsinkadapter.h
new file mode 100644
index 0000000000..d077e29b4f
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/logsinkadapter.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "logsink.h"
+#include <libcommon/logging/logsink.h>
+
+namespace shared::logging
+{
+
+//
+// Adapt common::logging::LogSink C++ world to
+// MullvadLogSink C world.
+//
+class LogSinkAdapter : public common::logging::LogSink
+{
+public:
+
+ LogSinkAdapter(MullvadLogSink target, void *context);
+
+private:
+
+ static common::logging::LogTarget MakeAdapter(MullvadLogSink target, void *context);
+};
+
+}
diff --git a/windows/libshared/src/libshared/logging/stdoutlogger.cpp b/windows/libshared/src/libshared/logging/stdoutlogger.cpp
new file mode 100644
index 0000000000..6a72009950
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/stdoutlogger.cpp
@@ -0,0 +1,33 @@
+#include "stdafx.h"
+#include "stdoutlogger.h"
+#include <iostream>
+
+namespace shared::logging
+{
+
+void __stdcall StdoutLogger(MULLVAD_LOG_LEVEL level, const char *msg, void*)
+{
+ switch (level)
+ {
+ case MULLVAD_LOG_LEVEL_WARNING:
+ std::cout << "Warning: ";
+ break;
+ case MULLVAD_LOG_LEVEL_INFO:
+ std::cout << "Info: ";
+ break;
+ case MULLVAD_LOG_LEVEL_DEBUG:
+ std::cout << "Debug: ";
+ break;
+ case MULLVAD_LOG_LEVEL_TRACE:
+ std::cout << "Trace: ";
+ break;
+ case MULLVAD_LOG_LEVEL_ERROR:
+ default:
+ std::cout << "Error: ";
+ break;
+ }
+
+ std::cout << msg << std::endl;
+}
+
+}
diff --git a/windows/libshared/src/libshared/logging/stdoutlogger.h b/windows/libshared/src/libshared/logging/stdoutlogger.h
new file mode 100644
index 0000000000..d6cee1b58b
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/stdoutlogger.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "logsink.h"
+
+namespace shared::logging
+{
+
+void __stdcall StdoutLogger(MULLVAD_LOG_LEVEL level, const char *msg, void *context);
+
+}
diff --git a/windows/libshared/src/libshared/logging/unwind.cpp b/windows/libshared/src/libshared/logging/unwind.cpp
new file mode 100644
index 0000000000..206ea81ce2
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/unwind.cpp
@@ -0,0 +1,21 @@
+#include "stdafx.h"
+#include "unwind.h"
+#include "logsinkadapter.h"
+#include <libcommon/error.h>
+
+namespace shared::logging
+{
+
+void UnwindAndLog(MullvadLogSink logSink, void *logSinkContext, const std::exception &err)
+{
+ if (nullptr == logSink)
+ {
+ return;
+ }
+
+ auto logger = std::make_shared<LogSinkAdapter>(logSink, logSinkContext);
+
+ common::error::UnwindException(err, logger);
+}
+
+}
diff --git a/windows/libshared/src/libshared/logging/unwind.h b/windows/libshared/src/libshared/logging/unwind.h
new file mode 100644
index 0000000000..ab3c6c519d
--- /dev/null
+++ b/windows/libshared/src/libshared/logging/unwind.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "logsink.h"
+#include <stdexcept>
+
+namespace shared::logging
+{
+
+void UnwindAndLog(MullvadLogSink logSink, void *logSinkContext, const std::exception &err);
+
+}
diff --git a/windows/libshared/src/libshared/network/interfaceutils.cpp b/windows/libshared/src/libshared/network/interfaceutils.cpp
new file mode 100644
index 0000000000..6d56ec82d2
--- /dev/null
+++ b/windows/libshared/src/libshared/network/interfaceutils.cpp
@@ -0,0 +1,177 @@
+#include "stdafx.h"
+#include <sstream>
+#include <algorithm>
+#include "interfaceutils.h"
+#include <libcommon/error.h>
+#include <libcommon/string.h>
+
+namespace shared::network
+{
+
+InterfaceUtils::NetworkAdapter::NetworkAdapter(
+ const common::network::Nci &nci,
+ const std::shared_ptr<std::vector<uint8_t>> addressesBuffer,
+ const IP_ADAPTER_ADDRESSES &entry
+)
+ : m_addressesBuffer(addressesBuffer)
+ , m_entry(entry)
+{
+ m_guid = common::string::ToWide(entry.AdapterName);
+
+ try
+ {
+ //
+ // FIXME:
+ // Work around incorrect alias sometimes
+ // being returned on Windows 8.
+ //
+ // Steps to reproduce:
+ // 1. Install NDIS 6 TAP driver v9.00.00.21.
+ // 2. Update driver to v9.24.2.601.
+ // 3. Rename TAP adapter.
+ //
+ // GetAdaptersAddresses() returns a generic name
+ // for the *first* adapter instead of the correct
+ // one, whereas ConvertInterfaceAliasToLuid() and
+ // ConvertInterfaceLuidToAlias() yield correct values.
+ //
+
+ IID guidObj = { 0 };
+ if (S_OK != IIDFromString(&m_guid[0], &guidObj))
+ {
+ throw std::runtime_error("IIDFromString() failed");
+ }
+
+ m_alias = nci.getConnectionName(guidObj);
+ }
+ catch (const std::exception &)
+ {
+ m_alias = entry.FriendlyName;
+ }
+
+ m_name = entry.Description;
+}
+
+//static
+std::set<InterfaceUtils::NetworkAdapter> InterfaceUtils::GetAllAdapters(ULONG family, ULONG flags)
+{
+ ULONG bufferSize = 0;
+
+ auto status = GetAdaptersAddresses(family, flags, nullptr, nullptr, &bufferSize);
+
+ THROW_UNLESS(ERROR_BUFFER_OVERFLOW, status, "Probe for adapter listing buffer size");
+
+ // Memory is cheap, this avoids a looping construct.
+ bufferSize *= 2;
+
+ auto buffer = std::make_shared<std::vector<uint8_t>>(bufferSize);
+ auto addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&(*buffer)[0]);
+
+ status = GetAdaptersAddresses(family, flags, nullptr, addresses, &bufferSize);
+
+ THROW_UNLESS(ERROR_SUCCESS, status, "Retrieve adapter listing");
+
+ std::set<NetworkAdapter> adapters;
+
+ common::network::Nci nci;
+
+ for (auto it = addresses; nullptr != it; it = it->Next)
+ {
+ adapters.emplace(NetworkAdapter(nci, buffer, *it));
+ }
+
+ return adapters;
+}
+
+//static
+void InterfaceUtils::AddDeviceIpAddresses(NET_LUID device, const std::vector<SOCKADDR_INET> &addresses)
+{
+ for (const auto &address : addresses)
+ {
+ MIB_UNICASTIPADDRESS_ROW row;
+ InitializeUnicastIpAddressEntry(&row);
+
+ row.InterfaceLuid = device;
+ row.Address = address;
+
+ THROW_UNLESS(NO_ERROR, CreateUnicastIpAddressEntry(&row), "Assign IP address on network interface");
+ }
+}
+
+//static
+std::set<InterfaceUtils::NetworkAdapter>
+InterfaceUtils::GetTapAdapters(const std::set<NetworkAdapter>& adapters)
+{
+ std::set<NetworkAdapter> tapAdapters;
+
+ for (const auto& adapter : adapters)
+ {
+ static const wchar_t name[] = L"TAP-Windows Adapter V9";
+
+ //
+ // Compare partial name, because once you start having more TAP adapters
+ // they're named "TAP-Windows Adapter V9 #2" and so on.
+ //
+
+ if (0 == adapter.name().compare(0, _countof(name) - 1, name))
+ {
+ tapAdapters.insert(adapter);
+ }
+ }
+
+ return tapAdapters;
+}
+
+//static
+std::wstring InterfaceUtils::GetTapInterfaceAlias()
+{
+ //
+ // Look for TAP adapter with alias "Mullvad".
+ //
+
+ using shared::network::InterfaceUtils;
+
+ auto adapters = InterfaceUtils::GetTapAdapters(InterfaceUtils::GetAllAdapters(
+ AF_INET,
+ GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
+ ));
+
+ auto findByAlias = [](const std::set<InterfaceUtils::NetworkAdapter>& adapters, const std::wstring& alias)
+ {
+ const auto it = std::find_if(adapters.begin(), adapters.end(), [&alias](const InterfaceUtils::NetworkAdapter& candidate)
+ {
+ return 0 == _wcsicmp(candidate.alias().c_str(), alias.c_str());
+ });
+
+ return it != adapters.end();
+ };
+
+ static const wchar_t baseAlias[] = L"Mullvad";
+
+ if (findByAlias(adapters, baseAlias))
+ {
+ return baseAlias;
+ }
+
+ //
+ // Look for TAP adapter with alias "Mullvad-1", "Mullvad-2", etc.
+ //
+
+ for (auto i = 0; i < 10; ++i)
+ {
+ std::wstringstream ss;
+
+ ss << baseAlias << L"-" << i;
+
+ const auto alias = ss.str();
+
+ if (findByAlias(adapters, alias))
+ {
+ return alias;
+ }
+ }
+
+ throw std::runtime_error("Unable to find TAP adapter");
+}
+
+}
diff --git a/windows/libshared/src/libshared/network/interfaceutils.h b/windows/libshared/src/libshared/network/interfaceutils.h
new file mode 100644
index 0000000000..85a243d591
--- /dev/null
+++ b/windows/libshared/src/libshared/network/interfaceutils.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <string>
+#include <set>
+#include <vector>
+#include <memory>
+#include <cstdint>
+
+// Secret include order to get most common networking structs/apis
+// And avoiding compilation errors
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2def.h>
+#include <ws2ipdef.h>
+#include <iphlpapi.h>
+#include <netioapi.h>
+// end
+
+#include <libcommon/network/nci.h>
+
+namespace shared::network
+{
+
+class InterfaceUtils
+{
+ InterfaceUtils() = delete;
+
+public:
+
+ class NetworkAdapter
+ {
+
+ public:
+
+ const std::wstring &guid() const { return m_guid; }
+ const std::wstring &name() const { return m_name; }
+ const std::wstring &alias() const { return m_alias; }
+
+ bool operator<(const NetworkAdapter &rhs) const
+ {
+ return _wcsicmp(m_guid.c_str(), rhs.m_guid.c_str()) < 0;
+ }
+
+ const IP_ADAPTER_ADDRESSES &raw() const
+ {
+ return m_entry;
+ }
+
+ private:
+
+ NetworkAdapter(
+ const common::network::Nci &nci,
+ const std::shared_ptr<std::vector<uint8_t>> addressesBuffer,
+ const IP_ADAPTER_ADDRESSES &entry
+ );
+
+ friend class InterfaceUtils;
+
+ const IP_ADAPTER_ADDRESSES &m_entry;
+ std::shared_ptr<std::vector<uint8_t>> m_addressesBuffer;
+
+ std::wstring m_guid;
+ std::wstring m_name;
+ std::wstring m_alias;
+ };
+
+ static std::set<NetworkAdapter> GetAllAdapters(ULONG family, ULONG flags);
+
+ static void AddDeviceIpAddresses(NET_LUID device, const std::vector<SOCKADDR_INET> &addresses);
+
+ static std::set<NetworkAdapter> GetTapAdapters(const std::set<NetworkAdapter> &adapters);
+
+ //
+ // Determines alias of primary TAP adapter.
+ //
+ static std::wstring GetTapInterfaceAlias();
+};
+
+}
diff --git a/windows/libshared/src/libshared/stdafx.cpp b/windows/libshared/src/libshared/stdafx.cpp
new file mode 100644
index 0000000000..c418cf5096
--- /dev/null
+++ b/windows/libshared/src/libshared/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// shared.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/windows/libshared/src/libshared/stdafx.h b/windows/libshared/src/libshared/stdafx.h
new file mode 100644
index 0000000000..59e4616a97
--- /dev/null
+++ b/windows/libshared/src/libshared/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+#include <string>
+#include <sstream>
+#include <algorithm>
diff --git a/windows/libshared/src/libshared/targetver.h b/windows/libshared/src/libshared/targetver.h
new file mode 100644
index 0000000000..ae4a5c032c
--- /dev/null
+++ b/windows/libshared/src/libshared/targetver.h
@@ -0,0 +1,12 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <WinSDKVer.h>
+
+#define _WIN32_WINNT _WIN32_WINNT_WIN7
+
+#include <SDKDDKVer.h>