Jump to content

Get Home DiskDrive SerialNumber


Go to solution Solved by Andreik,

Recommended Posts

1 minute ago, Andreik said:

it's 6 AM

..bright and early. Good time to start the day coding :D
This ( https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddstor/ne-ntddstor-_storage_protocol_nvme_data_type ) may bring some light into he dilemma.

g'night :) 
 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Thank you to all friends, Especially Andreik

I didn't want to use wmic because I was getting errors on some computers.

I tested Andreik's code on the computer where I was receiving the error and it displayed the serial code in the output without any problem.

You can also guide me about the following codes?

#include <MsgBoxConstants.au3>
#include <WinAPI.au3>



MsgBox($MB_ICONINFORMATION,"_Win32_ComputerSystem", _Win32_ComputerSystem())
MsgBox($MB_ICONINFORMATION,"_WinAPI_GetPhysicallyInstalledSystemMemory", __WinAPI_GetPhysicallyInstalledSystemMemory())
MsgBox($MB_ICONINFORMATION,"_Win32_ComputerSystemProduct", _Win32_ComputerSystemProduct())
MsgBox($MB_ICONINFORMATION,"_Win32_VideoController", _Win32_VideoController())
MsgBox($MB_ICONINFORMATION,"_Win32_Processor", _Win32_Processor())



Func _Win32_ComputerSystem()
        $Obj_WMIService = ObjGet("winmgmts:\\" & "localhost" & "\root\cimv2")
        $Obj_Services = $Obj_WMIService.ExecQuery("Select * from Win32_ComputerSystem")
        For $Obj_Item In $Obj_Services
            $manufacturer =  $Obj_Item.Manufacturer
            $Motherboard_System_Model_Info = $Obj_Item.Model
        Next

        IF ($Motherboard_System_Model_Info) Then
            Return $Motherboard_System_Model_Info
        Else
            Return "Error"
        EndIF
EndFunc



Func __WinAPI_GetPhysicallyInstalledSystemMemory()
        $Installed_RAM_Info = _WinAPI_GetPhysicallyInstalledSystemMemory()
        IF Not ($Installed_RAM_Info) OR ($Installed_RAM_Info == "0") Then
            $Installed_RAM_Info = "not available"
        ELSE
            $Installed_RAM_Info = $Installed_RAM_Info  /1024 /1000 & " GB"
        EndIF
        Return $Installed_RAM_Info
EndFunc



Func _Win32_ComputerSystemProduct()
        $oWMIService = ObjGet("winmgmts:\\" & "localhost" & "\root\cimv2")
        $oSysProd = $oWMIService.ExecQuery("Select * From Win32_ComputerSystemProduct")
        For $oSysProp In $oSysProd
            $Device_UUID = $oSysProp.UUID
        Next

        IF ($Device_UUID) Then
            Return $Device_UUID
        Else
            Return "Error"
        EndIF
EndFunc



Func _Win32_VideoController()
        $Obj_WMIService = ObjGet("winmgmts:\\" & "localhost" & "\root\cimv2")
        $Obj_Services = $Obj_WMIService.ExecQuery("Select * from Win32_VideoController")
        For $Obj_Item In $Obj_Services
            $Graphic_Info = $Obj_Item.Name
        Next

        IF ($Graphic_Info) Then
            Return $Graphic_Info
        Else
            Return "Error"
        EndIF
EndFunc



Func _Win32_Processor()
        $Obj_WMIService = ObjGet("winmgmts:\\" & "localhost" & "\root\cimv2")
        $Obj_Services = $Obj_WMIService.ExecQuery("Select * from Win32_Processor")
        For $Obj_Item In $Obj_Services
            $Cpu_Info = $Obj_Item.Name
        Next

        IF ($Cpu_Info) Then
            Return $Cpu_Info
        Else
            Return "Error"
        EndIF
EndFunc

 


I want to produce the output like hard disk serial without using wmic

Regards

Edited by r2du-soft
Link to comment
Share on other sites

5 hours ago, r2du-soft said:

I didn't want to use wmic because I was getting errors on some computers.

As you probably noticed, to get some info you need admin privileges. So this might be a reason why sometimes it doesn't work. Have you tried to get these info using command line and parse the output or power shell?

Link to comment
Share on other sites

  • 4 weeks later...
On 12/6/2023 at 10:02 PM, Andreik said:

As you probably noticed, to get some info you need admin privileges. So this might be a reason why sometimes it doesn't work. Have you tried to get these info using command line and parse the output or power shell?

 

Andreik

I apologize for my late reply,

No, I haven't done this, but I know that the access level of the items I have this problem with is the administrator, and the program is also run at the administrator level!
At the moment, I don't know where the problem is, if I get more information, I will put more detailed information .

Now I have a question, during the execution of the code that you send us, I was testing it on my work system and I noticed that the hardware serial is not generated.
The error occurs in the following code section

Local $aDevice = _WinAPI_GetDriveNumber ($sDriveLetter)
    If @error Then Return SetError(1, @error, Null)

And the serial output is empty.

I tried to solve the error using the following method:

Local $aDevice = _WinAPI_GetDriveNumber($sDriveLetter)
    ;If @error Then Return SetError(1, @error, Null)
    If IsArray($aDevice) THEN
        $aDeviceNum = $aDevice[1]
    Else
        $aDeviceNum = 0
    ENDIF
    Local $hDevice = _WinAPI_CreateFile('\\.\PhysicalDrive' & $aDeviceNum, 2, 2, 6)

 

But I think it is not right to do this!

I think what I did is not good, but it works and shows me the right hard drive!

What do you think is the best way to solve the problem?

 

 

in another way i import functions _WinAPI_GetDriveNumber and __CheckErrorCloseHandle to my app,

and just edit and comment line

;If Not $iCurErr And Not $aCall[0] Then $iCurErr = 10

now serial generate, But I still don't know if this is true or not
Doesn't it cause problems and errors later?

 

Edited by r2du-soft
Add more details
Link to comment
Share on other sites

I use this in SMF which doesn't require admin access. Not quite sure, but I think @trancexx provided a lot to this code.

#include <array.au3>
#include <WinAPI.au3>

$h_DLL_Kernel32 = DllOpen("kernel32.dll")

$aData = _Drive_GetHardwareInfos_SMF("c")
_ArrayDisplay($aData)

Func _Drive_GetHardwareInfos_SMF($DriveLetter)

    Local $a_Info_Drive_Hardware_temp[4]
    Local $ret, $tTemp, $ptrTemp

    $ret = DllCall($h_DLL_Kernel32, 'ptr', 'CreateFileW', _
            'wStr', '\\.\' & $DriveLetter & ':', _
            'dword', 0, _
            'dword', 7, _
            'ptr', 0, _
            'dword', 3, _
            'dword', 0, _
            'ptr', 0 _
            )

    If @error Then Return SetError(1, 0, $a_Info_Drive_Hardware_temp)
    If $ret[0] = 0xFFFFFFFF Then Return SetError(2, 0, $a_Info_Drive_Hardware_temp)

    Local $hDevice = $ret[0]

    Local Const $tagSTORAGE_PROPERTY_QUERY = 'ULONG_PTR PropertyId;ULONG_PTR QueryType;byte AdditionalParameters[4]'
    Local Const $tagSTORAGE_DESCRIPTOR_HEADER = 'ulong Version;ulong 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)

    ; IOCTL_STORAGE_QUERY_PROPERTY = 0x002d1400

    $ret = DllCall($h_DLL_Kernel32, '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

        ; https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddstor/ns-ntddstor-_storage_device_descriptor
        Local Const $tagSTORAGE_DEVICE_DESCRIPTOR = 'ulong Version;ulong Size;char DeviceType;char 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($h_DLL_Kernel32, '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

            $ptrTemp = DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "VendorIdOffset")

            $tTemp = DllStructCreate("char Temp[" & _WinAPI_StringLenA($ptrTemp) & "]", $ptrTemp)
            $a_Info_Drive_Hardware_temp[0] = DllStructGetData($tTemp, "Temp")
            ; ConsoleWrite($a_Info_Drive_Hardware_temp[0] & @CRLF)

        EndIf

        ;ConsoleWrite("ProductIdOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset") Then

            $ptrTemp = DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductIdOffset")

            $tTemp = DllStructCreate("char Temp[" & _WinAPI_StringLenA($ptrTemp) & "]", $ptrTemp)
            $a_Info_Drive_Hardware_temp[1] = DllStructGetData($tTemp, "Temp")
            ; ConsoleWrite($a_Info_Drive_Hardware_temp[1] & @CRLF)

        EndIf

        ;ConsoleWrite("ProductRevisionOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset") & @CRLF)
        If DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset") Then

            $ptrTemp = DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "ProductRevisionOffset")

            $tTemp = DllStructCreate("char Temp[" & _WinAPI_StringLenA($ptrTemp) & "]", $ptrTemp)
            $a_Info_Drive_Hardware_temp[2] = DllStructGetData($tTemp, "Temp")
            ; ConsoleWrite($a_Info_Drive_Hardware_temp[2] & @CRLF)

        EndIf

        ;ConsoleWrite("SerialNumberOffset " & DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset") & @CRLF)
        If "0x" & Hex(DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset")) <> "0xFFFFFFFF" Then

            $ptrTemp = DllStructGetPtr($tSTORAGE_DEVICE_DESCRIPTOR) + DllStructGetData($tSTORAGE_DEVICE_DESCRIPTOR, "SerialNumberOffset")

            $tTemp = DllStructCreate("char Temp[" & _WinAPI_StringLenA($ptrTemp) & "]", $ptrTemp)
            $a_Info_Drive_Hardware_temp[3] = DllStructGetData($tTemp, "Temp")
            ; ConsoleWrite($a_Info_Drive_Hardware_temp[3] & @CRLF)

        EndIf

    EndIf

    $a_Info_Drive_Hardware_temp[0] = _StringToReadable($a_Info_Drive_Hardware_temp[0])
    $a_Info_Drive_Hardware_temp[1] = _StringToReadable($a_Info_Drive_Hardware_temp[1])
    $a_Info_Drive_Hardware_temp[2] = _StringToReadable($a_Info_Drive_Hardware_temp[2])
    $a_Info_Drive_Hardware_temp[3] = _SwapStringOrder(_StringToReadable($a_Info_Drive_Hardware_temp[3]))

    DllCall($h_DLL_Kernel32, 'int', 'CloseHandle', 'hwnd', $hDevice)
    Return $a_Info_Drive_Hardware_temp
EndFunc   ;==>_Drive_GetHardwareInfos_SMF

Func _StringToReadable($sString)
    Local $sString_Return, $iAscCode
    Local $aString = StringSplit($sString, "")
    For $i = 1 To $aString[0]
        $iAscCode = Asc($aString[$i])
        Switch $iAscCode
            ; Case 32 to 126
            Case 32, 48 To 57, 65 To 90, 97 To 122
                $sString_Return &= $aString[$i]
        EndSwitch
    Next
    Return $sString_Return
EndFunc   ;==>_StringToReadable

Func _SwapStringOrder($sString)
    Local $sString_Return, $iAscCode
    ; ConsoleWrite($sString & @TAB & StringLen($sString) & @CRLF)
    Local $aString = StringSplit($sString, "")
    For $i = 1 To $aString[0] Step 2
        If $i + 1 > $aString[0] Then
            $sString_Return &= $aString[$i]
            ExitLoop
        EndIf
        $sString_Return &= $aString[$i + 1] & $aString[$i]
        ; ConsoleWrite($i & @TAB & $aString[0] & @CRLF)
    Next
    Return $sString_Return
EndFunc   ;==>_SwapStringOrder

 

Edited by KaFu
Link to comment
Share on other sites

2 hours ago, r2du-soft said:

I tried to solve the error using the following method:

Local $aDevice = _WinAPI_GetDriveNumber($sDriveLetter)
    ;If @error Then Return SetError(1, @error, Null)
    If IsArray($aDevice) THEN
        $aDeviceNum = $aDevice[1]
    Else
        $aDeviceNum = 0
    ENDIF
    Local $hDevice = _WinAPI_CreateFile('\\.\PhysicalDrive' & $aDeviceNum, 2, 2, 6)

 

But I think it is not right to do this!

I think what I did is not good, but it works and shows me the right hard drive!

What do you think is the best way to solve the problem?

This might work in certain conditions but the result it's not guaranteed. Since you can pass the drive letter as parameter to GetDiskSerial() if you have multiple hard drives certain drive letters for sure won't be mapped to PhysicalDrive0.

 

2 hours ago, r2du-soft said:

in another way i import functions _WinAPI_GetDriveNumber and __CheckErrorCloseHandle to my app,

and just edit and comment line

;If Not $iCurErr And Not $aCall[0] Then $iCurErr = 10

now serial generate, But I still don't know if this is true or not
Doesn't it cause problems and errors later?

It looks like a fail in calling DeviceIoControl() for IOCTL_STORAGE_GET_DEVICE_NUMBER control code. And since the members of the resulting structure is not filled with any data your happy result it's 0 by luck as the above hard coded value.

You can test this by calling this function instead of _WinAPI_GetDriveNumber():

Func __WinAPI_GetDriveNumber($sDrive)
    Local $hFile = _WinAPI_CreateFileEx('\\.\' & $sDrive, $OPEN_EXISTING, 0, $FILE_SHARE_READWRITE)
    If @error Then Return SetError(@error + 20, @extended, 0)

    Local $tSDN = DllStructCreate('dword;dword;dword')
    Local $aCall = DllCall('kernel32.dll', 'bool', 'DeviceIoControl', 'handle', $hFile, 'dword', 0x002D1080, 'ptr', 0, _
            'dword', 0, 'struct*', $tSDN, 'dword', DllStructGetSize($tSDN), 'dword*', 0, 'ptr', 0)
    
    ConsoleWrite(IsArray($aCall) & @CRLF)   ; <<< Added this line
        
    _WinAPI_CloseHandle($hFile)             ; And close the file handle without aditional checks

    Local $aRet[3]
    For $i = 0 To 2
        $aRet[$i] = DllStructGetData($tSDN, $i + 1)
    Next
    Return $aRet
EndFunc

 

Edit: looking at @KaFu's example it looks like you don't require admin privileges if DesiredAccess of _WinAPI_CreateFile() it's 0. Actually you can omit to get the actual physical drive if you are interested to use the function just with drive letter as parameter. Here is the modified version of the previous function:

#include <WinAPIFiles.au3>
#include <WinAPIHObj.au3>

MsgBox(0, 'Serial', 'Disk serial: ' & GetDiskSerial(@HomeDrive))

Func GetDiskSerial($sDriveLetter)
    Local Const $IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400
    Local $tagSTORAGE_PROPERTY_QUERY = 'int PropertyId; int QueryType; byte AdditionalParameters[1];'
    Local $tagSTORAGE_DESCRIPTOR_HEADER = 'dword Version;dword Size;'
    Local $tagSTORAGE_DEVICE_DESCRIPTOR = 'dword Version;dword Size; byte DeviceType;byte DeviceTypeModifier; boolean RemovableMedia;' & _
    'boolean CommandQueueing;dword VendorIdOffset;dword ProductIdOffset;dword ProductRevisionOffset;dword SerialNumberOffset;int BusType;' & _
    'dword RawPropertiesLength;byte RawDeviceProperties[1];'
    Local $hDevice = _WinAPI_CreateFile('\\.\' & $sDriveLetter, 2, 0, 6, 0, 0)
    If @error Then Return SetError(1, @error, Null)
    Local $tSTORAGE_PROPERTY_QUERY = DllStructCreate($tagSTORAGE_PROPERTY_QUERY)
    $tSTORAGE_PROPERTY_QUERY.PropertyId = 0          ; StorageDeviceProperty
    $tSTORAGE_PROPERTY_QUERY.QueryType = 0          ; PropertyStandardQuery
    Local $tSTORAGE_DESCRIPTOR_HEADER = DllStructCreate($tagSTORAGE_DESCRIPTOR_HEADER)
    If Not _WinAPI_DeviceIoControl($hDevice, $IOCTL_STORAGE_QUERY_PROPERTY, _
            DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            DllStructGetPtr($tSTORAGE_DESCRIPTOR_HEADER), DllStructGetSize($tSTORAGE_DESCRIPTOR_HEADER)) _
        Then
            _WinAPI_CloseHandle($hDevice)
            Return SetError(2, 0, Null)
    EndIf
    Local $tBuffer = DllStructCreate('byte[' & $tSTORAGE_DESCRIPTOR_HEADER.Size & ']')
    If Not _WinAPI_DeviceIoControl($hDevice, $IOCTL_STORAGE_QUERY_PROPERTY, _
            DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            DllStructGetPtr($tBuffer), DllStructGetSize($tBuffer)) _
        Then
            _WinAPI_CloseHandle($hDevice)
            Return SetError(3, 0, Null)
    EndIf
    Local $tSTORAGE_DEVICE_DESCRIPTOR = DllStructCreate($tagSTORAGE_DEVICE_DESCRIPTOR, DllStructGetPtr($tBuffer))
    If $tSTORAGE_DEVICE_DESCRIPTOR.SerialNumberOffset = 0 Then
        _WinAPI_CloseHandle($hDevice)
        Return SetError(4, 0, Null)
    EndIf
    Local $tSerial = DllStructCreate('char Serial[32]', DllStructGetPtr($tBuffer) + $tSTORAGE_DEVICE_DESCRIPTOR.SerialNumberOffset)
    _WinAPI_CloseHandle($hDevice)
    Return $tSerial.Serial
EndFunc

 

Edited by Andreik
Link to comment
Share on other sites

NVMe drives right ?. They are a different animal. The name and hardware firmware revision are right, but the hardware drive serial needs a look at:
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddstor/ne-ntddstor-_storage_protocol_nvme_data_type

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

  • 4 weeks later...
On 12/5/2023 at 2:54 AM, Andreik said:

The promised code:

#RequireAdmin
#include <WinAPIFiles.au3>
#include <WinAPIHObj.au3>

MsgBox(0, 'Serial', 'Disk serial: ' & GetDiskSerial(@HomeDrive))

Func GetDiskSerial($sDriveLetter)
    Local Const $IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400
    Local $tagSTORAGE_PROPERTY_QUERY = 'int PropertyId; int QueryType; byte AdditionalParameters[1];'
    Local $tagSTORAGE_DESCRIPTOR_HEADER = 'dword Version;dword Size;'
    Local $tagSTORAGE_DEVICE_DESCRIPTOR = 'dword Version;dword Size; byte DeviceType;byte DeviceTypeModifier; boolean RemovableMedia;' & _
    'boolean CommandQueueing;dword VendorIdOffset;dword ProductIdOffset;dword ProductRevisionOffset;dword SerialNumberOffset;int BusType;' & _
    'dword RawPropertiesLength;byte RawDeviceProperties[1];'
    Local $aDevice = _WinAPI_GetDriveNumber ($sDriveLetter)
    If @error Then Return SetError(1, @error, Null)
    Local $hDevice = _WinAPI_CreateFile('\\.\PhysicalDrive' & $aDevice[1], 2, 2, 6)
    If @error Then Return SetError(2, @error, Null)
    Local $tSTORAGE_PROPERTY_QUERY = DllStructCreate($tagSTORAGE_PROPERTY_QUERY)
    $tSTORAGE_PROPERTY_QUERY.PropertyId = 0         ; StorageDeviceProperty
    $tSTORAGE_PROPERTY_QUERY.QueryType = 0          ; PropertyStandardQuery
    Local $tSTORAGE_DESCRIPTOR_HEADER = DllStructCreate($tagSTORAGE_DESCRIPTOR_HEADER)
    If Not _WinAPI_DeviceIoControl($hDevice, $IOCTL_STORAGE_QUERY_PROPERTY, _
            DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            DllStructGetPtr($tSTORAGE_DESCRIPTOR_HEADER), DllStructGetSize($tSTORAGE_DESCRIPTOR_HEADER)) _
        Then
            _WinAPI_CloseHandle($hDevice)
            Return SetError(3, 0, Null)
    EndIf
    Local $tBuffer = DllStructCreate('byte[' & $tSTORAGE_DESCRIPTOR_HEADER.Size & ']')
    If Not _WinAPI_DeviceIoControl($hDevice, $IOCTL_STORAGE_QUERY_PROPERTY, _
            DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            DllStructGetPtr($tBuffer), DllStructGetSize($tBuffer)) _
        Then
            _WinAPI_CloseHandle($hDevice)
            Return SetError(4, 0, Null)
    EndIf
    Local $tSTORAGE_DEVICE_DESCRIPTOR = DllStructCreate($tagSTORAGE_DEVICE_DESCRIPTOR, DllStructGetPtr($tBuffer))
    If $tSTORAGE_DEVICE_DESCRIPTOR.SerialNumberOffset = 0 Then
        _WinAPI_CloseHandle($hDevice)
        Return SetError(5, 0, Null)
    EndIf
    Local $tSerial = DllStructCreate('char Serial[32]', DllStructGetPtr($tBuffer) + $tSTORAGE_DEVICE_DESCRIPTOR.SerialNumberOffset)
    _WinAPI_CloseHandle($hDevice)
    Return $tSerial.Serial
EndFunc

 

 


Hello
I was checking on Windows 7 installed on Virtualbox when I came across the following:
Each one shows something different!

1-CMD:
Longer hex string

2-Autoit:
Shorter hex string

3-Hwinfo:
String value different from CMD and Autoit string output

I am really confused and I don't know what the problem is

 

image.png.0313a66337501a4086b3307cd076b5a7.png

 

Edited by r2du-soft
Link to comment
Share on other sites

VB 58 3a 07 93 -d ce 29 f0 0
BV 85 a3 70 39 d- ec 92 0f 0

Edit:

$s = "VB583a0793-dce29f00"

MsgBox(0,"",$s & @crlf & @crlf & _SwapStringOrder($s))

Func _SwapStringOrder($sString)
    Local $sString_Return, $iAscCode
    ; ConsoleWrite($sString & @TAB & StringLen($sString) & @CRLF)
    Local $aString = StringSplit($sString, "")
    For $i = 1 To $aString[0] Step 2
        If $i + 1 > $aString[0] Then
            $sString_Return &= $aString[$i]
            ExitLoop
        EndIf
        $sString_Return &= $aString[$i + 1] & $aString[$i]
        ; ConsoleWrite($i & @TAB & $aString[0] & @CRLF)
    Next
    Return $sString_Return
EndFunc   ;==>_SwapStringOrder

 

Edited by KaFu
Link to comment
Share on other sites

On 12/30/2023 at 8:27 PM, Andreik said:

This might work in certain conditions but the result it's not guaranteed. Since you can pass the drive letter as parameter to GetDiskSerial() if you have multiple hard drives certain drive letters for sure won't be mapped to PhysicalDrive0.

 

It looks like a fail in calling DeviceIoControl() for IOCTL_STORAGE_GET_DEVICE_NUMBER control code. And since the members of the resulting structure is not filled with any data your happy result it's 0 by luck as the above hard coded value.

You can test this by calling this function instead of _WinAPI_GetDriveNumber():

Func __WinAPI_GetDriveNumber($sDrive)
    Local $hFile = _WinAPI_CreateFileEx('\\.\' & $sDrive, $OPEN_EXISTING, 0, $FILE_SHARE_READWRITE)
    If @error Then Return SetError(@error + 20, @extended, 0)

    Local $tSDN = DllStructCreate('dword;dword;dword')
    Local $aCall = DllCall('kernel32.dll', 'bool', 'DeviceIoControl', 'handle', $hFile, 'dword', 0x002D1080, 'ptr', 0, _
            'dword', 0, 'struct*', $tSDN, 'dword', DllStructGetSize($tSDN), 'dword*', 0, 'ptr', 0)
    
    ConsoleWrite(IsArray($aCall) & @CRLF)   ; <<< Added this line
        
    _WinAPI_CloseHandle($hFile)             ; And close the file handle without aditional checks

    Local $aRet[3]
    For $i = 0 To 2
        $aRet[$i] = DllStructGetData($tSDN, $i + 1)
    Next
    Return $aRet
EndFunc

 

Edit: looking at @KaFu's example it looks like you don't require admin privileges if DesiredAccess of _WinAPI_CreateFile() it's 0. Actually you can omit to get the actual physical drive if you are interested to use the function just with drive letter as parameter. Here is the modified version of the previous function:

#include <WinAPIFiles.au3>
#include <WinAPIHObj.au3>

MsgBox(0, 'Serial', 'Disk serial: ' & GetDiskSerial(@HomeDrive))

Func GetDiskSerial($sDriveLetter)
    Local Const $IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400
    Local $tagSTORAGE_PROPERTY_QUERY = 'int PropertyId; int QueryType; byte AdditionalParameters[1];'
    Local $tagSTORAGE_DESCRIPTOR_HEADER = 'dword Version;dword Size;'
    Local $tagSTORAGE_DEVICE_DESCRIPTOR = 'dword Version;dword Size; byte DeviceType;byte DeviceTypeModifier; boolean RemovableMedia;' & _
    'boolean CommandQueueing;dword VendorIdOffset;dword ProductIdOffset;dword ProductRevisionOffset;dword SerialNumberOffset;int BusType;' & _
    'dword RawPropertiesLength;byte RawDeviceProperties[1];'
    Local $hDevice = _WinAPI_CreateFile('\\.\' & $sDriveLetter, 2, 0, 6, 0, 0)
    If @error Then Return SetError(1, @error, Null)
    Local $tSTORAGE_PROPERTY_QUERY = DllStructCreate($tagSTORAGE_PROPERTY_QUERY)
    $tSTORAGE_PROPERTY_QUERY.PropertyId = 0          ; StorageDeviceProperty
    $tSTORAGE_PROPERTY_QUERY.QueryType = 0          ; PropertyStandardQuery
    Local $tSTORAGE_DESCRIPTOR_HEADER = DllStructCreate($tagSTORAGE_DESCRIPTOR_HEADER)
    If Not _WinAPI_DeviceIoControl($hDevice, $IOCTL_STORAGE_QUERY_PROPERTY, _
            DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            DllStructGetPtr($tSTORAGE_DESCRIPTOR_HEADER), DllStructGetSize($tSTORAGE_DESCRIPTOR_HEADER)) _
        Then
            _WinAPI_CloseHandle($hDevice)
            Return SetError(2, 0, Null)
    EndIf
    Local $tBuffer = DllStructCreate('byte[' & $tSTORAGE_DESCRIPTOR_HEADER.Size & ']')
    If Not _WinAPI_DeviceIoControl($hDevice, $IOCTL_STORAGE_QUERY_PROPERTY, _
            DllStructGetPtr($tSTORAGE_PROPERTY_QUERY), DllStructGetSize($tSTORAGE_PROPERTY_QUERY), _
            DllStructGetPtr($tBuffer), DllStructGetSize($tBuffer)) _
        Then
            _WinAPI_CloseHandle($hDevice)
            Return SetError(3, 0, Null)
    EndIf
    Local $tSTORAGE_DEVICE_DESCRIPTOR = DllStructCreate($tagSTORAGE_DEVICE_DESCRIPTOR, DllStructGetPtr($tBuffer))
    If $tSTORAGE_DEVICE_DESCRIPTOR.SerialNumberOffset = 0 Then
        _WinAPI_CloseHandle($hDevice)
        Return SetError(4, 0, Null)
    EndIf
    Local $tSerial = DllStructCreate('char Serial[32]', DllStructGetPtr($tBuffer) + $tSTORAGE_DEVICE_DESCRIPTOR.SerialNumberOffset)
    _WinAPI_CloseHandle($hDevice)
    Return $tSerial.Serial
EndFunc

 

xxxx_xxxx_xxxx_xxxx.thumb.jpg.1b9d7f82e130cf20c583a92f2c139299.jpg

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...