Retrieve S.M.A.R.T information from ATA, SAS, SATA disk

343 Views Asked by At

I want to retrieve S.M.A.R.T information from ATA, SAS, SATA disk on windows. I'm using Visual Studio.

I have already open disk using

HANDLE hDevice = CreateFile(deviceName.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

and using the below code to detect the bus type of disk

STORAGE_PROPERTY_QUERY storageProperty;
    storageProperty.PropertyId = StorageAdapterProperty;
    storageProperty.QueryType = PropertyStandardQuery;

    DWORD bytesReturned;
    STORAGE_DESCRIPTOR_HEADER storageDescriptor;

    BOOL success = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storageProperty, sizeof(STORAGE_PROPERTY_QUERY),
        &storageDescriptor, sizeof(STORAGE_DESCRIPTOR_HEADER), &bytesReturned, NULL);

    if (success) {
        if (storageDescriptor.Size > sizeof(STORAGE_DESCRIPTOR_HEADER)) {
            PSTORAGE_ADAPTER_DESCRIPTOR pstorageAdapterDescriptor = (PSTORAGE_ADAPTER_DESCRIPTOR)malloc(storageDescriptor.Size);

            success = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storageProperty, sizeof(STORAGE_PROPERTY_QUERY),
                pstorageAdapterDescriptor, storageDescriptor.Size, &bytesReturned, NULL);

            if (success) {
                std::cout << "Type number : " << (ULONG)pstorageAdapterDescriptor->BusType << "\n";
                if (pstorageAdapterDescriptor->BusType == BusTypeSata) {
                    std::cout << "The drive is SATA.\n";
                    SATAprintSMARTInfo(hDevice);
                }
                else if (pstorageAdapterDescriptor->BusType == BusTypeNvme) {
                    std::cout << "The drive is NVMe.\n";
                    NVMeprintSMARTInfo(hDevice);
                }
                else if (pstorageAdapterDescriptor->BusType == BusTypeAta) {
                    std::cout << "The drive is ATA.\n";
                    AtaPrintSMARTInfo(hDevice);
                }
                else if (pstorageAdapterDescriptor->BusType == BusTypeSas) {
                    std::cout << "The drive is SAS.\n";
                    SasPrintSMARTInfo(hDevice);
                }
                else if (pstorageAdapterDescriptor->BusType == BusTypeUnknown) {
                    std::cout << "The bus type is unknown.\n";
                }
                else {
                    std::cout << "The drive is of another type.\n";
                }
            }
            free(pstorageAdapterDescriptor);
        }
    }

But I don't know how to print the SMART information, for SATA, Ata, and Sas. I've searched Google and I know maybe I should use this windows API: DeviceIOControl, and for Ata using STORAGE_PROTOCOL_SPECIFIC_DATA this structure. However I'm not really sure how to write the code. Can anyone help me? Thanks in advance!

1

There are 1 best solutions below

2
On

Benefited from the resource @JerryCoffin supplies, IO control code SMART_RCV_DRIVE_DATA returns the ATA-2 identify data, the SMART thresholds, or the SMART attributes for the device.

Or use ROOT\WMI\MSStorageDriver_ATAPISmartData for ATA drives as the thread shows.

For NVMe drives and ATA drives, IOCTL_STORAGE_QUERY_PROPERTY can retrieve SMART/health data. See Example: NVMe Identify query.

DeviceIOControl

WMI