Getting HARDISK (hardware) serial, vendor, model with IOCTL_STORAGE_QUERY_PROPERTY

I once wrote in Clarion some snippet to get the HARDDISK serial (thus the one in chip in the HD itself, not a Partition or Volume serial)

You can get it by Smart (see other code I posted), or by retrieving it with

Other info on this way you can get as well (https://docs.microsoft.com/en-us/windows/win32/api/winioctl/ne-winioctl-storage_property_id)

like: typedef enum _STORAGE_PROPERTY_ID {
StorageDeviceProperty,
StorageAdapterProperty,
StorageDeviceIdProperty,
StorageDeviceUniqueIdProperty,
StorageDeviceWriteCacheProperty,
StorageMiniportProperty,
StorageAccessAlignmentProperty,
StorageDeviceSeekPenaltyProperty,
StorageDeviceTrimProperty,
StorageDeviceWriteAggregationProperty,
StorageDeviceDeviceTelemetryProperty,
StorageDeviceLBProvisioningProperty,
StorageDevicePowerProperty,
StorageDeviceCopyOffloadProperty,
StorageDeviceResiliencyProperty,
StorageDeviceMediumProductType,
StorageAdapterRpmbProperty,
StorageAdapterCryptoProperty,
StorageDeviceIoCapabilityProperty,
StorageAdapterProtocolSpecificProperty,
StorageDeviceProtocolSpecificProperty,
StorageAdapterTemperatureProperty,
StorageDeviceTemperatureProperty,
StorageAdapterPhysicalTopologyProperty,
StorageDevicePhysicalTopologyProperty,
StorageDeviceAttributesProperty,
StorageDeviceManagementStatus,
StorageAdapterSerialNumberProperty,
StorageDeviceLocationProperty,
StorageDeviceNumaProperty,
StorageDeviceZonedDeviceProperty,
StorageDeviceUnsafeShutdownCount,
StorageDeviceEnduranceProperty
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;

Up here the code:

STORAGE_PROPERTY_QUERY.STOR_PROPERTY_ID     = StorageDeviceProperty
IOReturn        = DeviceIoControl(LDeviceHandle, IOCTL_STORAGE_QUERY_PROPERTY, Address(STORAGE_PROPERTY_QUERY), Size(STORAGE_PROPERTY_QUERY), Address(LBUFFER16K), Size(LBUFFER16K), 0, Address(IOverlapped[IOverlappedIndex]))

PROCESS_DATA_IOCTL_STORAGE_QUERY_PROPERTY_StorageDeviceProperty ROUTINE

If OverlappedBytesReturned > 0
    HEADERGROUP = LBUFFER16K[1 : 8]
    If HEADERGROUP.SIZE > 0
        
        LGStorDevDescr:Version                  = Get32(LBUFFER16K[1 : 1 + 3])
        LGStorDevDescr:Size                     = Get32(LBUFFER16K[5 : 5 + 3])
        LGStorDevDescr:DeviceType               = Val(LBUFFER16K[9])
        LGStorDevDescr:DeviceTypeModifier       = Val(LBUFFER16K[10])
        LGStorDevDescr:RemovableMedia           = Val(LBUFFER16K[11])
        LGStorDevDescr:CommandQueueing          = Val(LBUFFER16K[12])
        LGStorDevDescr:VendorIdOffset           = Get32(LBUFFER16K[13 : 13 + 3])
        LGStorDevDescr:ProductIdOffset          = Get32(LBUFFER16K[17 : 17 + 3])
        LGStorDevDescr:ProductRevisionOffset    = Get32(LBUFFER16K[21 : 21 + 3])
        LGStorDevDescr:SerialNumberOffset       = Get32(LBUFFER16K[25 : 25 + 3])
        LGStorDevDescr:STORAGE_BUS_TYPE            = Get32(LBUFFER16K[29 : 29 + 3])
        
        CASE LGStorDevDescr:STORAGE_BUS_TYPE
        Of BusTypeUnknown
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Unknown'
        Of BusTypeScsi       
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Scsi'
        Of BusTypeAtapi          
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Atapi'
        Of BusTypeAta            
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Ata'
        Of BusType1394         
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = '1394'
        Of BusTypeSsa          
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Ssa'
        Of BusTypeFibre         
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Fibre'
        Of BusTypeUsb           
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Usb'
        Of BusTypeRAID        
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'RAID'
        Of BusTypeiScsi       
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Scsi'
        Of BusTypeSas       
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Sas'
        Of BusTypeSata      
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Sata'
        Of BusTypeSd          
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Sd'
        Of BusTypeMmc         
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Mmc'
        Of BusTypeVirtual       
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Virtual'
        Of BusTypeFileBackedVirtual
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'FileBackedVirtual'
            !EnumerateVirtualDiskMetadata(long VirtualDiskHandle,long NumberOfItems,long Items),LONG,PASCAL,RAW,PROC
            !X# = EnumerateVirtualDiskMetadata(DeviceHandle,Address(NumberOfItems),0)
            !Message(X# & ' , ' & NumberOfItems)
        Of BusTypeSpaces     
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Spaces'
        Of BusTypeMax        
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'Max'
        Of BusTypeMaxReserved 
            LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA = 'MaxReserved'
        End
        
        
        
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        
        QLDevPropExt:MessageId          = GLHDWorkerMes.MessageId
        QLDevPropExt:FunctionCall       = GetHDInfoPhase
        QLDevPropExt:OK                 = 0
        QLDevPropExt:ERROR              = 0
        QLDevPropExt:LASTERRORCODE      = 0
        QLDevPropExt:DURATION           = Clock() - StartTimeDeviceIoControl            
        
        QLDevPropExt:TagNameA           = 'StorageDeviceProperty'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'STORAGE_BUS_TYPE'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'string'
        QLDevPropExt:ValueA             = Clip(LGStorDevDescr:STORAGE_BUS_TYPE_STRINGA)
        QLDevPropExt:ValueLen           = 1
        Add(QLDevicePropExt)     
        
        LGStorDevDescr:RawPropertiesLength         = Get32(LBUFFER16K[33 : 33 + 3])
        
        !If IsSmartEnabled = 1
            If LGStorDevDescr:VendorIdOffset > 0 And LGStorDevDescr:VendorIdOffset < 700
                LGStorDevDescr:VendorIdStringA = LBUFFER16K[LGStorDevDescr:VendorIdOffset + 1 : LGStorDevDescr:VendorIdOffset + 200 + 1]
                XI# = INSTRING(Chr(0),LGStorDevDescr:VendorIdStringA)
                If XI# > 1
                    LGStorDevDescr:VendorIdStringA = Clip(Left(LGStorDevDescr:VendorIdStringA[1 : XI# - 1]))
                    Clear(QLDevicePropExt)
                    QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
                    QLDevPropExt:Id                 = QLDevicePropExtSeed
                    QLDevPropExt:MachineId          = ThisMachineId
                    QLDevPropExt:WinWorker          = LWinWorkerIndex
                    QLDevPropExt:DeviceId           = LQDeviceId
                    
                    QLDevPropExt:MessageId          = GLHDWorkerMes.MessageId
                    QLDevPropExt:FunctionCall       = GetHDInfoPhase
                    QLDevPropExt:OK                 = 0
                    QLDevPropExt:ERROR              = 0
                    QLDevPropExt:LASTERRORCODE      = 0
                    QLDevPropExt:DURATION           = Clock() - StartTimeDeviceIoControl       
                    
                    QLDevPropExt:TagNameA           = 'StorageDeviceProperty'
                    QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
                    QLDevPropExt:NameA              = 'VendorId'
                    QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
                    QLDevPropExt:DataType           = 1
                    QLDevPropExt:DataTypeString     = 'string'
                    QLDevPropExt:ValueA             = Clip(LGStorDevDescr:VendorIdStringA)
                    QLDevPropExt:ValueLen           = 1
                    Add(QLDevicePropExt)                     
                End
            End
            If LGStorDevDescr:ProductIdOffset > 0 And LGStorDevDescr:ProductIdOffset < 700
                LGStorDevDescr:ProductIdStringA = LBUFFER16K[LGStorDevDescr:ProductIdOffset + 1 : LGStorDevDescr:ProductIdOffset + 200 + 1]
                XI# = INSTRING(Chr(0),LGStorDevDescr:ProductIdStringA)
                If XI# > 1
                    LGStorDevDescr:ProductIdStringA = Clip(Left(LGStorDevDescr:ProductIdStringA[1 : XI# - 1]))
                    Clear(QLDevicePropExt)
                    QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
                    QLDevPropExt:Id                 = QLDevicePropExtSeed
                    QLDevPropExt:MachineId          = ThisMachineId
                    QLDevPropExt:WinWorker          = LWinWorkerIndex
                    QLDevPropExt:DeviceId           = LQDeviceId
                    
                    QLDevPropExt:MessageId          = GLHDWorkerMes.MessageId
                    QLDevPropExt:FunctionCall       = GetHDInfoPhase
                    QLDevPropExt:OK                 = 0
                    QLDevPropExt:ERROR              = 0
                    QLDevPropExt:LASTERRORCODE      = 0
                    QLDevPropExt:DURATION           = Clock() - StartTimeDeviceIoControl                               
                    
                    QLDevPropExt:TagNameA           = 'StorageDeviceProperty'
                    QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
                    QLDevPropExt:NameA              = 'ProductId'
                    QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
                    QLDevPropExt:DataType           = 1
                    QLDevPropExt:DataTypeString     = 'string'
                    QLDevPropExt:ValueA             = Clip(LGStorDevDescr:ProductIdStringA)
                    QLDevPropExt:ValueLen           = 1
                    Add(QLDevicePropExt)         
                    WinWorkers[LWinWorkerIndex].NameA = Clip(LGStorDevDescr:ProductIdStringA)
                End
            End
            If LGStorDevDescr:SerialNumberOffset > 0 And LGStorDevDescr:SerialNumberOffset < 700
                LGStorDevDescr:SerialNumberStringA = LBUFFER16K[LGStorDevDescr:SerialNumberOffset + 1: LGStorDevDescr:SerialNumberOffset + 200 + 1]
                XI# = INSTRING(Chr(0),LGStorDevDescr:SerialNumberStringA)
                If XI# > 1
                    LGStorDevDescr:SerialNumberStringA = Clip(Left(LGStorDevDescr:SerialNumberStringA[1 : XI# - 1]))
                End
                LGStorDevDescr:SerialNumberStringA = Clip(Left(LGStorDevDescr:SerialNumberStringA))
                Clear(QLDevicePropExt)
                QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
                QLDevPropExt:Id                 = QLDevicePropExtSeed
                QLDevPropExt:MachineId          = ThisMachineId
                QLDevPropExt:WinWorker          = LWinWorkerIndex
                QLDevPropExt:DeviceId           = LQDeviceId
                
                QLDevPropExt:MessageId          = GLHDWorkerMes.MessageId
                QLDevPropExt:FunctionCall       = GetHDInfoPhase
                QLDevPropExt:OK                 = 0
                QLDevPropExt:ERROR              = 0
                QLDevPropExt:LASTERRORCODE      = 0
                QLDevPropExt:DURATION           = Clock() - StartTimeDeviceIoControl                    
                
                QLDevPropExt:TagNameA           = 'StorageDeviceProperty'
                QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
                QLDevPropExt:NameA              = 'SerialNumber'
                QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
                QLDevPropExt:DataType           = 1
                QLDevPropExt:DataTypeString     = 'string'
                QLDevPropExt:ValueA             = Clip(LGStorDevDescr:SerialNumberStringA)
                QLDevPropExt:ValueLen           = 1
                Add(QLDevicePropExt)            
                WinWorkers[LWinWorkerIndex].Serial = Clip(LGStorDevDescr:SerialNumberStringA)
                
            End
            If LGStorDevDescr:RawPropertiesLength > 0
                LGStorDevDescr:RawDevicePropertiesStringA = LBUFFER16K[37 : 37 + LGStorDevDescr:RawPropertiesLength-1]
    !            Clear(QLDevicePropExt)
    !            QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
    !            QLDevPropExt:Id                 = QLDevicePropExtSeed
    !            QLDevPropExt:MachineId          = ThisMachineId
    !            QLDevPropExt:WinWorker          = LWinWorkerIndex
    !            QLDevPropExt:DeviceId           = LQDeviceId
    !            QLDevPropExt:TagNameA           = 'StorageDeviceProperty'
    !            QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
    !            QLDevPropExt:NameA              = 'VendorId'
    !            QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
    !            QLDevPropExt:DataType           = 1
    !            QLDevPropExt:DataTypeString     = 'string'
    !            QLDevPropExt:ValueA             = Clip(LGStorDevDescr:VendorIdStringA)
    !            QLDevPropExt:ValueLen           = 1
    !            Add(QLDevicePropExt)               
            End
            !LGStorDevDescriptor
        !End
    End
END