Leaked source code of windows server 2003
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.

1101 lines
32 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // copyfile.c
  8. //
  9. // Description:
  10. // This file has the dlgproc for the copy files page.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "pch.h"
  14. #include "resource.h"
  15. #define DAYS_IN_A_WEEK 7
  16. #define MONTHS_IN_A_YEAR 12
  17. //
  18. // This struct and is used to pack the input args passed to the tree
  19. // copy thread.
  20. //
  21. typedef struct {
  22. TCHAR lpSourceBuffer[MAX_PATH];
  23. TCHAR lpDestBuffer[MAX_PATH];
  24. HWND hwnd;
  25. } COPY_THREAD_PARAMS;
  26. //
  27. // String constants loaded from resource
  28. //
  29. static TCHAR *StrBuildingList;
  30. static TCHAR *StrCopyingFiles;
  31. static TCHAR *StrFileAlreadyExists;
  32. static TCHAR *StrModified;
  33. static TCHAR *StrBytes;
  34. static TCHAR *StrJanuary;
  35. static TCHAR *StrFebruary;
  36. static TCHAR *StrMarch;
  37. static TCHAR *StrApril;
  38. static TCHAR *StrMay;
  39. static TCHAR *StrJune;
  40. static TCHAR *StrJuly;
  41. static TCHAR *StrAugust;
  42. static TCHAR *StrSeptember;
  43. static TCHAR *StrOctober;
  44. static TCHAR *StrNovember;
  45. static TCHAR *StrDecember;
  46. static TCHAR *StrSunday;
  47. static TCHAR *StrMonday;
  48. static TCHAR *StrTuesday;
  49. static TCHAR *StrWednesday;
  50. static TCHAR *StrThursday;
  51. static TCHAR *StrFriday;
  52. static TCHAR *StrSaturday;
  53. static TCHAR *rgMonthsOfYear[MONTHS_IN_A_YEAR];
  54. static TCHAR *rgDaysOfWeek[DAYS_IN_A_WEEK + 1];
  55. //
  56. // Messages for the dialog procedure
  57. //
  58. #define WMX_BEGINCOPYING (WM_USER+1)
  59. #define WMX_FILECOPIED (WM_USER+2)
  60. #define WMX_ENDCOPYING (WM_USER+3)
  61. //
  62. // Global counters
  63. //
  64. HDSKSPC ghDiskSpaceList;
  65. int gnFilesCopied = 0;
  66. int gnTotalFiles = 0;
  67. //
  68. // Misc constants
  69. //
  70. #define ONE_MEG ( 1024 * 1024 )
  71. //
  72. // Confirm File replace constants
  73. //
  74. #define YES 1
  75. #define YESTOALL 2
  76. #define NO 3
  77. #define NOTOALL 4
  78. #define CANCEL 5
  79. #define MAX_DAY_OF_WEEK_LEN 64
  80. #define MAX_MONTHS_OF_YEAR_LEN 64
  81. static TCHAR g_szFileAlreadyExistsText[MAX_STRING_LEN] = _T("");
  82. static TCHAR g_szSrcFileDate[MAX_STRING_LEN] = _T("");
  83. static TCHAR g_szDestFileDate[MAX_STRING_LEN] = _T("");
  84. static TCHAR g_szSrcFileSize[MAX_STRING_LEN] = _T("");
  85. static TCHAR g_szDestFileSize[MAX_STRING_LEN] = _T("");
  86. static BOOL g_SetFocusYes;
  87. //
  88. // Dialog proc that runs in the copying thread's context
  89. //
  90. INT_PTR CALLBACK
  91. ConfirmFileReplaceDlgProc( IN HWND hwnd,
  92. IN UINT uMsg,
  93. IN WPARAM wParam,
  94. IN LPARAM lParam);
  95. //---------------------------------------------------------------------------
  96. //
  97. // This section of code runs in the context of a spawned thread. We do the
  98. // NT source copy work in a separate thread so that the dialog repaints
  99. // and such.
  100. //
  101. //---------------------------------------------------------------------------
  102. //---------------------------------------------------------------------------
  103. //
  104. // Function: CountSpaceNeeded
  105. //
  106. // Purpose: Routine that walks a tree and counts how many files there are
  107. // and how much diskspace is needed at the dest drive.
  108. //
  109. // Returns: VOID
  110. //
  111. //---------------------------------------------------------------------------
  112. VOID CountSpaceNeeded(HWND hwnd,
  113. LPTSTR SrcRootPath,
  114. LPTSTR DestRootPath)
  115. {
  116. LPTSTR SrcRootPathEnd = SrcRootPath + lstrlen(SrcRootPath);
  117. LPTSTR DestRootPathEnd = DestRootPath + lstrlen(DestRootPath);
  118. LONGLONG llFileSize;
  119. HANDLE FindHandle;
  120. WIN32_FIND_DATA FindData;
  121. //
  122. // Look for * in this dir
  123. //
  124. if ( ! ConcatenatePaths(SrcRootPath, _T("*"), NULL) )
  125. return;
  126. FindHandle = FindFirstFile(SrcRootPath, &FindData);
  127. if ( FindHandle == INVALID_HANDLE_VALUE )
  128. return;
  129. do {
  130. *SrcRootPathEnd = _T('\0');
  131. *DestRootPathEnd = _T('\0');
  132. if (lstrcmp(FindData.cFileName, _T(".") ) == 0 ||
  133. lstrcmp(FindData.cFileName, _T("..") ) == 0 )
  134. continue;
  135. if ( ! ConcatenatePaths(SrcRootPath, FindData.cFileName, NULL) ||
  136. ! ConcatenatePaths(DestRootPath, FindData.cFileName, NULL) )
  137. continue;
  138. //
  139. // If a file, increment space and TotalFile counters else
  140. // recurse down
  141. //
  142. if ( ! (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  143. llFileSize = (((LONGLONG) FindData.nFileSizeHigh) << 32) |
  144. FindData.nFileSizeLow;
  145. SetupAddToDiskSpaceList(ghDiskSpaceList,
  146. DestRootPath,
  147. llFileSize,
  148. FILEOP_COPY,
  149. NULL,
  150. 0);
  151. gnTotalFiles++;
  152. } else {
  153. CountSpaceNeeded(hwnd,
  154. SrcRootPath,
  155. DestRootPath);
  156. }
  157. } while ( FindNextFile(FindHandle, &FindData) );
  158. *SrcRootPathEnd = _T('\0');
  159. *DestRootPathEnd = _T('\0');
  160. FindClose(FindHandle);
  161. }
  162. //---------------------------------------------------------------------------
  163. //
  164. // Function: BuildTimeString
  165. //
  166. // Purpose:
  167. //
  168. // Arguments:
  169. //
  170. // Returns:
  171. //
  172. //---------------------------------------------------------------------------
  173. VOID
  174. BuildTimeString( IN FILETIME *FileTime, OUT TCHAR *szTimeString, IN DWORD cbSize )
  175. {
  176. // ISSUE-2002/02/28-stelo- should probably strip all of this low-level Time stuff out of here
  177. // and put in supplib
  178. FILETIME LocalTime;
  179. SYSTEMTIME LastWriteSystemTime;
  180. HRESULT hrPrintf;
  181. FileTimeToLocalFileTime( FileTime, &LocalTime);
  182. FileTimeToSystemTime( &LocalTime, &LastWriteSystemTime );
  183. hrPrintf=StringCchPrintf( szTimeString, cbSize,
  184. _T("%s: %s, %s %d, %d, %d:%.2d:%.2d"),
  185. StrModified,
  186. rgDaysOfWeek[LastWriteSystemTime.wDayOfWeek],
  187. rgMonthsOfYear[LastWriteSystemTime.wMonth-1],
  188. LastWriteSystemTime.wDay,
  189. LastWriteSystemTime.wYear,
  190. LastWriteSystemTime.wHour,
  191. LastWriteSystemTime.wMinute,
  192. LastWriteSystemTime.wSecond );
  193. }
  194. //---------------------------------------------------------------------------
  195. //
  196. // Function: CheckIfCancel
  197. //
  198. // Purpose: Ask user "You sure you want to cancel the file copy"?
  199. // And if user says YES, jump the wizard to the unsucessful
  200. // completion page.
  201. //
  202. // Returns:
  203. // TRUE - wizard is now canceled, quit copying files
  204. // FALSE - user wants to keep trying
  205. //
  206. //---------------------------------------------------------------------------
  207. BOOL CheckIfCancel(HWND hwnd)
  208. {
  209. UINT iRet;
  210. iRet = ReportErrorId(hwnd, MSGTYPE_YESNO, IDS_WARN_COPY_CANCEL);
  211. if ( iRet == IDYES ) {
  212. PostMessage(GetParent(hwnd),
  213. PSM_SETCURSELID,
  214. (WPARAM) 0,
  215. (LPARAM) IDD_FINISH2);
  216. return TRUE;
  217. }
  218. return FALSE;
  219. }
  220. //---------------------------------------------------------------------------
  221. //
  222. // Function: CopySingleFile
  223. //
  224. // Purpose: Copies a file, does all error reporting and interacting with
  225. // the user.
  226. //
  227. // If there are copy errors and the user cancels, this routine
  228. // cancels the whole wizard by jumping to the cancel page. In
  229. // that case it returns FALSE.
  230. //
  231. // After a file is successfully copied, gnFilesCopied will be
  232. // incremented and the gas-guage dlgproc will be notified.
  233. //
  234. // Note that this code runs in the spawned thread.
  235. //
  236. // Returns:
  237. // TRUE if file was copied
  238. // FALSE if file was not copied (user canceled)
  239. //
  240. //---------------------------------------------------------------------------
  241. BOOL CopySingleFile(HWND hwnd, LPTSTR Src, LPTSTR Dest)
  242. {
  243. BOOL bRetry = TRUE;
  244. UINT iRet, iRet2;
  245. static iOverwriteFiles = YES;
  246. HRESULT hrPrintf;
  247. // ISSUE-2002/02/28-stelo- I think this is actually going to have to be resolved so
  248. // it doesn't mess up copies on an edit, when a distrib folder is
  249. // already there, they just want to add files to it.
  250. //
  251. // ISSUE-2002/02/28-stelo- POSTPONED
  252. //
  253. // When we CopyFile from the CD, the readonly attribute is set on the
  254. // dest. So we call SetFileAttributes and reset it. If the user has
  255. // to redo the copy, he doesn't get a 1000 "Access Denied" errors.
  256. //
  257. // If the user cancels on the main wizard page, that thread jumps to
  258. // IDD_FINISH2. This thread keeps running.
  259. //
  260. // When the user finally clicks the Finish button, this thread gets
  261. // terminated the hard way because WinMain() in thread0 exits.
  262. //
  263. // Due to this, there will frequently be a file at the dest that still
  264. // has the readonly bit set when user cancels on the main wizard page.
  265. //
  266. // To fix this, we would need to synchronize with the wizard having
  267. // been canceled and back out gracefully (before the user has time to
  268. // push the Finish button).
  269. //
  270. // Note that when the wizard is canceled because a copy error already
  271. // ocurred, thread1 (this thread) does the popping up and it is this
  272. // thread that jumps to IDD_FINISH2. In this case we do back out
  273. // gracefully. This bug only happens when the user presses Cancel
  274. // on the wizard page while the gas-guage is happily painting.
  275. //
  276. // ISSUE-2002/02/28-stelo- this function needs to be cleaned up. To many if statements
  277. // scattered. Don't make if conditional so long.
  278. if( iOverwriteFiles != YESTOALL )
  279. {
  280. if( DoesFileExist( Dest ) )
  281. {
  282. INT_PTR iRetVal;
  283. HANDLE hSrcFile;
  284. HANDLE hDestFile;
  285. DWORD dwSrcSize;
  286. DWORD dwDestSize;
  287. FILETIME LastWriteTimeSrc;
  288. FILETIME LastWriteTimeDest;
  289. SYSTEMTIME LastWriteSystemTime;
  290. if( iOverwriteFiles == NOTOALL )
  291. {
  292. //
  293. // Give the illusion the file was copied
  294. //
  295. SendMessage( hwnd,
  296. WMX_FILECOPIED,
  297. (WPARAM) 0,
  298. (LPARAM) 0 );
  299. gnFilesCopied++;
  300. return( TRUE );
  301. }
  302. hrPrintf=StringCchPrintf( g_szFileAlreadyExistsText, AS(g_szFileAlreadyExistsText),
  303. StrFileAlreadyExists,
  304. MyGetFullPath( Dest ) );
  305. //
  306. // Open the files
  307. //
  308. hDestFile = CreateFile( Dest, GENERIC_READ, FILE_SHARE_READ, NULL,
  309. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  310. hSrcFile = CreateFile( Src, GENERIC_READ, FILE_SHARE_READ, NULL,
  311. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  312. GetFileTime( hSrcFile, NULL, NULL, &LastWriteTimeSrc );
  313. GetFileTime( hDestFile, NULL, NULL, &LastWriteTimeDest );
  314. // ISSUE-2002/02/28-stelo- need to display AM or PM, but what about other countries
  315. BuildTimeString( &LastWriteTimeSrc, g_szSrcFileDate, AS(g_szSrcFileDate) );
  316. BuildTimeString( &LastWriteTimeDest, g_szDestFileDate, AS(g_szSrcFileDate) );
  317. //
  318. // Default to NO if file times are equal
  319. //
  320. if( CompareFileTime( &LastWriteTimeSrc, &LastWriteTimeDest ) < 0 )
  321. {
  322. g_SetFocusYes = FALSE;
  323. }
  324. else
  325. {
  326. g_SetFocusYes = TRUE;
  327. }
  328. // ISSUE-2002/02/28-stelo- doesn't handle file sized > 2^32 bytes, need to catch
  329. // 2nd parameter value
  330. dwSrcSize = GetFileSize( hSrcFile, NULL );
  331. dwDestSize = GetFileSize( hDestFile, NULL );
  332. // ISSUE-2002/02/28-stelo- need to insert commas into size so it looks pretty
  333. hrPrintf=StringCchPrintf( g_szSrcFileSize,AS(g_szSrcFileSize), _T("%d %s"), dwSrcSize, StrBytes );
  334. hrPrintf=StringCchPrintf( g_szDestFileSize,AS(g_szDestFileSize), _T("%d %s"), dwDestSize, StrBytes );
  335. CloseHandle( hSrcFile );
  336. CloseHandle( hDestFile );
  337. iRetVal = DialogBox( FixedGlobals.hInstance,
  338. (LPCTSTR) IDD_CONFIRM_FILE_REPLACE,
  339. hwnd,
  340. ConfirmFileReplaceDlgProc );
  341. if( iRetVal == NO )
  342. {
  343. //
  344. // Give the illusion the file was copied
  345. //
  346. SendMessage( hwnd,
  347. WMX_FILECOPIED,
  348. (WPARAM) 0,
  349. (LPARAM) 0 );
  350. gnFilesCopied++;
  351. return( TRUE );
  352. }
  353. else if( iRetVal == YESTOALL )
  354. {
  355. iOverwriteFiles = YESTOALL;
  356. }
  357. else if( iRetVal == NOTOALL )
  358. {
  359. iOverwriteFiles = NOTOALL;
  360. }
  361. else if( iRetVal == CANCEL )
  362. {
  363. return( FALSE );
  364. }
  365. //
  366. // Not handling the YES case because that is the default, let this
  367. // function proceed and overwrite the file.
  368. //
  369. }
  370. }
  371. do
  372. {
  373. if ( CopyFile( Src, Dest, FALSE ) )
  374. {
  375. SetFileAttributes(Dest, FILE_ATTRIBUTE_NORMAL);
  376. SendMessage(hwnd,
  377. WMX_FILECOPIED,
  378. (WPARAM) 0,
  379. (LPARAM) 0);
  380. gnFilesCopied++;
  381. bRetry = FALSE;
  382. }
  383. else
  384. {
  385. iRet = ReportErrorId(hwnd,
  386. MSGTYPE_RETRYCANCEL | MSGTYPE_WIN32,
  387. IDS_ERR_COPY_FILE,
  388. Src, Dest);
  389. if ( iRet != IDRETRY ) {
  390. if ( CheckIfCancel(hwnd) )
  391. return FALSE;
  392. }
  393. }
  394. } while ( bRetry );
  395. return TRUE;
  396. }
  397. //---------------------------------------------------------------------------
  398. //
  399. // Function: CopyTheFiles
  400. //
  401. // Purpose: Recursive routine to oversee the copying of the bits.
  402. //
  403. // Returns:
  404. // TRUE if the whole tree was copied,
  405. // FALSE if user bailed on the tree copy
  406. //
  407. // Note that in the FALSE case CopySingleFile would have caused
  408. // thread0 to the FINISH2 wizard page (unsuccessful completion)
  409. // and thread1 (this code) will back out without further copies.
  410. //
  411. //---------------------------------------------------------------------------
  412. BOOL CopyTheFiles(HWND hwnd,
  413. LPTSTR SrcRootPath,
  414. LPTSTR DestRootPath)
  415. {
  416. LPTSTR SrcRootPathEnd = SrcRootPath + lstrlen(SrcRootPath);
  417. LPTSTR DestRootPathEnd = DestRootPath + lstrlen(DestRootPath);
  418. HANDLE FindHandle;
  419. WIN32_FIND_DATA FindData;
  420. BOOL bRet = TRUE;
  421. //
  422. // Look for * in this dir
  423. //
  424. if ( ! ConcatenatePaths(SrcRootPath, _T("*"), NULL) )
  425. return bRet;
  426. FindHandle = FindFirstFile(SrcRootPath, &FindData);
  427. if ( FindHandle == INVALID_HANDLE_VALUE )
  428. return bRet;
  429. do {
  430. *SrcRootPathEnd = _T('\0');
  431. *DestRootPathEnd = _T('\0');
  432. //
  433. // Don't copy the . and .. files (obviously)
  434. // If we run across an unattend.txt, don't copy it
  435. //
  436. if ( ( lstrcmp(FindData.cFileName, _T(".") ) == 0 ) ||
  437. ( lstrcmp(FindData.cFileName, _T("..") ) == 0 ) ||
  438. ( LSTRCMPI( FindData.cFileName, _T("unattend.txt") ) == 0 ) )
  439. continue;
  440. if ( ! ConcatenatePaths(SrcRootPath, FindData.cFileName, NULL) ||
  441. ! ConcatenatePaths(DestRootPath, FindData.cFileName, NULL) )
  442. continue;
  443. if ( ! (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  444. if ( ! CopySingleFile(hwnd, SrcRootPath, DestRootPath) ) {
  445. bRet = FALSE;
  446. goto CleanupAndReturn;
  447. }
  448. } else {
  449. //
  450. // Create the dir and recurse
  451. //
  452. if ( ! EnsureDirExists(DestRootPath) ) {
  453. UINT iRet;
  454. iRet = ReportErrorId(
  455. hwnd,
  456. MSGTYPE_RETRYCANCEL | MSGTYPE_WIN32,
  457. IDS_ERR_CREATE_FOLDER,
  458. DestRootPath);
  459. if ( iRet != IDRETRY ) {
  460. if ( CheckIfCancel(hwnd) ) {
  461. bRet = FALSE;
  462. goto CleanupAndReturn;
  463. }
  464. }
  465. }
  466. if ( ! CopyTheFiles(hwnd, SrcRootPath, DestRootPath) ) {
  467. bRet = FALSE;
  468. goto CleanupAndReturn;
  469. }
  470. }
  471. } while ( FindNextFile(FindHandle, &FindData) );
  472. CleanupAndReturn:
  473. *SrcRootPathEnd = _T('\0');
  474. *DestRootPathEnd = _T('\0');
  475. FindClose(FindHandle);
  476. return bRet;
  477. }
  478. //----------------------------------------------------------------------------
  479. //
  480. // Function: AsyncTreeCopy
  481. //
  482. // Purpose: The real thread entry
  483. //
  484. // Args: VOID *Args - really COPY_THREAD_PARAMS *
  485. //
  486. // Returns: 0
  487. //
  488. //----------------------------------------------------------------------------
  489. UINT AsyncTreeCopy(VOID* Args)
  490. {
  491. COPY_THREAD_PARAMS *InputArgs = (COPY_THREAD_PARAMS*) Args;
  492. TCHAR *CopySrc = InputArgs->lpSourceBuffer;
  493. TCHAR *CopyDest = InputArgs->lpDestBuffer;
  494. HWND hwnd = InputArgs->hwnd;
  495. BOOL bRet;
  496. LONGLONG llSpaceNeeded, llSpaceAvail;
  497. //
  498. // Figure out how much disk space is needed to copy the CD.
  499. //
  500. ghDiskSpaceList = SetupCreateDiskSpaceList(0, 0, 0);
  501. if (ghDiskSpaceList == NULL)
  502. {
  503. TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
  504. }
  505. CountSpaceNeeded(hwnd, CopySrc, CopyDest);
  506. //
  507. // Is there enough free space?
  508. //
  509. // NOTE:
  510. //
  511. // We give the user a retry_cancel, hopefully user can free up space
  512. // on the drive.
  513. //
  514. // We could popup and let them change the destpath. However, we may
  515. // have copied files on the AdditionalDirs page. So allowing them to
  516. // change the path means you need to check diskspace requirements for
  517. // OemFilesPath and treecopy it as well. If we ever allow changing
  518. // OemFilesPath, then the script would have to be updated as well,
  519. // and it has already been written out.
  520. //
  521. // We could check way back on the DistFolder page. But then we
  522. // would have to find the SourcePath before we know if it's a CD
  523. // or netpath and we couldn't know how much they might copy on the
  524. // AdditionalDirs page.
  525. //
  526. llSpaceNeeded =
  527. MySetupQuerySpaceRequiredOnDrive(ghDiskSpaceList, CopyDest);
  528. llSpaceAvail = MyGetDiskFreeSpace(CopyDest);
  529. if ( llSpaceAvail < llSpaceNeeded ) {
  530. UINT iRet;
  531. iRet = ReportErrorId(
  532. hwnd,
  533. MSGTYPE_RETRYCANCEL,
  534. IDS_ERR_INSUFICIENT_SPACE,
  535. CopyDest, // ISSUE-2002-02-28-stelo-
  536. (UINT) (llSpaceNeeded / ONE_MEG),
  537. (UINT) (llSpaceAvail / ONE_MEG));
  538. if ( iRet != IDRETRY ) {
  539. if ( CheckIfCancel(hwnd) )
  540. goto CleanupAndReturn;
  541. }
  542. }
  543. //
  544. // Update the message on the wizard page and start copying the files
  545. //
  546. SetDlgItemText(hwnd, IDC_TEXT, StrCopyingFiles);
  547. if ( CopyTheFiles(hwnd, CopySrc, CopyDest) ) {
  548. SendMessage(hwnd, WMX_ENDCOPYING, (WPARAM) 0, (LPARAM) 0);
  549. }
  550. //
  551. // Cleanup and return
  552. //
  553. CleanupAndReturn:
  554. SetupDestroyDiskSpaceList(ghDiskSpaceList);
  555. return 0;
  556. }
  557. //----------------------------------------------------------------------------
  558. //
  559. // This section of code runs in thread0.
  560. //
  561. //----------------------------------------------------------------------------
  562. //----------------------------------------------------------------------------
  563. //
  564. // Function: TreeCopyNtSources
  565. //
  566. // Purpose: Entry point for copying the NT sources (either from CD or
  567. // a net path).
  568. //
  569. // The dialog proc calls this one, and it takes care of the
  570. // details of spawning the thread.
  571. //
  572. // Arguments:
  573. // HWND hwnd - window to receive copy notifications (the dlgproc)
  574. // UINT Message - message to send on copy notifications (to dlgproc)
  575. // LPTSTR lpSource - root of copy source
  576. // LPTSTR lpDest - root of copy dest
  577. //
  578. // Returns: void
  579. //
  580. // Notes:
  581. // - Input strings will not be modified.
  582. //
  583. //----------------------------------------------------------------------------
  584. VOID TreeCopyNtSources(HWND hwnd,
  585. LPTSTR lpSource,
  586. LPTSTR lpDest)
  587. {
  588. DWORD dwThreadId;
  589. HANDLE hCopyThread;
  590. static COPY_THREAD_PARAMS ThreadParams;
  591. //
  592. // Fill in the ThreadParams and spawn it
  593. //
  594. // NTRAID#NTBUG9-551874-2002/02/27-stelo,swamip - CreateDistFolder, ShareTheDistFolder should use the code from OEM mode, reduce attack surface
  595. lstrcpyn(ThreadParams.lpSourceBuffer, lpSource,AS(ThreadParams.lpSourceBuffer));
  596. lstrcpyn(ThreadParams.lpDestBuffer, lpDest, AS(ThreadParams.lpDestBuffer));
  597. MyGetFullPath(ThreadParams.lpSourceBuffer);
  598. MyGetFullPath(ThreadParams.lpDestBuffer);
  599. ThreadParams.hwnd = hwnd;
  600. hCopyThread = CreateThread(NULL,
  601. 0,
  602. AsyncTreeCopy,
  603. &ThreadParams,
  604. 0,
  605. &dwThreadId);
  606. }
  607. //----------------------------------------------------------------------------
  608. //
  609. // Function: BuildCopyDestPath
  610. //
  611. // Purpose:
  612. //
  613. // DestPath is assumed to be of MAX_PATH length
  614. //
  615. // Arguments:
  616. //
  617. // Returns: VOID
  618. //
  619. //----------------------------------------------------------------------------
  620. VOID
  621. BuildCopyDestPath( IN TCHAR *DestPath, IN DWORD cbSize )
  622. {
  623. HRESULT hrCat;
  624. //
  625. // If the dist folder begins with a drive letter, just use that
  626. // If it is a UNC, then build the computer and share name and use that
  627. //
  628. if( WizGlobals.UncDistFolder[0] != _T('\\') )
  629. {
  630. lstrcpyn( DestPath, WizGlobals.UncDistFolder, cbSize );
  631. }
  632. else
  633. {
  634. GetComputerNameFromUnc( WizGlobals.UncDistFolder, DestPath, cbSize );
  635. hrCat=StringCchCat( DestPath, cbSize, _T("\\") );
  636. hrCat=StringCchCat( DestPath, cbSize, WizGlobals.DistShareName );
  637. }
  638. hrCat=StringCchCat( DestPath, cbSize, _T("\\") );
  639. hrCat=StringCchCat( DestPath, cbSize, WizGlobals.Architecture );
  640. }
  641. //----------------------------------------------------------------------------
  642. //
  643. // Function: OnCopyFilesInitDialog
  644. //
  645. // Purpose:
  646. //
  647. // Arguments: IN HWND hwnd - handle to the dialog
  648. //
  649. // Returns: VOID
  650. //
  651. //----------------------------------------------------------------------------
  652. static VOID
  653. OnCopyFilesInitDialog( IN HWND hwnd )
  654. {
  655. StrBuildingList = MyLoadString( IDS_COPYMSG1 );
  656. StrCopyingFiles = MyLoadString( IDS_COPYMSG2 );
  657. StrFileAlreadyExists = MyLoadString( IDS_FILE_ALREADY_EXISTS );
  658. StrModified = MyLoadString( IDS_MODIFIED );
  659. StrBytes = MyLoadString( IDS_BYTES );
  660. SetDlgItemText(hwnd, IDC_TEXT, StrBuildingList);
  661. //
  662. // Load Months
  663. //
  664. StrJanuary = MyLoadString( IDS_JANUARY );
  665. StrFebruary = MyLoadString( IDS_FEBRUARY );
  666. StrMarch = MyLoadString( IDS_MARCH );
  667. StrApril = MyLoadString( IDS_APRIL );
  668. StrMay = MyLoadString( IDS_MAY );
  669. StrJune = MyLoadString( IDS_JUNE );
  670. StrJuly = MyLoadString( IDS_JULY );
  671. StrAugust = MyLoadString( IDS_AUGUST );
  672. StrSeptember = MyLoadString( IDS_SEPTEMBER );
  673. StrOctober = MyLoadString( IDS_OCTOBER );
  674. StrNovember = MyLoadString( IDS_NOVEMBER );
  675. StrDecember = MyLoadString( IDS_DECEMBER );
  676. rgMonthsOfYear[0] = StrJanuary;
  677. rgMonthsOfYear[1] = StrFebruary;
  678. rgMonthsOfYear[2] = StrMarch;
  679. rgMonthsOfYear[3] = StrApril;
  680. rgMonthsOfYear[4] = StrMay;
  681. rgMonthsOfYear[5] = StrJune;
  682. rgMonthsOfYear[6] = StrJuly;
  683. rgMonthsOfYear[7] = StrAugust;
  684. rgMonthsOfYear[8] = StrSeptember;
  685. rgMonthsOfYear[9] = StrOctober;
  686. rgMonthsOfYear[10] = StrNovember;
  687. rgMonthsOfYear[11] = StrDecember;
  688. //
  689. // Load Days of Week
  690. //
  691. StrSunday = MyLoadString( IDS_SUNDAY );
  692. StrMonday = MyLoadString( IDS_MONDAY );
  693. StrTuesday = MyLoadString( IDS_TUESDAY );
  694. StrWednesday = MyLoadString( IDS_WEDNESDAY );
  695. StrThursday = MyLoadString( IDS_THURSDAY );
  696. StrFriday = MyLoadString( IDS_FRIDAY );
  697. StrSaturday = MyLoadString( IDS_SATURDAY );
  698. rgDaysOfWeek[0] = StrSunday;
  699. rgDaysOfWeek[1] = StrMonday;
  700. rgDaysOfWeek[2] = StrTuesday;
  701. rgDaysOfWeek[3] = StrWednesday;
  702. rgDaysOfWeek[4] = StrThursday;
  703. rgDaysOfWeek[5] = StrFriday;
  704. rgDaysOfWeek[6] = StrSaturday;
  705. rgDaysOfWeek[7] = StrSunday;
  706. }
  707. //----------------------------------------------------------------------------
  708. //
  709. // Function: DlgCopyFilesPage
  710. //
  711. // Purpose: This is the dialog procedure the copy files page
  712. //
  713. //----------------------------------------------------------------------------
  714. INT_PTR CALLBACK DlgCopyFilesPage(
  715. IN HWND hwnd,
  716. IN UINT uMsg,
  717. IN WPARAM wParam,
  718. IN LPARAM lParam)
  719. {
  720. UINT nPercent;
  721. BOOL bStatus = TRUE;
  722. switch (uMsg) {
  723. case WM_INITDIALOG:
  724. OnCopyFilesInitDialog( hwnd );
  725. break;
  726. case WMX_BEGINCOPYING:
  727. {
  728. TCHAR *SrcPath;
  729. TCHAR DestPath[MAX_PATH + 1];
  730. if ( WizGlobals.bCopyFromPath )
  731. SrcPath = WizGlobals.CopySourcePath;
  732. else
  733. SrcPath = WizGlobals.CdSourcePath;
  734. SendDlgItemMessage(hwnd,
  735. IDC_PROGRESS1,
  736. PBM_SETPOS,
  737. 0,
  738. 0);
  739. BuildCopyDestPath( DestPath, AS(DestPath) );
  740. TreeCopyNtSources(hwnd,
  741. SrcPath,
  742. DestPath);
  743. }
  744. break;
  745. case WMX_ENDCOPYING:
  746. SendDlgItemMessage(hwnd,
  747. IDC_PROGRESS1,
  748. PBM_SETPOS,
  749. (WPARAM) 100,
  750. 0);
  751. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
  752. //
  753. // The CD is done copying so Auto-Advance to the next page
  754. //
  755. // ISSUE-2002/02/28-stelo- this works, but I should really go through
  756. // RouteToProperPage or send a NEXT message but neither work
  757. PostMessage( GetParent(hwnd),
  758. PSM_SETCURSELID,
  759. (WPARAM) 0,
  760. (LPARAM) IDD_FINISH );
  761. break;
  762. case WMX_FILECOPIED:
  763. nPercent = (gnFilesCopied * 100) / gnTotalFiles;
  764. SendDlgItemMessage(hwnd,
  765. IDC_PROGRESS1,
  766. PBM_SETPOS,
  767. (WPARAM) nPercent,
  768. 0);
  769. break;
  770. case WM_NOTIFY:
  771. {
  772. LPNMHDR pnmh = (LPNMHDR)lParam;
  773. switch( pnmh->code ) {
  774. case PSN_QUERYCANCEL:
  775. CancelTheWizard(hwnd);
  776. break;
  777. case PSN_SETACTIVE:
  778. PropSheet_SetWizButtons(GetParent(hwnd), 0);
  779. PostMessage(hwnd, WMX_BEGINCOPYING, 0, 0);
  780. break;
  781. // Can't go back in the wizard from here
  782. case PSN_WIZBACK:
  783. break;
  784. case PSN_WIZNEXT:
  785. break;
  786. default:
  787. bStatus = FALSE;
  788. break;
  789. }
  790. }
  791. break;
  792. default:
  793. bStatus = FALSE;
  794. break;
  795. }
  796. return bStatus;
  797. }
  798. //----------------------------------------------------------------------------
  799. //
  800. // Function: ConfirmFileReplaceDlgProc
  801. //
  802. // Purpose: Confirm file replace dialog proc. Allows the user to chose to
  803. // overwrite the file, overwrite all files, do not overwrite or cancel the
  804. // copy all together. Runs in the copying thread's context
  805. //
  806. // Arguments: standard Win32 dialog proc arguments
  807. //
  808. // Returns: the button the user pressed(Yes, Yes to All, No, Cancel)
  809. //
  810. //----------------------------------------------------------------------------
  811. INT_PTR CALLBACK
  812. ConfirmFileReplaceDlgProc( IN HWND hwnd,
  813. IN UINT uMsg,
  814. IN WPARAM wParam,
  815. IN LPARAM lParam ) {
  816. BOOL bStatus = TRUE;
  817. switch( uMsg ) {
  818. case WM_INITDIALOG: {
  819. SetWindowText( GetDlgItem( hwnd, IDC_REPLACE_FILE_TEXT),
  820. g_szFileAlreadyExistsText );
  821. SetWindowText( GetDlgItem( hwnd, IDC_SRC_FILE_DATE),
  822. g_szSrcFileDate );
  823. SetWindowText( GetDlgItem( hwnd, IDC_SRC_FILE_SIZE),
  824. g_szSrcFileSize );
  825. SetWindowText( GetDlgItem( hwnd, IDC_DEST_FILE_DATE),
  826. g_szDestFileDate );
  827. SetWindowText( GetDlgItem( hwnd, IDC_DEST_FILE_SIZE),
  828. g_szDestFileSize );
  829. if( g_SetFocusYes ) {
  830. SetFocus( GetDlgItem( hwnd, IDC_YES_BUTTON ) );
  831. }
  832. else {
  833. SetFocus( GetDlgItem( hwnd, IDC_NO_BUTTON ) );
  834. }
  835. break;
  836. }
  837. case WM_COMMAND: {
  838. int nButtonId = LOWORD( wParam );
  839. switch ( nButtonId ) {
  840. case IDC_YES_BUTTON:
  841. {
  842. EndDialog( hwnd, YES );
  843. break;
  844. }
  845. case IDC_YESTOALL:
  846. {
  847. EndDialog( hwnd, YESTOALL );
  848. break;
  849. }
  850. case IDC_NO_BUTTON:
  851. {
  852. EndDialog( hwnd, NO );
  853. break;
  854. }
  855. case IDC_NOTOALL:
  856. {
  857. EndDialog( hwnd, NOTOALL );
  858. break;
  859. }
  860. case IDCANCEL:
  861. {
  862. if( CheckIfCancel( hwnd ) )
  863. {
  864. EndDialog( hwnd, CANCEL );
  865. }
  866. break;
  867. }
  868. }
  869. }
  870. default:
  871. bStatus = FALSE;
  872. break;
  873. }
  874. return( bStatus );
  875. }