From d2854834e18443876c8f75e0a7f3b88d1d549fc4 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:15:39 +0200 Subject: 4.2 --- lib/IFileOperation/file_op.cpp | 240 ++++++++++++++++------------------------- 1 file changed, 95 insertions(+), 145 deletions(-) (limited to 'lib/IFileOperation/file_op.cpp') 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 +#include #define WIN32_LEAN_AND_MEAN -#include #include #include -#include // Included for shell constants such as FO_* values -#include // Required for necessary shell dependencies -#include -#include +#include //shell constants such as FO_* values +#include 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 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 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 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 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 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; + } } -- cgit