OSDN Git Service

* fhandler_floppy.cc (fhandler_dev_floppy::get_drive_info): Always
authorcorinna <corinna>
Tue, 27 Sep 2005 15:33:00 +0000 (15:33 +0000)
committercorinna <corinna>
Tue, 27 Sep 2005 15:33:00 +0000 (15:33 +0000)
try IOCTL_DISK_GET_DRIVE_GEOMETRY_EX and
IOCTL_DISK_GET_PARTITION_INFO_EX ioctls first, to allow access to GPT
partitioned disks.  Fall back to old non-EX ioctls otherwise.
Add comment to explain NT4 weirdness.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler_floppy.cc

index bb9b37a..c29f841 100644 (file)
@@ -1,3 +1,11 @@
+2005-09-27  Corinna Vinschen  <corinna@vinschen.de>
+
+       * fhandler_floppy.cc (fhandler_dev_floppy::get_drive_info): Always
+       try IOCTL_DISK_GET_DRIVE_GEOMETRY_EX and
+       IOCTL_DISK_GET_PARTITION_INFO_EX ioctls first, to allow access to GPT
+       partitioned disks.  Fall back to old non-EX ioctls otherwise.
+       Add comment to explain NT4 weirdness.
+
 2005-09-26  Corinna Vinschen  <corinna@vinschen.de>
 
        * errno.cc (errmap): Map ERROR_SEEK and ERROR_SECTOR_NOT_FOUND.
index cafac8c..6f729ca 100644 (file)
@@ -52,48 +52,82 @@ fhandler_dev_floppy::fhandler_dev_floppy ()
 int
 fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo)
 {
-  DISK_GEOMETRY di;
-  PARTITION_INFORMATION pi;
+  char dbuf[256];
+  char pbuf[256];
+
+  DISK_GEOMETRY *di;
+  PARTITION_INFORMATION_EX *pix = NULL;
+  PARTITION_INFORMATION *pi = NULL;
   DWORD bytes_read = 0;
 
+  /* Always try using the new EX ioctls first (>= XP).  If not available,
+     fall back to trying the old non-EX ioctls. */
   if (!DeviceIoControl (get_handle (),
-                         IOCTL_DISK_GET_DRIVE_GEOMETRY,
-                         NULL, 0,
-                         &di, sizeof (di),
-                         &bytes_read, NULL))
+                       IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0,
+                       dbuf, 256, &bytes_read, NULL))
     {
-      __seterrno ();
-      return -1;
+      if (!DeviceIoControl (get_handle (),
+                           IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
+                           dbuf, 256, &bytes_read, NULL))
+       {
+         __seterrno ();
+         return -1;
+       }
+      di = (DISK_GEOMETRY *) dbuf;
     }
-  debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)",
-                di.Cylinders.LowPart,
-                di.TracksPerCylinder,
-                di.SectorsPerTrack,
-                di.BytesPerSector);
-  bytes_per_sector = di.BytesPerSector;
+  else
+    di = &((DISK_GEOMETRY_EX *) dbuf)->Geometry;
+    
   if (DeviceIoControl (get_handle (),
-                        IOCTL_DISK_GET_PARTITION_INFO,
-                        NULL, 0,
-                        &pi, sizeof (pi),
-                        &bytes_read, NULL))
+                      IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0,
+                      pbuf, 256, &bytes_read, NULL))
+    pix = (PARTITION_INFORMATION_EX *) pbuf;
+  else if (DeviceIoControl (get_handle (),
+                           IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
+                           pbuf, 256, &bytes_read, NULL))
+    pi = (PARTITION_INFORMATION *) pbuf;
+
+  debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)",
+                di->Cylinders.LowPart,
+                di->TracksPerCylinder,
+                di->SectorsPerTrack,
+                di->BytesPerSector);
+  bytes_per_sector = di->BytesPerSector;
+  if (pix)
+    {
+      debug_printf ("partition info: offset %D  length %D",
+                   pix->StartingOffset.QuadPart,
+                   pix->PartitionLength.QuadPart);
+      drive_size = pix->PartitionLength.QuadPart;
+    }
+  else if (pi)
     {
       debug_printf ("partition info: offset %D  length %D",
-                     pi.StartingOffset.QuadPart,
-                     pi.PartitionLength.QuadPart);
-      drive_size = pi.PartitionLength.QuadPart;
+                   pi->StartingOffset.QuadPart,
+                   pi->PartitionLength.QuadPart);
+      drive_size = pi->PartitionLength.QuadPart;
     }
   else
     {
-      drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder *
-                  di.SectorsPerTrack * di.BytesPerSector;
+      /* Getting the partition size by using the drive geometry information
+         looks wrong, but this is a historical necessity.  NT4 didn't maintain
+        partition information for the whole drive (aka "partition 0"), but
+        returned ERROR_INVALID_HANDLE instead.  That got fixed in W2K. */
+      drive_size = di->Cylinders.QuadPart * di->TracksPerCylinder *
+                  di->SectorsPerTrack * di->BytesPerSector;
     }
   debug_printf ("drive size: %D", drive_size);
   if (geo)
     {
-      geo->heads = di.TracksPerCylinder;
-      geo->sectors = di.SectorsPerTrack;
-      geo->cylinders = di.Cylinders.LowPart;
-      geo->start = pi.StartingOffset.QuadPart >> 9ULL;
+      geo->heads = di->TracksPerCylinder;
+      geo->sectors = di->SectorsPerTrack;
+      geo->cylinders = di->Cylinders.LowPart;
+      if (pix)
+       geo->start = pix->StartingOffset.QuadPart >> 9ULL;
+      else if (pi)
+       geo->start = pi->StartingOffset.QuadPart >> 9ULL;
+      else
+        geo->start = 0;
     }
   return 0;
 }