⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsicmd.cpp

📁 枚举windows操作系统中物理磁盘和逻辑磁盘的信息
💻 CPP
字号:
#pragma warning(disable:4005)
#include <stddef.h>
#include <Windows.h>
#include "scsicmd.h"
namespace NT{
#include <ntddk.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <scsi.h>
}
#include <memory>
using namespace std;
#define SENSEBUFSIZE 32
#define DATABUFSIZE 0xFC
#pragma pack(push,4)
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {
	NT::SCSI_PASS_THROUGH spt;
	ULONG             Filler;      // realign buffers to double word boundary
	UCHAR             ucSenseBuf[SENSEBUFSIZE];
	UCHAR             ucDataBuf[DATABUFSIZE];
} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;

typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER {
	NT::SCSI_PASS_THROUGH_DIRECT sptd;
	ULONG             Filler;      // realign buffer to double word boundary
	UCHAR             ucSenseBuf[SENSEBUFSIZE];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
#pragma pack(pop)
bool GetCapacity(wstring const&Device,DWORD&Sectors,DWORD&BytesPerSector){
	bool success=false;Sectors=BytesPerSector=0;
	HANDLE const hDrive=CreateFileW(Device.c_str(),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
	DWORD returned;
	SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
	NT::CDB&Cdb=(NT::CDB&)sptwb.spt.Cdb;
	memset(&sptwb,0,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
	sptwb.spt.Length = sizeof(NT::SCSI_PASS_THROUGH);
	//sptwb.spt.PathId = 0;
	//sptwb.spt.TargetId = 0;
	//sptwb.spt.Lun = 0;
	sptwb.spt.CdbLength = CDB10GENERIC_LENGTH;
	sptwb.spt.SenseInfoLength = SENSEBUFSIZE;
	sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
	sptwb.spt.DataTransferLength = DATABUFSIZE;
	sptwb.spt.TimeOutValue = 10;
	sptwb.spt.DataBufferOffset =offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
	sptwb.spt.SenseInfoOffset =offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
	sptwb.spt.Cdb[0] = SCSIOP_READ_CAPACITY;
	DWORD length=offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf)+sptwb.spt.DataTransferLength;
	BOOL status=DeviceIoControl(hDrive,IOCTL_SCSI_PASS_THROUGH,&sptwb,sizeof(NT::SCSI_PASS_THROUGH),&sptwb,length,&returned,NULL);
	if(status&&!sptwb.spt.ScsiStatus){
		if((sptwb.spt.DataTransferLength>7)&&(returned==sptwb.spt.DataTransferLength+sptwb.spt.DataBufferOffset)){
			union{
				DWORD u;
				BYTE by[4];
			}tmp;
			tmp.by[3]=sptwb.ucDataBuf[0];
			tmp.by[2]=sptwb.ucDataBuf[1];
			tmp.by[1]=sptwb.ucDataBuf[2];
			tmp.by[0]=sptwb.ucDataBuf[3];
			if(++tmp.u){
				Sectors=tmp.u;
				tmp.by[3]=sptwb.ucDataBuf[4];
				tmp.by[2]=sptwb.ucDataBuf[5];
				tmp.by[1]=sptwb.ucDataBuf[6];
				tmp.by[0]=sptwb.ucDataBuf[7];
				BytesPerSector=tmp.u;
				success=true;
			}
		}
	}
	CloseHandle(hDrive);
	return success;
}
BOOL SCSICommand(HANDLE const hDevice,UCHAR&ScsiStatus,
								 UCHAR*const ucSenseBuf,UCHAR&SenseSize,
								 UCHAR*const ucDataBuf,DWORD&DataSize,
								 NT::CDB const&Cdb,BYTE const CdbLength,UCHAR const DataIn){
	if(CdbLength>sizeof(((NT::SCSI_PASS_THROUGH_DIRECT*)NULL)->Cdb))
		return FALSE;
	DWORD const Align=4;
	DWORD const tmpSenseSize=SenseSize<SENSEBUFSIZE?SENSEBUFSIZE:SenseSize;
	auto_ptr<char>const tmpptr
		(new char[sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)+tmpSenseSize-SENSEBUFSIZE+Align]);
	SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER*const 
		psptdwb=(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER*)(DWORD(tmpptr.get()+Align-1)/Align*Align);
	DWORD const sptdwbSize=sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)+tmpSenseSize-SENSEBUFSIZE;
	memset(psptdwb,0,sptdwbSize);
	psptdwb->sptd.Length = sizeof(NT::SCSI_PASS_THROUGH_DIRECT);
	psptdwb->sptd.CdbLength = CdbLength;
	psptdwb->sptd.SenseInfoLength = ucSenseBuf?tmpSenseSize:0;
	psptdwb->sptd.DataIn = DataIn;
	psptdwb->sptd.DataTransferLength = DataSize;
	psptdwb->sptd.TimeOutValue = 10;
	psptdwb->sptd.DataBuffer = ucDataBuf;
	psptdwb->sptd.SenseInfoOffset =offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
	memcpy(psptdwb->sptd.Cdb,&Cdb,CdbLength);
	DWORD returned;
	BOOL const Status=DeviceIoControl(hDevice,IOCTL_SCSI_PASS_THROUGH_DIRECT,
		psptdwb,sizeof(NT::SCSI_PASS_THROUGH_DIRECT),
		psptdwb,sptdwbSize,&returned,NULL);
	if(!Status)
		return FALSE;
	if(returned<sizeof(NT::SCSI_PASS_THROUGH_DIRECT))
		return FALSE;
	if(sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)-SENSEBUFSIZE+psptdwb->sptd.SenseInfoLength!=returned)
		return FALSE;
	ScsiStatus=psptdwb->sptd.ScsiStatus;
	SenseSize=psptdwb->sptd.SenseInfoLength;
	if(ucSenseBuf&&SenseSize)
		memcpy(ucSenseBuf,psptdwb->ucSenseBuf,SenseSize);
	DataSize=psptdwb->sptd.DataTransferLength;
	return TRUE;
}
bool ModeSenseCheck(UCHAR const**const PageData,BOOL const Status,UCHAR const ScsiStatus,
	UCHAR const PageCode,UCHAR const CdbLength,UCHAR const PageSize,
	UCHAR*const DataBuf,DWORD const DataSize){
	if((!Status)||(ScsiStatus))
		return false;
	if((CdbLength!=CDB6GENERIC_LENGTH)&&(CdbLength!=CDB10GENERIC_LENGTH))
		return false;
	DWORD const HeadSize=(CdbLength==CDB6GENERIC_LENGTH)?4:8;
	if(DataSize<HeadSize)
		return false;
	WORD ModeDataLength,BlockLength;
	if(CdbLength==CDB6GENERIC_LENGTH){
		ModeDataLength=DataBuf[0]+1;
		BlockLength=DataBuf[3];
	}else{
		union{
			WORD w;
			BYTE b[2];
		}tmp;
		tmp.b[1]=DataBuf[0];
		tmp.b[0]=DataBuf[1];
		ModeDataLength=tmp.w+2;
		tmp.b[1]=DataBuf[6];
		tmp.b[0]=DataBuf[7];
		BlockLength=tmp.w;
	}
	if(ModeDataLength!=DataSize)
		return false;
	if((BlockLength&7)||(PageSize+BlockLength+HeadSize)>DataSize)
		return false;
	if(PageCode!=DataBuf[HeadSize+BlockLength])
		return false;
	if(PageSize!=DataBuf[HeadSize+BlockLength+1]+2)
		return false;
	if(PageData)
		*PageData=DataBuf+HeadSize+BlockLength;
	return true;
}
bool RigidDisk(HANDLE const hDrive,UCHAR const CdbLength,DWORD&Cylinders,DWORD&Heads,DWORD&Sectors,DWORD&SectorSize){
	if((CdbLength!=CDB6GENERIC_LENGTH)&&(CdbLength!=CDB10GENERIC_LENGTH))
		return false;
	NT::CDB Cdb;
	UCHAR DataBuf[DATABUFSIZE],SenseBuf[SENSEBUFSIZE];
	UCHAR SenseSize=sizeof(SenseBuf),ScsiStatus;
	DWORD DataSize=sizeof(DataBuf);
	UCHAR const*PageData;
	union{
		DWORD u;
		WORD w[2];
		BYTE by[4];
	}tmp;
	memset(&Cdb,0,sizeof(Cdb));
	if(CdbLength==CDB10GENERIC_LENGTH){
		Cdb.MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
		Cdb.MODE_SENSE10.PageCode=MODE_PAGE_RIGID_GEOMETRY;
		tmp.w[0]=sizeof(DataBuf);
		Cdb.MODE_SENSE10.AllocationLength[0] = tmp.by[1];
		Cdb.MODE_SENSE10.AllocationLength[1] = tmp.by[0];
	}else{
		Cdb.MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
		Cdb.MODE_SENSE.PageCode=MODE_PAGE_RIGID_GEOMETRY;
		Cdb.MODE_SENSE.AllocationLength = sizeof(DataBuf);
	}
	BOOL Status=SCSICommand(hDrive,ScsiStatus,
		SenseBuf,SenseSize,DataBuf,DataSize,Cdb,CdbLength,SCSI_IOCTL_DATA_IN);
	if(ModeSenseCheck(&PageData,Status,ScsiStatus,Cdb.MODE_SENSE.PageCode,CdbLength,24,DataBuf,DataSize)){
		tmp.by[3]=0;
		tmp.by[2]=PageData[2];
		tmp.by[1]=PageData[3];
		tmp.by[0]=PageData[4];
		Cylinders=tmp.u;
		Heads=PageData[5];
		SenseSize=sizeof(SenseBuf);
		DataSize=sizeof(DataBuf);
		memset(&Cdb,0,sizeof(Cdb));
		if(CdbLength==CDB10GENERIC_LENGTH){
			Cdb.MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
			Cdb.MODE_SENSE10.PageCode=MODE_PAGE_FORMAT_DEVICE;
			tmp.w[0]=sizeof(DataBuf);
			Cdb.MODE_SENSE10.AllocationLength[0] = tmp.by[1];
			Cdb.MODE_SENSE10.AllocationLength[1] = tmp.by[0];
		}else{
			Cdb.MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
			Cdb.MODE_SENSE.PageCode=MODE_PAGE_FORMAT_DEVICE;
			Cdb.MODE_SENSE.AllocationLength = sizeof(DataBuf);
		}
		Status=SCSICommand(hDrive,ScsiStatus,
			SenseBuf,SenseSize,DataBuf,DataSize,Cdb,CdbLength,SCSI_IOCTL_DATA_IN);
		if(ModeSenseCheck(&PageData,Status,ScsiStatus,Cdb.MODE_SENSE.PageCode,CdbLength,24,DataBuf,DataSize)){
			tmp.by[3]=tmp.by[2]=0;
			tmp.by[1]=PageData[10];
			tmp.by[0]=PageData[11];
			Sectors=tmp.u;
			tmp.by[1]=PageData[12];
			tmp.by[0]=PageData[13];
			SectorSize=tmp.u;
			return true;
		}
	}
	return false;
}
bool FlexibleDisk(HANDLE const hDrive,UCHAR const CdbLength,DWORD&Cylinders,DWORD&Heads,DWORD&Sectors,DWORD&SectorSize){
	if((CdbLength!=CDB6GENERIC_LENGTH)&&(CdbLength!=CDB10GENERIC_LENGTH))
		return false;
	NT::CDB Cdb;
	UCHAR DataBuf[DATABUFSIZE],SenseBuf[SENSEBUFSIZE];
	UCHAR SenseSize=sizeof(SenseBuf),ScsiStatus;
	DWORD DataSize=sizeof(DataBuf);
	UCHAR const*PageData;
	union{
		DWORD u;
		WORD w[2];
		BYTE by[4];
	}tmp;
	memset(&Cdb,0,sizeof(Cdb));
	if(CdbLength==CDB10GENERIC_LENGTH){
		Cdb.MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
		Cdb.MODE_SENSE10.PageCode=MODE_PAGE_FLEXIBILE;
		tmp.w[0]=sizeof(DataBuf);
		Cdb.MODE_SENSE10.AllocationLength[0] = tmp.by[1];
		Cdb.MODE_SENSE10.AllocationLength[1] = tmp.by[0];
	}else{
		Cdb.MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
		Cdb.MODE_SENSE.PageCode=MODE_PAGE_FLEXIBILE;
		Cdb.MODE_SENSE.AllocationLength = sizeof(DataBuf);
	}
	BOOL const Status=SCSICommand(hDrive,ScsiStatus,
		SenseBuf,SenseSize,DataBuf,DataSize,Cdb,CdbLength,SCSI_IOCTL_DATA_IN);
	if(ModeSenseCheck(&PageData,Status,ScsiStatus,Cdb.MODE_SENSE.PageCode,CdbLength,32,DataBuf,DataSize)){
		Heads=PageData[4];
		Sectors=PageData[5];
		tmp.by[3]=tmp.by[2]=0;
		tmp.by[1]=PageData[6];
		tmp.by[0]=PageData[7];
		SectorSize=tmp.u;
		tmp.by[1]=PageData[8];
		tmp.by[0]=PageData[9];
		Cylinders=tmp.u;
		return true;
	}
	return false;
}
bool GetGeometry(wstring const&Device,DWORD&Cylinders,DWORD&Heads,DWORD&Sectors,DWORD&SectorSize){
	Cylinders=Heads=Sectors=SectorSize=0;
	HANDLE const hDrive=CreateFileW(Device.c_str(),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
	bool res;
	if(!RigidDisk(hDrive,CDB10GENERIC_LENGTH,Cylinders,Heads,Sectors,SectorSize))
		if(!RigidDisk(hDrive,CDB6GENERIC_LENGTH,Cylinders,Heads,Sectors,SectorSize))
			if(!FlexibleDisk(hDrive,CDB10GENERIC_LENGTH,Cylinders,Heads,Sectors,SectorSize))
				res=FlexibleDisk(hDrive,CDB6GENERIC_LENGTH,Cylinders,Heads,Sectors,SectorSize);
	CloseHandle(hDrive);
	return res;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -