Winapi 如何取回";跟踪信息“;从带有DeviceIOControl()的CD?
我正在尝试将DeviceIoControl()与SCSI_PASS_THROUGH_DIRECT一起使用,以便获取曲目信息 此代码“有效”,但通过将ScsiStatus设置为2返回。Winapi 如何取回";跟踪信息“;从带有DeviceIOControl()的CD?,winapi,ioctl,scsi,cdda,Winapi,Ioctl,Scsi,Cdda,我正在尝试将DeviceIoControl()与SCSI_PASS_THROUGH_DIRECT一起使用,以便获取曲目信息 此代码“有效”,但通过将ScsiStatus设置为2返回。 关于“跟踪”数据字段的大小,似乎存在相互冲突的文档。mmc文档说它有1位长,但是在网络上我发现它有2位长 然而,无论如何,它都失败了 我整天绞尽脑汁,什么都没有。有人明白吗 #define kSCSICmd_READ_TRACK_INFORMATION 0x52 // Read Track Information
关于“跟踪”数据字段的大小,似乎存在相互冲突的文档。mmc文档说它有1位长,但是在网络上我发现它有2位长 然而,无论如何,它都失败了 我整天绞尽脑汁,什么都没有。有人明白吗
#define kSCSICmd_READ_TRACK_INFORMATION 0x52
// Read Track Information Format
struct CDTrackInfo
{
UInt16 dataLength;
UInt8 trackNumberLSB;
UInt8 sessionNumberLSB;
UInt8 reserved;
#ifdef __LITTLE_ENDIAN__
UInt8 trackMode:4;
UInt8 copy:1;
UInt8 damage:1;
UInt8 reserved3:2;
UInt8 dataMode:4;
UInt8 fixedPacket:1;
UInt8 packet:1;
UInt8 blank:1;
UInt8 reservedTrack:1;
UInt8 nextWritableAddressValid:1;
UInt8 lastRecordedAddressValid:1;
UInt8 reserved5:6;
#else /* !__LITTLE_ENDIAN__ */
UInt8 reserved3:2;
UInt8 damage:1;
UInt8 copy:1;
UInt8 trackMode:4;
UInt8 reservedTrack:1;
UInt8 blank:1;
UInt8 packet:1;
UInt8 fixedPacket:1;
UInt8 dataMode:4;
UInt8 reserved5:6;
UInt8 lastRecordedAddressValid:1;
UInt8 nextWritableAddressValid:1;
#endif /* !__LITTLE_ENDIAN__ */
UInt32 trackStartAddress;
UInt32 nextWritableAddress;
UInt32 freeBlocks;
UInt32 fixedPacketSize;
UInt32 trackSize;
UInt32 lastRecordedAddress;
UInt8 trackNumberMSB;
UInt8 sessionNumberMSB;
UInt8 reserved6;
UInt8 reserved7;
};
typedef struct CDTrackInfo CDTrackInfo;
/*
from mmc r10a
6.2.8 Read CD
table 140
page 110
*/
typedef struct {
UInt8 op_code;
#if TARGET_RT_BIG_ENDIAN
UInt8 reserved0 : 7; // <-- possibly 6?
UInt8 track : 1; // <-- possibly 2?
#else
UInt8 track : 1;
UInt8 reserved0 : 7;
#endif
UInt32 lba_or_track_number;
UInt8 reserved1;
UInt16 alloc_len;
UInt8 control;
} SCSICommandDescriptorBlock_ReadTrackInfo;
OSStatus CRawDiscReader::GetTrackInfo(int trackI, CDTrackInfo *trackInfoP)
{
OSStatus err = noErr;
if (i_deviceH == NULL) {
ERR(Open());
}
if (!err) {
SCSI_PASS_THROUGH_DIRECT pass_thru = { 0 };
SCSICommandDescriptorBlock_ReadTrackInfo& cdb(*(SCSICommandDescriptorBlock_ReadTrackInfo *)&pass_thru.Cdb[0]);
CF_ASSERT(sizeof(cdb) == kSCSICDBSize_10Byte);
structclr(*trackInfoP);
cdb.op_code = kSCSICmd_READ_TRACK_INFORMATION;
cdb.track = true;
cdb.lba_or_track_number = trackI;
cdb.alloc_len = sizeof(CDTrackInfo);
DWORD numRead = 0;
pass_thru.Length = sizeof(pass_thru);
pass_thru.CdbLength = sizeof(cdb);
pass_thru.DataIn = SCSI_IOCTL_DATA_IN;
pass_thru.TimeOutValue = kTimeOutSeconds;
pass_thru.DataBuffer = (PVOID)trackInfoP;
pass_thru.DataTransferLength = cdb.alloc_len;
if (!DeviceIoControl(
i_deviceH,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
(PVOID)&pass_thru,
(DWORD)sizeof(pass_thru),
(PVOID)&pass_thru,
(DWORD)sizeof(pass_thru),
&numRead, NULL)
) {
err = GetLastError();
LogErr("reading CD:", err);
} else if (numRead != pass_thru.Length) {
err = GetLastError();
LogErr("reading CD:", err);
err = noErr;
}
}
if (err && err != ERR_Already_Reported) {
#if OPT_WINOS
if (err == ERROR_INVALID_PARAMETER) {
err = paramErr;
} else
#endif
{
err = EIO;
}
}
return err;
}
#定义kSCSICmd_READ_TRACK_信息0x52
//读取轨道信息格式
结构CDTrackInfo
{
UInt16数据长度;
UInt8轨道号SB;
UInt8会议编号SB;
UInt8保留;
#伊夫迪夫·利特尔·恩迪安__
UInt8轨道模式:4;
UInt8份:1份;
UInt8损伤:1;
UInt8储备3:2;
UInt8数据模式:4;
UInt8固定数据包:1;
UInt8数据包:1;
UInt8空白:1;
UInt8预留轨道:1;
UInt8 nextWritableAddressValid:1;
UInt8 lastRecordedAddressValid:1;
UInt8预留5:6;
#else/*!\uuu LITTLE\uEndian\uu*/
UInt8储备3:2;
UInt8损伤:1;
UInt8份:1份;
UInt8轨道模式:4;
UInt8预留轨道:1;
UInt8空白:1;
UInt8数据包:1;
UInt8固定数据包:1;
UInt8数据模式:4;
UInt8预留5:6;
UInt8 lastRecordedAddressValid:1;
UInt8 nextWritableAddressValid:1;
#endif/*!\uuu LITTLE\u ENDIAN\uu*/
UInt32轨星服饰;
UInt32下一个可写地址;
UInt32自由区;
UInt32固定包装尺寸;
UInt32轨道尺寸;
UInt32上次记录的地址;
UInt8轨道编号MSB;
UInt8会议编号msb;
UInt8储备6;
UInt8保留7;
};
类型定义结构CDTrackInfo CDTrackInfo;
/*
来自mmc r10a
6.2.8读取CD
表140
第110页
*/
类型定义结构{
UInt8操作单元代码;
#如果目标是大的
UInt8 reserved0:7;//答案似乎是“不要使用IOCTL\u SCSI\u PASS\u THROUGH\u DIRECT”
也许我是在“艰难地”做这件事。我看到msdev网站上有一个“TRACK_INFORMATION2”结构,这正是我想要的,但我就是找不到关于如何获取它的信息。我意识到lba_或_TRACK_number和alloc_len是big-endian。我在代码中已经修复了它,但没有用:仍然不起作用
OSStatus CRawDiscReader::GetTrackInfo(IDiscRecorder2Ex *discP, int trackI, CDTrackInfo *trackInfoP)
{
OSStatus err = noErr;
HRESULT resultL = 0;
BYTE *dataP = NULL;
ULONG_IMAPI2_TRACK_INFORMATION outSize = 0;
structclr(*trackInfoP);
resultL = discP->GetTrackInformation(
trackI,
IMAPI_READ_TRACK_ADDRESS_TYPE_TRACK,
&dataP, &outSize);
XTE(TrapError("GetTrackInformation", resultL));
if (!err) {
CDTrackInfo *returnInfoP = (CDTrackInfo *)dataP;
*trackInfoP = *returnInfoP;
CoTaskMemFree(dataP);
dataP = NULL;
SwapTrackInfo(trackInfoP);
}
return err;
}