DeviceIoControl

Aus API-Wiki
Zur Navigation springenZur Suche springen

DeviceIoControl dient zur Kommunikation mit Geräten bzw. deren Treibern. Ab Windows NT können das Modems, CD/DVD-ROM Laufwerke, Festplatten, aber auch Dateien und Verzeichnisse sein, davor nur virtuelle Gerätetreiber. Dabei unterstützt jeder Treiber eine bestimmte Menge an Befehlen, die über bestimmte Codes identifiziert werden.

Declare Function DeviceIoControl Lib "kernel32.dll" ( _

                ByVal hDevice As Long, _
                ByVal dwIoControlCode As Long, _
                lpInBuffer As Any, _
                ByVal nInBufferSize As Long, _
                lpOutBuffer As Any, _
                ByVal nOutBufferSize As Long, _
                lpBytesReturned As Long, _
                lpOverlapped As Any) As Long

Parameter

hDevice

Ein über CreateFile geöffnetes Handle zu einem Gerät, Datei oder Verzeichnis.
Windows 9x/Me: hDevice muss ein Handle zu einem virtuellen Gerätetreiber sein, zum Beispiel "\\.\VWIN32".

dwIoControlCode

Ein Code, der dem Treiber anweist, welche Operation dieser durchführen soll.

lpInBuffer

Falls ein Treiber für dwIoControlCode Daten voraussetzt, sollten diese hier übergeben werden.

nInBufferSize

Die Größe der in lpInBuffer übergebenen Daten in Bytes.

lpOutBuffer

Falls der Treiber Daten zurückgibt, sollte hier ein Buffer übergeben werden, der die Menge an zurückgegebenen Bytes halten kann.

nOutBufferSize

Die Größe des Ausgabepuffer in Bytes.

lpBytesReturned

Hier wird die tatsächliche Menge der in lpOutBuffer geschriebenen Bytes angegeben.

lpOverlapped

Zeiger auf eine OVERLAPPED Struktur, nur benötigt, wenn hDevice mit dem Flag FILE_FLAG_OVERLAPPED geöffnet wurde. Dadurch wird die Operation asynchron ausgeführt, allerdings unterstützen nicht alle Control Codes asynchrone Bearbeitung.

Rückgabe

Ist die Operation erfolgreich, so ist der Rückgabewert ungleich 0. Andernfalls können weitere Fehlerinformationen mit Err.LastDLLError ermittelt werden.

Weiteres

Ein Control Code ist in C so angegeben:

#define IOCTL_DISK_PERFORMANCE \

 CTL_CODE(IOCTL_DISK_BASE, 0x0008, METHOD_BUFFERED, FILE_ANY_ACCESS)

Mit dem CTL_CODE Makro kann ein Control Code berechnet werden.
Übersetzt in VB würde dieses so aussehen:

IOCTL_DISK_PERFORMANCE = CTL_CODE(IOCTL_DISK_BASE, &H8, METHOD_BUFFERED, FILE_ANY_ACCESS)

Private Function CTL_CODE( _

   ByVal lDevType As Long, ByVal lFunction As Long, _
   ByVal lMethod As Long, ByVal lAccess As Long _

) As Long

   CTL_CODE = (lDevType * &H10000) Or (lAccess * &H4000) Or _
              (lFunction * &H4) Or lMethod

End Function

Beispiel

Folgendes Beispiel verwendet DeviceIoControl, um den Bustyp und den Hardwarenamen aller an Buchstaben gemappten Laufwerke des Systems zu ermitteln. Dazu wird der Control Code IOCTL_STORAGE_QUERY_PROPERTY verwendet, welcher mit Windows 2000 eingeführt wurde.

Modul mit Sub Main: Option Explicit

Private Declare Sub CpyMem Lib "kernel32" _ Alias "RtlMoveMemory" ( _

   pDst As Any, pSrc As Any, ByVal cb As Long _

)

Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" ( _

   lpString1 As Any, lpString2 As Any _

) As Long

Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" ( _

   lpString As Any _

) As Long

Private Declare Function CreateFile Lib "kernel32.dll" _ Alias "CreateFileA" ( _

   ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
   ByVal dwShareMode As Long, lpSecurityAttributes As Any, _
   ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
   ByVal hTemplateFile As Long _

) As Long

Private Declare Function DeviceIoControl Lib "kernel32" ( _

   ByVal hDevice As Long, ByVal dwIoControlCode As Long, _
   lpInBuffer As Any, ByVal nInBufferSize As Long, _
   lpOutBuffer As Any, ByVal nOutBufferSize As Long, _
   lpBytesReturned As Long, lpOverlapped As Any _

) As Long

Private Declare Function CloseHandle Lib "kernel32" ( _

   ByVal hObject As Long _

) As Long

Private Const OPEN_EXISTING As Long = 3& Private Const FILE_SHARE_READ As Long = &H1& Private Const FILE_SHARE_WRITE As Long = &H2& Private Const GENERIC_READ As Long = &H80000000

' CTL_CODE(IOCTL_STORAGE_BASE, &H0500, METHOD_BUFFERED, FILE_ANY_ACCESS) Private Const IOCTL_STORAGE_QUERY_PROPERTY As Long = &H2D1400

Private Type STORAGE_PROPERTY_QUERY

   PropertyId                              As STORAGE_PROPERTY_ID
   QueryType                               As STORAGE_QUERY_TYPE
   AdditionalParameters                    As Byte

End Type

Public Type DEVICE_INFORMATION

   Valid                                   As Boolean
   BusType                                 As STORAGE_BUS_TYPE
   Removable                               As Boolean
   VendorID                                As String
   ProductID                               As String
   ProductRevision                         As String

End Type

Private Type STORAGE_DEVICE_DESCRIPTOR

   Version                                 As Long
   Size                                    As Long
   DeviceType                              As Byte
   DeviceTypeModifier                      As Byte
   RemovableMedia                          As Byte
   CommandQueueing                         As Byte
   VendorIdOffset                          As Long
   ProductIdOffset                         As Long
   ProductRevisionOffset                   As Long
   SerialNumberOffset                      As Long
   BusType                                 As Integer
   RawPropertiesLength                     As Long
   RawDeviceProperties                     As Byte

End Type

Private Enum STORAGE_BUS_TYPE

   BusTypeUnknown = 0
   BusTypeScsi
   BusTypeAtapi
   BusTypeAta
   BusType1394
   BusTypeSsa
   BusTypeFibre
   BusTypeUsb
   BusTypeRAID
   BusTypeMaxReserved = &H7F

End Enum

Private Enum STORAGE_PROPERTY_ID

   StorageDeviceProperty = 0
   StorageAdapterProperty
   StorageDeviceIdProperty

End Enum

Private Enum STORAGE_QUERY_TYPE

   PropertyStandardQuery = 0
   PropertyExistsQuery
   PropertyMaskQuery
   PropertyQueryMaxDefined

End Enum

Sub Main()

   Dim i           As Long
   Dim strInfo     As String
   Dim strDevName  As String
   
   For i = 1 To 26
       With GetDevInfo(ChrW$(64 + i))
           If .Valid Then
               Select Case .BusType
                   Case BusTypeUsb:        strInfo = "USB"
                   Case BusType1394:       strInfo = "1394"
                   Case BusTypeAta:        strInfo = "ATA"
                   Case BusTypeAtapi:      strInfo = "ATAPI"
                   Case BusTypeFibre:      strInfo = "Fibre"
                   Case BusTypeRAID:       strInfo = "RAID"
                   Case BusTypeScsi:       strInfo = "SCSI"
                   Case BusTypeSsa:        strInfo = "SSA"
                   Case BusTypeUnknown:    strInfo = "Unknown"
               End Select
               
               strDevName = Trim$(Trim$(.VendorID) & " " & _
                                  Trim$(.ProductID) & " " & _
                                  Trim$(.ProductRevision))
               
               MsgBox "Laufwerk " & ChrW$(64 + i) & " (" & strDevName & ") hat den Bus Typ " & strInfo
           End If
       End With
   Next

End Sub

Private Function GetDevInfo(ByVal strDrive As String) As DEVICE_INFORMATION

   Dim hDrive          As Long
   Dim udtQuery        As STORAGE_PROPERTY_QUERY
   Dim dwOutBytes      As Long
   Dim lngResult       As Long
   Dim btBuffer(9999)  As Byte
   Dim udtOut          As STORAGE_DEVICE_DESCRIPTOR
   
   ' Laufwerke kann man ab Windows NT mit "\\.\X:" öffnen,
   ' wobei X für den Laufwerksbuchstaben steht
   hDrive = CreateFile("\\.\" & Left$(strDrive, 1) & ":", 0, _
                       FILE_SHARE_READ Or FILE_SHARE_WRITE, _
                       ByVal 0&, OPEN_EXISTING, 0, 0)
   If hDrive = -1 Then Exit Function
   
   With udtQuery
       .PropertyId = StorageDeviceProperty
       .QueryType = PropertyStandardQuery
   End With
   
   lngResult = DeviceIoControl(hDrive, IOCTL_STORAGE_QUERY_PROPERTY, _
                               udtQuery, LenB(udtQuery), _
                               btBuffer(0), UBound(btBuffer) + 1, _
                               dwOutBytes, ByVal 0&)
   
   If lngResult Then
       CpyMem udtOut, btBuffer(0), Len(udtOut)
       
       With GetDevInfo
           .Valid = True
           .BusType = udtOut.BusType
           .Removable = CBool(udtOut.RemovableMedia)
           
           If udtOut.ProductIdOffset > 0 Then _
               .ProductID = StringCopy(VarPtr(btBuffer(udtOut.ProductIdOffset)))
           If udtOut.ProductRevisionOffset > 0 Then _
               .ProductRevision = StringCopy(VarPtr(btBuffer(udtOut.ProductRevisionOffset)))
           If udtOut.VendorIdOffset > 0 Then
               .VendorID = StringCopy(VarPtr(btBuffer(udtOut.VendorIdOffset)))
           End If
       End With
   Else
       GetDevInfo.Valid = False
   End If
   
   CloseHandle hDrive

End Function

Private Function StringCopy(ByVal pBuffer As Long) As String

   Dim tmp As String
   
   tmp = Space(lstrlen(ByVal pBuffer))
   lstrcpy ByVal tmp, ByVal pBuffer
   StringCopy = Trim$(tmp)

End Function

Betriebssysteme

  • Windows 95 / 98 / Me
  • Windows NT 4.0 / 2000 / XP
  • Windows Vista

Verweise

MSDN US-Libary