|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Disk/Drive API Routines DeviceIoControl: Obtain Physical Drive Information |
|
Posted: | Saturday January 8, 2000 |
Updated: | Monday December 26, 2011 |
Applies to: | VB4-32, VB5, VB6 |
Developed with: | VB6, Windows NT4 |
OS restrictions: | Windows NT4, Windows 2000, Windows XP |
Author: | Thomas Kabir, VBnet - Randy Birch |
Related: |
DeviceIoControl: Check Media Availability DeviceIoControl: Load/Eject Removable Media DeviceIoControl: Lock/Unlock Removable Media Devices Win32_DiskDrive: WMI Disk Drive Information |
Prerequisites |
Windows NT, Windows 2000, Windows XP |
|
Win
NT/Win2000 developers have access to a unique API that provides low-level system information - DeviceIoControl.
This example succeeds only when it runs on Windows NT/Windows 2000/Windows XP, for two reasons:
On Windows NT/2000/XP, an application can use the DeviceIoControl function to perform direct input and output operations on, or retrieve information about, a floppy disk drive, hard disk drive, tape drive, or CD-ROM drive. This page demonstrates how to retrieve information about the installed physical drives on the system. It uses the CreateFile function to obtain a device handle to the physical drives, and then uses DeviceIoControl with the IOCTL_DISK_GET_DRIVE_GEOMETRY control code to fill a DISK_GEOMETRY structure with information about the drive. The IOCTL_DISK_GET_DRIVE_GEOMETRY control code returns information about the physical disk's geometry: type, number of cylinders, tracks per cylinder, sectors per track, and bytes per sector. The DISK_GEOMETRY structure describes the geometry of disk devices and media. Note that the first parameter of the DISK_GEOMETRY type is defined as a LARGE_INTEGER, requiring the VB Currency data type to be used instead of a traditional Long. This demo is based on code in Thomas Kabir's Physische Laufwerke demo,and is reproduced here with permission. Note: The demo uses the VB6 FormatNumber function, which is not available in VB4-32 or VB5. Users of these versions should use Format$() instead, i.e. Format$(value, "###,###,###). |
BAS Module Code |
Place the following code into the general declarations area of a bas module: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Const MAX_PATH As Long = 260 Public Const FORMAT_MESSAGE_FROM_SYSTEM As Long = &H1000 Public Const FORMAT_MESSAGE_IGNORE_INSERTS As Long = &H200 Public Const FILE_SHARE_READ As Long = &H1 Public Const FILE_SHARE_WRITE As Long = &H2 Public Const OPEN_EXISTING As Long = 3 Public Const INVALID_HANDLE_VALUE As Long = -1 Public Const ERROR_FILE_NOT_FOUND As Long = 2 Public Const IOCTL_DISK_GET_DRIVE_GEOMETRY As Long = &H70000 'media type constants Public Const unknown As Long = 0 Public Const F5_1Pt2_512 As Long = 1 Public Const F3_1Pt44_512 As Long = 2 Public Const F3_2Pt88_512 As Long = 3 Public Const F3_20Pt8_512 As Long = 4 Public Const F3_720_512 As Long = 5 Public Const F5_360_512 As Long = 6 Public Const F5_320_512 As Long = 7 Public Const F5_320_1024 As Long = 8 Public Const F5_180_512 As Long = 9 Public Const F5_160_512 As Long = 10 Public Const Removable As Long = 11 Public Const FixedMedia As Long = 12 Public Const F3_120M_512 As Long = 13 Public Const F3_640_512 As Long = 14 Public Const F5_640_512 As Long = 15 Public Const F5_720_512 As Long = 16 Public Const F3_1Pt2_512 As Long = 17 Public Const F3_1Pt23_1024 As Long = 18 Public Const F5_1Pt23_1024 As Long = 19 Public Const F3_128Mb_512 As Long = 20 Public Const F3_230Mb_512 As Long = 21 Public Const F8_256_128 As Long = 22 Public Const F3_200Mb_512 As Long = 23 Public Const F3_240M_512 As Long = 24 Public Const F3_32M_512 As Long = 25 Public Type DISK_GEOMETRY Cylinders As Currency 'LARGE_INTEGER (8 bytes) MediaType As Long TracksPerCylinder As Long SectorsPerTrack As Long BytesPerSector As Long End Type Public Declare Function FormatMessage Lib "kernel32" _ Alias "FormatMessageA" _ (ByVal dwFlags As Long, _ lpSource As Long, _ ByVal dwMessageId As Long, _ ByVal dwLanguageId As Long, _ ByVal lpBuffer As String, _ ByVal nSize As Long, _ Arguments As Any) As Long Public Declare Function CreateFile Lib "kernel32" _ Alias "CreateFileA" _ (ByVal lpFileName As String, _ ByVal dwDesiredAccess As Long, _ ByVal dwShareMode As Long, _ ByVal lpSecurityAttributes As Any, _ ByVal dwCreationDisposition As Long, _ ByVal dwFlagsAndAttributes As Long, _ ByVal hTemplateFile As Long) As Long Public Declare Function CloseHandle Lib "kernel32" _ (ByVal hObject As Long) As Long Public 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 Public Function GetDiskSizeString(dg As DISK_GEOMETRY) As String Dim nCapacity As Variant With dg 'Determine the disk capacity by multiplying 'the returned values. Because Cylinders is 'declared as Currency, it must be multiplied 'by 10,000 to eliminate the decimal. nCapacity = (.Cylinders * 10000) * _ .TracksPerCylinder * _ .SectorsPerTrack * _ .BytesPerSector End With 'Return a string representing the 'drive size to three decimal places. 'Note: FormatNumber is VB6-specific; 'if you use VB4-32 or VB5 use Format$ Select Case nCapacity Case Is < (2 ^ 20): GetDiskSizeString = FormatNumber(nCapacity / 2 ^ 10, 3) & " KB" Case Is < (2 ^ 30) GetDiskSizeString = FormatNumber(nCapacity / 2 ^ 20, 3) & " MB" Case Is < (2 ^ 40) GetDiskSizeString = FormatNumber(nCapacity / 2 ^ 30, 3) & " GB" Case Else GetDiskSizeString = FormatNumber(nCapacity / 2 ^ 40, 3) & " TB" End Select End Function Public Function GetDiskGeometry(hDevice As Long) As DISK_GEOMETRY Dim bytesReturned As Long 'Another handle check! If hDevice <> INVALID_HANDLE_VALUE Then 'Call the function. The returned 'information is passed directly 'to the return value of this function. DeviceIoControl hDevice, _ IOCTL_DISK_GET_DRIVE_GEOMETRY, _ ByVal 0&, _ 0&, _ GetDiskGeometry, _ Len(GetDiskGeometry), _ bytesReturned, _ ByVal 0& End If End Function Public Function GetMediaType(MediaType As Long) As String Select Case MediaType Case 0: GetMediaType = "Format unknown" Case F5_1Pt2_512: GetMediaType = "5.25, 1.2MB, 512 bytes/sector" Case F3_1Pt44_512: GetMediaType = "3.5, 1.44MB, 512 bytes/sector" Case F3_2Pt88_512: GetMediaType = "3.5, 2.88MB, 512 bytes/sector" Case F3_20Pt8_512: GetMediaType = "3.5, 20.8MB, 512 bytes/sector" Case F3_720_512: GetMediaType = "3.5, 720KB, 512 bytes/sector" Case F5_360_512: GetMediaType = "5.25, 360KB, 512 bytes/sector" Case F5_320_512: GetMediaType = "5.25, 320KB, 512 bytes/sector" Case F5_320_1024: GetMediaType = "5.25, 320KB, 1024 bytes/sector" Case F5_180_512: GetMediaType = "5.25, 180KB, 512 bytes/sector" Case F5_160_512: GetMediaType = "5.25, 160KB, 512 bytes/sector" Case Removable: GetMediaType = "Removable media other than floppy" Case FixedMedia: GetMediaType = "Fixed hard disk" Case F3_120M_512: GetMediaType = "3.5, 120M Floppy" Case F3_640_512: GetMediaType = "3.5, 640KB, 512 bytes/sector" Case F5_640_512: GetMediaType = "5.25, 640KB, 512 bytes/sector" Case F5_720_512: GetMediaType = "5.25, 720KB, 512 bytes/sector" Case F3_1Pt2_512: GetMediaType = "3.5, 1.2Mb, 512 bytes/sector" Case F3_1Pt23_1024: GetMediaType = "3.5, 1.23Mb, 1024 bytes/sector" Case F5_1Pt23_1024: GetMediaType = "5.25, 1.23MB, 1024 bytes/sector" Case F3_128Mb_512: GetMediaType = "3.5 MO 128Mb, 512 bytes/sector" Case F3_230Mb_512: GetMediaType = "3.5 MO 230Mb, 512 bytes/sector" Case F8_256_128: GetMediaType = "8, 256KB, 128 bytes/sector" Case F3_200Mb_512: GetMediaType = "3.5, 200M Floppy (HiFD)" Case F3_240M_512: GetMediaType = "3.5, 240Mb Floppy (HiFD)" Case F3_32M_512: GetMediaType = "3.5, 32Mb Floppy" End Select End Function Public Function GetSystemMessage(msgID As Long) As String Dim ret As Long Dim sBuff As String sBuff = Space(256) ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM _ Or FORMAT_MESSAGE_IGNORE_INSERTS, _ 0&, msgID, _ 0, sBuff, Len(sBuff), ByVal 0) If (ret <> 0) Then GetSystemMessage = Left(sBuff, ret) Else GetSystemMessage = "unknown error" End If End Function |
Form Code |
Add a listview (ListView1) and a command button to a form. To the listview, add seven column headers as shown above, and set the style to report mode. Add the following to the form: |
|
Option Explicit Private Sub Command1_Click() GetPhysicalDrives End Sub Private Sub GetPhysicalDrives() Dim hDevice As Long Dim dg As DISK_GEOMETRY Dim nCapacity As Variant Dim nDevice As Long Do 'Attempt to obtain a handle to the device 'that is to perform the operation, in this 'case physical drive n. The first drive 'is 0, second drive is 1 etc. ' 'hDevice will return INVALID_HANDLE_VALUE 'when no more physical drives are located. hDevice = CreateFile("\\.\PHYSICALDRIVE" & CStr(nDevice), _ 0&, _ FILE_SHARE_READ Or FILE_SHARE_WRITE, _ ByVal 0&, _ OPEN_EXISTING, _ 0&, 0&) 'If a valid handle, pass that to 'obtain the physical disk geometry If hDevice <> INVALID_HANDLE_VALUE Then 'Obtain the DISK_GEOMETRY type information 'and determine the disk capacity dg = GetDiskGeometry(hDevice) 'Add data to the listview LVAdd nDevice, dg 'Close the device handle and 'increment the device number count. CloseHandle hDevice nDevice = nDevice + 1 Else 'hDevice was invalid, so determine the error If Err.LastDllError = ERROR_FILE_NOT_FOUND Then 'No more physical drives. Exit Do Else 'This should never fire! MsgBox "GetPhysicalDrives error:" & vbCrLf & _ GetSystemMessage(Err.LastDllError), vbCritical Exit Do End If End If Loop End Sub Private Sub LVAdd(nDevice As Long, dg As DISK_GEOMETRY) Dim itmX As ListItem Set itmX = ListView1.ListItems.Add(, , "Drive " & nDevice) itmX.SubItems(1) = GetDiskSizeString(dg) 'size in KB, MB, GB, TB itmX.SubItems(2) = CStr(dg.Cylinders * 10000) itmX.SubItems(3) = CStr(dg.TracksPerCylinder) itmX.SubItems(4) = CStr(dg.SectorsPerTrack) itmX.SubItems(5) = CStr(dg.BytesPerSector) itmX.SubItems(6) = GetMediaType(dg.MediaType) 'media type, i.e. fixed End Sub |
Comments |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |