2012-05-19 3 views
0

Я пытаюсь получить путь к устройству с помощью функции SetupDiGetDeviceInterfaceDetail(), но каждый раз я вызываю его сбой. Я работаю над этим более 12 часов, но все еще не могу узнать, что с ним не так ... Может ли кто-нибудь увидеть, могут ли они найти то, что на самом деле вызывает это? Heres код:Программа вылетает, когда SetupDiGetDeviceInterfaceDetail вызывается

//DeviceManager.h 
#include <windows.h> 
//#include <hidsdi.h> 
#include <setupapi.h> 
#include <iostream> 
#include <cfgmgr32.h> 
#include <tchar.h> 
#include <devpkey.h> 
#include <string> 

extern "C"{ 
    #include <hidsdi.h> 
} 

//#pragma comment (lib, "setupapi.lib") 

class DeviceManager 
{ 
public: 
    DeviceManager(); 
    ~DeviceManager(); 

    void ListAllDevices(); 
    void GetDeviceHandler(); 

    //HANDLE PSMove; 
    //byte reportBuffer[57]; 
    GUID guid; 
//private: 
    HDEVINFO deviceInfoSet;    //A list of all the devices 
    SP_DEVINFO_DATA deviceInfoData;  //A device from deviceInfoSet 

    SP_DEVICE_INTERFACE_DATA deviceInterfaceData; 
    SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData; 
}; 

//DeviceManager.cpp 
#include"DeviceManager.h" 

DeviceManager::DeviceManager() 
{ 
    //deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA; 
    //deviceInterfaceDetailedData = new SP_DEVICE_INTERFACE_DETAIL_DATA; 

    HidD_GetHidGuid(&guid); 
    deviceInfoSet = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); //Gets all Devices 
    GetDeviceHandler(); 
} 

DeviceManager::~DeviceManager() 
{ 
} 

void DeviceManager::ListAllDevices() 
{ 
    DWORD deviceIndex = 0; 

    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG tcharSize; 
     CM_Get_Device_ID_Size(&tcharSize, deviceInfoData.DevInst, 0); 
     TCHAR* deviceIDBuffer = new TCHAR[tcharSize]; //the device ID will be stored in this array, so the tcharSize needs to be big enough to hold all the info. 
                 //Or we can use MAX_DEVICE_ID_LEN, which is 200 
     CM_Get_Device_ID(deviceInfoData.DevInst, deviceIDBuffer, MAX_PATH, 0); //gets the devices ID - a long string that looks like a file path. 

     std::cout << deviceIDBuffer << std::endl; 

     deviceIndex++; 
    } 
} 

void DeviceManager::GetDeviceHandler() 
{ 
    DWORD deviceIndex = 0; 

SP_DEVINFO_DATA deviceInfoData; 
SP_DEVICE_INTERFACE_DATA deviceInterfaceData; 
SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData; 

deviceInfoData.cbSize = sizeof(deviceInfoData); 

while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData)) 
{ 
    TCHAR deviceID[MAX_DEVICE_ID_LEN]; 

    CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, MAX_DEVICE_ID_LEN, 0); 

    //std::cout << deviceID << std::endl; 

    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 
    if(SetupDiEnumDeviceInterfaces(deviceInfoSet, &deviceInfoData, &guid, 0, &deviceInterfaceData)) 
    { 
     DWORD bufferLength = 0; 
     //deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 
     deviceInterfaceData.cbSize = 2048; 
     //std::cout << "it works not" << std::endl; 

     if(SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &bufferLength, NULL)) 
     { 
      //deviceInterfaceData.cbSize = sizeof(bufferLength); 
      std::cout << "It works!" << std::endl; 
     } 
     else 
     { 
      std::cout << GetLastError() << std::endl; 
     } 

    } 
    else 
    { 
     //std::cout << GetLastError() << std::endl; 
    } 


    deviceIndex++; 
} 

} 

//mainapp.cpp 
#pragma once 

int main() 
{ 
DeviceManager deviceManager; 

return 0; 
} 

Функция SetupDiGetDeviceInterfaceDetail вызывается в функции GetDeviceHandler() из DeviceManager.

Пожалуйста, помогите. Благодарю.

UPDATE: Я обнаружил, что он не сработал на первом SetupDiGetDeviceInterfaceDetail и возвращает ошибку 122 (ERROR_INSUFFICIENT_BUFFER). Но я только пытаюсь получить требуемый размер буфера, так как это может быть?

UPDATE 2: справа, я немного изменил функцию (см. Выше код), установив deviceInterfaceData.cbsize на 2048 (огромное пространство для тестирования), и теперь я получаю ERROR_INVALID_PARAMETER. Это становится все более запутанным ... Как параметры, которые я дал, недействительны? Просто не имеет смысла. Единственное различие, я прошел в ссылках вместо указателей, потому что в противном случае я получаю сообщение об ошибке нарушения прав доступа ...

ответ

1

Вы не правильно распределяете память для SP_DEVICE_INTERFACE_DETAIL_DATA.

Удалить SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData; и попытайтесь поместить это внутри if блока:

// Get the required bufferLength 
    SetupDiGetDeviceInterfaceDetail(deviceInfoSet, 
            &deviceInterfaceData, 
            nullptr, 
            0, 
            &bufferLength, 
            nullptr); 
    if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) 
    { 
     std::cout << "Failed to get bufferLength. Error " 
        << GetLastError() << '\n'; 
     return; 
    } 

    // Create device interface detailed information struct pointer 
    // and allocate memory to it. 
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData(nullptr); 
    deviceInterfaceDetailedData = 
     static_cast<PSP_INTERFACE_DEVICE_DETAIL_DATA>(malloc(bufferLength)); 
    if(deviceInterfaceDetailedData == nullptr) 
    { 
     std::cout << "Failed to allocate memory. Error " 
        << GetLastError() << '\n'; 
     return; 
    } 
    deviceInterfaceDetailedData->cbSize = 
     sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 

    // Get detailed information 
    if(SetupDiGetDeviceInterfaceDetail(deviceInfoSet, 
             &deviceInterfaceData, 
             deviceInterfaceDetailedData, 
             bufferLength, 
             &bufferLength, 
             nullptr)) 
    { 
     //deviceInterfaceData.cbSize = sizeof(bufferLength); 
     std::cout << "It works!" << std::endl; 
    } 
    else 
    { 
     std::cout << GetLastError() << std::endl; 
    } 

    free(deviceInterfaceDetailedData); 

Я не смотрел на остальной части кода, он может иметь ошибки тоже, но это отвечает на свой вопрос.

+0

Спасибо за ответ. Я ввел SetupDiGetDeviceInterfaceDetail (deviceInfoSet, & deviceInterfaceData, nullptr, 0, & bufferLength, nullptr); как вы показали, и это даже не получило этого. Он возвратил 122 (ERROR_INSUFFICIENT_BUFFER), как указано в коде :( – Danny

+0

Извините, nvm. Ваш код работает: P туманно что-то спасибо alot: D. – Danny

1

Это по определению MSDN:

Получить необходимый размер буфера. Вызовите SetupDiGetDeviceInterfaceDetail с указателем NULLDeviceInterfaceDetailData, DeviceInterfaceDetailDataSize нулевой и действительной переменной RequiredSize. В ответ на такой вызов эта функция возвращает требуемый размер буфера в RequiredSize и с ошибкой GetLastError возвращает ERROR_INSUFFICIENT_BUFFER.

Итак, после ошибки ERROR_INSUFFICIENT_BUFFER просто используйте необходимое значениеSize.

+0

спасибо за ответ. Однако я уже сделал это во второй функции SetupDiGetDeviceInterfaceDetail. Но до сих пор не повезло. – Danny

1

Обнаружив эту тему, я хотел бы поделиться своей проблемой, что, используя точно такой же источник, я получил ERROR_INVALID_USER_BUFFER из вызова.

Причина была линия:

deviceInterfaceDetailedData->cbSize = 
     sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 

, который на моем quadbyte выровнен компилятором установить значение 8 вместо требуемого значения 5.

Смежные вопросы