Seite 1 von 1

USB device/laufwerksinformationen problem (windows)

Verfasst: 20.06.2007 21:59
von Ramihyn_
Hallo erstmal. Ich schreibe normalerweise nur im englischen Forum aber dort hatte ich diese Anfrage schon gestellt aber keinerlei Antwort bisher bekommen (http://www.purebasic.fr/english/viewtopic.php?t=27644)

Ich versuche die Laufwerksbuchstaben von angeschlossenen USB Festplatten bzw. Flash-Laufwerken zu finden.

Nach viel suchen und studieren von MSDN, Forenartikeln und Webseiten scheint mir der Aufruf SetupDiGetDeviceInterfaceDetail den Pfad zu liefern. Hier ist das MSDN Beispiel dem ich folge: http://msdn2.microsoft.com/en-us/library/aa476413.aspx

Mein Problem ist nun, dass die Aufrufe immer als Fehler zurückmelden es wären keine weiteren Daten vorhanden. So als ob der Geräte/Interfacetyp welchen ich versuche aufzulisten einfach nicht vorhanden ist. Ich habe vorher erfolgreich per SetupDiEnumDeviceInfo and SetupDiGetDeviceRegistryProperty die USB GUIDs sowohl von den HUBs als auch von eingesteckten USB Laufwerken finden können und habe sowohl deren GUID als auch die GUID im MSDN Beispiel sowie die von Freaks tool (http://freak.purearea.net/tools/tools.html) gelistete USB GUID verwendet aber ich bekomme immer das gleiche Ergebnis.

Das Datenformat habe ich anhand der Quellen des DEFINE_GUID Makros sowie anderer Beispiele verifiziert.

Dies ist der Code um das erste Interface abzufragen. Geschrieben mit PB 4.02 für windows und auf Win-XP SP2 probiert. Falls jemand eine Idee hat wo das Problem liegt, so wäre ich über einen Tipp sehr dankbar :) Funktioniert es vielleicht auf anderen Rechnern?

Code: Alles auswählen

Structure SP_DEVINFO_DATA
  cbSize.l
  ClassGuid.GUID
  DevInst.l
  Reserved.l
EndStructure

Structure SP_DEVICE_INTERFACE_DATA
  cbSize.l
  InterfaceClassGuid.GUID
  Flags.l
  *Reserved.l
EndStructure

Structure SP_DEVICE_INTERFACE_DETAIL_DATA
  cbSize.l
  DevicePath.s[256]
EndStructure

DataSection

GUID_DEVCLASS_USB:      ; {36FC9E60-C465-11CF-8056-444553540000}
;   Data.l $36FC9E60
;   Data.w $C465, $11CF
;   Data.b $80, $56, $44, $45, $53, $54, $00, $00

  Data.l $058815b2
  Data.w $9805, $47d3
  Data.b $b7, $d5, $ab, $c4, $64, $d3, $ca, $06

EndDataSection

#DIGCF_PRESENT          = 2
#DIGCF_ALLCLASSES       = 4
#DIGCF_DEVICEINTERFACE  = 16

#SPDRP_DEVICEDESC                  =   0 ; ECP-Druckeranschluss
#SPDRP_HARDWAREID                  =   1 ; ACPI\PNP0401
#SPDRP_COMPATIBLEIDS               =   2 ; (err13)
#SPDRP_SERVICE                     =   4 ; Parport
#SPDRP_CLASS                       =   7 ; Ports
#SPDRP_CLASSGUID                   =   8 ; {4D36E978-E325-11CE-BFC1-08002BE10318}
#SPDRP_DRIVER                      =   9 ; {4D36E978-E325-11CE-BFC1-08002BE10318}\0000
#SPDRP_CONFIGFLAGS                 =  10 ; 127 (Zahl=Long)
#SPDRP_MFG                         =  11 ; (Standardanschlusstypen)
#SPDRP_FRIENDLYNAME                =  12 ; ECP-Druckeranschluss (LPT1)
#SPDRP_LOCATION_INFORMATION        =  13 ; (err13)
#SPDRP_PHYSICAL_DEVICE_OBJECT_NAME =  14 ; \Device\0000005c
#SPDRP_CAPABILITIES                =  15 ; 48 (Zahl=Long)
#SPDRP_UI_NUMBER                   =  16 ; (err13)
#SPDRP_UPPERFILTERS                =  17 ; (err13)
#SPDRP_LOWERFILTERS                =  18
#SPDRP_BUSTYPEGUID                 =  19
#SPDRP_LEGACYBUSTYPE               =  20
#SPDRP_BUSNUMBER                   =  21
#SPDRP_ENUMERATOR_NAME             =  22 ; ACPI
#SPDRP_SECURITY                    =  23
#SPDRP_SECURITY_SDS                =  24
#SPDRP_DEVTYPE                     =  25
#SPDRP_EXCLUSIVE                   =  26
#SPDRP_CHARACTERISTICS             =  27
#SPDRP_ADDRESS                     =  28
#SPDRP_UI_NUMBER_DESC_FORMAT       =  30

Prototype.l ProtoSetupDiGetDeviceInterfaceDetailA(DeviceInfoSet.l, *DeviceInterfaceData.l, *DeviceInterfaceDetailData.l, DeviceInterfaceDetailDataSize.l, *RequiredSize.l, *DeviceInfoData.l)
Prototype.l ProtoSetupDiEnumDeviceInterfaces(DeviceInfoSet.l, *DeviceInfoData.l, *InterfaceClassGuid.l, MemberIndex.l, *DeviceInterfaceData.l)

Procedure USB_Test()

  DeviceInfoData.SP_DEVINFO_DATA
  DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA
  DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA

  Debug "Start test"

  ; get DeviceInterface Api entries which arent natively supported by PB 4.x

  libHandle = OpenLibrary(#PB_Any, "Setupapi.dll")

  If (libHandle)
    SetupDiGetDeviceInterfaceDetail.ProtoSetupDiGetDeviceInterfaceDetailA = GetFunction(libHandle, "SetupDiGetDeviceInterfaceDetailA")
    SetupDiEnumDeviceInterfaces.ProtoSetupDiEnumDeviceInterfaces          = GetFunction(libHandle, "SetupDiEnumDeviceInterfaces")

    If ((SetupDiGetDeviceInterfaceDetail = 0) Or (SetupDiEnumDeviceInterfaces = 0))
      Debug "SetupApi interface initialisation failed"
      ProcedureReturn
    EndIf

;      If (ExamineLibraryFunctions(res))
;        While (NextLibraryFunction())
;          Debug "-> " + LibraryFunctionName()
;        Wend
;      EndIf
  Else
    Debug "Opening SetupApi failed"
    ProcedureReturn
  EndIf

  hDevInfo = SetupDiGetClassDevs_(?GUID_DEVCLASS_USB, #Null, #Null, #DIGCF_PRESENT | #DIGCF_DEVICEINTERFACE)

  If (hDevInfo = #INVALID_HANDLE_VALUE)
    Debug "Inv handle"

    ProcedureReturn
  EndIf

  ; -- DeviceInterface --

  DeviceInterfaceData\cbSize  = SizeOf(SP_DEVICE_INTERFACE_DATA)

  nstatus.l = SetupDiEnumDeviceInterfaces(hDevInfo, #Null, ?GUID_DEVCLASS_USB, 0, @DeviceInterfaceData)

  If (nstatus = #False)
    lerr = GetLastError_()
    msg$ = Space(4000)
    nchars.l = FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, lerr, 0, @msg$, 3500, 0)
    If (nchars > 2)
      Debug "Error (" + Str(lerr) + "): " + Left(msg$, nchars - 2)
    EndIf
  Else
    Debug "EnumDeviceInterface status: " + Str(nstatus)

    DeviceInterfaceDetailData\cbSize = SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA)
    nstatus = SetupDiGetDeviceInterfaceDetail(hDevInfo, @DeviceInterfaceData, @DeviceInterfaceDetailData, 248, 0, @DeviceInfoData)

    If (nstatus = 0)
      lerr = GetLastError_()
      msg$ = Space(4000)
      nchars.l = FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, lerr, 0, @msg$, 3500, 0)
      If (nchars > 2)
        Debug "Error: " + Left(msg$, nchars - 2)
      EndIf
    EndIf
   
  EndIf

  SetupDiDestroyDeviceInfoList_(hDevInfo)

  ProcedureReturn

EndProcedure


USB_Test() 
Weitere MSDN Referenzen die dazu nützlich sind:
http://msdn2.microsoft.com/en-us/library/ms791242.aspx
http://msdn2.microsoft.com/en-us/library/ms791134.aspx

Verfasst: 21.06.2007 10:36
von jear
@Rahmihyn_
Hier ein Code der zwar funktioniert, von dem ich aber die Quelle nicht nennen kann.

Code: Alles auswählen

Structure STORAGE_PROPERTY_QUERY 
  PropertyId.l;STORAGE_PROPERTY_ID 
  QueryType.l;STORAGE_QUERY_TYPE 
  AdditionalParameters.l 
EndStructure 

Structure STORAGE_DEVICE_DESCRIPTOR 
  Version.l 
  Size.l;                                    As Long 
  DeviceType.b;                              As Byte 
  DeviceTypeModifier.b;                      As Byte 
  RemovableMedia.b;                          As Byte 
  CommandQueueing.b;                         As Byte 
  VendorIdOffset.l;                          As Long 
  ProductIdOffset.l;                         As Long 
  ProductRevisionOffset.l;                   As Long 
  SerialNumberOffset.l;                      As Long 
  BusType.w;                                 As Integer 
  RawPropertiesLength.l;                     As Long 
  RawDeviceProperties.b;                     As Byte 
  reserved.b[1024] 
EndStructure 

#BusTypeUnknown = 0 
#BusTypeScsi=1 
#BusTypeAtapi=2 
#BusTypeAta=3 
#BusType1394=4 
#BusTypeSsa=5 
#BusTypeFibre=6 
#BusTypeUsb=7 
#BusTypeRAID=8 
#BusTypeMaxReserved = $7F 
    
#IOCTL_STORAGE_QUERY_PROPERTY  = $2D1400 



Procedure.l Hex2Dec(h$) 
  h$=UCase(h$) 
  For r=1 To Len(h$) 
    d<<4 : a$=Mid(h$,r,1) 
    If Asc(a$)>60 
      d+Asc(a$)-55 
    Else 
      d+Asc(a$)-48 
    EndIf 
  Next 
  ProcedureReturn d 
EndProcedure 

OpenConsole() 
PrintN("Enumerate devices") 

For Drives=1 To 26 
  
  strDrive.s="\\.\" + Chr(64+Drives) + ":" 
  
  hDrive = CreateFile_(strDrive, 0,#FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0) 
  If hDrive<>-1 
    
    PrintN("--------------------------------------------------") 
    
    udtQuery.STORAGE_PROPERTY_QUERY 
    udtOut.STORAGE_DEVICE_DESCRIPTOR 
    ;clear advanced Info.... 
    For p=0 To 1023 
      udtOut\reserved[p]=0 
    Next p 
    lngResult = DeviceIoControl_(hDrive, #IOCTL_STORAGE_QUERY_PROPERTY, udtQuery,SizeOf(udtQuery), @udtOut, SizeOf(udtout), @dwOutBytes, 0) 
    If lngResult 
      PrintN("Drive " + Chr(64+Drives) + ": is a ") 
      Select(udtOut\BusType) 
        Case     #BusTypeUnknown 
        Case #BusTypeScsi 
          PrintN(" SCSI Device") 
        Case #BusTypeAtapi 
          PrintN(" Atapi Device") 
        Case #BusTypeAta 
          PrintN(" Ata Device") 
        Case #BusType1394 
        Case #BusTypeSsa 
        Case #BusTypeFibre 
        Case #BusTypeUsb 
          PrintN(" USB Device") 
        Case #BusTypeRAID 
        Case #BusTypeMaxReserved 
        Default 
          PrintN("Bustype=" + Str(udtOut\BusType)) 
      EndSelect 
      
      If udtOut\RemovableMedia 
        PrintN("Device is Removable Media") 
      EndIf 
      
      If udtOut\ProductIdOffset > 0 
        PrintN("ProductID=" + PeekS(@udtOut + udtOut\ProductIdOffset)) 
      EndIf 
      
      If udtOut\ProductRevisionOffset > 0 
        PrintN("ProductRevision=" + PeekS(@udtOut +  udtOut\ProductRevisionOffset)) 
      EndIf 
      
      If udtOut\VendorIdOffset  > 0 
        PrintN("VendorID=" + PeekS(@udtOut +  udtOut\VendorIdOffset )) 
      EndIf 
      
      If udtOut\SerialNumberOffset  > 0 
        SerialNumber.s=PeekS(@udtOut +  udtOut\SerialNumberOffset ) 
        ;Now convert into readable format, coz its encrypted in HEX-Ascii 
        sdummy.s="" 
        For t=1 To Len(SerialNumber) Step 2 
          sdummy + Chr(Hex2Dec(Mid(SerialNumber,t,2))) 
        Next t 
        PrintN("SerialNumber=" + sdummy) 
      EndIf 
      
    Else 
      PrintN("No Device-IO info available.. for "+Chr(64+Drives) + ":") 
      
    EndIf 
  EndIf 
  CloseHandle_(hDrive) 
  
  
Next Drives 
  
wait.s=Input() 
CloseConsole() 

Verfasst: 21.06.2007 17:56
von Ramihyn_
Vielen Dank jear!

Per DeviceIoControl funktioniert es. :)

Verfasst: 01.07.2007 17:11
von kayfr72
Hab mir mal dein Listing angeschaut. So gehts auch wenn man auch andere Geräte suchen will. :freak:

Code: Alles auswählen

Structure SP_DEVINFO_DATA 
  cbSize.l 
  ClassGuid.GUID 
  DevInst.l 
  Reserved.l 
EndStructure 



#DIGCF_PRESENT          = 2 
#DIGCF_ALLCLASSES       = 4 
#DIGCF_DEVICEINTERFACE  = 16 



Prototype.l ProtoSetupDiGetDeviceInterfaceDetailA(DeviceInfoSet.l, *DeviceInterfaceData.l, *DeviceInterfaceDetailData.l, DeviceInterfaceDetailDataSize.l, *RequiredSize.l, *DeviceInfoData.l) 
Prototype.l ProtoSetupDiEnumDeviceInterfaces(DeviceInfoSet.l, *DeviceInfoData.l, *InterfaceClassGuid.l, MemberIndex.l, *DeviceInterfaceData.l) 

  



DeviceInfoData.SP_DEVINFO_DATA 

  
  
libHandle = OpenLibrary(0, "Setupapi.dll")
;If (ExamineLibraryFunctions(0)) 
;        While (NextLibraryFunction()) 
 ;         Debug "-> " + LibraryFunctionName() 
  ;      Wend 
   ;   EndIf
 If libHandle 
    SetupDiGetDeviceInterfaceDetail.ProtoSetupDiGetDeviceInterfaceDetailA = GetFunction(0, "SetupDiGetDeviceInterfaceDetailA") 
    SetupDiEnumDeviceInterfaces.ProtoSetupDiEnumDeviceInterfaces          =  GetFunction(0, "SetupDiEnumDeviceInterfaces") 
    
If ((SetupDiGetDeviceInterfaceDetail = 0) Or (SetupDiEnumDeviceInterfaces = 0)) 
      Debug "SetupApi interface initialisation failed" 
      
    EndIf 

 
  Else 
    Debug "Opening SetupApi failed" 
    
  EndIf     

   
 hDevInfo = SetupDiGetClassDevs_(#Null, 0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)
 
 
  DeviceInfoData\cbSize= SizeOf(SP_DEVINFO_DATA)

mem =AllocateMemory(400)

 While   SetupDiEnumDeviceInfo_(hDevInfo, s, @DeviceInfoData)
  
s=s+1
SetupDiGetDeviceRegistryProperty_(hDevInfo,@DeviceInfoData,0,0,mem,512,0)
 
Debug PeekS(mem)

Wend