0

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!

Tom
  • 47,574
  • 2
  • 16
  • 29
csypt
  • 1
  • 2
  • 2
    https://www.codeproject.com/articles/16671/hard-drive-information-using-s-m-a-r-t?display=printall&fid=365221&df=90&mpp=25&sort=Position&view=Normal&spc=Relaxed&fr=26&prof=True. To work with a modern OS, you also need to include a manifest with UAC level set to `requireAdministrator`. – Jerry Coffin Jul 05 '23 at 09:58
  • @JerryCoffin You mean to open this project exe in administrator mode? btw thanks for the resource :D – csypt Jul 06 '23 at 02:55
  • It isn't enough to just run it under an account with admin privileges. If you're building from the command line, you'd add something like `/link /manifest:embed /manifestuac='requireAdministrator'`. If you build it in VS, you go into the linker settings and select the same thing there. – Jerry Coffin Jul 06 '23 at 04:08
  • @JerryCoffin Ok, thanks for your reply! :D – csypt Jul 07 '23 at 06:31

1 Answers1

0

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

YangXiaoPo-MSFT
  • 1,589
  • 1
  • 4
  • 22
  • Could you demonstrate on how to retrieve SMART data on ATA device using IOCTL_STORAGE_QUERY_PROPERTY? I've succeed on NVMe device but ATA failed. Thanks a lot! – csypt Jul 07 '23 at 06:30
  • [STORAGE_PROTOCOL_SPECIFIC_DATA](https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-storage_protocol_specific_data#remarks) mentions that *To specify a type of ATA protocol-specific information, configure the STORAGE_PROTOCOL_SPECIFIC_DATA structure as follows: Set the ProtocolType field to ProtocolTypeAta. Set the DataType field to an enumeration value defined by STORAGE_PROTOCOL_ATA_DATA_TYPE: Use AtaDataTypeIdentify to identify the ATA drive. Use AtaDataTypeLogPage to get log pages from the ATA drive.* – YangXiaoPo-MSFT Jul 07 '23 at 06:52