709 lines
23 KiB
C
709 lines
23 KiB
C
/****************************************************************************/
|
|
/* */
|
|
/* WFSYS.C - */
|
|
/* */
|
|
/* Routines for Making Bootable Floppies */
|
|
/* */
|
|
/****************************************************************************/
|
|
|
|
#include "winfile.h"
|
|
#include "winnet.h"
|
|
#include "lfn.h"
|
|
#include "wfcopy.h"
|
|
|
|
#define CSYSFILES 3 /* Three system files are to be copied */
|
|
#define SYSFILENAMELEN 16 /* Example "A:\????????.???\0" */
|
|
|
|
#define SEEK_END 2 /* Used by _llseek() */
|
|
|
|
/* Error Codes. NOTE: Don't change this order! */
|
|
#define NOERROR 0 /* No error */
|
|
#define NOMEMORY 1 /* Insufficient memory */
|
|
#define NOSRCFILEBIOS 2 /* BIOS is missing */
|
|
#define NOSRCFILEDOS 3 /* DOS is missing */
|
|
#define NOSRCFILECMD 4 /* Command.Com is missing */
|
|
#define COPYFILEBIOS 5 /* Error in copying BIOS */
|
|
#define COPYFILEDOS 6 /* Error in copying DOS */
|
|
#define COPYFILECMD 7 /* Error in copying Command.com */
|
|
#define INVALIDBOOTSEC 8
|
|
#define INVALIDDSTDRIVE 9
|
|
#define DSTDISKERROR 10
|
|
#define NOTSYSABLE 11 /* First N clusters are NOT empty */
|
|
#define NOTSYSABLE1 12 /* First 2 entries in ROOT are not sys files */
|
|
#define NOTSYSABLE2 13 /* First N clusters are not allocated to SYS files */
|
|
#define NODISKSPACE 14 /* There is not sufficient disk space */
|
|
|
|
#define BUFFSIZE 8192
|
|
#define SECTORSIZE 512
|
|
|
|
LONG SysFileSize[CSYSFILES];
|
|
|
|
CHAR BIOSfile[SYSFILENAMELEN];
|
|
CHAR DOSfile[SYSFILENAMELEN];
|
|
CHAR COMMANDfile[130]; /* Command.com can have a full path name in COMSPEC= */
|
|
CHAR *SysFileNamePtr[CSYSFILES]; /* Ptrs to source file names */
|
|
|
|
/* SysNameTable contains the names of System files; First for PCDOS, the
|
|
* second set for MSDOS.
|
|
*/
|
|
CHAR *SysNameTable[2][3] = {
|
|
{"IBMBIO.COM", "IBMDOS.COM", "COMMAND.COM"},
|
|
{"IO.SYS", "MSDOS.SYS", "COMMAND.COM"}
|
|
};
|
|
|
|
|
|
BOOL
|
|
IsSYSable(
|
|
WORD iSrceDrive,
|
|
WORD iDestDrive,
|
|
CHAR DestFileNames[][SYSFILENAMELEN], /* NOTE: 2-dimensional array */
|
|
LPSTR lpFileBuff
|
|
);
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* SameFilenames() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* This checks whether the two filenames are the same or not.
|
|
* The problem lies in the fact that lpDirFileName points to the
|
|
* filename as it appears in a directory (filename padded with blanks
|
|
* up to eight characters and then followed by extension). But
|
|
* szFileName is an ASCII string with no embedded blanks and has a
|
|
* dot that seperates the extension from file name.
|
|
*/
|
|
|
|
BOOL
|
|
SameFilenames(
|
|
LPSTR lpDirFileName,
|
|
LPSTR szFileName
|
|
)
|
|
{
|
|
INT i;
|
|
CHAR c1;
|
|
CHAR c2;
|
|
|
|
/* lpDirFileName definitely has 11 characters (8+3). Nothing more!
|
|
* Nothing less!
|
|
*/
|
|
for (i=0; i < 11; i++) {
|
|
c1 = *lpDirFileName++;
|
|
c2 = *szFileName++;
|
|
if (c2 == '.') {
|
|
/* Skip all the blanks at the end of the filename */
|
|
while (c1 == ' ' && i < 11) {
|
|
c1 = *lpDirFileName++;
|
|
i++;
|
|
}
|
|
|
|
c2 = *szFileName++;
|
|
}
|
|
if (c1 != c2)
|
|
break;
|
|
}
|
|
return (i != 11);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* HasSystemFiles() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* See if the specified disk has IBMBIO.COM and IBMDOS.COM (or IO.SYS and
|
|
* MSDOS.SYS). If so, store their sizes in SysFileSize[].
|
|
*/
|
|
|
|
BOOL
|
|
APIENTRY
|
|
HasSystemFiles(
|
|
WORD iDrive
|
|
)
|
|
{
|
|
INT i;
|
|
HFILE fh;
|
|
DPB DPB;
|
|
BOOL rc;
|
|
CHAR ch;
|
|
LPSTR lpStr;
|
|
LPSTR lpFileBuff;
|
|
OFSTRUCT OFInfo;
|
|
HANDLE hFileBuff;
|
|
|
|
/* Initialise the source filename pointers */
|
|
SysFileNamePtr[0] = &BIOSfile[0];
|
|
SysFileNamePtr[1] = &DOSfile[0];
|
|
SysFileNamePtr[2] = &COMMANDfile[0];
|
|
|
|
hFileBuff = NULL;
|
|
lpFileBuff = NULL;
|
|
|
|
/* Acertain the presence of BIOS/DOS/COMMAND and grab their sizes.
|
|
* First we will try IBMBIO.COM. If it does not exist, then we will try
|
|
* IO.SYS. It it also does not exist, then it is an error.
|
|
*/
|
|
|
|
/* Get the DPB */
|
|
if (GetDPB(iDrive, &DPB) != NOERROR)
|
|
goto HSFError;
|
|
|
|
/* Check if the iDrive has standard sector size; If it doesn't then report
|
|
* error; (We can allocate a bigger buffer and proceed at this point, but
|
|
* int25 to read an abosolute sector may not work in pmodes, because they
|
|
* assume standard sector sizes;)
|
|
* Fix for Bug #10632 --SANKAR-- 03-21-90
|
|
*/
|
|
if (HIWORD(GetClusterInfo(iDrive)) > SECTORSIZE)
|
|
goto HSFError;
|
|
|
|
/* Allocate enough memory to read the first cluster of root dir. */
|
|
if (!(hFileBuff = LocalAlloc(LHND, (DWORD)SECTORSIZE)))
|
|
goto HSFError;
|
|
|
|
if (!(lpFileBuff = LocalLock(hFileBuff)))
|
|
goto HSFError;
|
|
|
|
/* Read the first cluster of the root directory. */
|
|
if (MyInt25(iDrive, lpFileBuff, 1, DPB.dir_sector))
|
|
goto HSFError;
|
|
|
|
/* Let us start with the first set of system files. */
|
|
for (i=0; i <= CSYSFILES-1; i++) {
|
|
lstrcpy((LPSTR)SysFileNamePtr[i], "C:\\");
|
|
lstrcat((LPSTR)SysFileNamePtr[i], SysNameTable[0][i]);
|
|
*SysFileNamePtr[i] = (BYTE)('A'+iDrive);
|
|
}
|
|
/* Get the command.com from the COMSPEC= environment variable */
|
|
lpStr = MGetDOSEnvironment();
|
|
|
|
/* Find the COMSPEC variable. */
|
|
while (*lpStr != TEXT('\0')) {
|
|
if (lstrlen(lpStr) > 8) {
|
|
ch = lpStr[7];
|
|
lpStr[7] = TEXT('\0');
|
|
if (lstrcmpi(lpStr, (LPSTR)"COMSPEC") == 0) {
|
|
lpStr[7] = ch;
|
|
break;
|
|
}
|
|
}
|
|
lpStr += lstrlen(lpStr)+1;
|
|
}
|
|
|
|
/* If no COMSPEC then things are really roached... */
|
|
if (*lpStr == TEXT('\0'))
|
|
goto HSFError;
|
|
|
|
/* The environment variable is COMSPEC; Look for '=' char */
|
|
while (*lpStr != '=')
|
|
lpStr = AnsiNext(lpStr);
|
|
|
|
/* Copy the command.com with the full pathname */
|
|
lstrcpy((LPSTR)SysFileNamePtr[2], lpStr);
|
|
|
|
/* Check if the IBMBIO.COM and IBMDOS.COM exist. */
|
|
if (SameFilenames(lpFileBuff, (LPSTR)(SysFileNamePtr[0]+3)) ||
|
|
SameFilenames(lpFileBuff+sizeof(DIRTYPE), (LPSTR)(SysFileNamePtr[1]+3))) {
|
|
/* Check if at least IO.SYS and MSDOS.SYS exist. */
|
|
lstrcpy((LPSTR)(SysFileNamePtr[0]+3), SysNameTable[1][0]);
|
|
lstrcpy((LPSTR)(SysFileNamePtr[1]+3), SysNameTable[1][1]);
|
|
if (SameFilenames(lpFileBuff, (SysFileNamePtr[0]+3)) ||
|
|
SameFilenames(lpFileBuff+sizeof(DIRTYPE), (SysFileNamePtr[1]+3)))
|
|
goto HSFError;
|
|
}
|
|
|
|
/* Check if COMMAND.COM exists in the source drive. */
|
|
if ((fh = MOpenFile((LPSTR)SysFileNamePtr[2], (LPOFSTRUCT)&OFInfo, OF_READ)) == -1)
|
|
goto HSFError;
|
|
|
|
/* Get the file sizes. */
|
|
SysFileSize[0] = ((LPDIRTYPE)lpFileBuff)->size;
|
|
SysFileSize[1] = ((LPDIRTYPE)(lpFileBuff+sizeof(DIRTYPE)))->size;
|
|
SysFileSize[2] = M_llseek(fh, 0L, SEEK_END);
|
|
M_lclose(fh);
|
|
rc = TRUE;
|
|
goto HSFExit;
|
|
|
|
HSFError:
|
|
rc = FALSE;
|
|
|
|
HSFExit:
|
|
if (lpFileBuff)
|
|
LocalUnlock(hFileBuff);
|
|
if (hFileBuff)
|
|
LocalFree(hFileBuff);
|
|
MFreeDOSEnvironment(lpStr);
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* CalcFreeSpace() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* Given an array of filenames and the number of files, this function
|
|
* calculates the freespace that would be created if those files are deleted.
|
|
*
|
|
* NOTE: This function returns TOTAL free space, (i.e) the summation of
|
|
* already existing free space and the space occupied by those files.
|
|
*/
|
|
|
|
INT
|
|
CalcFreeSpace(
|
|
CHAR DestFiles[][SYSFILENAMELEN],
|
|
INT cFiles,
|
|
INT cbCluster,
|
|
WORD wFreeClusters,
|
|
WORD wReqdClusters
|
|
)
|
|
{
|
|
INT i;
|
|
HFILE fh;
|
|
LONG lFileSize;
|
|
OFSTRUCT OFInfo;
|
|
|
|
ENTER("CalcFreeSpace");
|
|
|
|
/* Find out the space already occupied by SYS files, if any. */
|
|
for (i=0; i < cFiles; i++) {
|
|
fh = MOpenFile(&DestFiles[i][0], &OFInfo, OF_READ);
|
|
if (fh != (HFILE)-1) {
|
|
/* Get the file size */
|
|
lFileSize = M_llseek(fh, 0L, SEEK_END);
|
|
|
|
if (lFileSize != -1L)
|
|
wFreeClusters += LOWORD((lFileSize + cbCluster - 1)/cbCluster);
|
|
|
|
M_lclose(fh);
|
|
|
|
if (wFreeClusters >= wReqdClusters)
|
|
return (wFreeClusters);
|
|
}
|
|
}
|
|
LEAVE("CalcFreeSpace");
|
|
return (wFreeClusters);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* CheckDiskSpace() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
BOOL
|
|
CheckDiskSpace(
|
|
WORD iDestDrive,
|
|
INT cbCluster, /* Bytes/Cluster of dest drive */
|
|
CHAR DestFileNames[][SYSFILENAMELEN], /* NOTE: 2-dimensional array */
|
|
BOOL bDifferentSysFiles,
|
|
CHAR DestSysFiles[][SYSFILENAMELEN]
|
|
)
|
|
|
|
{
|
|
INT i;
|
|
INT wFreeClusters;
|
|
INT wReqdClusters;
|
|
|
|
/* Compute the number of clusters required. */
|
|
wReqdClusters = 0;
|
|
for (i=0; i < CSYSFILES; i++)
|
|
wReqdClusters += LOWORD((SysFileSize[i] + cbCluster - 1) / cbCluster);
|
|
|
|
/* Calculate the free disk space in clusters in the destination disk */
|
|
wFreeClusters = LOWORD(GetFreeDiskSpace(iDestDrive) / cbCluster);
|
|
|
|
if (wFreeClusters >= wReqdClusters)
|
|
/* We have enough space. */
|
|
return (TRUE);
|
|
|
|
wFreeClusters = CalcFreeSpace(DestFileNames, CSYSFILES, cbCluster, (WORD)wFreeClusters, (WORD)wReqdClusters);
|
|
if (wFreeClusters >= wReqdClusters)
|
|
return (TRUE);
|
|
|
|
/* Check if the sys files in the dest disk are different. */
|
|
if (bDifferentSysFiles) {
|
|
wFreeClusters = CalcFreeSpace(DestSysFiles, 2, cbCluster, (WORD)wFreeClusters, (WORD)wReqdClusters);
|
|
if (wFreeClusters >= wReqdClusters)
|
|
return (TRUE);
|
|
}
|
|
|
|
/* Insufficient disk space even if we delete the sys files. */
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* IsSYSable() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* The requirements for the destination disk to be sysable are either:
|
|
*
|
|
* 1) first two directory entries are empty
|
|
* 2) the first N clusters free where N = ceil (size IBMBIO/secPerClus)
|
|
* 3) there is enough room on the disk for IBMBIO/IBMDOS/COMMAND
|
|
*
|
|
* - or -
|
|
*
|
|
* 1) the first two directory entries are IBMBIO.COM and IBMDOS.COM
|
|
* or IO.SYS and MSDOS.SYS
|
|
* 2) the first N clusters are alloced to these files where N is defines above.
|
|
* 3) there is enough room on the disk for IBMBIO/IBMDOS/COMMAND after
|
|
* deleting the IBMBIO/IBMDOS/COMMAND on the disk.
|
|
*
|
|
* IMPORTANT NOTE:
|
|
* DestFileNames[][] contain the names of the sys files that would be
|
|
* created on the Destination diskette;
|
|
* DestSysFiles[][] contain the names of the sys files already
|
|
* present in the destination diskette, if any; Please Note that
|
|
* these two sets of filenames need not be the same, because you can
|
|
* install MSDOS on to a diskette that already has PCDOS and
|
|
* vice-versa.
|
|
*/
|
|
|
|
BOOL
|
|
IsSYSable(
|
|
WORD iSrceDrive,
|
|
WORD iDestDrive,
|
|
CHAR DestFileNames[][SYSFILENAMELEN], /* NOTE: 2-dimensional array */
|
|
LPSTR lpFileBuff
|
|
)
|
|
{
|
|
#ifdef LATER
|
|
INT i;
|
|
DPB DPB;
|
|
WORD clusTmp1, clusTmp2;
|
|
WORD clusBIOS, clusDOS;
|
|
INT cBytesPerCluster;
|
|
INT cBIOSsizeInClusters;
|
|
BOOL bDifferentDestFiles = FALSE;
|
|
CHAR chVolLabel[11]; /* This is NOT null terminated */
|
|
DWORD dwSerialNo;
|
|
CHAR DestSysFiles[2][SYSFILENAMELEN];
|
|
INT cContigClusters;
|
|
DWORD dwClusterInfo;
|
|
CHAR szTemp[SYSFILENAMELEN];
|
|
|
|
/* Grab DPB for destination. */
|
|
if (GetDPB(iDestDrive, &DPB))
|
|
return (FALSE);
|
|
|
|
/* Has the user aborted? */
|
|
if (WFQueryAbort())
|
|
return (FALSE);
|
|
|
|
/* Get bytes per cluster for destination. */
|
|
dwClusterInfo = GetClusterInfo(iDestDrive);
|
|
/* Bytes per cluster = sectors per cluster * size of a sector */
|
|
cBytesPerCluster = LOWORD(dwClusterInfo) * HIWORD(dwClusterInfo);
|
|
if (!cBytesPerCluster)
|
|
return (FALSE);
|
|
|
|
/* Has the user aborted? */
|
|
if (WFQueryAbort())
|
|
return (FALSE);
|
|
|
|
/* Convert size of BIOS into full clusters */
|
|
cBIOSsizeInClusters = LOWORD((SysFileSize[0] + cBytesPerCluster - 1) / cBytesPerCluster);
|
|
|
|
/* Number of clusters required to be contiguous depends on DOS versions.
|
|
* DOS 3.2 and below expect all clusters of BIOS to be contiguos.
|
|
* But 3.3 and above expect only the first stub loader (<2K) to be contiguous.
|
|
*/
|
|
cContigClusters = (GetDOSVersion() > 0x314) ?
|
|
((2048 + cBytesPerCluster - 1)/cBytesPerCluster) :
|
|
cBIOSsizeInClusters;
|
|
|
|
/* Grab first sector of destination root directory */
|
|
if (MyInt25(iDestDrive, lpFileBuff, 1, DPB.dir_sector))
|
|
return (FALSE);
|
|
|
|
/* Has the user aborted? */
|
|
if (WFQueryAbort())
|
|
return (FALSE);
|
|
|
|
/* Are the first two directory entries empty? */
|
|
if ((lpFileBuff[0] == 0 || (BYTE)lpFileBuff[0] == 0xE5) &&
|
|
(lpFileBuff[sizeof(DIRTYPE)] == 0 || (BYTE)lpFileBuff[sizeof(DIRTYPE)] == 0xE5)) {
|
|
/* Any of first N (= BIOS size) clusters not empty? */
|
|
for (i=0; i < cContigClusters; i++) {
|
|
/* Has the user aborted? */
|
|
if (WFQueryAbort())
|
|
return (FALSE);
|
|
}
|
|
} else {
|
|
/* Are the first two directory entries NOT BIOS/DOS? */
|
|
for (i=0; i < 2; i++) {
|
|
if ((!SameFilenames(lpFileBuff, SysNameTable[i][0])) ||
|
|
(!SameFilenames(lpFileBuff+sizeof(DIRTYPE), SysNameTable[i][1]))) {
|
|
/* Check if the destination files are the same as the source files */
|
|
if (lstrcmpi(&DestFileNames[0][3], SysNameTable[i][0])) {
|
|
/* No! Delete the other set of filenames. */
|
|
DestSysFiles[0][0] = DestSysFiles[1][0] = (BYTE)('A'+iDestDrive);
|
|
lstrcpy(&DestSysFiles[0][1], ":\\");
|
|
lstrcpy(&DestSysFiles[0][3], SysNameTable[i][0]);
|
|
lstrcpy(&DestSysFiles[1][1], ":\\");
|
|
lstrcpy(&DestSysFiles[1][3], SysNameTable[i][1]);
|
|
bDifferentDestFiles = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Did we find a match? */
|
|
if (i == 2)
|
|
/* Nope, the 2 entries are occupied by non-system files. */
|
|
return (FALSE);
|
|
|
|
/* Any of first N clusters NOT allocated to BIOS/DOS? */
|
|
clusBIOS = ((LPDIRTYPE)lpFileBuff)->first;
|
|
clusDOS = ((LPDIRTYPE)(lpFileBuff + sizeof(DIRTYPE)))->first;
|
|
|
|
/* Do it the hard way, for each cluster 2..N+2 see if it is in the chain.
|
|
*/
|
|
for (i=0; i < cContigClusters; i++) {
|
|
clusTmp1 = clusBIOS;
|
|
clusTmp2 = clusDOS;
|
|
|
|
/* Check if cluster #i+2 is allocated to either of these files. */
|
|
while (TRUE) {
|
|
if (i+2 == (INT)clusTmp1 || i+2 == (INT)clusTmp2)
|
|
break;
|
|
|
|
// if (clusTmp1 != -1)
|
|
if (clusTmp1 < 0xFFF0)
|
|
clusTmp1 = 0;
|
|
// if (clusTmp2 != -1)
|
|
if (clusTmp2 < 0xFFF0)
|
|
clusTmp2 = 0;
|
|
// if (clusTmp1 == -1 && clusTmp2 == -1)
|
|
if (clusTmp1 >= 0xFFF0 && clusTmp2 >= 0xFFF0)
|
|
return FALSE;
|
|
|
|
/* Did the user abort? */
|
|
if (WFQueryAbort())
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Let us check if there is enough space on the dest disk. */
|
|
if (CheckDiskSpace(iDestDrive, cBytesPerCluster, DestFileNames, bDifferentDestFiles, DestSysFiles) == FALSE)
|
|
return (FALSE);
|
|
|
|
/* Has the user aborted? */
|
|
if (WFQueryAbort())
|
|
return (FALSE);
|
|
|
|
/* Get the Present Volume label and preserve it. */
|
|
GetVolumeLabel(iDestDrive, (LPSTR)chVolLabel, FALSE);
|
|
|
|
/*** NOTE: chVolLabel remains in OEM characters! ***/
|
|
|
|
/* Get the serial no if any and preserve it. */
|
|
dwSerialNo = ReadSerialNumber(iDestDrive, lpFileBuff);
|
|
|
|
/* Copy and adjust boot sector from source to destination */
|
|
if (WriteBootSector(iSrceDrive, iDestDrive, NULL, lpFileBuff) != NOERROR)
|
|
return (FALSE);
|
|
|
|
/* Restore the old volume label and serial number in the boot rec. */
|
|
if (ModifyVolLabelInBootSec(iDestDrive, (LPSTR)chVolLabel, dwSerialNo, lpFileBuff))
|
|
return (FALSE);
|
|
|
|
/* Delete destination BIOS/DOS/COMMAND. */
|
|
for (i=0; i < CSYSFILES; i++) {
|
|
AnsiToOem(DestFileNames[i], szTemp);
|
|
SetFileAttributes(szTemp, 0);
|
|
DosDelete(szTemp);
|
|
if ((bDifferentDestFiles) && (i < 2)) {
|
|
SetFileAttributes(szTemp, 0);
|
|
DosDelete(szTemp);
|
|
}
|
|
|
|
/* Has the user aborted? */
|
|
if (WFQueryAbort())
|
|
return (FALSE);
|
|
}
|
|
|
|
/* Reset the DPB_next_free field of the DPB to 2, sothat when IBMBIO.COM is
|
|
* copied into this disk, the clusters will get allocated starting from 2.
|
|
*/
|
|
ModifyDPB(iDestDrive);
|
|
#endif // LATER
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* MakeSystemDiskette() - */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/* This routine is intended to mimic the functions of the SYS command
|
|
* under MSDOS: to transfer a version of the operating system from a source
|
|
* disk to a destination such that the destination will be bootable.
|
|
*
|
|
* The requirements of the source disk is that it contain:
|
|
*
|
|
* 1) a command processor (COMMAND.COM)
|
|
* 2) a default set of device drivers (IBMBIO.COM)
|
|
* 3) an operating system (IBMDOS.COM)
|
|
* 4) a boot sector appropriate to the device drivers
|
|
*
|
|
* The requirements for the destination disk are either:
|
|
*
|
|
* 1) first two directory entries are empty
|
|
* 2) the first N clusters free where N = ceil (size IBMBIO/secPerClus)
|
|
* 3) there is enough room on the disk for IBMBIO/IBMDOS/COMMAND
|
|
*
|
|
* - or -
|
|
*
|
|
* 1) the first two directory entries are IBMBIO.COM and IBMDOS.COM
|
|
* or IO.SYS and MSDOS.SYS
|
|
* 2) the first N clusters are alloced to these files where N is defined
|
|
* above
|
|
* 3) there is enough room on the disk for IBMBIO/IBMDOS/COMMAND after
|
|
* deleting the IBMBIO/IBMDOS/COMMAND on the disk.
|
|
*
|
|
* Inputs:
|
|
* iDestDrive 0-based drive number of formatted drive
|
|
* for destination.
|
|
* bEmptyFloppy : TRUE if the floppy is empty; Useful when
|
|
* the floppy is just formatted; No need to check if
|
|
* it is Sysable;
|
|
* Returns: 0 Successful transferral of boot sector and files
|
|
* <> 0 error code.
|
|
*/
|
|
|
|
|
|
BOOL
|
|
APIENTRY
|
|
MakeSystemDiskette(
|
|
WORD iDestDrive,
|
|
BOOL bEmptyFloppy
|
|
)
|
|
{
|
|
INT i;
|
|
HANDLE hFileBuff; /* Buffer to read in file contents etc., */
|
|
LPSTR lpFileBuff;
|
|
CHAR DestFileName[CSYSFILES][SYSFILENAMELEN];
|
|
CHAR szTemp1[SYSFILENAMELEN];
|
|
CHAR szTemp2[SYSFILENAMELEN];
|
|
WORD nSource;
|
|
|
|
nSource = (WORD)GetBootDisk();
|
|
|
|
|
|
if (!HasSystemFiles(nSource)) {
|
|
LoadString(hAppInstance, IDS_SYSDISKNOFILES, szMessage, sizeof(szMessage));
|
|
MessageBox(hdlgProgress, szMessage, szTitle, MB_OK | MB_ICONSTOP);
|
|
bUserAbort = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
if (iDestDrive == nSource) {
|
|
LoadString(hAppInstance, IDS_SYSDISKSAMEDRIVE, szMessage, sizeof(szMessage));
|
|
MessageBox(hdlgProgress, szMessage, szTitle, MB_OK | MB_ICONSTOP);
|
|
bUserAbort = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize variables for cleanup. */
|
|
hFileBuff = NULL;
|
|
lpFileBuff = NULL;
|
|
|
|
/* Flush the DOS buffers. */
|
|
DiskReset();
|
|
|
|
if (!(hFileBuff = LocalAlloc(LHND, (DWORD)BUFFSIZE)))
|
|
return (1);
|
|
|
|
lpFileBuff = LocalLock(hFileBuff);
|
|
|
|
for (i=0; i < (CSYSFILES - 1); i++) {
|
|
/* Create the destination file names */
|
|
lstrcpy((LPSTR)&DestFileName[i][0], (LPSTR)SysFileNamePtr[i]);
|
|
DestFileName[i][0] = (BYTE)('A' + iDestDrive);
|
|
}
|
|
|
|
/* Copy just the Command.COM without any path name */
|
|
lstrcpy((LPSTR)DestFileName[2], "X:\\");
|
|
lstrcat((LPSTR)DestFileName[2], (LPSTR)SysNameTable[0][2]);
|
|
DestFileName[2][0] = (BYTE)('A' + iDestDrive);
|
|
|
|
/* Check if it is an empty floppy; If so, there is no need to check if it
|
|
* is 'SYSable'. It is bound to be 'Sysable'. So, skip all the checks and
|
|
* go ahead with copying the sys files.
|
|
*/
|
|
if (!bEmptyFloppy) {
|
|
|
|
/* Check if the Destination floppy is SYS-able */
|
|
if (!IsSYSable(nSource, iDestDrive, DestFileName, lpFileBuff))
|
|
goto MSDErrExit;
|
|
|
|
/* Did the user abort? */
|
|
if (WFQueryAbort())
|
|
goto MSDErrExit;
|
|
}
|
|
|
|
/* Copy files */
|
|
|
|
bCopyReport = FALSE;
|
|
|
|
DisableFSC();
|
|
|
|
for (i=0; i < CSYSFILES; i++) {
|
|
/* Copy all files except command.com with sys attributes */
|
|
AnsiToOem(SysFileNamePtr[i], szTemp1);
|
|
AnsiToOem(DestFileName[i], szTemp2);
|
|
|
|
/* Make sure the destination file is deleted first */
|
|
SetFileAttributes(szTemp2, ATTR_ALL);
|
|
WFRemove(szTemp2);
|
|
|
|
// copy code preserves the attributes
|
|
if (FileCopy(szTemp1, szTemp2))
|
|
goto MSDErrExit2;
|
|
|
|
if (WFQueryAbort())
|
|
goto MSDErrExit2;
|
|
}
|
|
|
|
|
|
if (EndCopy()) // empty the copy queue
|
|
goto MSDErrExit2;
|
|
|
|
EnableFSC();
|
|
|
|
/* Normal Exit. */
|
|
|
|
LocalUnlock(hFileBuff);
|
|
LocalFree(hFileBuff);
|
|
|
|
return FALSE; // success
|
|
|
|
MSDErrExit2:
|
|
|
|
EnableFSC();
|
|
|
|
MSDErrExit:
|
|
|
|
CopyAbort(); // Purge any copy commands in copy queue
|
|
LocalUnlock(hFileBuff);
|
|
LocalFree(hFileBuff);
|
|
|
|
return TRUE; // failure
|
|
}
|