real disk size with IOCTL_DISK_GET_DRIVE_GEOMETRY_EX

Share your advanced PureBasic knowledge/code with the community.
User avatar
bingo
Enthusiast
Enthusiast
Posts: 210
Joined: Fri Apr 02, 2004 12:21 pm
Location: germany/thueringen
Contact:

real disk size with IOCTL_DISK_GET_DRIVE_GEOMETRY_EX

Post by bingo »

Code updated for 5.20+

Code: Select all

Structure DISK_GEOMETRY
  Cylinders.q
  MediaType.l
  TracksPerCylinder.l
  SectorsPerTrack.l
  BytesPerSector.l 
EndStructure

Structure DISK_GEOMETRY_EX
  pp1.DISK_GEOMETRY
  DiskSize.q
  byte.b[1];
EndStructure

pp.DISK_GEOMETRY_EX

#IOCTL_DISK_BASE                = 7  
#METHOD_BUFFERED                = 0
#FILE_ANY_ACCESS                = 0

Procedure.l CTL_CODE(DeviceType, Function, Method, Access)
  ProcedureReturn ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
EndProcedure

IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = CTL_CODE(#IOCTL_DISK_BASE, $28, #METHOD_BUFFERED, #FILE_ANY_ACCESS) 


hDevice = CreateFile_("\\.\PhysicalDrive0", #GENERIC_READ,#FILE_SHARE_READ,0,#OPEN_EXISTING,0,0)

If hDevice
  
  DeviceIoControl_(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,0,0,@pp,SizeOf(pp),@bytesret, 0)
  
EndIf

CloseHandle_(hDevice)

Debug pp\Disksize / (1024*1024*1024) ;in gb

;and other

Debug pp\pp1\cylinders
Debug pp\pp1\TracksPerCylinder
Debug pp\pp1\SectorsPerTrack
Debug pp\pp1\BytesPerSector
xp , vista (beta2) :D
["1:0>1"]
mskuma
Enthusiast
Enthusiast
Posts: 573
Joined: Sat Dec 03, 2005 1:31 am
Location: Australia

Post by mskuma »

Thanks. On my machine (XP) the code produced all zeros for the output until I changed:

Code: Select all

hDevice = CreateFile_("\\.\PhysicalDrive0", #GENERIC_READ,#FILE_SHARE_READ,0,#OPEN_EXISTING,0,0)
to:

Code: Select all

hDevice = CreateFile_("\\.\PhysicalDrive0", #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0) 
So perhaps the latter is safer.
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

it works for me.
but it seems a little bit cleaner this way :

Code: Select all

; winioctl.h

Structure DISK_GEOMETRY 
  Cylinders.q 
  MediaType.l 
  TracksPerCylinder.l 
  SectorsPerTrack.l 
  BytesPerSector.l 
EndStructure 

Structure DISK_GEOMETRY_EX Extends DISK_GEOMETRY 
  DiskSize.q 
  byte.b[1]
EndStructure 

#FILE_ANY_ACCESS = 0 
#METHOD_BUFFERED = 0 
#IOCTL_DISK_BASE = 7  

Macro CTL_CODE(DeviceType, Function, Method, Access) 
  ((DeviceType)<<16)|((Access)<<14)|((Function)<<2)|(Method) 
EndMacro

#IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = CTL_CODE(#IOCTL_DISK_BASE, $28, #METHOD_BUFFERED, #FILE_ANY_ACCESS) 

ProcedureDLL.q GetDiskSize(PhysicalDrive.l)
  
  Protected device.l, bytes.l, os.OSVERSIONINFO, disk.DISK_GEOMETRY_EX 
  
  os\dwOSVersionInfoSize = SizeOf(OSVERSIONINFO) 
  
  If GetVersionEx_(os)
    
    If os\dwPlatformId = #VER_PLATFORM_WIN32_WINDOWS
      device = CreateFile_("\\.\SMARTVSD", #GENERIC_READ, #FILE_SHARE_READ, 0, #OPEN_EXISTING, 0, 0) 
    Else
      device = CreateFile_("\\.\PhysicalDrive" + Str(PhysicalDrive), #GENERIC_READ|#GENERIC_WRITE, #FILE_SHARE_READ|#FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0) 
    EndIf
    
    If device <> #INVALID_HANDLE_VALUE
      DeviceIoControl_(device, #IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 0, 0, @disk, SizeOf(disk), @bytes, 0) 
      CloseHandle_(device) 
    EndIf 
    
  EndIf
  
  ProcedureReturn disk\Disksize

EndProcedure

Debug GetDiskSize(0)
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Post Reply