DeviceIoControl
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 sagt, was er tun 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 Output Buffers 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 geglückt, ist der Rückgabewert ungleich 0. Andernfalls können weitere Fehlerinformationen mit GetLastError 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 Bus Typ und den Hardwarenamen aller an Buchstaben gemappten Laufwerke des Systems zu ermitteln. Dazu wird der Control Code IOCTL_STORAGE_QUERY_PROPERTY verwendet, dieser wurde schätzungsweise mit Windows 2000 eingeführt.
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: