2020-07-07 15:42:39 +02:00
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright ( C ) 2018 - 2020 WireGuard LLC . All Rights Reserved .
*/
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"
# include "ntldr.h"
# include "registry.h"
# include "resource.h"
# 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 <newdev.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
2020-10-16 13:30:51 +02:00
static USHORT NativeMachine = IMAGE_FILE_PROCESS ;
2020-07-28 12:30:12 +02:00
2020-10-15 11:32:06 +02:00
WINTUN_STATUS
AdapterGetDrvInfoDetail (
_In_ HDEVINFO DevInfo ,
_In_opt_ SP_DEVINFO_DATA * DevInfoData ,
_In_ SP_DRVINFO_DATA_W * DrvInfoData ,
_Out_ SP_DRVINFO_DETAIL_DATA_W * * DrvInfoDetailData )
{
DWORD Size = sizeof ( SP_DRVINFO_DETAIL_DATA_W ) + 0x100 ;
for ( ; ; )
{
2020-10-30 13:08:57 +01:00
SP_DRVINFO_DETAIL_DATA_W * p = HeapAlloc ( ModuleHeap , 0 , Size ) ;
if ( ! p )
2020-10-15 12:38:05 +02:00
return LOG ( WINTUN_LOG_ERR , L " Out of memory " ) , ERROR_OUTOFMEMORY ;
2020-10-30 13:08:57 +01:00
p - > cbSize = sizeof ( SP_DRVINFO_DETAIL_DATA_W ) ;
if ( SetupDiGetDriverInfoDetailW ( DevInfo , DevInfoData , DrvInfoData , p , Size , & Size ) )
{
* DrvInfoDetailData = p ;
2020-10-15 11:32:06 +02:00
return ERROR_SUCCESS ;
2020-10-30 13:08:57 +01:00
}
2020-10-15 12:38:05 +02:00
DWORD Result = GetLastError ( ) ;
2020-10-30 13:08:57 +01:00
HeapFree ( ModuleHeap , 0 , p ) ;
2020-10-15 11:32:06 +02:00
if ( Result ! = ERROR_INSUFFICIENT_BUFFER )
2020-10-15 12:38:05 +02:00
return LOG_ERROR ( L " Failed " , Result ) ;
2020-10-15 11:32:06 +02:00
}
}
2020-07-21 16:43:34 +02:00
static WINTUN_STATUS
2020-07-21 11:11:14 +02:00
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 ,
_Out_ void * * Buf ,
_Inout_ DWORD * BufLen )
2020-07-07 15:42:39 +02:00
{
for ( ; ; )
{
2020-10-30 13:08:57 +01:00
BYTE * p = HeapAlloc ( ModuleHeap , 0 , * BufLen ) ;
if ( ! p )
2020-10-15 12:38:05 +02:00
return LOG ( WINTUN_LOG_ERR , L " Out of memory " ) , ERROR_OUTOFMEMORY ;
2020-10-30 13:08:57 +01:00
if ( SetupDiGetDeviceRegistryPropertyW ( DevInfo , DevInfoData , Property , ValueType , p , * BufLen , BufLen ) )
{
* Buf = p ;
2020-07-24 08:29:33 +02:00
return ERROR_SUCCESS ;
2020-10-30 13:08:57 +01:00
}
2020-07-24 08:29:33 +02:00
DWORD Result = GetLastError ( ) ;
2020-10-30 13:08:57 +01:00
HeapFree ( ModuleHeap , 0 , p ) ;
2020-07-24 08:29:33 +02:00
if ( Result ! = ERROR_INSUFFICIENT_BUFFER )
2020-10-14 13:04:29 +02:00
return LOG_ERROR ( L " Querying property failed " , Result ) ;
2020-07-07 15:42:39 +02:00
}
}
2020-07-21 16:43:34 +02:00
static WINTUN_STATUS
2020-07-21 11:11:14 +02:00
GetDeviceRegistryString (
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_ WCHAR * * Buf )
2020-07-07 15:42:39 +02:00
{
2020-07-24 08:29:33 +02:00
DWORD Result , ValueType , Size = 256 * sizeof ( WCHAR ) ;
Result = GetDeviceRegistryProperty ( DevInfo , DevInfoData , Property , & ValueType , Buf , & Size ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
return Result ;
switch ( ValueType )
{
case REG_SZ :
case REG_EXPAND_SZ :
2020-07-21 16:38:00 +02:00
case REG_MULTI_SZ :
2020-07-24 08:29:33 +02:00
Result = RegistryGetString ( Buf , Size / sizeof ( WCHAR ) , ValueType ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , * Buf ) ;
2020-07-07 15:42:39 +02:00
return Result ;
default :
2020-10-14 13:04:29 +02:00
LOG ( WINTUN_LOG_ERR , L " Property is not a string " ) ;
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , * Buf ) ;
2020-07-07 15:42:39 +02:00
return ERROR_INVALID_DATATYPE ;
}
}
2020-07-21 16:43:34 +02:00
static WINTUN_STATUS
2020-07-21 11:11:14 +02:00
GetDeviceRegistryMultiString (
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_ WCHAR * * Buf )
2020-07-07 15:42:39 +02:00
{
2020-07-24 08:29:33 +02:00
DWORD Result , ValueType , Size = 256 * sizeof ( WCHAR ) ;
Result = GetDeviceRegistryProperty ( DevInfo , DevInfoData , Property , & ValueType , Buf , & Size ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
return Result ;
switch ( ValueType )
{
case REG_SZ :
case REG_EXPAND_SZ :
case REG_MULTI_SZ :
2020-07-24 08:29:33 +02:00
Result = RegistryGetMultiString ( Buf , Size / sizeof ( WCHAR ) , ValueType ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , * Buf ) ;
2020-07-07 15:42:39 +02:00
return Result ;
default :
2020-10-14 13:04:29 +02:00
LOG ( WINTUN_LOG_ERR , L " Property is not a string " ) ;
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , * Buf ) ;
2020-07-07 15:42:39 +02:00
return ERROR_INVALID_DATATYPE ;
}
}
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-10-15 11:32:06 +02:00
static WINTUN_STATUS
2020-10-16 15:51:50 +02:00
IsOurAdapter ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData , _Out_ BOOL * IsOurs )
2020-07-21 18:19:15 +02:00
{
2020-10-15 11:32:06 +02:00
WCHAR * Hwids ;
DWORD Result = GetDeviceRegistryMultiString ( DevInfo , DevInfoData , SPDRP_HARDWAREID , & Hwids ) ;
if ( Result ! = ERROR_SUCCESS )
2020-11-02 11:52:54 +01:00
return LOG ( WINTUN_LOG_ERR , L " Failed to get hardware ID " ) , Result ;
2020-10-30 09:53:09 +01:00
* IsOurs = IsOurHardwareID ( Hwids ) ;
2020-10-15 11:32:06 +02:00
return ERROR_SUCCESS ;
}
static WINTUN_STATUS
GetDeviceObject ( _In_opt_z_ const WCHAR * InstanceId , _Out_ HANDLE * Handle )
{
ULONG InterfacesLen ;
2020-11-02 00:13:55 +01:00
DWORD Result = CM_MapCrToWin32Err ( CM_Get_Device_Interface_List_SizeW (
& InterfacesLen , ( GUID * ) & GUID_DEVINTERFACE_NET , ( DEVINSTID_W ) InstanceId , CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) , ERROR_GEN_FAILURE ) ;
if ( Result ! = ERROR_SUCCESS )
return LOG_ERROR ( L " Failed to query associated instances size " , Result ) ;
2020-10-24 22:12:47 +02:00
WCHAR * Interfaces = HeapAlloc ( ModuleHeap , 0 , InterfacesLen * sizeof ( WCHAR ) ) ;
2020-10-15 11:32:06 +02:00
if ( ! Interfaces )
2020-10-15 12:38:05 +02:00
return LOG ( WINTUN_LOG_ERR , L " Out of memory " ) , ERROR_OUTOFMEMORY ;
2020-11-02 00:13:55 +01:00
Result = CM_MapCrToWin32Err ( CM_Get_Device_Interface_ListW (
2020-10-15 11:32:06 +02:00
( GUID * ) & GUID_DEVINTERFACE_NET ,
( DEVINSTID_W ) InstanceId ,
Interfaces ,
InterfacesLen ,
2020-11-02 00:13:55 +01:00
CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) , ERROR_GEN_FAILURE ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-15 11:32:06 +02:00
{
2020-11-02 00:13:55 +01:00
LOG_ERROR ( L " Failed to get associated instances " , Result ) ;
2020-10-15 11:32:06 +02:00
goto cleanupBuf ;
}
* Handle = CreateFileW (
Interfaces ,
GENERIC_READ | GENERIC_WRITE ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
NULL ,
OPEN_EXISTING ,
0 ,
NULL ) ;
2020-11-02 11:52:54 +01:00
Result = * Handle ! = INVALID_HANDLE_VALUE ? ERROR_SUCCESS : LOG_LAST_ERROR ( L " Failed to connect to adapter " ) ;
2020-10-15 11:32:06 +02:00
cleanupBuf :
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , Interfaces ) ;
2020-10-15 11:32:06 +02:00
return Result ;
}
# define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
static WINTUN_STATUS
ForceCloseWintunAdapterHandle ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData )
{
DWORD Result = ERROR_SUCCESS ;
DWORD RequiredBytes ;
if ( SetupDiGetDeviceInstanceIdW ( DevInfo , DevInfoData , NULL , 0 , & RequiredBytes ) | |
( Result = GetLastError ( ) ) ! = ERROR_INSUFFICIENT_BUFFER )
2020-11-02 11:52:54 +01:00
return LOG_ERROR ( L " Failed to query instance ID size " , Result ) ;
2020-10-24 22:12:47 +02:00
WCHAR * InstanceId = HeapAlloc ( ModuleHeap , HEAP_ZERO_MEMORY , sizeof ( * InstanceId ) * RequiredBytes ) ;
2020-10-15 11:32:06 +02:00
if ( ! InstanceId )
2020-10-15 12:38:05 +02:00
return LOG ( WINTUN_LOG_ERR , L " Out of memory " ) , ERROR_OUTOFMEMORY ;
2020-10-15 11:32:06 +02:00
if ( ! SetupDiGetDeviceInstanceIdW ( DevInfo , DevInfoData , InstanceId , RequiredBytes , & RequiredBytes ) )
{
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to get instance ID " ) ;
2020-10-15 11:32:06 +02:00
goto out ;
}
HANDLE NdisHandle ;
Result = GetDeviceObject ( InstanceId , & NdisHandle ) ;
if ( Result ! = ERROR_SUCCESS )
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get adapter object " ) ;
2020-10-15 11:32:06 +02:00
goto out ;
}
2020-10-30 14:21:13 +01:00
if ( DeviceIoControl ( NdisHandle , TUN_IOCTL_FORCE_CLOSE_HANDLES , NULL , 0 , NULL , 0 , & RequiredBytes , NULL ) )
{
Result = ERROR_SUCCESS ;
Sleep ( 200 ) ;
}
else if ( GetLastError ( ) = = ERROR_NOTHING_TO_TERMINATE )
Result = ERROR_SUCCESS ;
else
Result = LOG_LAST_ERROR ( L " Failed to perform ioctl " ) ;
2020-10-15 11:32:06 +02:00
CloseHandle ( NdisHandle ) ;
out :
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , InstanceId ) ;
2020-10-15 11:32:06 +02:00
return Result ;
}
WINTUN_STATUS
AdapterDisableAllOurs ( _In_ HDEVINFO DevInfo , _Inout_ SP_DEVINFO_DATA_LIST * * DisabledAdapters )
{
SP_PROPCHANGE_PARAMS Params = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_PROPERTYCHANGE } ,
. StateChange = DICS_DISABLE ,
. Scope = DICS_FLAG_GLOBAL } ;
DWORD Result = ERROR_SUCCESS ;
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex )
{
2020-10-24 22:12:47 +02:00
SP_DEVINFO_DATA_LIST * DeviceNode = HeapAlloc ( ModuleHeap , 0 , sizeof ( SP_DEVINFO_DATA_LIST ) ) ;
2020-10-15 11:32:06 +02:00
if ( ! DeviceNode )
2020-10-15 12:38:05 +02:00
return LOG ( WINTUN_LOG_ERR , L " Out of memory " ) , ERROR_OUTOFMEMORY ;
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-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , DeviceNode ) ;
2020-10-15 11:32:06 +02:00
break ;
}
goto cleanupDeviceInfoData ;
}
2020-10-16 15:51:50 +02:00
BOOL IsOurs ;
if ( IsOurAdapter ( DevInfo , & DeviceNode - > Data , & IsOurs ) ! = ERROR_SUCCESS | | ! IsOurs )
2020-10-15 11:32:06 +02:00
goto cleanupDeviceInfoData ;
ULONG Status , ProblemCode ;
if ( CM_Get_DevNode_Status ( & Status , & ProblemCode , DeviceNode - > Data . DevInst , 0 ) ! = CR_SUCCESS | |
( ( Status & DN_HAS_PROBLEM ) & & ProblemCode = = CM_PROB_DISABLED ) )
goto cleanupDeviceInfoData ;
LOG ( WINTUN_LOG_INFO , L " Force closing all open handles for existing adapter " ) ;
if ( ForceCloseWintunAdapterHandle ( DevInfo , & DeviceNode - > Data ) ! = ERROR_SUCCESS )
LOG ( WINTUN_LOG_WARN , L " Failed to force close adapter handles " ) ;
LOG ( WINTUN_LOG_INFO , L " Disabling existing adapter " ) ;
if ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DeviceNode - > Data , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_PROPERTYCHANGE , DevInfo , & DeviceNode - > Data ) )
{
2020-11-02 11:52:54 +01:00
LOG_LAST_ERROR ( L " Failed to disable existing adapter " ) ;
2020-10-15 11:32:06 +02:00
Result = Result ! = ERROR_SUCCESS ? Result : GetLastError ( ) ;
goto cleanupDeviceInfoData ;
}
DeviceNode - > Next = * DisabledAdapters ;
* DisabledAdapters = DeviceNode ;
continue ;
cleanupDeviceInfoData :
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , & DeviceNode - > Data ) ;
2020-10-15 11:32:06 +02:00
}
return Result ;
}
WINTUN_STATUS
AdapterEnableAll ( _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA_LIST * AdaptersToEnable )
{
SP_PROPCHANGE_PARAMS Params = { . ClassInstallHeader = { . cbSize = sizeof ( SP_CLASSINSTALL_HEADER ) ,
. InstallFunction = DIF_PROPERTYCHANGE } ,
. StateChange = DICS_ENABLE ,
. Scope = DICS_FLAG_GLOBAL } ;
DWORD Result = ERROR_SUCCESS ;
for ( SP_DEVINFO_DATA_LIST * DeviceNode = AdaptersToEnable ; DeviceNode ; DeviceNode = DeviceNode - > Next )
{
LOG ( WINTUN_LOG_INFO , L " Enabling existing adapter " ) ;
if ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DeviceNode - > Data , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_PROPERTYCHANGE , DevInfo , & DeviceNode - > Data ) )
{
2020-11-02 11:52:54 +01:00
LOG_LAST_ERROR ( L " Failed to enable existing adapter " ) ;
2020-10-15 11:32:06 +02:00
Result = Result ! = ERROR_SUCCESS ? Result : GetLastError ( ) ;
}
}
return Result ;
}
WINTUN_STATUS
2020-10-30 06:03:21 +01:00
AdapterDeleteAllOurs ( void )
2020-10-15 11:32:06 +02:00
{
DWORD Result = ERROR_SUCCESS ;
HDEVINFO DevInfo = SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
if ( DevInfo = = INVALID_HANDLE_VALUE )
2020-11-02 11:52:54 +01:00
return LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
2020-10-15 11:32:06 +02: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-10-16 15:51:50 +02:00
BOOL IsOurs ;
if ( IsOurAdapter ( DevInfo , & DevInfoData , & IsOurs ) ! = ERROR_SUCCESS | | ! IsOurs )
2020-10-15 11:32:06 +02:00
continue ;
LOG ( WINTUN_LOG_INFO , L " Force closing all open handles for existing adapter " ) ;
if ( ForceCloseWintunAdapterHandle ( DevInfo , & DevInfoData ) ! = ERROR_SUCCESS )
LOG ( WINTUN_LOG_WARN , L " Failed to force close adapter handles " ) ;
LOG ( WINTUN_LOG_INFO , L " Removing existing adapter " ) ;
if ( ! SetupDiSetClassInstallParamsW ( DevInfo , & DevInfoData , & Params . ClassInstallHeader , sizeof ( Params ) ) | |
! SetupDiCallClassInstaller ( DIF_REMOVE , DevInfo , & DevInfoData ) )
{
2020-11-02 11:52:54 +01:00
LOG_LAST_ERROR ( L " Failed to remove existing adapter " ) ;
2020-10-15 11:32:06 +02:00
Result = Result ! = ERROR_SUCCESS ? Result : GetLastError ( ) ;
}
}
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
return Result ;
}
void
2020-10-30 06:03:21 +01:00
AdapterInit ( void )
2020-10-15 11:32:06 +02:00
{
2020-10-30 09:33:21 +01:00
# ifdef MAYBE_WOW64
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 ;
}
# endif
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
{
2020-10-14 13:04:29 +02:00
LOG_LAST_ERROR ( L " Retrieving device installation parameters failed " ) ;
2020-07-21 18:19:15 +02:00
return FALSE ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 18:19:15 +02:00
return ( DevInstallParams . Flags & ( DI_NEEDREBOOT | DI_NEEDRESTART ) ) ! = 0 ;
}
static WINTUN_STATUS
SetQuietInstall ( _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-14 13:04:29 +02:00
return LOG_LAST_ERROR ( L " Retrieving device installation parameters failed " ) ;
2020-07-21 18:19:15 +02:00
DevInstallParams . Flags | = DI_QUIETINSTALL ;
if ( ! SetupDiSetDeviceInstallParamsW ( DevInfo , DevInfoData , & DevInstallParams ) )
2020-10-14 13:04:29 +02:00
return LOG_LAST_ERROR ( L " Setting device installation parameters failed " ) ;
2020-07-21 18:19:15 +02:00
return ERROR_SUCCESS ;
}
2020-07-21 16:43:34 +02:00
static WINTUN_STATUS
2020-07-21 16:38:00 +02:00
GetNetCfgInstanceId ( _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 )
2020-10-14 13:04:29 +02:00
return LOG_LAST_ERROR ( L " Opening device registry key failed " ) ;
2020-07-21 18:19:15 +02:00
WCHAR * ValueStr ;
2020-10-23 22:04:40 +02:00
DWORD Result = RegistryQueryString ( Key , L " NetCfgInstanceId " , & ValueStr , TRUE ) ;
2020-07-21 16:38:00 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get NetCfgInstanceId " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupKey ;
2020-10-13 19:40:52 +02:00
}
if ( FAILED ( CLSIDFromString ( ValueStr , CfgInstanceID ) ) )
{
2020-10-14 13:04:29 +02:00
LOG ( WINTUN_LOG_ERR , L " NetCfgInstanceId is not a GUID " ) ;
2020-10-13 19:40:52 +02:00
Result = ERROR_INVALID_DATA ;
}
else
Result = ERROR_SUCCESS ;
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , ValueStr ) ;
2020-07-21 16:38:00 +02:00
cleanupKey :
RegCloseKey ( Key ) ;
return Result ;
}
2020-07-21 18:19:15 +02:00
static WINTUN_STATUS
GetDevInfoData ( _In_ const GUID * CfgInstanceID , _Out_ HDEVINFO * DevInfo , _Out_ SP_DEVINFO_DATA * DevInfoData )
{
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-02 11:52:54 +01:00
return LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
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 ;
2020-07-24 08:29:33 +02:00
if ( GetNetCfgInstanceId ( * DevInfo , DevInfoData , & CfgInstanceID2 ) = = ERROR_SUCCESS & &
! memcmp ( CfgInstanceID , & CfgInstanceID2 , sizeof ( GUID ) ) )
return ERROR_SUCCESS ;
2020-07-21 18:19:15 +02:00
}
SetupDiDestroyDeviceInfoList ( * DevInfo ) ;
2020-07-24 08:26:20 +02:00
return ERROR_FILE_NOT_FOUND ;
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-10-30 06:51:24 +01:00
static WINTUN_STATUS
2020-10-31 18:13:36 +01:00
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-10-30 06:51:24 +01:00
return LOG ( WINTUN_LOG_ERR , L " Pool name too long " ) , ERROR_INVALID_PARAMETER ;
return ERROR_SUCCESS ;
2020-07-21 18:19:15 +02:00
}
static WINTUN_STATUS
2020-10-31 18:13:36 +01:00
IsPoolMember ( _In_z_ const WCHAR * Pool , _In_ HDEVINFO DevInfo , _In_ SP_DEVINFO_DATA * DevInfoData , _Out_ BOOL * IsMember )
2020-07-21 18:19:15 +02:00
{
WCHAR * DeviceDesc , * FriendlyName ;
DWORD Result = GetDeviceRegistryString ( DevInfo , DevInfoData , SPDRP_DEVICEDESC , & DeviceDesc ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get adapter description " ) ;
2020-07-21 18:19:15 +02:00
return Result ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 18:19:15 +02:00
Result = GetDeviceRegistryString ( DevInfo , DevInfoData , SPDRP_FRIENDLYNAME , & FriendlyName ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get adapter friendly name " ) ;
2020-07-21 18:19:15 +02:00
goto cleanupDeviceDesc ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 18:19:15 +02:00
WCHAR PoolDeviceTypeName [ MAX_POOL_DEVICE_TYPE ] ;
2020-10-30 06:51:24 +01:00
Result = GetPoolDeviceTypeName ( Pool , PoolDeviceTypeName ) ;
if ( Result ! = ERROR_SUCCESS )
goto cleanupFriendlyName ;
2020-10-30 06:06:06 +01:00
if ( ! _wcsicmp ( FriendlyName , PoolDeviceTypeName ) | | ! _wcsicmp ( DeviceDesc , PoolDeviceTypeName ) )
2020-07-21 18:19:15 +02:00
{
* IsMember = TRUE ;
goto cleanupFriendlyName ;
}
2020-10-30 06:12:42 +01:00
RemoveNumberedSuffix ( FriendlyName ) ;
RemoveNumberedSuffix ( DeviceDesc ) ;
2020-10-30 06:06:06 +01:00
if ( ! _wcsicmp ( FriendlyName , PoolDeviceTypeName ) | | ! _wcsicmp ( DeviceDesc , PoolDeviceTypeName ) )
2020-07-21 18:19:15 +02:00
{
* IsMember = TRUE ;
goto cleanupFriendlyName ;
}
* IsMember = FALSE ;
cleanupFriendlyName :
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , FriendlyName ) ;
2020-07-21 18:19:15 +02:00
cleanupDeviceDesc :
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , DeviceDesc ) ;
2020-07-21 18:19:15 +02:00
return Result ;
}
2020-07-21 16:43:34 +02:00
static WINTUN_STATUS
2020-07-21 16:38:00 +02:00
CreateAdapterData (
2020-10-31 18:13:36 +01:00
_In_z_ const WCHAR * Pool ,
2020-07-07 15:42:39 +02:00
_In_ HDEVINFO DevInfo ,
_In_ SP_DEVINFO_DATA * DevInfoData ,
2020-07-21 16:38:00 +02:00
_Out_ WINTUN_ADAPTER * * Adapter )
2020-07-07 15:42:39 +02:00
{
DWORD Result ;
/* 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-10-14 13:04:29 +02:00
return LOG_LAST_ERROR ( L " Opening device registry key failed " ) ;
2020-07-07 15:42:39 +02:00
2020-10-30 13:08:57 +01:00
WINTUN_ADAPTER * a = HeapAlloc ( ModuleHeap , 0 , sizeof ( WINTUN_ADAPTER ) ) ;
if ( ! a )
2020-07-21 16:38:00 +02:00
{
2020-10-15 12:38:05 +02:00
LOG ( WINTUN_LOG_ERR , L " Out of memory " ) ;
2020-07-21 16:38:00 +02:00
Result = ERROR_OUTOFMEMORY ;
goto cleanupKey ;
}
2020-07-07 15:42:39 +02:00
/* Read the NetCfgInstanceId value and convert to GUID. */
2020-07-21 18:19:15 +02:00
WCHAR * ValueStr ;
2020-10-23 22:04:40 +02:00
Result = RegistryQueryString ( Key , L " NetCfgInstanceId " , & ValueStr , TRUE ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get NetCfgInstanceId " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-10-13 19:40:52 +02:00
}
2020-10-30 13:08:57 +01:00
if ( FAILED ( CLSIDFromString ( ValueStr , & a - > CfgInstanceID ) ) )
2020-07-07 15:42:39 +02:00
{
2020-10-14 13:04:29 +02:00
LOG ( WINTUN_LOG_ERR , L " NetCfgInstanceId is not a GUID " ) ;
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , ValueStr ) ;
2020-07-07 15:42:39 +02:00
Result = ERROR_INVALID_DATA ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-07-07 15:42:39 +02:00
}
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , ValueStr ) ;
2020-07-07 15:42:39 +02:00
/* Read the NetLuidIndex value. */
2020-10-30 13:08:57 +01:00
Result = RegistryQueryDWORD ( Key , L " NetLuidIndex " , & a - > LuidIndex , TRUE ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get NetLuidIndex " ) ;
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
/* Read the NetLuidIndex value. */
2020-10-30 13:08:57 +01:00
Result = RegistryQueryDWORD ( Key , L " *IfType " , & a - > IfType , TRUE ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get *IfType " ) ;
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-10-30 13:08:57 +01:00
if ( ! SetupDiGetDeviceInstanceIdW ( DevInfo , DevInfoData , a - > DevInstanceID , _countof ( a - > DevInstanceID ) , & Size ) )
2020-07-07 15:42:39 +02:00
{
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to get instance ID " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-07-07 15:42:39 +02:00
}
2020-10-30 13:08:57 +01:00
if ( wcsncpy_s ( a - > Pool , _countof ( a - > Pool ) , Pool , _TRUNCATE ) = = STRUNCATE )
2020-10-30 06:51:24 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Pool name too long " ) ;
Result = ERROR_INVALID_PARAMETER ;
goto cleanupAdapter ;
}
2020-10-30 13:08:57 +01:00
* Adapter = a ;
2020-07-07 15:42:39 +02:00
Result = ERROR_SUCCESS ;
2020-07-21 16:38:00 +02:00
cleanupAdapter :
if ( Result ! = ERROR_SUCCESS )
2020-10-30 13:08:57 +01:00
HeapFree ( ModuleHeap , 0 , a ) ;
2020-07-07 15:42:39 +02:00
cleanupKey :
RegCloseKey ( Key ) ;
return Result ;
}
2020-10-30 06:51:24 +01:00
static WINTUN_STATUS
2020-07-24 08:10:00 +02:00
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 )
return LOG ( WINTUN_LOG_ERR , L " Registry path too long " ) , ERROR_INVALID_PARAMETER ;
return ERROR_SUCCESS ;
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-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , Adapter ) ;
2020-07-07 15:42:39 +02:00
}
2020-07-21 16:43:34 +02:00
WINTUN_STATUS WINAPI
2020-10-31 18:13:36 +01:00
WintunGetAdapter ( _In_z_ const WCHAR * Pool , _In_z_ const WCHAR * Name , _Out_ WINTUN_ADAPTER * * Adapter )
2020-07-07 15:42:39 +02:00
{
2020-10-30 12:25:24 +01:00
if ( ! ElevateToSystem ( ) )
return LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) , ERROR_ACCESS_DENIED ;
2020-07-07 15:42:39 +02:00
DWORD Result ;
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
{
Result = ERROR_INVALID_HANDLE ;
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-02 11:52:54 +01:00
Result = 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 ;
2020-07-24 08:29:33 +02:00
if ( GetNetCfgInstanceId ( DevInfo , & DevInfoData , & CfgInstanceID ) ! = ERROR_SUCCESS )
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-10-16 15:51:50 +02:00
BOOL IsOurs ;
Result = IsOurAdapter ( DevInfo , & DevInfoData , & IsOurs ) ;
2020-07-07 15:42:39 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get hardware ID " ) ;
2020-07-07 15:42:39 +02:00
goto cleanupDevInfo ;
}
2020-10-16 15:51:50 +02:00
if ( ! IsOurs )
2020-07-07 15:42:39 +02:00
{
2020-10-15 12:21:55 +02:00
LOG ( WINTUN_LOG_ERR , L " Foreign adapter with the same name exists " ) ;
2020-07-07 15:42:39 +02:00
Result = ERROR_ALREADY_EXISTS ;
goto cleanupDevInfo ;
}
BOOL IsMember ;
Result = IsPoolMember ( Pool , DevInfo , & DevInfoData , & IsMember ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get pool membership " ) ;
2020-07-07 15:42:39 +02:00
goto cleanupDevInfo ;
2020-10-13 19:40:52 +02:00
}
2020-07-07 15:42:39 +02:00
if ( ! IsMember )
{
2020-10-15 12:21:55 +02:00
LOG ( WINTUN_LOG_ERR , L " Wintun adapter with the same name exists in another pool " ) ;
2020-07-07 15:42:39 +02:00
Result = ERROR_ALREADY_EXISTS ;
goto cleanupDevInfo ;
}
2020-07-21 18:19:15 +02:00
Result = CreateAdapterData ( Pool , DevInfo , & DevInfoData , Adapter ) ;
2020-10-13 19:40:52 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-15 12:21:55 +02:00
LOG ( WINTUN_LOG_ERR , L " Failed to create adapter data " ) ;
2020-10-13 19:40:52 +02:00
2020-07-21 16:38:00 +02:00
goto cleanupDevInfo ;
}
Result = ERROR_FILE_NOT_FOUND ;
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-07-21 16:38:00 +02:00
return Result ;
}
2020-07-21 16:43:34 +02:00
WINTUN_STATUS WINAPI
2020-07-21 18:19:15 +02:00
WintunGetAdapterName ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_ADAPTER_NAME ) WCHAR * Name )
2020-07-21 16:38:00 +02:00
{
return NciGetConnectionName ( & Adapter - > CfgInstanceID , Name , MAX_ADAPTER_NAME * sizeof ( WCHAR ) , NULL ) ;
}
2020-07-21 16:43:34 +02:00
static WINTUN_STATUS
2020-07-21 18:19:15 +02:00
ConvertInterfaceAliasToGuid ( _In_z_ const WCHAR * Name , _Out_ GUID * Guid )
2020-07-21 16:38:00 +02:00
{
NET_LUID Luid ;
2020-07-21 18:19:15 +02:00
DWORD Result = ConvertInterfaceAliasToLuid ( Name , & Luid ) ;
2020-07-21 16:38:00 +02:00
if ( Result ! = NO_ERROR )
2020-10-14 13:04:29 +02:00
return LOG_ERROR ( L " Failed convert interface alias name to the locally unique identifier " , Result ) ;
2020-07-21 16:38:00 +02:00
return ConvertInterfaceLuidToGuid ( & Luid , Guid ) ;
}
2020-07-21 16:43:34 +02:00
WINTUN_STATUS WINAPI
2020-10-31 18:13:36 +01:00
WintunSetAdapterName ( _In_ const WINTUN_ADAPTER * Adapter , _In_z_ const WCHAR * Name )
2020-07-21 16:38:00 +02:00
{
DWORD Result ;
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-10-31 18:13:36 +01:00
return LOG ( WINTUN_LOG_ERR , L " Adapter name too long " ) , ERROR_INVALID_PARAMETER ;
2020-07-21 16:38:00 +02:00
for ( int i = 0 ; ; + + i )
{
Result = NciSetConnectionName ( & Adapter - > CfgInstanceID , AvailableName ) ;
if ( Result = = ERROR_DUP_NAME )
2020-07-07 15:42:39 +02:00
{
2020-07-21 16:38:00 +02:00
GUID Guid2 ;
2020-07-21 18:19:15 +02:00
DWORD Result2 = ConvertInterfaceAliasToGuid ( AvailableName , & Guid2 ) ;
2020-07-21 16:38:00 +02:00
if ( Result2 = = ERROR_SUCCESS )
{
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 )
return LOG ( WINTUN_LOG_ERR , L " Adapter name too long " ) , ERROR_INVALID_PARAMETER ;
2020-07-21 16:38:00 +02:00
if ( _wcsnicmp ( Proposal , AvailableName , MAX_ADAPTER_NAME ) = = 0 )
continue ;
Result2 = NciSetConnectionName ( & Guid2 , Proposal ) ;
if ( Result2 = = ERROR_DUP_NAME )
continue ;
if ( Result2 = = ERROR_SUCCESS )
{
Result = NciSetConnectionName ( & Adapter - > CfgInstanceID , AvailableName ) ;
if ( Result = = ERROR_SUCCESS )
break ;
}
break ;
}
}
2020-07-07 15:42:39 +02:00
}
2020-07-21 16:38:00 +02:00
if ( Result = = ERROR_SUCCESS )
break ;
2020-10-30 06:57:56 +01:00
if ( i > = MaxSuffix | | Result ! = ERROR_DUP_NAME )
2020-10-14 13:04:29 +02:00
return LOG_ERROR ( L " Setting adapter name failed " , Result ) ;
2020-10-31 18:13:36 +01:00
if ( _snwprintf_s ( AvailableName , _countof ( AvailableName ) , _TRUNCATE , L " %s %d " , Name , i + 1 ) = = - 1 )
return LOG ( WINTUN_LOG_ERR , L " Adapter name too long " ) , ERROR_INVALID_PARAMETER ;
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-10-30 06:51:24 +01:00
Result = GetDeviceRegPath ( Adapter , DeviceRegPath ) ;
if ( Result ! = ERROR_SUCCESS )
return Result ;
2020-07-21 16:38:00 +02:00
Result = RegOpenKeyExW ( HKEY_LOCAL_MACHINE , DeviceRegPath , 0 , KEY_SET_VALUE , & DeviceRegKey ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-14 13:04:29 +02:00
return LOG_ERROR ( L " Failed to open registry key " , Result ) ;
2020-07-21 16:38:00 +02:00
WCHAR PoolDeviceTypeName [ MAX_POOL_DEVICE_TYPE ] ;
2020-10-30 06:51:24 +01:00
Result = GetPoolDeviceTypeName ( Adapter - > Pool , PoolDeviceTypeName ) ;
if ( Result ! = ERROR_SUCCESS )
goto cleanupDeviceRegKey ;
2020-07-21 16:38:00 +02:00
Result = RegSetKeyValueW (
DeviceRegKey ,
NULL ,
L " FriendlyName " ,
REG_SZ ,
PoolDeviceTypeName ,
( DWORD ) ( ( wcslen ( PoolDeviceTypeName ) + 1 ) * sizeof ( WCHAR ) ) ) ;
2020-10-30 06:51:24 +01:00
cleanupDeviceRegKey :
2020-07-21 16:38:00 +02:00
RegCloseKey ( DeviceRegKey ) ;
return Result ;
}
void WINAPI
WintunGetAdapterGUID ( _In_ const WINTUN_ADAPTER * Adapter , _Out_ GUID * Guid )
{
2020-07-28 12:51:20 +02:00
memcpy ( Guid , & Adapter - > CfgInstanceID , sizeof ( GUID ) ) ;
2020-07-21 16:38:00 +02:00
}
void WINAPI
WintunGetAdapterLUID ( _In_ const WINTUN_ADAPTER * Adapter , _Out_ LUID * Luid )
{
* ( LONGLONG * ) Luid = ( ( ( LONGLONG ) Adapter - > LuidIndex & ( ( 1 < < 24 ) - 1 ) ) < < 24 ) |
( ( ( LONGLONG ) Adapter - > IfType & ( ( 1 < < 16 ) - 1 ) ) < < 48 ) ;
}
2020-07-21 16:43:34 +02:00
WINTUN_STATUS WINAPI
2020-07-21 16:38:00 +02:00
WintunGetAdapterDeviceObject ( _In_ const WINTUN_ADAPTER * Adapter , _Out_ HANDLE * Handle )
{
2020-10-15 11:32:06 +02:00
return GetDeviceObject ( Adapter - > DevInstanceID , Handle ) ;
2020-07-21 16:38:00 +02:00
}
2020-10-15 15:54:37 +02:00
/* We can't use RtlGetVersion, because appcompat's aclayers.dll shims it to report Vista
* when run from legacy contexts . So , we instead use the undocumented RtlGetNtVersionNumbers .
*
* Another way would be reading from the PEB directly :
* ( ( DWORD * ) NtCurrentTeb ( ) - > ProcessEnvironmentBlock ) [ sizeof ( void * ) = = 8 ? 70 : 41 ]
* Or just read from KUSER_SHARED_DATA the same way on 32 - bit and 64 - bit :
* * ( DWORD * ) 0x7FFE026C
*/
extern VOID NTAPI
RtlGetNtVersionNumbers ( _Out_opt_ DWORD * MajorVersion , _Out_opt_ DWORD * MinorVersion , _Out_opt_ DWORD * BuildNumber ) ;
static BOOL
2020-10-30 06:03:21 +01:00
HaveWHQL ( void )
2020-10-15 15:54:37 +02:00
{
2020-10-30 12:25:20 +01:00
# if defined(HAVE_WHQL)
2020-10-15 15:54:37 +02:00
DWORD MajorVersion ;
RtlGetNtVersionNumbers ( & MajorVersion , NULL , NULL ) ;
return MajorVersion > = 10 ;
2020-10-30 08:17:33 +01:00
# else
return FALSE ;
# endif
2020-10-15 15:54:37 +02:00
}
static WINTUN_STATUS
InstallCertificate ( _In_z_ const WCHAR * SignedResource )
{
LOG ( WINTUN_LOG_INFO , L " Trusting code signing certificate " ) ;
2020-10-17 15:12:20 +02:00
const void * LockedResource ;
2020-10-15 15:54:37 +02:00
DWORD SizeResource ;
DWORD Result = ResourceGetAddress ( SignedResource , & LockedResource , & SizeResource ) ;
if ( Result ! = ERROR_SUCCESS )
return LOG ( WINTUN_LOG_ERR , L " Failed to locate resource " ) , Result ;
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 ) )
return LOG_LAST_ERROR ( L " Failed to find certificate " ) ;
HCERTSTORE TrustedStore =
CertOpenStore ( CERT_STORE_PROV_SYSTEM , 0 , 0 , CERT_SYSTEM_STORE_LOCAL_MACHINE , L " TrustedPublisher " ) ;
if ( ! TrustedStore )
{
Result = LOG_LAST_ERROR ( L " Failed to open store " ) ;
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 " ) ;
Result = Result ! = ERROR_SUCCESS ? Result : GetLastError ( ) ;
}
}
CertCloseStore ( TrustedStore , 0 ) ;
cleanupQueriedStore :
CertCloseStore ( QueriedStore , 0 ) ;
return Result ;
}
2020-10-30 09:53:09 +01:00
static BOOL
IsOurDrvInfoDetail ( _In_ const SP_DRVINFO_DETAIL_DATA_W * DrvInfoDetailData )
{
return DrvInfoDetailData - > CompatIDsOffset > 1 & & ! _wcsicmp ( DrvInfoDetailData - > HardwareID , WINTUN_HWID ) | |
DrvInfoDetailData - > CompatIDsLength & &
IsOurHardwareID ( DrvInfoDetailData - > HardwareID + DrvInfoDetailData - > CompatIDsOffset ) ;
}
2020-10-16 15:20:49 +02:00
static BOOL
IsNewer ( _In_ const SP_DRVINFO_DATA_W * DrvInfoData , _In_ const FILETIME * DriverDate , _In_ DWORDLONG DriverVersion )
{
if ( DrvInfoData - > DriverDate . dwHighDateTime > DriverDate - > dwHighDateTime )
return TRUE ;
if ( DrvInfoData - > DriverDate . dwHighDateTime < DriverDate - > dwHighDateTime )
return FALSE ;
if ( DrvInfoData - > DriverDate . dwLowDateTime > DriverDate - > dwLowDateTime )
return TRUE ;
if ( DrvInfoData - > DriverDate . dwLowDateTime < DriverDate - > dwLowDateTime )
return FALSE ;
if ( DrvInfoData - > DriverVersion > DriverVersion )
return TRUE ;
if ( DrvInfoData - > DriverVersion < DriverVersion )
return FALSE ;
return FALSE ;
}
2020-10-30 06:51:24 +01:00
static DWORD
2020-10-16 15:20:49 +02:00
GetTcpipAdapterRegPath ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_REG_PATH ) WCHAR * Path )
{
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 )
return LOG ( WINTUN_LOG_ERR , L " Registry path too long " ) , ERROR_INVALID_PARAMETER ;
return ERROR_SUCCESS ;
2020-10-16 15:20:49 +02:00
}
static WINTUN_STATUS
GetTcpipInterfaceRegPath ( _In_ const WINTUN_ADAPTER * Adapter , _Out_cap_c_ ( MAX_REG_PATH ) WCHAR * Path )
{
DWORD Result ;
HKEY TcpipAdapterRegKey ;
WCHAR TcpipAdapterRegPath [ MAX_REG_PATH ] ;
2020-10-30 06:51:24 +01:00
Result = GetTcpipAdapterRegPath ( Adapter , TcpipAdapterRegPath ) ;
if ( Result ! = ERROR_SUCCESS )
return Result ;
2020-10-16 15:20:49 +02:00
Result = RegOpenKeyExW ( HKEY_LOCAL_MACHINE , TcpipAdapterRegPath , 0 , KEY_QUERY_VALUE , & TcpipAdapterRegKey ) ;
if ( Result ! = ERROR_SUCCESS )
return LOG_ERROR ( L " Failed to open registry key " , Result ) ;
WCHAR * Paths ;
2020-10-23 22:04:40 +02:00
Result = RegistryQueryString ( TcpipAdapterRegKey , L " IpConfig " , & Paths , TRUE ) ;
2020-10-16 15:20:49 +02:00
if ( Result ! = ERROR_SUCCESS )
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get IpConfig " ) ;
2020-10-16 15:20:49 +02:00
goto cleanupTcpipAdapterRegKey ;
}
if ( ! Paths [ 0 ] )
{
LOG ( WINTUN_LOG_ERR , L " IpConfig is empty " ) ;
Result = ERROR_INVALID_DATA ;
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 )
{
LOG ( WINTUN_LOG_ERR , L " Registry path too long " ) ;
Result = ERROR_INVALID_PARAMETER ;
goto cleanupPaths ;
}
Result = ERROR_SUCCESS ;
2020-10-16 15:20:49 +02:00
cleanupPaths :
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , Paths ) ;
2020-10-16 15:20:49 +02:00
cleanupTcpipAdapterRegKey :
RegCloseKey ( TcpipAdapterRegKey ) ;
return Result ;
}
2020-10-30 18:20:57 +01:00
static DWORDLONG
VersionOfFile ( WCHAR * Filename )
{
DWORDLONG Version = 0 ;
DWORD Zero ;
DWORD Len = GetFileVersionInfoSizeW ( Filename , & Zero ) ;
if ( ! Len )
2020-11-02 11:52:54 +01:00
return LOG_LAST_ERROR ( L " Failed to query version info size " ) , Version ;
2020-10-30 18:20:57 +01:00
VOID * VersionInfo = HeapAlloc ( ModuleHeap , 0 , Len ) ;
if ( ! VersionInfo )
{
LOG ( WINTUN_LOG_ERR , L " Out of memory " ) ;
return Version ;
}
VS_FIXEDFILEINFO * FixedInfo ;
UINT FixedInfoLen = sizeof ( * FixedInfo ) ;
if ( ! GetFileVersionInfoW ( Filename , 0 , Len , VersionInfo ) )
{
LOG_LAST_ERROR ( L " Failed to get version info " ) ;
goto out ;
}
if ( ! VerQueryValueW ( VersionInfo , L " \\ " , & FixedInfo , & FixedInfoLen ) )
{
2020-11-02 11:52:54 +01:00
LOG_LAST_ERROR ( L " Failed to get version info root " ) ;
2020-10-30 18:20:57 +01:00
goto out ;
}
Version = ( DWORDLONG ) FixedInfo - > dwFileVersionLS | ( ( DWORDLONG ) FixedInfo - > dwFileVersionMS < < 32 ) ;
out :
HeapFree ( ModuleHeap , 0 , VersionInfo ) ;
return Version ;
}
2020-10-15 15:54:37 +02:00
static WINTUN_STATUS
CreateAdapter (
2020-10-31 18:13:36 +01:00
_In_z_ const WCHAR * InfPath ,
_In_z_ const WCHAR * Pool ,
_In_z_ const WCHAR * Name ,
2020-07-21 16:38:00 +02:00
_In_opt_ const GUID * RequestedGUID ,
_Out_ WINTUN_ADAPTER * * Adapter ,
_Inout_ BOOL * RebootRequired )
{
2020-11-01 03:19:21 +01:00
LOG ( WINTUN_LOG_INFO , L " Creating adapter " ) ;
2020-07-21 16:38:00 +02:00
DWORD Result ;
2020-11-02 12:07:05 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
2020-07-21 16:38:00 +02:00
if ( ! Mutex )
2020-07-24 08:26:20 +02:00
return ERROR_INVALID_HANDLE ;
2020-07-21 16:38:00 +02:00
2020-10-13 19:40:52 +02:00
HDEVINFO DevInfo = SetupDiCreateDeviceInfoListExW ( & GUID_DEVCLASS_NET , NULL , NULL , NULL ) ;
2020-07-21 16:38:00 +02:00
if ( DevInfo = = INVALID_HANDLE_VALUE )
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Creating empty device information set failed " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupMutex ;
}
WCHAR ClassName [ MAX_CLASS_NAME_LEN ] ;
2020-10-13 19:40:52 +02:00
if ( ! SetupDiClassNameFromGuidExW ( & GUID_DEVCLASS_NET , ClassName , _countof ( ClassName ) , NULL , NULL , NULL ) )
2020-07-21 16:38:00 +02:00
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Retrieving class name associated with class GUID failed " ) ;
2020-07-07 15:42:39 +02:00
goto cleanupDevInfo ;
}
2020-07-21 16:38:00 +02:00
WCHAR PoolDeviceTypeName [ MAX_POOL_DEVICE_TYPE ] ;
2020-10-30 06:51:24 +01:00
Result = GetPoolDeviceTypeName ( Pool , PoolDeviceTypeName ) ;
if ( Result ! = ERROR_SUCCESS )
goto cleanupDevInfo ;
2020-07-21 16:38:00 +02:00
SP_DEVINFO_DATA DevInfoData = { . cbSize = sizeof ( SP_DEVINFO_DATA ) } ;
if ( ! SetupDiCreateDeviceInfoW (
2020-10-13 19:40:52 +02:00
DevInfo , ClassName , & GUID_DEVCLASS_NET , PoolDeviceTypeName , NULL , DICD_GENERATE_ID , & DevInfoData ) )
2020-07-21 16:38:00 +02:00
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Creating new device information element failed " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupDevInfo ;
}
2020-10-15 15:54:37 +02:00
SP_DEVINSTALL_PARAMS_W DevInstallParams = { . cbSize = sizeof ( SP_DEVINSTALL_PARAMS_W ) } ;
if ( ! SetupDiGetDeviceInstallParamsW ( DevInfo , & DevInfoData , & DevInstallParams ) )
{
Result = LOG_LAST_ERROR ( L " Retrieving device installation parameters failed " ) ;
goto cleanupDevInfo ;
}
DevInstallParams . Flags | = DI_QUIETINSTALL | DI_ENUMSINGLEINF ;
2020-10-31 18:13:36 +01:00
if ( wcsncpy_s ( DevInstallParams . DriverPath , _countof ( DevInstallParams . DriverPath ) , InfPath , _TRUNCATE ) = = STRUNCATE )
{
LOG ( WINTUN_LOG_ERR , L " Inf path too long " ) ;
Result = ERROR_INVALID_PARAMETER ;
goto cleanupDevInfo ;
}
2020-10-15 15:54:37 +02:00
if ( ! SetupDiSetDeviceInstallParamsW ( DevInfo , & DevInfoData , & DevInstallParams ) )
{
Result = LOG_LAST_ERROR ( L " Setting device installation parameters failed " ) ;
goto cleanupDevInfo ;
}
2020-07-21 16:38:00 +02:00
if ( ! SetupDiSetSelectedDevice ( DevInfo , & DevInfoData ) )
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Failed selecting device " ) ;
2020-07-21 16:38:00 +02: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 ) ) )
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Failed setting hardware ID " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupDevInfo ;
}
if ( ! SetupDiBuildDriverInfoList ( DevInfo , & DevInfoData , SPDIT_COMPATDRIVER ) ) /* TODO: This takes ~510ms */
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Failed building driver info list " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupDevInfo ;
}
FILETIME DriverDate = { 0 , 0 } ;
DWORDLONG DriverVersion = 0 ;
2020-10-13 19:40:52 +02:00
for ( DWORD EnumIndex = 0 ; ; + + EnumIndex ) /* TODO: This loop takes ~600ms */
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 ) } ;
if ( ! SetupDiEnumDriverInfoW ( DevInfo , & DevInfoData , SPDIT_COMPATDRIVER , EnumIndex , & DrvInfoData ) )
2020-07-21 16:38:00 +02:00
{
if ( GetLastError ( ) = = ERROR_NO_MORE_ITEMS )
break ;
continue ;
}
/* Check the driver version first, since the check is trivial and will save us iterating over hardware IDs for
* any driver versioned prior our best match . */
2020-10-13 19:40:52 +02:00
if ( ! IsNewer ( & DrvInfoData , & DriverDate , DriverVersion ) )
2020-07-21 16:38:00 +02:00
continue ;
2020-10-15 11:32:06 +02:00
SP_DRVINFO_DETAIL_DATA_W * DrvInfoDetailData ;
if ( AdapterGetDrvInfoDetail ( DevInfo , & DevInfoData , & DrvInfoData , & DrvInfoDetailData ) ! = ERROR_SUCCESS )
2020-10-15 12:21:55 +02:00
{
LOG ( WINTUN_LOG_WARN , L " Failed getting driver info detail " ) ;
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-07-21 16:38:00 +02:00
{
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , DrvInfoDetailData ) ;
2020-07-21 16:38:00 +02:00
continue ;
}
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , DrvInfoDetailData ) ;
2020-07-21 16:38:00 +02:00
2020-10-13 19:40:52 +02:00
if ( ! SetupDiSetSelectedDriverW ( DevInfo , & DevInfoData , & DrvInfoData ) )
2020-07-21 16:38:00 +02:00
continue ;
2020-10-13 19:40:52 +02:00
DriverDate = DrvInfoData . DriverDate ;
DriverVersion = DrvInfoData . DriverVersion ;
2020-07-21 16:38:00 +02:00
}
if ( ! DriverVersion )
{
2020-10-14 13:04:29 +02:00
LOG ( WINTUN_LOG_ERR , L " No appropriate drivers found " ) ;
2020-07-21 16:38:00 +02:00
Result = ERROR_FILE_NOT_FOUND ;
goto cleanupDriverInfoList ;
}
if ( ! SetupDiCallClassInstaller ( DIF_REGISTERDEVICE , DevInfo , & DevInfoData ) )
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Registering device failed " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupDevice ;
}
2020-10-13 19:40:52 +02:00
if ( ! SetupDiCallClassInstaller ( DIF_REGISTER_COINSTALLERS , DevInfo , & DevInfoData ) )
2020-10-14 13:04:29 +02:00
LOG_LAST_ERROR ( L " Registering coinstallers failed " ) ;
2020-07-21 16:38:00 +02: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 ) ;
}
if ( NetDevRegKey = = INVALID_HANDLE_VALUE )
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Failed to open device-specific registry key " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupDevice ;
}
if ( RequestedGUID )
{
WCHAR RequestedGUIDStr [ MAX_GUID_STRING_LEN ] ;
Result = RegSetValueExW (
NetDevRegKey ,
L " NetSetupAnticipatedInstanceId " ,
0 ,
REG_SZ ,
( const BYTE * ) RequestedGUIDStr ,
StringFromGUID2 ( RequestedGUID , RequestedGUIDStr , _countof ( RequestedGUIDStr ) ) * sizeof ( WCHAR ) ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-10-14 13:04:29 +02:00
LOG_LAST_ERROR ( L " Failed to set NetSetupAnticipatedInstanceId " ) ;
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 ) )
2020-10-14 13:04:29 +02:00
LOG_LAST_ERROR ( L " Installing interfaces failed " ) ;
2020-07-21 16:38:00 +02:00
if ( ! SetupDiCallClassInstaller ( DIF_INSTALLDEVICE , DevInfo , & DevInfoData ) )
{
2020-10-14 13:04:29 +02:00
Result = LOG_LAST_ERROR ( L " Installing device failed " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
}
* RebootRequired = * RebootRequired | | CheckReboot ( DevInfo , & DevInfoData ) ;
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
{
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to set adapter description " ) ;
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-07-21 18:19:15 +02:00
WCHAR * DummyStr ;
2020-07-21 16:38:00 +02:00
Result = RegistryQueryStringWait ( NetDevRegKey , L " NetCfgInstanceId " , WAIT_FOR_REGISTRY_TIMEOUT , & DummyStr ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get NetCfgInstanceId " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupNetDevRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , DummyStr ) ;
2020-07-21 16:38:00 +02:00
DWORD DummyDWORD ;
Result = RegistryQueryDWORDWait ( NetDevRegKey , L " NetLuidIndex " , WAIT_FOR_REGISTRY_TIMEOUT , & DummyDWORD ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get NetLuidIndex " ) ;
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
Result = RegistryQueryDWORDWait ( NetDevRegKey , L " *IfType " , WAIT_FOR_REGISTRY_TIMEOUT , & DummyDWORD ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get *IfType " ) ;
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-30 13:08:57 +01:00
WINTUN_ADAPTER * a ;
Result = CreateAdapterData ( Pool , DevInfo , & DevInfoData , & a ) ;
2020-07-21 16:38:00 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-10-15 12:21:55 +02:00
LOG ( WINTUN_LOG_ERR , L " Failed to create adapter data " ) ;
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-10-30 13:08:57 +01:00
Result = GetTcpipAdapterRegPath ( a , TcpipAdapterRegPath ) ;
2020-10-30 06:51:24 +01:00
if ( Result ! = ERROR_SUCCESS )
goto cleanupAdapter ;
2020-07-21 16:38:00 +02:00
Result = RegistryOpenKeyWait (
HKEY_LOCAL_MACHINE ,
TcpipAdapterRegPath ,
KEY_QUERY_VALUE | KEY_NOTIFY ,
WAIT_FOR_REGISTRY_TIMEOUT ,
& TcpipAdapterRegKey ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to open adapter-specific TCP/IP interface registry key " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupAdapter ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 16:38:00 +02:00
Result = RegistryQueryStringWait ( TcpipAdapterRegKey , L " IpConfig " , WAIT_FOR_REGISTRY_TIMEOUT , & DummyStr ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get IpConfig " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupTcpipAdapterRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , DummyStr ) ;
2020-07-21 16:38:00 +02:00
HKEY TcpipInterfaceRegKey ;
2020-07-24 08:10:00 +02:00
WCHAR TcpipInterfaceRegPath [ MAX_REG_PATH ] ;
2020-10-30 13:08:57 +01:00
Result = GetTcpipInterfaceRegPath ( a , TcpipInterfaceRegPath ) ;
2020-07-21 16:38:00 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-10-15 12:21:55 +02:00
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-07-21 16:38:00 +02:00
Result = RegistryOpenKeyWait (
HKEY_LOCAL_MACHINE ,
TcpipInterfaceRegPath ,
KEY_QUERY_VALUE | KEY_SET_VALUE ,
WAIT_FOR_REGISTRY_TIMEOUT ,
& TcpipInterfaceRegKey ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-10-15 12:21:55 +02:00
LOG ( WINTUN_LOG_ERR , L " Failed to open interface-specific TCP/IP network registry key " ) ;
2020-07-21 16:38:00 +02:00
goto cleanupTcpipAdapterRegKey ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 16:38:00 +02:00
2020-10-15 11:32:06 +02:00
static const DWORD EnableDeadGWDetect = 0 ;
2020-10-13 19:40:52 +02:00
Result = RegSetKeyValueW (
2020-10-13 19:55:41 +02:00
TcpipInterfaceRegKey , NULL , L " EnableDeadGWDetect " , REG_DWORD , & EnableDeadGWDetect , sizeof ( EnableDeadGWDetect ) ) ;
2020-10-13 19:40:52 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-11-01 03:19:21 +01:00
{
2020-10-14 13:04:29 +02:00
LOG_ERROR ( L " Failed to set EnableDeadGWDetect " , Result ) ;
2020-11-01 03:19:21 +01:00
goto cleanupTcpipInterfaceRegKey ;
}
2020-07-21 16:38:00 +02:00
2020-10-30 13:08:57 +01:00
Result = WintunSetAdapterName ( a , Name ) ;
2020-11-01 03:19:21 +01:00
if ( Result ! = ERROR_SUCCESS )
{
2020-10-14 13:04:29 +02:00
LOG_ERROR ( L " Failed to set adapter name " , Result ) ;
2020-11-01 03:19:21 +01:00
goto cleanupTcpipInterfaceRegKey ;
}
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-01 03:47:19 +01:00
Result = RtlNtStatusToDosError ( ProblemStatus ) ;
if ( ProblemStatus ! = STATUS_PNP_DEVICE_CONFIGURATION_PENDING | | Tries = = 999 )
2020-11-01 03:19:21 +01:00
{
2020-11-01 03:47:19 +01:00
LOG_ERROR ( L " Failed to setup adapter " , Result ) ;
goto cleanupTcpipInterfaceRegKey ;
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
}
* Adapter = a ;
cleanupTcpipInterfaceRegKey :
2020-07-21 16:38:00 +02:00
RegCloseKey ( TcpipInterfaceRegKey ) ;
cleanupTcpipAdapterRegKey :
RegCloseKey ( TcpipAdapterRegKey ) ;
cleanupAdapter :
if ( Result ! = ERROR_SUCCESS )
2020-10-30 13:08:57 +01:00
HeapFree ( ModuleHeap , 0 , a ) ;
2020-07-21 16:38:00 +02:00
cleanupNetDevRegKey :
RegCloseKey ( NetDevRegKey ) ;
cleanupDevice :
if ( Result ! = ERROR_SUCCESS )
{
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 ) ;
}
cleanupDriverInfoList :
SetupDiDestroyDriverInfoList ( DevInfo , & DevInfoData , SPDIT_COMPATDRIVER ) ;
2020-07-07 15:42:39 +02:00
cleanupDevInfo :
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupMutex :
2020-10-15 11:32:06 +02:00
NamespaceReleaseMutex ( Mutex ) ;
2020-07-07 15:42:39 +02:00
return Result ;
}
2020-07-21 16:38:00 +02:00
2020-10-16 13:30:51 +02:00
static WINTUN_STATUS
CreateTemporaryDirectory ( _Out_cap_c_ ( MAX_PATH ) WCHAR * RandomTempSubDirectory )
2020-10-15 15:54:37 +02:00
{
WCHAR WindowsDirectory [ MAX_PATH ] ;
if ( ! GetWindowsDirectoryW ( WindowsDirectory , _countof ( WindowsDirectory ) ) )
return LOG_LAST_ERROR ( L " Failed to get Windows folder " ) ;
WCHAR WindowsTempDirectory [ MAX_PATH ] ;
if ( ! PathCombineW ( WindowsTempDirectory , WindowsDirectory , L " Temp " ) )
return ERROR_BUFFER_OVERFLOW ;
UCHAR RandomBytes [ 32 ] = { 0 } ;
2020-10-16 13:30:51 +02:00
# pragma warning(suppress : 6387)
2020-10-15 15:54:37 +02:00
if ( ! RtlGenRandom ( RandomBytes , sizeof ( RandomBytes ) ) )
return LOG_LAST_ERROR ( L " Failed to generate random " ) ;
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 ) )
return ERROR_BUFFER_OVERFLOW ;
2020-10-30 13:26:36 +01:00
if ( ! CreateDirectoryW ( RandomTempSubDirectory , & SecurityAttributes ) )
2020-10-15 15:54:37 +02:00
return LOG_LAST_ERROR ( L " Failed to create temporary folder " ) ;
2020-10-16 13:30:51 +02:00
return ERROR_SUCCESS ;
}
2020-11-01 05:54:56 +01:00
DWORDLONG
WintunGetVersion ( void )
2020-11-01 01:22:32 +01:00
{
DWORDLONG Version = 0 ;
PRTL_PROCESS_MODULES Modules ;
ULONG BufferSize = 128 * 1024 ;
for ( ; ; )
{
Modules = HeapAlloc ( ModuleHeap , 0 , BufferSize ) ;
if ( ! Modules )
{
LOG ( WINTUN_LOG_ERR , L " Out of memory " ) ;
return Version ;
}
NTSTATUS Status = NtQuerySystemInformation ( SystemModuleInformation , Modules , BufferSize , & BufferSize ) ;
if ( NT_SUCCESS ( Status ) )
break ;
HeapFree ( ModuleHeap , 0 , Modules ) ;
if ( Status = = STATUS_INFO_LENGTH_MISMATCH )
continue ;
LOG ( WINTUN_LOG_ERR , L " Failed to enumerate drivers " ) ;
return Version ;
}
for ( ULONG i = Modules - > NumberOfModules ; i - - > 0 ; )
{
const char * NtPath = ( const char * ) Modules - > Modules [ i ] . FullPathName ;
if ( ! _stricmp ( & NtPath [ Modules - > Modules [ i ] . OffsetToFileName ] , " wintun.sys " ) )
{
WCHAR FilePath [ MAX_PATH * 3 + 15 ] ;
if ( _snwprintf_s ( FilePath , _countof ( FilePath ) , _TRUNCATE , L " \\ \\ ? \\ GLOBALROOT%S " , NtPath ) = = - 1 )
continue ;
Version = VersionOfFile ( FilePath ) ;
goto out ;
}
}
out :
HeapFree ( ModuleHeap , 0 , Modules ) ;
return Version ;
}
static BOOL EnsureWintunUnloaded ( VOID )
{
BOOL Loaded ;
2020-11-01 05:54:56 +01:00
for ( int i = 0 ; ( Loaded = WintunGetVersion ( ) ! = 0 ) ! = FALSE & & i < 300 ; + + i )
2020-11-01 01:22:32 +01:00
Sleep ( 50 ) ;
return ! Loaded ;
}
static WINTUN_STATUS
InstallDriver ( _Out_writes_z_ ( MAX_PATH ) WCHAR InfStorePath [ MAX_PATH ] , _Inout_ BOOL * RebootRequired )
{
2020-11-02 12:07:05 +01:00
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex ( ) ;
if ( ! DriverInstallationLock )
return LOG_LAST_ERROR ( L " Failed to take driver installation mutex " ) ;
2020-11-01 01:22:32 +01:00
DWORD Result ;
WCHAR RandomTempSubDirectory [ MAX_PATH ] ;
if ( ( Result = CreateTemporaryDirectory ( RandomTempSubDirectory ) ) ! = ERROR_SUCCESS )
2020-11-02 12:07:05 +01:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to create temporary folder " ) ;
goto cleanupDriverInstallationLock ;
}
2020-11-01 01:22:32 +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 " ) )
{
Result = ERROR_BUFFER_OVERFLOW ;
goto cleanupDirectory ;
}
BOOL UseWHQL = HaveWHQL ( ) ;
if ( ! UseWHQL & & ( Result = InstallCertificate ( L " wintun.cat " ) ) ! = ERROR_SUCCESS )
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to install code signing certificate " ) ;
2020-11-01 01:22:32 +01:00
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_INFO , L " Extracting driver " ) ;
2020-11-01 01:22:32 +01:00
if ( ( Result = ResourceCopyToFile ( CatPath , UseWHQL ? L " wintun-whql.cat " : L " wintun.cat " ) ) ! = ERROR_SUCCESS | |
( Result = ResourceCopyToFile ( SysPath , UseWHQL ? L " wintun-whql.sys " : L " wintun.sys " ) ) ! = ERROR_SUCCESS | |
( Result = ResourceCopyToFile ( InfPath , UseWHQL ? L " wintun-whql.inf " : L " wintun.inf " ) ) ! = ERROR_SUCCESS )
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to extract driver " ) ;
2020-11-01 01:22:32 +01:00
goto cleanupDelete ;
}
2020-11-01 05:54:56 +01:00
DWORDLONG LoadedDriverVersion = WintunGetVersion ( ) ;
2020-11-01 01:22:32 +01:00
HDEVINFO DevInfo = INVALID_HANDLE_VALUE ;
SP_DEVINFO_DATA_LIST * ExistingAdapters = NULL ;
if ( LoadedDriverVersion )
{
DWORDLONG ProposedDriverVersion = VersionOfFile ( SysPath ) ;
if ( ! ProposedDriverVersion )
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get driver file version " ) ;
2020-11-01 01:22:32 +01:00
Result = ERROR_INVALID_DATA ;
goto cleanupDelete ;
}
if ( ProposedDriverVersion > LoadedDriverVersion )
{
DevInfo = SetupDiGetClassDevsExW ( & GUID_DEVCLASS_NET , NULL , NULL , DIGCF_PRESENT , NULL , NULL , NULL ) ;
if ( DevInfo = = INVALID_HANDLE_VALUE )
{
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to get present adapters " ) ;
2020-11-01 01:22:32 +01:00
goto cleanupDelete ;
}
AdapterDisableAllOurs ( DevInfo , & ExistingAdapters ) ;
LOG ( WINTUN_LOG_INFO , L " Waiting for existing driver to unload from kernel " ) ;
if ( ! EnsureWintunUnloaded ( ) )
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to unload existing driver, which means a reboot will likely be required " ) ;
2020-11-01 01:22:32 +01:00
}
}
LOG ( WINTUN_LOG_INFO , L " Installing driver " ) ;
2020-11-01 23:10:51 +01:00
if ( ! SetupCopyOEMInfW ( InfPath , NULL , SPOST_NONE , 0 , InfStorePath , MAX_PATH , NULL , NULL ) )
2020-11-01 01:22:32 +01:00
{
Result = LOG_LAST_ERROR ( L " Could not install driver to store " ) ;
goto cleanupCloseDevInfo ;
}
_Analysis_assume_nullterminated_ ( InfStorePath ) ;
BOOL UpdateRebootRequired = FALSE ;
if ( ExistingAdapters & &
! UpdateDriverForPlugAndPlayDevicesW (
NULL , WINTUN_HWID , InfStorePath , INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE , & UpdateRebootRequired ) )
LOG ( WINTUN_LOG_WARN , L " Could not update existing adapters " ) ;
* RebootRequired = * RebootRequired | | UpdateRebootRequired ;
cleanupCloseDevInfo :
if ( ExistingAdapters )
{
AdapterEnableAll ( DevInfo , ExistingAdapters ) ;
while ( ExistingAdapters )
{
SP_DEVINFO_DATA_LIST * Next = ExistingAdapters - > Next ;
HeapFree ( ModuleHeap , 0 , ExistingAdapters ) ;
ExistingAdapters = Next ;
}
}
if ( DevInfo ! = INVALID_HANDLE_VALUE )
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupDelete :
DeleteFileW ( CatPath ) ;
DeleteFileW ( SysPath ) ;
DeleteFileW ( InfPath ) ;
cleanupDirectory :
RemoveDirectoryW ( RandomTempSubDirectory ) ;
2020-11-02 12:07:05 +01:00
cleanupDriverInstallationLock :
NamespaceReleaseMutex ( DriverInstallationLock ) ;
2020-11-01 01:22:32 +01:00
return Result ;
}
2020-10-30 09:33:21 +01:00
# ifdef MAYBE_WOW64
2020-10-16 13:30:51 +02:00
2020-10-19 22:23:09 +02:00
typedef struct _PROCESS_STDOUT_STATE
{
HANDLE Stdout ;
WCHAR * Response ;
DWORD ResponseCapacity ;
} PROCESS_STDOUT_STATE ;
static DWORD WINAPI
ProcessStdout ( _Inout_ PROCESS_STDOUT_STATE * State )
{
for ( DWORD Offset = 0 , MaxLen = State - > ResponseCapacity - 1 ; Offset < MaxLen ; )
{
DWORD SizeRead ;
if ( ! ReadFile ( State - > Stdout , State - > Response + Offset , sizeof ( WCHAR ) * ( MaxLen - Offset ) , & SizeRead , NULL ) )
2020-10-30 07:29:40 +01:00
return ERROR_SUCCESS ;
2020-10-19 22:23:09 +02:00
if ( SizeRead % sizeof ( WCHAR ) )
2020-10-30 07:29:40 +01:00
return ERROR_INVALID_DATA ;
2020-10-19 22:23:09 +02:00
Offset + = SizeRead / sizeof ( WCHAR ) ;
State - > Response [ Offset ] = 0 ;
}
2020-10-30 07:29:40 +01:00
return ERROR_BUFFER_OVERFLOW ;
2020-10-19 22:23:09 +02:00
}
static DWORD WINAPI
ProcessStderr ( _In_ HANDLE Stderr )
{
enum
{
OnNone ,
OnLevelStart ,
OnLevel ,
OnLevelEnd ,
OnSpace ,
OnMsg
} State = OnNone ;
WCHAR Msg [ 0x200 ] ;
DWORD Count = 0 ;
WINTUN_LOGGER_LEVEL Level = WINTUN_LOG_INFO ;
for ( ; ; )
{
WCHAR Buf [ 0x200 ] ;
DWORD SizeRead ;
if ( ! ReadFile ( Stderr , Buf , sizeof ( Buf ) , & SizeRead , NULL ) )
2020-10-30 07:29:40 +01:00
return ERROR_SUCCESS ;
2020-10-19 22:23:09 +02:00
if ( SizeRead % sizeof ( WCHAR ) )
2020-10-30 07:29:40 +01:00
return ERROR_INVALID_DATA ;
2020-10-19 22:23:09 +02:00
SizeRead / = sizeof ( WCHAR ) ;
for ( DWORD i = 0 ; i < SizeRead ; + + i )
{
WCHAR c = Buf [ i ] ;
if ( State = = OnNone & & c = = L ' [ ' )
State = OnLevelStart ;
else if (
State = = OnLevelStart & & ( ( Level = WINTUN_LOG_INFO , c = = L ' + ' ) | |
( Level = WINTUN_LOG_WARN , c = = L ' - ' ) | | ( Level = WINTUN_LOG_ERR , c = = L ' ! ' ) ) )
State = OnLevelEnd ;
else if ( State = = OnLevelEnd & & c = = L ' ] ' )
State = OnSpace ;
else if ( State = = OnSpace & & ! iswspace ( c ) | | State = = OnMsg & & c ! = L ' \r ' & & c ! = L ' \n ' )
{
if ( Count < _countof ( Msg ) - 1 )
Msg [ Count + + ] = c ;
State = OnMsg ;
}
else if ( State = = OnMsg & & c = = L ' \n ' )
{
Msg [ Count ] = 0 ;
Logger ( Level , Msg ) ;
State = OnNone ;
Count = 0 ;
}
}
}
}
2020-10-16 13:30:51 +02:00
static WINTUN_STATUS
2020-10-19 22:23:09 +02:00
ExecuteRunDll32 (
_In_z_ const WCHAR * Arguments ,
_Out_z_cap_c_ ( ResponseCapacity ) WCHAR * Response ,
_In_ DWORD ResponseCapacity )
2020-10-16 13:30:51 +02:00
{
WCHAR WindowsDirectory [ MAX_PATH ] ;
if ( ! GetWindowsDirectoryW ( WindowsDirectory , _countof ( WindowsDirectory ) ) )
return LOG_LAST_ERROR ( L " Failed to get Windows folder " ) ;
WCHAR RunDll32Path [ MAX_PATH ] ;
if ( ! PathCombineW ( RunDll32Path , WindowsDirectory , L " Sysnative \\ rundll32.exe " ) )
return ERROR_BUFFER_OVERFLOW ;
2020-10-15 15:54:37 +02:00
2020-10-16 13:30:51 +02:00
DWORD Result ;
WCHAR RandomTempSubDirectory [ MAX_PATH ] ;
if ( ( Result = CreateTemporaryDirectory ( RandomTempSubDirectory ) ) ! = ERROR_SUCCESS )
return LOG ( WINTUN_LOG_ERR , L " Failed to create temporary folder " ) , Result ;
WCHAR DllPath [ MAX_PATH ] = { 0 } ;
if ( ! PathCombineW ( DllPath , RandomTempSubDirectory , L " wintun.dll " ) )
{
Result = ERROR_BUFFER_OVERFLOW ;
goto cleanupDirectory ;
}
2020-10-30 07:09:13 +01:00
const WCHAR * WintunDllResourceName ;
switch ( NativeMachine )
{
case IMAGE_FILE_MACHINE_AMD64 :
WintunDllResourceName = L " wintun-amd64.dll " ;
break ;
case IMAGE_FILE_MACHINE_ARM64 :
WintunDllResourceName = L " wintun-arm64.dll " ;
break ;
default :
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Unsupported platform " ) ;
2020-10-30 07:09:13 +01:00
Result = ERROR_NOT_SUPPORTED ;
goto cleanupDirectory ;
}
if ( ( Result = ResourceCopyToFile ( DllPath , WintunDllResourceName ) ) ! = ERROR_SUCCESS )
2020-10-16 13:30:51 +02:00
{
LOG ( WINTUN_LOG_ERR , L " Failed to copy resource " ) ;
goto cleanupDelete ;
}
size_t CommandLineLen = 10 + MAX_PATH + 2 + wcslen ( Arguments ) + 1 ;
2020-10-24 22:12:47 +02:00
WCHAR * CommandLine = HeapAlloc ( ModuleHeap , 0 , CommandLineLen * sizeof ( WCHAR ) ) ;
2020-10-16 13:30:51 +02:00
if ( ! CommandLine )
{
LOG ( WINTUN_LOG_ERR , L " Out of memory " ) ;
Result = ERROR_OUTOFMEMORY ;
goto cleanupDelete ;
}
2020-10-30 06:51:24 +01:00
if ( _snwprintf_s ( CommandLine , CommandLineLen , _TRUNCATE , L " rundll32 \" %.*s \" ,%s " , MAX_PATH , DllPath , Arguments ) = =
- 1 )
{
LOG ( WINTUN_LOG_ERR , L " Command line too long " ) ;
Result = ERROR_INVALID_PARAMETER ;
goto cleanupDelete ;
}
2020-10-30 07:29:40 +01:00
HANDLE StreamRStdout = INVALID_HANDLE_VALUE , StreamRStderr = INVALID_HANDLE_VALUE ,
StreamWStdout = INVALID_HANDLE_VALUE , StreamWStderr = INVALID_HANDLE_VALUE ;
2020-10-30 13:26:36 +01:00
if ( ! CreatePipe ( & StreamRStdout , & StreamWStdout , & SecurityAttributes , 0 ) | |
! CreatePipe ( & StreamRStderr , & StreamWStderr , & SecurityAttributes , 0 ) )
2020-10-19 22:23:09 +02:00
{
Result = LOG_LAST_ERROR ( L " Failed to create pipes " ) ;
goto cleanupPipes ;
}
2020-10-30 07:35:00 +01:00
if ( ! SetHandleInformation ( StreamWStdout , HANDLE_FLAG_INHERIT , HANDLE_FLAG_INHERIT ) | |
! SetHandleInformation ( StreamWStderr , HANDLE_FLAG_INHERIT , HANDLE_FLAG_INHERIT ) )
2020-10-19 22:23:09 +02:00
{
Result = LOG_LAST_ERROR ( L " Failed to set handle info " ) ;
goto cleanupPipes ;
}
if ( ResponseCapacity )
Response [ 0 ] = 0 ;
2020-10-30 07:29:40 +01:00
PROCESS_STDOUT_STATE ProcessStdoutState = { . Stdout = StreamRStdout ,
2020-10-19 22:23:09 +02:00
. Response = Response ,
. ResponseCapacity = ResponseCapacity } ;
2020-10-30 07:29:40 +01:00
HANDLE ThreadStdout = NULL , ThreadStderr = NULL ;
2020-10-30 13:26:36 +01:00
if ( ( ThreadStdout = CreateThread ( & SecurityAttributes , 0 , ProcessStdout , & ProcessStdoutState , 0 , NULL ) ) = = NULL | |
( ThreadStderr = CreateThread ( & SecurityAttributes , 0 , ProcessStderr , StreamRStderr , 0 , NULL ) ) = = NULL )
2020-10-19 22:23:09 +02:00
{
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to spawn readers " ) ;
2020-10-19 22:23:09 +02:00
goto cleanupThreads ;
}
STARTUPINFOW si = { . cb = sizeof ( STARTUPINFO ) ,
. dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES ,
. wShowWindow = SW_HIDE ,
2020-10-30 07:29:40 +01:00
. hStdOutput = StreamWStdout ,
. hStdError = StreamWStderr } ;
2020-10-16 13:30:51 +02:00
PROCESS_INFORMATION pi ;
2020-10-19 22:23:09 +02:00
if ( ! CreateProcessW ( RunDll32Path , CommandLine , NULL , NULL , TRUE , 0 , NULL , NULL , & si , & pi ) )
2020-10-16 13:30:51 +02:00
{
Result = LOG_LAST_ERROR ( L " Creating process failed " ) ;
2020-10-19 22:23:09 +02:00
goto cleanupThreads ;
2020-10-16 13:30:51 +02:00
}
WaitForSingleObject ( pi . hProcess , INFINITE ) ;
CloseHandle ( pi . hProcess ) ;
CloseHandle ( pi . hThread ) ;
2020-10-19 22:23:09 +02:00
cleanupThreads :
2020-10-30 07:29:40 +01:00
if ( ThreadStderr )
{
CloseHandle ( StreamWStderr ) ;
StreamWStderr = INVALID_HANDLE_VALUE ;
WaitForSingleObject ( ThreadStderr , INFINITE ) ;
CloseHandle ( ThreadStderr ) ;
}
if ( ThreadStdout )
{
CloseHandle ( StreamWStdout ) ;
StreamWStdout = INVALID_HANDLE_VALUE ;
WaitForSingleObject ( ThreadStdout , INFINITE ) ;
if ( ! GetExitCodeThread ( ThreadStdout , & Result ) )
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to retrieve stdout reader result " ) ;
2020-10-30 07:29:40 +01:00
else if ( Result ! = ERROR_SUCCESS )
LOG_ERROR ( L " Failed to read process output " , Result ) ;
CloseHandle ( ThreadStdout ) ;
}
2020-10-19 22:23:09 +02:00
cleanupPipes :
2020-10-30 07:29:40 +01:00
CloseHandle ( StreamRStderr ) ;
CloseHandle ( StreamWStderr ) ;
CloseHandle ( StreamRStdout ) ;
CloseHandle ( StreamWStdout ) ;
2020-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , CommandLine ) ;
2020-10-16 13:30:51 +02:00
cleanupDelete :
DeleteFileW ( DllPath ) ;
cleanupDirectory :
RemoveDirectoryW ( RandomTempSubDirectory ) ;
return Result ;
}
2020-10-19 22:23:09 +02:00
static WINTUN_STATUS
2020-10-31 18:13:36 +01:00
GetAdapter ( _In_z_ const WCHAR * Pool , _In_ const GUID * CfgInstanceID , _Out_ WINTUN_ADAPTER * * Adapter )
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 )
return ERROR_INVALID_HANDLE ;
HDEVINFO DevInfo ;
SP_DEVINFO_DATA DevInfoData ;
DWORD Result = GetDevInfoData ( CfgInstanceID , & DevInfo , & DevInfoData ) ;
if ( Result ! = ERROR_SUCCESS )
{
LOG ( WINTUN_LOG_ERR , L " Failed to locate adapter " ) ;
goto cleanupMutex ;
}
Result = CreateAdapterData ( Pool , DevInfo , & DevInfoData , Adapter ) ;
if ( Result ! = ERROR_SUCCESS )
LOG ( WINTUN_LOG_ERR , L " Failed to create adapter data " ) ;
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupMutex :
NamespaceReleaseMutex ( Mutex ) ;
return Result ;
}
2020-10-30 07:45:20 +01:00
static WINTUN_STATUS
CreateAdapterNatively (
2020-10-31 18:13:36 +01:00
_In_z_ const WCHAR * Pool ,
_In_z_ const WCHAR * Name ,
2020-10-30 07:45:20 +01:00
_In_opt_ const GUID * RequestedGUID ,
_Out_ WINTUN_ADAPTER * * Adapter ,
_Inout_ BOOL * RebootRequired )
{
LOG ( WINTUN_LOG_INFO , L " Spawning native process " ) ;
WCHAR RequestedGUIDStr [ MAX_GUID_STRING_LEN ] ;
2020-10-31 08:53:32 +01:00
WCHAR Arguments [ 15 + WINTUN_MAX_POOL + 3 + MAX_ADAPTER_NAME + 2 + MAX_GUID_STRING_LEN + 1 ] ;
2020-10-30 07:45:20 +01:00
if ( _snwprintf_s (
Arguments ,
_countof ( Arguments ) ,
_TRUNCATE ,
2020-10-31 18:13:36 +01:00
RequestedGUID ? L " CreateAdapter \" %s \" \" %s \" %.*s " : L " CreateAdapter \" %s \" \" %s \" " ,
2020-10-30 07:45:20 +01:00
Pool ,
Name ,
RequestedGUID ? StringFromGUID2 ( RequestedGUID , RequestedGUIDStr , _countof ( RequestedGUIDStr ) ) : 0 ,
RequestedGUIDStr ) = = - 1 )
return LOG ( WINTUN_LOG_ERR , L " Command line too long " ) , ERROR_INVALID_PARAMETER ;
WCHAR Response [ 8 + 1 + MAX_GUID_STRING_LEN + 1 + 8 + 1 ] ;
DWORD Result = ExecuteRunDll32 ( Arguments , Response , _countof ( Response ) ) ;
if ( Result ! = ERROR_SUCCESS )
{
LOG ( WINTUN_LOG_ERR , L " Error executing worker process " ) ;
return Result ;
}
int Argc ;
WCHAR * * Argv = CommandLineToArgvW ( Response , & Argc ) ;
GUID CfgInstanceID ;
if ( Argc < 3 | | FAILED ( CLSIDFromString ( Argv [ 1 ] , & CfgInstanceID ) ) )
{
LOG ( WINTUN_LOG_ERR , L " Incomplete or invalid response " ) ;
Result = ERROR_INVALID_PARAMETER ;
goto cleanupArgv ;
}
Result = wcstoul ( Argv [ 0 ] , NULL , 16 ) ;
if ( Result = = ERROR_SUCCESS & & GetAdapter ( Pool , & CfgInstanceID , Adapter ) ! = ERROR_SUCCESS )
{
LOG ( WINTUN_LOG_ERR , L " Failed to get adapter " ) ;
Result = ERROR_FILE_NOT_FOUND ;
}
if ( wcstoul ( Argv [ 2 ] , NULL , 16 ) )
* RebootRequired = TRUE ;
cleanupArgv :
LocalFree ( Argv ) ;
return Result ;
}
2020-10-16 13:30:51 +02:00
# endif
WINTUN_STATUS 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 ,
_Out_ WINTUN_ADAPTER * * Adapter ,
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 ( ) )
return LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) , ERROR_ACCESS_DENIED ;
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-10-30 12:25:24 +01:00
DWORD Result = ERROR_SUCCESS ;
2020-10-30 09:33:21 +01:00
# ifdef MAYBE_WOW64
2020-10-16 13:30:51 +02:00
if ( NativeMachine ! = IMAGE_FILE_PROCESS )
2020-10-30 12:25:24 +01:00
{
Result = CreateAdapterNatively ( Pool , Name , RequestedGUID , Adapter , RebootRequired ) ;
RevertToSelf ( ) ;
return Result ;
}
2020-10-16 13:30:51 +02:00
# endif
2020-10-30 09:53:09 +01:00
WCHAR InfStorePath [ MAX_PATH ] ;
2020-11-01 01:22:32 +01:00
if ( ( Result = InstallDriver ( InfStorePath , RebootRequired ) ) ! = ERROR_SUCCESS )
2020-10-15 15:54:37 +02:00
{
2020-11-01 01:22:32 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to install driver " ) ;
goto cleanupToken ;
2020-10-15 15:54:37 +02:00
}
2020-11-01 01:22:32 +01:00
Result = CreateAdapter ( InfStorePath , Pool , Name , RequestedGUID , Adapter , RebootRequired ) ;
2020-10-30 09:53:09 +01:00
2020-11-01 01:22:32 +01:00
if ( ! SetupUninstallOEMInfW ( PathFindFileNameW ( InfStorePath ) , SUOI_FORCEDELETE , NULL ) )
2020-10-30 09:53:09 +01:00
{
2020-11-02 11:52:54 +01:00
LOG_LAST_ERROR ( L " Failed to remove existing driver " ) ;
2020-10-30 09:53:09 +01:00
Result = Result ! = ERROR_SUCCESS ? Result : GetLastError ( ) ;
}
2020-10-30 12:25:24 +01:00
cleanupToken :
RevertToSelf ( ) ;
2020-10-15 15:54:37 +02:00
return Result ;
}
2020-10-30 09:33:21 +01:00
# ifdef MAYBE_WOW64
2020-10-30 07:45:20 +01:00
static WINTUN_STATUS
2020-10-30 14:34:40 +01:00
DeleteAdapterNatively ( _In_ const WINTUN_ADAPTER * Adapter , _In_ BOOL ForceCloseSessions , _Inout_ BOOL * RebootRequired )
2020-10-30 07:45:20 +01:00
{
LOG ( WINTUN_LOG_INFO , L " Spawning native process " ) ;
WCHAR GuidStr [ MAX_GUID_STRING_LEN ] ;
2020-10-30 14:34:40 +01:00
WCHAR Arguments [ 16 + MAX_GUID_STRING_LEN + 1 ] ;
2020-10-30 07:45:20 +01:00
if ( _snwprintf_s (
Arguments ,
_countof ( Arguments ) ,
_TRUNCATE ,
2020-10-30 14:34:40 +01:00
L " DeleteAdapter %d %.*s " ,
ForceCloseSessions ? 1 : 0 ,
2020-10-30 07:45:20 +01:00
StringFromGUID2 ( & Adapter - > CfgInstanceID , GuidStr , _countof ( GuidStr ) ) ,
GuidStr ) = = - 1 )
return LOG ( WINTUN_LOG_ERR , L " Command line too long " ) , ERROR_INVALID_PARAMETER ;
WCHAR Response [ 8 + 1 + 8 + 1 ] ;
DWORD Result = ExecuteRunDll32 ( Arguments , Response , _countof ( Response ) ) ;
if ( Result ! = ERROR_SUCCESS )
LOG ( WINTUN_LOG_ERR , L " Error executing worker process " ) ;
int Argc ;
WCHAR * * Argv = CommandLineToArgvW ( Response , & Argc ) ;
if ( Argc < 2 )
{
LOG ( WINTUN_LOG_ERR , L " Incomplete or invalid response " ) ;
Result = ERROR_INVALID_PARAMETER ;
goto cleanupArgv ;
}
Result = wcstoul ( Argv [ 0 ] , NULL , 16 ) ;
if ( wcstoul ( Argv [ 1 ] , NULL , 16 ) )
* RebootRequired = TRUE ;
cleanupArgv :
LocalFree ( Argv ) ;
return Result ;
}
# endif
2020-07-21 16:43:34 +02:00
WINTUN_STATUS WINAPI
2020-10-31 15:40:01 +01:00
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 ( ) )
return LOG ( WINTUN_LOG_ERR , L " Failed to impersonate SYSTEM user " ) , ERROR_ACCESS_DENIED ;
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-10-30 12:25:24 +01:00
DWORD Result ;
2020-10-30 09:33:21 +01:00
# ifdef MAYBE_WOW64
2020-10-16 13:30:51 +02:00
if ( NativeMachine ! = IMAGE_FILE_PROCESS )
2020-10-30 12:25:24 +01:00
{
2020-10-30 14:34:40 +01:00
Result = DeleteAdapterNatively ( Adapter , ForceCloseSessions , RebootRequired ) ;
2020-10-30 12:25:24 +01:00
RevertToSelf ( ) ;
return Result ;
}
2020-10-16 13:30:51 +02:00
# endif
2020-07-21 16:38:00 +02:00
HDEVINFO DevInfo ;
SP_DEVINFO_DATA DevInfoData ;
2020-10-30 12:25:24 +01:00
Result = GetDevInfoData ( & Adapter - > CfgInstanceID , & DevInfo , & DevInfoData ) ;
2020-07-24 08:26:20 +02:00
if ( Result = = ERROR_FILE_NOT_FOUND )
2020-10-30 12:25:24 +01:00
{
Result = ERROR_SUCCESS ;
goto cleanupToken ;
}
else if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get adapter info data " ) ;
2020-10-30 12:25:24 +01:00
goto cleanupToken ;
2020-10-13 19:40:52 +02:00
}
2020-10-30 14:21:13 +01:00
2020-10-30 14:34:40 +01:00
if ( ForceCloseSessions & & ForceCloseWintunAdapterHandle ( DevInfo , & DevInfoData ) ! = ERROR_SUCCESS )
2020-10-30 14:21:13 +01:00
LOG ( WINTUN_LOG_WARN , L " Failed to force close adapter handles " ) ;
2020-10-13 19:40:52 +02:00
SetQuietInstall ( DevInfo , & DevInfoData ) ;
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 ) ;
else
2020-11-02 11:52:54 +01:00
Result = LOG_LAST_ERROR ( L " Failed to remove existing adapter " ) ;
2020-07-21 16:38:00 +02:00
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
2020-10-30 12:25:24 +01:00
cleanupToken :
RevertToSelf ( ) ;
2020-07-21 16:38:00 +02:00
return Result ;
}
2020-07-21 16:43:34 +02:00
WINTUN_STATUS WINAPI
2020-10-31 23:08:00 +01:00
WintunEnumAdapters ( _In_z_ const WCHAR * Pool , _In_ WINTUN_ENUM_CALLBACK_FUNC Func , _In_ LPARAM Param )
2020-07-21 16:38:00 +02:00
{
2020-11-02 12:07:05 +01:00
HANDLE Mutex = NamespaceTakePoolMutex ( Pool ) ;
2020-07-21 16:38:00 +02:00
if ( ! Mutex )
2020-07-24 08:26:20 +02:00
return ERROR_INVALID_HANDLE ;
2020-10-15 11:32:06 +02:00
DWORD Result = ERROR_SUCCESS ;
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-02 11:52:54 +01:00
Result = 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-10-16 15:51:50 +02:00
BOOL IsOurs ;
if ( IsOurAdapter ( DevInfo , & DevInfoData , & IsOurs ) ! = ERROR_SUCCESS | | ! IsOurs )
2020-07-21 16:38:00 +02:00
continue ;
BOOL IsMember ;
Result = IsPoolMember ( Pool , DevInfo , & DevInfoData , & IsMember ) ;
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-11-02 11:52:54 +01:00
LOG ( WINTUN_LOG_ERR , L " Failed to get pool membership " ) ;
2020-07-21 16:38:00 +02:00
break ;
2020-10-13 19:40:52 +02:00
}
2020-07-21 16:38:00 +02:00
if ( ! IsMember )
continue ;
WINTUN_ADAPTER * Adapter ;
2020-07-21 18:19:15 +02:00
Result = CreateAdapterData ( Pool , DevInfo , & DevInfoData , & Adapter ) ;
2020-07-21 16:38:00 +02:00
if ( Result ! = ERROR_SUCCESS )
2020-10-13 19:40:52 +02:00
{
2020-10-15 12:21:55 +02:00
LOG ( WINTUN_LOG_ERR , L " Failed to create adapter data " ) ;
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-10-24 22:12:47 +02:00
HeapFree ( ModuleHeap , 0 , Adapter ) ;
2020-07-21 16:38:00 +02:00
}
SetupDiDestroyDeviceInfoList ( DevInfo ) ;
cleanupMutex :
2020-10-15 11:32:06 +02:00
NamespaceReleaseMutex ( Mutex ) ;
2020-07-21 16:38:00 +02:00
return Result ;
}