summaryrefslogtreecommitdiffhomepage
path: root/windows
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2018-06-27 11:45:57 +0100
committerEmīls Piņķis <emils@mullvad.net>2018-06-27 11:45:57 +0100
commit0f0ef6ff2447ce684d75920d259d84747962440f (patch)
tree6022b306d0f74b942a88251e7d1ee57759f567c4 /windows
parentfea7311975601287faed8182d48fa576483d384b (diff)
parentf97d2eb4aa9677802f7faff12d03459e0c173291 (diff)
downloadmullvadvpn-0f0ef6ff2447ce684d75920d259d84747962440f.tar.xz
mullvadvpn-0f0ef6ff2447ce684d75920d259d84747962440f.zip
Merge branch 'windows-route'
Diffstat (limited to 'windows')
-rw-r--r--windows/winfw/src/winfw/winfw.h2
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.cpp155
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.h26
-rw-r--r--windows/winroute/src/winroute/dllmain.cpp11
-rw-r--r--windows/winroute/src/winroute/stdafx.cpp8
-rw-r--r--windows/winroute/src/winroute/stdafx.h16
-rw-r--r--windows/winroute/src/winroute/targetver.h12
-rw-r--r--windows/winroute/src/winroute/winroute.cpp37
-rw-r--r--windows/winroute/src/winroute/winroute.def3
-rw-r--r--windows/winroute/src/winroute/winroute.h30
-rw-r--r--windows/winroute/src/winroute/winroute.vcxproj199
-rw-r--r--windows/winroute/src/winroute/winroute.vcxproj.filters18
-rw-r--r--windows/winroute/winroute.sln44
13 files changed, 560 insertions, 1 deletions
diff --git a/windows/winfw/src/winfw/winfw.h b/windows/winfw/src/winfw/winfw.h
index a575b4d436..4a7b0d5730 100644
--- a/windows/winfw/src/winfw/winfw.h
+++ b/windows/winfw/src/winfw/winfw.h
@@ -75,7 +75,7 @@ WinFw_Initialize(
//
// Deinitialize:
//
-// Call this function once before unloading WFPCTL or exiting the process.
+// Call this function once before unloading WINFW or exiting the process.
//
extern "C"
WINFW_LINKAGE
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.cpp b/windows/winroute/src/winroute/NetworkInterfaces.cpp
new file mode 100644
index 0000000000..4b2bc9319f
--- /dev/null
+++ b/windows/winroute/src/winroute/NetworkInterfaces.cpp
@@ -0,0 +1,155 @@
+#include "stdafx.h"
+
+#include <windows.h>
+
+#include "NetworkInterfaces.h"
+
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+#include <cstdint>
+
+#include <libcommon/string.h>
+
+
+
+
+
+PMIB_IPINTERFACE_ROW NetworkInterfaces::RowByLuid(NET_LUID rowId)
+{
+ for (int i = 0; i < (int)mInterfaces->NumEntries; ++i)
+ {
+ PMIB_IPINTERFACE_ROW row = &mInterfaces->Table[i];
+ // Currnetly, only IPv4 is supported
+ if (row->InterfaceLuid.Value == rowId.Value && row->Family == AF_INET)
+ {
+ return row;
+ }
+ }
+ return nullptr;
+}
+
+bool NetworkInterfaces::HasHighestMetric(PMIB_IPINTERFACE_ROW targetIface)
+{
+ for (unsigned int i = 0; i < mInterfaces->NumEntries; ++i)
+ {
+ PMIB_IPINTERFACE_ROW iface = &mInterfaces->Table[i];
+
+ if (iface->InterfaceLuid.Value != targetIface->InterfaceLuid.Value
+ && targetIface->Metric >= iface->Metric)
+ return false;
+ }
+ return true;
+}
+
+
+void NetworkInterfaces::EnsureIfaceMetricIsHighest(PMIB_IPINTERFACE_ROW targetIface)
+{
+ PMIB_IPINTERFACE_ROW iface;
+ DWORD success = 0;
+ for (int i = 0; i < (int)mInterfaces->NumEntries; ++i)
+ {
+ iface = &mInterfaces->Table[i];
+ // Ignoring the target interface.
+ if (iface->InterfaceLuid.Value == targetIface->InterfaceLuid.Value)
+ {
+ continue;
+ }
+
+ if (iface->UseAutomaticMetric)
+ {
+ continue;
+ }
+ iface->Metric++;
+ if (iface->Family == AF_INET) {
+ iface->SitePrefixLength = 0;
+ }
+ success = SetIpInterfaceEntry(iface);
+ if (success != NO_ERROR)
+ {
+ std::stringstream ss;
+ ss << L"Failed to increment metric for interface with LUID "
+ << &iface->InterfaceLuid.Value
+ << ": "
+ << success;
+ throw std::runtime_error(ss.str());
+ }
+
+ }
+}
+
+NetworkInterfaces::NetworkInterfaces()
+{
+ mInterfaces = nullptr;
+ DWORD success = 0;
+
+ success = GetIpInterfaceTable(AF_UNSPEC, &mInterfaces);
+ if (success != NO_ERROR)
+ {
+ std::stringstream ss;
+ ss << L"Failed to enumerate network interfaces: " << success;
+ throw std::runtime_error(ss.str());
+ }
+}
+
+bool NetworkInterfaces::SetTopMetricForInterfaceByAlias(const wchar_t * deviceAlias)
+{
+ NET_LUID targetIfaceLuid;
+ DWORD success = 0;
+ success = ConvertInterfaceAliasToLuid(deviceAlias, &targetIfaceLuid);
+ if (success != NO_ERROR)
+ {
+ std::wstringstream ss;
+ ss << L"Failed to convert interface alias '"
+ << deviceAlias
+ << "' into LUID: "
+ << success;
+ throw std::runtime_error(common::string::ToAnsi(ss.str()));
+ }
+ return SetTopMetricForInterfaceWithLuid(targetIfaceLuid);
+}
+
+bool NetworkInterfaces::SetTopMetricForInterfaceWithLuid(NET_LUID targetIfaceId)
+{
+
+ DWORD success = 0;
+
+ PMIB_IPINTERFACE_ROW targetIface = RowByLuid(targetIfaceId);
+ if (targetIface == nullptr)
+ {
+ std::stringstream ss;
+ ss << L"No interface with LUID " << targetIfaceId.Value;
+ throw std::runtime_error(ss.str());
+ }
+
+ if (targetIface->Metric == MAX_METRIC)
+ {
+ return false;
+ }
+
+ targetIface->UseAutomaticMetric = false;
+ targetIface->Metric = MAX_METRIC;
+ if (targetIface->Family == AF_INET) {
+ targetIface->SitePrefixLength = 0;
+ }
+
+ success = SetIpInterfaceEntry(targetIface);
+ if (success != NO_ERROR)
+ {
+ std::stringstream ss;
+ ss << L"Failed to set metric "
+ << MAX_METRIC
+ << " for interface with LUID "
+ << targetIfaceId.Value
+ << ". Error code - "
+ << success;
+ throw std::runtime_error(ss.str());
+ }
+ return true;
+}
+
+
+NetworkInterfaces::~NetworkInterfaces()
+{
+ FreeMibTable(mInterfaces);
+}
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.h b/windows/winroute/src/winroute/NetworkInterfaces.h
new file mode 100644
index 0000000000..66cea53fc0
--- /dev/null
+++ b/windows/winroute/src/winroute/NetworkInterfaces.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2ipdef.h>
+#include <iphlpapi.h>
+#include <netioapi.h>
+#include <cstdint>
+
+class NetworkInterfaces
+{
+
+private:
+ PMIB_IPINTERFACE_TABLE mInterfaces;
+ PMIB_IPINTERFACE_ROW RowByLuid(NET_LUID rowId);
+ bool HasHighestMetric(PMIB_IPINTERFACE_ROW targetIface);
+ void EnsureIfaceMetricIsHighest(PMIB_IPINTERFACE_ROW iface);
+
+public:
+ NetworkInterfaces();
+ bool SetTopMetricForInterfaceByAlias (const wchar_t *deviceAlias);
+ bool SetTopMetricForInterfaceWithLuid(NET_LUID targetIface);
+ ~NetworkInterfaces();
+};
+
+const static uint32_t MAX_METRIC = 1;
diff --git a/windows/winroute/src/winroute/dllmain.cpp b/windows/winroute/src/winroute/dllmain.cpp
new file mode 100644
index 0000000000..e66eb0495d
--- /dev/null
+++ b/windows/winroute/src/winroute/dllmain.cpp
@@ -0,0 +1,11 @@
+#include "stdafx.h"
+#include <windows.h>
+
+BOOL APIENTRY DllMain(HMODULE, DWORD, LPVOID)
+{
+ //
+ // Avoid doing work in DllMain since the loader lock is held
+ //
+
+ return TRUE;
+}
diff --git a/windows/winroute/src/winroute/stdafx.cpp b/windows/winroute/src/winroute/stdafx.cpp
new file mode 100644
index 0000000000..b29c52afc9
--- /dev/null
+++ b/windows/winroute/src/winroute/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// winroute.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/winroute/src/winroute/stdafx.h b/windows/winroute/src/winroute/stdafx.h
new file mode 100644
index 0000000000..677e68a9fa
--- /dev/null
+++ b/windows/winroute/src/winroute/stdafx.h
@@ -0,0 +1,16 @@
+// 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
+// Windows Header Files:
+#include <windows.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/windows/winroute/src/winroute/targetver.h b/windows/winroute/src/winroute/targetver.h
new file mode 100644
index 0000000000..b8b7263c9e
--- /dev/null
+++ b/windows/winroute/src/winroute/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>
diff --git a/windows/winroute/src/winroute/winroute.cpp b/windows/winroute/src/winroute/winroute.cpp
new file mode 100644
index 0000000000..fe5d82d3c3
--- /dev/null
+++ b/windows/winroute/src/winroute/winroute.cpp
@@ -0,0 +1,37 @@
+#include "stdafx.h"
+#include "winroute.h"
+#include "NetworkInterfaces.h"
+#include <cstdint>
+#include <stdexcept>
+
+
+extern "C"
+WINROUTE_LINKAGE
+WINROUTE_STATUS
+WINROUTE_API
+WinRoute_EnsureTopMetric(
+ const wchar_t *deviceAlias,
+ WinRouteErrorSink errorSink,
+ void* errorSinkContext
+) {
+ try
+ {
+ NetworkInterfaces interfaces;
+ bool metrics_set = interfaces.SetTopMetricForInterfaceByAlias(deviceAlias);
+ return metrics_set ? WINROUTE_STATUS::METRIC_SET : WINROUTE_STATUS::METRIC_NO_CHANGE;
+ }
+ catch (std::exception &err)
+ {
+ if (nullptr != errorSink)
+ {
+ errorSink(err.what(), errorSinkContext);
+ }
+ return WINROUTE_STATUS::FAILURE;
+
+ }
+ catch (...)
+ {
+ return WINROUTE_STATUS::FAILURE;
+ }
+};
+
diff --git a/windows/winroute/src/winroute/winroute.def b/windows/winroute/src/winroute/winroute.def
new file mode 100644
index 0000000000..d409889c50
--- /dev/null
+++ b/windows/winroute/src/winroute/winroute.def
@@ -0,0 +1,3 @@
+LIBRARY winroute
+EXPORTS
+ WinRoute_EnsureTopMetric \ No newline at end of file
diff --git a/windows/winroute/src/winroute/winroute.h b/windows/winroute/src/winroute/winroute.h
new file mode 100644
index 0000000000..593108936e
--- /dev/null
+++ b/windows/winroute/src/winroute/winroute.h
@@ -0,0 +1,30 @@
+#pragma once
+#include <cstdint>
+
+#ifdef WINROUTE_EXPORTS
+#define WINROUTE_LINKAGE __declspec(dllexport)
+#else
+#define WINROUTE_LINKAGE __declspec(dllimport)
+#endif
+
+#define WINROUTE_API __stdcall
+
+typedef void (WINROUTE_API *WinRouteErrorSink)(const char *errorMessage, void *context);
+
+enum class WINROUTE_STATUS : uint32_t
+{
+ METRIC_NO_CHANGE = 0,
+ METRIC_SET = 1,
+ FAILURE = 2,
+};
+
+
+extern "C"
+WINROUTE_LINKAGE
+WINROUTE_STATUS
+WINROUTE_API
+WinRoute_EnsureTopMetric(
+ const wchar_t *deviceAlias,
+ WinRouteErrorSink errorSink,
+ void* errorSinkContext
+); \ No newline at end of file
diff --git a/windows/winroute/src/winroute/winroute.vcxproj b/windows/winroute/src/winroute/winroute.vcxproj
new file mode 100644
index 0000000000..4cd827e52d
--- /dev/null
+++ b/windows/winroute/src/winroute/winroute.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.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>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="NetworkInterfaces.cpp" />
+ <ClCompile Include="stdafx.cpp" />
+ <ClCompile Include="winroute.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="NetworkInterfaces.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ <ClInclude Include="winroute.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="winroute.def" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>winroute</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</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|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)\bin\$(Platform)-$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)\bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <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)'=='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|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;WINROUTE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\windows-libraries\src\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ModuleDefinitionFile>winroute.def</ModuleDefinitionFile>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;WINROUTE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\windows-libraries\src\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <ModuleDefinitionFile>winroute.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;NDEBUG;WINROUTE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\windows-libraries\src\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ModuleDefinitionFile>winroute.def</ModuleDefinitionFile>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;WINROUTE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <LanguageStandard>stdcpplatest</LanguageStandard>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\windows-libraries\src\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ModuleDefinitionFile>winroute.def</ModuleDefinitionFile>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libcommon.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/windows/winroute/src/winroute/winroute.vcxproj.filters b/windows/winroute/src/winroute/winroute.vcxproj.filters
new file mode 100644
index 0000000000..0ca11ffdb2
--- /dev/null
+++ b/windows/winroute/src/winroute/winroute.vcxproj.filters
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="stdafx.cpp" />
+ <ClCompile Include="winroute.cpp" />
+ <ClCompile Include="NetworkInterfaces.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ <ClInclude Include="winroute.h" />
+ <ClInclude Include="NetworkInterfaces.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="winroute.def" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/windows/winroute/winroute.sln b/windows/winroute/winroute.sln
new file mode 100644
index 0000000000..28b21fc2f1
--- /dev/null
+++ b/windows/winroute/winroute.sln
@@ -0,0 +1,44 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2027
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winroute", "src\winroute\winroute.vcxproj", "{89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcommon", "..\windows-libraries\src\libcommon\libcommon.vcxproj", "{B52E2D10-A94A-4605-914A-2DCEF6A757EF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x64.ActiveCfg = Debug|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x64.Build.0 = Debug|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x86.ActiveCfg = Debug|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x86.Build.0 = Debug|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x64.ActiveCfg = Release|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x64.Build.0 = Release|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x86.ActiveCfg = Release|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x86.Build.0 = Release|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.ActiveCfg = Debug|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.Build.0 = Debug|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.ActiveCfg = Debug|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.Build.0 = Debug|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.ActiveCfg = Release|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.Build.0 = Release|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.ActiveCfg = Release|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B019612F-9475-4A56-A836-B74F90CE2E78}
+ EndGlobalSection
+EndGlobal