如何使用 ATA 命令读取磁盘的特定扇区?
How to Read particular sector of a disk using ATA command?
我想在 vc++ 中使用 ATA 命令读取磁盘的特定扇区(MBR 扇区)。我是 VC++ 的新手,所以在使用 DeviceIoControl 向磁盘发送命令时遇到问题。我提供了一个代码,我用它来使用命令 Read Sector(s)(0x20).
读出一个扇区
BOOL status = FALSE;
PATA_PASS_THROUGH_EX pATAData;
DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
BYTE Buffer[sizeof(ATA_PASS_THROUGH_EX) + 512];
DWORD bytescopied = 0;
pATAData = (ATA_PASS_THROUGH_EX*)Buffer;
ZeroMemory(pATAData,dataSize); // clears the buffer
pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->TimeOutValue = 2;
pATAData->CurrentTaskFile[1] = 0x01;
pATAData->CurrentTaskFile[2] = 0x00;
pATAData->CurrentTaskFile[3] = 0x00;
pATAData->CurrentTaskFile[4] = 0x00;
pATAData->AtaFlags =ATA_FLAGS_DATA_IN;
pATAData->CurrentTaskFile[6] = 0x20; // command Read Sector(s)(0x20)
/* sends the command to the device, **hDevice** is device handle*/
status = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, pATAData, dataSize,Buffer, dataSize, &bytescopied, NULL );
我不能理解这段代码有什么问题以及我在这里缺少什么,但它不起作用。
我在这里缺少什么?如果 PATA_PASS_THROUGH_EX 结构的参数有问题,请告知如何读取第一个扇区 (MBR)。
感谢你们的帮助。我得到了解决方案。我没有在 CurrentTaskFile 中分配设备句柄。
pATAData->CurrentTaskFile[5] = (UCHAR)hDevice;
但是 IDENTIFY_DEVICE(ECh) 命令在没有这个的情况下成功发送。我不知道这是对还是错,但这是有效的。
感谢大家的帮助。经过长时间的讨论,我发现我必须为大磁盘发送扩展命令。但现在我正在发送读取扇区 Ext(0x24 oppcode) 命令。
BOOL status = FALSE;
PATA_PASS_THROUGH_EX pATAData;
DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
BYTE Buffer[sizeof(ATA_PASS_THROUGH_EX) + 512];
DWORD bytescopied = 0;
pATAData = (ATA_PASS_THROUGH_EX*)Buffer;
ZeroMemory(pATAData,dataSize); // clears the buffer
pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->TimeOutValue = 2;
pATAData->CurrentTaskFile[0] = 0x00;
pATAData->CurrentTaskFile[1] = 0x01;
pATAData->CurrentTaskFile[2] = 0x01;
pATAData->CurrentTaskFile[3] = 0x00;
pATAData->CurrentTaskFile[4] = 0x00;
pATAData->CurrentTaskFile[5] = 0x40;
pATAData->CurrentTaskFile[7]= 0x00;
pATAData->AtaFlags =ATA_FLAGS_48BIT_COMMAND;
pATAData->PreviousTaskFile[0] = 0x00;
pATAData->PreviousTaskFile[1] = 0x00;
pATAData->PreviousTaskFile[2] = 0x00;
pATAData->PreviousTaskFile[3] = 0x00;
pATAData->PreviousTaskFile[4] = 0x00;
pATAData->PreviousTaskFile[5] = 0x04;
pATAData->PreviousTaskFile[7]= 0x00;
pATAData->CurrentTaskFile[6] = 0x24; // command Read Sector(s) Ext(0x24)
/* sends the command to the device, **hDevice** is device handle*/
status = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, pATAData, dataSize,Buffer, dataSize, &bytescopied, NULL );
但是这里也有同样的问题。命令已成功执行,但未读取任何扇区。我找不到任何错误。
谢谢大家的帮助。我得到了解决方案。我没有注意到的一点点事情。那就是 Ata Flags。我必须发送多个标志。例如。
pATAData->ataFlags = ATA_FLAGS_48BIT_COMMAND | ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN
并且还在 PreviousTaskFile[6] 中发送 ATA 命令操作码。
需要注意的几件事是
HDD的块大小是多少?它可能超过 512 字节,特别是如果它是一个大磁盘,如 (1TB...4TB)。因此,您需要相应地调整尺寸。执行EC identify ATA 命令可以看到大小是多少,然后查看生成的数据结构。
我想在 vc++ 中使用 ATA 命令读取磁盘的特定扇区(MBR 扇区)。我是 VC++ 的新手,所以在使用 DeviceIoControl 向磁盘发送命令时遇到问题。我提供了一个代码,我用它来使用命令 Read Sector(s)(0x20).
读出一个扇区 BOOL status = FALSE;
PATA_PASS_THROUGH_EX pATAData;
DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
BYTE Buffer[sizeof(ATA_PASS_THROUGH_EX) + 512];
DWORD bytescopied = 0;
pATAData = (ATA_PASS_THROUGH_EX*)Buffer;
ZeroMemory(pATAData,dataSize); // clears the buffer
pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->TimeOutValue = 2;
pATAData->CurrentTaskFile[1] = 0x01;
pATAData->CurrentTaskFile[2] = 0x00;
pATAData->CurrentTaskFile[3] = 0x00;
pATAData->CurrentTaskFile[4] = 0x00;
pATAData->AtaFlags =ATA_FLAGS_DATA_IN;
pATAData->CurrentTaskFile[6] = 0x20; // command Read Sector(s)(0x20)
/* sends the command to the device, **hDevice** is device handle*/
status = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, pATAData, dataSize,Buffer, dataSize, &bytescopied, NULL );
我不能理解这段代码有什么问题以及我在这里缺少什么,但它不起作用。 我在这里缺少什么?如果 PATA_PASS_THROUGH_EX 结构的参数有问题,请告知如何读取第一个扇区 (MBR)。
感谢你们的帮助。我得到了解决方案。我没有在 CurrentTaskFile 中分配设备句柄。
pATAData->CurrentTaskFile[5] = (UCHAR)hDevice;
但是 IDENTIFY_DEVICE(ECh) 命令在没有这个的情况下成功发送。我不知道这是对还是错,但这是有效的。
感谢大家的帮助。经过长时间的讨论,我发现我必须为大磁盘发送扩展命令。但现在我正在发送读取扇区 Ext(0x24 oppcode) 命令。
BOOL status = FALSE;
PATA_PASS_THROUGH_EX pATAData;
DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
BYTE Buffer[sizeof(ATA_PASS_THROUGH_EX) + 512];
DWORD bytescopied = 0;
pATAData = (ATA_PASS_THROUGH_EX*)Buffer;
ZeroMemory(pATAData,dataSize); // clears the buffer
pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->TimeOutValue = 2;
pATAData->CurrentTaskFile[0] = 0x00;
pATAData->CurrentTaskFile[1] = 0x01;
pATAData->CurrentTaskFile[2] = 0x01;
pATAData->CurrentTaskFile[3] = 0x00;
pATAData->CurrentTaskFile[4] = 0x00;
pATAData->CurrentTaskFile[5] = 0x40;
pATAData->CurrentTaskFile[7]= 0x00;
pATAData->AtaFlags =ATA_FLAGS_48BIT_COMMAND;
pATAData->PreviousTaskFile[0] = 0x00;
pATAData->PreviousTaskFile[1] = 0x00;
pATAData->PreviousTaskFile[2] = 0x00;
pATAData->PreviousTaskFile[3] = 0x00;
pATAData->PreviousTaskFile[4] = 0x00;
pATAData->PreviousTaskFile[5] = 0x04;
pATAData->PreviousTaskFile[7]= 0x00;
pATAData->CurrentTaskFile[6] = 0x24; // command Read Sector(s) Ext(0x24)
/* sends the command to the device, **hDevice** is device handle*/
status = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, pATAData, dataSize,Buffer, dataSize, &bytescopied, NULL );
但是这里也有同样的问题。命令已成功执行,但未读取任何扇区。我找不到任何错误。
谢谢大家的帮助。我得到了解决方案。我没有注意到的一点点事情。那就是 Ata Flags。我必须发送多个标志。例如。
pATAData->ataFlags = ATA_FLAGS_48BIT_COMMAND | ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN
并且还在 PreviousTaskFile[6] 中发送 ATA 命令操作码。 需要注意的几件事是 HDD的块大小是多少?它可能超过 512 字节,特别是如果它是一个大磁盘,如 (1TB...4TB)。因此,您需要相应地调整尺寸。执行EC identify ATA 命令可以看到大小是多少,然后查看生成的数据结构。