23 #elif defined(_MSC_VER)
39 #pragma comment(lib, "advapi32.lib")
40 #pragma comment(lib, "ole32.lib")
41 #pragma comment(lib, "setupapi.lib")
42 #pragma comment(lib, "newdev.lib")
46 const static GUID
GUID_DEVCLASS_NET = { 0x4d36e972L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
49 #define ADAPTER_REGKEY_PATH_MAX (_countof(TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")) - 1 + 38 + _countof(TEXT("\\")) - 1 + 38 + _countof(TEXT("\\Connection")))
67 WCHAR libpath[MAX_PATH];
71 if (!GetSystemDirectoryW(libpath, _countof(libpath)))
77 const size_t path_length = wcslen(libpath) + 1 + wcslen(libname);
78 if (path_length >= _countof(libpath))
80 SetLastError(ERROR_INSUFFICIENT_BUFFER);
83 wcscat_s(libpath, _countof(libpath), L
"\\");
84 wcscat_s(libpath, _countof(libpath), libname);
86 *m = LoadLibraryW(libpath);
91 fptr = GetProcAddress(*m, funcname);
112 for (s = szz; s[0]; s += _tcslen(s) + 1)
132 for (LPCTSTR s = szzHay; s[0]; s += _tcslen(s) + 1)
134 if (_tcsicmp(s, szNeedle) == 0)
161 _In_ HDEVINFO hDeviceInfoSet,
162 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
163 _Inout_ LPBOOL pbRebootRequired);
184 _In_ HDEVINFO hDeviceInfoSet,
185 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
186 _Inout_ LPBOOL pbRebootRequired)
188 if (pbRebootRequired == NULL)
190 return ERROR_BAD_ARGUMENTS;
193 SP_DEVINSTALL_PARAMS devinstall_params = { .cbSize =
sizeof(SP_DEVINSTALL_PARAMS) };
194 if (!SetupDiGetDeviceInstallParams(
199 DWORD dwResult = GetLastError();
204 if ((devinstall_params.Flags & (DI_NEEDREBOOT | DI_NEEDRESTART)) != 0)
206 *pbRebootRequired = TRUE;
209 return ERROR_SUCCESS;
231 _In_ HDEVINFO hDeviceInfoSet,
232 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
233 _Inout_ LPBOOL pbRebootRequired)
235 SP_REMOVEDEVICE_PARAMS params =
237 .ClassInstallHeader =
239 .cbSize =
sizeof(SP_CLASSINSTALL_HEADER),
240 .InstallFunction = DIF_REMOVE,
242 .Scope = DI_REMOVEDEVICE_GLOBAL,
247 if (!SetupDiSetClassInstallParams(
250 ¶ms.ClassInstallHeader,
251 sizeof(SP_REMOVEDEVICE_PARAMS)))
253 DWORD dwResult = GetLastError();
259 if (!SetupDiCallClassInstaller(
264 DWORD dwResult = GetLastError();
270 check_reboot(hDeviceInfoSet, pDeviceInfoData, pbRebootRequired);
271 return ERROR_SUCCESS;
295 _In_ HDEVINFO hDeviceInfoSet,
296 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
298 _Inout_ LPBOOL pbRebootRequired)
300 SP_PROPCHANGE_PARAMS params =
302 .ClassInstallHeader =
304 .cbSize =
sizeof(SP_CLASSINSTALL_HEADER),
305 .InstallFunction = DIF_PROPERTYCHANGE,
307 .StateChange = bEnable ? DICS_ENABLE : DICS_DISABLE,
308 .Scope = DICS_FLAG_GLOBAL,
313 if (!SetupDiSetClassInstallParams(
316 ¶ms.ClassInstallHeader,
317 sizeof(SP_PROPCHANGE_PARAMS)))
319 DWORD dwResult = GetLastError();
325 if (!SetupDiCallClassInstaller(
330 DWORD dwResult = GetLastError();
331 msg(
M_NONFATAL |
M_ERRNO,
"%s: SetupDiCallClassInstaller(DIF_PROPERTYCHANGE) failed", __FUNCTION__);
336 check_reboot(hDeviceInfoSet, pDeviceInfoData, pbRebootRequired);
337 return ERROR_SUCCESS;
359 _In_ HDEVINFO hDeviceInfoSet,
360 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
361 _Inout_ LPBOOL pbRebootRequired)
385 _In_ HDEVINFO hDeviceInfoSet,
386 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
387 _Inout_ LPBOOL pbRebootRequired)
411 _Out_ LPTSTR *pszValue)
413 if (pszValue == NULL)
415 return ERROR_BAD_ARGUMENTS;
418 DWORD dwValueType = REG_NONE, dwSize = 0;
419 DWORD dwResult = RegQueryValueEx(
426 if (dwResult != ERROR_SUCCESS)
428 SetLastError(dwResult);
439 LPTSTR szValue = (LPTSTR)malloc(dwSize);
442 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwSize);
443 return ERROR_OUTOFMEMORY;
446 dwResult = RegQueryValueEx(
453 if (dwResult != ERROR_SUCCESS)
455 SetLastError(dwResult);
461 if (dwValueType == REG_EXPAND_SZ)
465 dwSizeExp = dwSize * 2,
468 dwSizeExp /
sizeof(TCHAR);
470 dwSizeExp /
sizeof(TCHAR) - 1;
472 LPTSTR szValueExp = (LPTSTR)malloc(dwSizeExp);
473 if (szValueExp == NULL)
476 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwSizeExp);
477 return ERROR_OUTOFMEMORY;
480 DWORD dwCountExpResult = ExpandEnvironmentStrings(
482 szValueExp, dwCountExp
484 if (dwCountExpResult == 0)
491 else if (dwCountExpResult <= dwCountExp)
495 *pszValue = szValueExp;
496 return ERROR_SUCCESS;
503 dwSizeExp = dwCountExpResult *
sizeof(TCHAR);
506 dwSizeExp = (dwCountExpResult + 1) *
sizeof(TCHAR);
508 dwCountExp = dwCountExpResult;
509 szValueExp = (LPTSTR)malloc(dwSizeExp);
510 if (szValueExp == NULL)
513 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwSizeExp);
514 return ERROR_OUTOFMEMORY;
517 dwCountExpResult = ExpandEnvironmentStrings(
519 szValueExp, dwCountExp);
521 *pszValue = szValueExp;
522 return ERROR_SUCCESS;
528 return ERROR_SUCCESS;
534 return ERROR_UNSUPPORTED_TYPE;
559 _In_ HDEVINFO hDeviceInfoSet,
560 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
561 _In_ int iNumAttempts,
562 _Out_ LPGUID pguidAdapter)
564 DWORD dwResult = ERROR_BAD_ARGUMENTS;
566 if (pguidAdapter == NULL || iNumAttempts < 1)
568 return ERROR_BAD_ARGUMENTS;
572 HKEY hKey = SetupDiOpenDevRegKey(
579 if (hKey == INVALID_HANDLE_VALUE)
581 dwResult = GetLastError();
586 while (iNumAttempts > 0)
589 LPTSTR szCfgGuidString = NULL;
590 dwResult = RegQueryValueEx(hKey, TEXT(
"NetCfgInstanceId"), NULL, NULL, NULL, NULL);
591 if (dwResult != ERROR_SUCCESS)
593 if (dwResult == ERROR_FILE_NOT_FOUND && --iNumAttempts > 0)
600 SetLastError(dwResult);
601 msg(
M_NONFATAL |
M_ERRNO,
"%s: querying \"NetCfgInstanceId\" registry value failed", __FUNCTION__);
608 TEXT(
"NetCfgInstanceId"),
610 if (dwResult != ERROR_SUCCESS)
615 dwResult = SUCCEEDED(CLSIDFromString(szCfgGuidString, (LPCLSID)pguidAdapter)) ? ERROR_SUCCESS : ERROR_INVALID_DATA;
616 free(szCfgGuidString);
648 _In_ HDEVINFO hDeviceInfoSet,
649 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
650 _In_ DWORD dwProperty,
651 _Out_opt_ LPDWORD pdwPropertyRegDataType,
652 _Out_ LPVOID *ppData)
654 DWORD dwResult = ERROR_BAD_ARGUMENTS;
658 return ERROR_BAD_ARGUMENTS;
663 DWORD dwRequiredSize = 0;
664 if (SetupDiGetDeviceRegistryProperty(
668 pdwPropertyRegDataType,
674 *ppData = malloc(dwRequiredSize);
677 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwRequiredSize);
678 return ERROR_OUTOFMEMORY;
681 memcpy(*ppData, bBufStack, dwRequiredSize);
682 return ERROR_SUCCESS;
686 dwResult = GetLastError();
687 if (dwResult == ERROR_INSUFFICIENT_BUFFER)
690 *ppData = malloc(dwRequiredSize);
693 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwRequiredSize);
694 return ERROR_OUTOFMEMORY;
697 if (SetupDiGetDeviceRegistryProperty(
701 pdwPropertyRegDataType,
706 return ERROR_SUCCESS;
710 dwResult = GetLastError();
711 msg(
M_NONFATAL |
M_ERRNO,
"%s: SetupDiGetDeviceRegistryProperty(%u) failed", __FUNCTION__, dwProperty);
717 msg(
M_NONFATAL |
M_ERRNO,
"%s: SetupDiGetDeviceRegistryProperty(%u) failed", __FUNCTION__, dwProperty);
727 _In_opt_ LPCTSTR szDeviceDescription,
729 _Inout_ LPBOOL pbRebootRequired,
730 _Out_ LPGUID pguidAdapter)
733 HMODULE libnewdev = NULL;
736 || pbRebootRequired == NULL
737 || pguidAdapter == NULL)
739 return ERROR_BAD_ARGUMENTS;
743 HDEVINFO hDevInfoList = SetupDiCreateDeviceInfoList(&
GUID_DEVCLASS_NET, hwndParent);
744 if (hDevInfoList == INVALID_HANDLE_VALUE)
746 dwResult = GetLastError();
747 msg(
M_NONFATAL,
"%s: SetupDiCreateDeviceInfoList failed", __FUNCTION__);
752 TCHAR szClassName[MAX_CLASS_NAME_LEN];
753 if (!SetupDiClassNameFromGuid(
756 _countof(szClassName),
759 dwResult = GetLastError();
760 msg(
M_NONFATAL,
"%s: SetupDiClassNameFromGuid failed", __FUNCTION__);
761 goto cleanup_hDevInfoList;
765 SP_DEVINFO_DATA devinfo_data = { .cbSize =
sizeof(SP_DEVINFO_DATA) };
766 if (!SetupDiCreateDeviceInfo(
775 dwResult = GetLastError();
776 msg(
M_NONFATAL,
"%s: SetupDiCreateDeviceInfo failed", __FUNCTION__);
777 goto cleanup_hDevInfoList;
781 if (!SetupDiSetSelectedDevice(
785 dwResult = GetLastError();
786 msg(
M_NONFATAL,
"%s: SetupDiSetSelectedDevice failed", __FUNCTION__);
787 goto cleanup_hDevInfoList;
791 if (!SetupDiSetDeviceRegistryProperty(
795 (
const BYTE *)szHwId, (DWORD)((_tcslen(szHwId) + 1) *
sizeof(TCHAR))))
797 dwResult = GetLastError();
798 msg(
M_NONFATAL,
"%s: SetupDiSetDeviceRegistryProperty failed", __FUNCTION__);
799 goto cleanup_hDevInfoList;
803 if (!SetupDiCallClassInstaller(
808 dwResult = GetLastError();
809 msg(
M_NONFATAL,
"%s: SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed", __FUNCTION__);
810 goto cleanup_hDevInfoList;
818 #ifdef HAVE_DIINSTALLDEVICE
819 if (!DiInstallDevice(hwndParent, hDevInfoList, &devinfo_data, NULL, 0, pbRebootRequired))
822 typedef BOOL (WINAPI *DiInstallDeviceFn)(HWND, HDEVINFO, SP_DEVINFO_DATA *,
823 SP_DRVINFO_DATA *, DWORD, BOOL *);
824 DiInstallDeviceFn installfn
825 =
find_function(L
"newdev.dll",
"DiInstallDevice", &libnewdev);
829 dwResult = GetLastError();
831 goto cleanup_hDevInfoList;
834 if (!installfn(hwndParent, hDevInfoList, &devinfo_data, NULL, 0, pbRebootRequired))
837 dwResult = GetLastError();
839 goto cleanup_remove_device;
845 cleanup_remove_device:
846 if (dwResult != ERROR_SUCCESS)
849 SP_REMOVEDEVICE_PARAMS removedevice_params =
851 .ClassInstallHeader =
853 .cbSize =
sizeof(SP_CLASSINSTALL_HEADER),
854 .InstallFunction = DIF_REMOVE,
856 .Scope = DI_REMOVEDEVICE_GLOBAL,
861 if (SetupDiSetClassInstallParams(
864 &removedevice_params.ClassInstallHeader,
865 sizeof(SP_REMOVEDEVICE_PARAMS)))
868 if (SetupDiCallClassInstaller(
874 check_reboot(hDevInfoList, &devinfo_data, pbRebootRequired);
887 cleanup_hDevInfoList:
890 FreeLibrary(libnewdev);
892 SetupDiDestroyDeviceInfoList(hDevInfoList);
920 _In_ LPCGUID pguidAdapter,
922 _Inout_ LPBOOL pbRebootRequired)
926 if (pguidAdapter == NULL)
928 return ERROR_BAD_ARGUMENTS;
932 HDEVINFO hDevInfoList = SetupDiGetClassDevsEx(
940 if (hDevInfoList == INVALID_HANDLE_VALUE)
942 dwResult = GetLastError();
943 msg(
M_NONFATAL,
"%s: SetupDiGetClassDevsEx failed", __FUNCTION__);
948 SP_DEVINFO_LIST_DETAIL_DATA devinfo_list_detail_data = { .cbSize =
sizeof(SP_DEVINFO_LIST_DETAIL_DATA) };
949 if (!SetupDiGetDeviceInfoListDetail(hDevInfoList, &devinfo_list_detail_data))
951 dwResult = GetLastError();
952 msg(
M_NONFATAL,
"%s: SetupDiGetDeviceInfoListDetail failed", __FUNCTION__);
953 goto cleanup_hDevInfoList;
957 for (DWORD dwIndex = 0;; dwIndex++)
960 SP_DEVINFO_DATA devinfo_data = { .cbSize =
sizeof(SP_DEVINFO_DATA) };
961 if (!SetupDiEnumDeviceInfo(
966 if (GetLastError() == ERROR_NO_MORE_ITEMS)
968 LPOLESTR szAdapterId = NULL;
969 StringFromIID((REFIID)pguidAdapter, &szAdapterId);
971 CoTaskMemFree(szAdapterId);
972 dwResult = ERROR_FILE_NOT_FOUND;
973 goto cleanup_hDevInfoList;
978 msg(
M_WARN |
M_ERRNO,
"%s: SetupDiEnumDeviceInfo(%u) failed", __FUNCTION__, dwIndex);
986 if (dwResult != ERROR_SUCCESS)
993 if (memcmp(pguidAdapter, &guidAdapter,
sizeof(GUID)) == 0)
995 dwResult = funcOperation(hDevInfoList, &devinfo_data, pbRebootRequired);
1000 cleanup_hDevInfoList:
1001 SetupDiDestroyDeviceInfoList(hDevInfoList);
1009 _In_ LPCGUID pguidAdapter,
1010 _Inout_ LPBOOL pbRebootRequired)
1019 _In_ LPCGUID pguidAdapter,
1021 _Inout_ LPBOOL pbRebootRequired)
1032 PROCESS_INFORMATION pi;
1033 DWORD proc_flags = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
1034 WCHAR *cmdline_dup = NULL;
1036 ZeroMemory(&si,
sizeof(si));
1037 ZeroMemory(&pi,
sizeof(pi));
1042 cmdline_dup = _wcsdup(cmdline);
1043 if (cmdline_dup && CreateProcessW(NULL, cmdline_dup, NULL, NULL, FALSE,
1044 proc_flags, NULL, NULL, &si, &pi))
1046 WaitForSingleObject(pi.hProcess, INFINITE);
1047 if (!GetExitCodeProcess(pi.hProcess, &exit_code))
1049 exit_code = GetLastError();
1052 CloseHandle(pi.hProcess);
1053 CloseHandle(pi.hThread);
1057 exit_code = GetLastError();
1066 _In_ LPCGUID pguidAdapter,
1074 if (pguidAdapter == NULL ||
szName == NULL)
1076 return ERROR_BAD_ARGUMENTS;
1080 LPOLESTR szDevClassNetId = NULL;
1084 LPOLESTR szAdapterId = NULL;
1085 StringFromIID((REFIID)pguidAdapter, &szAdapterId);
1090 szRegKey, _countof(szRegKey),
1097 dwResult = RegOpenKeyEx(
1103 if (dwResult != ERROR_SUCCESS)
1105 SetLastError(dwResult);
1106 msg(msg_flag,
"%s: RegOpenKeyEx(HKLM, \"%" PRIsLPTSTR "\") failed", __FUNCTION__, szRegKey);
1107 goto cleanup_szAdapterId;
1110 LPTSTR szOldName = NULL;
1112 if (dwResult != ERROR_SUCCESS)
1114 SetLastError(dwResult);
1115 msg(msg_flag,
"%s: Error reading adapter name", __FUNCTION__);
1120 const TCHAR *szFmt = TEXT(
"netsh interface set interface name=\"%")
1122 size_t ncmdline = _tcslen(szFmt) + _tcslen(szOldName) + _tcslen(
szName) + 1;
1123 WCHAR *szCmdLine = malloc(ncmdline *
sizeof(TCHAR));
1124 _stprintf_s(szCmdLine, ncmdline, szFmt, szOldName,
szName);
1131 if (dwResult != ERROR_SUCCESS)
1133 SetLastError(dwResult);
1134 msg(msg_flag,
"%s: Error renaming adapter", __FUNCTION__);
1140 cleanup_szAdapterId:
1141 CoTaskMemFree(szAdapterId);
1142 CoTaskMemFree(szDevClassNetId);
1155 if (ppAdapter == NULL)
1157 return ERROR_BAD_ARGUMENTS;
1161 HDEVINFO hDevInfoList = SetupDiGetClassDevsEx(
1169 if (hDevInfoList == INVALID_HANDLE_VALUE)
1171 dwResult = GetLastError();
1172 msg(
M_NONFATAL,
"%s: SetupDiGetClassDevsEx failed", __FUNCTION__);
1177 SP_DEVINFO_LIST_DETAIL_DATA devinfo_list_detail_data = { .cbSize =
sizeof(SP_DEVINFO_LIST_DETAIL_DATA) };
1178 if (!SetupDiGetDeviceInfoListDetail(hDevInfoList, &devinfo_list_detail_data))
1180 dwResult = GetLastError();
1181 msg(
M_NONFATAL,
"%s: SetupDiGetDeviceInfoListDetail failed", __FUNCTION__);
1182 goto cleanup_hDevInfoList;
1186 LPOLESTR szDevClassNetId = NULL;
1192 for (DWORD dwIndex = 0;; dwIndex++)
1195 SP_DEVINFO_DATA devinfo_data = { .cbSize =
sizeof(SP_DEVINFO_DATA) };
1196 if (!SetupDiEnumDeviceInfo(
1201 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1208 msg(
M_WARN |
M_ERRNO,
"%s: SetupDiEnumDeviceInfo(%u) failed", __FUNCTION__, dwIndex);
1214 DWORD dwDataType = REG_NONE;
1215 LPTSTR szzDeviceHardwareIDs = NULL;
1221 (LPVOID)&szzDeviceHardwareIDs);
1222 if (dwResult != ERROR_SUCCESS)
1229 if (dwDataType == REG_SZ)
1231 if (szzHwIDs && !
_tcszistr(szzHwIDs, szzDeviceHardwareIDs))
1234 goto cleanup_szzDeviceHardwareIDs;
1237 else if (dwDataType == REG_MULTI_SZ)
1241 for (LPTSTR s = szzDeviceHardwareIDs;; s += _tcslen(s) + 1)
1246 goto cleanup_szzDeviceHardwareIDs;
1259 goto cleanup_szzDeviceHardwareIDs;
1265 if (dwResult != ERROR_SUCCESS)
1268 goto cleanup_szzDeviceHardwareIDs;
1272 LPOLESTR szAdapterId = NULL;
1273 StringFromIID((REFIID)&guidAdapter, &szAdapterId);
1278 szRegKey, _countof(szRegKey),
1285 dwResult = RegOpenKeyEx(
1291 if (dwResult != ERROR_SUCCESS)
1293 SetLastError(dwResult);
1295 goto cleanup_szAdapterId;
1304 if (dwResult != ERROR_SUCCESS)
1306 SetLastError(dwResult);
1312 size_t hwid_size = (
_tcszlen(szzDeviceHardwareIDs) + 1) *
sizeof(TCHAR);
1313 size_t name_size = (_tcslen(
szName) + 1) *
sizeof(TCHAR);
1318 dwResult = ERROR_OUTOFMEMORY;
goto cleanup_szName;
1321 memcpy(&node->
guid, &guidAdapter,
sizeof(GUID));
1329 pAdapterTail->
pNext = node;
1330 pAdapterTail = node;
1334 *ppAdapter = pAdapterTail = node;
1341 cleanup_szAdapterId:
1342 CoTaskMemFree(szAdapterId);
1343 cleanup_szzDeviceHardwareIDs:
1344 free(szzDeviceHardwareIDs);
1347 dwResult = ERROR_SUCCESS;
1349 CoTaskMemFree(szDevClassNetId);
1350 cleanup_hDevInfoList:
1351 SetupDiDestroyDeviceInfoList(hDevInfoList);
1361 while (pAdapterList)
1364 pAdapterList = pAdapterList->
pNext;