2522 lines
71 KiB
C
2522 lines
71 KiB
C
#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 );
|
|
}
|