diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:39 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:39 +0200 |
commit | d2854834e18443876c8f75e0a7f3b88d1d549fc4 (patch) | |
tree | e967b628081e50abc7c34cd264e6586271c7e728 /lib/IFileOperation/file_op.cpp | |
parent | 4.1 (diff) | |
download | FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.tar.gz FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.tar.bz2 FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.zip |
4.2
Diffstat (limited to 'lib/IFileOperation/file_op.cpp')
-rw-r--r-- | lib/IFileOperation/file_op.cpp | 240 |
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; + } } |