Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using DeviceIOControl to get disk geometry

Status
Not open for further replies.

Jasen

IS-IT--Management
May 1, 2002
435
US
I'm using the p/invoke API calls for "CreateFile" and "DeviceIOControl" in a small program that creates a disk image.
As the code stands, it runs without errors, I can open the file handle (verified by reading data from it), however the call to the deviceiocontrol function to grab disk geometry (and calculate physical disk size) returns an empty object. I've tried varying the function signatures slightly, thinking maybe a data type somewhere was the issue, but with no effect.

I'll keep the code example as brief as possible here...
These are the structure and API function declarations I've settled on:
Code:
Private Const IOCTL_DISK_GET_DRIVE_GEOMETRY As Long = &H70000

<System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)> _
Public Structure DISK_GEOMETRY
    Public Cylinders As Long
    Public MediaType As MEDIA_TYPE
    Public TracksPerCylinder As Integer
    Public SectorsPerTrack As Integer
    Public BytesPerSector As Integer

    Public ReadOnly Property DiskSize() As Long
        Get
            Return Cylinders * CLng(TracksPerCylinder) * CLng(SectorsPerTrack) * CLng(BytesPerSector)
        End Get
    End Property
End Structure

Public Enum Media_Type As Integer
    Unknown = 0
    Removable = 11
    FixedMedia = 12
End Enum

<DllImport("Kernel32.dll", SetLastError:=False, CharSet:=CharSet.Auto)>
Public Shared Function DeviceIoControl( _
        ByVal hDevice As Microsoft.Win32.SafeHandles.SafeFileHandle, _
        ByVal IoControlCode As Long, _
        <MarshalAs(UnmanagedType.AsAny), [In]()> ByVal InBuffer As Object, _
        ByVal nInBufferSize As UInteger, _
        <MarshalAs(UnmanagedType.AsAny), [Out]()> ByVal OutBuffer As Object, _
        ByVal nOutBufferSize As UInteger, _
        ByRef pBytesReturned As UInteger, _
        <[In]()> ByRef Overlapped As Object) As Boolean
End Function
   
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function CreateFile( _
        ByVal lpFileName As String, _
        ByVal dwDesiredAccess As Int32, _
        ByVal dwShareMode As Int32, _
        ByVal lpSecurityAttributes As Int32, _
        ByVal dwCreationDisposition As Int32, _
        ByVal dwFlagsAndAttributes As Int32, _
        ByVal hTemplateFile As Int32) As SafeFileHandle
End Function

And this is the code that actually calls the functions:
Code:
Dim hDevice As SafeFileHandle

hDevice = CreateFile("\\.\PHYSICALDRIVE0", _
          0, _
          FILE_SHARE_READ Or FILE_SHARE_WRITE, _
          0, _
          OPEN_EXISTING, _
          0, 0)

If Not hDevice.IsInvalid Then

     Dim dg As DISK_GEOMETRY
     Dim bytesReturned As Long

     DeviceIoControl(hDevice, _
                     IOCTL_DISK_GET_DRIVE_GEOMETRY, _
                     IntPtr.Zero, _
                     0, _
                     dg, _
                     Marshal.SizeOf(dg), _
                     bytesReturned, _
                     IntPtr.Zero)

     debug.print(dg.DiskSize)
End If

hDevice.Close

As I said, the codes runs with no errors, however my "dg" object at the end there is full of zeros. I've tried changing the SafeFileHandles to Longs, as the older API examples all used, but that also changes nothing. Has anyone done this in VB or C# that can show me what might be wrong?
This is being done with VS2010, 3.5 framework, if it matters.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top