summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-02-04 17:00:34 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-02-04 17:00:34 +0100
commitef166a9f898eb9a98cc35d6b6dfb2fd410831892 (patch)
treec95213f25501f63025e631a765c0d9722d221250
parent94849a26faa34223e61282d0b9595bd26c70c4e2 (diff)
parent7f6e1ae579189756f4e9a133d93b938ed769efbf (diff)
downloadmullvadvpn-ef166a9f898eb9a98cc35d6b6dfb2fd410831892.tar.xz
mullvadvpn-ef166a9f898eb9a98cc35d6b6dfb2fd410831892.zip
Merge branch 'driverlogic-update'
m---------dist-assets/binaries0
-rw-r--r--dist-assets/windows/installer.nsh86
-rw-r--r--windows/driverlogic/src/driverlogic.cpp247
3 files changed, 150 insertions, 183 deletions
diff --git a/dist-assets/binaries b/dist-assets/binaries
-Subproject 90a76633747020f346f07cf7b92e6470941ad00
+Subproject 90b0c06b59a0b9d6cda69924377335f39854b21
diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh
index d25ec9c58c..d44b0a7aae 100644
--- a/dist-assets/windows/installer.nsh
+++ b/dist-assets/windows/installer.nsh
@@ -27,14 +27,6 @@
# Return codes from driverlogic
!define DL_GENERAL_ERROR 0
!define DL_GENERAL_SUCCESS 1
-!define DL_DELETE_NO_ADAPTERS_REMAIN 2
-!define DL_DELETE_SOME_ADAPTERS_REMAIN 3
-
-# Return codes from tapinstall
-!define DEVCON_EXIT_OK 0
-!define DEVCON_EXIT_REBOOT 1
-!define DEVCON_EXIT_FAIL 2
-!define DEVCON_EXIT_USAGE 3
# Log targets
!define LOG_FILE 0
@@ -66,27 +58,27 @@
!define BreakInstallation '!insertmacro "BreakInstallation"'
#
-# ExtractDriver
+# ExtractTapDriver
#
# Extract the correct driver for the current platform
-# placing it into $TEMP\driver
+# placing it into $TEMP\tap-driver
#
-!macro ExtractDriver
+!macro ExtractTapDriver
- SetOutPath "$TEMP\driver"
+ SetOutPath "$TEMP\tap-driver"
File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-Release\driverlogic.exe"
- File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\driver\*"
+ File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\tap-driver\*"
${If} ${AtLeastWin10}
- File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\driver\win10\*"
+ File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\tap-driver\win10\*"
${Else}
- File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\driver\win8\*"
+ File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\tap-driver\win8\*"
${EndIf}
!macroend
-!define ExtractDriver '!insertmacro "ExtractDriver"'
+!define ExtractTapDriver '!insertmacro "ExtractTapDriver"'
#
# ExtractWintun
@@ -171,7 +163,7 @@
Push $0
Push $1
- nsExec::ExecToStack '"$TEMP\driver\tapinstall.exe" remove ${TAP_HARDWARE_ID}'
+ nsExec::ExecToStack '"$TEMP\tap-driver\driverlogic.exe" remove ${TAP_HARDWARE_ID}'
Pop $0
Pop $1
@@ -194,7 +186,7 @@
log::Log "RemoveVanillaTap()"
- nsExec::ExecToStack '"$TEMP\driver\driverlogic.exe" remove-vanilla-tap'
+ nsExec::ExecToStack '"$TEMP\tap-driver\driverlogic.exe" remove-vanilla-tap'
Pop $0
Pop $1
@@ -206,23 +198,6 @@
Goto RemoveVanillaTap_return
${EndIf}
- ${If} $0 == ${DL_DELETE_NO_ADAPTERS_REMAIN}
- log::Log "Removing vanilla TAP adapter driver since it is no longer in use"
-
- nsExec::ExecToStack '"$TEMP\driver\tapinstall.exe" remove ${DEPRECATED_TAP_HARDWARE_ID}'
-
- Pop $0
- Pop $1
-
- ${If} $0 != ${DEVCON_EXIT_OK}
- ${AndIf} $0 != ${DEVCON_EXIT_REBOOT}
- StrCpy $R0 "Failed to remove driver: $1"
- log::Log $R0
-
- Goto RemoveVanillaTap_return
- ${EndIf}
- ${EndIf}
-
log::Log "RemoveVanillaTap() completed successfully"
RemoveVanillaTap_return:
@@ -238,17 +213,17 @@
!define RemoveVanillaTap '!insertmacro "RemoveVanillaTap"'
#
-# InstallDriver
+# InstallTapDriver
#
-# Install tunnel driver or update it if already present on the system
+# Install OpenVPN TAP adapter driver
#
# Returns: 0 in $R0 on success, otherwise an error message in $R0
#
-!macro InstallDriver
+!macro InstallTapDriver
- Var /GLOBAL InstallDriver_TapName
+ Var /GLOBAL InstallTapDriver_TapName
- log::Log "InstallDriver()"
+ log::Log "InstallTapDriver()"
Push $0
Push $1
@@ -264,7 +239,7 @@
${IfNot} ${AtLeastWin10}
log::Log "Adding OpenVPN certificate to the certificate store"
- nsExec::ExecToStack '"$SYSDIR\certutil.exe" -f -addstore TrustedPublisher "$TEMP\driver\driver.cer"'
+ nsExec::ExecToStack '"$SYSDIR\certutil.exe" -f -addstore TrustedPublisher "$TEMP\tap-driver\driver.cer"'
Pop $0
Pop $1
@@ -275,20 +250,19 @@
${EndIf}
log::Log "Creating new virtual adapter"
- nsExec::ExecToStack '"$TEMP\driver\driverlogic.exe" install "$TEMP\driver\OemVista.inf"'
+ nsExec::ExecToStack '"$TEMP\tap-driver\driverlogic.exe" install "$TEMP\tap-driver\OemVista.inf"'
Pop $0
Pop $1
- ${If} $0 != ${DEVCON_EXIT_OK}
- ${AndIf} $0 != ${DEVCON_EXIT_REBOOT}
+ ${If} $0 != ${DL_GENERAL_SUCCESS}
StrCpy $R0 "Failed to create virtual adapter: error $0"
log::LogWithDetails $R0 $1
- Goto InstallDriver_return
+ Goto InstallTapDriver_return
${EndIf}
log::Log "Identifying recently added adapter"
- nsExec::ExecToStack '"$TEMP\driver\driverlogic.exe" find-tap'
+ nsExec::ExecToStack '"$TEMP\tap-driver\driverlogic.exe" find-tap'
Pop $0
Pop $1
@@ -296,10 +270,10 @@
${If} $0 != ${DL_GENERAL_SUCCESS}
StrCpy $R0 "Failed to identify new adapter: $1"
log::Log $R0
- Goto InstallDriver_return
+ Goto InstallTapDriver_return
${EndIf}
- StrCpy $InstallDriver_TapName $1
+ StrCpy $InstallTapDriver_TapName $1
log::Log "New virtual adapter is named $\"$1$\""
log::Log "Renaming adapter to $\"Mullvad$\""
@@ -313,26 +287,26 @@
StrCpy $R0 "Failed to rename virtual adapter: error $0"
log::LogWithDetails $R0 $1
- ${ForceRenameAdapter} $InstallDriver_TapName "Mullvad"
+ ${ForceRenameAdapter} $InstallTapDriver_TapName "Mullvad"
${If} $R0 != 0
- Goto InstallDriver_return
+ Goto InstallTapDriver_return
${EndIf}
${EndIf}
- log::Log "InstallDriver() completed successfully"
+ log::Log "InstallTapDriver() completed successfully"
Push 0
Pop $R0
- InstallDriver_return:
+ InstallTapDriver_return:
Pop $1
Pop $0
!macroend
-!define InstallDriver '!insertmacro "InstallDriver"'
+!define InstallTapDriver '!insertmacro "InstallTapDriver"'
#
# RemoveWintun
@@ -763,8 +737,8 @@
${RemoveRelayCache}
- ${ExtractDriver}
- ${InstallDriver}
+ ${ExtractTapDriver}
+ ${InstallTapDriver}
${If} $R0 != 0
MessageBox MB_OK "Fatal error during driver installation: $R0"
@@ -846,7 +820,7 @@
${RemoveCLIFromEnvironPath}
# Remove the TAP adapter
- ${ExtractDriver}
+ ${ExtractTapDriver}
${RemoveBrandedTap}
# If not ran silently
diff --git a/windows/driverlogic/src/driverlogic.cpp b/windows/driverlogic/src/driverlogic.cpp
index 16704b6c2b..e426cc2243 100644
--- a/windows/driverlogic/src/driverlogic.cpp
+++ b/windows/driverlogic/src/driverlogic.cpp
@@ -14,6 +14,7 @@
#include <devguid.h>
#include <devpkey.h>
#include <newdev.h>
+#include <cfgmgr32.h>
namespace
@@ -26,9 +27,7 @@ constexpr wchar_t TAP_BASE_ALIAS[] = L"Mullvad";
enum ReturnCodes
{
GENERAL_ERROR,
- GENERAL_SUCCESS,
- DELETE_NO_ADAPTERS_REMAIN,
- DELETE_SOME_ADAPTERS_REMAIN
+ GENERAL_SUCCESS
};
struct NetworkAdapter
@@ -69,7 +68,7 @@ void LogAdapters(const std::wstring &description, const std::set<NetworkAdapter>
std::optional<std::wstring> GetDeviceRegistryStringProperty(
HDEVINFO devInfo,
- SP_DEVINFO_DATA *devInfoData,
+ const SP_DEVINFO_DATA &devInfoData,
DWORD property
)
{
@@ -81,7 +80,7 @@ std::optional<std::wstring> GetDeviceRegistryStringProperty(
const auto sizeStatus = SetupDiGetDeviceRegistryPropertyW(
devInfo,
- devInfoData,
+ const_cast<SP_DEVINFO_DATA*>(&devInfoData),
property,
nullptr,
nullptr,
@@ -110,7 +109,7 @@ std::optional<std::wstring> GetDeviceRegistryStringProperty(
const auto status = SetupDiGetDeviceRegistryPropertyW(
devInfo,
- devInfoData,
+ const_cast<SP_DEVINFO_DATA*>(&devInfoData),
property,
nullptr,
reinterpret_cast<PBYTE>(&buffer[0]),
@@ -128,7 +127,7 @@ std::optional<std::wstring> GetDeviceRegistryStringProperty(
std::wstring GetDeviceStringProperty(
HDEVINFO devInfo,
- SP_DEVINFO_DATA *devInfoData,
+ const SP_DEVINFO_DATA &devInfoData,
const DEVPROPKEY *property
)
{
@@ -141,7 +140,7 @@ std::wstring GetDeviceStringProperty(
const auto sizeStatus = SetupDiGetDevicePropertyW(
devInfo,
- devInfoData,
+ const_cast<SP_DEVINFO_DATA*>(&devInfoData),
property,
&type,
nullptr,
@@ -168,7 +167,7 @@ std::wstring GetDeviceStringProperty(
const auto status = SetupDiGetDevicePropertyW(
devInfo,
- devInfoData,
+ const_cast<SP_DEVINFO_DATA*>(&devInfoData),
property,
&type,
reinterpret_cast<PBYTE>(&buffer[0]),
@@ -187,14 +186,14 @@ std::wstring GetDeviceStringProperty(
std::wstring GetDeviceInstanceId(
HDEVINFO devInfo,
- SP_DEVINFO_DATA *devInfoData
+ const SP_DEVINFO_DATA &devInfoData
)
{
DWORD requiredSize = 0;
SetupDiGetDeviceInstanceIdW(
devInfo,
- devInfoData,
+ const_cast<SP_DEVINFO_DATA*>(&devInfoData),
nullptr,
0,
&requiredSize
@@ -204,7 +203,7 @@ std::wstring GetDeviceInstanceId(
const auto status = SetupDiGetDeviceInstanceIdW(
devInfo,
- devInfoData,
+ const_cast<SP_DEVINFO_DATA *>(&devInfoData),
&deviceInstanceId[0],
requiredSize,
nullptr
@@ -257,11 +256,41 @@ std::wstring GetNetCfgInstanceId(HDEVINFO devInfo, const SP_DEVINFO_DATA &devInf
return instanceId.data();
}
-std::set<NetworkAdapter> GetTapAdapters(const std::wstring &tapHardwareId)
+bool DeleteDevice(HDEVINFO devInfo, const SP_DEVINFO_DATA &devInfoData)
{
- std::set<NetworkAdapter> adapters;
+ const auto data = const_cast<SP_DEVINFO_DATA *>(&devInfoData);
+
+ wchar_t devId[MAX_DEVICE_ID_LEN];
+ if (CR_SUCCESS != CM_Get_Device_IDW(data->DevInst, devId, sizeof(devId) / sizeof(devId[0]), 0))
+ {
+ // skip
+ return false;
+ }
+
+ SP_REMOVEDEVICE_PARAMS rmdParams = { 0 };
+ rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
+ rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
+ rmdParams.HwProfile = 0;
+
+ auto status = SetupDiSetClassInstallParamsW(devInfo, data, &rmdParams.ClassInstallHeader, sizeof(rmdParams));
+ if (FALSE == status)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "SetupDiSetClassInstallParamsW");
+ }
+
+ status = SetupDiCallClassInstaller(DIF_REMOVE, devInfo, data);
+ if (FALSE == status)
+ {
+ THROW_WINDOWS_ERROR(GetLastError(), "SetupDiCallClassInstaller");
+ }
- HDEVINFO devInfo = SetupDiGetClassDevs(
+ return true;
+}
+
+void ForEachDevice(const std::wstring &tapHardwareId, std::function<void(HDEVINFO, const SP_DEVINFO_DATA &)> func)
+{
+ HDEVINFO devInfo = SetupDiGetClassDevsW(
&GUID_DEVCLASS_NET,
nullptr,
nullptr,
@@ -270,17 +299,15 @@ std::set<NetworkAdapter> GetTapAdapters(const std::wstring &tapHardwareId)
if (INVALID_HANDLE_VALUE == devInfo)
{
- THROW_WINDOWS_ERROR(GetLastError(), "SetupDiGetClassDevs() failed");
+ THROW_WINDOWS_ERROR(GetLastError(), "SetupDiGetClassDevsW");
}
- common::memory::ScopeDestructor scopeDestructor;
- scopeDestructor += [devInfo]()
+ common::memory::ScopeDestructor cleanupDevList;
+ cleanupDevList += [&devInfo]()
{
SetupDiDestroyDeviceInfoList(devInfo);
};
- common::network::Nci nci;
-
for (int memberIndex = 0; ; memberIndex++)
{
SP_DEVINFO_DATA devInfoData = { 0 };
@@ -292,26 +319,45 @@ std::set<NetworkAdapter> GetTapAdapters(const std::wstring &tapHardwareId)
if (ERROR_NO_MORE_ITEMS == lastError)
{
- // Done
break;
}
- THROW_WINDOWS_ERROR(lastError, "SetupDiEnumDeviceInfo() failed while enumerating network adapters");
+ THROW_WINDOWS_ERROR(lastError, "Enumerating network adapters");
}
try
{
- //
- // Check whether this is a TAP adapter
- //
+ const auto hardwareId = GetDeviceRegistryStringProperty(devInfo, devInfoData, SPDRP_HARDWAREID);
- const auto hardwareId = GetDeviceRegistryStringProperty(devInfo, &devInfoData, SPDRP_HARDWAREID);
- if (!hardwareId.has_value()
- || wcscmp(hardwareId.value().c_str(), tapHardwareId.c_str()) != 0)
+ if (!hardwareId.has_value() ||
+ 0 != tapHardwareId.compare(hardwareId.value()))
{
continue;
}
+ }
+ catch (const std::exception & e)
+ {
+ //
+ // Skip this adapter
+ //
+ std::cerr << "Skipping TAP adapter due to exception caught while iterating: "
+ << e.what() << std::endl;
+ continue;
+ }
+
+ func(devInfo, devInfoData);
+ }
+}
+
+std::set<NetworkAdapter> GetTapAdapters(const std::wstring &tapHardwareId)
+{
+ std::set<NetworkAdapter> adapters;
+ common::network::Nci nci;
+
+ ForEachDevice(tapHardwareId, [&](HDEVINFO devInfo, const SP_DEVINFO_DATA &devInfoData) {
+ try
+ {
//
// Construct NetworkAdapter
//
@@ -321,21 +367,21 @@ std::set<NetworkAdapter> GetTapAdapters(const std::wstring &tapHardwareId)
adapters.emplace(NetworkAdapter(
guid,
- GetDeviceStringProperty(devInfo, &devInfoData, &DEVPKEY_Device_DriverDesc),
+ GetDeviceStringProperty(devInfo, devInfoData, &DEVPKEY_Device_DriverDesc),
nci.getConnectionName(guidObj),
- GetDeviceInstanceId(devInfo, &devInfoData)
+ GetDeviceInstanceId(devInfo, devInfoData)
));
}
catch (const std::exception & e)
{
//
- // Log exception and skip this adapter
+ // Skip this adapter
//
std::cerr << "Skipping TAP adapter due to exception caught while iterating: "
<< e.what() << std::endl;
}
- }
+ });
return adapters;
}
@@ -459,9 +505,9 @@ std::optional<NetworkAdapter> FindMullvadAdapter(const std::set<NetworkAdapter>
auto findByAlias = [](const std::set<NetworkAdapter> &adapters, const std::wstring &alias)
{
const auto it = std::find_if(adapters.begin(), adapters.end(), [&alias](const NetworkAdapter &candidate)
- {
- return 0 == _wcsicmp(candidate.alias.c_str(), alias.c_str());
- });
+ {
+ return 0 == _wcsicmp(candidate.alias.c_str(), alias.c_str());
+ });
return it;
};
@@ -514,13 +560,26 @@ NetworkAdapter FindBrandedTap()
return *added.begin();
}
-enum class DeletionResult
+void RemoveTapDriver(const std::wstring &tapHardwareId)
{
- NO_REMAINING_TAP_ADAPTERS,
- SOME_REMAINING_TAP_ADAPTERS
-};
+ ForEachDevice(tapHardwareId, [](HDEVINFO devInfo, const SP_DEVINFO_DATA &devInfoData) {
+ try
+ {
+ DeleteDevice(devInfo, devInfoData);
+ }
+ catch (const std::exception & e)
+ {
+ //
+ // Skip this adapter
+ //
-DeletionResult DeleteVanillaMullvadAdapter()
+ std::cerr << "Skipping TAP adapter due to exception caught while iterating: "
+ << e.what() << std::endl;
+ }
+ });
+}
+
+void DeleteVanillaMullvadAdapter()
{
auto tapAdapters = GetTapAdapters(DEPRECATED_TAP_HARDWARE_ID);
std::optional<NetworkAdapter> mullvadAdapter = FindMullvadAdapter(tapAdapters);
@@ -531,98 +590,32 @@ DeletionResult DeleteVanillaMullvadAdapter()
}
const auto mullvadGuid = mullvadAdapter.value().guid;
+ bool deletedAdapter = false;
- HDEVINFO devInfo = SetupDiGetClassDevsW(
- &GUID_DEVCLASS_NET,
- nullptr,
- nullptr,
- DIGCF_PRESENT
- );
-
- if (INVALID_HANDLE_VALUE == devInfo)
- {
- THROW_WINDOWS_ERROR(GetLastError(), "SetupDiGetClassDevsW() failed");
- }
-
- common::memory::ScopeDestructor cleanupDevList;
- cleanupDevList += [&devInfo]()
- {
- SetupDiDestroyDeviceInfoList(devInfo);
- };
-
- int numRemainingAdapters = 0;
-
- for (int memberIndex = 0; ; memberIndex++)
- {
- SP_DEVINFO_DATA devInfoData = { 0 };
- devInfoData.cbSize = sizeof(devInfoData);
-
- if (FALSE == SetupDiEnumDeviceInfo(devInfo, memberIndex, &devInfoData))
- {
- const auto lastError = GetLastError();
-
- if (ERROR_NO_MORE_ITEMS == lastError)
- {
- break;
- }
-
- THROW_WINDOWS_ERROR(lastError, "Error enumerating network adapters");
- }
-
+ ForEachDevice(DEPRECATED_TAP_HARDWARE_ID, [&](HDEVINFO devInfo, const SP_DEVINFO_DATA &devInfoData) {
try
{
- const auto hardwareId = GetDeviceRegistryStringProperty(devInfo, &devInfoData, SPDRP_HARDWAREID);
-
- if (!hardwareId.has_value())
- {
- continue;
- }
- if (0 != wcscmp(DEPRECATED_TAP_HARDWARE_ID, hardwareId.value().data()))
- {
- continue;
- }
- if (0 != GetNetCfgInstanceId(devInfo, devInfoData).compare(mullvadGuid))
- {
- numRemainingAdapters++;
- continue;
- }
-
- //
- // Delete existing device
- //
-
- SP_REMOVEDEVICE_PARAMS rmdParams;
- rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
- rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
- rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
- rmdParams.HwProfile = 0;
-
- auto status = SetupDiSetClassInstallParamsW(devInfo, &devInfoData, &rmdParams.ClassInstallHeader, sizeof(rmdParams));
- if (FALSE == status)
+ if (0 == GetNetCfgInstanceId(devInfo, devInfoData).compare(mullvadGuid))
{
- THROW_WINDOWS_ERROR(GetLastError(), "SetupDiSetClassInstallParamsW");
- }
-
- status = SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData);
- if (FALSE == status)
- {
- THROW_WINDOWS_ERROR(GetLastError(), "SetupDiCallClassInstaller");
+ deletedAdapter = DeleteDevice(devInfo, devInfoData) || deletedAdapter;
}
}
catch (const std::exception & e)
{
//
- // Log exception and skip this adapter
+ // Skip this adapter
//
std::cerr << "Skipping TAP adapter due to exception caught while iterating: "
- << e.what();
+ << e.what() << std::endl;
+ return;
}
- }
+ });
- return (numRemainingAdapters > 0)
- ? DeletionResult::SOME_REMAINING_TAP_ADAPTERS
- : DeletionResult::NO_REMAINING_TAP_ADAPTERS;
+ if (!deletedAdapter)
+ {
+ THROW_ERROR("TAP adapter was not removed");
+ }
}
} // anonymous namespace
@@ -655,18 +648,18 @@ int wmain(int argc, const wchar_t * argv[], const wchar_t * [])
UpdateTapDriver(argv[2]);
}
- else if (0 == _wcsicmp(argv[1], L"remove-vanilla-tap"))
+ else if (0 == _wcsicmp(argv[1], L"remove"))
{
- switch (DeleteVanillaMullvadAdapter())
+ if (3 != argc)
{
- case DeletionResult::NO_REMAINING_TAP_ADAPTERS:
- std::wcout << L"Removed vanilla Mullvad TAP.";
- return DELETE_NO_ADAPTERS_REMAIN;
-
- case DeletionResult::SOME_REMAINING_TAP_ADAPTERS:
- std::wcout << L"Removed vanilla Mullvad TAP.";
- return DELETE_SOME_ADAPTERS_REMAIN;
+ goto INVALID_ARGUMENTS;
}
+
+ RemoveTapDriver(argv[2]);
+ }
+ else if (0 == _wcsicmp(argv[1], L"remove-vanilla-tap"))
+ {
+ DeleteVanillaMullvadAdapter();
}
else if (0 == _wcsicmp(argv[1], L"find-tap"))
{