Ошибка SetupDiGetClassDevs для отображения дисков SCSI с кодом ошибки 13 (ERROR_INVALID_DATA)

У меня есть довольно интересная проблема, для которой я не могу найти решение. Я использую Setup API для отображения дисков в системе. У меня нет проблем с использованием приведенного ниже кода при установке перечислителя на «IDE». Моя тревога возникает, когда значение перечислителя установлено на «SCSI». Код, который воспроизводит эту проблему, приведен ниже:

#include <iostream>
#include <Windows.h>
#include <SetupAPI.h>
#include <cfgmgr32.h>
#include <devguid.h>

int main() {
    std::cout << "Looking for only SCSI disks" << std::endl;
    HDEVINFO hDevs(SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, "SCSI", NULL, DIGCF_PRESENT));
    if(INVALID_HANDLE_VALUE == hDevs) {
        DWORD error(GetLastError());
        std::cout << "Handle returned is invalid. Error code: " << error << std::endl;
        return 1;
    }

    SP_DEVINFO_DATA sp = {sizeof(SP_DEVINFO_DATA)};
    char buff[256];
    memset(buff, 0, 256);
    DWORD index(0);

    std::cout << "The handle is valid, listing drives now" << std::endl;
    while(SetupDiEnumDeviceInfo(hDevs, index++, &sp)) {
        CM_Get_Device_ID(sp.DevInst, buff, 256, 0);
        std::cout << buff << std::endl;
        memset(buff, 0, 256);
    }

    SetupDiDestroyDeviceInfoList(hDevs);
    return 0;
}

Как видите, ничего примечательного в этом коде нет. Проблема в том, что на некоторых ноутбуках этот код приводит к ошибкам в SetupDiGetClassDevs(). Проверка GetLastError() показывает, что она не удалась из-за ошибки ERROR_INVALID_DATA (0xd). Чего я не понимаю, так это почему. Эта точно такая же программа, запущенная на моем компьютере для разработки и как мой пользователь (с правами администратора), и как непривилегированный пользователь, прекрасно работает независимо от того, присутствуют ли диски SCSI.

Я знаю, что используемый GUID правильный. Он определен в devguid.h. «SCSI» — это допустимый перечислитель PnP, как указано в этом страница MSDN, а также просмотрев свойство "Перечислитель" в диспетчере устройств. Третий аргумент может быть NULL, а четвертый является допустимым определенным флагом для этой функции. Я знаю это, потому что, за исключением этих ноутбуков, это работает на всех системах, на которых я когда-либо пробовал (которых в моей организации довольно много). Я надеюсь, что кто-то здесь может знать о том, что может привести к сбою SetupDiGetClassDevs() из-за этой ошибки с этими условиями, или, по крайней мере, может указать мне правильное направление. Я не эксперт по Windows, и я мог что-то упустить в конфигурации системы или разрешениях (хотя это не подразумевается из ошибки).

Как я надеюсь, понятно, я запустил этот код на одном ноутбуке, на котором я могу протестировать его как в качестве пользователя с правами администратора, так и в качестве пользователя-администратора: оба с одинаковым результатом. Ноутбук представляет собой HP EliteBook 8460p под управлением 64-разрядной версии Windows 7 с пакетом обновления 1. Компиляция этого кода в 32 или 64 бита не имеет значения.


person Andrew Falanga    schedule 18.01.2013    source источник
comment
Ваша обработка ошибок не работает. Всегда получайте значение GetLastError() прежде чем делать что-либо еще, включая запись в cout.   -  person Hans Passant    schedule 18.01.2013
comment
Интересно. Я этого не знал, но, похоже, это разумно. Я изменил свой код на то, что показывает редактирование. Я все еще получаю код ошибки 13 (0xd).   -  person Andrew Falanga    schedule 19.01.2013


Ответы (1)


Я собираюсь опубликовать ответ, который я получил от товарища на форумах поддержки MSDN, чтобы помочь тому, кто может быть сбит с толку этой же проблемой. По-видимому, это ожидаемое поведение для Windows 7. Если система никогда не видела оборудование с перечислителем, указанным для SetupDiGetClassDevs(), то происходит сбой и ожидается этот код ошибки.

Для справки, ветка, в которой я задал этот вопрос, связана здесь.

person Andrew Falanga    schedule 30.01.2013