Задача решена. Через одно место, но работает. Итак, я не стал больше разбираться с (почему-то) неработающей функцией. Сделал по-другому. Ниже привожу исходник 2х функций. GetDisabledAdapters возвращает массив, каждый элемент которого имеет запись с описанием адаптера и с уникальным идентификатором, по которому это устройство позже можно найти. EnableAdapter включает либо отключает адаптер, на который указывает идентификатор DevInstID (тот самый, который хранится в TDevDescAndInstID.DevInstID). Вообще-то сюда можно передать не только такой идентификатор, но и любой валидный перечислитель (например 'PCI'), тогда будут включены/отключены все попавшие в список устройства, хотя я это не тестировал. Выходной параметр NeedReboot покажет, что устройство/а нужда(е/ю)тся в перезагрузке для изменения статуса. | Код | const GUIDSTR_DEVINTERFACE_NET = '{AD498944-762F-11D0-8DCB-00C04FC3358C}';
type TDevDescAndInstID = record DevDesc : string; DevInstID : string; end; TDevDescAndInstIDArray = array of TDevDescAndInstID;
function GetDisabledAdapters: TDevDescAndInstIDArray;
function GetDevRegStr(const InfoSet: HDEVINFO; const DevInfoData: SP_DEVINFO_DATA; const MemberIndex: DWORD; const Property_: DWORD): string; var RegDataBuffer : PChar; RegDataBufferSize : DWORD; ErrorCode : DWORD; DevInfoEnumRet : LongBool; begin RegDataBufferSize := 0; RegDataBuffer := nil; try while not SetupDiGetDeviceRegistryProperty( InfoSet, DevInfoData, Property_, nil, PByte(RegDataBuffer), RegDataBufferSize, @RegDataBufferSize) do begin ErrorCode := GetLastError; if ErrorCode = ERROR_INSUFFICIENT_BUFFER then begin if RegDataBuffer <> nil then FreeMemory(RegDataBuffer); GetMem(RegDataBuffer, RegDataBufferSize); end else RaiseLastOSError; end;
Result := string(RegDataBuffer);
finally FreeMem(RegDataBuffer); RegDataBuffer := nil; RegDataBufferSize := 0; end; end;
function GetDeviceInstID(DevInst: DWORD): string; var BuffLen: LongWord; DevInstID: PChar; ErrorCode: DWORD; begin BuffLen := 0; DevInstID := nil;
ErrorCode := CM_Get_Device_ID_Size( BuffLen, DevInst, 0); Win32Check(ErrorCode = CR_SUCCESS); Inc(BuffLen); GetMem(DevInstID, BuffLen); try ErrorCode := CM_Get_Device_ID( DevInst, DevInstID, BuffLen, 0); Win32Check(ErrorCode = CR_SUCCESS); Result := string(DevInstID);
finally FreeMem(DevInstID); end; end;
var LANIntfClassGuid: TGUID; LANIntfInfoSetHandle: HDEVINFO; LANDevInfoData: SP_DEVINFO_DATA; DevIntfData: SP_DEVICE_INTERFACE_DATA; IntfIndex: Integer; ResultLen: Integer;
begin ResultLen := 0;
LANIntfClassGuid := StringToGUID(GUIDSTR_DEVINTERFACE_NET); LANIntfInfoSetHandle := SetupDiGetClassDevs( @LANIntfClassGuid, nil, 0, DIGCF_DEVICEINTERFACE); Win32Check(THandle(LANIntfInfoSetHandle) <> INVALID_HANDLE_VALUE);
try DevIntfData.cbSize := SizeOf(SP_DEVICE_INTERFACE_DATA);
IntfIndex := 0; while SetupDiEnumDeviceInterfaces( LANIntfInfoSetHandle, nil, LANIntfClassGuid, IntfIndex, DevIntfData) do begin if not LongBool(DevIntfData.Flags and SPINT_ACTIVE) then //disabled adapter found begin LANDevInfoData.cbSize := SizeOf(SP_DEVINFO_DATA); Win32Check( SetupDiEnumDeviceInfo( LANIntfInfoSetHandle, IntfIndex, LANDevInfoData));
SetLength(Result, Succ(ResultLen));
Result[ResultLen].DevInstID := GetDeviceInstID(LANDevInfoData.DevInst); Result[ResultLen].DevDesc := GetDevRegStr( LANIntfInfoSetHandle, LANDevInfoData, IntfIndex, SPDRP_DEVICEDESC);
Inc(ResultLen); end;
Inc(IntfIndex); end; //SetupDiEnumDeviceInterfaces if GetLastError <> ERROR_NO_MORE_ITEMS then RaiseLastOSError;
finally Win32Check(SetupDiDestroyDeviceInfoList(LANIntfInfoSetHandle)); end; end;
procedure EnableAdapter(const DevInstID: string; Enable: Boolean; out NeedReboot: Boolean); var LANIntfClassGuid: TGUID; LANIntfInfoSetHandle: HDEVINFO; DevInfoData: SP_DEVINFO_DATA; ChangeParams: SP_PROPCHANGE_PARAMS; DevInstParams: SP_DEVINSTALL_PARAMS_A; IntfIndex: LongWord; begin NeedReboot := False; LANIntfClassGuid := StringToGUID(GUIDSTR_DEVINTERFACE_NET); LANIntfInfoSetHandle := SetupDiGetClassDevs( @LANIntfClassGuid, PChar(DevInstID), 0, DIGCF_DEVICEINTERFACE); Win32Check(THandle(LANIntfInfoSetHandle) <> INVALID_HANDLE_VALUE);
try DevInfoData.cbSize := SizeOf(SP_DEVICE_INTERFACE_DATA); IntfIndex := 0;
//normaly(if DevInstID specifies 1 device) it will do only 1 loop while SetupDiEnumDeviceInfo( LANIntfInfoSetHandle, IntfIndex, DevInfoData) do begin
ChangeParams.ClassInstallHeader.cbSize := SizeOf(SP_CLASSINSTALL_HEADER); ChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE; if Enable then ChangeParams.StateChange := DICS_ENABLE else ChangeParams.StateChange := DICS_DISABLE; ChangeParams.HwProfile := 0; ChangeParams.Scope := DICS_FLAG_CONFIGSPECIFIC; Win32Check( SetupDiSetClassInstallParams( LANIntfInfoSetHandle, @DevInfoData, @ChangeParams, SizeOf(ChangeParams)) ); Win32Check( SetupDiCallClassInstaller( DIF_PROPERTYCHANGE, LANIntfInfoSetHandle, @DevInfoData));
DevInstParams.cbSize := SizeOf(DevInstParams); Win32Check( SetupDiGetDeviceInstallParams( LANIntfInfoSetHandle, @DevInfoData, DevInstParams));
NeedReboot := NeedReboot and LongBool(DevInstParams.Flags and (DI_NEEDRESTART or DI_NEEDREBOOT));
Inc(IntfIndex); end; //SetupDiEnumDeviceInterfaces if GetLastError <> ERROR_NO_MORE_ITEMS then RaiseLastOSError;
finally Win32Check(SetupDiDestroyDeviceInfoList(LANIntfInfoSetHandle)); end; end;
|
ПС: ненавижу майкрософт. Это сообщение отредактировал(а) Knuckles - 25.1.2008, 07:44
|