Link to home
Create AccountLog in
Avatar of jason4659
jason4659

asked on

GetDriveGeometry() Gives Wrong Information

I'm writing a program that calls the DeviceIoControl API in order to use the GetDriveGeometry method.  However, when I obtain the information from GetDriveGeometry(), most of the information is incorrect.  It gives the correct number of cylinders, but everything else (bytes per sector, sectors per track, disk size, etc.) is wrong.  I am mainly concerned with the disk size, but the other properties would be nice to double check that all the information is correct.  Can anyone help me find what is going on here, and how to fix it?
[DllImport("Kernel32.dll", SetLastError = true)]
        static extern unsafe bool DeviceIoControl(IntPtr handle, EIOControlCode IoControlCode,
            IntPtr lpInBuffer, uint InBufferSize, DISK_GEOMETRY lpOutBuffer, uint nOutBufferSize,
            ref uint lpBytesReturned, IntPtr lpOverlapped);
 
unsafe static public bool GetDriveGeometry(DISK_GEOMETRY pdg)
            {
                uint junk = 51200; //DISCARD RESULTS
 
                if (handle.ToInt32() <= 0)
                    return false;
 
                byte[] buffer = new byte[512];
 
               bool result = DeviceIoControl(handle, EIOControlCode.DiskGetDriveGeometry, IntPtr.Zero, (uint)0,
                   pdg, (uint)buffer.Length, ref junk, IntPtr.Zero);
 
                if(Marshal.GetLastWin32Error() != 0)
                    Console.WriteLine("Geometry Error: " + Marshal.GetLastWin32Error());
 
                return result;
 
            }
 
        } 
 
    [StructLayout(LayoutKind.Sequential)]
    internal class DISK_GEOMETRY
    {
        public long cylinders;
        public uint tracksPerCylinder;
        public uint sectorsPerTrack;
        public uint bytesPerSector;
    }
 
Console.WriteLine("  Cylinders = {0}", pdg.cylinders);
                    Console.WriteLine("  Tracks per cylinder = {0}", pdg.tracksPerCylinder);
                    Console.WriteLine("  Sectors per track = {0}", pdg.sectorsPerTrack);
                    Console.WriteLine("  Bytes per sector = {0}", pdg.bytesPerSector);
 
                    diskSize = pdg.cylinders * pdg.tracksPerCylinder *
                    pdg.sectorsPerTrack * pdg.bytesPerSector;
                    Console.WriteLine("  Disk size = {0} (Bytes) = {1} (Mb)\n", diskSize,
                    diskSize / (1024 * 1024));

Open in new window

Avatar of graye
graye
Flag of United States of America image

Just curious.... have you tried the "extended" versions of  this IOCTL call (IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) http://msdn.microsoft.com/en-us/library/aa365171(VS.85).aspx
Also, recall that actual drive geometry is a thing of the past... modern drives virutalize all of those parameters to be backwards compatible.   For example, on all modern drives, the number of physical sectors per cylinder changes as the cylinders get closer to the outer edge.
Avatar of jason4659
jason4659

ASKER

I've tried using IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, but I'm using hex values to define these methods and I haven't been able to find the hex value for this call.  Any ideas on the best place to find these values?
You can find almost everything on P/Invoke "wiki" http://www.pinvoke.net/
 
That's the source I've been using for a lot of help, but unfortunately they don't offer help with the extended version of GetDriveGeometry..
ASKER CERTIFIED SOLUTION
Avatar of graye
graye
Flag of United States of America image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer