windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/copy.c

2522 lines
71 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "precomp.h"
#pragma hdrstop
/* File: filecm.c */
/*************************************************************************
** Install: File Copying commands.
**************************************************************************/
extern HWND hwndFrame;
extern HANDLE hinstShell;
extern HWND hwndProgressGizmo;
extern CHP rgchBufTmpLong[];
/* Globals */
CHP szFullPathSrc[cchpFullPathBuf] = "\0";
CHP szFullPathDst[cchpFullPathBuf] = "\0";
CHP szFullPathBak[cchpFullPathBuf] = "\0";
CHAR GaugeText1[50], GaugeText2[50];
BOOL fNTUpgradeSetup,fInitialSetup;
SZ APIENTRY SzGetSrcDollar(SZ szFullPathSrc,CHAR ch);
PSTR LOCAL_SOURCE_DIRECTORY = "\\$WIN_NT$.~LS";
int
DetermineDriveType(
IN CHAR DriveLetter
);
BOOL
FGetFileSecurity(
PCHAR File,
PSECURITY_DESCRIPTOR *SdBuf,
CB *SdLen
);
BOOL
FSetFileSecurity(
PCHAR File,
PSECURITY_DESCRIPTOR SdBuf
);
VOID
ValidateAndChecksumFile(
IN PSTR Filename,
OUT PBOOLEAN IsNtImage,
OUT PULONG Checksum,
OUT PBOOLEAN Valid
);
BOOL
DoesFileReplaceThirdPartyFile(
SZ szFullPathDst
);
/*
** Purpose:
** Copies all files in the current copy list and resets the list to
** empty. Copying is sorted by source disk to limit potential disk
** swapping.
** Arguments:
** hInstance: non-NULL instance handle for getting strings from
** resources for SwapDisk message Box.
** Returns:
** Returns fTrue if all copies successful, fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY FCopyFilesInCopyList(hInstance)
HANDLE hInstance;
{
DID did;
PCLN pclnCur;
PPCLN ppclnPrev;
LONG lTotalSize;
PPCLN ppclnHead;
PPPCLN pppclnTail;
PSDLE psdle;
BOOL fSilentSystem = FGetSilent();
UINT fuModeSav;
PINFPERMINFO pPermInfo;
PSDLE psdleGlobalHead = (PSDLE)NULL;
PSDLE psdleGlobalEnd = (PSDLE)NULL;
PSDLE psdleGlobal;
DID didGlobalCur;
BOOL fCopyStatus = fFalse;
SZ sz;
if(!InitDiamond()) {
return(fFalse);
}
fInitialSetup = fFalse;
fNTUpgradeSetup = fFalse;
if (!fSilentSystem) {
ProOpen(hwndFrame, 0);
ProSetBarRange(10000);
}
//
// Determine if we are in initial setup
//
if ((sz = SzFindSymbolValueInSymTab("!STF_INSTALL_TYPE")) != (SZ)NULL &&
(CrcStringCompareI(sz, "SETUPBOOTED") == crcEqual)) {
fInitialSetup = fTrue;
}
//
// Determine if we are an NT upgrade setup
//
if (fInitialSetup
&& (sz = SzFindSymbolValueInSymTab("!STF_NTUPGRADE")) != (SZ)NULL
&& (CrcStringCompareI(sz, "YES") == crcEqual)) {
fNTUpgradeSetup = fTrue;
}
//
// Go through all the disk media descriptions and assign universal
// ids for all source media. This is necessary because two infs
// may refer to the same disk using different ids.
//
pPermInfo = pInfPermInfoHead;
didGlobalCur = didMin;
while ( pPermInfo ) {
//
// If the INF has a source media description list, go through list
//
psdle = pPermInfo->psdleHead;
while ( psdle ) {
//
// search all the global psdles for a match with the current
// disk. search based on disk label ( which is hopefully unique )
//
psdleGlobal = psdleGlobalHead;
while ( psdleGlobal ) {
if( !CrcStringCompareI( psdleGlobal->szLabel, psdle->szLabel ) ) {
break;
}
psdleGlobal = psdleGlobal->psdleNext;
}
if ( psdleGlobal == NULL ) {
PSDLE psdleNew;
if ((psdleNew = PsdleAlloc()) == (PSDLE)NULL ||
(psdleNew->szLabel = SzDupl(psdle->szLabel)) == (SZ)NULL ||
(psdle->szTagFile != NULL && ((psdleNew->szTagFile = SzDupl(psdle->szTagFile)) == (SZ)NULL)) ||
(psdle->szNetPath != NULL && ((psdleNew->szNetPath = SzDupl(psdle->szNetPath)) == (SZ)NULL))) {
goto CopyFailed;
}
psdleNew->psdleNext = (PSDLE)NULL;
if ( !psdleGlobalHead ) {
psdleGlobalHead = psdleGlobalEnd = psdleNew;
}
else {
psdleGlobalEnd->psdleNext = psdleNew;
psdleGlobalEnd = psdleNew;
}
psdleGlobal = psdleNew;
psdleGlobal->didGlobal = didGlobalCur++;
}
psdle->didGlobal = psdleGlobal->didGlobal;
psdle = psdle->psdleNext;
}
pPermInfo = pPermInfo->pNext;
}
//
// Go through the copy list of all infs and calculate total copy
// list cost
//
pPermInfo = pInfPermInfoHead;
lTotalSize = 0L;
while ( pPermInfo ) {
//
// If the INF has a source media description list, look at the
// copy list
//
if ( pPermInfo->psdleHead ) {
Assert(FValidCopyList( pPermInfo ));
ppclnHead = PpclnHeadList( pPermInfo );
pppclnTail = PppclnTailList( pPermInfo );
#if DBG
*pppclnTail = NULL; /* for FValidCopyList() calls */
#endif
pclnCur = *ppclnHead;
//
// Traverse the copy list and determine the total size of the
// files to copy.
//
while (pclnCur != (PCLN)NULL) {
if (pclnCur->psfd->oer.ctuCopyTime > 0) {
lTotalSize += pclnCur->psfd->oer.ctuCopyTime;
} else {
lTotalSize += pclnCur->psfd->oer.lSize;
}
pclnCur = pclnCur->pclnNext;
}
}
pPermInfo = pPermInfo->pNext;
}
if (lTotalSize == 0L) {
lTotalSize = 1L;
}
//
// Show gauge stuff if not in silent mode.
//
if (!fSilentSystem) {
SZ szText;
ProSetBarPos(0);
szText = SzFindSymbolValueInSymTab("ProText1");
if( szText ) {
strcpy(GaugeText1, szText);
}
else {
strcpy(GaugeText1, "");
}
szText = SzFindSymbolValueInSymTab("ProText2");
if( szText ) {
strcpy(GaugeText2, szText);
}
else {
strcpy(GaugeText2, "");
}
ProSetText(ID_STATUS3, "");
ProSetText(ID_STATUS4, "");
}
//
// Copy the files
//
psdleGlobal = psdleGlobalHead;
while (psdleGlobal ) {
didGlobalCur = psdleGlobal->didGlobal;
pPermInfo = pInfPermInfoHead;
while ( pPermInfo ) {
//
// Verify that this INF has a copy list
//
if ((psdle = pPermInfo->psdleHead) == (PSDLE)NULL ) {
Assert( !*PpclnHeadList( pPermInfo ) );
pPermInfo = pPermInfo->pNext;
continue;
}
Assert(FValidCopyList( pPermInfo ));
//
// If it does, go through its source media descriptions finding
// all disks that match the current global disk id and copy all
// files which are described by the disks found
//
while ( psdle ) {
if( psdle->didGlobal != didGlobalCur ) {
psdle = psdle->psdleNext;
continue;
}
did = psdle->did;
ppclnHead = PpclnHeadList( pPermInfo );
pppclnTail = PppclnTailList( pPermInfo );
#if DBG
*pppclnTail = NULL; /* for FValidCopyList() calls */
#endif
ppclnPrev = ppclnHead;
pclnCur = *ppclnHead;
//
// Now traverse the copy list, copying all
// the files that match the disk id
//
while (pclnCur != (PCLN)NULL) {
if ( (pclnCur->psfd->did != did) ||
(pclnCur->psfd->InfId != pPermInfo->InfId ) ) {
ppclnPrev = &(pclnCur->pclnNext);
pclnCur = pclnCur->pclnNext;
continue;
}
fuModeSav = SetErrorMode(
SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
);
if(!FCopyListFile(hInstance,pclnCur,psdle,lTotalSize)) {
SetErrorMode(fuModeSav);
goto CopyFailed;
}
SetErrorMode(fuModeSav);
//
// File copied, delete its entry from the copy list
//
*ppclnPrev = pclnCur->pclnNext;
EvalAssert(FFreePcln(pclnCur));
pclnCur = *ppclnPrev;
Assert(FValidCopyList( pPermInfo ));
}
psdle = psdle->psdleNext;
}
pPermInfo = pPermInfo->pNext;
}
psdleGlobal = psdleGlobal->psdleNext;
}
if (!fSilentSystem) {
ProSetBarPos(10000 - 1);
}
fCopyStatus = fTrue;
CopyFailed:
if (!fSilentSystem) {
ProClose(hwndFrame);
UpdateWindow(hwndFrame);
}
pPermInfo = pInfPermInfoHead;
while ( pPermInfo ) {
EvalAssert(FFreeCopyList( pPermInfo ));
pPermInfo = pPermInfo->pNext;
}
psdleGlobal = psdleGlobalHead;
while ( psdleGlobal ) {
PSDLE psdleNext = psdleGlobal->psdleNext;
FFreePsdle( psdleGlobal );
psdleGlobal = psdleNext;
}
TermDiamond();
RestoreDiskLoggingDone();
return(fCopyStatus);
}
/*
** Purpose:
** To determine if the given file is read only.
** Arguments:
** szFullPathDst : a non-Null, zero-terminated string containing the fully
** qualified valid path (including the drive) to the file in
** question. File must exist.
** Returns:
** ynrcYes if the file is read only, ynrcNo otherwise.
**
**************************************************************************/
YNRC APIENTRY YnrcFileReadOnly(szFullPathDst)
SZ szFullPathDst;
{
BOOL fOkay = fTrue;
unsigned uiAttrib;
ChkArg(szFullPathDst != (SZ)NULL && FValidPath(szFullPathDst) &&
FFileFound(szFullPathDst), 1, ynrcErr1);
if ((uiAttrib = GetFileAttributes(szFullPathDst)) == -1)
fOkay = fFalse;
if (!fOkay)
return(ynrcErr1);
return((uiAttrib & FILE_ATTRIBUTE_READONLY) ? ynrcYes : ynrcNo);
}
/*
** Purpose:
** To set the read only status of a file to either read only or normal.
** Arguments:
** szFullPathDst: a non-Null, zero-terminated string containing the fully
** qualified valid path (including drive) whose status is to be
** set. File must already exist.
** fReadOnly: fTrue if the status is to be set to read only, fFalse
** if the status is to be set to normal
** Returns:
** fTrue if the function succeeds in setting the status as specified,
** fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY FSetFileReadOnlyStatus(SZ szFullPathDst,BOOL fReadOnly)
{
BOOL fRet = fFalse;
DWORD uiAttrib;
DWORD newAttrib;
ChkArg(szFullPathDst != (SZ)NULL && FValidPath(szFullPathDst) &&
FFileFound(szFullPathDst), 1, fFalse);
if ((uiAttrib = GetFileAttributes(szFullPathDst)) != -1) {
if(fReadOnly) {
newAttrib = uiAttrib | FILE_ATTRIBUTE_READONLY;
} else {
newAttrib = uiAttrib & ~FILE_ATTRIBUTE_READONLY;
}
if((newAttrib == uiAttrib) || SetFileAttributes(szFullPathDst, newAttrib)) {
fRet = fTrue;
}
}
return(fRet);
}
/*
** Purpose:
** To determine if there is already a destination file that is "newer" than
** the source file.
** Arguments:
** dateSrc: valid date value in unsigned int form extracted from INF.
** szFullPathDst: a non-Null, zero terminated string containing the fully
** qualified valid path (including disk drive) to the destination
** file. File must exist.
** dwVerSrcMS: Most significant 32 bits of source file version stamp.
** dwVerSrcLS: Least significant 32 bits of source file version stamp.
** Returns:
** ynrcYes if the destination file already exists and is newer than
** the source file.
** ynrcErr1, ynrcErr2, or ynrcErr3 in errors.
** ynrcNo otherwise.
**
**************************************************************************/
YNRC APIENTRY YnrcNewerExistingFile(USHORT dateSrc,
SZ szFullPathDst, DWORD dwVerSrcMS, DWORD dwVerSrcLS)
{
USHORT dateDst, timeDst;
PFH pfhDst;
FILETIME WriteTime;
DWORD dwVerDstMS;
DWORD dwVerDstLS;
ChkArg(szFullPathDst != (SZ)NULL && FValidPath(szFullPathDst) &&
FFileFound(szFullPathDst), 2, ynrcErr1);
if ( (dwVerSrcMS != 0L || dwVerSrcLS != 0L) &&
FGetFileVersion(szFullPathDst, &dwVerDstMS, &dwVerDstLS)) {
if (dwVerDstMS > dwVerSrcMS ||
(dwVerDstMS == dwVerSrcMS && dwVerDstLS > dwVerSrcLS)) {
return(ynrcYes);
}
else {
return(ynrcNo);
}
}
else {
if ((pfhDst = PfhOpenFile(szFullPathDst, ofmRead)) == NULL) {
return(ynrcErr1);
}
if (!GetFileTime((HANDLE)LongToHandle(pfhDst->iDosfh), NULL, NULL, &WriteTime) ||
!FileTimeToDosDateTime(&WriteTime, &dateDst, &timeDst)) {
FCloseFile(pfhDst);
return(ynrcErr2);
}
if (!FCloseFile(pfhDst)) {
return(ynrcErr3);
}
if (dateDst > dateSrc) {
return(ynrcYes);
}
}
return(ynrcNo);
}
/*
** Purpose:
** Gets the file version values from the given file and sets the
** given pdwMS/pdwLS variables.
** Arguments:
** szFullPath: a zero terminated character string containing the fully
** qualified path (including disk drive) to the file.
** pdwMS: Most significant 32 bits of source file version stamp.
** pdwLS: Least significant 32 bits of source file version stamp.
** Returns:
** fTrue if file and file version resource found and retrieved,
** fFalse if not.
+++
** Implementation:
**************************************************************************/
BOOL APIENTRY FGetFileVersion(szFullPath, pdwMS, pdwLS)
SZ szFullPath;
DWORD * pdwMS;
DWORD * pdwLS;
{
BOOL fRet = fFalse;
DWORD dwHandle;
DWORD dwLen;
LPSTR lpData;
ChkArg(szFullPath != (SZ)NULL, 1, fFalse);
ChkArg(pdwMS != (DWORD *)NULL, 2, fFalse);
ChkArg(pdwLS != (DWORD *)NULL, 3, fFalse);
//
// Get the file version info size
//
if ((dwLen = GetFileVersionInfoSize((LPSTR)szFullPath, &dwHandle)) == 0) {
return (fRet);
}
//
// Allocate enough size to hold version info
//
while ((lpData = (LPSTR)SAlloc((CB)dwLen)) == (LPSTR)NULL) {
if (!FHandleOOM(hwndFrame)) {
return (fRet);
}
}
//
// Get the version info
//
fRet = GetFileVersionInfo((LPSTR)szFullPath, dwHandle, dwLen, lpData);
if (fRet) {
VS_FIXEDFILEINFO *pvsfi;
DWORD dwLen;
fRet = VerQueryValue(
(LPVOID)lpData,
(LPSTR)"\\",
(LPVOID *)&pvsfi,
&dwLen
);
if (fRet) {
*pdwMS = pvsfi->dwFileVersionMS;
*pdwLS = pvsfi->dwFileVersionLS;
}
}
SFree(lpData);
return (fRet);
}
/*
** Purpose:
** Renames the given destination file as a backup file based on
** the backup file name given. If a backup file with the given
** name already exists, the function does nothing and returns.
** Arguments:
** szDst: a zero terminated char string containing the fully
** qualified path to the file to be backed up.
** szBackup: a zero terminated char string containing the file name
** of the file that will be the backup copy of szDst. This is
** not a fully qualified path, or subpath, it is only the filename
** (i.e. primary.ext).
** psfd: pointer to the Section-File Description(SFD) structure of
** the file being backed up.
** Returns:
** ynrcNo: if the backup file name is invalid or if unable to create
** the backup and user chooses to abort.
** ynrcErr1: if unable to create the backup and the user chooses ignore.
** ynrcYes: if the backup is successfully created or already exists.
**
**************************************************************************/
YNRC APIENTRY YnrcBackupFile(szDst, szBackup, psfd)
SZ szDst;
SZ szBackup;
PSFD psfd;
{
YNRC ynrcRet = ynrcYes;
Unused(szBackup);
Assert(psfd->oer.szAppend == (SZ)NULL);
if (!FBuildFullBakPath(szFullPathBak, szDst, psfd) ||
!FValidPath(szFullPathBak))
return(ynrcNo);
/* If the backup file already exists, leave the existing backup
** and return. (Either the user made it and we don't want to kill
** his, or we made it and we don't need to make another one.)
*/
if (FFileFound(szFullPathBak))
return(ynrcYes);
while (rename(szFullPathDst, szFullPathBak))
{
EERC eerc;
if ((eerc = EercErrorHandler(hwndFrame, grcRenameFileErr,
psfd->oer.oef & oefVital, szFullPathDst, szFullPathBak, 0))
== eercAbort)
{
ynrcRet = ynrcNo;
break;
}
else if (eerc == eercIgnore)
{
ynrcRet = ynrcErr1;
break;
}
Assert(eerc == eercRetry);
}
return(ynrcRet);
}
/*
**************************************************************************/
USHORT APIENTRY DateFromSz(SZ sz)
{
USHORT usAns, usYear, usMonth, usDay;
ChkArg(sz == (SZ)NULL || FValidOerDate(sz), 1, 0);
if (sz == (SZ)NULL)
{
usYear = 1980;
usMonth = 1;
usDay = 1;
}
else
{
usYear = (USHORT)atoi(sz);
usMonth = (USHORT)atoi(sz + 5);
usDay = (USHORT)atoi(sz + 8);
}
Assert(usYear >= 1980 && usYear <= 2099);
Assert(usMonth >= 1 && usMonth <= 12);
Assert(usDay >= 1 && usDay <= 31);
usAns = usDay + (usMonth << 5) + ((usYear - (USHORT)1980) << 9);
return(usAns);
}
BOOL
CreateTargetAsLinkToMaster(
IN SZ FullSourceFilename,
IN SZ FullTargetFilename,
IN BOOL TargetExists
)
{
//BUGBUG: handle case of target file in use.
//BUGBUG: handle case of target already exists.
//BUGBUG: handle owm modes
//BUGBUG: The following code is written to work with the prototype COW
// server, not with the real SIS server. If the target file
// exists, we assume it is the correct version (in the master
// tree) and don't do the copy.
//
if ( TargetExists ) {
//DbgPrint( "SIS: Target %s exists; not copying\n", FullTargetFilename );
return NO_ERROR; // target exists; don't copy
}
//DbgPrint( "SIS: Target %s doesn't exist; copying\n", FullTargetFilename );
return ERROR_FILE_NOT_FOUND; // target doesn't exist; copy by usual means
}
/*
** Purpose:
** Performs the copy defined by the given copy list node.
** Arguments:
** hInstance: non-NULL instance handle for getting strings from
** resources for SwapDisk message Box.
** pcln: pointer to the Copy List Node (CLN) of the file to be
** copied.
** psdle: non-NULL Source-Description-List-Element pointer to be
** used by FPromptForDisk().
** lTotalSize: the total of all of the sizes (i.e. oer.ctuCopyTime or
** oer.lSize) for all of the files on the disk currently being copied.
** Returns:
** fTrue if the copy was successful, fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY
FCopyListFile(
HANDLE hInstance,
PCLN pcln,
PSDLE psdle,
LONG lTotalSize
)
{
PSFD psfd = pcln->psfd;
POER poer = &(psfd->oer);
BOOL fDstExists, fCompressedName;
SZ szSrcDollar = NULL;
BOOL fVital = poer->oef & oefVital;
EERC eerc;
int Removable;
LONG lSize;
USHORT dateSrc = DateFromSz(poer->szDate);
PSECURITY_DESCRIPTOR Sd = NULL;
CB SdLen;
CHP szNonCompressedFullPathSrc[cchpFullPathBuf] = "\0";
SZ SymbolValue;
CHAR szSrcDrive[10];
ChkArg(pcln != (PCLN)NULL, 1, fFalse);
ChkArg(psdle != (PSDLE)NULL, 2, fFalse);
//
// Only if a drive is removable do we check for the tagfile, in the case
// of a net drive the error is caught later on when we look for the src
// file. Note that the tag file is relative to the root of the removable
// drive.
//
// Because of a bug in 3.51 there are CD's which expect the tagfile to be
// locatable in a subdirectory. We'll use a hack based on STF_CWDDIR
// to make that work.
//
Removable = DetermineDriveType(*(pcln->szSrcDir));
if((Removable < 0) && psdle->szTagFile) {
strcpy(szSrcDrive,"?:\\");
szSrcDrive[0] = *(pcln->szSrcDir);
if(!FBuildFullSrcPath(szFullPathSrc,szSrcDrive,psdle->szTagFile,NULL)) {
EercErrorHandler(hwndFrame,grcInvalidPathErr,fVital,szSrcDrive,psdle->szTagFile,0);
return(!fVital);
}
if((Removable == -2) && (SymbolValue = SzFindSymbolValueInSymTab("!STF_CWDDIR"))) {
if(!FBuildFullSrcPath(szFullPathDst,SymbolValue,psdle->szTagFile,NULL)) {
szFullPathDst[0] = 0;
}
} else {
szFullPathDst[0] = 0;
}
//
// Strip the backslash off the drive letter.
//
szSrcDrive[2] = '\0';
//
// If we can't find the tag file at the root then also look in
// STF_CWDDIR, if there is one.
//
while(!FFileFound(szFullPathSrc) && (!szFullPathDst[0] || !FFileFound(szFullPathDst))) {
MessageBeep(0);
ShowOwnedPopups(hwndFrame,FALSE);
if(FPromptForDisk(hInstance, psdle->szLabel, szSrcDrive)) {
ShowOwnedPopups(hwndFrame,TRUE);
} else {
HWND hwndSav = GetFocus();
BOOL b;
CCHL szTmpText[cchpBufTmpLongMax];
//
// Make sure this is what he *really* wants to do.
//
LoadString(hInstance, IDS_SURECANCEL, rgchBufTmpLong, cchpBufTmpLongMax);
LoadString(hInstance, IDS_ERROR, (LPSTR)szTmpText, cchpBufTmpLongMax);
b = (MessageBox(hwndFrame, rgchBufTmpLong, (LPSTR)szTmpText, MB_YESNO|MB_TASKMODAL) == IDYES);
ShowOwnedPopups(hwndFrame,TRUE);
SetFocus(hwndSav);
SendMessage(hwndFrame, WM_NCACTIVATE, 1, 0L);
if(b) {
return(fFalse);
}
}
}
}
if (!FBuildFullSrcPath(szFullPathSrc, pcln->szSrcDir, psfd->szFile,
(Removable < 0) ? NULL : psdle->szNetPath)) {
EvalAssert(EercErrorHandler(hwndFrame, grcInvalidPathErr, fVital,
pcln->szSrcDir, psfd->szFile, 0) == eercAbort);
return(!fVital);
}
//
// Determine the source file name:
// Check to see if source file exists as the regular name or
// a compressed name
//
lstrcpy( szNonCompressedFullPathSrc, szFullPathSrc );
fCompressedName = fFalse;
while (!FFileFound( szFullPathSrc )) {
if (szSrcDollar == (SZ)NULL) {
while ((szSrcDollar = SzGetSrcDollar(szFullPathSrc,'_')) == (SZ)NULL) {
if (!FHandleOOM(hwndFrame)) {
return(!fVital);
}
}
}
if (FFileFound( szSrcDollar )) {
lstrcpy( szFullPathSrc, szSrcDollar );
fCompressedName = fTrue;
break;
}
#define DOLLAR_NAME
#ifdef DOLLAR_NAME
SFree(szSrcDollar);
while((szSrcDollar = SzGetSrcDollar(szFullPathSrc,'$')) == (SZ)NULL) {
if (!FHandleOOM(hwndFrame)) {
return(!fVital);
}
}
if(FFileFound(szSrcDollar)) {
lstrcpy(szFullPathSrc,szSrcDollar);
fCompressedName = fTrue;
break;
}
#endif
SFree( szSrcDollar);
szSrcDollar = NULL;
//
// Unable to locate the source file.
// If we are supposed to skip missing files, ignore it.
// Text setup sets a symbol called SMF to YES if we are
// supposed to skip missing files.
//
if((SymbolValue = SzFindSymbolValueInSymTab("!SMF")) && !lstrcmpi(SymbolValue,"YES")) {
return(fTrue);
}
//
// If the file exists on the target and this is a winnt
// non-upgrade setup, just assume the file was already copied.
//
if(/*fInitialSetup &&*/ !fNTUpgradeSetup
&& !_strnicmp(szFullPathSrc+2,LOCAL_SOURCE_DIRECTORY,lstrlen(LOCAL_SOURCE_DIRECTORY)))
{
if(!FBuildFullDstPath(szFullPathDst, pcln->szDstDir, psfd, FALSE)) {
if (!FHandleOOM(hwndFrame)) {
return(!fVital);
}
}
if(FFileExists(szFullPathDst)) {
return(fTrue);
}
}
if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
szFullPathSrc, 0, 0)) != eercRetry) {
return(eerc == eercIgnore);
}
}
if (szSrcDollar) {
SFree( szSrcDollar);
szSrcDollar = (SZ)NULL;
}
//
// Determine the destination file name:
//
if (!FBuildFullDstPath(szFullPathDst, pcln->szDstDir, psfd, fCompressedName) ||
!FValidPath(szFullPathDst)) {
EvalAssert(EercErrorHandler(hwndFrame, grcInvalidPathErr, fVital,
pcln->szDstDir, psfd->szFile, 0) == eercAbort);
return(!fVital);
}
fDstExists = FFileFound(szFullPathDst);
#ifdef REMOTE_BOOT
if (1) { //BUGBUG: how to turn on SIS check here?
DWORD rc;
if (!fCompressedName) {
rc = CreateTargetAsLinkToMaster(
szFullPathSrc,
szFullPathDst,
fDstExists
);
if (rc == NO_ERROR) {
return TRUE;
}
}
}
#endif
if (fDstExists != fFalse) {
OWM owm;
YNRC ynrc;
//
// Check overwrite mode. The overwrite mode can be:
//
// 1. Never : No further checking. The file is not copied
//
// 2. Unprotected: Check to see if file on destination is readonly.
//
// 3. Older : The release version / date is checked against the
// the destination file
//
// 4. VerifySourceOlder: The checking is postponed till we have actually
// found the source file. The source time is then
// compared against the destination time and only
// if the destination is older the file is copied.
if ((owm = poer->owm) & owmNever) {
return(fTrue);
}
else if (owm & owmUnprotected) {
while ((ynrc = YnrcFileReadOnly(szFullPathDst)) == ynrcErr1) {
if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
return(eerc == eercIgnore);
}
}
if (ynrc == ynrcYes) {
return(fTrue);
}
}
else if (owm & owmOlder) {
while ((ynrc = YnrcNewerExistingFile(dateSrc, szFullPathDst,
poer->ulVerMS, poer->ulVerLS)) != ynrcYes
&& ynrc != ynrcNo) {
if (ynrc == ynrcErr1 &&
(eerc = EercErrorHandler(hwndFrame, grcOpenFileErr,
fVital, szFullPathDst, 0, 0)) != eercRetry)
return(eerc == eercIgnore);
else if (ynrc == ynrcErr2 &&
(eerc = EercErrorHandler(hwndFrame, grcReadFileErr,
fVital, szFullPathDst, 0, 0)) != eercRetry)
return(eerc == eercIgnore);
else if (ynrc == ynrcErr3 &&
(eerc = EercErrorHandler(hwndFrame, grcCloseFileErr,
fVital, szFullPathDst, 0, 0)) != eercRetry)
return(eerc == eercIgnore);
}
if (ynrc == ynrcYes)
return(fTrue);
Assert(ynrc == ynrcNo);
}
}
else {
//
// Destination doesn't exist, check to see if we are in upgradeonly
// mode, in which case we need not copy the file and we can just
// return.
OEF oef = poer->oef;
if ( oef & oefUpgradeOnly ) {
return( fTrue );
}
}
//
// If destination exists then we need to preserve the security that is
// there on the file. We read the security on the existing file
// and once the new file is copied over then we set the security read
// on the new file. Note that we don't do this for initial setup since
// we are going to fix permissions on the file anyway.
//
if(fDstExists && !fInitialSetup) {
if(!FGetFileSecurity(szFullPathDst, &Sd, &SdLen)) {
return( fFalse );
}
}
if (fDstExists &&
poer->szBackup != NULL)
{
YNRC ynrc;
if ((ynrc = YnrcBackupFile(szFullPathDst, poer->szBackup, psfd)) !=
ynrcYes)
return(ynrc != ynrcNo);
fDstExists = FFileFound(szFullPathDst);
}
if (fDstExists)
{
while (!FSetFileReadOnlyStatus(szFullPathDst, fOff))
{
if ((eerc = EercErrorHandler(hwndFrame, grcWriteFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry)
return(eerc == eercIgnore);
}
}
if(!fSilentSystem) {
LPSTR p;
CHAR chSave;
EvalAssert((p = SzFindFileFromPath(szFullPathSrc)) != NULL);
if(!p) {
p = szFullPathSrc;
}
wsprintf(rgchBufTmpLong,"%s %s",GaugeText1,p);
ProSetText(ID_STATUS1,rgchBufTmpLong);
EvalAssert((p = SzFindFileFromPath(szFullPathDst)) != NULL);
if(p) {
if(!ISUNC(szFullPathDst) && (p - szFullPathDst != 3)) { // account for file in root
p--;
}
chSave = *p;
*p = '\0';
wsprintf(rgchBufTmpLong,"%s %s",GaugeText2,szFullPathDst);
*p = chSave;
} else {
rgchBufTmpLong[0] = '\0';
}
ProSetText(ID_STATUS2,rgchBufTmpLong);
}
lSize = (poer->ctuCopyTime > 0) ? (LONG)(poer->ctuCopyTime) : poer->lSize;
if (!FCopy(szFullPathSrc, szFullPathDst, poer->oef, poer->owm,
(poer->szAppend != NULL),
(int)((DWORD)10000 * lSize / lTotalSize), dateSrc,psdle,szNonCompressedFullPathSrc))
return(fFalse);
if( Sd ) {
//
// BUGBUG -
//
// Preservation of file security is broken, since the most files
// were overwritten during textmode setup.
// So this is currently disabled.
//
// BOOL Status;
// Status = FSetFileSecurity(szFullPathDst, Sd);
SFree(Sd);
// return(Status);
}
return(fTrue);
}
/*
** Purpose:
** Uses the Compression DollarSign translation algorithm on its argument.
** If the file has no extension, then '._' is added. If the extension
** has less than 3 characters, then a '_' is appended. Otherwise, the
** third character of the extension is replaced by a dollarsign.
** Arguments:
** szFullPathSrc: a zero terminated character string containing the fully
** qualified path (including drive) for the source file.
** Returns:
**
**************************************************************************/
SZ APIENTRY SzGetSrcDollar(SZ szFullPathSrc,CHAR ch)
{
SZ szDot = (SZ)NULL;
SZ szCur = szFullPathSrc;
CHAR dotch[3];
dotch[0] = '.';
dotch[1] = ch;
dotch[2] = 0;
ChkArg(szFullPathSrc != (SZ)NULL, 1, (SZ)NULL);
while (*szCur != '\0')
{
if (*szCur == '.')
szDot = szCur;
else if (*szCur == '\\')
szDot = (SZ)NULL;
szCur = SzNextChar(szCur);
}
Assert(szDot == (SZ)NULL || *szDot == '.');
if (szDot == (SZ)NULL)
{
if ((szDot = (SZ)SAlloc(strlen(szFullPathSrc) + 3)) != (SZ)NULL)
{
EvalAssert(strcpy(szDot, szFullPathSrc) == szDot);
EvalAssert(SzStrCat(szDot, dotch) == szDot);
}
}
else
{
CHP chpSav = '\0';
SZ szRest;
CB cb;
if (*(szCur = ++szDot) != '\0' &&
*(szCur = SzNextChar(szCur)) != '\0' &&
*(szCur = SzNextChar(szCur)) != '\0')
{
chpSav = *szCur;
szRest = SzNextChar(szCur);
*szCur = '\0';
}
cb = strlen(szFullPathSrc) + 2;
if (chpSav != '\0')
{
Assert(szRest != (SZ)NULL);
cb += strlen(szRest);
}
if ((szDot = (SZ)SAlloc(cb)) != (SZ)NULL)
{
EvalAssert(strcpy(szDot, szFullPathSrc) == szDot);
EvalAssert(SzStrCat(szDot, &dotch[1]) == szDot);
if (chpSav != '\0')
{
Assert(szRest != (SZ)NULL);
EvalAssert(SzStrCat(szDot, szRest) == szDot);
*szCur = chpSav;
}
}
}
return(szDot);
}
static int iTickMax = 0;
static int iTickCur = 0;
int far WFromW(int iTick)
{
if (iTick > iTickMax - iTickCur)
iTick = iTickMax - iTickCur;
if (iTick > 0)
{
ProDeltaPos(iTick);
iTickCur += iTick;
}
return(1);
}
/*
** Purpose:
** To physically copy the source file to the destination file. This
** can include several options including appending, open and closing src
** and dst files, but not actually copying the contents of the files,
** decompressing, timestamping the dst file, and setting the read only
** status of the dst file.
** Arguments:
** szFullPathSrc: a zero terminated character string containing the fully
** qualified path (including drive) for the source file.
** szFullPathDst: a zero terminated character string containing the fully
** qualified path (including drive) for the destination file.
** oef: option element flags for the Section-File Description
** The valid flags include oefVital, oefCopy, oefUndo,
** oefRoot, oefDecompress, oefTimeStamp, oefReadOnly,
** oefNone and oefAll.
** fAppend: fTrue if the contents of szFullPathSrc are to be
** appended to the contents of szFullPathDst.
** cProgTicks: number of ticks to advance Progress Gizmo.
** dateSrc: DATE value from INF for src file.
** Returns:
** fTrue if the copy is successfully completed, fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY
FCopy(
SZ szFullPathSrc,
SZ szFullPathDst,
OEF oef,
OWM owm,
BOOL fAppend,
int cProgTicks,
USHORT dateSrc,
PSDLE psdle,
SZ szNonCompressedFullPathSrc
)
{
#if 0
CB cbSize;
CB cbActual;
#endif
PB pbBuffer = NULL;
PFH pfhSrc = NULL;
PFH pfhDst = NULL;
LFA lfaDst = 0L;
HANDLE hSource = NULL;
BOOL fVital = oef & oefVital;
BOOL fDecomp = oef & oefDecompress;
BOOL fRet = !fVital;
BOOL fRemovePartialFile = fFalse;
EERC eerc;
YNRC ynrc;
FILETIME CreateTime, AccessTime, WriteTime;
BOOL fSilentSystem = FGetSilent();
LONG lRet;
ULONG Checksum = 0;
BOOL fThirdPartyFile = oef & oefThirdPartyFile;
BOOL OnLocalSource;
BOOLEAN IsValid;
BOOLEAN IsNtImage;
BOOL fCsdInstall = oef & oefCsdInstall;
SZ szActiveFileTmpName = NULL;
if( fCsdInstall &&
DoesFileReplaceThirdPartyFile( szFullPathDst+2 ) ) {
return( TRUE );
}
OnLocalSource = (_strnicmp(szFullPathSrc+2,LOCAL_SOURCE_DIRECTORY,lstrlen(LOCAL_SOURCE_DIRECTORY)) == 0);
do {
while ((pfhSrc = PfhOpenFile(szFullPathSrc, ofmRead)) == (PFH)NULL) {
if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
szFullPathSrc, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
while (!GetFileTime((HANDLE)LongToHandle(pfhSrc->iDosfh), &CreateTime, &AccessTime,
&WriteTime)) {
if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
szFullPathSrc, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
if (!(oef & oefCopy))
{
if (!FCloseFile(pfhSrc))
while ((eerc = EercErrorHandler(hwndFrame, grcCloseFileErr, fVital,
szFullPathSrc, 0, 0)) != eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
pfhSrc = NULL;
if (cProgTicks > 0 && !fSilentSystem)
ProDeltaPos(cProgTicks);
fRet = fTrue;
goto DelSrc;
}
if(FFileFound(szFullPathDst)) {
//
// We need to check if we have been asked to compare actual file times
//
if ( owm & owmVerifySourceOlder ) {
PFH pfh;
FILETIME DstWriteTime;
BOOL Older = fFalse;
if ((pfh = PfhOpenFile(szFullPathDst, ofmRead)) != NULL) {
if (GetFileTime((HANDLE)LongToHandle(pfh->iDosfh), NULL, NULL, &DstWriteTime)) {
if( CompareFileTime( &DstWriteTime, &WriteTime ) == -1 ) {
Older = fTrue;
}
}
FCloseFile(pfh);
}
if( !Older ) {
FCloseFile(pfhSrc);
pfhSrc = NULL;
if (cProgTicks > 0 && !fSilentSystem)
ProDeltaPos(cProgTicks);
fRet = fTrue;
goto DelSrc;
}
}
//
// if this is a CSD, then we need to back up the old file in case
// the copy fails for some reason. (We also gotta make sure that
// the files aren't the same, otherwise we'll get a bogus error)
//
if( fCsdInstall && lstrcmpi(szFullPathSrc, szFullPathDst) ) {
//
// We don't want to back up the file again, if we're retrying
//
if(!szActiveFileTmpName) {
while(!(szActiveFileTmpName = FRenameActiveFile(szFullPathDst))) {
//
// Error opening, present critical error to user
//
if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
}
}
}
if ((ynrc = YnrcEnsurePathExists(szFullPathDst, fVital, NULL)) != ynrcYes)
{
fRet = (ynrc == ynrcErr1);
goto LCopyError;
}
while ((pfhDst = PfhOpenFile(szFullPathDst,
(OFM)(fAppend ? ofmReadWrite : ofmCreate))) == NULL) {
DWORD dw;
dw = GetLastError();
//
// if it is a sharing violation and this is because both the source
// and destination are the same, then present the error to the user.
//
if (dw == ERROR_SHARING_VIOLATION && !lstrcmpi(szFullPathSrc, szFullPathDst)) {
if ((eerc = EercErrorHandler(hwndFrame, grcOpenSameFileErr, fFalse,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
else {
continue;
}
}
//
// For active files access will be denied
//
if(((dw == ERROR_ACCESS_DENIED) || (dw == ERROR_SHARING_VIOLATION) || (dw == ERROR_USER_MAPPED_FILE))
&& !fAppend) {
//
// make sure we don't already have a backup (if this is a retry)
//
if((szActiveFileTmpName) || (szActiveFileTmpName = FRenameActiveFile(szFullPathDst))) {
continue;
}
}
//
// Error opening, present critical error to user
//
if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
fRemovePartialFile = fTrue;
if (fAppend) {
USHORT dateDst, timeDst;
while(!GetFileTime((HANDLE)LongToHandle(pfhDst->iDosfh), NULL, NULL, &WriteTime)
|| !FileTimeToDosDateTime(&WriteTime, &dateDst, &timeDst)) {
if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
if (dateDst != dateSrc || timeDst != 0) {
fRet = fTrue;
fRemovePartialFile = fFalse;
goto LCopyError;
}
while ((lfaDst = LfaSeekFile(pfhDst, 0, sfmEnd)) == (LFA)(-1)) {
if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
}
if (fDecomp) {
INT rc;
while ((rc = LZInit( pfhSrc->iDosfh) ) < 0) {
GRC grc;
switch (rc) {
case LZERROR_UNKNOWNALG:
grc = grcDecompUnknownAlgErr;
break;
case LZERROR_GLOBLOCK:
case LZERROR_READ:
case LZERROR_BADINHANDLE:
grc = grcReadFileErr;
break;
case LZERROR_GLOBALLOC:
grc = grcOutOfMemory;
break;
default:
grc = grcDecompGenericErr;
break;
}
if ((eerc = EercErrorHandler(hwndFrame, grc, fVital, szFullPathSrc,
0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
hSource = NULL;
goto LCopyError;
}
}
hSource = (HANDLE)LongToHandle(rc);
}
else {
hSource = (HANDLE)LongToHandle(pfhSrc->iDosfh);
}
if (fDecomp) {
BOOL isDiamondFile;
iTickMax = cProgTicks;
iTickCur = 0;
//
// Determine whether the file is a diamond cabinet/compressed file.
// If it is, we'll call a separate diamond decompressor. If it isn't,
// we'll call the lz routine, which will decompress an lz file or copy
// a non-lz (and non-diamond) file.
//
isDiamondFile = IsDiamondFile(szFullPathSrc);
do {
if(isDiamondFile) {
lRet = DecompDiamondFile(
szFullPathSrc,
(HANDLE)LongToHandle(pfhDst->iDosfh),
fSilentSystem ? NULL: WFromW,
cProgTicks
);
} else {
lRet = LcbDecompFile(
hSource,
(HANDLE)LongToHandle(pfhDst->iDosfh),
fSilentSystem ? NULL: WFromW,
cProgTicks
);
}
if(lRet < 0) {
GRC grc;
SZ sz = szFullPathSrc;
switch (lRet) {
case rcReadError:
case rcReadSeekError:
grc = grcReadFileErr;
break;
case rcWriteError:
case rcWriteSeekError:
grc = grcWriteFileErr;
sz = szFullPathDst;
break;
case rcOutOfMemory:
grc = grcOutOfMemory;
break;
case rcDiskFull:
grc = grcDiskFull;
fVital = TRUE;
break;
case rcUserQuit:
fRet = fFalse;
goto LCopyError;
break;
default:
grc = grcDecompGenericErr;
break;
}
if ((eerc = EercErrorHandler(hwndFrame, grc, fVital, sz)) !=
eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
//
// Before retrying we need to rewind the destination pointer to
// the place where we began the write
//
while (LfaSeekFile(pfhDst, lfaDst, sfmSet) == (LFA)(-1)) {
if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
}
} while(lRet < 0);
Assert(iTickCur <= cProgTicks);
cProgTicks -= iTickCur;
}
else {
iTickMax = cProgTicks;
iTickCur = 0;
while ((lRet = LcbCopyFile(
hSource,
(HANDLE)LongToHandle(pfhDst->iDosfh),
fSilentSystem ? NULL: WFromW,
cProgTicks
)) < 0) {
GRC grc;
SZ sz = szFullPathSrc;
switch (lRet) {
case rcReadError:
case rcReadSeekError:
grc = grcReadFileErr;
break;
case rcWriteError:
case rcWriteSeekError:
grc = grcWriteFileErr;
sz = szFullPathDst;
break;
case rcOutOfMemory:
grc = grcOutOfMemory;
break;
case rcDiskFull:
grc = grcDiskFull;
fVital = TRUE;
break;
case rcUserQuit:
fRet = fFalse;
goto LCopyError;
break;
default:
grc = grcDecompGenericErr;
break;
}
if ((eerc = EercErrorHandler(hwndFrame, grc, fVital, sz)) !=
eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
//
// Before retrying we need to rewind the destination pointer to
// the place where we began the write
//
while (LfaSeekFile(pfhDst, lfaDst, sfmSet) == (LFA)(-1)) {
if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry) {
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
}
Assert(iTickCur <= cProgTicks);
cProgTicks -= iTickCur;
}
if (oef & oefTimeStamp)
while (!SetFileTime((HANDLE)LongToHandle(pfhDst->iDosfh), &CreateTime, &AccessTime,
&WriteTime))
if ((eerc = EercErrorHandler(hwndFrame, grcWriteFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
if (fDecomp) {
LZClose ( HandleToUlong(hSource) );
FreePfh ( pfhSrc );
hSource = NULL;
pfhSrc = NULL;
}
else {
while (!FCloseFile(pfhSrc)) {
if ((eerc = EercErrorHandler(hwndFrame, grcCloseFileErr, fVital,
szFullPathSrc, 0, 0)) != eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
pfhSrc = NULL;
}
//
// If we get here, the file was copied successfully.
// Close the file before we get the checksum
//
while (!FCloseFile(pfhDst)) {
if ((eerc = EercErrorHandler(hwndFrame, grcCloseFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
pfhDst = NULL;
ValidateAndChecksumFile( szFullPathDst,
&IsNtImage,
&Checksum,
&IsValid );
if(!IsValid) {
if ((eerc = EercErrorHandler(hwndFrame, grcVerifyFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
} while(!IsValid);
fRemovePartialFile = fFalse;
//
// At this point, we can delete the backup file we made (if we made one)
//
if(szActiveFileTmpName) {
if(!FRemoveFile(szActiveFileTmpName)) {
//
// It must be locked, so set it to be deleted on reboot
//
AddFileToDeleteList(szActiveFileTmpName);
}
free(szActiveFileTmpName);
szActiveFileTmpName = NULL;
}
if (oef & oefReadOnly)
while (!FSetFileReadOnlyStatus(szFullPathDst, fOn))
{
if ((eerc = EercErrorHandler(hwndFrame, grcWriteFileErr, fVital,
szFullPathDst, 0, 0)) != eercRetry)
{
fRet = (eerc == eercIgnore);
goto LCopyError;
}
}
fRet = fTrue;
LCopyError:
//
// Log the file.
//
if(psdle && !(oef & oefNoLog) && !fCsdInstall) {
LogOneFile( szNonCompressedFullPathSrc,
szFullPathDst,
psdle->szLabel,
Checksum,
psdle->szTagFile,
fThirdPartyFile
);
}
if (pbBuffer != (PB)NULL) {
SFree(pbBuffer);
}
if (fDecomp && hSource != (HANDLE)NULL) {
LZClose (HandleToUlong(hSource));
FreePfh (pfhSrc);
}
else if (pfhSrc != (PFH)NULL) {
EvalAssert(FCloseFile(pfhSrc));
}
if (pfhDst != (PFH)NULL) {
EvalAssert(FCloseFile(pfhDst));
}
if (fRemovePartialFile) {
FRemoveFile(szFullPathDst);
if(szActiveFileTmpName) {
MoveFile(szActiveFileTmpName, szFullPathDst);
free(szActiveFileTmpName);
}
}
//
// If we have any remaining ticks on the gauge for this file,
// go ahead and do them. This could happen if the file copy was
// aborted part way through.
//
if (cProgTicks > 0 && !fSilentSystem) {
ProDeltaPos(cProgTicks);
}
DelSrc:
//
// Determine whether we are supposed to delete the source file. This
// is the case when it is coming from a local source as created by the
// DOS Setup program, and is not marked oefNoDeleteSource.
//
if(!fNTUpgradeSetup && OnLocalSource && !(oef & oefNoDeleteSource))
{
if (NULL == SzFindSymbolValueInSymTab("!STF_NETDELETEOVERIDE"))
{
DeleteFile(szFullPathSrc);
}
}
return(fRet);
}
/*
** Purpose:
** To find a pointer to the beginning of the file name (i.e. primary.ext)
** at the end of a fully qualified pathname.
** Arguments:
** szFullPath: a non-Null, zero-terminated string containing a
** pathname ending in a file name.
** Returns:
** an SZ which is a pointer to the beginning of the file name within the
** argument SZ.
**
**************************************************************************/
SZ APIENTRY SzFindFileFromPath(szFullPath)
SZ szFullPath;
{
SZ sz;
SZ szSave = szFullPath;
ChkArg(szFullPath != (SZ)NULL && *szFullPath != '\0'
&& *SzLastChar(szFullPath) != '\\', 1, (SZ)NULL);
for (sz = szFullPath; *sz != '\0'; sz = SzNextChar(sz))
if (*sz == '\\')
szSave = sz;
Assert(szSave != NULL);
if (*szSave == '\\')
szSave = SzNextChar(szSave);
Assert(szSave != NULL && *szSave != '\0');
return(szSave);
}
/*
** Purpose:
** To find the beginning the beginning of the extension part of the file
** name within a string containing a file name (without the preceeding
** path name).
** Arguments:
** szFile: a zero terminated character string containing a valid file
** name (without the preceeding path name).
** Returns:
** an SZ that points to the '.' that begins the extension or '\0' if the
** file has no extension.
**
**************************************************************************/
SZ APIENTRY SzFindExt(szFile)
SZ szFile;
{
ChkArg(szFile != (SZ)NULL, 1, (SZ)NULL);
for ( ; *szFile != '\0' && *szFile != '.'; szFile = SzNextChar(szFile))
;
return(szFile);
}
/*
** Purpose:
** Build full path (check for ROOT and RENAME options)
** Arguments:
** szPath: non-NULL buffer to fill with full path.
** szDst: non-NULL string for szDstDir supplied on script line.
** psfd: non-NULL pointer to the Section-File Description structure(SFD).
** Assumes:
** szPath large enough for result.
** Returns:
** fTrue if successfully able to create the path, fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY
FBuildFullDstPath(
SZ szPath,
SZ szDst,
PSFD psfd,
BOOL fCompressedName
)
{
SZ szFile;
SZ szFileDollar = NULL;
POER poer = &(psfd->oer);
BOOL bStatus;
ChkArg(szPath != (SZ)NULL, 1, fFalse);
ChkArg(szDst != (SZ)NULL && FValidDir(szDst), 2, fFalse);
ChkArg(psfd != (PSFD)NULL, 3, fFalse);
if (poer->szDest != NULL) {
szDst = poer->szDest;
}
if (poer->szAppend != NULL) {
szFile = poer->szAppend;
}
else if (poer->szRename != NULL) {
szFile = poer->szRename;
}
else {
if (poer->oef & oefRoot) {
szFile = SzFindFileFromPath(psfd->szFile);
}
else {
szFile = psfd->szFile;
}
if (!(poer->oef & oefDecompress) && fCompressedName) {
while ((szFileDollar = SzGetSrcDollar(szFile,'_')) == (SZ)NULL) {
if (!FHandleOOM(hwndFrame)) {
return(fFalse);
}
}
szFile = szFileDollar;
}
}
bStatus = FMakePathFromDirAndSubPath(szDst, szFile, szPath, cchpFullPathBuf);
if ( szFileDollar ) {
SFree( szFileDollar);
}
return(bStatus);
}
/*
** Purpose:
** Build full source path
** Arguments:
** szPath: non-NULL buffer to store result in.
** szDst: non-NULL valid subpath for dest.
** szFile: non-NULL file name.
** szNetPath: string pointer for netpath to use; NULL to ignore.
** Assumes:
** szPath large enough for result.
** Returns:
** fTrue if the path is built correctly, fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY FBuildFullSrcPath(szPath, szDst, szFile, szNetPath)
SZ szPath;
SZ szDst;
SZ szFile;
SZ szNetPath;
{
CHP szPathTmp[cchpFullPathBuf];
ChkArg(szPath != (SZ)NULL, 1, fFalse);
ChkArg(szDst != (SZ)NULL, 2, fFalse);
ChkArg(szFile != (SZ)NULL, 3, fFalse);
if (szNetPath == NULL)
return(FMakePathFromDirAndSubPath(szDst, szFile, szPath,
cchpFullPathBuf));
else if (FMakePathFromDirAndSubPath(szDst, szNetPath, szPathTmp,
cchpFullPathBuf) &&
FMakePathFromDirAndSubPath(szPathTmp, szFile, szPath,
cchpFullPathBuf))
return(fTrue);
else
return(fFalse);
}
/*
** Purpose:
** Build full BackupPath
** Arguments:
** szPath: non-NULL buffer to store result in.
** szDst: non-NULL valid subpath for dest.
** psfd: non-NULL SFD pointer.
** Assumes:
** szPath large enough for result.
** Returns:
** fTrue if successful; fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY FBuildFullBakPath(szPath, szDst, psfd)
SZ szPath;
SZ szDst;
PSFD psfd;
{
SZ sz;
ChkArg(szPath != (SZ)NULL, 1, fFalse);
ChkArg(szDst != (SZ)NULL && *szDst != '\0', 2, fFalse);
ChkArg(psfd != (PSFD)NULL && (psfd->oer).szBackup != NULL, 3, fFalse);
EvalAssert(szPath == szDst || strcpy(szPath, szDst) == szPath);
sz = SzFindFileFromPath(szPath);
Assert(sz != NULL && *sz != '\0');
if (*((psfd->oer).szBackup) == '*')
{
sz = SzFindExt(szPath);
*sz++ = '.';
*sz++ = 'B'; /* REVIEW INTL */
*sz++ = 'A';
*sz++ = 'K';
*sz++ = '\0';
return(fTrue);
}
*sz = '\0';
return(FMakePathFromDirAndSubPath(szPath, (psfd->oer).szBackup, szPath,
cchpFullPathBuf));
}
/*
** Purpose:
** Verifies given file actually exists.
** Arguments:
** Returns:
**
**************************************************************************/
BOOL APIENTRY FFileFound(szPath)
SZ szPath;
{
WIN32_FIND_DATA ffd;
HANDLE SearchHandle;
ChkArg(szPath != (SZ)NULL &&
*szPath != '\0', 1, fFalse);
if ( (SearchHandle = FindFirstFile( szPath, &ffd )) == INVALID_HANDLE_VALUE ) {
return( fFalse );
}
else {
FindClose( SearchHandle );
return( fTrue );
}
}
/*
** Purpose:
** Arguments:
** Returns:
**
**************************************************************************/
BOOL APIENTRY FYield(VOID)
{
MSG msg;
BOOL fRet = fTrue;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (hwndProgressGizmo != NULL
&& IsDialogMessage(hwndProgressGizmo, &msg))
continue;
if (msg.message == WM_QUIT)
fRet = fFalse;
// if (CheckSpecialKeys(&msg))
// continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(fRet);
}
/*
** Purpose:
** To check and see if the directory specified in szFullPathDst exists.
** If not, it will create the directory (including any intermediate
** directories). For example if szFullPathDst = "c:\\a\\b\\File" and
** none of these directories exist (i.e. a or b) they will all be
** created so that the complete path exists (File is not created).
** Arguments:
** szFullPathDst: The complete pathname (including drive) of the directory
** in question.
** fCritical: if fTrue success of this operation is required for
** success of the setup program as a whole. Setup will be terminated
** if fCritical is fTrue and this function fails.
** szMsg: The complete pathname (including drive) of the directory
** to display in an error. If NULL use szFullPathDst.
** Returns:
** a YNRC error code (see _filecm.h) indicating the outcome of this
** function.
**
**************************************************************************/
YNRC APIENTRY YnrcEnsurePathExists(szFullPathDst, fCritical, szMsg)
SZ szFullPathDst;
BOOL fCritical;
SZ szMsg;
{
CHP szTmp[cchpFullPathBuf];
SZ sz;
DWORD Attr;
EERC eerc;
YNRC ynrc = ynrcYes;
ChkArg(FValidPath(szFullPathDst),1,ynrcNo);
if (szMsg == (SZ)NULL) {
szMsg = szFullPathDst;
}
EvalAssert(strcpy((SZ)szTmp, szFullPathDst) ==
(SZ)szTmp);
EvalAssert((sz = SzFindFileFromPath(szTmp)) != (SZ)NULL);
EvalAssert((sz = SzPrevChar(szTmp, sz)) != (SZ)NULL);
Assert(*sz == '\\');
*sz = '\0';
while ( !( ((Attr = GetFileAttributes(szTmp)) != 0xFFFFFFFF && (Attr & FILE_ATTRIBUTE_DIRECTORY ))
|| CreateDirectory( szTmp, NULL )
)
) {
if ((eerc = EercErrorHandler(hwndFrame, grcCreateDirErr, fCritical,
szMsg, 0, 0)) != eercRetry) {
ynrc = (eerc == eercIgnore) ? ynrcErr1 : ynrcNo;
break;
}
}
return( ynrc );
}
int
DetermineDriveType(
IN CHAR DriveLetter
)
/*++
Routine Description:
Determine whether a drive is removable media -- which can be
a floppy or a CD-ROM. Removeable hard drives are NOT considered
removeable by this routine.
Arguments:
DriveLetter - supplies drive letter of drive to check. If this
is not a valid alpha char, FALSE is returned.
Return Value:
-2 - Drive is a CD-ROM
-1 - Drive is some other removeable type (such as floppy)
0 - Drive is not removeable (or we couldn't tell)
--*/
{
CHAR Name[4];
UINT DriveType;
CHAR DevicePath[MAX_PATH];
Name[0] = DriveLetter;
Name[1] = ':';
Name[2] = '\\';
Name[3] = 0;
DriveType = GetDriveType(Name);
if(DriveType == DRIVE_REMOVABLE) {
Name[2] = 0;
if(QueryDosDevice(Name,DevicePath,MAX_PATH)) {
CharUpper(DevicePath);
if(strstr(DevicePath,"HARDDISK")) {
DriveType = DRIVE_FIXED;
}
}
}
if(DriveType == DRIVE_REMOVABLE) {
return(-1);
}
if(DriveType == DRIVE_CDROM) {
return(-2);
}
return(0);
}
/*
** Purpose:
** Arguments:
** hInstance: non-NULL instance handle for getting strings from
** resources for SwapDisk message Box.
** szLabel: non-Null zero-terminated ANSI string to display as the
** label of the diskette to prompt for.
** szSrcDir: non-Null zero-terminated ANSI string to display as the
** drive/directory the user is to insert the diskette into.
** Returns:
**
**************************************************************************/
BOOL APIENTRY FPromptForDisk(hInstance, szLabel, szSrcDir)
HANDLE hInstance;
SZ szLabel;
SZ szSrcDir;
{
CHAR szTmpText[cchpBufTmpLongMax];
CHAR rgchBuf[3*cchpFullPathBuf];
BOOL fRet;
HWND hwndSav;
ChkArg(hInstance,1,fFalse);
ChkArg(szLabel && *szLabel &&
strlen(szLabel) <= cchpFullPathMax, 2, fFalse);
ChkArg(szSrcDir &&
*szSrcDir &&
strlen(szSrcDir) <= cchpFullPathMax, 3, fFalse);
EvalAssert(LoadString(hInstance, IDS_INS_DISK, rgchBuf,3*cchpFullPathBuf));
EvalAssert(SzStrCat(rgchBuf, szLabel) == rgchBuf);
EvalAssert(LoadString(hInstance, IDS_INTO, szTmpText,
cchpBufTmpLongMax));
EvalAssert(SzStrCat(rgchBuf, szTmpText) == rgchBuf);
EvalAssert(SzStrCat(rgchBuf, szSrcDir) == rgchBuf);
EvalAssert(LoadString(hInstance, IDS_ERROR, szTmpText,
cchpBufTmpLongMax));
hwndSav = GetFocus();
fRet = (MessageBox(hwndFrame,rgchBuf,szTmpText,MB_OKCANCEL|MB_TASKMODAL) == IDOK);
SetFocus(hwndSav);
SendMessage(hwndFrame, WM_NCACTIVATE, 1, 0L);
return(fRet);
}
/*
** Purpose:
** To rename an active file as an del????.tmp file which will be deleted if
** the new file is copied successfully.
** Arguments:
** szFullPath: Full pathname of active file
** Returns:
** The name of the renamed file, or NULL if unsuccessful.
**
**************************************************************************/
SZ APIENTRY
FRenameActiveFile(
SZ szFullPath
)
{
SZ szTmpName;
CHP szDir[MAX_PATH];
SZ sz;
ChkArg ( szFullPath != NULL, 1, NULL);
//
// Try to find a temp filename we can use in the destination directory
//
lstrcpy( szDir, szFullPath );
if( !(sz = strrchr( szDir, '\\')) ) {
return NULL;
}
*sz = '\0';
if(!(szTmpName = malloc((lstrlen(szDir) + 14) * sizeof(CHP)))) {
return NULL;
}
if(!GetTempFileName( szDir, "del", 0, szTmpName )) {
goto FileRenameFailed;
}
//
// GetTempFileName creates the temp file. It needs to be deleted
//
if (FFileFound(szTmpName) && !FRemoveFile(szTmpName)) {
goto FileRenameFailed;
}
//
// Rename the original file to this filename
//
if( MoveFile( szFullPath, szTmpName ) ) {
return szTmpName;
}
FileRenameFailed:
free(szTmpName);
return NULL;
}
BOOL
FGetFileSecurity(
PCHAR File,
PSECURITY_DESCRIPTOR *SdBuf,
CB *SdLen
)
{
#define CBSDBUF 1024
SECURITY_INFORMATION Si;
PSECURITY_DESCRIPTOR Sd, SdNew;
DWORD cbSd = CBSDBUF;
DWORD cbSdReq;
BOOL FirstTime = fTrue;
DWORD dw1, dw2;
EERC eerc;
static CHAR Root[MAX_PATH] = "\0";
static BOOL IsNtfs = FALSE;
CHAR VolumeFSName[MAX_PATH];
//
// Initialize
//
*SdBuf = NULL;
//
// Check if the volume information is in the cache, if not so get the
// volume information and put it in the cache
//
if( Root[0] == '\0' ) {
if( !ISUNC( File ) ) {
strncpy( Root, File, 3 );
Root[3] = '\0';
} else {
PCHAR p;
ULONG n;
p = File + 2;
if( ( ( p = strchr( p, '\\' ) ) == NULL ) ||
( ( p = strchr( p + 1, '\\' ) ) == NULL ) ) {
return( FALSE );
}
n = (ULONG)(p - File + 1);
strncpy( Root, File, n );
Root[ n ] = '\0';
}
while(!GetVolumeInformation( Root, NULL, 0, NULL, &dw1, &dw2, VolumeFSName, MAX_PATH )) {
if ((eerc = EercErrorHandler(hwndFrame, grcGetVolInfo, FALSE, Root, File, 0)) != eercRetry) {
return(eerc == eercIgnore);
}
}
IsNtfs = !lstrcmpi( VolumeFSName, "NTFS" );
}
if(!IsNtfs) {
return(TRUE);
}
//
// Allocate memory for the security descriptor
//
while ((Sd = SAlloc(cbSd)) == NULL ) {
if (!FHandleOOM(hwndFrame)) {
return(fFalse);
}
}
//
// Get the security information from the source file
//
Si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
while(!GetFileSecurity(File,Si,Sd,cbSd,&cbSdReq)) {
if( FirstTime && (cbSdReq > cbSd) ) {
while(!(SdNew = SRealloc(Sd,cbSdReq))) {
if (!FHandleOOM(hwndFrame)) {
SFree(Sd);
return(fFalse);
}
}
cbSd = cbSdReq;
Sd = SdNew;
}
else {
if ((eerc = EercErrorHandler(hwndFrame, grcGetFileSecurity, FALSE, File, 0, 0)) != eercRetry) {
SFree(Sd);
return(eerc == eercIgnore);
}
}
FirstTime = fFalse;
}
*SdBuf = Sd;
*SdLen = cbSd;
return(TRUE);
}
BOOL
FSetFileSecurity(
PCHAR File,
PSECURITY_DESCRIPTOR SdBuf
)
{
EERC eerc;
SECURITY_INFORMATION Si;
//
// Set the Security on the dest file
//
Si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
while(!SetFileSecurity(File, Si, SdBuf)) {
#if 0
//
// BUGBUG - This is to find an error in DaveC's machine
//
CHAR DbgBuffer[256];
ULONG Error;
Error = GetLastError();
sprintf( DbgBuffer, "SetFileSecurity() failed. \nFile = %s. \nError = %d \n\nPlease contact JaimeS at x65903", File, Error );
MessageBox(NULL, DbgBuffer, "Debug Message",
MB_OK | MB_ICONHAND);
#endif
if ((eerc = EercErrorHandler(hwndFrame, grcSetFileSecurity, FALSE, File, 0, 0)) != eercRetry) {
return(eerc == eercIgnore);
}
}
return(TRUE);
}
BOOL
DoesFileReplaceThirdPartyFile(
SZ szFullPathDst
)
{
CHAR SetupLogFilePath[ MAX_PATH ];
PSTR SectionName;
CHAR ReturnBuffer[512];
PSTR DefaultString = "";
PSTR SectionsToSearch[] = {
"Files.WinNt",
"Files.SystemPartition"
};
ULONG Count;
BOOL ReplaceThirdParty;
*SetupLogFilePath = '\0';
GetWindowsDirectory( SetupLogFilePath, sizeof( SetupLogFilePath ) );
strcat( SetupLogFilePath, SETUP_REPAIR_DIRECTORY );
strcat( SetupLogFilePath, SETUP_LOG_FILE );
for( Count = 0;
Count < sizeof( SectionsToSearch ) / sizeof( PSTR );
Count++ ) {
SectionName = SectionsToSearch[Count];
*ReturnBuffer = '\0';
GetPrivateProfileString( SectionName,
szFullPathDst,
DefaultString,
ReturnBuffer,
sizeof( ReturnBuffer ),
SetupLogFilePath );
if( *ReturnBuffer != '\0' ) {
break;
}
}
ReplaceThirdParty = FALSE;
if( *ReturnBuffer != 0 ) {
PSTR SourceFileName;
PSTR ChkSumString;
PSTR DirectoryOnSourceDevice;
PSTR DiskDescription;
PSTR DiskTag;
PSTR Delimiters = "\" ,";
SourceFileName = strtok( ReturnBuffer, Delimiters );
SourceFileName = strtok( NULL, Delimiters );
ChkSumString = strtok( NULL, Delimiters );
DirectoryOnSourceDevice = strtok( NULL, Delimiters );
DiskDescription = strtok( NULL, Delimiters );
DiskTag = strtok( NULL, Delimiters );
if( ( DiskDescription != NULL ) || ( DiskTag != NULL ) ) {
ReplaceThirdParty = TRUE;
}
}
return( ReplaceThirdParty );
}