OSDN Git Service

* errno.cc (errmap): Map ERROR_BEGINNING_OF_MEDIA and
authorcorinna <corinna>
Sun, 14 Mar 2004 18:01:45 +0000 (18:01 +0000)
committercorinna <corinna>
Sun, 14 Mar 2004 18:01:45 +0000 (18:01 +0000)
ERROR_SETMARK_DETECTED to EIO instead of ESPIPE.
Handle ERROR_FILEMARK_DETECTED.
* fhandler_tape.cc (TAPE_FUNC): Add comment that ERROR_BUS_RESET
has still to be handled correctly.
(fhandler_dev_tape::open): Accomodate fact that get.mt_dsreg
also contains density code.
(fhandler_dev_tape::ioctl): Rearrange slightly.  Reset devbuf also on
MTNOP, MTWSM, MTSETBLK, MTSETDRVBUFFER, MTSETPART and MTMKPART.
(fhandler_dev_tape::tape_set_pos): Rearrange.  Match behaviour to
the Linux tape driver.
(fhandler_dev_tape::tape_status): Call IOCTL_STORAGE_GET_MEDIA_TYPES_EX
if available.  Return device type and density code in appropriate
mtget members.
* wincap.h (wincaps::has_ioctl_storage_get_media_types_ex): New element.
* wincap.cc: Implement above element throughout.
* include/cygwin/mtio.h: Add tape device types as returned by
IOCTL_STORAGE_GET_MEDIA_TYPES_EX.
(MT_TAPE_INFO): Use above type codes.
(struct mtget): Change mt_dsreg comment.

winsup/cygwin/ChangeLog
winsup/cygwin/errno.cc
winsup/cygwin/fhandler_tape.cc
winsup/cygwin/include/cygwin/mtio.h
winsup/cygwin/wincap.cc
winsup/cygwin/wincap.h

index 98a69c5..712880a 100644 (file)
@@ -1,7 +1,30 @@
+2004-03-12  Corinna Vinschen  <corinna@vinschen.de>
+
+       * errno.cc (errmap): Map ERROR_BEGINNING_OF_MEDIA and
+       ERROR_SETMARK_DETECTED to EIO instead of ESPIPE.
+       Handle ERROR_FILEMARK_DETECTED.
+       * fhandler_tape.cc (TAPE_FUNC): Add comment that ERROR_BUS_RESET
+       has still to be handled correctly.
+       (fhandler_dev_tape::open): Accomodate fact that get.mt_dsreg
+       also contains density code.
+       (fhandler_dev_tape::ioctl): Rearrange slightly.  Reset devbuf also on
+       MTNOP, MTWSM, MTSETBLK, MTSETDRVBUFFER, MTSETPART and MTMKPART.
+       (fhandler_dev_tape::tape_set_pos): Rearrange.  Match behaviour to
+       the Linux tape driver.
+       (fhandler_dev_tape::tape_status): Call IOCTL_STORAGE_GET_MEDIA_TYPES_EX
+       if available.  Return device type and density code in appropriate
+       mtget members.
+       * wincap.h (wincaps::has_ioctl_storage_get_media_types_ex): New element.
+       * wincap.cc: Implement above element throughout.
+       * include/cygwin/mtio.h: Add tape device types as returned by
+       IOCTL_STORAGE_GET_MEDIA_TYPES_EX.
+       (MT_TAPE_INFO): Use above type codes.
+       (struct mtget): Change mt_dsreg comment.
+
 2004-03-14  Pierre Humblet <pierre.humblet@ieee.org>
 
-        * dir.cc (rmdir): Construct real_dir with flag PC_FULL.
-        Use a loop instead of recursion to handle the current directory.
+       * dir.cc (rmdir): Construct real_dir with flag PC_FULL.
+       Use a loop instead of recursion to handle the current directory.
 
 2004-03-14  Christopher Faylor  <cgf@redhat.com>
 
index 27284ba..2c7915c 100644 (file)
@@ -102,8 +102,8 @@ static NO_COPY struct
   X (NOT_OWNER,                        EPERM),
   X (END_OF_MEDIA,             ENOSPC),
   X (EOM_OVERFLOW,             ENOSPC),
-  X (BEGINNING_OF_MEDIA,       ESPIPE),
-  X (SETMARK_DETECTED,         ESPIPE),
+  X (BEGINNING_OF_MEDIA,       EIO),
+  X (SETMARK_DETECTED,         EIO),
   X (NO_DATA_DETECTED,         ENOSPC),
   X (POSSIBLE_DEADLOCK,                EDEADLOCK),
   X (CRC,                      EIO),
@@ -115,6 +115,7 @@ static NO_COPY struct
   X (INVALID_ADDRESS,          EOVERFLOW),
   X (INVALID_BLOCK_LENGTH,     EIO),
   X (BUS_RESET,                        EIO),
+  X (FILEMARK_DETECTED,                EIO),
   { 0, NULL, 0}
 };
 
index 0b74520..2fa5f43 100644 (file)
@@ -12,7 +12,9 @@ details. */
 #include "winsup.h"
 #include <sys/termios.h>
 #include <unistd.h>
+#include <stdlib.h>
 #include <sys/mtio.h>
+#include <ddk/ntddstor.h>
 #include "cygerrno.h"
 #include "perprocess.h"
 #include "security.h"
@@ -24,6 +26,10 @@ details. */
 /* Media changes and bus resets are sometimes reported and the function
    hasn't been executed.  We repeat all functions which return with one
    of these error codes. */
+/* FIXME: Note that this is wrong!  The correct behaviour after getting
+   an ERROR_BUS_RESET is to raise a flag and then to block any access,
+   except for MTREW, MTOFFL, MT_RETEN, MTERASE, MTSEEK and MTEOM, and
+   to set errno to EIO in all other cases. */
 #define TAPE_FUNC(func) do { \
                          lasterr = (func); \
                        } while (lasterr == ERROR_MEDIA_CHANGED \
@@ -127,12 +133,16 @@ fhandler_dev_tape::open (int flags, mode_t)
                                    (varlen = sizeof dp, &varlen), &dp));
 
       if (!ioctl (MTIOCGET, &get))
-       /* Tape drive supports and is set to variable block size. */
-       if (get.mt_dsreg == 0)
-         devbufsiz = get.mt_maxblksize;
-       else
-         devbufsiz = get.mt_dsreg;
-       varblkop = get.mt_dsreg == 0;
+        {
+         long blksize = (get.mt_dsreg & MT_ST_BLKSIZE_MASK)
+                        >> MT_ST_BLKSIZE_SHIFT;
+         /* Tape drive supports and is set to variable block size. */
+         if (blksize == 0)
+           devbufsiz = get.mt_maxblksize;
+         else
+           devbufsiz = blksize;
+         varblkop = blksize == 0;
+       }
 
       if (devbufsiz > 1L)
        devbuf = new char [devbufsiz];
@@ -319,9 +329,11 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
            ret = tape_set_pos (TAPE_REWIND, 0);
            break;
          case MTOFFL:
+         case MTUNLOAD:
            ret = tape_prepare (TAPE_UNLOAD);
            break;
          case MTNOP:
+           reset_devbuf ();
            break;
          case MTRETEN:
            if (!tape_get_feature (TAPE_DRIVE_END_OF_DATA))
@@ -350,63 +362,59 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
            ret = ERROR_INVALID_PARAMETER;
            break;
          case MTSETBLK:
-           {
-             if (!tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
-               {
-                 ret = ERROR_INVALID_PARAMETER;
-                 break;
-               }
-             if ((devbuf && (size_t) op->mt_count == devbufsiz)
-                 || (!devbuf && op->mt_count == 0))
-               {
-                 /* Nothing has changed. */
-                 ret = 0;
-                 break;
-               }
-             if ((op->mt_count == 0
-                  && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
-                 || (op->mt_count > 0
-                     && ((DWORD) op->mt_count < dp.MinimumBlockSize
-                         || (DWORD) op->mt_count > dp.MaximumBlockSize)))
-               {
-                 ret = ERROR_INVALID_PARAMETER;
-                 break;
-               }
-             if (devbuf && devbufend - devbufstart > 0
-                 && (op->mt_count == 0
-                     || (op->mt_count > 0
-                         && (size_t) op->mt_count < devbufend - devbufstart)))
-               {
-                 /* Not allowed if still data in devbuf. */
-                 ret = ERROR_INVALID_BLOCK_LENGTH; /* EIO */
-                 break;
-               }
-             if (!(ret = tape_set_blocksize (op->mt_count)))
-               {
-                 char *buf = NULL;
-                 if (op->mt_count > 1L && !(buf = new char [op->mt_count]))
-                   {
-                     ret = ERROR_OUTOFMEMORY;
-                     break;
-                   }
-                 if (devbufsiz > 1L && op->mt_count > 1L)
-                   {
-                     memcpy (buf, devbuf + devbufstart,
-                             devbufend - devbufstart);
-                     devbufend -= devbufstart;
-                   }
-                 else
-                   devbufend = 0;
-                 devbufstart = 0;
-                 delete [] devbuf;
-                 devbuf = buf;
-                 devbufsiz = op->mt_count;
-                 varblkop = op->mt_count == 0;
-               }
-           }
-           break;
-         case MTSETDENSITY:
-           ret = ERROR_INVALID_PARAMETER;
+           if (!tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
+             {
+               ret = ERROR_INVALID_PARAMETER;
+               break;
+             }
+           if ((devbuf && (size_t) op->mt_count == devbufsiz)
+               || (!devbuf && op->mt_count == 0))
+             {
+               /* Nothing has changed. */
+               ret = 0;
+               break;
+             }
+           if ((op->mt_count == 0
+                && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
+               || (op->mt_count > 0
+                   && ((DWORD) op->mt_count < dp.MinimumBlockSize
+                       || (DWORD) op->mt_count > dp.MaximumBlockSize)))
+             {
+               ret = ERROR_INVALID_PARAMETER;
+               break;
+             }
+           if (devbuf && devbufend - devbufstart > 0
+               && (op->mt_count == 0
+                   || (op->mt_count > 0
+                       && (size_t) op->mt_count < devbufend - devbufstart)))
+             {
+               /* Not allowed if still data in devbuf. */
+               ret = ERROR_INVALID_BLOCK_LENGTH; /* EIO */
+               break;
+             }
+           if (!(ret = tape_set_blocksize (op->mt_count)))
+             {
+               char *buf = NULL;
+               if (op->mt_count > 1L && !(buf = new char [op->mt_count]))
+                 {
+                   ret = ERROR_OUTOFMEMORY;
+                   break;
+                 }
+               if (devbufsiz > 1L && op->mt_count > 1L)
+                 {
+                   memcpy (buf, devbuf + devbufstart,
+                           devbufend - devbufstart);
+                   devbufend -= devbufstart;
+                 }
+               else
+                 devbufend = 0;
+               devbufstart = 0;
+               delete [] devbuf;
+               devbuf = buf;
+               devbufsiz = op->mt_count;
+               varblkop = op->mt_count == 0;
+             }
+           reset_devbuf ();
            break;
          case MTSEEK:
            if (tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK)
@@ -420,9 +428,6 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
            if (!(ret = tape_get_pos (&block)))
              op->mt_count = block;
            break;
-         case MTSETDRVBUFFER:
-           ret = ERROR_INVALID_PARAMETER;
-           break;
          case MTFSS:
            ret = tape_set_pos (TAPE_SPACE_SETMARKS, op->mt_count);
            break;
@@ -431,6 +436,7 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
            break;
          case MTWSM:
            ret = tape_write_marks (TAPE_SETMARKS, op->mt_count);
+           reset_devbuf ();
            break;
          case MTLOCK:
            ret = tape_prepare (TAPE_LOCK);
@@ -441,14 +447,14 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
          case MTLOAD:
            ret = tape_prepare (TAPE_LOAD);
            break;
-         case MTUNLOAD:
-           ret = tape_prepare (TAPE_UNLOAD);
-           break;
          case MTCOMPRESSION:
            ret = tape_compression (op->mt_count);
            break;
          case MTSETPART:
          case MTMKPART:
+         case MTSETDENSITY:
+         case MTSETDRVBUFFER:
+           reset_devbuf ();
          default:
            ret = ERROR_INVALID_PARAMETER;
            break;
@@ -541,67 +547,29 @@ fhandler_dev_tape::_tape_set_pos (int mode, long count)
 int
 fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func)
 {
-  unsigned long pos, tgtpos;
-
   switch (mode)
     {
       case TAPE_SPACE_RELATIVE_BLOCKS:
-       if (tape_get_pos (&pos))
-         return lasterr;
-
-       tgtpos = pos + count;
-
-       while (count && (_tape_set_pos (mode, count), IS_EOF (lasterr)))
-         {
-           if (tape_get_pos (&pos))
-             return lasterr;
-           count = tgtpos - pos;
-         }
-
-       if (lasterr == ERROR_BEGINNING_OF_MEDIA && !tgtpos)
-         lasterr = NO_ERROR;
-
-       break;
       case TAPE_SPACE_FILEMARKS:
-       if (count < 0)
-         {
-           if (pos > 0)
-             {
-               if (!_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -1)
-                   || (sfm_func))
-                 ++count;
-               _tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, 1);
-             }
-
-           while (!_tape_set_pos (mode, -1) && count++ < 0)
-             ;
-
-           if (lasterr == ERROR_BEGINNING_OF_MEDIA)
-             {
-               if (!count)
-                 lasterr = NO_ERROR;
-             }
-           else if (!sfm_func)
-             _tape_set_pos (mode, 1);
-         }
-       else
+        if (!count)
          {
-           if (sfm_func)
-             {
-               if (_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, 1)
-                   == ERROR_FILEMARK_DETECTED)
-                 ++count;
-               _tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -1);
-             }
-
-           if (!_tape_set_pos (mode, count) && sfm_func)
-             _tape_set_pos (mode, -1);
+           lasterr = 0;
+           return tape_error ("tape_set_pos");
          }
        break;
       case TAPE_ABSOLUTE_BLOCK:
-       if (!tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK))
+        if (!tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK))
          mode = TAPE_LOGICAL_BLOCK;
-       _tape_set_pos (mode, count);
+       break;
+    }
+  _tape_set_pos (mode, count);
+  switch (mode)
+    {
+      case TAPE_SPACE_FILEMARKS:
+       if (!lasterr && sfm_func)
+         return tape_set_pos (mode, count > 0 ? -1 : 1, false);
+       break;
+      case TAPE_ABSOLUTE_BLOCK:
        /* Workaround bug in Tandberg SLR device driver, which pretends
           to support absolute block positioning but instead returns
           ERROR_INVALID_FUNCTION. */
@@ -612,13 +580,7 @@ fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func)
            _tape_set_pos (TAPE_LOGICAL_BLOCK, count);
          }
          break;
-      case TAPE_SPACE_SETMARKS:
-      case TAPE_SPACE_END_OF_DATA:
-      case TAPE_REWIND:
-       _tape_set_pos (mode, count);
-       break;
     }
-
   return tape_error ("tape_set_pos");
 }
 
@@ -693,10 +655,37 @@ fhandler_dev_tape::tape_status (struct mtget *get)
     }
 
   if (tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE) && !notape)
-    get->mt_dsreg = mp.BlockSize;
+    get->mt_dsreg = (mp.BlockSize << MT_ST_BLKSIZE_SHIFT)
+                   & MT_ST_BLKSIZE_MASK;
   else
-    get->mt_dsreg = dp.DefaultBlockSize;
-
+    get->mt_dsreg = (dp.DefaultBlockSize << MT_ST_BLKSIZE_SHIFT)
+                   & MT_ST_BLKSIZE_MASK;
+  if (wincap.has_ioctl_storage_get_media_types_ex ())
+    {
+      DWORD size = sizeof (GET_MEDIA_TYPES) + 10 * sizeof (DEVICE_MEDIA_INFO);
+      void *buf = alloca (size);
+      if (DeviceIoControl (get_handle (), IOCTL_STORAGE_GET_MEDIA_TYPES_EX,
+                          NULL, 0, buf, size, &size, NULL)
+         || GetLastError () == ERROR_MORE_DATA)
+       {
+         PGET_MEDIA_TYPES gmt = (PGET_MEDIA_TYPES) buf;
+         for (DWORD i = 0; i < gmt->MediaInfoCount; ++i)
+           {
+             PDEVICE_MEDIA_INFO dmi = &gmt->MediaInfo[i];
+#define TINFO DeviceSpecific.TapeInfo
+             if (dmi->TINFO.MediaCharacteristics & MEDIA_CURRENTLY_MOUNTED)
+               {
+                 get->mt_type = dmi->DeviceSpecific.TapeInfo.MediaType;
+                 if (dmi->TINFO.BusType == BusTypeScsi)
+                   get->mt_dsreg |=
+                     (dmi->TINFO.BusSpecificData.ScsiInformation.DensityCode
+                      << MT_ST_DENSITY_SHIFT)
+                     & MT_ST_DENSITY_MASK;
+               }
+#undef TINFO
+           }
+       }
+    }
   if (notape)
     get->mt_gstat |= GMT_DR_OPEN (-1);
 
index 04e6523..dabf812 100644 (file)
@@ -89,8 +89,8 @@ struct        mtget {
                                 *  Cygwin: remaining KB.
                                 */
        /* the following registers are device dependent */
-       long    mt_dsreg;       /* status register, Cygwin returns current
-                                  blocksize here. */
+       long    mt_dsreg;       /* status register, Contains blocksize and
+                                  density code.  See MT_ST_xxx macros below */
        long    mt_gstat;       /* generic (device independent) status */
        long    mt_erreg;       /* error register */
        /* The next two fields are not always used */
@@ -157,6 +157,8 @@ struct      mtpos {
 /*
  * Constants for mt_type. Not all of these are supported,
  * and these are not all of the ones that are supported.
+ *
+ * Only used when not colliding with Windows codes (see below)
  */
 #define MT_ISUNKNOWN           0x01
 #define MT_ISQIC02             0x02    /* Generic QIC-02 tape streamer */
@@ -177,6 +179,41 @@ struct     mtpos {
 #define MT_ISSCSI1             0x71    /* Generic ANSI SCSI-1 tape unit */
 #define MT_ISSCSI2             0x72    /* Generic ANSI SCSI-2 tape unit */
 
+/* More constants for mt_type.  These are the codes used by Windows >= 5.1 */
+#define MT_ISDDS_4mm           0x20
+#define MT_ISMiniQic           0x21
+#define MT_ISTravan            0x22
+#define MT_ISQIC               0x23
+#define MT_ISMP_8mm            0x24
+#define MT_ISAME_8mm           0x25
+#define MT_ISAIT1_8mm          0x26
+#define MT_ISDLT               0x27
+#define MT_ISNCTP              0x28
+#define MT_ISIBM_3480          0x29
+#define MT_ISIBM_3490E                 0x2a
+#define MT_ISIBM_Magstar_3590  0x2b
+#define MT_ISIBM_Magstar_MP    0x2c
+#define MT_ISSTK_DATA_D3       0x2d
+#define MT_ISSONY_DTF          0x2e
+#define MT_ISDV_6mm            0x2f
+#define MT_ISDMI               0x30
+#define MT_ISSONY_D2           0x31
+#define MT_ISCLEANER_CARTRIDGE         0x32
+#define MT_ISAVATAR_F2                 0x4f
+#define MT_ISMP2_8mm           0x50
+#define MT_ISDST_S             0x51
+#define MT_ISDST_M             0x52
+#define MT_ISDST_L             0x53
+#define MT_ISVXATape_1                 0x54
+#define MT_ISVXATape_2                 0x55
+#define MT_ISSTK_9840          0x56
+#define MT_ISLTO_Ultrium       0x57
+#define MT_ISLTO_Accelis       0x58
+#define MT_ISAIT_8mm           0x5a
+#define MT_ISADR_1             0x5b
+#define MT_ISADR_2             0x5c
+#define MT_ISSTK_9940          0x5d
+
 struct mt_tape_info {
        long t_type;            /* device type id (mt_type) */
        char *t_name;           /* descriptive name */
@@ -196,7 +233,39 @@ struct mt_tape_info {
        {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \
        {MT_ISWT5099EEN24,      "Wangtek 5099-een24, 60MB"}, \
        {MT_ISTEAC_MT2ST,       "Teac MT-2ST 155mb data cassette drive"}, \
-       {MT_ISEVEREX_FT40A,     "Everex FT40A, QIC-40"}, \
+       {MT_ISDDS_4mm,          "DDS"}, \
+       {MT_ISMiniQic,          "MiniQic"}, \
+       {MT_ISTravan,           "Travan tape"}, \
+       {MT_ISQIC,              "QIC tape"}, \
+       {MT_ISMP_8mm,           "8mm Exabyte metal particle tape"}, \
+       {MT_ISAME_8mm,          "8mm Exabyte advanced metal evap tape"}, \
+       {MT_ISAIT1_8mm,         "8mm Sony AIT1 tape"}, \
+       {MT_ISDLT,              "DLT compact tape)"}, \
+       {MT_ISNCTP,             "Philips NCTP tape"}, \
+       {MT_ISIBM_3480,         "IBM 3480 tape"}, \
+       {MT_ISIBM_3490E,        "IBM 3490E tape"}, \
+       {MT_ISIBM_Magstar_3590, "IBM Magstar 3590 tape"}, \
+       {MT_ISIBM_Magstar_MP,   "IBM Magstar MP tape"}, \
+       {MT_ISSTK_DATA_D3,      "STK data D3 tape"}, \
+       {MT_ISSONY_DTF,         "Sony DTF tape"}, \
+       {MT_ISDV_6mm,           "6mm digital video tape"}, \
+       {MT_ISDMI,              "Exabyte DMI tape"}, \
+       {MT_ISSONY_D2,          "Sony D2S or D2L tape"}, \
+       {MT_ISCLEANER_CARTRIDGE, "Cleaner (all drive types that support cleaners)"}, \
+       {MT_ISAVATAR_F2,        "Avatar 2"}, \
+       {MT_ISMP2_8mm,          "8mm Hitachi tape"}, \
+       {MT_ISDST_S,            "Ampex DST small tape"}, \
+       {MT_ISDST_M,            "Ampex DST medium tape"}, \
+       {MT_ISDST_L,            "Ampex DST large tape"}, \
+       {MT_ISVXATape_1,        "Ecrix 8mm tape"}, \
+       {MT_ISVXATape_2,        "Ecrix 8mm tape"}, \
+       {MT_ISSTK_9840,         "STK 9840"}, \
+       {MT_ISLTO_Ultrium,      "LTO Ultrium (IBM, HP, Seagate)"}, \
+       {MT_ISLTO_Accelis,      "LTO Accelis (IBM, HP, Seagate)"}, \
+       {MT_ISAIT_8mm,          "AIT tape (AIT2 or higher)"}, \
+       {MT_ISADR_1,            "OnStream ADR1"}, \
+       {MT_ISADR_2,            "OnStream ADR2"}, \
+       {MT_ISSTK_9940,         "STK 9940"}, \
        {MT_ISSCSI1,            "Generic SCSI-1 tape"}, \
        {MT_ISSCSI2,            "Generic SCSI-2 tape"}, \
        {0, NULL} \
index dfa9a6d..4018a6e 100644 (file)
@@ -52,7 +52,8 @@ static NO_COPY wincaps wincap_unknown = {
   pty_needs_alloc_console:false,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_95 = {
@@ -96,7 +97,8 @@ static NO_COPY wincaps wincap_95 = {
   pty_needs_alloc_console:false,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:true
+  cant_debug_dll_entry:true,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_95osr2 = {
@@ -140,7 +142,8 @@ static NO_COPY wincaps wincap_95osr2 = {
   pty_needs_alloc_console:false,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:true
+  cant_debug_dll_entry:true,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_98 = {
@@ -184,7 +187,8 @@ static NO_COPY wincaps wincap_98 = {
   pty_needs_alloc_console:false,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:true
+  cant_debug_dll_entry:true,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_98se = {
@@ -228,7 +232,8 @@ static NO_COPY wincaps wincap_98se = {
   pty_needs_alloc_console:false,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:true
+  cant_debug_dll_entry:true,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_me = {
@@ -272,7 +277,8 @@ static NO_COPY wincaps wincap_me = {
   pty_needs_alloc_console:false,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:true
+  cant_debug_dll_entry:true,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_nt3 = {
@@ -316,7 +322,8 @@ static NO_COPY wincaps wincap_nt3 = {
   pty_needs_alloc_console:true,
   has_terminal_services:false,
   has_switch_to_thread:false,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_nt4 = {
@@ -360,7 +367,8 @@ static NO_COPY wincaps wincap_nt4 = {
   pty_needs_alloc_console:true,
   has_terminal_services:false,
   has_switch_to_thread:true,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_nt4sp4 = {
@@ -404,7 +412,8 @@ static NO_COPY wincaps wincap_nt4sp4 = {
   pty_needs_alloc_console:true,
   has_terminal_services:false,
   has_switch_to_thread:true,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_2000 = {
@@ -448,7 +457,8 @@ static NO_COPY wincaps wincap_2000 = {
   pty_needs_alloc_console:true,
   has_terminal_services:true,
   has_switch_to_thread:true,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:false
 };
 
 static NO_COPY wincaps wincap_xp = {
@@ -492,7 +502,8 @@ static NO_COPY wincaps wincap_xp = {
   pty_needs_alloc_console:true,
   has_terminal_services:true,
   has_switch_to_thread:true,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:true
 };
 
 static NO_COPY wincaps wincap_2003 = {
@@ -536,7 +547,8 @@ static NO_COPY wincaps wincap_2003 = {
   pty_needs_alloc_console:true,
   has_terminal_services:true,
   has_switch_to_thread:true,
-  cant_debug_dll_entry:false
+  cant_debug_dll_entry:false,
+  has_ioctl_storage_get_media_types_ex:true
 };
 
 wincapc wincap;
index 7794f0e..cdda1d8 100644 (file)
@@ -54,6 +54,7 @@ struct wincaps
   unsigned has_terminal_services                       : 1;
   unsigned has_switch_to_thread                                : 1;
   unsigned cant_debug_dll_entry                                : 1;
+  unsigned has_ioctl_storage_get_media_types_ex                : 1;
 };
 
 class wincapc
@@ -112,6 +113,7 @@ public:
   bool  IMPLEMENT (has_terminal_services)
   bool  IMPLEMENT (has_switch_to_thread)
   bool IMPLEMENT (cant_debug_dll_entry)
+  bool IMPLEMENT (has_ioctl_storage_get_media_types_ex)
 
 #undef IMPLEMENT
 };