#include <stdio.h>char *GetAscii(unsigned int inData[], int offStart, int offEnd); int main(void) { unsigned int diskData[256]; /* Disk data */ unsigned int offset; /* Disk data offset */ int loop; int numDrv; /* Number of IDE hard drives */ union REGS registers; unsigned int biosCyl[2]; /* Cylinders, Heads, Sectors */ unsigned int biosHead[2]; unsigned int biosSec [2]; numDrv = peekb(0x40, 0x75); /* BIOS Data area, Number of Hard disks */ for (loop = 0; loop < numDrv; loop++) { while (inp(0x01f7) != 0x50); /* Wait for controller not busy */ outp(0x01f6, (loop == 0 ? 0xa0 : 0xb0)); /* Get first/second drive */ outp(0x01f7, 0xec); /* Get drive info data */ while (inp(0x1f7) != 0x58); /* Wait for data ready */ for (offset = 0; offset != 256; offset++) /* Read "sector" */ diskData[offset] = inpw(0x1f0); /* Get BIOS drive info */ registers.h.ah = 0x08; /* Get drive info */ registers.h.dl = 0x80 + loop; /* Drive is 80H for Disk 0, 81H for Disk 1 */ int86(0x13, ?isters, ?isters); if (!registers.x.cflag) /* All OK if carry not set */ { biosHead[loop] = registers.h.dh + 1; /* Heads are from 0 */ biosSec[loop] = registers.h.cl & 0x3f; /* sec is bits 5 - 0 */ /* +1 because starts from 0 and +1 for FDISK leaving one out */ biosCyl[loop] = ((registers.h.cl & 0xc0) << 2) + registers.h.ch + 2; } /* end of if */ printf("DRIVE %d:\n", loop); printf("Model Number______________________: %s\n", GetAscii(diskData, 27, 46)); printf("Serial Number_____________________: %s\n", GetAscii(diskData, 10, 19)); printf("Controller Revision Number________: %s\n\n", GetAscii(diskData, 23, 26)); printf("Able to do Double Word Transfer___: %6s\n", (diskData[48] == 0 ? "No" : "Yes")); printf("Controller type___________________: %04X\n", diskData[20]); printf("Controller buffer size (bytes)____: %6u\n", diskData[21] * 512); printf("Number of ECC bytes transferred___: %6u\n", diskData[22]); printf("Number of sectors per interrupt___: %6u\n\n", diskData[47]); printf("Hard Disk Reports\n"); printf("Number of Cylinders (Fixed)_______: %6u\n", diskData[1]); printf("Number of Heads___________________: %6u\n", diskData[3]); printf("Number of Sectors per Track_______: %6u\n\n", diskData[6]); printf("BIOS Reports\n"); printf("Number of Cylinders_______________: %6u\n", biosCyl[loop]); printf("Number of Heads___________________: %6u\n", biosHead[loop]); printf("Number of Sectors per Track_______: %6u\n\n", biosSec[loop]); printf("Press any key to continue...\n\n"); getch(); } /* end of for */ return 0; } /* main() */ char *GetAscii(unsigned int inData[], int offStart, int offEnd) { static char retVal[255]; int loop, loop1; for (loop = offStart, loop1 = 0; loop <= offEnd; loop++) { retVal[loop1++] = (char )(inData[loop] / 256); /* Get High byte */ retVal[loop1++] = (char )(inData[loop] % 256); /* Get Low byte */ } /* end of for */ retVal[loop1] = '\0'; /* Make sure it ends in a NULL character */ return retVal; } /* GetAscii() */
直接从RING3获取硬盘序列号(1) [ 作者: 陆麟 添加时间: 2001-6-2 0:04:28 ] 通常情况下,我们通过0XEC命令对IDE端口进行监测.获取硬盘信息. 一般情况下,我们就写个VXD或者DRIVER来完成.但是现在,通过MS的S.M.A.R.T.接口,我们可以直接从RING3调用API DeviceIoControl()来获取硬盘信息.下面乃是我的例程: 另外,也有编译好的版本供大家平时使用.欢迎下载. *注:在WIN98SE,WINDOWS ME中,S.M.A.R.T并不缺省安装.请将SMARTVSD.VXD拷贝到%SYSTEM%\IOSUBSYS目录下. 在WINDOWS2000下,由于非ADMINISTRATORS组的用户对硬盘连GENERIC_READ的权限也没有,所以请以ADMINISTRATOR登录后使用. /*+++ HDID.CPP Written by Lu Lin http://lu0.126.com 2000.11.3 ---*/ #include <windows.h> #include <iostream.h> #include <stdio.h> #define DFP_GET_VERSION 0x00074080 #define DFP_SEND_DRIVE_COMMAND 0x0007c084 #define DFP_RECEIVE_DRIVE_DATA 0x0007c088 #pragma pack(1) typedef struct _GETVERSIONOUTPARAMS { BYTE bVersion; // Binary driver version. BYTE bRevision; // Binary driver revision. BYTE bReserved; // Not used. BYTE bIDEDeviceMap; // Bit map of IDE devices. DWORD fCapabilities; // Bit mask of driver capabilities. DWORD dwReserved[4]; // For future use. } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS; typedef struct _IDEREGS { BYTE bFeaturesReg; // Used for specifying SMART "commands". BYTE bSectorCountReg; // IDE sector count register BYTE bSectorNumberReg; // IDE sector number register BYTE bCylLowReg; // IDE low order cylinder value BYTE bCylHighReg; // IDE high order cylinder value BYTE bDriveHeadReg; // IDE drive/head register BYTE bCommandReg; // Actual IDE command. BYTE bReserved; // reserved for future use. Must be zero. } IDEREGS, *PIDEREGS, *LPIDEREGS; typedef struct _SENDCMDINPARAMS { DWORD cBufferSize; // Buffer size in bytes IDEREGS irDriveRegs; // Structure with drive register values. BYTE bDriveNumber; // Physical drive number to send // command to (0,1,2,3). BYTE bReserved[3]; // Reserved for future expansion. DWORD dwReserved[4]; // For future use. //BYTE bBuffer[1]; // Input buffer. } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS; typedef struct _DRIVERSTATUS { BYTE bDriverError; // Error code from driver, // or 0 if no error. BYTE bIDEStatus; // Contents of IDE Error register. // Only valid when bDriverError // is SMART_IDE_ERROR. BYTE bReserved[2]; // Reserved for future expansion. DWORD dwReserved[2]; // Reserved for future expansion. } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; typedef struct _SENDCMDOUTPARAMS { DWORD cBufferSize; // Size of bBuffer in bytes DRIVERSTATUS DriverStatus; // Driver status structure. BYTE bBuffer[512]; // Buffer of arbitrary length // in which to store the data read from the drive. } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS; typedef struct _IDSECTOR { USHORT wGenConfig; USHORT wNumCyls; USHORT wReserved; USHORT wNumHeads; USHORT wBytesPerTrack; USHORT wBytesPerSector; USHORT wSectorsPerTrack; USHORT wVendorUnique[3]; CHAR sSerialNumber[20]; USHORT wBufferType; USHORT wBufferSize; USHORT wECCSize; CHAR sFirmwareRev[8]; CHAR sModelNumber[40]; USHORT wMoreVendorUnique; USHORT wDoubleWordIO; USHORT wCapabilities; USHORT wReserved1; USHORT wPIOTiming; USHORT wDMATiming; USHORT wBS; USHORT wNumCurrentCyls; USHORT wNumCurrentHeads; USHORT wNumCurrentSectorsPerTrack; ULONG ulCurrentSectorCapacity; USHORT wMultSectorStuff; ULONG ulTotalAddressableSectors; USHORT wSingleWordDMA; USHORT wMultiWordDMA; BYTE bReserved[128]; } IDSECTOR, *PIDSECTOR;
int main(void)
{
unsigned int diskData[256]; /* Disk data */
unsigned int offset; /* Disk data offset */
int loop;
int numDrv; /* Number of IDE hard drives */
union REGS registers;
unsigned int biosCyl[2]; /* Cylinders, Heads, Sectors */
unsigned int biosHead[2];
unsigned int biosSec [2];
numDrv = peekb(0x40, 0x75); /* BIOS Data area, Number of Hard disks */
for (loop = 0; loop < numDrv; loop++)
{
while (inp(0x01f7) != 0x50); /* Wait for controller not busy */
outp(0x01f6, (loop == 0 ? 0xa0 : 0xb0)); /* Get first/second drive */
outp(0x01f7, 0xec); /* Get drive info data */
while (inp(0x1f7) != 0x58); /* Wait for data ready */
for (offset = 0; offset != 256; offset++) /* Read "sector" */
diskData[offset] = inpw(0x1f0);
/* Get BIOS drive info */
registers.h.ah = 0x08; /* Get drive info */
registers.h.dl = 0x80 + loop; /* Drive is 80H for Disk 0, 81H for Disk 1 */
int86(0x13, ?isters, ?isters);
if (!registers.x.cflag) /* All OK if carry not set */
{
biosHead[loop] = registers.h.dh + 1; /* Heads are from 0 */
biosSec[loop] = registers.h.cl & 0x3f; /* sec is bits 5 - 0 */
/* +1 because starts from 0 and +1 for FDISK leaving one out */
biosCyl[loop] = ((registers.h.cl & 0xc0) << 2) + registers.h.ch + 2;
} /* end of if */
printf("DRIVE %d:\n", loop);
printf("Model Number______________________: %s\n", GetAscii(diskData, 27, 46));
printf("Serial Number_____________________: %s\n", GetAscii(diskData, 10, 19));
printf("Controller Revision Number________: %s\n\n", GetAscii(diskData, 23, 26));
printf("Able to do Double Word Transfer___: %6s\n", (diskData[48] == 0 ? "No" : "Yes"));
printf("Controller type___________________: %04X\n", diskData[20]);
printf("Controller buffer size (bytes)____: %6u\n", diskData[21] * 512);
printf("Number of ECC bytes transferred___: %6u\n", diskData[22]);
printf("Number of sectors per interrupt___: %6u\n\n", diskData[47]);
printf("Hard Disk Reports\n");
printf("Number of Cylinders (Fixed)_______: %6u\n", diskData[1]);
printf("Number of Heads___________________: %6u\n", diskData[3]);
printf("Number of Sectors per Track_______: %6u\n\n", diskData[6]);
printf("BIOS Reports\n");
printf("Number of Cylinders_______________: %6u\n", biosCyl[loop]);
printf("Number of Heads___________________: %6u\n", biosHead[loop]);
printf("Number of Sectors per Track_______: %6u\n\n", biosSec[loop]);
printf("Press any key to continue...\n\n");
getch();
} /* end of for */
return 0;
} /* main() */
char *GetAscii(unsigned int inData[], int offStart, int offEnd)
{
static char retVal[255];
int loop, loop1;
for (loop = offStart, loop1 = 0; loop <= offEnd; loop++)
{
retVal[loop1++] = (char )(inData[loop] / 256); /* Get High byte */
retVal[loop1++] = (char )(inData[loop] % 256); /* Get Low byte */
} /* end of for */
retVal[loop1] = '\0'; /* Make sure it ends in a NULL character */
return retVal;
} /* GetAscii() */
[ 作者: 陆麟 添加时间: 2001-6-2 0:04:28 ]
通常情况下,我们通过0XEC命令对IDE端口进行监测.获取硬盘信息.
一般情况下,我们就写个VXD或者DRIVER来完成.但是现在,通过MS的S.M.A.R.T.接口,我们可以直接从RING3调用API DeviceIoControl()来获取硬盘信息.下面乃是我的例程:
另外,也有编译好的版本供大家平时使用.欢迎下载.
*注:在WIN98SE,WINDOWS ME中,S.M.A.R.T并不缺省安装.请将SMARTVSD.VXD拷贝到%SYSTEM%\IOSUBSYS目录下.
在WINDOWS2000下,由于非ADMINISTRATORS组的用户对硬盘连GENERIC_READ的权限也没有,所以请以ADMINISTRATOR登录后使用.
/*+++
HDID.CPP
Written by Lu Lin
http://lu0.126.com
2000.11.3
---*/
#include <windows.h>
#include <iostream.h>
#include <stdio.h>
#define DFP_GET_VERSION 0x00074080
#define DFP_SEND_DRIVE_COMMAND 0x0007c084
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088
#pragma pack(1)
typedef struct _GETVERSIONOUTPARAMS {
BYTE bVersion; // Binary driver version.
BYTE bRevision; // Binary driver revision.
BYTE bReserved; // Not used.
BYTE bIDEDeviceMap; // Bit map of IDE devices.
DWORD fCapabilities; // Bit mask of driver capabilities.
DWORD dwReserved[4]; // For future use.
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
typedef struct _IDEREGS {
BYTE bFeaturesReg; // Used for specifying SMART "commands".
BYTE bSectorCountReg; // IDE sector count register
BYTE bSectorNumberReg; // IDE sector number register
BYTE bCylLowReg; // IDE low order cylinder value
BYTE bCylHighReg; // IDE high order cylinder value
BYTE bDriveHeadReg; // IDE drive/head register
BYTE bCommandReg; // Actual IDE command.
BYTE bReserved; // reserved for future use. Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;
typedef struct _SENDCMDINPARAMS {
DWORD cBufferSize; // Buffer size in bytes
IDEREGS irDriveRegs; // Structure with drive register values.
BYTE bDriveNumber; // Physical drive number to send
// command to (0,1,2,3).
BYTE bReserved[3]; // Reserved for future expansion.
DWORD dwReserved[4]; // For future use.
//BYTE bBuffer[1]; // Input buffer.
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
typedef struct _DRIVERSTATUS {
BYTE bDriverError; // Error code from driver,
// or 0 if no error.
BYTE bIDEStatus; // Contents of IDE Error register.
// Only valid when bDriverError
// is SMART_IDE_ERROR.
BYTE bReserved[2]; // Reserved for future expansion.
DWORD dwReserved[2]; // Reserved for future expansion.
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
typedef struct _SENDCMDOUTPARAMS {
DWORD cBufferSize; // Size of bBuffer in bytes
DRIVERSTATUS DriverStatus; // Driver status structure.
BYTE bBuffer[512]; // Buffer of arbitrary length
// in which to store the data read from the drive.
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
typedef struct _IDSECTOR {
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
} IDSECTOR, *PIDSECTOR;
unsigned long GetDiskSerialNo()
{
LPCTSTR lpRootPathName="c:\\"; //取C盘的序列号
char lpVolumeNameBuffer[12]; //磁盘卷标
DWORD nVolumeNameSize=12;
DWORD VolumeSerialNumber; //磁盘序列号
DWORD MaximumComponentLength;
char lpFileSystemNameBuffer[12];
DWORD nFileSystemNameSize=10;
DWORD FileSystemFlags;
GetVolumeInformation(lpRootPathName,
lpVolumeNameBuffer,
nVolumeNameSize,
&VolumeSerialNumber,
&MaximumComponentLength,
&FileSystemFlags,
lpFileSystemNameBuffer,
nFileSystemNameSize
); return VolumeSerialNumber;
}