mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-18 20:47:53 +00:00
Kill the devcon.exe dependency by dynamically loading cfgmgr32, newdev, and setupapi and using these functions directly.
This commit is contained in:
parent
7cd3c419ee
commit
8169b35482
@ -1,7 +0,0 @@
|
||||
This is the Microsoft "devcon" utility, which as far as I know is
|
||||
fair game to redistribute. It's packaged with OpenVPN and several
|
||||
other things and also distributed in source code form as an example
|
||||
program by Microsoft.
|
||||
|
||||
It's called by zerotier-one.exe to automagically install and remove
|
||||
instances of the tap device.
|
Binary file not shown.
Binary file not shown.
@ -62,8 +62,6 @@
|
||||
<ROW Component="WdfCoinstaller01011.dll" ComponentId="{2E3DD7BE-00C0-44A1-ABA9-6F0468FC9EAA}" Directory_="x64_Dir" Attributes="256" Condition="VersionNT64" KeyPath="WdfCoinstaller01011.dll"/>
|
||||
<ROW Component="WdfCoinstaller01011.dll_1" ComponentId="{137E5A80-62C3-4B30-9900-131919675AC9}" Directory_="x86_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="WdfCoinstaller01011.dll_1"/>
|
||||
<ROW Component="ZeroTierOne.exe" ComponentId="{18B51525-77BF-4FD9-9C18-A10D4CFC25BA}" Directory_="APPDIR" Attributes="0" KeyPath="ZeroTierOne.exe"/>
|
||||
<ROW Component="devcon_x64.exe" ComponentId="{0711ACF9-EEF5-48B0-95D7-8421B74AE314}" Directory_="One_Dir" Attributes="256" Condition="VersionNT64" KeyPath="devcon_x64.exe"/>
|
||||
<ROW Component="devcon_x86.exe" ComponentId="{335F6945-AC5D-40DD-B671-C9BA9C304623}" Directory_="One_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="devcon_x86.exe"/>
|
||||
<ROW Component="index.html" ComponentId="{24AB46DC-56EA-4F3C-A8B7-95957509CDD1}" Directory_="ui_Dir" Attributes="0" KeyPath="index.html" Type="0"/>
|
||||
<ROW Component="networks.d" ComponentId="{EF54D0DF-889F-41DC-AF5C-4E7F96AB1C8B}" Directory_="networks.d_Dir" Attributes="0"/>
|
||||
<ROW Component="regid.201001.com.zerotier" ComponentId="{A39C80FC-6A8F-454F-9052-10DAC3C3B139}" Directory_="regid.201001.com.zerotier_Dir" Attributes="0"/>
|
||||
@ -73,15 +71,13 @@
|
||||
<ROW Component="zttap300.cat_1" ComponentId="{9F913E48-095B-4EA3-98DA-EDAB1593F3E3}" Directory_="x86_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="zttap300.cat_3" Type="0"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||
<ROW Feature="ZeroTierOne" Title="MainFeature" Description="ZeroTier One" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="AI_CustomARPName AI_DisableModify ProductInformation WdfCoinstaller01011.dll WdfCoinstaller01011.dll_1 ZeroTierOne.exe devcon_x64.exe devcon_x86.exe index.html networks.d regid.201001.com.zerotier zerotierone_x64.exe zerotierone_x86.exe zttap300.cat zttap300.cat_1"/>
|
||||
<ROW Feature="ZeroTierOne" Title="MainFeature" Description="ZeroTier One" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="AI_CustomARPName AI_DisableModify ProductInformation WdfCoinstaller01011.dll WdfCoinstaller01011.dll_1 ZeroTierOne.exe index.html networks.d regid.201001.com.zerotier zerotierone_x64.exe zerotierone_x86.exe zttap300.cat zttap300.cat_1"/>
|
||||
<ATTRIBUTE name="CurrentFeature" value="ZeroTierOne"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
||||
<ROW File="WdfCoinstaller01011.dll" Component_="WdfCoinstaller01011.dll" FileName="WDFCOI~1.DLL|WdfCoinstaller01011.dll" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\WdfCoinstaller01011.dll" SelfReg="false" NextFile="WdfCoinstaller01011.dll_1"/>
|
||||
<ROW File="WdfCoinstaller01011.dll_1" Component_="WdfCoinstaller01011.dll_1" FileName="WDFCOI~1.DLL|WdfCoinstaller01011.dll" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\WdfCoinstaller01011.dll" SelfReg="false" NextFile="zttap300.cat_2"/>
|
||||
<ROW File="ZeroTierOne.exe" Component_="ZeroTierOne.exe" FileName="ZEROTI~1.EXE|ZeroTier One.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\bin\win-ui-wrapper\ZeroTier One.exe" SelfReg="false" NextFile="WdfCoinstaller01011.dll"/>
|
||||
<ROW File="devcon_x64.exe" Component_="devcon_x64.exe" FileName="DEVCON~1.EXE|devcon_x64.exe" Attributes="0" SourcePath="..\..\bin\devcon\devcon_x64.exe" SelfReg="false" NextFile="devcon_x86.exe"/>
|
||||
<ROW File="devcon_x86.exe" Component_="devcon_x86.exe" FileName="DEVCON~2.EXE|devcon_x86.exe" Attributes="0" SourcePath="..\..\bin\devcon\devcon_x86.exe" SelfReg="false" NextFile="zerotierone_x86.exe"/>
|
||||
<ROW File="index.html" Component_="index.html" FileName="INDEX~1.HTM|index.html" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\ui\index.html" SelfReg="false" NextFile="main.js"/>
|
||||
<ROW File="main.js" Component_="index.html" FileName="main.js" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\ui\main.js" SelfReg="false" NextFile="react.min.js"/>
|
||||
<ROW File="react.min.js" Component_="index.html" FileName="REACTM~1.JS|react.min.js" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\ui\react.min.js" SelfReg="false" NextFile="simpleajax.min.js"/>
|
||||
@ -234,10 +230,8 @@
|
||||
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder]ZeroTier\One"/>
|
||||
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]" MultiBuildTarget="DefaultBuild:[ProgramMenuFolder]"/>
|
||||
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
|
||||
<ROW Action="TapDeviceRemove32_NDIS5" Type="3154" Source="devcon_x86.exe" Target="remove zttap200"/>
|
||||
<ROW Action="TapDeviceRemove32_NDIS6" Type="3154" Source="devcon_x86.exe" Target="remove zttap300"/>
|
||||
<ROW Action="TapDeviceRemove64_NDIS5" Type="3154" Source="devcon_x64.exe" Target="remove zttap200"/>
|
||||
<ROW Action="TapDeviceRemove64_NDIS6" Type="3154" Source="devcon_x64.exe" Target="remove zttap300"/>
|
||||
<ROW Action="TapDeviceRemove32" Type="3154" Source="zerotierone_x86.exe" Target="-D"/>
|
||||
<ROW Action="TapDeviceRemove64" Type="3154" Source="zerotierone_x64.exe" Target="-D"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiEmbeddedChainerComponent">
|
||||
<ROW MsiEmbeddedChainer="msichainer.exe" Condition="VersionMsi >= "4.05"" CommandLine="[AI_CHAINER_CMD_LINE]" Source="msichainer.exe" Type="2"/>
|
||||
@ -259,10 +253,8 @@
|
||||
<ROW Action="InstallFinalize" Sequence="6596" SeqType="0" MsiKey="InstallFinalize"/>
|
||||
<ROW Action="AI_RemoveExternalUIStub" Condition="(REMOVE="ALL") AND ((VersionNT > 500) OR((VersionNT = 500) AND (ServicePackLevel >= 4)))" Sequence="1501"/>
|
||||
<ROW Action="AI_GetArpIconPath" Sequence="1401"/>
|
||||
<ROW Action="TapDeviceRemove32_NDIS6" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( NOT VersionNT64 )" Sequence="1602"/>
|
||||
<ROW Action="TapDeviceRemove64_NDIS6" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( VersionNT64 )" Sequence="1604"/>
|
||||
<ROW Action="TapDeviceRemove32_NDIS5" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( NOT VersionNT64 )" Sequence="1601"/>
|
||||
<ROW Action="TapDeviceRemove64_NDIS5" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( VersionNT64 )" Sequence="1603"/>
|
||||
<ROW Action="TapDeviceRemove32" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( NOT VersionNT64 )" Sequence="1601"/>
|
||||
<ROW Action="TapDeviceRemove64" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( VersionNT64 )" Sequence="1602"/>
|
||||
<ROW Action="AI_PrepareChainers" Condition="VersionMsi >= "4.05"" Sequence="5851"/>
|
||||
<ROW Action="AI_FwInstall" Condition="(VersionNT >= 501) AND (REMOVE <> "ALL")" Sequence="5802"/>
|
||||
<ROW Action="AI_DATA_SETTER_3" Condition="(VersionNT >= 501) AND (REMOVE <> "ALL")" Sequence="5801"/>
|
||||
@ -306,6 +298,11 @@
|
||||
<ROW Registry="VersionMajor" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="VersionMajor" Value="#0" Component_="AI_CustomARPName"/>
|
||||
<ROW Registry="VersionMinor" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="VersionMinor" Value="#7" Component_="AI_CustomARPName"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiRemoveFileComponent">
|
||||
<ROW FileKey="devcon.log" Component_="ProductInformation" FileName="devcon.log" DirProperty="One_Dir" InstallMode="3"/>
|
||||
<ROW FileKey="devcon_x64.exe" Component_="ProductInformation" FileName="devcon_x64.exe" DirProperty="One_Dir" InstallMode="3"/>
|
||||
<ROW FileKey="devcon_x86.exe" Component_="ProductInformation" FileName="devcon_x86.exe" DirProperty="One_Dir" InstallMode="3"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiServCtrlComponent">
|
||||
<ROW ServiceControl="zerotierone_x64.exe" Name="ZeroTierOneService" Event="163" Wait="1" Component_="zerotierone_x64.exe"/>
|
||||
<ROW ServiceControl="zerotierone_x86.exe" Name="ZeroTierOneService" Event="163" Wait="1" Component_="zerotierone_x86.exe"/>
|
||||
|
35
one.cpp
35
one.cpp
@ -42,6 +42,7 @@
|
||||
#include <lmcons.h>
|
||||
#include <newdev.h>
|
||||
#include <atlbase.h>
|
||||
#include "osdep/WindowsEthernetTap.hpp"
|
||||
#include "windows/ZeroTierOne/ServiceInstaller.h"
|
||||
#include "windows/ZeroTierOne/ServiceBase.h"
|
||||
#include "windows/ZeroTierOne/ZeroTierOneService.h"
|
||||
@ -914,17 +915,20 @@ static void printHelp(const char *cn,FILE *out)
|
||||
fprintf(out," -U - Run as unprivileged user (skip privilege check)"ZT_EOL_S);
|
||||
fprintf(out," -p<port> - Port for UDP and TCP/HTTP (default: 9993)"ZT_EOL_S);
|
||||
//fprintf(out," -T<path> - Override root topology, do not authenticate or update"ZT_EOL_S);
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)"ZT_EOL_S);
|
||||
#endif // __UNIX_LIKE__
|
||||
fprintf(out," -i - Generate and manage identities (zerotier-idtool)"ZT_EOL_S);
|
||||
fprintf(out," -q - Query API (zerotier-cli)"ZT_EOL_S);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
fprintf(out," -C - Run from command line instead of as service (Windows)"ZT_EOL_S);
|
||||
fprintf(out," -I - Install Windows service (Windows)"ZT_EOL_S);
|
||||
fprintf(out," -R - Uninstall Windows service (Windows)"ZT_EOL_S);
|
||||
fprintf(out," -D - Load tap driver into system driver store (Windows)"ZT_EOL_S);
|
||||
fprintf(out," -D - Remove all instances of Windows tap device (Windows)"ZT_EOL_S);
|
||||
#endif // __WINDOWS__
|
||||
|
||||
fprintf(out," -i - Generate and manage identities (zerotier-idtool)"ZT_EOL_S);
|
||||
fprintf(out," -q - Query API (zerotier-cli)"ZT_EOL_S);
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
@ -1059,26 +1063,15 @@ int main(int argc,char **argv)
|
||||
return 0;
|
||||
} break;
|
||||
|
||||
#if 0
|
||||
case 'D': { // Install Windows driver (since PNPUTIL.EXE seems to be weirdly unreliable)
|
||||
std::string pathToInf;
|
||||
#ifdef _WIN64
|
||||
pathToInf = ZT_DEFAULTS.defaultHomePath + "\\tap-windows\\x64\\zttap200.inf";
|
||||
#else
|
||||
pathToInf = ZT_DEFAULTS.defaultHomePath + "\\tap-windows\\x86\\zttap200.inf";
|
||||
#endif
|
||||
printf("Installing ZeroTier One virtual Ethernet port driver."ZT_EOL_S""ZT_EOL_S"NOTE: If you don't see a confirmation window to allow driver installation,"ZT_EOL_S"check to make sure it didn't appear under the installer."ZT_EOL_S);
|
||||
BOOL needReboot = FALSE;
|
||||
if (DiInstallDriverA(NULL,pathToInf.c_str(),DIIRFLAG_FORCE_INF,&needReboot)) {
|
||||
printf("%s: driver successfully installed from %s"ZT_EOL_S,argv[0],pathToInf.c_str());
|
||||
return 0;
|
||||
} else {
|
||||
printf("%s: failed installing %s: %d"ZT_EOL_S,argv[0],pathToInf.c_str(),(int)GetLastError());
|
||||
case 'D': {
|
||||
std::string err = WindowsEthernetTap::destroyAllPersistentTapDevices();
|
||||
if (err.length() > 0) {
|
||||
fprintf(stderr,"%s: unable to uninstall one or more persistent tap devices: %s"ZT_EOL_S,argv[0],err.c_str());
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
} break;
|
||||
#endif // __WINDOWS__
|
||||
#endif
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
@ -1134,6 +1127,10 @@ int main(int argc,char **argv)
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// Uninstall legacy tap devices. New devices will automatically be installed and configured
|
||||
// when tap instances are created.
|
||||
WindowsEthernetTap::destroyAllLegacyPersistentTapDevices();
|
||||
|
||||
if (winRunFromCommandLine) {
|
||||
// Running in "interactive" mode (mostly for debugging)
|
||||
if (IsCurrentUserLocalAdministrator() != TRUE) {
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <malloc.h>
|
||||
#include <winreg.h>
|
||||
#include <wchar.h>
|
||||
#include <ws2ipdef.h>
|
||||
@ -42,6 +43,9 @@
|
||||
#include <atlbase.h>
|
||||
#include <netlistmgr.h>
|
||||
#include <nldef.h>
|
||||
#include <SetupAPI.h>
|
||||
#include <newdev.h>
|
||||
#include <cfgmgr32.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
@ -55,15 +59,28 @@
|
||||
|
||||
#include "..\windows\TapDriver6\tap-windows.h"
|
||||
|
||||
// ff:ff:ff:ff:ff:ff with no ADI
|
||||
//static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
|
||||
// Create a fake unused default route to force detection of network type on networks without gateways
|
||||
#define ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
|
||||
|
||||
// Function signatures of dynamically loaded functions, from newdev.h, setupapi.h, and cfgmgr32.h
|
||||
typedef BOOL (WINAPI *UpdateDriverForPlugAndPlayDevicesA_t)(_In_opt_ HWND hwndParent,_In_ LPCSTR HardwareId,_In_ LPCSTR FullInfPath,_In_ DWORD InstallFlags,_Out_opt_ PBOOL bRebootRequired);
|
||||
typedef BOOL (WINAPI *SetupDiGetINFClassA_t)(_In_ PCSTR InfName,_Out_ LPGUID ClassGuid,_Out_writes_(ClassNameSize) PSTR ClassName,_In_ DWORD ClassNameSize,_Out_opt_ PDWORD RequiredSize);
|
||||
typedef HDEVINFO (WINAPI *SetupDiCreateDeviceInfoList_t)(_In_opt_ CONST GUID *ClassGuid,_In_opt_ HWND hwndParent);
|
||||
typedef BOOL (WINAPI *SetupDiCreateDeviceInfoA_t)(_In_ HDEVINFO DeviceInfoSet,_In_ PCSTR DeviceName,_In_ CONST GUID *ClassGuid,_In_opt_ PCSTR DeviceDescription,_In_opt_ HWND hwndParent,_In_ DWORD CreationFlags,_Out_opt_ PSP_DEVINFO_DATA DeviceInfoData);
|
||||
typedef BOOL (WINAPI *SetupDiSetDeviceRegistryPropertyA_t)(_In_ HDEVINFO DeviceInfoSet,_Inout_ PSP_DEVINFO_DATA DeviceInfoData,_In_ DWORD Property,_In_reads_bytes_opt_(PropertyBufferSize) CONST BYTE *PropertyBuffer,_In_ DWORD PropertyBufferSize);
|
||||
typedef BOOL (WINAPI *SetupDiCallClassInstaller_t)(_In_ DI_FUNCTION InstallFunction,_In_ HDEVINFO DeviceInfoSet,_In_opt_ PSP_DEVINFO_DATA DeviceInfoData);
|
||||
typedef BOOL (WINAPI *SetupDiDestroyDeviceInfoList_t)(_In_ HDEVINFO DeviceInfoSet);
|
||||
typedef HDEVINFO (WINAPI *SetupDiGetClassDevsExA_t)(_In_opt_ CONST GUID *ClassGuid,_In_opt_ PCSTR Enumerator,_In_opt_ HWND hwndParent,_In_ DWORD Flags,_In_opt_ HDEVINFO DeviceInfoSet,_In_opt_ PCSTR MachineName,_Reserved_ PVOID Reserved);
|
||||
typedef BOOL (WINAPI *SetupDiOpenDeviceInfoA_t)(_In_ HDEVINFO DeviceInfoSet,_In_ PCSTR DeviceInstanceId,_In_opt_ HWND hwndParent,_In_ DWORD OpenFlags,_Out_opt_ PSP_DEVINFO_DATA DeviceInfoData);
|
||||
typedef BOOL (WINAPI *SetupDiEnumDeviceInfo_t)(_In_ HDEVINFO DeviceInfoSet,_In_ DWORD MemberIndex,_Out_ PSP_DEVINFO_DATA DeviceInfoData);
|
||||
typedef BOOL (WINAPI *SetupDiSetClassInstallParamsA_t)(_In_ HDEVINFO DeviceInfoSet,_In_opt_ PSP_DEVINFO_DATA DeviceInfoData,_In_reads_bytes_opt_(ClassInstallParamsSize) PSP_CLASSINSTALL_HEADER ClassInstallParams,_In_ DWORD ClassInstallParamsSize);
|
||||
typedef CONFIGRET (WINAPI *CM_Get_Device_ID_ExA_t)(_In_ DEVINST dnDevInst,_Out_writes_(BufferLen) PSTR Buffer,_In_ ULONG BufferLen,_In_ ULONG ulFlags,_In_opt_ HMACHINE hMachine);
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace {
|
||||
|
||||
// Static/singleton class that when initialized loads a bunch of environment information and a few dynamically loaded DLLs
|
||||
class WindowsEthernetTapEnv
|
||||
{
|
||||
public:
|
||||
@ -71,29 +88,349 @@ public:
|
||||
{
|
||||
#ifdef _WIN64
|
||||
is64Bit = TRUE;
|
||||
devcon = "\\devcon_x64.exe";
|
||||
tapDriverNdis5 = "\\tap-windows\\x64\\zttap200.inf";
|
||||
tapDriverNdis6 = "\\tap-windows\\x64\\zttap300.inf";
|
||||
tapDriverPath = "\\tap-windows\\x64\\zttap300.inf";
|
||||
#else
|
||||
is64Bit = FALSE;
|
||||
IsWow64Process(GetCurrentProcess(),&is64Bit);
|
||||
devcon = ((is64Bit == TRUE) ? "\\devcon_x64.exe" : "\\devcon_x86.exe");
|
||||
tapDriverNdis5 = ((is64Bit == TRUE) ? "\\tap-windows\\x64\\zttap200.inf" : "\\tap-windows\\x86\\zttap200.inf");
|
||||
tapDriverNdis6 = ((is64Bit == TRUE) ? "\\tap-windows\\x64\\zttap300.inf" : "\\tap-windows\\x86\\zttap300.inf");
|
||||
#endif
|
||||
if (is64Bit) {
|
||||
fprintf(stderr,"FATAL: you must use the 64-bit ZeroTier One service on 64-bit Windows systems\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
BOOL is64Bit;
|
||||
const char *devcon;
|
||||
const char *tapDriverNdis5;
|
||||
const char *tapDriverNdis6;
|
||||
tapDriverPath = "\\tap-windows\\x86\\zttap300.inf";
|
||||
#endif
|
||||
tapDriverName = "zttap300";
|
||||
|
||||
setupApiMod = LoadLibraryA("setupapi.dll");
|
||||
if (!setupApiMod) {
|
||||
fprintf(stderr,"FATAL: unable to dynamically load setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiGetINFClassA = (SetupDiGetINFClassA_t)GetProcAddress(setupApiMod,"SetupDiGetINFClassA"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiGetINFClassA not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiCreateDeviceInfoList = (SetupDiCreateDeviceInfoList_t)GetProcAddress(setupApiMod,"SetupDiCreateDeviceInfoList"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiCreateDeviceInfoList not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiCreateDeviceInfoA = (SetupDiCreateDeviceInfoA_t)GetProcAddress(setupApiMod,"SetupDiCreateDeviceInfoA"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiCreateDeviceInfoA not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiSetDeviceRegistryPropertyA = (SetupDiSetDeviceRegistryPropertyA_t)GetProcAddress(setupApiMod,"SetupDiSetDeviceRegistryPropertyA"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiSetDeviceRegistryPropertyA not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiCallClassInstaller = (SetupDiCallClassInstaller_t)GetProcAddress(setupApiMod,"SetupDiCallClassInstaller"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiCallClassInstaller not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiDestroyDeviceInfoList = (SetupDiDestroyDeviceInfoList_t)GetProcAddress(setupApiMod,"SetupDiDestroyDeviceInfoList"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiDestroyDeviceInfoList not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiGetClassDevsExA = (SetupDiGetClassDevsExA_t)GetProcAddress(setupApiMod,"SetupDiGetClassDevsExA"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiGetClassDevsExA not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiOpenDeviceInfoA = (SetupDiOpenDeviceInfoA_t)GetProcAddress(setupApiMod,"SetupDiOpenDeviceInfoA"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiOpenDeviceInfoA not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiEnumDeviceInfo = (SetupDiEnumDeviceInfo_t)GetProcAddress(setupApiMod,"SetupDiEnumDeviceInfo"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiEnumDeviceInfo not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->SetupDiSetClassInstallParamsA = (SetupDiSetClassInstallParamsA_t)GetProcAddress(setupApiMod,"SetupDiSetClassInstallParamsA"))) {
|
||||
fprintf(stderr,"FATAL: SetupDiSetClassInstallParamsA not found in setupapi.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
newDevMod = LoadLibraryA("newdev.dll");
|
||||
if (!newDevMod) {
|
||||
fprintf(stderr,"FATAL: unable to dynamically load newdev.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->UpdateDriverForPlugAndPlayDevicesA = (UpdateDriverForPlugAndPlayDevicesA_t)GetProcAddress(newDevMod,"UpdateDriverForPlugAndPlayDevicesA"))) {
|
||||
fprintf(stderr,"FATAL: UpdateDriverForPlugAndPlayDevicesA not found in newdev.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
cfgMgrMod = LoadLibraryA("cfgmgr32.dll");
|
||||
if (!cfgMgrMod) {
|
||||
fprintf(stderr,"FATAL: unable to dynamically load cfgmgr32.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (!(this->CM_Get_Device_ID_ExA = (CM_Get_Device_ID_ExA_t)GetProcAddress(cfgMgrMod,"CM_Get_Device_ID_ExA"))) {
|
||||
fprintf(stderr,"FATAL: CM_Get_Device_ID_ExA not found in cfgmgr32.dll\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL is64Bit; // is the system 64-bit, regardless of whether this binary is or not
|
||||
std::string tapDriverPath;
|
||||
std::string tapDriverName;
|
||||
|
||||
UpdateDriverForPlugAndPlayDevicesA_t UpdateDriverForPlugAndPlayDevicesA;
|
||||
|
||||
SetupDiGetINFClassA_t SetupDiGetINFClassA;
|
||||
SetupDiCreateDeviceInfoList_t SetupDiCreateDeviceInfoList;
|
||||
SetupDiCreateDeviceInfoA_t SetupDiCreateDeviceInfoA;
|
||||
SetupDiSetDeviceRegistryPropertyA_t SetupDiSetDeviceRegistryPropertyA;
|
||||
SetupDiCallClassInstaller_t SetupDiCallClassInstaller;
|
||||
SetupDiDestroyDeviceInfoList_t SetupDiDestroyDeviceInfoList;
|
||||
SetupDiGetClassDevsExA_t SetupDiGetClassDevsExA;
|
||||
SetupDiOpenDeviceInfoA_t SetupDiOpenDeviceInfoA;
|
||||
SetupDiEnumDeviceInfo_t SetupDiEnumDeviceInfo;
|
||||
SetupDiSetClassInstallParamsA_t SetupDiSetClassInstallParamsA;
|
||||
|
||||
CM_Get_Device_ID_ExA_t CM_Get_Device_ID_ExA;
|
||||
|
||||
private:
|
||||
HMODULE setupApiMod;
|
||||
HMODULE newDevMod;
|
||||
HMODULE cfgMgrMod;
|
||||
};
|
||||
static const WindowsEthernetTapEnv WINENV;
|
||||
|
||||
// Only create or delete devices one at a time
|
||||
static Mutex _systemTapInitLock;
|
||||
|
||||
// Only perform installation or uninstallation options one at a time
|
||||
static Mutex _systemDeviceManagementLock;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::string WindowsEthernetTap::addNewPersistentTapDevice(const char *pathToInf)
|
||||
{
|
||||
Mutex::Lock _l(_systemDeviceManagementLock);
|
||||
|
||||
GUID classGuid;
|
||||
char className[4096];
|
||||
if (!WINENV.SetupDiGetINFClassA(pathToInf,&classGuid,className,sizeof(className),(PDWORD)0)) {
|
||||
return std::string("SetupDiGetINFClassA() failed -- unable to read zttap driver INF file");
|
||||
}
|
||||
|
||||
HDEVINFO deviceInfoSet = WINENV.SetupDiCreateDeviceInfoList(&classGuid,(HWND)0);
|
||||
if (deviceInfoSet == INVALID_HANDLE_VALUE) {
|
||||
return std::string("SetupDiCreateDeviceInfoList() failed");
|
||||
}
|
||||
|
||||
SP_DEVINFO_DATA deviceInfoData;
|
||||
memset(&deviceInfoData,0,sizeof(deviceInfoData));
|
||||
deviceInfoData.cbSize = sizeof(deviceInfoData);
|
||||
if (!WINENV.SetupDiCreateDeviceInfoA(deviceInfoSet,className,&classGuid,(PCSTR)0,(HWND)0,DICD_GENERATE_ID,&deviceInfoData)) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return std::string("SetupDiCreateDeviceInfoA() failed");
|
||||
}
|
||||
|
||||
if (!WINENV.SetupDiSetDeviceRegistryPropertyA(deviceInfoSet,&deviceInfoData,SPDRP_HARDWAREID,(const BYTE *)WINENV.tapDriverName.c_str(),(DWORD)(WINENV.tapDriverName.length() + 1))) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return std::string("SetupDiSetDeviceRegistryPropertyA() failed");
|
||||
}
|
||||
|
||||
if (!WINENV.SetupDiCallClassInstaller(DIF_REGISTERDEVICE,deviceInfoSet,&deviceInfoData)) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return std::string("SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed");
|
||||
}
|
||||
|
||||
BOOL rebootRequired = FALSE;
|
||||
if (!WINENV.UpdateDriverForPlugAndPlayDevicesA((HWND)0,WINENV.tapDriverName.c_str(),pathToInf,INSTALLFLAG_FORCE|INSTALLFLAG_NONINTERACTIVE,&rebootRequired)) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return std::string("UpdateDriverForPlugAndPlayDevices() failed -- unable to install driver on device");
|
||||
}
|
||||
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string WindowsEthernetTap::destroyAllLegacyPersistentTapDevices()
|
||||
{
|
||||
char subkeyName[4096];
|
||||
char subkeyClass[4096];
|
||||
char data[4096];
|
||||
|
||||
std::set<std::string> instanceIdPathsToRemove;
|
||||
{
|
||||
HKEY nwAdapters;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
|
||||
return std::string("Could not open registry key");
|
||||
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
DWORD type;
|
||||
DWORD dataLen;
|
||||
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||
FILETIME lastWriteTime;
|
||||
if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
|
||||
if ((!strnicmp(data,"zttap",5))&&(WINENV.tapDriverName != data)) {
|
||||
std::string instanceIdPath;
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
instanceIdPath.assign(data,dataLen);
|
||||
if (instanceIdPath.length() != 0)
|
||||
instanceIdPathsToRemove.insert(instanceIdPath);
|
||||
}
|
||||
}
|
||||
} else break; // end of list or failure
|
||||
}
|
||||
|
||||
RegCloseKey(nwAdapters);
|
||||
}
|
||||
|
||||
for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp) {
|
||||
std::string err = deletePersistentTapDevice(iidp->c_str());
|
||||
if (err.length() > 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string WindowsEthernetTap::destroyAllPersistentTapDevices()
|
||||
{
|
||||
char subkeyName[4096];
|
||||
char subkeyClass[4096];
|
||||
char data[4096];
|
||||
|
||||
std::set<std::string> instanceIdPathsToRemove;
|
||||
{
|
||||
HKEY nwAdapters;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
|
||||
return std::string("Could not open registry key");
|
||||
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
DWORD type;
|
||||
DWORD dataLen;
|
||||
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||
FILETIME lastWriteTime;
|
||||
if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
|
||||
if (!strnicmp(data,"zttap",5)) {
|
||||
std::string instanceIdPath;
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
instanceIdPath.assign(data,dataLen);
|
||||
if (instanceIdPath.length() != 0)
|
||||
instanceIdPathsToRemove.insert(instanceIdPath);
|
||||
}
|
||||
}
|
||||
} else break; // end of list or failure
|
||||
}
|
||||
|
||||
RegCloseKey(nwAdapters);
|
||||
}
|
||||
|
||||
for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp) {
|
||||
std::string err = deletePersistentTapDevice(iidp->c_str());
|
||||
if (err.length() > 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string WindowsEthernetTap::deletePersistentTapDevice(const char *instanceId)
|
||||
{
|
||||
char iid[256];
|
||||
SP_REMOVEDEVICE_PARAMS rmdParams;
|
||||
|
||||
memset(&rmdParams,0,sizeof(rmdParams));
|
||||
rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
||||
rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
|
||||
rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
|
||||
rmdParams.HwProfile = 0;
|
||||
|
||||
Mutex::Lock _l(_systemDeviceManagementLock);
|
||||
|
||||
HDEVINFO devInfo = WINENV.SetupDiGetClassDevsExA((const GUID *)0,(PCSTR)0,(HWND)0,DIGCF_ALLCLASSES,(HDEVINFO)0,(PCSTR)0,(PVOID)0);
|
||||
if (devInfo == INVALID_HANDLE_VALUE)
|
||||
return std::string("SetupDiGetClassDevsExA() failed");
|
||||
WINENV.SetupDiOpenDeviceInfoA(devInfo,instanceId,(HWND)0,0,(PSP_DEVINFO_DATA)0);
|
||||
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
memset(&devInfoData,0,sizeof(devInfoData));
|
||||
devInfoData.cbSize = sizeof(devInfoData);
|
||||
for(DWORD devIndex=0;WINENV.SetupDiEnumDeviceInfo(devInfo,devIndex,&devInfoData);devIndex++) {
|
||||
if ((WINENV.CM_Get_Device_ID_ExA(devInfoData.DevInst,iid,sizeof(iid),0,(HMACHINE)0) == CR_SUCCESS)&&(!strcmp(iid,instanceId))) {
|
||||
if (!WINENV.SetupDiSetClassInstallParamsA(devInfo,&devInfoData,&rmdParams.ClassInstallHeader,sizeof(rmdParams))) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return std::string("SetupDiSetClassInstallParams() failed");
|
||||
}
|
||||
|
||||
if (!WINENV.SetupDiCallClassInstaller(DIF_REMOVE,devInfo,&devInfoData)) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return std::string("SetupDiCallClassInstaller(DIF_REMOVE) failed");
|
||||
}
|
||||
|
||||
WINENV.SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
WINENV.SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return std::string("instance ID not found");
|
||||
}
|
||||
|
||||
bool WindowsEthernetTap::setPersistentTapDeviceState(const char *instanceId,bool enabled)
|
||||
{
|
||||
char iid[256];
|
||||
SP_PROPCHANGE_PARAMS params;
|
||||
|
||||
Mutex::Lock _l(_systemDeviceManagementLock);
|
||||
|
||||
HDEVINFO devInfo = WINENV.SetupDiGetClassDevsExA((const GUID *)0,(PCSTR)0,(HWND)0,DIGCF_ALLCLASSES,(HDEVINFO)0,(PCSTR)0,(PVOID)0);
|
||||
if (devInfo == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
WINENV.SetupDiOpenDeviceInfoA(devInfo,instanceId,(HWND)0,0,(PSP_DEVINFO_DATA)0);
|
||||
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
memset(&devInfoData,0,sizeof(devInfoData));
|
||||
devInfoData.cbSize = sizeof(devInfoData);
|
||||
for(DWORD devIndex=0;WINENV.SetupDiEnumDeviceInfo(devInfo,devIndex,&devInfoData);devIndex++) {
|
||||
if ((WINENV.CM_Get_Device_ID_ExA(devInfoData.DevInst,iid,sizeof(iid),0,(HMACHINE)0) == CR_SUCCESS)&&(!strcmp(iid,instanceId))) {
|
||||
memset(¶ms,0,sizeof(params));
|
||||
params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
||||
params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
|
||||
params.StateChange = enabled ? DICS_ENABLE : DICS_DISABLE;
|
||||
params.Scope = DICS_FLAG_GLOBAL;
|
||||
params.HwProfile = 0;
|
||||
|
||||
WINENV.SetupDiSetClassInstallParamsA(devInfo,&devInfoData,¶ms.ClassInstallHeader,sizeof(params));
|
||||
WINENV.SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,devInfo,&devInfoData);
|
||||
|
||||
memset(¶ms,0,sizeof(params));
|
||||
params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
||||
params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
|
||||
params.StateChange = enabled ? DICS_ENABLE : DICS_DISABLE;
|
||||
params.Scope = DICS_FLAG_CONFIGSPECIFIC;
|
||||
params.HwProfile = 0;
|
||||
|
||||
WINENV.SetupDiSetClassInstallParamsA(devInfo,&devInfoData,¶ms.ClassInstallHeader,sizeof(params));
|
||||
WINENV.SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,devInfo,&devInfoData);
|
||||
|
||||
WINENV.SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
WINENV.SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
WindowsEthernetTap::WindowsEthernetTap(
|
||||
const char *hp,
|
||||
const MAC &mac,
|
||||
@ -118,35 +455,21 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
char subkeyClass[4096];
|
||||
char data[4096];
|
||||
char tag[24];
|
||||
std::set<std::string> existingDeviceInstances;
|
||||
std::string mySubkeyName;
|
||||
|
||||
if (mtu > 2800)
|
||||
throw std::runtime_error("MTU too large for Windows tap");
|
||||
|
||||
Mutex::Lock _l(_systemTapInitLock);
|
||||
// We "tag" registry entries with the network ID to identify persistent devices
|
||||
Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid);
|
||||
|
||||
// Use NDIS5 if it's installed, since we don't want to switch out the driver on
|
||||
// pre-existing installs (yet). We won't ship NDIS5 anymore so new installs will
|
||||
// use NDIS6.
|
||||
std::string tapDriverPath(_pathToHelpers + WINENV.tapDriverNdis5);
|
||||
const char *tapDriverName = "zttap200";
|
||||
if (::PathFileExistsA(tapDriverPath.c_str()) == FALSE) {
|
||||
tapDriverPath = _pathToHelpers + WINENV.tapDriverNdis6;
|
||||
tapDriverName = "zttap300";
|
||||
if (::PathFileExistsA(tapDriverPath.c_str()) == FALSE) {
|
||||
throw std::runtime_error("no tap driver available: cannot find zttap300.inf (NDIS6) or zttap200.inf (NDIS5) under home path");
|
||||
}
|
||||
}
|
||||
Mutex::Lock _l(_systemTapInitLock);
|
||||
|
||||
HKEY nwAdapters;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
|
||||
throw std::runtime_error("unable to open registry key for network adapter enumeration");
|
||||
|
||||
std::set<std::string> existingDeviceInstances;
|
||||
std::string mySubkeyName;
|
||||
|
||||
// We "tag" registry entries with the network ID to identify persistent devices
|
||||
Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid);
|
||||
|
||||
// Look for the tap instance that corresponds with this network
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
DWORD type;
|
||||
@ -158,8 +481,9 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
if (!strnicmp(data,"zttap",5)) {
|
||||
data[dataLen] = (char)0;
|
||||
|
||||
if (WINENV.tapDriverName == data) {
|
||||
std::string instanceId;
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
@ -196,34 +520,9 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
// If there is no device, try to create one
|
||||
bool creatingNewDevice = (_netCfgInstanceId.length() == 0);
|
||||
if (creatingNewDevice) {
|
||||
// Log devcon output to a file
|
||||
HANDLE devconLog = CreateFileA((_pathToHelpers + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
SetFilePointer(devconLog,0,0,FILE_END);
|
||||
|
||||
// Execute devcon to create a new tap device
|
||||
STARTUPINFOA startupInfo;
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
if (devconLog != INVALID_HANDLE_VALUE) {
|
||||
SetFilePointer(devconLog,0,0,FILE_END);
|
||||
startupInfo.hStdOutput = devconLog;
|
||||
startupInfo.hStdError = devconLog;
|
||||
}
|
||||
PROCESS_INFORMATION processInfo;
|
||||
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||
if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _pathToHelpers + WINENV.devcon + "\" install \"" + tapDriverPath + "\" " + tapDriverName).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
RegCloseKey(nwAdapters);
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
throw std::runtime_error(std::string("unable to find or execute devcon at ") + WINENV.devcon);
|
||||
}
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
std::string errm = addNewPersistentTapDevice((std::string(_pathToHelpers) + WINENV.tapDriverPath).c_str());
|
||||
if (errm.length() != 0)
|
||||
throw std::runtime_error(errm);
|
||||
|
||||
// Scan for the new instance by simply looking for taps that weren't originally there...
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
@ -237,7 +536,8 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
if (!strnicmp(data,"zttap",5)) {
|
||||
|
||||
if (WINENV.tapDriverName == data) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
@ -281,6 +581,7 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"*IfType",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
|
||||
if (creatingNewDevice) {
|
||||
// Set EnableDHCP to 0 by default on new devices
|
||||
tmp = 0;
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
}
|
||||
@ -291,7 +592,7 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
}
|
||||
|
||||
{
|
||||
char nobraces[128];
|
||||
char nobraces[128]; // strip braces from GUID before converting it, because Windows
|
||||
const char *nbtmp1 = _netCfgInstanceId.c_str();
|
||||
char *nbtmp2 = nobraces;
|
||||
while (*nbtmp1) {
|
||||
@ -304,17 +605,15 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
|
||||
}
|
||||
|
||||
// Look up interface LUID... why are there (at least) four fucking ways to refer to a network device in Windows?
|
||||
// Get the LUID, which is one of like four fucking ways to refer to a network device in Windows
|
||||
if (ConvertInterfaceGuidToLuid(&_deviceGuid,&_deviceLuid) != NO_ERROR)
|
||||
throw std::runtime_error("unable to convert device interface GUID to LUID");
|
||||
|
||||
// Certain functions can now work (e.g. ips())
|
||||
_initialized = true;
|
||||
|
||||
if (friendlyName)
|
||||
setFriendlyName(friendlyName);
|
||||
|
||||
// Start background thread that actually performs I/O
|
||||
_injectSemaphore = CreateSemaphore(NULL,0,1,NULL);
|
||||
_thread = Thread::start(this);
|
||||
}
|
||||
@ -325,7 +624,7 @@ WindowsEthernetTap::~WindowsEthernetTap()
|
||||
ReleaseSemaphore(_injectSemaphore,1,NULL);
|
||||
Thread::join(_thread);
|
||||
CloseHandle(_injectSemaphore);
|
||||
_disableTapDevice();
|
||||
setPersistentTapDeviceState(_deviceInstanceId.c_str(),false);
|
||||
}
|
||||
|
||||
void WindowsEthernetTap::setEnabled(bool en)
|
||||
@ -572,14 +871,15 @@ void WindowsEthernetTap::threadMain()
|
||||
|
||||
try {
|
||||
while (_run) {
|
||||
_enableTapDevice();
|
||||
setPersistentTapDeviceState(_deviceInstanceId.c_str(),true);
|
||||
Sleep(500);
|
||||
|
||||
_tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
|
||||
if (_tap == INVALID_HANDLE_VALUE) {
|
||||
_disableTapDevice();
|
||||
_enableTapDevice();
|
||||
Sleep(1000);
|
||||
setPersistentTapDeviceState(_deviceInstanceId.c_str(),false);
|
||||
Sleep(500);
|
||||
setPersistentTapDeviceState(_deviceInstanceId.c_str(),true);
|
||||
Sleep(500);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -761,131 +1061,6 @@ void WindowsEthernetTap::threadMain()
|
||||
} catch ( ... ) {} // catch unexpected exceptions -- this should not happen but would prevent program crash or other weird issues since threads should not throw
|
||||
}
|
||||
|
||||
void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers)
|
||||
{
|
||||
char subkeyName[4096];
|
||||
char subkeyClass[4096];
|
||||
char data[4096];
|
||||
|
||||
std::set<std::string> instanceIdPathsToRemove;
|
||||
{
|
||||
HKEY nwAdapters;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
DWORD type;
|
||||
DWORD dataLen;
|
||||
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||
FILETIME lastWriteTime;
|
||||
if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
if (!strnicmp(data,"zttap",5)) {
|
||||
std::string instanceIdPath;
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
instanceIdPath.assign(data,dataLen);
|
||||
if (instanceIdPath.length() != 0)
|
||||
instanceIdPathsToRemove.insert(instanceIdPath);
|
||||
}
|
||||
}
|
||||
} else break; // end of list or failure
|
||||
}
|
||||
|
||||
RegCloseKey(nwAdapters);
|
||||
}
|
||||
|
||||
for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp)
|
||||
deletePersistentTapDevice(pathToHelpers,iidp->c_str());
|
||||
}
|
||||
|
||||
void WindowsEthernetTap::deletePersistentTapDevice(const char *pathToHelpers,const char *instanceId)
|
||||
{
|
||||
HANDLE devconLog = CreateFileA((std::string(pathToHelpers) + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
STARTUPINFOA startupInfo;
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
if (devconLog != INVALID_HANDLE_VALUE) {
|
||||
SetFilePointer(devconLog,0,0,FILE_END);
|
||||
startupInfo.hStdOutput = devconLog;
|
||||
startupInfo.hStdError = devconLog;
|
||||
}
|
||||
PROCESS_INFORMATION processInfo;
|
||||
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL,(LPSTR)(std::string("\"") + pathToHelpers + WINENV.devcon + "\" remove @" + instanceId).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
}
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
}
|
||||
|
||||
bool WindowsEthernetTap::_disableTapDevice()
|
||||
{
|
||||
HANDLE devconLog = CreateFileA((_pathToHelpers + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
SetFilePointer(devconLog,0,0,FILE_END);
|
||||
|
||||
STARTUPINFOA startupInfo;
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
if (devconLog != INVALID_HANDLE_VALUE) {
|
||||
startupInfo.hStdOutput = devconLog;
|
||||
startupInfo.hStdError = devconLog;
|
||||
}
|
||||
PROCESS_INFORMATION processInfo;
|
||||
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||
if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _pathToHelpers + WINENV.devcon + "\" disable @" + _deviceInstanceId).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
return false;
|
||||
}
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WindowsEthernetTap::_enableTapDevice()
|
||||
{
|
||||
HANDLE devconLog = CreateFileA((_pathToHelpers + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
SetFilePointer(devconLog,0,0,FILE_END);
|
||||
|
||||
STARTUPINFOA startupInfo;
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
if (devconLog != INVALID_HANDLE_VALUE) {
|
||||
startupInfo.hStdOutput = devconLog;
|
||||
startupInfo.hStdError = devconLog;
|
||||
}
|
||||
PROCESS_INFORMATION processInfo;
|
||||
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||
if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _pathToHelpers + WINENV.devcon + "\" enable @" + _deviceInstanceId).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
return false;
|
||||
}
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
|
||||
if (devconLog != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(devconLog);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NET_IFINDEX WindowsEthernetTap::_getDeviceIndex()
|
||||
{
|
||||
MIB_IF_TABLE2 *ift = (MIB_IF_TABLE2 *)0;
|
||||
|
@ -48,6 +48,45 @@ namespace ZeroTier {
|
||||
class WindowsEthernetTap
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Installs a new instance of the ZT tap driver
|
||||
*
|
||||
* @param pathToInf Path to zttap driver .inf file
|
||||
* @return Empty string on success, otherwise an error message
|
||||
*/
|
||||
static std::string addNewPersistentTapDevice(const char *pathToInf);
|
||||
|
||||
/**
|
||||
* Uninstalls all persistent tap devices that have legacy drivers
|
||||
*
|
||||
* @return Empty string on success, otherwise an error message
|
||||
*/
|
||||
static std::string destroyAllLegacyPersistentTapDevices();
|
||||
|
||||
/**
|
||||
* Uninstalls all persistent tap devices on the system
|
||||
*
|
||||
* @return Empty string on success, otherwise an error message
|
||||
*/
|
||||
static std::string destroyAllPersistentTapDevices();
|
||||
|
||||
/**
|
||||
* Uninstall a specific persistent tap device by instance ID
|
||||
*
|
||||
* @param instanceId Device instance ID
|
||||
* @return Empty string on success, otherwise an error message
|
||||
*/
|
||||
static std::string deletePersistentTapDevice(const char *instanceId);
|
||||
|
||||
/**
|
||||
* Disable a persistent tap device by instance ID
|
||||
*
|
||||
* @param instanceId Device instance ID
|
||||
* @param enabled Enable device?
|
||||
* @return True if device was found and disabled
|
||||
*/
|
||||
static bool setPersistentTapDeviceState(const char *instanceId,bool enabled);
|
||||
|
||||
WindowsEthernetTap(
|
||||
const char *hp,
|
||||
const MAC &mac,
|
||||
@ -77,9 +116,6 @@ public:
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
static void destroyAllPersistentTapDevices(const char *pathToHelpers);
|
||||
static void deletePersistentTapDevice(const char *pathToHelpers,const char *instanceId);
|
||||
|
||||
private:
|
||||
bool _disableTapDevice();
|
||||
bool _enableTapDevice();
|
||||
|
@ -982,7 +982,7 @@ public:
|
||||
_tapAssignedIps.erase(nwid);
|
||||
#ifdef __WINDOWS__
|
||||
if ((op == ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY)&&(winInstanceId.length() > 0))
|
||||
WindowsEthernetTap::deletePersistentTapDevice(_homePath.c_str(),winInstanceId.c_str());
|
||||
WindowsEthernetTap::deletePersistentTapDevice(winInstanceId.c_str());
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -217,7 +217,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -232,7 +232,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -257,7 +257,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -282,7 +282,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user