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

📄 os_win32.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	UCHAR  PathId;	UCHAR  TargetId;	UCHAR  Lun;	UCHAR  ReservedAsUchar;	ULONG  DataTransferLength;	ULONG  TimeOutValue;	ULONG  ReservedAsUlong;	ULONG/*_PTR*/ DataBufferOffset;	UCHAR  PreviousTaskFile[8];	UCHAR  CurrentTaskFile[8];} ATA_PASS_THROUGH_EX, *PATA_PASS_THROUGH_EX;ASSERT_SIZEOF(ATA_PASS_THROUGH_EX, 40);#define ATA_FLAGS_DRDY_REQUIRED 0x01#define ATA_FLAGS_DATA_IN       0x02#define ATA_FLAGS_DATA_OUT      0x04#define ATA_FLAGS_48BIT_COMMAND 0x08/////////////////////////////////////////////////////////////////////////////static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize){ 	typedef struct {		ATA_PASS_THROUGH_EX apt;		ULONG Filler;		UCHAR ucDataBuf[512];	} ATA_PASS_THROUGH_EX_WITH_BUFFERS;	const unsigned char magic = 0xcf;	ATA_PASS_THROUGH_EX_WITH_BUFFERS ab; memset(&ab, 0, sizeof(ab));	ab.apt.Length = sizeof(ATA_PASS_THROUGH_EX);	//ab.apt.PathId = 0;	//ab.apt.TargetId = 0;	//ab.apt.Lun = 0;	ab.apt.TimeOutValue = 10;	unsigned size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf);	ab.apt.DataBufferOffset = size; 	if (datasize > 0) {		if (datasize > (int)sizeof(ab.ucDataBuf)) {			errno = EINVAL;			return -1;		}		ab.apt.AtaFlags = ATA_FLAGS_DATA_IN;		ab.apt.DataTransferLength = datasize;		size += datasize;		ab.ucDataBuf[0] = magic;	}	else if (datasize < 0) {		if (-datasize > (int)sizeof(ab.ucDataBuf)) {			errno = EINVAL;			return -1;		}		ab.apt.AtaFlags = ATA_FLAGS_DATA_OUT;		ab.apt.DataTransferLength = -datasize;		size += -datasize;		memcpy(ab.ucDataBuf, data, -datasize);	}	else {		assert(ab.apt.AtaFlags == 0);		assert(ab.apt.DataTransferLength == 0);	}	assert(sizeof(ab.apt.CurrentTaskFile) == sizeof(IDEREGS));	IDEREGS * ctfregs = (IDEREGS *)ab.apt.CurrentTaskFile;	*ctfregs = *regs;	DWORD num_out;	if (!DeviceIoControl(hdevice, IOCTL_ATA_PASS_THROUGH,		&ab, size, &ab, size, &num_out, NULL)) {		long err = GetLastError();		if (con->reportataioctl) {			pout("  IOCTL_ATA_PASS_THROUGH failed, Error=%ld\n", err);			print_ide_regs_io(regs, NULL);		}		errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);		return -1;	}	// Check ATA status	if (ctfregs->bCommandReg/*Status*/ & 0x01) {		if (con->reportataioctl) {			pout("  IOCTL_ATA_PASS_THROUGH command failed:\n");			print_ide_regs_io(regs, ctfregs);		}		errno = EIO;		return -1;	}	// Check and copy data	if (datasize > 0) {		if (   num_out != size		    || (ab.ucDataBuf[0] == magic && !nonempty(ab.ucDataBuf+1, datasize-1))) {			if (con->reportataioctl) {				pout("  IOCTL_ATA_PASS_THROUGH output data missing (%lu)\n", num_out);				print_ide_regs_io(regs, ctfregs);			}			errno = EIO;			return -1;		}		memcpy(data, ab.ucDataBuf, datasize);	}	if (con->reportataioctl > 1) {		pout("  IOCTL_ATA_PASS_THROUGH suceeded, bytes returned: %lu\n", num_out);		print_ide_regs_io(regs, ctfregs);	}	*regs = *ctfregs;	return 0;}/////////////////////////////////////////////////////////////////////////////// ATA PASS THROUGH via SCSI PASS THROUGH (WinNT4 only)#define IOCTL_SCSI_PASS_THROUGH \	CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH, 0x04d004);#define SCSI_IOCTL_DATA_OUT          0#define SCSI_IOCTL_DATA_IN           1#define SCSI_IOCTL_DATA_UNSPECIFIED  2// undocumented SCSI opcode to for ATA passthrough#define SCSIOP_ATA_PASSTHROUGH    0xCCtypedef struct _SCSI_PASS_THROUGH {	USHORT  Length;	UCHAR  ScsiStatus;	UCHAR  PathId;	UCHAR  TargetId;	UCHAR  Lun;	UCHAR  CdbLength;	UCHAR  SenseInfoLength;	UCHAR  DataIn;	ULONG  DataTransferLength;	ULONG  TimeOutValue;	ULONG/*_PTR*/ DataBufferOffset;	ULONG  SenseInfoOffset;	UCHAR  Cdb[16];} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;ASSERT_SIZEOF(SCSI_PASS_THROUGH, 44);/////////////////////////////////////////////////////////////////////////////static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize){	typedef struct {		SCSI_PASS_THROUGH spt;		ULONG Filler;		UCHAR ucSenseBuf[32];		UCHAR ucDataBuf[512];	} SCSI_PASS_THROUGH_WITH_BUFFERS;	SCSI_PASS_THROUGH_WITH_BUFFERS sb;	IDEREGS * cdbregs;	unsigned int size;	DWORD num_out;	const unsigned char magic = 0xcf;	memset(&sb, 0, sizeof(sb));	sb.spt.Length = sizeof(SCSI_PASS_THROUGH);	//sb.spt.PathId = 0;	sb.spt.TargetId = 1;	//sb.spt.Lun = 0;	sb.spt.CdbLength = 10; sb.spt.SenseInfoLength = 24;	sb.spt.TimeOutValue = 10;	sb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);	size = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf);	sb.spt.DataBufferOffset = size; 	if (datasize) {		if (datasize > sizeof(sb.ucDataBuf)) {			errno = EINVAL;			return -1;		}		sb.spt.DataIn = SCSI_IOCTL_DATA_IN;		sb.spt.DataTransferLength = datasize;		size += datasize;		sb.ucDataBuf[0] = magic;	}	else {		sb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;		//sb.spt.DataTransferLength = 0;	}	// Use pseudo SCSI command followed by registers	sb.spt.Cdb[0] = SCSIOP_ATA_PASSTHROUGH;	cdbregs = (IDEREGS *)(sb.spt.Cdb+2);	*cdbregs = *regs;	if (!DeviceIoControl(hdevice, IOCTL_SCSI_PASS_THROUGH,		&sb, size, &sb, size, &num_out, NULL)) {		long err = GetLastError();		if (con->reportataioctl)			pout("  ATA via IOCTL_SCSI_PASS_THROUGH failed, Error=%ld\n", err);		errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);		return -1;	}	// Cannot check ATA status, because command does not return IDEREGS	// Check and copy data	if (datasize) {		if (   num_out != size		    || (sb.ucDataBuf[0] == magic && !nonempty(sb.ucDataBuf+1, datasize-1))) {			if (con->reportataioctl) {				pout("  ATA via IOCTL_SCSI_PASS_THROUGH output data missing (%lu)\n", num_out);				print_ide_regs_io(regs, NULL);			}			errno = EIO;			return -1;		}		memcpy(data, sb.ucDataBuf, datasize);	}	if (con->reportataioctl > 1) {		pout("  ATA via IOCTL_SCSI_PASS_THROUGH suceeded, bytes returned: %lu\n", num_out);		print_ide_regs_io(regs, NULL);	}	return 0;}/////////////////////////////////////////////////////////////////////////////// SMART IOCTL via SCSI MINIPORT ioctl// This function is handled by ATAPI port driver (atapi.sys) or by SCSI// miniport driver (via SCSI port driver scsiport.sys).// It can be used to skip the missing or broken handling of some SMART// command codes (e.g. READ_LOG) in the disk class driver (disk.sys)#define IOCTL_SCSI_MINIPORT \	CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)ASSERT_CONST(IOCTL_SCSI_MINIPORT, 0x04d008);typedef struct _SRB_IO_CONTROL {	ULONG HeaderLength;	UCHAR Signature[8];	ULONG Timeout;	ULONG ControlCode;	ULONG ReturnCode;	ULONG Length;} SRB_IO_CONTROL, *PSRB_IO_CONTROL;ASSERT_SIZEOF(SRB_IO_CONTROL, 28);#define FILE_DEVICE_SCSI 0x001b#define IOCTL_SCSI_MINIPORT_SMART_VERSION               ((FILE_DEVICE_SCSI << 16) + 0x0500)#define IOCTL_SCSI_MINIPORT_IDENTIFY                    ((FILE_DEVICE_SCSI << 16) + 0x0501)#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS          ((FILE_DEVICE_SCSI << 16) + 0x0502)#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS       ((FILE_DEVICE_SCSI << 16) + 0x0503)#define IOCTL_SCSI_MINIPORT_ENABLE_SMART                ((FILE_DEVICE_SCSI << 16) + 0x0504)#define IOCTL_SCSI_MINIPORT_DISABLE_SMART               ((FILE_DEVICE_SCSI << 16) + 0x0505)#define IOCTL_SCSI_MINIPORT_RETURN_STATUS               ((FILE_DEVICE_SCSI << 16) + 0x0506)#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE     ((FILE_DEVICE_SCSI << 16) + 0x0507)#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES       ((FILE_DEVICE_SCSI << 16) + 0x0508)#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS       ((FILE_DEVICE_SCSI << 16) + 0x0509)#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE ((FILE_DEVICE_SCSI << 16) + 0x050a)#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG              ((FILE_DEVICE_SCSI << 16) + 0x050b)#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG             ((FILE_DEVICE_SCSI << 16) + 0x050c)/////////////////////////////////////////////////////////////////////////////static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize){	// Select code	DWORD code = 0; const char * name = 0;	if (regs->bCommandReg == ATA_IDENTIFY_DEVICE) {		code = IOCTL_SCSI_MINIPORT_IDENTIFY; name = "IDENTIFY";	}	else if (regs->bCommandReg == ATA_SMART_CMD) switch (regs->bFeaturesReg) {	  case ATA_SMART_READ_VALUES:		code = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS; name = "READ_SMART_ATTRIBS"; break;	  case ATA_SMART_READ_THRESHOLDS:		code = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS; name = "READ_SMART_THRESHOLDS"; break;	  case ATA_SMART_ENABLE:		code = IOCTL_SCSI_MINIPORT_ENABLE_SMART; name = "ENABLE_SMART"; break;	  case ATA_SMART_DISABLE:		code = IOCTL_SCSI_MINIPORT_DISABLE_SMART; name = "DISABLE_SMART"; break;	  case ATA_SMART_STATUS:		code = IOCTL_SCSI_MINIPORT_RETURN_STATUS; name = "RETURN_STATUS"; break;	  case ATA_SMART_AUTOSAVE:		code = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE; name = "ENABLE_DISABLE_AUTOSAVE"; break;	//case ATA_SMART_SAVE: // obsolete since ATA-6, not used by smartmontools	//	code = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES; name = "SAVE_ATTRIBUTE_VALUES"; break;	  case ATA_SMART_IMMEDIATE_OFFLINE:		code = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS; name = "EXECUTE_OFFLINE_DIAGS"; break;	  case ATA_SMART_AUTO_OFFLINE:		code = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE; name = "ENABLE_DISABLE_AUTO_OFFLINE"; break;	  case ATA_SMART_READ_LOG_SECTOR:		code = IOCTL_SCSI_MINIPORT_READ_SMART_LOG; name = "READ_SMART_LOG"; break;	  case ATA_SMART_WRITE_LOG_SECTOR:		code = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG; name = "WRITE_SMART_LOG"; break;	}	if (!code) {		errno = ENOSYS;		return -1;	}	// Set SRB	struct {		SRB_IO_CONTROL srbc;		union {			SENDCMDINPARAMS in;			SENDCMDOUTPARAMS out;		} params;		char space[512-1];	} sb;	ASSERT_SIZEOF(sb, sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS)-1+512);	memset(&sb, 0, sizeof(sb));	unsigned size;	if (datasize > 0) {		if (datasize > (int)sizeof(sb.space)+1) {			errno = EINVAL;			return -1;		}		size = datasize;	}	else if (datasize < 0) {		if (-datasize > (int)sizeof(sb.space)+1) {			errno = EINVAL;			return -1;		}		size = -datasize;		memcpy(sb.params.in.bBuffer, data, size);	}	else if (code == IOCTL_SCSI_MINIPORT_RETURN_STATUS)		size = sizeof(IDEREGS);	else		size = 0;	sb.srbc.HeaderLength = sizeof(SRB_IO_CONTROL);	memcpy(sb.srbc.Signature, "SCSIDISK", 8); // atapi.sys	sb.srbc.Timeout = 60; // seconds	sb.srbc.ControlCode = code;	//sb.srbc.ReturnCode = 0;	sb.srbc.Length = sizeof(SENDCMDINPARAMS)-1 + size;	sb.params.in.irDriveRegs = *regs;	sb.params.in.cBufferSize = size;	// Call miniport ioctl	size += sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)-1;	DWORD num_out;	if (!DeviceIoControl(hdevice, IOCTL_SCSI_MINIPORT,		&sb, size, &sb, size, &num_out, NULL)) {		long err = GetLastError();		if (con->reportataioctl) {			pout("  IOCTL_SCSI_MINIPORT_%s failed, Error=%ld\n", name, err);			print_ide_regs_io(regs, NULL);		}		errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);		return -1;	}	// Check result	if (sb.srbc.ReturnCode) {		if (con->reportataioctl) {			pout("  IOCTL_SCSI_MINIPORT_%s failed, ReturnCode=0x%08lx\n", name, sb.srbc.ReturnCode);			print_ide_regs_io(regs, NULL);		}		errno = EIO;		return -1;	}	if (sb.params.out.DriverStatus.bDriverError) {		if (con->reportataioctl) {			pout("  IOCTL_SCSI_MINIPORT_%s failed, DriverError=0x%02x, IDEError=0x%02x\n", name,				sb.params.out.DriverStatus.bDriverError, sb.params.out.DriverStatus.bIDEError);			print_ide_regs_io(regs, NULL);		}		errno = (!sb.params.out.DriverStatus.bIDEError ? ENOSYS : EIO);		return -1;	}	if (con->reportataioctl > 1) {		pout("  IOCTL_SCSI_MINIPORT_%s suceeded, bytes returned: %lu (buffer %lu)\n", name,			num_out, sb.params.out.cBufferSize);		print_ide_regs_io(regs, (code == IOCTL_SCSI_MINIPORT_RETURN_STATUS ?		                         (const IDEREGS *)(sb.params.out.bBuffer) : 0));	}	if (datasize > 0)		memcpy(data, sb.params.out.bBuffer, datasize);	else if (datasize == 0 && code == IOCTL_SCSI_MINIPORT_RETURN_STATUS)		*regs = *(const IDEREGS *)(sb.params.out.bBuffer);	return 0;}/////////////////////////////////////////////////////////////////////////////// ATA PASS THROUGH via 3ware specific SCSI MINIPORT ioctlstatic int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize, int port){	struct {		SRB_IO_CONTROL srbc;		IDEREGS regs;		UCHAR buffer[512];	} sb;	ASSERT_SIZEOF(sb, sizeof(SRB_IO_CONTROL)+sizeof(IDEREGS)+512);	if (!(0 <= datasize && datasize <= (int)sizeof(sb.buffer) && port >= 0)) {		errno = EINVAL;		return -1;	}	memset(&sb, 0, sizeof(sb));	strcpy((char *)sb.srbc.Signature, "<3ware>");	sb.srbc.HeaderLength = sizeof(SRB_IO_CONTROL);	sb.srbc.Timeout = 60; // seconds	sb.srbc.ControlCode = 0xA0000000;	sb.srbc.ReturnCode = 0;	sb.srbc.Length = sizeof(IDEREGS) + (datasize > 0 ? datasize : 1);

⌨️ 快捷键说明

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