2015-05-08 5 views
1

Я хочу прочитать конкретный сектор (сектор MBR) диска, используя команды ATA в vC++. Я новичок в VC++, поэтому перед отправкой команды на диск я сталкиваюсь с проблемой, используя DeviceIoControl. Я предоставляю код, который я использую, чтобы читать сектор, используя команду Read Sector (s) (0x20).Как прочитать конкретный сектор диска с помощью команды ATA?

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); 

Я не могу undersatnd, что неправильно в этом коде и то, что я здесь отсутствует, но это не работает. Что мне здесь не хватает? Если есть проблема с параметрами структуры PATA_PASS_THROUGH_EX, чем сказать, как читать первый сектор (MBR).

+1

Вы вызвали GetLastError, чтобы понять, почему это не удалось? –

+0

Не уверен, что это применимо, поскольку вы не показываете код для открытия устройства, но вы можете взглянуть в любом случае. http://stackoverflow.com/questions/3362037/problem-reading-mbr-with-deviceiocontrol-function –

+1

Почему у этого есть тег 'qt'? Вы можете получить лучшую помощь с другими тегами, такими как: 'device',' hard-drive' или 'sata'. Кроме того, какая ошибка вы получаете? – titusjan

ответ

0

Спасибо всем за помощь. Я получил решение. Немного, чего я не заметил. Это Ата Флаги. Мне нужно отправить несколько флагов. Например.

pATAData->ataFlags = ATA_FLAGS_48BIT_COMMAND | ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN 

, а также отправьте команду Opa Code ATA в PreviousTaskFile [6]. И несколько вещей, которые нужно заметить, это Каков размер блока на жестком диске? Это может быть больше 512 байтов, особенно если это большой диск (1TB ... 4TB). Таким образом, вам необходимо соответствующим образом отрегулировать размеры. Вы можете видеть, какой размер, выполнив EC, идентифицирует команду ATA, а затем посмотрите на результирующую структуру данных.

0

Спасибо за помощь, ребята. Я получил решение. Я не назначал ручку устройства в CurrentTaskFile.

pATAData->CurrentTaskFile[5] = (UCHAR)hDevice; 

Но команда IDENTIFY_DEVICE (ECh) была успешно отправлена ​​без этого. Я не знаю, что это правильно или неправильно, но это работает.

+0

Теперь я могу читать сектора, но теперь мне приходится читать большой диск с памятью (до 4 ТБ). Кто-нибудь может мне помочь, как отправить данные в CurrentTaskFile [], чтобы прочитать большой космический диск. Поскольку CurrentTaskFile [] является массивом типа UCHAR. Если я хочу прочитать последний сектор с диска 1 ТБ. – Sam

+0

Вам необходимо использовать расширенные команды (EXT) вместе с PreviousTaskFile [] –

+0

Относительно CurrentTaskFile [5], ака реестра «Устройство». Старая спецификация ATA зарезервировала бит 6 этого регистра для «режима LBA». Это означает, что вы должны установить этот бит для включения режима «LBA» и очистить его от использования режима «CHS».Чтобы все было просто, просто используйте режим LBA, установив этот регистр в 0x40. Причина, по которой команда IDENTIFY_DEVICE работает, заключается в том, что она не имеет доступа к каким-либо секторам, поэтому ей не нужен режим LBA или CHS. –

0

Спасибо, ребята, за вашу помощь. После долгого обсуждения я обнаружил, что мне приходится отправлять расширенные команды для большого диска. Но теперь я отправляю команду Read Sector (s) 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); 

Но вот эта же проблема. команда выполнена успешно, но она не читает ни одного сектора. Я не могу найти никакой ошибки.

+0

Существует два типа ошибок, которые необходимо учитывать при использовании DeviceIoControl. (1) Первый из DeviceIoControl говорит вам, успешно ли отправлена ​​команда на устройство. (2) Второй - это устройство само собой. В этом случае - диск SATA или PATA. Каждая команда возвращает статус, указывающий, успешна ли команда или нет. Это будет в регистре «Статус» (CurrentTaskFile [7]) и в регистре «Ошибка» (CurrentTaskFile [0]). Регистр «Статус» сообщает вам, есть ли ошибка, и регистр «Ошибка» сообщит вам тип ошибки. –

+0

У меня не было ошибок. Все выглядит нормально, но буфер не считывается с диска. Регистр «Status» (CurrentTaskFile [7] и «Error» (CurrentTaskFile [0]) равен нулю. GetLastError() извлекает код (0x57) (ERROR_INVALID_PARAMETER). DeviceIoControl возвращает TRUE, но выходной буфер пуст. Значение параметра lpBytesReturned 40 (точно размер структуры PATA_PASS_THROUGH_EX), это означает, что данные не считываются с диска. – Sam

+0

Регистр ошибок может быть нулевым, но в регистре состояния должен быть бит бит «Устройство готов», бит которого равен одному (бит 6). Не верю в статус возврата DeviceIoControl(). Похоже, что GetLastError() говорит правду. –