[转载]纯VB代码取得硬盘的物理序列号

本文原来地址: http://blog.csdn.net/fxy_2002/services/trackbacks/436183.aspx

本来想收藏的,但是不知道怎么做,所以直接copy下来了

    网上有很多获取硬盘序列号的代码,但大部分都只能取得逻辑分区的序列号,而不能取得硬盘的物理序列号。我们知道,逻辑分区的序列号是FORMAT时产生的,重新FORMAT将会改变。这对于要求唯一识别码的程式来说是致命的。这段代码利用API可以取得物理硬盘的很多特性,包括硬盘出厂时的唯一编号。这段代码我是从CSDN论坛获得,原作者不详。我将其稍做修改和增添,独立出两个常用的函数:GetDiskVolume 、GetHardDiskInfo  ......

'============================================
'模块功能:取得硬盘的信息
'编    程:来自互联网,阿勇修改
'更新日期:2005/7/8
'调用方法:
'   GetDiskVolume() 取得逻辑盘的序列号
'   GetHardDiskInfo() 取得物理盘的型号或序列号
'============================================

Private Const MAX_IDE_DRIVES As Long = 4   ' Max number of drives assuming primary/secondary, master/slave topology
Private Const READ_ATTRIBUTE_BUFFER_SIZE As Long = 512
Private Const IDENTIFY_BUFFER_SIZE As Long = 512
Private Const READ_THRESHOLD_BUFFER_SIZE As Long = 512
Private Const DFP_GET_VERSION As Long = &H74080
Private Const DFP_SEND_DRIVE_COMMAND As Long = &H7C084
Private Const DFP_RECEIVE_DRIVE_DATA As Long = &H7C088

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

Private Const CAP_IDE_ID_FUNCTION As Long = 1               ' ATA ID command supported
Private Const CAP_IDE_ATAPI_ID As Long = 2                  ' ATAPI ID command supported
Private Const CAP_IDE_EXECUTE_SMART_FUNCTION As Long = 4    ' SMART commannds supported

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

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       ' Reserved for future expansion.
    dwReserved(3) As Long      ' For future use.
    bBuffer(0) As Byte         ' Input buffer.
End Type

Private Const IDE_ATAPI_ID As Long = &HA1  ' Returns ID sector for ATAPI.
Private Const IDE_ID_FUNCTION As Long = &HEC  ' Returns ID sector for ATA.
Private Const IDE_EXECUTE_SMART_FUNCTION As Long = &HB0  ' Performs SMART cmd.
Private Const SMART_CYL_LOW As Long = &H4F
Private Const SMART_CYL_HI As Long = &HC2

Private Type DRIVERSTATUS
    bDriverError As Byte       ' Error code from driver,
    bIDEStatus As Byte         ' Contents of IDE Error register.
    bReserved(1) As Byte       ' Reserved for future expansion.
    dwReserved(1) As Long      ' Reserved for future expansion.
End Type

Private Const SMART_NO_ERROR As Long = 0  ' No error
Private Const SMART_IDE_ERROR As Long = 1  ' Error from IDE controller
Private Const SMART_INVALID_FLAG As Long = 2  ' Invalid command flag
Private Const SMART_INVALID_COMMAND As Long = 3  ' Invalid command byte
Private Const SMART_INVALID_BUFFER As Long = 4  ' Bad buffer (null, invalid addr..)
Private Const SMART_INVALID_DRIVE As Long = 5  ' Drive number not valid
Private Const SMART_INVALID_IOCTL As Long = 6   ' Invalid IOCTL
Private Const SMART_ERROR_NO_MEM As Long = 7  ' Could not lock user's buffer
Private Const SMART_INVALID_REGISTER As Long = 8  ' Some IDE Register not valid
Private Const SMART_NOT_SUPPORTED As Long = 9  ' Invalid cmd flag set
Private Const SMART_NO_IDE_DEVICE As Long = 10 ' Cmd issued to device not present

Private Type SENDCMDOUTPARAMS
    cBufferSize As Long        ' Size of bBuffer in bytes
    drvStatus As DRIVERSTATUS  ' Driver status structure.
    bBuffer(0) As Byte         ' Buffer of arbitrary length in which to store the data read from the                                          ' drive.
End Type

Private Const SMART_READ_ATTRIBUTE_VALUES As Long = &HD0    ' ATA4: Renamed
Private Const SMART_READ_ATTRIBUTE_THRESHOLDS As Long = &HD1    ' Obsoleted in ATA4!
Private Const SMART_ENABLE_DISABLE_ATTRIBUTE_AUTOSAVE As Long = &HD2
Private Const SMART_SAVE_ATTRIBUTE_VALUES As Long = &HD3
Private Const SMART_EXECUTE_OFFLINE_IMMEDIATE As Long = &HD4    ' ATA4
Private Const SMART_ENABLE_SMART_OPERATIONS As Long = &HD8
Private Const SMART_DISABLE_SMART_OPERATIONS As Long = &HD9
Private Const SMART_RETURN_SMART_STATUS As Long = &HDA

Private Type DRIVEATTRIBUTE
    bAttrID As Byte        ' Identifies which attribute
    wStatusFlags As Integer    ' see bit definitions below
    bAttrValue As Byte     ' Current normalized value
    bWorstValue As Byte    ' How bad has it ever been?
    bRawValue(5) As Byte   ' Un-normalized value
    bReserved As Byte      ' ...
End Type

Private Type ATTRTHRESHOLD
    bAttrID As Byte            ' Identifies which attribute
    bWarrantyThreshold As Byte ' Triggering value
    bReserved(9) As Byte      ' ...
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(3) As Byte    '这里只能用byte,因为VB没有无符号的LONG型变量
    wMultSectorStuff As Integer
    ulTotalAddressableSectors(3) As Byte   '这里只能用byte,因为VB没有无符号的LONG型变量
    wSingleWordDMA As Integer
    wMultiWordDMA As Integer
    bReserved(127) As Byte
End Type

Private Const ATTR_INVALID As Long = 0
Private Const ATTR_READ_ERROR_RATE As Long = 1
Private Const ATTR_THROUGHPUT_PERF As Long = 2
Private Const ATTR_SPIN_UP_TIME As Long = 3
Private Const ATTR_START_STOP_COUNT As Long = 4
Private Const ATTR_REALLOC_SECTOR_COUNT As Long = 5
Private Const ATTR_READ_CHANNEL_MARGIN As Long = 6
Private Const ATTR_SEEK_ERROR_RATE As Long = 7
Private Const ATTR_SEEK_TIME_PERF As Long = 8
Private Const ATTR_POWER_ON_HRS_COUNT As Long = 9
Private Const ATTR_SPIN_RETRY_COUNT As Long = 10
Private Const ATTR_CALIBRATION_RETRY_COUNT As Long = 11
Private Const ATTR_POWER_CYCLE_COUNT As Long = 12

Private Const PRE_FAILURE_WARRANTY As Long = &H1
Private Const ON_LINE_COLLECTION As Long = &H2
Private Const PERFORMANCE_ATTRIBUTE As Long = &H4
Private Const ERROR_RATE_ATTRIBUTE As Long = &H8
Private Const EVENT_COUNT_ATTRIBUTE As Long = &H10
Private Const SELF_PRESERVING_ATTRIBUTE As Long = &H20

Private Const NUM_ATTRIBUTE_STRUCTS As Long = 30
Private Const INVALID_HANDLE_VALUE As Long = -1

Private Const VER_PLATFORM_WIN32s As Long = 0
Private Const VER_PLATFORM_WIN32_WINDOWS As Long = 1
Private Const VER_PLATFORM_WIN32_NT As Long = 2

Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128      '  Maintenance string for PSS usage
End Type

Private Const CREATE_NEW As Long = 1
Private Const GENERIC_READ As Long = &H80000000
Private Const GENERIC_WRITE As Long = &H40000000
Private Const FILE_SHARE_READ As Long = &H1
Private Const FILE_SHARE_WRITE As Long = &H2
Private Const OPEN_EXISTING  As Long = 3

Private m_DiskInfo As IDSECTOR

Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) 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 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
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As Long

'信息类型枚举
Enum eumInfoType
    hdmodelsn = 0
    hdOnlyModel = 1
    hdOnlySN = 2
End Enum

'磁盘通道枚举
Enum eumDiskNo
    hdPrimaryMaster = 0
    hdPrimarySlave = 1
    hdSecondaryMaster = 2
    hdSecondarySlave = 3
End Enum

'取得逻辑盘序列号(非唯一)
Function GetDiskVolume(Optional ByVal strDiskName = "C") As String
    Dim TempStr1 As String * 256, TempStr2 As String * 256
    Dim TempLon1 As Long, TempLon2 As Long, GetVal As Long
   
    Dim tmpVol As String
   
    Call GetVolumeInformation(strDiskName & ":/", TempStr1, 256, GetVal, TempLon1, TempLon2, TempStr2, 256)
    If GetVal = 0 Then
        tmpVol = ""
    Else
        tmpVol = Hex(GetVal)
        tmpVol = String(8 - Len(tmpVol), "0") & tmpVol
        tmpVol = Left(tmpVol, 4) & "-" & Right(tmpVol, 4)
    End If
    GetDiskVolume = tmpVol
End Function

'取得硬盘信息:型号/物理系列号(唯一)
Function GetHardDiskInfo(Optional ByVal numDisk As eumDiskNo = hdPrimaryMaster, Optional ByVal numType As eumInfoType = hdOnlySN) As String

    If GetDiskInfo(numDisk) = 1 Then
        Dim pSerialNumber As String, pModelNumber As String
        pSerialNumber = StrConv(m_DiskInfo.sSerialNumber, vbUnicode)
        pModelNumber = StrConv(m_DiskInfo.sModelNumber, vbUnicode)
       
        Select Case numType
            Case hdOnlyModel  '仅型号
                GetHardDiskInfo = Trim(pModelNumber)
            Case hdOnlySN  '仅系列号
                GetHardDiskInfo = Trim(pSerialNumber)
            Case Else   '型号,系列号
                GetHardDiskInfo = Trim(pModelNumber) & "," & Trim(pSerialNumber)
        End Select
     End If

End Function

Private Function OpenSMART(ByVal nDrive As Byte) As Long
  Dim hSMARTIOCTL As Long
  Dim hd As String
  Dim VersionInfo As OSVERSIONINFO

    hSMARTIOCTL = INVALID_HANDLE_VALUE
    VersionInfo.dwOSVersionInfoSize = Len(VersionInfo)
    GetVersionEx VersionInfo
    Select Case VersionInfo.dwPlatformId
      Case VER_PLATFORM_WIN32s
        OpenSMART = hSMARTIOCTL
      Case VER_PLATFORM_WIN32_WINDOWS
        hSMARTIOCTL = CreateFile("//./SMARTVSD", 0, 0, 0, CREATE_NEW, 0, 0)
      Case VER_PLATFORM_WIN32_NT
        If nDrive < MAX_IDE_DRIVES Then
            hd = "//./PhysicalDrive" & nDrive
            hSMARTIOCTL = CreateFile(hd, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
        End If
    End Select
    OpenSMART = hSMARTIOCTL

End Function

Private Function DoIDENTIFY(ByVal hSMARTIOCTL As Long, pSCIP As SENDCMDINPARAMS, pSCOP() As Byte, ByVal bIDCmd As Byte, ByVal bDriveNum As Byte, lpcbBytesReturned As Long) As Boolean
    pSCIP.cBufferSize = IDENTIFY_BUFFER_SIZE

    pSCIP.irDriveRegs.bFeaturesReg = 0
    pSCIP.irDriveRegs.bSectorCountReg = 1
    pSCIP.irDriveRegs.bSectorNumberReg = 1
    pSCIP.irDriveRegs.bCylLowReg = 0
    pSCIP.irDriveRegs.bCylHighReg = 0

    pSCIP.irDriveRegs.bDriveHeadReg = &HA0 Or ((bDriveNum And 1) * 2 ^ 4)
    '
    pSCIP.irDriveRegs.bCommandReg = bIDCmd
    pSCIP.bDriveNumber = bDriveNum
    pSCIP.cBufferSize = IDENTIFY_BUFFER_SIZE
   DoIDENTIFY = CBool(DeviceIoControl(hSMARTIOCTL, DFP_RECEIVE_DRIVE_DATA, _
                 pSCIP, 32, _
                 pSCOP(0), 528, _
                 lpcbBytesReturned, 0))

End Function

Private Function DoEnableSMART(ByVal hSMARTIOCTL As Long, pSCIP As SENDCMDINPARAMS, pSCOP As SENDCMDOUTPARAMS, ByVal bDriveNum As Byte, lpcbBytesReturned As Long) As Boolean
    pSCIP.cBufferSize = 0

    pSCIP.irDriveRegs.bFeaturesReg = SMART_ENABLE_SMART_OPERATIONS
    pSCIP.irDriveRegs.bSectorCountReg = 1
    pSCIP.irDriveRegs.bSectorNumberReg = 1
    pSCIP.irDriveRegs.bCylLowReg = SMART_CYL_LOW
    pSCIP.irDriveRegs.bCylHighReg = SMART_CYL_HI
    pSCIP.irDriveRegs.bDriveHeadReg = &HA0 Or ((bDriveNum And 1) * 2 ^ 4)
    pSCIP.irDriveRegs.bCommandReg = IDE_EXECUTE_SMART_FUNCTION
    pSCIP.bDriveNumber = bDriveNum

    DoEnableSMART = CBool(DeviceIoControl(hSMARTIOCTL, DFP_SEND_DRIVE_COMMAND, _
                    pSCIP, LenB(pSCIP) - 1, _
                    pSCOP, LenB(pSCOP) - 1, _
                    lpcbBytesReturned, 0))

End Function

'---------------------------------------------------------------------
'---------------------------------------------------------------------
Private Sub ChangeByteOrder(szString() As Byte, ByVal uscStrSize As Integer)

  Dim i As Integer
  Dim bTemp As Byte

    For i = 0 To uscStrSize - 1 Step 2
        bTemp = szString(i)
        szString(i) = szString(i + 1)
        szString(i + 1) = bTemp
    Next i

End Sub

Private Sub DisplayIdInfo(pids As IDSECTOR, pSCIP As SENDCMDINPARAMS, ByVal bIDCmd As Byte, ByVal bDfpDriveMap As Byte, ByVal bDriveNum As Byte)

    ChangeByteOrder pids.sModelNumber, UBound(pids.sModelNumber) + 1

    ChangeByteOrder pids.sFirmwareRev, UBound(pids.sFirmwareRev) + 1

    ChangeByteOrder pids.sSerialNumber, UBound(pids.sSerialNumber) + 1

End Sub

Public Function GetDiskInfo(ByVal nDrive As Byte) As Long

  Dim hSMARTIOCTL As Long
  Dim cbBytesReturned As Long
  Dim VersionParams As GETVERSIONOUTPARAMS
  Dim scip As SENDCMDINPARAMS
  Dim scop() As Byte
  Dim OutCmd As SENDCMDOUTPARAMS
  Dim bDfpDriveMap As Byte
  Dim bIDCmd As Byte                    ' IDE or ATAPI IDENTIFY cmd
  Dim uDisk As IDSECTOR

    m_DiskInfo = uDisk
    '
    '
    hSMARTIOCTL = OpenSMART(nDrive)
    If hSMARTIOCTL <> INVALID_HANDLE_VALUE Then

        Call DeviceIoControl(hSMARTIOCTL, DFP_GET_VERSION, ByVal 0, 0, VersionParams, Len(VersionParams), cbBytesReturned, 0)

        If Not (VersionParams.bIDEDeviceMap / 2 ^ nDrive And &H10) Then
            If DoEnableSMART(hSMARTIOCTL, scip, OutCmd, nDrive, cbBytesReturned) Then
                bDfpDriveMap = bDfpDriveMap Or 2 ^ nDrive
            End If
        End If
        bIDCmd = IIf((VersionParams.bIDEDeviceMap / 2 ^ nDrive And &H10), IDE_ATAPI_ID, IDE_ID_FUNCTION)

        ReDim scop(LenB(OutCmd) + IDENTIFY_BUFFER_SIZE - 1) As Byte
        If DoIDENTIFY(hSMARTIOCTL, scip, scop, bIDCmd, nDrive, cbBytesReturned) Then
            CopyMemory m_DiskInfo, scop(LenB(OutCmd) - 4), LenB(m_DiskInfo)
            Call DisplayIdInfo(m_DiskInfo, scip, bIDCmd, bDfpDriveMap, nDrive)
            CloseHandle hSMARTIOCTL
            GetDiskInfo = 1
            Exit Function '>---> Bottom
        End If
        CloseHandle hSMARTIOCTL
        GetDiskInfo = 0
      Else 'NOT HSMARTIOCTL...
        GetDiskInfo = -1
    End If

End Function




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值