Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

980 lines
32 KiB

/****************************************************************************/
/* */
/* 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);
_fmemcpy(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 NEAR PASCAL 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;
}
// this can fail
DeviceParameters(nDrive, pNewDevPB, IOCTL_SET_DPB);
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 = IOCTL_Functions((LPSTR)&FormatParams, IOCTL_FORMAT, nDisk))
{
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)
{
MEDIASENSE ms;
if (!IOCTL_Functions((LPSTR)&ms, IOCTL_MEDIASSENSE, nDrive))
return ms.DeviceType;
else
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;
WNDPROC lpfnDialog;
CHAR szMsg[128];
BOOL fLowCapacity = FALSE; /* Is a 360KB floppy in a 1.2MB drive? */
INT ret = 0; // default to success
nSource = 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.
*/
lpfnDialog = (WNDPROC)MakeProcInstance((FARPROC)ProgressDlgProc, hAppInstance);
hdlgProgress = CreateDialog(hAppInstance, MAKEINTRESOURCE(FORMATPROGRESSDLG), hWnd, lpfnDialog);
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));
// dpbDiskParms.SplFunctions = 0; /* Build BPB */
if (DeviceParameters(nDest, &dpbDiskParms, IOCTL_GET_DPB)) {
ret = IDS_FFERR;
goto FFErrExit5;
}
pBPB = &(dpbDiskParms.BPB);
#ifdef DEBUG
{
CHAR buf[400];
wsprintf(buf, "specail functions %x\r\n"
"num tracks %d\r\n"
"sec per track %d\r\n"
"bytes per sector %d\r\n"
"# sectors %d\r\n"
"sec per cluster %d\r\n"
"# heads %d\r\n",
dpbDiskParms.SplFunctions,
dpbDiskParms.NumCyls,
pBPB->secPerTrack,
pBPB->cbSec,
pBPB->cSec,
pBPB->secPerClus,
pBPB->cHead);
MessageBox(hdlgProgress, buf, "disk params", MB_OK);
}
#endif
if (iCapacity != -1) {
w = GetMediaType(nDest);
if (w) {
#ifdef DEBUG
{
CHAR szBuf[80];
wsprintf(szBuf, "Media Sense returns %x", i);
MessageBox(hdlgProgress, szBuf, "Media Sense capable", MB_OK);
}
#endif
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 (IsHPMachine() || !pBPB->cSec)
dwSec = LongMult(dpbDiskParms.NumCyls, pBPB->secPerTrack * pBPB->cHead);
/* Calculate the clusters for the disk. */
cClusters = (WORD)LongDiv(dwSec, pBPB->secPerClus) -
(pBPB->cSecRes + (pBPB->cFAT * pBPB->secPerFAT) +
(pBPB->cDir*32 + pBPB->cbSec - 1) / pBPB->cbSec) / pBPB->secPerClus;
#ifdef DEBUG
{
CHAR buf[100];
wsprintf(buf, "# sectors %ld\r\n# clusters %d", dwSec, cClusters);
MessageBox(hdlgProgress, buf, "Computed Parameters", MB_OK);
}
#endif
}
/* 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 */
_fmemcpy(&(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 = dpbDiskParms.NumCyls;
else
cTracksToFormat = 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 FAR *)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 = 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, (LONG)(LPSTR)szMessage);
if (++wCurrentHead >= pBPB->cHead) {
wCurrentHead = 0;
wCurrentTrack++;
}
}
}
/* Write out the boot sector(s). */
w = 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);
/* Initialize the FAT global variables. */
OpenFAT(FAT_WRITE);
/* Create the special first two FAT entries. */
PackFAT(&DPB, lpDiskBuffer, 0, pBPB->bMedia+0xFF00);
PackFAT(&DPB, lpDiskBuffer, 1, 0xFFFF);
// 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 = UnpackFAT(&DPB, lpDiskBuffer, w);
// is this entry reserved or marked as bad
// UnpackFAT() converts to 16 bits
if ((wFATValue >= 0xFFF0) &&
(wFATValue <= 0xFFF7)) {
// yes, don't change it!
} else {
// mark as free
if (PackFAT(&DPB, lpDiskBuffer, w, 0x0000)) {
// 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 (PackFAT(&DPB, lpDiskBuffer, w, wFATValue)) {
// ret = IDS_FFERR_WRITEFAT;
ret = IDS_FFERR;
goto FFErrExit;
}
}
if (WFQueryAbort()) { /* Has the user aborted? */
ret = IDS_FFERR_USERABORT;
goto FFErrExit;
}
}
/* Flush the remaining FAT sector. */
if (FlushFAT(&DPB, lpDiskBuffer)) {
// ret = IDS_FFERR_WRITEFAT;
ret = IDS_FFERR;
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;
}
if (MyInt26(nDest, lpDiskBuffer, 1, DPB.dir_sector+w)) {
// ret = IDS_FFERR_WRITEROOT;
ret = IDS_FFERR;
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, (LONG)(LPSTR)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;
DeviceParameters(nDest, pdpbSaveDiskParms, IOCTL_SET_DPB);
LocalUnlock(hSaveDiskParms);
LocalFree(hSaveDiskParms);
}
LocalFree(hDiskBuffer);
*lpDBT = dbtSave;
EnableWindow(hWnd, TRUE);
DestroyWindow(hdlgProgress);
hdlgProgress = NULL;
FreeProcInstance(lpfnDialog);
return TRUE;
FFErrExit:
LocalUnlock(hBadClusterList);
LocalFree(hBadClusterList);
FFErrExit5:
if (hSaveDiskParms)
{
/* Restore the DriveParameterBlock */
pdpbSaveDiskParms->SplFunctions = 4;
DeviceParameters(nDest, pdpbSaveDiskParms, IOCTL_SET_DPB);
LocalUnlock(hSaveDiskParms);
LocalFree(hSaveDiskParms);
}
LocalUnlock(hDiskBuffer);
LocalFree(hDiskBuffer);
FFErrExit3:
*lpDBT = dbtSave;
FFErrExit2:
EnableWindow(hWnd, TRUE);
DestroyWindow(hdlgProgress);
hdlgProgress = NULL;
FFErrExit1:
FreeProcInstance(lpfnDialog);
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 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));
dpbDiskParms.SplFunctions = 0;
if (DeviceParameters(nDrive, &dpbDiskParms, IOCTL_GET_DPB))
return 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;
}
}
}