summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xbuild.sh2
-rw-r--r--build_windows_libraries.sh45
-rw-r--r--electron-builder.yml2
-rw-r--r--talpid-core/build.rs59
-rw-r--r--talpid-core/src/firewall/windows/mod.rs11
-rw-r--r--talpid-core/src/firewall/windows/route.rs63
-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
19 files changed, 693 insertions, 50 deletions
diff --git a/build.sh b/build.sh
index c75bcde8c4..afadb4d5fd 100755
--- a/build.sh
+++ b/build.sh
@@ -104,7 +104,7 @@ sed -i.bak \
################################################################################
if [[ "$(uname -s)" == "MINGW"* ]]; then
- ./build_windows_libraries.sh $1
+ CPP_BUILD_MODES="Release" ./build_windows_libraries.sh $1
fi
echo "Building Rust code in release mode using $RUSTC_VERSION..."
diff --git a/build_windows_libraries.sh b/build_windows_libraries.sh
index 2726170c75..b675112e28 100644
--- a/build_windows_libraries.sh
+++ b/build_windows_libraries.sh
@@ -3,12 +3,14 @@ set -eu
# List of solutions to build
WINFW_SOLUTIONS=${WINFW_SOLUTIONS:-"winfw"}
WINDNS_SOLUTIONS=${WINDNS_SOLUTIONS:-"windns"}
+WINROUTE_SOLUTIONS=${WINROUTE_SOLUTIONS:-"winroute"}
-# Override this variable to set your own list of build configurations for
-# wfpctl
-CPP_BUILD_MODES=${CPP_BUILD_MODES:-"Debug Release"}
-# Override this variable to set different target platforms for wfpctl
-CPP_BUILD_TARGETS=${CPP_BUILD_TARGETS:-"x86 x64"}
+# Override this variable to set your own list of build configurations. Set this
+# to "Release" to build release versions.
+CPP_BUILD_MODES=${CPP_BUILD_MODES:-"Debug"}
+# Override this variable to set different target platforms. Add "x86" to build
+# win32 versions.
+CPP_BUILD_TARGETS=${CPP_BUILD_TARGETS:-"x64"}
# Override this to set a different cargo target directory
CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-"./target/"}
@@ -46,18 +48,18 @@ function to_win_path
fi
}
-function get_wfp_output_path
+function get_solution_output_path
{
- local wfp_root=$1
+ local solution_root=$1
local build_target=$2
local build_mode=$3
case $build_target in
"x86")
- echo "$wfp_root/bin/Win32-$build_mode"
+ echo "$solution_root/bin/Win32-$build_mode"
;;
"x64")
- echo "$wfp_root/bin/x64-$build_mode"
+ echo "$solution_root/bin/x64-$build_mode"
;;
*)
echo Unkown build target $build_target
@@ -87,6 +89,25 @@ function get_cargo_target_dir
echo "$CARGO_TARGET_DIR/$platform_triplet/${build_mode,,}"
}
+function copy_outputs
+{
+ local solution_path=$1
+ local artifacts=$2
+
+ for mode in $CPP_BUILD_MODES; do
+ for target in $CPP_BUILD_TARGETS; do
+ local dll_path=$(get_solution_output_path $solution_path $target $mode)
+ local cargo_target=$(get_cargo_target_dir $target $mode)
+ mkdir -p $cargo_target
+ for artifact in $artifacts; do
+ cp "$dll_path/$artifact" "$cargo_target"
+ done
+ done
+ done
+
+}
+
+
# Since Microsoft likes to name their architectures differently from Rust, this
# function tries to match microsoft names to Rust names.
function arch_from_build_target
@@ -120,9 +141,15 @@ function main
local winfw_root_path=${CPP_ROOT_PATH:-"./windows/winfw"}
local windns_root_path=${CPP_ROOT_PATH:-"./windows/windns"}
+ local winroute_root_path=${CPP_ROOT_PATH:-"./windows/winroute"}
build_project "$winfw_root_path/winfw.sln" "$WINFW_SOLUTIONS"
build_project "$windns_root_path/windns.sln" "$WINDNS_SOLUTIONS"
+ build_project "$winroute_root_path/winroute.sln" "$WINROUTE_SOLUTIONS"
+
+ copy_outputs $winfw_root_path "winfw.dll"
+ copy_outputs $windns_root_path "windns.dll"
+ copy_outputs $winroute_root_path "winroute.dll"
}
main
diff --git a/electron-builder.yml b/electron-builder.yml
index 3558e82a69..529a47c88a 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -76,6 +76,8 @@ win:
to: .
- from: ./windows/windns/bin/x64-Release/windns.dll
to: .
+ - from: ./windows/winroute/bin/x64-Release/winroute.dll
+ to: .
- from: ./dist-assets/binaries/windows/openvpn.exe
to: .
diff --git a/talpid-core/build.rs b/talpid-core/build.rs
index 7b433cf28f..b4c66db87c 100644
--- a/talpid-core/build.rs
+++ b/talpid-core/build.rs
@@ -3,19 +3,12 @@ mod win {
use std::env;
use std::path::PathBuf;
- static WINFW_BUILD_DIR: &'static str = "..\\windows\\winfw\\bin";
- static WINDNS_BUILD_DIR: &'static str = "..\\windows\\windns\\bin";
+ pub static WINFW_BUILD_DIR: &'static str = "..\\windows\\winfw\\bin";
+ pub static WINDNS_BUILD_DIR: &'static str = "..\\windows\\windns\\bin";
+ pub static WINROUTE_BUILD_DIR: &'static str = "..\\windows\\winroute\\bin";
- pub fn default_winfw_output_dir() -> PathBuf {
- manifest_dir()
- .join(WINFW_BUILD_DIR)
- .join(&target_platform_dir())
- }
-
- pub fn default_windns_output_dir() -> PathBuf {
- manifest_dir()
- .join(WINDNS_BUILD_DIR)
- .join(&target_platform_dir())
+ pub fn default_windows_build_artifact_dir(build_dir: &str) -> PathBuf {
+ manifest_dir().join(build_dir).join(&target_platform_dir())
}
fn target_platform_dir() -> PathBuf {
@@ -43,39 +36,27 @@ mod win {
"Debug"
}
}
+
+ pub fn declare_library(env_var: &str, default_dir: &str, lib_name: &str) {
+ println!("cargo:rerun-if-env-changed={}", env_var);
+ let lib_dir = env::var_os(env_var)
+ .map(PathBuf::from)
+ .unwrap_or_else(|| default_windows_build_artifact_dir(default_dir));
+ println!("cargo:rustc-link-search={}", lib_dir.display());
+ println!("cargo:rustc-link-lib=dylib={}", lib_name);
+ }
}
#[cfg(windows)]
fn main() {
- use std::env;
- use std::path::PathBuf;
use win::*;
- const WINFW_LIB_DIR_VAR: &str = "WINFW_LIB_DIR";
- println!("cargo:rerun-if-env-changed={}", WINFW_LIB_DIR_VAR);
- let winfw_dir = env::var_os(WINFW_LIB_DIR_VAR)
- .map(PathBuf::from)
- .unwrap_or_else(default_winfw_output_dir);
-
- println!(
- "cargo:rustc-link-search={}",
- winfw_dir
- .to_str()
- .expect("failed to construct path for winfw include directory")
- );
- println!("cargo:rustc-link-lib=dylib=winfw");
-
- let windns_dir = env::var_os("WINDNS_INCLUDE_DIR")
- .map(PathBuf::from)
- .unwrap_or_else(default_windns_output_dir);
- println!(
- "cargo:rustc-link-search={}",
- windns_dir
- .to_str()
- .expect("failed to construct path for windns include directory")
- );
-
- println!("cargo:rustc-link-lib=dylib=windns");
+ const WINFW_DIR_VAR: &str = "WINFW_LIB_DIR";
+ const WINDNS_DIR_VAR: &str = "WINDNS_LIB_DIR";
+ const WINROUTE_DIR_VAR: &str = "WINROUTE_LIB_DIR";
+ declare_library(WINFW_DIR_VAR, WINFW_BUILD_DIR, "winfw");
+ declare_library(WINDNS_DIR_VAR, WINDNS_BUILD_DIR, "windns");
+ declare_library(WINROUTE_DIR_VAR, WINROUTE_BUILD_DIR, "winroute");
}
#[cfg(not(windows))]
diff --git a/talpid-core/src/firewall/windows/mod.rs b/talpid-core/src/firewall/windows/mod.rs
index 01c6dd4c53..4068cd0970 100644
--- a/talpid-core/src/firewall/windows/mod.rs
+++ b/talpid-core/src/firewall/windows/mod.rs
@@ -14,6 +14,7 @@ use self::widestring::WideCString;
#[macro_use]
mod ffi;
mod dns;
+mod route;
mod system_state;
use self::dns::WinDns;
@@ -48,6 +49,7 @@ error_chain!{
links {
WinDns(dns::Error, dns::ErrorKind) #[doc = "WinDNS failure"];
+ WinRoute(route::Error, route::ErrorKind) #[doc = "Failure to modify system routing metrics"];
}
}
@@ -157,6 +159,15 @@ impl WindowsFirewall {
};
self.dns.set_dns(&vec![tunnel_metadata.gateway.into()])?;
+
+ let metrics_set = route::ensure_top_metric_for_interface(&tunnel_metadata.interface)?;
+ if metrics_set {
+ debug!("Network interface metrics were changed");
+ } else {
+ debug!("Network interface metrics were not changed");
+ }
+
+
unsafe {
WinFw_ApplyPolicyConnected(
winfw_settings,
diff --git a/talpid-core/src/firewall/windows/route.rs b/talpid-core/src/firewall/windows/route.rs
new file mode 100644
index 0000000000..6ecf336956
--- /dev/null
+++ b/talpid-core/src/firewall/windows/route.rs
@@ -0,0 +1,63 @@
+use super::ffi;
+use super::widestring::WideCString;
+use libc;
+use std::ptr;
+
+error_chain!{
+ errors{
+ /// Failure to set metrics of network interfaces
+ MetricApplication{
+ description("Failed to set the metrics for a network interface")
+ }
+ InvalidInterfaceAlias{
+ description("Supplied interface alias is invalid")
+ }
+ }
+}
+
+/// Returns true if metrics were changed, false otherwise
+pub fn ensure_top_metric_for_interface(interface_alias: &str) -> Result<bool> {
+ let interface_alias_ws =
+ WideCString::from_str(interface_alias).chain_err(|| ErrorKind::InvalidInterfaceAlias)?;
+ unsafe {
+ WinRoute_EnsureTopMetric(
+ interface_alias_ws.as_wide_c_str().as_ptr(),
+ Some(ffi::error_sink),
+ ptr::null_mut(),
+ ).into()
+ }
+}
+
+// Allowing dead code here as this type should only ever be constructed by an
+// FFI function.
+#[allow(dead_code)]
+#[repr(u32)]
+enum MetricResult {
+ MetricsUnchanged = 0u32,
+ MetricsChanged = 1u32,
+ Failure = 2u32,
+ UnexpectedValue,
+}
+
+impl Into<Result<bool>> for MetricResult {
+ fn into(self) -> Result<bool> {
+ match self {
+ MetricResult::MetricsUnchanged => Ok(false),
+ MetricResult::MetricsChanged => Ok(true),
+ MetricResult::Failure => Err(Error::from(ErrorKind::MetricApplication)),
+ MetricResult::UnexpectedValue => {
+ error!("Unexpected return code from WinRoute_EnsureTopMetric");
+ Err(Error::from(ErrorKind::MetricApplication))
+ }
+ }
+ }
+}
+
+extern "system" {
+ #[link_name(WinRoute_EnsureTopMetric)]
+ fn WinRoute_EnsureTopMetric(
+ tunnel_interface_alias: *const libc::wchar_t,
+ sink: Option<ffi::ErrorSink>,
+ sink_context: *mut libc::c_void,
+ ) -> MetricResult;
+}
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