37 #pragma comment(lib, "advapi32.lib")
38 #pragma comment(lib, "ole32.lib")
39 #pragma comment(lib, "setupapi.lib")
40 #pragma comment(lib, "newdev.lib")
44 const static GUID
GUID_DEVCLASS_NET = { 0x4d36e972L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
47 #define ADAPTER_REGKEY_PATH_MAX (_countof(TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\")) - 1 + 38 + _countof(TEXT("\\")) - 1 + 38 + _countof(TEXT("\\Connection")))
65 WCHAR libpath[MAX_PATH];
69 if (!GetSystemDirectoryW(libpath, _countof(libpath)))
75 const size_t path_length = wcslen(libpath) + 1 + wcslen(libname);
76 if (path_length >= _countof(libpath))
78 SetLastError(ERROR_INSUFFICIENT_BUFFER);
81 wcscat_s(libpath, _countof(libpath), L
"\\");
82 wcscat_s(libpath, _countof(libpath), libname);
84 *m = LoadLibraryW(libpath);
89 fptr = GetProcAddress(*m, funcname);
110 for (s = szz; s[0]; s += _tcslen(s) + 1)
130 for (LPCTSTR s = szzHay; s[0]; s += _tcslen(s) + 1)
132 if (_tcsicmp(s, szNeedle) == 0)
159 _In_ HDEVINFO hDeviceInfoSet,
160 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
161 _Inout_ LPBOOL pbRebootRequired);
182 _In_ HDEVINFO hDeviceInfoSet,
183 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
184 _Inout_ LPBOOL pbRebootRequired)
186 if (pbRebootRequired == NULL)
188 return ERROR_BAD_ARGUMENTS;
191 SP_DEVINSTALL_PARAMS devinstall_params = { .cbSize =
sizeof(SP_DEVINSTALL_PARAMS) };
192 if (!SetupDiGetDeviceInstallParams(
197 DWORD dwResult = GetLastError();
202 if ((devinstall_params.Flags & (DI_NEEDREBOOT | DI_NEEDRESTART)) != 0)
204 *pbRebootRequired = TRUE;
207 return ERROR_SUCCESS;
229 _In_ HDEVINFO hDeviceInfoSet,
230 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
231 _Inout_ LPBOOL pbRebootRequired)
233 SP_REMOVEDEVICE_PARAMS params =
235 .ClassInstallHeader =
237 .cbSize =
sizeof(SP_CLASSINSTALL_HEADER),
238 .InstallFunction = DIF_REMOVE,
240 .Scope = DI_REMOVEDEVICE_GLOBAL,
245 if (!SetupDiSetClassInstallParams(
248 ¶ms.ClassInstallHeader,
249 sizeof(SP_REMOVEDEVICE_PARAMS)))
251 DWORD dwResult = GetLastError();
257 if (!SetupDiCallClassInstaller(
262 DWORD dwResult = GetLastError();
268 check_reboot(hDeviceInfoSet, pDeviceInfoData, pbRebootRequired);
269 return ERROR_SUCCESS;
293 _In_ HDEVINFO hDeviceInfoSet,
294 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
296 _Inout_ LPBOOL pbRebootRequired)
298 SP_PROPCHANGE_PARAMS params =
300 .ClassInstallHeader =
302 .cbSize =
sizeof(SP_CLASSINSTALL_HEADER),
303 .InstallFunction = DIF_PROPERTYCHANGE,
305 .StateChange = bEnable ? DICS_ENABLE : DICS_DISABLE,
306 .Scope = DICS_FLAG_GLOBAL,
311 if (!SetupDiSetClassInstallParams(
314 ¶ms.ClassInstallHeader,
315 sizeof(SP_PROPCHANGE_PARAMS)))
317 DWORD dwResult = GetLastError();
323 if (!SetupDiCallClassInstaller(
328 DWORD dwResult = GetLastError();
329 msg(
M_NONFATAL |
M_ERRNO,
"%s: SetupDiCallClassInstaller(DIF_PROPERTYCHANGE) failed", __FUNCTION__);
334 check_reboot(hDeviceInfoSet, pDeviceInfoData, pbRebootRequired);
335 return ERROR_SUCCESS;
357 _In_ HDEVINFO hDeviceInfoSet,
358 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
359 _Inout_ LPBOOL pbRebootRequired)
383 _In_ HDEVINFO hDeviceInfoSet,
384 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
385 _Inout_ LPBOOL pbRebootRequired)
409 _Out_ LPTSTR *pszValue)
411 if (pszValue == NULL)
413 return ERROR_BAD_ARGUMENTS;
416 DWORD dwValueType = REG_NONE, dwSize = 0;
417 DWORD dwResult = RegQueryValueEx(
424 if (dwResult != ERROR_SUCCESS)
426 SetLastError(dwResult);
437 LPTSTR szValue = (LPTSTR)malloc(dwSize);
440 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwSize);
441 return ERROR_OUTOFMEMORY;
444 dwResult = RegQueryValueEx(
451 if (dwResult != ERROR_SUCCESS)
453 SetLastError(dwResult);
459 if (dwValueType == REG_EXPAND_SZ)
463 dwSizeExp = dwSize * 2,
466 dwSizeExp /
sizeof(TCHAR);
468 dwSizeExp /
sizeof(TCHAR) - 1;
470 LPTSTR szValueExp = (LPTSTR)malloc(dwSizeExp);
471 if (szValueExp == NULL)
474 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwSizeExp);
475 return ERROR_OUTOFMEMORY;
478 DWORD dwCountExpResult = ExpandEnvironmentStrings(
480 szValueExp, dwCountExp
482 if (dwCountExpResult == 0)
489 else if (dwCountExpResult <= dwCountExp)
493 *pszValue = szValueExp;
494 return ERROR_SUCCESS;
501 dwSizeExp = dwCountExpResult *
sizeof(TCHAR);
504 dwSizeExp = (dwCountExpResult + 1) *
sizeof(TCHAR);
506 dwCountExp = dwCountExpResult;
507 szValueExp = (LPTSTR)malloc(dwSizeExp);
508 if (szValueExp == NULL)
511 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwSizeExp);
512 return ERROR_OUTOFMEMORY;
515 dwCountExpResult = ExpandEnvironmentStrings(
517 szValueExp, dwCountExp);
519 *pszValue = szValueExp;
520 return ERROR_SUCCESS;
526 return ERROR_SUCCESS;
532 return ERROR_UNSUPPORTED_TYPE;
557 _In_ HDEVINFO hDeviceInfoSet,
558 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
559 _In_ int iNumAttempts,
560 _Out_ LPGUID pguidAdapter)
562 DWORD dwResult = ERROR_BAD_ARGUMENTS;
564 if (pguidAdapter == NULL || iNumAttempts < 1)
566 return ERROR_BAD_ARGUMENTS;
570 HKEY hKey = SetupDiOpenDevRegKey(
577 if (hKey == INVALID_HANDLE_VALUE)
579 dwResult = GetLastError();
584 while (iNumAttempts > 0)
587 LPTSTR szCfgGuidString = NULL;
588 dwResult = RegQueryValueEx(hKey, TEXT(
"NetCfgInstanceId"), NULL, NULL, NULL, NULL);
589 if (dwResult != ERROR_SUCCESS)
591 if (dwResult == ERROR_FILE_NOT_FOUND && --iNumAttempts > 0)
598 SetLastError(dwResult);
599 msg(
M_NONFATAL |
M_ERRNO,
"%s: querying \"NetCfgInstanceId\" registry value failed", __FUNCTION__);
606 TEXT(
"NetCfgInstanceId"),
608 if (dwResult != ERROR_SUCCESS)
613 dwResult = SUCCEEDED(CLSIDFromString(szCfgGuidString, (LPCLSID)pguidAdapter)) ? ERROR_SUCCESS : ERROR_INVALID_DATA;
614 free(szCfgGuidString);
646 _In_ HDEVINFO hDeviceInfoSet,
647 _In_ PSP_DEVINFO_DATA pDeviceInfoData,
648 _In_ DWORD dwProperty,
649 _Out_opt_ LPDWORD pdwPropertyRegDataType,
650 _Out_ LPVOID *ppData)
652 DWORD dwResult = ERROR_BAD_ARGUMENTS;
656 return ERROR_BAD_ARGUMENTS;
661 DWORD dwRequiredSize = 0;
662 if (SetupDiGetDeviceRegistryProperty(
666 pdwPropertyRegDataType,
672 *ppData = malloc(dwRequiredSize);
675 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwRequiredSize);
676 return ERROR_OUTOFMEMORY;
679 memcpy(*ppData, bBufStack, dwRequiredSize);
680 return ERROR_SUCCESS;
684 dwResult = GetLastError();
685 if (dwResult == ERROR_INSUFFICIENT_BUFFER)
688 *ppData = malloc(dwRequiredSize);
691 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, dwRequiredSize);
692 return ERROR_OUTOFMEMORY;
695 if (SetupDiGetDeviceRegistryProperty(
699 pdwPropertyRegDataType,
704 return ERROR_SUCCESS;
708 dwResult = GetLastError();
709 msg(
M_NONFATAL |
M_ERRNO,
"%s: SetupDiGetDeviceRegistryProperty(%u) failed", __FUNCTION__, dwProperty);
715 msg(
M_NONFATAL |
M_ERRNO,
"%s: SetupDiGetDeviceRegistryProperty(%u) failed", __FUNCTION__, dwProperty);
725 _In_opt_ LPCTSTR szDeviceDescription,
727 _Inout_ LPBOOL pbRebootRequired,
728 _Out_ LPGUID pguidAdapter)
731 HMODULE libnewdev = NULL;
734 || pbRebootRequired == NULL
735 || pguidAdapter == NULL)
737 return ERROR_BAD_ARGUMENTS;
741 HDEVINFO hDevInfoList = SetupDiCreateDeviceInfoList(&
GUID_DEVCLASS_NET, hwndParent);
742 if (hDevInfoList == INVALID_HANDLE_VALUE)
744 dwResult = GetLastError();
745 msg(
M_NONFATAL,
"%s: SetupDiCreateDeviceInfoList failed", __FUNCTION__);
750 TCHAR szClassName[MAX_CLASS_NAME_LEN];
751 if (!SetupDiClassNameFromGuid(
754 _countof(szClassName),
757 dwResult = GetLastError();
758 msg(
M_NONFATAL,
"%s: SetupDiClassNameFromGuid failed", __FUNCTION__);
759 goto cleanup_hDevInfoList;
763 SP_DEVINFO_DATA devinfo_data = { .cbSize =
sizeof(SP_DEVINFO_DATA) };
764 if (!SetupDiCreateDeviceInfo(
773 dwResult = GetLastError();
774 msg(
M_NONFATAL,
"%s: SetupDiCreateDeviceInfo failed", __FUNCTION__);
775 goto cleanup_hDevInfoList;
779 if (!SetupDiSetSelectedDevice(
783 dwResult = GetLastError();
784 msg(
M_NONFATAL,
"%s: SetupDiSetSelectedDevice failed", __FUNCTION__);
785 goto cleanup_hDevInfoList;
789 if (!SetupDiSetDeviceRegistryProperty(
793 (
const BYTE *)szHwId, (DWORD)((_tcslen(szHwId) + 1) *
sizeof(TCHAR))))
795 dwResult = GetLastError();
796 msg(
M_NONFATAL,
"%s: SetupDiSetDeviceRegistryProperty failed", __FUNCTION__);
797 goto cleanup_hDevInfoList;
801 if (!SetupDiCallClassInstaller(
806 dwResult = GetLastError();
807 msg(
M_NONFATAL,
"%s: SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed", __FUNCTION__);
808 goto cleanup_hDevInfoList;
816 #ifdef HAVE_DIINSTALLDEVICE
817 if (!DiInstallDevice(hwndParent, hDevInfoList, &devinfo_data, NULL, 0, pbRebootRequired))
820 typedef BOOL (WINAPI *DiInstallDeviceFn)(HWND, HDEVINFO, SP_DEVINFO_DATA *,
821 SP_DRVINFO_DATA *, DWORD, BOOL *);
822 DiInstallDeviceFn installfn
823 =
find_function(L
"newdev.dll",
"DiInstallDevice", &libnewdev);
827 dwResult = GetLastError();
829 goto cleanup_hDevInfoList;
832 if (!installfn(hwndParent, hDevInfoList, &devinfo_data, NULL, 0, pbRebootRequired))
835 dwResult = GetLastError();
837 goto cleanup_remove_device;
843 cleanup_remove_device:
844 if (dwResult != ERROR_SUCCESS)
847 SP_REMOVEDEVICE_PARAMS removedevice_params =
849 .ClassInstallHeader =
851 .cbSize =
sizeof(SP_CLASSINSTALL_HEADER),
852 .InstallFunction = DIF_REMOVE,
854 .Scope = DI_REMOVEDEVICE_GLOBAL,
859 if (SetupDiSetClassInstallParams(
862 &removedevice_params.ClassInstallHeader,
863 sizeof(SP_REMOVEDEVICE_PARAMS)))
866 if (SetupDiCallClassInstaller(
872 check_reboot(hDevInfoList, &devinfo_data, pbRebootRequired);
885 cleanup_hDevInfoList:
888 FreeLibrary(libnewdev);
890 SetupDiDestroyDeviceInfoList(hDevInfoList);
918 _In_ LPCGUID pguidAdapter,
920 _Inout_ LPBOOL pbRebootRequired)
924 if (pguidAdapter == NULL)
926 return ERROR_BAD_ARGUMENTS;
930 HDEVINFO hDevInfoList = SetupDiGetClassDevsEx(
938 if (hDevInfoList == INVALID_HANDLE_VALUE)
940 dwResult = GetLastError();
941 msg(
M_NONFATAL,
"%s: SetupDiGetClassDevsEx failed", __FUNCTION__);
946 SP_DEVINFO_LIST_DETAIL_DATA devinfo_list_detail_data = { .cbSize =
sizeof(SP_DEVINFO_LIST_DETAIL_DATA) };
947 if (!SetupDiGetDeviceInfoListDetail(hDevInfoList, &devinfo_list_detail_data))
949 dwResult = GetLastError();
950 msg(
M_NONFATAL,
"%s: SetupDiGetDeviceInfoListDetail failed", __FUNCTION__);
951 goto cleanup_hDevInfoList;
955 for (DWORD dwIndex = 0;; dwIndex++)
958 SP_DEVINFO_DATA devinfo_data = { .cbSize =
sizeof(SP_DEVINFO_DATA) };
959 if (!SetupDiEnumDeviceInfo(
964 if (GetLastError() == ERROR_NO_MORE_ITEMS)
966 LPOLESTR szAdapterId = NULL;
967 StringFromIID((REFIID)pguidAdapter, &szAdapterId);
969 CoTaskMemFree(szAdapterId);
970 dwResult = ERROR_FILE_NOT_FOUND;
971 goto cleanup_hDevInfoList;
976 msg(
M_WARN |
M_ERRNO,
"%s: SetupDiEnumDeviceInfo(%u) failed", __FUNCTION__, dwIndex);
984 if (dwResult != ERROR_SUCCESS)
991 if (memcmp(pguidAdapter, &guidAdapter,
sizeof(GUID)) == 0)
993 dwResult = funcOperation(hDevInfoList, &devinfo_data, pbRebootRequired);
998 cleanup_hDevInfoList:
999 SetupDiDestroyDeviceInfoList(hDevInfoList);
1007 _In_ LPCGUID pguidAdapter,
1008 _Inout_ LPBOOL pbRebootRequired)
1017 _In_ LPCGUID pguidAdapter,
1019 _Inout_ LPBOOL pbRebootRequired)
1030 PROCESS_INFORMATION pi;
1031 DWORD proc_flags = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
1032 WCHAR *cmdline_dup = NULL;
1034 ZeroMemory(&si,
sizeof(si));
1035 ZeroMemory(&pi,
sizeof(pi));
1040 cmdline_dup = _wcsdup(cmdline);
1041 if (cmdline_dup && CreateProcessW(NULL, cmdline_dup, NULL, NULL, FALSE,
1042 proc_flags, NULL, NULL, &si, &pi))
1044 WaitForSingleObject(pi.hProcess, INFINITE);
1045 if (!GetExitCodeProcess(pi.hProcess, &exit_code))
1047 exit_code = GetLastError();
1050 CloseHandle(pi.hProcess);
1051 CloseHandle(pi.hThread);
1055 exit_code = GetLastError();
1064 _In_ LPCGUID pguidAdapter,
1072 if (pguidAdapter == NULL ||
szName == NULL)
1074 return ERROR_BAD_ARGUMENTS;
1078 LPOLESTR szDevClassNetId = NULL;
1082 LPOLESTR szAdapterId = NULL;
1083 StringFromIID((REFIID)pguidAdapter, &szAdapterId);
1088 szRegKey, _countof(szRegKey),
1095 dwResult = RegOpenKeyEx(
1101 if (dwResult != ERROR_SUCCESS)
1103 SetLastError(dwResult);
1104 msg(msg_flag,
"%s: RegOpenKeyEx(HKLM, \"%" PRIsLPTSTR "\") failed", __FUNCTION__, szRegKey);
1105 goto cleanup_szAdapterId;
1108 LPTSTR szOldName = NULL;
1110 if (dwResult != ERROR_SUCCESS)
1112 SetLastError(dwResult);
1113 msg(msg_flag,
"%s: Error reading adapter name", __FUNCTION__);
1118 const TCHAR *szFmt = TEXT(
"netsh interface set interface name=\"%")
1120 size_t ncmdline = _tcslen(szFmt) + _tcslen(szOldName) + _tcslen(
szName) + 1;
1121 WCHAR *szCmdLine = malloc(ncmdline *
sizeof(TCHAR));
1122 _stprintf_s(szCmdLine, ncmdline, szFmt, szOldName,
szName);
1129 if (dwResult != ERROR_SUCCESS)
1131 SetLastError(dwResult);
1132 msg(msg_flag,
"%s: Error renaming adapter", __FUNCTION__);
1138 cleanup_szAdapterId:
1139 CoTaskMemFree(szAdapterId);
1140 CoTaskMemFree(szDevClassNetId);
1153 if (ppAdapter == NULL)
1155 return ERROR_BAD_ARGUMENTS;
1159 HDEVINFO hDevInfoList = SetupDiGetClassDevsEx(
1167 if (hDevInfoList == INVALID_HANDLE_VALUE)
1169 dwResult = GetLastError();
1170 msg(
M_NONFATAL,
"%s: SetupDiGetClassDevsEx failed", __FUNCTION__);
1175 SP_DEVINFO_LIST_DETAIL_DATA devinfo_list_detail_data = { .cbSize =
sizeof(SP_DEVINFO_LIST_DETAIL_DATA) };
1176 if (!SetupDiGetDeviceInfoListDetail(hDevInfoList, &devinfo_list_detail_data))
1178 dwResult = GetLastError();
1179 msg(
M_NONFATAL,
"%s: SetupDiGetDeviceInfoListDetail failed", __FUNCTION__);
1180 goto cleanup_hDevInfoList;
1184 LPOLESTR szDevClassNetId = NULL;
1190 for (DWORD dwIndex = 0;; dwIndex++)
1193 SP_DEVINFO_DATA devinfo_data = { .cbSize =
sizeof(SP_DEVINFO_DATA) };
1194 if (!SetupDiEnumDeviceInfo(
1199 if (GetLastError() == ERROR_NO_MORE_ITEMS)
1206 msg(
M_WARN |
M_ERRNO,
"%s: SetupDiEnumDeviceInfo(%u) failed", __FUNCTION__, dwIndex);
1212 DWORD dwDataType = REG_NONE;
1213 LPTSTR szzDeviceHardwareIDs = NULL;
1219 (LPVOID)&szzDeviceHardwareIDs);
1220 if (dwResult != ERROR_SUCCESS)
1227 if (dwDataType == REG_SZ)
1229 if (szzHwIDs && !
_tcszistr(szzHwIDs, szzDeviceHardwareIDs))
1232 goto cleanup_szzDeviceHardwareIDs;
1235 else if (dwDataType == REG_MULTI_SZ)
1239 for (LPTSTR s = szzDeviceHardwareIDs;; s += _tcslen(s) + 1)
1244 goto cleanup_szzDeviceHardwareIDs;
1257 goto cleanup_szzDeviceHardwareIDs;
1263 if (dwResult != ERROR_SUCCESS)
1266 goto cleanup_szzDeviceHardwareIDs;
1270 LPOLESTR szAdapterId = NULL;
1271 StringFromIID((REFIID)&guidAdapter, &szAdapterId);
1276 szRegKey, _countof(szRegKey),
1283 dwResult = RegOpenKeyEx(
1289 if (dwResult != ERROR_SUCCESS)
1291 SetLastError(dwResult);
1293 goto cleanup_szAdapterId;
1302 if (dwResult != ERROR_SUCCESS)
1304 SetLastError(dwResult);
1310 size_t hwid_size = (
_tcszlen(szzDeviceHardwareIDs) + 1) *
sizeof(TCHAR);
1311 size_t name_size = (_tcslen(
szName) + 1) *
sizeof(TCHAR);
1316 dwResult = ERROR_OUTOFMEMORY;
goto cleanup_szName;
1319 memcpy(&node->
guid, &guidAdapter,
sizeof(GUID));
1327 pAdapterTail->
pNext = node;
1328 pAdapterTail = node;
1332 *ppAdapter = pAdapterTail = node;
1339 cleanup_szAdapterId:
1340 CoTaskMemFree(szAdapterId);
1341 cleanup_szzDeviceHardwareIDs:
1342 free(szzDeviceHardwareIDs);
1345 dwResult = ERROR_SUCCESS;
1347 CoTaskMemFree(szDevClassNetId);
1348 cleanup_hDevInfoList:
1349 SetupDiDestroyDeviceInfoList(hDevInfoList);
1359 while (pAdapterList)
1362 pAdapterList = pAdapterList->
pNext;