OpenVPN
Macros | Typedefs | Functions | Variables
tap.c File Reference
#include "tap.h"
#include "error.h"
#include <windows.h>
#include <cfgmgr32.h>
#include <objbase.h>
#include <setupapi.h>
#include <stdio.h>
#include <tchar.h>
#include <newdev.h>
Include dependency graph for tap.c:

Go to the source code of this file.

Macros

#define ADAPTER_REGKEY_PATH_MAX   (_countof(TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")) - 1 + 38 + _countof(TEXT("\\")) - 1 + 38 + _countof(TEXT("\\Connection")))
 

Typedefs

typedef DWORD(* devop_func_t) (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _Inout_ LPBOOL pbRebootRequired)
 Function that performs a specific task on a device. More...
 

Functions

static void * find_function (const WCHAR *libname, const char *funcname, HMODULE *m)
 Dynamically load a library and find a function in it. More...
 
static size_t _tcszlen (_In_z_ LPCTSTR szz)
 Returns length of string of strings. More...
 
static LPCTSTR _tcszistr (_In_z_ LPCTSTR szzHay, _In_z_ LPCTSTR szNeedle)
 Checks if string is contained in the string of strings. More...
 
static DWORD check_reboot (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _Inout_ LPBOOL pbRebootRequired)
 Checks device install parameters if a system reboot is required. More...
 
static DWORD delete_device (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _Inout_ LPBOOL pbRebootRequired)
 Deletes the device. More...
 
static DWORD change_device_state (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _In_ BOOL bEnable, _Inout_ LPBOOL pbRebootRequired)
 Changes the device state. More...
 
static DWORD enable_device (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _Inout_ LPBOOL pbRebootRequired)
 Enables the device. More...
 
static DWORD disable_device (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _Inout_ LPBOOL pbRebootRequired)
 Disables the device. More...
 
static DWORD get_reg_string (_In_ HKEY hKey, _In_ LPCTSTR szName, _Out_ LPTSTR *pszValue)
 Reads string value from registry key. More...
 
static DWORD get_net_adapter_guid (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _In_ int iNumAttempts, _Out_ LPGUID pguidAdapter)
 Returns network adapter ID. More...
 
static DWORD get_device_reg_property (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _In_ DWORD dwProperty, _Out_opt_ LPDWORD pdwPropertyRegDataType, _Out_ LPVOID *ppData)
 Returns a specified Plug and Play device property. More...
 
DWORD tap_create_adapter (_In_opt_ HWND hwndParent, _In_opt_ LPCTSTR szDeviceDescription, _In_ LPCTSTR szHwId, _Inout_ LPBOOL pbRebootRequired, _Out_ LPGUID pguidAdapter)
 Creates a TUN/TAP adapter. More...
 
static DWORD execute_on_first_adapter (_In_opt_ HWND hwndParent, _In_ LPCGUID pguidAdapter, _In_ devop_func_t funcOperation, _Inout_ LPBOOL pbRebootRequired)
 Performs a given task on an adapter. More...
 
DWORD tap_delete_adapter (_In_opt_ HWND hwndParent, _In_ LPCGUID pguidAdapter, _Inout_ LPBOOL pbRebootRequired)
 Deletes an adapter. More...
 
DWORD tap_enable_adapter (_In_opt_ HWND hwndParent, _In_ LPCGUID pguidAdapter, _In_ BOOL bEnable, _Inout_ LPBOOL pbRebootRequired)
 Enables or disables an adapter. More...
 
static DWORD ExecCommand (const WCHAR *cmdline)
 
DWORD tap_set_adapter_name (_In_ LPCGUID pguidAdapter, _In_ LPCTSTR szName, _In_ BOOL bSilent)
 Sets adapter name. More...
 
DWORD tap_list_adapters (_In_opt_ HWND hwndParent, _In_opt_ LPCTSTR szzHwIDs, _Out_ struct tap_adapter_node **ppAdapter)
 Creates a list of existing network adapters. More...
 
void tap_free_adapter_list (_In_ struct tap_adapter_node *pAdapterList)
 Frees a list of network adapters. More...
 

Variables

const static GUID GUID_DEVCLASS_NET = { 0x4d36e972L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } }
 
const static TCHAR szAdapterRegKeyPathTemplate [] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\%") TEXT(PRIsLPOLESTR) TEXT("\\%") TEXT(PRIsLPOLESTR) TEXT("\\Connection")
 

Macro Definition Documentation

◆ ADAPTER_REGKEY_PATH_MAX

#define ADAPTER_REGKEY_PATH_MAX   (_countof(TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")) - 1 + 38 + _countof(TEXT("\\")) - 1 + 38 + _countof(TEXT("\\Connection")))

Definition at line 47 of file tap.c.

Typedef Documentation

◆ devop_func_t

typedef DWORD(* devop_func_t) (_In_ HDEVINFO hDeviceInfoSet, _In_ PSP_DEVINFO_DATA pDeviceInfoData, _Inout_ LPBOOL pbRebootRequired)

Function that performs a specific task on a device.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 158 of file tap.c.

Function Documentation

◆ _tcszistr()

static LPCTSTR _tcszistr ( _In_z_ LPCTSTR  szzHay,
_In_z_ LPCTSTR  szNeedle 
)
static

Checks if string is contained in the string of strings.

Comparison is made case-insensitive.

Parameters
szzHayPointer to a string of strings (terminated by an empty string) we are looking in
szNeedleThe string we are searching for
Returns
Pointer to the string in szzHay that matches szNeedle is found; NULL otherwise

Definition at line 128 of file tap.c.

Referenced by tap_list_adapters().

◆ _tcszlen()

static size_t _tcszlen ( _In_z_ LPCTSTR  szz)
inlinestatic

Returns length of string of strings.

Parameters
szzPointer to a string of strings (terminated by an empty string)
Returns
Number of characters not counting the final zero terminator

Definition at line 107 of file tap.c.

Referenced by tap_list_adapters().

◆ change_device_state()

static DWORD change_device_state ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_In_ BOOL  bEnable,
_Inout_ LPBOOL  pbRebootRequired 
)
static

Changes the device state.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
bEnableTRUE to enable the device; FALSE to disable.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 292 of file tap.c.

References check_reboot(), M_ERRNO, M_NONFATAL, and msg.

Referenced by disable_device(), and enable_device().

◆ check_reboot()

static DWORD check_reboot ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_Inout_ LPBOOL  pbRebootRequired 
)
static

Checks device install parameters if a system reboot is required.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 181 of file tap.c.

References M_ERRNO, M_NONFATAL, and msg.

Referenced by change_device_state(), delete_device(), and tap_create_adapter().

◆ delete_device()

static DWORD delete_device ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_Inout_ LPBOOL  pbRebootRequired 
)
static

Deletes the device.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 228 of file tap.c.

References check_reboot(), M_ERRNO, M_NONFATAL, and msg.

Referenced by tap_delete_adapter().

◆ disable_device()

static DWORD disable_device ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_Inout_ LPBOOL  pbRebootRequired 
)
static

Disables the device.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 382 of file tap.c.

References change_device_state().

Referenced by tap_enable_adapter().

◆ enable_device()

static DWORD enable_device ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_Inout_ LPBOOL  pbRebootRequired 
)
static

Enables the device.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 356 of file tap.c.

References change_device_state().

Referenced by tap_enable_adapter().

◆ ExecCommand()

static DWORD ExecCommand ( const WCHAR *  cmdline)
static

Definition at line 1026 of file tap.c.

Referenced by tap_set_adapter_name().

◆ execute_on_first_adapter()

static DWORD execute_on_first_adapter ( _In_opt_ HWND  hwndParent,
_In_ LPCGUID  pguidAdapter,
_In_ devop_func_t  funcOperation,
_Inout_ LPBOOL  pbRebootRequired 
)
static

Performs a given task on an adapter.

Parameters
hwndParentA handle to the top-level window to use for any user adapter that is related to non-device-specific actions (such as a select-device dialog box that uses the global class driver list). This handle is optional and can be NULL. If a specific top-level window is not required, set hwndParent to NULL.
pguidAdapterA pointer to GUID that contains network adapter ID.
funcOperationA pointer for the function to perform specific task on the adapter.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 916 of file tap.c.

References get_net_adapter_guid(), GUID_DEVCLASS_NET, M_ERRNO, M_NONFATAL, M_WARN, msg, and PRIsLPOLESTR.

Referenced by tap_delete_adapter(), and tap_enable_adapter().

◆ find_function()

static void* find_function ( const WCHAR *  libname,
const char *  funcname,
HMODULE *  m 
)
static

Dynamically load a library and find a function in it.

Parameters
libnameName of the library to load
funcnameName of the function to find
mPointer to a module. On return this is set to the the handle to the loaded library. The caller must free it by calling FreeLibrary() if not NULL.
Returns
Pointer to the function NULL on error – use GetLastError() to find the error code.

Definition at line 63 of file tap.c.

Referenced by tap_create_adapter().

◆ get_device_reg_property()

static DWORD get_device_reg_property ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_In_ DWORD  dwProperty,
_Out_opt_ LPDWORD  pdwPropertyRegDataType,
_Out_ LPVOID *  ppData 
)
static

Returns a specified Plug and Play device property.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
dwPropertySpecifies the property to be retrieved. See https://msdn.microsoft.com/en-us/library/windows/hardware/ff551967.aspx

@pdwPropertyRegDataType A pointer to a variable that receives the data type of the property that is being retrieved. This is one of the standard registry data types. This parameter is optional and can be NULL.

Parameters
ppDataA pointer to pointer to data that receives the device property. The data must be released with free() after use.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 645 of file tap.c.

References M_ERRNO, M_FATAL, M_NONFATAL, and msg.

Referenced by tap_list_adapters().

◆ get_net_adapter_guid()

static DWORD get_net_adapter_guid ( _In_ HDEVINFO  hDeviceInfoSet,
_In_ PSP_DEVINFO_DATA  pDeviceInfoData,
_In_ int  iNumAttempts,
_Out_ LPGUID  pguidAdapter 
)
static

Returns network adapter ID.

Parameters
hDeviceInfoSetA handle to a device information set that contains a device information element that represents the device.
pDeviceInfoDataA pointer to an SP_DEVINFO_DATA structure that specifies the device information element in hDeviceInfoSet.
iNumAttemptsAfter the device is created, it might take some time before the registry key is populated. This parameter specifies the number of attempts to read NetCfgInstanceId value from registry. A 1sec sleep is inserted between retry attempts.
pguidAdapterA pointer to GUID that receives network adapter ID.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 556 of file tap.c.

References get_reg_string(), M_ERRNO, M_NONFATAL, and msg.

Referenced by execute_on_first_adapter(), tap_create_adapter(), and tap_list_adapters().

◆ get_reg_string()

static DWORD get_reg_string ( _In_ HKEY  hKey,
_In_ LPCTSTR  szName,
_Out_ LPTSTR *  pszValue 
)
static

Reads string value from registry key.

Parameters
hKeyHandle of the registry key to read from. Must be opened with read access.
szNameName of the value to read.
pszValuePointer to string to retrieve registry value. If the value type is REG_EXPAND_SZ the value is expanded using ExpandEnvironmentStrings(). The string must be released with free() after use.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 406 of file tap.c.

References M_ERRNO, M_FATAL, M_NONFATAL, msg, PRIsLPTSTR, and tap_adapter_node::szName.

Referenced by get_net_adapter_guid(), tap_list_adapters(), and tap_set_adapter_name().

◆ tap_create_adapter()

DWORD tap_create_adapter ( _In_opt_ HWND  hwndParent,
_In_opt_ LPCTSTR  szDeviceDescription,
_In_ LPCTSTR  szHwId,
_Inout_ LPBOOL  pbRebootRequired,
_Out_ LPGUID  pguidAdapter 
)

Creates a TUN/TAP adapter.

Parameters
hwndParentA handle to the top-level window to use for any user adapter that is related to non-device-specific actions (such as a select-device dialog box that uses the global class driver list). This handle is optional and can be NULL. If a specific top-level window is not required, set hwndParent to NULL.
szDeviceDescriptionA pointer to a NULL-terminated string that supplies the text description of the device. This pointer is optional and can be NULL.
szHwIdA pointer to a NULL-terminated string that supplies the hardware id of the device (e.g. "root\\tap0901", "Wintun").
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
pguidAdapterA pointer to GUID that receives network adapter ID.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 723 of file tap.c.

References check_reboot(), find_function(), get_net_adapter_guid(), GUID_DEVCLASS_NET, M_ERRNO, M_NONFATAL, and msg.

Referenced by _tmain(), and ProcessDeferredAction().

◆ tap_delete_adapter()

DWORD tap_delete_adapter ( _In_opt_ HWND  hwndParent,
_In_ LPCGUID  pguidAdapter,
_Inout_ LPBOOL  pbRebootRequired 
)

Deletes an adapter.

Parameters
hwndParentA handle to the top-level window to use for any user adapter that is related to non-device-specific actions (such as a select-device dialog box that uses the global class driver list). This handle is optional and can be NULL. If a specific top-level window is not required, set hwndParent to NULL.
pguidAdapterA pointer to GUID that contains network adapter ID.
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 1005 of file tap.c.

References delete_device(), and execute_on_first_adapter().

Referenced by _tmain(), and ProcessDeferredAction().

◆ tap_enable_adapter()

DWORD tap_enable_adapter ( _In_opt_ HWND  hwndParent,
_In_ LPCGUID  pguidAdapter,
_In_ BOOL  bEnable,
_Inout_ LPBOOL  pbRebootRequired 
)

Enables or disables an adapter.

Parameters
hwndParentA handle to the top-level window to use for any user adapter that is related to non-device-specific actions (such as a select-device dialog box that uses the global class driver list). This handle is optional and can be NULL. If a specific top-level window is not required, set hwndParent to NULL.
pguidAdapterA pointer to GUID that contains network adapter ID.
bEnableTRUE to enable; FALSE to disable
pbRebootRequiredA pointer to a BOOL flag. If the device requires a system restart, this flag is set to TRUE. Otherwise, the flag is left unmodified. This allows the flag to be globally initialized to FALSE and reused for multiple adapter manipulations.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 1015 of file tap.c.

References disable_device(), enable_device(), and execute_on_first_adapter().

Referenced by ProcessDeferredAction().

◆ tap_free_adapter_list()

void tap_free_adapter_list ( _In_ struct tap_adapter_node pAdapterList)

Frees a list of network adapters.

Parameters
pAdapterListA pointer to the first adapter in the list to free.

Definition at line 1355 of file tap.c.

References tap_adapter_node::pNext.

Referenced by _tmain(), find_adapters(), ProcessDeferredAction(), schedule_adapter_create(), and schedule_adapter_delete().

◆ tap_list_adapters()

DWORD tap_list_adapters ( _In_opt_ HWND  hwndParent,
_In_opt_ LPCTSTR  szzHwIDs,
_Out_ struct tap_adapter_node **  ppAdapterList 
)

Creates a list of existing network adapters.

Parameters
hwndParentA handle to the top-level window to use for any user adapter that is related to non-device-specific actions (such as a select-device dialog box that uses the global class driver list). This handle is optional and can be NULL. If a specific top-level window is not required, set hwndParent to NULL.
szzHwIDsA string of strings that supplies the list of hardware IDs of the device. This pointer is optional and can be NULL. When NULL, all network adapters found are added to the list.
ppAdapterListA pointer to the list to receive pointer to the first adapter in the list. After the list is no longer required, free it using tap_free_adapter_list().
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 1146 of file tap.c.

References _tcszistr(), _tcszlen(), ADAPTER_REGKEY_PATH_MAX, get_device_reg_property(), get_net_adapter_guid(), get_reg_string(), tap_adapter_node::guid, GUID_DEVCLASS_NET, M_ERRNO, M_FATAL, M_NONFATAL, M_WARN, msg, tap_adapter_node::pNext, PRIsLPOLESTR, PRIsLPTSTR, szAdapterRegKeyPathTemplate, tap_adapter_node::szName, and tap_adapter_node::szzHardwareIDs.

Referenced by _tmain(), find_adapters(), ProcessDeferredAction(), schedule_adapter_create(), and schedule_adapter_delete().

◆ tap_set_adapter_name()

DWORD tap_set_adapter_name ( _In_ LPCGUID  pguidAdapter,
_In_ LPCTSTR  szName,
_In_ BOOL  bSilent 
)

Sets adapter name.

Parameters
pguidAdapterA pointer to GUID that contains network adapter ID.
szNameNew adapter name - must be unique
bSilentIf true, MSI installer won't display message box and only print error to log.
Returns
ERROR_SUCCESS on success; Win32 error code otherwise

Definition at line 1063 of file tap.c.

References ADAPTER_REGKEY_PATH_MAX, ExecCommand(), get_reg_string(), GUID_DEVCLASS_NET, M_ERRNO, M_NONFATAL, M_WARN, msg, PRIsLPTSTR, szAdapterRegKeyPathTemplate, and tap_adapter_node::szName.

Referenced by _tmain(), and ProcessDeferredAction().

Variable Documentation

◆ GUID_DEVCLASS_NET

const static GUID GUID_DEVCLASS_NET = { 0x4d36e972L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } }
static

◆ szAdapterRegKeyPathTemplate

const static TCHAR szAdapterRegKeyPathTemplate[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\%") TEXT(PRIsLPOLESTR) TEXT("\\%") TEXT(PRIsLPOLESTR) TEXT("\\Connection")
static

Definition at line 46 of file tap.c.

Referenced by tap_list_adapters(), and tap_set_adapter_name().