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, §or_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, §or_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