ChangeLog: * dlls/winedos/int21.c * msdos/int21.c - Move the functions that have anything to do with DPB or EDPB to winedos. - Move free space functions to winedos. nog.
--- dlls/winedos/int21.c.a5 2002-11-09 09:46:27.000000000 +0200 +++ dlls/winedos/int21.c 2002-11-09 10:46:47.000000000 +0200 @@ -39,8 +39,88 @@ WINE_DEFAULT_DEBUG_CHANNEL(int21); +/* 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 */ + +}; + +struct DosHeap { + BYTE InDosFlag; + BYTE mediaID; + BYTE biosdate[8]; + struct DPB dpb; + BYTE DummyDBCSLeadTable[6]; +}; +static struct DosHeap *heap; +static WORD DosHeapHandle; + +DWORD dpbsegptr; + WORD CodePage = 437; +static BOOL INT21_CreateHeap(void) +{ + if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap)))) + { + WARN("Out of memory\n"); + return FALSE; + } + heap = (struct DosHeap *) GlobalLock16(DosHeapHandle); + dpbsegptr = MAKESEGPTR(DosHeapHandle,(int)&heap->dpb-(int)heap); + heap->InDosFlag = 0; + strcpy(heap->biosdate, "01/01/80"); + memset(heap->DummyDBCSLeadTable, 0, 6); + return TRUE; +} + static int GetDosDrive(int drive) { if(drive) @@ -52,6 +132,125 @@ } } +static int IsDriveValid( int drive ) +{ + char driveA[] = "A:\\"; + UINT res; + + *driveA += drive; + res = GetDriveTypeA(driveA); + + if((res == DRIVE_NO_ROOT_DIR) || (res == DRIVE_UNKNOWN)) + return 0; + else + return 1; +} + +/* Many calls translate a drive argument like this: + drive number (00h = default, 01h = A:, etc) + */ +static char drivestring[]="default"; + +char *INT21_DriveName(int drive) +{ + + if(drive > 0) + { + drivestring[0] = (unsigned char)drive + '@'; + drivestring[1] = ':'; + drivestring[2] = 0; + } + return drivestring; +} + +static int INT21_GetFreeDiskSpace(CONTEXT86 *context) +{ + DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters; + char root[] = "A:\\"; + + *root += GetDosDrive(DL_reg(context)); + if (!GetDiskFreeSpaceA(root, &cluster_sectors, §or_bytes, + &free_clusters, &total_clusters)) return 0; + SET_AX(context, cluster_sectors); + SET_BX(context, free_clusters); + SET_CX(context, sector_bytes); + SET_DX(context, total_clusters); + return 1; +} + +static int INT21_GetDriveAllocInfo(CONTEXT86 *context) +{ + if (!INT21_GetFreeDiskSpace(context)) return 0; + if (!heap && !INT21_CreateHeap()) return 0; + heap->mediaID = 0xf0; + context->SegDs = DosHeapHandle; + SET_BX(context, (int)&heap->mediaID - (int)heap); + return 1; +} + +static int FillInDrivePB(int drive) +{ + if(!IsDriveValid(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.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 void INT21_GetDBCSLeadTable( CONTEXT86 *context ) +{ + if (heap || INT21_CreateHeap()) + { /* return an empty table just as DOS 4.0+ does */ + context->SegDs = DosHeapHandle; + SET_SI( context, (int)&heap->DummyDBCSLeadTable - (int)heap ); + } + else + { + SET_AX( context, 0x1 ); /* error */ + SET_CFLAG(context); + } +} + static BYTE *GetCurrentDTA(CONTEXT86 *context) { TDB *pTask = GlobalLock16(GetCurrentTask()); @@ -407,11 +606,24 @@ SET_AL( context, 0 ); break; + case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */ + SET_DL( context, 0 ); + if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); + break; + + case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */ + if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); + break; + case 0x1d: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */ case 0x1e: SET_AL( context, 0 ); break; + case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */ + GetDrivePB(context, GetDosDrive(0)); + break; + case 0x20: /* NULL FUNCTION FOR CP/M COMPATIBILITY */ SET_AL( context, 0 ); break; @@ -466,6 +678,12 @@ FIXME("TERMINATE AND STAY RESIDENT stub\n"); 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, GetDosDrive( DL_reg(context) ) ); + break; + case 0x33: /* MULTIPLEXED */ switch (AL_reg(context)) { @@ -513,6 +731,13 @@ } break; + case 0x34: /* GET ADDRESS OF INDOS FLAG */ + TRACE("GET ADDRESS OF INDOS FLAG\n"); + if (!heap) INT21_CreateHeap(); + context->SegEs = DosHeapHandle; + SET_BX( context, (int)&heap->InDosFlag - (int)heap ); + break; + case 0x35: /* GET INTERRUPT VECTOR */ TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); if(DOSVM_IsWin16()) DOS3Call(context); @@ -523,6 +748,12 @@ } break; + case 0x36: /* GET FREE DISK SPACE */ + TRACE("GET FREE DISK SPACE FOR DRIVE %s\n", + INT21_DriveName( DL_reg(context))); + if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff ); + break; + case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */ TRACE("GET COUNTRY-SPECIFIC INFORMATION for country 0x%02x\n", AL_reg(context)); @@ -755,6 +986,9 @@ } break; + case 0x61: /* UNUSED */ + break; + case 0x62: /* GET PSP ADDRESS */ TRACE("GET CURRENT PSP ADDRESS\n"); /* FIXME: should we return the original DOS PSP upon */ @@ -763,6 +997,14 @@ else SET_BX( context, DOSVM_psp ); break; + case 0x63: /* misc. language support */ + switch (AL_reg(context)) { + case 0x00: /* GET DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE */ + INT21_GetDBCSLeadTable(context); + break; + } + break; + case 0x64: /* OS/2 DOS BOX */ INT_BARF( context, 0x21 ); SET_CFLAG(context); @@ -857,6 +1099,85 @@ SET_AL( context, 0 ); 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; + DWORD 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 += GetDosDrive(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: DOS3Call( context ); } --- msdos/int21.c.a5 2002-11-09 09:46:38.000000000 +0200 +++ msdos/int21.c 2002-11-09 10:49:14.000000000 +0200 @@ -72,85 +72,8 @@ #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 InDosFlag; - BYTE mediaID; - BYTE biosdate[8]; - struct DPB dpb; - BYTE DummyDBCSLeadTable[6]; -}; -static struct DosHeap *heap; -static WORD DosHeapHandle; - extern char TempDirectory[]; -static BOOL INT21_CreateHeap(void) -{ - if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap)))) - { - WARN("Out of memory\n"); - return FALSE; - } - heap = (struct DosHeap *) GlobalLock16(DosHeapHandle); - dpbsegptr = MAKESEGPTR(DosHeapHandle,(int)&heap->dpb-(int)heap); - heap->InDosFlag = 0; - strcpy(heap->biosdate, "01/01/80"); - memset(heap->DummyDBCSLeadTable, 0, 6); - return TRUE; -} - static BYTE *GetCurrentDTA( CONTEXT86 *context ) { TDB *pTask = TASK_GetCurrent(); @@ -201,85 +124,6 @@ } } -static int INT21_GetFreeDiskSpace( CONTEXT86 *context ) -{ - DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters; - char root[] = "A:\\"; - - *root += DOS_GET_DRIVE( DL_reg(context) ); - if (!GetDiskFreeSpaceA( root, &cluster_sectors, §or_bytes, - &free_clusters, &total_clusters )) return 0; - SET_AX( context, cluster_sectors ); - SET_BX( context, free_clusters ); - SET_CX( context, sector_bytes ); - SET_DX( context, total_clusters ); - return 1; -} - -static int INT21_GetDriveAllocInfo( CONTEXT86 *context ) -{ - if (!INT21_GetFreeDiskSpace( context )) return 0; - if (!heap && !INT21_CreateHeap()) return 0; - heap->mediaID = 0xf0; - context->SegDs = DosHeapHandle; - SET_BX( context, (int)&heap->mediaID - (int)heap ); - 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 void ioctlGetDeviceInfo( CONTEXT86 *context ) { int curr_drive; @@ -655,22 +499,6 @@ return TRUE; } - -static void INT21_GetDBCSLeadTable( CONTEXT86 *context ) -{ - if (heap || INT21_CreateHeap()) - { /* return an empty table just as DOS 4.0+ does */ - context->SegDs = DosHeapHandle; - SET_SI( context, (int)&heap->DummyDBCSLeadTable - (int)heap ); - } - else - { - SET_AX( context, 0x1 ); /* error */ - SET_CFLAG(context); - } -} - - static int INT21_GetDiskSerialNumber( CONTEXT86 *context ) { BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); @@ -1023,19 +851,6 @@ } break; - case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */ - SET_DL( context, 0 ); - if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); - break; - - case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */ - if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); - break; - - case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */ - GetDrivePB(context, DRIVE_GetCurrentDrive()); - break; - case 0x25: /* SET INTERRUPT VECTOR */ INT_SetPMHandler( AL_reg(context), (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context))); break; @@ -1066,19 +881,6 @@ SET_CX( context, 0x0000 ); 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 0x34: /* GET ADDRESS OF INDOS FLAG */ - TRACE("GET ADDRESS OF INDOS FLAG\n"); - if (!heap) INT21_CreateHeap(); - context->SegEs = DosHeapHandle; - SET_BX( context, (int)&heap->InDosFlag - (int)heap ); - break; - case 0x35: /* GET INTERRUPT VECTOR */ TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); { @@ -1088,12 +890,6 @@ } break; - case 0x36: /* GET FREE DISK SPACE */ - TRACE("GET FREE DISK SPACE FOR DRIVE %s\n", - INT21_DriveName( DL_reg(context))); - if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff ); - break; - case 0x37: { unsigned char switchchar='/'; @@ -1513,15 +1309,6 @@ } break; - case 0x61: /* UNUSED */ - case 0x63: /* misc. language support */ - switch (AL_reg(context)) { - case 0x00: /* GET DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE */ - INT21_GetDBCSLeadTable(context); - break; - } - break; - case 0x67: /* SET HANDLE COUNT */ TRACE("SET HANDLE COUNT to %d\n",BX_reg(context) ); SetHandleCount16( BX_reg(context) ); @@ -1756,85 +1543,6 @@ SET_AL( context, 0 ); 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 ); break;