原创 编程获取硬盘序列号

2008-4-7 13:19 6872 6 9 分类: 软件与OS
昨天查了查网上的文章,发现有人已经提出通过向磁盘驱动程序发送Ioctl请求来获取硬盘序列号的。参考别人的
代码,把那个获取硬盘序列号的程序写出来了,测试通过。
下面的API函数用于获取硬盘序列号:
SYSINFO_API BOOL GetHardDiskSerialNumber(char *buffer,int DiskNum)
{
DWORD dwDataBuf[256];
WORD wDataBuf[256];
char SerialNum[256];
int i,j;

if(!GetIdeDiskInformation(dwDataBuf,DiskNum)){
if(!GetScsiDiskInformation(dwDataBuf,DiskNum)){
SysInfoDebug("GetHardDiskSerialNumber--failed");
return FALSE;
}
}

for(i=0;i<256;i++)
wDataBuf=(WORD)dwDataBuf;
/* convert WORD data to char array(string)*/
i=ConvertToString(wDataBuf,27,46,SerialNum,0);
SerialNum='-';
j=ConvertToString(wDataBuf,10,19,SerialNum,i+1);
SerialNum[j]='-';
ConvertToString(wDataBuf,23,26,SerialNum,j+1);
strcpy(buffer,SerialNum);
return TRUE;
}

首先调用GetIdeDiskInformation来获取IDE硬盘的信息,如果系统没有IDE硬盘,那么再用GetScsiDiskInformation试图获取
Scsi硬盘的信息,两者都找不到就返回FALSE。找到信息后,调用ConvertToString把序列号相关的信息转换为string
存在buffer参数指定的内存中,返回给调用者。
GetIdeDiskInformation的代码如下:
/*get IDE disk infromation
Arguments:
* buffer--return the IDE disk first sector information
* DiskNum--IDE disk number, must between 0 and MAX_IDE_DISK
*return:
* FALSE---can't get infromation
* TRUE---successfully, the buffer contains all information we need
*/
BOOL GetIdeDiskInformation(DWORD *buffer, int DiskNum)
{
char szIdeDeviceName[32];
HANDLE hIdeDriver;
DWORD dwByteRet;
GETVERSIONOUTPARAMS  VersionParam;
SENDCMDINPARAMS  InParam;
BYTE bIdCmd;
BYTE OutBuf[sizeof(SENDCMDOUTPARAMS)+IDENTIFY_BUFFER_SIZE-1];
int i;
USHORT *pIdSector;

if((DiskNum>MAX_IDE_DISK-1)||(DiskNum<0)){
SysInfoDebug(" GetIdeDiskInformation--Invalid Disk Number");
return FALSE;
}
sprintf(szIdeDeviceName,"\\\\.\\PhysicalDrive%d",DiskNum);
hIdeDriver=CreateFile(szIdeDeviceName,GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hIdeDriver!=INVALID_HANDLE_VALUE){
SysInfoDebug("GetIdeDiskInformation--Open Disk success");
memset((void*)&VersionParam,0,sizeof(VersionParam));
if(DeviceIoControl(hIdeDriver,SMART_GET_VERSION,NULL,0,&VersionParam,
 sizeof(VersionParam),&dwByteRet,NULL)){
if(VersionParam.bIDEDeviceMap > 0){
bIdCmd=(VersionParam.bIDEDeviceMap>>DiskNum&0x10)?IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
memset((void*)&InParam,0,sizeof(InParam));
memset((void*)OutBuf,0,sizeof(OutBuf));
if(DoIdentify(hIdeDriver,&InParam,(PSENDCMDOUTPARAMS)&OutBuf,bIdCmd,(BYTE)DiskNum,&dwByteRet)){
pIdSector=(USHORT *)((PSENDCMDOUTPARAMS)OutBuf)->bBuffer;
for(i=0;i<256;i++)
buffer=pIdSector;
SysInfoDebug("GetIdeDiskInformation--get disk information success");
return TRUE;
}
}
}
}
SysInfoDebug("GetIdeDiskInformation--cannot get disk information");
return FALSE;
}

其中调用了DoIdentify这个辅助函数,代码如下:
BOOL DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
              PDWORD pdwBytesReturned)
{
    // Set up data structures for IDENTIFY command.
    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;

    // Compute the drive number.
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;

    // The command can either be IDE identify or ATAPI identify.
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    pSCIP->bDriveNumber = btDriveNum;
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

    return (DeviceIoControl(hPhysicalDriveIOCTL, SMART_RCV_DRIVE_DATA,
           (LPVOID)pSCIP,
           sizeof(SENDCMDINPARAMS) - 1,
           (LPVOID)pSCOP,
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
           pdwBytesReturned, NULL));
}

而GetScsiDiskInformation的代码如下:
/* get scsi disk information ,if any
* we query scsi miniport driver to get these information
* Arguments:
* buffer--return the scsi disk first sector information
* DiskNum--scsi disk number, must between 0 and MAX_SCSI_DISK
*return:
* FALSE---can't get infromation
* TRUE---successfully, the buffer contains all information we need
*/

BOOL GetScsiDiskInformation(DWORD *buffer,int DiskNum)
{
HANDLE hScsiDriver;
int j;
DWORD dwByteRet;
char szScsiDeviceName[32];
char tmpbuf[sizeof(SRB_IO_CONTROL)+SENDIDLENGTH];
SRB_IO_CONTROL *pSrb=(SRB_IO_CONTROL *)tmpbuf;
SENDCMDINPARAMS  *pin=(SENDCMDINPARAMS *)(tmpbuf+sizeof(SRB_IO_CONTROL));
SENDCMDOUTPARAMS *pout;
IDSECTOR *pid;
USHORT * pIdSector;

if((DiskNum>MAX_SCSI_DISK-1)||(DiskNum<0)){
SysInfoDebug("GetScsiDiskInformation--Invalid disk number");
return FALSE;
}
sprintf(szScsiDeviceName,"\\\\.\\SCSI%d:",DiskNum);
hScsiDriver=CreateFile(szScsiDeviceName,GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hScsiDriver!=INVALID_HANDLE_VALUE){
SysInfoDebug("GetScsiDiskInformation--Open disk success");
memset(tmpbuf,0,sizeof(tmpbuf));
pSrb->HeaderLength=sizeof(SRB_IO_CONTROL);
pSrb->Timeout=10000;
pSrb->Length=SENDIDLENGTH;
pSrb->ControlCode=IOCTL_SCSI_MINIPORT_IDENTIFY;
strncpy((char*)pSrb->Signature,"SCSIDISK",8);
pin->bDriveNumber=DiskNum;
pin->irDriveRegs.bCommandReg=IDE_ATA_IDENTIFY;
if(DeviceIoControl(hScsiDriver,IOCTL_SCSI_MINIPORT,tmpbuf,sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS)-1,
tmpbuf,sizeof(tmpbuf),&dwByteRet,NULL)){
pout=(SENDCMDOUTPARAMS *)(tmpbuf+sizeof(SRB_IO_CONTROL));
pid=(IDSECTOR *)(pout->bBuffer);
if(pid->sModelNumber[0]){
pIdSector=(USHORT *)pid;
for(j=0;j<256;j++)
buffer[j]=(char)pIdSector[j];
CloseHandle(hScsiDriver);
return TRUE;
}
}
CloseHandle(hScsiDriver);
}
SysInfoDebug("GetScsiDiskInformation--Can not Get Disk Information");
return FALSE;
}

文章评论3条评论)

登录后参与讨论

用户1361860 2009-3-9 13:42

我这里贴出的代码并不是完整的代码,SYSINFO_API是定义的一个dll导出宏。那些在头文件中定义的

用户180278 2009-3-3 21:38

运行后出现下面三个错误,怎么解决,谢谢error C2146: syntax error : missing ';' before identifier 'BOOL' : error C2501: 'SYSINFO_API' : missing storage-class or type specifiers fatal error C1004: unexpected end of file found Error executing cl.exe. StdAfx.obj - 3 error(s), 0 warning(s)

用户180278 2009-3-3 21:34

PSendCmdInParams是什么标志符,为什么程序运行出错呢?
相关推荐阅读
用户1361860 2012-06-28 23:44
Nicrosystem Freescale Kinetis教程---SDHC
这是研究生翻译的SDHC的中文文档,里面很多句子不通,但我现在没时间去修改了。先放出来,应该还是会有一点作用  ...
用户1361860 2012-06-26 12:39
Nicrosystem Freescale Kinetis教程--低功耗定时器
Freescale Kinetis内部集成了一个独特的低功耗定时器,它可以在系统处于低功耗模式下,仍然以极低功耗运行,可以用于在适当时候唤醒系统进入正常工作模式  ...
用户1361860 2012-06-24 22:11
Nicrosystem Freescale Kinetis教程----RTC实时时钟
Nicrosystem的飞思卡尔kinetis教程之片上RTC  ...
用户1361860 2012-06-22 10:21
TI C2000微控制器指南
这是官方的C2000的介绍,C2000做电机控制那是业界最好的。  ...
用户1361860 2012-06-20 23:52
Nicrosystem Freescale Kinetis教程--PIT定时器教程
这是PIT定时器的教程,PIT是 Kinetis支持的另一种定时器,相对于上一讲的flextimer要简单。 今晚赶到北京,到宾馆发一篇博客  ...
用户1361860 2012-06-19 13:15
Nicrosystem Freescale Kinetis教程--Flextimer教程
Kinetis的Flextimer定时器教程 kinetis集成了众多功能各异的定时器,flextimer是其中最为复杂的一个  ...
我要评论
3
6
关闭 站长推荐上一条 /2 下一条