Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2521 lines
71 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /* File: filecm.c */
  4. /*************************************************************************
  5. ** Install: File Copying commands.
  6. **************************************************************************/
  7. extern HWND hwndFrame;
  8. extern HANDLE hinstShell;
  9. extern HWND hwndProgressGizmo;
  10. extern CHP rgchBufTmpLong[];
  11. /* Globals */
  12. CHP szFullPathSrc[cchpFullPathBuf] = "\0";
  13. CHP szFullPathDst[cchpFullPathBuf] = "\0";
  14. CHP szFullPathBak[cchpFullPathBuf] = "\0";
  15. CHAR GaugeText1[50], GaugeText2[50];
  16. BOOL fNTUpgradeSetup,fInitialSetup;
  17. SZ APIENTRY SzGetSrcDollar(SZ szFullPathSrc,CHAR ch);
  18. PSTR LOCAL_SOURCE_DIRECTORY = "\\$WIN_NT$.~LS";
  19. int
  20. DetermineDriveType(
  21. IN CHAR DriveLetter
  22. );
  23. BOOL
  24. FGetFileSecurity(
  25. PCHAR File,
  26. PSECURITY_DESCRIPTOR *SdBuf,
  27. CB *SdLen
  28. );
  29. BOOL
  30. FSetFileSecurity(
  31. PCHAR File,
  32. PSECURITY_DESCRIPTOR SdBuf
  33. );
  34. VOID
  35. ValidateAndChecksumFile(
  36. IN PSTR Filename,
  37. OUT PBOOLEAN IsNtImage,
  38. OUT PULONG Checksum,
  39. OUT PBOOLEAN Valid
  40. );
  41. BOOL
  42. DoesFileReplaceThirdPartyFile(
  43. SZ szFullPathDst
  44. );
  45. /*
  46. ** Purpose:
  47. ** Copies all files in the current copy list and resets the list to
  48. ** empty. Copying is sorted by source disk to limit potential disk
  49. ** swapping.
  50. ** Arguments:
  51. ** hInstance: non-NULL instance handle for getting strings from
  52. ** resources for SwapDisk message Box.
  53. ** Returns:
  54. ** Returns fTrue if all copies successful, fFalse otherwise.
  55. **
  56. **************************************************************************/
  57. BOOL APIENTRY FCopyFilesInCopyList(hInstance)
  58. HANDLE hInstance;
  59. {
  60. DID did;
  61. PCLN pclnCur;
  62. PPCLN ppclnPrev;
  63. LONG lTotalSize;
  64. PPCLN ppclnHead;
  65. PPPCLN pppclnTail;
  66. PSDLE psdle;
  67. BOOL fSilentSystem = FGetSilent();
  68. UINT fuModeSav;
  69. PINFPERMINFO pPermInfo;
  70. PSDLE psdleGlobalHead = (PSDLE)NULL;
  71. PSDLE psdleGlobalEnd = (PSDLE)NULL;
  72. PSDLE psdleGlobal;
  73. DID didGlobalCur;
  74. BOOL fCopyStatus = fFalse;
  75. SZ sz;
  76. if(!InitDiamond()) {
  77. return(fFalse);
  78. }
  79. fInitialSetup = fFalse;
  80. fNTUpgradeSetup = fFalse;
  81. if (!fSilentSystem) {
  82. ProOpen(hwndFrame, 0);
  83. ProSetBarRange(10000);
  84. }
  85. //
  86. // Determine if we are in initial setup
  87. //
  88. if ((sz = SzFindSymbolValueInSymTab("!STF_INSTALL_TYPE")) != (SZ)NULL &&
  89. (CrcStringCompareI(sz, "SETUPBOOTED") == crcEqual)) {
  90. fInitialSetup = fTrue;
  91. }
  92. //
  93. // Determine if we are an NT upgrade setup
  94. //
  95. if (fInitialSetup
  96. && (sz = SzFindSymbolValueInSymTab("!STF_NTUPGRADE")) != (SZ)NULL
  97. && (CrcStringCompareI(sz, "YES") == crcEqual)) {
  98. fNTUpgradeSetup = fTrue;
  99. }
  100. //
  101. // Go through all the disk media descriptions and assign universal
  102. // ids for all source media. This is necessary because two infs
  103. // may refer to the same disk using different ids.
  104. //
  105. pPermInfo = pInfPermInfoHead;
  106. didGlobalCur = didMin;
  107. while ( pPermInfo ) {
  108. //
  109. // If the INF has a source media description list, go through list
  110. //
  111. psdle = pPermInfo->psdleHead;
  112. while ( psdle ) {
  113. //
  114. // search all the global psdles for a match with the current
  115. // disk. search based on disk label ( which is hopefully unique )
  116. //
  117. psdleGlobal = psdleGlobalHead;
  118. while ( psdleGlobal ) {
  119. if( !CrcStringCompareI( psdleGlobal->szLabel, psdle->szLabel ) ) {
  120. break;
  121. }
  122. psdleGlobal = psdleGlobal->psdleNext;
  123. }
  124. if ( psdleGlobal == NULL ) {
  125. PSDLE psdleNew;
  126. if ((psdleNew = PsdleAlloc()) == (PSDLE)NULL ||
  127. (psdleNew->szLabel = SzDupl(psdle->szLabel)) == (SZ)NULL ||
  128. (psdle->szTagFile != NULL && ((psdleNew->szTagFile = SzDupl(psdle->szTagFile)) == (SZ)NULL)) ||
  129. (psdle->szNetPath != NULL && ((psdleNew->szNetPath = SzDupl(psdle->szNetPath)) == (SZ)NULL))) {
  130. goto CopyFailed;
  131. }
  132. psdleNew->psdleNext = (PSDLE)NULL;
  133. if ( !psdleGlobalHead ) {
  134. psdleGlobalHead = psdleGlobalEnd = psdleNew;
  135. }
  136. else {
  137. psdleGlobalEnd->psdleNext = psdleNew;
  138. psdleGlobalEnd = psdleNew;
  139. }
  140. psdleGlobal = psdleNew;
  141. psdleGlobal->didGlobal = didGlobalCur++;
  142. }
  143. psdle->didGlobal = psdleGlobal->didGlobal;
  144. psdle = psdle->psdleNext;
  145. }
  146. pPermInfo = pPermInfo->pNext;
  147. }
  148. //
  149. // Go through the copy list of all infs and calculate total copy
  150. // list cost
  151. //
  152. pPermInfo = pInfPermInfoHead;
  153. lTotalSize = 0L;
  154. while ( pPermInfo ) {
  155. //
  156. // If the INF has a source media description list, look at the
  157. // copy list
  158. //
  159. if ( pPermInfo->psdleHead ) {
  160. Assert(FValidCopyList( pPermInfo ));
  161. ppclnHead = PpclnHeadList( pPermInfo );
  162. pppclnTail = PppclnTailList( pPermInfo );
  163. #if DBG
  164. *pppclnTail = NULL; /* for FValidCopyList() calls */
  165. #endif
  166. pclnCur = *ppclnHead;
  167. //
  168. // Traverse the copy list and determine the total size of the
  169. // files to copy.
  170. //
  171. while (pclnCur != (PCLN)NULL) {
  172. if (pclnCur->psfd->oer.ctuCopyTime > 0) {
  173. lTotalSize += pclnCur->psfd->oer.ctuCopyTime;
  174. } else {
  175. lTotalSize += pclnCur->psfd->oer.lSize;
  176. }
  177. pclnCur = pclnCur->pclnNext;
  178. }
  179. }
  180. pPermInfo = pPermInfo->pNext;
  181. }
  182. if (lTotalSize == 0L) {
  183. lTotalSize = 1L;
  184. }
  185. //
  186. // Show gauge stuff if not in silent mode.
  187. //
  188. if (!fSilentSystem) {
  189. SZ szText;
  190. ProSetBarPos(0);
  191. szText = SzFindSymbolValueInSymTab("ProText1");
  192. if( szText ) {
  193. strcpy(GaugeText1, szText);
  194. }
  195. else {
  196. strcpy(GaugeText1, "");
  197. }
  198. szText = SzFindSymbolValueInSymTab("ProText2");
  199. if( szText ) {
  200. strcpy(GaugeText2, szText);
  201. }
  202. else {
  203. strcpy(GaugeText2, "");
  204. }
  205. ProSetText(ID_STATUS3, "");
  206. ProSetText(ID_STATUS4, "");
  207. }
  208. //
  209. // Copy the files
  210. //
  211. psdleGlobal = psdleGlobalHead;
  212. while (psdleGlobal ) {
  213. didGlobalCur = psdleGlobal->didGlobal;
  214. pPermInfo = pInfPermInfoHead;
  215. while ( pPermInfo ) {
  216. //
  217. // Verify that this INF has a copy list
  218. //
  219. if ((psdle = pPermInfo->psdleHead) == (PSDLE)NULL ) {
  220. Assert( !*PpclnHeadList( pPermInfo ) );
  221. pPermInfo = pPermInfo->pNext;
  222. continue;
  223. }
  224. Assert(FValidCopyList( pPermInfo ));
  225. //
  226. // If it does, go through its source media descriptions finding
  227. // all disks that match the current global disk id and copy all
  228. // files which are described by the disks found
  229. //
  230. while ( psdle ) {
  231. if( psdle->didGlobal != didGlobalCur ) {
  232. psdle = psdle->psdleNext;
  233. continue;
  234. }
  235. did = psdle->did;
  236. ppclnHead = PpclnHeadList( pPermInfo );
  237. pppclnTail = PppclnTailList( pPermInfo );
  238. #if DBG
  239. *pppclnTail = NULL; /* for FValidCopyList() calls */
  240. #endif
  241. ppclnPrev = ppclnHead;
  242. pclnCur = *ppclnHead;
  243. //
  244. // Now traverse the copy list, copying all
  245. // the files that match the disk id
  246. //
  247. while (pclnCur != (PCLN)NULL) {
  248. if ( (pclnCur->psfd->did != did) ||
  249. (pclnCur->psfd->InfId != pPermInfo->InfId ) ) {
  250. ppclnPrev = &(pclnCur->pclnNext);
  251. pclnCur = pclnCur->pclnNext;
  252. continue;
  253. }
  254. fuModeSav = SetErrorMode(
  255. SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX
  256. );
  257. if(!FCopyListFile(hInstance,pclnCur,psdle,lTotalSize)) {
  258. SetErrorMode(fuModeSav);
  259. goto CopyFailed;
  260. }
  261. SetErrorMode(fuModeSav);
  262. //
  263. // File copied, delete its entry from the copy list
  264. //
  265. *ppclnPrev = pclnCur->pclnNext;
  266. EvalAssert(FFreePcln(pclnCur));
  267. pclnCur = *ppclnPrev;
  268. Assert(FValidCopyList( pPermInfo ));
  269. }
  270. psdle = psdle->psdleNext;
  271. }
  272. pPermInfo = pPermInfo->pNext;
  273. }
  274. psdleGlobal = psdleGlobal->psdleNext;
  275. }
  276. if (!fSilentSystem) {
  277. ProSetBarPos(10000 - 1);
  278. }
  279. fCopyStatus = fTrue;
  280. CopyFailed:
  281. if (!fSilentSystem) {
  282. ProClose(hwndFrame);
  283. UpdateWindow(hwndFrame);
  284. }
  285. pPermInfo = pInfPermInfoHead;
  286. while ( pPermInfo ) {
  287. EvalAssert(FFreeCopyList( pPermInfo ));
  288. pPermInfo = pPermInfo->pNext;
  289. }
  290. psdleGlobal = psdleGlobalHead;
  291. while ( psdleGlobal ) {
  292. PSDLE psdleNext = psdleGlobal->psdleNext;
  293. FFreePsdle( psdleGlobal );
  294. psdleGlobal = psdleNext;
  295. }
  296. TermDiamond();
  297. RestoreDiskLoggingDone();
  298. return(fCopyStatus);
  299. }
  300. /*
  301. ** Purpose:
  302. ** To determine if the given file is read only.
  303. ** Arguments:
  304. ** szFullPathDst : a non-Null, zero-terminated string containing the fully
  305. ** qualified valid path (including the drive) to the file in
  306. ** question. File must exist.
  307. ** Returns:
  308. ** ynrcYes if the file is read only, ynrcNo otherwise.
  309. **
  310. **************************************************************************/
  311. YNRC APIENTRY YnrcFileReadOnly(szFullPathDst)
  312. SZ szFullPathDst;
  313. {
  314. BOOL fOkay = fTrue;
  315. unsigned uiAttrib;
  316. ChkArg(szFullPathDst != (SZ)NULL && FValidPath(szFullPathDst) &&
  317. FFileFound(szFullPathDst), 1, ynrcErr1);
  318. if ((uiAttrib = GetFileAttributes(szFullPathDst)) == -1)
  319. fOkay = fFalse;
  320. if (!fOkay)
  321. return(ynrcErr1);
  322. return((uiAttrib & FILE_ATTRIBUTE_READONLY) ? ynrcYes : ynrcNo);
  323. }
  324. /*
  325. ** Purpose:
  326. ** To set the read only status of a file to either read only or normal.
  327. ** Arguments:
  328. ** szFullPathDst: a non-Null, zero-terminated string containing the fully
  329. ** qualified valid path (including drive) whose status is to be
  330. ** set. File must already exist.
  331. ** fReadOnly: fTrue if the status is to be set to read only, fFalse
  332. ** if the status is to be set to normal
  333. ** Returns:
  334. ** fTrue if the function succeeds in setting the status as specified,
  335. ** fFalse otherwise.
  336. **
  337. **************************************************************************/
  338. BOOL APIENTRY FSetFileReadOnlyStatus(SZ szFullPathDst,BOOL fReadOnly)
  339. {
  340. BOOL fRet = fFalse;
  341. DWORD uiAttrib;
  342. DWORD newAttrib;
  343. ChkArg(szFullPathDst != (SZ)NULL && FValidPath(szFullPathDst) &&
  344. FFileFound(szFullPathDst), 1, fFalse);
  345. if ((uiAttrib = GetFileAttributes(szFullPathDst)) != -1) {
  346. if(fReadOnly) {
  347. newAttrib = uiAttrib | FILE_ATTRIBUTE_READONLY;
  348. } else {
  349. newAttrib = uiAttrib & ~FILE_ATTRIBUTE_READONLY;
  350. }
  351. if((newAttrib == uiAttrib) || SetFileAttributes(szFullPathDst, newAttrib)) {
  352. fRet = fTrue;
  353. }
  354. }
  355. return(fRet);
  356. }
  357. /*
  358. ** Purpose:
  359. ** To determine if there is already a destination file that is "newer" than
  360. ** the source file.
  361. ** Arguments:
  362. ** dateSrc: valid date value in unsigned int form extracted from INF.
  363. ** szFullPathDst: a non-Null, zero terminated string containing the fully
  364. ** qualified valid path (including disk drive) to the destination
  365. ** file. File must exist.
  366. ** dwVerSrcMS: Most significant 32 bits of source file version stamp.
  367. ** dwVerSrcLS: Least significant 32 bits of source file version stamp.
  368. ** Returns:
  369. ** ynrcYes if the destination file already exists and is newer than
  370. ** the source file.
  371. ** ynrcErr1, ynrcErr2, or ynrcErr3 in errors.
  372. ** ynrcNo otherwise.
  373. **
  374. **************************************************************************/
  375. YNRC APIENTRY YnrcNewerExistingFile(USHORT dateSrc,
  376. SZ szFullPathDst, DWORD dwVerSrcMS, DWORD dwVerSrcLS)
  377. {
  378. USHORT dateDst, timeDst;
  379. PFH pfhDst;
  380. FILETIME WriteTime;
  381. DWORD dwVerDstMS;
  382. DWORD dwVerDstLS;
  383. ChkArg(szFullPathDst != (SZ)NULL && FValidPath(szFullPathDst) &&
  384. FFileFound(szFullPathDst), 2, ynrcErr1);
  385. if ( (dwVerSrcMS != 0L || dwVerSrcLS != 0L) &&
  386. FGetFileVersion(szFullPathDst, &dwVerDstMS, &dwVerDstLS)) {
  387. if (dwVerDstMS > dwVerSrcMS ||
  388. (dwVerDstMS == dwVerSrcMS && dwVerDstLS > dwVerSrcLS)) {
  389. return(ynrcYes);
  390. }
  391. else {
  392. return(ynrcNo);
  393. }
  394. }
  395. else {
  396. if ((pfhDst = PfhOpenFile(szFullPathDst, ofmRead)) == NULL) {
  397. return(ynrcErr1);
  398. }
  399. if (!GetFileTime((HANDLE)LongToHandle(pfhDst->iDosfh), NULL, NULL, &WriteTime) ||
  400. !FileTimeToDosDateTime(&WriteTime, &dateDst, &timeDst)) {
  401. FCloseFile(pfhDst);
  402. return(ynrcErr2);
  403. }
  404. if (!FCloseFile(pfhDst)) {
  405. return(ynrcErr3);
  406. }
  407. if (dateDst > dateSrc) {
  408. return(ynrcYes);
  409. }
  410. }
  411. return(ynrcNo);
  412. }
  413. /*
  414. ** Purpose:
  415. ** Gets the file version values from the given file and sets the
  416. ** given pdwMS/pdwLS variables.
  417. ** Arguments:
  418. ** szFullPath: a zero terminated character string containing the fully
  419. ** qualified path (including disk drive) to the file.
  420. ** pdwMS: Most significant 32 bits of source file version stamp.
  421. ** pdwLS: Least significant 32 bits of source file version stamp.
  422. ** Returns:
  423. ** fTrue if file and file version resource found and retrieved,
  424. ** fFalse if not.
  425. +++
  426. ** Implementation:
  427. **************************************************************************/
  428. BOOL APIENTRY FGetFileVersion(szFullPath, pdwMS, pdwLS)
  429. SZ szFullPath;
  430. DWORD * pdwMS;
  431. DWORD * pdwLS;
  432. {
  433. BOOL fRet = fFalse;
  434. DWORD dwHandle;
  435. DWORD dwLen;
  436. LPSTR lpData;
  437. ChkArg(szFullPath != (SZ)NULL, 1, fFalse);
  438. ChkArg(pdwMS != (DWORD *)NULL, 2, fFalse);
  439. ChkArg(pdwLS != (DWORD *)NULL, 3, fFalse);
  440. //
  441. // Get the file version info size
  442. //
  443. if ((dwLen = GetFileVersionInfoSize((LPSTR)szFullPath, &dwHandle)) == 0) {
  444. return (fRet);
  445. }
  446. //
  447. // Allocate enough size to hold version info
  448. //
  449. while ((lpData = (LPSTR)SAlloc((CB)dwLen)) == (LPSTR)NULL) {
  450. if (!FHandleOOM(hwndFrame)) {
  451. return (fRet);
  452. }
  453. }
  454. //
  455. // Get the version info
  456. //
  457. fRet = GetFileVersionInfo((LPSTR)szFullPath, dwHandle, dwLen, lpData);
  458. if (fRet) {
  459. VS_FIXEDFILEINFO *pvsfi;
  460. DWORD dwLen;
  461. fRet = VerQueryValue(
  462. (LPVOID)lpData,
  463. (LPSTR)"\\",
  464. (LPVOID *)&pvsfi,
  465. &dwLen
  466. );
  467. if (fRet) {
  468. *pdwMS = pvsfi->dwFileVersionMS;
  469. *pdwLS = pvsfi->dwFileVersionLS;
  470. }
  471. }
  472. SFree(lpData);
  473. return (fRet);
  474. }
  475. /*
  476. ** Purpose:
  477. ** Renames the given destination file as a backup file based on
  478. ** the backup file name given. If a backup file with the given
  479. ** name already exists, the function does nothing and returns.
  480. ** Arguments:
  481. ** szDst: a zero terminated char string containing the fully
  482. ** qualified path to the file to be backed up.
  483. ** szBackup: a zero terminated char string containing the file name
  484. ** of the file that will be the backup copy of szDst. This is
  485. ** not a fully qualified path, or subpath, it is only the filename
  486. ** (i.e. primary.ext).
  487. ** psfd: pointer to the Section-File Description(SFD) structure of
  488. ** the file being backed up.
  489. ** Returns:
  490. ** ynrcNo: if the backup file name is invalid or if unable to create
  491. ** the backup and user chooses to abort.
  492. ** ynrcErr1: if unable to create the backup and the user chooses ignore.
  493. ** ynrcYes: if the backup is successfully created or already exists.
  494. **
  495. **************************************************************************/
  496. YNRC APIENTRY YnrcBackupFile(szDst, szBackup, psfd)
  497. SZ szDst;
  498. SZ szBackup;
  499. PSFD psfd;
  500. {
  501. YNRC ynrcRet = ynrcYes;
  502. Unused(szBackup);
  503. Assert(psfd->oer.szAppend == (SZ)NULL);
  504. if (!FBuildFullBakPath(szFullPathBak, szDst, psfd) ||
  505. !FValidPath(szFullPathBak))
  506. return(ynrcNo);
  507. /* If the backup file already exists, leave the existing backup
  508. ** and return. (Either the user made it and we don't want to kill
  509. ** his, or we made it and we don't need to make another one.)
  510. */
  511. if (FFileFound(szFullPathBak))
  512. return(ynrcYes);
  513. while (rename(szFullPathDst, szFullPathBak))
  514. {
  515. EERC eerc;
  516. if ((eerc = EercErrorHandler(hwndFrame, grcRenameFileErr,
  517. psfd->oer.oef & oefVital, szFullPathDst, szFullPathBak, 0))
  518. == eercAbort)
  519. {
  520. ynrcRet = ynrcNo;
  521. break;
  522. }
  523. else if (eerc == eercIgnore)
  524. {
  525. ynrcRet = ynrcErr1;
  526. break;
  527. }
  528. Assert(eerc == eercRetry);
  529. }
  530. return(ynrcRet);
  531. }
  532. /*
  533. **************************************************************************/
  534. USHORT APIENTRY DateFromSz(SZ sz)
  535. {
  536. USHORT usAns, usYear, usMonth, usDay;
  537. ChkArg(sz == (SZ)NULL || FValidOerDate(sz), 1, 0);
  538. if (sz == (SZ)NULL)
  539. {
  540. usYear = 1980;
  541. usMonth = 1;
  542. usDay = 1;
  543. }
  544. else
  545. {
  546. usYear = (USHORT)atoi(sz);
  547. usMonth = (USHORT)atoi(sz + 5);
  548. usDay = (USHORT)atoi(sz + 8);
  549. }
  550. Assert(usYear >= 1980 && usYear <= 2099);
  551. Assert(usMonth >= 1 && usMonth <= 12);
  552. Assert(usDay >= 1 && usDay <= 31);
  553. usAns = usDay + (usMonth << 5) + ((usYear - (USHORT)1980) << 9);
  554. return(usAns);
  555. }
  556. BOOL
  557. CreateTargetAsLinkToMaster(
  558. IN SZ FullSourceFilename,
  559. IN SZ FullTargetFilename,
  560. IN BOOL TargetExists
  561. )
  562. {
  563. //BUGBUG: handle case of target file in use.
  564. //BUGBUG: handle case of target already exists.
  565. //BUGBUG: handle owm modes
  566. //BUGBUG: The following code is written to work with the prototype COW
  567. // server, not with the real SIS server. If the target file
  568. // exists, we assume it is the correct version (in the master
  569. // tree) and don't do the copy.
  570. //
  571. if ( TargetExists ) {
  572. //DbgPrint( "SIS: Target %s exists; not copying\n", FullTargetFilename );
  573. return NO_ERROR; // target exists; don't copy
  574. }
  575. //DbgPrint( "SIS: Target %s doesn't exist; copying\n", FullTargetFilename );
  576. return ERROR_FILE_NOT_FOUND; // target doesn't exist; copy by usual means
  577. }
  578. /*
  579. ** Purpose:
  580. ** Performs the copy defined by the given copy list node.
  581. ** Arguments:
  582. ** hInstance: non-NULL instance handle for getting strings from
  583. ** resources for SwapDisk message Box.
  584. ** pcln: pointer to the Copy List Node (CLN) of the file to be
  585. ** copied.
  586. ** psdle: non-NULL Source-Description-List-Element pointer to be
  587. ** used by FPromptForDisk().
  588. ** lTotalSize: the total of all of the sizes (i.e. oer.ctuCopyTime or
  589. ** oer.lSize) for all of the files on the disk currently being copied.
  590. ** Returns:
  591. ** fTrue if the copy was successful, fFalse otherwise.
  592. **
  593. **************************************************************************/
  594. BOOL APIENTRY
  595. FCopyListFile(
  596. HANDLE hInstance,
  597. PCLN pcln,
  598. PSDLE psdle,
  599. LONG lTotalSize
  600. )
  601. {
  602. PSFD psfd = pcln->psfd;
  603. POER poer = &(psfd->oer);
  604. BOOL fDstExists, fCompressedName;
  605. SZ szSrcDollar = NULL;
  606. BOOL fVital = poer->oef & oefVital;
  607. EERC eerc;
  608. int Removable;
  609. LONG lSize;
  610. USHORT dateSrc = DateFromSz(poer->szDate);
  611. PSECURITY_DESCRIPTOR Sd = NULL;
  612. CB SdLen;
  613. CHP szNonCompressedFullPathSrc[cchpFullPathBuf] = "\0";
  614. SZ SymbolValue;
  615. CHAR szSrcDrive[10];
  616. ChkArg(pcln != (PCLN)NULL, 1, fFalse);
  617. ChkArg(psdle != (PSDLE)NULL, 2, fFalse);
  618. //
  619. // Only if a drive is removable do we check for the tagfile, in the case
  620. // of a net drive the error is caught later on when we look for the src
  621. // file. Note that the tag file is relative to the root of the removable
  622. // drive.
  623. //
  624. // Because of a bug in 3.51 there are CD's which expect the tagfile to be
  625. // locatable in a subdirectory. We'll use a hack based on STF_CWDDIR
  626. // to make that work.
  627. //
  628. Removable = DetermineDriveType(*(pcln->szSrcDir));
  629. if((Removable < 0) && psdle->szTagFile) {
  630. strcpy(szSrcDrive,"?:\\");
  631. szSrcDrive[0] = *(pcln->szSrcDir);
  632. if(!FBuildFullSrcPath(szFullPathSrc,szSrcDrive,psdle->szTagFile,NULL)) {
  633. EercErrorHandler(hwndFrame,grcInvalidPathErr,fVital,szSrcDrive,psdle->szTagFile,0);
  634. return(!fVital);
  635. }
  636. if((Removable == -2) && (SymbolValue = SzFindSymbolValueInSymTab("!STF_CWDDIR"))) {
  637. if(!FBuildFullSrcPath(szFullPathDst,SymbolValue,psdle->szTagFile,NULL)) {
  638. szFullPathDst[0] = 0;
  639. }
  640. } else {
  641. szFullPathDst[0] = 0;
  642. }
  643. //
  644. // Strip the backslash off the drive letter.
  645. //
  646. szSrcDrive[2] = '\0';
  647. //
  648. // If we can't find the tag file at the root then also look in
  649. // STF_CWDDIR, if there is one.
  650. //
  651. while(!FFileFound(szFullPathSrc) && (!szFullPathDst[0] || !FFileFound(szFullPathDst))) {
  652. MessageBeep(0);
  653. ShowOwnedPopups(hwndFrame,FALSE);
  654. if(FPromptForDisk(hInstance, psdle->szLabel, szSrcDrive)) {
  655. ShowOwnedPopups(hwndFrame,TRUE);
  656. } else {
  657. HWND hwndSav = GetFocus();
  658. BOOL b;
  659. CCHL szTmpText[cchpBufTmpLongMax];
  660. //
  661. // Make sure this is what he *really* wants to do.
  662. //
  663. LoadString(hInstance, IDS_SURECANCEL, rgchBufTmpLong, cchpBufTmpLongMax);
  664. LoadString(hInstance, IDS_ERROR, (LPSTR)szTmpText, cchpBufTmpLongMax);
  665. b = (MessageBox(hwndFrame, rgchBufTmpLong, (LPSTR)szTmpText, MB_YESNO|MB_TASKMODAL) == IDYES);
  666. ShowOwnedPopups(hwndFrame,TRUE);
  667. SetFocus(hwndSav);
  668. SendMessage(hwndFrame, WM_NCACTIVATE, 1, 0L);
  669. if(b) {
  670. return(fFalse);
  671. }
  672. }
  673. }
  674. }
  675. if (!FBuildFullSrcPath(szFullPathSrc, pcln->szSrcDir, psfd->szFile,
  676. (Removable < 0) ? NULL : psdle->szNetPath)) {
  677. EvalAssert(EercErrorHandler(hwndFrame, grcInvalidPathErr, fVital,
  678. pcln->szSrcDir, psfd->szFile, 0) == eercAbort);
  679. return(!fVital);
  680. }
  681. //
  682. // Determine the source file name:
  683. // Check to see if source file exists as the regular name or
  684. // a compressed name
  685. //
  686. lstrcpy( szNonCompressedFullPathSrc, szFullPathSrc );
  687. fCompressedName = fFalse;
  688. while (!FFileFound( szFullPathSrc )) {
  689. if (szSrcDollar == (SZ)NULL) {
  690. while ((szSrcDollar = SzGetSrcDollar(szFullPathSrc,'_')) == (SZ)NULL) {
  691. if (!FHandleOOM(hwndFrame)) {
  692. return(!fVital);
  693. }
  694. }
  695. }
  696. if (FFileFound( szSrcDollar )) {
  697. lstrcpy( szFullPathSrc, szSrcDollar );
  698. fCompressedName = fTrue;
  699. break;
  700. }
  701. #define DOLLAR_NAME
  702. #ifdef DOLLAR_NAME
  703. SFree(szSrcDollar);
  704. while((szSrcDollar = SzGetSrcDollar(szFullPathSrc,'$')) == (SZ)NULL) {
  705. if (!FHandleOOM(hwndFrame)) {
  706. return(!fVital);
  707. }
  708. }
  709. if(FFileFound(szSrcDollar)) {
  710. lstrcpy(szFullPathSrc,szSrcDollar);
  711. fCompressedName = fTrue;
  712. break;
  713. }
  714. #endif
  715. SFree( szSrcDollar);
  716. szSrcDollar = NULL;
  717. //
  718. // Unable to locate the source file.
  719. // If we are supposed to skip missing files, ignore it.
  720. // Text setup sets a symbol called SMF to YES if we are
  721. // supposed to skip missing files.
  722. //
  723. if((SymbolValue = SzFindSymbolValueInSymTab("!SMF")) && !lstrcmpi(SymbolValue,"YES")) {
  724. return(fTrue);
  725. }
  726. //
  727. // If the file exists on the target and this is a winnt
  728. // non-upgrade setup, just assume the file was already copied.
  729. //
  730. if(/*fInitialSetup &&*/ !fNTUpgradeSetup
  731. && !_strnicmp(szFullPathSrc+2,LOCAL_SOURCE_DIRECTORY,lstrlen(LOCAL_SOURCE_DIRECTORY)))
  732. {
  733. if(!FBuildFullDstPath(szFullPathDst, pcln->szDstDir, psfd, FALSE)) {
  734. if (!FHandleOOM(hwndFrame)) {
  735. return(!fVital);
  736. }
  737. }
  738. if(FFileExists(szFullPathDst)) {
  739. return(fTrue);
  740. }
  741. }
  742. if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
  743. szFullPathSrc, 0, 0)) != eercRetry) {
  744. return(eerc == eercIgnore);
  745. }
  746. }
  747. if (szSrcDollar) {
  748. SFree( szSrcDollar);
  749. szSrcDollar = (SZ)NULL;
  750. }
  751. //
  752. // Determine the destination file name:
  753. //
  754. if (!FBuildFullDstPath(szFullPathDst, pcln->szDstDir, psfd, fCompressedName) ||
  755. !FValidPath(szFullPathDst)) {
  756. EvalAssert(EercErrorHandler(hwndFrame, grcInvalidPathErr, fVital,
  757. pcln->szDstDir, psfd->szFile, 0) == eercAbort);
  758. return(!fVital);
  759. }
  760. fDstExists = FFileFound(szFullPathDst);
  761. #ifdef REMOTE_BOOT
  762. if (1) { //BUGBUG: how to turn on SIS check here?
  763. DWORD rc;
  764. if (!fCompressedName) {
  765. rc = CreateTargetAsLinkToMaster(
  766. szFullPathSrc,
  767. szFullPathDst,
  768. fDstExists
  769. );
  770. if (rc == NO_ERROR) {
  771. return TRUE;
  772. }
  773. }
  774. }
  775. #endif
  776. if (fDstExists != fFalse) {
  777. OWM owm;
  778. YNRC ynrc;
  779. //
  780. // Check overwrite mode. The overwrite mode can be:
  781. //
  782. // 1. Never : No further checking. The file is not copied
  783. //
  784. // 2. Unprotected: Check to see if file on destination is readonly.
  785. //
  786. // 3. Older : The release version / date is checked against the
  787. // the destination file
  788. //
  789. // 4. VerifySourceOlder: The checking is postponed till we have actually
  790. // found the source file. The source time is then
  791. // compared against the destination time and only
  792. // if the destination is older the file is copied.
  793. if ((owm = poer->owm) & owmNever) {
  794. return(fTrue);
  795. }
  796. else if (owm & owmUnprotected) {
  797. while ((ynrc = YnrcFileReadOnly(szFullPathDst)) == ynrcErr1) {
  798. if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
  799. szFullPathDst, 0, 0)) != eercRetry) {
  800. return(eerc == eercIgnore);
  801. }
  802. }
  803. if (ynrc == ynrcYes) {
  804. return(fTrue);
  805. }
  806. }
  807. else if (owm & owmOlder) {
  808. while ((ynrc = YnrcNewerExistingFile(dateSrc, szFullPathDst,
  809. poer->ulVerMS, poer->ulVerLS)) != ynrcYes
  810. && ynrc != ynrcNo) {
  811. if (ynrc == ynrcErr1 &&
  812. (eerc = EercErrorHandler(hwndFrame, grcOpenFileErr,
  813. fVital, szFullPathDst, 0, 0)) != eercRetry)
  814. return(eerc == eercIgnore);
  815. else if (ynrc == ynrcErr2 &&
  816. (eerc = EercErrorHandler(hwndFrame, grcReadFileErr,
  817. fVital, szFullPathDst, 0, 0)) != eercRetry)
  818. return(eerc == eercIgnore);
  819. else if (ynrc == ynrcErr3 &&
  820. (eerc = EercErrorHandler(hwndFrame, grcCloseFileErr,
  821. fVital, szFullPathDst, 0, 0)) != eercRetry)
  822. return(eerc == eercIgnore);
  823. }
  824. if (ynrc == ynrcYes)
  825. return(fTrue);
  826. Assert(ynrc == ynrcNo);
  827. }
  828. }
  829. else {
  830. //
  831. // Destination doesn't exist, check to see if we are in upgradeonly
  832. // mode, in which case we need not copy the file and we can just
  833. // return.
  834. OEF oef = poer->oef;
  835. if ( oef & oefUpgradeOnly ) {
  836. return( fTrue );
  837. }
  838. }
  839. //
  840. // If destination exists then we need to preserve the security that is
  841. // there on the file. We read the security on the existing file
  842. // and once the new file is copied over then we set the security read
  843. // on the new file. Note that we don't do this for initial setup since
  844. // we are going to fix permissions on the file anyway.
  845. //
  846. if(fDstExists && !fInitialSetup) {
  847. if(!FGetFileSecurity(szFullPathDst, &Sd, &SdLen)) {
  848. return( fFalse );
  849. }
  850. }
  851. if (fDstExists &&
  852. poer->szBackup != NULL)
  853. {
  854. YNRC ynrc;
  855. if ((ynrc = YnrcBackupFile(szFullPathDst, poer->szBackup, psfd)) !=
  856. ynrcYes)
  857. return(ynrc != ynrcNo);
  858. fDstExists = FFileFound(szFullPathDst);
  859. }
  860. if (fDstExists)
  861. {
  862. while (!FSetFileReadOnlyStatus(szFullPathDst, fOff))
  863. {
  864. if ((eerc = EercErrorHandler(hwndFrame, grcWriteFileErr, fVital,
  865. szFullPathDst, 0, 0)) != eercRetry)
  866. return(eerc == eercIgnore);
  867. }
  868. }
  869. if(!fSilentSystem) {
  870. LPSTR p;
  871. CHAR chSave;
  872. EvalAssert((p = SzFindFileFromPath(szFullPathSrc)) != NULL);
  873. if(!p) {
  874. p = szFullPathSrc;
  875. }
  876. wsprintf(rgchBufTmpLong,"%s %s",GaugeText1,p);
  877. ProSetText(ID_STATUS1,rgchBufTmpLong);
  878. EvalAssert((p = SzFindFileFromPath(szFullPathDst)) != NULL);
  879. if(p) {
  880. if(!ISUNC(szFullPathDst) && (p - szFullPathDst != 3)) { // account for file in root
  881. p--;
  882. }
  883. chSave = *p;
  884. *p = '\0';
  885. wsprintf(rgchBufTmpLong,"%s %s",GaugeText2,szFullPathDst);
  886. *p = chSave;
  887. } else {
  888. rgchBufTmpLong[0] = '\0';
  889. }
  890. ProSetText(ID_STATUS2,rgchBufTmpLong);
  891. }
  892. lSize = (poer->ctuCopyTime > 0) ? (LONG)(poer->ctuCopyTime) : poer->lSize;
  893. if (!FCopy(szFullPathSrc, szFullPathDst, poer->oef, poer->owm,
  894. (poer->szAppend != NULL),
  895. (int)((DWORD)10000 * lSize / lTotalSize), dateSrc,psdle,szNonCompressedFullPathSrc))
  896. return(fFalse);
  897. if( Sd ) {
  898. //
  899. // BUGBUG -
  900. //
  901. // Preservation of file security is broken, since the most files
  902. // were overwritten during textmode setup.
  903. // So this is currently disabled.
  904. //
  905. // BOOL Status;
  906. // Status = FSetFileSecurity(szFullPathDst, Sd);
  907. SFree(Sd);
  908. // return(Status);
  909. }
  910. return(fTrue);
  911. }
  912. /*
  913. ** Purpose:
  914. ** Uses the Compression DollarSign translation algorithm on its argument.
  915. ** If the file has no extension, then '._' is added. If the extension
  916. ** has less than 3 characters, then a '_' is appended. Otherwise, the
  917. ** third character of the extension is replaced by a dollarsign.
  918. ** Arguments:
  919. ** szFullPathSrc: a zero terminated character string containing the fully
  920. ** qualified path (including drive) for the source file.
  921. ** Returns:
  922. **
  923. **************************************************************************/
  924. SZ APIENTRY SzGetSrcDollar(SZ szFullPathSrc,CHAR ch)
  925. {
  926. SZ szDot = (SZ)NULL;
  927. SZ szCur = szFullPathSrc;
  928. CHAR dotch[3];
  929. dotch[0] = '.';
  930. dotch[1] = ch;
  931. dotch[2] = 0;
  932. ChkArg(szFullPathSrc != (SZ)NULL, 1, (SZ)NULL);
  933. while (*szCur != '\0')
  934. {
  935. if (*szCur == '.')
  936. szDot = szCur;
  937. else if (*szCur == '\\')
  938. szDot = (SZ)NULL;
  939. szCur = SzNextChar(szCur);
  940. }
  941. Assert(szDot == (SZ)NULL || *szDot == '.');
  942. if (szDot == (SZ)NULL)
  943. {
  944. if ((szDot = (SZ)SAlloc(strlen(szFullPathSrc) + 3)) != (SZ)NULL)
  945. {
  946. EvalAssert(strcpy(szDot, szFullPathSrc) == szDot);
  947. EvalAssert(SzStrCat(szDot, dotch) == szDot);
  948. }
  949. }
  950. else
  951. {
  952. CHP chpSav = '\0';
  953. SZ szRest;
  954. CB cb;
  955. if (*(szCur = ++szDot) != '\0' &&
  956. *(szCur = SzNextChar(szCur)) != '\0' &&
  957. *(szCur = SzNextChar(szCur)) != '\0')
  958. {
  959. chpSav = *szCur;
  960. szRest = SzNextChar(szCur);
  961. *szCur = '\0';
  962. }
  963. cb = strlen(szFullPathSrc) + 2;
  964. if (chpSav != '\0')
  965. {
  966. Assert(szRest != (SZ)NULL);
  967. cb += strlen(szRest);
  968. }
  969. if ((szDot = (SZ)SAlloc(cb)) != (SZ)NULL)
  970. {
  971. EvalAssert(strcpy(szDot, szFullPathSrc) == szDot);
  972. EvalAssert(SzStrCat(szDot, &dotch[1]) == szDot);
  973. if (chpSav != '\0')
  974. {
  975. Assert(szRest != (SZ)NULL);
  976. EvalAssert(SzStrCat(szDot, szRest) == szDot);
  977. *szCur = chpSav;
  978. }
  979. }
  980. }
  981. return(szDot);
  982. }
  983. static int iTickMax = 0;
  984. static int iTickCur = 0;
  985. int far WFromW(int iTick)
  986. {
  987. if (iTick > iTickMax - iTickCur)
  988. iTick = iTickMax - iTickCur;
  989. if (iTick > 0)
  990. {
  991. ProDeltaPos(iTick);
  992. iTickCur += iTick;
  993. }
  994. return(1);
  995. }
  996. /*
  997. ** Purpose:
  998. ** To physically copy the source file to the destination file. This
  999. ** can include several options including appending, open and closing src
  1000. ** and dst files, but not actually copying the contents of the files,
  1001. ** decompressing, timestamping the dst file, and setting the read only
  1002. ** status of the dst file.
  1003. ** Arguments:
  1004. ** szFullPathSrc: a zero terminated character string containing the fully
  1005. ** qualified path (including drive) for the source file.
  1006. ** szFullPathDst: a zero terminated character string containing the fully
  1007. ** qualified path (including drive) for the destination file.
  1008. ** oef: option element flags for the Section-File Description
  1009. ** The valid flags include oefVital, oefCopy, oefUndo,
  1010. ** oefRoot, oefDecompress, oefTimeStamp, oefReadOnly,
  1011. ** oefNone and oefAll.
  1012. ** fAppend: fTrue if the contents of szFullPathSrc are to be
  1013. ** appended to the contents of szFullPathDst.
  1014. ** cProgTicks: number of ticks to advance Progress Gizmo.
  1015. ** dateSrc: DATE value from INF for src file.
  1016. ** Returns:
  1017. ** fTrue if the copy is successfully completed, fFalse otherwise.
  1018. **
  1019. **************************************************************************/
  1020. BOOL APIENTRY
  1021. FCopy(
  1022. SZ szFullPathSrc,
  1023. SZ szFullPathDst,
  1024. OEF oef,
  1025. OWM owm,
  1026. BOOL fAppend,
  1027. int cProgTicks,
  1028. USHORT dateSrc,
  1029. PSDLE psdle,
  1030. SZ szNonCompressedFullPathSrc
  1031. )
  1032. {
  1033. #if 0
  1034. CB cbSize;
  1035. CB cbActual;
  1036. #endif
  1037. PB pbBuffer = NULL;
  1038. PFH pfhSrc = NULL;
  1039. PFH pfhDst = NULL;
  1040. LFA lfaDst = 0L;
  1041. HANDLE hSource = NULL;
  1042. BOOL fVital = oef & oefVital;
  1043. BOOL fDecomp = oef & oefDecompress;
  1044. BOOL fRet = !fVital;
  1045. BOOL fRemovePartialFile = fFalse;
  1046. EERC eerc;
  1047. YNRC ynrc;
  1048. FILETIME CreateTime, AccessTime, WriteTime;
  1049. BOOL fSilentSystem = FGetSilent();
  1050. LONG lRet;
  1051. ULONG Checksum = 0;
  1052. BOOL fThirdPartyFile = oef & oefThirdPartyFile;
  1053. BOOL OnLocalSource;
  1054. BOOLEAN IsValid;
  1055. BOOLEAN IsNtImage;
  1056. BOOL fCsdInstall = oef & oefCsdInstall;
  1057. SZ szActiveFileTmpName = NULL;
  1058. if( fCsdInstall &&
  1059. DoesFileReplaceThirdPartyFile( szFullPathDst+2 ) ) {
  1060. return( TRUE );
  1061. }
  1062. OnLocalSource = (_strnicmp(szFullPathSrc+2,LOCAL_SOURCE_DIRECTORY,lstrlen(LOCAL_SOURCE_DIRECTORY)) == 0);
  1063. do {
  1064. while ((pfhSrc = PfhOpenFile(szFullPathSrc, ofmRead)) == (PFH)NULL) {
  1065. if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
  1066. szFullPathSrc, 0, 0)) != eercRetry) {
  1067. fRet = (eerc == eercIgnore);
  1068. goto LCopyError;
  1069. }
  1070. }
  1071. while (!GetFileTime((HANDLE)LongToHandle(pfhSrc->iDosfh), &CreateTime, &AccessTime,
  1072. &WriteTime)) {
  1073. if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
  1074. szFullPathSrc, 0, 0)) != eercRetry) {
  1075. fRet = (eerc == eercIgnore);
  1076. goto LCopyError;
  1077. }
  1078. }
  1079. if (!(oef & oefCopy))
  1080. {
  1081. if (!FCloseFile(pfhSrc))
  1082. while ((eerc = EercErrorHandler(hwndFrame, grcCloseFileErr, fVital,
  1083. szFullPathSrc, 0, 0)) != eercRetry)
  1084. {
  1085. fRet = (eerc == eercIgnore);
  1086. goto LCopyError;
  1087. }
  1088. pfhSrc = NULL;
  1089. if (cProgTicks > 0 && !fSilentSystem)
  1090. ProDeltaPos(cProgTicks);
  1091. fRet = fTrue;
  1092. goto DelSrc;
  1093. }
  1094. if(FFileFound(szFullPathDst)) {
  1095. //
  1096. // We need to check if we have been asked to compare actual file times
  1097. //
  1098. if ( owm & owmVerifySourceOlder ) {
  1099. PFH pfh;
  1100. FILETIME DstWriteTime;
  1101. BOOL Older = fFalse;
  1102. if ((pfh = PfhOpenFile(szFullPathDst, ofmRead)) != NULL) {
  1103. if (GetFileTime((HANDLE)LongToHandle(pfh->iDosfh), NULL, NULL, &DstWriteTime)) {
  1104. if( CompareFileTime( &DstWriteTime, &WriteTime ) == -1 ) {
  1105. Older = fTrue;
  1106. }
  1107. }
  1108. FCloseFile(pfh);
  1109. }
  1110. if( !Older ) {
  1111. FCloseFile(pfhSrc);
  1112. pfhSrc = NULL;
  1113. if (cProgTicks > 0 && !fSilentSystem)
  1114. ProDeltaPos(cProgTicks);
  1115. fRet = fTrue;
  1116. goto DelSrc;
  1117. }
  1118. }
  1119. //
  1120. // if this is a CSD, then we need to back up the old file in case
  1121. // the copy fails for some reason. (We also gotta make sure that
  1122. // the files aren't the same, otherwise we'll get a bogus error)
  1123. //
  1124. if( fCsdInstall && lstrcmpi(szFullPathSrc, szFullPathDst) ) {
  1125. //
  1126. // We don't want to back up the file again, if we're retrying
  1127. //
  1128. if(!szActiveFileTmpName) {
  1129. while(!(szActiveFileTmpName = FRenameActiveFile(szFullPathDst))) {
  1130. //
  1131. // Error opening, present critical error to user
  1132. //
  1133. if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
  1134. szFullPathDst, 0, 0)) != eercRetry) {
  1135. fRet = (eerc == eercIgnore);
  1136. goto LCopyError;
  1137. }
  1138. }
  1139. }
  1140. }
  1141. }
  1142. if ((ynrc = YnrcEnsurePathExists(szFullPathDst, fVital, NULL)) != ynrcYes)
  1143. {
  1144. fRet = (ynrc == ynrcErr1);
  1145. goto LCopyError;
  1146. }
  1147. while ((pfhDst = PfhOpenFile(szFullPathDst,
  1148. (OFM)(fAppend ? ofmReadWrite : ofmCreate))) == NULL) {
  1149. DWORD dw;
  1150. dw = GetLastError();
  1151. //
  1152. // if it is a sharing violation and this is because both the source
  1153. // and destination are the same, then present the error to the user.
  1154. //
  1155. if (dw == ERROR_SHARING_VIOLATION && !lstrcmpi(szFullPathSrc, szFullPathDst)) {
  1156. if ((eerc = EercErrorHandler(hwndFrame, grcOpenSameFileErr, fFalse,
  1157. szFullPathDst, 0, 0)) != eercRetry) {
  1158. fRet = (eerc == eercIgnore);
  1159. goto LCopyError;
  1160. }
  1161. else {
  1162. continue;
  1163. }
  1164. }
  1165. //
  1166. // For active files access will be denied
  1167. //
  1168. if(((dw == ERROR_ACCESS_DENIED) || (dw == ERROR_SHARING_VIOLATION) || (dw == ERROR_USER_MAPPED_FILE))
  1169. && !fAppend) {
  1170. //
  1171. // make sure we don't already have a backup (if this is a retry)
  1172. //
  1173. if((szActiveFileTmpName) || (szActiveFileTmpName = FRenameActiveFile(szFullPathDst))) {
  1174. continue;
  1175. }
  1176. }
  1177. //
  1178. // Error opening, present critical error to user
  1179. //
  1180. if ((eerc = EercErrorHandler(hwndFrame, grcOpenFileErr, fVital,
  1181. szFullPathDst, 0, 0)) != eercRetry) {
  1182. fRet = (eerc == eercIgnore);
  1183. goto LCopyError;
  1184. }
  1185. }
  1186. fRemovePartialFile = fTrue;
  1187. if (fAppend) {
  1188. USHORT dateDst, timeDst;
  1189. while(!GetFileTime((HANDLE)LongToHandle(pfhDst->iDosfh), NULL, NULL, &WriteTime)
  1190. || !FileTimeToDosDateTime(&WriteTime, &dateDst, &timeDst)) {
  1191. if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
  1192. szFullPathDst, 0, 0)) != eercRetry) {
  1193. fRet = (eerc == eercIgnore);
  1194. goto LCopyError;
  1195. }
  1196. }
  1197. if (dateDst != dateSrc || timeDst != 0) {
  1198. fRet = fTrue;
  1199. fRemovePartialFile = fFalse;
  1200. goto LCopyError;
  1201. }
  1202. while ((lfaDst = LfaSeekFile(pfhDst, 0, sfmEnd)) == (LFA)(-1)) {
  1203. if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
  1204. szFullPathDst, 0, 0)) != eercRetry) {
  1205. fRet = (eerc == eercIgnore);
  1206. goto LCopyError;
  1207. }
  1208. }
  1209. }
  1210. if (fDecomp) {
  1211. INT rc;
  1212. while ((rc = LZInit( pfhSrc->iDosfh) ) < 0) {
  1213. GRC grc;
  1214. switch (rc) {
  1215. case LZERROR_UNKNOWNALG:
  1216. grc = grcDecompUnknownAlgErr;
  1217. break;
  1218. case LZERROR_GLOBLOCK:
  1219. case LZERROR_READ:
  1220. case LZERROR_BADINHANDLE:
  1221. grc = grcReadFileErr;
  1222. break;
  1223. case LZERROR_GLOBALLOC:
  1224. grc = grcOutOfMemory;
  1225. break;
  1226. default:
  1227. grc = grcDecompGenericErr;
  1228. break;
  1229. }
  1230. if ((eerc = EercErrorHandler(hwndFrame, grc, fVital, szFullPathSrc,
  1231. 0, 0)) != eercRetry) {
  1232. fRet = (eerc == eercIgnore);
  1233. hSource = NULL;
  1234. goto LCopyError;
  1235. }
  1236. }
  1237. hSource = (HANDLE)LongToHandle(rc);
  1238. }
  1239. else {
  1240. hSource = (HANDLE)LongToHandle(pfhSrc->iDosfh);
  1241. }
  1242. if (fDecomp) {
  1243. BOOL isDiamondFile;
  1244. iTickMax = cProgTicks;
  1245. iTickCur = 0;
  1246. //
  1247. // Determine whether the file is a diamond cabinet/compressed file.
  1248. // If it is, we'll call a separate diamond decompressor. If it isn't,
  1249. // we'll call the lz routine, which will decompress an lz file or copy
  1250. // a non-lz (and non-diamond) file.
  1251. //
  1252. isDiamondFile = IsDiamondFile(szFullPathSrc);
  1253. do {
  1254. if(isDiamondFile) {
  1255. lRet = DecompDiamondFile(
  1256. szFullPathSrc,
  1257. (HANDLE)LongToHandle(pfhDst->iDosfh),
  1258. fSilentSystem ? NULL: WFromW,
  1259. cProgTicks
  1260. );
  1261. } else {
  1262. lRet = LcbDecompFile(
  1263. hSource,
  1264. (HANDLE)LongToHandle(pfhDst->iDosfh),
  1265. fSilentSystem ? NULL: WFromW,
  1266. cProgTicks
  1267. );
  1268. }
  1269. if(lRet < 0) {
  1270. GRC grc;
  1271. SZ sz = szFullPathSrc;
  1272. switch (lRet) {
  1273. case rcReadError:
  1274. case rcReadSeekError:
  1275. grc = grcReadFileErr;
  1276. break;
  1277. case rcWriteError:
  1278. case rcWriteSeekError:
  1279. grc = grcWriteFileErr;
  1280. sz = szFullPathDst;
  1281. break;
  1282. case rcOutOfMemory:
  1283. grc = grcOutOfMemory;
  1284. break;
  1285. case rcDiskFull:
  1286. grc = grcDiskFull;
  1287. fVital = TRUE;
  1288. break;
  1289. case rcUserQuit:
  1290. fRet = fFalse;
  1291. goto LCopyError;
  1292. break;
  1293. default:
  1294. grc = grcDecompGenericErr;
  1295. break;
  1296. }
  1297. if ((eerc = EercErrorHandler(hwndFrame, grc, fVital, sz)) !=
  1298. eercRetry)
  1299. {
  1300. fRet = (eerc == eercIgnore);
  1301. goto LCopyError;
  1302. }
  1303. //
  1304. // Before retrying we need to rewind the destination pointer to
  1305. // the place where we began the write
  1306. //
  1307. while (LfaSeekFile(pfhDst, lfaDst, sfmSet) == (LFA)(-1)) {
  1308. if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
  1309. szFullPathDst, 0, 0)) != eercRetry) {
  1310. fRet = (eerc == eercIgnore);
  1311. goto LCopyError;
  1312. }
  1313. }
  1314. }
  1315. } while(lRet < 0);
  1316. Assert(iTickCur <= cProgTicks);
  1317. cProgTicks -= iTickCur;
  1318. }
  1319. else {
  1320. iTickMax = cProgTicks;
  1321. iTickCur = 0;
  1322. while ((lRet = LcbCopyFile(
  1323. hSource,
  1324. (HANDLE)LongToHandle(pfhDst->iDosfh),
  1325. fSilentSystem ? NULL: WFromW,
  1326. cProgTicks
  1327. )) < 0) {
  1328. GRC grc;
  1329. SZ sz = szFullPathSrc;
  1330. switch (lRet) {
  1331. case rcReadError:
  1332. case rcReadSeekError:
  1333. grc = grcReadFileErr;
  1334. break;
  1335. case rcWriteError:
  1336. case rcWriteSeekError:
  1337. grc = grcWriteFileErr;
  1338. sz = szFullPathDst;
  1339. break;
  1340. case rcOutOfMemory:
  1341. grc = grcOutOfMemory;
  1342. break;
  1343. case rcDiskFull:
  1344. grc = grcDiskFull;
  1345. fVital = TRUE;
  1346. break;
  1347. case rcUserQuit:
  1348. fRet = fFalse;
  1349. goto LCopyError;
  1350. break;
  1351. default:
  1352. grc = grcDecompGenericErr;
  1353. break;
  1354. }
  1355. if ((eerc = EercErrorHandler(hwndFrame, grc, fVital, sz)) !=
  1356. eercRetry)
  1357. {
  1358. fRet = (eerc == eercIgnore);
  1359. goto LCopyError;
  1360. }
  1361. //
  1362. // Before retrying we need to rewind the destination pointer to
  1363. // the place where we began the write
  1364. //
  1365. while (LfaSeekFile(pfhDst, lfaDst, sfmSet) == (LFA)(-1)) {
  1366. if ((eerc = EercErrorHandler(hwndFrame, grcReadFileErr, fVital,
  1367. szFullPathDst, 0, 0)) != eercRetry) {
  1368. fRet = (eerc == eercIgnore);
  1369. goto LCopyError;
  1370. }
  1371. }
  1372. }
  1373. Assert(iTickCur <= cProgTicks);
  1374. cProgTicks -= iTickCur;
  1375. }
  1376. if (oef & oefTimeStamp)
  1377. while (!SetFileTime((HANDLE)LongToHandle(pfhDst->iDosfh), &CreateTime, &AccessTime,
  1378. &WriteTime))
  1379. if ((eerc = EercErrorHandler(hwndFrame, grcWriteFileErr, fVital,
  1380. szFullPathDst, 0, 0)) != eercRetry)
  1381. {
  1382. fRet = (eerc == eercIgnore);
  1383. goto LCopyError;
  1384. }
  1385. if (fDecomp) {
  1386. LZClose ( HandleToUlong(hSource) );
  1387. FreePfh ( pfhSrc );
  1388. hSource = NULL;
  1389. pfhSrc = NULL;
  1390. }
  1391. else {
  1392. while (!FCloseFile(pfhSrc)) {
  1393. if ((eerc = EercErrorHandler(hwndFrame, grcCloseFileErr, fVital,
  1394. szFullPathSrc, 0, 0)) != eercRetry)
  1395. {
  1396. fRet = (eerc == eercIgnore);
  1397. goto LCopyError;
  1398. }
  1399. }
  1400. pfhSrc = NULL;
  1401. }
  1402. //
  1403. // If we get here, the file was copied successfully.
  1404. // Close the file before we get the checksum
  1405. //
  1406. while (!FCloseFile(pfhDst)) {
  1407. if ((eerc = EercErrorHandler(hwndFrame, grcCloseFileErr, fVital,
  1408. szFullPathDst, 0, 0)) != eercRetry)
  1409. {
  1410. fRet = (eerc == eercIgnore);
  1411. goto LCopyError;
  1412. }
  1413. }
  1414. pfhDst = NULL;
  1415. ValidateAndChecksumFile( szFullPathDst,
  1416. &IsNtImage,
  1417. &Checksum,
  1418. &IsValid );
  1419. if(!IsValid) {
  1420. if ((eerc = EercErrorHandler(hwndFrame, grcVerifyFileErr, fVital,
  1421. szFullPathDst, 0, 0)) != eercRetry)
  1422. {
  1423. fRet = (eerc == eercIgnore);
  1424. goto LCopyError;
  1425. }
  1426. }
  1427. } while(!IsValid);
  1428. fRemovePartialFile = fFalse;
  1429. //
  1430. // At this point, we can delete the backup file we made (if we made one)
  1431. //
  1432. if(szActiveFileTmpName) {
  1433. if(!FRemoveFile(szActiveFileTmpName)) {
  1434. //
  1435. // It must be locked, so set it to be deleted on reboot
  1436. //
  1437. AddFileToDeleteList(szActiveFileTmpName);
  1438. }
  1439. free(szActiveFileTmpName);
  1440. szActiveFileTmpName = NULL;
  1441. }
  1442. if (oef & oefReadOnly)
  1443. while (!FSetFileReadOnlyStatus(szFullPathDst, fOn))
  1444. {
  1445. if ((eerc = EercErrorHandler(hwndFrame, grcWriteFileErr, fVital,
  1446. szFullPathDst, 0, 0)) != eercRetry)
  1447. {
  1448. fRet = (eerc == eercIgnore);
  1449. goto LCopyError;
  1450. }
  1451. }
  1452. fRet = fTrue;
  1453. LCopyError:
  1454. //
  1455. // Log the file.
  1456. //
  1457. if(psdle && !(oef & oefNoLog) && !fCsdInstall) {
  1458. LogOneFile( szNonCompressedFullPathSrc,
  1459. szFullPathDst,
  1460. psdle->szLabel,
  1461. Checksum,
  1462. psdle->szTagFile,
  1463. fThirdPartyFile
  1464. );
  1465. }
  1466. if (pbBuffer != (PB)NULL) {
  1467. SFree(pbBuffer);
  1468. }
  1469. if (fDecomp && hSource != (HANDLE)NULL) {
  1470. LZClose (HandleToUlong(hSource));
  1471. FreePfh (pfhSrc);
  1472. }
  1473. else if (pfhSrc != (PFH)NULL) {
  1474. EvalAssert(FCloseFile(pfhSrc));
  1475. }
  1476. if (pfhDst != (PFH)NULL) {
  1477. EvalAssert(FCloseFile(pfhDst));
  1478. }
  1479. if (fRemovePartialFile) {
  1480. FRemoveFile(szFullPathDst);
  1481. if(szActiveFileTmpName) {
  1482. MoveFile(szActiveFileTmpName, szFullPathDst);
  1483. free(szActiveFileTmpName);
  1484. }
  1485. }
  1486. //
  1487. // If we have any remaining ticks on the gauge for this file,
  1488. // go ahead and do them. This could happen if the file copy was
  1489. // aborted part way through.
  1490. //
  1491. if (cProgTicks > 0 && !fSilentSystem) {
  1492. ProDeltaPos(cProgTicks);
  1493. }
  1494. DelSrc:
  1495. //
  1496. // Determine whether we are supposed to delete the source file. This
  1497. // is the case when it is coming from a local source as created by the
  1498. // DOS Setup program, and is not marked oefNoDeleteSource.
  1499. //
  1500. if(!fNTUpgradeSetup && OnLocalSource && !(oef & oefNoDeleteSource))
  1501. {
  1502. if (NULL == SzFindSymbolValueInSymTab("!STF_NETDELETEOVERIDE"))
  1503. {
  1504. DeleteFile(szFullPathSrc);
  1505. }
  1506. }
  1507. return(fRet);
  1508. }
  1509. /*
  1510. ** Purpose:
  1511. ** To find a pointer to the beginning of the file name (i.e. primary.ext)
  1512. ** at the end of a fully qualified pathname.
  1513. ** Arguments:
  1514. ** szFullPath: a non-Null, zero-terminated string containing a
  1515. ** pathname ending in a file name.
  1516. ** Returns:
  1517. ** an SZ which is a pointer to the beginning of the file name within the
  1518. ** argument SZ.
  1519. **
  1520. **************************************************************************/
  1521. SZ APIENTRY SzFindFileFromPath(szFullPath)
  1522. SZ szFullPath;
  1523. {
  1524. SZ sz;
  1525. SZ szSave = szFullPath;
  1526. ChkArg(szFullPath != (SZ)NULL && *szFullPath != '\0'
  1527. && *SzLastChar(szFullPath) != '\\', 1, (SZ)NULL);
  1528. for (sz = szFullPath; *sz != '\0'; sz = SzNextChar(sz))
  1529. if (*sz == '\\')
  1530. szSave = sz;
  1531. Assert(szSave != NULL);
  1532. if (*szSave == '\\')
  1533. szSave = SzNextChar(szSave);
  1534. Assert(szSave != NULL && *szSave != '\0');
  1535. return(szSave);
  1536. }
  1537. /*
  1538. ** Purpose:
  1539. ** To find the beginning the beginning of the extension part of the file
  1540. ** name within a string containing a file name (without the preceeding
  1541. ** path name).
  1542. ** Arguments:
  1543. ** szFile: a zero terminated character string containing a valid file
  1544. ** name (without the preceeding path name).
  1545. ** Returns:
  1546. ** an SZ that points to the '.' that begins the extension or '\0' if the
  1547. ** file has no extension.
  1548. **
  1549. **************************************************************************/
  1550. SZ APIENTRY SzFindExt(szFile)
  1551. SZ szFile;
  1552. {
  1553. ChkArg(szFile != (SZ)NULL, 1, (SZ)NULL);
  1554. for ( ; *szFile != '\0' && *szFile != '.'; szFile = SzNextChar(szFile))
  1555. ;
  1556. return(szFile);
  1557. }
  1558. /*
  1559. ** Purpose:
  1560. ** Build full path (check for ROOT and RENAME options)
  1561. ** Arguments:
  1562. ** szPath: non-NULL buffer to fill with full path.
  1563. ** szDst: non-NULL string for szDstDir supplied on script line.
  1564. ** psfd: non-NULL pointer to the Section-File Description structure(SFD).
  1565. ** Assumes:
  1566. ** szPath large enough for result.
  1567. ** Returns:
  1568. ** fTrue if successfully able to create the path, fFalse otherwise.
  1569. **
  1570. **************************************************************************/
  1571. BOOL APIENTRY
  1572. FBuildFullDstPath(
  1573. SZ szPath,
  1574. SZ szDst,
  1575. PSFD psfd,
  1576. BOOL fCompressedName
  1577. )
  1578. {
  1579. SZ szFile;
  1580. SZ szFileDollar = NULL;
  1581. POER poer = &(psfd->oer);
  1582. BOOL bStatus;
  1583. ChkArg(szPath != (SZ)NULL, 1, fFalse);
  1584. ChkArg(szDst != (SZ)NULL && FValidDir(szDst), 2, fFalse);
  1585. ChkArg(psfd != (PSFD)NULL, 3, fFalse);
  1586. if (poer->szDest != NULL) {
  1587. szDst = poer->szDest;
  1588. }
  1589. if (poer->szAppend != NULL) {
  1590. szFile = poer->szAppend;
  1591. }
  1592. else if (poer->szRename != NULL) {
  1593. szFile = poer->szRename;
  1594. }
  1595. else {
  1596. if (poer->oef & oefRoot) {
  1597. szFile = SzFindFileFromPath(psfd->szFile);
  1598. }
  1599. else {
  1600. szFile = psfd->szFile;
  1601. }
  1602. if (!(poer->oef & oefDecompress) && fCompressedName) {
  1603. while ((szFileDollar = SzGetSrcDollar(szFile,'_')) == (SZ)NULL) {
  1604. if (!FHandleOOM(hwndFrame)) {
  1605. return(fFalse);
  1606. }
  1607. }
  1608. szFile = szFileDollar;
  1609. }
  1610. }
  1611. bStatus = FMakePathFromDirAndSubPath(szDst, szFile, szPath, cchpFullPathBuf);
  1612. if ( szFileDollar ) {
  1613. SFree( szFileDollar);
  1614. }
  1615. return(bStatus);
  1616. }
  1617. /*
  1618. ** Purpose:
  1619. ** Build full source path
  1620. ** Arguments:
  1621. ** szPath: non-NULL buffer to store result in.
  1622. ** szDst: non-NULL valid subpath for dest.
  1623. ** szFile: non-NULL file name.
  1624. ** szNetPath: string pointer for netpath to use; NULL to ignore.
  1625. ** Assumes:
  1626. ** szPath large enough for result.
  1627. ** Returns:
  1628. ** fTrue if the path is built correctly, fFalse otherwise.
  1629. **
  1630. **************************************************************************/
  1631. BOOL APIENTRY FBuildFullSrcPath(szPath, szDst, szFile, szNetPath)
  1632. SZ szPath;
  1633. SZ szDst;
  1634. SZ szFile;
  1635. SZ szNetPath;
  1636. {
  1637. CHP szPathTmp[cchpFullPathBuf];
  1638. ChkArg(szPath != (SZ)NULL, 1, fFalse);
  1639. ChkArg(szDst != (SZ)NULL, 2, fFalse);
  1640. ChkArg(szFile != (SZ)NULL, 3, fFalse);
  1641. if (szNetPath == NULL)
  1642. return(FMakePathFromDirAndSubPath(szDst, szFile, szPath,
  1643. cchpFullPathBuf));
  1644. else if (FMakePathFromDirAndSubPath(szDst, szNetPath, szPathTmp,
  1645. cchpFullPathBuf) &&
  1646. FMakePathFromDirAndSubPath(szPathTmp, szFile, szPath,
  1647. cchpFullPathBuf))
  1648. return(fTrue);
  1649. else
  1650. return(fFalse);
  1651. }
  1652. /*
  1653. ** Purpose:
  1654. ** Build full BackupPath
  1655. ** Arguments:
  1656. ** szPath: non-NULL buffer to store result in.
  1657. ** szDst: non-NULL valid subpath for dest.
  1658. ** psfd: non-NULL SFD pointer.
  1659. ** Assumes:
  1660. ** szPath large enough for result.
  1661. ** Returns:
  1662. ** fTrue if successful; fFalse otherwise.
  1663. **
  1664. **************************************************************************/
  1665. BOOL APIENTRY FBuildFullBakPath(szPath, szDst, psfd)
  1666. SZ szPath;
  1667. SZ szDst;
  1668. PSFD psfd;
  1669. {
  1670. SZ sz;
  1671. ChkArg(szPath != (SZ)NULL, 1, fFalse);
  1672. ChkArg(szDst != (SZ)NULL && *szDst != '\0', 2, fFalse);
  1673. ChkArg(psfd != (PSFD)NULL && (psfd->oer).szBackup != NULL, 3, fFalse);
  1674. EvalAssert(szPath == szDst || strcpy(szPath, szDst) == szPath);
  1675. sz = SzFindFileFromPath(szPath);
  1676. Assert(sz != NULL && *sz != '\0');
  1677. if (*((psfd->oer).szBackup) == '*')
  1678. {
  1679. sz = SzFindExt(szPath);
  1680. *sz++ = '.';
  1681. *sz++ = 'B'; /* REVIEW INTL */
  1682. *sz++ = 'A';
  1683. *sz++ = 'K';
  1684. *sz++ = '\0';
  1685. return(fTrue);
  1686. }
  1687. *sz = '\0';
  1688. return(FMakePathFromDirAndSubPath(szPath, (psfd->oer).szBackup, szPath,
  1689. cchpFullPathBuf));
  1690. }
  1691. /*
  1692. ** Purpose:
  1693. ** Verifies given file actually exists.
  1694. ** Arguments:
  1695. ** Returns:
  1696. **
  1697. **************************************************************************/
  1698. BOOL APIENTRY FFileFound(szPath)
  1699. SZ szPath;
  1700. {
  1701. WIN32_FIND_DATA ffd;
  1702. HANDLE SearchHandle;
  1703. ChkArg(szPath != (SZ)NULL &&
  1704. *szPath != '\0', 1, fFalse);
  1705. if ( (SearchHandle = FindFirstFile( szPath, &ffd )) == INVALID_HANDLE_VALUE ) {
  1706. return( fFalse );
  1707. }
  1708. else {
  1709. FindClose( SearchHandle );
  1710. return( fTrue );
  1711. }
  1712. }
  1713. /*
  1714. ** Purpose:
  1715. ** Arguments:
  1716. ** Returns:
  1717. **
  1718. **************************************************************************/
  1719. BOOL APIENTRY FYield(VOID)
  1720. {
  1721. MSG msg;
  1722. BOOL fRet = fTrue;
  1723. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  1724. {
  1725. if (hwndProgressGizmo != NULL
  1726. && IsDialogMessage(hwndProgressGizmo, &msg))
  1727. continue;
  1728. if (msg.message == WM_QUIT)
  1729. fRet = fFalse;
  1730. // if (CheckSpecialKeys(&msg))
  1731. // continue;
  1732. TranslateMessage(&msg);
  1733. DispatchMessage(&msg);
  1734. }
  1735. return(fRet);
  1736. }
  1737. /*
  1738. ** Purpose:
  1739. ** To check and see if the directory specified in szFullPathDst exists.
  1740. ** If not, it will create the directory (including any intermediate
  1741. ** directories). For example if szFullPathDst = "c:\\a\\b\\File" and
  1742. ** none of these directories exist (i.e. a or b) they will all be
  1743. ** created so that the complete path exists (File is not created).
  1744. ** Arguments:
  1745. ** szFullPathDst: The complete pathname (including drive) of the directory
  1746. ** in question.
  1747. ** fCritical: if fTrue success of this operation is required for
  1748. ** success of the setup program as a whole. Setup will be terminated
  1749. ** if fCritical is fTrue and this function fails.
  1750. ** szMsg: The complete pathname (including drive) of the directory
  1751. ** to display in an error. If NULL use szFullPathDst.
  1752. ** Returns:
  1753. ** a YNRC error code (see _filecm.h) indicating the outcome of this
  1754. ** function.
  1755. **
  1756. **************************************************************************/
  1757. YNRC APIENTRY YnrcEnsurePathExists(szFullPathDst, fCritical, szMsg)
  1758. SZ szFullPathDst;
  1759. BOOL fCritical;
  1760. SZ szMsg;
  1761. {
  1762. CHP szTmp[cchpFullPathBuf];
  1763. SZ sz;
  1764. DWORD Attr;
  1765. EERC eerc;
  1766. YNRC ynrc = ynrcYes;
  1767. ChkArg(FValidPath(szFullPathDst),1,ynrcNo);
  1768. if (szMsg == (SZ)NULL) {
  1769. szMsg = szFullPathDst;
  1770. }
  1771. EvalAssert(strcpy((SZ)szTmp, szFullPathDst) ==
  1772. (SZ)szTmp);
  1773. EvalAssert((sz = SzFindFileFromPath(szTmp)) != (SZ)NULL);
  1774. EvalAssert((sz = SzPrevChar(szTmp, sz)) != (SZ)NULL);
  1775. Assert(*sz == '\\');
  1776. *sz = '\0';
  1777. while ( !( ((Attr = GetFileAttributes(szTmp)) != 0xFFFFFFFF && (Attr & FILE_ATTRIBUTE_DIRECTORY ))
  1778. || CreateDirectory( szTmp, NULL )
  1779. )
  1780. ) {
  1781. if ((eerc = EercErrorHandler(hwndFrame, grcCreateDirErr, fCritical,
  1782. szMsg, 0, 0)) != eercRetry) {
  1783. ynrc = (eerc == eercIgnore) ? ynrcErr1 : ynrcNo;
  1784. break;
  1785. }
  1786. }
  1787. return( ynrc );
  1788. }
  1789. int
  1790. DetermineDriveType(
  1791. IN CHAR DriveLetter
  1792. )
  1793. /*++
  1794. Routine Description:
  1795. Determine whether a drive is removable media -- which can be
  1796. a floppy or a CD-ROM. Removeable hard drives are NOT considered
  1797. removeable by this routine.
  1798. Arguments:
  1799. DriveLetter - supplies drive letter of drive to check. If this
  1800. is not a valid alpha char, FALSE is returned.
  1801. Return Value:
  1802. -2 - Drive is a CD-ROM
  1803. -1 - Drive is some other removeable type (such as floppy)
  1804. 0 - Drive is not removeable (or we couldn't tell)
  1805. --*/
  1806. {
  1807. CHAR Name[4];
  1808. UINT DriveType;
  1809. CHAR DevicePath[MAX_PATH];
  1810. Name[0] = DriveLetter;
  1811. Name[1] = ':';
  1812. Name[2] = '\\';
  1813. Name[3] = 0;
  1814. DriveType = GetDriveType(Name);
  1815. if(DriveType == DRIVE_REMOVABLE) {
  1816. Name[2] = 0;
  1817. if(QueryDosDevice(Name,DevicePath,MAX_PATH)) {
  1818. CharUpper(DevicePath);
  1819. if(strstr(DevicePath,"HARDDISK")) {
  1820. DriveType = DRIVE_FIXED;
  1821. }
  1822. }
  1823. }
  1824. if(DriveType == DRIVE_REMOVABLE) {
  1825. return(-1);
  1826. }
  1827. if(DriveType == DRIVE_CDROM) {
  1828. return(-2);
  1829. }
  1830. return(0);
  1831. }
  1832. /*
  1833. ** Purpose:
  1834. ** Arguments:
  1835. ** hInstance: non-NULL instance handle for getting strings from
  1836. ** resources for SwapDisk message Box.
  1837. ** szLabel: non-Null zero-terminated ANSI string to display as the
  1838. ** label of the diskette to prompt for.
  1839. ** szSrcDir: non-Null zero-terminated ANSI string to display as the
  1840. ** drive/directory the user is to insert the diskette into.
  1841. ** Returns:
  1842. **
  1843. **************************************************************************/
  1844. BOOL APIENTRY FPromptForDisk(hInstance, szLabel, szSrcDir)
  1845. HANDLE hInstance;
  1846. SZ szLabel;
  1847. SZ szSrcDir;
  1848. {
  1849. CHAR szTmpText[cchpBufTmpLongMax];
  1850. CHAR rgchBuf[3*cchpFullPathBuf];
  1851. BOOL fRet;
  1852. HWND hwndSav;
  1853. ChkArg(hInstance,1,fFalse);
  1854. ChkArg(szLabel && *szLabel &&
  1855. strlen(szLabel) <= cchpFullPathMax, 2, fFalse);
  1856. ChkArg(szSrcDir &&
  1857. *szSrcDir &&
  1858. strlen(szSrcDir) <= cchpFullPathMax, 3, fFalse);
  1859. EvalAssert(LoadString(hInstance, IDS_INS_DISK, rgchBuf,3*cchpFullPathBuf));
  1860. EvalAssert(SzStrCat(rgchBuf, szLabel) == rgchBuf);
  1861. EvalAssert(LoadString(hInstance, IDS_INTO, szTmpText,
  1862. cchpBufTmpLongMax));
  1863. EvalAssert(SzStrCat(rgchBuf, szTmpText) == rgchBuf);
  1864. EvalAssert(SzStrCat(rgchBuf, szSrcDir) == rgchBuf);
  1865. EvalAssert(LoadString(hInstance, IDS_ERROR, szTmpText,
  1866. cchpBufTmpLongMax));
  1867. hwndSav = GetFocus();
  1868. fRet = (MessageBox(hwndFrame,rgchBuf,szTmpText,MB_OKCANCEL|MB_TASKMODAL) == IDOK);
  1869. SetFocus(hwndSav);
  1870. SendMessage(hwndFrame, WM_NCACTIVATE, 1, 0L);
  1871. return(fRet);
  1872. }
  1873. /*
  1874. ** Purpose:
  1875. ** To rename an active file as an del????.tmp file which will be deleted if
  1876. ** the new file is copied successfully.
  1877. ** Arguments:
  1878. ** szFullPath: Full pathname of active file
  1879. ** Returns:
  1880. ** The name of the renamed file, or NULL if unsuccessful.
  1881. **
  1882. **************************************************************************/
  1883. SZ APIENTRY
  1884. FRenameActiveFile(
  1885. SZ szFullPath
  1886. )
  1887. {
  1888. SZ szTmpName;
  1889. CHP szDir[MAX_PATH];
  1890. SZ sz;
  1891. ChkArg ( szFullPath != NULL, 1, NULL);
  1892. //
  1893. // Try to find a temp filename we can use in the destination directory
  1894. //
  1895. lstrcpy( szDir, szFullPath );
  1896. if( !(sz = strrchr( szDir, '\\')) ) {
  1897. return NULL;
  1898. }
  1899. *sz = '\0';
  1900. if(!(szTmpName = malloc((lstrlen(szDir) + 14) * sizeof(CHP)))) {
  1901. return NULL;
  1902. }
  1903. if(!GetTempFileName( szDir, "del", 0, szTmpName )) {
  1904. goto FileRenameFailed;
  1905. }
  1906. //
  1907. // GetTempFileName creates the temp file. It needs to be deleted
  1908. //
  1909. if (FFileFound(szTmpName) && !FRemoveFile(szTmpName)) {
  1910. goto FileRenameFailed;
  1911. }
  1912. //
  1913. // Rename the original file to this filename
  1914. //
  1915. if( MoveFile( szFullPath, szTmpName ) ) {
  1916. return szTmpName;
  1917. }
  1918. FileRenameFailed:
  1919. free(szTmpName);
  1920. return NULL;
  1921. }
  1922. BOOL
  1923. FGetFileSecurity(
  1924. PCHAR File,
  1925. PSECURITY_DESCRIPTOR *SdBuf,
  1926. CB *SdLen
  1927. )
  1928. {
  1929. #define CBSDBUF 1024
  1930. SECURITY_INFORMATION Si;
  1931. PSECURITY_DESCRIPTOR Sd, SdNew;
  1932. DWORD cbSd = CBSDBUF;
  1933. DWORD cbSdReq;
  1934. BOOL FirstTime = fTrue;
  1935. DWORD dw1, dw2;
  1936. EERC eerc;
  1937. static CHAR Root[MAX_PATH] = "\0";
  1938. static BOOL IsNtfs = FALSE;
  1939. CHAR VolumeFSName[MAX_PATH];
  1940. //
  1941. // Initialize
  1942. //
  1943. *SdBuf = NULL;
  1944. //
  1945. // Check if the volume information is in the cache, if not so get the
  1946. // volume information and put it in the cache
  1947. //
  1948. if( Root[0] == '\0' ) {
  1949. if( !ISUNC( File ) ) {
  1950. strncpy( Root, File, 3 );
  1951. Root[3] = '\0';
  1952. } else {
  1953. PCHAR p;
  1954. ULONG n;
  1955. p = File + 2;
  1956. if( ( ( p = strchr( p, '\\' ) ) == NULL ) ||
  1957. ( ( p = strchr( p + 1, '\\' ) ) == NULL ) ) {
  1958. return( FALSE );
  1959. }
  1960. n = (ULONG)(p - File + 1);
  1961. strncpy( Root, File, n );
  1962. Root[ n ] = '\0';
  1963. }
  1964. while(!GetVolumeInformation( Root, NULL, 0, NULL, &dw1, &dw2, VolumeFSName, MAX_PATH )) {
  1965. if ((eerc = EercErrorHandler(hwndFrame, grcGetVolInfo, FALSE, Root, File, 0)) != eercRetry) {
  1966. return(eerc == eercIgnore);
  1967. }
  1968. }
  1969. IsNtfs = !lstrcmpi( VolumeFSName, "NTFS" );
  1970. }
  1971. if(!IsNtfs) {
  1972. return(TRUE);
  1973. }
  1974. //
  1975. // Allocate memory for the security descriptor
  1976. //
  1977. while ((Sd = SAlloc(cbSd)) == NULL ) {
  1978. if (!FHandleOOM(hwndFrame)) {
  1979. return(fFalse);
  1980. }
  1981. }
  1982. //
  1983. // Get the security information from the source file
  1984. //
  1985. Si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
  1986. while(!GetFileSecurity(File,Si,Sd,cbSd,&cbSdReq)) {
  1987. if( FirstTime && (cbSdReq > cbSd) ) {
  1988. while(!(SdNew = SRealloc(Sd,cbSdReq))) {
  1989. if (!FHandleOOM(hwndFrame)) {
  1990. SFree(Sd);
  1991. return(fFalse);
  1992. }
  1993. }
  1994. cbSd = cbSdReq;
  1995. Sd = SdNew;
  1996. }
  1997. else {
  1998. if ((eerc = EercErrorHandler(hwndFrame, grcGetFileSecurity, FALSE, File, 0, 0)) != eercRetry) {
  1999. SFree(Sd);
  2000. return(eerc == eercIgnore);
  2001. }
  2002. }
  2003. FirstTime = fFalse;
  2004. }
  2005. *SdBuf = Sd;
  2006. *SdLen = cbSd;
  2007. return(TRUE);
  2008. }
  2009. BOOL
  2010. FSetFileSecurity(
  2011. PCHAR File,
  2012. PSECURITY_DESCRIPTOR SdBuf
  2013. )
  2014. {
  2015. EERC eerc;
  2016. SECURITY_INFORMATION Si;
  2017. //
  2018. // Set the Security on the dest file
  2019. //
  2020. Si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
  2021. while(!SetFileSecurity(File, Si, SdBuf)) {
  2022. #if 0
  2023. //
  2024. // BUGBUG - This is to find an error in DaveC's machine
  2025. //
  2026. CHAR DbgBuffer[256];
  2027. ULONG Error;
  2028. Error = GetLastError();
  2029. sprintf( DbgBuffer, "SetFileSecurity() failed. \nFile = %s. \nError = %d \n\nPlease contact JaimeS at x65903", File, Error );
  2030. MessageBox(NULL, DbgBuffer, "Debug Message",
  2031. MB_OK | MB_ICONHAND);
  2032. #endif
  2033. if ((eerc = EercErrorHandler(hwndFrame, grcSetFileSecurity, FALSE, File, 0, 0)) != eercRetry) {
  2034. return(eerc == eercIgnore);
  2035. }
  2036. }
  2037. return(TRUE);
  2038. }
  2039. BOOL
  2040. DoesFileReplaceThirdPartyFile(
  2041. SZ szFullPathDst
  2042. )
  2043. {
  2044. CHAR SetupLogFilePath[ MAX_PATH ];
  2045. PSTR SectionName;
  2046. CHAR ReturnBuffer[512];
  2047. PSTR DefaultString = "";
  2048. PSTR SectionsToSearch[] = {
  2049. "Files.WinNt",
  2050. "Files.SystemPartition"
  2051. };
  2052. ULONG Count;
  2053. BOOL ReplaceThirdParty;
  2054. *SetupLogFilePath = '\0';
  2055. GetWindowsDirectory( SetupLogFilePath, sizeof( SetupLogFilePath ) );
  2056. strcat( SetupLogFilePath, SETUP_REPAIR_DIRECTORY );
  2057. strcat( SetupLogFilePath, SETUP_LOG_FILE );
  2058. for( Count = 0;
  2059. Count < sizeof( SectionsToSearch ) / sizeof( PSTR );
  2060. Count++ ) {
  2061. SectionName = SectionsToSearch[Count];
  2062. *ReturnBuffer = '\0';
  2063. GetPrivateProfileString( SectionName,
  2064. szFullPathDst,
  2065. DefaultString,
  2066. ReturnBuffer,
  2067. sizeof( ReturnBuffer ),
  2068. SetupLogFilePath );
  2069. if( *ReturnBuffer != '\0' ) {
  2070. break;
  2071. }
  2072. }
  2073. ReplaceThirdParty = FALSE;
  2074. if( *ReturnBuffer != 0 ) {
  2075. PSTR SourceFileName;
  2076. PSTR ChkSumString;
  2077. PSTR DirectoryOnSourceDevice;
  2078. PSTR DiskDescription;
  2079. PSTR DiskTag;
  2080. PSTR Delimiters = "\" ,";
  2081. SourceFileName = strtok( ReturnBuffer, Delimiters );
  2082. SourceFileName = strtok( NULL, Delimiters );
  2083. ChkSumString = strtok( NULL, Delimiters );
  2084. DirectoryOnSourceDevice = strtok( NULL, Delimiters );
  2085. DiskDescription = strtok( NULL, Delimiters );
  2086. DiskTag = strtok( NULL, Delimiters );
  2087. if( ( DiskDescription != NULL ) || ( DiskTag != NULL ) ) {
  2088. ReplaceThirdParty = TRUE;
  2089. }
  2090. }
  2091. return( ReplaceThirdParty );
  2092. }