1071 lines
32 KiB
C
1071 lines
32 KiB
C
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
COPYFILE.C
|
||
|
||
Abstract:
|
||
|
||
file copy conf. dialog
|
||
|
||
Author:
|
||
|
||
Bob Watson (a-robw)
|
||
|
||
Revision History:
|
||
|
||
17 Feb 94 Written
|
||
|
||
--*/
|
||
//
|
||
// Windows Include Files
|
||
//
|
||
|
||
#include <windows.h>
|
||
#include <stdio.h>
|
||
#include <malloc.h>
|
||
#include <tchar.h> // unicode macros
|
||
//
|
||
// app include files
|
||
//
|
||
#include "otnboot.h"
|
||
#include "otnbtdlg.h"
|
||
//
|
||
// Debugging defines
|
||
//
|
||
#define SHOW_DEBUG_INFO 0
|
||
|
||
// local windows message
|
||
|
||
#define NCDU_START_FILE_COPY (WM_USER +101)
|
||
|
||
//
|
||
// Static data for this module
|
||
//
|
||
static BOOL bCopying; // 1= copying, 0 = done
|
||
static DWORD dwBytesCopied; // running total of bytes copied
|
||
static DWORD dwTotalCBytes; // total bytes divided by 100 (for % computation)
|
||
static DWORD dwCurrentPercent; // current percent copied
|
||
|
||
#define MAX_DOS_FILENAME_LENGTH (8 * sizeof(TCHAR))
|
||
#define MAX_DOS_FILE_EXT_LENGTH (3 * sizeof(TCHAR))
|
||
|
||
static
|
||
BOOL
|
||
DisplayScrunchedFilePath (
|
||
IN HWND hWnd,
|
||
IN LPCTSTR szInPath
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
sets the window text of hWnd to be the "scrunched" version of
|
||
the path string in szInPath. If the path string is too long
|
||
to fit in a single line of hWnd, then directories are removed
|
||
from the path until it does fit. The directories are removed
|
||
from the "top" down. The root drive\dir is kept as is the
|
||
filename and as many directories that will fit.
|
||
|
||
Arguments:
|
||
|
||
IN HWND hWnd
|
||
handle of window to put text in
|
||
|
||
IN LPCTSTR szInPath
|
||
path to display in window
|
||
|
||
Return Value:
|
||
|
||
TRUE if no error
|
||
FALSE if error
|
||
|
||
--*/
|
||
{
|
||
LPTSTR szOutPath;
|
||
RECT rWindow;
|
||
LONG lWindowWidth;
|
||
HDC hDC;
|
||
SIZE sText;
|
||
LONG lRootBs, lRootBsCount;
|
||
|
||
LPTSTR szRootBs, szFileBs, szSrc, szDest, szDotsBs;
|
||
|
||
GetWindowRect (hWnd, &rWindow); // get window size
|
||
lWindowWidth = rWindow.right - rWindow.left;
|
||
|
||
hDC = GetDC (hWnd); // get DC for window
|
||
|
||
szOutPath = GlobalAlloc (GPTR, ((lstrlen(szInPath) + 8) * sizeof(TCHAR)));
|
||
if (szOutPath == NULL) {
|
||
return FALSE;
|
||
} else {
|
||
//buffer allocation succeeded, so copy path to local buffer
|
||
lstrcpy (szOutPath, szInPath);
|
||
}
|
||
|
||
if (IsUncPath(szOutPath)) {
|
||
lRootBs = 4; // the 4th backslash is the "Root" backslash for UNC
|
||
} else {
|
||
lRootBs = 1; // for DOS file paths, the 1st backslash is the Root
|
||
}
|
||
|
||
GetTextExtentPoint32(hDC,
|
||
szOutPath, lstrlen(szOutPath), &sText);
|
||
|
||
szSrc = szDest = szOutPath;
|
||
szDotsBs = szRootBs = szFileBs = NULL;
|
||
lRootBsCount = 0;
|
||
|
||
while (sText.cx > lWindowWidth) {
|
||
// take dirs out until it fits
|
||
// go through path string
|
||
while (*szSrc != 0) {
|
||
// see if we've passed the root
|
||
if (szRootBs == NULL) {
|
||
if (*szSrc == cBackslash) lRootBsCount++;
|
||
if (lRootBsCount == lRootBs) szDotsBs = szRootBs = szDest;
|
||
} else {
|
||
// root's done, now were; working on the pathname
|
||
// so we'll scope out the rest of the string
|
||
if (*szSrc == cBackslash) szFileBs = szDest;
|
||
}
|
||
*szDest++ = *szSrc++;
|
||
}
|
||
if (szRootBs == NULL) {
|
||
// then this is a bogus path so exit now
|
||
break;
|
||
}
|
||
if (szFileBs == NULL) {
|
||
// if the File backslash didn't get defined, then the file is
|
||
// in the root directory and we should leave now, since there
|
||
// isn't much to do about it.
|
||
szFileBs = szRootBs;
|
||
break;
|
||
}
|
||
// now yank a dir or two (more than one will be pulled if the dir
|
||
// name is < 4 chars
|
||
// if a directory hasn't been pulled, yet, go ahead
|
||
// and take one out
|
||
// initialize the pointers
|
||
if (szRootBs == szDotsBs) {
|
||
// then the ... havent been added so see if they'll fit and add em
|
||
if ((szDotsBs+4) < szFileBs) {
|
||
// they'll fit so addem
|
||
szDest = szDotsBs + 1;
|
||
*szDest++ = cPeriod;
|
||
*szDest++ = cPeriod;
|
||
*szDest++ = cPeriod;
|
||
*szDest = cBackslash;
|
||
szDotsBs = szDest;
|
||
szSrc = ++szDest;
|
||
} else {
|
||
// no room to left to pull files
|
||
break;
|
||
}
|
||
} else {
|
||
// dot's have already been added so set pointers
|
||
szSrc = szDest = szDotsBs+1;
|
||
}
|
||
// go to next dir
|
||
while (*szSrc++ != cBackslash);
|
||
// copy the rest of the string
|
||
while (*szSrc != 0) *szDest++ = *szSrc++;
|
||
|
||
*szDest = 0; // terminate the new string
|
||
|
||
// get size of new string
|
||
GetTextExtentPoint32(hDC,
|
||
szOutPath, lstrlen(szOutPath), &sText);
|
||
}
|
||
|
||
// the string is as small as it's going to get so set the window text
|
||
|
||
SetWindowText (hWnd, szOutPath);
|
||
|
||
FREE_IF_ALLOC (szOutPath);
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
LONG
|
||
CreateDirectoryFromPath (
|
||
IN LPCTSTR szPath,
|
||
IN LPSECURITY_ATTRIBUTES lpSA
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates the directory specified in szPath and any other "higher"
|
||
directories in the specified path that don't exist.
|
||
|
||
Arguments:
|
||
|
||
IN LPCTSTR szPath
|
||
directory path to create (assumed to be a DOS path, not a UNC)
|
||
|
||
IN LPSECURITY_ATTRIBUTES lpSA
|
||
pointer to security attributes argument used by CreateDirectory
|
||
|
||
|
||
Return Value:
|
||
|
||
TRUE if directory(ies) created
|
||
FALSE if error (GetLastError to find out why)
|
||
|
||
--*/
|
||
{
|
||
LPTSTR szLocalPath;
|
||
LPTSTR szEnd;
|
||
LONG lReturn = 0L;
|
||
|
||
szLocalPath = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
|
||
|
||
if (szLocalPath == NULL) {
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return FALSE;
|
||
} else {
|
||
// so far so good...
|
||
SetLastError (ERROR_SUCCESS); // initialize error value to SUCCESS
|
||
}
|
||
|
||
lstrcpy (szLocalPath, szPath);
|
||
|
||
szEnd = &szLocalPath[3];
|
||
|
||
if (*szEnd != 0) {
|
||
// then there are sub dirs to create
|
||
while (*szEnd != 0) {
|
||
// go to next backslash
|
||
while ((*szEnd != cBackslash) && (*szEnd != 0)) szEnd++;
|
||
if (*szEnd == cBackslash) {
|
||
// terminate path here and create directory
|
||
*szEnd = 0;
|
||
if (!CreateDirectory (szLocalPath, lpSA)) {
|
||
// see what the error was and "adjust" it if necessary
|
||
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
||
// this is OK
|
||
SetLastError (ERROR_SUCCESS);
|
||
} else {
|
||
lReturn = 0;
|
||
}
|
||
} else {
|
||
// directory created successfully so update count
|
||
lReturn++;
|
||
}
|
||
// replace backslash and go to next dir
|
||
*szEnd++ = cBackslash;
|
||
}
|
||
}
|
||
// create last dir in path now
|
||
if (!CreateDirectory (szLocalPath, lpSA)) {
|
||
// see what the error was and "adjust" it if necessary
|
||
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
||
// this is OK
|
||
SetLastError (ERROR_SUCCESS);
|
||
lReturn++;
|
||
} else {
|
||
lReturn = 0;
|
||
}
|
||
} else {
|
||
// directory created successfully
|
||
lReturn++;
|
||
}
|
||
} else {
|
||
#ifndef TERMSRV
|
||
// else this is a root dir only so return success.
|
||
lReturn = 1;
|
||
#else // TERMSRV
|
||
// for terminal server return FALSE.
|
||
lReturn = 0;
|
||
#endif // TERMSRV
|
||
|
||
}
|
||
FREE_IF_ALLOC (szLocalPath);
|
||
return lReturn;
|
||
|
||
}
|
||
|
||
static
|
||
DWORD
|
||
UpdatePercentComplete (
|
||
IN HWND hwndDlg,
|
||
IN LPCTSTR szFileName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds the size of the specified file to the running total of
|
||
bytes copied and computes the current percentage of total
|
||
copied. The display string is updated if the new percentage is
|
||
different from the current percentage
|
||
|
||
Arguments:
|
||
|
||
IN HWND hwndDlg
|
||
Handle to dialog Box window
|
||
|
||
IN LPTSTR szFileName
|
||
filename (& path) of file whose size should be added to the
|
||
current total bytes copied value.
|
||
|
||
Return Value:
|
||
|
||
returns the current percentage of total bytes that have been
|
||
copied (including this file)
|
||
|
||
--*/
|
||
{
|
||
HANDLE hFile;
|
||
|
||
DWORD dwFileSizeLow, dwFileSizeHigh;
|
||
DWORD dwPercent = 0;
|
||
|
||
LPTSTR szOutBuff;
|
||
|
||
szOutBuff = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
|
||
|
||
if (szOutBuff == NULL) return 0;
|
||
|
||
if (dwTotalCBytes == 0) {
|
||
SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE,
|
||
GetStringResource (FMT_WORKING));
|
||
dwPercent = 0;
|
||
} else {
|
||
hFile = CreateFile (
|
||
szFileName,
|
||
GENERIC_READ,
|
||
(FILE_SHARE_READ | FILE_SHARE_WRITE),
|
||
NULL,
|
||
OPEN_EXISTING,
|
||
FILE_ATTRIBUTE_NORMAL,
|
||
NULL);
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE) {
|
||
dwFileSizeLow = GetFileSize (hFile, &dwFileSizeHigh);
|
||
if (dwFileSizeLow != 0xFFFFFFFF) {
|
||
dwBytesCopied += dwFileSizeLow;
|
||
dwPercent = dwBytesCopied / dwTotalCBytes;
|
||
if (dwPercent != dwCurrentPercent) {
|
||
if (dwPercent > 100) dwPercent = 100;
|
||
dwCurrentPercent = dwPercent;
|
||
_stprintf (szOutBuff,
|
||
GetStringResource (FMT_PERCENT_COMPLETE),
|
||
dwPercent);
|
||
SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE, szOutBuff);
|
||
}
|
||
}
|
||
CloseHandle (hFile);
|
||
}
|
||
}
|
||
|
||
FREE_IF_ALLOC (szOutBuff);
|
||
|
||
return dwPercent;
|
||
}
|
||
|
||
static
|
||
BOOL
|
||
IsDosFileName (
|
||
LPCTSTR szName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
examines string to see if it conforms to the DOS filename length
|
||
conventions
|
||
|
||
Arguments:
|
||
|
||
szName filename and extension to parse
|
||
|
||
|
||
Return Value:
|
||
|
||
TRUE if it passes
|
||
FALSE if not
|
||
|
||
--*/
|
||
{
|
||
LPTSTR szNameBegin, szNameEnd;
|
||
LPTSTR szExtBegin, szExtEnd;
|
||
LPTSTR szDot;
|
||
LPTSTR szTmp;
|
||
LPTSTR szBack_slash;
|
||
|
||
|
||
szBack_slash = szDot = NULL;
|
||
szTmp = (LPTSTR)szName;
|
||
|
||
while (*szTmp) {
|
||
if (*szTmp == '.') szDot = szTmp;
|
||
if (*szTmp == '\\') szBack_slash = szTmp;
|
||
szTmp++;
|
||
}
|
||
|
||
// find beginning and end of each component
|
||
|
||
if (szBack_slash) {
|
||
// backslash char found in string, pointer points to
|
||
// last occurance, name starts immediately after
|
||
szNameBegin = szBack_slash + 1;
|
||
} else {
|
||
// no backslash char found so name starts at beginning
|
||
// of string
|
||
szNameBegin = (LPTSTR)szName;
|
||
}
|
||
|
||
if (szDot) {
|
||
// dot char found in string
|
||
if (szDot == szName) {
|
||
// it's the first char in the string (i.e.
|
||
// no filename)
|
||
szNameEnd = (LPTSTR)szName;
|
||
// a dot was found, then the extension starts right
|
||
// after the dot
|
||
szExtBegin = szDot + 1;
|
||
} else if (szDot < szNameBegin) {
|
||
// then there's no dot in the filename, but
|
||
// it's somewhere else in the path
|
||
szNameEnd = szTmp;
|
||
// no dot so ext "begins" at the end of the string
|
||
szExtBegin = szTmp;
|
||
} else {
|
||
// not the first char, and not before the filename
|
||
// so the name ends with the dot
|
||
szNameEnd = szDot;
|
||
// a dot was found, then the extension starts right
|
||
// after the dot
|
||
szExtBegin = szDot + 1;
|
||
}
|
||
} else {
|
||
// no dot was found in the string so there's no
|
||
// file extension in this string. The end of the string
|
||
// must be the end of the file name , and the beginning of
|
||
// the extension (and also the end of the extension)
|
||
szNameEnd = szTmp;
|
||
szExtBegin = szTmp;
|
||
}
|
||
|
||
// the end of the file extension is always the end of the string
|
||
szExtEnd = szTmp;
|
||
|
||
// check the components for correct length:
|
||
// 0 <= filename <= MAX_DOS_FILENAME_LENGTH (8)
|
||
// 0 <= ext <= MAX_DOS_FILE_EXT_LENGTH (3)
|
||
|
||
if ((LONG)(szNameEnd-szNameBegin) <= MAX_DOS_FILENAME_LENGTH) {
|
||
// name is ok, check extension
|
||
if ((LONG)(szExtEnd-szExtBegin) <= MAX_DOS_FILE_EXT_LENGTH) {
|
||
return TRUE;
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
static
|
||
LONG
|
||
CopyDir (
|
||
IN HWND hwndDlg,
|
||
IN LPCTSTR szFromDir,
|
||
IN LPCTSTR szToDir,
|
||
IN DWORD dwFlags,
|
||
IN PDWORD pdwFiles,
|
||
IN PDWORD pdwDirs
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copies all files in the specified from directory to the specified
|
||
to directory. Specific behavior is controlled by the flags as
|
||
documented below.
|
||
|
||
Arguments:
|
||
|
||
hwndDlg window handle to dialog box
|
||
szFromDir directory containing files to copy
|
||
szToDir directory to recieve files
|
||
dwFlags Flags that control routine's behavior
|
||
|
||
CD_FLAGS_COPY_SUB_DIR copies all sub dir's as well
|
||
CD_FLAGS_DONT_CREATE default is to create dirs as needed
|
||
CD_FLAGS_IGNORE_ATTR ignore attributes
|
||
CD_FLAGS_COPY_ATTR copy attributes as well (default
|
||
is for dest fils to be normal)
|
||
CD_FLAGS_IGNORE_ERROR continue with copy even if errors occur
|
||
CD_FLAGS_LONG_NAMES allows filenames longer than FAT
|
||
other bits are ignored
|
||
pdwFiles Pointer to DWORD that will get count of files copied
|
||
pdwDirs Pointer to DWORD that will get count of dirs created
|
||
|
||
Return Value:
|
||
|
||
Win 32 status value
|
||
ERROR_SUCCESS routine completed normally
|
||
|
||
--*/
|
||
{
|
||
LPTSTR szFromPathName; // full path of FromDir
|
||
LPTSTR szFromFileName; // full path of source file
|
||
LPTSTR szFromFileStart; // pointer to where to attach file name to path
|
||
LPTSTR szSearchName; // search file name
|
||
LPTSTR szToPathName; // full path of destdir
|
||
LPTSTR szToFileName; // full path of detination file name
|
||
LPTSTR szToFileStart; // pointer to where to attach file name to path
|
||
|
||
DWORD dwFileAttributes; // attributes of source file
|
||
|
||
PWIN32_FIND_DATA pwfdSearchData; // buffer used for file find ops
|
||
HANDLE hSearch;
|
||
|
||
int nMbResult;
|
||
|
||
BOOL bStatus;
|
||
LONG lStatus;
|
||
|
||
MSG msg;
|
||
|
||
DWORD dwFileCopyCount; // local counter variables
|
||
DWORD dwDirCreateCount;
|
||
|
||
|
||
// allocate buffers
|
||
|
||
szFromPathName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
|
||
szFromFileName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
|
||
szSearchName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
|
||
szToPathName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
|
||
szToFileName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH * sizeof(TCHAR));
|
||
pwfdSearchData = (PWIN32_FIND_DATA)GlobalAlloc (GPTR, sizeof(WIN32_FIND_DATA));
|
||
|
||
if (szFromPathName &&
|
||
szFromFileName &&
|
||
szSearchName &&
|
||
szToPathName &&
|
||
szToFileName &&
|
||
pwfdSearchData) {
|
||
|
||
// initialize counter fields (to support recursive calls)
|
||
|
||
if (pdwFiles != NULL) {
|
||
dwFileCopyCount = *pdwFiles;
|
||
} else {
|
||
dwFileCopyCount = 0;
|
||
}
|
||
|
||
if (pdwDirs != NULL) {
|
||
dwDirCreateCount = *pdwDirs;
|
||
} else {
|
||
dwDirCreateCount = 0;
|
||
}
|
||
// get full pathnames of from & to files
|
||
|
||
GetFullPathName (
|
||
szFromDir,
|
||
(DWORD)GlobalSize(szFromPathName) / sizeof(TCHAR),
|
||
szFromPathName,
|
||
NULL);
|
||
|
||
GetFullPathName (
|
||
szToDir,
|
||
(DWORD)GlobalSize(szToPathName) / sizeof(TCHAR),
|
||
szToPathName,
|
||
NULL);
|
||
|
||
lStatus = ERROR_SUCCESS;
|
||
} else {
|
||
lStatus = ERROR_OUTOFMEMORY;
|
||
}
|
||
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
// validate from dir and create target if valid
|
||
|
||
dwFileAttributes = QuietGetFileAttributes (
|
||
szFromPathName);
|
||
|
||
if ((dwFileAttributes != 0xFFFFFFFF) &&
|
||
(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||
// from directory is for real so create or check
|
||
// target dir now
|
||
|
||
if (dwFlags & CD_FLAGS_DONT_CREATE) {
|
||
// if don't create, then at least validate
|
||
dwFileAttributes = QuietGetFileAttributes (
|
||
szToPathName);
|
||
|
||
if ((dwFileAttributes != 0xFFFFFFFF) &&
|
||
(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||
lStatus = ERROR_SUCCESS;
|
||
} else {
|
||
lStatus = ERROR_DIRECTORY;
|
||
}
|
||
} else {
|
||
// create sub dirs if necessary
|
||
if (!(dwFlags & CD_FLAGS_LONG_NAMES)) {
|
||
// check to see if name conforms to DOS 8.3 format
|
||
if (!IsDosFileName(szFromPathName)) {
|
||
lStatus = ERROR_FILENAME_EXCED_RANGE;
|
||
} else {
|
||
lStatus = ERROR_SUCCESS;
|
||
}
|
||
|
||
} else {
|
||
lStatus = ERROR_SUCCESS;
|
||
}
|
||
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
lStatus = CreateDirectoryFromPath (
|
||
szToPathName, NULL);
|
||
if (lStatus == 0) {
|
||
lStatus = GetLastError();
|
||
if (lStatus == ERROR_ALREADY_EXISTS) {
|
||
// this is OK
|
||
lStatus = ERROR_SUCCESS;
|
||
// no dirs were created so don't change the
|
||
// count.
|
||
}
|
||
} else {
|
||
// if lStatus is not 0, then it's then number of
|
||
// directories that were created
|
||
dwDirCreateCount += lStatus;
|
||
// now set it to the Error Status value the rest of the function
|
||
// is expecting
|
||
lStatus = ERROR_SUCCESS;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
lStatus = ERROR_DIRECTORY;
|
||
}
|
||
}
|
||
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
// if target directory is valid, then
|
||
// create filename bases and start copying files
|
||
|
||
lstrcpy (szFromFileName, szFromPathName);
|
||
if (szFromFileName[lstrlen(szFromFileName)-1] != cBackslash) lstrcat (szFromFileName, cszBackslash);
|
||
szFromFileStart = szFromFileName + lstrlen(szFromFileName);
|
||
|
||
lstrcpy (szToFileName, szToPathName);
|
||
if (szToFileName[lstrlen(szToFileName)-1] != cBackslash) lstrcat (szToFileName, cszBackslash);
|
||
szToFileStart = szToFileName + lstrlen(szToFileName);
|
||
|
||
// create search name
|
||
|
||
lstrcpy (szSearchName, szFromPathName);
|
||
lstrcat (szSearchName, cszWildcardFile);
|
||
|
||
hSearch = FindFirstFile (
|
||
szSearchName,
|
||
pwfdSearchData);
|
||
|
||
if (hSearch != INVALID_HANDLE_VALUE) {
|
||
lStatus = ERROR_SUCCESS;
|
||
bStatus = TRUE;
|
||
while (((lStatus == ERROR_SUCCESS) && bStatus) && bCopying) {
|
||
// check & save file attributes of each file, if not
|
||
// normal, then ignore unless flag set
|
||
//
|
||
lstrcpy (szFromFileStart, pwfdSearchData->cFileName); //make full path
|
||
|
||
if (!DotOrDotDotDir(pwfdSearchData->cFileName)) { //ignore these dirs
|
||
dwFileAttributes = QuietGetFileAttributes(
|
||
szFromFileName);
|
||
|
||
if (dwFileAttributes != 0xFFFFFFFF) {
|
||
// attributes are valid, so
|
||
// make full pathname of source file found
|
||
// and dest. file to be created
|
||
lstrcpy (szToFileStart, pwfdSearchData->cFileName); //make full path
|
||
|
||
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||
// if it's a dir and subdirs is true, then
|
||
// copy them too if the copy sub dir flag is set
|
||
|
||
if (dwFlags & CD_FLAGS_COPY_SUB_DIR) {
|
||
lStatus = CopyDir (
|
||
hwndDlg,
|
||
szFromFileName,
|
||
szToFileName,
|
||
dwFlags,
|
||
&dwFileCopyCount,
|
||
&dwDirCreateCount);
|
||
} else {
|
||
// ignore directories if flag not set
|
||
}
|
||
} else { // not a dir, so see if we can copy it
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
// copy the file if either the ignore bit is
|
||
// set or the attributes are OK
|
||
//
|
||
if (!(dwFlags & CD_FLAGS_LONG_NAMES)) {
|
||
// check to see if name conforms to DOS 8.3 format
|
||
if (!IsDosFileName(szFromFileName)) {
|
||
lStatus = ERROR_FILENAME_EXCED_RANGE;
|
||
} else {
|
||
lStatus = ERROR_SUCCESS;
|
||
}
|
||
}
|
||
|
||
DisplayScrunchedFilePath (
|
||
GetDlgItem (hwndDlg, NCDU_FROM_PATH),
|
||
(LPCTSTR)_tcslwr(szFromFileName));
|
||
|
||
DisplayScrunchedFilePath (
|
||
GetDlgItem (hwndDlg, NCDU_TO_PATH),
|
||
(LPCTSTR)_tcslwr(szToFileName));
|
||
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
bStatus = CopyFile(
|
||
szFromFileName,
|
||
szToFileName,
|
||
FALSE); // overwrite existing file
|
||
|
||
//verify file was created
|
||
if (bStatus) {
|
||
if (QuietGetFileAttributes(szToFileName) == 0xFFFFFFFF) {
|
||
// unable to read attributes of created file
|
||
// so return error
|
||
lStatus = ERROR_CANNOT_MAKE;
|
||
}
|
||
} else {
|
||
// get copy error
|
||
lStatus = BOOL_TO_STATUS (bStatus);
|
||
}
|
||
}
|
||
|
||
// if copy successful reset source file attributes
|
||
// and optionally destination file attributes
|
||
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
// set file attributes to NORMAL
|
||
SetFileAttributes (
|
||
szToFileName,
|
||
FILE_ATTRIBUTE_NORMAL);
|
||
// update filesize
|
||
UpdatePercentComplete(hwndDlg, szFromFileName);
|
||
// update count
|
||
dwFileCopyCount++;
|
||
} else {
|
||
// bail out here since there was a copy error
|
||
nMbResult = MessageBox (
|
||
hwndDlg,
|
||
GetStringResource (CSZ_UNABLE_COPY),
|
||
szFromFileName,
|
||
MB_OKCANCEL_TASK_EXCL);
|
||
if (nMbResult == IDCANCEL) {
|
||
bCopying = FALSE;
|
||
}
|
||
// the error has already been handled so return
|
||
// success to prevent the calling routine from
|
||
// signalling this error
|
||
lStatus = ERROR_SUCCESS;
|
||
}
|
||
|
||
// check for messages
|
||
|
||
while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
|
||
TranslateMessage (&msg);
|
||
DispatchMessage (&msg);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
lStatus = GetLastError();
|
||
}
|
||
}
|
||
|
||
if (dwFlags & CD_FLAGS_IGNORE_ERROR) {
|
||
// if ignore error, then set to success
|
||
lStatus = ERROR_SUCCESS;
|
||
}
|
||
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
bStatus = FindNextFile (
|
||
hSearch,
|
||
pwfdSearchData);
|
||
} else {
|
||
bStatus = FALSE; // abort loop
|
||
}
|
||
} // end while files in dir
|
||
FindClose (hSearch);
|
||
} else {
|
||
// invalid find handle so return error
|
||
lStatus = GetLastError();
|
||
}
|
||
} // end of valid directory block
|
||
|
||
FREE_IF_ALLOC(szFromPathName);
|
||
FREE_IF_ALLOC(szFromFileName);
|
||
FREE_IF_ALLOC(szSearchName);
|
||
FREE_IF_ALLOC(szToPathName);
|
||
FREE_IF_ALLOC(szToFileName);
|
||
FREE_IF_ALLOC(pwfdSearchData);
|
||
|
||
// set the counter fields if they were passed in
|
||
|
||
if (pdwFiles != NULL) {
|
||
*pdwFiles = dwFileCopyCount;
|
||
}
|
||
|
||
if (pdwDirs != NULL) {
|
||
*pdwDirs = dwDirCreateCount;
|
||
}
|
||
|
||
return lStatus;
|
||
}
|
||
|
||
static
|
||
BOOL
|
||
CopyFileDlg_NCDU_START_FILE_COPY (
|
||
IN HWND hwndDlg,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Formats values from Dialog Box parameter structure to argument list of
|
||
copy directory function
|
||
|
||
Arguments:
|
||
|
||
IN HWND hwndDlg
|
||
handle to dialog box window
|
||
|
||
IN WPARAM wParam
|
||
Not Used
|
||
|
||
IN LPARAM lParam
|
||
address of copy file structure.
|
||
|
||
Return Value:
|
||
|
||
FALSE, always
|
||
|
||
--*/
|
||
{
|
||
PCF_DLG_DATA pCF;
|
||
|
||
pCF = (PCF_DLG_DATA)lParam;
|
||
|
||
#if SHOW_DEBUG_INFO
|
||
// debug message box
|
||
{
|
||
LPTSTR szMessageBuffer;
|
||
DWORD dwSourceAttr, dwDestAttr;
|
||
UINT nMbReturn;
|
||
|
||
szMessageBuffer = GlobalAlloc (GPTR, SMALL_BUFFER_SIZE);
|
||
if (szMessageBuffer != NULL) {
|
||
dwSourceAttr = QuietGetFileAttributes (pCF->szSourceDir);
|
||
dwDestAttr = QuietGetFileAttributes (pCF->szDestDir);
|
||
_stprintf (szMessageBuffer,
|
||
fmtPrepareToCopy,
|
||
pCF->szDisplayName,
|
||
pCF->szSourceDir, dwSourceAttr,
|
||
pCF->szDestDir, dwDestAttr,
|
||
pCF->dwCopyFlags);
|
||
nMbReturn = MessageBox (hwndDlg,
|
||
szMessageBuffer,
|
||
cszDebug,
|
||
MB_OKCANCEL_TASK_INFO);
|
||
FREE_IF_ALLOC (szMessageBuffer);
|
||
} else {
|
||
nMbReturn = IDOK;
|
||
}
|
||
|
||
if (nMbReturn == IDCANCEL) {
|
||
// then bail here
|
||
EndDialog (hwndDlg, IDCANCEL);
|
||
return TRUE;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
if (CopyDir (
|
||
hwndDlg,
|
||
pCF->szSourceDir,
|
||
pCF->szDestDir,
|
||
pCF->dwCopyFlags,
|
||
&pCF->dwFilesCopied,
|
||
&pCF->dwDirsCreated) != ERROR_SUCCESS) {
|
||
|
||
// display error message
|
||
DisplayMessageBox (
|
||
hwndDlg,
|
||
CSZ_COPY_ERROR,
|
||
0L,
|
||
MB_OK_TASK_EXCL);
|
||
bCopying = FALSE; // to indicate error or non-completion
|
||
|
||
}
|
||
|
||
EndDialog (hwndDlg, (bCopying ? IDOK : IDCANCEL));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static
|
||
BOOL
|
||
CopyFileDlg_WM_INITDIALOG (
|
||
IN HWND hwndDlg,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog box initialization routine.
|
||
|
||
Arguments:
|
||
|
||
IN HWND hwndDlg
|
||
Handle to dialog box window
|
||
|
||
IN WPARAM wParam
|
||
not used
|
||
|
||
IN LPARAM lParam
|
||
address of Copy file data structure passed by calling routine.
|
||
|
||
Return Value:
|
||
|
||
FALSE if valid param block address
|
||
TRUE if not
|
||
|
||
--*/
|
||
{
|
||
PCF_DLG_DATA pCF;
|
||
|
||
pCF = (PCF_DLG_DATA)lParam;
|
||
|
||
if (pCF != NULL) {
|
||
// intialize Global data
|
||
bCopying = TRUE;
|
||
|
||
dwBytesCopied = 0;
|
||
dwCurrentPercent = 0;
|
||
dwTotalCBytes = (pCF->dwTotalSize + 50) / 100;
|
||
|
||
PositionWindow (hwndDlg);
|
||
SetDlgItemText (hwndDlg, NCDU_COPY_APPNAME, pCF->szDisplayName);
|
||
SetDlgItemText (hwndDlg, NCDU_FROM_PATH, cszEmptyString);
|
||
SetDlgItemText (hwndDlg, NCDU_TO_PATH, cszEmptyString);
|
||
SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE,
|
||
GetStringResource (FMT_ZERO_PERCENT_COMPLETE));
|
||
SetFocus (GetDlgItem(hwndDlg, IDCANCEL));
|
||
// start copying files
|
||
PostMessage (hwndDlg, NCDU_START_FILE_COPY, 0, lParam);
|
||
return FALSE;
|
||
} else {
|
||
// illegal parameter
|
||
EndDialog (hwndDlg, IDCANCEL);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
static
|
||
BOOL
|
||
CopyFileDlg_WM_COMMAND (
|
||
IN HWND hwndDlg,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Processes WM_COMMAND messages to dialog box.
|
||
Only IDCANCEL button is processed here (ceasing copy function)
|
||
all other button commands are ignored (since there aren't any)
|
||
|
||
Arguments:
|
||
|
||
IN HWND hwndDlg
|
||
handle to dialog box window
|
||
|
||
IN WPARAM wParam
|
||
LOWORD has the id of the control that issued the message
|
||
|
||
IN LPARAM lParam
|
||
Not used.
|
||
|
||
Return Value:
|
||
|
||
if button is IDCANCEL, then FALSE
|
||
otherwise TRUE (i.e. not processed.)
|
||
|
||
--*/
|
||
{
|
||
switch (LOWORD(wParam)) {
|
||
case IDCANCEL:
|
||
switch (HIWORD(wParam)) {
|
||
case BN_CLICKED:
|
||
if (DisplayMessageBox(hwndDlg,
|
||
NCDU_RU_SURE, 0,
|
||
MB_OKCANCEL_TASK_EXCL_DEF2) == IDOK) {
|
||
bCopying = FALSE;
|
||
}
|
||
return TRUE;
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
|
||
default: return FALSE;
|
||
}
|
||
}
|
||
|
||
INT_PTR CALLBACK
|
||
CopyFileDlgProc (
|
||
IN HWND hwndDlg,
|
||
IN UINT message,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Main Dialog box window proc. Processes the following windows messages:
|
||
WM_INITDIALOG: dialog box initialization procedure
|
||
WM_COMMAND: windows messages (resulting from user commands)
|
||
NCDU_START_FILE_COPY: local message to begin copying files
|
||
|
||
all other messages are processed by the DefDialogProc
|
||
|
||
Arguments:
|
||
|
||
Standard WNDPROC arguments
|
||
|
||
Return Value:
|
||
|
||
FALSE if not processed, otherwise value returned by
|
||
called routine.
|
||
|
||
--*/
|
||
{
|
||
switch (message) {
|
||
case WM_INITDIALOG: return (CopyFileDlg_WM_INITDIALOG (hwndDlg, wParam, lParam));
|
||
case WM_COMMAND: return (CopyFileDlg_WM_COMMAND (hwndDlg, wParam, lParam));
|
||
case NCDU_START_FILE_COPY: return (CopyFileDlg_NCDU_START_FILE_COPY (hwndDlg, wParam, lParam));
|
||
default: return FALSE;
|
||
}
|
||
}
|
||
|
||
|