mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
613 lines
16 KiB
C++
613 lines
16 KiB
C++
|
#include "main.h"
|
||
|
#include "./copyfiles.h"
|
||
|
#include "./copyinternal.h"
|
||
|
#include "./resource.h"
|
||
|
#include "./settings.h"
|
||
|
#include "../nu/trace.h"
|
||
|
#include <api/service/waServiceFactory.h>
|
||
|
#include <shlwapi.h>
|
||
|
#include <strsafe.h>
|
||
|
|
||
|
static LONG szBusyDrive[26] = {0, };
|
||
|
static CRITICAL_SECTION cs_copy = { 0,};
|
||
|
|
||
|
static void NotifyDialog(COPYDATA *pcd, UINT uTask, UINT uOperation, LPARAM lParam)
|
||
|
{
|
||
|
if(pcd->hDialog) PostMessage(pcd->hDialog, CFM_NOTIFY, MAKEWPARAM(uTask, uOperation), lParam);
|
||
|
}
|
||
|
|
||
|
static INT_PTR QueryDialog(COPYDATA *pcd, UINT uTask, UINT uOperation, LPARAM lParam)
|
||
|
{
|
||
|
return (pcd->hDialog) ? SendMessage(pcd->hDialog, CFM_NOTIFY, MAKEWPARAM(uTask, uOperation), lParam) : FALSE;
|
||
|
}
|
||
|
|
||
|
static void CopyFiles_MarkDrivesBusy(LPCTSTR *ppsz, INT count, BOOL bBusy)
|
||
|
{
|
||
|
INT i, n;
|
||
|
DWORD driveMask = 0x00;
|
||
|
|
||
|
EnterCriticalSection(&cs_copy);
|
||
|
if (bBusy)
|
||
|
{
|
||
|
for(i = 0; i < count; i++)
|
||
|
{
|
||
|
n = PathGetDriveNumber(ppsz[i]);
|
||
|
if (-1 != n)
|
||
|
{
|
||
|
if (0 == szBusyDrive[n]) driveMask |= (((DWORD)0x01) << n);
|
||
|
szBusyDrive[n]++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(i = 0; i < count; i++)
|
||
|
{
|
||
|
n = PathGetDriveNumber(ppsz[i]);
|
||
|
if (-1 != n)
|
||
|
{
|
||
|
if (szBusyDrive[n] <= 0) continue;
|
||
|
szBusyDrive[n]--;
|
||
|
if (0 == szBusyDrive[n]) driveMask |= (((DWORD)0x01) << n);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
LeaveCriticalSection(&cs_copy);
|
||
|
|
||
|
if (0x00 != driveMask)
|
||
|
{
|
||
|
static UINT uMsgCopyNotify = 0;
|
||
|
if (!uMsgCopyNotify) uMsgCopyNotify = RegisterWindowMessageA("WACOPY_BROADCAST_MSG");
|
||
|
if (uMsgCopyNotify)
|
||
|
{
|
||
|
for (CHAR c = 'A'; 0x00 != driveMask; c++, driveMask>>=1)
|
||
|
{
|
||
|
if (0 == (0x01 & driveMask)) continue;
|
||
|
if (bBusy) SendNotifyMessage(HWND_BROADCAST, uMsgCopyNotify, MAKEWPARAM(c, 0), (LPARAM)TRUE);
|
||
|
else
|
||
|
{
|
||
|
SendNotifyMessage(HWND_BROADCAST, uMsgCopyNotify, MAKEWPARAM(c, 0), (LPARAM)FALSE);
|
||
|
SendNotifyMessage(HWND_BROADCAST, uMsgCopyNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
static BOOL ReadCopyParameters(COPYDATA *pcd)
|
||
|
{
|
||
|
BOOL bVal;
|
||
|
HRESULT hr = S_OK;
|
||
|
pcd->uFlags = 0;
|
||
|
if (S_OK == hr) hr = Settings_ReadString(C_COPY, CF_PATH, pcd->szDestination, ARRAYSIZE(pcd->szDestination));
|
||
|
if (S_OK == hr) hr = Settings_ReadString(C_COPY, CF_TITLEFMT, pcd->szTitleFormat, ARRAYSIZE(pcd->szTitleFormat));
|
||
|
if (S_OK == hr && S_OK == (hr = Settings_GetBool(C_COPY, CF_ADDTOMLDB, &bVal)) && bVal) pcd->uFlags |= FCF_ADDTOMLDB;
|
||
|
if (S_OK == hr && S_OK == (hr = Settings_GetBool(C_COPY, CF_USETITLEFMT, &bVal)) && bVal) pcd->uFlags |= FCF_USETITLEFMT;
|
||
|
CleanupDirectoryString(pcd->szDestination);
|
||
|
|
||
|
return (S_OK == hr);
|
||
|
|
||
|
}
|
||
|
|
||
|
void MLDisc_InitializeCopyData()
|
||
|
{
|
||
|
InitializeCriticalSection(&cs_copy);
|
||
|
}
|
||
|
|
||
|
void MLDisc_ReleaseCopyData()
|
||
|
{
|
||
|
DeleteCriticalSection(&cs_copy);
|
||
|
}
|
||
|
|
||
|
BOOL MLDisc_IsDiscCopying(CHAR cLetter)
|
||
|
{
|
||
|
if (cLetter >= 'a' && cLetter <= 'z') cLetter -= 0x20;
|
||
|
return (cLetter >= 'A' && cLetter <= 'Z' && szBusyDrive[cLetter - 'A'] > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL MLDisc_CopyFiles(HWND hParent, LPWSTR *ppszFiles, ULONGLONG *pFSizes, INT count)
|
||
|
{
|
||
|
if (!ppszFiles || !count) return FALSE;
|
||
|
if (NULL == hParent) hParent = plugin.hwndLibraryParent;
|
||
|
|
||
|
COPYDATA *pcd = (COPYDATA*)CoTaskMemAlloc(sizeof(COPYDATA));
|
||
|
if (!pcd) return FALSE;
|
||
|
ZeroMemory(pcd, sizeof(COPYDATA));
|
||
|
|
||
|
CopyFiles_AddRef(pcd);
|
||
|
|
||
|
pcd->hOwner = hParent;
|
||
|
pcd->ppszFiles = ppszFiles;
|
||
|
pcd->pFSizes = pFSizes;
|
||
|
pcd->count = count;
|
||
|
pcd->bCancel = FALSE;
|
||
|
|
||
|
waServiceFactory *factory = plugin.service->service_getServiceByGuid(api_metadataGUID);
|
||
|
if (factory) pcd->pMetaReader = (api_metadata*) factory->getInterface();
|
||
|
factory = plugin.service->service_getServiceByGuid(mldbApiGuid);
|
||
|
if (factory) pcd->pMlDb = (api_mldb*) factory->getInterface();
|
||
|
|
||
|
HWND hRoot = GetAncestor(hParent, GA_ROOT);
|
||
|
if (NULL == hRoot) hRoot = hParent;
|
||
|
|
||
|
INT_PTR result = WASABI_API_DIALOGBOXPARAMW(IDD_FILECOPY_PREPARE, hRoot, CopyPrepare_DialogProc, (LPARAM)pcd);
|
||
|
if (IDCANCEL != result)
|
||
|
{
|
||
|
if (ReadCopyParameters(pcd))
|
||
|
{
|
||
|
HWND hCopy = WASABI_API_CREATEDIALOGPARAMW(IDD_FILECOPY_PROGRESS, hRoot, CopyProgress_DialogProc, (LPARAM)pcd);
|
||
|
if (hCopy)
|
||
|
{
|
||
|
pcd->hDialog = hCopy;
|
||
|
ShowWindow(hCopy, SW_SHOWNORMAL);
|
||
|
RedrawWindow(hCopy, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||
|
}
|
||
|
CopyFiles_StartCopy(pcd);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CopyFiles_Release(pcd);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CopyFiles_CancelCopy(COPYDATA *pcd)
|
||
|
{
|
||
|
if (pcd) pcd->bCancel = TRUE;
|
||
|
return (NULL != pcd);
|
||
|
}
|
||
|
|
||
|
LONG CopyFiles_AddRef(COPYDATA *pcd)
|
||
|
{
|
||
|
return (pcd) ? InterlockedIncrement(&pcd->ref) : 0;
|
||
|
|
||
|
}
|
||
|
LONG CopyFiles_Release(COPYDATA *pcd)
|
||
|
{
|
||
|
if (pcd && pcd->ref > 0)
|
||
|
{
|
||
|
LONG r = InterlockedDecrement(&pcd->ref);
|
||
|
if ( 0 == r)
|
||
|
{
|
||
|
if (pcd->ppszFiles)
|
||
|
{
|
||
|
for (int i = 0; i < pcd->count; i++) CoTaskMemFree(pcd->ppszFiles[i]);
|
||
|
CoTaskMemFree(pcd->ppszFiles);
|
||
|
}
|
||
|
if (pcd->pFSizes) CoTaskMemFree(pcd->pFSizes);
|
||
|
if (pcd->hThread) CloseHandle(pcd->hThread);
|
||
|
|
||
|
if(pcd->pMetaReader)
|
||
|
{
|
||
|
waServiceFactory *factory = plugin.service->service_getServiceByGuid(api_metadataGUID);
|
||
|
if (factory) factory->releaseInterface(pcd->pMetaReader);
|
||
|
}
|
||
|
if(pcd->pMlDb)
|
||
|
{
|
||
|
waServiceFactory *factory = plugin.service->service_getServiceByGuid(mldbApiGuid);
|
||
|
if (factory) factory->releaseInterface(pcd->pMlDb);
|
||
|
}
|
||
|
CoTaskMemFree(pcd);
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static ULONGLONG CopyFiles_CalculateTotalSize(COPYDATA *pcd)
|
||
|
{
|
||
|
ULONGLONG total = 0;
|
||
|
if (!pcd->pFSizes)
|
||
|
{
|
||
|
pcd->pFSizes = (ULONGLONG*)CoTaskMemAlloc(sizeof(ULONGLONG)*pcd->count);
|
||
|
if (!pcd->pFSizes)
|
||
|
{
|
||
|
pcd->errorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
return 0;
|
||
|
}
|
||
|
LARGE_INTEGER fs;
|
||
|
for(int i = 0; i < pcd->count; i++)
|
||
|
{
|
||
|
HANDLE hFile = CreateFile(pcd->ppszFiles[i], FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
|
||
|
if (INVALID_HANDLE_VALUE == hFile)
|
||
|
{
|
||
|
pcd->errorCode = GetLastError();
|
||
|
return 0;
|
||
|
}
|
||
|
if (!GetFileSizeEx(hFile, &fs)) { pcd->errorCode = GetLastError(); CloseHandle(hFile); return 0; }
|
||
|
CloseHandle(hFile);
|
||
|
pcd->pFSizes[i] = fs.QuadPart;
|
||
|
}
|
||
|
}
|
||
|
for(int i = 0; i < pcd->count; i++) total += pcd->pFSizes[i];
|
||
|
return total;
|
||
|
}
|
||
|
|
||
|
BOOL CopyFiles_CreateDirectory(LPCTSTR pszDirectory)
|
||
|
{
|
||
|
DWORD ec = ERROR_SUCCESS;
|
||
|
if (!CreateDirectory(pszDirectory, NULL))
|
||
|
{
|
||
|
ec = GetLastError();
|
||
|
if (ERROR_PATH_NOT_FOUND == ec)
|
||
|
{
|
||
|
LPCTSTR pszBlock = pszDirectory;
|
||
|
TCHAR szBuffer[MAX_PATH] = {0};
|
||
|
|
||
|
LPCTSTR pszCursor = PathFindNextComponent(pszBlock);
|
||
|
ec = (pszCursor == pszBlock || S_OK != StringCchCopyN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock))) ?
|
||
|
ERROR_INVALID_NAME : ERROR_SUCCESS;
|
||
|
|
||
|
pszBlock = pszCursor;
|
||
|
|
||
|
while (ERROR_SUCCESS == ec && NULL != (pszCursor = PathFindNextComponent(pszBlock)))
|
||
|
{
|
||
|
if (pszCursor == pszBlock || S_OK != StringCchCatN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock)))
|
||
|
ec = ERROR_INVALID_NAME;
|
||
|
|
||
|
if (ERROR_SUCCESS == ec && !CreateDirectory(szBuffer, NULL))
|
||
|
{
|
||
|
ec = GetLastError();
|
||
|
if (ERROR_ALREADY_EXISTS == ec) ec = ERROR_SUCCESS;
|
||
|
}
|
||
|
pszBlock = pszCursor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ERROR_ALREADY_EXISTS == ec) ec = ERROR_SUCCESS;
|
||
|
}
|
||
|
SetLastError(ec);
|
||
|
return (ERROR_SUCCESS == ec);
|
||
|
}
|
||
|
|
||
|
|
||
|
static BOOL CopyFiles_CheckDestination(COPYDATA *pcd, ULONGLONG needSize)
|
||
|
{
|
||
|
TCHAR szRoot[MAX_PATH] = {0};
|
||
|
if (S_OK != StringCchCopy(szRoot, ARRAYSIZE(szRoot), pcd->szDestination))
|
||
|
{
|
||
|
pcd->errorCode = ERROR_OUTOFMEMORY;
|
||
|
return FALSE;
|
||
|
}
|
||
|
PathStripToRoot(szRoot);
|
||
|
ULARGE_INTEGER free, total;
|
||
|
if (!GetDiskFreeSpaceEx(szRoot, &free, &total, NULL))
|
||
|
{
|
||
|
pcd->errorCode = GetLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (needSize > free.QuadPart)
|
||
|
{
|
||
|
pcd->errorCode = ERROR_DISK_FULL;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(pcd->szDestination))
|
||
|
{
|
||
|
DWORD ec = GetLastError();
|
||
|
if (ERROR_PATH_NOT_FOUND == ec || ERROR_FILE_NOT_FOUND == ec)
|
||
|
{
|
||
|
if (TRUE == QueryDialog(pcd, CFT_CONFLICT, CFO_DESTNOTEXIST, (LPARAM)pcd->szDestination))
|
||
|
pcd->errorCode = ERROR_REQUEST_ABORTED;
|
||
|
}
|
||
|
else pcd->errorCode = ec;
|
||
|
|
||
|
if (ERROR_SUCCESS != pcd->errorCode)
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_DIRECTORYCREATE_FAILED;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (!CopyFiles_CreateDirectory(pcd->szDestination))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_DIRECTORYCREATE_FAILED;
|
||
|
pcd->errorCode = ERROR_CANNOT_MAKE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL CopyFiles_FixCdAttributes(LPCTSTR pszFileName)
|
||
|
{
|
||
|
DWORD attr = GetFileAttributes(pszFileName);
|
||
|
if (INVALID_FILE_ATTRIBUTES == attr) return FALSE;
|
||
|
return SetFileAttributes(pszFileName, (attr & ~FILE_ATTRIBUTE_READONLY) | FILE_ATTRIBUTE_ARCHIVE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static BOOL CopyFiles_DeleteFile(LPCTSTR pszFileName, COPYDATA *pcd)
|
||
|
{
|
||
|
DWORD attr = GetFileAttributes(pszFileName);
|
||
|
if (INVALID_FILE_ATTRIBUTES == attr) return FALSE;
|
||
|
if (FILE_ATTRIBUTE_READONLY & attr)
|
||
|
{
|
||
|
BOOL bReset = FALSE;
|
||
|
if (FCF_DELETEREADONLY & pcd->uFlags) bReset = TRUE;
|
||
|
else
|
||
|
{
|
||
|
INT_PTR r = QueryDialog(pcd, CFT_CONFLICT, CFO_READONLY, (LPARAM)pszFileName);
|
||
|
switch(r)
|
||
|
{
|
||
|
case READONLY_CANCELCOPY:
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_USERABORT;
|
||
|
SetLastError(ERROR_REQUEST_ABORTED);
|
||
|
return FALSE;
|
||
|
case READONLY_DELETEALL: pcd->uFlags |= FCF_DELETEREADONLY; // no break
|
||
|
case READONLY_DELETE: bReset = TRUE; break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bReset)
|
||
|
{
|
||
|
if (!SetFileAttributes(pszFileName, (attr & ~FILE_ATTRIBUTE_READONLY)))
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
return DeleteFile(pszFileName);
|
||
|
}
|
||
|
|
||
|
#define NOT_EXIST 0
|
||
|
#define EXIST_AND_SKIP 1
|
||
|
#define EXIST_AND_OVERWRITE 2
|
||
|
#define EXIST_AND_CANCEL 3
|
||
|
|
||
|
static DWORD CopyFiles_CheckIfExist(LPCTSTR pszFileNameDest, LPCTSTR pszFileNameSource, COPYDATA *pcd)
|
||
|
{
|
||
|
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(pszFileNameDest))
|
||
|
{
|
||
|
return NOT_EXIST;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (FCF_SKIPFILE & pcd->uFlags) return EXIST_AND_SKIP;
|
||
|
if (FCF_OVERWRITEFILE & pcd->uFlags) return EXIST_AND_OVERWRITE;
|
||
|
|
||
|
FILECONFLICT conflict;
|
||
|
ZeroMemory(&conflict, sizeof(FILECONFLICT));
|
||
|
|
||
|
pcd->uFlags &= ~(FCF_SKIPFILE | FCF_OVERWRITEFILE);
|
||
|
|
||
|
conflict.pszNameExisting = pszFileNameDest;
|
||
|
conflict.pszNameNew = pszFileNameSource;
|
||
|
|
||
|
INT_PTR r = QueryDialog(pcd, CFT_CONFLICT, CFO_FILEALREDYEXIST, (LPARAM)&conflict);
|
||
|
|
||
|
switch(0xFF & r)
|
||
|
{
|
||
|
case EXISTFILE_CANCELCOPY: return EXIST_AND_CANCEL;
|
||
|
case EXISTFILE_SKIP:
|
||
|
if (EXISTFILE_APPLY_TO_ALL & r) pcd->uFlags |= FCF_SKIPFILE;
|
||
|
return EXIST_AND_SKIP;
|
||
|
case EXISTFILE_OVERWRITE:
|
||
|
if (EXISTFILE_APPLY_TO_ALL & r) pcd->uFlags |= FCF_OVERWRITEFILE;
|
||
|
return EXIST_AND_OVERWRITE;
|
||
|
}
|
||
|
|
||
|
return NOT_EXIST;
|
||
|
}
|
||
|
|
||
|
typedef struct _COPYPROGRESS
|
||
|
{
|
||
|
ULONGLONG total;
|
||
|
ULONGLONG completed;
|
||
|
HWND hDialog;
|
||
|
INT percent;
|
||
|
} COPYPROGRESS;
|
||
|
|
||
|
static DWORD CALLBACK CopyFiles_ProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize,
|
||
|
LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason,
|
||
|
HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData)
|
||
|
{
|
||
|
COPYPROGRESS *pProgress = (COPYPROGRESS*)lpData;
|
||
|
if (pProgress)
|
||
|
{
|
||
|
switch(dwCallbackReason)
|
||
|
{
|
||
|
case CALLBACK_STREAM_SWITCH:
|
||
|
pProgress->completed += TotalFileSize.QuadPart;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
INT p = (INT)((pProgress->completed - TotalFileSize.QuadPart + TotalBytesTransferred.QuadPart) * 100 / pProgress->total);
|
||
|
if (p != pProgress->percent)
|
||
|
{
|
||
|
pProgress->percent = p;
|
||
|
if (pProgress->hDialog)
|
||
|
PostMessage(pProgress->hDialog, CFM_NOTIFY, MAKEWPARAM(CFT_COPYING, CFO_PROGRESS), p);
|
||
|
}
|
||
|
}
|
||
|
return PROGRESS_CONTINUE;
|
||
|
};
|
||
|
|
||
|
static DWORD WINAPI CopyFiles_ThreadProc(LPVOID param)
|
||
|
{
|
||
|
|
||
|
COPYDATA *pcd = (COPYDATA*)param;
|
||
|
if (!pcd) return 1;
|
||
|
|
||
|
CopyFiles_MarkDrivesBusy((LPCTSTR*)pcd->ppszFiles, pcd->count, TRUE);
|
||
|
|
||
|
ULONGLONG needSize;
|
||
|
NotifyDialog(pcd, CFT_INITIALIZING, CFO_INIT, 0L);
|
||
|
NotifyDialog(pcd, CFT_INITIALIZING, CFO_CACLSIZE, 0L);
|
||
|
needSize = CopyFiles_CalculateTotalSize(pcd);
|
||
|
BOOL bSuccess = (ERROR_SUCCESS == pcd->errorCode);
|
||
|
if (bSuccess)
|
||
|
{
|
||
|
NotifyDialog(pcd, CFT_INITIALIZING, CFO_CHECKDESTINATION, 0L);
|
||
|
bSuccess = CopyFiles_CheckDestination(pcd, needSize);
|
||
|
}
|
||
|
|
||
|
if (!bSuccess)
|
||
|
{
|
||
|
if (0 == pcd->errorMsgId)
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_INITIALIZATION_FAILED;
|
||
|
NotifyDialog(pcd, CFT_FINISHED, CFO_FAILED, pcd->errorCode);
|
||
|
CopyFiles_MarkDrivesBusy((LPCTSTR*)pcd->ppszFiles, pcd->count, FALSE);
|
||
|
CopyFiles_Release(pcd);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
COPYPROGRESS progress;
|
||
|
ZeroMemory(&progress, sizeof(COPYPROGRESS));
|
||
|
progress.total = needSize;
|
||
|
progress.hDialog = pcd->hDialog;
|
||
|
|
||
|
NotifyDialog(pcd, CFT_COPYING, CFO_INIT, 0L);
|
||
|
|
||
|
TCHAR szFile[MAX_PATH] = {0};
|
||
|
|
||
|
for (int i = 0; i < pcd->count && ERROR_SUCCESS == pcd->errorCode; i++)
|
||
|
{
|
||
|
if (pcd->bCancel)
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_USERABORT;
|
||
|
pcd->errorCode = ERROR_REQUEST_ABORTED;
|
||
|
}
|
||
|
|
||
|
LPCTSTR pszOrigFileName = PathFindFileName(pcd->ppszFiles[i]);
|
||
|
|
||
|
NotifyDialog(pcd, CFT_COPYING, CFO_NEXTFILE, MAKELPARAM(i, pcd->count));
|
||
|
|
||
|
if (NULL == PathCombine(szFile, pcd->szDestination, pszOrigFileName))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_FAILED;
|
||
|
pcd->errorCode = ERROR_BAD_PATHNAME;
|
||
|
}
|
||
|
|
||
|
DWORD r = CopyFiles_CheckIfExist(szFile, pcd->ppszFiles[i], pcd);
|
||
|
switch(r)
|
||
|
{
|
||
|
case EXIST_AND_SKIP:
|
||
|
continue;
|
||
|
break;
|
||
|
case EXIST_AND_OVERWRITE:
|
||
|
if (!CopyFiles_DeleteFile(szFile, pcd))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_DELETEFILE_FAILED;
|
||
|
pcd->errorCode = GetLastError();
|
||
|
}
|
||
|
break;
|
||
|
case EXIST_AND_CANCEL:
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_USERABORT;
|
||
|
pcd->errorCode = ERROR_REQUEST_ABORTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// copy
|
||
|
if (ERROR_SUCCESS == pcd->errorCode && !CopyFileEx(pcd->ppszFiles[i], szFile, CopyFiles_ProgressRoutine, &progress, &pcd->bCancel, 0))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_FAILED;
|
||
|
pcd->errorCode = GetLastError();
|
||
|
}
|
||
|
|
||
|
if (pcd->bCancel)
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_USERABORT;
|
||
|
pcd->errorCode = ERROR_REQUEST_ABORTED;
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS == pcd->errorCode) // post copy
|
||
|
{
|
||
|
// fix attributes
|
||
|
if (ERROR_SUCCESS == pcd->errorCode && !CopyFiles_FixCdAttributes(szFile))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_SETATTRIBUTES_FAILED;
|
||
|
pcd->errorCode = GetLastError();
|
||
|
}
|
||
|
|
||
|
// format title & rename
|
||
|
if (ERROR_SUCCESS == pcd->errorCode && (FCF_USETITLEFMT & pcd->uFlags) && pcd->pMetaReader)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH] = {0};
|
||
|
if (!CopyFiles_FormatFileName(szBuffer, ARRAYSIZE(szBuffer), szFile, pszOrigFileName,
|
||
|
pcd->szDestination, pcd->szTitleFormat, pcd->pMetaReader))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_TITLEFORMAT_FAILED;
|
||
|
pcd->errorCode = GetLastError();
|
||
|
}
|
||
|
|
||
|
if (pcd->bCancel)
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_USERABORT;
|
||
|
pcd->errorCode = ERROR_REQUEST_ABORTED;
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS == pcd->errorCode &&
|
||
|
CSTR_EQUAL != CompareString(STRCOMP_INVARIANT, 0, szBuffer, -1, szFile, -1))
|
||
|
{
|
||
|
|
||
|
DWORD r = CopyFiles_CheckIfExist(szBuffer, szFile, pcd);
|
||
|
switch(r)
|
||
|
{
|
||
|
case EXIST_AND_SKIP:
|
||
|
CopyFiles_DeleteFile(szFile, pcd);
|
||
|
continue;
|
||
|
break;
|
||
|
case EXIST_AND_OVERWRITE:
|
||
|
if (!CopyFiles_DeleteFile(szBuffer, pcd))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_DELETEFILE_FAILED;
|
||
|
pcd->errorCode = GetLastError();
|
||
|
}
|
||
|
break;
|
||
|
case EXIST_AND_CANCEL:
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_COPYFILE_USERABORT;
|
||
|
pcd->errorCode = ERROR_REQUEST_ABORTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS == pcd->errorCode)
|
||
|
{
|
||
|
if (!MoveFileEx(szFile, szBuffer, MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_TITLEFORMAT_FAILED;
|
||
|
pcd->errorCode = GetLastError();
|
||
|
}
|
||
|
else StringCchCopy(szFile, ARRAYSIZE(szFile), szBuffer);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (ERROR_SUCCESS != pcd->errorCode)
|
||
|
{
|
||
|
CopyFiles_DeleteFile(szFile, pcd);
|
||
|
}
|
||
|
else if ((FCF_ADDTOMLDB & pcd->uFlags) && pcd->pMlDb)
|
||
|
{
|
||
|
if (0 == pcd->pMlDb->AddFile(szFile))
|
||
|
{
|
||
|
pcd->errorMsgId = IDS_COPY_ERRMSG_ADDTOMLDB_FAILED;
|
||
|
pcd->errorCode = ERROR_FILE_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
NotifyDialog(pcd, CFT_FINISHED, (ERROR_SUCCESS == pcd->errorCode) ? CFO_SUCCESS : CFO_FAILED, pcd->errorCode);
|
||
|
if ((FCF_ADDTOMLDB & pcd->uFlags) && pcd->pMlDb) pcd->pMlDb->Sync();
|
||
|
CopyFiles_MarkDrivesBusy((LPCTSTR*)pcd->ppszFiles, pcd->count, FALSE);
|
||
|
CopyFiles_Release(pcd);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
BOOL CopyFiles_StartCopy(COPYDATA *pcd)
|
||
|
{
|
||
|
DWORD threadId;
|
||
|
|
||
|
CopyFiles_AddRef(pcd);
|
||
|
|
||
|
pcd->hThread = CreateThread(NULL, 0, CopyFiles_ThreadProc, pcd, 0, &threadId);
|
||
|
if (pcd->hThread) return TRUE;
|
||
|
|
||
|
|
||
|
pcd->errorCode = GetLastError();
|
||
|
NotifyDialog(pcd, CFT_FINISHED, CFO_FAILED, pcd->errorCode);
|
||
|
CopyFiles_Release(pcd);
|
||
|
return FALSE;
|
||
|
}
|