2020-07-07 15:42:39 +02:00
/* SPDX-License-Identifier: GPL-2.0
*
2021-01-30 16:45:26 +01:00
* Copyright ( C ) 2018 - 2021 WireGuard LLC . All Rights Reserved .
2020-07-07 15:42:39 +02:00
*/
2020-10-31 11:55:26 +01:00
# include "adapter.h"
# include "elevate.h"
# include "entry.h"
# include "logger.h"
# include "namespace.h"
# include "nci.h"
2020-11-03 15:28:17 +01:00
# include "ntdll.h"
2020-10-31 11:55:26 +01:00
# include "registry.h"
# include "resource.h"
2020-11-03 17:06:20 +01:00
# include "wintun-inf.h"
2020-10-31 11:55:26 +01:00
# include <Windows.h>
# include <winternl.h>
2020-10-31 18:13:36 +01:00
# define _NTDEF_ /* TODO: figure out how to include ntsecapi and winternal together without requiring this */
2020-10-31 11:55:26 +01:00
# include <cfgmgr32.h>
# include <devguid.h>
# include <iphlpapi.h>
# include <ndisguid.h>
# include <NTSecAPI.h>
# include <SetupAPI.h>
# include <Shlwapi.h>
# include <wchar.h>
2020-11-02 13:52:47 +01:00
# include <initguid.h> /* Keep these two at bottom in this order, so that we only generate extra GUIDs for devpkey. The other keys we'll get from uuid.lib like usual. */
# include <devpkey.h>
2020-07-07 15:42:39 +02:00
2020-10-15 15:54:37 +02:00
# pragma warning(disable : 4221) /* nonstandard: address of automatic in initializer */
2020-10-31 08:53:32 +01:00
# define WAIT_FOR_REGISTRY_TIMEOUT 10000 /* ms */
# define MAX_POOL_DEVICE_TYPE (WINTUN_MAX_POOL + 8) /* Should accommodate a pool name with " Tunnel" appended */
2020-10-16 13:30:51 +02:00
# if defined(_M_IX86)
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_I386
# elif defined(_M_AMD64)
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_AMD64
# elif defined(_M_ARM)
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARMNT
# elif defined(_M_ARM64)
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARM64
# else
# error Unsupported architecture
# endif
2020-07-07 15:42:39 +02:00
2021-01-30 16:39:33 +01:00
static const DEVPROPKEY DEVPKEY_Wintun_Pool = {
{ 0xaba51201 , 0xdf7a , 0x3a38 , { 0x0a , 0xd9 , 0x90 , 0x64 , 0x42 , 0xd2 , 0x71 , 0xae } } ,
DEVPROPID_FIRST_USABLE + 0
} ;
2020-11-02 16:28:51 +01:00
typedef struct _SP_DEVINFO_DATA_LIST
{
SP_DEVINFO_DATA Data ;
struct _SP_DEVINFO_DATA_LIST * Next ;
} SP_DEVINFO_DATA_LIST ;
2020-10-16 13:30:51 +02:00
static USHORT NativeMachine = IMAGE_FILE_PROCESS ;
2020-07-28 12:30:12 +02:00
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL ) SP_DRVINFO_DETAIL_DATA_W * GetAdapterDrvInfoDetail (
2020-10-15 11:32:06 +02:00
_In_ HDEVINFO DevInfo ,
_In_opt_ SP_DEVINFO_DATA * DevInfoData ,
2020-11-03 12:29:34 +01:00
_In_ SP_DRVINFO_DATA_W * DrvInfoData )
2020-10-15 11:32:06 +02:00
{
DWORD Size = sizeof ( SP_DRVINFO_DETAIL_DATA_W ) + 0x100 ;
for ( ; ; )
{
2020-11-04 12:55:25 +01:00
SP_DRVINFO_DETAIL_DATA_W * DrvInfoDetailData = Alloc ( Size ) ;
2020-11-03 12:29:34 +01:00
if ( ! DrvInfoDetailData )
return NULL ;
DrvInfoDetailData - > cbSize = sizeof ( SP_DRVINFO_DETAIL_DATA_W ) ;
if ( SetupDiGetDriverInfoDetailW ( DevInfo , DevInfoData , DrvInfoData , DrvInfoDetailData , Size , & Size ) )
return DrvInfoDetailData ;
DWORD LastError = GetLastError ( ) ;
2020-11-04 12:55:25 +01:00
Free ( DrvInfoDetailData ) ;
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_INSUFFICIENT_BUFFER )
{
2021-02-02 13:12:45 +01:00
if ( DevInfoData )
LOG_ERROR ( LastError , L " Failed for adapter %u " , DevInfoData - > DevInst ) ;
else
LOG_ERROR ( LastError , L " Failed " ) ;
SetLastError ( LastError ) ;
2020-11-03 12:29:34 +01:00
return NULL ;
2020-10-30 13:08:57 +01:00
}
2020-10-15 11:32:06 +02:00
}
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL ) void * GetDeviceRegistryProperty (
2020-07-07 15:42:39 +02:00
_In_ HDEVINFO DevInfo ,
_In_ SP_DEVINFO_DATA * DevInfoData ,
_In_ DWORD Property ,
2020-07-24 08:29:33 +02:00
_Out_opt_ DWORD * ValueType ,
_Inout_ DWORD * BufLen )
2020-07-07 15:42:39 +02:00
{
for ( ; ; )
{
2020-11-04 12:55:25 +01:00
BYTE * Data = Alloc ( * BufLen ) ;
2020-11-03 12:29:34 +01:00
if ( ! Data )
return NULL ;
if ( SetupDiGetDeviceRegistryPropertyW ( DevInfo , DevInfoData , Property , ValueType , Data , * BufLen , BufLen ) )
return Data ;
DWORD LastError = GetLastError ( ) ;
2020-11-04 12:55:25 +01:00
Free ( Data ) ;
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_INSUFFICIENT_BUFFER )
2020-10-30 13:08:57 +01:00
{
2021-02-02 13:12:45 +01:00
SetLastError (
LOG_ERROR ( LastError , L " Querying adapter %u property 0x%x failed " , DevInfoData - > DevInst , Property ) ) ;
2020-11-03 12:29:34 +01:00
return NULL ;
2020-10-30 13:08:57 +01:00
}
2020-07-07 15:42:39 +02:00
}
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL )
WCHAR * GetDeviceRegistryString ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData , _In_ DWORD Property )
2020-07-07 15:42:39 +02:00
{
2020-11-03 12:29:34 +01:00
DWORD LastError , ValueType , Size = 256 * sizeof ( WCHAR ) ;
WCHAR * Buf = GetDeviceRegistryProperty ( DevInfo , DevInfoData , Property , & ValueType , & Size ) ;
if ( ! Buf )
return NULL ;
2020-07-07 15:42:39 +02:00
switch ( ValueType )
{
case REG_SZ :
case REG_EXPAND_SZ :
2020-07-21 16:38:00 +02:00
case REG_MULTI_SZ :
2020-11-03 12:29:34 +01:00
if ( RegistryGetString ( & Buf , Size / sizeof ( WCHAR ) , ValueType ) )
return Buf ;
LastError = GetLastError ( ) ;
break ;
2020-07-07 15:42:39 +02:00
default :
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR ,
L " Adapter %u property 0x%x is not a string (type: %u) " ,
DevInfoData - > DevInst ,
Property ,
ValueType ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_DATATYPE ;
2020-07-07 15:42:39 +02:00
}
2020-11-04 12:55:25 +01:00
Free ( Buf ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( LastError ) ;
return NULL ;
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL )
WCHAR * GetDeviceRegistryMultiString ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData , _In_ DWORD Property )
2020-07-07 15:42:39 +02:00
{
2020-11-03 12:29:34 +01:00
DWORD LastError , ValueType , Size = 256 * sizeof ( WCHAR ) ;
WCHAR * Buf = GetDeviceRegistryProperty ( DevInfo , DevInfoData , Property , & ValueType , & Size ) ;
if ( ! Buf )
return NULL ;
2020-07-07 15:42:39 +02:00
switch ( ValueType )
{
case REG_SZ :
case REG_EXPAND_SZ :
case REG_MULTI_SZ :
2020-11-03 12:29:34 +01:00
if ( RegistryGetMultiString ( & Buf , Size / sizeof ( WCHAR ) , ValueType ) )
return Buf ;
LastError = GetLastError ( ) ;
break ;
2020-07-07 15:42:39 +02:00
default :
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR ,
L " Adapter %u property 0x%x is not a string (type: %u) " ,
DevInfoData - > DevInst ,
Property ,
ValueType ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_DATATYPE ;
2020-07-07 15:42:39 +02:00
}
2020-11-04 12:55:25 +01:00
Free ( Buf ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( LastError ) ;
return NULL ;
2020-07-07 15:42:39 +02:00
}
2020-10-30 09:53:09 +01:00
static BOOL
IsOurHardwareID ( _In_z_ const WCHAR * Hwids )
{
for ( ; Hwids [ 0 ] ; Hwids + = wcslen ( Hwids ) + 1 )
if ( ! _wcsicmp ( Hwids , WINTUN_HWID ) )
return TRUE ;
return FALSE ;
}
2020-11-03 12:29:34 +01:00
static BOOL
IsOurAdapter ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
2020-07-21 18:19:15 +02:00
{
2020-11-03 12:29:34 +01:00
WCHAR * Hwids = GetDeviceRegistryMultiString ( DevInfo , DevInfoData , SPDRP_HARDWAREID ) ;
if ( ! Hwids )
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to get adapter %u hardware ID " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
BOOL IsOurs = IsOurHardwareID ( Hwids ) ;
2020-11-04 12:55:25 +01:00
Free ( Hwids ) ;
2020-11-03 12:29:34 +01:00
return IsOurs ;
2020-10-15 11:32:06 +02:00
}
2021-02-02 12:53:40 +01:00
static _Return_type_success_ ( return ! = NULL ) WCHAR * GetDeviceObjectFileName ( _In_z_ const WCHAR * InstanceId )
2020-10-15 11:32:06 +02:00
{
ULONG InterfacesLen ;
2020-11-03 12:29:34 +01:00
DWORD LastError = CM_MapCrToWin32Err (
2020-11-02 16:28:51 +01:00
CM_Get_Device_Interface_List_SizeW (
& InterfacesLen ,
( GUID * ) & GUID_DEVINTERFACE_NET ,
( DEVINSTID_W ) InstanceId ,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) ,
ERROR_GEN_FAILURE ) ;
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_SUCCESS )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Failed to query adapter %s associated instances size " , InstanceId ) ) ;
2021-02-03 22:32:58 +01:00
return NULL ;
2020-11-03 12:29:34 +01:00
}
2020-11-04 12:55:25 +01:00
WCHAR * Interfaces = Alloc ( InterfacesLen * sizeof ( WCHAR ) ) ;
2020-10-15 11:32:06 +02:00
if ( ! Interfaces )
2021-02-03 22:32:58 +01:00
return NULL ;
2020-11-03 12:29:34 +01:00
LastError = CM_MapCrToWin32Err (
2020-11-02 16:28:51 +01:00
CM_Get_Device_Interface_ListW (
( GUID * ) & GUID_DEVINTERFACE_NET ,
( DEVINSTID_W ) InstanceId ,
Interfaces ,
InterfacesLen ,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) ,
ERROR_GEN_FAILURE ) ;
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_SUCCESS )
2020-10-15 11:32:06 +02:00
{
2021-02-02 13:12:45 +01:00
LOG_ERROR ( LastError , L " Failed to get adapter %s associated instances " , InstanceId ) ;
2021-02-03 22:32:58 +01:00
Free ( Interfaces ) ;
SetLastError ( LastError ) ;
return NULL ;
2020-10-15 11:32:06 +02:00
}
2021-02-03 22:32:58 +01:00
return Interfaces ;
}
2021-02-02 12:53:40 +01:00
static _Return_type_success_ ( return ! = INVALID_HANDLE_VALUE ) HANDLE OpenDeviceObject ( _In_z_ const WCHAR * InstanceId )
2021-02-03 22:32:58 +01:00
{
WCHAR * Filename = GetDeviceObjectFileName ( InstanceId ) ;
if ( ! Filename )
return INVALID_HANDLE_VALUE ;
HANDLE Handle = CreateFileW (
Filename ,
2020-10-15 11:32:06 +02:00
GENERIC_READ | GENERIC_WRITE ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
NULL ,
OPEN_EXISTING ,
0 ,
NULL ) ;
2021-02-03 22:32:58 +01:00
if ( Handle = = INVALID_HANDLE_VALUE )
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to connect to adapter %s associated instance %s " , InstanceId , Filename ) ;
Free ( Filename ) ;
2020-11-03 12:29:34 +01:00
return Handle ;
2020-10-15 11:32:06 +02:00
}
2021-02-03 22:32:58 +01:00
static BOOL
2021-02-02 12:53:40 +01:00
EnsureDeviceObject ( _In_z_ const WCHAR * InstanceId )
2021-02-03 22:32:58 +01:00
{
WCHAR * Filename = GetDeviceObjectFileName ( InstanceId ) ;
if ( ! Filename )
return FALSE ;
BOOL Exists = TRUE ;
const int Attempts = 100 ;
for ( int i = 0 ; i < Attempts ; + + i )
{
HANDLE Handle = CreateFileW ( Filename , 0 , 0 , NULL , OPEN_EXISTING , 0 , NULL ) ;
if ( Handle ! = INVALID_HANDLE_VALUE )
{
CloseHandle ( Handle ) ;
goto out ;
}
if ( i ! = Attempts - 1 )
Sleep ( 50 ) ;
}
Exists = FALSE ;
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to connect to adapter %s associated instance %s " , InstanceId , Filename ) ;
2021-02-03 22:32:58 +01:00
out :
Free ( Filename ) ;
return Exists ;
}
2020-10-15 11:32:06 +02:00
# define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
ForceCloseWintunAdapterHandle ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
2020-10-15 11:32:06 +02:00
{
2020-11-03 12:29:34 +01:00
DWORD LastError = ERROR_SUCCESS ;
2020-10-15 11:32:06 +02:00
DWORD RequiredBytes ;
if ( SetupDiGetDeviceInstanceIdW ( DevInfo , DevInfoData , NULL , 0 , & RequiredBytes ) | |
2020-11-03 12:29:34 +01:00
( LastError = GetLastError ( ) ) ! = ERROR_INSUFFICIENT_BUFFER )
{
2021-02-02 13:12:45 +01:00
LOG_ERROR ( LastError , L " Failed to query adapter %u instance ID size " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
2020-11-04 12:55:25 +01:00
WCHAR * InstanceId = Zalloc ( sizeof ( * InstanceId ) * RequiredBytes ) ;
2020-10-15 11:32:06 +02:00
if ( ! InstanceId )
2020-11-03 12:29:34 +01:00
return FALSE ;
2020-10-15 11:32:06 +02:00
if ( ! SetupDiGetDeviceInstanceIdW ( DevInfo , DevInfoData , InstanceId , RequiredBytes , & RequiredBytes ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get adapter %u instance ID " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
goto cleanupInstanceId ;
2020-10-15 11:32:06 +02:00
}
2020-11-03 12:29:34 +01:00
HANDLE NdisHandle = OpenDeviceObject ( InstanceId ) ;
if ( NdisHandle = = INVALID_HANDLE_VALUE )
2020-10-15 11:32:06 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get adapter %u object " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
goto cleanupInstanceId ;
2020-10-15 11:32:06 +02:00
}
2020-10-30 14:21:13 +01:00
if ( DeviceIoControl ( NdisHandle , TUN_IOCTL_FORCE_CLOSE_HANDLES , NULL , 0 , NULL , 0 , & RequiredBytes , NULL ) )
{
2020-11-03 12:29:34 +01:00
LastError = ERROR_SUCCESS ;
2020-10-30 14:21:13 +01:00
Sleep ( 200 ) ;
}
else if ( GetLastError ( ) = = ERROR_NOTHING_TO_TERMINATE )
2020-11-03 12:29:34 +01:00
LastError = ERROR_SUCCESS ;
2020-10-30 14:21:13 +01:00
else
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to perform ioctl on adapter %u " , DevInfoData - > DevInst ) ;
2020-10-15 11:32:06 +02:00
CloseHandle ( NdisHandle ) ;
2020-11-03 12:29:34 +01:00
cleanupInstanceId :
2020-11-04 12:55:25 +01:00
Free ( InstanceId ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-10-15 11:32:06 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
DisableAllOurAdapters ( _In_ HDEVINFO DevInfo , _Inout_ SP_DEVINFO_DATA_LIST * * DisabledAdapters )
2020-10-15 11:32:06 +02:00
{
SP_PROPCHANGE_PARAMS Params = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_PROPERTYCHANGE } ,
. StateChange = DICS_DISABLE ,
. Scope = DICS_FLAG_GLOBAL } ;
2020-11-03 12:29:34 +01:00
DWORD LastError = ERROR_SUCCESS ;
2020-10-15 11:32:06 +02:00
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
{
2020-11-04 12:55:25 +01:00
SP_DEVINFO_DATA_LIST * DeviceNode = Alloc ( sizeof ( SP_DEVINFO_DATA_LIST ) ) ;
2020-10-15 11:32:06 +02:00
if ( ! DeviceNode )
2020-11-03 12:29:34 +01:00
return FALSE ;
2020-10-15 11:32:06 +02:00
DeviceNode - > Data . cbSize = sizeof ( SP_DEVINFO_DATA ) ;
if ( ! SetupDiEnumDeviceInfo ( DevInfo , EnumIndex , & DeviceNode - > Data ) )
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
{
2020-11-04 12:55:25 +01:00
Free ( DeviceNode ) ;
2020-10-15 11:32:06 +02:00
break ;
}
2020-11-02 23:21:16 +01:00
goto cleanupDeviceNode ;
2020-10-15 11:32:06 +02:00
}
2020-11-03 12:29:34 +01:00
if ( ! IsOurAdapter ( DevInfo , & DeviceNode - > Data ) )
2020-11-02 23:21:16 +01:00
goto cleanupDeviceNode ;
2020-10-15 11:32:06 +02:00
ULONG Status , ProblemCode ;
if ( CM_Get_DevNode_Status ( & Status , & ProblemCode , DeviceNode - > Data . DevInst , 0 ) ! = CR_SUCCESS | |
( ( Status & DN_HAS_PROBLEM ) & & ProblemCode = = CM_PROB_DISABLED ) )
2020-11-02 23:21:16 +01:00
goto cleanupDeviceNode ;
2020-10-15 11:32:06 +02:00
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO , L " Force closing all adapter %u open handles " , DeviceNode - > Data . DevInst ) ;
2020-11-03 12:29:34 +01:00
if ( ! ForceCloseWintunAdapterHandle ( DevInfo , & DeviceNode - > Data ) )
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to force close adapter %u handles " , DeviceNode - > Data . DevInst ) ;
2020-10-15 11:32:06 +02:00
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO , L " Disabling adapter %u " , DeviceNode - > Data . DevInst ) ;
2020-10-15 11:32:06 +02:00
if ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DeviceNode - > Data , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_PROPERTYCHANGE , DevInfo , & DeviceNode - > Data ) )
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to disable adapter %u " , DeviceNode - > Data . DevInst ) ;
2020-11-03 12:29:34 +01:00
LastError = LastError ! = ERROR_SUCCESS ? LastError : GetLastError ( ) ;
2020-11-02 23:21:16 +01:00
goto cleanupDeviceNode ;
2020-10-15 11:32:06 +02:00
}
DeviceNode - > Next = * DisabledAdapters ;
* DisabledAdapters = DeviceNode ;
continue ;
2020-11-02 23:21:16 +01:00
cleanupDeviceNode :
2020-11-04 12:55:25 +01:00
Free ( DeviceNode ) ;
2020-10-15 11:32:06 +02:00
}
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-10-15 11:32:06 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
EnableAllOurAdapters ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA_LIST * AdaptersToEnable )
2020-10-15 11:32:06 +02:00
{
SP_PROPCHANGE_PARAMS Params = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_PROPERTYCHANGE } ,
. StateChange = DICS_ENABLE ,
. Scope = DICS_FLAG_GLOBAL } ;
2020-11-03 12:29:34 +01:00
DWORD LastError = ERROR_SUCCESS ;
2020-10-15 11:32:06 +02:00
for ( SP_DEVINFO_DATA_LIST * DeviceNode = AdaptersToEnable ; DeviceNode ; DeviceNode = DeviceNode - > Next )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO , L " Enabling adapter %u " , DeviceNode - > Data . DevInst ) ;
2020-10-15 11:32:06 +02:00
if ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DeviceNode - > Data , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_PROPERTYCHANGE , DevInfo , & DeviceNode - > Data ) )
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to enable adapter %u " , DeviceNode - > Data . DevInst ) ;
2020-11-03 12:29:34 +01:00
LastError = LastError ! = ERROR_SUCCESS ? LastError : GetLastError ( ) ;
2020-10-15 11:32:06 +02:00
}
}
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-10-15 11:32:06 +02:00
}
void
2020-10-30 06:03:21 +01:00
AdapterInit ( void )
2020-10-15 11:32:06 +02:00
{
2020-11-03 02:09:00 +01:00
if ( ! MAYBE_WOW64 )
return ;
2020-10-16 13:30:51 +02:00
typedef BOOL ( WINAPI * IsWow64Process2_t ) (
_In_ HANDLE hProcess , _Out_ USHORT * pProcessMachine , _Out_opt_ USHORT * pNativeMachine ) ;
HANDLE Kernel32 ;
IsWow64Process2_t IsWow64Process2 ;
USHORT ProcessMachine ;
if ( ( Kernel32 = GetModuleHandleW ( L " kernel32.dll " ) ) = = NULL | |
( IsWow64Process2 = ( IsWow64Process2_t ) GetProcAddress ( Kernel32 , " IsWow64Process2 " ) ) = = NULL | |
! IsWow64Process2 ( GetCurrentProcess ( ) , & ProcessMachine , & NativeMachine ) )
{
BOOL IsWoW64 ;
NativeMachine =
IsWow64Process ( GetCurrentProcess ( ) , & IsWoW64 ) & & IsWoW64 ? IMAGE_FILE_MACHINE_AMD64 : IMAGE_FILE_PROCESS ;
}
2020-10-15 11:32:06 +02:00
}
2020-07-21 18:19:15 +02:00
static BOOL
CheckReboot ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
{
SP_DEVINSTALL_PARAMS_W DevInstallParams = { . cbSize = sizeof ( SP_DEVINSTALL_PARAMS_W ) } ;
if ( ! SetupDiGetDeviceInstallParamsW ( DevInfo , DevInfoData , & DevInstallParams ) )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Retrieving adapter %u device installation parameters failed " , DevInfoData - > DevInst ) ;
2020-07-21 18:19:15 +02:00
return FALSE ;
2020-10-13 19:40:52 +02:00
}
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_SUCCESS ) ;
2020-07-21 18:19:15 +02:00
return ( DevInstallParams . Flags & ( DI_NEEDREBOOT | DI_NEEDRESTART ) ) ! = 0 ;
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
SetQuietInstall ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
2020-07-21 18:19:15 +02:00
{
SP_DEVINSTALL_PARAMS_W DevInstallParams = { . cbSize = sizeof ( SP_DEVINSTALL_PARAMS_W ) } ;
if ( ! SetupDiGetDeviceInstallParamsW ( DevInfo , DevInfoData , & DevInstallParams ) )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Retrieving adapter %u device installation parameters failed " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
2020-07-21 18:19:15 +02:00
DevInstallParams . Flags | = DI_QUIETINSTALL ;
if ( ! SetupDiSetDeviceInstallParamsW ( DevInfo , DevInfoData , & DevInstallParams ) )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Setting adapter %u device installation parameters failed " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
return TRUE ;
2020-07-21 18:19:15 +02:00
}
2021-02-02 12:53:40 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL GetNetCfgInstanceIdFromHKEY ( _In_ HKEY Key , _Out_ GUID * CfgInstanceID )
2020-07-21 16:38:00 +02:00
{
2020-11-03 12:29:34 +01:00
WCHAR * ValueStr = RegistryQueryString ( Key , L " NetCfgInstanceId " , TRUE ) ;
if ( ! ValueStr )
2021-02-02 13:12:45 +01:00
{
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( Key , RegPath ) ;
return RET_ERROR ( TRUE , LOG ( WINTUN_LOG_ERR , L " Failed to get %.*s \\ NetCfgInstanceId " , MAX_REG_PATH , RegPath ) ) ;
}
2021-02-01 10:41:36 +01:00
DWORD LastError = ERROR_SUCCESS ;
2020-10-13 19:40:52 +02:00
if ( FAILED ( CLSIDFromString ( ValueStr , CfgInstanceID ) ) )
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( Key , RegPath ) ;
LOG ( WINTUN_LOG_ERR , L " %.*s \\ NetCfgInstanceId is not a GUID: %s " , MAX_REG_PATH , RegPath , ValueStr ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_DATA ;
2020-10-13 19:40:52 +02:00
}
2020-11-04 12:55:25 +01:00
Free ( ValueStr ) ;
2021-02-01 10:41:36 +01:00
return RET_ERROR ( TRUE , LastError ) ;
}
static _Return_type_success_ ( return ! = FALSE ) BOOL
GetNetCfgInstanceIdFromDevInfo ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData , _Out_ GUID * CfgInstanceID )
{
HKEY Key = SetupDiOpenDevRegKey ( DevInfo , DevInfoData , DICS_FLAG_GLOBAL , 0 , DIREG_DRV , KEY_QUERY_VALUE ) ;
if ( Key = = INVALID_HANDLE_VALUE )
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Opening adapter %u device registry key failed " , DevInfoData - > DevInst ) ;
2021-02-01 10:41:36 +01:00
return FALSE ;
}
DWORD LastError = ERROR_SUCCESS ;
if ( ! GetNetCfgInstanceIdFromHKEY ( Key , CfgInstanceID ) )
LastError = GetLastError ( ) ;
2020-07-21 16:38:00 +02:00
RegCloseKey ( Key ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
GetDevInfoData ( _In_ const GUID * CfgInstanceID , _Out_ HDEVINFO * DevInfo , _Out_ SP_DEVINFO_DATA * DevInfoData )
2020-07-21 18:19:15 +02:00
{
2020-10-13 19:40:52 +02:00
* DevInfo = SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
2020-07-21 18:19:15 +02:00
if ( ! * DevInfo )
2020-11-03 12:29:34 +01:00
{
LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
return FALSE ;
}
2020-10-13 19:40:52 +02:00
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
2020-07-21 18:19:15 +02:00
{
DevInfoData - > cbSize = sizeof ( SP_DEVINFO_DATA ) ;
2020-10-13 19:40:52 +02:00
if ( ! SetupDiEnumDeviceInfo ( * DevInfo , EnumIndex , DevInfoData ) )
2020-07-21 18:19:15 +02:00
{
2020-07-24 08:29:33 +02:00
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
2020-07-21 18:19:15 +02:00
break ;
continue ;
}
GUID CfgInstanceID2 ;
2021-02-01 10:41:36 +01:00
if ( GetNetCfgInstanceIdFromDevInfo ( * DevInfo , DevInfoData , & CfgInstanceID2 ) & &
2020-07-24 08:29:33 +02:00
! memcmp ( CfgInstanceID , & CfgInstanceID2 , sizeof ( GUID ) ) )
2020-11-03 12:29:34 +01:00
return TRUE ;
2020-07-21 18:19:15 +02:00
}
SetupDiDestroyDeviceInfoList ( * DevInfo ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_FILE_NOT_FOUND ) ;
return FALSE ;
2020-07-21 18:19:15 +02:00
}
static void
2020-10-30 06:12:42 +01:00
RemoveNumberedSuffix ( _Inout_z_ WCHAR * Name )
2020-07-21 18:19:15 +02:00
{
2020-10-30 06:12:42 +01:00
for ( size_t i = wcslen ( Name ) ; i - - ; )
2020-07-21 18:19:15 +02:00
{
2020-10-30 06:12:42 +01:00
if ( ( Name [ i ] < L ' 0 ' | | Name [ i ] > L ' 9 ' ) & & ! iswspace ( Name [ i ] ) )
2020-07-21 18:19:15 +02:00
return ;
2020-10-30 06:12:42 +01:00
Name [ i ] = 0 ;
2020-07-21 18:19:15 +02:00
}
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
GetPoolDeviceTypeName ( _In_z_ const WCHAR * Pool , _Out_cap_c_ ( MAX_POOL_DEVICE_TYPE ) WCHAR * Name )
2020-07-21 18:19:15 +02:00
{
2020-10-31 18:13:36 +01:00
if ( _snwprintf_s ( Name , MAX_POOL_DEVICE_TYPE , _TRUNCATE , L " %s Tunnel " , Pool ) = = - 1 )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Pool name too long: %s " , Pool ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
}
return TRUE ;
2020-07-21 18:19:15 +02:00
}
2020-11-03 12:29:34 +01:00
static BOOL
IsPoolMember ( _In_z_ const WCHAR * Pool , _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
2020-07-21 18:19:15 +02:00
{
2021-01-30 16:39:33 +01:00
WCHAR PoolProp [ MAX_POOL_DEVICE_TYPE ] ;
DEVPROPTYPE PropType ;
if ( SetupDiGetDevicePropertyW (
DevInfo , DevInfoData , & DEVPKEY_Wintun_Pool , & PropType , ( PBYTE ) PoolProp , sizeof ( PoolProp ) , NULL , 0 ) & &
PropType = = DEVPROP_TYPE_STRING )
return ! _wcsicmp ( PoolProp , Pool ) ;
LOG_LAST_ERROR ( L " Reading pool devpkey failed, falling back " ) ;
2020-11-03 12:29:34 +01:00
DWORD LastError = ERROR_SUCCESS ;
BOOL Ret = FALSE ;
2021-01-30 16:39:33 +01:00
WCHAR * DeviceDesc = GetDeviceRegistryString ( DevInfo , DevInfoData , SPDRP_DEVICEDESC ) ;
WCHAR * FriendlyName = GetDeviceRegistryString ( DevInfo , DevInfoData , SPDRP_FRIENDLYNAME ) ;
2020-07-21 18:19:15 +02:00
WCHAR PoolDeviceTypeName [ MAX_POOL_DEVICE_TYPE ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetPoolDeviceTypeName ( Pool , PoolDeviceTypeName ) )
{
LastError = GetLastError ( ) ;
2020-11-09 15:30:34 +01:00
goto cleanupNames ;
2020-07-21 18:19:15 +02:00
}
2020-11-09 15:30:34 +01:00
Ret = ( FriendlyName & & ! _wcsicmp ( FriendlyName , PoolDeviceTypeName ) ) | |
( DeviceDesc & & ! _wcsicmp ( DeviceDesc , PoolDeviceTypeName ) ) ;
if ( Ret )
goto cleanupNames ;
if ( FriendlyName )
RemoveNumberedSuffix ( FriendlyName ) ;
if ( DeviceDesc )
RemoveNumberedSuffix ( DeviceDesc ) ;
Ret = ( FriendlyName & & ! _wcsicmp ( FriendlyName , PoolDeviceTypeName ) ) | |
( DeviceDesc & & ! _wcsicmp ( DeviceDesc , PoolDeviceTypeName ) ) ;
cleanupNames :
2020-11-04 12:55:25 +01:00
Free ( FriendlyName ) ;
Free ( DeviceDesc ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( LastError ) ;
return Ret ;
2020-07-21 18:19:15 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL ) WINTUN_ADAPTER
* CreateAdapterData ( _In_z_ const WCHAR * Pool , _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
2020-07-07 15:42:39 +02:00
{
/* Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<class>\<id> registry key. */
HKEY Key = SetupDiOpenDevRegKey ( DevInfo , DevInfoData , DICS_FLAG_GLOBAL , 0 , DIREG_DRV , KEY_QUERY_VALUE ) ;
if ( Key = = INVALID_HANDLE_VALUE )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Opening adapter %u device registry key failed " , DevInfoData - > DevInst ) ;
2020-11-03 12:29:34 +01:00
return NULL ;
}
2020-07-07 15:42:39 +02:00
2020-11-03 12:29:34 +01:00
DWORD LastError ;
2020-11-04 12:55:25 +01:00
WINTUN_ADAPTER * Adapter = Alloc ( sizeof ( WINTUN_ADAPTER ) ) ;
2020-11-03 12:29:34 +01:00
if ( ! Adapter )
2020-07-21 16:38:00 +02:00
{
2020-11-04 12:55:25 +01:00
LastError = GetLastError ( ) ;
2020-07-21 16:38:00 +02:00
goto cleanupKey ;
}
2021-02-01 10:41:36 +01:00
if ( ! GetNetCfgInstanceIdFromHKEY ( Key , & Adapter - > CfgInstanceID ) )
2020-07-07 15:42:39 +02:00
{
2021-02-01 10:41:36 +01:00
LastError = GetLastError ( ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
if ( ! RegistryQueryDWORD ( Key , L " NetLuidIndex " , & Adapter - > LuidIndex , TRUE ) )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( Key , RegPath ) ;
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %.*s \\ NetLuidIndex " , MAX_REG_PATH , RegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-10-13 19:40:52 +02:00
}
2020-07-07 15:42:39 +02:00
2020-11-03 12:29:34 +01:00
if ( ! RegistryQueryDWORD ( Key , L " *IfType " , & Adapter - > IfType , TRUE ) )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( Key , RegPath ) ;
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %.*s \\ *IfType " , MAX_REG_PATH , RegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-10-13 19:40:52 +02:00
}
2020-07-07 15:42:39 +02:00
DWORD Size ;
2020-11-03 12:29:34 +01:00
if ( ! SetupDiGetDeviceInstanceIdW (
DevInfo , DevInfoData , Adapter - > DevInstanceID , _countof ( Adapter - > DevInstanceID ) , & Size ) )
2020-07-07 15:42:39 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get adapter %u instance ID " , DevInfoData - > DevInst ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
if ( wcsncpy_s ( Adapter - > Pool , _countof ( Adapter - > Pool ) , Pool , _TRUNCATE ) = = STRUNCATE )
2020-10-30 06:51:24 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Pool name too long: %s " , Pool ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_PARAMETER ;
2020-10-30 06:51:24 +01:00
goto cleanupAdapter ;
}
2020-11-03 12:29:34 +01:00
RegCloseKey ( Key ) ;
return Adapter ;
2020-07-07 15:42:39 +02:00
2020-07-21 16:38:00 +02:00
cleanupAdapter :
2020-11-04 12:55:25 +01:00
Free ( Adapter ) ;
2020-07-07 15:42:39 +02:00
cleanupKey :
RegCloseKey ( Key ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( LastError ) ;
return NULL ;
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
GetDeviceRegPath ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_REG_PATH ) WCHAR * Path )
2020-07-21 16:38:00 +02:00
{
2020-10-30 06:51:24 +01:00
if ( _snwprintf_s (
Path ,
MAX_REG_PATH ,
_TRUNCATE ,
L " SYSTEM \\ CurrentControlSet \\ Enum \\ %.*s " ,
MAX_INSTANCE_ID ,
Adapter - > DevInstanceID ) = = - 1 )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Registry path too long: %.*s " , MAX_INSTANCE_ID , Adapter - > DevInstanceID ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
}
return TRUE ;
2020-07-21 16:38:00 +02:00
}
2020-07-21 18:19:15 +02:00
void WINAPI
2020-07-07 15:42:39 +02:00
WintunFreeAdapter ( _In_ WINTUN_ADAPTER * Adapter )
{
2020-11-04 12:55:25 +01:00
Free ( Adapter ) ;
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = NULL ) WINTUN_ADAPTER * WINAPI
2020-11-05 13:39:13 +01:00
WintunOpenAdapter ( _In_z_ const WCHAR * Pool , _In_z_ const WCHAR * Name )
2020-07-07 15:42:39 +02:00
{
2020-10-30 12:25:24 +01:00
if ( ! ElevateToSystem ( ) )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) ;
return NULL ;
}
DWORD LastError ;
WINTUN_ADAPTER * Adapter = NULL ;
2020-11-02 12:07:05 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
2020-07-07 15:42:39 +02:00
if ( ! Mutex )
2020-10-30 12:25:24 +01:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to take %s pool mutex " , Pool ) ;
2020-10-30 12:25:24 +01:00
goto cleanupToken ;
}
2020-07-07 15:42:39 +02:00
2020-10-13 19:40:52 +02:00
HDEVINFO DevInfo = SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
2020-07-07 15:42:39 +02:00
if ( DevInfo = = INVALID_HANDLE_VALUE )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
2020-07-07 15:42:39 +02:00
goto cleanupMutex ;
}
2020-10-13 19:40:52 +02:00
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
2020-07-07 15:42:39 +02:00
{
SP_DEVINFO_DATA DevInfoData = { . cbSize = sizeof ( SP_DEVINFO_DATA ) } ;
2020-10-13 19:40:52 +02:00
if ( ! SetupDiEnumDeviceInfo ( DevInfo , EnumIndex , & DevInfoData ) )
2020-07-07 15:42:39 +02:00
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
break ;
continue ;
}
GUID CfgInstanceID ;
2021-02-01 10:41:36 +01:00
if ( ! GetNetCfgInstanceIdFromDevInfo ( DevInfo , & DevInfoData , & CfgInstanceID ) )
2020-07-07 15:42:39 +02:00
continue ;
/* TODO: is there a better way than comparing ifnames? */
2020-07-28 12:38:17 +02:00
WCHAR Name2 [ MAX_ADAPTER_NAME ] ;
2020-07-21 16:38:00 +02:00
if ( NciGetConnectionName ( & CfgInstanceID , Name2 , sizeof ( Name2 ) , NULL ) ! = ERROR_SUCCESS )
2020-07-07 15:42:39 +02:00
continue ;
2020-07-21 16:38:00 +02:00
Name2 [ _countof ( Name2 ) - 1 ] = 0 ;
2020-10-30 06:06:06 +01:00
if ( _wcsicmp ( Name , Name2 ) )
2020-07-28 12:38:17 +02:00
{
2020-10-30 06:12:42 +01:00
RemoveNumberedSuffix ( Name2 ) ;
2020-10-30 06:06:06 +01:00
if ( _wcsicmp ( Name , Name2 ) )
2020-07-28 12:38:17 +02:00
continue ;
}
2020-07-07 15:42:39 +02:00
2020-10-15 11:32:06 +02:00
/* Check the Hardware ID to make sure it's a real Wintun device. */
2020-11-03 12:29:34 +01:00
if ( ! IsOurAdapter ( DevInfo , & DevInfoData ) )
2020-07-07 15:42:39 +02:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Foreign adapter %u named %s exists " , DevInfoData . DevInst , Name ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_ALREADY_EXISTS ;
2020-07-07 15:42:39 +02:00
goto cleanupDevInfo ;
}
2020-11-03 12:29:34 +01:00
if ( ! IsPoolMember ( Pool , DevInfo , & DevInfoData ) )
2020-07-07 15:42:39 +02:00
{
2020-11-03 12:29:34 +01:00
if ( ( LastError = GetLastError ( ) ) = = ERROR_SUCCESS )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Adapter %u named %s is not a member of %s pool " , DevInfoData . DevInst , Name , Pool ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_ALREADY_EXISTS ;
goto cleanupDevInfo ;
}
else
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get adapter %u pool membership " , DevInfoData . DevInst ) ;
2020-11-03 12:29:34 +01:00
goto cleanupDevInfo ;
}
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
Adapter = CreateAdapterData ( Pool , DevInfo , & DevInfoData ) ;
2021-02-03 22:32:58 +01:00
if ( ! Adapter )
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to create adapter %u data " , DevInfoData . DevInst ) ;
2021-02-03 22:32:58 +01:00
goto cleanupDevInfo ;
}
if ( ! EnsureDeviceObject ( Adapter - > DevInstanceID ) )
{
2021-02-02 13:12:45 +01:00
LastError = GetLastError ( ) ;
2021-02-03 22:32:58 +01:00
goto cleanupDevInfo ;
}
LastError = ERROR_SUCCESS ;
2020-07-21 16:38:00 +02:00
goto cleanupDevInfo ;
}
2020-11-03 12:29:34 +01:00
LastError = ERROR_FILE_NOT_FOUND ;
2020-07-21 16:38:00 +02:00
cleanupDevInfo :
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupMutex :
2020-10-15 11:32:06 +02:00
NamespaceReleaseMutex ( Mutex ) ;
2020-10-30 12:25:24 +01:00
cleanupToken :
RevertToSelf ( ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( LastError ) ;
return Adapter ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = FALSE ) BOOL WINAPI
WintunGetAdapterName ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_ADAPTER_NAME ) WCHAR * Name )
2020-07-21 16:38:00 +02:00
{
2020-11-03 12:29:34 +01:00
DWORD LastError = NciGetConnectionName ( & Adapter - > CfgInstanceID , Name , MAX_ADAPTER_NAME * sizeof ( WCHAR ) , NULL ) ;
if ( LastError ! = ERROR_SUCCESS )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Failed to get name " ) ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
return TRUE ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
ConvertInterfaceAliasToGuid ( _In_z_ const WCHAR * Name , _Out_ GUID * Guid )
2020-07-21 16:38:00 +02:00
{
NET_LUID Luid ;
2020-11-03 12:29:34 +01:00
DWORD LastError = ConvertInterfaceAliasToLuid ( Name , & Luid ) ;
if ( LastError ! = NO_ERROR )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Failed convert interface %s name to the locally unique identifier " , Name ) ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
LastError = ConvertInterfaceLuidToGuid ( & Luid , Guid ) ;
if ( LastError ! = NO_ERROR )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Failed to convert interface %s LUID (%I64u) to GUID " , Name , Luid . Value ) ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
return TRUE ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = FALSE ) BOOL WINAPI
WintunSetAdapterName ( _In_ const WINTUN_ADAPTER * Adapter , _In_z_ const WCHAR * Name )
2020-07-21 16:38:00 +02:00
{
2020-11-03 12:29:34 +01:00
DWORD LastError ;
2020-07-21 16:38:00 +02:00
const int MaxSuffix = 1000 ;
WCHAR AvailableName [ MAX_ADAPTER_NAME ] ;
2020-10-30 06:51:24 +01:00
if ( wcsncpy_s ( AvailableName , _countof ( AvailableName ) , Name , _TRUNCATE ) = = STRUNCATE )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Adapter name too long: %s " , Name ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
}
2020-07-21 16:38:00 +02:00
for ( int i = 0 ; ; + + i )
{
2020-11-03 12:29:34 +01:00
LastError = NciSetConnectionName ( & Adapter - > CfgInstanceID , AvailableName ) ;
if ( LastError = = ERROR_DUP_NAME )
2020-07-07 15:42:39 +02:00
{
2020-07-21 16:38:00 +02:00
GUID Guid2 ;
2020-11-03 12:29:34 +01:00
if ( ConvertInterfaceAliasToGuid ( AvailableName , & Guid2 ) )
2020-07-21 16:38:00 +02:00
{
for ( int j = 0 ; j < MaxSuffix ; + + j )
{
WCHAR Proposal [ MAX_ADAPTER_NAME ] ;
2020-10-31 18:13:36 +01:00
if ( _snwprintf_s ( Proposal , _countof ( Proposal ) , _TRUNCATE , L " %s %d " , Name , j + 1 ) = = - 1 )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Adapter name too long: %s %d " , Name , j + 1 ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
}
2020-07-21 16:38:00 +02:00
if ( _wcsnicmp ( Proposal , AvailableName , MAX_ADAPTER_NAME ) = = 0 )
continue ;
2020-11-03 12:29:34 +01:00
DWORD LastError2 = NciSetConnectionName ( & Guid2 , Proposal ) ;
if ( LastError2 = = ERROR_DUP_NAME )
2020-07-21 16:38:00 +02:00
continue ;
2020-11-03 12:29:34 +01:00
if ( LastError2 = = ERROR_SUCCESS )
2020-07-21 16:38:00 +02:00
{
2020-11-03 12:29:34 +01:00
LastError = NciSetConnectionName ( & Adapter - > CfgInstanceID , AvailableName ) ;
if ( LastError = = ERROR_SUCCESS )
2020-07-21 16:38:00 +02:00
break ;
}
break ;
}
}
2020-07-07 15:42:39 +02:00
}
2020-11-03 12:29:34 +01:00
if ( LastError = = ERROR_SUCCESS )
2020-07-21 16:38:00 +02:00
break ;
2020-11-03 12:29:34 +01:00
if ( i > = MaxSuffix | | LastError ! = ERROR_DUP_NAME )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Setting adapter name failed " ) ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
2020-10-31 18:13:36 +01:00
if ( _snwprintf_s ( AvailableName , _countof ( AvailableName ) , _TRUNCATE , L " %s %d " , Name , i + 1 ) = = - 1 )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Adapter name too long: %s %d " , Name , i + 1 ) ;
2020-11-03 12:29:34 +01:00
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
}
2020-07-21 16:38:00 +02:00
}
/* TODO: This should use NetSetup2 so that it doesn't get unset. */
HKEY DeviceRegKey ;
2020-07-24 08:10:00 +02:00
WCHAR DeviceRegPath [ MAX_REG_PATH ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetDeviceRegPath ( Adapter , DeviceRegPath ) )
return FALSE ;
LastError = RegOpenKeyExW ( HKEY_LOCAL_MACHINE , DeviceRegPath , 0 , KEY_SET_VALUE , & DeviceRegKey ) ;
if ( LastError ! = ERROR_SUCCESS )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Failed to open registry key %s " , DeviceRegPath ) ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
2020-07-21 16:38:00 +02:00
WCHAR PoolDeviceTypeName [ MAX_POOL_DEVICE_TYPE ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetPoolDeviceTypeName ( Adapter - > Pool , PoolDeviceTypeName ) )
{
LastError = GetLastError ( ) ;
2020-10-30 06:51:24 +01:00
goto cleanupDeviceRegKey ;
2020-11-03 12:29:34 +01:00
}
LastError = RegSetKeyValueW (
2020-07-21 16:38:00 +02:00
DeviceRegKey ,
NULL ,
L " FriendlyName " ,
REG_SZ ,
PoolDeviceTypeName ,
( DWORD ) ( ( wcslen ( PoolDeviceTypeName ) + 1 ) * sizeof ( WCHAR ) ) ) ;
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_SUCCESS )
2021-02-02 13:12:45 +01:00
LOG_ERROR ( LastError , L " Failed to set %s \\ FriendlyName " , DeviceRegPath ) ;
2020-10-30 06:51:24 +01:00
cleanupDeviceRegKey :
2020-07-21 16:38:00 +02:00
RegCloseKey ( DeviceRegKey ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-07-21 16:38:00 +02:00
}
void WINAPI
2020-11-02 18:34:49 +01:00
WintunGetAdapterLUID ( _In_ const WINTUN_ADAPTER * Adapter , _Out_ NET_LUID * Luid )
2020-07-21 16:38:00 +02:00
{
2020-11-02 18:34:49 +01:00
Luid - > Info . Reserved = 0 ;
Luid - > Info . NetLuidIndex = Adapter - > LuidIndex ;
Luid - > Info . IfType = Adapter - > IfType ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = INVALID_HANDLE_VALUE ) HANDLE WINAPI
2020-11-05 15:25:52 +01:00
AdapterOpenDeviceObject ( _In_ const WINTUN_ADAPTER * Adapter )
2020-07-21 16:38:00 +02:00
{
2020-11-03 12:29:34 +01:00
return OpenDeviceObject ( Adapter - > DevInstanceID ) ;
2020-07-21 16:38:00 +02:00
}
2020-10-15 15:54:37 +02:00
static BOOL
2020-10-30 06:03:21 +01:00
HaveWHQL ( void )
2020-10-15 15:54:37 +02:00
{
2020-11-03 02:09:00 +01:00
if ( HAVE_WHQL )
{
DWORD MajorVersion ;
RtlGetNtVersionNumbers ( & MajorVersion , NULL , NULL ) ;
return MajorVersion > = 10 ;
}
2020-10-30 08:17:33 +01:00
return FALSE ;
2020-10-15 15:54:37 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL InstallCertificate ( _In_z_ const WCHAR * SignedResource )
2020-10-15 15:54:37 +02:00
{
LOG ( WINTUN_LOG_INFO , L " Trusting code signing certificate " ) ;
DWORD SizeResource ;
2020-11-03 12:29:34 +01:00
const void * LockedResource = ResourceGetAddress ( SignedResource , & SizeResource ) ;
if ( ! LockedResource )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to locate resource %s " , SignedResource ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
2020-10-15 15:54:37 +02:00
const CERT_BLOB CertBlob = { . cbData = SizeResource , . pbData = ( BYTE * ) LockedResource } ;
HCERTSTORE QueriedStore ;
if ( ! CryptQueryObject (
CERT_QUERY_OBJECT_BLOB ,
& CertBlob ,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED ,
CERT_QUERY_FORMAT_FLAG_ALL ,
0 ,
0 ,
0 ,
0 ,
& QueriedStore ,
0 ,
NULL ) )
2020-11-03 12:29:34 +01:00
{
LOG_LAST_ERROR ( L " Failed to find certificate " ) ;
return FALSE ;
}
DWORD LastError = ERROR_SUCCESS ;
2020-10-15 15:54:37 +02:00
HCERTSTORE TrustedStore =
CertOpenStore ( CERT_STORE_PROV_SYSTEM , 0 , 0 , CERT_SYSTEM_STORE_LOCAL_MACHINE , L " TrustedPublisher " ) ;
if ( ! TrustedStore )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to open store " ) ;
2020-10-15 15:54:37 +02:00
goto cleanupQueriedStore ;
}
LPSTR CodeSigningOid [ ] = { szOID_PKIX_KP_CODE_SIGNING } ;
CERT_ENHKEY_USAGE EnhancedUsage = { . cUsageIdentifier = 1 , . rgpszUsageIdentifier = CodeSigningOid } ;
for ( const CERT_CONTEXT * CertContext = NULL ; ( CertContext = CertFindCertificateInStore (
QueriedStore ,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG ,
CERT_FIND_ENHKEY_USAGE ,
& EnhancedUsage ,
CertContext ) ) ! = NULL ; )
{
CERT_EXTENSION * Ext = CertFindExtension (
szOID_BASIC_CONSTRAINTS2 , CertContext - > pCertInfo - > cExtension , CertContext - > pCertInfo - > rgExtension ) ;
CERT_BASIC_CONSTRAINTS2_INFO Constraints ;
DWORD Size = sizeof ( Constraints ) ;
if ( Ext & &
CryptDecodeObjectEx (
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
szOID_BASIC_CONSTRAINTS2 ,
Ext - > Value . pbData ,
Ext - > Value . cbData ,
0 ,
NULL ,
& Constraints ,
& Size ) & &
! Constraints . fCA )
if ( ! CertAddCertificateContextToStore ( TrustedStore , CertContext , CERT_STORE_ADD_REPLACE_EXISTING , NULL ) )
{
LOG_LAST_ERROR ( L " Failed to add certificate to store " ) ;
2020-11-03 12:29:34 +01:00
LastError = LastError ! = ERROR_SUCCESS ? LastError : GetLastError ( ) ;
2020-10-15 15:54:37 +02:00
}
}
CertCloseStore ( TrustedStore , 0 ) ;
cleanupQueriedStore :
CertCloseStore ( QueriedStore , 0 ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-10-15 15:54:37 +02:00
}
2020-10-30 09:53:09 +01:00
static BOOL
IsOurDrvInfoDetail ( _In_ const SP_DRVINFO_DETAIL_DATA_W * DrvInfoDetailData )
{
2020-11-03 09:47:42 +01:00
if ( DrvInfoDetailData - > CompatIDsOffset > 1 & & ! _wcsicmp ( DrvInfoDetailData - > HardwareID , WINTUN_HWID ) )
return TRUE ;
if ( DrvInfoDetailData - > CompatIDsLength & &
IsOurHardwareID ( DrvInfoDetailData - > HardwareID + DrvInfoDetailData - > CompatIDsOffset ) )
return TRUE ;
return FALSE ;
2020-10-30 09:53:09 +01:00
}
2020-10-16 15:20:49 +02:00
static BOOL
2020-11-02 16:28:51 +01:00
IsNewer (
_In_ const FILETIME * DriverDate1 ,
_In_ DWORDLONG DriverVersion1 ,
_In_ const FILETIME * DriverDate2 ,
_In_ DWORDLONG DriverVersion2 )
2020-10-16 15:20:49 +02:00
{
2020-11-02 16:28:51 +01:00
if ( DriverDate1 - > dwHighDateTime > DriverDate2 - > dwHighDateTime )
2020-10-16 15:20:49 +02:00
return TRUE ;
2020-11-02 16:28:51 +01:00
if ( DriverDate1 - > dwHighDateTime < DriverDate2 - > dwHighDateTime )
2020-10-16 15:20:49 +02:00
return FALSE ;
2020-11-02 16:28:51 +01:00
if ( DriverDate1 - > dwLowDateTime > DriverDate2 - > dwLowDateTime )
2020-10-16 15:20:49 +02:00
return TRUE ;
2020-11-02 16:28:51 +01:00
if ( DriverDate1 - > dwLowDateTime < DriverDate2 - > dwLowDateTime )
2020-10-16 15:20:49 +02:00
return FALSE ;
2020-11-02 16:28:51 +01:00
if ( DriverVersion1 > DriverVersion2 )
2020-10-16 15:20:49 +02:00
return TRUE ;
2020-11-02 16:28:51 +01:00
if ( DriverVersion1 < DriverVersion2 )
2020-10-16 15:20:49 +02:00
return FALSE ;
return FALSE ;
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
GetTcpipAdapterRegPath ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_REG_PATH ) WCHAR * Path )
2020-10-16 15:20:49 +02:00
{
WCHAR Guid [ MAX_GUID_STRING_LEN ] ;
2020-10-30 06:51:24 +01:00
if ( _snwprintf_s (
Path ,
MAX_REG_PATH ,
_TRUNCATE ,
L " SYSTEM \\ CurrentControlSet \\ Services \\ Tcpip \\ Parameters \\ Adapters \\ %.*s " ,
StringFromGUID2 ( & Adapter - > CfgInstanceID , Guid , _countof ( Guid ) ) ,
Guid ) = = - 1 )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Registry path too long " ) ;
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
}
return TRUE ;
2020-10-16 15:20:49 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
GetTcpipInterfaceRegPath ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_REG_PATH ) WCHAR * Path )
2020-10-16 15:20:49 +02:00
{
HKEY TcpipAdapterRegKey ;
WCHAR TcpipAdapterRegPath [ MAX_REG_PATH ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetTcpipAdapterRegPath ( Adapter , TcpipAdapterRegPath ) )
return FALSE ;
DWORD LastError = RegOpenKeyExW ( HKEY_LOCAL_MACHINE , TcpipAdapterRegPath , 0 , KEY_QUERY_VALUE , & TcpipAdapterRegKey ) ;
if ( LastError ! = ERROR_SUCCESS )
{
2021-02-02 13:12:45 +01:00
SetLastError ( LOG_ERROR ( LastError , L " Failed to open registry key %s " , TcpipAdapterRegPath ) ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
WCHAR * Paths = RegistryQueryString ( TcpipAdapterRegKey , L " IpConfig " , TRUE ) ;
if ( ! Paths )
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %s \\ IpConfig " , TcpipAdapterRegPath ) ;
2020-10-16 15:20:49 +02:00
goto cleanupTcpipAdapterRegKey ;
}
if ( ! Paths [ 0 ] )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " %s \\ IpConfig is empty " , TcpipAdapterRegPath ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_DATA ;
2020-10-16 15:20:49 +02:00
goto cleanupPaths ;
}
2020-10-30 06:51:24 +01:00
if ( _snwprintf_s ( Path , MAX_REG_PATH , _TRUNCATE , L " SYSTEM \\ CurrentControlSet \\ Services \\ %s " , Paths ) = = - 1 )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Registry path too long: %s " , Paths ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_PARAMETER ;
2020-10-30 06:51:24 +01:00
goto cleanupPaths ;
}
2020-10-16 15:20:49 +02:00
cleanupPaths :
2020-11-04 12:55:25 +01:00
Free ( Paths ) ;
2020-10-16 15:20:49 +02:00
cleanupTcpipAdapterRegKey :
RegCloseKey ( TcpipAdapterRegKey ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-10-16 15:20:49 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = 0 ) DWORD VersionOfFile ( _In_z_ const WCHAR * Filename )
2020-10-30 18:20:57 +01:00
{
DWORD Zero ;
DWORD Len = GetFileVersionInfoSizeW ( Filename , & Zero ) ;
if ( ! Len )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to query %s version info size " , Filename ) ;
2020-11-03 12:29:34 +01:00
return 0 ;
}
2020-11-04 12:55:25 +01:00
VOID * VersionInfo = Alloc ( Len ) ;
2020-10-30 18:20:57 +01:00
if ( ! VersionInfo )
2020-11-03 12:29:34 +01:00
return 0 ;
DWORD LastError = ERROR_SUCCESS , Version = 0 ;
2020-10-30 18:20:57 +01:00
VS_FIXEDFILEINFO * FixedInfo ;
UINT FixedInfoLen = sizeof ( * FixedInfo ) ;
if ( ! GetFileVersionInfoW ( Filename , 0 , Len , VersionInfo ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get %s version info " , Filename ) ;
2020-10-30 18:20:57 +01:00
goto out ;
}
if ( ! VerQueryValueW ( VersionInfo , L " \\ " , & FixedInfo , & FixedInfoLen ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get %s version info root " , Filename ) ;
2020-10-30 18:20:57 +01:00
goto out ;
}
2020-11-03 11:00:53 +01:00
Version = FixedInfo - > dwFileVersionMS ;
2020-11-03 12:29:34 +01:00
if ( ! Version )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_WARN , L " Determined version of %s, but was v0.0, so returning failure " , Filename ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_VERSION_PARSE_ERROR ;
}
2020-10-30 18:20:57 +01:00
out :
2020-11-04 12:55:25 +01:00
Free ( VersionInfo ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( Version , LastError ) ;
2020-10-30 18:20:57 +01:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
CreateTemporaryDirectory ( _Out_cap_c_ ( MAX_PATH ) WCHAR * RandomTempSubDirectory )
2020-07-21 16:38:00 +02:00
{
2020-11-02 16:28:51 +01:00
WCHAR WindowsDirectory [ MAX_PATH ] ;
if ( ! GetWindowsDirectoryW ( WindowsDirectory , _countof ( WindowsDirectory ) ) )
2020-11-03 12:29:34 +01:00
{
LOG_LAST_ERROR ( L " Failed to get Windows folder " ) ;
return FALSE ;
}
2020-11-02 16:28:51 +01:00
WCHAR WindowsTempDirectory [ MAX_PATH ] ;
if ( ! PathCombineW ( WindowsTempDirectory , WindowsDirectory , L " Temp " ) )
2020-11-03 12:29:34 +01:00
{
SetLastError ( ERROR_BUFFER_OVERFLOW ) ;
return FALSE ;
}
2020-11-02 16:28:51 +01:00
UCHAR RandomBytes [ 32 ] = { 0 } ;
# pragma warning(suppress : 6387)
if ( ! RtlGenRandom ( RandomBytes , sizeof ( RandomBytes ) ) )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to generate random " ) ;
SetLastError ( ERROR_GEN_FAILURE ) ;
return FALSE ;
}
2020-11-02 16:28:51 +01:00
WCHAR RandomSubDirectory [ sizeof ( RandomBytes ) * 2 + 1 ] ;
for ( int i = 0 ; i < sizeof ( RandomBytes ) ; + + i )
swprintf_s ( & RandomSubDirectory [ i * 2 ] , 3 , L " %02x " , RandomBytes [ i ] ) ;
if ( ! PathCombineW ( RandomTempSubDirectory , WindowsTempDirectory , RandomSubDirectory ) )
2020-11-03 12:29:34 +01:00
{
SetLastError ( ERROR_BUFFER_OVERFLOW ) ;
return FALSE ;
}
2020-11-02 16:28:51 +01:00
if ( ! CreateDirectoryW ( RandomTempSubDirectory , & SecurityAttributes ) )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to create temporary folder %s " , RandomTempSubDirectory ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
return TRUE ;
2020-11-02 16:28:51 +01:00
}
2020-07-21 16:38:00 +02:00
2020-11-06 10:25:15 +01:00
static DWORD WINAPI
MaybeGetRunningDriverVersion ( BOOL ReturnOneIfRunningInsteadOfVersion )
2020-11-02 16:28:51 +01:00
{
PRTL_PROCESS_MODULES Modules ;
ULONG BufferSize = 128 * 1024 ;
for ( ; ; )
2020-10-31 18:13:36 +01:00
{
2020-11-04 12:55:25 +01:00
Modules = Alloc ( BufferSize ) ;
2020-11-02 16:28:51 +01:00
if ( ! Modules )
2020-11-03 12:29:34 +01:00
return 0 ;
2020-11-02 16:28:51 +01:00
NTSTATUS Status = NtQuerySystemInformation ( SystemModuleInformation , Modules , BufferSize , & BufferSize ) ;
if ( NT_SUCCESS ( Status ) )
break ;
2020-11-04 12:55:25 +01:00
Free ( Modules ) ;
2020-11-02 16:28:51 +01:00
if ( Status = = STATUS_INFO_LENGTH_MISMATCH )
continue ;
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to enumerate drivers (status: 0x%x) " , Status ) ;
2020-11-04 01:08:41 +01:00
SetLastError ( RtlNtStatusToDosError ( Status ) ) ;
2020-11-03 12:29:34 +01:00
return 0 ;
2020-10-31 18:13:36 +01:00
}
2020-11-03 12:29:34 +01:00
DWORD LastError = ERROR_SUCCESS , Version = 0 ;
2020-11-02 16:28:51 +01:00
for ( ULONG i = Modules - > NumberOfModules ; i - - > 0 ; )
2020-10-15 15:54:37 +02:00
{
2020-11-02 16:28:51 +01:00
const char * NtPath = ( const char * ) Modules - > Modules [ i ] . FullPathName ;
if ( ! _stricmp ( & NtPath [ Modules - > Modules [ i ] . OffsetToFileName ] , " wintun.sys " ) )
{
2020-11-06 10:25:15 +01:00
if ( ReturnOneIfRunningInsteadOfVersion )
{
Version = 1 ;
goto cleanupModules ;
}
2020-11-02 16:28:51 +01:00
WCHAR FilePath [ MAX_PATH * 3 + 15 ] ;
if ( _snwprintf_s ( FilePath , _countof ( FilePath ) , _TRUNCATE , L " \\ \\ ? \\ GLOBALROOT%S " , NtPath ) = = - 1 )
continue ;
Version = VersionOfFile ( FilePath ) ;
2020-11-03 12:29:34 +01:00
if ( ! Version )
LastError = GetLastError ( ) ;
goto cleanupModules ;
2020-11-02 16:28:51 +01:00
}
2020-10-15 15:54:37 +02:00
}
2020-11-03 12:29:34 +01:00
LastError = ERROR_FILE_NOT_FOUND ;
cleanupModules :
2020-11-04 12:55:25 +01:00
Free ( Modules ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( Version , LastError ) ;
2020-11-02 16:28:51 +01:00
}
2020-07-21 16:38:00 +02:00
2020-11-06 10:25:15 +01:00
DWORD WINAPI
WintunGetRunningDriverVersion ( void )
{
return MaybeGetRunningDriverVersion ( FALSE ) ;
}
2020-11-02 16:28:51 +01:00
static BOOL
EnsureWintunUnloaded ( void )
{
BOOL Loaded ;
2020-11-06 10:25:15 +01:00
for ( int i = 0 ; ( Loaded = MaybeGetRunningDriverVersion ( TRUE ) ! = 0 ) ! = FALSE & & i < 300 ; + + i )
2020-11-02 16:28:51 +01:00
Sleep ( 50 ) ;
return ! Loaded ;
}
2020-07-21 16:38:00 +02:00
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL SelectDriver (
2020-11-02 16:28:51 +01:00
_In_ HDEVINFO DevInfo ,
2021-02-02 12:53:40 +01:00
_In_ SP_DEVINFO_DATA * DevInfoData ,
2020-11-09 14:45:41 +01:00
_Inout_ SP_DEVINSTALL_PARAMS_W * DevInstallParams )
2020-11-02 16:28:51 +01:00
{
2020-11-03 17:06:20 +01:00
static const FILETIME OurDriverDate = WINTUN_INF_FILETIME ;
static const DWORDLONG OurDriverVersion = WINTUN_INF_VERSION ;
2020-11-02 16:28:51 +01:00
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex ( ) ;
if ( ! DriverInstallationLock )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to take driver installation mutex " ) ;
return FALSE ;
}
DWORD LastError ;
2020-11-02 16:28:51 +01:00
if ( ! SetupDiBuildDriverInfoList ( DevInfo , DevInfoData , SPDIT_COMPATDRIVER ) )
2020-07-21 16:38:00 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed building adapter %u driver info list " , DevInfoData - > DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDriverInstallationLock ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 10:34:37 +01:00
BOOL DestroyDriverInfoListOnCleanup = TRUE ;
2020-11-02 16:28:51 +01:00
FILETIME DriverDate = { 0 } ;
2020-07-21 16:38:00 +02:00
DWORDLONG DriverVersion = 0 ;
2020-11-02 16:28:51 +01:00
HDEVINFO DevInfoExistingAdapters = INVALID_HANDLE_VALUE ;
SP_DEVINFO_DATA_LIST * ExistingAdapters = NULL ;
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
2020-07-21 16:38:00 +02:00
{
2020-10-13 19:40:52 +02:00
SP_DRVINFO_DATA_W DrvInfoData = { . cbSize = sizeof ( SP_DRVINFO_DATA_W ) } ;
2020-11-02 16:28:51 +01:00
if ( ! SetupDiEnumDriverInfoW ( DevInfo , DevInfoData , SPDIT_COMPATDRIVER , EnumIndex , & DrvInfoData ) )
2020-07-21 16:38:00 +02:00
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
break ;
continue ;
}
2020-11-03 12:29:34 +01:00
SP_DRVINFO_DETAIL_DATA_W * DrvInfoDetailData = GetAdapterDrvInfoDetail ( DevInfo , DevInfoData , & DrvInfoData ) ;
if ( ! DrvInfoDetailData )
2020-10-15 12:21:55 +02:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed getting adapter %u driver info detail " , DevInfoData - > DevInst ) ;
2020-07-21 16:38:00 +02:00
continue ;
2020-10-15 12:21:55 +02:00
}
2020-10-30 09:53:09 +01:00
if ( ! IsOurDrvInfoDetail ( DrvInfoDetailData ) )
2020-11-02 16:28:51 +01:00
goto next ;
if ( IsNewer ( & OurDriverDate , OurDriverVersion , & DrvInfoData . DriverDate , DrvInfoData . DriverVersion ) )
2020-07-21 16:38:00 +02:00
{
2020-11-02 16:28:51 +01:00
if ( DevInfoExistingAdapters = = INVALID_HANDLE_VALUE )
{
DevInfoExistingAdapters =
SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
if ( DevInfoExistingAdapters = = INVALID_HANDLE_VALUE )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
2020-11-04 12:55:25 +01:00
Free ( DrvInfoDetailData ) ;
2020-11-03 10:34:37 +01:00
goto cleanupExistingAdapters ;
2020-11-02 16:28:51 +01:00
}
_Analysis_assume_ ( DevInfoExistingAdapters ! = NULL ) ;
DisableAllOurAdapters ( DevInfoExistingAdapters , & ExistingAdapters ) ;
LOG ( WINTUN_LOG_INFO , L " Waiting for existing driver to unload from kernel " ) ;
if ( ! EnsureWintunUnloaded ( ) )
LOG ( WINTUN_LOG_WARN ,
L " Failed to unload existing driver, which means a reboot will likely be required " ) ;
}
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO ,
L " Removing existing driver %u.%u " ,
( DWORD ) ( ( DrvInfoData . DriverVersion & 0xffff000000000000 ) > > 48 ) ,
( DWORD ) ( ( DrvInfoData . DriverVersion & 0x0000ffff00000000 ) > > 32 ) ) ;
LPWSTR InfFileName = PathFindFileNameW ( DrvInfoDetailData - > InfFileName ) ;
if ( ! SetupUninstallOEMInfW ( InfFileName , SUOI_FORCEDELETE , NULL ) )
LOG_LAST_ERROR ( L " Unable to remove existing driver %s " , InfFileName ) ;
2020-11-02 16:28:51 +01:00
goto next ;
}
if ( ! IsNewer ( & DrvInfoData . DriverDate , DrvInfoData . DriverVersion , & DriverDate , DriverVersion ) )
goto next ;
if ( ! SetupDiSetSelectedDriverW ( DevInfo , DevInfoData , & DrvInfoData ) )
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR (
L " Failed to select driver %s for adapter %u " , DrvInfoDetailData - > InfFileName , DevInfoData - > DevInst ) ;
2020-11-02 16:28:51 +01:00
goto next ;
2020-07-21 16:38:00 +02:00
}
2020-10-13 19:40:52 +02:00
DriverDate = DrvInfoData . DriverDate ;
DriverVersion = DrvInfoData . DriverVersion ;
2020-11-02 16:28:51 +01:00
next :
2020-11-04 12:55:25 +01:00
Free ( DrvInfoDetailData ) ;
2020-07-21 16:38:00 +02:00
}
2020-11-02 16:28:51 +01:00
if ( DriverVersion )
2020-11-03 10:34:37 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO ,
L " Using existing driver %u.%u " ,
( DWORD ) ( ( DriverVersion & 0xffff000000000000 ) > > 48 ) ,
( DWORD ) ( ( DriverVersion & 0x0000ffff00000000 ) > > 32 ) ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_SUCCESS ;
2020-11-03 10:34:37 +01:00
DestroyDriverInfoListOnCleanup = FALSE ;
2020-11-02 16:28:51 +01:00
goto cleanupExistingAdapters ;
2020-11-03 10:34:37 +01:00
}
2020-07-21 16:38:00 +02:00
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO ,
L " Installing driver %u.%u " ,
( DWORD ) ( ( OurDriverVersion & 0xffff000000000000 ) > > 48 ) ,
( DWORD ) ( ( OurDriverVersion & 0x0000ffff00000000 ) > > 32 ) ) ;
2020-11-02 16:28:51 +01:00
WCHAR RandomTempSubDirectory [ MAX_PATH ] ;
2020-11-03 12:29:34 +01:00
if ( ! CreateTemporaryDirectory ( RandomTempSubDirectory ) )
2020-07-21 16:38:00 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to create temporary folder %s " , RandomTempSubDirectory ) ;
2020-11-02 16:28:51 +01:00
goto cleanupExistingAdapters ;
2020-07-21 16:38:00 +02:00
}
2020-11-02 16:28:51 +01:00
WCHAR CatPath [ MAX_PATH ] = { 0 } ;
WCHAR SysPath [ MAX_PATH ] = { 0 } ;
WCHAR InfPath [ MAX_PATH ] = { 0 } ;
if ( ! PathCombineW ( CatPath , RandomTempSubDirectory , L " wintun.cat " ) | |
! PathCombineW ( SysPath , RandomTempSubDirectory , L " wintun.sys " ) | |
! PathCombineW ( InfPath , RandomTempSubDirectory , L " wintun.inf " ) )
2020-07-21 16:38:00 +02:00
{
2020-11-03 12:29:34 +01:00
LastError = ERROR_BUFFER_OVERFLOW ;
2020-11-02 16:28:51 +01:00
goto cleanupDirectory ;
}
BOOL UseWHQL = HaveWHQL ( ) ;
2020-11-03 12:29:34 +01:00
if ( ! UseWHQL & & ! InstallCertificate ( L " wintun.cat " ) )
2020-11-02 16:28:51 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to install code signing certificate " ) ;
LOG ( WINTUN_LOG_INFO , L " Extracting driver " ) ;
2020-11-03 12:29:34 +01:00
if ( ! ResourceCopyToFile ( CatPath , UseWHQL ? L " wintun-whql.cat " : L " wintun.cat " ) | |
! ResourceCopyToFile ( SysPath , UseWHQL ? L " wintun-whql.sys " : L " wintun.sys " ) | |
! ResourceCopyToFile ( InfPath , UseWHQL ? L " wintun-whql.inf " : L " wintun.inf " ) )
2020-11-02 16:28:51 +01:00
{
2020-11-03 12:29:34 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to extract driver " ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
LOG ( WINTUN_LOG_INFO , L " Installing driver " ) ;
WCHAR InfStorePath [ MAX_PATH ] ;
if ( ! SetupCopyOEMInfW ( InfPath , NULL , SPOST_NONE , 0 , InfStorePath , MAX_PATH , NULL , NULL ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Could not install driver %s to store " , InfPath ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
_Analysis_assume_nullterminated_ ( InfStorePath ) ;
SetupDiDestroyDriverInfoList ( DevInfo , DevInfoData , SPDIT_COMPATDRIVER ) ;
2020-11-03 10:34:37 +01:00
DestroyDriverInfoListOnCleanup = FALSE ;
2020-11-02 16:28:51 +01:00
DevInstallParams - > Flags | = DI_ENUMSINGLEINF ;
if ( wcsncpy_s ( DevInstallParams - > DriverPath , _countof ( DevInstallParams - > DriverPath ) , InfStorePath , _TRUNCATE ) = =
STRUNCATE )
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Inf path too long: %s " , InfStorePath ) ;
2020-11-03 12:29:34 +01:00
LastError = ERROR_INVALID_PARAMETER ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
if ( ! SetupDiSetDeviceInstallParamsW ( DevInfo , DevInfoData , DevInstallParams ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Setting adapter %u device installation parameters failed " , DevInfoData - > DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
if ( ! SetupDiBuildDriverInfoList ( DevInfo , DevInfoData , SPDIT_COMPATDRIVER ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed rebuilding adapter %u driver info list " , DevInfoData - > DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
2020-11-03 10:34:37 +01:00
DestroyDriverInfoListOnCleanup = TRUE ;
2020-11-02 16:28:51 +01:00
SP_DRVINFO_DATA_W DrvInfoData = { . cbSize = sizeof ( SP_DRVINFO_DATA_W ) } ;
if ( ! SetupDiEnumDriverInfoW ( DevInfo , DevInfoData , SPDIT_COMPATDRIVER , 0 , & DrvInfoData ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get adapter %u driver " , DevInfoData - > DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
if ( ! SetupDiSetSelectedDriverW ( DevInfo , DevInfoData , & DrvInfoData ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to set adapter %u driver " , DevInfoData - > DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDelete ;
}
2020-11-03 12:29:34 +01:00
LastError = ERROR_SUCCESS ;
2020-11-03 10:34:37 +01:00
DestroyDriverInfoListOnCleanup = FALSE ;
2020-11-02 16:28:51 +01:00
cleanupDelete :
DeleteFileW ( CatPath ) ;
DeleteFileW ( SysPath ) ;
DeleteFileW ( InfPath ) ;
cleanupDirectory :
RemoveDirectoryW ( RandomTempSubDirectory ) ;
cleanupExistingAdapters :
if ( ExistingAdapters )
{
EnableAllOurAdapters ( DevInfoExistingAdapters , ExistingAdapters ) ;
while ( ExistingAdapters )
{
SP_DEVINFO_DATA_LIST * Next = ExistingAdapters - > Next ;
2020-11-04 12:55:25 +01:00
Free ( ExistingAdapters ) ;
2020-11-02 16:28:51 +01:00
ExistingAdapters = Next ;
}
}
if ( DevInfoExistingAdapters ! = INVALID_HANDLE_VALUE )
SetupDiDestroyDeviceInfoList ( DevInfoExistingAdapters ) ;
2020-11-03 10:34:37 +01:00
if ( DestroyDriverInfoListOnCleanup )
2020-11-02 16:28:51 +01:00
SetupDiDestroyDriverInfoList ( DevInfo , DevInfoData , SPDIT_COMPATDRIVER ) ;
cleanupDriverInstallationLock :
NamespaceReleaseMutex ( DriverInstallationLock ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-11-02 16:28:51 +01:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL ) WINTUN_ADAPTER * CreateAdapter (
2020-11-02 16:28:51 +01:00
_In_z_ const WCHAR * Pool ,
_In_z_ const WCHAR * Name ,
_In_opt_ const GUID * RequestedGUID ,
_Inout_ BOOL * RebootRequired )
{
LOG ( WINTUN_LOG_INFO , L " Creating adapter " ) ;
HDEVINFO DevInfo = SetupDiCreateDeviceInfoListExW ( & GUID_DEVCLASS_NET , NULL , NULL , NULL ) ;
if ( DevInfo = = INVALID_HANDLE_VALUE )
2020-11-03 12:29:34 +01:00
{
LOG_LAST_ERROR ( L " Creating empty device information set failed " ) ;
return NULL ;
}
DWORD LastError ;
WINTUN_ADAPTER * Adapter = NULL ;
2020-11-02 16:28:51 +01:00
WCHAR ClassName [ MAX_CLASS_NAME_LEN ] ;
if ( ! SetupDiClassNameFromGuidExW ( & GUID_DEVCLASS_NET , ClassName , _countof ( ClassName ) , NULL , NULL , NULL ) )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Retrieving class name associated with class GUID failed " ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
WCHAR PoolDeviceTypeName [ MAX_POOL_DEVICE_TYPE ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetPoolDeviceTypeName ( Pool , PoolDeviceTypeName ) )
{
LastError = GetLastError ( ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
2020-11-03 12:29:34 +01:00
}
2020-11-02 16:28:51 +01:00
SP_DEVINFO_DATA DevInfoData = { . cbSize = sizeof ( SP_DEVINFO_DATA ) } ;
if ( ! SetupDiCreateDeviceInfoW (
DevInfo , ClassName , & GUID_DEVCLASS_NET , PoolDeviceTypeName , NULL , DICD_GENERATE_ID , & DevInfoData ) )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Creating new device information element failed " ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
SP_DEVINSTALL_PARAMS_W DevInstallParams = { . cbSize = sizeof ( SP_DEVINSTALL_PARAMS_W ) } ;
if ( ! SetupDiGetDeviceInstallParamsW ( DevInfo , & DevInfoData , & DevInstallParams ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Retrieving adapter %u device installation parameters failed " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
DevInstallParams . Flags | = DI_QUIETINSTALL ;
if ( ! SetupDiSetDeviceInstallParamsW ( DevInfo , & DevInfoData , & DevInstallParams ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Setting adapter %u device installation parameters failed " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
if ( ! SetupDiSetSelectedDevice ( DevInfo , & DevInfoData ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed selecting adapter %u device " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
static const WCHAR Hwids [ _countof ( WINTUN_HWID ) + 1 /*Multi-string terminator*/ ] = WINTUN_HWID ;
if ( ! SetupDiSetDeviceRegistryPropertyW ( DevInfo , & DevInfoData , SPDRP_HARDWAREID , ( const BYTE * ) Hwids , sizeof ( Hwids ) ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed setting adapter %u hardware ID " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
2020-11-09 14:45:41 +01:00
if ( ! SelectDriver ( DevInfo , & DevInfoData , & DevInstallParams ) )
2020-11-02 16:28:51 +01:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to select adapter %u driver " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevInfo ;
}
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
if ( ! Mutex )
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to take %s pool mutex " , Pool ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDriverInfoList ;
}
if ( ! SetupDiCallClassInstaller ( DIF_REGISTERDEVICE , DevInfo , & DevInfoData ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Registering adapter %u device failed " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDevice ;
}
if ( ! SetupDiCallClassInstaller ( DIF_REGISTER_COINSTALLERS , DevInfo , & DevInfoData ) )
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Registering adapter %u coinstallers failed " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
HKEY NetDevRegKey = INVALID_HANDLE_VALUE ;
const int PollTimeout = 50 /* ms */ ;
for ( int i = 0 ; NetDevRegKey = = INVALID_HANDLE_VALUE & & i < WAIT_FOR_REGISTRY_TIMEOUT / PollTimeout ; + + i )
{
if ( i )
Sleep ( PollTimeout ) ;
NetDevRegKey = SetupDiOpenDevRegKey (
DevInfo , & DevInfoData , DICS_FLAG_GLOBAL , 0 , DIREG_DRV , KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_NOTIFY ) ;
2020-07-21 16:38:00 +02:00
}
if ( NetDevRegKey = = INVALID_HANDLE_VALUE )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to open adapter %u device-specific registry key " , DevInfoData . DevInst ) ;
2020-07-21 16:38:00 +02:00
goto cleanupDevice ;
}
if ( RequestedGUID )
{
WCHAR RequestedGUIDStr [ MAX_GUID_STRING_LEN ] ;
2020-11-03 12:29:34 +01:00
LastError = RegSetValueExW (
2020-07-21 16:38:00 +02:00
NetDevRegKey ,
L " NetSetupAnticipatedInstanceId " ,
0 ,
REG_SZ ,
( const BYTE * ) RequestedGUIDStr ,
StringFromGUID2 ( RequestedGUID , RequestedGUIDStr , _countof ( RequestedGUIDStr ) ) * sizeof ( WCHAR ) ) ;
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( NetDevRegKey , RegPath ) ;
LOG_ERROR ( LastError , L " Failed to set %.*s \\ NetSetupAnticipatedInstanceId " , MAX_REG_PATH , RegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 16:38:00 +02:00
}
2020-10-13 19:40:52 +02:00
if ( ! SetupDiCallClassInstaller ( DIF_INSTALLINTERFACES , DevInfo , & DevInfoData ) )
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Installing adapter %u interfaces failed " , DevInfoData . DevInst ) ;
2020-07-21 16:38:00 +02:00
if ( ! SetupDiCallClassInstaller ( DIF_INSTALLDEVICE , DevInfo , & DevInfoData ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Installing adapter %u device failed " , DevInfoData . DevInst ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
}
* RebootRequired = * RebootRequired | | CheckReboot ( DevInfo , & DevInfoData ) ;
2021-01-30 16:39:33 +01:00
if ( ! SetupDiSetDevicePropertyW (
DevInfo ,
& DevInfoData ,
& DEVPKEY_Wintun_Pool ,
DEVPROP_TYPE_STRING ,
# pragma warning(suppress : 4090)
( const BYTE * ) Pool ,
( DWORD ) ( ( wcslen ( Pool ) + 1 ) * sizeof ( WCHAR ) ) ,
0 ) )
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to set adapter %u pool " , DevInfoData . DevInst ) ;
2021-01-30 16:39:33 +01:00
goto cleanupNetDevRegKey ;
}
2020-07-21 16:38:00 +02:00
if ( ! SetupDiSetDeviceRegistryPropertyW (
DevInfo ,
& DevInfoData ,
SPDRP_DEVICEDESC ,
( const BYTE * ) PoolDeviceTypeName ,
2020-07-22 13:21:51 +02:00
( DWORD ) ( ( wcslen ( PoolDeviceTypeName ) + 1 ) * sizeof ( WCHAR ) ) ) )
2020-07-21 16:38:00 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to set adapter %u description " , DevInfoData . DevInst ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
}
/* DIF_INSTALLDEVICE returns almost immediately, while the device installation continues in the background. It might
* take a while , before all registry keys and values are populated . */
2020-11-03 12:29:34 +01:00
WCHAR * DummyStr = RegistryQueryStringWait ( NetDevRegKey , L " NetCfgInstanceId " , WAIT_FOR_REGISTRY_TIMEOUT ) ;
if ( ! DummyStr )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( NetDevRegKey , RegPath ) ;
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %.*s \\ NetCfgInstanceId " , MAX_REG_PATH , RegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-11-04 12:55:25 +01:00
Free ( DummyStr ) ;
2020-07-21 16:38:00 +02:00
DWORD DummyDWORD ;
2020-11-03 12:29:34 +01:00
if ( ! RegistryQueryDWORDWait ( NetDevRegKey , L " NetLuidIndex " , WAIT_FOR_REGISTRY_TIMEOUT , & DummyDWORD ) )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( NetDevRegKey , RegPath ) ;
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %.*s \\ NetLuidIndex " , MAX_REG_PATH , RegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-11-03 12:29:34 +01:00
if ( ! RegistryQueryDWORDWait ( NetDevRegKey , L " *IfType " , WAIT_FOR_REGISTRY_TIMEOUT , & DummyDWORD ) )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR RegPath [ MAX_REG_PATH ] ;
LoggerGetRegistryKeyPath ( NetDevRegKey , RegPath ) ;
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %.*s \\ *IfType " , MAX_REG_PATH , RegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 16:38:00 +02:00
2020-11-03 12:29:34 +01:00
Adapter = CreateAdapterData ( Pool , DevInfo , & DevInfoData ) ;
if ( ! Adapter )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to create adapter %u data " , DevInfoData . DevInst ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 16:38:00 +02:00
HKEY TcpipAdapterRegKey ;
2020-07-24 08:10:00 +02:00
WCHAR TcpipAdapterRegPath [ MAX_REG_PATH ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetTcpipAdapterRegPath ( Adapter , TcpipAdapterRegPath ) )
{
LastError = GetLastError ( ) ;
2020-10-30 06:51:24 +01:00
goto cleanupAdapter ;
2020-11-03 12:29:34 +01:00
}
TcpipAdapterRegKey = RegistryOpenKeyWait (
HKEY_LOCAL_MACHINE , TcpipAdapterRegPath , KEY_QUERY_VALUE | KEY_NOTIFY , WAIT_FOR_REGISTRY_TIMEOUT ) ;
if ( ! TcpipAdapterRegKey )
{
2021-02-02 13:12:45 +01:00
LastError = LOG (
WINTUN_LOG_ERR , L " Failed to open adapter-specific TCP/IP interface registry key %s " , TcpipAdapterRegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-10-13 19:40:52 +02:00
}
2020-11-03 12:29:34 +01:00
DummyStr = RegistryQueryStringWait ( TcpipAdapterRegKey , L " IpConfig " , WAIT_FOR_REGISTRY_TIMEOUT ) ;
if ( ! DummyStr )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to get %s \\ IpConfig " , TcpipAdapterRegPath ) ;
2020-07-21 16:38:00 +02:00
goto cleanupTcpipAdapterRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-11-04 12:55:25 +01:00
Free ( DummyStr ) ;
2020-07-21 16:38:00 +02:00
2020-07-24 08:10:00 +02:00
WCHAR TcpipInterfaceRegPath [ MAX_REG_PATH ] ;
2020-11-03 12:29:34 +01:00
if ( ! GetTcpipInterfaceRegPath ( Adapter , TcpipInterfaceRegPath ) )
2020-10-13 19:40:52 +02:00
{
2020-11-03 12:29:34 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to determine interface-specific TCP/IP network registry key path " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupTcpipAdapterRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-11-17 15:30:00 +01:00
for ( int Tries = 0 ; Tries < 300 ; + + Tries )
2020-10-13 19:40:52 +02:00
{
2020-11-17 15:30:00 +01:00
HKEY TcpipInterfaceRegKey = RegistryOpenKeyWait (
HKEY_LOCAL_MACHINE , TcpipInterfaceRegPath , KEY_QUERY_VALUE | KEY_SET_VALUE , WAIT_FOR_REGISTRY_TIMEOUT ) ;
if ( ! TcpipInterfaceRegKey )
{
2021-02-02 13:12:45 +01:00
LastError =
LOG ( WINTUN_LOG_ERR ,
L " Failed to open interface-specific TCP/IP network registry key %s " ,
TcpipInterfaceRegPath ) ;
2020-11-17 15:30:00 +01:00
goto cleanupTcpipAdapterRegKey ;
}
2020-07-21 16:38:00 +02:00
2020-11-17 15:30:00 +01:00
static const DWORD EnableDeadGWDetect = 0 ;
LastError = RegSetKeyValueW (
TcpipInterfaceRegKey ,
NULL ,
L " EnableDeadGWDetect " ,
REG_DWORD ,
& EnableDeadGWDetect ,
sizeof ( EnableDeadGWDetect ) ) ;
RegCloseKey ( TcpipInterfaceRegKey ) ;
if ( LastError = = ERROR_SUCCESS )
break ;
2020-11-17 16:27:11 +01:00
if ( LastError ! = ERROR_TRANSACTION_NOT_ACTIVE )
2020-11-17 15:30:00 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_ERROR ( LastError , L " Failed to set %s \\ EnableDeadGWDetect " , TcpipInterfaceRegPath ) ;
2020-11-17 15:30:00 +01:00
goto cleanupTcpipAdapterRegKey ;
}
Sleep ( 10 ) ;
2020-11-01 03:19:21 +01:00
}
2020-07-21 16:38:00 +02:00
2020-11-03 12:29:34 +01:00
if ( ! WintunSetAdapterName ( Adapter , Name ) )
2020-11-01 03:19:21 +01:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to set adapter name %s " , Name ) ;
2020-11-17 15:30:00 +01:00
goto cleanupTcpipAdapterRegKey ;
2020-11-01 03:19:21 +01:00
}
2020-11-01 03:47:19 +01:00
DEVPROPTYPE PropertyType ;
for ( int Tries = 0 ; Tries < 1000 ; + + Tries )
{
NTSTATUS ProblemStatus ;
if ( SetupDiGetDevicePropertyW (
DevInfo ,
& DevInfoData ,
& DEVPKEY_Device_ProblemStatus ,
& PropertyType ,
( PBYTE ) & ProblemStatus ,
sizeof ( ProblemStatus ) ,
NULL ,
0 ) & &
PropertyType = = DEVPROP_TYPE_NTSTATUS )
2020-11-01 03:19:21 +01:00
{
2020-11-03 12:29:34 +01:00
LastError = RtlNtStatusToDosError ( ProblemStatus ) ;
_Analysis_assume_ ( LastError ! = ERROR_SUCCESS ) ;
2020-11-01 03:47:19 +01:00
if ( ProblemStatus ! = STATUS_PNP_DEVICE_CONFIGURATION_PENDING | | Tries = = 999 )
2020-11-01 03:19:21 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_ERROR ( LastError , L " Failed to setup adapter (status: 0x%x) " , ProblemStatus ) ;
2020-11-17 15:30:00 +01:00
goto cleanupTcpipAdapterRegKey ;
2020-11-01 03:19:21 +01:00
}
2020-11-01 03:47:19 +01:00
Sleep ( 10 ) ;
2020-11-01 03:19:21 +01:00
}
2020-11-01 03:47:19 +01:00
else
break ;
2020-11-01 03:19:21 +01:00
}
2021-02-03 22:32:58 +01:00
if ( ! EnsureDeviceObject ( Adapter - > DevInstanceID ) )
{
LastError = LOG_LAST_ERROR ( L " Device object file did not appear " ) ;
goto cleanupTcpipAdapterRegKey ;
}
2020-11-03 12:29:34 +01:00
LastError = ERROR_SUCCESS ;
2020-11-01 03:19:21 +01:00
2020-07-21 16:38:00 +02:00
cleanupTcpipAdapterRegKey :
RegCloseKey ( TcpipAdapterRegKey ) ;
cleanupAdapter :
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_SUCCESS )
{
2020-11-04 12:55:25 +01:00
Free ( Adapter ) ;
2020-11-03 12:29:34 +01:00
Adapter = NULL ;
}
2020-07-21 16:38:00 +02:00
cleanupNetDevRegKey :
RegCloseKey ( NetDevRegKey ) ;
cleanupDevice :
2020-11-03 12:29:34 +01:00
if ( LastError ! = ERROR_SUCCESS )
2020-07-21 16:38:00 +02:00
{
2020-07-21 18:19:15 +02:00
/* The adapter failed to install, or the adapter ID was unobtainable. Clean-up. */
2020-07-21 16:38:00 +02:00
SP_REMOVEDEVICE_PARAMS RemoveDeviceParams = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_REMOVE } ,
. Scope = DI_REMOVEDEVICE_GLOBAL } ;
if ( SetupDiSetClassInstallParamsW (
DevInfo , & DevInfoData , & RemoveDeviceParams . ClassInstallHeader , sizeof ( RemoveDeviceParams ) ) & &
SetupDiCallClassInstaller ( DIF_REMOVE , DevInfo , & DevInfoData ) )
* RebootRequired = * RebootRequired | | CheckReboot ( DevInfo , & DevInfoData ) ;
}
2020-11-02 16:28:51 +01:00
NamespaceReleaseMutex ( Mutex ) ;
2020-07-21 16:38:00 +02:00
cleanupDriverInfoList :
SetupDiDestroyDriverInfoList ( DevInfo , & DevInfoData , SPDIT_COMPATDRIVER ) ;
2020-07-07 15:42:39 +02:00
cleanupDevInfo :
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( Adapter , LastError ) ;
2020-11-01 01:22:32 +01:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = NULL )
WINTUN_ADAPTER * GetAdapter ( _In_z_ const WCHAR * Pool , _In_ const GUID * CfgInstanceID )
2020-10-19 22:23:09 +02:00
{
2020-11-02 12:07:05 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
2020-10-19 22:23:09 +02:00
if ( ! Mutex )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to take %s pool mutex " , Pool ) ;
2020-11-03 12:29:34 +01:00
return NULL ;
}
DWORD LastError ;
WINTUN_ADAPTER * Adapter = NULL ;
2020-10-19 22:23:09 +02:00
HDEVINFO DevInfo ;
SP_DEVINFO_DATA DevInfoData ;
2020-11-03 12:29:34 +01:00
if ( ! GetDevInfoData ( CfgInstanceID , & DevInfo , & DevInfoData ) )
2020-10-19 22:23:09 +02:00
{
2021-02-02 13:12:45 +01:00
WCHAR Guid [ MAX_GUID_STRING_LEN ] ;
LastError =
LOG ( WINTUN_LOG_ERR ,
L " Failed to locate adapter %.*s " ,
StringFromGUID2 ( CfgInstanceID , Guid , _countof ( Guid ) ) ,
Guid ) ;
2020-10-19 22:23:09 +02:00
goto cleanupMutex ;
}
2020-11-03 12:29:34 +01:00
Adapter = CreateAdapterData ( Pool , DevInfo , & DevInfoData ) ;
2021-02-02 13:12:45 +01:00
LastError = Adapter ? ERROR_SUCCESS : LOG ( WINTUN_LOG_ERR , L " Failed to create adapter %u data " , DevInfoData . DevInst ) ;
2020-10-19 22:23:09 +02:00
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupMutex :
NamespaceReleaseMutex ( Mutex ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( Adapter , LastError ) ;
2020-10-19 22:23:09 +02:00
}
2020-11-04 08:11:44 +01:00
# include "rundll32_i.c"
2020-10-16 13:30:51 +02:00
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = NULL ) WINTUN_ADAPTER * WINAPI WintunCreateAdapter (
2020-10-31 18:13:36 +01:00
_In_z_ const WCHAR * Pool ,
_In_z_ const WCHAR * Name ,
2020-10-16 13:30:51 +02:00
_In_opt_ const GUID * RequestedGUID ,
2020-10-31 15:40:01 +01:00
_Out_opt_ BOOL * RebootRequired )
2020-10-16 13:30:51 +02:00
{
2020-10-30 12:25:24 +01:00
if ( ! ElevateToSystem ( ) )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) ;
return NULL ;
}
2020-10-31 15:40:01 +01:00
BOOL DummyRebootRequired ;
if ( ! RebootRequired )
RebootRequired = & DummyRebootRequired ;
2020-10-31 15:33:54 +01:00
* RebootRequired = FALSE ;
2020-11-03 12:29:34 +01:00
DWORD LastError ;
WINTUN_ADAPTER * Adapter ;
2020-11-03 02:09:00 +01:00
if ( MAYBE_WOW64 & & NativeMachine ! = IMAGE_FILE_PROCESS )
2020-11-03 12:29:34 +01:00
{
Adapter = CreateAdapterViaRundll32 ( Pool , Name , RequestedGUID , RebootRequired ) ;
LastError = Adapter ? ERROR_SUCCESS : GetLastError ( ) ;
goto cleanupToken ;
}
Adapter = CreateAdapter ( Pool , Name , RequestedGUID , RebootRequired ) ;
LastError = Adapter ? ERROR_SUCCESS : GetLastError ( ) ;
cleanupToken :
2020-10-30 12:25:24 +01:00
RevertToSelf ( ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( Adapter , LastError ) ;
2020-10-15 15:54:37 +02:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = FALSE ) BOOL WINAPI WintunDeleteAdapter (
_In_ const WINTUN_ADAPTER * Adapter ,
_In_ BOOL ForceCloseSessions ,
_Out_opt_ BOOL * RebootRequired )
2020-07-21 16:38:00 +02:00
{
2020-10-30 12:25:24 +01:00
if ( ! ElevateToSystem ( ) )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) ;
return FALSE ;
}
2020-10-31 15:40:01 +01:00
BOOL DummyRebootRequired ;
if ( ! RebootRequired )
RebootRequired = & DummyRebootRequired ;
2020-10-31 15:33:54 +01:00
* RebootRequired = FALSE ;
2020-11-03 12:29:34 +01:00
DWORD LastError ;
2020-11-03 02:09:00 +01:00
if ( MAYBE_WOW64 & & NativeMachine ! = IMAGE_FILE_PROCESS )
2020-10-30 12:25:24 +01:00
{
2020-11-03 12:29:34 +01:00
LastError =
DeleteAdapterViaRundll32 ( Adapter , ForceCloseSessions , RebootRequired ) ? ERROR_SUCCESS : GetLastError ( ) ;
goto cleanupToken ;
2020-10-30 12:25:24 +01:00
}
2020-10-16 13:30:51 +02:00
2020-11-09 13:10:16 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Adapter - > Pool ) ;
if ( ! Mutex )
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to take %s pool mutex " , Adapter - > Pool ) ;
2020-11-09 13:10:16 +01:00
goto cleanupToken ;
}
2020-07-21 16:38:00 +02:00
HDEVINFO DevInfo ;
SP_DEVINFO_DATA DevInfoData ;
2020-11-03 12:29:34 +01:00
if ( ! GetDevInfoData ( & Adapter - > CfgInstanceID , & DevInfo , & DevInfoData ) )
2020-10-30 12:25:24 +01:00
{
2020-11-03 12:29:34 +01:00
if ( ( LastError = GetLastError ( ) ) = = ERROR_FILE_NOT_FOUND )
LastError = ERROR_SUCCESS ;
else
2021-02-02 13:12:45 +01:00
{
WCHAR Guid [ MAX_GUID_STRING_LEN ] ;
LOG ( WINTUN_LOG_ERR ,
L " Failed to get adapter %.*s info data " ,
StringFromGUID2 ( & Adapter - > CfgInstanceID , Guid , _countof ( Guid ) ) ,
Guid ) ;
}
2020-11-09 13:10:16 +01:00
goto cleanupMutex ;
2020-10-13 19:40:52 +02:00
}
2020-10-30 14:21:13 +01:00
2020-11-03 12:29:34 +01:00
if ( ForceCloseSessions & & ! ForceCloseWintunAdapterHandle ( DevInfo , & DevInfoData ) )
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to force close adapter %u handles " , DevInfoData . DevInst ) ;
2020-10-30 14:21:13 +01:00
2020-10-13 19:40:52 +02:00
SetQuietInstall ( DevInfo , & DevInfoData ) ;
2020-11-03 12:29:34 +01:00
SP_REMOVEDEVICE_PARAMS Params = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_REMOVE } ,
. Scope = DI_REMOVEDEVICE_GLOBAL } ;
2020-11-09 13:02:31 +01:00
if ( ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DevInfoData , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_REMOVE , DevInfo , & DevInfoData ) ) & &
GetLastError ( ) ! = ERROR_NO_SUCH_DEVINST )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to remove adapter %u " , DevInfoData . DevInst ) ;
2020-11-03 12:29:34 +01:00
goto cleanupDevInfo ;
}
LastError = ERROR_SUCCESS ;
cleanupDevInfo :
* RebootRequired = * RebootRequired | | CheckReboot ( DevInfo , & DevInfoData ) ;
2020-07-21 16:38:00 +02:00
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
2020-11-09 13:10:16 +01:00
cleanupMutex :
NamespaceReleaseMutex ( Mutex ) ;
2020-10-30 12:25:24 +01:00
cleanupToken :
RevertToSelf ( ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-07-21 16:38:00 +02:00
}
2020-11-03 12:29:34 +01:00
static _Return_type_success_ ( return ! = FALSE ) BOOL
DeleteAllOurAdapters ( _In_ const WCHAR Pool [ WINTUN_MAX_POOL ] , _Inout_ BOOL * RebootRequired )
2020-11-02 16:28:51 +01:00
{
2020-11-03 12:27:42 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
if ( ! Mutex )
2020-11-03 12:29:34 +01:00
{
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to take %s pool mutex " , Pool ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
DWORD LastError = ERROR_SUCCESS ;
2020-11-02 16:28:51 +01:00
HDEVINFO DevInfo = SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
if ( DevInfo = = INVALID_HANDLE_VALUE )
2020-11-03 12:27:42 +01:00
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
goto cleanupMutex ;
2020-11-03 12:27:42 +01:00
}
2020-11-02 16:28:51 +01:00
SP_REMOVEDEVICE_PARAMS Params = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_REMOVE } ,
. Scope = DI_REMOVEDEVICE_GLOBAL } ;
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
{
SP_DEVINFO_DATA DevInfoData = { . cbSize = sizeof ( SP_DEVINFO_DATA ) } ;
if ( ! SetupDiEnumDeviceInfo ( DevInfo , EnumIndex , & DevInfoData ) )
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
break ;
continue ;
}
2020-11-03 12:29:34 +01:00
if ( ! IsOurAdapter ( DevInfo , & DevInfoData ) | | ! IsPoolMember ( Pool , DevInfo , & DevInfoData ) )
2020-11-03 12:27:42 +01:00
continue ;
2020-11-02 16:28:51 +01:00
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO , L " Force closing all adapter %u open handles " , DevInfoData . DevInst ) ;
2020-11-03 12:29:34 +01:00
if ( ! ForceCloseWintunAdapterHandle ( DevInfo , & DevInfoData ) )
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to force close adapter %u handles " , DevInfoData . DevInst ) ;
2020-11-02 16:28:51 +01:00
2021-02-02 13:12:45 +01:00
LOG ( WINTUN_LOG_INFO , L " Removing adapter %u " , DevInfoData . DevInst ) ;
2020-11-09 13:02:31 +01:00
if ( ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DevInfoData , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_REMOVE , DevInfo , & DevInfoData ) ) & &
GetLastError ( ) ! = ERROR_NO_SUCH_DEVINST )
2020-11-02 16:28:51 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Failed to remove adapter %u " , DevInfoData . DevInst ) ;
2020-11-03 12:29:34 +01:00
LastError = LastError ! = ERROR_SUCCESS ? LastError : GetLastError ( ) ;
2020-11-02 16:28:51 +01:00
}
2020-11-03 12:29:34 +01:00
* RebootRequired = * RebootRequired | | CheckReboot ( DevInfo , & DevInfoData ) ;
2020-11-02 16:28:51 +01:00
}
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
2020-11-03 12:29:34 +01:00
cleanupMutex :
2020-11-03 12:27:42 +01:00
NamespaceReleaseMutex ( Mutex ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-11-02 16:28:51 +01:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = FALSE ) BOOL WINAPI
WintunDeletePoolDriver ( _In_z_ const WCHAR * Pool , _Out_opt_ BOOL * RebootRequired )
2020-11-02 16:28:51 +01:00
{
if ( ! ElevateToSystem ( ) )
2020-11-03 12:29:34 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) ;
return FALSE ;
}
2020-11-02 16:28:51 +01:00
2020-11-03 12:27:42 +01:00
BOOL DummyRebootRequired ;
if ( ! RebootRequired )
RebootRequired = & DummyRebootRequired ;
* RebootRequired = FALSE ;
2020-11-02 23:55:59 +01:00
2020-11-03 12:29:34 +01:00
DWORD LastError = ERROR_SUCCESS ;
2020-11-03 02:09:00 +01:00
if ( MAYBE_WOW64 & & NativeMachine ! = IMAGE_FILE_PROCESS )
2020-11-02 16:28:51 +01:00
{
2020-11-03 12:29:34 +01:00
LastError = DeletePoolDriverViaRundll32 ( Pool , RebootRequired ) ? ERROR_SUCCESS : GetLastError ( ) ;
goto cleanupToken ;
2020-11-02 16:28:51 +01:00
}
2020-11-03 12:29:34 +01:00
if ( ! DeleteAllOurAdapters ( Pool , RebootRequired ) )
{
LastError = GetLastError ( ) ;
2020-11-03 12:27:42 +01:00
goto cleanupToken ;
2020-11-03 12:29:34 +01:00
}
2020-11-03 12:27:42 +01:00
2020-11-02 16:28:51 +01:00
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex ( ) ;
if ( ! DriverInstallationLock )
{
2020-11-03 12:29:34 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to take driver installation mutex " ) ;
2020-11-02 16:28:51 +01:00
goto cleanupToken ;
}
HDEVINFO DeviceInfoSet = SetupDiGetClassDevsW ( & GUID_DEVCLASS_NET , NULL , NULL , 0 ) ;
if ( ! DeviceInfoSet )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get adapter information " ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDriverInstallationLock ;
}
if ( ! SetupDiBuildDriverInfoList ( DeviceInfoSet , NULL , SPDIT_CLASSDRIVER ) )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed building driver info list " ) ;
2020-11-02 16:28:51 +01:00
goto cleanupDeviceInfoSet ;
}
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
{
SP_DRVINFO_DATA_W DriverInfo = { . cbSize = sizeof ( DriverInfo ) } ;
if ( ! SetupDiEnumDriverInfoW ( DeviceInfoSet , NULL , SPDIT_CLASSDRIVER , EnumIndex , & DriverInfo ) )
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
break ;
continue ;
}
2020-11-03 12:29:34 +01:00
SP_DRVINFO_DETAIL_DATA_W * DriverDetail = GetAdapterDrvInfoDetail ( DeviceInfoSet , NULL , & DriverInfo ) ;
if ( ! DriverDetail )
2020-11-02 16:28:51 +01:00
continue ;
if ( ! _wcsicmp ( DriverDetail - > HardwareID , WINTUN_HWID ) )
{
2021-02-02 13:12:45 +01:00
LPCWSTR Path = PathFindFileNameW ( DriverDetail - > InfFileName ) ;
LOG ( WINTUN_LOG_INFO , L " Removing driver %s " , Path ) ;
if ( ! SetupUninstallOEMInfW ( Path , 0 , NULL ) )
2020-11-02 16:28:51 +01:00
{
2021-02-02 13:12:45 +01:00
LOG_LAST_ERROR ( L " Unable to remove driver %s " , Path ) ;
2020-11-03 12:29:34 +01:00
LastError = LastError ! = ERROR_SUCCESS ? LastError : GetLastError ( ) ;
2020-11-02 16:28:51 +01:00
}
}
2020-11-04 12:55:25 +01:00
Free ( DriverDetail ) ;
2020-11-02 16:28:51 +01:00
}
SetupDiDestroyDriverInfoList ( DeviceInfoSet , NULL , SPDIT_CLASSDRIVER ) ;
cleanupDeviceInfoSet :
SetupDiDestroyDeviceInfoList ( DeviceInfoSet ) ;
cleanupDriverInstallationLock :
NamespaceReleaseMutex ( DriverInstallationLock ) ;
cleanupToken :
RevertToSelf ( ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-11-02 16:28:51 +01:00
}
2020-11-03 12:29:34 +01:00
_Return_type_success_ ( return ! = FALSE ) BOOL WINAPI
2020-11-04 15:45:27 +01:00
WintunEnumAdapters ( _In_z_ const WCHAR * Pool , _In_ WINTUN_ENUM_CALLBACK Func , _In_ LPARAM Param )
2020-07-21 16:38:00 +02:00
{
2021-03-08 13:48:29 +01:00
if ( ! ElevateToSystem ( ) )
2020-11-03 12:29:34 +01:00
{
2021-03-08 13:48:29 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) ;
2020-11-03 12:29:34 +01:00
return FALSE ;
}
DWORD LastError = ERROR_SUCCESS ;
2021-03-08 13:48:29 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
if ( ! Mutex )
{
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to take %s pool mutex " , Pool ) ;
goto cleanupToken ;
}
2020-10-13 19:40:52 +02:00
HDEVINFO DevInfo = SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
2020-07-21 16:38:00 +02:00
if ( DevInfo = = INVALID_HANDLE_VALUE )
{
2020-11-03 12:29:34 +01:00
LastError = LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupMutex ;
}
2020-10-15 11:32:06 +02:00
BOOL Continue = TRUE ;
for ( DWORD EnumIndex = 0 ; Continue ; + + EnumIndex )
2020-07-21 16:38:00 +02:00
{
SP_DEVINFO_DATA DevInfoData = { . cbSize = sizeof ( SP_DEVINFO_DATA ) } ;
2020-10-13 19:40:52 +02:00
if ( ! SetupDiEnumDeviceInfo ( DevInfo , EnumIndex , & DevInfoData ) )
2020-07-21 16:38:00 +02:00
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
break ;
continue ;
}
2020-11-03 12:29:34 +01:00
if ( ! IsOurAdapter ( DevInfo , & DevInfoData ) | | ! IsPoolMember ( Pool , DevInfo , & DevInfoData ) )
2020-07-21 16:38:00 +02:00
continue ;
2020-11-03 12:29:34 +01:00
WINTUN_ADAPTER * Adapter = CreateAdapterData ( Pool , DevInfo , & DevInfoData ) ;
if ( ! Adapter )
2020-10-13 19:40:52 +02:00
{
2021-02-02 13:12:45 +01:00
LastError = LOG ( WINTUN_LOG_ERR , L " Failed to create adapter %u data " , DevInfoData . DevInst ) ;
2020-07-21 16:38:00 +02:00
break ;
2020-10-13 19:40:52 +02:00
}
2020-10-15 11:32:06 +02:00
Continue = Func ( Adapter , Param ) ;
2020-11-04 12:55:25 +01:00
Free ( Adapter ) ;
2020-07-21 16:38:00 +02:00
}
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupMutex :
2020-10-15 11:32:06 +02:00
NamespaceReleaseMutex ( Mutex ) ;
2021-03-08 13:48:29 +01:00
cleanupToken :
RevertToSelf ( ) ;
2020-11-03 12:29:34 +01:00
return RET_ERROR ( TRUE , LastError ) ;
2020-07-21 16:38:00 +02:00
}