Jump to content

Recommended Posts

Posted

Need to use DeviceIoControl and IOCTL_DISK_GET_DRIVE_LAYOUT_EX :

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365174%28v=vs.85%29.aspx

Can't figure out how to create the structure in DllStructCreate, since it consist nested variable-sized arrays:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364001%28v=vs.85%29.aspx

Reading the comments makes the confusion even bigger:

DRIVE_LAYOUT_INFORMATION_EX memory allocation

C99 Standard states that the last member of structure can be an array whose size is omitted.

DRIVE_LAYOUT_INFORMATION_EX is using this feathure, to call this control code correctly,

you cannot just declare a struct, should do something like this:

DWORD layout_size = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + MAX_NUM_PARTITION * sizeof(PARTITION_INFORMATION_EX);

DRIVE_LAYOUT_INFORMATION_EX *disk_layout = (DRIVE_LAYOUT_INFORMATION_EX*) new char[layout_size];

MAX_NUM_PARTITION , maximum number of partitions on that disk.

How this could be done in AutoIt, some help please?
Posted

A quick thought have you tried looking at WinAPIEx by Yashied?

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Posted

Yep, the first thing I did, there is _WinAPI_GetDriveGeometryEx, which is different with a different return structure.

Posted

Requires by Yashied.

A union in a structure occupies the size of it's larger member, thus the dword[26] and byte[36] elements for the MBR part to trap the larger space required for the GPT structures. Not fully tested, MBR might work :) and I don't have a GPT drive at hand to test it. Copied some of the code (esp. structures) from

Not finished but might give you some new ideas ;)...

#include <array.au3>
#include <StructureConstants.au3>
#include <WinAPIEx.au3>
Global Const $IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x70050
$aDriveNumber = _WinAPI_GetDriveNumber("c:")
If @error Then Exit
$aDriveLayout = _WinAPI_GetDriveLayoutEx($aDriveNumber[1])
_ArrayDisplay($aDriveLayout)
Func _WinAPI_GetDriveLayoutEx($iDrive)
 Local $hFile = _WinAPI_CreateFileEx('.PhysicalDrive' & $iDrive, 3, 0, 0x01)
 If Not $hFile Then
  Return SetError(1, 0, 0)
 EndIf
 Local $tagStructure = "dword PartitionStyle;dword PartitionCount;byte[4096]"
 Local $tDGEX = DllStructCreate($tagStructure)
 Local $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'ptr', $hFile, 'dword', $IOCTL_DISK_GET_DRIVE_LAYOUT_EX, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($tDGEX), 'dword', DllStructGetSize($tDGEX), 'dword*', 0, 'ptr', 0)
 If (@error) Or (Not $Ret[0]) Then
  $Ret = 0
 EndIf
 If Not IsArray($Ret) Then
  _WinAPI_CloseHandle($hFile)
  Return SetError(2, 0, 0)
 EndIf
 Local Const $tagPARTITION_INFORMATION_GPT = $tagGUID & $tagGUID & "uint64 Attributes;wchar Name[36];"
 Local Const $tagPARTITION_INFORMATION_EX_GPT = _
   "int PartitionStyle;" & _
   "int64 StartingOffset;" & _
   "int64 PartitionLength;" & _
   "uint PartitionNumber;" & _
   "ubyte RewritePartition;" & _
   $tagPARTITION_INFORMATION_GPT
 Local Const $tagPARTITION_INFORMATION_MBR = "byte PartitionType;byte BootIndicator;byte RecognizedPartition;dword HiddenSectors;"
 Local Const $tagPARTITION_INFORMATION_EX_MBR = _
   "STRUCT;" & _
   "int PartitionStyle;" & _
   "int64 StartingOffset;" & _
   "int64 PartitionLength;" & _
   "uint PartitionNumber;" & _
   "ubyte RewritePartition;" & _
   $tagPARTITION_INFORMATION_MBR & "dword[26];ENDSTRUCT;"
 If Not DllStructGetData($tDGEX, 2) > 0 Then Return SetError(3, 0, 0) ; no partition count found
 Local $iPartitionCount = DllStructGetData($tDGEX, 2)
 ConsoleWrite("$iPartitionCount " & $iPartitionCount & @CRLF)
 Local $i_structure_Elements = 0
 Switch DllStructGetData($tDGEX, 1)
  Case 0 ; PARTITION_STYLE_MBR
   $tagStructure = "dword PartitionStyle;dword PartitionCount;ulong Signature;byte[36];"
   $i_structure_Elements += 4
   For $i = 1 To $iPartitionCount
    $tagStructure &= $tagPARTITION_INFORMATION_EX_MBR
    $i_structure_Elements += 10
   Next
  Case 1 ; PARTITION_STYLE_GPT
   $tagStructure = "dword PartitionStyle;dword PartitionCount;" & $tagGUID & ";int64 StartingUsableOffset;int64 UsableLength;ulong MaxPartitionCount;"
   $i_structure_Elements += 9
   For $i = 1 To $iPartitionCount
    $tagStructure &= $tagPARTITION_INFORMATION_EX_MBR
    $i_structure_Elements += 15
   Next
  Case 2 ; PARTITION_STYLE_RAW, Partition not formatted in either of the recognized formats—MBR or GPT.
   _WinAPI_CloseHandle($hFile)
   Return SetError(4, 0, 0)
 EndSwitch
 $tDGEX = 0
 $tDGEX = DllStructCreate($tagStructure)
 Local $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'ptr', $hFile, 'dword', $IOCTL_DISK_GET_DRIVE_LAYOUT_EX, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($tDGEX), 'dword', DllStructGetSize($tDGEX), 'dword*', 0, 'ptr', 0)
 If (@error) Or (Not $Ret[0]) Then
  $Ret = 0
 EndIf
 If Not IsArray($Ret) Then
  Return SetError(5, 0, 0)
 EndIf
 _WinAPI_CloseHandle($hFile)
 Local $Result[$i_structure_Elements]
 For $i = 0 To $i_structure_Elements - 1
  $Result[$i] = DllStructGetData($tDGEX, $i + 1)
 Next
 Return $Result
EndFunc   ;==>_WinAPI_GetDriveLayoutEx
Posted (edited)

Some corrections to the structures :)...

#include <array.au3>
#include <WinAPIEx.au3>

Global Const $IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x70050

$aDriveNumber = _WinAPI_GetDriveNumber("c:")
If @error Then Exit

$aDriveLayout = _WinAPI_GetDriveLayoutEx($aDriveNumber[1])
_ArrayDisplay($aDriveLayout)

Func _WinAPI_GetDriveLayoutEx($iDrive)
    Local $hFile = _WinAPI_CreateFileEx('.PhysicalDrive' & $iDrive, 3, 0, 0x01)
    If Not $hFile Then
        Return SetError(1, 0, 0)
    EndIf
    Local $tagStructure = "dword PartitionStyle;dword PartitionCount;byte[4096]"
    Local $tDGEX = DllStructCreate($tagStructure)
    Local $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'ptr', $hFile, 'dword', $IOCTL_DISK_GET_DRIVE_LAYOUT_EX, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($tDGEX), 'dword', DllStructGetSize($tDGEX), 'dword*', 0, 'ptr', 0)
    If (@error) Or (Not $Ret[0]) Then
        $Ret = 0
    EndIf
    If Not IsArray($Ret) Then
        _WinAPI_CloseHandle($hFile)
        Return SetError(2, 0, 0)
    EndIf
    Local Const $tagPARTITION_INFORMATION_GPT = "STRUCT;" & $tagGUID & $tagGUID & "uint64 Attributes;wchar Name[36];ENDSTRUCT;"
    Local Const $tagPARTITION_INFORMATION_EX_GPT = _
            "STRUCT;" & _
            "int PartitionStyle;" & _
            "int64 StartingOffset;" & _
            "int64 PartitionLength;" & _
            "uint PartitionNumber;" & _
            "ubyte RewritePartition;ENDSTRUCT;" & _
            $tagPARTITION_INFORMATION_GPT
    Local Const $tagPARTITION_INFORMATION_MBR = "STRUCT;byte PartitionType;byte BootIndicator;byte RecognizedPartition;dword HiddenSectors;ENDSTRUCT;"
    Local Const $tagPARTITION_INFORMATION_EX_MBR = _
            "STRUCT;" & _
            "int PartitionStyle;" & _
            "int64 StartingOffset;" & _
            "int64 PartitionLength;" & _
            "uint PartitionNumber;" & _
            "ubyte RewritePartition;" & _
            $tagPARTITION_INFORMATION_MBR & "dword[26];ENDSTRUCT;"
    If Not DllStructGetData($tDGEX, 2) > 0 Then Return SetError(3, 0, 0) ; no partition count found
    Local $iPartitionCount = DllStructGetData($tDGEX, 2)
    ConsoleWrite("$iPartitionCount " & $iPartitionCount & @CRLF)
    Local $i_structure_Elements = 0
    Switch DllStructGetData($tDGEX, 1)
        Case 0 ; PARTITION_STYLE_MBR
            $tagStructure = "dword PartitionStyle;dword PartitionCount;STRUCT;ulong Signature;byte[36];ENDSTRUCT;"
            $i_structure_Elements += 4
            For $i = 1 To $iPartitionCount
                $tagStructure &= $tagPARTITION_INFORMATION_EX_MBR
                $i_structure_Elements += 10
            Next
        Case 1 ; PARTITION_STYLE_GPT
            $tagStructure = "dword PartitionStyle;dword PartitionCount;STRUCT;" & $tagGUID & ";int64 StartingUsableOffset;int64 UsableLength;ulong MaxPartitionCount;ENDSTRUCT;"
            $i_structure_Elements += 9
            For $i = 1 To $iPartitionCount
                $tagStructure &= $tagPARTITION_INFORMATION_EX_MBR
                $i_structure_Elements += 15
            Next
        Case 2 ; PARTITION_STYLE_RAW, Partition not formatted in either of the recognized formats—MBR or GPT.
            _WinAPI_CloseHandle($hFile)
            Return SetError(4, 0, 0)
    EndSwitch
    $tDGEX = 0
    $tDGEX = DllStructCreate($tagStructure)
    Local $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'ptr', $hFile, 'dword', $IOCTL_DISK_GET_DRIVE_LAYOUT_EX, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($tDGEX), 'dword', DllStructGetSize($tDGEX), 'dword*', 0, 'ptr', 0)
    If (@error) Or (Not $Ret[0]) Then
        $Ret = 0
    EndIf
    If Not IsArray($Ret) Then
        Return SetError(5, 0, 0)
    EndIf
    _WinAPI_CloseHandle($hFile)
    Local $Result[$i_structure_Elements]
    For $i = 0 To $i_structure_Elements - 1
        $Result[$i] = DllStructGetData($tDGEX, $i + 1)
    Next
    Return $Result
EndFunc   ;==>_WinAPI_GetDriveLayoutEx
Edited by KaFu
Posted (edited)

For MBR it seems to works so

#include <WinAPI.au3>

$_PARTITION_INFORMATION_MBR = 'byte PartitionType;' & _
'byte BootIndicator;' & _
'byte RecognizedPartition;' & _
'dword HiddenSectors;'

$_PARTITION_INFORMATION_GPT = 'byte TypeGuid[16];' & _
'byte IDGuid[16];' & _
'int64 Attributes;' & _
'wchar Name[36];'

$_PARTITION_INFORMATION_EX = 'int PartitionStyle;' & _
'int64 StartingOffset;' & _
'int64 PartitionLength;' & _
'dword PartitionNumber;' & _
'byte RewritePartition;' & _
'byte pad[3];' & _
$_PARTITION_INFORMATION_MBR & _
$_PARTITION_INFORMATION_GPT


$_PARTITION_INFORMATION_EX_2 = 'int PartitionStyle;' & _
'int64 StartingOffset;' & _
'int64 PartitionLength;' & _
'dword PartitionNumber;' & _
'byte RewritePartition;' & _
'byte pad[3];' & _
$_PARTITION_INFORMATION_GPT



$DRIVE_LAYOUT_INFORMATION_MBR = 'ULONG Signature;'

$DRIVE_LAYOUT_INFORMATION_GPT = 'byte Guid[16];' & _
'int64 StartingUsableOffset;' & _
'int64 UsableLength;' & _
'ulong MaxPartitionCount;'

$_DRIVE_LAYOUT = DllStructCreate('dword PartitionStyle;' & _
'dword PartitionCount;' & _
'byte union[40];' & _
'byte PartitionEntry[8192]')



$hDrive = _WinAPI_CreateFile('.PHYSICALDRIVE0', 2, 0)
local $Ret = DllCall("kernel32.dll", "int", "DeviceIoControl", _
"hwnd", $hDrive, _
"dword", 0x00070050, _
"ptr", 0, _
"dword", 0, _
"ptr", DllStructGetPtr($_DRIVE_LAYOUT), _
"dword", DllStructGetSize($_DRIVE_LAYOUT), _
"dword*", 0, _
"ptr", 0)



Switch DllStructGetData($_DRIVE_LAYOUT, "PartitionStyle")
Case 0 ;MBR

$data = DllStructGetData($_DRIVE_LAYOUT, "union")
$binaryStruct = DllStructCreate('byte[8192]')
DllStructSetData($binaryStruct, 1, $data)
$DriveMBRInfo = DllStructCreate($DRIVE_LAYOUT_INFORMATION_MBR , DllStructGetPtr($binaryStruct))
ConsoleWrite('MBR Signature: ' & Hex(DllStructGetData($DriveMBRInfo, "Signature"), 8) & @CRLF & @CRLF)


$PartitionCount = DllStructGetData($_DRIVE_LAYOUT, "PartitionCount")

$PartitionEntry = 'byte[144];'
For $x = 2 To $PartitionCount
$PartitionEntry &= 'byte[144];'
Next
$PartitionEntry &= 'byte[8192]'


$data = DllStructGetData($_DRIVE_LAYOUT, "PartitionEntry")
$binaryStruct = DllStructCreate('byte[8192]')
DllStructSetData($binaryStruct, 1, $data)
$PartitionEntry = DllStructCreate($PartitionEntry, DllStructGetPtr($binaryStruct))


For $x = 1 To $PartitionCount
$Partion = DllStructCreate($_PARTITION_INFORMATION_EX, DllStructGetPtr($PartitionEntry, $x))
IF Not DllStructGetData($Partion, 'PartitionNumber') Then ContinueLoop
ConsoleWrite('PartitionNumber: ' & DllStructGetData($Partion, 'PartitionNumber') & @CRLF)
ConsoleWrite('PartitionStyle: ' & DllStructGetData($Partion, 'PartitionStyle') & @CRLF)
ConsoleWrite('StartingOffset: ' & DllStructGetData($Partion, 'StartingOffset') & @CRLF)
ConsoleWrite('PartitionLength: ' & DllStructGetData($Partion,'PartitionLength') & @CRLF)
ConsoleWrite('RecognizedPartition: ' & DllStructGetData($Partion, 'RecognizedPartition') & @CRLF)
ConsoleWrite('PartitionType: ' & DllStructGetData($Partion, 'PartitionType') & @CRLF)
ConsoleWrite('BootIndicator: ' & DllStructGetData($Partion, 'BootIndicator') & @CRLF)
ConsoleWrite('HiddenSectors: ' & DllStructGetData($Partion, 'HiddenSectors') & @CRLF & @CRLF)
Next

Case 1 ;GPT
;GPT stuff here ...

$data = DllStructGetData($_DRIVE_LAYOUT, "union")
$binaryStruct = DllStructCreate('byte[8192]')
DllStructSetData($binaryStruct, 1, $data)
$DriveGPTInfo = DllStructCreate($DRIVE_LAYOUT_INFORMATION_GPT , DllStructGetPtr($binaryStruct))
ConsoleWrite('Guid: ' & _BeautyGUID(DllStructGetData($DriveGPTInfo, "Guid")) & @CRLF & @CRLF)
ConsoleWrite('StartingUsableOffset: ' & Int(DllStructGetData($DriveGPTInfo, "StartingUsableOffset")) & @CRLF)
ConsoleWrite('UsableLength: ' & Int(DllStructGetData($DriveGPTInfo, "UsableLength")) & @CRLF)
ConsoleWrite('MaxPartitionCount: ' & Int(DllStructGetData($DriveGPTInfo, "MaxPartitionCount")) & @CRLF & @CRLF)

$PartitionCount = DllStructGetData($_DRIVE_LAYOUT, "PartitionCount")

$PartitionEntry = 'byte[144];'
For $x = 2 To $PartitionCount
$PartitionEntry &= 'byte[144];'
Next
$PartitionEntry &= 'byte[8192]'

$data = DllStructGetData($_DRIVE_LAYOUT, "PartitionEntry")
$binaryStruct = DllStructCreate('byte[8192]')
DllStructSetData($binaryStruct, 1, $data)
$PartitionEntry = DllStructCreate($PartitionEntry, DllStructGetPtr($binaryStruct))


For $x = 1 To $PartitionCount
$Partion = DllStructCreate($_PARTITION_INFORMATION_EX_2, DllStructGetPtr($PartitionEntry, $x))
IF Not DllStructGetData($Partion, 'PartitionNumber') Then ContinueLoop
ConsoleWrite('Name: ' & DllStructGetData($Partion, 'Name') & @CRLF)
ConsoleWrite('PartitionNumber: ' & DllStructGetData($Partion, 'PartitionNumber') & @CRLF)
ConsoleWrite('PartitionStyle: ' & DllStructGetData($Partion, 'PartitionStyle') & @CRLF)
ConsoleWrite('StartingOffset: ' & DllStructGetData($Partion, 'StartingOffset') & @CRLF)
ConsoleWrite('PartitionLength: ' & DllStructGetData($Partion,'PartitionLength') & @CRLF)
ConsoleWrite('TypeGuid: ' & _BeautyGUID(DllStructGetData($Partion, 'TypeGuid')) & @CRLF)
ConsoleWrite('IDGuid: ' & _BeautyGUID(DllStructGetData($Partion, 'IDGuid')) & @CRLF)
ConsoleWrite('Attributes: ' & Int(DllStructGetData($Partion, 'Attributes')) & @CRLF & @CRLF)
Next

Case 2 ; RAW
ConsoleWrite('RAW Disk - no information available' & @CRLF)

EndSwitch



Func _BeautyGUID($GUID)
$GUID = StringLower($GUID)
IF StringLeft($GUID, 2) = '0x' Then $GUID = StringTrimLeft($GUID, 2)
Return '{' & StringLeft($GUID, 8) & '-' & StringMid($GUID, 9, 4) & '-' & StringMid($GUID, 13, 4) & '-' & StringMid($GUID, 17, 4) & '-' & StringRight($GUID, 8) & '}'
EndFunc

Edit: added GPT now also works

Edit2: runs with limited user privileges, Thanks Kafu

Edited by JFX
Posted

Awesome ;) , delivers the same result as my function does, thanks for this verification :). Had to change the createfile call on Win7 to

$hDrive = _WinAPI_CreateFile('.PHYSICALDRIVE0', 3, 0)

and... maybe my function delivers the GPT results too, can't test it ;)...

Posted (edited)

Awesome, thanks a lot guys, quite useful and a lot to learn from those examples. :)

Will test more later on and post, at first glance everything works as expected.

Edited by ilko
Posted (edited)

Had to change the createfile call on Win7 to

$hDrive = _WinAPI_CreateFile('.PHYSICALDRIVE0', 3, 0)

Thanks Kafu.

I did not know that it can work without admin rights :)

Have added the GPT informations

Edited by JFX
Posted (edited)

Upsa, it should be:

$hDrive = _WinAPI_CreateFile('.PHYSICALDRIVE0', 2, 0)

For _WinAPI_CreateFileEx() the corresponding flag is 3 = $OPEN_EXISTING, which is translated to 2 for the _WinAPI_CreateFile() function :) ...

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

"The dwDesiredAccess parameter can be zero, allowing the application to query device attributes without accessing a device. This is useful for an application to determine the size of a floppy disk drive and the formats it supports without requiring a floppy disk in a drive, for instance. It can also be used for reading statistics without requiring higher-level data read/write permission."

Edited by KaFu
  • 2 weeks later...

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
  • Recently Browsing   0 members

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