用于阅读原始CD-ROM数据的Windows IOCTL不返回纠错数据

gwo2fgha  于 7个月前  发布在  Windows
关注(0)|答案(1)|浏览(53)

我试图使一个程序,提取原始部门的数据,从光盘的各种类型,开始与CD(数据和音频)。
这没什么特别的,这个概念本身很好,可以在具有类似IOCTL的Linux上工作。
我在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;
}

字符串
输出和IsoBuster扇区视图之间的并排比较:x1c 0d1x
供参考的任何人来这里在未来,下一个最好的事情,让这工作肯定是使用SPTI如这里所述:How to issue a READ CD command to a CD-ROM drive in Windows?。我不想考虑这是一个答案,为什么Windows IOCTL不工作,虽然(省略EDC)!

sdnqo3pr

sdnqo3pr1#

答案可能有点晚,但在这里,简短的一个:你不能使用IOCTL_CDROM_RAW_READ控制代码以原始的方式读取模式1轨道。
冗长的回答:当你看到x_size时,你会发现函数没有读取你期望的数据量。你期望的是CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE,即2744,但是你只收到了2456。这个事实的另一个泄露是在你的屏幕截图中显示的0xCD字符。Visual C在调试模式下将内存中的值设置为0xCD,以便于调试。所以这部分数组可能根本没有被写入。
那么你实际上从函数调用中接收到了哪些数据呢?在我看来,你收到了12字节的同步数据,然后是4字节的扇区头(3字节用于地址,在您的情况下为0x00 0x02 0x00,1字节用于模式,在您的情况下为0x01),然后是2048字节的用户数据,然后是296字节的C2错误信息,然后是96字节的子码。你可以很容易地识别子码,因为MSB在所有字节中都设置为1,这是CD上每个轨道开始的情况。
我没有成功地找到一个文档,关于这个控制代码返回的C2错误信息的确切含义。但是因为它有足够的空间来容纳原始扇区的每个字节的一位,我的猜测是,每一位都表示在C2纠错之后,相应的字节是否仍然可能包含错误。如果只返回数据磁道的用户数据,这个假设是否仍然成立,更不用说这些信息是毫无意义的,因为函数返回的用户数据应该已经被随后的P和Q奇偶校验纠正了,即使它最初可能包含C2错误。
尝试读取模式1数据时,其他磁道模式的行为如下:

  • YellowMode2XAForm2将失败。
  • RawWithC2RawWithSubCode的行为类似于RawWithC2AndSubCode
  • CDDA将产生乱码数据。

另外,请注意,如果printf模式的值小于0x10,则每个字符只打印一位数字。如果您希望始终打印两位数字,则"%02hhX"将是合适的。

相关问题