I've got a cool piece of code taken from a VC++ project which gets complete information of the hard disk drive WITHOUT using WMI (since WMI has got its own problems) I ask those of you who are comfortable with API functions to try to convert this VB6 code into VB (or C#) .NET and help A LOT of people who are in great need of this utility class. I've spent lots of time and searched the entire net to find ways to get the actual model and serial number of HDD and eventually found this one, if only it were in .NET... Here is the code and sorry about its formatting problems, just paste it into VB6 IDE:
Option Explicit
''// Antonio Giuliana, 2001-2003
''// Costanti per l'individuazione della versione di OS
Private Const VER_PLATFORM_WIN32S = 0
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VER_PLATFORM_WIN32_NT = 2
''// Costanti per la comunicazione con il driver IDE
Private Const DFP_RECEIVE_DRIVE_DATA = &H7C088
''// Costanti per la CreateFile
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_EXISTING = 3
Private Const CREATE_NEW = 1
''// Enumerazione dei comandi per la CmnGetHDData
Private Enum HDINFO
HD_MODEL_NUMBER
HD_SERIAL_NUMBER
HD_FIRMWARE_REVISION
End Enum
''// Struttura per l'individuazione della versione di OS
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
''// Struttura per il campo irDriveRegs della struttura SENDCMDINPARAMS
Private Type IDEREGS
bFeaturesReg As Byte
bSectorCountReg As Byte
bSectorNumberReg As Byte
bCylLowReg As Byte
bCylHighReg As Byte
bDriveHeadReg As Byte
bCommandReg As Byte
bReserved As Byte
End Type
''// Struttura per l'I/O dei comandi al driver IDE
Private Type SENDCMDINPARAMS
cBufferSize As Long
irDriveRegs As IDEREGS
bDriveNumber As Byte
bReserved(1 To 3) As Byte
dwReserved(1 To 4) As Long
End Type
''// Struttura per il campo DStatus della struttura SENDCMDOUTPARAMS
Private Type DRIVERSTATUS
bDriveError As Byte
bIDEStatus As Byte
bReserved(1 To 2) As Byte
dwReserved(1 To 2) As Long
End Type
''// Struttura per l'I/O dei comandi al driver IDE
Private Type SENDCMDOUTPARAMS
cBufferSize As Long
DStatus As DRIVERSTATUS ''// ovvero DriverStatus
bBuffer(1 To 512) As Byte
End Type
''// Per ottenere la versione del SO
Private Declare Function GetVersionEx _
Lib "kernel32" Alias "GetVersionExA" _
(lpVersionInformation As OSVERSIONINFO) As Long
''// Per ottenere un handle al device IDE
Private Declare Function CreateFile _
Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
''// Per chiudere l'handle del device IDE
Private Declare Function CloseHandle _
Lib "kernel32" _
(ByVal hObject As Long) As Long
''// Per comunicare con il driver IDE
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, _
ByVal lpOverlapped As Long) As Long
''// Per azzerare buffer di scambio dati
Private Declare Sub ZeroMemory _
Lib "kernel32" Alias "RtlZeroMemory" _
(dest As Any, _
ByVal numBytes As Long)
''// Per copiare porzioni di memoria
Private Declare Sub CopyMemory _
Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
Private Declare Function GetLastError _
Lib "kernel32" () As Long
Private mvarCurrentDrive As Byte ''// Drive corrente
Private mvarPlatform As String ''// Piattaforma usata
Public Property Get Copyright() As String
''// Copyright
Copyright = "HDSN Vrs. 1.00, (C) Antonio Giuliana, 2001-2003"
End Property
''// Metodo GetModelNumber
Public Function GetModelNumber() As String
''// Ottiene il ModelNumber
GetModelNumber = CmnGetHDData(HD_MODEL_NUMBER)
End Function
''// Metodo GetSerialNumber
Public Function GetSerialNumber() As String
''// Ottiene il SerialNumber
GetSerialNumber = CmnGetHDData(HD_SERIAL_NUMBER)
End Function
''// Metodo GetFirmwareRevision
Public Function GetFirmwareRevision() As String
''// Ottiene la FirmwareRevision
GetFirmwareRevision = CmnGetHDData(HD_FIRMWARE_REVISION)
End Function
''// Proprieta' CurrentDrive
Public Property Let CurrentDrive(ByVal vData As Byte)
''// Controllo numero di drive fisico IDE
If vData < 0 Or vData > 3 Then
Err.Raise 10000, , "Illegal drive number" ''// IDE drive 0..3
End If
''// Nuovo drive da considerare
mvarCurrentDrive = vData
End Property
''// Proprieta' CurrentDrive
Public Property Get CurrentDrive() As Byte
''// Restituisce drive fisico corrente (IDE 0..3)
CurrentDrive = mvarCurrentDrive
End Property
''// Proprieta' Platform
Public Property Get Platform() As String
''// Restituisce tipo OS
Platform = mvarPlatform
End Property
Private Sub Class_Initialize()
''// Individuazione del tipo di OS
Dim OS As OSVERSIONINFO
OS.dwOSVersionInfoSize = Len(OS)
Call GetVersionEx(OS)
mvarPlatform = "Unk"
Select Case OS.dwPlatformId
Case Is = VER_PLATFORM_WIN32S
mvarPlatform = "32S" ''// Win32S
Case Is = VER_PLATFORM_WIN32_WINDOWS
If OS.dwMinorVersion = 0 Then
mvarPlatform = "W95" ''// Win 95
Else
mvarPlatform = "W98" ''// Win 98
End If
Case Is = VER_PLATFORM_WIN32_NT
mvarPlatform = "WNT" ''// Win NT/2000
End Select
End Sub
Private Function CmnGetHDData(hdi As HDINFO) As String
''// Rilevazione proprieta' IDE
Dim bin As SENDCMDINPARAMS
Dim bout As SENDCMDOUTPARAMS
Dim hdh As Long
Dim br As Long
Dim ix As Long
Dim hddfr As Long
Dim hddln As Long
Dim s As String
Select Case hdi ''// Selezione tipo caratteristica richiesta
Case HD_MODEL_NUMBER
hddfr = 55 ''// Posizione nel buffer del ModelNumber
hddln = 40 ''// Lunghezza nel buffer del ModelNumber
Case HD_SERIAL_NUMBER
hddfr = 21 ''// Posizione nel buffer del SerialNumber
hddln = 20 ''// Lunghezza nel buffer del SerialNumber
Case HD_FIRMWARE_REVISION
hddfr = 47 ''// Posizione nel buffer del FirmwareRevision
hddln = 8 ''// Lunghezza nel buffer del FirmwareRevision
Case Else
Err.Raise 10001, "Illegal HD Data type"
End Select
Select Case mvarPlatform
Case "WNT"
''// Per Win NT/2000 apertura handle al drive fisico
hdh = CreateFile("\\.\PhysicalDrive" & mvarCurrentDrive, _
GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, _
0, OPEN_EXISTING, 0, 0)
Case "W95", "W98"
''// Per Win 9X apertura handle al driver SMART
''// (in \WINDOWS\SYSTEM da spostare in \WINDOWS\SYSTEM\IOSUBSYS)
''// che comunica con il driver IDE
hdh = CreateFile("\\.\Smartvsd", _
0, 0, 0, CREATE_NEW, 0, 0)
Case Else
''// Piattaforma non supportata (Win32S)
Err.Raise 10002, , "Illegal platform (only WNT, W98 or W95)"
End Select
''// Controllo validità handle
If hdh = 0 Then
Err.Raise 10003, , "Error on CreateFile"
End If
''// Azzeramento strutture per l'I/O da driver
ZeroMemory bin, Len(bin)
ZeroMemory bout, Len(bout)
''// Preparazione parametri struttura di richiesta al driver
With bin
.bDriveNumber = mvarCurrentDrive
.cBufferSize = 512
With .irDriveRegs
If (mvarCurrentDrive And 1) Then
.bDriveHeadReg = &HB0
Else
.bDriveHeadReg = &HA0
End If
.bCommandReg = &HEC
.bSectorCountReg = 1
.bSectorNumberReg = 1
End With
End With
''// Richiesta al driver
DeviceIoControl hdh, DFP_RECEIVE_DRIVE_DATA, _
bin, Len(bin), bout, Len(bout), br, 0
''// Formazione stringa di risposta
''// da buffer di uscita
''// L'ordine dei byte e' invertito
s = ""
For ix = hddfr To hddfr + hddln - 1 Step 2
If bout.bBuffer(ix + 1) = 0 Then Exit For
s = s & Chr(bout.bBuffer(ix + 1))
If bout.bBuffer(ix) = 0 Then Exit For
s = s & Chr(bout.bBuffer(ix))
Next ix
''// Chiusura handle
CloseHandle hdh
''// Restituzione informazione richiesta
CmnGetHDData = Trim(s)
End Function
Yeah, I know VB6 but the problem is with the API function declarations and the attributes required to pass those structures (types) to them. That's where I don't have the time to spend! If you have an automated VB6 to VB.NET tool and VB6 itself, please save the code as a VB6 project and do convert the code. I don't have my VB6 around.
That's a lot of code to wade through for someone who doesn't understand the spoken language used in the comments.
I will says this: Anywhere in that code you see the
Type
keyword you probably want to useStructure
instead, the syntax used for Properties in .Net is a little different, function calls require parentheses, and VB.Net doesn't have an 'Any' type (maybeSystem.IntPtr
instead? not sure).Most of the rest of the syntax in VB.Net is the same, and so you might have better luck making the fixes I've already mentioned and then addressing each error (or type of error) you get when building the resulting code individually.
Sorry I don't have time to convert it for you, but if nobody else comes up with the code, you could do worse than take a look at http://www.pinvoke.net. Your VB6 code has to call Windows API functions to do the work, and VB.NET code has to do the same. It will call the same API functions.
For example, here is the page for DeviceIoControl.
But if you wait long enough, somebody else might just have the code to hand :-)
I found it! Here is the equivalent VB.NET code. It's not exactly the converted version of the VB6 code, but does the same thing. Enjoy!
You can get this data of WMI. Let me get you an example