Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Получить параметры устройства, SetupDiХХХ функция не работает 
V
    Опции темы
Knuckles
  Дата 24.1.2008, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 33
Регистрация: 8.3.2006

Репутация: 1
Всего: 2



Пытаюсь найти все отключенные сетевые адаптеры. Перечислить все адаптеры могу (SetupDiGetClassDevs, затем SetupDiEnumDeviceInfo), но при попытке посмотреть параметры устройства функция SetupDiGetDeviceInstallParams просто ничего не делает. Вызываю так:

Код

LANDevsInfoSetHandle: HDEVINFO;  //получен SetupDiGetClassDevs
LANDevInfoData: SP_DEVINFO_DATA; //обновляется в каждом цикле вызова SetupDiEnumDeviceInfo
DevInstallParams: SP_DEVINSTALL_PARAMS;  //собственно тут должна быть информация
//..
LANDevInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
FillChar(DevInstallParams, SizeOf(SP_DEVINSTALL_PARAMS), 0);
DevInstallParams.cbSize := SizeOf(SP_DEVINSTALL_PARAMS);

    DevInfoEnumRet := True;
    DevIndex := 0;
    while SetupDiEnumDeviceInfo(
            LANDevsInfoSetHandle,
            DevIndex,
            @LANDevInfoData) do
        begin
        if not SetupDiGetDeviceInstallParams(
            LANDevsInfoSetHandle,
            @LANDevInfoData,
            @DevInstallParams) then
            RaiseLastOSError;

        Inc(DevIndex);
        end;
//...


Собственно, все функции возвращают LongBool True, GetLastError везде 0, SetupDiEnumDeviceInfo перечисляет девайсы, но в DevInstallParams никакой информации. Вообще. Структура просто не меняется, SetupDiGetDeviceInstallParams ничего не делает. Что я делаю не так?
На всякий случай, ф-я объявлена так:
Код

function SetupDiGetDeviceInstallParams(DeviceInfoSet: HDEVINFO;
  DeviceInfoData: PSP_DEVINFO_DATA;
  DeviceInstallParams: PSP_DEVINSTALL_PARAMS): LongBool; stdcall;


Это сообщение отредактировал(а) Knuckles - 24.1.2008, 10:11
PM   Вверх
Knuckles
  Дата 24.1.2008, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 33
Регистрация: 8.3.2006

Репутация: 1
Всего: 2



Задача решена. Через одно место, но работает. Итак, я не стал больше разбираться с (почему-то) неработающей функцией. Сделал по-другому. Ниже привожу исходник 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
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0468 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.