summaryrefslogtreecommitdiff
path: root/lib/IFileOperation
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:15:39 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:15:39 +0200
commitd2854834e18443876c8f75e0a7f3b88d1d549fc4 (patch)
treee967b628081e50abc7c34cd264e6586271c7e728 /lib/IFileOperation
parent4.1 (diff)
downloadFreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.tar.gz
FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.tar.bz2
FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.zip
4.2
Diffstat (limited to 'lib/IFileOperation')
-rw-r--r--lib/IFileOperation/file_op.cpp240
1 files changed, 95 insertions, 145 deletions
diff --git a/lib/IFileOperation/file_op.cpp b/lib/IFileOperation/file_op.cpp
index 10eac5de..fca802f0 100644
--- a/lib/IFileOperation/file_op.cpp
+++ b/lib/IFileOperation/file_op.cpp
@@ -5,69 +5,38 @@
// **************************************************************************
#include "file_op.h"
+#include <algorithm>
+#include <string>
#define WIN32_LEAN_AND_MEAN
-#include <zen/win.h>
#include <zen/com_ptr.h>
#include <zen/com_error.h>
-#include <Shellapi.h> // Included for shell constants such as FO_* values
-#include <shobjidl.h> // Required for necessary shell dependencies
-#include <algorithm>
-#include <string>
+#include <shellapi.h> //shell constants such as FO_* values
+#include <shobjidl.h>
using namespace zen;
-namespace fileop
+namespace
{
-inline
-void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize)
+void moveToRecycleBin(const wchar_t* fileNames[], //throw ComError
+ size_t fileNo) //size of fileNames array
{
- if (bufferSize > 0)
- {
- //size_t endPos = input.copy(buffer, bufferSize - 1);
- //buffer[endPos] = 0;
- const size_t maxSize = std::min(input.length(), bufferSize - 1);
- std::copy(input.begin(), input.begin() + maxSize, buffer);
- buffer[maxSize] = 0;
- }
-}
-
-std::wstring lastErrorMessage; //this should really be thread-local!!!
-}
-
-
-bool fileop::moveToRecycleBin(const wchar_t* fileNames[],
- size_t fileNo) //size of fileNames array
-{
- HRESULT hr;
-
- // Create the IFileOperation interface
ComPtr<IFileOperation> fileOp;
- hr = ::CoCreateInstance(CLSID_FileOperation,
- NULL,
- CLSCTX_ALL,
- IID_PPV_ARGS(fileOp.init()));
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(::CoCreateInstance(CLSID_FileOperation, //throw ComError
+ NULL,
+ CLSCTX_ALL,
+ IID_PPV_ARGS(fileOp.init())));
// Set the operation flags. Turn off all UI
// from being shown to the user during the
// operation. This includes error, confirmation
// and progress dialogs.
- hr = fileOp->SetOperationFlags(FOF_ALLOWUNDO |
- FOF_NOCONFIRMATION |
- FOF_SILENT |
- FOFX_EARLYFAILURE |
- FOF_NOERRORUI);
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"SetOperationFlags\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(fileOp->SetOperationFlags(FOF_ALLOWUNDO | //throw ComError
+ FOF_NOCONFIRMATION |
+ FOF_SILENT |
+ FOFX_EARLYFAILURE |
+ FOF_NOERRORUI));
int operationCount = 0;
@@ -75,161 +44,142 @@ bool fileop::moveToRecycleBin(const wchar_t* fileNames[],
{
//create file/folder item object
ComPtr<IShellItem> psiFile;
- hr = ::SHCreateItemFromParsingName(fileNames[i],
- NULL,
- IID_PPV_ARGS(psiFile.init()));
+ HRESULT hr = ::SHCreateItemFromParsingName(fileNames[i],
+ NULL,
+ IID_PPV_ARGS(psiFile.init()));
if (FAILED(hr))
{
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || //file not existing anymore
hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))
continue;
-
- std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for file:\n");
- message += std::wstring(L"\"") + fileNames[i] + L"\".";
-
- lastErrorMessage = generateErrorMsg(message, hr);
- return false;
+ throw ComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for file:\n") + L"\"" + fileNames[i] + L"\".", hr);
}
- hr = fileOp->DeleteItem(psiFile.get(), NULL);
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"DeleteItem\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(fileOp->DeleteItem(psiFile.get(), NULL));
++operationCount;
}
- if (operationCount == 0) //calling PerformOperations() without anything to do results in E_UNEXPECTED
- return true;
+ if (operationCount == 0) //calling PerformOperations() without anything to do would result in E_UNEXPECTED
+ return;
//perform actual operations
- hr = fileOp->PerformOperations();
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"PerformOperations\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(fileOp->PerformOperations());
//check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors!
BOOL pfAnyOperationsAborted = FALSE;
- hr = fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted);
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"GetAnyOperationsAborted\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted));
if (pfAnyOperationsAborted == TRUE)
- {
- lastErrorMessage = L"Operation did not complete successfully.";
- return false;
- }
-
- return true;
+ throw ComError(L"Operation did not complete successfully.");
}
-bool fileop::copyFile(const wchar_t* sourceFile,
- const wchar_t* targetFile)
+void copyFile(const wchar_t* sourceFile, //throw ComError
+ const wchar_t* targetFile)
{
- HRESULT hr;
-
- // Create the IFileOperation interface
ComPtr<IFileOperation> fileOp;
- hr = ::CoCreateInstance(CLSID_FileOperation,
- NULL,
- CLSCTX_ALL,
- IID_PPV_ARGS(fileOp.init()));
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(::CoCreateInstance(CLSID_FileOperation, //throw ComError
+ NULL,
+ CLSCTX_ALL,
+ IID_PPV_ARGS(fileOp.init())));
// Set the operation flags. Turn off all UI
// from being shown to the user during the
// operation. This includes error, confirmation
// and progress dialogs.
- hr = fileOp->SetOperationFlags(FOF_NOCONFIRMATION |
- FOF_SILENT |
- FOFX_EARLYFAILURE |
- FOF_NOERRORUI);
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"SetOperationFlags\".", hr);
- return false;
- }
-
+ ZEN_CHECK_COM(fileOp->SetOperationFlags(FOF_NOCONFIRMATION | //throw ComError
+ FOF_SILENT |
+ FOFX_EARLYFAILURE |
+ FOF_NOERRORUI));
//create source object
ComPtr<IShellItem> psiSourceFile;
- hr = ::SHCreateItemFromParsingName(sourceFile,
- NULL,
- IID_PPV_ARGS(psiSourceFile.init()));
- if (FAILED(hr))
{
- std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for file:\n");
- message += std::wstring(L"\"") + sourceFile + L"\".";
- lastErrorMessage = generateErrorMsg(message, hr);
- return false;
+ HRESULT hr = ::SHCreateItemFromParsingName(sourceFile,
+ NULL,
+ IID_PPV_ARGS(psiSourceFile.init()));
+ if (FAILED(hr))
+ throw ComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for file:\n") + L"\"" + sourceFile + L"\".", hr);
}
const size_t pos = std::wstring(targetFile).find_last_of(L'\\');
if (pos == std::wstring::npos)
- {
- lastErrorMessage = L"Target filename does not contain a path separator.";
- return false;
- }
+ throw ComError(L"Target filename does not contain a path separator.");
const std::wstring targetFolder(targetFile, pos);
const std::wstring targetFileNameShort = targetFile + pos + 1;
//create target folder object
ComPtr<IShellItem> psiTargetFolder;
- hr = ::SHCreateItemFromParsingName(targetFolder.c_str(),
- NULL,
- IID_PPV_ARGS(psiTargetFolder.init()));
- if (FAILED(hr))
{
- std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for folder:\n");
- message += std::wstring(L"\"") + targetFolder + L"\".";
- lastErrorMessage = generateErrorMsg(message, hr);
- return false;
+ HRESULT hr = ::SHCreateItemFromParsingName(targetFolder.c_str(),
+ NULL,
+ IID_PPV_ARGS(psiTargetFolder.init()));
+ if (FAILED(hr))
+ throw ComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for folder:\n") + L"\"" + targetFolder + L"\".", hr);
}
//schedule file copy operation
- hr = fileOp->CopyItem(psiSourceFile.get(), psiTargetFolder.get(), targetFileNameShort.c_str(), NULL);
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"CopyItem\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(fileOp->CopyItem(psiSourceFile.get(), psiTargetFolder.get(), targetFileNameShort.c_str(), NULL));
//perform actual operations
- hr = fileOp->PerformOperations();
- if (FAILED(hr))
- {
- lastErrorMessage = generateErrorMsg(L"Error calling \"PerformOperations\".", hr);
- return false;
- }
+ ZEN_CHECK_COM(fileOp->PerformOperations());
//check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors!
BOOL pfAnyOperationsAborted = FALSE;
- hr = fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted);
- if (FAILED(hr))
+ ZEN_CHECK_COM(fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted));
+
+ if (pfAnyOperationsAborted == TRUE)
+ throw ComError(L"Operation did not complete successfully.");
+}
+
+
+inline
+void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize)
+{
+ if (bufferSize > 0)
{
- lastErrorMessage = generateErrorMsg(L"Error calling \"GetAnyOperationsAborted\".", hr);
- return false;
+ //size_t endPos = input.copy(buffer, bufferSize - 1);
+ //buffer[endPos] = 0;
+ const size_t maxSize = std::min(input.length(), bufferSize - 1);
+ std::copy(input.begin(), input.begin() + maxSize, buffer);
+ buffer[maxSize] = 0;
}
+}
- if (pfAnyOperationsAborted == TRUE)
+std::wstring lastErrorMessage; //this should really be thread-local!!!
+}
+
+
+bool fileop::moveToRecycleBin(const wchar_t* fileNames[],
+ size_t fileNo) //size of fileNames array
+{
+ try
+ {
+ ::moveToRecycleBin(fileNames, fileNo); //throw ComError
+ return true;
+ }
+ catch (const zen::ComError& e)
{
- lastErrorMessage = L"Operation did not complete successfully.";
+ lastErrorMessage = e.toString();
return false;
}
+}
+
- return true;
+bool fileop::copyFile(const wchar_t* sourceFile,
+ const wchar_t* targetFile)
+{
+ try
+ {
+ ::copyFile(sourceFile, targetFile); //throw ComError
+ return true;
+ }
+ catch (const zen::ComError& e)
+ {
+ lastErrorMessage = e.toString();
+ return false;
+ }
}
bgstack15