|
|
/****************************************************************************/ /* */ /* WFFORMAT.C - */ /* */ /* Windows File Manager Diskette Formatting Routines */ /* */ /****************************************************************************/
#include "winfile.h"
/* MyGetDriveType() returns */ #define NOCHANGE 0
#define CHANGE 1
/* Parameter Block for IOCTL Format call */ struct FORMATPARAMS { BYTE bSpl; /* Special byte */ WORD wHead; WORD wCylinder; };
typedef struct _MEDIASENSE { BYTE IsDefault; BYTE DeviceType; BYTE res[10]; } MEDIASENSE;
/*--------------------------------------------------------------------------*/ /* BIOS Parameter Block Table for Removable Media */ /*--------------------------------------------------------------------------*/
/* Each entry contains data about a floppy drive type in the following format:
* Length * cbSec - Bytes/Sector 2 * secPerClus - Sectors/Cluster 1 * cSecRes - # of Reserved Sectors 2 * cFAT - # of FATs 1 * cDir - # of Root Directory Entries 2 * cSec - # of Sectors on the disk 2 * bMedia - Media Descriptor Byte 1 * secPerFAT - Sectors/FAT 2 * secPerTrack - Sectors/Track 2 * cHead - # of Disk Heads 2 * cSecHidden - # of Hidden Sectors 2 */
BPB bpbList[] = { {512, 1, 1, 2, 64, 1*8*40, MEDIA_160, 1, 8, 1, 0}, /* 8sec SS 48tpi 160KB 5.25" DOS 1.0 & above */ {512, 2, 1, 2, 112, 2*8*40, MEDIA_320, 1, 8, 2, 0}, /* 8sec DS 48tpi 320KB 5.25" DOS 1.1 & above */ {512, 1, 1, 2, 64, 1*9*40, MEDIA_180, 2, 9, 1, 0}, /* 9sec SS 48tpi 180KB 5.25" DOS 2.0 & above */ {512, 2, 1, 2, 112, 2*9*40, MEDIA_360, 2, 9, 2, 0}, /* 9sec DS 48tpi 360KB 5.25" DOS 2.0 & above */ {512, 1, 1, 2, 224, 2*15*80, MEDIA_1200, 7, 15, 2, 0}, /* 15sec DS 96tpi 1.2MB 5.25" DOS 3.0 & above */ {512, 2, 1, 2, 112, 2*9*80, MEDIA_720, 3, 9, 2, 0}, /* 9sec DS 96tpi 720KB 3.5" DOS 3.2 & above */ {512, 1, 1, 2, 224, 2*18*80, MEDIA_1440, 9, 18, 2, 0}, /* 18sec DS 96tpi 1.44M 3.5" DOS 3.3 & above */ {512, 2, 1, 2, 240, 2*36*80, MEDIA_2880, 9, 36, 2, 0} /* 36sec DS 96tpi 2.88M 3.5" DOS 5.0 & above */ };
/* Precompute the total number of usable clusters...
* cCluster = (cSec/secPerClus) - { cSecRes * + (cFAT * secPerFat) * + (cDir*32+cbSec-1)/cbSec }/secPerClus; */ WORD cCluster[] = {0x0139, 0x013B, 0x015F, 0x0162, 0x0943, 0x02C9, 0x0B1F, 0xB2F, 0};
/*--------------------------------------------------------------------------*/ /* */ /* BuildDevPB() - */ /* */ /*--------------------------------------------------------------------------*/
HANDLE APIENTRY BuildDevPB( PDevPB pDevPB ) { WORD wCount; register HANDLE hNewDevPB; PDevPB pNewDevPB; WORD wSecSize; register WORD *wPtr; WORD wTrackNumber;
wCount = pDevPB->BPB.secPerTrack;
if (!(hNewDevPB = LocalAlloc(LHND, TRACKLAYOUT_OFFSET+2+wCount*4))) return NULL;
pNewDevPB = (PDevPB)LocalLock(hNewDevPB);
memcpy(pNewDevPB, pDevPB, TRACKLAYOUT_OFFSET); wSecSize = pDevPB->BPB.cbSec;
wPtr = (WORD *)((LPSTR)pNewDevPB + TRACKLAYOUT_OFFSET); *wPtr++ = wCount;
for (wTrackNumber=1; wTrackNumber <= wCount; wTrackNumber++) { *wPtr++ = wTrackNumber; *wPtr++ = wSecSize; }
LocalUnlock(hNewDevPB); return hNewDevPB; }
/*--------------------------------------------------------------------------*/ /* */ /* SetDevParamsForFormat() - */ /* */ /*--------------------------------------------------------------------------*/
BOOL SetDevParamsForFormat( INT nDrive, PDevPB pDevPB, BOOL fLowCapacity ) { HANDLE hLocHandle; PDevPB pNewDevPB;
/* Allocate for the DPB with track layout */ if (!(hLocHandle = BuildDevPB(pDevPB))) return FALSE;
pNewDevPB = (PDevPB)LocalLock(hLocHandle);
pNewDevPB->SplFunctions = 5; /* Is this a 360KB floppy in a 1.2Mb drive */ if (fLowCapacity) { /* Yes! Then change the number of cylinders and Media type */ /* Fix for Bug #???? --SANKAR-- 01-10-90 -- */ pNewDevPB->NumCyls = 40; pNewDevPB->bMediaType = 1; }
LocalUnlock(hLocHandle); LocalFree(hLocHandle);
return TRUE;
}
/*--------------------------------------------------------------------------*/ /* */ /* GenericFormatTrack() - */ /* */ /*--------------------------------------------------------------------------*/
/* This calls IOCTL format if DOS ver >= 3.2; Else calls BIOS.
* * Returns : 0 if no error * > 0 if tolerable error (resuling in bad sectors); * -1 if fatal error (Format has to be aborted); */
INT APIENTRY GenericFormatTrack( WORD nDisk, WORD wCylinder, WORD wHead, WORD wSecPerTrack, LPSTR lpDiskBuffer ) { struct FORMATPARAMS FormatParams; INT iRetVal = -1; /* FATAL Error by default */ register INT iErrCode;
#ifdef DEBUG
wsprintf(szMessage, "Formatting Head #%d, Cylinder#%d\n\r", wHead, wCylinder); OutputDebugString(szMessage); #endif
/* Check the DOS version */ if (wDOSversion >= DOS_320) { FormatParams.bSpl = 0; FormatParams.wHead = wHead; FormatParams.wCylinder = wCylinder; switch (iErrCode = 0) { case NOERROR: case CRCERROR: case SECNOTFOUND: case GENERALERROR: iRetVal = iErrCode; break; } } else { switch (iErrCode = FormatTrackHead(nDisk, wCylinder, wHead, wSecPerTrack, lpDiskBuffer)) { case NOERROR: case DATAERROR: case ADDMARKNOTFOUND: case SECTORNOTFOUND: iRetVal = iErrCode; break; } } return (iRetVal); }
INT APIENTRY GetMediaType(INT nDrive) { return 0; }
/*--------------------------------------------------------------------------*/ /* */ /* FormatFloppy() - */ /* */ /*--------------------------------------------------------------------------*/
// note, the below comment is out of date. leave for reference only
/* The Format routine is intended to mimic the actions of the FORMAT command
* on MSDOS. We restrict the possible set of operations that Format must use * in order to simplify life. The RESTRICTIONS are: * * -- If the drive selected for formatting is a Quad density drive, then the * user will be asked if he wants to format it for 1.2 MB or 360 KB * and the format will proceed accordingly; * -- For all other types of drives, it will format the disk to the maximum * capacity that the drive can handle. * * The requirements for Format are: * * 1) there be a disk in a "source" drive that contains a valid boot sector * 2) there be a disk in a "destination" drive that is formattable. * * The algorithm for determining a drive's capacity is as follows: * * If Source == Destination then * error * If dosversion >= 3.20 * { * Use generic get_device_parameters and Get BPB. * if (the drive is a Quad density drive (1.2 MB), and if user wants * to format for 360KB), take BPB for 360KB from the bpbList[]. * In all other cases, use the BPB of the device. * } * else * { * Ask INT 13 for the drive type. * If error then { * assume 48tpi double side * Attempt to format track 0, head 1 * If error then * assume 48tpi single side * else * if sectors per track = 15 then * assume 96tpi * Ask user if he wants to format for 1.2MB or 360KB and * use the proper BPB from bpbList[] * else * error * } * * Note that this does NOT take into account non-contiguous drive letters * (see 3.2 spec) nor future drives nor user-installed device drivers. * * Format (dSrc, nDstDrive, nDstDriveInt13) will format drive nDstDrive using an updated * boot sector from drive dSrc. We will allocate two blocks of memory, but * only one at a time. The first one we allocate is the bit-map of bad * clusters that we find during the format. The second is for the boot * sector. * * Returns: 0 Success * <> 0 error code * 1 => NOMEMORY * 3 => Invalid boot sector. * 4 => System area of the floppy is bad * 7 => Problem in writing in Dest diskette. * 8 => Internal error * 9 => Format has been aborted by user. */
// in:
// hWnd window to base messages on
//
// nSource drive to swipe boot stuff from
//
// nDest drive to format
//
// iCapacity SS48
// DS48
// DS96
// DS720KB
// DS144M
// DS288M
// -1 (device capacity)
//
// bMakeSysDisk make a system disk too
//
// bQuick do a quick format
//
// returns:
// 0 success
// != 0 error
//
INT APIENTRY FormatFloppy( HWND hWnd, WORD nDest, INT iCapacity, BOOL bMakeSysDisk, BOOL bQuick ) { DPB DPB; DBT dbtSave; /* Disk Base Table */ INT iErrCode; PBPB pBPB; WORD w; WORD cClusters; WORD wFATValue; WORD wBadCluster; WORD cBadSectors; WORD cTotalTracks; WORD wCurrentHead; WORD wPercentDone; WORD wCurrentTrack; WORD cTracksToFormat; WORD wFirstDataSector; WORD nSource; DevPB dpbDiskParms; /* Device Parameters */ LPDBT lpDBT; LPSTR lpDiskBuffer; LPSTR lpBadClusterList; HANDLE hDiskBuffer; HANDLE hBadClusterList; HANDLE hSaveDiskParms = NULL; PDevPB pdpbSaveDiskParms; CHAR szMsg[128]; BOOL fLowCapacity = FALSE; /* Is a 360KB floppy in a 1.2MB drive? */ INT ret = 0; // default to success
nSource = (WORD)GetBootDisk();
/* Initialize for cleanup. */ hDiskBuffer = NULL; lpDiskBuffer = NULL; hBadClusterList = NULL; lpBadClusterList = NULL; bUserAbort = FALSE;
/* Create a dialogbox that displays the progress of formatting; and also
* gives the user a chance to abort formatting at anytime. */ hdlgProgress = CreateDialog(hAppInstance, MAKEINTRESOURCE(FORMATPROGRESSDLG), hWnd, ProgressDlgProc); if (!hdlgProgress) { ret = IDS_FFERR_MEM; // out of memory
goto FFErrExit1; }
EnableWindow(hWnd, FALSE);
/* Flush to DOS disk buffers. */ DiskReset();
/* Get the Disk Base Table. */ if (!(lpDBT = GetDBT())) { ret = IDS_FFERR_MEM; goto FFErrExit2; }
dbtSave = *lpDBT;
// this checks to see if we are trying to format the boot drive
// this is a no no
if ((nDest == nSource) || (!IsRemovableDrive(nDest))) { ret = IDS_FFERR_SRCEQDST; goto FFErrExit3; }
/* Check if the sector size is of standard size; If not report error */ if (HIWORD(GetClusterInfo(nSource)) > CBSECTORSIZE) { ret = IDS_FFERR_SECSIZE; goto FFErrExit3; }
/* Allocate boot sector, sector buffer, track buffer */ if (!(hDiskBuffer = LocalAlloc(LHND, (LONG)(2*CBSECTORSIZE)))) { ret = IDS_FFERR_MEM; goto FFErrExit3; }
lpDiskBuffer = LocalLock(hDiskBuffer);
/* If DOS Version is 3.2 or above, use DeviceParameters() to get the BPB. */ if (wDOSversion >= DOS_320) {
/* NOTE: All the fields of dpbDiskParms must be initialized to 0,
* otherwise, INT 21h, Function 44h, Subfunction 0Dh does NOT work; * This function is called in DeviceParameters(). */ memset(&dpbDiskParms, 0, sizeof(DevPB)); pBPB = &(dpbDiskParms.BPB);
if (iCapacity != -1) {
w = (WORD)GetMediaType(nDest);
if (w) { switch (w) { case 2: // 720
if (iCapacity > DS720KB) { w = IDS_720KB; iCapacity = DS720KB; } else goto SensePass; break;
case 7: // 1.44
if (iCapacity > DS144M) { w = IDS_144MB; iCapacity = DS144M; } else goto SensePass; break; default: // 2.88 and unknown case
goto SensePass; }
LoadString(hAppInstance, IDS_FFERR_MEDIASENSE, szMsg, sizeof(szMsg)); LoadString(hAppInstance, w, szTitle, sizeof(szTitle)); wsprintf(szMessage, szMsg, (LPSTR)szTitle); LoadString(hAppInstance, IDS_FORMATERR, szTitle, sizeof(szTitle)); if (MessageBox(hdlgProgress, szMessage, szTitle, MB_YESNO | MB_ICONINFORMATION) != IDYES) { ret = IDS_FFERR_USERABORT; goto FFErrExit3; } }
SensePass:
pBPB = &bpbList[iCapacity]; cClusters = cCluster[iCapacity];
// if we are formatting a 360K disk in a 1.2 MB drive set this
// special flag
if (iCapacity == DS48) { // We must remember to change the number of cylinders
// while doing Set Device parameters; So, set this flag;
fLowCapacity = TRUE; } } else { DWORD dwSec = pBPB->cSec;
// use the default device parameters
// NOTE: pBPB already points to proper data
/* HPVECTRA: DOS 3.2 and above gives wrong sector count. */ if (!pBPB->cSec) dwSec = dpbDiskParms.NumCyls * pBPB->secPerTrack * pBPB->cHead;
/* Calculate the clusters for the disk. */ cClusters = (WORD)(dwSec / pBPB->secPerClus) - (pBPB->cSecRes + (pBPB->cFAT * pBPB->secPerFAT) + (pBPB->cDir*32 + pBPB->cbSec - 1) / pBPB->cbSec) / pBPB->secPerClus; }
/* Save the DriveParameterBlock for restoration latter */ hSaveDiskParms = BuildDevPB(&dpbDiskParms); if (!hSaveDiskParms) { ret = IDS_FFERR_MEM; goto FFErrExit3; } pdpbSaveDiskParms = (PDevPB)LocalLock(hSaveDiskParms);
/* Modify the parameters just for format */ memcpy(&(dpbDiskParms.BPB), pBPB, sizeof(BPB)); if (!SetDevParamsForFormat(nDest, &dpbDiskParms, fLowCapacity)) { ret = IDS_FFERR_MEM; goto FFErrExit3; }
} else { // DOS < 3.2
/* See if INT 13 knows the drive type. */ switch (MyGetDriveType(nDest)) { case NOCHANGE: /* We assume that the machine is using old ROMS...
* Assume that we are using a 9-sector Double-sided 48tpi diskette. */ pBPB = &bpbList[DS48]; cClusters = cCluster[DS48]; lpDBT->lastsector = (BYTE)pBPB->secPerTrack; lpDBT->gaplengthf = 0x50;
/* Try to format a track on side 1. If this fails, assume that we
* have a Single-sided 48tpi diskette. */ if (FormatTrackHead(nDest, 0, 1, pBPB->secPerTrack, lpDiskBuffer)) { pBPB = &bpbList[SS48]; cClusters = cCluster[SS48]; } break;
case CHANGE: if (iCapacity == DS48) { /* User wants to format a 360KB floppy. */ pBPB = &bpbList[DS48]; cClusters = cCluster[DS48]; } else { /* User wants to format a 1.2 MB floppy */ pBPB = &bpbList[DS96]; cClusters = cCluster[DS96]; } break;
default: ret = IDS_FFERR_DRIVETYPE; goto FFErrExit5; } }
lpDBT->lastsector = (BYTE)pBPB->secPerTrack; lpDBT->gaplengthf = (BYTE)(pBPB->secPerTrack == 15 ? 0x54 : 0x50);
if (wDOSversion < DOS_320) { /* If 96tpi, fix up the Disk Base Table. */ if (pBPB->bMedia == MEDIA_1200) /* high density */ if (pBPB->secPerTrack == 15) /* then 1.2 Meg Drive */ SetDASD(nDest, 3); /* 1.2 MB floppy in 1.2MB drive */ }
LoadString(hAppInstance, IDS_PERCENTCOMP, szMsg, sizeof(szMsg));
/* We believe that we know EXACTLY what is out there. Allocate the boot
* sector and the bad-cluster bit-map. The boot sector buffer is reused as * two consecutive sectors of the FAT. */ if (!(hBadClusterList = LocalAlloc(LHND, (LONG)((2 + cClusters + 7) / 8)))) { ret = IDS_FFERR_MEM; goto FFErrExit5; }
lpBadClusterList = LocalLock(hBadClusterList);
/* Let's format 1 track at a time and record the bad sectors in the
* bitmap. Note that we round DOWN the number of tracks so that we * don't format what might not be ours. Fail if there are any bad * sectors in the system area. */
/* Compute number of tracks to format. */ if (!pBPB->cSec) cTracksToFormat = (WORD)dpbDiskParms.NumCyls; else cTracksToFormat = (WORD)(pBPB->cSec / pBPB->secPerTrack);
/* Compute the starting track and head. */ wCurrentTrack = pBPB->cSecHidden / (pBPB->secPerTrack * pBPB->cHead); wCurrentHead = (pBPB->cSecHidden % (pBPB->secPerTrack * pBPB->cHead))/pBPB->secPerTrack;
/* Compute the number of the first sector after the system area. */ wFirstDataSector = pBPB->cSecRes + pBPB->cFAT * pBPB->secPerFAT + (pBPB->cDir * 32 + pBPB->cbSec-1) / pBPB->cbSec;
cTotalTracks = cTracksToFormat;
if (bQuick) {
// read the boot sector to make sure the capacity selected
// matches what it has been formated to
iErrCode = GenericReadWriteSector(lpDiskBuffer, INT13_READ, nDest, 0, 0, 1);
if (iErrCode || ((iCapacity != -1) && ((BOOTSEC *)lpDiskBuffer)->BPB.bMedia != bpbList[iCapacity].bMedia)) {
fFormatFlags &= ~FF_QUICK; bQuick = FALSE;
LoadString(hAppInstance, IDS_FORMATQUICKFAILURE, szMessage, 128); LoadString(hAppInstance, IDS_FORMAT, szTitle, 128);
iErrCode = MessageBox(hdlgProgress, szMessage, szTitle, MB_YESNO | MB_ICONEXCLAMATION);
if (iErrCode == IDYES) goto NormalFormat; else { ret = IDS_FFERR_USERABORT; goto FFErrExit; } }
} else {
NormalFormat:
/* Format tracks one by one, checking if the user has "Aborted"
* after each track is formatted; DlgProgreeProc() will set the global * bUserAbort, if the user has aborted; */ while (cTracksToFormat) {
/* Has the user aborted? */ if (WFQueryAbort()) { ret = IDS_FFERR_USERABORT; goto FFErrExit; }
/* If no message is pending, go ahead and format one track */ if ((iErrCode = GenericFormatTrack(nDest, wCurrentTrack, wCurrentHead, pBPB->secPerTrack, lpDiskBuffer))) {
/* Check if it is a fatal error */ if (iErrCode == -1) { // ret = IDS_FFERR_BADTRACK;
ret = IDS_FFERR; goto FFErrExit; }
/* Bad Track. Compute the number of the first bad sector */ cBadSectors = (wCurrentTrack * pBPB->cHead + wCurrentHead) * pBPB->secPerTrack;
/* Fail if bad sector is in the system area */ if (cBadSectors < wFirstDataSector) { // ret = IDS_FFERR_BADTRACK;
ret = IDS_FFERR; goto FFErrExit; }
/* Enumerate all bad sectors and mark the corresponding
* clusters as bad. */ for (w=cBadSectors; w < cBadSectors + pBPB->secPerTrack; w++) { wBadCluster = (w - wFirstDataSector) / pBPB->secPerClus + 2; lpBadClusterList[wBadCluster/8] |= 1 << (wBadCluster % 8); } }
cTracksToFormat--;
/* Display the percentage of progress message */ wPercentDone = (WORD)MulDiv(cTotalTracks - cTracksToFormat, 100, cTotalTracks);
/* All tracks might have been formatted. But,
* Still FAT and Root dir are to be created; It takes time; So, * make the user believe that still 1% formatting is left. */ if (wPercentDone == 100) LoadString(hAppInstance, IDS_CREATEROOT, szMessage, sizeof(szMessage)); else wsprintf(szMessage, szMsg, wPercentDone);
SendDlgItemMessage(hdlgProgress, IDD_PROGRESS, WM_SETTEXT, 0, (LPARAM)szMessage);
if (++wCurrentHead >= pBPB->cHead) { wCurrentHead = 0; wCurrentTrack++; } } }
/* Write out the boot sector(s). */ w = (WORD)WriteBootSector(nSource, nDest, pBPB, lpDiskBuffer); if (w) { // ret = IDS_FFERR_WRITEBOOT;
if (w == 0x16) // int24 unknown command, assume
ret = IDS_SYSDISKNOFILES; // the int25 read failed
else ret = IDS_FFERR; goto FFErrExit; }
/* Has the user aborted? */ if (WFQueryAbort()) { ret = IDS_FFERR_USERABORT; goto FFErrExit; }
/* Format is complete. Create correct DPB in system */ SetDPB(nDest, pBPB, &DPB);
// if doing a quick format keep the old bad cluster list
/* Create FAT entries for each of the formatted clusters. */ for (w=2; w < (WORD)(cClusters+2); w++) {
if (bQuick) { wFATValue = 0;
// is this entry reserved or marked as bad
if ((wFATValue >= 0xFFF0) && (wFATValue <= 0xFFF7)) { // yes, don't change it!
} else { // mark as free
if (0) { // ret = IDS_FFERR_WRITEFAT;
ret = IDS_FFERR; goto FFErrExit; } }
} else { /* Was this cluster bad? */ if (lpBadClusterList[w/8] & (1 << (w % 8))) wFATValue = 0xFFF7; else wFATValue = 0;
/* Add this entry to the FAT (possibly writing the sector). */ if (0) { // ret = IDS_FFERR_WRITEFAT;
ret = IDS_FFERR; goto FFErrExit; }
} if (WFQueryAbort()) { /* Has the user aborted? */ ret = IDS_FFERR_USERABORT; goto FFErrExit; } }
/* Clean out the root directory. */ memset(lpDiskBuffer, 0, CBSECTORSIZE);
for (w=0; w < (WORD)((pBPB->cDir*32 + pBPB->cbSec-1)/pBPB->cbSec); w++) { /* Has the user aborted? */ if (WFQueryAbort()) { ret = IDS_FFERR_USERABORT; goto FFErrExit; } }
/* Should we make it a system disk also? */ if (bMakeSysDisk) { LoadString(hAppInstance, IDS_COPYSYSFILES, szMessage, 32); SendDlgItemMessage(hdlgProgress, IDD_PROGRESS, WM_SETTEXT, 0, (LPARAM)szMessage); if (MakeSystemDiskette(nDest, TRUE)) { if (bUserAbort) ret = IDS_FFERR_USERABORT; else ret = IDS_FFERR_SYSFILES; goto FFErrExit; } }
/* Normal Exit. */
LocalUnlock(hBadClusterList); LocalFree(hBadClusterList); LocalUnlock(hDiskBuffer);
if (hSaveDiskParms) { /* Restore the DriveParameterBlock */ pdpbSaveDiskParms->SplFunctions = 4;
LocalUnlock(hSaveDiskParms); LocalFree(hSaveDiskParms); }
LocalFree(hDiskBuffer); *lpDBT = dbtSave; EnableWindow(hWnd, TRUE); DestroyWindow(hdlgProgress); hdlgProgress = NULL; return TRUE;
FFErrExit: LocalUnlock(hBadClusterList); LocalFree(hBadClusterList); FFErrExit5: if (hSaveDiskParms) { /* Restore the DriveParameterBlock */ pdpbSaveDiskParms->SplFunctions = 4;
LocalUnlock(hSaveDiskParms); LocalFree(hSaveDiskParms); } LocalUnlock(hDiskBuffer); LocalFree(hDiskBuffer); FFErrExit3: *lpDBT = dbtSave; FFErrExit2: EnableWindow(hWnd, TRUE); DestroyWindow(hdlgProgress); hdlgProgress = NULL; FFErrExit1:
if (ret != IDS_FFERR_USERABORT) { LoadString(hAppInstance, IDS_FORMATERR, szTitle, sizeof(szTitle)); LoadString(hAppInstance, ret, szMessage, sizeof(szMessage)); MessageBox(hWnd, szMessage, szTitle, MB_OK | MB_ICONSTOP); } return FALSE; }
/*--------------------------------------------------------------------------*/ /* */ /* GetDriveCapacity() - */ /* */ /*--------------------------------------------------------------------------*/
/* Parameter:
* Drive number; * Returns: * 0 if Error; * 1 if 360KB floppy; * 2 if 1.2MB floppy; * 3 if 720KB, 3.5" floppy; * 4 if 1.44MB, 3.5" floppy; * 5 if 2.88MB, 3.5" floppy; * * these are used +2 as indexes into bpbList[] FIX31 * * HACK ALERT: * One might wonder why on earth we are not using int13h Fn 8 to * perform this function; The reason is that in old compaq 386/16 * machines(though the BIOS is dated Sep 1986), this function is NOT * supported! So, we are forced to do the following: * We check the DOS version; If it is >= 3.2, then we make IOCTL * calls to get the Drive parameters and we find the Drive capacity; * If DOS version is < 3.2, then there can't be 3.5" floppies at all; * The only high capacity floppy possible is the 5.25", 1.2MB floppy; * So, we call MyGetDriveType() (int13h, Fn 15h) to find if the * change-line is supported by the drive; If it is supported then it * must be a 1.2MB floppy; Otherwise, it is a 360KB floppy; * What do you think? Smart! Ugh? */
WORD APIENTRY GetDriveCapacity( WORD nDrive ) { DevPB dpbDiskParms; /* Device Parameters */ PBPB pBPB;
if (wDOSversion >= DOS_320) {
/* NOTE: All the fields of dpbDiskParms must be initialized to 0,
* otherwise, INT 21h, Function 44h, Subfunction 0Dh does NOT work; * This function is called in DeviceParameters(). */ memset(&dpbDiskParms, 0, sizeof(DevPB)); dpbDiskParms.SplFunctions = 0;
pBPB = &(dpbDiskParms.BPB);
/* Check if this is a 1.44MB drive */ if (pBPB->bMedia == MEDIA_1440) { if (pBPB->secPerTrack == 18) return 4; /* 1.44MB drive */ else if (pBPB->secPerTrack == 36) return 5; /* 2.88MB drive */ }
/* Check if this is a 720KB or 1.2MB drive */ if (pBPB->bMedia == MEDIA_1200) { if (pBPB->secPerFAT == 3) return 3; /* 720KB drive */ if (pBPB->secPerFAT == 7) return 2; /* 1.2MB drive */ }
if (pBPB->bMedia == MEDIA_360) return 1; /* Must be a 386KB floppy. */
return 0; // I don't know!
} else {
/* See if INT 13 Fn 15h knows the drive type. */ switch (MyGetDriveType(nDrive)) { case NOCHANGE: /* We assume that the machine is using old ROMS... */ return 1; /* No changeline support! Must be 360KB floppy */ break;
case CHANGE: return 2; /* DOS versions < 3.2 can not have 1.44 or 720KB
* drive; So, this has to be a 1.2MB drive */ break; default: return 0; } } }
|