Read and Write to PhysicalDrive0 using DeviceIoControl

165 views Asked by At

I have this code, that should make changes to the PhysicalDrive0, so I try to read from it, change the buffer and write it back.

Read:

HANDLE device = CreateFileW(L"\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, nullptr);
if (device == INVALID_HANDLE_VALUE) {
    std::cerr << "Failed to open the drive. Error code: " << GetLastError() << std::endl;
    return 1;
}

STORAGE_PROPERTY_QUERY storage_query;
storage_query.PropertyId = StorageDeviceProperty;
storage_query.QueryType = PropertyStandardQuery;

STORAGE_DESCRIPTOR_HEADER storage_descriptor;

DWORD bytes_returned = 0;
if (!DeviceIoControl(device, IOCTL_STORAGE_QUERY_PROPERTY, &storage_query, sizeof(STORAGE_PROPERTY_QUERY),
                     &storage_descriptor, sizeof(STORAGE_DESCRIPTOR_HEADER), &bytes_returned, nullptr)) {
    std::cerr << "Failed to query storage property. Error code: " << GetLastError() << std::endl;
    CloseHandle(device);
    return 2;
}

DWORD buffer_size = storage_descriptor.Size;
BYTE* buffer = new BYTE[buffer_size];

if (!DeviceIoControl(device, IOCTL_STORAGE_QUERY_PROPERTY, &storage_query, sizeof(STORAGE_PROPERTY_QUERY),
                     buffer, buffer_size, &bytes_returned, nullptr)) {
    std::cerr << "Failed to query storage property again. Error code: " << GetLastError() << std::endl;
    CloseHandle(device);
    delete[] buffer;
    return 3;
}

Then I want to change some things on the buffer. And then write it back:

if (!DeviceIoControl(device, IOCTL_STORAGE_SET_PROPERTY, buffer, buffer_size, nullptr, 0, nullptr, nullptr)) {
    unsigned long code = GetLastError();
    std::cerr << "Failed to write to the drive. Error code: " << code << std::endl;
    CloseHandle(device);
    delete[] buffer;
    return 5;
}

std::cout << "Write successful." << std::endl;

CloseHandle(device);
delete[] buffer;

EDIT 1: Also tried this:

ULONG new_buffer_size = sizeof(STORAGE_PROPERTY_SET) + buffer_size;
BYTE* new_buffer = new BYTE[new_buffer_size];

STORAGE_PROPERTY_SET set;
set.SetType = PropertyStandardSet;
set.PropertyId = StorageDeviceProperty;

memcpy(new_buffer, &set, sizeof(STORAGE_PROPERTY_SET));
memcpy(new_buffer + sizeof(STORAGE_PROPERTY_SET), buffer, buffer_size);

// Write the buffer combined with STORAGE_PROPERTY_SET and STORAGE_DEVICE_DESCRIPTOR (buffer), I also tried with no output buffer, but same issue
if (!DeviceIoControl(device, IOCTL_STORAGE_SET_PROPERTY, new_buffer, new_buffer_size, new_buffer, new_buffer_size, &bytes_returned, nullptr)) {
    DWORD code = GetLastError();
    std::cerr << "Failed to write to the drive. Error code: " << code << std::endl;
    CloseHandle(device);
    delete[] buffer;
    delete[] new_buffer;
    return 5;
}

std::cout << "Write successful." << std::endl;

CloseHandle(device);
delete[] buffer;
delete[] new_buffer;

EDIT 2: Also tried this:

ULONG new_buffer_size = sizeof(STORAGE_PROPERTY_SET) + buffer_size;
BYTE* new_buffer = new BYTE[new_buffer_size];

STORAGE_PROPERTY_SET set;
set.SetType = PropertyStandardSet;
set.PropertyId = StorageDeviceProperty;

memcpy(new_buffer, &set, sizeof(STORAGE_PROPERTY_SET));
memcpy(&((STORAGE_PROPERTY_SET*)new_buffer)->AdditionalParameters[0], buffer, buffer_size);

// Write the buffer combined with STORAGE_PROPERTY_SET and STORAGE_DEVICE_DESCRIPTOR (buffer), I also tried with no output buffer, but same issue
if (!DeviceIoControl(device, IOCTL_STORAGE_SET_PROPERTY, new_buffer, new_buffer_size, new_buffer, new_buffer_size, &bytes_returned, nullptr)) {
    DWORD code = GetLastError();
    std::cerr << "Failed to write to the drive. Error code: " << code << std::endl;
    CloseHandle(device);
    delete[] buffer;
    delete[] new_buffer;
    return 5;
}

std::cout << "Write successful." << std::endl;

CloseHandle(device);
delete[] buffer;
delete[] new_buffer;

But the IOCTL_STORAGE_SET_PROPERTY device io control operation fails with code 1. Why are the function parameters invalid?

0

There are 0 answers