不用驱动直接获取硬盘信息(硬盘型号,硬盘序列号,硬盘缓存大小,硬盘容量) By MengXP(于2007-11-20发表)

下载SRC&EXE

;by MengXP
;2007.11.11
;2007.11.19 修正: 使用IOCTL_DISK_GET_DRIVE_GEOMETRY获取硬盘容量


.386
.Model Flat,StdCall
Option CaseMap :None

Include Windows.inc
Include User32.inc
Include Kernel32.inc
Include winioctl.inc

IncludeLib User32.lib
IncludeLib Kernel32.lib

IDEREGS    struct
    bFeaturesReg    db ?    ;// 特征寄存器(用于SMART命令)
    bSectorCountReg    db ?    ;// 扇区数目寄存器
    bSectorNumberReg    db ?    ;// 开始扇区寄存器
    bCylLowReg        db ?    ;// 开始柱面低字节寄存器
    bCylHighReg        db ?    ;// 开始柱面高字节寄存器
    bDriveHeadReg    db ?    ;// 驱动器/磁头寄存器
    bCommandReg        db ?    ;// 指令寄存器
    bReserved        db ?    ;// 保留
IDEREGS    ends

SENDCMDINPARAMS    struct
    cBufferSize        dd ?        ;// 缓冲区字节数
    irDriveRegs        IDEREGS <>    ;// IDE寄存器组
    bDriveNumber    db ?        ;// 驱动器号
    bReserved        db 3 dup(?)    ;// 保留
    dwReserved        dd 4 dup(?)    ;// 保留
    bBuffer        db ?        ;// 输入缓冲区(此处象征性地包含1字节)
SENDCMDINPARAMS    ends

.Data
szInfo        db 1024 dup(?)
szInfoFmt    db "硬盘型号: %s",13,10
        db "硬盘大小: %d GB",13,10
        db "硬盘缓存: %d KB",13,10
        db "硬盘序号: %s",0
hDevice        dd ?
stIn        SENDCMDINPARAMS <>
stOut        dd 256 dup(?)        ;输出缓冲区就不定义结构了
dwReturnBytes    dd ?
stDG        DISK_GEOMETRY <>


dwDriveSize    dd ?
dwCacheSize    dd ?
szDriveName    db 48 dup(?)
szSerialNum    db 24 dup(?)

.Code
Start:
    mov    stIn.irDriveRegs.bCommandReg,0ECh    ;IDE_ATA_IDENTIFY
    mov    stIn.cBufferSize,0
    mov    stOut,512    ;返回缓冲区大小
    
    invoke    CreateFile,CTEXT("\\.\PhysicalDrive0"),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL
    mov    hDevice,eax
    invoke    DeviceIoControl,hDevice,0007C088h,addr stIn,sizeof SENDCMDINPARAMS - 1,addr stOut,256*4,addr dwReturnBytes,0
    
    lea    esi,stOut
    add    esi,16        ;跳过头部直接到达512字节数据
    
    movzx    eax,word ptr [esi+42]    ;取缓存大小 KB
    xor    edx,edx
    mov    ecx,2
    div    ecx
    mov    dwCacheSize,eax
    
    xor    ecx,ecx
    .While    ecx < 40    ;按字整理硬盘型号数据
        mov    ax,word ptr [esi+54+ecx]
        xchg    ah,al
        mov    word ptr [esi+54+ecx],ax
        add    ecx,2
    .EndW
    invoke    RtlMoveMemory,addr szDriveName,addr [esi+54],40
    
    xor    ecx,ecx
    .While    ecx < 20    ;按字整理硬盘序列号数据
        mov    ax,word ptr [esi+20+ecx]
        xchg    ah,al
        mov    word ptr [esi+20+ecx],ax
        add    ecx,2
    .EndW
    invoke    RtlMoveMemory,addr szSerialNum,addr [esi+20],20
    
    invoke    DeviceIoControl,hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,0,0,addr stDG,sizeof DISK_GEOMETRY,addr dwReturnBytes,0
    invoke    CloseHandle,hDevice
    
    lea    esi,stDG
    mov    eax,[esi]
    mov    edx,[esi+4]
    mov    ecx,stDG.TracksPerCylinder
    mul    ecx
    mov    ecx,stDG.SectorsPerTrack
    mul    ecx
    mov    ecx,stDG.BytesPerSector
    mul    ecx
    mov    ecx,1000*1000*1000
    div    ecx
    mov    dwDriveSize,eax
    
    invoke    wsprintf,addr szInfo,addr szInfoFmt,addr szDriveName,dwDriveSize,dwCacheSize,addr szSerialNum
    invoke    MessageBox,0,addr szInfo,0,0
    invoke    ExitProcess,0
End    Start

并不是所有的贴子都是原创,此时作者均指发表的人而不是文章的作者,作者会说明是否是转贴