#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 ); }