IOCTL_DISK_GET_LENGTH_INFO doesn’t work on floppy disks

I was trying to write a floppy disk image to a physical disk the other day, and my home-made imaging tool was refusing to work.  Once I got around to tracking this down, it turned out that IOCTL_DISK_GET_LENGTH_INFO simply doesn’t work on floppy disks, returning error code 1, ERROR_INVALID_FUNCTION, Incorrect Function.

This happens on both Windows XP and Windows 7, and presumably on other versions as well.  I suspect Microsoft would categorise this as a feature rather than a bug. 🙂

I’m not sure if this is the best workaround, but it’s what I came up with.  Note that IOCTL_DISK_GET_DRIVE_GEOMETRY_EX also doesn’t work for floppy disks.

I haven’t tested this with, e.g., ZIP disks, or with a wide range of USB memory sticks.  Feel free to copy-and-paste this code segment into your own project if it will help, but it comes without any warranty, express or implied.

if (!DeviceIoControl
 (
  houtput,
  IOCTL_DISK_GET_DRIVE_GEOMETRY,
  NULL,
  0,
  &target_diskgeometry,
  sizeof(target_diskgeometry),
  &byte_count,
  NULL
 ))
{
 err = GetLastError();
 fprintf(stderr, "Error %u getting output device geometry.\n", err);
 return err;
}

switch (target_diskgeometry.MediaType)
{
case Unknown:
case RemovableMedia:
case FixedMedia:

 if (!DeviceIoControl
  (
   houtput,
   IOCTL_DISK_GET_LENGTH_INFO,
   NULL,
   0,
   &target_disklength,
   sizeof(target_disklength),
   &byte_count,
   NULL
  ))
 {
  err = GetLastError();
  fprintf(stderr, "Error %u getting output device length.\n", err);
  return err;
 }

 fprintf(stderr, "Output disk has %I64i bytes.\n\n", target_disklength.Length.QuadPart);
 break;

default:

 target_disklength.Length.QuadPart =
  target_diskgeometry.Cylinders.QuadPart *
  target_diskgeometry.TracksPerCylinder *
  target_diskgeometry.SectorsPerTrack *
  target_diskgeometry.BytesPerSector;

 fprintf(stderr,
  "\n"
  "Output device appears to be a floppy disk.  WARNING: if this is not a\n"
  "floppy disk the calculated output device size is probably incorrect,\n"
  "which might result in an incomplete copy.\n"
  "\n"
  "Output disk has %I64i bytes.\n"
  "\n",
  target_disklength.Length.QuadPart);

 break;
}

Hope this helps.

Addendum: note that the figures returned by IOCTL_DISK_GET_DRIVE_GEOMETRY don’t give you the correct device length for hard disk drives, so that’s why this code uses IOCTL_DISK_GET_LENGTH_INFO unless the device is a floppy disk.

Advertisements

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: