/**************************************************************************************** Purpose: change state of the selected device Input : hDevInfo device info set pDeviceInfoData selected device info NewState one of enable/disable Output : TRUE for success, FALSE for failed ****************************************************************************************/ BOOL ChangeDeviceState(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDeviceInfoData, DWORD NewState) { SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)}; SP_DEVINSTALL_PARAMS devParams; if (!pDeviceInfoData) { return FALSE; } PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC; PropChangeParams.StateChange = NewState; PropChangeParams.HwProfile = 0; if (!SetupDiSetClassInstallParams(hDevInfo,pDeviceInfoData, (SP_CLASSINSTALL_HEADER *)&PropChangeParams,sizeof(PropChangeParams)) || !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,pDeviceInfoData)) { return FALSE; } reutrn TRUE; } /* hDevInfo如何得到***********************************************************/ m_hDevInfo = SetupDiGetClassDevs( (LPGUID) &GUID_DEVCLASS_NET, /* GUID_DEVCLASS_NET表示仅列出网络设备 */ NULL, this->m_hWnd, DIGCF_PRESENT); if (INVALID_HANDLE_VALUE == m_hDevInfo) { return FALSE; } /* pDeviceInfoData如何得到**************************************************/ k = 0; while (SetupDiEnumDeviceInfo(m_hDevInfo, k ,&DeviceInfoData)) { k++; if (CR_SUCCESS != CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0)) { continue; } if ((Status & DN_NO_SHOW_IN_DM)) { continue; } if (GetRegistryProperty(m_hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, &pBuffer, &Length)) { m_Adapter[adapter_num].index = k - 1; /* 当前网卡在设备信息集中的索引 */ _tcscpy(m_Adapter[adapter_num].desc, pBuffer); /* 当前网卡 */ GetRegistryProperty(m_hDevInfo, &DeviceInfoData, SPDRP_DRIVER, &pBuffer, &Length); _tcscpy(m_Adapter[adapter_num].driver, pBuffer); adapter_num++; } } /* GetRegistryProperty是对SetupDiGetDeviceRegistryProperty封装***************/ BOOL GetRegistryProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, ULONG Property, LPTSTR* Buffer, PULONG Length) { while (!SetupDiGetDeviceRegistryProperty( DeviceInfoSet, DeviceInfoData, Property, NULL, (PBYTE)(*Buffer), *Length, Length )) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (*(LPTSTR *)Buffer) LocalFree(*(LPTSTR *)Buffer); *Buffer = (LPTSTR)LocalAlloc(LPTR, *Length); }else { return FALSE; } } return TRUE; } /* m_Adapter的数据结构 */ typedef struct adapter_info_s { char name[NAME_LEN]; /* 内部设备名, UUID的字符串形式 */ char desc[NAME_LEN]; /* 网卡描述 */ char driver[NAME_LEN]; /* 网卡在注册表中的位置, 如{4D36E972-E325-11CE-BFC1-08002BE10318}\0011 实际完整的键名为System\\CurrentControlSet\\Control\\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0011 该键包含的内容与SetupDiGetDeviceRegistryProperty得到的设备属性基本相同 如NetCfgInstanceId即为内部设备名 DriverDesc为设备描述 */ int index; }adapter_info_t; /***************************************************************************** 用何名称区分不同的网卡 有如下名称可供选择 本地连接名, 这是系统使用的方法, 调用的是netman.dll中的未公开函数HrLanConnectionNameFromGuidOrPath(其原型笔者正在调试之中, 成功之后会另行撰文); 其实也可从注册表中获得HKLM\System\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Connection\Name 网卡类型描述 设备友好名 它与网卡类型描述基本相同, 当存在同种类型的网卡, 它会加#n(n = 2, 3, 4...)以示区分 如本程序中笔者即以设备友好名区分网卡 *****************************************************************************/ /* 重启网卡的过程************************************************************/ k = pAdapter->GetCurSel(); /* m_Adapter[k]即当前网卡 */ if (SetupDiEnumDeviceInfo(m_hDevInfo, m_Adapter[k].index ,&DeviceInfoData)) { hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_DISABLE); /* 禁用网卡 */ ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_ENABLE); /* 启用网卡 */ /* 重启网卡, 一般情况下, 以下命令相当于前两命令的组合. 但我仍建议使用前者 */ // ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_PROPCHANGE); SetCursor(hCursor); } /* 扫尾工作 */ SetupDiDestroyDeviceInfoList(m_hDevInfo);