summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2022-08-26 10:42:38 +0200
committerDavid Lönnhager <david.l@mullvad.net>2022-08-26 10:42:38 +0200
commit1499e2ab919b853e714cb18a323b77db640e0a51 (patch)
tree6104e6bd86cfff5875833f71589964a7a7165b49
parent32e61accd7e01ffe08cdcf2fc743aa36346d3b43 (diff)
parent48938553008cb32fd1b5358f5f47ec82865dab27 (diff)
downloadmullvadvpn-1499e2ab919b853e714cb18a323b77db640e0a51.tar.xz
mullvadvpn-1499e2ab919b853e714cb18a323b77db640e0a51.zip
Merge branch 'install-st-on-demand'
-rw-r--r--Cargo.lock1
-rw-r--r--dist-assets/windows/installer.nsh157
-rw-r--r--gui/tasks/distribution.js1
-rw-r--r--talpid-core/Cargo.toml3
-rw-r--r--talpid-core/src/split_tunnel/windows/driver.rs15
-rw-r--r--talpid-core/src/split_tunnel/windows/mod.rs58
-rw-r--r--talpid-core/src/split_tunnel/windows/service.rs205
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs1
-rw-r--r--windows/driverlogic/driverlogic.vcxproj2
-rw-r--r--windows/driverlogic/driverlogic.vcxproj.filters2
-rw-r--r--windows/driverlogic/src/device.cpp170
-rw-r--r--windows/driverlogic/src/device.h7
-rw-r--r--windows/driverlogic/src/driverlogic.cpp115
-rw-r--r--windows/driverlogic/src/service.cpp96
-rw-r--r--windows/driverlogic/src/service.h2
-rw-r--r--windows/driverlogic/src/version.cpp125
-rw-r--r--windows/driverlogic/src/version.h30
17 files changed, 394 insertions, 596 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3be1fd40c4..ae54ff53cc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3120,6 +3120,7 @@ dependencies = [
"which",
"widestring 0.5.1",
"winapi",
+ "windows-service",
"windows-sys",
"winreg",
"zeroize",
diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh
index 7b1f552e2e..444846a3a0 100644
--- a/dist-assets/windows/installer.nsh
+++ b/dist-assets/windows/installer.nsh
@@ -23,10 +23,6 @@
# Return codes from driverlogic
!define DL_GENERAL_SUCCESS 0
!define DL_GENERAL_ERROR 1
-!define DL_ST_DRIVER_NONE_INSTALLED 2
-!define DL_ST_DRIVER_SAME_VERSION_INSTALLED 3
-!define DL_ST_DRIVER_OLDER_VERSION_INSTALLED 4
-!define DL_ST_DRIVER_NEWER_VERSION_INSTALLED 5
# Log targets
!define LOG_INSTALL 0
@@ -74,7 +70,6 @@
# The working directory cannot be deleted, so make sure it's set to $TEMP.
SetOutPath "$TEMP"
- RMDir /r "$TEMP\mullvad-split-tunnel"
Delete "$TEMP\wintun.dll"
Delete "$TEMP\mullvad-wireguard.dll"
Delete "$TEMP\driverlogic.exe"
@@ -88,6 +83,20 @@
!define CleanupTempFiles '!insertmacro "CleanupTempFiles"'
#
+# ExtractDriverlogic
+#
+# Extract device setup tools to $TEMP
+#
+!macro ExtractDriverlogic
+
+ SetOutPath "$TEMP"
+ File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe"
+
+!macroend
+
+!define ExtractDriverlogic '!insertmacro "ExtractDriverlogic"'
+
+#
# ExtractWireGuard
#
# Extract Wintun and WireGuardNT installer into $TEMP
@@ -97,7 +106,6 @@
SetOutPath "$TEMP"
File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wintun\wintun.dll"
File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wireguard-nt\mullvad-wireguard.dll"
- File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe"
!macroend
@@ -119,23 +127,6 @@
!define ExtractMullvadSetup '!insertmacro "ExtractMullvadSetup"'
#
-# ExtractSplitTunnelDriver
-#
-# Extract split tunnel driver and associated files into $TEMP\mullvad-split-tunnel
-#
-!macro ExtractSplitTunnelDriver
-
- SetOutPath "$TEMP\mullvad-split-tunnel"
- File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\split-tunnel\mullvad-split-tunnel.cat"
- File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\split-tunnel\mullvad-split-tunnel.inf"
- File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\split-tunnel\mullvad-split-tunnel.sys"
- File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe"
-
-!macroend
-
-!define ExtractSplitTunnelDriver '!insertmacro "ExtractSplitTunnelDriver"'
-
-#
# RemoveWintun
#
# Try to remove Wintun
@@ -314,97 +305,6 @@
!define InstallService '!insertmacro "InstallService"'
#
-# InstallSplitTunnelDriver
-#
-# Install split tunnel driver
-#
-# Returns: 0 in $R0 on success, otherwise an error message in $R0
-#
-!macro InstallSplitTunnelDriver
-
- log::Log "InstallSplitTunnelDriver()"
-
- Push $0
- Push $1
-
- log::Log "Searching for and evaluating already installed Split Tunneling driver"
- nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-evaluate "$TEMP\mullvad-split-tunnel\mullvad-split-tunnel.inf"'
-
- Pop $0
- Pop $1
-
- ${If} $0 == ${DL_ST_DRIVER_NONE_INSTALLED}
- log::Log "No currently installed Split Tunneling driver"
- Goto InstallSplitTunnelDriver_new_install
- ${OrIf} $0 == ${DL_ST_DRIVER_SAME_VERSION_INSTALLED}
- log::Log "Up-to-date Split Tunneling driver already installed"
- Goto InstallSplitTunnelDriver_success
- ${OrIf} $0 == ${DL_ST_DRIVER_OLDER_VERSION_INSTALLED}
- log::Log "An older version of the Split Tunneling driver is installed"
- Goto InstallSplitTunnelDriver_force_install
- ${OrIf} $0 == ${DL_ST_DRIVER_NEWER_VERSION_INSTALLED}
- log::Log "A newer version of the Split Tunneling driver is installed"
- Goto InstallSplitTunnelDriver_force_install
- ${Else}
- IntFmt $0 "0x%X" $0
- StrCpy $R0 "Failed to search for and evaluate driver: error $0"
- log::LogWithDetails $R0 $1
- Goto InstallSplitTunnelDriver_return
- ${EndIf}
-
- InstallSplitTunnelDriver_new_install:
-
- log::Log "Installing Split Tunneling driver"
- nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-new-install "$TEMP\mullvad-split-tunnel\mullvad-split-tunnel.inf"'
-
- Pop $0
- Pop $1
-
- ${If} $0 != ${DL_GENERAL_SUCCESS}
- IntFmt $0 "0x%X" $0
- StrCpy $R0 "Failed to install driver: error $0"
- log::LogWithDetails $R0 $1
- Goto InstallSplitTunnelDriver_return
- ${EndIf}
-
- Goto InstallSplitTunnelDriver_success
-
- InstallSplitTunnelDriver_force_install:
-
- #
- # Would be possible to check driver state here and warn the user if driver is engaged.
- #
-
- log::Log "Installing Split Tunneling driver"
- nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-force-install "$TEMP\mullvad-split-tunnel\mullvad-split-tunnel.inf"'
-
- Pop $0
- Pop $1
-
- ${If} $0 != ${DL_GENERAL_SUCCESS}
- IntFmt $0 "0x%X" $0
- StrCpy $R0 "Failed to install driver: error $0"
- log::LogWithDetails $R0 $1
- Goto InstallSplitTunnelDriver_return
- ${EndIf}
-
- InstallSplitTunnelDriver_success:
-
- log::Log "InstallSplitTunnelDriver() completed successfully"
-
- Push 0
- Pop $R0
-
- InstallSplitTunnelDriver_return:
-
- Pop $1
- Pop $0
-
-!macroend
-
-!define InstallSplitTunnelDriver '!insertmacro "InstallSplitTunnelDriver"'
-
-#
# RemoveSplitTunnelDriver
#
# Reset and remove split tunnel driver
@@ -417,7 +317,7 @@
Push $1
log::Log "Removing Split Tunneling driver"
- nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-remove'
+ nsExec::ExecToStack '"$TEMP\driverlogic.exe" st-remove'
Pop $0
Pop $1
@@ -893,18 +793,21 @@
${RemoveRelayCache}
${RemoveApiAddressCache}
- SetOutPath "$TEMP"
- File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe"
+ ${ExtractDriverlogic}
${RemoveAbandonedWintunAdapter}
- ${ExtractSplitTunnelDriver}
- ${InstallSplitTunnelDriver}
+ ${If} $R0 != 0
+ MessageBox MB_OK "$R0"
+ Goto customInstall_abort_installation
+ ${EndIf}
+
+ ${RemoveSplitTunnelDriver}
${If} $R0 != 0
MessageBox MB_OK "$R0"
Goto customInstall_abort_installation
${EndIf}
-
+
${InstallService}
${If} $R0 != 0
@@ -1133,6 +1036,7 @@
Pop $Silent
+ ${ExtractDriverlogic}
${ExtractMullvadSetup}
${If} $Silent == 1
@@ -1179,6 +1083,16 @@
Goto customRemoveFiles_abort
${EndIf}
+ # Precaution: If the daemon fails to exit gracefully,
+ # attempt to remove the driver here. Otherwise, the
+ # installer may fail to delete the install dir.
+
+ ${RemoveSplitTunnelDriver}
+
+ ${If} $R0 != 0
+ Goto customRemoveFiles_abort
+ ${EndIf}
+
# Remove application files
log::Log "Deleting $INSTDIR"
RMDir /r $INSTDIR
@@ -1212,9 +1126,6 @@
${RemoveWintun}
${RemoveWireGuardNt}
- ${ExtractSplitTunnelDriver}
- ${RemoveSplitTunnelDriver}
-
log::SetLogTarget ${LOG_VOID}
${RemoveLogsAndCache}
diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js
index 8fde833d4f..75e0f246cc 100644
--- a/gui/tasks/distribution.js
+++ b/gui/tasks/distribution.js
@@ -146,6 +146,7 @@ const config = {
{ from: distAssets('binaries/x86_64-pc-windows-msvc/openvpn.exe'), to: '.' },
{ from: root('build/lib/x86_64-pc-windows-msvc/libwg.dll'), to: '.' },
{ from: distAssets('binaries/x86_64-pc-windows-msvc/wintun/wintun.dll'), to: '.' },
+ { from: distAssets('binaries/x86_64-pc-windows-msvc/split-tunnel/mullvad-split-tunnel.sys'), to: '.' },
{
from: distAssets('binaries/x86_64-pc-windows-msvc/wireguard-nt/mullvad-wireguard.dll'),
to: '.',
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index 6216a23bb2..d36460cf41 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -84,12 +84,14 @@ winreg = { version = "0.7", features = ["transactions"] }
winapi = { version = "0.3.6", features = ["ws2def"] }
talpid-platform-metadata = { path = "../talpid-platform-metadata" }
memoffset = "0.6"
+windows-service = "0.5.0"
[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.36.1"
features = [
"Win32_Foundation",
"Win32_Globalization",
+ "Win32_Security",
"Win32_System_Com",
"Win32_System_Diagnostics_ToolHelp",
"Win32_System_Ioctl",
@@ -97,6 +99,7 @@ features = [
"Win32_System_LibraryLoader",
"Win32_System_ProcessStatus",
"Win32_System_Registry",
+ "Win32_System_Services",
"Win32_System_SystemServices",
"Win32_System_Threading",
"Win32_System_WindowsProgramming",
diff --git a/talpid-core/src/split_tunnel/windows/driver.rs b/talpid-core/src/split_tunnel/windows/driver.rs
index f73e170cce..a3eb338c8c 100644
--- a/talpid-core/src/split_tunnel/windows/driver.rs
+++ b/talpid-core/src/split_tunnel/windows/driver.rs
@@ -214,8 +214,14 @@ pub enum DeviceHandleError {
impl DeviceHandle {
pub fn new() -> Result<Self, DeviceHandleError> {
- // Connect to the driver
+ let device = Self::new_handle_only()?;
+ device.reinitialize()?;
+ Ok(device)
+ }
+
+ pub(super) fn new_handle_only() -> Result<Self, DeviceHandleError> {
log::trace!("Connecting to the driver");
+
let handle = OpenOptions::new()
.read(true)
.write(true)
@@ -228,10 +234,7 @@ impl DeviceHandle {
Some(ERROR_ACCESS_DENIED) => DeviceHandleError::ConnectionDenied,
_ => DeviceHandleError::ConnectionError(e),
})?;
-
- let device = Self { handle };
- device.reinitialize()?;
- Ok(device)
+ Ok(Self { handle })
}
pub fn reinitialize(&self) -> Result<(), DeviceHandleError> {
@@ -385,7 +388,7 @@ impl DeviceHandle {
Ok(())
}
- fn reset(&self) -> io::Result<()> {
+ pub(super) fn reset(&self) -> io::Result<()> {
device_io_control(self, DriverIoctlCode::Reset as u32, None, 0)?;
Ok(())
}
diff --git a/talpid-core/src/split_tunnel/windows/mod.rs b/talpid-core/src/split_tunnel/windows/mod.rs
index 47c7d4ec8f..ed5102ab45 100644
--- a/talpid-core/src/split_tunnel/windows/mod.rs
+++ b/talpid-core/src/split_tunnel/windows/mod.rs
@@ -1,5 +1,6 @@
mod driver;
mod path_monitor;
+mod service;
mod volume_monitor;
mod windows;
@@ -39,10 +40,18 @@ const RESERVED_IP_V4: Ipv4Addr = Ipv4Addr::new(192, 0, 2, 123);
#[derive(err_derive::Error, Debug)]
#[error(no_from)]
pub enum Error {
+ /// Failed to install or start driver service
+ #[error(display = "Failed to start driver service")]
+ ServiceError(#[error(source)] service::Error),
+
/// Failed to initialize the driver
#[error(display = "Failed to initialize driver")]
InitializationError(#[error(source)] driver::DeviceHandleError),
+ /// Failed to reset the driver
+ #[error(display = "Failed to reset driver")]
+ ResetError(#[error(source)] io::Error),
+
/// Failed to set paths to excluded applications
#[error(display = "Failed to set list of excluded applications")]
SetConfiguration(#[error(source)] io::Error),
@@ -117,6 +126,7 @@ enum Request {
SetPaths(Vec<OsString>),
RegisterIps(InterfaceAddresses),
Restart,
+ Stop,
}
type RequestResponseTx = sync_mpsc::Sender<Result<(), Error>>;
type RequestTx = sync_mpsc::Sender<(Request, RequestResponseTx)>;
@@ -173,6 +183,7 @@ impl SplitTunnel {
/// Initialize the split tunnel device.
pub fn new(
runtime: tokio::runtime::Handle,
+ resource_dir: PathBuf,
daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>,
volume_update_rx: mpsc::UnboundedReceiver<()>,
power_mgmt_rx: PowerManagementListener,
@@ -180,7 +191,7 @@ impl SplitTunnel {
let excluded_processes = Arc::new(RwLock::new(HashMap::new()));
let (request_tx, handle) =
- Self::spawn_request_thread(volume_update_rx, excluded_processes.clone())?;
+ Self::spawn_request_thread(resource_dir, volume_update_rx, excluded_processes.clone())?;
let (event_thread, quit_event) =
Self::spawn_event_listener(handle, excluded_processes.clone())?;
@@ -400,6 +411,7 @@ impl SplitTunnel {
}
fn spawn_request_thread(
+ resource_dir: PathBuf,
volume_update_rx: mpsc::UnboundedReceiver<()>,
excluded_processes: Arc<RwLock<HashMap<usize, ExcludedProcess>>>,
) -> Result<(RequestTx, Arc<driver::DeviceHandle>), Error> {
@@ -421,10 +433,14 @@ impl SplitTunnel {
);
std::thread::spawn(move || {
- let result = driver::DeviceHandle::new()
- .map(Arc::new)
- .map_err(Error::InitializationError);
- let handle = match result {
+ let init_fn = || {
+ service::install_driver_if_required(&resource_dir).map_err(Error::ServiceError)?;
+ driver::DeviceHandle::new()
+ .map(Arc::new)
+ .map_err(Error::InitializationError)
+ };
+
+ let handle = match init_fn() {
Ok(handle) => {
let _ = init_tx.send(Ok(handle.clone()));
handle
@@ -518,6 +534,20 @@ impl SplitTunnel {
Ok(())
})()
}
+ Request::Stop => {
+ if let Err(error) = handle.reset().map_err(Error::ResetError) {
+ let _ = response_tx.send(Err(error));
+ continue;
+ }
+
+ monitored_paths.lock().unwrap().clear();
+ excluded_processes.write().unwrap().clear();
+
+ let _ = response_tx.send(Ok(()));
+
+ // Stop listening to commands
+ break;
+ }
};
if response_tx.send(response).is_err() {
log::error!("A response could not be sent for a completed request");
@@ -531,6 +561,16 @@ impl SplitTunnel {
error.display_chain_with_msg("Failed to shut down path monitor")
);
}
+
+ drop(handle);
+
+ log::debug!("Stopping ST service");
+ if let Err(error) = service::stop_driver_service() {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to stop ST service")
+ );
+ }
});
let handle = init_rx
@@ -718,9 +758,11 @@ impl Drop for SplitTunnel {
// Not joining `event_thread`: It may be unresponsive.
}
- let paths: [&OsStr; 0] = [];
- if let Err(error) = self.set_paths_sync(&paths) {
- log::error!("{}", error.display_chain());
+ if let Err(error) = self.send_request(Request::Stop) {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to stop ST driver service")
+ );
}
}
}
diff --git a/talpid-core/src/split_tunnel/windows/service.rs b/talpid-core/src/split_tunnel/windows/service.rs
new file mode 100644
index 0000000000..e71e9abc1d
--- /dev/null
+++ b/talpid-core/src/split_tunnel/windows/service.rs
@@ -0,0 +1,205 @@
+use std::{
+ ffi::{OsStr, OsString},
+ io,
+ path::{Path, PathBuf},
+ time::Duration,
+};
+use windows_service::{
+ service::{
+ Service, ServiceAccess, ServiceErrorControl, ServiceInfo, ServiceStartType, ServiceState,
+ ServiceType,
+ },
+ service_manager::{ServiceManager, ServiceManagerAccess},
+};
+use windows_sys::Win32::Foundation::{ERROR_SERVICE_ALREADY_RUNNING, ERROR_SERVICE_DOES_NOT_EXIST};
+
+const SPLIT_TUNNEL_SERVICE: &str = "mullvad-split-tunnel";
+const SPLIT_TUNNEL_DISPLAY_NAME: &str = "Mullvad Split Tunnel Service";
+const DRIVER_FILENAME: &str = "mullvad-split-tunnel.sys";
+
+const WAIT_STATUS_TIMEOUT: Duration = Duration::from_secs(8);
+
+#[derive(err_derive::Error, Debug)]
+#[error(no_from)]
+pub enum Error {
+ /// Failed to open service control manager
+ #[error(display = "Failed to connect to service control manager")]
+ OpenServiceControlManager(#[error(source)] windows_service::Error),
+
+ /// Failed to create a service handle
+ #[error(display = "Failed to open service")]
+ OpenServiceHandle(#[error(source)] windows_service::Error),
+
+ /// Failed to start split tunnel service
+ #[error(display = "Failed to start split tunnel device driver service")]
+ StartService(#[error(source)] windows_service::Error),
+
+ /// Failed to check service status
+ #[error(display = "Failed to query service status")]
+ QueryServiceStatus(#[error(source)] windows_service::Error),
+
+ /// Failed to open service config
+ #[error(display = "Failed to retrieve service config")]
+ QueryServiceConfig(#[error(source)] windows_service::Error),
+
+ /// Failed to install ST service
+ #[error(display = "Failed to install split tunnel driver")]
+ InstallService(#[error(source)] windows_service::Error),
+
+ /// Failed to start ST service
+ #[error(display = "Timed out waiting on service to start")]
+ StartTimeout,
+
+ /// Failed to connect to existing driver
+ #[error(display = "Failed to open service handle")]
+ OpenHandle(#[error(source)] super::driver::DeviceHandleError),
+
+ /// Failed to reset existing driver
+ #[error(display = "Failed to reset driver state")]
+ ResetDriver(#[error(source)] io::Error),
+}
+
+pub fn install_driver_if_required(resource_dir: &Path) -> Result<(), Error> {
+ let scm = ServiceManager::local_computer(
+ None::<OsString>,
+ ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE,
+ )
+ .map_err(Error::OpenServiceControlManager)?;
+
+ let expected_syspath = resource_dir.join(DRIVER_FILENAME);
+
+ let service = match scm.open_service(SPLIT_TUNNEL_SERVICE, ServiceAccess::all()) {
+ Ok(service) => service,
+ Err(error) => {
+ return match error {
+ windows_service::Error::Winapi(io_error)
+ if io_error.raw_os_error() == Some(ERROR_SERVICE_DOES_NOT_EXIST as i32) =>
+ {
+ // TODO: could be marked for deletion
+ install_driver(&scm, &expected_syspath)
+ }
+ error => Err(Error::OpenServiceHandle(error)),
+ };
+ }
+ };
+
+ if expected_syspath != get_driver_binpath(&service)? {
+ log::debug!("ST driver is already installed");
+ return start_and_wait_for_service(&service);
+ }
+
+ log::debug!("Replacing ST driver due to unexpected path");
+
+ remove_device(service)?;
+ install_driver(&scm, &expected_syspath)
+}
+
+pub fn stop_driver_service() -> Result<(), Error> {
+ let scm = ServiceManager::local_computer(None::<OsString>, ServiceManagerAccess::CONNECT)
+ .map_err(Error::OpenServiceControlManager)?;
+
+ let service = match scm.open_service(SPLIT_TUNNEL_SERVICE, ServiceAccess::all()) {
+ Ok(service) => service,
+ Err(error) => {
+ return match error {
+ windows_service::Error::Winapi(io_error)
+ if io_error.raw_os_error() == Some(ERROR_SERVICE_DOES_NOT_EXIST as i32) =>
+ {
+ Ok(())
+ }
+ error => Err(Error::OpenServiceHandle(error)),
+ };
+ }
+ };
+
+ stop_service(&service)
+}
+
+fn stop_service(service: &Service) -> Result<(), Error> {
+ let _ = service.stop();
+ wait_for_status(service, ServiceState::Stopped)
+}
+
+fn remove_device(service: Service) -> Result<(), Error> {
+ reset_driver(&service)?;
+ stop_service(&service)?;
+ let _ = service.delete();
+ Ok(())
+}
+
+fn reset_driver(service: &Service) -> Result<(), Error> {
+ let status = service.query_status().map_err(Error::QueryServiceStatus)?;
+
+ if status.current_state == ServiceState::Running {
+ let old_handle =
+ super::driver::DeviceHandle::new_handle_only().map_err(Error::OpenHandle)?;
+ old_handle.reset().map_err(Error::ResetDriver)?;
+ }
+
+ Ok(())
+}
+
+fn install_driver(scm: &ServiceManager, syspath: &Path) -> Result<(), Error> {
+ log::debug!("Installing split tunnel driver");
+
+ let service_info = ServiceInfo {
+ name: SPLIT_TUNNEL_SERVICE.into(),
+ display_name: SPLIT_TUNNEL_DISPLAY_NAME.into(),
+ service_type: ServiceType::KERNEL_DRIVER,
+ start_type: ServiceStartType::OnDemand,
+ error_control: ServiceErrorControl::Normal,
+ executable_path: syspath.to_path_buf(),
+ launch_arguments: vec![],
+ dependencies: vec![],
+ account_name: None,
+ account_password: None,
+ };
+
+ let service = scm
+ .create_service(
+ &service_info,
+ ServiceAccess::START | ServiceAccess::QUERY_STATUS,
+ )
+ .map_err(Error::InstallService)?;
+
+ start_and_wait_for_service(&service)
+}
+
+fn start_and_wait_for_service(service: &Service) -> Result<(), Error> {
+ log::debug!("Starting split tunnel service");
+
+ if let Err(error) = service.start::<&OsStr>(&[]) {
+ if let windows_service::Error::Winapi(error) = &error {
+ if error.raw_os_error() == Some(ERROR_SERVICE_ALREADY_RUNNING as i32) {
+ return Ok(());
+ }
+ }
+ return Err(Error::StartService(error));
+ }
+
+ wait_for_status(service, ServiceState::Running)
+}
+
+fn wait_for_status(service: &Service, target_state: ServiceState) -> Result<(), Error> {
+ let initial_time = std::time::Instant::now();
+ loop {
+ let status = service.query_status().map_err(Error::QueryServiceStatus)?;
+
+ if status.current_state == target_state {
+ break;
+ }
+
+ if initial_time.elapsed() >= WAIT_STATUS_TIMEOUT {
+ return Err(Error::StartTimeout);
+ }
+
+ std::thread::sleep(std::time::Duration::from_secs(1));
+ }
+
+ Ok(())
+}
+
+fn get_driver_binpath(service: &Service) -> Result<PathBuf, Error> {
+ let config = service.query_config().map_err(Error::QueryServiceConfig)?;
+ Ok(config.executable_path)
+}
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 061798b1e2..c1b52278f0 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -261,6 +261,7 @@ impl TunnelStateMachine {
#[cfg(windows)]
let split_tunnel = split_tunnel::SplitTunnel::new(
runtime.clone(),
+ args.resource_dir.clone(),
args.command_tx.clone(),
volume_update_rx,
power_mgmt_rx.clone(),
diff --git a/windows/driverlogic/driverlogic.vcxproj b/windows/driverlogic/driverlogic.vcxproj
index cc46c1ac72..3172356a60 100644
--- a/windows/driverlogic/driverlogic.vcxproj
+++ b/windows/driverlogic/driverlogic.vcxproj
@@ -104,7 +104,6 @@
<ClCompile Include="src\service.cpp" />
<ClCompile Include="src\stdafx.cpp" />
<ClCompile Include="src\util.cpp" />
- <ClCompile Include="src\version.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\devenum.h" />
@@ -115,7 +114,6 @@
<ClInclude Include="src\stdafx.h" />
<ClInclude Include="src\targetver.h" />
<ClInclude Include="src\util.h" />
- <ClInclude Include="src\version.h" />
<ClInclude Include="src\wintun.h" />
<ClInclude Include="src\wireguard.h" />
</ItemGroup>
diff --git a/windows/driverlogic/driverlogic.vcxproj.filters b/windows/driverlogic/driverlogic.vcxproj.filters
index 9665231376..bd73d30029 100644
--- a/windows/driverlogic/driverlogic.vcxproj.filters
+++ b/windows/driverlogic/driverlogic.vcxproj.filters
@@ -13,7 +13,6 @@
<ClCompile Include="src\device.cpp" />
<ClCompile Include="src\service.cpp" />
<ClCompile Include="src\log.cpp" />
- <ClCompile Include="src\version.cpp" />
<ClCompile Include="src\util.cpp" />
<ClCompile Include="src\devenum.cpp" />
</ItemGroup>
@@ -24,7 +23,6 @@
<ClInclude Include="src\device.h" />
<ClInclude Include="src\service.h" />
<ClInclude Include="src\log.h" />
- <ClInclude Include="src\version.h" />
<ClInclude Include="src\util.h" />
<ClInclude Include="src\wintun.h" />
<ClInclude Include="src\devenum.h" />
diff --git a/windows/driverlogic/src/device.cpp b/windows/driverlogic/src/device.cpp
index e38709f01d..71abb56266 100644
--- a/windows/driverlogic/src/device.cpp
+++ b/windows/driverlogic/src/device.cpp
@@ -38,47 +38,6 @@ constexpr SIZE_T ST_DRIVER_STATE_STARTED = 1;
// Onwards.
//
-void
-ThrowUpdateException
-(
- DWORD lastError,
- const char *operation
-)
-{
- if (ERROR_DEVICE_INSTALLER_NOT_READY == lastError)
- {
- bool deviceInstallDisabled = false;
-
- try
- {
- const auto key = common::registry::Registry::OpenKey
- (
- HKEY_LOCAL_MACHINE,
- L"SYSTEM\\CurrentControlSet\\Services\\DeviceInstall\\Parameters"
- );
-
- deviceInstallDisabled = (0 != key->readUint32(L"DeviceInstallDisabled"));
- }
- catch (...)
- {
- }
-
- if (deviceInstallDisabled)
- {
- throw common::error::WindowsException
- (
- "Device installs must be enabled to continue. "
- "Enable them in the Local Group Policy editor, or "
- "update the registry value DeviceInstallDisabled in "
- "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DeviceInstall\\Parameters]",
- lastError
- );
- }
- }
-
- THROW_SETUPAPI_ERROR(lastError, operation);
-}
-
} // anonymous namespace
std::wstring
@@ -196,135 +155,6 @@ GetDeviceNetCfgInstanceId
}
void
-CreateDevice
-(
- const GUID &classGuid,
- const std::wstring &deviceName,
- const std::wstring &deviceHardwareId
-)
-{
- Log(L"Attempting to create device");
-
- const auto deviceInfoSet = SetupDiCreateDeviceInfoList(&classGuid, 0);
-
- if (INVALID_HANDLE_VALUE == deviceInfoSet)
- {
- THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiCreateDeviceInfoList");
- }
-
- common::memory::ScopeDestructor scopeDestructor;
-
- scopeDestructor += [&deviceInfoSet]()
- {
- SetupDiDestroyDeviceInfoList(deviceInfoSet);
- };
-
- SP_DEVINFO_DATA devInfoData {0};
- devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-
- auto status = SetupDiCreateDeviceInfoW
- (
- deviceInfoSet,
- deviceName.c_str(),
- &classGuid,
- nullptr,
- 0,
- DICD_GENERATE_ID,
- &devInfoData
- );
-
- if (FALSE == status)
- {
- THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiCreateDeviceInfoW");
- }
-
- status = SetupDiSetDeviceRegistryPropertyW
- (
- deviceInfoSet,
- &devInfoData,
- SPDRP_HARDWAREID,
- reinterpret_cast<const BYTE *>(deviceHardwareId.c_str()),
- static_cast<DWORD>(deviceHardwareId.size() * sizeof(wchar_t))
- );
-
- if (FALSE == status)
- {
- THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiSetDeviceRegistryPropertyW");
- }
-
- //
- // Create a devnode in the PnP HW tree
- //
- status = SetupDiCallClassInstaller
- (
- DIF_REGISTERDEVICE,
- deviceInfoSet,
- &devInfoData
- );
-
- if (FALSE == status)
- {
- THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiCallClassInstaller");
- }
-
- Log(L"Created new device successfully");
-}
-
-void
-InstallDriverForDevice
-(
- const std::wstring &deviceHardwareId,
- const std::wstring &infPath
-)
-{
- Log(L"Attempting to install new driver");
-
- DWORD installFlags = 0;
- BOOL rebootRequired = FALSE;
-
- for (;;)
- {
- auto result = UpdateDriverForPlugAndPlayDevicesW
- (
- nullptr,
- deviceHardwareId.c_str(),
- infPath.c_str(),
- installFlags,
- &rebootRequired
- );
-
- if (FALSE != result)
- {
- break;
- }
-
- const auto lastError = GetLastError();
-
- if (ERROR_NO_MORE_ITEMS == lastError
- && (0 == (installFlags & INSTALLFLAG_FORCE)))
- {
- Log(L"Driver installation/update failed. Attempting forced install.");
- installFlags |= INSTALLFLAG_FORCE;
-
- continue;
- }
-
- ThrowUpdateException(lastError, "UpdateDriverForPlugAndPlayDevicesW");
- }
-
- //
- // Driver successfully installed or updated
- //
-
- std::wstringstream ss;
-
- ss << L"Device driver update complete. Reboot required: "
- << rebootRequired;
-
- Log(ss.str());
-}
-
-void
UninstallDevice
(
const EnumeratedDevice &device
diff --git a/windows/driverlogic/src/device.h b/windows/driverlogic/src/device.h
index b8bc0e7f41..4dc8c4500d 100644
--- a/windows/driverlogic/src/device.h
+++ b/windows/driverlogic/src/device.h
@@ -39,13 +39,6 @@ CreateDevice
);
void
-InstallDriverForDevice
-(
- const std::wstring &deviceHardwareId,
- const std::wstring &infPath
-);
-
-void
UninstallDevice
(
const EnumeratedDevice &device
diff --git a/windows/driverlogic/src/driverlogic.cpp b/windows/driverlogic/src/driverlogic.cpp
index 2fdcc3046c..895272fa4f 100644
--- a/windows/driverlogic/src/driverlogic.cpp
+++ b/windows/driverlogic/src/driverlogic.cpp
@@ -3,7 +3,6 @@
#include "device.h"
#include "service.h"
#include "log.h"
-#include "version.h"
#include "wintun.h"
#include "wireguard.h"
#include "devenum.h"
@@ -20,8 +19,6 @@
namespace
{
-constexpr wchar_t SPLIT_TUNNEL_HARDWARE_ID[] = L"Root\\mullvad-split-tunnel";
-
DEFINE_GUID(WFP_CALLOUTS_CLASS_ID,
0x57465043, 0x616C, 0x6C6F, 0x75, 0x74, 0x5F, 0x63, 0x6C, 0x61, 0x73, 0x73);
@@ -30,11 +27,7 @@ constexpr wchar_t SPLIT_TUNNEL_DEVICE_NAME[] = L"Mullvad Split Tunnel Device";
enum ReturnCode
{
GENERAL_SUCCESS = 0,
- GENERAL_ERROR = 1,
- ST_DRIVER_NONE_INSTALLED = 2,
- ST_DRIVER_SAME_VERSION_INSTALLED = 3,
- ST_DRIVER_OLDER_VERSION_INSTALLED = 4,
- ST_DRIVER_NEWER_VERSION_INSTALLED = 5
+ GENERAL_ERROR = 1
};
class ArgumentContext
@@ -105,74 +98,6 @@ std::unique_ptr<DeviceEnumerator> CreateSplitTunnelDeviceEnumerator()
}
//
-// CommandSplitTunnelEvaluate()
-//
-// Search for existing device.
-// Evaluate if provided inf can/should be installed.
-//
-ReturnCode CommandSplitTunnelEvaluate(const std::vector<std::wstring> &args)
-{
- ArgumentContext argsContext(args);
-
- argsContext.ensureExactArgumentCount(1);
-
- const auto infPath = argsContext.next();
-
- //
- // Find first matching device
- //
-
- auto enumerator = CreateSplitTunnelDeviceEnumerator();
-
- EnumeratedDevice device;
-
- if (!enumerator->next(device))
- {
- return ReturnCode::ST_DRIVER_NONE_INSTALLED;
- }
-
- //
- // Retrieve driver versions
- //
-
- auto existingVersion = GetDriverVersion(device);
- auto proposedVersion = InfGetDriverVersion(infPath);
-
- //
- // Compare driver versions
- //
-
- switch (EvaluateDriverUpgrade(existingVersion, proposedVersion))
- {
- case DRIVER_UPGRADE_STATUS::WOULD_UPGRADE:
- return ReturnCode::ST_DRIVER_OLDER_VERSION_INSTALLED;
- case DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE:
- return ReturnCode::ST_DRIVER_NEWER_VERSION_INSTALLED;
- case DRIVER_UPGRADE_STATUS::WOULD_INSTALL_SAME_VERSION:
- return ReturnCode::ST_DRIVER_SAME_VERSION_INSTALLED;
- default:
- Log(L"Unexpected return value from EvaluateDriverUpgrade()");
- }
-
- return ReturnCode::GENERAL_ERROR;
-}
-
-ReturnCode CommandSplitTunnelNewInstall(const std::vector<std::wstring> &args)
-{
- ArgumentContext argsContext(args);
-
- argsContext.ensureExactArgumentCount(1);
-
- const auto infPath = argsContext.next();
-
- CreateDevice(WFP_CALLOUTS_CLASS_ID, SPLIT_TUNNEL_DEVICE_NAME, SPLIT_TUNNEL_HARDWARE_ID);
-
- InstallDriverForDevice(SPLIT_TUNNEL_HARDWARE_ID, infPath);
-
- return ReturnCode::GENERAL_SUCCESS;
-}
-
-//
// CommandSplitTunnelRemove()
//
// Reset driver
@@ -186,48 +111,29 @@ ReturnCode CommandSplitTunnelRemove(const std::vector<std::wstring> &args)
argsContext.ensureExactArgumentCount(0);
+ if (ServiceIsRunning(L"mullvad-split-tunnel"))
+ {
+ ResetDriverState();
+ }
+
//
- // Find first matching device
+ // Uninstall device, if it exists
//
auto enumerator = CreateSplitTunnelDeviceEnumerator();
EnumeratedDevice device;
- if (!enumerator->next(device))
+ if (enumerator->next(device))
{
- Log(L"Could not find split tunnel device");
-
- return ReturnCode::GENERAL_SUCCESS;
+ UninstallDevice(device);
}
- ResetDriverState();
-
- UninstallDevice(device);
-
PokeService(L"mullvad-split-tunnel", true, true);
return ReturnCode::GENERAL_SUCCESS;
}
-//
-// CommandSplitTunnelForceInstall()
-//
-// There's an existing device that needs to be stopped and removed.
-// After this, create a new device and associate the specified inf.
-//
-ReturnCode CommandSplitTunnelForceInstall(const std::vector<std::wstring> &args)
-{
- auto status = CommandSplitTunnelRemove({});
-
- if (ReturnCode::GENERAL_SUCCESS != status)
- {
- return status;
- }
-
- return CommandSplitTunnelNewInstall(args);
-}
-
ReturnCode CommandWintunDeleteDriver(const std::vector<std::wstring> &args)
{
ArgumentContext argsContext(args);
@@ -336,9 +242,6 @@ int wmain(int argc, const wchar_t *argv[])
std::vector<CommandHandler> handlers =
{
- { L"st-evaluate", CommandSplitTunnelEvaluate },
- { L"st-new-install", CommandSplitTunnelNewInstall },
- { L"st-force-install", CommandSplitTunnelForceInstall },
{ L"st-remove", CommandSplitTunnelRemove },
{ L"wintun-delete-driver", CommandWintunDeleteDriver },
{ L"wintun-delete-abandoned-device", CommandWintunDeleteAbandonedDevice },
diff --git a/windows/driverlogic/src/service.cpp b/windows/driverlogic/src/service.cpp
index 14ed7880fa..cdaaf77ea9 100644
--- a/windows/driverlogic/src/service.cpp
+++ b/windows/driverlogic/src/service.cpp
@@ -43,29 +43,46 @@ private:
TTime m_maxWaitTime;
};
+SERVICE_STATUS_PROCESS GetServiceProcessStatus(SC_HANDLE service)
+{
+ SERVICE_STATUS_PROCESS ssp;
+
+ DWORD bytesNeeded;
+
+ auto status = QueryServiceStatusEx
+ (
+ service,
+ SC_STATUS_PROCESS_INFO,
+ reinterpret_cast<BYTE*>(&ssp),
+ sizeof(ssp),
+ &bytesNeeded
+ );
+
+ if (status != 0)
+ {
+ return ssp;
+ }
+
+ THROW_WINDOWS_ERROR(GetLastError(), "QueryServiceStatusEx");
+}
+
void WaitUntilServiceStopped(SC_HANDLE service, DWORD maxWaitMs)
{
TimeBox timer(maxWaitMs);
for (;;)
{
- SERVICE_STATUS_PROCESS ssp;
-
- DWORD bytesNeeded;
-
- auto status = QueryServiceStatusEx
- (
- service,
- SC_STATUS_PROCESS_INFO,
- reinterpret_cast<BYTE*>(&ssp),
- sizeof(ssp),
- &bytesNeeded
- );
+ try
+ {
+ const auto status = GetServiceProcessStatus(service);
- if (status != 0
- && ssp.dwCurrentState == SERVICE_STOPPED)
+ if (status.dwCurrentState == SERVICE_STOPPED)
+ {
+ return;
+ }
+ }
+ catch (...)
{
- return;
}
if (timer.expired())
@@ -77,6 +94,44 @@ void WaitUntilServiceStopped(SC_HANDLE service, DWORD maxWaitMs)
}
}
+bool ServiceIsRunning(const std::wstring &serviceName)
+{
+ const auto serviceManager = OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
+
+ if (serviceManager == NULL)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "OpenSCManagerW");
+ }
+
+ common::memory::ScopeDestructor dtor;
+
+ dtor += [serviceManager]()
+ {
+ CloseServiceHandle(serviceManager);
+ };
+
+ const auto service = OpenServiceW(serviceManager, serviceName.c_str(), SERVICE_ALL_ACCESS);
+
+ if (service == NULL)
+ {
+ const auto error = GetLastError();
+
+ if (error != ERROR_SERVICE_DOES_NOT_EXIST)
+ {
+ THROW_WINDOWS_ERROR(error, "OpenServiceW");
+ }
+
+ return false;
+ }
+
+ dtor += [service]()
+ {
+ CloseServiceHandle(service);
+ };
+
+ return GetServiceProcessStatus(service).dwCurrentState == SERVICE_RUNNING;
+}
+
void PokeService(const std::wstring &serviceName, bool stopService, bool deleteService)
{
auto serviceManager = OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
@@ -97,7 +152,16 @@ void PokeService(const std::wstring &serviceName, bool stopService, bool deleteS
if (service == NULL)
{
- THROW_WINDOWS_ERROR(GetLastError(), "OpenServiceW");
+ const auto error = GetLastError();
+
+ if (error != ERROR_SERVICE_DOES_NOT_EXIST)
+ {
+ THROW_WINDOWS_ERROR(error, "OpenServiceW");
+ }
+
+ // If the service does not exist, we're done.
+
+ return;
}
dtor += [service]()
diff --git a/windows/driverlogic/src/service.h b/windows/driverlogic/src/service.h
index 87632faf1b..423d16c0f0 100644
--- a/windows/driverlogic/src/service.h
+++ b/windows/driverlogic/src/service.h
@@ -2,6 +2,6 @@
#include <windows.h>
-void WaitUntilServiceStopped(SC_HANDLE service, DWORD maxWaitMs);
+bool ServiceIsRunning(const std::wstring &serviceName);
void PokeService(const std::wstring &serviceName, bool stopService, bool deleteService);
diff --git a/windows/driverlogic/src/version.cpp b/windows/driverlogic/src/version.cpp
deleted file mode 100644
index d7394e224b..0000000000
--- a/windows/driverlogic/src/version.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "stdafx.h"
-#include "version.h"
-#include "device.h"
-#include <setupapi.h>
-#include <initguid.h>
-#include <devpkey.h>
-#include <libcommon/string.h>
-#include <libcommon/memory.h>
-#include <stdexcept>
-
-DRIVER_UPGRADE_STATUS
-EvaluateDriverUpgrade
-(
- const std::wstring &existingVersion,
- const std::wstring &proposedVersion
-)
-{
- //
- // "x.y.z.a"
- //
-
- using namespace common::string;
-
- auto et = Tokenize(existingVersion, L".");
- auto pt = Tokenize(proposedVersion, L".");
-
- auto items = min(et.size(), pt.size());
-
- for (auto index = 0; index < items; ++index)
- {
- auto ev = wcstoul(et[index].c_str(), nullptr, 10);
- auto pv = wcstoul(pt[index].c_str(), nullptr, 10);
-
- if (pv > ev)
- {
- return DRIVER_UPGRADE_STATUS::WOULD_UPGRADE;
- }
-
- if (ev > pv)
- {
- return DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE;
- }
- }
-
- if (pt.size() > et.size())
- {
- return DRIVER_UPGRADE_STATUS::WOULD_UPGRADE;
- }
-
- if (et.size() > pt.size())
- {
- return DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE;
- }
-
- return DRIVER_UPGRADE_STATUS::WOULD_INSTALL_SAME_VERSION;
-}
-
-std::wstring
-InfGetDriverVersion
-(
- const std::wstring &filePath
-)
-{
- auto infHandle = SetupOpenInfFileW(filePath.c_str(), nullptr, INF_STYLE_WIN4, nullptr);
-
- if (infHandle == INVALID_HANDLE_VALUE)
- {
- throw std::runtime_error("SetupOpenInfFileW()");
- }
-
- common::memory::ScopeDestructor dtor;
-
- dtor += [infHandle]()
- {
- SetupCloseInfFile(infHandle);
- };
-
- INFCONTEXT infContext { 0 };
-
- auto status = SetupFindFirstLineW(infHandle, L"Version", L"DriverVer", &infContext);
-
- if (status == FALSE)
- {
- throw std::runtime_error("SetupFindFirstLineW()");
- }
-
- DWORD requiredSize;
-
- //
- // This is a multi-value key.
- // 0 = key, 1 = driver date
- //
- const DWORD VersionFieldIndex = 2;
-
- status = SetupGetStringFieldW(&infContext, VersionFieldIndex, nullptr, 0, &requiredSize);
-
- if (status == FALSE || requiredSize < 2)
- {
- throw std::runtime_error("SetupGetStringFieldW()");
- }
-
- std::vector<wchar_t> buffer(requiredSize);
-
- status = SetupGetStringFieldW(&infContext, VersionFieldIndex,
- &buffer[0], static_cast<DWORD>(buffer.size()), nullptr);
-
- if (status == FALSE)
- {
- throw std::runtime_error("SetupGetStringFieldW()");
- }
-
- // Remove null terminator.
- buffer.resize(requiredSize - 1);
-
- return buffer.data();
-}
-
-std::wstring
-GetDriverVersion
-(
- const EnumeratedDevice &device
-)
-{
- return GetDeviceStringProperty(device.deviceInfoSet, device.deviceInfo, &DEVPKEY_Device_DriverVersion);
-}
diff --git a/windows/driverlogic/src/version.h b/windows/driverlogic/src/version.h
deleted file mode 100644
index fc88b3b232..0000000000
--- a/windows/driverlogic/src/version.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-#include <string>
-#include "device.h"
-
-enum class DRIVER_UPGRADE_STATUS
-{
- WOULD_DOWNGRADE,
- WOULD_INSTALL_SAME_VERSION,
- WOULD_UPGRADE
-};
-
-DRIVER_UPGRADE_STATUS
-EvaluateDriverUpgrade
-(
- const std::wstring &existingVersion,
- const std::wstring &proposedVersion
-);
-
-std::wstring
-InfGetDriverVersion
-(
- const std::wstring &filePath
-);
-
-std::wstring
-GetDriverVersion
-(
- const EnumeratedDevice &device
-);