aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Library/ml_disc/copyfiles.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Library/ml_disc/copyfiles.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Library/ml_disc/copyfiles.cpp')
-rw-r--r--Src/Plugins/Library/ml_disc/copyfiles.cpp613
1 files changed, 613 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_disc/copyfiles.cpp b/Src/Plugins/Library/ml_disc/copyfiles.cpp
new file mode 100644
index 00000000..426bd79d
--- /dev/null
+++ b/Src/Plugins/Library/ml_disc/copyfiles.cpp
@@ -0,0 +1,613 @@
+#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;
+} \ No newline at end of file