Sign in to follow this  
Followers 0
KaFu

_Drive_GetHardwareInfos not reliable

9 posts in this topic

HiHo Forum :),

attached is a function to extract the VendorId, ProductId, ProductRevision & SerialNumber from a drive. It is derived from (an old version of) Yashieds _WinAPI_GetDriveBusType() function (part of the now).

It works in most cases...

- but it does not seem to be x64 save (crashes on extracting data from my DVD-Drive)

- and for some drives (Western Digital) the VendorId return is just the character "(" and the true VendorId seems to be part of the ProductId

- for virtual drives the SerialNumber is just some arbitrary characters

I'm not sure if the functions contains faults (for x64 compatibility for sure, as on 32bit it works fine on all drives), or if this just happens because the manufactures just don't stick to the conventions.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <array.au3>

$var = DriveGetDrive( "all" )
If NOT @error Then
    ; MsgBox(4096,"", "Found " & $var[0] & " drives")
    For $i = 1 to $var[0]
        ;MsgBox(4096,"Drive " & $i, $var[$i])
        ConsoleWrite($var[$i])
        $aRes = _Drive_GetHardwareInfos(StringLeft($var[$i],1))
        ConsoleWrite(@tab & @error & @crlf)
        _ArrayDisplay($aRes, $var[$i])
    Next
EndIf


Func _Drive_GetHardwareInfos($DriveLetter)
    Local Const $tagSTORAGE_PROPERTY_QUERY_Own = 'ulong PropertyId;ulong QueryType;byte AdditionalParameters[4]'
    Local Const $tagSTORAGE_DEVICE_DESCRIPTOR_Own = 'ulong Version;ulong Size;byte DeviceType;byte DeviceTypeModifier;byte RemovableMedia;byte CommandQueueing;ulong VendorIdOffset;ulong ProductIdOffset;ulong ProductRevisionOffset;ulong SerialNumberOffset;ulong BusType;ulong RawPropertiesLength;byte RawDeviceProperties[512]'

    Local $a_Info_Drive_Hardware_temp[4]
    Local $Ret
    $Ret = DllCall('kernel32.dll', 'hwnd', 'CreateFile', _
            'str', '\\.\' & $DriveLetter & ':', _
            'dword', 0, _
            'dword', 0, _
            'ptr', 0, _
            'dword', 3, _
            'dword', 0, _
            'ptr', 0 _
            )
    If @error Then
        Return SetError(1, 0, $a_Info_Drive_Hardware_temp)
    EndIf
    If $Ret[0] = 0xFFFFFFFF Then
        Return SetError(2, 0, $a_Info_Drive_Hardware_temp)
    EndIf

    Local $tSTORAGE_DEVICE_DESCRIPTOR = DllStructCreate($tagSTORAGE_DEVICE_DESCRIPTOR_Own)
    Local $tSTORAGE_PROPERTY_QUERY = DllStructCreate($tagSTORAGE_PROPERTY_QUERY_Own)
    DllStructSetData($tSTORAGE_PROPERTY_QUERY, 'PropertyId', 0)
    DllStructSetData($tSTORAGE_PROPERTY_QUERY, 'QueryType', 0)

    Local $hDevice = $Ret[0]
    $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', _
            'ptr', $hDevice, _
            'dword', 0x002D1400, _
            'ptr', DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), _
            'dword', DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            'ptr', DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR), _
            'dword', DllStructGetSize($tSTORAGE_DEVICE_DESCRIPTOR), _
            'dword*', 0, _
            'ptr', 0 _
            )

    Local $stTemp = DllStructCreate("char Temp[128]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset"))
    ;ConsoleWrite("VendorId" & @tab & @tab & DllStructGetData($stTemp, "Temp") & @CRLF)
    $a_Info_Drive_Hardware_temp[0] = DllStructGetData($stTemp, "Temp")

    $stTemp = DllStructCreate("char Temp[128]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset"))
    ; ConsoleWrite("ProductId" & @tab & @tab & DllStructGetData($stTemp, "Temp") & @CRLF)
    $a_Info_Drive_Hardware_temp[1] = DllStructGetData($stTemp, "Temp")

    $stTemp = DllStructCreate("char Temp[128]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset"))
    ;ConsoleWrite("ProductRevision" & @tab & @tab & DllStructGetData($stTemp, "Temp") & @CRLF)
    $a_Info_Drive_Hardware_temp[2] = DllStructGetData($stTemp, "Temp")

    $stTemp = DllStructCreate("char Temp[128]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset"))
    ;ConsoleWrite("SerialNumber" & @tab & @tab & DllStructGetData($stTemp, "Temp") & @CRLF)
    $a_Info_Drive_Hardware_temp[3] = DllStructGetData($stTemp, "Temp")

    DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $hDevice)
    Return $a_Info_Drive_Hardware_temp
EndFunc   ;==>_Drive_GetHardwareInfos

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Here the result on my notebook running Win7 x64 compared with SIW:

Your code / SIW

c:

ST932042 / ST9320423AS

3AS / na

0006 / 0006HPM1

V54HF8ZX / 5VH48FXZ

d: (DVD)

hp / hp DVDRAM GT30L

DVDRAM GT30L / na

mP04 / mP04

6MA6870A43 9 / M66A78A0349

Seems that array[0] and array[1] belongs together as on value.

Otherwise no crash when running it via SciTE or comnpiled.

If no serial number is given it will return some undefined characters!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Seems that array[0] and array[1] belongs together as on value.

Looks definitely better that way :), though strange enough these are two different values in the returned structure.

Otherwise no crash when running it via SciTE or comnpiled.

Did you set #AutoIt3Wrapper_UseX64=y?

If no serial number is given it will return some undefined characters!

If this is also what SIW returns then I guess it's save to assume that it's the standard return ;).

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

When I use #AutoIt3Wrapper_UseX64=y it is crashing on my last drive which I didn't mention above (ELBY virtual DVD ROM).

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Happens on the DeviceIoControl call, I guess either STORAGE_PROPERTY_QUERY (seems simple enough) or STORAGE_DEVICE_DESCRIPTOR (more likely) is not defined correctly... can't see the issue :) ...

Share this post


Link to post
Share on other sites

Happens on the DeviceIoControl call, I guess either STORAGE_PROPERTY_QUERY (seems simple enough) or STORAGE_DEVICE_DESCRIPTOR (more likely) is not defined correctly... can't see the issue :) ...

You should never ever do something like this:

Local $stTemp = DllStructCreate("char Temp[128]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset"))
    ;ConsoleWrite("VendorId" & @tab & @tab & DllStructGetData($stTemp, "Temp") & @CRLF)
    $a_Info_Drive_Hardware_temp[0] = DllStructGetData($stTemp, "Temp")

Creating a buffer at address of space not allocated by you should be done in properly calculated size. Crash is very likely to happen when accessing data in that buffer.

Documentation for STORAGE_DEVICE_DESCRIPTOR says that, for example, VendorIdOffset is ... byte offset from the beginning of the structure to a null-terminated ASCII string that contains the device's vendor ID. If the device has no vendor ID, this member is zero.

Null-terminated means call some function that calculates the length of that type of strings. Logically it would be lstrlen for this case. There are plenty of examples around considering it's very basic function.

Long story short... Wrong thing for sure is:

"char Temp[128]"

First fix that, then see if there would be other problems.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

First fix that, then see if there would be other problems.

Nice ;), this fixes the crash on x64. Other problems I see are that for my DVD Drives the Serial Number offset is arbitrary (4294967295) and for my harddrives the returned Serial Number is still encoded somehow :) ...

Edit: "If the device has no serial number, this member is 0xffffffff." => 4294967295 = 0xffffffff

#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <array.au3>

$var = DriveGetDrive("all")
If Not @error Then
    For $i = 1 To $var[0]
        ConsoleWrite($var[$i] & @CRLF)
        $aRes = _Drive_GetHardwareInfos(StringLeft($var[$i], 1))
        ConsoleWrite(@CRLF & $aRes[0] & @CRLF & $aRes[1] & @CRLF & $aRes[2] & @CRLF & @CRLF)
        ;_ArrayDisplay($aRes, $var[$i])
    Next
EndIf


Func _Drive_GetHardwareInfos($DriveLetter)

    Local $a_Info_Drive_Hardware_temp[3]
    Local $Ret, $tTemp

    $Ret = DllCall('kernel32.dll', 'hwnd', 'CreateFile', _
            'str', '\\.\' & $DriveLetter & ':', _
            'dword', 0, _
            'dword', 0, _
            'ptr', 0, _
            'dword', 3, _
            'dword', 0, _
            'ptr', 0 _
            )

    If @error Then
        Return SetError(1, 0, $a_Info_Drive_Hardware_temp)
    EndIf
    If $Ret[0] = 0xFFFFFFFF Then
        Return SetError(2, 0, $a_Info_Drive_Hardware_temp)
    EndIf
    Local $hDevice = $Ret[0]


    Local Const $tagSTORAGE_PROPERTY_QUERY = 'ULONG_PTR PropertyId;ULONG_PTR QueryType;byte AdditionalParameters[4]'
    Local Const $tagSTORAGE_DESCRIPTOR_HEADER = 'dword Version;dword Size'

    Local $tSTORAGE_PROPERTY_QUERY = DllStructCreate($tagSTORAGE_PROPERTY_QUERY)
    DllStructSetData($tSTORAGE_PROPERTY_QUERY, 'PropertyId', 0)
    DllStructSetData($tSTORAGE_PROPERTY_QUERY, 'QueryType', 0)

    Local $tSTORAGE_DESCRIPTOR_HEADER = DllStructCreate($tagSTORAGE_DESCRIPTOR_HEADER)

    $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', _
            'handle', $hDevice, _
            'dword', 0x002D1400, _
            'PTR', DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), _
            'dword', DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            'PTR', DllStructGetPtr($tSTORAGE_DESCRIPTOR_HEADER), _
            'dword', DllStructGetSize($tSTORAGE_DESCRIPTOR_HEADER), _
            'dword*', 0, _
            'PTR', 0 _
            )

    If DllStructGetData($tSTORAGE_DESCRIPTOR_HEADER, "Size") Then

        Local Const $tagSTORAGE_DEVICE_DESCRIPTOR = 'ulong Version;ulong Size;byte DeviceType;byte DeviceTypeModifier;byte RemovableMedia;byte CommandQueueing;ulong VendorIdOffset;ulong ProductIdOffset;ulong ProductRevisionOffset;ulong SerialNumberOffset;ulong BusType;ulong RawPropertiesLength;byte RawDeviceProperties[' & DllStructGetData($tSTORAGE_DESCRIPTOR_HEADER, "Size") & ']'
        Local $tSTORAGE_DEVICE_DESCRIPTOR = DllStructCreate($tagSTORAGE_DEVICE_DESCRIPTOR)

        $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', _
                'handle', $hDevice, _
                'dword', 0x002D1400, _
                'PTR', DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), _
                'dword', DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
                'PTR', DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR), _
                'dword', DllStructGetSize($tSTORAGE_DEVICE_DESCRIPTOR), _
                'dword*', 0, _
                'PTR', 0 _
                )

        ConsoleWrite("VendorIdOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset") Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset"))
            $a_Info_Drive_Hardware_temp[0] = DllStructGetData($tTemp, "Temp")
        EndIf

        ConsoleWrite("ProductIdOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset") Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset"))
            $a_Info_Drive_Hardware_temp[0] &= DllStructGetData($tTemp, "Temp")
        EndIf

        ConsoleWrite("ProductRevisionOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset") Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset"))
            $a_Info_Drive_Hardware_temp[1] = DllStructGetData($tTemp, "Temp")
        EndIf

        ConsoleWrite("SerialNumberOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset") & @CRLF)
        If "0x" & Hex(DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset")) <> "0xFFFFFFFF" Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset"))
            $a_Info_Drive_Hardware_temp[2] = DllStructGetData($tTemp, "Temp")
        EndIf

    EndIf

    DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $hDevice)
    Return $a_Info_Drive_Hardware_temp
EndFunc   ;==>_Drive_GetHardwareInfos
Edited by KaFu

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

After some more research I came to the conclusion that extracting Hardware infos via the Api is a never ending story... better stick to a WMI call for consistent results *sigh*... but at least I managed to "decode" the Serialnumber :), at least for me it's now the same returned by WMI as the computer-info tool SIW display (which seems to use wmi too?).

; Generated by AutoIt Scriptomatic February 06, 2011

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output = ""
$Output &= "Computer: " & $strComputer & @CRLF
$Output &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) Then
    For $objItem In $colItems
        $Output &= "Availability: " & $objItem.Availability & @CRLF
        $Output &= "BytesPerSector: " & $objItem.BytesPerSector & @CRLF
        $strCapabilities = $objItem.Capabilities(0)
        $Output &= "Capabilities: " & $strCapabilities & @CRLF
        $strCapabilityDescriptions = $objItem.CapabilityDescriptions(0)
        $Output &= "CapabilityDescriptions: " & $strCapabilityDescriptions & @CRLF
        $Output &= "Caption: " & $objItem.Caption & @CRLF
        $Output &= "CompressionMethod: " & $objItem.CompressionMethod & @CRLF
        $Output &= "ConfigManagerErrorCode: " & $objItem.ConfigManagerErrorCode & @CRLF
        $Output &= "ConfigManagerUserConfig: " & $objItem.ConfigManagerUserConfig & @CRLF
        $Output &= "CreationClassName: " & $objItem.CreationClassName & @CRLF
        $Output &= "DefaultBlockSize: " & $objItem.DefaultBlockSize & @CRLF
        $Output &= "Description: " & $objItem.Description & @CRLF
        $Output &= "DeviceID: " & $objItem.DeviceID & @CRLF
        $Output &= "ErrorCleared: " & $objItem.ErrorCleared & @CRLF
        $Output &= "ErrorDescription: " & $objItem.ErrorDescription & @CRLF
        $Output &= "ErrorMethodology: " & $objItem.ErrorMethodology & @CRLF
        $Output &= "FirmwareRevision: " & $objItem.FirmwareRevision & @CRLF
        $Output &= "Index: " & $objItem.Index & @CRLF
        $Output &= "InstallDate: " & WMIDateStringToDate($objItem.InstallDate) & @CRLF
        $Output &= "InterfaceType: " & $objItem.InterfaceType & @CRLF
        $Output &= "LastErrorCode: " & $objItem.LastErrorCode & @CRLF
        $Output &= "Manufacturer: " & $objItem.Manufacturer & @CRLF
        $Output &= "MaxBlockSize: " & $objItem.MaxBlockSize & @CRLF
        $Output &= "MaxMediaSize: " & $objItem.MaxMediaSize & @CRLF
        $Output &= "MediaLoaded: " & $objItem.MediaLoaded & @CRLF
        $Output &= "MediaType: " & $objItem.MediaType & @CRLF
        $Output &= "MinBlockSize: " & $objItem.MinBlockSize & @CRLF
        $Output &= "Model: " & $objItem.Model & @CRLF
        $Output &= "Name: " & $objItem.Name & @CRLF
        $Output &= "NeedsCleaning: " & $objItem.NeedsCleaning & @CRLF
        $Output &= "NumberOfMediaSupported: " & $objItem.NumberOfMediaSupported & @CRLF
        $Output &= "Partitions: " & $objItem.Partitions & @CRLF
        $Output &= "PNPDeviceID: " & $objItem.PNPDeviceID & @CRLF
        $strPowerManagementCapabilities = $objItem.PowerManagementCapabilities(0)
        $Output &= "PowerManagementCapabilities: " & $strPowerManagementCapabilities & @CRLF
        $Output &= "PowerManagementSupported: " & $objItem.PowerManagementSupported & @CRLF
        $Output &= "SCSIBus: " & $objItem.SCSIBus & @CRLF
        $Output &= "SCSILogicalUnit: " & $objItem.SCSILogicalUnit & @CRLF
        $Output &= "SCSIPort: " & $objItem.SCSIPort & @CRLF
        $Output &= "SCSITargetId: " & $objItem.SCSITargetId & @CRLF
        $Output &= "SectorsPerTrack: " & $objItem.SectorsPerTrack & @CRLF
        $Output &= "SerialNumber: " & WMISerialNumberConversion($objItem.SerialNumber) & @CRLF
        ;ClipPut($objItem.SerialNumber)
        $Output &= "Signature: " & $objItem.Signature & @CRLF
        $Output &= "Size: " & $objItem.Size & @CRLF
        $Output &= "Status: " & $objItem.Status & @CRLF
        $Output &= "StatusInfo: " & $objItem.StatusInfo & @CRLF
        $Output &= "SystemCreationClassName: " & $objItem.SystemCreationClassName & @CRLF
        $Output &= "SystemName: " & $objItem.SystemName & @CRLF
        $Output &= "TotalCylinders: " & $objItem.TotalCylinders & @CRLF
        $Output &= "TotalHeads: " & $objItem.TotalHeads & @CRLF
        $Output &= "TotalSectors: " & $objItem.TotalSectors & @CRLF
        $Output &= "TotalTracks: " & $objItem.TotalTracks & @CRLF
        $Output &= "TracksPerCylinder: " & $objItem.TracksPerCylinder & @CRLF
        If MsgBox(1, "WMI Output", $Output) = 2 Then ExitLoop
        $Output = ""
    Next
Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_DiskDrive")
EndIf

Func WMIDateStringToDate($dtmDate)

    Return (StringMid($dtmDate, 5, 2) & "/" & _
            StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
             & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc   ;==>WMIDateStringToDate

Func WMISerialNumberConversion($string = "")
    ; By KaFu
    If Not $string Then Return
    Local $string_new, $string_new2
    For $i = 1 To StringLen($string) Step 2
        ;ConsoleWrite(StringMid($string, $i, 2) & @TAB & Chr("0x" & StringMid($string, $i, 2)) & @CRLF)
        $string_new &= Chr("0x" & StringMid($string, $i, 2))
    Next
    For $i = 1 To StringLen($string_new) Step 2
        $string_new2 &= StringMid($string_new, $i + 1, 1)
        $string_new2 &= StringMid($string_new, $i, 1)
    Next
    $string_new2 = StringStripWS($string_new2, 7)
    Return $string_new2
EndFunc   ;==>WMISerialNumberConversion

Edit:

And here's a quick&dirty example of how to track down the underlying physical disk serial number from the logical disk drive letter ;)...

Global $s_DriveName_Logical = "c"
Global $s_DriveName_Partition
Global $s_DriveName_PhysicalDisk
$s_DriveName_Logical = StringUpper($s_DriveName_Logical)

; Generated by AutoIt Scriptomatic February 06, 2011

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output = ""
$Output &= "Computer: " & $strComputer & @CRLF
$Output &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) Then
    For $objItem In $colItems
        ;$Output &= "Antecedent: " & $objItem.Antecedent & @CRLF
        ;$Output &= "Dependent: " & $objItem.Dependent & @CRLF
        If StringInStr($objItem.Dependent, 'Win32_LogicalDisk.DeviceID="' & $s_DriveName_Logical & ':"') Then
            If Not StringInStr($objItem.Antecedent, 'Win32_DiskPartition.DeviceID="') Then
                MsgBox(0, "Error", "")
            Else
                $s_DriveName_Partition = StringMid($objItem.Antecedent, StringInStr($objItem.Antecedent, '"', 0, -2)+1, StringLen($objItem.Antecedent) - StringInStr($objItem.Antecedent, '"', 0, -2) - 1)
                ;ConsoleWrite($s_DriveName_Partition & @CRLF)
                ;StringMid(
                ;StringInStr($objItem.Antecedent, 'Win32_DiskPartition.DeviceID="')
            EndIf
            ;ClipPut($objItem.Antecedent)
            ;\\HEAVENSGATE\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #1"
            ExitLoop
        EndIf

        ;$Output &= "EndingAddress: " & $objItem.EndingAddress & @CRLF
        ;$Output &= "StartingAddress: " & $objItem.StartingAddress & @CRLF
        ;if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
        ;$Output=""
    Next
Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_LogicalDiskToPartition")
EndIf




; Generated by AutoIt Scriptomatic February 06, 2011

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output = ""
$Output &= "Computer: " & $strComputer & @CRLF
$Output &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDriveToDiskPartition", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) Then
    For $objItem In $colItems
        $Output &= "Antecedent: " & $objItem.Antecedent & @CRLF
        $Output &= "Dependent: " & $objItem.Dependent & @CRLF
        if StringInStr($objItem.Dependent,$s_DriveName_Partition) Then
            $s_DriveName_PhysicalDisk = StringMid($objItem.Antecedent, StringInStr($objItem.Antecedent, '"', 0, -2)+1, StringLen($objItem.Antecedent) - StringInStr($objItem.Antecedent, '"', 0, -2) - 1)
            ExitLoop
        endif
        ;If MsgBox(1, "WMI Output", $Output) = 2 Then ExitLoop
        $Output = ""
    Next
Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_DiskDriveToDiskPartition")
EndIf

ConsoleWrite($s_DriveName_PhysicalDisk & @crlf)
;exit

; Generated by AutoIt Scriptomatic February 06, 2011

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output = ""
$Output &= "Computer: " & $strComputer & @CRLF
$Output &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive WHERE DeviceID='" & $s_DriveName_PhysicalDisk & "'", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) Then
    For $objItem In $colItems
        $Output &= "Availability: " & $objItem.Availability & @CRLF
        $Output &= "BytesPerSector: " & $objItem.BytesPerSector & @CRLF
        $strCapabilities = $objItem.Capabilities(0)
        $Output &= "Capabilities: " & $strCapabilities & @CRLF
        $strCapabilityDescriptions = $objItem.CapabilityDescriptions(0)
        $Output &= "CapabilityDescriptions: " & $strCapabilityDescriptions & @CRLF
        $Output &= "Caption: " & $objItem.Caption & @CRLF
        $Output &= "CompressionMethod: " & $objItem.CompressionMethod & @CRLF
        $Output &= "ConfigManagerErrorCode: " & $objItem.ConfigManagerErrorCode & @CRLF
        $Output &= "ConfigManagerUserConfig: " & $objItem.ConfigManagerUserConfig & @CRLF
        $Output &= "CreationClassName: " & $objItem.CreationClassName & @CRLF
        $Output &= "DefaultBlockSize: " & $objItem.DefaultBlockSize & @CRLF
        $Output &= "Description: " & $objItem.Description & @CRLF
        $Output &= "DeviceID: " & $objItem.DeviceID & @CRLF
        ;ClipPut($objItem.DeviceID)
        $Output &= "ErrorCleared: " & $objItem.ErrorCleared & @CRLF
        $Output &= "ErrorDescription: " & $objItem.ErrorDescription & @CRLF
        $Output &= "ErrorMethodology: " & $objItem.ErrorMethodology & @CRLF
        $Output &= "FirmwareRevision: " & $objItem.FirmwareRevision & @CRLF
        $Output &= "Index: " & $objItem.Index & @CRLF
        $Output &= "InstallDate: " & WMIDateStringToDate($objItem.InstallDate) & @CRLF
        $Output &= "InterfaceType: " & $objItem.InterfaceType & @CRLF
        $Output &= "LastErrorCode: " & $objItem.LastErrorCode & @CRLF
        $Output &= "Manufacturer: " & $objItem.Manufacturer & @CRLF
        $Output &= "MaxBlockSize: " & $objItem.MaxBlockSize & @CRLF
        $Output &= "MaxMediaSize: " & $objItem.MaxMediaSize & @CRLF
        $Output &= "MediaLoaded: " & $objItem.MediaLoaded & @CRLF
        $Output &= "MediaType: " & $objItem.MediaType & @CRLF
        $Output &= "MinBlockSize: " & $objItem.MinBlockSize & @CRLF
        $Output &= "Model: " & $objItem.Model & @CRLF
        $Output &= "Name: " & $objItem.Name & @CRLF
        $Output &= "NeedsCleaning: " & $objItem.NeedsCleaning & @CRLF
        $Output &= "NumberOfMediaSupported: " & $objItem.NumberOfMediaSupported & @CRLF
        $Output &= "Partitions: " & $objItem.Partitions & @CRLF
        $Output &= "PNPDeviceID: " & $objItem.PNPDeviceID & @CRLF
        $strPowerManagementCapabilities = $objItem.PowerManagementCapabilities(0)
        $Output &= "PowerManagementCapabilities: " & $strPowerManagementCapabilities & @CRLF
        $Output &= "PowerManagementSupported: " & $objItem.PowerManagementSupported & @CRLF
        $Output &= "SCSIBus: " & $objItem.SCSIBus & @CRLF
        $Output &= "SCSILogicalUnit: " & $objItem.SCSILogicalUnit & @CRLF
        $Output &= "SCSIPort: " & $objItem.SCSIPort & @CRLF
        $Output &= "SCSITargetId: " & $objItem.SCSITargetId & @CRLF
        $Output &= "SectorsPerTrack: " & $objItem.SectorsPerTrack & @CRLF
        $Output &= "SerialNumber: " & WMISerialNumberConversion($objItem.SerialNumber) & @CRLF
        ;ClipPut($objItem.SerialNumber)
        $Output &= "Signature: " & $objItem.Signature & @CRLF
        $Output &= "Size: " & $objItem.Size & @CRLF
        $Output &= "Status: " & $objItem.Status & @CRLF
        $Output &= "StatusInfo: " & $objItem.StatusInfo & @CRLF
        $Output &= "SystemCreationClassName: " & $objItem.SystemCreationClassName & @CRLF
        $Output &= "SystemName: " & $objItem.SystemName & @CRLF
        $Output &= "TotalCylinders: " & $objItem.TotalCylinders & @CRLF
        $Output &= "TotalHeads: " & $objItem.TotalHeads & @CRLF
        $Output &= "TotalSectors: " & $objItem.TotalSectors & @CRLF
        $Output &= "TotalTracks: " & $objItem.TotalTracks & @CRLF
        $Output &= "TracksPerCylinder: " & $objItem.TracksPerCylinder & @CRLF
        If MsgBox(1, "Logical Drive " & $s_DriveName_Logical & ":\", $Output) = 2 Then ExitLoop
        $Output = ""
    Next
Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_DiskDrive")
EndIf

Func WMIDateStringToDate($dtmDate)

    Return (StringMid($dtmDate, 5, 2) & "/" & _
            StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
             & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc   ;==>WMIDateStringToDate

Func WMISerialNumberConversion($string = "")
    ; By KaFu
    If Not $string Then Return
    Local $string_new, $string_new2
    For $i = 1 To StringLen($string) Step 2
        ;ConsoleWrite(StringMid($string, $i, 2) & @TAB & Chr("0x" & StringMid($string, $i, 2)) & @CRLF)
        $string_new &= Chr("0x" & StringMid($string, $i, 2))
    Next
    For $i = 1 To StringLen($string_new) Step 2
        $string_new2 &= StringMid($string_new, $i + 1, 1)
        $string_new2 &= StringMid($string_new, $i, 1)
    Next
    $string_new2 = StringStripWS($string_new2, 7)
    Return $string_new2
EndFunc   ;==>WMISerialNumberConversion

Edit2:

Oh, and the SN decoding also works on the DeviceIoControl example :idiot:.

#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <array.au3>

$var = DriveGetDrive("all")
If Not @error Then
    For $i = 1 To $var[0]
        ConsoleWrite($var[$i] & @CRLF)
        $aRes = _Drive_GetHardwareInfos(StringLeft($var[$i], 1))
        ConsoleWrite(@CRLF & $aRes[0] & @CRLF & $aRes[1] & @CRLF & $aRes[2] & @CRLF & @CRLF)
        ;_ArrayDisplay($aRes, $var[$i])
    Next
EndIf


Func _Drive_GetHardwareInfos($DriveLetter)

    Local $a_Info_Drive_Hardware_temp[3]
    Local $Ret, $tTemp

    $Ret = DllCall('kernel32.dll', 'hwnd', 'CreateFile', _
            'str', '\\.\' & $DriveLetter & ':', _
            'dword', 0, _
            'dword', 0, _
            'ptr', 0, _
            'dword', 3, _
            'dword', 0, _
            'ptr', 0 _
            )

    If @error Then
        Return SetError(1, 0, $a_Info_Drive_Hardware_temp)
    EndIf
    If $Ret[0] = 0xFFFFFFFF Then
        Return SetError(2, 0, $a_Info_Drive_Hardware_temp)
    EndIf
    Local $hDevice = $Ret[0]


    Local Const $tagSTORAGE_PROPERTY_QUERY = 'ULONG_PTR PropertyId;ULONG_PTR QueryType;byte AdditionalParameters[4]'
    Local Const $tagSTORAGE_DESCRIPTOR_HEADER = 'dword Version;dword Size'

    Local $tSTORAGE_PROPERTY_QUERY = DllStructCreate($tagSTORAGE_PROPERTY_QUERY)
    DllStructSetData($tSTORAGE_PROPERTY_QUERY, 'PropertyId', 0)
    DllStructSetData($tSTORAGE_PROPERTY_QUERY, 'QueryType', 0)

    Local $tSTORAGE_DESCRIPTOR_HEADER = DllStructCreate($tagSTORAGE_DESCRIPTOR_HEADER)

    $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', _
            'handle', $hDevice, _
            'dword', 0x002D1400, _
            'PTR', DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), _
            'dword', DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            'PTR', DllStructGetPtr($tSTORAGE_DESCRIPTOR_HEADER), _
            'dword', DllStructGetSize($tSTORAGE_DESCRIPTOR_HEADER), _
            'dword*', 0, _
            'PTR', 0 _
            )

    If DllStructGetData($tSTORAGE_DESCRIPTOR_HEADER, "Size") Then

        Local Const $tagSTORAGE_DEVICE_DESCRIPTOR = 'ulong Version;ulong Size;byte DeviceType;byte DeviceTypeModifier;byte RemovableMedia;byte CommandQueueing;ulong VendorIdOffset;ulong ProductIdOffset;ulong ProductRevisionOffset;ulong SerialNumberOffset;ulong BusType;ulong RawPropertiesLength;byte RawDeviceProperties[' & DllStructGetData($tSTORAGE_DESCRIPTOR_HEADER, "Size") & ']'
        Local $tSTORAGE_DEVICE_DESCRIPTOR = DllStructCreate($tagSTORAGE_DEVICE_DESCRIPTOR)

        $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', _
                'handle', $hDevice, _
                'dword', 0x002D1400, _
                'PTR', DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), _
                'dword', DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
                'PTR', DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR), _
                'dword', DllStructGetSize($tSTORAGE_DEVICE_DESCRIPTOR), _
                'dword*', 0, _
                'PTR', 0 _
                )

        ConsoleWrite("VendorIdOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset") Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset"))
            $a_Info_Drive_Hardware_temp[0] = DllStructGetData($tTemp, "Temp")
        EndIf

        ConsoleWrite("ProductIdOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset") Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset"))
            $a_Info_Drive_Hardware_temp[0] &= DllStructGetData($tTemp, "Temp")
        EndIf

        ConsoleWrite("ProductRevisionOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset") Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset"))
            $a_Info_Drive_Hardware_temp[1] = DllStructGetData($tTemp, "Temp")
        EndIf

        ConsoleWrite("SerialNumberOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset") & @CRLF)
        If "0x" & Hex(DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset")) <> "0xFFFFFFFF" Then
            $Ret = DllCall("kernel32.dll", "int", "lstrlen", "ptr", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset"))
            $tTemp = DllStructCreate("char Temp[" & $Ret[0] & "]", DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset"))
            $a_Info_Drive_Hardware_temp[2] = WMISerialNumberConversion(DllStructGetData($tTemp, "Temp"))
        EndIf

    EndIf

    DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $hDevice)
    Return $a_Info_Drive_Hardware_temp
EndFunc   ;==>_Drive_GetHardwareInfos


Func WMISerialNumberConversion($string = "")
    ; By KaFu
    If Not $string Then Return
    Local $string_new, $string_new2
    For $i = 1 To StringLen($string) Step 2
        ;ConsoleWrite(StringMid($string, $i, 2) & @TAB & Chr("0x" & StringMid($string, $i, 2)) & @CRLF)
        $string_new &= Chr("0x" & StringMid($string, $i, 2))
    Next
    For $i = 1 To StringLen($string_new) Step 2
        $string_new2 &= StringMid($string_new, $i + 1, 1)
        $string_new2 &= StringMid($string_new, $i, 1)
    Next
    $string_new2 = StringStripWS($string_new2, 7)
    Return $string_new2
EndFunc   ;==>WMISerialNumberConversion
Edited by KaFu

Share this post


Link to post
Share on other sites

#9 ·  Posted

the RemovableDisk can not get the  serial number,Do you have other way?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0