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.

1070 lines
32 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. COPYFILE.C
  5. Abstract:
  6. file copy conf. dialog
  7. Author:
  8. Bob Watson (a-robw)
  9. Revision History:
  10. 17 Feb 94 Written
  11. --*/
  12. //
  13. // Windows Include Files
  14. //
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <malloc.h>
  18. #include <tchar.h> // unicode macros
  19. //
  20. // app include files
  21. //
  22. #include "otnboot.h"
  23. #include "otnbtdlg.h"
  24. //
  25. // Debugging defines
  26. //
  27. #define SHOW_DEBUG_INFO 0
  28. // local windows message
  29. #define NCDU_START_FILE_COPY (WM_USER +101)
  30. //
  31. // Static data for this module
  32. //
  33. static BOOL bCopying; // 1= copying, 0 = done
  34. static DWORD dwBytesCopied; // running total of bytes copied
  35. static DWORD dwTotalCBytes; // total bytes divided by 100 (for % computation)
  36. static DWORD dwCurrentPercent; // current percent copied
  37. #define MAX_DOS_FILENAME_LENGTH (8 * sizeof(TCHAR))
  38. #define MAX_DOS_FILE_EXT_LENGTH (3 * sizeof(TCHAR))
  39. static
  40. BOOL
  41. DisplayScrunchedFilePath (
  42. IN HWND hWnd,
  43. IN LPCTSTR szInPath
  44. )
  45. /*++
  46. Routine Description:
  47. sets the window text of hWnd to be the "scrunched" version of
  48. the path string in szInPath. If the path string is too long
  49. to fit in a single line of hWnd, then directories are removed
  50. from the path until it does fit. The directories are removed
  51. from the "top" down. The root drive\dir is kept as is the
  52. filename and as many directories that will fit.
  53. Arguments:
  54. IN HWND hWnd
  55. handle of window to put text in
  56. IN LPCTSTR szInPath
  57. path to display in window
  58. Return Value:
  59. TRUE if no error
  60. FALSE if error
  61. --*/
  62. {
  63. LPTSTR szOutPath;
  64. RECT rWindow;
  65. LONG lWindowWidth;
  66. HDC hDC;
  67. SIZE sText;
  68. LONG lRootBs, lRootBsCount;
  69. LPTSTR szRootBs, szFileBs, szSrc, szDest, szDotsBs;
  70. GetWindowRect (hWnd, &rWindow); // get window size
  71. lWindowWidth = rWindow.right - rWindow.left;
  72. hDC = GetDC (hWnd); // get DC for window
  73. szOutPath = GlobalAlloc (GPTR, ((lstrlen(szInPath) + 8) * sizeof(TCHAR)));
  74. if (szOutPath == NULL) {
  75. return FALSE;
  76. } else {
  77. //buffer allocation succeeded, so copy path to local buffer
  78. lstrcpy (szOutPath, szInPath);
  79. }
  80. if (IsUncPath(szOutPath)) {
  81. lRootBs = 4; // the 4th backslash is the "Root" backslash for UNC
  82. } else {
  83. lRootBs = 1; // for DOS file paths, the 1st backslash is the Root
  84. }
  85. GetTextExtentPoint32(hDC,
  86. szOutPath, lstrlen(szOutPath), &sText);
  87. szSrc = szDest = szOutPath;
  88. szDotsBs = szRootBs = szFileBs = NULL;
  89. lRootBsCount = 0;
  90. while (sText.cx > lWindowWidth) {
  91. // take dirs out until it fits
  92. // go through path string
  93. while (*szSrc != 0) {
  94. // see if we've passed the root
  95. if (szRootBs == NULL) {
  96. if (*szSrc == cBackslash) lRootBsCount++;
  97. if (lRootBsCount == lRootBs) szDotsBs = szRootBs = szDest;
  98. } else {
  99. // root's done, now were; working on the pathname
  100. // so we'll scope out the rest of the string
  101. if (*szSrc == cBackslash) szFileBs = szDest;
  102. }
  103. *szDest++ = *szSrc++;
  104. }
  105. if (szRootBs == NULL) {
  106. // then this is a bogus path so exit now
  107. break;
  108. }
  109. if (szFileBs == NULL) {
  110. // if the File backslash didn't get defined, then the file is
  111. // in the root directory and we should leave now, since there
  112. // isn't much to do about it.
  113. szFileBs = szRootBs;
  114. break;
  115. }
  116. // now yank a dir or two (more than one will be pulled if the dir
  117. // name is < 4 chars
  118. // if a directory hasn't been pulled, yet, go ahead
  119. // and take one out
  120. // initialize the pointers
  121. if (szRootBs == szDotsBs) {
  122. // then the ... havent been added so see if they'll fit and add em
  123. if ((szDotsBs+4) < szFileBs) {
  124. // they'll fit so addem
  125. szDest = szDotsBs + 1;
  126. *szDest++ = cPeriod;
  127. *szDest++ = cPeriod;
  128. *szDest++ = cPeriod;
  129. *szDest = cBackslash;
  130. szDotsBs = szDest;
  131. szSrc = ++szDest;
  132. } else {
  133. // no room to left to pull files
  134. break;
  135. }
  136. } else {
  137. // dot's have already been added so set pointers
  138. szSrc = szDest = szDotsBs+1;
  139. }
  140. // go to next dir
  141. while (*szSrc++ != cBackslash);
  142. // copy the rest of the string
  143. while (*szSrc != 0) *szDest++ = *szSrc++;
  144. *szDest = 0; // terminate the new string
  145. // get size of new string
  146. GetTextExtentPoint32(hDC,
  147. szOutPath, lstrlen(szOutPath), &sText);
  148. }
  149. // the string is as small as it's going to get so set the window text
  150. SetWindowText (hWnd, szOutPath);
  151. FREE_IF_ALLOC (szOutPath);
  152. return TRUE;
  153. }
  154. LONG
  155. CreateDirectoryFromPath (
  156. IN LPCTSTR szPath,
  157. IN LPSECURITY_ATTRIBUTES lpSA
  158. )
  159. /*++
  160. Routine Description:
  161. Creates the directory specified in szPath and any other "higher"
  162. directories in the specified path that don't exist.
  163. Arguments:
  164. IN LPCTSTR szPath
  165. directory path to create (assumed to be a DOS path, not a UNC)
  166. IN LPSECURITY_ATTRIBUTES lpSA
  167. pointer to security attributes argument used by CreateDirectory
  168. Return Value:
  169. TRUE if directory(ies) created
  170. FALSE if error (GetLastError to find out why)
  171. --*/
  172. {
  173. LPTSTR szLocalPath;
  174. LPTSTR szEnd;
  175. LONG lReturn = 0L;
  176. szLocalPath = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
  177. if (szLocalPath == NULL) {
  178. SetLastError (ERROR_OUTOFMEMORY);
  179. return FALSE;
  180. } else {
  181. // so far so good...
  182. SetLastError (ERROR_SUCCESS); // initialize error value to SUCCESS
  183. }
  184. lstrcpy (szLocalPath, szPath);
  185. szEnd = &szLocalPath[3];
  186. if (*szEnd != 0) {
  187. // then there are sub dirs to create
  188. while (*szEnd != 0) {
  189. // go to next backslash
  190. while ((*szEnd != cBackslash) && (*szEnd != 0)) szEnd++;
  191. if (*szEnd == cBackslash) {
  192. // terminate path here and create directory
  193. *szEnd = 0;
  194. if (!CreateDirectory (szLocalPath, lpSA)) {
  195. // see what the error was and "adjust" it if necessary
  196. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  197. // this is OK
  198. SetLastError (ERROR_SUCCESS);
  199. } else {
  200. lReturn = 0;
  201. }
  202. } else {
  203. // directory created successfully so update count
  204. lReturn++;
  205. }
  206. // replace backslash and go to next dir
  207. *szEnd++ = cBackslash;
  208. }
  209. }
  210. // create last dir in path now
  211. if (!CreateDirectory (szLocalPath, lpSA)) {
  212. // see what the error was and "adjust" it if necessary
  213. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  214. // this is OK
  215. SetLastError (ERROR_SUCCESS);
  216. lReturn++;
  217. } else {
  218. lReturn = 0;
  219. }
  220. } else {
  221. // directory created successfully
  222. lReturn++;
  223. }
  224. } else {
  225. #ifndef TERMSRV
  226. // else this is a root dir only so return success.
  227. lReturn = 1;
  228. #else // TERMSRV
  229. // for terminal server return FALSE.
  230. lReturn = 0;
  231. #endif // TERMSRV
  232. }
  233. FREE_IF_ALLOC (szLocalPath);
  234. return lReturn;
  235. }
  236. static
  237. DWORD
  238. UpdatePercentComplete (
  239. IN HWND hwndDlg,
  240. IN LPCTSTR szFileName
  241. )
  242. /*++
  243. Routine Description:
  244. Adds the size of the specified file to the running total of
  245. bytes copied and computes the current percentage of total
  246. copied. The display string is updated if the new percentage is
  247. different from the current percentage
  248. Arguments:
  249. IN HWND hwndDlg
  250. Handle to dialog Box window
  251. IN LPTSTR szFileName
  252. filename (& path) of file whose size should be added to the
  253. current total bytes copied value.
  254. Return Value:
  255. returns the current percentage of total bytes that have been
  256. copied (including this file)
  257. --*/
  258. {
  259. HANDLE hFile;
  260. DWORD dwFileSizeLow, dwFileSizeHigh;
  261. DWORD dwPercent = 0;
  262. LPTSTR szOutBuff;
  263. szOutBuff = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
  264. if (szOutBuff == NULL) return 0;
  265. if (dwTotalCBytes == 0) {
  266. SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE,
  267. GetStringResource (FMT_WORKING));
  268. dwPercent = 0;
  269. } else {
  270. hFile = CreateFile (
  271. szFileName,
  272. GENERIC_READ,
  273. (FILE_SHARE_READ | FILE_SHARE_WRITE),
  274. NULL,
  275. OPEN_EXISTING,
  276. FILE_ATTRIBUTE_NORMAL,
  277. NULL);
  278. if (hFile != INVALID_HANDLE_VALUE) {
  279. dwFileSizeLow = GetFileSize (hFile, &dwFileSizeHigh);
  280. if (dwFileSizeLow != 0xFFFFFFFF) {
  281. dwBytesCopied += dwFileSizeLow;
  282. dwPercent = dwBytesCopied / dwTotalCBytes;
  283. if (dwPercent != dwCurrentPercent) {
  284. if (dwPercent > 100) dwPercent = 100;
  285. dwCurrentPercent = dwPercent;
  286. _stprintf (szOutBuff,
  287. GetStringResource (FMT_PERCENT_COMPLETE),
  288. dwPercent);
  289. SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE, szOutBuff);
  290. }
  291. }
  292. CloseHandle (hFile);
  293. }
  294. }
  295. FREE_IF_ALLOC (szOutBuff);
  296. return dwPercent;
  297. }
  298. static
  299. BOOL
  300. IsDosFileName (
  301. LPCTSTR szName
  302. )
  303. /*++
  304. Routine Description:
  305. examines string to see if it conforms to the DOS filename length
  306. conventions
  307. Arguments:
  308. szName filename and extension to parse
  309. Return Value:
  310. TRUE if it passes
  311. FALSE if not
  312. --*/
  313. {
  314. LPTSTR szNameBegin, szNameEnd;
  315. LPTSTR szExtBegin, szExtEnd;
  316. LPTSTR szDot;
  317. LPTSTR szTmp;
  318. LPTSTR szBack_slash;
  319. szBack_slash = szDot = NULL;
  320. szTmp = (LPTSTR)szName;
  321. while (*szTmp) {
  322. if (*szTmp == '.') szDot = szTmp;
  323. if (*szTmp == '\\') szBack_slash = szTmp;
  324. szTmp++;
  325. }
  326. // find beginning and end of each component
  327. if (szBack_slash) {
  328. // backslash char found in string, pointer points to
  329. // last occurance, name starts immediately after
  330. szNameBegin = szBack_slash + 1;
  331. } else {
  332. // no backslash char found so name starts at beginning
  333. // of string
  334. szNameBegin = (LPTSTR)szName;
  335. }
  336. if (szDot) {
  337. // dot char found in string
  338. if (szDot == szName) {
  339. // it's the first char in the string (i.e.
  340. // no filename)
  341. szNameEnd = (LPTSTR)szName;
  342. // a dot was found, then the extension starts right
  343. // after the dot
  344. szExtBegin = szDot + 1;
  345. } else if (szDot < szNameBegin) {
  346. // then there's no dot in the filename, but
  347. // it's somewhere else in the path
  348. szNameEnd = szTmp;
  349. // no dot so ext "begins" at the end of the string
  350. szExtBegin = szTmp;
  351. } else {
  352. // not the first char, and not before the filename
  353. // so the name ends with the dot
  354. szNameEnd = szDot;
  355. // a dot was found, then the extension starts right
  356. // after the dot
  357. szExtBegin = szDot + 1;
  358. }
  359. } else {
  360. // no dot was found in the string so there's no
  361. // file extension in this string. The end of the string
  362. // must be the end of the file name , and the beginning of
  363. // the extension (and also the end of the extension)
  364. szNameEnd = szTmp;
  365. szExtBegin = szTmp;
  366. }
  367. // the end of the file extension is always the end of the string
  368. szExtEnd = szTmp;
  369. // check the components for correct length:
  370. // 0 <= filename <= MAX_DOS_FILENAME_LENGTH (8)
  371. // 0 <= ext <= MAX_DOS_FILE_EXT_LENGTH (3)
  372. if ((LONG)(szNameEnd-szNameBegin) <= MAX_DOS_FILENAME_LENGTH) {
  373. // name is ok, check extension
  374. if ((LONG)(szExtEnd-szExtBegin) <= MAX_DOS_FILE_EXT_LENGTH) {
  375. return TRUE;
  376. } else {
  377. return FALSE;
  378. }
  379. } else {
  380. return FALSE;
  381. }
  382. }
  383. static
  384. LONG
  385. CopyDir (
  386. IN HWND hwndDlg,
  387. IN LPCTSTR szFromDir,
  388. IN LPCTSTR szToDir,
  389. IN DWORD dwFlags,
  390. IN PDWORD pdwFiles,
  391. IN PDWORD pdwDirs
  392. )
  393. /*++
  394. Routine Description:
  395. Copies all files in the specified from directory to the specified
  396. to directory. Specific behavior is controlled by the flags as
  397. documented below.
  398. Arguments:
  399. hwndDlg window handle to dialog box
  400. szFromDir directory containing files to copy
  401. szToDir directory to recieve files
  402. dwFlags Flags that control routine's behavior
  403. CD_FLAGS_COPY_SUB_DIR copies all sub dir's as well
  404. CD_FLAGS_DONT_CREATE default is to create dirs as needed
  405. CD_FLAGS_IGNORE_ATTR ignore attributes
  406. CD_FLAGS_COPY_ATTR copy attributes as well (default
  407. is for dest fils to be normal)
  408. CD_FLAGS_IGNORE_ERROR continue with copy even if errors occur
  409. CD_FLAGS_LONG_NAMES allows filenames longer than FAT
  410. other bits are ignored
  411. pdwFiles Pointer to DWORD that will get count of files copied
  412. pdwDirs Pointer to DWORD that will get count of dirs created
  413. Return Value:
  414. Win 32 status value
  415. ERROR_SUCCESS routine completed normally
  416. --*/
  417. {
  418. LPTSTR szFromPathName; // full path of FromDir
  419. LPTSTR szFromFileName; // full path of source file
  420. LPTSTR szFromFileStart; // pointer to where to attach file name to path
  421. LPTSTR szSearchName; // search file name
  422. LPTSTR szToPathName; // full path of destdir
  423. LPTSTR szToFileName; // full path of detination file name
  424. LPTSTR szToFileStart; // pointer to where to attach file name to path
  425. DWORD dwFileAttributes; // attributes of source file
  426. PWIN32_FIND_DATA pwfdSearchData; // buffer used for file find ops
  427. HANDLE hSearch;
  428. int nMbResult;
  429. BOOL bStatus;
  430. LONG lStatus;
  431. MSG msg;
  432. DWORD dwFileCopyCount; // local counter variables
  433. DWORD dwDirCreateCount;
  434. // allocate buffers
  435. szFromPathName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
  436. szFromFileName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
  437. szSearchName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
  438. szToPathName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
  439. szToFileName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
  440. pwfdSearchData = (PWIN32_FIND_DATA)GlobalAlloc (GPTR, sizeof(WIN32_FIND_DATA));
  441. if (szFromPathName &&
  442. szFromFileName &&
  443. szSearchName &&
  444. szToPathName &&
  445. szToFileName &&
  446. pwfdSearchData) {
  447. // initialize counter fields (to support recursive calls)
  448. if (pdwFiles != NULL) {
  449. dwFileCopyCount = *pdwFiles;
  450. } else {
  451. dwFileCopyCount = 0;
  452. }
  453. if (pdwDirs != NULL) {
  454. dwDirCreateCount = *pdwDirs;
  455. } else {
  456. dwDirCreateCount = 0;
  457. }
  458. // get full pathnames of from & to files
  459. GetFullPathName (
  460. szFromDir,
  461. (DWORD)GlobalSize(szFromPathName) / sizeof(TCHAR),
  462. szFromPathName,
  463. NULL);
  464. GetFullPathName (
  465. szToDir,
  466. (DWORD)GlobalSize(szToPathName) / sizeof(TCHAR),
  467. szToPathName,
  468. NULL);
  469. lStatus = ERROR_SUCCESS;
  470. } else {
  471. lStatus = ERROR_OUTOFMEMORY;
  472. }
  473. if (lStatus == ERROR_SUCCESS) {
  474. // validate from dir and create target if valid
  475. dwFileAttributes = QuietGetFileAttributes (
  476. szFromPathName);
  477. if ((dwFileAttributes != 0xFFFFFFFF) &&
  478. (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  479. // from directory is for real so create or check
  480. // target dir now
  481. if (dwFlags & CD_FLAGS_DONT_CREATE) {
  482. // if don't create, then at least validate
  483. dwFileAttributes = QuietGetFileAttributes (
  484. szToPathName);
  485. if ((dwFileAttributes != 0xFFFFFFFF) &&
  486. (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  487. lStatus = ERROR_SUCCESS;
  488. } else {
  489. lStatus = ERROR_DIRECTORY;
  490. }
  491. } else {
  492. // create sub dirs if necessary
  493. if (!(dwFlags & CD_FLAGS_LONG_NAMES)) {
  494. // check to see if name conforms to DOS 8.3 format
  495. if (!IsDosFileName(szFromPathName)) {
  496. lStatus = ERROR_FILENAME_EXCED_RANGE;
  497. } else {
  498. lStatus = ERROR_SUCCESS;
  499. }
  500. } else {
  501. lStatus = ERROR_SUCCESS;
  502. }
  503. if (lStatus == ERROR_SUCCESS) {
  504. lStatus = CreateDirectoryFromPath (
  505. szToPathName, NULL);
  506. if (lStatus == 0) {
  507. lStatus = GetLastError();
  508. if (lStatus == ERROR_ALREADY_EXISTS) {
  509. // this is OK
  510. lStatus = ERROR_SUCCESS;
  511. // no dirs were created so don't change the
  512. // count.
  513. }
  514. } else {
  515. // if lStatus is not 0, then it's then number of
  516. // directories that were created
  517. dwDirCreateCount += lStatus;
  518. // now set it to the Error Status value the rest of the function
  519. // is expecting
  520. lStatus = ERROR_SUCCESS;
  521. }
  522. }
  523. }
  524. } else {
  525. lStatus = ERROR_DIRECTORY;
  526. }
  527. }
  528. if (lStatus == ERROR_SUCCESS) {
  529. // if target directory is valid, then
  530. // create filename bases and start copying files
  531. lstrcpy (szFromFileName, szFromPathName);
  532. if (szFromFileName[lstrlen(szFromFileName)-1] != cBackslash) lstrcat (szFromFileName, cszBackslash);
  533. szFromFileStart = szFromFileName + lstrlen(szFromFileName);
  534. lstrcpy (szToFileName, szToPathName);
  535. if (szToFileName[lstrlen(szToFileName)-1] != cBackslash) lstrcat (szToFileName, cszBackslash);
  536. szToFileStart = szToFileName + lstrlen(szToFileName);
  537. // create search name
  538. lstrcpy (szSearchName, szFromPathName);
  539. lstrcat (szSearchName, cszWildcardFile);
  540. hSearch = FindFirstFile (
  541. szSearchName,
  542. pwfdSearchData);
  543. if (hSearch != INVALID_HANDLE_VALUE) {
  544. lStatus = ERROR_SUCCESS;
  545. bStatus = TRUE;
  546. while (((lStatus == ERROR_SUCCESS) && bStatus) && bCopying) {
  547. // check & save file attributes of each file, if not
  548. // normal, then ignore unless flag set
  549. //
  550. lstrcpy (szFromFileStart, pwfdSearchData->cFileName); //make full path
  551. if (!DotOrDotDotDir(pwfdSearchData->cFileName)) { //ignore these dirs
  552. dwFileAttributes = QuietGetFileAttributes(
  553. szFromFileName);
  554. if (dwFileAttributes != 0xFFFFFFFF) {
  555. // attributes are valid, so
  556. // make full pathname of source file found
  557. // and dest. file to be created
  558. lstrcpy (szToFileStart, pwfdSearchData->cFileName); //make full path
  559. if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  560. // if it's a dir and subdirs is true, then
  561. // copy them too if the copy sub dir flag is set
  562. if (dwFlags & CD_FLAGS_COPY_SUB_DIR) {
  563. lStatus = CopyDir (
  564. hwndDlg,
  565. szFromFileName,
  566. szToFileName,
  567. dwFlags,
  568. &dwFileCopyCount,
  569. &dwDirCreateCount);
  570. } else {
  571. // ignore directories if flag not set
  572. }
  573. } else { // not a dir, so see if we can copy it
  574. if (lStatus == ERROR_SUCCESS) {
  575. // copy the file if either the ignore bit is
  576. // set or the attributes are OK
  577. //
  578. if (!(dwFlags & CD_FLAGS_LONG_NAMES)) {
  579. // check to see if name conforms to DOS 8.3 format
  580. if (!IsDosFileName(szFromFileName)) {
  581. lStatus = ERROR_FILENAME_EXCED_RANGE;
  582. } else {
  583. lStatus = ERROR_SUCCESS;
  584. }
  585. }
  586. DisplayScrunchedFilePath (
  587. GetDlgItem (hwndDlg, NCDU_FROM_PATH),
  588. (LPCTSTR)_tcslwr(szFromFileName));
  589. DisplayScrunchedFilePath (
  590. GetDlgItem (hwndDlg, NCDU_TO_PATH),
  591. (LPCTSTR)_tcslwr(szToFileName));
  592. if (lStatus == ERROR_SUCCESS) {
  593. bStatus = CopyFile(
  594. szFromFileName,
  595. szToFileName,
  596. FALSE); // overwrite existing file
  597. //verify file was created
  598. if (bStatus) {
  599. if (QuietGetFileAttributes(szToFileName) == 0xFFFFFFFF) {
  600. // unable to read attributes of created file
  601. // so return error
  602. lStatus = ERROR_CANNOT_MAKE;
  603. }
  604. } else {
  605. // get copy error
  606. lStatus = BOOL_TO_STATUS (bStatus);
  607. }
  608. }
  609. // if copy successful reset source file attributes
  610. // and optionally destination file attributes
  611. if (lStatus == ERROR_SUCCESS) {
  612. // set file attributes to NORMAL
  613. SetFileAttributes (
  614. szToFileName,
  615. FILE_ATTRIBUTE_NORMAL);
  616. // update filesize
  617. UpdatePercentComplete(hwndDlg, szFromFileName);
  618. // update count
  619. dwFileCopyCount++;
  620. } else {
  621. // bail out here since there was a copy error
  622. nMbResult = MessageBox (
  623. hwndDlg,
  624. GetStringResource (CSZ_UNABLE_COPY),
  625. szFromFileName,
  626. MB_OKCANCEL_TASK_EXCL);
  627. if (nMbResult == IDCANCEL) {
  628. bCopying = FALSE;
  629. }
  630. // the error has already been handled so return
  631. // success to prevent the calling routine from
  632. // signalling this error
  633. lStatus = ERROR_SUCCESS;
  634. }
  635. // check for messages
  636. while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
  637. TranslateMessage (&msg);
  638. DispatchMessage (&msg);
  639. }
  640. }
  641. }
  642. } else {
  643. lStatus = GetLastError();
  644. }
  645. }
  646. if (dwFlags & CD_FLAGS_IGNORE_ERROR) {
  647. // if ignore error, then set to success
  648. lStatus = ERROR_SUCCESS;
  649. }
  650. if (lStatus == ERROR_SUCCESS) {
  651. bStatus = FindNextFile (
  652. hSearch,
  653. pwfdSearchData);
  654. } else {
  655. bStatus = FALSE; // abort loop
  656. }
  657. } // end while files in dir
  658. FindClose (hSearch);
  659. } else {
  660. // invalid find handle so return error
  661. lStatus = GetLastError();
  662. }
  663. } // end of valid directory block
  664. FREE_IF_ALLOC(szFromPathName);
  665. FREE_IF_ALLOC(szFromFileName);
  666. FREE_IF_ALLOC(szSearchName);
  667. FREE_IF_ALLOC(szToPathName);
  668. FREE_IF_ALLOC(szToFileName);
  669. FREE_IF_ALLOC(pwfdSearchData);
  670. // set the counter fields if they were passed in
  671. if (pdwFiles != NULL) {
  672. *pdwFiles = dwFileCopyCount;
  673. }
  674. if (pdwDirs != NULL) {
  675. *pdwDirs = dwDirCreateCount;
  676. }
  677. return lStatus;
  678. }
  679. static
  680. BOOL
  681. CopyFileDlg_NCDU_START_FILE_COPY (
  682. IN HWND hwndDlg,
  683. IN WPARAM wParam,
  684. IN LPARAM lParam
  685. )
  686. /*++
  687. Routine Description:
  688. Formats values from Dialog Box parameter structure to argument list of
  689. copy directory function
  690. Arguments:
  691. IN HWND hwndDlg
  692. handle to dialog box window
  693. IN WPARAM wParam
  694. Not Used
  695. IN LPARAM lParam
  696. address of copy file structure.
  697. Return Value:
  698. FALSE, always
  699. --*/
  700. {
  701. PCF_DLG_DATA pCF;
  702. pCF = (PCF_DLG_DATA)lParam;
  703. #if SHOW_DEBUG_INFO
  704. // debug message box
  705. {
  706. LPTSTR szMessageBuffer;
  707. DWORD dwSourceAttr, dwDestAttr;
  708. UINT nMbReturn;
  709. szMessageBuffer = GlobalAlloc (GPTR, SMALL_BUFFER_SIZE);
  710. if (szMessageBuffer != NULL) {
  711. dwSourceAttr = QuietGetFileAttributes (pCF->szSourceDir);
  712. dwDestAttr = QuietGetFileAttributes (pCF->szDestDir);
  713. _stprintf (szMessageBuffer,
  714. fmtPrepareToCopy,
  715. pCF->szDisplayName,
  716. pCF->szSourceDir, dwSourceAttr,
  717. pCF->szDestDir, dwDestAttr,
  718. pCF->dwCopyFlags);
  719. nMbReturn = MessageBox (hwndDlg,
  720. szMessageBuffer,
  721. cszDebug,
  722. MB_OKCANCEL_TASK_INFO);
  723. FREE_IF_ALLOC (szMessageBuffer);
  724. } else {
  725. nMbReturn = IDOK;
  726. }
  727. if (nMbReturn == IDCANCEL) {
  728. // then bail here
  729. EndDialog (hwndDlg, IDCANCEL);
  730. return TRUE;
  731. }
  732. }
  733. #endif
  734. if (CopyDir (
  735. hwndDlg,
  736. pCF->szSourceDir,
  737. pCF->szDestDir,
  738. pCF->dwCopyFlags,
  739. &pCF->dwFilesCopied,
  740. &pCF->dwDirsCreated) != ERROR_SUCCESS) {
  741. // display error message
  742. DisplayMessageBox (
  743. hwndDlg,
  744. CSZ_COPY_ERROR,
  745. 0L,
  746. MB_OK_TASK_EXCL);
  747. bCopying = FALSE; // to indicate error or non-completion
  748. }
  749. EndDialog (hwndDlg, (bCopying ? IDOK : IDCANCEL));
  750. return TRUE;
  751. }
  752. static
  753. BOOL
  754. CopyFileDlg_WM_INITDIALOG (
  755. IN HWND hwndDlg,
  756. IN WPARAM wParam,
  757. IN LPARAM lParam
  758. )
  759. /*++
  760. Routine Description:
  761. Dialog box initialization routine.
  762. Arguments:
  763. IN HWND hwndDlg
  764. Handle to dialog box window
  765. IN WPARAM wParam
  766. not used
  767. IN LPARAM lParam
  768. address of Copy file data structure passed by calling routine.
  769. Return Value:
  770. FALSE if valid param block address
  771. TRUE if not
  772. --*/
  773. {
  774. PCF_DLG_DATA pCF;
  775. pCF = (PCF_DLG_DATA)lParam;
  776. if (pCF != NULL) {
  777. // intialize Global data
  778. bCopying = TRUE;
  779. dwBytesCopied = 0;
  780. dwCurrentPercent = 0;
  781. dwTotalCBytes = (pCF->dwTotalSize + 50) / 100;
  782. PositionWindow (hwndDlg);
  783. SetDlgItemText (hwndDlg, NCDU_COPY_APPNAME, pCF->szDisplayName);
  784. SetDlgItemText (hwndDlg, NCDU_FROM_PATH, cszEmptyString);
  785. SetDlgItemText (hwndDlg, NCDU_TO_PATH, cszEmptyString);
  786. SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE,
  787. GetStringResource (FMT_ZERO_PERCENT_COMPLETE));
  788. SetFocus (GetDlgItem(hwndDlg, IDCANCEL));
  789. // start copying files
  790. PostMessage (hwndDlg, NCDU_START_FILE_COPY, 0, lParam);
  791. return FALSE;
  792. } else {
  793. // illegal parameter
  794. EndDialog (hwndDlg, IDCANCEL);
  795. return TRUE;
  796. }
  797. }
  798. static
  799. BOOL
  800. CopyFileDlg_WM_COMMAND (
  801. IN HWND hwndDlg,
  802. IN WPARAM wParam,
  803. IN LPARAM lParam
  804. )
  805. /*++
  806. Routine Description:
  807. Processes WM_COMMAND messages to dialog box.
  808. Only IDCANCEL button is processed here (ceasing copy function)
  809. all other button commands are ignored (since there aren't any)
  810. Arguments:
  811. IN HWND hwndDlg
  812. handle to dialog box window
  813. IN WPARAM wParam
  814. LOWORD has the id of the control that issued the message
  815. IN LPARAM lParam
  816. Not used.
  817. Return Value:
  818. if button is IDCANCEL, then FALSE
  819. otherwise TRUE (i.e. not processed.)
  820. --*/
  821. {
  822. switch (LOWORD(wParam)) {
  823. case IDCANCEL:
  824. switch (HIWORD(wParam)) {
  825. case BN_CLICKED:
  826. if (DisplayMessageBox(hwndDlg,
  827. NCDU_RU_SURE, 0,
  828. MB_OKCANCEL_TASK_EXCL_DEF2) == IDOK) {
  829. bCopying = FALSE;
  830. }
  831. return TRUE;
  832. default:
  833. return FALSE;
  834. }
  835. default: return FALSE;
  836. }
  837. }
  838. INT_PTR CALLBACK
  839. CopyFileDlgProc (
  840. IN HWND hwndDlg,
  841. IN UINT message,
  842. IN WPARAM wParam,
  843. IN LPARAM lParam
  844. )
  845. /*++
  846. Routine Description:
  847. Main Dialog box window proc. Processes the following windows messages:
  848. WM_INITDIALOG: dialog box initialization procedure
  849. WM_COMMAND: windows messages (resulting from user commands)
  850. NCDU_START_FILE_COPY: local message to begin copying files
  851. all other messages are processed by the DefDialogProc
  852. Arguments:
  853. Standard WNDPROC arguments
  854. Return Value:
  855. FALSE if not processed, otherwise value returned by
  856. called routine.
  857. --*/
  858. {
  859. switch (message) {
  860. case WM_INITDIALOG: return (CopyFileDlg_WM_INITDIALOG (hwndDlg, wParam, lParam));
  861. case WM_COMMAND: return (CopyFileDlg_WM_COMMAND (hwndDlg, wParam, lParam));
  862. case NCDU_START_FILE_COPY: return (CopyFileDlg_NCDU_START_FILE_COPY (hwndDlg, wParam, lParam));
  863. default: return FALSE;
  864. }
  865. }