Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Получение расширенной информации о подключенном флэш-накопителе

7
03 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Требуется получить максимум информации о подключенном устройстве. Мои познания ограничены только GetVolumeInformation(), но я знаю, что через SetupDi…/DeviceIoControl() тоже что-то можно получить. Однако, экспресс-изучение этих функций конкретных результатов не дало. Например, интересует, как получить имя устройства, которое пишется в диспетчере устройств (обычно производитель).
7
07 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Спасибо всем, кто помогал! (а таких тут лишь один человек, но неважно ☺)
Т.к. на приличных форумах у приличных людей заведено делиться найденными решениями, привожу результаты своих стараний, многочасовых поисков и несколько менее многочасовых проб и ошибок.
Код:
STORAGE_DEVICE_NUMBER sdnSrc;
char szDevName[8]="\\\\.\\";DWORD dwBytes;
lstrcat(szDevName,szDrive);
szDevName[6]=0;
HANDLE hDev=CreateFile(szDevName,0,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,0,OPEN_EXISTING,0,0);
if(hDev!=(HANDLE)-1){
    if(!DeviceIoControl(hDev,IOCTL_STORAGE_GET_DEVICE_NUMBER,0,0,&sdnSrc,sizeof sdnSrc,&dwBytes,0))
        MessageBox(hDlg,"DeviceIoControl(Src)",0,MB_ICONERROR);
    CloseHandle(hDev);
}else
    MessageBox(hDlg,"CreateFile(Src)",0,MB_ICONERROR);
GUID guid=GUID_DEVINTERFACE_DISK;
HDEVINFO hDevs=SetupDiGetClassDevs(&guid,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if(hDevs!=(HANDLE)-1){
    bool bSearch=true;DWORD i=0;SP_DEVINFO_DATA DevData={sizeof SP_DEVINFO_DATA};
    while(bSearch){
        if(SetupDiEnumDeviceInfo(hDevs,i,&DevData)){
            DWORD j=0;SP_DEVICE_INTERFACE_DATA DevIface={sizeof SP_DEVICE_INTERFACE_DATA};
            while(bSearch){
                if(SetupDiEnumDeviceInterfaces(hDevs,&DevData,&guid,j,&DevIface)){
                    SetupDiGetDeviceInterfaceDetail(hDevs,&DevIface,0,0,&dwBytes,0);
                    SP_DEVICE_INTERFACE_DETAIL_DATA *pDevIfDetail=(SP_DEVICE_INTERFACE_DETAIL_DATA*)HeapAlloc(hHeap,0,dwBytes);
                    pDevIfDetail->cbSize=sizeof SP_DEVICE_INTERFACE_DETAIL_DATA;
                    SetupDiGetDeviceInterfaceDetail(hDevs,&DevIface,pDevIfDetail,dwBytes,0,0);
                    HANDLE hTest=CreateFile(pDevIfDetail->DevicePath,0,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,0,OPEN_EXISTING,0,0);
                    HeapFree(hHeap,0,pDevIfDetail);
                    if(hTest!=(HANDLE)-1){
                        STORAGE_DEVICE_NUMBER sdn;
                        if(DeviceIoControl(hTest,IOCTL_STORAGE_GET_DEVICE_NUMBER,0,0,&sdn,sizeof sdn,&dwBytes,0)){
                            if(sdn.DeviceNumber==sdnSrc.DeviceNumber){
                                SetupDiGetDeviceRegistryProperty(hDevs,&DevData,SPDRP_FRIENDLYNAME,0,0,0,&dwBytes);
                                char *szName=(char*)HeapAlloc(hHeap,0,dwBytes);
                                SetupDiGetDeviceRegistryProperty(hDevs,&DevData,SPDRP_FRIENDLYNAME,0,(PBYTE)szName,dwBytes,0);
                                char *szBuf=(char*)HeapAlloc(hHeap,0,lstrlen(szFormat)+lstrlen(szVolName)+lstrlen(szVolFS)+dwBytes+15);
                                wsprintf(szBuf,szFormat,szVolName,dwVolSN,szVolFS,(DWORD)dwTNF.QuadPart/1048576,(DWORD)dwTNB.QuadPart/1048576,szName);
                                HeapFree(hHeap,0,szName);
                                SetDlgItemText(hDlg,LblDevInfo,szBuf);
                                HeapFree(hHeap,0,szBuf);
                                bSearch=false;
                            }
                        }else
                            MessageBox(hDlg,"DeviceIoControl(Test)",0,MB_ICONERROR);
                        CloseHandle(hTest);
                    }else
                        MessageBox(hDlg,"CreateFile(Test)",0,MB_ICONERROR);
                }else if(GetLastError()==ERROR_NO_MORE_ITEMS)
                    break;
                j++;
            }
        }else if(GetLastError()==ERROR_NO_MORE_ITEMS)
            break;
        i++;
    }
    SetupDiDestroyDeviceInfoList(hDevs);
}else
    MessageBox(hDlg,"Невозможно получить список устройств",0,MB_ICONERROR);
Код вырван из контекста, поэтому некоторые переменные могут быть не определены, например.
Если кто-то не понял, или ещё какие-то вопросы будут — обращайтесь ☺
327
04 июля 2015 года
UserNet2008
748 / / 03.04.2010
SetupDiGetDeviceRegistryProperty
Функция SPDRP_MFG
строка REG_SZ - производитель устройства.
7
04 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
И сразу вопросы:
0. Где взять DeviceInfoSet?
1. Где взять GUID?
Я просто ни разу вообще не работал с SetupAPI :D Поэтому для меня это в новинку, а в MSDN всё как-то запутано.
7
06 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Начал разбираться. Пишу
Код:
HDEVINFO hDevs=SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK,0,0,DIGCF_PRESENT);
if(hDevs!=(HANDLE)-1){
    DWORD i=0;SP_DEVINFO_DATA DevData={sizeof SP_DEVINFO_DATA};
    while(true){
        if(SetupDiEnumDeviceInfo(hDevs,i,&DevData)){
            …
        }else if(GetLastError()==ERROR_NO_MORE_ITEMS)
            break;
        i++;
    }
    SetupDiDestroyDeviceInfoList(hDevs);
}
Не работает! Сразу заканчивается цикл после 1-й итерации. ЧЯДНТ?
326
06 июля 2015 года
sadovoya
757 / / 19.11.2005
Рабочий код в MinGW, но находит все диски, не только флешки:
Код:
//Codec Windows-1251
//Список

#include <cstdio>
#include <clocale>
#include <windows.h>
#include <setupapi.h> //прилинковать стат. библиотеку libsetupapi.a (для MinGW)

int main() {

    setlocale(0, "");
    //если нет заголовочника, то можно вручную так:
    CONST GUID GUID_DEVINTERFACE_DISK = {0x53f56307L, 0xb6bf, 0x11d0,
    0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b
    };
    HDEVINFO lst = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
    if (INVALID_HANDLE_VALUE == lst)
        return -3000;
    DWORD k = 0;
    SP_DEVINFO_DATA DeviceInfoData;
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);//нужно
    const DWORD BufferSize = 1024; //должно хватить
    char Buffer[BufferSize];
    while (SetupDiEnumDeviceInfo(lst, k, &DeviceInfoData)) {
        if (SetupDiGetDeviceRegistryPropertyA(lst, &DeviceInfoData,
                SPDRP_FRIENDLYNAME, NULL, (BYTE *)Buffer, BufferSize, NULL)
        )
            printf("%s\n", Buffer);
        else if (
            SetupDiGetDeviceRegistryPropertyA(lst, &DeviceInfoData,
                SPDRP_DEVICEDESC, NULL, (BYTE *)Buffer, BufferSize, NULL)
        )
            printf("%s\n", Buffer);
        k++;
    }
    SetupDiDestroyDeviceInfoList(lst);//не забывать закрыть


    printf("\n\nНажмите клавишу...\n");
    getchar();

    return 0;
}
7
06 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Ну, с заголовочными файлами и библиотеками проблем нет ☺ Я в студии работаю, если что.
Проблема в том, что у меня код как раз такой же в целом, но первая попытка Enum'а возвращает мне нифига. И вот тут я просто офигеваю!
326
06 июля 2015 года
sadovoya
757 / / 19.11.2005
Флаг DIGCF_DEVICEINTERFACE используете?
7
06 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Изначально нет, но с ним тоже пытался — не помогло. А почему без него нельзя, какова его роль?
(MSDN я, конечно, читал, но в силу того, что эта тема для меня нова, тамошние слова для меня малопонятны пока что :))
326
06 июля 2015 года
sadovoya
757 / / 19.11.2005
Я этот код сделал из своего трехгодичной давности (для которого наверняка заготовку в инете нашел). Он у меня перечислял все устройства в системе в виде а-ля диспетчер устройств. Просто вставил в него гуид из вашего кода. Такой вот гибрид. У меня он хард и флеху определил. Флаг важен, но уже не помню, почему. Кажется в винде две категории гуидов, для одной из них этот флаг. Но, боюсь наврать, уже все забыть успел :)
7
06 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Как я понял из описания, тот флаг нужен, когда мы интерфейсы получаем. В вышеприведённом коде интерфейсов нет, однако он вроде как должен работать.

Чюдиса! Друг спас друга!
Видимо, такую комбинацию я не использовал, а зря =) По крайней мере, дома этот код заработал. Что ж, не поблагодарить за это было бы весьма неприлично, поэтому спасибо за хоть и маленький, но очень значимый вклад ☺

И тогда такой вопрос — а как можно определить, какая буква назначена устройству? Потому что в моём коде информация получается по щелчку на путь устройства (например, F:), т.е. мне нужно где-то найти совпадение.
326
06 июля 2015 года
sadovoya
757 / / 19.11.2005
Спасибо видимо тому, у кого я в свою очередь заготовку позаимствовал :)
По поводу перевода из букв в гуид - скорее всего с помощью WinIoCtl. Так навскидку мне слабо.
Блин, вопрос то о другом был.. Но скорей всего через тот-же IoCtl.
7
07 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Итак, чего я добился. Сейчас я могу получить либо все диски (как устройства), либо все тома с помощью кода
Код:
HDEVINFO hDevs=SetupDiGetClassDevs(&GUID_DEVINTERFACE_…,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if(hDevs!=(HANDLE)-1){
    DWORD i=0,dwBytes;SP_DEVINFO_DATA DevData={sizeof SP_DEVINFO_DATA};
    while(true){
        if(SetupDiEnumDeviceInfo(hDevs,i,&DevData)){
            SetupDiGetDeviceRegistryProperty(hDevs,&DevData,SPDRP_…,0,0,0,&dwBytes);
            char *szProp=(char*)HeapAlloc(hHeap,0,dwBytes);
            SetupDiGetDeviceRegistryProperty(hDevs,&DevData,SPDRP_…,0,(PBYTE)szProp,dwBytes,&dwBytes);
            MessageBox(hDlg,szProp,0,MB_ICONINFORMATION);
            HeapFree(hHeap,0,szProp);
        }else if(GetLastError()==ERROR_NO_MORE_ITEMS)
            break;
        i++;
    }
    SetupDiDestroyDeviceInfoList(hDevs);
}
Соответственно, использую для этого нужный GUID. Теперь надо как-то связать имя тома на диске с конкретным устройством, и тут-то начинается самое весёлое.
Имя устройства я получаю с помощью комбинации GUID_DEVINTERFACE_DISK / SPDRP_FRIENDLYNAME, а путь к устройству — через GUID_DEVINTERFACE_VOLUME / SPDRP_PHYSICAL_DEVICE_OBJECT_NAME (потом с помощью QueryDosDevice я могу из имени тома получить путь к устройству). Но как мне определить, что какой-то том находится на устройстве?

Upd.: рассуждая логически, можно перечислять все диски, а потом перечислять тома, принадлежащие этим дискам. Но это возможно только в случае иерархической структуры, но пока я такой возможности не нашёл.
7
07 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Думал, что отца русской демократии спасёт попытка получения родительского устройства. Наваял следующий код
Код:
HDEVINFO hDevs=SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if(hDevs!=(HANDLE)-1){
    DWORD i=0,dwBytes;SP_DEVINFO_DATA DevData={sizeof SP_DEVINFO_DATA};
    while(true){
        if(SetupDiEnumDeviceInfo(hDevs,i,&DevData)){
            ULONG ul;
            if(!CM_Get_DevNode_Status(&ul,&ul,DevData.DevInst,0)){
                DEVINST hDIParent;
                if(!CM_Get_Parent(&hDIParent,DevData.DevInst,0)){
                    CM_Get_Device_ID_Size(&ul,hDIParent,0);
                    char *szDevId=(char*)HeapAlloc(hHeap,0,++ul);
                    if(!CM_Get_Device_ID(hDIParent,szDevId,ul,0)){
                        HDEVINFO hParentDev=SetupDiCreateDeviceInfoList(0,0);
                        if(SetupDiOpenDeviceInfo(hParentDev,szDevId,0,0,&DevData)){
                            SetupDiGetDeviceRegistryProperty(hParentDev,&DevData,SPDRP_ENUMERATOR_NAME,0,0,0,&dwBytes);
                            char *szName=(char*)HeapAlloc(hHeap,0,dwBytes);
                            SetupDiGetDeviceRegistryProperty(hParentDev,&DevData,SPDRP_ENUMERATOR_NAME,0,(PBYTE)szName,dwBytes,&dwBytes);
                            MessageBox(hDlg,szName,0,MB_ICONINFORMATION);
                            HeapFree(hHeap,0,szName);
                        }else
                            MessageBox(hDlg,"SetupDiOpenDeviceInfo",0,MB_ICONERROR);
                        SetupDiDestroyDeviceInfoList(hParentDev);
                    }else
                        MessageBox(hDlg,"CM_Get_Device_ID",0,MB_ICONERROR);
                    HeapFree(hHeap,0,szDevId);
                }else
                    MessageBox(hDlg,"CM_Get_Parent",0,MB_ICONERROR);
            }else
                MessageBox(hDlg,"CM_Get_DevNode_Status",0,MB_ICONERROR);
        }else if(GetLastError()==ERROR_NO_MORE_ITEMS)
            break;
        i++;
    }
    SetupDiDestroyDeviceInfoList(hDevs);
}
Но нет, снова прогадал! Родителями томов являются не устройства, а просто ROOT.
Как тогда система определяет (в окне безопасного извлечения устройств), к какому устройству относятся тома?
326
08 июля 2015 года
sadovoya
757 / / 19.11.2005
Значит IOCTL_STORAGE_GET_DEVICE_NUMBER лазейка. +1
7
08 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Типа того. Увы, от томов к устройствам у меня перейти не получилось, так же, как и перечислять GUID_DEVINTERFACE для USB (там я вряд ли бы такое провернул, хотя попробовать стоило бы). Но я рад тому, чего достиг ☺
326
08 июля 2015 года
sadovoya
757 / / 19.11.2005
Вот видимо поэтому многие винду не любят, что у них что ни возьми, без бубна редко :( Хорошо, что MSDN получше стал за последние годы.
7
08 июля 2015 года
@pixo $oft
3.4K / / 20.09.2006
Думаешь, в линуксах и прочих макосях лучше? Не думаю.
Просто у всего есть своя логика, и её надо понять. Для меня эта тема была новой, поэтому пришлось долго и упорно разбираться. В конце концов, это лишь один из способов, и тот факт, что их несколько, даже лучше — если нет возможности реализовать задуманное одним способом, найдётся как минимум ещё один ;-)

Насчёт получше не знаю. Как и раньше — не хватает какой-нибудь ключевой информации или пояснений; и хорошо, если в комментариях найти можно :D
326
08 июля 2015 года
sadovoya
757 / / 19.11.2005
Цитата:
В конце концов, это лишь один из способов, и тот факт, что их несколько, даже лучше — если нет возможности реализовать задуманное одним способом, найдётся как минимум ещё один ;-)

Я бы сказал еще один и даже больше, которыми тоже нельзя :) Можно на самом деле, но иногда слишком все запутано.
В MSDN сейчас некоторые разделы дописаны до вполне исчерпывающего состояния. Например, работа с COM портами. Было бы во всем так.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог