请教各位高手,小弟最近需要完成windows下执行磁盘ATA command security eraser 的命令,调用DeviceIoControl() API,参数为IOCTL_ATA_PASS_THROUGH,已经确保磁盘security状态为非frozen状态,发送各security命令时总是出错,但该代码如果执行其它ATA command则没有错误(非security命令,如IDENTITY,SMART),相关代码如下:#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
#define IOCTL_ATA_PASS_THROUGH   CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)typedef struct
{
  ATA_PASS_THROUGH_EX apt;
  ULONG Filler;
  UCHAR ucDataBuf[max_sectors * 512];
}ATA_PASS_THROUGH_WITH_BUFFERS, *PATA_PASS_THROUGH_WITH_BUFFERS;#define  IDE_ATA_SECURITY_DISABLE_PASSWORD   0xF6
#define  IDE_ATA_SECURITY_ERASE_PREPARE      0xF3
#define  IDE_ATA_SECURITY_ERASE_UNIT         0xF4
#define  IDE_ATA_SECURITY_FREEZE_LOCK        0xF5
#define  IDE_ATA_SECURITY_SET_PASSWORD       0xF1
#define  IDE_ATA_SECURITY_SECURITY_UNLOCK    0xF2typedef 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 _ATA_PASS_THROUGH_EX {
  USHORT Length;
  USHORT AtaFlags;
  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;bSECmd = IDE_ATA_SECURITY_SET_PASSWORD;IDEREGS *regs = (IDEREGS*)malloc(sizeof(IDEREGS)); 
regs->bSectorCountReg = 1;
regs->bSectorNumberReg = 1;
regs->bCylLowReg = 0;
regs->bFeaturesReg = 0;
regs->bCylHighReg = 0;
        
// Compute the drive number.
regs->bDriveHeadReg = 0xA0 | ((drive & 1) << 4);
        
// The command can either be IDE identify or ATAPI identify.
regs->bCommandReg = bSECmd;
      
char sec_pwd[33];
memset(sec_pwd, 0 , 33);
strcpy(sec_pwd,"passwd");
int iATARegsSize;
DWORD dwReturned = 0;
bool bRet;
unsigned int uSize = FIELD_OFFSET(ATA_PASS_THROUGH_WITH_BUFFERS, ucDataBuf);/////////////////////////////////////////////////////////////////////
ATA_PASS_THROUGH_WITH_BUFFERS APT;
memset(&APT, 0, sizeof(APT));
APT.ucDataBuf[0] = 0x00;//master
APT.ucDataBuf[1] = 0x00;//highmemcpy(APT.ucDataBuf+2,sec_pwd,32);
APT.ucDataBuf[34] = 0x11;
APT.ucDataBuf[35] = 0xFF;APT.apt.AtaFlags = ATA_FLAGS_DATA_OUT; //Data IN
APT.apt.Length = sizeof(ATA_PASS_THROUGH_EX);
APT.apt.ReservedAsUchar= 0;
APT.apt.DataTransferLength = 512;
APT.apt.TimeOutValue = 10;
APT.apt.ReservedAsUlong = 0;
        
APT.apt.DataBufferOffset = uSize;
memset(&APT.apt.PreviousTaskFile,0,sizeof(APT.apt. PreviousTaskFile));
memset(&APT.apt.CurrentTaskFile,0,sizeof(APT.apt.CurrentTaskFile));
        
memcpy(APT.apt.CurrentTaskFile, regs, sizeof(IDEREGS));
        
iATARegsSize = uSize + APT.apt.DataTransferLength;
        
IDEREGS *ctfregs = (IDEREGS *)APT.apt.CurrentTaskFile;
IDEREGS *ptfregs = (IDEREGS *)APT.apt.PreviousTaskFile;
*ctfregs = *regs;
      
bRet = DeviceIoControl(hPhysicalDriveIOCTL, IOCTL_ATA_PASS_THROUGH , &APT, iATARegsSize, &APT, iATARegsSize, &dwReturned, FALSE);