1102 lines
31 KiB
C
1102 lines
31 KiB
C
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Copyright (c) 1997-1999 Microsoft Corporation
|
|||
|
// All rights reserved.
|
|||
|
//
|
|||
|
// File Name:
|
|||
|
// copyfile.c
|
|||
|
//
|
|||
|
// Description:
|
|||
|
// This file has the dlgproc for the copy files page.
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
#include "resource.h"
|
|||
|
|
|||
|
#define DAYS_IN_A_WEEK 7
|
|||
|
#define MONTHS_IN_A_YEAR 12
|
|||
|
|
|||
|
//
|
|||
|
// This struct and is used to pack the input args passed to the tree
|
|||
|
// copy thread.
|
|||
|
//
|
|||
|
|
|||
|
typedef struct {
|
|||
|
TCHAR lpSourceBuffer[MAX_PATH];
|
|||
|
TCHAR lpDestBuffer[MAX_PATH];
|
|||
|
HWND hwnd;
|
|||
|
} COPY_THREAD_PARAMS;
|
|||
|
|
|||
|
//
|
|||
|
// String constants loaded from resource
|
|||
|
//
|
|||
|
|
|||
|
static TCHAR *StrBuildingList;
|
|||
|
static TCHAR *StrCopyingFiles;
|
|||
|
static TCHAR *StrFileAlreadyExists;
|
|||
|
static TCHAR *StrModified;
|
|||
|
static TCHAR *StrBytes;
|
|||
|
|
|||
|
static TCHAR *StrJanuary;
|
|||
|
static TCHAR *StrFebruary;
|
|||
|
static TCHAR *StrMarch;
|
|||
|
static TCHAR *StrApril;
|
|||
|
static TCHAR *StrMay;
|
|||
|
static TCHAR *StrJune;
|
|||
|
static TCHAR *StrJuly;
|
|||
|
static TCHAR *StrAugust;
|
|||
|
static TCHAR *StrSeptember;
|
|||
|
static TCHAR *StrOctober;
|
|||
|
static TCHAR *StrNovember;
|
|||
|
static TCHAR *StrDecember;
|
|||
|
|
|||
|
static TCHAR *StrSunday;
|
|||
|
static TCHAR *StrMonday;
|
|||
|
static TCHAR *StrTuesday;
|
|||
|
static TCHAR *StrWednesday;
|
|||
|
static TCHAR *StrThursday;
|
|||
|
static TCHAR *StrFriday;
|
|||
|
static TCHAR *StrSaturday;
|
|||
|
|
|||
|
static TCHAR *rgMonthsOfYear[MONTHS_IN_A_YEAR];
|
|||
|
static TCHAR *rgDaysOfWeek[DAYS_IN_A_WEEK + 1];
|
|||
|
|
|||
|
//
|
|||
|
// Messages for the dialog procedure
|
|||
|
//
|
|||
|
|
|||
|
#define WMX_BEGINCOPYING (WM_USER+1)
|
|||
|
#define WMX_FILECOPIED (WM_USER+2)
|
|||
|
#define WMX_ENDCOPYING (WM_USER+3)
|
|||
|
|
|||
|
//
|
|||
|
// Global counters
|
|||
|
//
|
|||
|
|
|||
|
HDSKSPC ghDiskSpaceList;
|
|||
|
int gnFilesCopied = 0;
|
|||
|
int gnTotalFiles = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Misc constants
|
|||
|
//
|
|||
|
|
|||
|
#define ONE_MEG ( 1024 * 1024 )
|
|||
|
|
|||
|
//
|
|||
|
// Confirm File replace constants
|
|||
|
//
|
|||
|
#define YES 1
|
|||
|
#define YESTOALL 2
|
|||
|
#define NO 3
|
|||
|
#define NOTOALL 4
|
|||
|
#define CANCEL 5
|
|||
|
|
|||
|
#define MAX_DAY_OF_WEEK_LEN 64
|
|||
|
#define MAX_MONTHS_OF_YEAR_LEN 64
|
|||
|
|
|||
|
static TCHAR g_szFileAlreadyExistsText[MAX_STRING_LEN] = _T("");
|
|||
|
static TCHAR g_szSrcFileDate[MAX_STRING_LEN] = _T("");
|
|||
|
static TCHAR g_szDestFileDate[MAX_STRING_LEN] = _T("");
|
|||
|
static TCHAR g_szSrcFileSize[MAX_STRING_LEN] = _T("");
|
|||
|
static TCHAR g_szDestFileSize[MAX_STRING_LEN] = _T("");
|
|||
|
static BOOL g_SetFocusYes;
|
|||
|
|
|||
|
//
|
|||
|
// Dialog proc that runs in the copying thread's context
|
|||
|
//
|
|||
|
INT_PTR CALLBACK
|
|||
|
ConfirmFileReplaceDlgProc( IN HWND hwnd,
|
|||
|
IN UINT uMsg,
|
|||
|
IN WPARAM wParam,
|
|||
|
IN LPARAM lParam);
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// This section of code runs in the context of a spawned thread. We do the
|
|||
|
// NT source copy work in a separate thread so that the dialog repaints
|
|||
|
// and such.
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CountSpaceNeeded
|
|||
|
//
|
|||
|
// Purpose: Routine that walks a tree and counts how many files there are
|
|||
|
// and how much diskspace is needed at the dest drive.
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID CountSpaceNeeded(HWND hwnd,
|
|||
|
LPTSTR SrcRootPath,
|
|||
|
LPTSTR DestRootPath)
|
|||
|
{
|
|||
|
LPTSTR SrcRootPathEnd = SrcRootPath + lstrlen(SrcRootPath);
|
|||
|
LPTSTR DestRootPathEnd = DestRootPath + lstrlen(DestRootPath);
|
|||
|
|
|||
|
LONGLONG llFileSize;
|
|||
|
HANDLE FindHandle;
|
|||
|
|
|||
|
WIN32_FIND_DATA FindData;
|
|||
|
|
|||
|
//
|
|||
|
// Look for * in this dir
|
|||
|
//
|
|||
|
if ( ! ConcatenatePaths(SrcRootPath, _T("*"), NULL) )
|
|||
|
return;
|
|||
|
|
|||
|
FindHandle = FindFirstFile(SrcRootPath, &FindData);
|
|||
|
|
|||
|
if ( FindHandle == INVALID_HANDLE_VALUE )
|
|||
|
return;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
*SrcRootPathEnd = _T('\0');
|
|||
|
*DestRootPathEnd = _T('\0');
|
|||
|
|
|||
|
if (lstrcmp(FindData.cFileName, _T(".") ) == 0 ||
|
|||
|
lstrcmp(FindData.cFileName, _T("..") ) == 0 )
|
|||
|
continue;
|
|||
|
|
|||
|
if ( ! ConcatenatePaths(SrcRootPath, FindData.cFileName, NULL) ||
|
|||
|
! ConcatenatePaths(DestRootPath, FindData.cFileName, NULL) )
|
|||
|
continue;
|
|||
|
|
|||
|
//
|
|||
|
// If a file, increment space and TotalFile counters else
|
|||
|
// recurse down
|
|||
|
//
|
|||
|
if ( ! (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
|
|||
|
|
|||
|
llFileSize = (((LONGLONG) FindData.nFileSizeHigh) << 32) |
|
|||
|
FindData.nFileSizeLow;
|
|||
|
|
|||
|
SetupAddToDiskSpaceList(ghDiskSpaceList,
|
|||
|
DestRootPath,
|
|||
|
llFileSize,
|
|||
|
FILEOP_COPY,
|
|||
|
NULL,
|
|||
|
0);
|
|||
|
|
|||
|
gnTotalFiles++;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CountSpaceNeeded(hwnd,
|
|||
|
SrcRootPath,
|
|||
|
DestRootPath);
|
|||
|
}
|
|||
|
|
|||
|
} while ( FindNextFile(FindHandle, &FindData) );
|
|||
|
|
|||
|
*SrcRootPathEnd = _T('\0');
|
|||
|
*DestRootPathEnd = _T('\0');
|
|||
|
|
|||
|
FindClose(FindHandle);
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: BuildTimeString
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
BuildTimeString( IN FILETIME *FileTime, OUT TCHAR *szTimeString, IN DWORD cbSize )
|
|||
|
{
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- should probably strip all of this low-level Time stuff out of here
|
|||
|
// and put in supplib
|
|||
|
|
|||
|
FILETIME LocalTime;
|
|||
|
SYSTEMTIME LastWriteSystemTime;
|
|||
|
HRESULT hrPrintf;
|
|||
|
|
|||
|
FileTimeToLocalFileTime( FileTime, &LocalTime);
|
|||
|
|
|||
|
FileTimeToSystemTime( &LocalTime, &LastWriteSystemTime );
|
|||
|
|
|||
|
hrPrintf=StringCchPrintf( szTimeString, cbSize,
|
|||
|
_T("%s: %s, %s %d, %d, %d:%.2d:%.2d"),
|
|||
|
StrModified,
|
|||
|
rgDaysOfWeek[LastWriteSystemTime.wDayOfWeek],
|
|||
|
rgMonthsOfYear[LastWriteSystemTime.wMonth-1],
|
|||
|
LastWriteSystemTime.wDay,
|
|||
|
LastWriteSystemTime.wYear,
|
|||
|
LastWriteSystemTime.wHour,
|
|||
|
LastWriteSystemTime.wMinute,
|
|||
|
LastWriteSystemTime.wSecond );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CheckIfCancel
|
|||
|
//
|
|||
|
// Purpose: Ask user "You sure you want to cancel the file copy"?
|
|||
|
// And if user says YES, jump the wizard to the unsucessful
|
|||
|
// completion page.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// TRUE - wizard is now canceled, quit copying files
|
|||
|
// FALSE - user wants to keep trying
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CheckIfCancel(HWND hwnd)
|
|||
|
{
|
|||
|
UINT iRet;
|
|||
|
|
|||
|
iRet = ReportErrorId(hwnd, MSGTYPE_YESNO, IDS_WARN_COPY_CANCEL);
|
|||
|
|
|||
|
if ( iRet == IDYES ) {
|
|||
|
PostMessage(GetParent(hwnd),
|
|||
|
PSM_SETCURSELID,
|
|||
|
(WPARAM) 0,
|
|||
|
(LPARAM) IDD_FINISH2);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CopySingleFile
|
|||
|
//
|
|||
|
// Purpose: Copies a file, does all error reporting and interacting with
|
|||
|
// the user.
|
|||
|
//
|
|||
|
// If there are copy errors and the user cancels, this routine
|
|||
|
// cancels the whole wizard by jumping to the cancel page. In
|
|||
|
// that case it returns FALSE.
|
|||
|
//
|
|||
|
// After a file is successfully copied, gnFilesCopied will be
|
|||
|
// incremented and the gas-guage dlgproc will be notified.
|
|||
|
//
|
|||
|
// Note that this code runs in the spawned thread.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// TRUE if file was copied
|
|||
|
// FALSE if file was not copied (user canceled)
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CopySingleFile(HWND hwnd, LPTSTR Src, LPTSTR Dest)
|
|||
|
{
|
|||
|
BOOL bRetry = TRUE;
|
|||
|
UINT iRet, iRet2;
|
|||
|
static iOverwriteFiles = YES;
|
|||
|
HRESULT hrPrintf;
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- I think this is actually going to have to be resolved so
|
|||
|
// it doesn't mess up copies on an edit, when a distrib folder is
|
|||
|
// already there, they just want to add files to it.
|
|||
|
|
|||
|
//
|
|||
|
// ISSUE-2002/02/28-stelo- POSTPONED
|
|||
|
//
|
|||
|
// When we CopyFile from the CD, the readonly attribute is set on the
|
|||
|
// dest. So we call SetFileAttributes and reset it. If the user has
|
|||
|
// to redo the copy, he doesn't get a 1000 "Access Denied" errors.
|
|||
|
//
|
|||
|
// If the user cancels on the main wizard page, that thread jumps to
|
|||
|
// IDD_FINISH2. This thread keeps running.
|
|||
|
//
|
|||
|
// When the user finally clicks the Finish button, this thread gets
|
|||
|
// terminated the hard way because WinMain() in thread0 exits.
|
|||
|
//
|
|||
|
// Due to this, there will frequently be a file at the dest that still
|
|||
|
// has the readonly bit set when user cancels on the main wizard page.
|
|||
|
//
|
|||
|
// To fix this, we would need to synchronize with the wizard having
|
|||
|
// been canceled and back out gracefully (before the user has time to
|
|||
|
// push the Finish button).
|
|||
|
//
|
|||
|
// Note that when the wizard is canceled because a copy error already
|
|||
|
// ocurred, thread1 (this thread) does the popping up and it is this
|
|||
|
// thread that jumps to IDD_FINISH2. In this case we do back out
|
|||
|
// gracefully. This bug only happens when the user presses Cancel
|
|||
|
// on the wizard page while the gas-guage is happily painting.
|
|||
|
//
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- this function needs to be cleaned up. To many if statements
|
|||
|
// scattered. Don't make if conditional so long.
|
|||
|
if( iOverwriteFiles != YESTOALL )
|
|||
|
{
|
|||
|
|
|||
|
if( DoesFileExist( Dest ) )
|
|||
|
{
|
|||
|
|
|||
|
INT_PTR iRetVal;
|
|||
|
HANDLE hSrcFile;
|
|||
|
HANDLE hDestFile;
|
|||
|
DWORD dwSrcSize;
|
|||
|
DWORD dwDestSize;
|
|||
|
FILETIME LastWriteTimeSrc;
|
|||
|
FILETIME LastWriteTimeDest;
|
|||
|
SYSTEMTIME LastWriteSystemTime;
|
|||
|
|
|||
|
if( iOverwriteFiles == NOTOALL )
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Give the illusion the file was copied
|
|||
|
//
|
|||
|
SendMessage( hwnd,
|
|||
|
WMX_FILECOPIED,
|
|||
|
(WPARAM) 0,
|
|||
|
(LPARAM) 0 );
|
|||
|
|
|||
|
gnFilesCopied++;
|
|||
|
|
|||
|
return( TRUE );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
hrPrintf=StringCchPrintf( g_szFileAlreadyExistsText, AS(g_szFileAlreadyExistsText),
|
|||
|
StrFileAlreadyExists,
|
|||
|
MyGetFullPath( Dest ) );
|
|||
|
|
|||
|
//
|
|||
|
// Open the files
|
|||
|
//
|
|||
|
hDestFile = CreateFile( Dest, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|||
|
|
|||
|
hSrcFile = CreateFile( Src, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|||
|
|
|||
|
GetFileTime( hSrcFile, NULL, NULL, &LastWriteTimeSrc );
|
|||
|
GetFileTime( hDestFile, NULL, NULL, &LastWriteTimeDest );
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- need to display AM or PM, but what about other countries
|
|||
|
BuildTimeString( &LastWriteTimeSrc, g_szSrcFileDate, AS(g_szSrcFileDate) );
|
|||
|
BuildTimeString( &LastWriteTimeDest, g_szDestFileDate, AS(g_szSrcFileDate) );
|
|||
|
|
|||
|
//
|
|||
|
// Default to NO if file times are equal
|
|||
|
//
|
|||
|
if( CompareFileTime( &LastWriteTimeSrc, &LastWriteTimeDest ) < 0 )
|
|||
|
{
|
|||
|
g_SetFocusYes = FALSE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
g_SetFocusYes = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- doesn't handle file sized > 2^32 bytes, need to catch
|
|||
|
// 2nd parameter value
|
|||
|
dwSrcSize = GetFileSize( hSrcFile, NULL );
|
|||
|
dwDestSize = GetFileSize( hDestFile, NULL );
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- need to insert commas into size so it looks pretty
|
|||
|
hrPrintf=StringCchPrintf( g_szSrcFileSize,AS(g_szSrcFileSize), _T("%d %s"), dwSrcSize, StrBytes );
|
|||
|
hrPrintf=StringCchPrintf( g_szDestFileSize,AS(g_szDestFileSize), _T("%d %s"), dwDestSize, StrBytes );
|
|||
|
|
|||
|
CloseHandle( hSrcFile );
|
|||
|
CloseHandle( hDestFile );
|
|||
|
|
|||
|
iRetVal = DialogBox( FixedGlobals.hInstance,
|
|||
|
(LPCTSTR) IDD_CONFIRM_FILE_REPLACE,
|
|||
|
hwnd,
|
|||
|
ConfirmFileReplaceDlgProc );
|
|||
|
|
|||
|
if( iRetVal == NO )
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Give the illusion the file was copied
|
|||
|
//
|
|||
|
SendMessage( hwnd,
|
|||
|
WMX_FILECOPIED,
|
|||
|
(WPARAM) 0,
|
|||
|
(LPARAM) 0 );
|
|||
|
|
|||
|
gnFilesCopied++;
|
|||
|
|
|||
|
return( TRUE );
|
|||
|
|
|||
|
}
|
|||
|
else if( iRetVal == YESTOALL )
|
|||
|
{
|
|||
|
|
|||
|
iOverwriteFiles = YESTOALL;
|
|||
|
|
|||
|
}
|
|||
|
else if( iRetVal == NOTOALL )
|
|||
|
{
|
|||
|
|
|||
|
iOverwriteFiles = NOTOALL;
|
|||
|
}
|
|||
|
else if( iRetVal == CANCEL )
|
|||
|
{
|
|||
|
|
|||
|
return( FALSE );
|
|||
|
|
|||
|
}
|
|||
|
//
|
|||
|
// Not handling the YES case because that is the default, let this
|
|||
|
// function proceed and overwrite the file.
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
|
|||
|
if ( CopyFile( Src, Dest, FALSE ) )
|
|||
|
{
|
|||
|
|
|||
|
SetFileAttributes(Dest, FILE_ATTRIBUTE_NORMAL);
|
|||
|
|
|||
|
SendMessage(hwnd,
|
|||
|
WMX_FILECOPIED,
|
|||
|
(WPARAM) 0,
|
|||
|
(LPARAM) 0);
|
|||
|
|
|||
|
gnFilesCopied++;
|
|||
|
|
|||
|
bRetry = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
iRet = ReportErrorId(hwnd,
|
|||
|
MSGTYPE_RETRYCANCEL | MSGTYPE_WIN32,
|
|||
|
IDS_ERR_COPY_FILE,
|
|||
|
Src, Dest);
|
|||
|
|
|||
|
if ( iRet != IDRETRY ) {
|
|||
|
if ( CheckIfCancel(hwnd) )
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} while ( bRetry );
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CopyTheFiles
|
|||
|
//
|
|||
|
// Purpose: Recursive routine to oversee the copying of the bits.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// TRUE if the whole tree was copied,
|
|||
|
// FALSE if user bailed on the tree copy
|
|||
|
//
|
|||
|
// Note that in the FALSE case CopySingleFile would have caused
|
|||
|
// thread0 to the FINISH2 wizard page (unsuccessful completion)
|
|||
|
// and thread1 (this code) will back out without further copies.
|
|||
|
//
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CopyTheFiles(HWND hwnd,
|
|||
|
LPTSTR SrcRootPath,
|
|||
|
LPTSTR DestRootPath)
|
|||
|
{
|
|||
|
LPTSTR SrcRootPathEnd = SrcRootPath + lstrlen(SrcRootPath);
|
|||
|
LPTSTR DestRootPathEnd = DestRootPath + lstrlen(DestRootPath);
|
|||
|
HANDLE FindHandle;
|
|||
|
WIN32_FIND_DATA FindData;
|
|||
|
BOOL bRet = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Look for * in this dir
|
|||
|
//
|
|||
|
|
|||
|
if ( ! ConcatenatePaths(SrcRootPath, _T("*"), NULL) )
|
|||
|
return bRet;
|
|||
|
|
|||
|
FindHandle = FindFirstFile(SrcRootPath, &FindData);
|
|||
|
|
|||
|
if ( FindHandle == INVALID_HANDLE_VALUE )
|
|||
|
return bRet;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
*SrcRootPathEnd = _T('\0');
|
|||
|
*DestRootPathEnd = _T('\0');
|
|||
|
|
|||
|
//
|
|||
|
// Don't copy the . and .. files (obviously)
|
|||
|
// If we run across an unattend.txt, don't copy it
|
|||
|
//
|
|||
|
if ( ( lstrcmp(FindData.cFileName, _T(".") ) == 0 ) ||
|
|||
|
( lstrcmp(FindData.cFileName, _T("..") ) == 0 ) ||
|
|||
|
( LSTRCMPI( FindData.cFileName, _T("unattend.txt") ) == 0 ) )
|
|||
|
continue;
|
|||
|
|
|||
|
if ( ! ConcatenatePaths(SrcRootPath, FindData.cFileName, NULL) ||
|
|||
|
! ConcatenatePaths(DestRootPath, FindData.cFileName, NULL) )
|
|||
|
continue;
|
|||
|
|
|||
|
if ( ! (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
|
|||
|
|
|||
|
if ( ! CopySingleFile(hwnd, SrcRootPath, DestRootPath) ) {
|
|||
|
bRet = FALSE;
|
|||
|
goto CleanupAndReturn;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Create the dir and recurse
|
|||
|
//
|
|||
|
|
|||
|
if ( ! EnsureDirExists(DestRootPath) ) {
|
|||
|
|
|||
|
UINT iRet;
|
|||
|
|
|||
|
iRet = ReportErrorId(
|
|||
|
hwnd,
|
|||
|
MSGTYPE_RETRYCANCEL | MSGTYPE_WIN32,
|
|||
|
IDS_ERR_CREATE_FOLDER,
|
|||
|
DestRootPath);
|
|||
|
|
|||
|
if ( iRet != IDRETRY ) {
|
|||
|
if ( CheckIfCancel(hwnd) ) {
|
|||
|
bRet = FALSE;
|
|||
|
goto CleanupAndReturn;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( ! CopyTheFiles(hwnd, SrcRootPath, DestRootPath) ) {
|
|||
|
bRet = FALSE;
|
|||
|
goto CleanupAndReturn;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} while ( FindNextFile(FindHandle, &FindData) );
|
|||
|
|
|||
|
CleanupAndReturn:
|
|||
|
*SrcRootPathEnd = _T('\0');
|
|||
|
*DestRootPathEnd = _T('\0');
|
|||
|
FindClose(FindHandle);
|
|||
|
|
|||
|
return bRet;
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: AsyncTreeCopy
|
|||
|
//
|
|||
|
// Purpose: The real thread entry
|
|||
|
//
|
|||
|
// Args: VOID *Args - really COPY_THREAD_PARAMS *
|
|||
|
//
|
|||
|
// Returns: 0
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
UINT AsyncTreeCopy(VOID* Args)
|
|||
|
{
|
|||
|
COPY_THREAD_PARAMS *InputArgs = (COPY_THREAD_PARAMS*) Args;
|
|||
|
|
|||
|
TCHAR *CopySrc = InputArgs->lpSourceBuffer;
|
|||
|
TCHAR *CopyDest = InputArgs->lpDestBuffer;
|
|||
|
HWND hwnd = InputArgs->hwnd;
|
|||
|
|
|||
|
BOOL bRet;
|
|||
|
LONGLONG llSpaceNeeded, llSpaceAvail;
|
|||
|
|
|||
|
//
|
|||
|
// Figure out how much disk space is needed to copy the CD.
|
|||
|
//
|
|||
|
|
|||
|
ghDiskSpaceList = SetupCreateDiskSpaceList(0, 0, 0);
|
|||
|
if (ghDiskSpaceList == NULL)
|
|||
|
{
|
|||
|
TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
|
|||
|
}
|
|||
|
|
|||
|
CountSpaceNeeded(hwnd, CopySrc, CopyDest);
|
|||
|
|
|||
|
//
|
|||
|
// Is there enough free space?
|
|||
|
//
|
|||
|
// NOTE:
|
|||
|
//
|
|||
|
// We give the user a retry_cancel, hopefully user can free up space
|
|||
|
// on the drive.
|
|||
|
//
|
|||
|
// We could popup and let them change the destpath. However, we may
|
|||
|
// have copied files on the AdditionalDirs page. So allowing them to
|
|||
|
// change the path means you need to check diskspace requirements for
|
|||
|
// OemFilesPath and treecopy it as well. If we ever allow changing
|
|||
|
// OemFilesPath, then the script would have to be updated as well,
|
|||
|
// and it has already been written out.
|
|||
|
//
|
|||
|
// We could check way back on the DistFolder page. But then we
|
|||
|
// would have to find the SourcePath before we know if it's a CD
|
|||
|
// or netpath and we couldn't know how much they might copy on the
|
|||
|
// AdditionalDirs page.
|
|||
|
//
|
|||
|
|
|||
|
llSpaceNeeded =
|
|||
|
MySetupQuerySpaceRequiredOnDrive(ghDiskSpaceList, CopyDest);
|
|||
|
|
|||
|
llSpaceAvail = MyGetDiskFreeSpace(CopyDest);
|
|||
|
|
|||
|
if ( llSpaceAvail < llSpaceNeeded ) {
|
|||
|
|
|||
|
UINT iRet;
|
|||
|
|
|||
|
iRet = ReportErrorId(
|
|||
|
hwnd,
|
|||
|
MSGTYPE_RETRYCANCEL,
|
|||
|
IDS_ERR_INSUFICIENT_SPACE,
|
|||
|
CopyDest, // ISSUE-2002-02-28-stelo-
|
|||
|
(UINT) (llSpaceNeeded / ONE_MEG),
|
|||
|
(UINT) (llSpaceAvail / ONE_MEG));
|
|||
|
|
|||
|
if ( iRet != IDRETRY ) {
|
|||
|
if ( CheckIfCancel(hwnd) )
|
|||
|
goto CleanupAndReturn;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update the message on the wizard page and start copying the files
|
|||
|
//
|
|||
|
|
|||
|
SetDlgItemText(hwnd, IDC_TEXT, StrCopyingFiles);
|
|||
|
|
|||
|
if ( CopyTheFiles(hwnd, CopySrc, CopyDest) ) {
|
|||
|
SendMessage(hwnd, WMX_ENDCOPYING, (WPARAM) 0, (LPARAM) 0);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Cleanup and return
|
|||
|
//
|
|||
|
|
|||
|
CleanupAndReturn:
|
|||
|
SetupDestroyDiskSpaceList(ghDiskSpaceList);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// This section of code runs in thread0.
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: TreeCopyNtSources
|
|||
|
//
|
|||
|
// Purpose: Entry point for copying the NT sources (either from CD or
|
|||
|
// a net path).
|
|||
|
//
|
|||
|
// The dialog proc calls this one, and it takes care of the
|
|||
|
// details of spawning the thread.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
// HWND hwnd - window to receive copy notifications (the dlgproc)
|
|||
|
// UINT Message - message to send on copy notifications (to dlgproc)
|
|||
|
// LPTSTR lpSource - root of copy source
|
|||
|
// LPTSTR lpDest - root of copy dest
|
|||
|
//
|
|||
|
// Returns: void
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// - Input strings will not be modified.
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID TreeCopyNtSources(HWND hwnd,
|
|||
|
LPTSTR lpSource,
|
|||
|
LPTSTR lpDest)
|
|||
|
{
|
|||
|
DWORD dwThreadId;
|
|||
|
HANDLE hCopyThread;
|
|||
|
|
|||
|
static COPY_THREAD_PARAMS ThreadParams;
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the ThreadParams and spawn it
|
|||
|
//
|
|||
|
|
|||
|
// NTRAID#NTBUG9-551874-2002/02/27-stelo,swamip - CreateDistFolder, ShareTheDistFolder should use the code from OEM mode, reduce attack surface
|
|||
|
lstrcpyn(ThreadParams.lpSourceBuffer, lpSource,AS(ThreadParams.lpSourceBuffer));
|
|||
|
lstrcpyn(ThreadParams.lpDestBuffer, lpDest, AS(ThreadParams.lpDestBuffer));
|
|||
|
|
|||
|
MyGetFullPath(ThreadParams.lpSourceBuffer);
|
|||
|
MyGetFullPath(ThreadParams.lpDestBuffer);
|
|||
|
|
|||
|
ThreadParams.hwnd = hwnd;
|
|||
|
|
|||
|
hCopyThread = CreateThread(NULL,
|
|||
|
0,
|
|||
|
AsyncTreeCopy,
|
|||
|
&ThreadParams,
|
|||
|
0,
|
|||
|
&dwThreadId);
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: BuildCopyDestPath
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// DestPath is assumed to be of MAX_PATH length
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
BuildCopyDestPath( IN TCHAR *DestPath, IN DWORD cbSize )
|
|||
|
{
|
|||
|
HRESULT hrCat;
|
|||
|
|
|||
|
//
|
|||
|
// If the dist folder begins with a drive letter, just use that
|
|||
|
// If it is a UNC, then build the computer and share name and use that
|
|||
|
//
|
|||
|
if( WizGlobals.UncDistFolder[0] != _T('\\') )
|
|||
|
{
|
|||
|
|
|||
|
lstrcpyn( DestPath, WizGlobals.UncDistFolder, cbSize );
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
GetComputerNameFromUnc( WizGlobals.UncDistFolder, DestPath, cbSize );
|
|||
|
|
|||
|
hrCat=StringCchCat( DestPath, cbSize, _T("\\") );
|
|||
|
hrCat=StringCchCat( DestPath, cbSize, WizGlobals.DistShareName );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
hrCat=StringCchCat( DestPath, cbSize, _T("\\") );
|
|||
|
hrCat=StringCchCat( DestPath, cbSize, WizGlobals.Architecture );
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: OnCopyFilesInitDialog
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// Arguments: IN HWND hwnd - handle to the dialog
|
|||
|
//
|
|||
|
// Returns: VOID
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
static VOID
|
|||
|
OnCopyFilesInitDialog( IN HWND hwnd )
|
|||
|
{
|
|||
|
StrBuildingList = MyLoadString( IDS_COPYMSG1 );
|
|||
|
|
|||
|
StrCopyingFiles = MyLoadString( IDS_COPYMSG2 );
|
|||
|
|
|||
|
StrFileAlreadyExists = MyLoadString( IDS_FILE_ALREADY_EXISTS );
|
|||
|
|
|||
|
StrModified = MyLoadString( IDS_MODIFIED );
|
|||
|
|
|||
|
StrBytes = MyLoadString( IDS_BYTES );
|
|||
|
|
|||
|
SetDlgItemText(hwnd, IDC_TEXT, StrBuildingList);
|
|||
|
|
|||
|
//
|
|||
|
// Load Months
|
|||
|
//
|
|||
|
|
|||
|
StrJanuary = MyLoadString( IDS_JANUARY );
|
|||
|
StrFebruary = MyLoadString( IDS_FEBRUARY );
|
|||
|
StrMarch = MyLoadString( IDS_MARCH );
|
|||
|
StrApril = MyLoadString( IDS_APRIL );
|
|||
|
StrMay = MyLoadString( IDS_MAY );
|
|||
|
StrJune = MyLoadString( IDS_JUNE );
|
|||
|
StrJuly = MyLoadString( IDS_JULY );
|
|||
|
StrAugust = MyLoadString( IDS_AUGUST );
|
|||
|
StrSeptember = MyLoadString( IDS_SEPTEMBER );
|
|||
|
StrOctober = MyLoadString( IDS_OCTOBER );
|
|||
|
StrNovember = MyLoadString( IDS_NOVEMBER );
|
|||
|
StrDecember = MyLoadString( IDS_DECEMBER );
|
|||
|
|
|||
|
rgMonthsOfYear[0] = StrJanuary;
|
|||
|
rgMonthsOfYear[1] = StrFebruary;
|
|||
|
rgMonthsOfYear[2] = StrMarch;
|
|||
|
rgMonthsOfYear[3] = StrApril;
|
|||
|
rgMonthsOfYear[4] = StrMay;
|
|||
|
rgMonthsOfYear[5] = StrJune;
|
|||
|
rgMonthsOfYear[6] = StrJuly;
|
|||
|
rgMonthsOfYear[7] = StrAugust;
|
|||
|
rgMonthsOfYear[8] = StrSeptember;
|
|||
|
rgMonthsOfYear[9] = StrOctober;
|
|||
|
rgMonthsOfYear[10] = StrNovember;
|
|||
|
rgMonthsOfYear[11] = StrDecember;
|
|||
|
|
|||
|
//
|
|||
|
// Load Days of Week
|
|||
|
//
|
|||
|
|
|||
|
StrSunday = MyLoadString( IDS_SUNDAY );
|
|||
|
StrMonday = MyLoadString( IDS_MONDAY );
|
|||
|
StrTuesday = MyLoadString( IDS_TUESDAY );
|
|||
|
StrWednesday = MyLoadString( IDS_WEDNESDAY );
|
|||
|
StrThursday = MyLoadString( IDS_THURSDAY );
|
|||
|
StrFriday = MyLoadString( IDS_FRIDAY );
|
|||
|
StrSaturday = MyLoadString( IDS_SATURDAY );
|
|||
|
|
|||
|
rgDaysOfWeek[0] = StrSunday;
|
|||
|
rgDaysOfWeek[1] = StrMonday;
|
|||
|
rgDaysOfWeek[2] = StrTuesday;
|
|||
|
rgDaysOfWeek[3] = StrWednesday;
|
|||
|
rgDaysOfWeek[4] = StrThursday;
|
|||
|
rgDaysOfWeek[5] = StrFriday;
|
|||
|
rgDaysOfWeek[6] = StrSaturday;
|
|||
|
rgDaysOfWeek[7] = StrSunday;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DlgCopyFilesPage
|
|||
|
//
|
|||
|
// Purpose: This is the dialog procedure the copy files page
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
INT_PTR CALLBACK DlgCopyFilesPage(
|
|||
|
IN HWND hwnd,
|
|||
|
IN UINT uMsg,
|
|||
|
IN WPARAM wParam,
|
|||
|
IN LPARAM lParam)
|
|||
|
{
|
|||
|
UINT nPercent;
|
|||
|
BOOL bStatus = TRUE;
|
|||
|
|
|||
|
switch (uMsg) {
|
|||
|
|
|||
|
case WM_INITDIALOG:
|
|||
|
|
|||
|
OnCopyFilesInitDialog( hwnd );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case WMX_BEGINCOPYING:
|
|||
|
{
|
|||
|
TCHAR *SrcPath;
|
|||
|
TCHAR DestPath[MAX_PATH + 1];
|
|||
|
|
|||
|
if ( WizGlobals.bCopyFromPath )
|
|||
|
SrcPath = WizGlobals.CopySourcePath;
|
|||
|
else
|
|||
|
SrcPath = WizGlobals.CdSourcePath;
|
|||
|
|
|||
|
SendDlgItemMessage(hwnd,
|
|||
|
IDC_PROGRESS1,
|
|||
|
PBM_SETPOS,
|
|||
|
0,
|
|||
|
0);
|
|||
|
|
|||
|
BuildCopyDestPath( DestPath, AS(DestPath) );
|
|||
|
|
|||
|
TreeCopyNtSources(hwnd,
|
|||
|
SrcPath,
|
|||
|
DestPath);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case WMX_ENDCOPYING:
|
|||
|
|
|||
|
SendDlgItemMessage(hwnd,
|
|||
|
IDC_PROGRESS1,
|
|||
|
PBM_SETPOS,
|
|||
|
(WPARAM) 100,
|
|||
|
0);
|
|||
|
|
|||
|
PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
|
|||
|
|
|||
|
//
|
|||
|
// The CD is done copying so Auto-Advance to the next page
|
|||
|
//
|
|||
|
|
|||
|
// ISSUE-2002/02/28-stelo- this works, but I should really go through
|
|||
|
// RouteToProperPage or send a NEXT message but neither work
|
|||
|
PostMessage( GetParent(hwnd),
|
|||
|
PSM_SETCURSELID,
|
|||
|
(WPARAM) 0,
|
|||
|
(LPARAM) IDD_FINISH );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case WMX_FILECOPIED:
|
|||
|
nPercent = (gnFilesCopied * 100) / gnTotalFiles;
|
|||
|
SendDlgItemMessage(hwnd,
|
|||
|
IDC_PROGRESS1,
|
|||
|
PBM_SETPOS,
|
|||
|
(WPARAM) nPercent,
|
|||
|
0);
|
|||
|
break;
|
|||
|
|
|||
|
case WM_NOTIFY:
|
|||
|
{
|
|||
|
LPNMHDR pnmh = (LPNMHDR)lParam;
|
|||
|
switch( pnmh->code ) {
|
|||
|
|
|||
|
case PSN_QUERYCANCEL:
|
|||
|
CancelTheWizard(hwnd);
|
|||
|
break;
|
|||
|
|
|||
|
case PSN_SETACTIVE:
|
|||
|
PropSheet_SetWizButtons(GetParent(hwnd), 0);
|
|||
|
PostMessage(hwnd, WMX_BEGINCOPYING, 0, 0);
|
|||
|
break;
|
|||
|
|
|||
|
// Can't go back in the wizard from here
|
|||
|
case PSN_WIZBACK:
|
|||
|
break;
|
|||
|
|
|||
|
case PSN_WIZNEXT:
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
bStatus = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
bStatus = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
return bStatus;
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: ConfirmFileReplaceDlgProc
|
|||
|
//
|
|||
|
// Purpose: Confirm file replace dialog proc. Allows the user to chose to
|
|||
|
// overwrite the file, overwrite all files, do not overwrite or cancel the
|
|||
|
// copy all together. Runs in the copying thread's context
|
|||
|
//
|
|||
|
// Arguments: standard Win32 dialog proc arguments
|
|||
|
//
|
|||
|
// Returns: the button the user pressed(Yes, Yes to All, No, Cancel)
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
INT_PTR CALLBACK
|
|||
|
ConfirmFileReplaceDlgProc( IN HWND hwnd,
|
|||
|
IN UINT uMsg,
|
|||
|
IN WPARAM wParam,
|
|||
|
IN LPARAM lParam ) {
|
|||
|
|
|||
|
BOOL bStatus = TRUE;
|
|||
|
|
|||
|
switch( uMsg ) {
|
|||
|
|
|||
|
case WM_INITDIALOG: {
|
|||
|
|
|||
|
SetWindowText( GetDlgItem( hwnd, IDC_REPLACE_FILE_TEXT),
|
|||
|
g_szFileAlreadyExistsText );
|
|||
|
|
|||
|
SetWindowText( GetDlgItem( hwnd, IDC_SRC_FILE_DATE),
|
|||
|
g_szSrcFileDate );
|
|||
|
|
|||
|
SetWindowText( GetDlgItem( hwnd, IDC_SRC_FILE_SIZE),
|
|||
|
g_szSrcFileSize );
|
|||
|
|
|||
|
SetWindowText( GetDlgItem( hwnd, IDC_DEST_FILE_DATE),
|
|||
|
g_szDestFileDate );
|
|||
|
|
|||
|
SetWindowText( GetDlgItem( hwnd, IDC_DEST_FILE_SIZE),
|
|||
|
g_szDestFileSize );
|
|||
|
|
|||
|
if( g_SetFocusYes ) {
|
|||
|
SetFocus( GetDlgItem( hwnd, IDC_YES_BUTTON ) );
|
|||
|
}
|
|||
|
else {
|
|||
|
SetFocus( GetDlgItem( hwnd, IDC_NO_BUTTON ) );
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
case WM_COMMAND: {
|
|||
|
|
|||
|
int nButtonId = LOWORD( wParam );
|
|||
|
|
|||
|
switch ( nButtonId ) {
|
|||
|
|
|||
|
case IDC_YES_BUTTON:
|
|||
|
{
|
|||
|
EndDialog( hwnd, YES );
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IDC_YESTOALL:
|
|||
|
{
|
|||
|
EndDialog( hwnd, YESTOALL );
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IDC_NO_BUTTON:
|
|||
|
{
|
|||
|
EndDialog( hwnd, NO );
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IDC_NOTOALL:
|
|||
|
{
|
|||
|
EndDialog( hwnd, NOTOALL );
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IDCANCEL:
|
|||
|
{
|
|||
|
if( CheckIfCancel( hwnd ) )
|
|||
|
{
|
|||
|
EndDialog( hwnd, CANCEL );
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
bStatus = FALSE;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return( bStatus );
|
|||
|
|
|||
|
}
|