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 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