diff options
author | Bernhard Schmidt <berni@debian.org> | 2020-09-30 21:10:50 +0200 |
---|---|---|
committer | Bernhard Schmidt <berni@debian.org> | 2020-09-30 21:10:50 +0200 |
commit | 5246174f27866c0e9e22844d998f3c97cac54050 (patch) | |
tree | 7cdcbac7dfb50f319c053b2f35325c5dc368bdd8 /src/tapctl | |
parent | 57f0b7b331088e489e93ae89ee0aed98381d8806 (diff) |
New upstream version 2.5~rc2upstream/2.5_rc2
Diffstat (limited to 'src/tapctl')
-rw-r--r-- | src/tapctl/main.c | 2 | ||||
-rw-r--r-- | src/tapctl/tap.c | 242 | ||||
-rw-r--r-- | src/tapctl/tap.h | 6 |
3 files changed, 90 insertions, 160 deletions
diff --git a/src/tapctl/main.c b/src/tapctl/main.c index 31bb2ec..d5bc729 100644 --- a/src/tapctl/main.c +++ b/src/tapctl/main.c @@ -237,7 +237,7 @@ _tmain(int argc, LPCTSTR argv[]) } /* Rename the adapter. */ - dwResult = tap_set_adapter_name(&guidAdapter, szName); + dwResult = tap_set_adapter_name(&guidAdapter, szName, FALSE); if (dwResult != ERROR_SUCCESS) { StringFromIID((REFIID)&guidAdapter, &szAdapterId); diff --git a/src/tapctl/tap.c b/src/tapctl/tap.c index 7cb3ded..dd4a10a 100644 --- a/src/tapctl/tap.c +++ b/src/tapctl/tap.c @@ -33,18 +33,69 @@ #include <setupapi.h> #include <stdio.h> #include <tchar.h> +#include <newdev.h> #ifdef _MSC_VER #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "ole32.lib") #pragma comment(lib, "setupapi.lib") +#pragma comment(lib, "newdev.lib") #endif + 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"); #define ADAPTER_REGKEY_PATH_MAX (_countof(TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")) - 1 + 38 + _countof(TEXT("\\")) - 1 + 38 + _countof(TEXT("\\Connection"))) +/** + * Dynamically load a library and find a function in it + * + * @param libname Name of the library to load + * @param funcname Name of the function to find + * @param m Pointer 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. + * + * @return Pointer to the function + * NULL on error -- use GetLastError() to find the error code. + * + **/ +static void * +find_function(const WCHAR *libname, const char *funcname, HMODULE *m) +{ + WCHAR libpath[MAX_PATH]; + void *fptr = NULL; + + /* Make sure the dll is loaded from the system32 folder */ + if (!GetSystemDirectoryW(libpath, _countof(libpath))) + { + return NULL; + } + + size_t len = _countof(libpath) - wcslen(libpath) - 1; + if (len < wcslen(libname) + 1) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return NULL; + } + wcsncat(libpath, L"\\", len); + wcsncat(libpath, libname, len-1); + + *m = LoadLibraryW(libpath); + if (*m == NULL) + { + return NULL; + } + fptr = GetProcAddress(*m, funcname); + if (!fptr) + { + FreeLibrary(*m); + *m = NULL; + return NULL; + } + return fptr; +} /** * Returns length of string of strings @@ -678,6 +729,7 @@ tap_create_adapter( _Out_ LPGUID pguidAdapter) { DWORD dwResult; + HMODULE libnewdev = NULL; if (szHwId == NULL || pbRebootRequired == NULL @@ -746,129 +798,7 @@ tap_create_adapter( goto cleanup_hDevInfoList; } - /* Search for the driver. */ - if (!SetupDiBuildDriverInfoList( - hDevInfoList, - &devinfo_data, - SPDIT_CLASSDRIVER)) - { - dwResult = GetLastError(); - msg(M_NONFATAL, "%s: SetupDiBuildDriverInfoList failed", __FUNCTION__); - goto cleanup_hDevInfoList; - } - DWORDLONG dwlDriverVersion = 0; - DWORD drvinfo_detail_data_size = sizeof(SP_DRVINFO_DETAIL_DATA) + 0x100; - SP_DRVINFO_DETAIL_DATA *drvinfo_detail_data = (SP_DRVINFO_DETAIL_DATA *)malloc(drvinfo_detail_data_size); - if (drvinfo_detail_data == NULL) - { - msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, drvinfo_detail_data_size); - dwResult = ERROR_OUTOFMEMORY; goto cleanup_DriverInfoList; - } - - for (DWORD dwIndex = 0;; dwIndex++) - { - /* Get a driver from the list. */ - SP_DRVINFO_DATA drvinfo_data = { .cbSize = sizeof(SP_DRVINFO_DATA) }; - if (!SetupDiEnumDriverInfo( - hDevInfoList, - &devinfo_data, - SPDIT_CLASSDRIVER, - dwIndex, - &drvinfo_data)) - { - if (GetLastError() == ERROR_NO_MORE_ITEMS) - { - break; - } - else - { - /* Something is wrong with this driver. Skip it. */ - msg(M_WARN | M_ERRNO, "%s: SetupDiEnumDriverInfo(%u) failed", __FUNCTION__, dwIndex); - continue; - } - } - - /* Get driver info details. */ - DWORD dwSize; - drvinfo_detail_data->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); - if (!SetupDiGetDriverInfoDetail( - hDevInfoList, - &devinfo_data, - &drvinfo_data, - drvinfo_detail_data, - drvinfo_detail_data_size, - &dwSize)) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - /* (Re)allocate buffer. */ - if (drvinfo_detail_data) - { - free(drvinfo_detail_data); - } - - drvinfo_detail_data_size = dwSize; - drvinfo_detail_data = (SP_DRVINFO_DETAIL_DATA *)malloc(drvinfo_detail_data_size); - if (drvinfo_detail_data == NULL) - { - msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, drvinfo_detail_data_size); - dwResult = ERROR_OUTOFMEMORY; goto cleanup_DriverInfoList; - } - - /* Re-get driver info details. */ - drvinfo_detail_data->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); - if (!SetupDiGetDriverInfoDetail( - hDevInfoList, - &devinfo_data, - &drvinfo_data, - drvinfo_detail_data, - drvinfo_detail_data_size, - &dwSize)) - { - /* Something is wrong with this driver. Skip it. */ - continue; - } - } - else - { - /* Something is wrong with this driver. Skip it. */ - msg(M_WARN | M_ERRNO, "%s: SetupDiGetDriverInfoDetail(\"%hs\") failed", __FUNCTION__, drvinfo_data.Description); - continue; - } - } - - /* Check the driver version and hardware ID. */ - if (dwlDriverVersion < drvinfo_data.DriverVersion - && drvinfo_detail_data->HardwareID - && _tcszistr(drvinfo_detail_data->HardwareID, szHwId)) - { - /* Newer version and matching hardware ID found. Select the driver. */ - if (!SetupDiSetSelectedDriver( - hDevInfoList, - &devinfo_data, - &drvinfo_data)) - { - /* Something is wrong with this driver. Skip it. */ - msg(M_WARN | M_ERRNO, "%s: SetupDiSetSelectedDriver(\"%hs\") failed", __FUNCTION__, drvinfo_data.Description); - continue; - } - - dwlDriverVersion = drvinfo_data.DriverVersion; - } - } - if (drvinfo_detail_data) - { - free(drvinfo_detail_data); - } - - if (dwlDriverVersion == 0) - { - dwResult = ERROR_NOT_FOUND; - msg(M_NONFATAL, "%s: No driver for device \"%" PRIsLPTSTR "\" installed.", __FUNCTION__, szHwId); - goto cleanup_DriverInfoList; - } - - /* Call appropriate class installer. */ + /* Register the device instance with the PnP Manager */ if (!SetupDiCallClassInstaller( DIF_REGISTERDEVICE, hDevInfoList, @@ -876,43 +806,38 @@ tap_create_adapter( { dwResult = GetLastError(); msg(M_NONFATAL, "%s: SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed", __FUNCTION__); - goto cleanup_DriverInfoList; + goto cleanup_hDevInfoList; } - /* Register device co-installers if any. */ - if (!SetupDiCallClassInstaller( - DIF_REGISTER_COINSTALLERS, - hDevInfoList, - &devinfo_data)) - { - dwResult = GetLastError(); - msg(M_WARN | M_ERRNO, "%s: SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed", __FUNCTION__); - } + /* Install the device using DiInstallDevice() + * We instruct the system to use the best driver in the driver store + * by setting the drvinfo argument of DiInstallDevice as NULL. This + * assumes a driver is already installed in the driver store. + */ +#ifdef HAVE_DIINSTALLDEVICE + if (!DiInstallDevice(hwndParent, hDevInfoList, &devinfo_data, NULL, 0, pbRebootRequired)) +#else + /* mingw does not resolve DiInstallDevice, so load it at run time. */ + typedef BOOL (WINAPI *DiInstallDeviceFn) (HWND, HDEVINFO, SP_DEVINFO_DATA *, + SP_DRVINFO_DATA *, DWORD, BOOL *); + DiInstallDeviceFn installfn + = find_function (L"newdev.dll", "DiInstallDevice", &libnewdev); - /* Install adapters if any. */ - if (!SetupDiCallClassInstaller( - DIF_INSTALLINTERFACES, - hDevInfoList, - &devinfo_data)) + if (!installfn) { dwResult = GetLastError(); - msg(M_WARN | M_ERRNO, "%s: SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed", __FUNCTION__); + msg(M_NONFATAL | M_ERRNO, "%s: Failed to locate DiInstallDevice()", __FUNCTION__); + goto cleanup_hDevInfoList; } - /* Install the device. */ - if (!SetupDiCallClassInstaller( - DIF_INSTALLDEVICE, - hDevInfoList, - &devinfo_data)) + if (!installfn(hwndParent, hDevInfoList, &devinfo_data, NULL, 0, pbRebootRequired)) +#endif { dwResult = GetLastError(); - msg(M_NONFATAL | M_ERRNO, "%s: SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed", __FUNCTION__); + msg(M_NONFATAL | M_ERRNO, "%s: DiInstallDevice failed", __FUNCTION__); goto cleanup_remove_device; } - /* Check if a system reboot is required. (Ignore errors) */ - check_reboot(hDevInfoList, &devinfo_data, pbRebootRequired); - /* Get network adapter ID from registry. Retry for max 30sec. */ dwResult = get_net_adapter_guid(hDevInfoList, &devinfo_data, 30, pguidAdapter); @@ -958,13 +883,11 @@ cleanup_remove_device: } } -cleanup_DriverInfoList: - SetupDiDestroyDriverInfoList( - hDevInfoList, - &devinfo_data, - SPDIT_CLASSDRIVER); - cleanup_hDevInfoList: + if (libnewdev) + { + FreeLibrary(libnewdev); + } SetupDiDestroyDeviceInfoList(hDevInfoList); return dwResult; } @@ -1140,9 +1063,12 @@ ExecCommand(const WCHAR* cmdline) DWORD tap_set_adapter_name( _In_ LPCGUID pguidAdapter, - _In_ LPCTSTR szName) + _In_ LPCTSTR szName, + _In_ BOOL bSilent) { DWORD dwResult; + int msg_flag = bSilent ? M_WARN : M_NONFATAL; + msg_flag |= M_ERRNO; if (pguidAdapter == NULL || szName == NULL) { @@ -1176,7 +1102,7 @@ tap_set_adapter_name( if (dwResult != ERROR_SUCCESS) { SetLastError(dwResult); /* MSDN does not mention RegOpenKeyEx() to set GetLastError(). But we do have an error code. Set last error manually. */ - msg(M_NONFATAL | M_ERRNO, "%s: RegOpenKeyEx(HKLM, \"%" PRIsLPTSTR "\") failed", __FUNCTION__, szRegKey); + msg(msg_flag, "%s: RegOpenKeyEx(HKLM, \"%" PRIsLPTSTR "\") failed", __FUNCTION__, szRegKey); goto cleanup_szAdapterId; } @@ -1185,7 +1111,7 @@ tap_set_adapter_name( if (dwResult != ERROR_SUCCESS) { SetLastError(dwResult); - msg(M_NONFATAL | M_ERRNO, "%s: Error reading adapter name", __FUNCTION__); + msg(msg_flag, "%s: Error reading adapter name", __FUNCTION__); goto cleanup_hKey; } @@ -1203,7 +1129,7 @@ tap_set_adapter_name( if (dwResult != ERROR_SUCCESS) { SetLastError(dwResult); - msg(M_NONFATAL | M_ERRNO, "%s: Error renaming adapter", __FUNCTION__); + msg(msg_flag, "%s: Error renaming adapter", __FUNCTION__); goto cleanup_hKey; } diff --git a/src/tapctl/tap.h b/src/tapctl/tap.h index 102de32..63d791c 100644 --- a/src/tapctl/tap.h +++ b/src/tapctl/tap.h @@ -118,12 +118,16 @@ tap_enable_adapter( * * @param szName New adapter name - must be unique * + * @param bSilent If true, MSI installer won't display message box and + * only print error to log. + * * @return ERROR_SUCCESS on success; Win32 error code otherwise **/ DWORD tap_set_adapter_name( _In_ LPCGUID pguidAdapter, - _In_ LPCTSTR szName); + _In_ LPCTSTR szName, + _In_ BOOL bSilent); /** |