DeviceIoControl

Aus API-Wiki
Wechseln zu: Navigation, Suche

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