どうもありがとうございました。
アドバイスのおかげで一応何とかそれらしい手法に辿り着きました。
しかし、以下のようなコードで転送量(BUF_SIZE)をある値以上に大きくすると
素早く返ってきてScsiStatus=0になるのですが、
ある値以下にするとえらく遅く戻ってきてScsiStatus=2になります。
遅い場合、TimOutValueを5秒とかに設定していると
DeviceIoControl()がセマフォタイムアウトエラー(121)で失敗します。
いったい何が起こっているのでしょうか?
転送量が少ない方が遅いというのが謎です。
ちなみに「ある値」はコロコロ変わるようです。(0x92eだと思ったら0x7feになってた・・・)
それと、そもそもScsiStatusは0だとSS_PENDINGで結果が返ってこない状態だと思うのですが、
SPTIは同期的に働くのだというのでこれも不可思議です。
しかもSS_PENDINGなのにセクタデータはちゃんとバッファに入るようです。
またScsiStatus=2でもこれはSS_ABORTEDでエラーだと思うのですが、
これもセクタデータはちゃんとバッファに入るようです。
324 :
296:2006/10/13(金) 00:41:52
#include <windows.h>
#include "devioctl.h"
#include "ntddscsi.h"
#include "spti.h"
main(){
HANDLE hDev;
hDev = CreateFileA("\\\\.\\E:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDev == INVALID_HANDLE_VALUE){
printf("CreateFile() failed\n");
exit(-1);
}
//#define BUF_SIZE 0xc00 //素早い
#define BUF_SIZE 0x10 //遅い
BYTE _rgbBuf[BUF_SIZE + 0x0f];
BYTE *rgbBuf = (BYTE *)(((DWORD)_rgbBuf + 0x0f) & 0xfffffff0);
memset(rgbBuf, -1, BUF_SIZE);
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
memset(&sptdwb, 0, sizeof(sptdwb));
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.CdbLength = 12;
325 :
296:2006/10/13(金) 00:42:22
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptdwb.sptd.SenseInfoLength = 14;
sptdwb.sptd.DataTransferLength = BUF_SIZE;
sptdwb.sptd.TimeOutValue = 30;
sptdwb.sptd.DataBuffer = rgbBuf;
sptdwb.sptd.SenseInfoOffset = (BYTE *)&sptdwb.ucSenseBuf - (BYTE *)&sptdwb;
sptdwb.sptd.Cdb[0] = 0xbe; // Read CD
sptdwb.sptd.Cdb[8] = 1;
sptdwb.sptd.Cdb[9] = 0x10;
BOOL bRes;
DWORD dwResCnt;
printf("rgbBuf[0] = %02X\n", rgbBuf[0]);
bRes = DeviceIoControl(hDev, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptdwb, sizeof(sptdwb), &sptdwb, sizeof(sptdwb), &dwResCnt, NULL);
if (!bRes){
printf("DeviceIoControl() failed\n");
exit(-1);
}
printf("rgbBuf[0] = %02X\n", rgbBuf[0]);
printf("sptdwb.sptd.ScsiStatus = 0x%08X\n", sptdwb.sptd.ScsiStatus);
}