ATA command device IDENTIFY

5.8k views Asked by At

I am trying to identify a device using ATA_PASS_THROUGH_EX.

When I see the output buffer, it has all invalid data. Can someone help me what I am doing wrong?

#include <Windows.h>
#include <ntddscsi.h>
#include <iostream>

void main() {
    WCHAR *fileName = (WCHAR * ) "\\.\PhysicalDrive0";
    HANDLE handle = CreateFile(
       fileName, 
       GENERIC_READ | GENERIC_WRITE, //IOCTL_ATA_PASS_THROUGH requires read-write
       FILE_SHARE_READ, 
       NULL,            //no security attributes
       OPEN_EXISTING,
       0,              //flags and attributes
       NULL             //no template file
    );


    ATA_PASS_THROUGH_EX inputBuffer;
    inputBuffer.Length = sizeof(ATA_PASS_THROUGH_EX);
    inputBuffer.AtaFlags = ATA_FLAGS_DATA_IN;
    inputBuffer.DataTransferLength = 0;
    inputBuffer.DataBufferOffset = 0;

    IDEREGS *ir  = (IDEREGS *) inputBuffer.CurrentTaskFile;
    ir->bCommandReg = 0xEC; //identify device
    ir->bSectorCountReg = 1;

    unsigned int inputBufferSize = sizeof(ATA_PASS_THROUGH_EX);

    UINT8 outputBuffer[512];
    UINT32 outputBufferSize = 512;
    LPDWORD bytesReturned = 0;

    DeviceIoControl( handle, IOCTL_ATA_PASS_THROUGH_DIRECT, &inputBuffer,    inputBufferSize, &outputBuffer, outputBufferSize, bytesReturned, NULL);

    DWORD error = GetLastError();

    std::cout << outputBuffer << std::endl;
    system("pause");
}

update: When I check the error value, it is 5, which means it is an access violation. I am running in admin mode. Am I doing something wrong?

-Nick

1

There are 1 answers

2
Bukes On BEST ANSWER

I've done this using code that looks like this:

int foo()
{
    int iRet( 0 );

    // Open handle to disk.
    HANDLE hDevice( ::CreateFileW( L"\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ) );
    if( hDevice == INVALID_HANDLE_VALUE )
    {
        std::wcout << L"CreateFileW( " << sPath << L" ) failed.  LastError: " << GetLastError() << std::endl;
        return -1;
    }

    //
    // Use IOCTL_ATA_PASS_THROUGH
    //
    std::vector< UCHAR > vBuffer( sizeof( ATA_PASS_THROUGH_EX ) + sizeof( IDENTIFY_DEVICE_DATA ), 0 );
    PATA_PASS_THROUGH_EX pATARequest( reinterpret_cast< PATA_PASS_THROUGH_EX >( &vBuffer[0] ) );
    pATARequest->AtaFlags = ATA_FLAGS_DATA_IN | ATA_FLAGS_DRDY_REQUIRED;
    pATARequest->Length = sizeof( ATA_PASS_THROUGH_EX );
    pATARequest->DataBufferOffset = sizeof( ATA_PASS_THROUGH_EX );
    pATARequest->DataTransferLength = sizeof( IDENTIFY_DEVICE_DATA );
    pATARequest->TimeOutValue = 2;
    pATARequest->CurrentTaskFile[6] = ID_CMD;

    ULONG ulBytesRead;
    if( DeviceIoControl( hDevice, IOCTL_ATA_PASS_THROUGH, 
        &vBuffer[0], ULONG( vBuffer.size() ),
        &vBuffer[0], ULONG( vBuffer.size() ),
        &ulBytesRead, NULL ) == FALSE )
    {
        std::cout << "DeviceIoControl(IOCTL_ATA_PASS_THROUGH) failed.  LastError: " << GetLastError() << std::endl;
        iRet = -1;
    }
    else
    {
        // Fetch identity blob from output buffer.
        PIDENTIFY_DEVICE_DATA pIdentityBlob( reinterpret_cast< PIDENTIFY_DEVICE_DATA >( &vBuffer[ sizeof( ATA_PASS_THROUGH_EX ) ] ) );
    }

    CloseHandle( hDevice );

    return iRet;
}

Note that this must be run from an administrator account or elevated context.