www.pudn.com > IdeDiskInfo.zip > GetIdeDiskInfo.cpp


#include "stdafx.h"
#include "GetIdeDiskInfo.h" 
 
// 打开设备 
// filename: 设备的“文件名” 
HANDLE OpenDevice(LPCTSTR filename) 
{ 
	HANDLE hDevice; 
 
	// 打开设备 
	hDevice= ::CreateFile(filename,					// 文件名 
			GENERIC_READ | GENERIC_WRITE,			// 读写方式 
			FILE_SHARE_READ | FILE_SHARE_WRITE,		// 共享方式 
			NULL,									// 默认的安全描述符 
			OPEN_EXISTING,							// 创建方式 
			0,										// 不需设置文件属性 
			NULL);									// 不需参照模板文件 
 
	return hDevice; 
} 
 
// 向驱动发“IDENTIFY DEVICE”命令,获得设备信息 
// hDevice: 设备句柄 
// pIdInfo:  设备信息结构指针 
BOOL IdentifyDevice(HANDLE hDevice, PIDINFO pIdInfo) 
{ 
	PSENDCMDINPARAMS pSCIP;		// 输入数据结构指针 
	PSENDCMDOUTPARAMS pSCOP;	// 输出数据结构指针 
	DWORD dwOutBytes;			// IOCTL输出数据长度 
	BOOL bResult;				// IOCTL返回值 
 
	// 申请输入/输出数据结构空间 
    pSCIP = (PSENDCMDINPARAMS)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SENDCMDINPARAMS)-1); 
    pSCOP = (PSENDCMDOUTPARAMS)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SENDCMDOUTPARAMS)+sizeof(IDINFO)-1); 
 
	// 指定ATA/ATAPI命令的寄存器值 
//	pSCIP->irDriveRegs.bFeaturesReg = 0; 
//	pSCIP->irDriveRegs.bSectorCountReg = 0; 
//	pSCIP->irDriveRegs.bSectorNumberReg = 0; 
//	pSCIP->irDriveRegs.bCylLowReg = 0; 
//	pSCIP->irDriveRegs.bCylHighReg = 0; 
//	pSCIP->irDriveRegs.bDriveHeadReg = 0; 
	pSCIP->irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; 
 
	// 指定输入/输出数据缓冲区大小 
	pSCIP->cBufferSize = 0; 
	pSCOP->cBufferSize = sizeof(IDINFO); 
 
	// IDENTIFY DEVICE 
	bResult = ::DeviceIoControl(hDevice,						// 设备句柄 
		DFP_RECEIVE_DRIVE_DATA,									// 指定IOCTL 
		pSCIP, sizeof(SENDCMDINPARAMS) - 1,						// 输入数据缓冲区 
		pSCOP, sizeof(SENDCMDOUTPARAMS) + sizeof(IDINFO) - 1,	// 输出数据缓冲区 
		&dwOutBytes,											// 输出数据长度 
		(LPOVERLAPPED)NULL);									// 用同步I/O 
 
	// 复制设备参数结构 
	::memcpy(pIdInfo, pSCOP->bBuffer, sizeof(IDINFO)); 
 
	// 释放输入/输出数据空间 
	::GlobalFree(pSCOP); 
	::GlobalFree(pSCIP); 
 
	return bResult; 
} 
 
// 向SCSI MINI-PORT驱动发“IDENTIFY PACKET DEVICE”命令,获得设备信息 
// hDevice: 设备句柄 
// pIdInfo:  设备信息结构指针 
BOOL IdentifyDeviceAsScsi(HANDLE hDevice, int nDrive, PIDINFO pIdInfo) 
{ 
	PSENDCMDINPARAMS pSCIP;		// 输入数据结构指针 
	PSENDCMDOUTPARAMS pSCOP;	// 输出数据结构指针 
	PSRB_IO_CONTROL pSRBIO;		// SCSI输入输出数据结构指针 
	DWORD dwOutBytes;			// IOCTL输出数据长度 
	BOOL bResult;				// IOCTL返回值 
 
	// 申请输入/输出数据结构空间 
    pSRBIO = (PSRB_IO_CONTROL)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS)+sizeof(IDINFO)-1); 
    pSCIP = (PSENDCMDINPARAMS)((char *)pSRBIO+sizeof(SRB_IO_CONTROL)); 
    pSCOP = (PSENDCMDOUTPARAMS)((char *)pSRBIO+sizeof(SRB_IO_CONTROL)); 
 
	// 填充输入/输出数据 
	pSRBIO->HeaderLength = sizeof(SRB_IO_CONTROL); 
	pSRBIO->Timeout = 10000; 
	pSRBIO->Length = sizeof(SENDCMDOUTPARAMS)+sizeof(IDINFO)-1; 
	pSRBIO->ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY; 
    ::strncpy ((char *)pSRBIO->Signature, "SCSIDISK", 8); 
 
	// 指定ATA/ATAPI命令的寄存器值 
//	pSCIP->irDriveRegs.bFeaturesReg = 0; 
//	pSCIP->irDriveRegs.bSectorCountReg = 0; 
//	pSCIP->irDriveRegs.bSectorNumberReg = 0; 
//	pSCIP->irDriveRegs.bCylLowReg = 0; 
//	pSCIP->irDriveRegs.bCylHighReg = 0; 
//	pSCIP->irDriveRegs.bDriveHeadReg = 0; 
	pSCIP->irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; 
	pSCIP->bDriveNumber = nDrive; 
 
	// IDENTIFY DEVICE 
	bResult = ::DeviceIoControl(hDevice,						// 设备句柄 
		IOCTL_SCSI_MINIPORT,									// 指定IOCTL 
		pSRBIO, sizeof(SRB_IO_CONTROL) +sizeof(SENDCMDINPARAMS) - 1,						// 输入数据缓冲区 
		pSRBIO, sizeof(SRB_IO_CONTROL) +sizeof(SENDCMDOUTPARAMS) + sizeof(IDINFO) - 1,	// 输出数据缓冲区 
		&dwOutBytes,											// 输出数据长度 
		(LPOVERLAPPED)NULL);									// 用同步I/O 
	 
	// 复制设备参数结构 
	::memcpy(pIdInfo, pSCOP->bBuffer, sizeof(IDINFO)); 
 
	// 释放输入/输出数据空间 
	::GlobalFree(pSRBIO); 
 
	return bResult; 
} 
 
// 将串中的字符两两颠倒 
// 原因是ATA/ATAPI中的WORD,与Windows采用的字节顺序相反 
// 驱动程序中已经将收到的数据全部反过来,我们来个负负得正 
void AdjustString(char* str, int len) 
{ 
	char ch; 
	int i; 
 
	// 两两颠倒 
	for(i=0;i=0 && str[i]==' ') 
	{ 
		str[i] = '\0'; 
		i--; 
	} 
} 
 
// 读取IDE硬盘的设备信息,必须有足够权限 
// nDrive: 驱动器号(0=第一个硬盘,1=0=第二个硬盘,......) 
// pIdInfo: 设备信息结构指针 
BOOL GetPhysicalDriveInfoInNT(int nDrive, PIDINFO pIdInfo) 
{ 
	HANDLE hDevice;			// 设备句柄 
	BOOL bResult;			// 返回结果 
	char szFileName[20];	// 文件名 
 
	::sprintf(szFileName,"\\\\.\\PhysicalDrive%d", nDrive); 
 
	hDevice = ::OpenDevice(szFileName); 
 
	if(hDevice == INVALID_HANDLE_VALUE) 
	{ 
		return FALSE; 
	} 
 
	// IDENTIFY DEVICE 
	bResult = ::IdentifyDevice(hDevice, pIdInfo); 
 
	if(bResult) 
	{ 
		// 调整字符串 
		::AdjustString(pIdInfo->sSerialNumber, 20); 
		::AdjustString(pIdInfo->sModelNumber, 40); 
		::AdjustString(pIdInfo->sFirmwareRev, 8); 
	} 
 
	::CloseHandle (hDevice); 
 
	return bResult; 
} 
 
// 用SCSI驱动读取IDE硬盘的设备信息,不受权限制约 
// nDrive: 驱动器号(0=Primary Master, 1=Promary Slave, 2=Secondary master, 3=Secondary slave) 
// pIdInfo: 设备信息结构指针 
BOOL GetIdeDriveAsScsiInfoInNT(int nDrive, PIDINFO pIdInfo) 
{ 
	HANDLE hDevice;			// 设备句柄 
	BOOL bResult;			// 返回结果 
	char szFileName[20];	// 文件名 
 
	::sprintf(szFileName,"\\\\.\\Scsi%d:", nDrive/2); 
 
	hDevice = ::OpenDevice(szFileName); 
       
	if(hDevice == INVALID_HANDLE_VALUE) 
	{ 
		return FALSE; 
	} 
 
	// IDENTIFY DEVICE 
	bResult = ::IdentifyDeviceAsScsi(hDevice, nDrive%2, pIdInfo); 
 
	// 检查是不是空串 
	if(pIdInfo->sModelNumber[0]=='\0') 
	{ 
		bResult = FALSE; 
	} 
 
	if(bResult) 
	{ 
		// 调整字符串 
		::AdjustString(pIdInfo->sSerialNumber, 20); 
		::AdjustString(pIdInfo->sModelNumber, 40); 
		::AdjustString(pIdInfo->sFirmwareRev, 8); 
	} 
 
	return bResult; 
}