1

我正在尝试使用 D 将 scsi ReadCapacity16 (0x9E) 发送到 Windows 上的卷。CDB 是规范的,我的 ReadCapacity16 在 Linux 上工作,scsi Inquiries 在 Windows 上工作。只有 Windows 上的非查询调用无法使用 Windows 内核中的“不正确的功能”。

既然只有查询有效,那么通过 Windows 内核发送非查询有什么技巧吗?关于让它工作的任何提示?我研究了几个星期并没有解决这个问题。

这是 CDB 的一个示例:

\\.\physicaldrive0 CDB 缓冲区内容:9e 10 00 00 00 00 00 00 - 00 00 00 00 00 20 00 00 sgio.exceptions.IoctlFailException@sgio\exceptions.d(13):ioctl 错误代码为 1。函数不正确。

这里是将 CDB 复制到 DeviceIoControl 调用的缓冲区的位置,这与成功发送 Inquiry 命令(但 readcap 失败)的代码路径相同。github中的代码粘贴在下面:

void sgio_execute(ubyte[] cdb_buf, ubyte[] dataout_buf, ubyte[] datain_buf, ubyte[] sense_buf)
   version (Windows)
   {
      const uint SENSE_LENGTH = 196;
      ubyte[512] iobuffer = 0;
      DWORD amountTransferred = -1;
      SCSI_PASS_THROUGH_DIRECT scsiPassThrough = {0};
      scsiPassThrough.Cdb[] = 0;
      uint size = cast(uint)((cdb_buf.length <= scsiPassThrough.Cdb.length ?
                        cdb_buf.length : scsiPassThrough.Cdb.length));

      scsiPassThrough.Cdb[0..size] = cdb_buf[0..size];
      scsiPassThrough.Length             = SCSI_PASS_THROUGH_DIRECT.sizeof;
      scsiPassThrough.ScsiStatus         = 0x00;
      scsiPassThrough.TimeOutValue       = 0x40;
      scsiPassThrough.CdbLength          = cast(ubyte)(size);
      scsiPassThrough.SenseInfoOffset    = SCSI_PASS_THROUGH_DIRECT.sizeof;
      scsiPassThrough.SenseInfoLength    = SENSE_LENGTH;
      scsiPassThrough.DataIn             = SCSI_IOCTL_DATA_IN;
      scsiPassThrough.DataBuffer         = datain_buf.ptr;
      scsiPassThrough.DataTransferLength = bigEndianToNative!ushort(cast(ubyte[2]) cdb_buf[3..5]);

      int status = DeviceIoControl( m_device,
                                    IOCTL_SCSI_PASS_THROUGH_DIRECT,
                                    &scsiPassThrough,
                                    iobuffer.length, //scsiPassThrough.sizeof,
                                    &iobuffer,
                                    iobuffer.length,
                                    &amountTransferred,
                                    null);
      if (status == 0)
      {
         int errorCode = GetLastError();
         // build error message ...
         throw new IoctlFailException(exceptionMessage);
      }
   }
}
4

1 回答 1

1

仔细阅读Windows SCSI_PASS_THROUGH_DIRECT 结构文档,我注意到了这一点:

DataTransferLength:表示数据缓冲区的大小(以字节为单位)。许多设备传输预定义长度的数据块。DataTransferLength 中的值必须是设备指定的此预定义最小长度的整数倍。如果发生欠载,微型端口驱动程序必须将此成员更新为实际传输的字节数。

通过增加 datain_buffer 的大小,我将代码更改为对 DataTransferLength 使用 512 字节,现在代码可以正常工作了。

于 2015-06-24T08:35:53.203 回答