winedos / Migrate drive parameter block stuff to winedos, 2nd try

Jukka Heinonen jhei at iki.fi
Sun Oct 26 04:16:26 CST 2003


Okay, here is a fixed version of the patch.
The previous versos did not compile because
I changed magic value into sizeof and forgot to
do a test compilation.




Changelog:
  Move drive parameter block (DPB) routines to winedos.




Index: dlls/winedos/int21.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int21.c,v
retrieving revision 1.43
diff -u -r1.43 int21.c
--- dlls/winedos/int21.c	16 Oct 2003 19:12:49 -0000	1.43
+++ dlls/winedos/int21.c	26 Oct 2003 10:10:16 -0000
@@ -59,6 +59,42 @@
 #include "pshpack1.h"
 
 /*
+ * Extended Drive Parameter Block.
+ * This structure is compatible with standard DOS4+ DPB and 
+ * extended DOS7 DPB.
+ */
+typedef struct _INT21_DPB {
+    BYTE   drive;                /* 00 drive number (0=A, ...) */
+    BYTE   unit;                 /* 01 unit number within device driver */
+    WORD   sector_bytes;         /* 02 bytes per sector */
+    BYTE   cluster_sectors;      /* 04 highest sector number within a cluster */
+    BYTE   shift;                /* 05 shift count to convert clusters into sectors */
+    WORD   num_reserved;         /* 06 reserved sectors at beginning of drive */
+    BYTE   num_FAT;              /* 08 number of FATs */
+    WORD   num_root_entries;     /* 09 number of root directory entries */
+    WORD   first_data_sector;    /* 0b number of first sector containing user data */
+    WORD   num_clusters1;        /* 0d highest cluster number (number of data clusters + 1) */
+    WORD   sectors_per_FAT;      /* 0f number of sectors per FAT */
+    WORD   first_dir_sector;     /* 11 sector number of first directory sector */
+    SEGPTR driver_header;        /* 13 address of device driver header */
+    BYTE   media_ID;             /* 17 media ID byte */
+    BYTE   access_flag;          /* 18 0x00 if disk accessed, 0xff if not */
+    SEGPTR next;                 /* 19 pointer to next DPB */
+    WORD   search_cluster1;      /* 1d cluster at which to start search for free space */
+    WORD   free_clusters_lo;     /* 1f number of free clusters on drive or 0xffff if unknown */
+    WORD   free_clusters_hi;     /* 21 hiword of clusters_free */
+    WORD   mirroring_flags;      /* 23 active FAT/mirroring flags */
+    WORD   info_sector;          /* 25 sector number of file system info sector or 0xffff for none */
+    WORD   spare_boot_sector;    /* 27 sector number of backup boot sector or 0xffff for none */
+    DWORD  first_cluster_sector; /* 29 sector number of the first cluster */
+    DWORD  num_clusters2;        /* 2d maximum cluster number */
+    DWORD  fat_clusters;         /* 31 number of clusters occupied by FAT */
+    DWORD  root_cluster;         /* 35 cluster number of start of root directory */
+    DWORD  search_cluster2;      /* 39 cluster at which to start searching for free space */
+} INT21_DPB;
+
+
+/*
  * Structure for DOS data that can be accessed directly from applications.
  * Real and protected mode pointers will be returned to this structure so
  * the structure must be correctly packed.
@@ -87,7 +123,11 @@
     WORD dbcs_size;                  /* Number of valid ranges in the following table */
     BYTE dbcs_table[16];             /* Start/end bytes for N ranges and 00/00 as terminator */
 
-    BYTE misc_indos;                 /* Interrupt 21 nesting flag */
+    BYTE      misc_indos;                    /* Interrupt 21 nesting flag */
+    WORD      misc_segment;                  /* Real mode segment for INT21_HEAP */
+    WORD      misc_selector;                 /* Protected mode selector for INT21_HEAP */
+    INT21_DPB misc_dpb_list[MAX_DOS_DRIVES]; /* Drive parameter blocks for all drives */
+
 } INT21_HEAP;
 
 
@@ -353,6 +393,39 @@
      * Initialize InDos flag.
      */
     heap->misc_indos = 0;
+
+    /*
+     * FIXME: Should drive parameter blocks (DPB) be
+     *        initialized here and linked to DOS LOL?
+     */
+}
+
+
+/***********************************************************************
+ *           INT21_GetHeapPointer
+ *
+ * Get pointer for DOS heap (INT21_HEAP).
+ * Creates and initializes heap on first call.
+ */
+static INT21_HEAP *INT21_GetHeapPointer( void )
+{
+    static INT21_HEAP *heap_pointer = NULL;
+
+    if (!heap_pointer)
+    {
+        WORD heap_segment;
+        WORD heap_selector;
+
+        heap_pointer = DOSVM_AllocDataUMB( sizeof(INT21_HEAP), 
+                                           &heap_segment,
+                                           &heap_selector );
+
+        heap_pointer->misc_segment  = heap_segment;
+        heap_pointer->misc_selector = heap_selector;
+        INT21_FillHeap( heap_pointer );
+    }
+
+    return heap_pointer;
 }
 
 
@@ -364,23 +437,94 @@
  */
 static WORD INT21_GetHeapSelector( CONTEXT86 *context )
 {
-    static WORD heap_segment = 0;
-    static WORD heap_selector = 0;
-    static BOOL heap_initialized = FALSE;
-
-    if (!heap_initialized)
-    {
-        INT21_HEAP *ptr = DOSVM_AllocDataUMB( sizeof(INT21_HEAP), 
-                                              &heap_segment,
-                                              &heap_selector );
-        INT21_FillHeap( ptr );
-        heap_initialized = TRUE;
-    }
+    INT21_HEAP *heap = INT21_GetHeapPointer();
 
     if (!ISV86(context) && DOSVM_IsWin16())
-        return heap_selector;
+        return heap->misc_selector;
     else
-        return heap_segment;
+        return heap->misc_segment;
+}
+
+
+/***********************************************************************
+ *           INT21_FillDrivePB
+ *
+ * Fill DOS heap drive parameter block for the specified drive.
+ * Return TRUE if drive was valid and there were
+ * no errors while reading drive information.
+ */
+static BOOL INT21_FillDrivePB( BYTE drive )
+{
+    WCHAR       drivespec[3] = {'A', ':', 0};
+    INT21_HEAP *heap = INT21_GetHeapPointer();
+    INT21_DPB  *dpb;
+    UINT        drivetype;
+    DWORD       cluster_sectors;
+    DWORD       sector_bytes;
+    DWORD       free_clusters;
+    DWORD       total_clusters;
+
+    if (drive >= MAX_DOS_DRIVES)
+        return FALSE;
+
+    dpb = &heap->misc_dpb_list[drive];
+    drivespec[0] += drive;
+    drivetype = GetDriveTypeW( drivespec );
+
+    /*
+     * FIXME: Does this check work correctly with floppy/cdrom drives?
+     */
+    if (drivetype == DRIVE_NO_ROOT_DIR || drivetype == DRIVE_UNKNOWN)
+        return FALSE;
+
+    /*
+     * FIXME: Does this check work correctly with floppy/cdrom drives?
+     */
+    if (!GetDiskFreeSpaceW( drivespec, &cluster_sectors, &sector_bytes,
+                            &free_clusters, &total_clusters ))
+        return FALSE;
+
+    /*
+     * FIXME: Most of the values listed below are incorrect.
+     *        All values should be validated.
+     */
+ 
+    dpb->drive           = drive;
+    dpb->unit            = 0;
+    dpb->sector_bytes    = sector_bytes;
+    dpb->cluster_sectors = cluster_sectors - 1;
+
+    dpb->shift = 0;
+    while (cluster_sectors > 1)
+    {
+        cluster_sectors /= 2;
+        dpb->shift++;
+    }
+
+    dpb->num_reserved         = 0;
+    dpb->num_FAT              = 1;
+    dpb->num_root_entries     = 2;
+    dpb->first_data_sector    = 2;
+    dpb->num_clusters1        = total_clusters;
+    dpb->sectors_per_FAT      = 1;
+    dpb->first_dir_sector     = 1;
+    dpb->driver_header        = 0;
+    dpb->media_ID             = (drivetype == DRIVE_FIXED) ? 0xF8 : 0xF0;
+    dpb->access_flag          = 0;
+    dpb->next                 = 0;
+    dpb->search_cluster1      = 0;
+    dpb->free_clusters_lo     = LOWORD(free_clusters);
+    dpb->free_clusters_hi     = HIWORD(free_clusters);
+    dpb->mirroring_flags      = 0;
+    dpb->info_sector          = 0xffff;
+    dpb->spare_boot_sector    = 0xffff;
+    dpb->first_cluster_sector = 0;
+    dpb->num_clusters2        = total_clusters;
+    dpb->fat_clusters         = 32;
+    dpb->root_cluster         = 0;
+    dpb->search_cluster2      = 0;
+
+    return TRUE;
 }
 
 
@@ -2283,6 +2427,62 @@
 
 
 /***********************************************************************
+ *           INT21_Fat32
+ *
+ * Handler for function 0x73.
+ */
+static BOOL INT21_Fat32( CONTEXT86 *context )
+{
+    switch (AL_reg(context))
+    {
+    case 0x02: /* FAT32 - GET EXTENDED DPB */
+        {
+            BYTE drive = INT21_MapDrive( DL_reg(context) );
+            WORD *ptr = CTX_SEG_OFF_TO_LIN(context, 
+                                           context->SegEs, context->Edi);
+            INT21_DPB *target = (INT21_DPB*)(ptr + 1);
+            INT21_DPB *source;
+
+            TRACE( "FAT32 - GET EXTENDED DPB %d\n", DL_reg(context) );
+
+            if ( CX_reg(context) < sizeof(INT21_DPB) + 2 || *ptr < sizeof(INT21_DPB) )
+            {
+                SetLastError( ERROR_BAD_LENGTH );
+                return FALSE;
+            }
+
+            if ( !INT21_FillDrivePB( drive ) )
+            {
+                SetLastError( ERROR_INVALID_DRIVE );
+                return FALSE;
+            }
+
+            source = &INT21_GetHeapPointer()->misc_dpb_list[drive];
+
+            *ptr = sizeof(INT21_DPB);
+            memcpy( target, source, sizeof(INT21_DPB));
+
+            if (LOWORD(context->Esi) != 0xF1A6)
+            {
+                target->driver_header = 0;
+                target->next          = 0;
+            }
+            else
+            {
+                FIXME( "Caller requested driver and next DPB pointers!\n" );
+            }
+        }
+        break;
+
+    default:
+        INT_BARF( context, 0x21 );
+    }
+
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           INT21_LongFilename
  *
  * Handler for function 0x71.
@@ -2862,7 +3062,21 @@
         break;
 
     case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
-        INT_Int21Handler( context );
+        {
+            BYTE drive = INT21_MapDrive( 0 ); 
+            TRACE( "GET DPB FOR DEFAULT DRIVE\n" );
+
+            if (INT21_FillDrivePB( drive ))
+            {
+                SET_AL( context, 0x00 ); /* success */
+                SET_BX( context, offsetof( INT21_HEAP, misc_dpb_list[drive] ) );
+                context->SegDs = INT21_GetHeapSelector( context );
+            }
+            else
+            {
+                SET_AL( context, 0xff ); /* invalid or network drive */
+            }
+        }
         break;
 
     case 0x20: /* NULL FUNCTION FOR CP/M COMPATIBILITY */
@@ -3008,7 +3222,21 @@
         break;
 
     case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
-        INT_Int21Handler( context );
+        {
+            BYTE drive = INT21_MapDrive( DL_reg(context) );           
+            TRACE( "GET DPB FOR SPECIFIC DRIVE %d\n", DL_reg(context) );
+
+            if (INT21_FillDrivePB( drive ))
+            {
+                SET_AL( context, 0x00 ); /* success */
+                SET_DX( context, offsetof( INT21_HEAP, misc_dpb_list[drive] ) );
+                context->SegDs = INT21_GetHeapSelector( context );
+            }
+            else
+            {
+                SET_AL( context, 0xff ); /* invalid or network drive */
+            }
+        }
         break;
 
     case 0x33: /* MULTIPLEXED */
@@ -3695,7 +3923,8 @@
         break;
 
     case 0x73: /* MSDOS7 - FAT32 */
-        INT_Int21Handler( context );
+        if (!INT21_Fat32( context ))
+            bSetDOSExtendedError = TRUE;
         break;
 
     case 0xdc: /* CONNECTION SERVICES - GET CONNECTION NUMBER */




Index: msdos/int21.c
===================================================================
RCS file: /home/wine/wine/msdos/int21.c,v
retrieving revision 1.99
diff -u -r1.99 int21.c
--- msdos/int21.c	22 Sep 2003 21:18:11 -0000	1.99
+++ msdos/int21.c	26 Oct 2003 10:10:19 -0000
@@ -73,62 +73,9 @@
 
 #define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive())
 
-/* Define the drive parameter block, as used by int21/1F
- * and int21/32.  This table can be accessed through the
- * global 'dpb' pointer, which points into the local dos
- * heap.
- */
-struct DPB
-{
-    BYTE drive_num;         /* 0=A, etc. */
-    BYTE unit_num;          /* Drive's unit number (?) */
-    WORD sector_size;       /* Sector size in bytes */
-    BYTE high_sector;       /* Highest sector in a cluster */
-    BYTE shift;             /* Shift count (?) */
-    WORD reserved;          /* Number of reserved sectors at start */
-    BYTE num_FAT;           /* Number of FATs */
-    WORD dir_entries;       /* Number of root dir entries */
-    WORD first_data;        /* First data sector */
-    WORD high_cluster;      /* Highest cluster number */
-    WORD sectors_in_FAT;    /* Number of sectors per FAT */
-    WORD start_dir;         /* Starting sector of first dir */
-    DWORD driver_head;      /* Address of device driver header (?) */
-    BYTE media_ID;          /* Media ID */
-    BYTE access_flag;       /* Prev. accessed flag (0=yes,0xFF=no) */
-    DWORD next;             /* Pointer to next DPB in list */
-    WORD free_search;       /* Free cluster search start */
-    WORD free_clusters;     /* Number of free clusters (0xFFFF=unknown) */
-};
-
-struct EDPB			/* FAT32 extended Drive Parameter Block */
-{				/* from Ralf Brown's Interrupt List */
-	struct DPB dpb;		/* first 24 bytes = original DPB */
-
-	BYTE edpb_flags;	/* undocumented/unknown flags */
-	DWORD next_edpb;	/* pointer to next EDPB */
-	WORD free_cluster;	/* cluster to start search for free space on write, typically
-	                           the last cluster allocated */
-	WORD clusters_free;	/* number of free clusters on drive or FFFF = unknown */
-	WORD clusters_free_hi;	/* hiword of clusters_free */
-	WORD mirroring_flags;	/* mirroring flags: bit 7 set = do not mirror active FAT */
-				/* bits 0-3 = 0-based number of the active FAT */
-	WORD info_sector;	/* sector number of file system info sector, or FFFF for none */
-	WORD spare_boot_sector;	/* sector number of backup boot sector, or FFFF for none */
-	DWORD first_cluster;	/* sector number of the first cluster */
-	DWORD max_cluster;	/* sector number of the last cluster */
-	DWORD fat_clusters;	/* number of clusters occupied by FAT */
-	DWORD root_cluster;	/* cluster number of start of root directory */
-	DWORD free_cluster2;	/* same as free_cluster: cluster at which to start
-	                           search for free space when writing */
-
-};
-
-DWORD dpbsegptr;
-
 struct DosHeap {
         BYTE mediaID;
 	BYTE biosdate[8];
-        struct DPB dpb;
 };
 static struct DosHeap *heap;
 static WORD DosHeapHandle;
@@ -143,7 +90,6 @@
         return FALSE;
     }
     heap = (struct DosHeap *) GlobalLock16(DosHeapHandle);
-    dpbsegptr = MAKESEGPTR(DosHeapHandle,(int)&heap->dpb-(int)heap);
     strcpy(heap->biosdate, "01/01/80");
     return TRUE;
 }
@@ -223,60 +169,6 @@
     return 1;
 }
 
-static int FillInDrivePB( int drive )
-{
-        if(!DRIVE_IsValid(drive))
-        {
-            SetLastError( ERROR_INVALID_DRIVE );
-			return 0;
-        }
-        else if (heap || INT21_CreateHeap())
-        {
-                /* FIXME: I have no idea what a lot of this information should
-                 * say or whether it even really matters since we're not allowing
-                 * direct block access.  However, some programs seem to depend on
-                 * getting at least _something_ back from here.  The 'next' pointer
-                 * does worry me, though.  Should we have a complete table of
-                 * separate DPBs per drive?  Probably, but I'm lazy. :-)  -CH
-                 */
-                heap->dpb.drive_num = heap->dpb.unit_num = drive; /*The same?*/
-                heap->dpb.sector_size = 512;
-                heap->dpb.high_sector = 1;
-                heap->dpb.shift = drive < 2 ? 0 : 6; /*6 for HD, 0 for floppy*/
-                heap->dpb.reserved = 0;
-                heap->dpb.num_FAT = 1;
-                heap->dpb.dir_entries = 2;
-                heap->dpb.first_data = 2;
-                heap->dpb.high_cluster = 64000;
-                heap->dpb.sectors_in_FAT = 1;
-                heap->dpb.start_dir = 1;
-                heap->dpb.driver_head = 0;
-                heap->dpb.media_ID = (drive > 1) ? 0xF8 : 0xF0;
-                heap->dpb.access_flag = 0;
-                heap->dpb.next = 0;
-                heap->dpb.free_search = 0;
-                heap->dpb.free_clusters = 0xFFFF;    /* unknown */
-				return 1;
-		}
-
-		return 0;
-}
-
-static void GetDrivePB( CONTEXT86 *context, int drive )
-{
-	if (FillInDrivePB( drive ))
-	{
-                SET_AL( context, 0x00 );
-                context->SegDs = SELECTOROF(dpbsegptr);
-                SET_BX( context, OFFSETOF(dpbsegptr) );
-        }
-	else
-	{
-        SET_AX( context, 0x00ff );
-	}
-}
-
-
 static BOOL ioctlGenericBlkDevReq( CONTEXT86 *context )
 {
 	BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
@@ -722,20 +614,10 @@
         if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff );
         break;
 
-    case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
-        GetDrivePB(context, DRIVE_GetCurrentDrive());
-        break;
-
     case 0x29: /* PARSE FILENAME INTO FCB */
         INT21_ParseFileNameIntoFCB(context);
         break;
 
-    case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
-        TRACE("GET DOS DRIVE PARAMETER BLOCK FOR DRIVE %s\n",
-	      INT21_DriveName( DL_reg(context)));
-        GetDrivePB(context, DOS_GET_DRIVE( DL_reg(context) ) );
-        break;
-
     case 0x36: /* GET FREE DISK SPACE */
 	TRACE("GET FREE DISK SPACE FOR DRIVE %s\n",
 	      INT21_DriveName( DL_reg(context)));
@@ -940,86 +822,6 @@
             break;
         }
         break;
-
-
-    case 0x73: /* MULTIPLEXED: Win95 OSR2/Win98 FAT32 calls */
-        TRACE("windows95 function AX %04x\n",
-                    AX_reg(context));
-
-        switch (AL_reg(context))
-		{
-		case 0x02:	/* Get Extended Drive Parameter Block for specific drive */
-		    		/* ES:DI points to word with length of data (should be 0x3d) */
-			{
-				WORD *buffer;
-				struct EDPB *edpb;
-			    DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters;
-			    char root[] = "A:\\";
-
-				buffer = (WORD *)CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
-
-				TRACE("Get Extended DPB: linear buffer address is %p\n", buffer);
-
-				/* validate passed-in buffer lengths */
-				if ((*buffer != 0x3d) || (context->Ecx != 0x3f))
-				{
-					WARN("Get Extended DPB: buffer lengths incorrect\n");
-					WARN("CX = %lx, buffer[0] = %x\n", context->Ecx, *buffer);
-					SET_CFLAG(context);
-					SET_AL( context, 0x18 );		/* bad buffer length */
-				}
-
-				/* buffer checks out */
-				buffer++;		/* skip over length word now */
-				if (FillInDrivePB( DX_reg(context) ) )
-				{
-				 	edpb = (struct EDPB *)buffer;
-
-					/* copy down the old-style DPB portion first */
-					memcpy(&edpb->dpb, &heap->dpb, sizeof(struct DPB));
-
-					/* now fill in the extended entries */
-					edpb->edpb_flags = 0;
-					edpb->next_edpb = 0;
-					edpb->free_cluster = edpb->free_cluster2 = 0;
-
-					/* determine free disk space */
-				    *root += DOS_GET_DRIVE( DX_reg(context) );
-				    GetDiskFreeSpaceA( root, &cluster_sectors, &sector_bytes,
-                              &free_clusters, &total_clusters );
-
-					edpb->clusters_free = (free_clusters&0xffff);
-
-					edpb->clusters_free_hi = free_clusters >> 16;
-					edpb->mirroring_flags = 0;
-					edpb->info_sector = 0xffff;
-					edpb->spare_boot_sector = 0xffff;
-					edpb->first_cluster = 0;
-					edpb->max_cluster = total_clusters;
-					edpb->fat_clusters = 32;	/* made-up value */
-					edpb->root_cluster = 0;
-
-					RESET_CFLAG(context);	/* clear carry */
-					SET_AX( context, 0 );
-				}
-				else
-				{
-                                    SET_AX( context, 0x00ff );
-                                    SET_CFLAG(context);
-				}
-			}
-			break;
-
-		case 0x03:	/* Get Extended free space on drive */
-		case 0x04:  /* Set DPB for formatting */
-		case 0x05:  /* extended absolute disk read/write */
-			FIXME("Unimplemented FAT32 int32 function %04x\n", AX_reg(context));
-			SET_CFLAG(context);
-			SET_AL( context, 0 );
-			break;
-		}
-
-		break;
 
     default:
         INT_BARF( context, 0x21 );



-- 
Jukka Heinonen <http://www.iki.fi/jhei/>



More information about the wine-patches mailing list