DeviceIoRequest для получения STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR для USB-накопителя завершается ошибкой

#winapi #storage #ioctl

Вопрос:

Я пытаюсь получить STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR устройства хранения данных, запросив IOCTL_STORAGE_QUERY_PROPERTY IOCTL с правильно заполненной STORAGE_PROPERTY_QUERY структурой. Это отлично работает для хранения без USB, но для USB-накопителя это не работает ERROR_INVALID_FUNCTION .

Я также проверил, существует ли это свойство, установив значение QueryType PropertyExistsQuery и не предоставляя выходной буфер. Оказывается, он существует. Я не понимаю, почему это не сработает ERROR_INVALID_FUNCTION .

Вот сокращенная версия кода, который я использовал (без обработки ошибок и т. Д.):

 #include <Windows.h>
#include <SetupAPI.h>
#include <stdio.h>

int main(void){
    HDEVINFO diskClassDevs;
    diskClassDevs = SetupDiGetClassDevs(amp;GUID_DEVINTERFACE_DISK,
                                        NULL,
                                        NULL,
                                        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    DWORD devIdx = 0;
    SP_DEVICE_INTERFACE_DATA devInterfaceData;
    devInterfaceData.cbSize = sizeof(devInterfaceData);
    while(SetupDiEnumDeviceInterfaces(diskClassDevs,
                                      NULL,
                                      amp;GUID_DEVINTERFACE_DISK,
                                      devIdx,
                                      amp;devInterfaceData)){
        devIdx  ;

        DWORD requiredSize;
        DWORD result = SetupDiGetDeviceInterfaceDetail(diskClassDevs,
                                                       amp;devInterfaceData,
                                                       NULL,
                                                       0,
                                                       amp;requiredSize,
                                                       0);
        SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetailData;
        devInterfaceDetailData = malloc(requiredSize);
        devInterfaceDetailData->cbSize = sizeof(*devInterfaceDetailData);
        SP_DEVINFO_DATA devInfoData;
        devInfoData.cbSize = sizeof(devInfoData);
        result = SetupDiGetDeviceInterfaceDetail(diskClassDevs,
                                                 amp;devInterfaceData,
                                                 devInterfaceDetailData,
                                                 requiredSize,
                                                 NULL,
                                                 amp;devInfoData);

        HANDLE devHandle;
        devHandle = CreateFile(devInterfaceDetailData->DevicePath,
                               GENERIC_READ,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL,
                               OPEN_EXISTING,
                               0,
                               NULL);

        STORAGE_DESCRIPTOR_HEADER diskDescriptorSizeInfo;
        diskDescriptorSizeInfo.Version = sizeof(diskDescriptorSizeInfo);

        STORAGE_PROPERTY_QUERY diskProperty;
        diskProperty.QueryType = PropertyStandardQuery;
        diskProperty.PropertyId = StorageDeviceProperty;
        result = DeviceIoControl(devHandle,
                                 IOCTL_STORAGE_QUERY_PROPERTY,
                                 amp;diskProperty,
                                 sizeof(diskProperty),
                                 amp;diskDescriptorSizeInfo,
                                 sizeof(diskDescriptorSizeInfo),
                                 amp;requiredSize,
                                 NULL);

        STORAGE_DEVICE_DESCRIPTOR *diskDescriptor;
        diskDescriptor = malloc(diskDescriptorSizeInfo.Size);

        diskDescriptor->Version = diskDescriptorSizeInfo.Size;
        result = DeviceIoControl(devHandle,
                                 IOCTL_STORAGE_QUERY_PROPERTY,
                                 amp;diskProperty,
                                 sizeof(diskProperty),
                                 diskDescriptor,
                                 diskDescriptorSizeInfo.Size,
                                 amp;requiredSize,
                                 NULL);

        printf("Bus Type: %sn", (diskDescriptor->BusType == 7 ? "USB" : "not USB"));

        //GET STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR HERE
        diskProperty.PropertyId = StorageAccessAlignmentProperty;
        STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment;
        diskAlignment.Version = sizeof(diskAlignment);
        result = DeviceIoControl(devHandle,
                                 IOCTL_STORAGE_QUERY_PROPERTY,
                                 amp;diskProperty,
                                 sizeof(diskProperty),
                                 amp;diskAlignment,
                                 sizeof(diskAlignment),
                                 amp;requiredSize,
                                 NULL);
        if(!result){
            printf("IOCTL_STORAGE_QUERY_PROPERTY failed (Error: %lu)n", GetLastError());
        }else{
            printf("Physical sector size: %lun", diskAlignment.BytesPerPhysicalSector);
        }
        printf("----------------n");
    }
}
 

Комментарии:

1. просто некоторые устройства не могут реализовать это свойство и вернуть STATUS_INVALID_DEVICE_REQUEST . посмотрите, как это было сделано здесь и здесь . для PropertyExistsQuery обычно всегда возвращаемого ок — этот запрос не информативен

2. Я понимаю, спасибо. В чем причина того, что для PropertyExists обычно возвращается ok , независимо от того, можно ли запросить свойство?

3. но я вставляю вам ссылку на реализацию — github.com/microsoft/Windows-driver-samples/blob/master/storage/… — для if (query->QueryType == PropertyExistsQuery) всегда status = STATUS_SUCCESS; goto Exit; , для других типов запросов — if (query->QueryType != PropertyStandardQuery) — возвращена ошибка status = STATUS_NOT_SUPPORTED; goto Exit; и PropertyStandardQuery зависит от драйвера порта