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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|