2014-07-03 2 views
0

Mon but est d'écrire un c-dll (compilé avec MinGW) capable de rechercher certains modèles de clés USB connectées à l'ordinateur et de fournir le numéro de série, le fournisseur ID, l'ID du produit et la lettre de lecteur. J'ai cherché sur internet pendant plusieurs heures mais je n'ai pas trouvé d'approche qui fonctionne pour moi. J'utilise Setup Api pour obtenir une liste de tous les périphériques USB connectés. Pour chaque périphérique USB, j'ai un chemin qui ressemble à ceci: \?\usb#vid_048d&pid_1172#00000020370220#{a5dcbf10-6530-11d2-901f-00c04fb951ed} De cette chaîne, je peux obtenir l'identifiant du fournisseur, l'identifiant du produit et le numéro de série que je recherche.Obtenir la lettre du lecteur de disquette USB par chemin d'accès ou poignée

Mon problème est maintenant de déterminer la lettre de lecteur du lecteur USB qui est liée à ce chemin de périphérique. Au cours de ma recherche sur Internet, j'ai trouvé l'approche suivante plusieurs fois (par exemple ici http://oroboro.com/usb-serial-number/): Une fois que le chemin de périphérique est trouvé, le lecteur USB doit être ouvert par CreateFile. Le handle renvoyé par cette fonction peut être utilisé pour obtenir le numéro de périphérique par la fonction DeviceIOControl avec IOCTL_STORAGE_GET_DEVICE_NUMBER. Après cela, la fonction CreateFile pourrait être utilisée pour ouvrir chaque lettre de lecteur (à partir de :) et essayer d'obtenir le numéro de périphérique de la même manière que décrit ci-dessus. Une fois que le même numéro de périphérique est à nouveau trouvé, la relation entre le chemin du périphérique et la lettre du lecteur est établie.

Mon problème est que l'appel IOCTL_STORAGE_GET_DEVICE_NUMBER ne fonctionne pas. La fonction DeviceIOControl renvoie le code d'erreur 50, ce qui signifie "La demande n'est pas prise en charge".

Je ne suis pas en mesure de créer un lien entre le chemin de périphérique d'une clé USB et la lettre de lecteur. J'ai essayé plusieurs appels IOCTL_STORAGE and IOCTL_VOLUME mais aucun n'a fonctionné pour les clés USB que j'ai essayées. J'ai également lu dans un autre forum que les gens avaient des problèmes avec les résultats de la fonction DeviceIOControl. Il restituait le résultat souhaité sur certains PC alors qu'il faisait du mal aux autres. Existe-t-il un autre moyen d'atteindre mon objectif?

J'ai déjà jeté un coup d'oeil dans le registre où je peux également trouver les données désirées. Mais encore une fois, j'ai eu le problème de créer la connexion entre le chemin de périphérique et la lettre de lecteur. Je ne voudrais pas utiliser le WMI. J'ai lu que ce n'est toujours pas vraiment supporté par MinGW. J'ai une implémentation pour tout cela avec C# où il est vraiment facile d'obtenir les informations désirées, mais maintenant j'ai aussi besoin d'un qui est créé avec du code non managé et peut être utilisé pour remplacer un c-dll également inclus dans les projets Delphi.

J'apprécierais toutes les suggestions pour une solution à mon problème.

Cordialement, Florian

Et ici le code si quelqu'un est intéressé. La position avec ce commentaire "// ICI EST O WH JE VOUDRAIS OBTENIR LE NUMÉRO DE L'APPAREIL !!!" est où la demande du numéro de périphérique serait utilisée si cela fonctionnerait.

typedef struct ty_TUSB_Device 
{ 
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData; 
    char        devicePath[300]; 

}TUSB_Device; 

int 
GetUSBDevices (TUSB_Device *devList[], int size) 
{ 
    HANDLE  hHCDev; 

    HDEVINFO       deviceInfo; 
    SP_DEVICE_INTERFACE_DATA   deviceInfoData; 
    ULONG       index; 
    ULONG       requiredLength; 
    int        devCount = 0; 
    //SP_DEVINFO_DATA    DevInfoData; 




    // Now iterate over host controllers using the new GUID based interface 
    // 
    deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USB_DEVICE, 
            NULL, 
            NULL, 
            (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); 

    if (deviceInfo != INVALID_HANDLE_VALUE) 
    { 
     deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 

     for (index=0; 
      SetupDiEnumDeviceInterfaces(deviceInfo, 
             0, 
             (LPGUID)&GUID_DEVINTERFACE_USB_DEVICE, 
             index, 
             &deviceInfoData); 
      index++) 
     { 
      SetupDiGetDeviceInterfaceDetail(deviceInfo, 
              &deviceInfoData, 
              NULL, 
              0, 
              &requiredLength, 
              NULL); 

      //allocate memory for pointer to TUSB_Device structure 
      devList[devCount] = malloc(sizeof(TUSB_Device)); 

      devList[devCount]->deviceDetailData = GlobalAlloc(GPTR, requiredLength); 

      devList[devCount]->deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 

      SetupDiGetDeviceInterfaceDetail(deviceInfo, 
              &deviceInfoData, 
              devList[devCount]->deviceDetailData, 
              requiredLength, 
              &requiredLength, 
              NULL); 

      //open the usb device 
      hHCDev = CreateFile(devList[devCount]->deviceDetailData->DevicePath, 
           GENERIC_WRITE, 
           FILE_SHARE_WRITE, 
           NULL, 
           OPEN_EXISTING, 
           0, 
           NULL); 


      // If the handle is valid, then we've successfully found a usb device 
      // 
      if (hHCDev != INVALID_HANDLE_VALUE) 
      { 
       strncpy(devList[devCount]->devicePath, devList[devCount]->deviceDetailData->DevicePath, sizeof(devList[devCount]->devicePath)); 

       //HERE IS WHERE I WOULD LIKE TO GET THE DEVICE NUMBER!!! 

       CloseHandle(hHCDev); 

       devCount++; 
      } 

      //GlobalFree(devList[devCount]->deviceDetailData); 

     } 

     SetupDiDestroyDeviceInfoList(deviceInfo); 
    } 

    return devCount; 
} 

Répondre

0

J'ai trouvé quel était mon problème. D'après ce que j'ai lu sur internet, il semble que d'autres personnes aient les mêmes problèmes que moi, donc je posterai ma solution. Le point entier est qu'il existe évidemment différentes valeurs de chemin que l'on peut obtenir pour un périphérique USB en utilisant SetupApi. Toutes les valeurs de chemin peuvent être utilisées pour obtenir un handle pour ce périphérique, mais il existe évidemment des différences sur ce qui peut être fait avec le handle. Mon échec était d'utiliser GUID_DEVINTERFACE_USB_DEVICE pour lister les périphériques. J'ai découvert que lorsque j'utilise GUID_DEVINTERFACE_DISK, j'obtiens une valeur de chemin différente qui me permet de demander le numéro de périphérique. De cette façon, je suis en mesure d'obtenir le lien vers la lettre de lecteur. Cette valeur de chemin obtenue avec GUID_DEVINTERFACE_DISK contient également le numéro de série mais pas les identifiants de fournisseur et de produit. Mais puisque les deux valeurs de chemin contiennent la série, il n'y a aucun problème pour les obtenir toutes les deux et construire la relation.

J'ai testé le code avec Windows XP, 7 et 8 et cela fonctionne très bien. Seul le code FileCreate de l'exemple de code ci-dessus doit être ajusté (remplacez GENERIC_WRITE par 0). Sinon, les droits d'administrateur ou le mode de compatibilité sont requis.

Je n'ai pas essayé de savoir ce que représentaient ces différentes valeurs GUID. Quelqu'un ayant une connaissance plus approfondie dans ce domaine pourrait probablement fournir une meilleure explication.

Cordialement, Florian

+0

On peut supposer que le périphérique USB est également le parent du dispositif de disque, vous pouvez aussi les relier de cette façon. –

Questions connexes