Jump to content

Need help with IOCTL_DISK_GET_DRIVE_LAYOUT_EX


ilko
 Share

Recommended Posts

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?
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

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

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

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 ;)...

Link to comment
Share on other sites

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

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

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

  • 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
 Share

  • Recently Browsing   0 members

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