我正在尝试制作一个程序,从CD(数据和音频)开始从各种类型的光盘中提取原始扇区数据。
这没什么特别的,这个概念本身很好,可以在Linux上使用类似的IOCTL。
我在Windows上遇到的问题是ECC / EDC数据不正确(基本上已清零)。您可以通过比较命令返回的内容与其他程序输出(如IsoBuster或ImgBurn(或在Linux上使用等效命令))来查看。
这些数据是否因某些原因导致Windows安全策略受到影响?还是一个驱动程序错误?
请注意,我在Windows 10上看到这种情况。在以管理员身份运行时,我得到相同的结果。
要清楚哪些数据受到影响,请参阅此处的好表: https://en.wikipedia.org/wiki/CD-ROM#CD-ROM_format。在普通数据CD(模式1)上,它是2352扇区的最后288个字节。
用于演示此问题的代码:
#include <windows.h>
#include <winioctl.h> // From the Win32 SDK \Mstools\Include
#include "ntddcdrm.h" // From the Windows NT DDK \Ddk\Src\Storage\Inc
int main()
{
HANDLE hCD = CreateFile(L"\\\\.\\D:", GENERIC_READ,
FILE_SHARE_READ,
0, OPEN_EXISTING, 0,
0);
//the sector to read
int lba = 0;
RAW_READ_INFO rawReadInfo;
rawReadInfo.DiskOffset.QuadPart = (long long)lba * 2048;
rawReadInfo.SectorCount = 1;
rawReadInfo.TrackMode = RawWithC2AndSubCode;
DWORD x_size;
char* buf = (char*)malloc(CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE);
int rc = DeviceIoControl(hCD, IOCTL_CDROM_RAW_READ,
&rawReadInfo, sizeof(rawReadInfo),
buf, CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE,
&x_size, NULL);
printf("rc: %d\n", rc);
printf("x_size: %d\n", x_size);
int i;
printf("\nSync, Addr, Mode (16 bytes)\n");
for (i = 0; i < 16; i++) {
printf("%hhX", buf[i]); //this data comes back fine
}
printf("\nData (2048 bytes)\n");
for (i = 16; i < 16+2048; i++) {
printf("%hhX", buf[i]); //this data comes back fine
}
printf("\nED, RZ, EC (288 bytes)\n");
for (i = 16 + 2048; i < 16 + 2048 + 288; i++) {
printf("%hhX", buf[i]); //this data comes back wrong
}
printf("\nC2, Sub (392 bytes)\n");
for (i = 16 + 2048 + 288; i < 2744; i++) {
printf("%hhX", buf[i]); //not sure if this is right or not
}
//dumb code to block terminal from closing
char str[80];
fgets(str, 10, stdin);
return 0;
}
对于今后来到这里的任何人来说,下一个最好的方法就是使用SPTI,如下所述:How to issue a READ CD command to a CD-ROM drive in Windows?。我不想考虑为什么Windows IOCTL无法正常工作(省略EDC)的答案!