Автор вопроса: BUG(O)R | Web-сайт:hunger.ru | ICQ: 827887
Приветствую!
Прошу дать пример или ссылку на пример где с помощью SMART получают сриейный номер винта, WMI и прочие методы прошу не предлагать, не подходит.
Смотрел в исходниках HDDInfo, но утонул в тамашних структурах и решил попросить здесь:) Нужно срочно, поэтому искать особо не могу, проект горит.
Знаю, что вроде был пример на vb.kiev.ua, но облазил все разделы, не нашёл блин.
Заранее спасибо.
'GETVERSIONOUTPARAMS contains the data returned
'from the Get Driver Version function
Private Type GETVERSIONOUTPARAMS
bVersion As Byte 'Binary driver version.
bRevision As Byte 'Binary driver revision
bReserved As Byte 'Not used
bIDEDeviceMap As Byte 'Bit map of IDE devices
fCapabilities As Long 'Bit mask of driver capabilities
dwReserved(3) As Long 'For future use
End Type
'IDE registers
Private Type IDEREGS
bFeaturesReg As Byte 'Used for specifying SMART "commands"
bSectorCountReg As Byte 'IDE sector count register
bSectorNumberReg As Byte 'IDE sector number register
bCylLowReg As Byte 'IDE low order cylinder value
bCylHighReg As Byte 'IDE high order cylinder value
bDriveHeadReg As Byte 'IDE drive/head register
bCommandReg As Byte 'Actual IDE command
bReserved As Byte 'reserved for future use - must be zero
End Type
'SENDCMDINPARAMS contains the input parameters for the
'Send Command to Drive function
Private Type SENDCMDINPARAMS
cBufferSize As Long 'Buffer size in bytes
irDriveRegs As IDEREGS 'Structure with drive register values.
bDriveNumber As Byte 'Physical drive number to send command to (0,1,2,3).
bReserved(2) As Byte 'Bytes reserved
dwReserved(3) As Long 'DWORDS reserved
bBuffer() As Byte 'Input buffer.
End Type
'Valid values for the bCommandReg member of IDEREGS.
Private Const IDE_ID_FUNCTION = &HEC 'Returns ID sector for ATA.
Private Const IDE_EXECUTE_SMART_FUNCTION = &HB0 'Performs SMART cmd.
'Requires valid bFeaturesReg,
'bCylLowReg, and bCylHighReg
'Status returned from driver
Private Type DRIVERSTATUS
bDriverError As Byte 'Error code from driver, or 0 if no error
bIDEStatus As Byte 'Contents of IDE Error register
'Only valid when bDriverError is SMART_IDE_ERROR
bReserved(1) As Byte
dwReserved(1) As Long
End Type
Private Type IDSECTOR
wGenConfig As Integer
wNumCyls As Integer
wReserved As Integer
wNumHeads As Integer
wBytesPerTrack As Integer
wBytesPerSector As Integer
wSectorsPerTrack As Integer
wVendorUnique(2) As Integer
sSerialNumber(19) As Byte
wBufferType As Integer
wBufferSize As Integer
wECCSize As Integer
sFirmwareRev(7) As Byte
sModelNumber(39) As Byte
wMoreVendorUnique As Integer
wDoubleWordIO As Integer
wCapabilities As Integer
wReserved1 As Integer
wPIOTiming As Integer
wDMATiming As Integer
wBS As Integer
wNumCurrentCyls As Integer
wNumCurrentHeads As Integer
wNumCurrentSectorsPerTrack As Integer
ulCurrentSectorCapacity As Long
wMultSectorStuff As Integer
ulTotalAddressableSectors As Long
wSingleWordDMA As Integer
wMultiWordDMA As Integer
bReserved(127) As Byte
End Type
'Structure returned by SMART IOCTL commands
Private Type SENDCMDOUTPARAMS
cBufferSize As Long 'Size of Buffer in bytes
 RIVERSTATUS As DRIVERSTATUS 'Driver status structure
bBuffer() As Byte 'Buffer of arbitrary length for data read from drive
End Type
Private Type ATTR_DATA
AttrID As Byte
AttrName As String
AttrValue As Byte
ThresholdValue As Byte
WorstValue As Byte
StatusFlags As STATUS_FLAGS
End Type
Private Type DRIVE_INFO
bDriveType As Byte
SerialNumber As String
Model As String
FirmWare As String
Cilinders As Long
Heads As Long
SecPerTrack As Long
BytesPerSector As Long
BytesperTrack As Long
NumAttributes As Byte
Attributes() As ATTR_DATA
End Type
Private Declare Function CreateFile Lib "kernel32" _
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 CloseHandle Lib "kernel32" _
 ByVal hObject 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 Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" _
 hpvDest As Any, _
hpvSource As Any, _
ByVal cbCopy As Long)
Private Type OSVERSIONINFO
OSVSize As Long
dwVerMajor As Long
dwVerMinor As Long
dwBuildNumber As Long
PlatformID As Long
szCSDVersion As String * 128
End Type
Private Declare Function GetVersionEx Lib "kernel32" _
Alias "GetVersionExA" _
 LpVersionInformation As OSVERSIONINFO) As Long
Private Function GetDriveInfo(drvNumber As IDE_DRIVE_NUMBER) As DRIVE_INFO
 im hDrive As Long
 im di As DRIVE_INFO
hDrive = SmartOpen(drvNumber)
If hDrive <> INVALID_HANDLE_VALUE Then
If SmartGetVersion(hDrive) = True Then
With di
.bDriveType = 0
.NumAttributes = 0
ReDim .Attributes(0)
.bDriveType = 1
End With
If SmartCheckEnabled(hDrive, drvNumber) Then
If IdentifyDrive(hDrive, IDE_ID_FUNCTION, drvNumber, di) = True Then
GetDriveInfo = di
End If 'IdentifyDrive
End If 'SmartCheckEnabled
End If 'SmartGetVersion
End If 'hDrive <> INVALID_HANDLE_VALUE
CloseHandle hDrive
End Function
Private Function IdentifyDrive(ByVal hDrive As Long, _
ByVal IDCmd As Byte, _
ByVal drvNumber As IDE_DRIVE_NUMBER, _
di As DRIVE_INFO) As Boolean
'Function: Send an IDENTIFY command to the drive
'drvNumber = 0-3
'IDCmd = IDE_ID_FUNCTION or IDE_ATAPI_ID
 im SCIP As SENDCMDINPARAMS
 im IDSEC As IDSECTOR
 im bArrOut(OUTPUT_DATA_SIZE - 1) As Byte
 im cbBytesReturned As Long
With SCIP
.cBufferSize = IDENTIFY_BUFFER_SIZE
.bDriveNumber = CByte(drvNumber)
With .irDriveRegs
.bFeaturesReg = 0
.bSectorCountReg = 1
.bSectorNumberReg = 1
.bCylLowReg = 0
.bCylHighReg = 0
.bDriveHeadReg = &HA0 'compute the drive number
If Not IsWinNT4Plus Then
.bDriveHeadReg = .bDriveHeadReg Or ((drvNumber And 1) * 16)
End If
'the command can either be IDE
'identify or ATAPI identify.
.bCommandReg = CByte(IDCmd)
End With
End With
If DeviceIoControl(hDrive, _
 FP_RECEIVE_DRIVE_DATA, _
SCIP, _
Len(SCIP) - 4, _
bArrOut(0), _
OUTPUT_DATA_SIZE, _
cbBytesReturned, _
ByVal 0& Then
'returns True if running Windows NT4 or later
 im osv As OSVERSIONINFO
osv.OSVSize = Len(osv)
If GetVersionEx(osv) = 1 Then
IsWinNT4Plus = (osv.PlatformID = VER_PLATFORM_WIN32_NT) And _
 osv.dwVerMajor >= 4)
End If
End Function
Private Function SmartCheckEnabled(ByVal hDrive As Long, _
drvNumber As IDE_DRIVE_NUMBER) As Boolean
'SmartCheckEnabled - Check if SMART enable
'FUNCTION: Send a SMART_ENABLE_SMART_OPERATIONS command to the drive
'bDriveNum = 0-3
 im SCIP As SENDCMDINPARAMS
 im SCOP As SENDCMDOUTPARAMS
 im cbBytesReturned As Long
.bDriveHeadReg = &HA0
If Not IsWinNT4Plus Then
.bDriveHeadReg = .bDriveHeadReg Or ((drvNumber And 1) * 16)
End If
.bCommandReg = IDE_EXECUTE_SMART_FUNCTION
SmartOpen = CreateFile("\\.\SMARTVSD", _
0&, 0&, _
ByVal 0&, _
CREATE_NEW, _
0&, _
0&
End If
End Function
Private Function SwapBytes(b() As Byte) As Byte()
'Note: VB4-32 and VB5 do not support the
'return of arrays from a function. For
'developers using these VB versions there
'are two workarounds to this restriction:
'
'1) Change the return data type ( As Byte() )
' to As Variant (no brackets). No change
' to the calling code is required.
'
'2) Change the function to a sub, remove
' the last line of code (SwapBytes = b()),
' and take advantage of the fact the
' original byte array is being passed
' to the function ByRef, therefore any
' changes made to the passed data are
' actually being made to the original data.
' With this workaround the calling code
' also requires modification:
'
' di.Model = StrConv(SwapBytes(IDSEC.sModelNumber), vbUnicode)
'
' ... to ...
'
' Call SwapBytes(IDSEC.sModelNumber)
' di.Model = StrConv(IDSEC.sModelNumber, vbUnicode)
 im bTemp As Byte
 im cnt As Long
For cnt = LBound(b) To UBound(b) Step 2
bTemp = b(cnt)
b(cnt) = b(cnt + 1)
b(cnt + 1) = bTemp
Next cnt
SwapBytes = b()
End Function
Public Function Получить_Серийный_Номер_Компьютера()
Dim di As DRIVE_INFO
 im drvNumber As Long
drvNumber = PRIMARY_MASTER
di = GetDriveInfo(drvNumber)
With di
Select Case .bDriveType
Case 1
Получить_Серийный_Номер_Компьютера = Trim$(.Model) & Trim$(.SerialNumber)
End Select
End With
End Function
Public Function isExist(FilePath As String) As Boolean
On Error GoTo errorhandler
Call FileLen(FilePath)
isExist = True
Exit Function
Attribute VB_Name = "GetIdeInfo"
Option Explicit
Option Base 0
'============================================================
Private Declare Sub MemCpy Lib "KERNEL32" Alias "RtlMoveMemory" _
 ByVal hpvDest As Any, ByVal hpvSource As Any, ByVal cbCopy As Long)
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
Private Declare Function CloseHandle Lib "KERNEL32" ( _
ByVal hObject As Long) As Long
Private Declare Function DeviceIoControl Lib "KERNEL32" ( _
ByVal hDevice As Long, _
ByVal dwIoControlCode As Long, _
ByVal lpInBuffer As Long, _
ByVal nInBufferSize As Long, _
ByVal lpOutBuffer As Long, _
ByVal nOutBufferSize As Long, _
ByRef lpBytesReturned As Long, _
ByVal lpOverlapped As Long) As Long
Private Declare Function lstrcpy Lib "KERNEL32" Alias "lstrcpyA" _
 ByVal lpString1 As String, ByVal lpString2 As Long) As Long
Private Declare Function FormatMessage Lib "KERNEL32" _
Alias "FormatMessageA" _
 ByVal dwFlags As Long, ByVal lpSource As Long, _
ByVal dwMessageId As Long, ByVal dwLanguageId As Long, _
lpBuffer As Long, ByVal nSize As Long, _
ByVal Arguments As Long) As Long
Private Declare Function GetLastError Lib "KERNEL32" () As Long
'============================================================
Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100&
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200&
Private Const FORMAT_MESSAGE_FROM_STRING = &H400&
Private Const FORMAT_MESSAGE_FROM_HMODULE = &H800&
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000&
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000&
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF&
'============================================================
Private Type SrbIoControl
HeaderLength As Long
Signature(7) As Byte
Timeout As Long
ControlCode As Long
ReturnCode As Long
Length As Long
End Type 'len=28
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 'len=8
Public Type IDEInfo
serial_number As String
firmware As String
model_number As String
End Type
Private Type SendCmdInParams
cBufferSize As Long
irDriveRegs As IDERegs
bDriveNumber As Byte
bReserved(2) As Byte
dwReserved(3) As Long
bBuffer(0) As Byte
End Type 'len=26+len(Buffer)
Private Buffer() As Byte
Dim buffin() As Byte
Dim buffout() As Byte
Private Function ReverseOrderByte(buffin() As Byte, buffout() As Byte)
Dim i As Integer
Dim bufflen As Integer
bufflen = UBound(buffin) + 1
ReDim buffout(bufflen - 1)
For i = 0 To (bufflen) - 1 Step 2
buffout(i) = buffin(i + 1)
buffout(i + 1) = buffin(i)
Next
End Function
Private Function GetInfo(offset As Integer, leninfo As Integer) As String
Dim str As String
ReDim buffin(leninfo - 1)
MemCpy VarPtr(buffin(0)), VarPtr(Buffer(offset)), UBound(buffin) + 1
ReverseOrderByte buffin, buffout
str = String(UBound(buffin) + 1, " "
MemCpy str, VarPtr(buffout(0)), UBound(buffin) + 1
str = LTrim(str)
str = RTrim(str)
GetInfo = str
End Function
Private Sub PrintErrorMessage(ErrCode As Long, Optional MyStr As String)
Dim StrErr As String
Dim MyFlags As Long
Dim MyPtr As Long
Dim MyBuff() As Byte
Dim i As Long
StrErr = String(255, " "
MyFlags = FORMAT_MESSAGE_FROM_SYSTEM Or _
FORMAT_MESSAGE_IGNORE_INSERTS Or _
FORMAT_MESSAGE_ALLOCATE_BUFFER
i = FormatMessage(MyFlags, vbNull, ErrCode, 0, MyPtr, 0, vbNull)
If i = 0 Then
StrErr = "Unknow Error!"
Else
ReDim Preserve MyBuff(1 To i)
lstrcpy StrErr, MyPtr
StrErr = Left(StrErr, i - 2)
End If
MsgBox StrErr & " Error Code #" & ErrCode & " " & MyStr, vbCritical
End Sub
Public Function GetInfoIDE() As IDEInfo
Dim Scsi As String 'scsi channel nunber
Dim DriveNumber As Integer 'scsi drive number
Dim DataSize As Integer
Dim BufferSize As Integer
Dim srbControl As SrbIoControl
Dim SendCmdInParams As SendCmdInParams
Dim hDevice As Long
Dim cbBytesReturned As Long
Dim retval As Long
Dim str As String
Scsi = "0"
hDevice = CreateFile("\\.\Scsi" & Scsi & ":", _
&H40000000 Or &H80000000, &H1 Or &H2, 0, 3, 0, 0)
If hDevice = -1 Then PrintErrorMessage Err.LastDllError, "Point#1": End
 riveNumber = 0
 ataSize = Len(SendCmdInParams) - 1 + 512
BufferSize = Len(srbControl) + DataSize
ReDim Buffer(BufferSize - 1)
srbControl.HeaderLength = Len(srbControl)
MemCpy VarPtr(srbControl.Signature(0)), "SCSIDISK", 8
srbControl.Timeout = 2
srbControl.ControlCode = &H1B0501
srbControl.Length = DataSize
With SendCmdInParams
.cBufferSize = 512
.bDriveNumber = DriveNumber
With .irDriveRegs
.bFeaturesReg = 0
.bSectorCountReg = 1
.bSectorNumberReg = 1
.bCylLowReg = 0
.bCylHighReg = 0
.bDriveHeadReg = &HA0 Or ((DriveNumber And 1) * 8 ^ 4)
.bCommandReg = &HEC
End With
End With
MemCpy VarPtr(Buffer(0)), VarPtr(srbControl.HeaderLength), Len(srbControl)
MemCpy VarPtr(Buffer(Len(srbControl))), VarPtr(SendCmdInParams.cBufferSize), _
Len(SendCmdInParams)
retval = DeviceIoControl(hDevice, &H4D008, VarPtr(Buffer(0)), BufferSize, _
VarPtr(Buffer(0)), BufferSize, cbBytesReturned, 0)
If retval = 0 Then PrintErrorMessage Err.LastDllError, "Point#2": End
CloseHandle (hDevice)
str = GetInfo(64, 20)
GetInfoIDE.serial_number = str
str = GetInfo(90, 8)
GetInfoIDE.firmware = str
str = GetInfo(98, 40)
GetInfoIDE.model_number = str
End Function