windows-nt/Source/XPSP1/NT/sdktools/winobj/wfdcopy.c
2020-09-26 16:20:57 +08:00

940 lines
32 KiB
C

/****************************************************************************/
/* */
/* WFDCOPY.C - */
/* */
/* File Manager Diskette Copying Routines */
/* */
/****************************************************************************/
#include "winfile.h"
LONG APIENTRY LongPtrAdd(LPSTR, DWORD);
PBPB GetBootBPB(INT nSrceDrive);
PBPB GetBPB(INT nDrive, PDevPB pDevicePB);
BOOL CheckBPBCompatibility(PBPB pSrceBPB, int nSrcDriveType, PBPB pDestBPB, int nDestDriveType);
BOOL ModifyDeviceParams(
INT nDrive,
PDevPB pdpbParams,
HANDLE *phSaveParams,
PBPB pDriveBPB,
PBPB pMediaBPB);
BOOL FormatAllTracks(
PDISKINFO pDisketteInfo,
WORD wStartCylinder,
WORD wStartHead,
LPSTR lpDiskBuffer);
BOOL AllocDiskCopyBuffers(PDISKINFO pDisketteInfo);
VOID FreeBuffers(VOID);
VOID GetDisketteInfo(PDISKINFO pDisketteInfo, PBPB pBPB);
VOID DCopyMessageBox(HWND hwnd, WORD idString, WORD wFlags);
VOID PromptDisketteChange(HWND hwnd, BOOL bWrite);
INT ReadWriteMaxPossible(BOOL bWrite, WORD wStartCylinder, PDISKINFO pDisketteInfo);
INT ReadWrite(BOOL bWrite, WORD wStartCylinder, PDISKINFO pDisketteInfo);
BOOL RestoreDPB(INT nDisk, HANDLE hSavedParams);
INT ReadWriteCylinder(BOOL bWrite, WORD wCylinder, PDISKINFO pDisketteInfo);
/* The following structure is the Parameter block for the read-write
* operations using the IOCTL calls in DOS
*/
struct RW_PARMBLOCK {
BYTE bSplFn;
WORD wHead;
WORD wCylinder;
WORD wStSector;
WORD wCount;
LPSTR lpBuffer;
};
/* Global Variables */
BOOL bFormatDone;
BOOL bSingleDrive = TRUE;
WORD wCompletedCylinders = 0;
DWORD dwDisketteBufferSize;
LPSTR lpDosMemory;
LPSTR lpFormatBuffer;
LPSTR lpReadWritePtr;
LPSTR hpDisketteBuffer;
HANDLE hFormatBuffer;
HANDLE hDosMemory;
HANDLE hDisketteBuffer;
PDevPB pTrackLayout; /* DevPB with the track layout */
BOOTSEC BootSec;
/* External Variables */
extern BPB bpbList[];
/*--------------------------------------------------------------------------*/
/* */
/* GetBootBPB() - */
/* */
/*--------------------------------------------------------------------------*/
/* This reads the boot sector of a floppy and returns a ptr to
* the BIOS PARAMETER BLOCK in the Boot sector.
*/
PBPB
GetBootBPB(
INT nSrceDrive
)
{
INT rc;
/* Make sure that the source diskette's boot sector is valid. */
rc = GenericReadWriteSector((LPSTR)&BootSec, INT13_READ, (WORD)nSrceDrive, 0, 0, 1);
if ((rc < 0) || ((BootSec.jump[0] != 0xE9) && (BootSec.jump[0] != 0xEB)))
return (PBPB)NULL;
return (PBPB)&(BootSec.BPB);
}
/*--------------------------------------------------------------------------*/
/* */
/* GetBPB() - */
/* */
/*--------------------------------------------------------------------------*/
/* Gets get the BPB of the Physical Drive.
*
* This uses the IOCTL calls if DOS ver >= 3.2; Otherwise it uses the
* BIOS calls to find out the drive type and picks us the BPB from a table.
* It also returns the DeviceParameterBlock thro params if DOS >= 3.2.
* Sets devType field of DeviceParameterBlock in any case (11.12.91) v-dougk
*/
PBPB
GetBPB(
INT nDrive,
PDevPB pDevicePB
)
{
INT iDisketteType;
PBPB pBPB = NULL;
/* Check the DOS version */
if (wDOSversion >= DOS_320) {
/* All fields in pDevicePB must be initialized to zero. */
memset(pDevicePB, 0, sizeof(DevPB));
/* Spl Function field must be set to get parameters */
pDevicePB->SplFunctions = 0;
pBPB = &(pDevicePB->BPB);
} else {
/* Find out the Drive type using the BIOS. */
if ((iDisketteType = GetDriveCapacity((WORD)nDrive)) == 0)
goto GBPB_Error;
/* Lookup this drive's default BPB. */
pBPB = &bpbList[iDisketteType+2];
switch (iDisketteType) {
case 1:
pDevicePB->devType = 0; // 360K
break;
case 2:
pDevicePB->devType = 1; // 1.2M
break;
}
}
GBPB_Error:
return (pBPB);
}
/*--------------------------------------------------------------------------*/
/* */
/* CheckBPBCompatibility() - */
/* */
/*--------------------------------------------------------------------------*/
/* Checks whether the two BPB are compatible for the purpose of performing
* the diskcopy operation.
*/
BOOL
CheckBPBCompatibility(
PBPB pSrceBPB,
int nSrcDriveType,
PBPB pDestBPB,
int nDestDriveType
)
{
/* Let us compare the media byte */
if (pSrceBPB->bMedia == 0xF9) {
/* If the source and dest have the same number of sectors,
* or if srce is 720KB and Dest is 1.44MB floppy drive,
* thnigs are kosher.
*/
if ((pSrceBPB->cSec == pDestBPB->cSec) ||
((pSrceBPB->secPerTrack == 9) && (pDestBPB -> bMedia == 0xF0)))
return (TRUE);
} else {
/* If they have the same media byte */
if ((pSrceBPB->bMedia == pDestBPB->bMedia) &&
(pSrceBPB->cbSec == pDestBPB->cbSec) && // bytes per sector are the same
(pSrceBPB->cSec == pDestBPB->cSec)) // total sectors on drive are the same
return (TRUE); /* They are compatible */
else if
/* srce is 160KB and dest is 320KB drive */
(((pSrceBPB->bMedia == MEDIA_160) && (pDestBPB->bMedia == MEDIA_320)) ||
/* or if srce is 180KB and dest is 360KB drive */
((pSrceBPB->bMedia == MEDIA_180) && (pDestBPB->bMedia == MEDIA_360)) ||
/* or if srce is 1.44MB and dest is 2.88MB drive */
((pSrceBPB->bMedia == MEDIA_1440) && (pDestBPB->bMedia == MEDIA_2880)
&& ((nSrcDriveType == 7) || (nSrcDriveType == 9))
&& (nDestDriveType == 9)) ||
/* or if srce is 360KB and dest is 1.2MB drive */
((pSrceBPB->bMedia == MEDIA_360) && (pDestBPB->secPerTrack == 15)))
return (TRUE); /* They are compatible */
}
/* All other combinations are currently incompatible. */
return (FALSE);
}
/*--------------------------------------------------------------------------*/
/* */
/* ModifyDeviceParams() - */
/* */
/*--------------------------------------------------------------------------*/
/* Saves a copy of the drive parameters block and
* Checks if the BPB of Drive and BPB of disk are different and if
* so, modifies the drive parameter block accordingly.
*/
BOOL
ModifyDeviceParams(
INT nDrive,
PDevPB pdpbParams,
HANDLE *phSaveParams,
PBPB pDriveBPB,
PBPB pMediaBPB)
{
INT iDriveCode;
HANDLE hNewDPB;
PDevPB pNewDPB;
if (!(*phSaveParams = BuildDevPB(pdpbParams)))
return FALSE;
/* Check if the Disk and Drive have the same parameters */
if (pMediaBPB->bMedia != pDriveBPB->bMedia) {
/* They are not equal; So, it must be a 360KB floppy in a 1.2MB drive
* or a 720KB floppy in a 1.44MB drive kind of situation!.
* So, modify the DriveParameterBlock's BPB.
*/
*(PBPB)&(pdpbParams->BPB) = *pMediaBPB;
}
if (wDOSversion >= DOS_320) {
/* Build a DPB with TrackLayout */
if (!(hNewDPB = BuildDevPB(pdpbParams)))
goto MDP_Error;
pNewDPB = (PDevPB)LocalLock(hNewDPB);
pNewDPB->SplFunctions = 4; /* To Set parameters */
/* Check if this is a 360KB floppy; And if it is a 1.2MB drive, the
* number of cylinders and mediatype field are wrong; So, we modify
* these fields here anyway;
* This is required to format a 360KB floppy on a NCR PC916 machine;
* Fix for Bug #6894 --01-10-90-- SANKAR
*/
if (pMediaBPB->bMedia == MEDIA_360) {
pNewDPB->NumCyls = 40;
pNewDPB->bMediaType = 1;
}
LocalUnlock(hNewDPB);
LocalFree(hNewDPB);
} else {
iDriveCode = 0;
switch (pMediaBPB->bMedia) {
case MEDIA_360:
case MEDIA_320:
if ((pDriveBPB->bMedia == MEDIA_360) ||
(pDriveBPB->bMedia == MEDIA_320))
iDriveCode = 1; /* Must be 360/320KB in 360KB drive */
else
iDriveCode = 2; /* Must be 360/320Kb in 1.2MB drive */
break;
case MEDIA_1200:
iDriveCode = 3; /* Must be 1.2MB in 1.2MB drive */
break;
}
if (iDriveCode)
SetDASD((WORD)nDrive, (BYTE)iDriveCode);
}
return (TRUE);
/* Error handling */
MDP_Error:
if (hNewDPB)
LocalFree(hNewDPB);
if (*phSaveParams) {
LocalFree(*phSaveParams);
*phSaveParams = NULL;
}
return (FALSE);
}
/*--------------------------------------------------------------------------*/
/* */
/* FormatAllTracks() - */
/* */
/*--------------------------------------------------------------------------*/
BOOL
FormatAllTracks(
PDISKINFO pDisketteInfo,
WORD wStartCylinder,
WORD wStartHead,
LPSTR lpDiskBuffer)
{
INT iErrCode;
BOOL bRetValue = TRUE;
WORD wTotalCylinders;
WORD wSecPerTrack;
WORD wHeads;
WORD wDrive;
LoadString(hAppInstance, IDS_FORMATTINGDEST, szMessage, 128);
SendDlgItemMessage(hdlgProgress, IDD_PROGRESS, WM_SETTEXT, 0, (LPARAM)szMessage);
bFormatDone = TRUE;
wDrive = pDisketteInfo->wDrive;
if (wDOSversion >= DOS_320) {
pTrackLayout->SplFunctions = 5;
} else {
if ((pTrackLayout->BPB.bMedia == 0xF9) && /* high density */
(pTrackLayout->BPB.secPerTrack == 15)) /* 1.2 Meg Drive */
SetDASD(wDrive, 3); /* 1.2 MB floppy in 1.2MB drive */
}
wTotalCylinders = pDisketteInfo->wLastCylinder + 1;
wSecPerTrack = pDisketteInfo->wSectorsPerTrack;
wHeads = pDisketteInfo->wHeads;
/* 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 (wStartCylinder < wTotalCylinders) {
/* Has the user aborted? */
if (WFQueryAbort()) {
bRetValue = FALSE;
break;
}
/* If no message is pending, go ahead and format one track */
if ((iErrCode = GenericFormatTrack(wDrive, wStartCylinder, wStartHead, wSecPerTrack, lpDiskBuffer))) {
/* Check if it is a fatal error */
if (iErrCode == -1) {
bRetValue = FALSE;
break;
}
}
if (++wStartHead >= wHeads) {
wStartHead = 0;
wStartCylinder++;
}
}
if (wDOSversion >= DOS_320) {
pTrackLayout->SplFunctions = 4;
}
return (bRetValue);
}
/*--------------------------------------------------------------------------*/
/* */
/* GenericReadWriteSector() - */
/* */
/*--------------------------------------------------------------------------*/
/* Checks the DOS version number; If it is >= 3.2, then IOCTL
* calls are made to read/write; Else it calls int13 read/write.
*/
INT
APIENTRY
GenericReadWriteSector(
LPSTR lpBuffer,
WORD wFunction,
WORD wDrive,
WORD wCylinder,
WORD wHead,
WORD wCount)
{
struct RW_PARMBLOCK RW_ParmBlock;
/* If the DOS version is >= 3.2, we use DOS IOCTL function calls. */
if (wDOSversion >= DOS_320) {
RW_ParmBlock.bSplFn = 0;
RW_ParmBlock.wHead = wHead;
RW_ParmBlock.wCylinder = wCylinder;
RW_ParmBlock.wStSector = 0;
RW_ParmBlock.wCount = wCount;
RW_ParmBlock.lpBuffer = lpBuffer;
return (0);
} else
/* Use Int13 function calls. */
return (MyReadWriteSector(lpBuffer, wFunction, wDrive, wCylinder, wHead, wCount));
}
/*--------------------------------------------------------------------------*/
/* */
/* AllocDiskCopyBuffers() - */
/* */
/*--------------------------------------------------------------------------*/
BOOL
AllocDiskCopyBuffers(
PDISKINFO pDisketteInfo
)
{
HANDLE hMemTemp;
ENTER("AllocDiskCopyBuffers");
hFormatBuffer = LocalAlloc(LHND, (LONG)(2*CBSECTORSIZE));
if (!hFormatBuffer)
return FALSE;
lpFormatBuffer = (LPSTR)LocalLock(hFormatBuffer);
// We will try to reserve 16K for dialog boxes that comeup during diskcopy
hMemTemp = LocalAlloc(LHND, (16 * 1024));
if (!hMemTemp)
goto Failure;
hDosMemory = (HANDLE)NULL;
// now, lets try to allocate a buffer for the whole disk, and
// if that fails try smaller
// note, standard mode will only give us 1M chuncks
dwDisketteBufferSize = pDisketteInfo->wCylinderSize * (pDisketteInfo->wLastCylinder + 1);
// we will try down to 8 cylinders worth, less than that means
// there will be too much disk swapping so don't bother
do {
hDisketteBuffer = LocalAlloc(LHND, dwDisketteBufferSize);
if (hDisketteBuffer) {
hpDisketteBuffer = (LPSTR)LocalLock(hDisketteBuffer);
break;
} else {
// reduce request by 4 cylinders.
dwDisketteBufferSize -= pDisketteInfo->wCylinderSize * 4;
}
} while (dwDisketteBufferSize > (DWORD)(8 * pDisketteInfo->wCylinderSize));
LocalFree(hMemTemp); // now free this up for user
if (hDisketteBuffer)
return TRUE;
// fall through here to the failure case
Failure:
if (lpFormatBuffer) {
LocalUnlock(hFormatBuffer);
LocalFree(hFormatBuffer);
}
if (hDosMemory)
// +++GlobalDosFree - NO 32BIT FORM+++(hDosMemory);
LocalFree(hDosMemory);
LEAVE("AllocDiskCopyBuffers");
return FALSE;
}
/*--------------------------------------------------------------------------*/
/* */
/* FreeBuffers() - */
/* */
/*--------------------------------------------------------------------------*/
VOID
FreeBuffers()
{
if (lpFormatBuffer) {
LocalUnlock(hFormatBuffer);
LocalFree(hFormatBuffer);
}
if (hDosMemory)
// +++GlobalDosFree - NO 32BIT FORM+++(hDosMemory);
LocalFree(hDosMemory);
if (hpDisketteBuffer) {
LocalUnlock(hDisketteBuffer);
LocalFree(hDisketteBuffer);
}
}
/*--------------------------------------------------------------------------*/
/* */
/* GetDisketteInfo() - */
/* */
/*--------------------------------------------------------------------------*/
VOID
GetDisketteInfo(
PDISKINFO pDisketteInfo,
PBPB pBPB
)
{
WORD secPerTrack;
secPerTrack = pBPB->secPerTrack;
/* Fill the DisketteInfo with the info from the default BPB. */
pDisketteInfo->wCylinderSize = secPerTrack * pBPB->cbSec * pBPB->cHead;
pDisketteInfo->wLastCylinder = (pBPB->cSec / (secPerTrack * pBPB->cHead))-1;
pDisketteInfo->wHeads = pBPB->cHead;
pDisketteInfo->wSectorsPerTrack = secPerTrack;
pDisketteInfo->wSectorSize = pBPB->cbSec;
}
/*--------------------------------------------------------------------------*/
/* */
/* DCopyMessageBox() - */
/* */
/*--------------------------------------------------------------------------*/
VOID
DCopyMessageBox(
HWND hwnd,
WORD idString,
WORD wFlags
)
{
LoadString(hAppInstance, IDS_COPYDISK, szTitle, sizeof(szTitle));
LoadString(hAppInstance, idString, szMessage, sizeof(szMessage));
MessageBox(hwnd, szMessage, szTitle, wFlags);
}
/*--------------------------------------------------------------------------*/
/* */
/* PromptDisketteChange() - */
/* */
/*--------------------------------------------------------------------------*/
VOID
PromptDisketteChange(
HWND hwnd,
BOOL bWrite
)
{
WORD idString;
if (bWrite)
idString = IDS_INSERTDEST;
else
idString = IDS_INSERTSRC;
/* These dialogs have to be sysmodal because the DiskCopy progress dialog
* is now made a SysModal one; The following messagebox will hang if it
* is NOT sysmodal;
* A part of the Fix for Bug #10075 --SANKAR-- 03-05-90
*/
DCopyMessageBox(hwnd, idString, MB_OK | MB_SYSTEMMODAL | MB_ICONINFORMATION);
}
/*--------------------------------------------------------------------------*/
/* */
/* ReadWriteCylinder() - */
// BOOL bWrite; TRUE for Write, FALSE for Read
/* */
/*--------------------------------------------------------------------------*/
INT
ReadWriteCylinder(
BOOL bWrite,
WORD wCylinder,
PDISKINFO pDisketteInfo
)
{
register INT rc;
WORD wHead;
WORD wDrive;
WORD wSectorCount;
WORD wTrackSize;
LPSTR lpBuffer;
wDrive = pDisketteInfo->wDrive;
wSectorCount = pDisketteInfo->wSectorsPerTrack;
wTrackSize = (wSectorCount * pDisketteInfo->wSectorSize);
if (hDosMemory)
lpBuffer = lpDosMemory;
/* Perform the operation for all the heads for a given cylinder */
for (wHead=0; wHead < pDisketteInfo->wHeads; wHead++) {
if (!hDosMemory)
lpBuffer = lpReadWritePtr;
if (bWrite) {
if (hDosMemory)
memcpy(lpBuffer, lpReadWritePtr, wTrackSize);
rc = GenericReadWriteSector((LPSTR)lpBuffer,
INT13_WRITE,
wDrive,
wCylinder,
wHead,
wSectorCount);
if (rc) {
/* Format all tracks starting from the given track */
if (!bFormatDone) {
if (!FormatAllTracks(pDisketteInfo, wCylinder, wHead, lpFormatBuffer))
return (-1); /* Failure */
rc = GenericReadWriteSector((LPSTR)lpBuffer,
INT13_WRITE,
wDrive,
wCylinder,
wHead,
wSectorCount);
} else
break;
}
} else {
rc = GenericReadWriteSector((LPSTR)lpBuffer,
INT13_READ,
wDrive,
wCylinder,
wHead,
wSectorCount);
if (hDosMemory)
memcpy(lpReadWritePtr, lpBuffer, wTrackSize);
/*** FIX30: What about the DOS 4.0 volume stuff??? ***/
}
if (rc)
return (-1);
lpReadWritePtr += wTrackSize;
}
return (0);
}
/*--------------------------------------------------------------------------*/
/* */
/* ReadWriteMaxPossible() - */
// BOOL bWrite TRUE for Write, FALSE for Read
/* */
/*--------------------------------------------------------------------------*/
/* This reads or writes as many cylinders as possible into the hpDisketteBuffer.
* It returns the next cylinder to be read.
*/
INT
ReadWriteMaxPossible(
BOOL bWrite,
WORD wStartCylinder,
PDISKINFO pDisketteInfo
)
{
MSG msg;
WORD wPercentDone;
DWORD dwBufferSize;
dwBufferSize = dwDisketteBufferSize;
/* We will read a cylinder only if we can read the entire cylinder. */
while (dwBufferSize >= pDisketteInfo->wCylinderSize) {
/* Check if any messages are pending */
if (!PeekMessage((LPMSG)&msg, (HWND)NULL, 0, 0, PM_REMOVE)) {
/* No message; So, go ahead with read/write */
if (ReadWriteCylinder(bWrite, wStartCylinder, pDisketteInfo))
return (-1);
wStartCylinder++;
wCompletedCylinders++;
/* Have we read/written all the cylinders? */
if (wStartCylinder > pDisketteInfo->wLastCylinder)
break;
/* Since each cylinder is counted once during read and once during
* write, number of cylinders is multiplied by 50 and not 100.
*/
wPercentDone = (wCompletedCylinders * 50) / (pDisketteInfo->wLastCylinder + 1);
if (LoadString(hAppInstance, IDS_PERCENTCOMP, szTitle, 32)) {
wsprintf(szMessage, szTitle, wPercentDone);
SendDlgItemMessage(hdlgProgress, IDD_PROGRESS, WM_SETTEXT, 0, (LPARAM)szMessage);
}
dwBufferSize -= pDisketteInfo->wCylinderSize;
} else {
/* Check if this is a message for the ProgressDlg */
if (!IsDialogMessage(hdlgProgress, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
/* That message might have resulted in a Abort */
if (bUserAbort)
return (-1);
}
}
}
return (wStartCylinder);
}
/*--------------------------------------------------------------------------*/
/* */
/* ReadWrite() - */
// BOOL bWrite TRUE for Write, FALSE for Read
/* */
/*--------------------------------------------------------------------------*/
/* This reads or writes as many cylinders as possible into the hpDisketteBuffer.
* It returns the next cylinder to be read.
*/
INT
ReadWrite(
BOOL bWrite,
WORD wStartCylinder,
PDISKINFO pDisketteInfo
)
{
INT iRetVal = 0;
return (iRetVal);
}
/*--------------------------------------------------------------------------*/
/* */
/* RestoreDPB() - */
/* */
/*--------------------------------------------------------------------------*/
BOOL
RestoreDPB(
INT nDisk,
HANDLE hSavedParams
)
{
register PDevPB pDevPB;
if (!(pDevPB = (PDevPB)LocalLock(hSavedParams)))
return (FALSE);
pDevPB->SplFunctions = 4;
LocalUnlock(hSavedParams);
LocalFree(hSavedParams);
return (TRUE);
}
/*--------------------------------------------------------------------------*/
/* */
/* CopyDiskette() - */
/* */
/*--------------------------------------------------------------------------*/
/* NOTE: Returns positive value for success otherwise failure. */
INT
APIENTRY
CopyDiskette(
HWND hwnd,
WORD nSourceDisk,
WORD nDestDisk
)
{
INT rc = -1;
register WORD wCylinder;
WORD wNextCylinder;
PBPB pIoctlBPB; /* Source Drive's BPB (taken from DevicePB) */
PBPB pBootBPB; /* Boot Drive's BPB (taken from Boot sector) */
PBPB pDestBPB;
DevPB dpbSrceParams;
DevPB dpbDestParams;
HANDLE hTrackLayout = NULL;
HANDLE hSaveSrceParams;
HANDLE hSaveDestParams;
FARPROC lpfnDialog;
DISKINFO SourceDisketteInfo;
DISKINFO DestDisketteInfo;
/* Check if it is a two drive system; put message to insert both floppies */
if (nSourceDisk != nDestDisk) {
bSingleDrive = FALSE;
DCopyMessageBox(hwnd, IDS_INSERTSRCDEST, MB_OK);
} else {
bSingleDrive = TRUE;
DCopyMessageBox(hwnd, IDS_INSERTSRC, MB_OK);
}
/* Get the BiosParameterBlock of source drive */
if (!(pIoctlBPB = GetBPB(nSourceDisk, &dpbSrceParams)))
return (0);
/* Get the BiosParameterBlock of the Source Diskette */
if (!(pBootBPB = GetBootBPB(nSourceDisk)))
return (0);
/* Get the BPB and DPB for the Destination drive also; */
if (!bSingleDrive) {
if (!(pDestBPB = GetBPB(nDestDisk, &dpbDestParams)))
return (0);
/* Compare BPB of source and Dest to see if they are compatible */
if (!(CheckBPBCompatibility(pIoctlBPB, dpbSrceParams.devType, pDestBPB, dpbDestParams.devType))) {
DCopyMessageBox(hwnd, IDS_COPYSRCDESTINCOMPAT, MB_ICONHAND | MB_OK);
return (0);
}
}
if (!ModifyDeviceParams(nSourceDisk, &dpbSrceParams, &hSaveSrceParams, pIoctlBPB, pBootBPB))
return (0);
if (!bSingleDrive) {
if (!ModifyDeviceParams(nDestDisk, &dpbDestParams, &hSaveDestParams, pDestBPB, pBootBPB)) {
RestoreDPB(nSourceDisk, hSaveSrceParams);
return (0);
}
}
GetDisketteInfo((PDISKINFO)&SourceDisketteInfo, pBootBPB);
/* The Destination Diskette must have the same format as the source */
DestDisketteInfo = SourceDisketteInfo;
/* Except the drive number */
SourceDisketteInfo.wDrive = nSourceDisk;
DestDisketteInfo.wDrive = nDestDisk;
/* In case we need to format the destination diskette, we need to know the
* track layout; So, build a DPB with the required track layout;
*/
if (wDOSversion >= DOS_320) {
if (!(hTrackLayout = BuildDevPB(&dpbSrceParams)))
goto Failure0;
pTrackLayout = (PDevPB)LocalLock(hTrackLayout);
/* The following is required to format a 360KB floppy in a 1.2MB
* drive of NCR PC916 machine; We do formatting, if the destination
* floppy is an unformatted one;
* Fix for Bug #6894 --01-10-90-- SANKAR --
*/
if (pTrackLayout->BPB.bMedia == MEDIA_360) {
pTrackLayout->NumCyls = 40;
pTrackLayout->bMediaType = 1;
}
}
/* We wish we could do the following allocation at the begining of this
* function, but we can not do so, because we need SourceDisketteInfo
* and we just got it;
*/
if (!AllocDiskCopyBuffers((PDISKINFO)&SourceDisketteInfo)) {
DCopyMessageBox(hwnd, IDS_REASONS+DE_INSMEM, MB_ICONHAND | MB_OK);
goto Failure0;
}
bUserAbort = FALSE;
wCompletedCylinders = 0;
hdlgProgress = CreateDialog(hAppInstance, (LPSTR)MAKEINTRESOURCE(DISKCOPYPROGRESSDLG), hwnd, ProgressDlgProc);
if (!hdlgProgress)
goto Failure2;
EnableWindow(hwnd, FALSE);
/* Start with the first cylinder. */
wCylinder = 0;
while (wCylinder <= SourceDisketteInfo.wLastCylinder) {
/* If this is a single drive system, ask the user to insert
* the source diskette.
* Do not prompt for the first time, because the Source diskette is
* already in the drive.
*/
if (bSingleDrive && (wCylinder > 0))
PromptDisketteChange(hdlgProgress, FALSE);
/* Read in the current cylinder. */
rc = ReadWrite(FALSE, wCylinder, (PDISKINFO)&SourceDisketteInfo);
if (rc < 0)
break;
else
wNextCylinder = (WORD)rc;
/* If this is a single drive system, ask the user to insert
* the destination diskette.
*/
if (bSingleDrive)
PromptDisketteChange(hdlgProgress, TRUE);
/* Write out the current cylinder. */
bFormatDone = FALSE;
rc = ReadWrite(TRUE, wCylinder, (PDISKINFO)&DestDisketteInfo);
if (rc < 0)
break;
wCylinder = wNextCylinder;
}
EnableWindow(hwnd, TRUE);
DestroyWindow(hdlgProgress);
hdlgProgress = NULL;
Failure2:
FreeBuffers();
Failure0:
if (wDOSversion >= DOS_320) {
/* Reset the Source drive parameters to the same as old */
RestoreDPB(nSourceDisk, hSaveSrceParams);
if (!bSingleDrive) {
/* Reset the Dest drive parameters to the same as old */
RestoreDPB(nDestDisk, hSaveDestParams);
}
}
if ((wDOSversion >= DOS_320) && hTrackLayout) {
LocalUnlock(hTrackLayout);
LocalFree(hTrackLayout);
}
return (rc);
}