diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:08:06 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:08:06 +0200 |
commit | fbe76102e941b9f1edaf236788e42678f05fdf9a (patch) | |
tree | f5f538316019fa89be8dc478103490c3a826f3ac /shared | |
parent | 3.8 (diff) | |
download | FreeFileSync-fbe76102e941b9f1edaf236788e42678f05fdf9a.tar.gz FreeFileSync-fbe76102e941b9f1edaf236788e42678f05fdf9a.tar.bz2 FreeFileSync-fbe76102e941b9f1edaf236788e42678f05fdf9a.zip |
3.9
Diffstat (limited to 'shared')
-rw-r--r-- | shared/IFileOperation/FileOperation_Vista.vcxproj | 6 | ||||
-rw-r--r-- | shared/IFileOperation/dll_main.cpp (renamed from shared/IFileOperation/dllmain.cpp) | 14 | ||||
-rw-r--r-- | shared/IFileOperation/file_op.cpp (renamed from shared/IFileOperation/fileOp.cpp) | 107 | ||||
-rw-r--r-- | shared/IFileOperation/file_op.h (renamed from shared/IFileOperation/fileOp.h) | 0 | ||||
-rw-r--r-- | shared/ShadowCopy/Shadow_2003.vcxproj | 2 | ||||
-rw-r--r-- | shared/ShadowCopy/Shadow_XP.vcxproj | 2 | ||||
-rw-r--r-- | shared/ShadowCopy/dll_main.cpp (renamed from shared/ShadowCopy/dllmain.cpp) | 14 | ||||
-rw-r--r-- | shared/ShadowCopy/shadow.cpp | 139 | ||||
-rw-r--r-- | shared/ShadowCopy/shadow.h | 2 | ||||
-rw-r--r-- | shared/Taskbar_Seven/Taskbar_Seven.vcxproj | 2 | ||||
-rw-r--r-- | shared/Taskbar_Seven/dll_main.cpp (renamed from shared/Taskbar_Seven/dllmain.cpp) | 16 | ||||
-rw-r--r-- | shared/Taskbar_Seven/taskbar.cpp | 30 | ||||
-rw-r--r-- | shared/app_main.cpp (renamed from shared/appMain.cpp) | 6 | ||||
-rw-r--r-- | shared/app_main.h (renamed from shared/appMain.h) | 2 | ||||
-rw-r--r-- | shared/assert_static.h | 37 | ||||
-rw-r--r-- | shared/build_info.h (renamed from shared/buildInfo.h) | 2 | ||||
-rw-r--r-- | shared/checkExist.cpp | 54 | ||||
-rw-r--r-- | shared/checkExist.h | 19 | ||||
-rw-r--r-- | shared/check_exist.cpp | 83 | ||||
-rw-r--r-- | shared/check_exist.h | 25 | ||||
-rw-r--r-- | shared/com_error.h | 77 | ||||
-rw-r--r-- | shared/com_ptr.h | 186 | ||||
-rw-r--r-- | shared/com_util.h | 155 | ||||
-rw-r--r-- | shared/custom_button.cpp (renamed from shared/customButton.cpp) | 2 | ||||
-rw-r--r-- | shared/custom_button.h (renamed from shared/customButton.h) | 0 | ||||
-rw-r--r-- | shared/custom_combo_box.cpp (renamed from shared/customComboBox.cpp) | 2 | ||||
-rw-r--r-- | shared/custom_combo_box.h (renamed from shared/customComboBox.h) | 0 | ||||
-rw-r--r-- | shared/custom_tooltip.cpp (renamed from shared/customTooltip.cpp) | 2 | ||||
-rw-r--r-- | shared/custom_tooltip.h (renamed from shared/customTooltip.h) | 0 | ||||
-rw-r--r-- | shared/debug_new.cpp (renamed from shared/debugNew.cpp) | 2 | ||||
-rw-r--r-- | shared/debug_new.h (renamed from shared/debugNew.h) | 4 | ||||
-rw-r--r-- | shared/dll_loader.cpp (renamed from shared/dllLoader.cpp) | 12 | ||||
-rw-r--r-- | shared/dll_loader.h (renamed from shared/dllLoader.h) | 2 | ||||
-rw-r--r-- | shared/drag_n_drop.cpp (renamed from shared/dragAndDrop.cpp) | 60 | ||||
-rw-r--r-- | shared/drag_n_drop.h (renamed from shared/dragAndDrop.h) | 5 | ||||
-rw-r--r-- | shared/file_error.h (renamed from shared/fileError.h) | 11 | ||||
-rw-r--r-- | shared/file_handling.cpp (renamed from shared/fileHandling.cpp) | 879 | ||||
-rw-r--r-- | shared/file_handling.h (renamed from shared/fileHandling.h) | 22 | ||||
-rw-r--r-- | shared/file_id.cpp (renamed from shared/fileID.cpp) | 28 | ||||
-rw-r--r-- | shared/file_id.h (renamed from shared/fileID.h) | 34 | ||||
-rw-r--r-- | shared/file_io.cpp (renamed from shared/fileIO.cpp) | 52 | ||||
-rw-r--r-- | shared/file_io.h (renamed from shared/fileIO.h) | 10 | ||||
-rw-r--r-- | shared/file_traverser.cpp (renamed from shared/fileTraverser.cpp) | 48 | ||||
-rw-r--r-- | shared/file_traverser.h (renamed from shared/fileTraverser.h) | 4 | ||||
-rw-r--r-- | shared/global_func.cpp (renamed from shared/globalFunctions.cpp) | 10 | ||||
-rw-r--r-- | shared/global_func.h (renamed from shared/globalFunctions.h) | 22 | ||||
-rw-r--r-- | shared/guid.cpp | 18 | ||||
-rw-r--r-- | shared/guid.h | 3 | ||||
-rw-r--r-- | shared/help_provider.cpp (renamed from shared/helpProvider.cpp) | 8 | ||||
-rw-r--r-- | shared/help_provider.h (renamed from shared/helpProvider.h) | 2 | ||||
-rw-r--r-- | shared/localization.cpp | 24 | ||||
-rw-r--r-- | shared/localization.h | 2 | ||||
-rw-r--r-- | shared/lock.cpp | 8 | ||||
-rw-r--r-- | shared/long_path_prefix.cpp (renamed from shared/longPathPrefix.cpp) | 8 | ||||
-rw-r--r-- | shared/long_path_prefix.h (renamed from shared/longPathPrefix.h) | 2 | ||||
-rw-r--r-- | shared/parallelCall.cpp | 159 | ||||
-rw-r--r-- | shared/parallelCall.h | 34 | ||||
-rw-r--r-- | shared/perf.h | 42 | ||||
-rw-r--r-- | shared/recycler.cpp | 42 | ||||
-rw-r--r-- | shared/recycler.h | 4 | ||||
-rw-r--r-- | shared/serialize.cpp | 6 | ||||
-rw-r--r-- | shared/serialize.h | 4 | ||||
-rw-r--r-- | shared/shadow.cpp | 204 | ||||
-rw-r--r-- | shared/shadow.h | 22 | ||||
-rw-r--r-- | shared/signal_processing.h | 166 | ||||
-rw-r--r-- | shared/standard_paths.cpp (renamed from shared/standardPaths.cpp) | 32 | ||||
-rw-r--r-- | shared/standard_paths.h (renamed from shared/standardPaths.h) | 2 | ||||
-rw-r--r-- | shared/staticAssert.h | 24 | ||||
-rw-r--r-- | shared/string_conv.h (renamed from shared/stringConv.h) | 2 | ||||
-rw-r--r-- | shared/system_constants.h (renamed from shared/systemConstants.h) | 2 | ||||
-rw-r--r-- | shared/system_func.cpp (renamed from shared/systemFunctions.cpp) | 10 | ||||
-rw-r--r-- | shared/system_func.h (renamed from shared/systemFunctions.h) | 2 | ||||
-rw-r--r-- | shared/taskbar.cpp | 28 | ||||
-rw-r--r-- | shared/taskbar.h | 2 | ||||
-rw-r--r-- | shared/toggle_button.cpp (renamed from shared/toggleButton.cpp) | 2 | ||||
-rw-r--r-- | shared/toggle_button.h (renamed from shared/toggleButton.h) | 0 | ||||
-rw-r--r-- | shared/util.cpp | 42 | ||||
-rw-r--r-- | shared/util.h | 12 | ||||
-rw-r--r-- | shared/xml_base.cpp (renamed from shared/xmlBase.cpp) | 22 | ||||
-rw-r--r-- | shared/xml_base.h (renamed from shared/xmlBase.h) | 14 | ||||
-rw-r--r-- | shared/xml_error.h (renamed from shared/xmlError.h) | 2 | ||||
-rw-r--r-- | shared/zstring.cpp | 36 | ||||
-rw-r--r-- | shared/zstring.h | 55 |
83 files changed, 1989 insertions, 1249 deletions
diff --git a/shared/IFileOperation/FileOperation_Vista.vcxproj b/shared/IFileOperation/FileOperation_Vista.vcxproj index 1cbb4a28..9f9a9c28 100644 --- a/shared/IFileOperation/FileOperation_Vista.vcxproj +++ b/shared/IFileOperation/FileOperation_Vista.vcxproj @@ -209,7 +209,7 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="dllmain.cpp"> + <ClCompile Include="dll_main.cpp"> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </PrecompiledHeader> <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged> @@ -223,10 +223,10 @@ </PrecompiledHeader> <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged> </ClCompile> - <ClCompile Include="fileOp.cpp" /> + <ClCompile Include="file_op.cpp" /> </ItemGroup> <ItemGroup> - <ClInclude Include="fileOp.h" /> + <ClInclude Include="file_op.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/shared/IFileOperation/dllmain.cpp b/shared/IFileOperation/dll_main.cpp index 8dae897a..142e26a2 100644 --- a/shared/IFileOperation/dllmain.cpp +++ b/shared/IFileOperation/dll_main.cpp @@ -8,20 +8,18 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> - -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) +//optional: add init/teardown logic here +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) { - switch (ul_reason_for_call) + switch (fdwReason) { case DLL_PROCESS_ATTACH: + case DLL_PROCESS_DETACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: break; } return TRUE; } - diff --git a/shared/IFileOperation/fileOp.cpp b/shared/IFileOperation/file_op.cpp index 761ec06d..f37a2e66 100644 --- a/shared/IFileOperation/fileOp.cpp +++ b/shared/IFileOperation/file_op.cpp @@ -4,7 +4,9 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "fileOp.h" +#include "file_op.h" +#include "../com_ptr.h" +#include "../com_error.h" #define WIN32_LEAN_AND_MEAN #include "windows.h" @@ -14,7 +16,7 @@ #include <algorithm> #include <string> #include <cstdio> -#include <comdef.h> +#include <comdef.h> void writeString(const std::wstring& input, wchar_t* output, size_t outputBufferLen) @@ -25,44 +27,6 @@ void writeString(const std::wstring& input, wchar_t* output, size_t outputBuffer } -std::wstring numberToHexString(long number) -{ - wchar_t result[100]; - swprintf(result, 100, L"0x%08x", number); - return std::wstring(result); -} - - -std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr) -{ - std::wstring output(input); - output += L" ("; - output += numberToHexString(hr); - output += L": "; - output += _com_error(hr).ErrorMessage(); - output += L")"; - return output; -} - - -//IShellItem resource management -template <class T> -class ReleaseAtExit -{ -public: - ReleaseAtExit(T*& item) : item_(item) {} - ~ReleaseAtExit() - { - if (item_ != NULL) - item_->Release(); - } -private: - ReleaseAtExit(const ReleaseAtExit&); - ReleaseAtExit& operator=(const ReleaseAtExit&); - T*& item_; -}; - - namespace FileOp { std::wstring lastErrorMessage; @@ -72,15 +36,16 @@ std::wstring lastErrorMessage; bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], size_t fileNo) //size of fileNames array { + using Util::ComPtr; + using Util::generateErrorMsg; HRESULT hr; // Create the IFileOperation interface - IFileOperation* pfo = NULL; - ReleaseAtExit<IFileOperation> dummy(pfo); + ComPtr<IFileOperation> fileOp; hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, - IID_PPV_ARGS(&pfo)); + IID_PPV_ARGS(fileOp.init())); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr); @@ -91,10 +56,10 @@ bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], // from being shown to the user during the // operation. This includes error, confirmation // and progress dialogs. - hr = pfo->SetOperationFlags(FOF_ALLOWUNDO | - FOF_NOCONFIRMATION | - FOF_SILENT | - FOF_NOERRORUI); + hr = fileOp->SetOperationFlags(FOF_ALLOWUNDO | + FOF_NOCONFIRMATION | + FOF_SILENT | + FOF_NOERRORUI); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"SetOperationFlags\".", hr); @@ -104,11 +69,10 @@ bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], for (size_t i = 0; i < fileNo; ++i) { //create file/folder item object - IShellItem* psiFile = NULL; - ReleaseAtExit<IShellItem> dummy2(psiFile); + ComPtr<IShellItem> psiFile; hr = SHCreateItemFromParsingName(fileNames[i], NULL, - IID_PPV_ARGS(&psiFile)); + IID_PPV_ARGS(psiFile.init())); if (FAILED(hr)) { std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for file:\n"); @@ -118,7 +82,7 @@ bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], return false; } - hr = pfo->DeleteItem(psiFile, NULL); + hr = fileOp->DeleteItem(psiFile.get(), NULL); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"DeleteItem\".", hr); @@ -127,7 +91,7 @@ bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], } //perform actual operations - hr = pfo->PerformOperations(); + hr = fileOp->PerformOperations(); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"PerformOperations\".", hr); @@ -136,7 +100,7 @@ bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], //check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors! BOOL pfAnyOperationsAborted = FALSE; - hr = pfo->GetAnyOperationsAborted(&pfAnyOperationsAborted); + hr = fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"GetAnyOperationsAborted\".", hr); @@ -156,15 +120,17 @@ bool FileOp::moveToRecycleBin(const wchar_t* fileNames[], bool FileOp::copyFile(const wchar_t* sourceFile, const wchar_t* targetFile) { + using Util::ComPtr; + using Util::generateErrorMsg; + HRESULT hr; // Create the IFileOperation interface - IFileOperation* pfo = NULL; - ReleaseAtExit<IFileOperation> dummy(pfo); + ComPtr<IFileOperation> fileOp; hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, - IID_PPV_ARGS(&pfo)); + IID_PPV_ARGS(fileOp.init())); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr); @@ -175,10 +141,10 @@ bool FileOp::copyFile(const wchar_t* sourceFile, // from being shown to the user during the // operation. This includes error, confirmation // and progress dialogs. - hr = pfo->SetOperationFlags(FOF_NOCONFIRMATION | - FOF_SILENT | - FOFX_EARLYFAILURE | - FOF_NOERRORUI); + hr = fileOp->SetOperationFlags(FOF_NOCONFIRMATION | + FOF_SILENT | + FOFX_EARLYFAILURE | + FOF_NOERRORUI); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"SetOperationFlags\".", hr); @@ -186,11 +152,10 @@ bool FileOp::copyFile(const wchar_t* sourceFile, } //create source object - IShellItem* psiSourceFile = NULL; - ReleaseAtExit<IShellItem> dummy2(psiSourceFile); + ComPtr<IShellItem> psiSourceFile; hr = SHCreateItemFromParsingName(sourceFile, NULL, - IID_PPV_ARGS(&psiSourceFile)); + IID_PPV_ARGS(psiSourceFile.init())); if (FAILED(hr)) { std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for file:\n"); @@ -199,7 +164,7 @@ bool FileOp::copyFile(const wchar_t* sourceFile, return false; } - const size_t pos = std::wstring(targetFile).find_last_of(L'\\'); + 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."; @@ -210,11 +175,10 @@ bool FileOp::copyFile(const wchar_t* sourceFile, const std::wstring targetFileNameShort = targetFile + pos + 1; //create target folder object - IShellItem* psiTargetFolder = NULL; - ReleaseAtExit<IShellItem> dummy3(psiTargetFolder); - hr = SHCreateItemFromParsingName(targetFolder.c_str(), + ComPtr<IShellItem> psiTargetFolder; + hr = SHCreateItemFromParsingName(targetFolder.c_str(), NULL, - IID_PPV_ARGS(&psiTargetFolder)); + IID_PPV_ARGS(psiTargetFolder.init())); if (FAILED(hr)) { std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for folder:\n"); @@ -224,7 +188,7 @@ bool FileOp::copyFile(const wchar_t* sourceFile, } //schedule file copy operation - hr = pfo->CopyItem(psiSourceFile, psiTargetFolder, targetFileNameShort.c_str(), NULL); + hr = fileOp->CopyItem(psiSourceFile.get(), psiTargetFolder.get(), targetFileNameShort.c_str(), NULL); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"CopyItem\".", hr); @@ -232,7 +196,7 @@ bool FileOp::copyFile(const wchar_t* sourceFile, } //perform actual operations - hr = pfo->PerformOperations(); + hr = fileOp->PerformOperations(); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"PerformOperations\".", hr); @@ -241,14 +205,13 @@ bool FileOp::copyFile(const wchar_t* sourceFile, //check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors! BOOL pfAnyOperationsAborted = FALSE; - hr = pfo->GetAnyOperationsAborted(&pfAnyOperationsAborted); + hr = fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted); if (FAILED(hr)) { lastErrorMessage = generateErrorMsg(L"Error calling \"GetAnyOperationsAborted\".", hr); return false; } - if (pfAnyOperationsAborted == TRUE) { lastErrorMessage = L"Operation did not complete successfully."; diff --git a/shared/IFileOperation/fileOp.h b/shared/IFileOperation/file_op.h index 8fa6a75b..8fa6a75b 100644 --- a/shared/IFileOperation/fileOp.h +++ b/shared/IFileOperation/file_op.h diff --git a/shared/ShadowCopy/Shadow_2003.vcxproj b/shared/ShadowCopy/Shadow_2003.vcxproj index b7d31ae4..5351cc1d 100644 --- a/shared/ShadowCopy/Shadow_2003.vcxproj +++ b/shared/ShadowCopy/Shadow_2003.vcxproj @@ -210,7 +210,7 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="dllmain.cpp"> + <ClCompile Include="dll_main.cpp"> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </PrecompiledHeader> <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged> diff --git a/shared/ShadowCopy/Shadow_XP.vcxproj b/shared/ShadowCopy/Shadow_XP.vcxproj index 5c531a27..d096297a 100644 --- a/shared/ShadowCopy/Shadow_XP.vcxproj +++ b/shared/ShadowCopy/Shadow_XP.vcxproj @@ -211,7 +211,7 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="dllmain.cpp"> + <ClCompile Include="dll_main.cpp"> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </PrecompiledHeader> <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged> diff --git a/shared/ShadowCopy/dllmain.cpp b/shared/ShadowCopy/dll_main.cpp index 8dae897a..142e26a2 100644 --- a/shared/ShadowCopy/dllmain.cpp +++ b/shared/ShadowCopy/dll_main.cpp @@ -8,20 +8,18 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> - -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) +//optional: add init/teardown logic here +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) { - switch (ul_reason_for_call) + switch (fdwReason) { case DLL_PROCESS_ATTACH: + case DLL_PROCESS_DETACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: break; } return TRUE; } - diff --git a/shared/ShadowCopy/shadow.cpp b/shared/ShadowCopy/shadow.cpp index 1fb78769..2e739146 100644 --- a/shared/ShadowCopy/shadow.cpp +++ b/shared/ShadowCopy/shadow.cpp @@ -8,6 +8,8 @@ #define WIN32_LEAN_AND_MEAN #include "windows.h" +#include "../com_ptr.h" +#include "../com_error.h" #ifdef USE_SHADOW_XP #include "xp/inc/vss.h" @@ -15,7 +17,7 @@ #include "xp/inc/vsbackup.h" #elif defined USE_SHADOW_2003 -#include "Server 2003/inc/vss.h" +#include "Server 2003/inc/vss.h" #include "Server 2003/inc/vswriter.h" #include "Server 2003/inc/vsbackup.h" #else @@ -30,79 +32,37 @@ adapt! //typedef GUID VSS_ID; - -//IShellItem resource management: better handled with boost::shared_ptr or CComPtr, but we avoid dependency with boost and ATL in this case -template <class T> -class ItemHolder -{ -public: - ItemHolder(T* item) : item_(item) {} - ~ItemHolder() - { - if (item_) - item_->Release(); - } - - T* release() -{ -T* rv = item_; -item_ = 0; - return rv; - } - - T* operator->() const -{ - return item_; - } -private: - ItemHolder(const ItemHolder&); - ItemHolder& operator=(const ItemHolder&); - T* item_; -}; - - void writeString(const wchar_t* input, wchar_t* output, unsigned int outputBufferLen) { const size_t newSize = min(wcslen(input) + 1, outputBufferLen); //including null-termination memcpy(output, input, newSize * sizeof(wchar_t)); - output[newSize-1] = 0; //if output buffer is too small... -} - - -std::wstring numberToHexString(const long number) -{ - wchar_t result[100]; - swprintf(result, 100, L"0x%08x", number); - return std::wstring(result); + output[newSize-1] = 0; //if output buffer is too small... } void writeErrorMsg(const wchar_t* input, HRESULT hr, wchar_t* output, unsigned int outputBufferLen) { - std::wstring formattedMsg(input); - formattedMsg += L" ("; - formattedMsg += numberToHexString(hr); - formattedMsg += L": "; - formattedMsg += _com_error(hr).ErrorMessage(); - formattedMsg += L")"; - - writeString(formattedMsg.c_str(), output, outputBufferLen); + writeString(Util::generateErrorMsg(input, hr).c_str(), output, outputBufferLen); } -bool Shadow::createShadowCopy(const wchar_t* volumeName, + +bool shadow::createShadowCopy(const wchar_t* volumeName, wchar_t* shadowVolName, unsigned int shadowBufferLen, void** backupHandle, wchar_t* errorMessage, unsigned int errorBufferLen) { + using Util::ComPtr; + using Util::generateErrorMsg; + //MessageBox(0, L"backup err", L"", 0); */ *backupHandle = NULL; HRESULT hr = NULL; - IVssBackupComponents* pBackupPtr = NULL; - if (FAILED(hr = CreateVssBackupComponents(&pBackupPtr))) + ComPtr<IVssBackupComponents> backupComp; + if (FAILED(hr = CreateVssBackupComponents(backupComp.init()))) { if (hr == E_ACCESSDENIED) writeErrorMsg(L"The caller does not have sufficient backup privileges or is not an administrator.", hr, errorMessage, errorBufferLen); @@ -111,97 +71,96 @@ bool Shadow::createShadowCopy(const wchar_t* volumeName, return false; } - ItemHolder<IVssBackupComponents> pBackupComponents(pBackupPtr); - - if (FAILED(hr = pBackupComponents->InitializeForBackup())) + if (FAILED(hr = backupComp->InitializeForBackup())) { writeErrorMsg(L"Error calling \"InitializeForBackup\".", hr, errorMessage, errorBufferLen); return false; } - - if (FAILED(hr = pBackupComponents->SetBackupState(false, false, VSS_BT_FULL))) + if (FAILED(hr = backupComp->SetBackupState(false, false, VSS_BT_FULL))) { writeErrorMsg(L"Error calling \"SetBackupState\".", hr, errorMessage, errorBufferLen); return false; } - - IVssAsync* pWriteMetaData = NULL; - if (FAILED(hr = pBackupComponents->GatherWriterMetadata( &pWriteMetaData ))) - { //this can happen if XP-version of VSS is used on Windows Vista (which needs at least VSS-Server2003 build) + ComPtr<IVssAsync> vssWriters; + if (FAILED(hr = backupComp->GatherWriterMetadata(vssWriters.init()))) + { + //this can happen if XP-version of VSS is used on Windows Vista (which needs at least VSS-Server2003 build) writeErrorMsg(L"Error calling \"GatherWriterMetadata\".", hr, errorMessage, errorBufferLen); return false; } //wait for shadow copy writers to complete - hr = pWriteMetaData->Wait(); - if (SUCCEEDED(hr)) - pWriteMetaData->QueryStatus(&hr, NULL); //check if the async operation succeeded... - - pWriteMetaData->Release(); - if (FAILED(hr)) + if (FAILED(hr = vssWriters->Wait())) { - writeErrorMsg(L"Error calling \"ppWriteMetaData->Wait\".", hr, errorMessage, errorBufferLen); + writeErrorMsg(L"Error calling \"vssWriters->Wait\".", hr, errorMessage, errorBufferLen); return false; } + vssWriters->QueryStatus(&hr, NULL); //check if the async operation succeeded... + if (FAILED(hr)) + { + writeErrorMsg(L"Error calling \"vssWriters->QueryStatus\".", hr, errorMessage, errorBufferLen); + return false; + } VSS_ID snapshotSetId = {0}; - if (FAILED(hr = pBackupComponents->StartSnapshotSet( &snapshotSetId ))) + if (FAILED(hr = backupComp->StartSnapshotSet(&snapshotSetId))) { writeErrorMsg(L"Error calling \"StartSnapshotSet\".", hr, errorMessage, errorBufferLen); return false; } - VSS_ID SnapShotId = {0}; - if (FAILED(hr = pBackupComponents->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId))) + if (FAILED(hr = backupComp->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId))) { writeErrorMsg(L"Error calling \"AddToSnapshotSet\".", hr, errorMessage, errorBufferLen); return false; } - - IVssAsync* pPrepare = NULL; - if (FAILED(hr = pBackupComponents->PrepareForBackup( &pPrepare ))) + ComPtr<IVssAsync> vssPrepare; + if (FAILED(hr = backupComp->PrepareForBackup(vssPrepare.init()))) { writeErrorMsg(L"Error calling \"PrepareForBackup\".", hr, errorMessage, errorBufferLen); return false; } - hr = pPrepare->Wait(); - if (SUCCEEDED(hr)) - pPrepare->QueryStatus(&hr, NULL); //check if the async operation succeeded... + if (FAILED(hr = vssPrepare->Wait())) + { + writeErrorMsg(L"Error calling \"vssPrepare->Wait\".", hr, errorMessage, errorBufferLen); + return false; + } - pPrepare->Release(); + vssPrepare->QueryStatus(&hr, NULL); //check if the async operation succeeded... if (FAILED(hr)) { - writeErrorMsg(L"Error calling \"pPrepare->Wait\".", hr, errorMessage, errorBufferLen); + writeErrorMsg(L"Error calling \"vssPrepare->QueryStatus\".", hr, errorMessage, errorBufferLen); return false; } - - IVssAsync* pDoShadowCopy = NULL; - if (FAILED(hr = pBackupComponents->DoSnapshotSet(&pDoShadowCopy))) + ComPtr<IVssAsync> vssDoShadowCopy; + if (FAILED(hr = backupComp->DoSnapshotSet(vssDoShadowCopy.init()))) { writeErrorMsg(L"Error calling \"DoSnapshotSet\".", hr, errorMessage, errorBufferLen); return false; } - hr = pDoShadowCopy->Wait(); - if (SUCCEEDED(hr)) - pDoShadowCopy->QueryStatus(&hr, NULL); //check if the async operation succeeded... + if (FAILED(hr = vssDoShadowCopy->Wait())) + { + writeErrorMsg(L"Error calling \"vssDoShadowCopy->Wait\".", hr, errorMessage, errorBufferLen); + return false; + } - pDoShadowCopy->Release(); + vssDoShadowCopy->QueryStatus(&hr, NULL); //check if the async operation succeeded... if (FAILED(hr)) { - writeErrorMsg(L"Error calling \"pPrepare->Wait\".", hr, errorMessage, errorBufferLen); + writeErrorMsg(L"Error calling \"vssDoShadowCopy->QueryStatus\".", hr, errorMessage, errorBufferLen); return false; } VSS_SNAPSHOT_PROP props; - if (FAILED(hr = pBackupComponents->GetSnapshotProperties( SnapShotId, &props ))) + if (FAILED(hr = backupComp->GetSnapshotProperties(SnapShotId, &props))) { writeErrorMsg(L"Error calling \"GetSnapshotProperties\".", hr, errorMessage, errorBufferLen); return false; @@ -212,13 +171,13 @@ bool Shadow::createShadowCopy(const wchar_t* volumeName, VssFreeSnapshotProperties(&props); - *backupHandle = pBackupComponents.release(); //release ownership + *backupHandle = backupComp.release(); //release ownership return true; } -void Shadow::releaseShadowCopy(void* backupHandle) +void shadow::releaseShadowCopy(void* backupHandle) { if (backupHandle != NULL) static_cast<IVssBackupComponents*>(backupHandle)->Release(); diff --git a/shared/ShadowCopy/shadow.h b/shared/ShadowCopy/shadow.h index 61d6ae7e..a9120e8a 100644 --- a/shared/ShadowCopy/shadow.h +++ b/shared/ShadowCopy/shadow.h @@ -14,7 +14,7 @@ #endif -namespace Shadow +namespace shadow { //COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize diff --git a/shared/Taskbar_Seven/Taskbar_Seven.vcxproj b/shared/Taskbar_Seven/Taskbar_Seven.vcxproj index db8b6feb..5b04a98c 100644 --- a/shared/Taskbar_Seven/Taskbar_Seven.vcxproj +++ b/shared/Taskbar_Seven/Taskbar_Seven.vcxproj @@ -208,7 +208,7 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="dllmain.cpp"> + <ClCompile Include="dll_main.cpp"> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </PrecompiledHeader> <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged> diff --git a/shared/Taskbar_Seven/dllmain.cpp b/shared/Taskbar_Seven/dll_main.cpp index 18bb453d..142e26a2 100644 --- a/shared/Taskbar_Seven/dllmain.cpp +++ b/shared/Taskbar_Seven/dll_main.cpp @@ -7,21 +7,19 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> - -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) +//optional: add init/teardown logic here +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) { - switch (ul_reason_for_call) + switch (fdwReason) { case DLL_PROCESS_ATTACH: + case DLL_PROCESS_DETACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: break; - } + } return TRUE; } - diff --git a/shared/Taskbar_Seven/taskbar.cpp b/shared/Taskbar_Seven/taskbar.cpp index f5249e08..c9a2e7df 100644 --- a/shared/Taskbar_Seven/taskbar.cpp +++ b/shared/Taskbar_Seven/taskbar.cpp @@ -13,7 +13,7 @@ #include <map> #include <string> #include <comdef.h> - +#include "../com_error.h" namespace { @@ -24,27 +24,7 @@ void writeString(const std::wstring& input, wchar_t* output, size_t outputBuffer output[newSize-1] = 0; //if output buffer is too small... } - -std::wstring numberToHexString(const long number) -{ - wchar_t result[100]; - swprintf(result, 100, L"0x%08x", number); - return std::wstring(result); -} - - -std::wstring writeErrorMsg(const wchar_t* input, HRESULT hr) -{ - std::wstring output(input); - output += L" ("; - output += numberToHexString(hr); - output += L": "; - output += _com_error(hr).ErrorMessage(); - output += L")"; - return output; -} - - +using Util::generateErrorMsg; using TaskbarSeven::TBHandle; typedef std::map<TBHandle, ITaskbarList3*> TaskBarHandleMap; @@ -70,7 +50,7 @@ TaskbarSeven::TBHandle TaskbarSeven::init() //call on app initializaiton; return IID_PPV_ARGS(&pto)); if (FAILED(hr)) { - lastErrorMessage = writeErrorMsg(L"Error calling \"CoCreateInstance\".", hr); + lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr); return 0; } @@ -123,7 +103,7 @@ bool TaskbarSeven::setStatus(TBHandle handle, flag); //[in] TBPFLAG tbpFlags if (FAILED(hr)) { - lastErrorMessage = writeErrorMsg(L"Error calling \"SetProgressState\".", hr); + lastErrorMessage = generateErrorMsg(L"Error calling \"SetProgressState\".", hr); return false; } } @@ -146,7 +126,7 @@ bool TaskbarSeven::setProgress(TBHandle handle, total); //[in] ULONGLONG ullTotal if (FAILED(hr)) { - lastErrorMessage = writeErrorMsg(L"Error calling \"SetProgressValue\".", hr); + lastErrorMessage = generateErrorMsg(L"Error calling \"SetProgressValue\".", hr); return false; } } diff --git a/shared/appMain.cpp b/shared/app_main.cpp index bf65e6c8..7225ba62 100644 --- a/shared/appMain.cpp +++ b/shared/app_main.cpp @@ -4,17 +4,17 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "appMain.h" +#include "app_main.h" #include <wx/window.h> #include <wx/app.h> -using namespace FreeFileSync; +using namespace ffs3; bool AppMainWindow::mainWndAct = false; -void FreeFileSync::AppMainWindow::setMainWindow(wxWindow* window) +void ffs3::AppMainWindow::setMainWindow(wxWindow* window) { wxTheApp->SetTopWindow(window); wxTheApp->SetExitOnFrameDelete(true); diff --git a/shared/appMain.h b/shared/app_main.h index a4222a75..d0b76122 100644 --- a/shared/appMain.h +++ b/shared/app_main.h @@ -9,7 +9,7 @@ class wxWindow; -namespace FreeFileSync +namespace ffs3 { //just some wrapper around a global variable representing the (logical) main application window class AppMainWindow diff --git a/shared/assert_static.h b/shared/assert_static.h new file mode 100644 index 00000000..9eb94f3c --- /dev/null +++ b/shared/assert_static.h @@ -0,0 +1,37 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef ASSERTSTATIC_H_INCLUDED +#define ASSERTSTATIC_H_INCLUDED + +//compile time assert based on Loki (http://loki-lib.sourceforge.net) + +#ifdef NDEBUG + +#define assert_static(x) ((void)0) + +#else /* debugging enabled */ +namespace StaticCheckImpl +{ +template<int> +struct CompileTimeError; + +template<> +struct CompileTimeError<true> {}; +} + +#define LOKI_CONCAT( X, Y ) LOKI_CONCAT_SUB( X, Y ) +#define LOKI_CONCAT_SUB( X, Y ) X##Y + +#define assert_static(expr) \ + enum { LOKI_CONCAT(loki_enum_dummy_value, __LINE__) = sizeof(StaticCheckImpl::CompileTimeError<static_cast<bool>(expr) >) } + +/*#define assert_static(expr) \ + { Loki::CompileTimeError<((expr) != 0)> Static_Assert_Has_Failed; (void)Static_Assert_Has_Failed; } */ + +#endif + +#endif //ASSERTSTATIC_H_INCLUDED diff --git a/shared/buildInfo.h b/shared/build_info.h index 3aed3269..945284d2 100644 --- a/shared/buildInfo.h +++ b/shared/build_info.h @@ -7,7 +7,7 @@ #ifndef BUILDINFO_H_INCLUDED #define BUILDINFO_H_INCLUDED -namespace Utility +namespace util { //determine build info //seems to be safer than checking for _WIN64 (defined on windows for 64-bit compilations only) while _WIN32 is always defined (even for x64 compiler!) diff --git a/shared/checkExist.cpp b/shared/checkExist.cpp deleted file mode 100644 index 3f71afb8..00000000 --- a/shared/checkExist.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "checkExist.h" -#include "parallelCall.h" -#include "fileHandling.h" - - -namespace -{ -template <bool (*testExist)(const Zstring&)> -class CheckObjectExists : public Async::Procedure -{ -public: - CheckObjectExists(const Zstring& filename) : - filename_(filename.c_str()), //deep copy: worker thread may run longer than main! Avoid shared data - isExisting(false) {} - - virtual void doWork() - { - isExisting = testExist(filename_); //throw() - } - - bool doesExist() const //retrieve result - { - return isExisting; - } - -private: - const Zstring filename_; //no reference, lifetime not known - bool isExisting; -}; - - -template <bool (*testExist)(const Zstring&)> -inline -Utility::ResultExist objExists(const Zstring& filename, size_t timeout) //timeout in ms -{ - typedef CheckObjectExists<testExist> CheckObjEx; - boost::shared_ptr<CheckObjEx> proc(new CheckObjEx(filename)); - - return Async::execute(proc, timeout) == Async::TIMEOUT ? Utility::EXISTING_TIMEOUT : - (proc->doesExist() ? Utility::EXISTING_TRUE : Utility::EXISTING_FALSE); -} -} - - -Utility::ResultExist Utility::fileExists(const Zstring& filename, size_t timeout) //timeout in ms -{ - return objExists<FreeFileSync::fileExists>(filename, timeout); -} - - -Utility::ResultExist Utility::dirExists(const Zstring& dirname, size_t timeout) //timeout in ms -{ - return objExists<FreeFileSync::dirExists>(dirname, timeout); -} diff --git a/shared/checkExist.h b/shared/checkExist.h deleted file mode 100644 index bae5580c..00000000 --- a/shared/checkExist.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CHECKEXIST_H_INCLUDED -#define CHECKEXIST_H_INCLUDED - -#include "zstring.h" - -namespace Utility -{ -enum ResultExist -{ - EXISTING_TRUE, - EXISTING_FALSE, - EXISTING_TIMEOUT -}; - -ResultExist fileExists(const Zstring& filename, size_t timeout); //timeout in ms -ResultExist dirExists( const Zstring& dirname, size_t timeout); //timeout in ms -} - -#endif // CHECKEXIST_H_INCLUDED diff --git a/shared/check_exist.cpp b/shared/check_exist.cpp new file mode 100644 index 00000000..fcb865fd --- /dev/null +++ b/shared/check_exist.cpp @@ -0,0 +1,83 @@ +#include "check_exist.h" +#include "file_handling.h" +#include <boost/thread.hpp> +#include <boost/shared_ptr.hpp> + + +#ifdef __MINGW32__ +//oh well, nothing is for free... +//https://svn.boost.org/trac/boost/ticket/4258 +#warning fix this issue at some time... +extern "C" void tss_cleanup_implemented() {} +#endif + + +namespace +{ +template <bool (*testExist)(const Zstring&)> +class ExistenceChecker +{ +public: + ExistenceChecker(const Zstring& filename, const boost::shared_ptr<bool>& isExisting) : + filename_(filename.c_str()), //deep copy: worker thread may run longer than main! avoid shared data + isExisting_(isExisting) {} //not accessed during thread run + + void operator()() + { + *isExisting_ = testExist(filename_); //throw() + } + +private: + const Zstring filename_; //no reference, lifetime not known + boost::shared_ptr<bool> isExisting_; +}; + + +template <bool (*fun)(const Zstring&)> +util::ResultExist checkExistence(const Zstring& objName, size_t timeout) //timeout in ms +{ + using namespace util; + + boost::shared_ptr<bool> isExisting(new bool(false)); + + ExistenceChecker<fun> task(objName, isExisting); + boost::thread worker(task); + + if (worker.timed_join(boost::posix_time::milliseconds(timeout))) + return *isExisting ? EXISTING_TRUE : EXISTING_FALSE; + else + return EXISTING_TIMEOUT; + /* + main/worker thread may access different shared_ptr instances safely (even though they have the same target!) + http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm?sess=8153b05b34d890e02d48730db1ff7ddc#ThreadSafety + */ + +#ifndef _MSC_VER +#warning migrate this at some time... +#endif + /* + unfortunately packaged_task/future is not mature enough to be used... + boost::packaged_task<bool> pt(boost::bind(fun, objName.c_str())); //attention: Zstring is not thread-safe => make deep copy + boost::unique_future<bool> fut = pt.get_future(); + + boost::thread worker(boost::move(pt)); //launch task on a thread + + if (fut.timed_wait(boost::posix_time::milliseconds(timeout))) + return fut.get() ? EXISTING_TRUE : EXISTING_FALSE; + else + return EXISTING_TIMEOUT; + */ +} +} + + +util::ResultExist util::fileExists(const Zstring& filename, size_t timeout) //timeout in ms +{ + return ::checkExistence<ffs3::fileExists>(filename, timeout); +} + + +util::ResultExist util::dirExists(const Zstring& dirname, size_t timeout) //timeout in ms +{ + return ::checkExistence<ffs3::dirExists>(dirname, timeout); +} diff --git a/shared/check_exist.h b/shared/check_exist.h new file mode 100644 index 00000000..7e9cecd8 --- /dev/null +++ b/shared/check_exist.h @@ -0,0 +1,25 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef CHECKEXIST_H_INCLUDED +#define CHECKEXIST_H_INCLUDED + +#include "zstring.h" + +namespace util +{ +enum ResultExist +{ + EXISTING_TRUE, + EXISTING_FALSE, + EXISTING_TIMEOUT +}; + +ResultExist fileExists(const Zstring& filename, size_t timeout); //timeout in ms +ResultExist dirExists( const Zstring& dirname, size_t timeout); //timeout in ms +} + +#endif // CHECKEXIST_H_INCLUDED diff --git a/shared/com_error.h b/shared/com_error.h new file mode 100644 index 00000000..ab365977 --- /dev/null +++ b/shared/com_error.h @@ -0,0 +1,77 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef COM_ERROR_HEADER +#define COM_ERROR_HEADER + +#include <string> +#include <cstdio> +#include <comdef.h> + +namespace util +{ +std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr); + + +class ComException +{ +public: + ComException(const std::wstring& message, HRESULT hr = NO_ERROR) + : message_(message), hr_(hr) {} + + std::wstring show() const + { + return hr_ != NO_ERROR ? generateErrorMsg(message_, hr_) : message_; + } + +private: + const std::wstring message_; + const HRESULT hr_; +}; + + + + + + + + + + + + + + + + + + + + + +//################# implementation ##################### +inline +std::wstring numberToHexString(long number) +{ + wchar_t result[100]; + swprintf(result, 100, L"0x%08x", number); + return std::wstring(result); +} + + +inline +std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr) +{ + std::wstring output(input); + output += L" ("; + output += numberToHexString(hr); + output += L": "; + output += _com_error(hr).ErrorMessage(); + output += L")"; + return output; +} +} +#endif //COM_ERROR_HEADER
\ No newline at end of file diff --git a/shared/com_ptr.h b/shared/com_ptr.h new file mode 100644 index 00000000..1ce7eae6 --- /dev/null +++ b/shared/com_ptr.h @@ -0,0 +1,186 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef SMART_COM_PTR_H +#define SMART_COM_PTR_H + +#include <Objbase.h> +#include <algorithm> + +namespace util +{ +/* +ComPtr: RAII class handling COM objects + +Example: + -------- + ComPtr<IUPnPDeviceFinder> devFinder; + if (FAILED(::CoCreateInstance(CLSID_UPnPDeviceFinder, + NULL, + CLSCTX_ALL, + IID_PPV_ARGS(devFinder.init())))) + return -1; + + ComPtr<IEnumUnknown> devEnum = com_dynamic_cast<IEnumUnknown>(devColl); + if (!devEnum) + return -1; +*/ + +template <class T> +class ComPtr +{ +public: + ComPtr(); + ComPtr(const ComPtr& rhs); + ComPtr& operator=(const ComPtr& rhs); + ~ComPtr(); + T** init(); //get pointer for use with ::CoCreateInstance() + T* get() const; + T* release(); + void swap(ComPtr& rhs); //throw() + T* operator->() const; + operator bool() const; + +private: + T* ptr; +}; + + +template <class S, class T> +ComPtr<S> com_dynamic_cast(const ComPtr<T>& other); //throw() + + + + + + + + + + + + + + + + + + + + + + + + + +//################# Inline Implementation ############################# + +template <class T> +inline +ComPtr<T>::ComPtr() : ptr(NULL) {} + + +template <class T> +inline +ComPtr<T>::ComPtr(const ComPtr& rhs) : ptr(rhs.ptr) +{ + if (ptr) + ptr->AddRef(); +} + + +template <class T> +inline +ComPtr<T>& ComPtr<T>::operator=(const ComPtr<T>& rhs) +{ + ComPtr(rhs).swap(*this); + return *this; +} + + +template <class T> +inline +ComPtr<T>::~ComPtr() +{ + if (ptr) + ptr->Release(); +} + + +template <class T> +inline +T** ComPtr<T>::init() //get pointer for use with ::CoCreateInstance() +{ + ComPtr<T>().swap(*this); + return &ptr; +} + + +template <class T> +inline +T* ComPtr<T>::get() const +{ + return ptr; +} + + +template <class T> +inline +T* ComPtr<T>::release() //throw() +{ + T* tmp = ptr; + ptr = NULL; + return tmp; +} + + +template <class T> +inline +void ComPtr<T>::swap(ComPtr<T>& rhs) //throw() +{ + std::swap(ptr, rhs.ptr); +} + + +//we cannot specialize std::swap() for a class template and are not allowed to overload it => offer swap in own namespace +template <class T> +inline +void swap(util::ComPtr<T>& lhs, util::ComPtr<T>& rhs) +{ + lhs.swap(rhs); +} + + +template <class T> +inline +T* ComPtr<T>::operator->() const +{ + return ptr; +} + + +template <class T> +inline +ComPtr<T>::operator bool() const +{ + return ptr != NULL; +} + + +template <class S, class T> +inline +ComPtr<S> com_dynamic_cast(const ComPtr<T>& other) //throw() +{ + ComPtr<S> outPtr; + if (other) + other->QueryInterface(IID_PPV_ARGS(outPtr.init())); + return outPtr; +} + +} + + +#endif //SMART_COM_PTR_H
\ No newline at end of file diff --git a/shared/com_util.h b/shared/com_util.h new file mode 100644 index 00000000..bda3c732 --- /dev/null +++ b/shared/com_util.h @@ -0,0 +1,155 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef COM_UTILÎTY_HEADER +#define COM_UTILÎTY_HEADER + +#include "com_ptr.h" +#include <string> +#include <cassert> + + +namespace util +{ +//get an enumeration interface as a std::vector of bound(!) ComPtr(s) +template <class T, class U> +std::vector<ComPtr<T> > convertEnum(const ComPtr<U>& enumObj); //enumObj: must have the "_NewEnum" property that supports the IEnumUnknown interface + +/* +extract text from com object member function returning a single BSTR: HRESULT ComInterface::MemFun([out] BSTR *pbstr); + Example: ComPtr<...> comObj =...; + std::wstring description = getText(comObj, &IUPnPDevice::get_Description); +*/ +template <class T, class MemFun> +std::wstring getText(ComPtr<T> comObj, MemFun memFun); + + +//RAII class handling BSTR +class Bstring +{ +public: + Bstring(const std::wstring& str); + ~Bstring(); + + const BSTR get() const; + +private: + Bstring(const Bstring&); //not implemented + Bstring& operator=(const Bstring&); // + + BSTR str_; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//############################ inline implemenatation ################################## +template <class T, class U> +inline +std::vector<ComPtr<T> > convertEnum(const ComPtr<U>& enumObj) +{ + std::vector<ComPtr<T> > output; + + if (enumObj) + { + ComPtr<IUnknown> unknown; + enumObj->get__NewEnum(unknown.init()); + ComPtr<IEnumUnknown> enumUnknown = com_dynamic_cast<IEnumUnknown>(unknown); + + assert(enumUnknown); //IEnumUnknown must be supported! + if (enumUnknown) + { + ComPtr<IUnknown> itemTmp; + while (enumUnknown->Next(1, itemTmp.init(), NULL) == S_OK) //returns S_FALSE == 1 when finished! Don't use SUCCEEDED()!!! + { + ComPtr<T> itemNew = com_dynamic_cast<T>(itemTmp); + if (itemNew) + output.push_back(itemNew); + } + } + } + + return output; +} + + +template <class T, class MemFun> +inline +std::wstring getText(ComPtr<T> comObj, MemFun memFun) +{ + std::wstring text; + { + if (!comObj) + return std::wstring(); + + BSTR bstr = NULL; + if (FAILED((comObj.get()->*memFun)(&bstr))) + return std::wstring(); + + if (bstr) //NULL means "no text" + { + text = std::wstring(bstr, ::SysStringLen(bstr)); //correctly copy 0-characters + ::SysFreeString(bstr); + } + } + return text; +} + + +inline +Bstring::Bstring(const std::wstring& str) +{ + str_ = ::SysAllocStringLen(str.data(), str.length()); //string::data() returns unmodified string potentially containing 0-values +} + + +inline +Bstring::~Bstring() +{ + if (str_) + ::SysFreeString(str_); +} + + +inline +const BSTR Bstring::get() const +{ + return str_; +} +} + + +#endif //COM_UTILÎTY_HEADER
\ No newline at end of file diff --git a/shared/customButton.cpp b/shared/custom_button.cpp index 4e897844..fec3b4bb 100644 --- a/shared/customButton.cpp +++ b/shared/custom_button.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "customButton.h" +#include "custom_button.h" #include <wx/dcmemory.h> #include <wx/image.h> diff --git a/shared/customButton.h b/shared/custom_button.h index b50dd4da..b50dd4da 100644 --- a/shared/customButton.h +++ b/shared/custom_button.h diff --git a/shared/customComboBox.cpp b/shared/custom_combo_box.cpp index c27ce505..3c2a118c 100644 --- a/shared/customComboBox.cpp +++ b/shared/custom_combo_box.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "customComboBox.h" +#include "custom_combo_box.h" CustomComboBox::CustomComboBox(wxWindow* parent, diff --git a/shared/customComboBox.h b/shared/custom_combo_box.h index 7db8cecf..7db8cecf 100644 --- a/shared/customComboBox.h +++ b/shared/custom_combo_box.h diff --git a/shared/customTooltip.cpp b/shared/custom_tooltip.cpp index e483f7c7..b915b226 100644 --- a/shared/customTooltip.cpp +++ b/shared/custom_tooltip.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "customTooltip.h" +#include "custom_tooltip.h" #include <wx/stattext.h> #include <wx/sizer.h> #include <wx/statbmp.h> diff --git a/shared/customTooltip.h b/shared/custom_tooltip.h index c6bf6cd6..c6bf6cd6 100644 --- a/shared/customTooltip.h +++ b/shared/custom_tooltip.h diff --git a/shared/debugNew.cpp b/shared/debug_new.cpp index dad0cdd0..f5cd8368 100644 --- a/shared/debugNew.cpp +++ b/shared/debug_new.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "debugNew.h" +#include "debug_new.h" #include <wx/msw/wrapwin.h> //includes "windows.h" #include "DbgHelp.h" diff --git a/shared/debugNew.h b/shared/debug_new.h index 702cf774..c9c3dbf6 100644 --- a/shared/debugNew.h +++ b/shared/debug_new.h @@ -14,9 +14,9 @@ /*all this header does is to globally overwrite "operator new" to give some more detailed error messages and write memory dumps Usage: - - Include everywhere before any other file: $(ProjectDir)\shared\debugNew.h + - Include everywhere before any other file: $(ProjectDir)\shared\debug_new.h For Minidumps: - - Compile "debugNew.cpp" + - Compile "debug_new.cpp" - Include library "Dbghelp.lib" - Compile in Debug build (need Symbols and less restrictive Optimization) */ diff --git a/shared/dllLoader.cpp b/shared/dll_loader.cpp index f5242d83..6aa48fd7 100644 --- a/shared/dllLoader.cpp +++ b/shared/dll_loader.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "dllLoader.h" +#include "dll_loader.h" #include <wx/msw/wrapwin.h> //includes "windows.h" #include <map> #include <cassert> @@ -26,9 +26,9 @@ public: if (foundEntry == handles.end()) { HINSTANCE newHandle = ::LoadLibrary(libraryName.c_str()); - handles.insert(std::make_pair(libraryName, newHandle)); + if (newHandle != NULL) + handles.insert(std::make_pair(libraryName, newHandle)); - assert(handles.find(libraryName) != handles.end()); return newHandle; } else @@ -41,16 +41,16 @@ private: ~DllHandler() { for (HandleMap::const_iterator i = handles.begin(); i != handles.end(); ++i) - if (i->second != NULL) ::FreeLibrary(i->second); + ::FreeLibrary(i->second); } typedef std::map<std::wstring, HINSTANCE> HandleMap; - HandleMap handles; + HandleMap handles; //only valid handles here! }; } -void* Utility::loadSymbol(const std::wstring& libraryName, const std::string& functionName) +void* util::loadSymbol(const std::wstring& libraryName, const std::string& functionName) { const HINSTANCE libHandle = DllHandler::getInstance().getHandle(libraryName); diff --git a/shared/dllLoader.h b/shared/dll_loader.h index 318997d5..86723c68 100644 --- a/shared/dllLoader.h +++ b/shared/dll_loader.h @@ -9,7 +9,7 @@ #include <string> -namespace Utility +namespace util { //load function from a DLL library, e.g. from kernel32.dll diff --git a/shared/dragAndDrop.cpp b/shared/drag_n_drop.cpp index c5919e76..c4fc98f6 100644 --- a/shared/dragAndDrop.cpp +++ b/shared/drag_n_drop.cpp @@ -4,16 +4,16 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "dragAndDrop.h" +#include "drag_n_drop.h" #include <wx/dnd.h> #include <wx/window.h> #include <wx/combobox.h> #include <wx/textctrl.h> #include <wx/filepicker.h> #include <wx/filename.h> -#include "fileHandling.h" -#include "stringConv.h" -#include "checkExist.h" +#include "file_handling.h" +#include "string_conv.h" +#include "check_exist.h" //define new event type @@ -27,17 +27,17 @@ typedef void (wxEvtHandler::*FFSFileDropEventFunction)(FFSFileDropEvent&); class FFSFileDropEvent : public wxCommandEvent { public: - FFSFileDropEvent(const wxString& nameDropped, const wxWindow* dropWindow) : + FFSFileDropEvent(const std::vector<wxString>& filesDropped, const wxWindow* dropWindow) : wxCommandEvent(FFS_DROP_FILE_EVENT), - nameDropped_(nameDropped), + filesDropped_(filesDropped), dropWindow_(dropWindow) {} virtual wxEvent* Clone() const { - return new FFSFileDropEvent(nameDropped_, dropWindow_); + return new FFSFileDropEvent(filesDropped_, dropWindow_); } - const wxString nameDropped_; + const std::vector<wxString> filesDropped_; const wxWindow* dropWindow_; }; @@ -50,15 +50,17 @@ public: WindowDropTarget(wxWindow* dropWindow) : dropWindow_(dropWindow) {} - virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) + virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& fileArray) { - if (!filenames.IsEmpty()) - { - const wxString droppedFileName = filenames[0]; + std::vector<wxString> filenames; + for (size_t i = 0; i < fileArray.GetCount(); ++i) + filenames.push_back(fileArray[i]); + if (!filenames.empty()) + { //create a custom event on drop window: execute event after file dropping is completed! (e.g. after mouse is released) - FFSFileDropEvent evt(droppedFileName, dropWindow_); - dropWindow_->AddPendingEvent(evt); + FFSFileDropEvent evt(filenames, dropWindow_); + dropWindow_->GetEventHandler()->AddPendingEvent(evt); } return false; } @@ -71,7 +73,7 @@ private: //############################################################################################################## -using FreeFileSync::DragDropOnMainDlg; +using ffs3::DragDropOnMainDlg; DragDropOnMainDlg::DragDropOnMainDlg(wxWindow* dropWindow1, wxWindow* dropWindow2, @@ -91,19 +93,22 @@ DragDropOnMainDlg::DragDropOnMainDlg(wxWindow* dropWindow1, dropWindow2->Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(DragDropOnMainDlg::OnFilesDropped), NULL, this); //keep dirPicker and dirName synchronous - dirName->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DragDropOnMainDlg::OnWriteDirManually ), NULL, this ); - dirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( DragDropOnMainDlg::OnDirSelected ), NULL, this ); + dirName-> Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DragDropOnMainDlg::OnWriteDirManually), NULL, this ); + dirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler(DragDropOnMainDlg::OnDirSelected), NULL, this ); } void DragDropOnMainDlg::OnFilesDropped(FFSFileDropEvent& event) { + if (event.filesDropped_.empty()) + return; + if ( this->dropWindow1_ == event.dropWindow_ || //file may be dropped on window 1 or 2 this->dropWindow2_ == event.dropWindow_) { - if (AcceptDrop(event.nameDropped_)) + if (AcceptDrop(event.filesDropped_)) { - wxString fileName = event.nameDropped_; + wxString fileName = event.filesDropped_[0]; if (wxDirExists(fileName)) { dirName_->SetSelection(wxNOT_FOUND); @@ -122,8 +127,6 @@ void DragDropOnMainDlg::OnFilesDropped(FFSFileDropEvent& event) } } } - else //should never be reached - event.Skip(); } @@ -131,7 +134,7 @@ void DragDropOnMainDlg::OnWriteDirManually(wxCommandEvent& event) { const Zstring newDir = getFormattedDirectoryName(wxToZ(event.GetString())); - if (Utility::dirExists(newDir, 100) == Utility::EXISTING_TRUE) //potentially slow network access: wait 100 ms at most + if (util::dirExists(newDir, 100) == util::EXISTING_TRUE) //potentially slow network access: wait 100 ms at most dirPicker_->SetPath(zToWx(newDir)); event.Skip(); @@ -150,7 +153,7 @@ void DragDropOnMainDlg::OnDirSelected(wxFileDirPickerEvent& event) //############################################################################################################## -using FreeFileSync::DragDropOnDlg; +using ffs3::DragDropOnDlg; DragDropOnDlg::DragDropOnDlg(wxWindow* dropWindow, wxDirPickerCtrl* dirPicker, @@ -173,9 +176,12 @@ DragDropOnDlg::DragDropOnDlg(wxWindow* dropWindow, void DragDropOnDlg::OnFilesDropped(FFSFileDropEvent& event) { + if (event.filesDropped_.empty()) + return; + if (this->dropWindow_ == event.dropWindow_) { - wxString fileName = event.nameDropped_; + wxString fileName = event.filesDropped_[0]; if (wxDirExists(fileName)) { dirName_->SetValue(fileName); @@ -191,15 +197,13 @@ void DragDropOnDlg::OnFilesDropped(FFSFileDropEvent& event) } } } - else //should never be reached - event.Skip(); } void DragDropOnDlg::OnWriteDirManually(wxCommandEvent& event) { - const Zstring newDir = FreeFileSync::getFormattedDirectoryName(wxToZ(event.GetString())); - if (Utility::dirExists(newDir, 100) == Utility::EXISTING_TRUE) //potentially slow network access: wait 100 ms at most + const Zstring newDir = ffs3::getFormattedDirectoryName(wxToZ(event.GetString())); + if (util::dirExists(newDir, 100) == util::EXISTING_TRUE) //potentially slow network access: wait 100 ms at most dirPicker_->SetPath(zToWx(newDir)); event.Skip(); diff --git a/shared/dragAndDrop.h b/shared/drag_n_drop.h index 4fc839c0..88bb68c4 100644 --- a/shared/dragAndDrop.h +++ b/shared/drag_n_drop.h @@ -8,6 +8,7 @@ #define DRAGANDDROP_H_INCLUDED #include <wx/event.h> +#include <vector> class wxWindow; class wxDirPickerCtrl; @@ -19,7 +20,7 @@ class wxCommandEvent; class wxFileDirPickerEvent; -namespace FreeFileSync +namespace ffs3 { //add drag and drop functionality, coordinating a wxWindow, wxDirPickerCtrl, and wxComboBox/wxTextCtrl @@ -33,7 +34,7 @@ public: virtual ~DragDropOnMainDlg() {} - virtual bool AcceptDrop(const wxString& dropName) = 0; //return true if drop should be processed + virtual bool AcceptDrop(const std::vector<wxString>& droppedFiles) = 0; //return true if drop should be processed private: void OnFilesDropped(FFSFileDropEvent& event); diff --git a/shared/fileError.h b/shared/file_error.h index 210d1029..2804e337 100644 --- a/shared/fileError.h +++ b/shared/file_error.h @@ -10,7 +10,7 @@ #include <wx/string.h> -namespace FreeFileSync +namespace ffs3 { class FileError //Exception base class used to notify file/directory copy/delete errors { @@ -20,7 +20,7 @@ public: virtual ~FileError() {} - const wxString& show() const + const wxString& msg() const { return errorMessage; } @@ -28,6 +28,13 @@ public: private: const wxString errorMessage; }; + + +class ErrorNotExisting : public FileError +{ +public: + ErrorNotExisting(const wxString& message) : FileError(message) {} +}; } #endif // FILEERROR_H_INCLUDED diff --git a/shared/fileHandling.cpp b/shared/file_handling.cpp index 2a8af46a..3f56abe4 100644 --- a/shared/fileHandling.cpp +++ b/shared/file_handling.cpp @@ -4,38 +4,40 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "fileHandling.h" +#include "file_handling.h" #include <wx/intl.h> -#include "systemFunctions.h" -#include "globalFunctions.h" -#include "systemConstants.h" -#include "fileTraverser.h" +#include "system_func.h" +#include "global_func.h" +#include "system_constants.h" +#include "file_traverser.h" #include <boost/bind.hpp> #include <algorithm> #include <wx/datetime.h> -#include "stringConv.h" +#include "string_conv.h" #include <wx/utils.h> #include <boost/scoped_array.hpp> #include <boost/shared_ptr.hpp> #include <stdexcept> #include "loki/TypeManip.h" #include "loki/ScopeGuard.h" +#include <map> #ifdef FFS_WIN -#include "dllLoader.h" +#include "dll_loader.h" #include <wx/msw/wrapwin.h> //includes "windows.h" -#include "longPathPrefix.h" +#include "long_path_prefix.h" +#include <Aclapi.h> #elif defined FFS_LINUX #include <sys/stat.h> -#include "fileIO.h" +#include "file_io.h" #include <time.h> #include <utime.h> #include <cerrno> #include <sys/time.h> #endif -using FreeFileSync::FileError; +using ffs3::FileError; namespace @@ -80,7 +82,7 @@ bool replaceMacro(wxString& macro) //macro without %-characters, return true if if (macro.CmpNoCase(wxT("time")) == 0) { macro = wxDateTime::Now().FormatISOTime(); - macro.Replace(wxT(":"), wxT("-")); + macro.Replace(wxT(":"), wxT("")); return true; } @@ -90,6 +92,24 @@ bool replaceMacro(wxString& macro) //macro without %-characters, return true if return true; } + if (macro.CmpNoCase(wxT("month")) == 0) + { + macro = wxDateTime::Now().Format(wxT("%B")); + return true; + } + + if (macro.CmpNoCase(wxT("week")) == 0) + { + macro = wxDateTime::Now().Format(wxT("%U")); + return true; + } + + if (macro.CmpNoCase(wxT("year")) == 0) + { + macro = wxDateTime::Now().Format(wxT("%Y")); + return true; + } + //try to apply environment variables wxString envValue; if (wxGetEnv(macro, &envValue)) @@ -143,7 +163,7 @@ void expandMacros(wxString& text) } -Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname) +Zstring ffs3::getFormattedDirectoryName(const Zstring& dirname) { //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names. //note: don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix! @@ -170,14 +190,14 @@ Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname) */ dirnameTmp = zToWx(resolveRelativePath(wxToZ(dirnameTmp))); - if (!dirnameTmp.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR))) - dirnameTmp += zToWx(globalFunctions::FILE_NAME_SEPARATOR); + if (!dirnameTmp.EndsWith(zToWx(common::FILE_NAME_SEPARATOR))) + dirnameTmp += zToWx(common::FILE_NAME_SEPARATOR); return wxToZ(dirnameTmp); } -bool FreeFileSync::fileExists(const Zstring& filename) +bool ffs3::fileExists(const Zstring& filename) { //symbolic links (broken or not) are also treated as existing files! #ifdef FFS_WIN @@ -194,7 +214,7 @@ bool FreeFileSync::fileExists(const Zstring& filename) } -bool FreeFileSync::dirExists(const Zstring& dirname) +bool ffs3::dirExists(const Zstring& dirname) { //symbolic links (broken or not) are also treated as existing directories! #ifdef FFS_WIN @@ -212,7 +232,7 @@ bool FreeFileSync::dirExists(const Zstring& dirname) } -bool FreeFileSync::symlinkExists(const Zstring& objname) +bool ffs3::symlinkExists(const Zstring& objname) { #ifdef FFS_WIN const DWORD ret = ::GetFileAttributes(applyLongPathPrefix(objname).c_str()); @@ -226,7 +246,7 @@ bool FreeFileSync::symlinkExists(const Zstring& objname) } -bool FreeFileSync::somethingExists(const Zstring& objname) //throw() check whether any object with this name exists +bool ffs3::somethingExists(const Zstring& objname) //throw() check whether any object with this name exists { #ifdef FFS_WIN return ::GetFileAttributes(applyLongPathPrefix(objname).c_str()) != INVALID_FILE_ATTRIBUTES; @@ -244,7 +264,7 @@ namespace wxULongLong getFileSizeSymlink(const Zstring& linkName) //throw (FileError) { //open handle to target of symbolic link - const HANDLE hFile = ::CreateFile(FreeFileSync::applyLongPathPrefix(linkName).c_str(), + const HANDLE hFile = ::CreateFile(ffs3::applyLongPathPrefix(linkName).c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -260,14 +280,14 @@ wxULongLong getFileSizeSymlink(const Zstring& linkName) //throw (FileError) return wxULongLong(fileInfoByHandle.nFileSizeHigh, fileInfoByHandle.nFileSizeLow); } - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + FreeFileSync::zToWx(linkName) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + ffs3::zToWx(linkName) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } } #endif -wxULongLong FreeFileSync::getFilesize(const Zstring& filename) //throw (FileError) +wxULongLong ffs3::getFilesize(const Zstring& filename) //throw (FileError) { #ifdef FFS_WIN WIN32_FIND_DATA fileMetaData; @@ -275,7 +295,7 @@ wxULongLong FreeFileSync::getFilesize(const Zstring& filename) //throw (FileErro if (searchHandle == INVALID_HANDLE_VALUE) { const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } ::FindClose(searchHandle); @@ -290,7 +310,7 @@ wxULongLong FreeFileSync::getFilesize(const Zstring& filename) //throw (FileErro if (::stat(filename.c_str(), &fileInfo) != 0) //follow symbolic links { const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } return fileInfo.st_size; @@ -313,8 +333,8 @@ DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! return 0; Zstring volumePath = buffer.get(); - if (!volumePath.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) - volumePath += globalFunctions::FILE_NAME_SEPARATOR; + if (!volumePath.EndsWith(common::FILE_NAME_SEPARATOR)) + volumePath += common::FILE_NAME_SEPARATOR; DWORD volumeSerial = 0; if (!::GetVolumeInformation(volumePath.c_str(), //__in_opt LPCTSTR lpRootPathName, @@ -336,13 +356,13 @@ dev_t retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! Zstring volumePathName = pathName; //remove trailing slash - if (volumePathName.size() > 1 && volumePathName.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) //exception: allow '/' - volumePathName = volumePathName.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); + if (volumePathName.size() > 1 && volumePathName.EndsWith(common::FILE_NAME_SEPARATOR)) //exception: allow '/' + volumePathName = volumePathName.BeforeLast(common::FILE_NAME_SEPARATOR); struct stat fileInfo; while (::lstat(volumePathName.c_str(), &fileInfo) != 0) { - volumePathName = volumePathName.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); //returns empty string if ch not found + volumePathName = volumePathName.BeforeLast(common::FILE_NAME_SEPARATOR); //returns empty string if ch not found if (volumePathName.empty()) return 0; //this includes path "/" also! } @@ -353,7 +373,7 @@ dev_t retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! } -FreeFileSync::ResponseSameVol FreeFileSync::onSameVolume(const Zstring& folderLeft, const Zstring& folderRight) //throw() +ffs3::ResponseSameVol ffs3::onSameVolume(const Zstring& folderLeft, const Zstring& folderRight) //throw() { #ifdef FFS_WIN typedef DWORD VolSerial; @@ -369,7 +389,7 @@ FreeFileSync::ResponseSameVol FreeFileSync::onSameVolume(const Zstring& folderLe } -void FreeFileSync::removeFile(const Zstring& filename) //throw (FileError); +void ffs3::removeFile(const Zstring& filename) //throw (FileError); { //no error situation if file is not existing! manual deletion relies on it! if (!somethingExists(filename)) @@ -395,13 +415,13 @@ void FreeFileSync::removeFile(const Zstring& filename) //throw (FileError); } wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } #elif defined FFS_LINUX if (::unlink(filename.c_str()) != 0) { wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } #endif } @@ -409,7 +429,7 @@ void FreeFileSync::removeFile(const Zstring& filename) //throw (FileError); namespace { -struct ErrorDifferentVolume : public FreeFileSync::FileError +struct ErrorDifferentVolume : public ffs3::FileError { ErrorDifferentVolume(const wxString& message) : FileError(message) {} }; @@ -425,7 +445,7 @@ struct ErrorDifferentVolume : public FreeFileSync::FileError //throw (FileError); ErrorDifferentVolume if it is due to moving file to another volume void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw (FileError, ErrorDifferentVolume) { - using namespace FreeFileSync; //for zToWx() + using namespace ffs3; //for zToWx() #ifdef FFS_WIN const Zstring oldNameFmt = applyLongPathPrefix(oldName); @@ -467,7 +487,7 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw } const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(oldName) + wxT("\" ->\n\"") + zToWx(newName) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted(); + wxT("\n\n") + ffs3::getLastErrorFormatted(); if (::GetLastError() == ERROR_NOT_SAME_DEVICE) throw ErrorDifferentVolume(errorMessage); else @@ -479,7 +499,7 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw if (::rename(oldName.c_str(), newName.c_str()) != 0) { const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(oldName) + wxT("\" ->\n\"") + zToWx(newName) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted(); + wxT("\n\n") + ffs3::getLastErrorFormatted(); if (errno == EXDEV) throw ErrorDifferentVolume(errorMessage); else @@ -506,7 +526,7 @@ void renameFileInternalNoThrow(const Zstring& oldName, const Zstring& newName) / template <typename Function> Zstring getFilenameFmt(const Zstring& filename, Function fun) //throw(); returns empty string on error { - const Zstring filenameFmt = FreeFileSync::applyLongPathPrefix(filename); + const Zstring filenameFmt = ffs3::applyLongPathPrefix(filename); const DWORD bufferSize = fun(filenameFmt.c_str(), NULL, 0); if (bufferSize == 0) @@ -526,10 +546,10 @@ Zstring getFilenameFmt(const Zstring& filename, Function fun) //throw(); returns Zstring createTemp8Dot3Name(const Zstring& fileName) //find a unique 8.3 short name { - const Zstring pathPrefix = fileName.Find(globalFunctions::FILE_NAME_SEPARATOR) != Zstring::npos ? - (fileName.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) + globalFunctions::FILE_NAME_SEPARATOR) : Zstring(); + const Zstring pathPrefix = fileName.Find(common::FILE_NAME_SEPARATOR) != Zstring::npos ? + (fileName.BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR) : Zstring(); - Zstring extension = fileName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR).AfterLast(DefaultChar('.')); //extension needn't contain reasonable data + Zstring extension = fileName.AfterLast(common::FILE_NAME_SEPARATOR).AfterLast(DefaultChar('.')); //extension needn't contain reasonable data if (extension.empty()) extension = DefaultStr("FFS"); extension.Truncate(3); @@ -537,7 +557,7 @@ Zstring createTemp8Dot3Name(const Zstring& fileName) //find a unique 8.3 short n for (int index = 0; index < 100000000; ++index) //filename must be representable by <= 8 characters { const Zstring output = pathPrefix + numberToZstring(index) + DefaultChar('.') + extension; - if (!FreeFileSync::somethingExists(output)) //ensure uniqueness + if (!ffs3::somethingExists(output)) //ensure uniqueness return output; } @@ -548,26 +568,26 @@ Zstring createTemp8Dot3Name(const Zstring& fileName) //find a unique 8.3 short n //try to handle issues with already existing short 8.3 file names on Windows 7 bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw (FileError); return "true" if rename operation succeeded { - using namespace FreeFileSync; + using namespace ffs3; - if (newName.Find(globalFunctions::FILE_NAME_SEPARATOR) == Zstring::npos) + if (newName.Find(common::FILE_NAME_SEPARATOR) == Zstring::npos) return false; - if (FreeFileSync::somethingExists(newName)) //name OR directory! + if (ffs3::somethingExists(newName)) //name OR directory! { - const Zstring fileNameOrig = newName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR); //returns the whole string if ch not found - const Zstring fileNameShort = getFilenameFmt(newName, ::GetShortPathName).AfterLast(globalFunctions::FILE_NAME_SEPARATOR); //throw() returns empty string on error - const Zstring fileNameLong = getFilenameFmt(newName, ::GetLongPathName).AfterLast(globalFunctions::FILE_NAME_SEPARATOR); //throw() returns empty string on error + const Zstring fileNameOrig = newName.AfterLast(common::FILE_NAME_SEPARATOR); //returns the whole string if ch not found + const Zstring fileNameShort = getFilenameFmt(newName, ::GetShortPathName).AfterLast(common::FILE_NAME_SEPARATOR); //throw() returns empty string on error + const Zstring fileNameLong = getFilenameFmt(newName, ::GetLongPathName).AfterLast(common::FILE_NAME_SEPARATOR); //throw() returns empty string on error if ( !fileNameShort.empty() && !fileNameLong.empty() && - fileNameOrig.cmpFileName(fileNameShort) == 0 && - fileNameShort.cmpFileName(fileNameLong) != 0) + cmpFileName(fileNameOrig, fileNameShort) == 0 && + cmpFileName(fileNameShort, fileNameLong) != 0) { //we detected an event where newName is in shortname format (although it is intended to be a long name) and //writing target file failed because another unrelated file happens to have the same short name - const Zstring newNameFullPathLong = newName.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) + globalFunctions::FILE_NAME_SEPARATOR + + const Zstring newNameFullPathLong = newName.BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + fileNameLong; //find another name in short format: this ensures the actual short name WILL be renamed as well! @@ -575,7 +595,7 @@ bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw //move already existing short name out of the way for now renameFileInternal(newNameFullPathLong, parkedTarget); //throw (FileError, ErrorDifferentVolume); - //DON'T call FreeFileSync::renameFile() to avoid reentrance! + //DON'T call ffs3::renameFile() to avoid reentrance! //schedule cleanup; the file system should assign this unrelated file a new (unique) short name Loki::ScopeGuard guard = Loki::MakeGuard(renameFileInternalNoThrow, parkedTarget, newNameFullPathLong);//equivalent to Boost.ScopeExit in this case @@ -592,7 +612,7 @@ bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw //rename file: no copying!!! -void FreeFileSync::renameFile(const Zstring& oldName, const Zstring& newName) //throw (FileError, ErrorDifferentVolume); +void ffs3::renameFile(const Zstring& oldName, const Zstring& newName) //throw (FileError, ErrorDifferentVolume); { try { @@ -609,9 +629,9 @@ void FreeFileSync::renameFile(const Zstring& oldName, const Zstring& newName) // } -using FreeFileSync::MoveFileCallback; +using ffs3::MoveFileCallback; -class CopyCallbackImpl : public FreeFileSync::CopyFileCallback //callback functionality +class CopyCallbackImpl : public ffs3::CopyFileCallback //callback functionality { public: CopyCallbackImpl(MoveFileCallback* callback) : moveCallback(callback) {} @@ -634,7 +654,7 @@ private: }; -void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCallback* callback) //throw (FileError); +void ffs3::moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCallback* callback) //throw (FileError); { if (somethingExists(targetFile)) //test file existence: e.g. Linux might silently overwrite existing symlinks { @@ -660,6 +680,7 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile copyFile(sourceFile, targetFile, true, //copy symbolic links + false, //dont copy filesystem permissions #ifdef FFS_WIN NULL, //supply handler for making shadow copies #endif @@ -671,7 +692,7 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile } -class TraverseOneLevel : public FreeFileSync::TraverseCallback +class TraverseOneLevel : public ffs3::TraverseCallback { public: typedef std::vector<std::pair<Zstring, Zstring> > NamePair; @@ -710,12 +731,12 @@ private: void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback) //throw (FileError); { - using namespace FreeFileSync; + using namespace ffs3; //handle symbolic links if (symlinkExists(sourceDir)) { - createDirectory(targetDir, sourceDir, true); //copy symbolic link + createDirectory(targetDir, sourceDir, true, false); //copy symbolic link, don't copy permissions removeDirectory(sourceDir); //if target is already another symlink or directory, sourceDir-symlink is silently deleted return; } @@ -740,7 +761,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool catch (const ErrorDifferentVolume&) {} //create target - createDirectory(targetDir, sourceDir, false); //throw (FileError); + createDirectory(targetDir, sourceDir, false, false); //throw (FileError); don't copy permissions } //call back once per folder @@ -763,13 +784,13 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool TraverseOneLevel traverseCallback(fileList, dirList); traverseFolder(sourceDir, false, &traverseCallback); //traverse one level, don't follow symlinks - const Zstring targetDirFormatted = targetDir.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //ends with path separator + const Zstring targetDirFormatted = targetDir.EndsWith(common::FILE_NAME_SEPARATOR) ? //ends with path separator targetDir : - targetDir + globalFunctions::FILE_NAME_SEPARATOR; + targetDir + common::FILE_NAME_SEPARATOR; //move files for (TraverseOneLevel::NamePair::const_iterator i = fileList.begin(); i != fileList.end(); ++i) - FreeFileSync::moveFile(i->second, targetDirFormatted + i->first, callback); + ffs3::moveFile(i->second, targetDirFormatted + i->first, callback); //move directories for (TraverseOneLevel::NamePair::const_iterator i = dirList.begin(); i != dirList.end(); ++i) @@ -782,7 +803,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool } -void FreeFileSync::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback) //throw (FileError); +void ffs3::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback) //throw (FileError); { #ifdef FFS_WIN const Zstring& sourceDirFormatted = sourceDir; @@ -790,12 +811,12 @@ void FreeFileSync::moveDirectory(const Zstring& sourceDir, const Zstring& target #elif defined FFS_LINUX const Zstring sourceDirFormatted = //remove trailing slash - sourceDir.size() > 1 && sourceDir.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //exception: allow '/' - sourceDir.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) : + sourceDir.size() > 1 && sourceDir.EndsWith(common::FILE_NAME_SEPARATOR) ? //exception: allow '/' + sourceDir.BeforeLast(common::FILE_NAME_SEPARATOR) : sourceDir; const Zstring targetDirFormatted = //remove trailing slash - targetDir.size() > 1 && targetDir.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //exception: allow '/' - targetDir.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) : + targetDir.size() > 1 && targetDir.EndsWith(common::FILE_NAME_SEPARATOR) ? //exception: allow '/' + targetDir.BeforeLast(common::FILE_NAME_SEPARATOR) : targetDir; #endif @@ -803,7 +824,7 @@ void FreeFileSync::moveDirectory(const Zstring& sourceDir, const Zstring& target } -class FilesDirsOnlyTraverser : public FreeFileSync::TraverseCallback +class FilesDirsOnlyTraverser : public ffs3::TraverseCallback { public: FilesDirsOnlyTraverser(std::vector<Zstring>& files, std::vector<Zstring>& dirs) : @@ -837,7 +858,7 @@ private: }; -void FreeFileSync::removeDirectory(const Zstring& directory) +void ffs3::removeDirectory(const Zstring& directory) { //no error situation if directory is not existing! manual deletion relies on it! if (!somethingExists(directory)) @@ -852,7 +873,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory) FILE_ATTRIBUTE_NORMAL)) // attributes to set { wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } #endif @@ -867,7 +888,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory) #endif { wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } return; } @@ -877,7 +898,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory) //get all files and directories from current directory (WITHOUT subdirectories!) FilesDirsOnlyTraverser traverser(fileList, dirList); - FreeFileSync::traverseFolder(directory, false, &traverser); //don't follow symlinks + ffs3::traverseFolder(directory, false, &traverser); //don't follow symlinks //delete files std::for_each(fileList.begin(), fileList.end(), removeFile); @@ -893,13 +914,13 @@ void FreeFileSync::removeDirectory(const Zstring& directory) #endif { wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } } //optionally: copy directory last change date, DO NOTHING if something fails -bool FreeFileSync::copyFileTimes(const Zstring& sourceDir, const Zstring& targetDir, bool deRefSymlinks) //throw() +void ffs3::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool deRefSymlinks) //throw (FileError) { #ifdef FFS_WIN FILETIME creationTime = {0}; @@ -908,30 +929,39 @@ bool FreeFileSync::copyFileTimes(const Zstring& sourceDir, const Zstring& target { WIN32_FILE_ATTRIBUTE_DATA sourceAttr; - if (!::GetFileAttributesEx(applyLongPathPrefix(sourceDir).c_str(), //__in LPCTSTR lpFileName, + if (!::GetFileAttributesEx(applyLongPathPrefix(sourceObj).c_str(), //__in LPCTSTR lpFileName, GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId, &sourceAttr)) //__out LPVOID lpFileInformation - return false; + { + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } if ((sourceAttr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && deRefSymlinks) //we have a symlink AND need to dereference... { - HANDLE hDirRead = ::CreateFile(applyLongPathPrefix(sourceDir).c_str(), - FILE_READ_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, //needed to open a directory; no FILE_FLAG_OPEN_REPARSE_POINT => deref symlinks - NULL); - if (hDirRead == INVALID_HANDLE_VALUE) - return false; - - boost::shared_ptr<void> dummy(hDirRead, ::CloseHandle); - - if (!::GetFileTime(hDirRead, //__in HANDLE hFile, + HANDLE hSource = ::CreateFile(applyLongPathPrefix(sourceObj).c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, //needed to open a directory; no FILE_FLAG_OPEN_REPARSE_POINT => deref symlinks + NULL); + if (hSource == INVALID_HANDLE_VALUE) + { + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } + + boost::shared_ptr<void> dummy(hSource, ::CloseHandle); + + if (!::GetFileTime(hSource, //__in HANDLE hFile, &creationTime, //__out_opt LPFILETIME lpCreationTime, &lastAccessTime, //__out_opt LPFILETIME lpLastAccessTime, &lastWriteTime)) //__out_opt LPFILETIME lpLastWriteTime - return false; + { + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } } else { @@ -941,59 +971,75 @@ bool FreeFileSync::copyFileTimes(const Zstring& sourceDir, const Zstring& target } } + HANDLE hTarget = ::CreateFile(applyLongPathPrefix(targetObj).c_str(), + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | //needed to open a directory + (deRefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), //process symlinks + NULL); + if (hTarget == INVALID_HANDLE_VALUE) + { + wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } - HANDLE hDirWrite = ::CreateFile(applyLongPathPrefix(targetDir).c_str(), - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | //needed to open a directory - (deRefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), //process symlinks - NULL); - if (hDirWrite == INVALID_HANDLE_VALUE) - return false; - - boost::shared_ptr<void> dummy(hDirWrite, ::CloseHandle); + boost::shared_ptr<void> dummy(hTarget, ::CloseHandle); - if (!::SetFileTime(hDirWrite, + if (!::SetFileTime(hTarget, &creationTime, &lastAccessTime, &lastWriteTime)) //return value not evalutated! - return false; + { + wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } #elif defined FFS_LINUX if (deRefSymlinks) { - struct stat dirInfo; - if (::stat(sourceDir.c_str(), &dirInfo) != 0) //read file attributes from source directory - return false; + struct stat objInfo; + if (::stat(sourceObj.c_str(), &objInfo) != 0) //read file attributes from source directory + { + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } struct utimbuf newTimes; - newTimes.actime = dirInfo.st_atime; - newTimes.modtime = dirInfo.st_mtime; + newTimes.actime = objInfo.st_atime; + newTimes.modtime = objInfo.st_mtime; //(try to) set new "last write time" - if (::utime(targetDir.c_str(), &newTimes) != 0) //return value not evalutated! - return false; + if (::utime(targetObj.c_str(), &newTimes) != 0) //return value not evalutated! + { + wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } } else { - struct stat dirInfo; - if (::lstat(sourceDir.c_str(), &dirInfo) != 0) //read file attributes from source directory - return false; + struct stat objInfo; + if (::lstat(sourceObj.c_str(), &objInfo) != 0) //read file attributes from source directory + { + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } struct timeval newTimes[2]; - newTimes[0].tv_sec = dirInfo.st_atime; /* seconds */ + newTimes[0].tv_sec = objInfo.st_atime; /* seconds */ newTimes[0].tv_usec = 0; /* microseconds */ - newTimes[1].tv_sec = dirInfo.st_mtime; /* seconds */ + newTimes[1].tv_sec = objInfo.st_mtime; /* seconds */ newTimes[1].tv_usec = 0; /* microseconds */ - if (::lutimes(targetDir.c_str(), newTimes) != 0) //return value not evalutated! - return false; + if (::lutimes(targetObj.c_str(), newTimes) != 0) //return value not evalutated! + { + wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); + } } #endif - return true; } @@ -1003,7 +1049,7 @@ namespace Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target path of symbolic link to a directory { //open handle to target of symbolic link - const HANDLE hDir = ::CreateFile(FreeFileSync::applyLongPathPrefix(dirLinkName).c_str(), + const HANDLE hDir = ::CreateFile(ffs3::applyLongPathPrefix(dirLinkName).c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -1018,7 +1064,6 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa const size_t BUFFER_SIZE = 10000; TCHAR targetPath[BUFFER_SIZE]; - //dynamically load windows API function typedef DWORD (WINAPI *GetFinalPathNameByHandleWFunc)( HANDLE hFile, @@ -1026,7 +1071,7 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa DWORD cchFilePath, DWORD dwFlags); static const GetFinalPathNameByHandleWFunc getFinalPathNameByHandle = - Utility::loadDllFunction<GetFinalPathNameByHandleWFunc>(L"kernel32.dll", "GetFinalPathNameByHandleW"); + util::loadDllFunction<GetFinalPathNameByHandleWFunc>(L"kernel32.dll", "GetFinalPathNameByHandleW"); if (getFinalPathNameByHandle == NULL) throw FileError(wxString(_("Error loading library function:")) + wxT("\n\"") + wxT("GetFinalPathNameByHandleW") + wxT("\"")); @@ -1042,55 +1087,11 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa return targetPath; } -//#include <aclapi.h> -////optionally: copy additional metadata, DO NOTHING if something fails -//void copyAdditionalMetadata(const Zstring& sourceDir, const Zstring& targetDir) -//{ -// //copy NTFS permissions -// -// PSECURITY_DESCRIPTOR pSD; -// -// PACL pDacl; -// if (::GetNamedSecurityInfo( -// const_cast<DefaultChar*>(sourceDir.c_str()), -// SE_FILE_OBJECT, //file or directory -// DACL_SECURITY_INFORMATION, -// NULL, -// NULL, -// &pDacl, -// NULL, -// &pSD -// ) == ERROR_SUCCESS) -// { -// //(try to) set new security information -// if (::SetNamedSecurityInfo( -// const_cast<DefaultChar*>(targetDir.c_str()), -// SE_FILE_OBJECT, //file or directory -// DACL_SECURITY_INFORMATION, -// NULL, -// NULL, -// pDacl, -// NULL) != ERROR_SUCCESS) //return value not evalutated! -// { -// const wxString errorMessage = wxString(wxT("Error 2:")) + wxT("\n\"") + targetDir.c_str() + wxT("\""); -// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); -// } -// -//#warning BUG! -// LocalFree(pSD); -// } -// else -// { -// const wxString errorMessage = wxString(wxT("Error 1:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\""); -// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); -// } -// -//} #elif defined FFS_LINUX -void copySymlinkInternal(const Zstring& sourceLink, const Zstring& targetLink) //throw (FileError) +void copySymlinkInternal(const Zstring& sourceLink, const Zstring& targetLink, bool copyFilePermissions) //throw (FileError) { - using namespace FreeFileSync; + using namespace ffs3; //copy symbolic link const int BUFFER_SIZE = 10000; @@ -1099,7 +1100,7 @@ void copySymlinkInternal(const Zstring& sourceLink, const Zstring& targetLink) / if (bytesWritten < 0 || bytesWritten == BUFFER_SIZE) { wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zToWx(sourceLink) + wxT("\""); - if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + FreeFileSync::getLastErrorFormatted(); + if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + ffs3::getLastErrorFormatted(); throw FileError(errorMessage); } //set null-terminating char @@ -1108,54 +1109,325 @@ void copySymlinkInternal(const Zstring& sourceLink, const Zstring& targetLink) / if (::symlink(buffer, targetLink.c_str()) != 0) { const wxString errorMessage = wxString(_("Error copying symbolic link:")) + wxT("\n\"") + zToWx(sourceLink) + wxT("\" ->\n\"") + zToWx(targetLink) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } //allow only consistent objects to be created -> don't place before ::symlink, targetLink may already exist Loki::ScopeGuard guardTargetLink = Loki::MakeGuard(::unlink, targetLink); - if (!copyFileTimes(sourceLink, targetLink, false)) + copyFileTimes(sourceLink, targetLink, false); //throw (FileError) + + if (copyFilePermissions) + copyObjectPermissions(sourceLink, targetLink, false); //throw FileError() + + guardTargetLink.Dismiss(); +} +#endif +} + + +namespace ffs3 +{ +#ifdef FFS_WIN +class Privileges +{ +public: + static Privileges& getInstance() { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetLink) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + static Privileges instance; + return instance; } - guardTargetLink.Dismiss(); + void ensureActive(LPCTSTR privilege) //throw FileError() + { + if (activePrivileges.find(privilege) != activePrivileges.end()) + return; //privilege already active + + if (privilegeIsActive(privilege)) //privilege was already active before starting this tool + activePrivileges.insert(std::make_pair(privilege, false)); + else + { + setPrivilege(privilege, true); + activePrivileges.insert(std::make_pair(privilege, true)); + } + } + +private: + Privileges() {} + Privileges(Privileges&); + void operator=(Privileges&); + + ~Privileges() //clean up: deactivate all privileges that have been activated by this application + { + for (PrivBuffType::const_iterator i = activePrivileges.begin(); i != activePrivileges.end(); ++i) + try + { + if (i->second) + Privileges::setPrivilege(i->first, false); + } + catch(...) {} + } + + static bool privilegeIsActive(LPCTSTR privilege); //throw FileError() + static void setPrivilege(LPCTSTR privilege, bool enable); //throw FileError() + + typedef std::map<Zstring, bool> PrivBuffType; //bool: enabled by this application + + PrivBuffType activePrivileges; +}; + + +bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw FileError() +{ + HANDLE hToken = NULL; + if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, + TOKEN_QUERY, //__in DWORD DesiredAccess, + &hToken)) //__out PHANDLE TokenHandle + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + boost::shared_ptr<void> dummy(hToken, ::CloseHandle); + + LUID luid = {0}; + if (!::LookupPrivilegeValue( + NULL, //__in_opt LPCTSTR lpSystemName, + privilege, //__in LPCTSTR lpName, + &luid )) //__out PLUID lpLuid + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + + PRIVILEGE_SET priv = {0}; + priv.PrivilegeCount = 1; + priv.Control = PRIVILEGE_SET_ALL_NECESSARY; + priv.Privilege[0].Luid = luid; + priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + + BOOL alreadyGranted = FALSE; + if (!::PrivilegeCheck( + hToken, //__in HANDLE ClientToken, + &priv, //__inout PPRIVILEGE_SET RequiredPrivileges, + &alreadyGranted)) //__out LPBOOL pfResult + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + + return alreadyGranted == TRUE; } + + +void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw FileError() +{ + HANDLE hToken = NULL; + if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, + TOKEN_ADJUST_PRIVILEGES, //__in DWORD DesiredAccess, + &hToken)) //__out PHANDLE TokenHandle + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + boost::shared_ptr<void> dummy(hToken, ::CloseHandle); + + LUID luid = {0}; + if (!::LookupPrivilegeValue( + NULL, //__in_opt LPCTSTR lpSystemName, + privilege, //__in LPCTSTR lpName, + &luid )) //__out PLUID lpLuid + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + + TOKEN_PRIVILEGES tp = {0}; + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; + + if (!::AdjustTokenPrivileges( + hToken, //__in HANDLE TokenHandle, + false, //__in BOOL DisableAllPrivileges, + &tp, //__in_opt PTOKEN_PRIVILEGES NewState, + 0, //__in DWORD BufferLength, + NULL, //__out_opt PTOKEN_PRIVILEGES PreviousState, + NULL)) //__out_opt PDWORD ReturnLength + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + + if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED) //check although previous function returned with success! + { + const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } +} +#endif +} + + +//copy permissions for files, directories or symbolic links +void ffs3::copyObjectPermissions(const Zstring& source, const Zstring& target, bool derefSymlinks) //throw FileError(); probably requires admin rights +{ +#ifdef FFS_WIN + //enable privilege: required to read/write SACL information + Privileges::getInstance().ensureActive(SE_SECURITY_NAME); //polling allowed... + + //enable privilege: required to copy owner information + Privileges::getInstance().ensureActive(SE_RESTORE_NAME); + + //the following privilege may be required according to http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx (although not needed nor active in my tests) + Privileges::getInstance().ensureActive(SE_BACKUP_NAME); + + PSECURITY_DESCRIPTOR buffer = NULL; + PSID owner = NULL; + PSID group = NULL; + PACL dacl = NULL; + PACL sacl = NULL; + + //http://msdn.microsoft.com/en-us/library/aa364399(v=VS.85).aspx + const HANDLE hSource = ::CreateFile(ffs3::applyLongPathPrefix(source).c_str(), + READ_CONTROL | ACCESS_SYSTEM_SECURITY, //ACCESS_SYSTEM_SECURITY required for SACL access + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | (derefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), //FILE_FLAG_BACKUP_SEMANTICS needed to open a directory + NULL); + if (hSource == INVALID_HANDLE_VALUE) + throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(source) + wxT("\"") + + wxT("\n\n") + ffs3::getLastErrorFormatted()); + boost::shared_ptr<void> dummy(hSource, ::CloseHandle); + +// DWORD rc = ::GetNamedSecurityInfo(const_cast<WCHAR*>(applyLongPathPrefix(source).c_str()), -> does NOT dereference symlinks! + DWORD rc = ::GetSecurityInfo( + hSource, //__in LPTSTR pObjectName, + SE_FILE_OBJECT, //__in SE_OBJECT_TYPE ObjectType, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInfo, + &owner, //__out_opt PSID *ppsidOwner, + &group, //__out_opt PSID *ppsidGroup, + &dacl, //__out_opt PACL *ppDacl, + &sacl, //__out_opt PACL *ppSacl, + &buffer); //__out_opt PSECURITY_DESCRIPTOR *ppSecurityDescriptor + if (rc != ERROR_SUCCESS) + { + const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted(rc)); + } + boost::shared_ptr<void> dummy2(buffer, ::LocalFree); + + + const Zstring targetFmt = ffs3::applyLongPathPrefix(target); + + //read-only file attribute may cause trouble: temporarily reset it + const DWORD targetAttr = ::GetFileAttributes(targetFmt.c_str()); + Loki::ScopeGuard resetAttributes = Loki::MakeGuard(::SetFileAttributes, targetFmt, targetAttr); + if ( targetAttr != INVALID_FILE_ATTRIBUTES && + (targetAttr & FILE_ATTRIBUTE_READONLY)) + ::SetFileAttributes(targetFmt.c_str(), targetAttr & (~FILE_ATTRIBUTE_READONLY)); //try to... + else + resetAttributes.Dismiss(); + + + HANDLE hTarget = ::CreateFile( targetFmt.c_str(), // lpFileName + FILE_GENERIC_WRITE | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY, // dwDesiredAccess: all four seem to be required!!! + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // dwShareMode + NULL, // lpSecurityAttributes + OPEN_EXISTING, // dwCreationDisposition + FILE_FLAG_BACKUP_SEMANTICS | (derefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), // dwFlagsAndAttributes + NULL); // hTemplateFile + if (hTarget == INVALID_HANDLE_VALUE) + throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(target) + wxT("\"") + + wxT("\n\n") + ffs3::getLastErrorFormatted()); + boost::shared_ptr<void> dummy3(hTarget, ::CloseHandle); + +// rc = ::SetNamedSecurityInfo(const_cast<WCHAR*>(applyLongPathPrefix(target).c_str()), //__in LPTSTR pObjectName, -> does NOT dereference symlinks! + rc = ::SetSecurityInfo( + hTarget, //__in LPTSTR pObjectName, + SE_FILE_OBJECT, //__in SE_OBJECT_TYPE ObjectType, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInfo, + owner, //__in_opt PSID psidOwner, + group, //__in_opt PSID psidGroup, + dacl, //__in_opt PACL pDacl, + sacl); //__in_opt PACL pSacl + + if (rc != ERROR_SUCCESS) + { + const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted(rc)); + } + +#elif defined FFS_LINUX + if (derefSymlinks) + { + struct stat fileInfo; + if ( ::stat(source.c_str(), &fileInfo) != 0 || + ::chown(target.c_str(), fileInfo.st_uid, fileInfo.st_gid) != 0 || // may require admin rights! + ::chmod(target.c_str(), fileInfo.st_mode) != 0) + { + const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + } + else + { + struct stat fileInfo; + if ( ::lstat(source.c_str(), &fileInfo) != 0 || + ::lchown(target.c_str(), fileInfo.st_uid, fileInfo.st_gid) != 0 || // may require admin rights! + (!symlinkExists(target) && ::chmod(target.c_str(), fileInfo.st_mode) != 0)) //setting access permissions doesn't make sense for symlinks on Linux: there is no lchmod() + { + const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\"") + wxT("\n\n"); + throw FileError(errorMessage + ffs3::getLastErrorFormatted()); + } + } #endif } -void createDirectoryRecursively(const Zstring& directory, const Zstring& templateDir, const bool copyDirectorySymLinks, const int level) + +void createDirectoryRecursively(const Zstring& directory, const Zstring& templateDir, bool copyDirectorySymLinks, bool copyFilePermissions, int level) { - using namespace FreeFileSync; + using namespace ffs3; - if (FreeFileSync::dirExists(directory)) + if (ffs3::dirExists(directory)) return; if (level == 100) //catch endless recursion return; //try to create parent folders first - const Zstring dirParent = directory.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); - if (!dirParent.empty() && !FreeFileSync::dirExists(dirParent)) + const Zstring dirParent = directory.BeforeLast(common::FILE_NAME_SEPARATOR); + if (!dirParent.empty() && !ffs3::dirExists(dirParent)) { //call function recursively - const Zstring templateParent = templateDir.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); - createDirectoryRecursively(dirParent, templateParent, false, level + 1); //don't create symbolic links in recursion! + const Zstring templateParent = templateDir.BeforeLast(common::FILE_NAME_SEPARATOR); + createDirectoryRecursively(dirParent, templateParent, false, copyFilePermissions, level + 1); //don't create symbolic links in recursion! } + struct TryCleanUp + { + static void tryDeleteDir(const Zstring& linkname) //throw () + { + try + { + removeDirectory(linkname); + } + catch (...) {} + } + }; + //now creation should be possible #ifdef FFS_WIN - const DWORD templateAttr = templateDir.empty() ? - INVALID_FILE_ATTRIBUTES : + const DWORD templateAttr = templateDir.empty() ? INVALID_FILE_ATTRIBUTES : ::GetFileAttributes(applyLongPathPrefix(templateDir).c_str()); //returns successful for broken symlinks if (templateAttr == INVALID_FILE_ATTRIBUTES) //fallback { if (!::CreateDirectory(applyLongPathPrefixCreateDir(directory).c_str(), // pointer to a directory path string - NULL) && level == 0) + NULL)) { + if (level != 0) return; const wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } } else @@ -1169,22 +1441,18 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat const Zstring linkPath = resolveDirectorySymlink(templateDir); if (linkPath.empty()) { - if (level == 0) - throw FileError(wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + templateDir.c_str() + wxT("\"")); + if (level != 0) return; + throw FileError(wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + templateDir.c_str() + wxT("\"")); } - else - { - if (!::CreateDirectoryEx( // this function automatically copies symbolic links if encountered - applyLongPathPrefix(linkPath).c_str(), // pointer to path string of template directory - applyLongPathPrefixCreateDir(directory).c_str(), // pointer to a directory path string - NULL) && level == 0) - { - const wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); - } - //(try to) copy additional metadata like last modification time: no measurable performance drawback - //copyAdditionalMetadata(linkPath, directory); + if (!::CreateDirectoryEx( // this function automatically copies symbolic links if encountered + applyLongPathPrefix(linkPath).c_str(), // pointer to path string of template directory + applyLongPathPrefixCreateDir(directory).c_str(), // pointer to a directory path string + NULL)) + { + if (level != 0) return; + const wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } } else //in all other cases @@ -1192,45 +1460,28 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat if (!::CreateDirectoryEx( // this function automatically copies symbolic links if encountered applyLongPathPrefix(templateDir).c_str(), // pointer to path string of template directory applyLongPathPrefixCreateDir(directory).c_str(), // pointer to a directory path string - NULL) && level == 0) + NULL)) { + if (level != 0) return; const wxString errorMessage = isSymlink ? //give a more meaningful errormessage if copying a symbolic link failed, e.g. "C:\Users\ZenJu\Application Data" (wxString(_("Error copying symbolic link:")) + wxT("\n\"") + templateDir.c_str() + wxT("\" ->\n\"") + directory.c_str() + wxT("\"")) : (wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"")); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } + } + //ensure cleanup: + Loki::ScopeGuard guardNewDir = Loki::MakeGuard(&TryCleanUp::tryDeleteDir, directory); - if (copyDirectorySymLinks && isSymlink) //we need to copy the Symbolic Link's change date manually - { - struct TryCleanUp - { - static void tryDeleteLink(const Zstring& linkname) //throw () - { - try - { - removeDirectory(linkname); - } - catch (...) {} - } - }; - //allow only consistent objects to be created -> don't place before ::CreateDirectoryEx, targetLink may already exist - Loki::ScopeGuard guardTargetLink = Loki::MakeGuard(&TryCleanUp::tryDeleteLink, directory); - - if (!copyFileTimes(templateDir, directory, false)) - { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); - } + if (copyDirectorySymLinks && isSymlink) //we need to copy the Symbolic Link's change date manually + copyFileTimes(templateDir, directory, false); //throw (FileError) - guardTargetLink.Dismiss(); - } + if (copyFilePermissions) + copyObjectPermissions(templateDir, directory, !copyDirectorySymLinks); //throw FileError() - //(try to) copy additional metadata like last modification time: no measurable performance drawback - //copyAdditionalMetadata(templateDir, directory); - } + guardNewDir.Dismiss(); //target has been created successfully! } #elif defined FFS_LINUX //symbolic link handling @@ -1238,51 +1489,45 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat !templateDir.empty() && symlinkExists(templateDir)) //there is no directory-type symlink in Linux! => just copy as file - return copySymlinkInternal(templateDir, directory); //throw (FileError) + return copySymlinkInternal(templateDir, directory, copyFilePermissions); //throw (FileError) //default directory creation - if (::mkdir(directory.c_str(), 0755) != 0 && level == 0) + if (::mkdir(directory.c_str(), 0755) != 0) { + if (level != 0) return; wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } -//copy directory permissions: not sure if this is a good idea: if a directory is read-only copying/sync'ing of files will fail... - /* - if (templateDirExists) - { - struct stat fileInfo; - if (stat(templateDir.c_str(), &fileInfo) != 0) //read permissions from template directory - throw FileError(Zstring(_("Error reading file attributes:")) + wxT("\n\"") + templateDir + wxT("\"")); + //ensure cleanup: + Loki::ScopeGuard guardNewDir = Loki::MakeGuard(&TryCleanUp::tryDeleteDir, directory); - // reset the umask as we want to create the directory with exactly the same permissions as the template - wxCHANGE_UMASK(0); + if (!templateDir.empty() && copyFilePermissions) + copyObjectPermissions(templateDir, directory, true); //throw FileError() - if (mkdir(directory.c_str(), fileInfo.st_mode) != 0 && level == 0) - throw FileError(Zstring(_("Error creating directory:")) + wxT("\n\"") + directory + wxT("\"")); - } - else - { - if (mkdir(directory.c_str(), 0777) != 0 && level == 0) - throw FileError(Zstring(_("Error creating directory:")) + wxT("\n\"") + directory + wxT("\"")); - } - */ + guardNewDir.Dismiss(); //target has been created successfully! #endif } -void FreeFileSync::createDirectory(const Zstring& directory, const Zstring& templateDir, bool copyDirectorySymLinks) +void ffs3::createDirectory(const Zstring& directory, const Zstring& templateDir, bool copyDirectorySymLinks, bool copyFilePermissions) { //remove trailing separator - const Zstring dirFormatted = directory.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? - directory.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) : + const Zstring dirFormatted = directory.EndsWith(common::FILE_NAME_SEPARATOR) ? + directory.BeforeLast(common::FILE_NAME_SEPARATOR) : directory; - const Zstring templateFormatted = templateDir.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? - templateDir.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) : + const Zstring templateFormatted = templateDir.EndsWith(common::FILE_NAME_SEPARATOR) ? + templateDir.BeforeLast(common::FILE_NAME_SEPARATOR) : templateDir; - createDirectoryRecursively(dirFormatted, templateFormatted, copyDirectorySymLinks, 0); + createDirectoryRecursively(dirFormatted, templateFormatted, copyDirectorySymLinks, copyFilePermissions, 0); +} + + +void ffs3::createDirectory(const Zstring& directory) +{ + ffs3::createDirectory(directory, Zstring(), false, false); } @@ -1290,11 +1535,15 @@ namespace { Zstring createTempName(const Zstring& filename) { - Zstring output = filename + FreeFileSync::TEMP_FILE_ENDING; + Zstring output = filename + ffs3::TEMP_FILE_ENDING; + +#ifndef _MSC_VER +#warning TEMP_FILE_ENDING -> harmonize with other "endings" remove trailing dot +#endif //ensure uniqueness - for (int i = 1; FreeFileSync::somethingExists(output); ++i) - output = filename + DefaultChar('_') + numberToZstring(i) + FreeFileSync::TEMP_FILE_ENDING; + for (int i = 1; ffs3::somethingExists(output); ++i) + output = filename + DefaultChar('_') + numberToZstring(i) + ffs3::TEMP_FILE_ENDING; return output; } @@ -1318,7 +1567,7 @@ DWORD CALLBACK copyCallbackInternal( HANDLE hDestinationFile, LPVOID lpData) { - using FreeFileSync::CopyFileCallback; + using ffs3::CopyFileCallback; //small performance optimization: it seems this callback function is called for every 64 kB (depending on cluster size). static size_t callNr = 0; @@ -1334,15 +1583,20 @@ DWORD CALLBACK copyCallbackInternal( This will then be handled in future versions of FreeFileSync.\n\nThanks -ZenJu"), NULL, 0); - CopyFileCallback* callback = static_cast<CopyFileCallback*>(lpData); - - switch (callback->updateCopyStatus(wxULongLong(totalBytesTransferred.HighPart, totalBytesTransferred.LowPart))) + try { - case CopyFileCallback::CONTINUE: - break; - case CopyFileCallback::CANCEL: - return PROGRESS_CANCEL; + switch (callback->updateCopyStatus(wxULongLong(totalBytesTransferred.HighPart, totalBytesTransferred.LowPart))) + { + case CopyFileCallback::CONTINUE: + break; + case CopyFileCallback::CANCEL: + return PROGRESS_CANCEL; + } + } + catch (...) + { + ::MessageBox(NULL, wxT("Exception in callback ffs3::copyFile! Please contact the author of FFS."), NULL, 0); } } } @@ -1354,7 +1608,7 @@ DWORD CALLBACK copyCallbackInternal( bool supportForSymbolicLinks() { OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + ::ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); //symbolic links are supported starting with Vista @@ -1377,7 +1631,7 @@ bool supportForNonEncryptedDestination() osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); //encrypted destination is not supported with Windows 2000 - if (GetVersionEx(&osvi)) + if (::GetVersionEx(&osvi)) return osvi.dwMajorVersion > 5 || (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion > 0); //2000 has majorVersion == 5, minorVersion == 0 //overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx @@ -1386,16 +1640,16 @@ bool supportForNonEncryptedDestination() } -void FreeFileSync::copyFile(const Zstring& sourceFile, - const Zstring& targetFile, - bool copyFileSymLinks, - FreeFileSync::ShadowCopy* shadowCopyHandler, - FreeFileSync::CopyFileCallback* callback) +void ffs3::copyFile(const Zstring& sourceFile, + const Zstring& targetFile, + bool copyFileSymLinks, + bool copyFilePermissions, + shadow::ShadowCopy* shadowCopyHandler, + ffs3::CopyFileCallback* callback) { - //FreeFileSync::fileExists(targetFile) -> avoid this call, performance; + //ffs3::fileExists(targetFile) -> avoid this call, performance; //if target exists (very unlikely, because sync-algorithm deletes it) renaming below will fail! - DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS; //copy symbolic links instead of the files pointed at @@ -1442,47 +1696,71 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, lastError == ERROR_LOCK_VIOLATION)) { //shadowFilename already contains prefix: E.g. "\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Program Files\FFS\sample.dat" - const Zstring shadowFilename(shadowCopyHandler->makeShadowCopy(sourceFile)); + + Zstring shadowFilename; + try + { + shadowFilename = shadowCopyHandler->makeShadowCopy(sourceFile); //throw (FileError) + } + catch (const FileError& e) + { + wxString errorMsg = _("Error copying locked file %x!"); + errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(sourceFile) + wxT("\"")); + errorMsg += wxT("\n\n") + e.msg(); + throw FileError(errorMsg); + } + return copyFile(shadowFilename, //transferred bytes is automatically reset when new file is copied targetFile, copyFileSymLinks, + copyFilePermissions, NULL, callback); } //assemble error message... const wxString errorMessage = wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"") + wxT("\n\n"); - throw FileError(errorMessage + FreeFileSync::getLastErrorFormatted(lastError)); + throw FileError(errorMessage + ffs3::getLastErrorFormatted(lastError)); } //rename temporary file: do not add anything else here (note specific error handing) - FreeFileSync::renameFile(temporary, targetFile); + ffs3::renameFile(temporary, targetFile); guardTempFile.Dismiss(); //no need to delete temp file anymore - //copy creation date (last modification date is redundantly written, too, even for symlinks) - copyFileTimes(sourceFile, targetFile, !copyFileSymLinks); //throw() + Loki::ScopeGuard guardTargetFile = Loki::MakeGuard(&TryCleanUp::tryDeleteFile, targetFile); + + if (copyFilePermissions) + copyObjectPermissions(sourceFile, targetFile, !copyFileSymLinks); //throw FileError() + + //copy creation date (last modification date is REDUNDANTLY written, too, even for symlinks) + copyFileTimes(sourceFile, targetFile, !copyFileSymLinks); //throw (FileError) + + guardTargetFile.Dismiss(); } #elif defined FFS_LINUX -void FreeFileSync::copyFile(const Zstring& sourceFile, - const Zstring& targetFile, - bool copyFileSymLinks, - CopyFileCallback* callback) +void ffs3::copyFile(const Zstring& sourceFile, + const Zstring& targetFile, + bool copyFileSymLinks, + bool copyFilePermissions, + CopyFileCallback* callback) { - using FreeFileSync::CopyFileCallback; + using ffs3::CopyFileCallback; //symbolic link handling if ( copyFileSymLinks && symlinkExists(sourceFile)) - return copySymlinkInternal(sourceFile, targetFile); //throw (FileError) + { + return copySymlinkInternal(sourceFile, targetFile, copyFilePermissions); //throw (FileError) + } //begin of regular file copy struct stat fileInfo; if (::stat(sourceFile.c_str(), &fileInfo) != 0) //read file attributes from source file (resolving symlinks) { const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + throw FileError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); } //open sourceFile for reading @@ -1528,26 +1806,19 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, //close output stream before changing attributes fileOut.close(); - //adapt file modification time: - if (!copyFileTimes(sourceFile, temporary, true)) //throw() - { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); - } - //rename temporary file - FreeFileSync::renameFile(temporary, targetFile); + ffs3::renameFile(temporary, targetFile); guardTempFile.Dismiss(); //ensure cleanup: - Loki::ScopeGuard guardTargetFile = Loki::MakeGuard(::unlink, targetFile.c_str()); //don't use Utility::CleanUp here + Loki::ScopeGuard guardTargetFile = Loki::MakeGuard(::unlink, targetFile.c_str()); - //set file access rights - if (::chmod(targetFile.c_str(), fileInfo.st_mode) != 0) - { - const wxString errorMessage = wxString(_("Error writing file attributes:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); - } + //adapt file modification time: + copyFileTimes(sourceFile, targetFile, true); //throw (FileError) + + //set file permissions + if (copyFilePermissions) + copyObjectPermissions(sourceFile, targetFile, true); //throw FileError() guardTargetFile.Dismiss(); //target has been created successfully! } @@ -1564,11 +1835,11 @@ Zstring getDriveName(const Zstring& directoryName) //GetVolume() doesn't work un if (volumeName.empty()) return Zstring(); - return volumeName + wxFileName::GetVolumeSeparator().c_str() + globalFunctions::FILE_NAME_SEPARATOR; + return volumeName + wxFileName::GetVolumeSeparator().c_str() + common::FILE_NAME_SEPARATOR; } -bool FreeFileSync::isFatDrive(const Zstring& directoryName) +bool ffs3::isFatDrive(const Zstring& directoryName) { const Zstring driveName = getDriveName(directoryName); if (driveName.empty()) diff --git a/shared/fileHandling.h b/shared/file_handling.h index 6c57e8e4..36bf976f 100644 --- a/shared/fileHandling.h +++ b/shared/file_handling.h @@ -8,7 +8,7 @@ #define FILE_HANDLING_H_INCLUDED #include "zstring.h" -#include "fileError.h" +#include "file_error.h" #include <wx/longlong.h> #ifdef FFS_WIN @@ -16,7 +16,7 @@ #endif -namespace FreeFileSync +namespace ffs3 { Zstring getFormattedDirectoryName(const Zstring& dirname); @@ -35,9 +35,11 @@ enum ResponseSameVol }; ResponseSameVol onSameVolume(const Zstring& folderLeft, const Zstring& folderRight); //throw() -//optionally: copy file or directory create/last change date, DOES NOTHING if something fails -//does NOT dereference symlinks! -bool copyFileTimes(const Zstring& sourceDir, const Zstring& targetDir, bool deRefSymlinks); //throw(); returns true on success +//copy file or directory create/last change date, +void copyFileTimes(const Zstring& sourceDir, const Zstring& targetDir, bool derefSymlinks); //throw (FileError) + +//copy filesystem permissions: probably requires admin rights +void copyObjectPermissions(const Zstring& source, const Zstring& target, bool derefSymlinks); //throw FileError(); //symlink handling: always evaluate target wxULongLong getFilesize(const Zstring& filename); //throw (FileError) @@ -71,7 +73,8 @@ void moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCall void moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback = NULL); //throw (FileError); //creates superdirectories automatically: -void createDirectory(const Zstring& directory, const Zstring& templateDir = Zstring(), bool copyDirectorySymLinks = false); //throw (FileError); +void createDirectory(const Zstring& directory, const Zstring& templateDir, bool copyDirectorySymLinks, bool copyFilePermissions); //throw (FileError); +void createDirectory(const Zstring& directory); //throw (FileError); -> function overload avoids default parameter ambiguity issues! struct CopyFileCallback //callback functionality { @@ -85,13 +88,14 @@ struct CopyFileCallback //callback functionality virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) = 0; //DON'T throw exceptions here, at least in Windows build! }; -void copyFile(const Zstring& sourceFile, +void copyFile(const Zstring& sourceFile, //throw (FileError); const Zstring& targetFile, bool copyFileSymLinks, + bool copyFilePermissions, #ifdef FFS_WIN - ShadowCopy* shadowCopyHandler = NULL, //supply handler for making shadow copies + shadow::ShadowCopy* shadowCopyHandler, //supply handler for making shadow copies, may be NULL #endif - CopyFileCallback* callback = NULL); //throw (FileError); + CopyFileCallback* callback); //may be NULL //Note: it MAY happen that copyFile() leaves temp files behind, e.g. temporary network drop. // => clean them up at an appropriate time (automatically set sync directions to delete them). They have the following ending: const Zstring TEMP_FILE_ENDING = DefaultStr(".ffs_tmp"); diff --git a/shared/fileID.cpp b/shared/file_id.cpp index 2c608afc..f61108c0 100644 --- a/shared/fileID.cpp +++ b/shared/file_id.cpp @@ -4,12 +4,12 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "fileID.h" +#include "file_id.h" #ifdef FFS_WIN -#include "staticAssert.h" +#include "assert_static.h" #include <wx/msw/wrapwin.h> //includes "windows.h" -#include "longPathPrefix.h" +#include "long_path_prefix.h" #include <boost/shared_ptr.hpp> #elif defined FFS_LINUX @@ -19,15 +19,15 @@ #ifdef FFS_WIN -Utility::FileID Utility::retrieveFileID(const Zstring& filename) +util::FileID util::retrieveFileID(const Zstring& filename) { //ensure our DWORD_FFS really is the same as DWORD - assert_static(sizeof(Utility::FileID::DWORD_FFS) == sizeof(DWORD)); + assert_static(sizeof(util::FileID::DWORD_FFS) == sizeof(DWORD)); //WARNING: CreateFile() is SLOW, while GetFileInformationByHandle() is quite cheap! //http://msdn.microsoft.com/en-us/library/aa363788(VS.85).aspx - const HANDLE hFile = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename).c_str(), + const HANDLE hFile = ::CreateFile(ffs3::applyLongPathPrefix(filename).c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -41,31 +41,31 @@ Utility::FileID Utility::retrieveFileID(const Zstring& filename) BY_HANDLE_FILE_INFORMATION info; if (::GetFileInformationByHandle(hFile, &info)) { - return Utility::FileID(info.dwVolumeSerialNumber, + return util::FileID(info.dwVolumeSerialNumber, info.nFileIndexHigh, info.nFileIndexLow); } } - return Utility::FileID(); //empty ID + return util::FileID(); //empty ID } #elif defined FFS_LINUX -Utility::FileID Utility::retrieveFileID(const Zstring& filename) +util::FileID util::retrieveFileID(const Zstring& filename) { struct stat fileInfo; if (::lstat(filename.c_str(), &fileInfo) == 0) //lstat() does not resolve symlinks - return Utility::FileID(fileInfo.st_dev, fileInfo.st_ino); + return util::FileID(fileInfo.st_dev, fileInfo.st_ino); - return Utility::FileID(); //empty ID + return util::FileID(); //empty ID } #endif -bool Utility::sameFileSpecified(const Zstring& file1, const Zstring& file2) +bool util::sameFileSpecified(const Zstring& file1, const Zstring& file2) { - const Utility::FileID id1 = retrieveFileID(file1); - const Utility::FileID id2 = retrieveFileID(file2); + const util::FileID id1 = retrieveFileID(file1); + const util::FileID id2 = retrieveFileID(file2); if (id1 != FileID() && id2 != FileID()) return id1 == id2; diff --git a/shared/fileID.h b/shared/file_id.h index 7b48412a..d00ca20a 100644 --- a/shared/fileID.h +++ b/shared/file_id.h @@ -17,7 +17,7 @@ //unique file identifier -namespace Utility +namespace util { class FileID { @@ -60,7 +60,7 @@ FileID retrieveFileID(const Zstring& filename); //test whether two distinct paths point to the same file or directory: // true: paths point to same files/dirs -// false: error occured OR point to different files/dirs +// false: error occurred OR point to different files/dirs bool sameFileSpecified(const Zstring& file1, const Zstring& file2); } @@ -85,13 +85,13 @@ bool sameFileSpecified(const Zstring& file1, const Zstring& file2); //---------------Inline Implementation--------------------------------------------------- #ifdef FFS_WIN inline -Utility::FileID::FileID() : +util::FileID::FileID() : dwVolumeSerialNumber(0), nFileIndexHigh(0), nFileIndexLow(0) {} inline -Utility::FileID::FileID(DWORD_FFS dwVolumeSN, +util::FileID::FileID(DWORD_FFS dwVolumeSN, DWORD_FFS fileIndexHi, DWORD_FFS fileIndexLo) : dwVolumeSerialNumber(dwVolumeSN), @@ -99,7 +99,7 @@ Utility::FileID::FileID(DWORD_FFS dwVolumeSN, nFileIndexLow(fileIndexLo) {} inline -bool Utility::FileID::isNull() const +bool util::FileID::isNull() const { return dwVolumeSerialNumber == 0 && nFileIndexHigh == 0 && @@ -107,7 +107,7 @@ bool Utility::FileID::isNull() const } inline -bool Utility::FileID::operator==(const FileID& rhs) const +bool util::FileID::operator==(const FileID& rhs) const { return dwVolumeSerialNumber == rhs.dwVolumeSerialNumber && nFileIndexHigh == rhs.nFileIndexHigh && @@ -115,7 +115,7 @@ bool Utility::FileID::operator==(const FileID& rhs) const } inline -bool Utility::FileID::operator<(const FileID& rhs) const +bool util::FileID::operator<(const FileID& rhs) const { if (dwVolumeSerialNumber != rhs.dwVolumeSerialNumber) return dwVolumeSerialNumber < rhs.dwVolumeSerialNumber; @@ -127,7 +127,7 @@ bool Utility::FileID::operator<(const FileID& rhs) const } inline -Utility::FileID::FileID(wxInputStream& stream) //read +util::FileID::FileID(wxInputStream& stream) //read { stream.Read(&dwVolumeSerialNumber, sizeof(dwVolumeSerialNumber)); stream.Read(&nFileIndexHigh, sizeof(nFileIndexHigh)); @@ -135,7 +135,7 @@ Utility::FileID::FileID(wxInputStream& stream) //read } inline -void Utility::FileID::toStream(wxOutputStream& stream) const //write +void util::FileID::toStream(wxOutputStream& stream) const //write { stream.Write(&dwVolumeSerialNumber, sizeof(dwVolumeSerialNumber)); stream.Write(&nFileIndexHigh, sizeof(nFileIndexHigh)); @@ -144,32 +144,32 @@ void Utility::FileID::toStream(wxOutputStream& stream) const //write #elif defined FFS_LINUX inline -Utility::FileID::FileID() : +util::FileID::FileID() : deviceId(0), inodeId(0) {} inline -Utility::FileID::FileID(dev_t devId, +util::FileID::FileID(dev_t devId, ino_t inId) : deviceId(devId), inodeId(inId) {} inline -bool Utility::FileID::isNull() const +bool util::FileID::isNull() const { return deviceId == 0 && inodeId == 0; } inline -bool Utility::FileID::operator==(const FileID& rhs) const +bool util::FileID::operator==(const FileID& rhs) const { return deviceId == rhs.deviceId && inodeId == rhs.inodeId; } inline -bool Utility::FileID::operator<(const FileID& rhs) const +bool util::FileID::operator<(const FileID& rhs) const { if (deviceId != rhs.deviceId) return deviceId < rhs.deviceId; @@ -178,21 +178,21 @@ bool Utility::FileID::operator<(const FileID& rhs) const } inline -Utility::FileID::FileID(wxInputStream& stream) //read +util::FileID::FileID(wxInputStream& stream) //read { stream.Read(&deviceId, sizeof(deviceId)); stream.Read(&inodeId, sizeof(inodeId)); } inline -void Utility::FileID::toStream(wxOutputStream& stream) const //write +void util::FileID::toStream(wxOutputStream& stream) const //write { stream.Write(&deviceId, sizeof(deviceId)); stream.Write(&inodeId, sizeof(inodeId)); } #endif inline -bool Utility::FileID::operator!=(const FileID& rhs) const +bool util::FileID::operator!=(const FileID& rhs) const { return !(*this == rhs); } diff --git a/shared/fileIO.cpp b/shared/file_io.cpp index 92fb7193..345234fd 100644 --- a/shared/fileIO.cpp +++ b/shared/file_io.cpp @@ -4,16 +4,18 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "fileIO.h" +#include "file_io.h" #include <wx/intl.h> -#include "stringConv.h" -#include "systemFunctions.h" +#include "string_conv.h" +#include "system_func.h" #ifdef FFS_WIN -#include "longPathPrefix.h" +#include "long_path_prefix.h" +#elif defined FFS_LINUX +#include <errno.h> #endif -using namespace FreeFileSync; +using namespace ffs3; FileInput::FileInput(const Zstring& filename) : //throw FileError() @@ -23,7 +25,7 @@ FileInput::FileInput(const Zstring& filename) : //throw FileError() filename_(filename) { #ifdef FFS_WIN - fileHandle = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename).c_str(), + fileHandle = ::CreateFile(ffs3::applyLongPathPrefix(filename).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //all shared modes are required to read files that are open in other applications NULL, @@ -55,13 +57,25 @@ FileInput::FileInput(const Zstring& filename) : //throw FileError() */ NULL); if (fileHandle == INVALID_HANDLE_VALUE) - throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + { + const DWORD lastError = ::GetLastError(); + const wxString& errorMessage = wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + wxT("\n\n") + ffs3::getLastErrorFormatted(lastError); + if (lastError == ERROR_FILE_NOT_FOUND) + throw ErrorNotExisting(errorMessage); + else + throw FileError(errorMessage); + } #elif defined FFS_LINUX fileHandle = ::fopen(filename.c_str(), "rb,type=record,noseek"); //utilize UTF-8 filename - if (!fileHandle) - throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + if (fileHandle == NULL) + { + const int lastError = errno; + const wxString& errorMessage = wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + wxT("\n\n") + ffs3::getLastErrorFormatted(lastError); + if (lastError == ENOENT) + throw ErrorNotExisting(errorMessage); + else + throw FileError(errorMessage); + } #endif } @@ -84,12 +98,12 @@ size_t FileInput::read(void* buffer, size_t bytesToRead) //returns actual number if (!::ReadFile( fileHandle, //__in HANDLE hFile, buffer, //__out LPVOID lpBuffer, - static_cast<DWORD>(bytesToRead), //__in DWORD nNumberOfBytesToRead, + static_cast<DWORD>(bytesToRead), //__in DWORD nNumberOfBytesToRead, &bytesRead, //__out_opt LPDWORD lpNumberOfBytesRead, NULL) //__inout_opt LPOVERLAPPED lpOverlapped || bytesRead > bytesToRead) //must be fulfilled throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + wxT("\n\n") + ffs3::getLastErrorFormatted()); if (bytesRead < bytesToRead) eofReached = true; @@ -99,7 +113,7 @@ size_t FileInput::read(void* buffer, size_t bytesToRead) //returns actual number const size_t bytesRead = ::fread(buffer, 1, bytesToRead, fileHandle); if (::ferror(fileHandle) != 0) throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + wxT("\n\n") + ffs3::getLastErrorFormatted()); return bytesRead; #endif } @@ -119,7 +133,7 @@ FileOutput::FileOutput(const Zstring& filename) : //throw FileError() filename_(filename) { #ifdef FFS_WIN - fileHandle = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename).c_str(), + fileHandle = ::CreateFile(ffs3::applyLongPathPrefix(filename).c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, @@ -128,12 +142,12 @@ FileOutput::FileOutput(const Zstring& filename) : //throw FileError() NULL); if (fileHandle == INVALID_HANDLE_VALUE) throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + wxT("\n\n") + ffs3::getLastErrorFormatted()); #elif defined FFS_LINUX fileHandle = ::fopen(filename.c_str(), "wb,type=record,noseek"); //utilize UTF-8 filename if (!fileHandle) throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + wxT("\n\n") + ffs3::getLastErrorFormatted()); #endif } @@ -157,12 +171,12 @@ void FileOutput::write(const void* buffer, size_t bytesToWrite) //throw FileErro NULL) //__inout_opt LPOVERLAPPED lpOverlapped || bytesWritten != bytesToWrite) //must be fulfilled for synchronous writes! throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + wxT("\n\n") + ffs3::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message! #elif defined FFS_LINUX const size_t bytesWritten = ::fwrite(buffer, 1, bytesToWrite, fileHandle); if (::ferror(fileHandle) != 0 || bytesWritten != bytesToWrite) throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") + - wxT("\n\n") + FreeFileSync::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message! + wxT("\n\n") + ffs3::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message! #endif } diff --git a/shared/fileIO.h b/shared/file_io.h index a04d8a0e..c3fb3f65 100644 --- a/shared/fileIO.h +++ b/shared/file_io.h @@ -16,19 +16,19 @@ #endif #include "zstring.h" -#include "fileError.h" +#include "file_error.h" -namespace FreeFileSync +namespace ffs3 { -//file IO optimized for sequential read/write accesses + better error reporting + long path support +//file IO optimized for sequential read/write accesses + better error reporting + long path support (following symlinks) class FileInput { public: - FileInput(const Zstring& filename); //throw FileError() + FileInput(const Zstring& filename); //throw (FileError, ErrorNotExisting) ~FileInput(); - size_t read(void* buffer, size_t bytesToRead); //returns actual number of bytes read; throw FileError() + size_t read(void* buffer, size_t bytesToRead); //throw FileError(); returns actual number of bytes read bool eof(); //end of file reached private: diff --git a/shared/fileTraverser.cpp b/shared/file_traverser.cpp index 465c2f8f..8e9d5f0d 100644 --- a/shared/fileTraverser.cpp +++ b/shared/file_traverser.cpp @@ -4,18 +4,18 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "fileTraverser.h" -#include "systemConstants.h" -#include "systemFunctions.h" +#include "file_traverser.h" +#include "system_constants.h" +#include "system_func.h" #include <wx/intl.h> -#include "stringConv.h" +#include "string_conv.h" #include <boost/shared_ptr.hpp> #include <boost/scoped_array.hpp> #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" #include "WinIoCtl.h" -#include "longPathPrefix.h" +#include "long_path_prefix.h" #elif defined FFS_LINUX #include <sys/stat.h> @@ -29,8 +29,8 @@ //{ //public: // DisableWow64Redirection() : -// wow64DisableWow64FsRedirection(Utility::loadDllFunction<Wow64DisableWow64FsRedirectionFunc>(L"kernel32.dll", "Wow64DisableWow64FsRedirection")), -// wow64RevertWow64FsRedirection(Utility::loadDllFunction<Wow64RevertWow64FsRedirectionFunc>(L"kernel32.dll", "Wow64RevertWow64FsRedirection")), +// wow64DisableWow64FsRedirection(util::loadDllFunction<Wow64DisableWow64FsRedirectionFunc>(L"kernel32.dll", "Wow64DisableWow64FsRedirection")), +// wow64RevertWow64FsRedirection(util::loadDllFunction<Wow64RevertWow64FsRedirectionFunc>(L"kernel32.dll", "Wow64RevertWow64FsRedirection")), // oldValue(NULL) // { // if ( wow64DisableWow64FsRedirection && @@ -164,7 +164,7 @@ inline void setWin32FileInformation(const FILETIME& lastWriteTime, const DWORD fileSizeHigh, const DWORD fileSizeLow, - FreeFileSync::TraverseCallback::FileInfo& output) + ffs3::TraverseCallback::FileInfo& output) { output.lastWriteTimeRaw = getWin32TimeInformation(lastWriteTime); output.fileSize = wxULongLong(fileSizeHigh, fileSizeLow); @@ -172,10 +172,10 @@ void setWin32FileInformation(const FILETIME& lastWriteTime, inline -bool setWin32FileInformationFromSymlink(const Zstring& linkName, FreeFileSync::TraverseCallback::FileInfo& output) +bool setWin32FileInformationFromSymlink(const Zstring& linkName, ffs3::TraverseCallback::FileInfo& output) { //open handle to target of symbolic link - HANDLE hFile = ::CreateFile(FreeFileSync::applyLongPathPrefix(linkName).c_str(), + HANDLE hFile = ::CreateFile(ffs3::applyLongPathPrefix(linkName).c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -199,9 +199,9 @@ bool setWin32FileInformationFromSymlink(const Zstring& linkName, FreeFileSync::T template <bool followSymlinks> -void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* sink, int level) +void traverseDirectory(const Zstring& directory, ffs3::TraverseCallback* sink, int level) { - using namespace FreeFileSync; + using namespace ffs3; if (level == 100) //catch endless recursion { @@ -211,9 +211,9 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* #ifdef FFS_WIN //ensure directoryFormatted ends with backslash - const Zstring directoryFormatted = directory.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? + const Zstring directoryFormatted = directory.EndsWith(common::FILE_NAME_SEPARATOR) ? directory : - directory + globalFunctions::FILE_NAME_SEPARATOR; + directory + common::FILE_NAME_SEPARATOR; WIN32_FIND_DATA fileMetaData; HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(directoryFormatted + DefaultChar('*')).c_str(), //__in LPCTSTR lpFileName @@ -228,7 +228,7 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* //else: we have a problem... report it: const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") + wxT("\n\n") + - FreeFileSync::getLastErrorFormatted(lastError); + ffs3::getLastErrorFormatted(lastError); sink->onError(errorMessage); return; @@ -298,7 +298,7 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* //else: we have a problem... report it: const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; - sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError)); + sink->onError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted(lastError)); return; #elif defined FFS_LINUX @@ -306,7 +306,7 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* if (dirObj == NULL) { const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; - sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + sink->onError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); return; } @@ -323,7 +323,7 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* //else: we have a problem... report it: const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; - sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + sink->onError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); return; } @@ -334,15 +334,15 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* shortName[1] == wxChar('\0'))) continue; - const Zstring fullName = directory.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //e.g. "/" + const Zstring fullName = directory.EndsWith(common::FILE_NAME_SEPARATOR) ? //e.g. "/" directory + shortName : - directory + globalFunctions::FILE_NAME_SEPARATOR + shortName; + directory + common::FILE_NAME_SEPARATOR + shortName; struct stat fileInfo; if (::lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks { const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(fullName) + wxT("\""); - sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + sink->onError(errorMessage + wxT("\n\n") + ffs3::getLastErrorFormatted()); continue; } @@ -401,7 +401,7 @@ void traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* } -void FreeFileSync::traverseFolder(const Zstring& directory, +void ffs3::traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback* sink) { @@ -409,8 +409,8 @@ void FreeFileSync::traverseFolder(const Zstring& directory, const Zstring& directoryFormatted = directory; #elif defined FFS_LINUX const Zstring directoryFormatted = //remove trailing slash - directory.size() > 1 && directory.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //exception: allow '/' - directory.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR) : + directory.size() > 1 && directory.EndsWith(common::FILE_NAME_SEPARATOR) ? //exception: allow '/' + directory.BeforeLast(common::FILE_NAME_SEPARATOR) : directory; #endif diff --git a/shared/fileTraverser.h b/shared/file_traverser.h index b9cd3ff1..d61ff1cd 100644 --- a/shared/fileTraverser.h +++ b/shared/file_traverser.h @@ -13,7 +13,7 @@ //advanced file traverser returning metadata and hierarchical information on files and directories -namespace FreeFileSync +namespace ffs3 { class TraverseCallback { @@ -61,7 +61,7 @@ public: void traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback* sink); //throw(); //followSymlinks: //"true": Symlinks dereferenced and reported via onFile() and onDir() => onSymlink not used! -//"false": Symlinks directly reported via onSymlink() +//"false": Symlinks directly reported via onSymlink(), directory symlinks are not followed } #endif // FILETRAVERSER_H_INCLUDED diff --git a/shared/globalFunctions.cpp b/shared/global_func.cpp index 63831e1a..d1ab9d2c 100644 --- a/shared/globalFunctions.cpp +++ b/shared/global_func.cpp @@ -4,14 +4,14 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "globalFunctions.h" +#include "global_func.h" #include <wx/msgdlg.h> #include <wx/file.h> #include <wx/stopwatch.h> -#include "systemConstants.h" +#include "system_constants.h" -size_t globalFunctions::getDigitCount(size_t number) //count number of digits +size_t common::getDigitCount(size_t number) //count number of digits { return number == 0 ? 1 : static_cast<size_t>(::log10(static_cast<double>(number))) + 1; } @@ -81,7 +81,7 @@ void DebugLog::write(const wxString& logText) } logFile->Write(wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ")); - logFile->Write(logText + globalFunctions::LINE_BREAK); + logFile->Write(logText + common::LINE_BREAK); } //DebugLog logDebugInfo; @@ -89,5 +89,5 @@ void DebugLog::write(const wxString& logText) wxString getCodeLocation(const wxString file, const int line) { - return wxString(file).AfterLast(globalFunctions::FILE_NAME_SEPARATOR) + wxT(", LINE ") + wxLongLong(line).ToString() + wxT(" | "); + return wxString(file).AfterLast(common::FILE_NAME_SEPARATOR) + wxT(", LINE ") + wxLongLong(line).ToString() + wxT(" | "); } diff --git a/shared/globalFunctions.h b/shared/global_func.h index fe65889f..ba455371 100644 --- a/shared/globalFunctions.h +++ b/shared/global_func.h @@ -19,7 +19,7 @@ class wxStopWatch; -namespace globalFunctions +namespace common { //------------------------------------------------ // FUNCTIONS @@ -34,7 +34,7 @@ template <class T> inline T abs(const T& d) //absolute value { - return(d < 0 ? -d : d); + return d < 0 ? -d : d; } @@ -136,7 +136,7 @@ wxString getCodeLocation(const wxString file, const int line); //---------------Inline Implementation--------------------------------------------------- template <class CharType, class T> inline -std::basic_string<CharType> globalFunctions::numberToString(const T& number) //convert number to string the C++ way +std::basic_string<CharType> common::numberToString(const T& number) //convert number to string the C++ way { std::basic_ostringstream<CharType> ss; ss << number; @@ -146,7 +146,7 @@ std::basic_string<CharType> globalFunctions::numberToString(const T& number) //c template <class T, class CharType> inline -T globalFunctions::stringToNumber(const std::basic_string<CharType>& input) //convert number to string the C++ way +T common::stringToNumber(const std::basic_string<CharType>& input) //convert number to string the C++ way { std::basic_istringstream<CharType> ss(input); T number; @@ -157,7 +157,7 @@ T globalFunctions::stringToNumber(const std::basic_string<CharType>& input) //co template <class T> inline -wxString globalFunctions::numberToString(const T& number) +wxString common::numberToString(const T& number) { return numberToString<wxChar, T>(number).c_str(); } @@ -165,16 +165,16 @@ wxString globalFunctions::numberToString(const T& number) template <class T> inline -T globalFunctions::stringToNumber(const wxString& input) +T common::stringToNumber(const wxString& input) { - const std::basic_string<wxChar> inputConv = input.c_str(); + const std::basic_string<wxChar> inputConv(input.c_str()); return stringToNumber<T, wxChar>(inputConv); } //Note: the following lines are a performance optimization for deleting elements from a vector: linear runtime at most! template <class T> -void globalFunctions::removeRowsFromVector(const std::set<size_t>& rowsToRemove, std::vector<T>& grid) +void common::removeRowsFromVector(const std::set<size_t>& rowsToRemove, std::vector<T>& grid) { if (rowsToRemove.empty()) return; @@ -208,7 +208,7 @@ void globalFunctions::removeRowsFromVector(const std::set<size_t>& rowsToRemove, //enhanced binary search template: returns an iterator template <class ForwardIterator, class T, typename Compare> inline -ForwardIterator globalFunctions::custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) +ForwardIterator common::custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) { first = lower_bound(first, last, value, comp); if (first != last && !comp(value, *first)) @@ -220,7 +220,7 @@ ForwardIterator globalFunctions::custom_binary_search(ForwardIterator first, For template <class T> inline -T globalFunctions::readNumber(std::istream& stream) +T common::readNumber(std::istream& stream) { T result = 0; stream.read(reinterpret_cast<char*>(&result), sizeof(T)); @@ -230,7 +230,7 @@ T globalFunctions::readNumber(std::istream& stream) template <class T> inline -void globalFunctions::writeNumber(std::ostream& stream, T number) +void common::writeNumber(std::ostream& stream, T number) { stream.write(reinterpret_cast<const char*>(&number), sizeof(T)); } diff --git a/shared/guid.cpp b/shared/guid.cpp index 7a2ec68f..d359c29c 100644 --- a/shared/guid.cpp +++ b/shared/guid.cpp @@ -8,17 +8,17 @@ #include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid_generators.hpp> #include <cassert> -#include <algorithm> -#include <vector> +#include <algorithm> +#include <vector> + +using namespace util; + -using namespace Utility; - - struct UniqueId::IntData -{ - boost::uuids::uuid nativeRep; +{ + boost::uuids::uuid nativeRep; }; - + UniqueId::UniqueId() : pData(new IntData) { @@ -35,7 +35,7 @@ bool UniqueId::operator==(const UniqueId rhs) const bool UniqueId::operator<(const UniqueId rhs) const { return pData->nativeRep < rhs.pData->nativeRep; -} +} UniqueId::UniqueId(wxInputStream& stream) : //read diff --git a/shared/guid.h b/shared/guid.h index d639fff5..49d2f008 100644 --- a/shared/guid.h +++ b/shared/guid.h @@ -10,7 +10,7 @@ #include <wx/stream.h> #include <boost/shared_ptr.hpp> -namespace Utility +namespace util { class UniqueId { @@ -27,7 +27,6 @@ private: struct IntData; boost::shared_ptr<IntData> pData; }; - } diff --git a/shared/helpProvider.cpp b/shared/help_provider.cpp index 73c71eb1..0110934c 100644 --- a/shared/helpProvider.cpp +++ b/shared/help_provider.cpp @@ -4,9 +4,9 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "helpProvider.h" +#include "help_provider.h" #include <wx/help.h> -#include "standardPaths.h" +#include "standard_paths.h" #include <wx/image.h> namespace @@ -16,7 +16,7 @@ class HelpProvider public: HelpProvider() { - controller.Initialize(FreeFileSync::getResourceDir() + + controller.Initialize(ffs3::getResourceDir() + #ifdef FFS_WIN wxT("FreeFileSync.chm")); #elif defined FFS_LINUX @@ -39,7 +39,7 @@ private: }; } -void FreeFileSync::displayHelpEntry(const wxString& section) +void ffs3::displayHelpEntry(const wxString& section) { static HelpProvider provider; provider.showHelp(section); diff --git a/shared/helpProvider.h b/shared/help_provider.h index 538e151c..b59f47a8 100644 --- a/shared/helpProvider.h +++ b/shared/help_provider.h @@ -9,7 +9,7 @@ #include <wx/string.h> -namespace FreeFileSync +namespace ffs3 { void displayHelpEntry(const wxString& section = wxEmptyString); } diff --git a/shared/localization.cpp b/shared/localization.cpp index 1ff7f6bd..ef3e02d2 100644 --- a/shared/localization.cpp +++ b/shared/localization.cpp @@ -6,15 +6,15 @@ // #include "localization.h" #include <wx/msgdlg.h> -#include "../shared/standardPaths.h" -#include "../shared/stringConv.h" -#include "systemConstants.h" +#include "../shared/standard_paths.h" +#include "../shared/string_conv.h" +#include "system_constants.h" #include <fstream> #include <map> #include <wx/ffile.h> -using FreeFileSync::CustomLocale; -using FreeFileSync::LocalizationInfo; +using ffs3::CustomLocale; +using ffs3::LocalizationInfo; //_("Browse") <- dummy string for wxDirPickerCtrl to be recognized by automatic text extraction! @@ -27,19 +27,19 @@ wxString DECIMAL_POINT = wxT("."); } -wxString FreeFileSync::getThousandsSeparator() +wxString ffs3::getThousandsSeparator() { return THOUSANDS_SEPARATOR; } -wxString FreeFileSync::getDecimalPoint() +wxString ffs3::getDecimalPoint() { return DECIMAL_POINT; } -const std::vector<FreeFileSync::LocInfoLine>& LocalizationInfo::getMapping() +const std::vector<ffs3::LocInfoLine>& LocalizationInfo::getMapping() { static LocalizationInfo instance; return instance.locMapping; @@ -50,7 +50,7 @@ namespace { struct CompareByName { - bool operator()(const FreeFileSync::LocInfoLine& lhs, const FreeFileSync::LocInfoLine& rhs) const + bool operator()(const ffs3::LocInfoLine& lhs, const ffs3::LocInfoLine& rhs) const { return lhs.languageName < rhs.languageName; } @@ -60,7 +60,7 @@ struct CompareByName LocalizationInfo::LocalizationInfo() { - FreeFileSync::LocInfoLine newEntry; + ffs3::LocInfoLine newEntry; newEntry.languageID = wxLANGUAGE_CZECH; newEntry.languageName = wxT("Čeština"); @@ -501,8 +501,8 @@ void CustomLocale::setLanguage(const int language) translationDB->clear(); if (!languageFile.empty()) { - UnicodeFileReader langFile(FreeFileSync::getResourceDir() + wxT("Languages") + - zToWx(globalFunctions::FILE_NAME_SEPARATOR) + languageFile); + UnicodeFileReader langFile(ffs3::getResourceDir() + wxT("Languages") + + zToWx(common::FILE_NAME_SEPARATOR) + languageFile); if (langFile.isOkay()) { int rowNumber = 0; diff --git a/shared/localization.h b/shared/localization.h index 1e4cb6ed..1c1773e9 100644 --- a/shared/localization.h +++ b/shared/localization.h @@ -14,7 +14,7 @@ class Translation; -namespace FreeFileSync +namespace ffs3 { //language independent global variables: just use operating system's default setting! wxString getThousandsSeparator(); diff --git a/shared/lock.cpp b/shared/lock.cpp index e8e027c2..6b3dbcbb 100644 --- a/shared/lock.cpp +++ b/shared/lock.cpp @@ -5,18 +5,18 @@ // ************************************************************************** // #include "lock.h" -#include "fileHandling.h" +#include "file_handling.h" // // -//Utility::LockDirectory::LockDirectory(const Zstring& dirname) +//util::LockDirectory::LockDirectory(const Zstring& dirname) //{ // //} // // -//Utility::LockDirectory::~LockDirectory() +//util::LockDirectory::~LockDirectory() //{ //} // // -//bool Utility::LockDirectoryisLocked(const Zstring& dirname); +//bool util::LockDirectoryisLocked(const Zstring& dirname); diff --git a/shared/longPathPrefix.cpp b/shared/long_path_prefix.cpp index e8b14b90..bc784f70 100644 --- a/shared/longPathPrefix.cpp +++ b/shared/long_path_prefix.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "longPathPrefix.h" +#include "long_path_prefix.h" #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -30,20 +30,20 @@ Zstring applyLongPathPrefixImpl(const Zstring& path) } -Zstring FreeFileSync::applyLongPathPrefix(const Zstring& path) +Zstring ffs3::applyLongPathPrefix(const Zstring& path) { return applyLongPathPrefixImpl<MAX_PATH>(path); } -Zstring FreeFileSync::applyLongPathPrefixCreateDir(const Zstring& path) //throw() +Zstring ffs3::applyLongPathPrefixCreateDir(const Zstring& path) //throw() { //special rule for ::CreateDirectoryEx(): MAX_PATH - 12(=^ 8.3 filename) is threshold return applyLongPathPrefixImpl<MAX_PATH - 12>(path); } -Zstring FreeFileSync::removeLongPathPrefix(const Zstring& path) //throw() +Zstring ffs3::removeLongPathPrefix(const Zstring& path) //throw() { if (path.StartsWith(LONG_PATH_PREFIX)) { diff --git a/shared/longPathPrefix.h b/shared/long_path_prefix.h index 4ebe7a9d..b14a17dc 100644 --- a/shared/longPathPrefix.h +++ b/shared/long_path_prefix.h @@ -13,7 +13,7 @@ use in windows build only! #include "zstring.h" -namespace FreeFileSync +namespace ffs3 { //handle filenames longer-equal 260 (== MAX_PATH) characters by applying \\?\-prefix (Reference: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath) /* diff --git a/shared/parallelCall.cpp b/shared/parallelCall.cpp deleted file mode 100644 index ce0a3633..00000000 --- a/shared/parallelCall.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** -// -#include "parallelCall.h" -#include <wx/thread.h> -#include <stdexcept> -#include <wx/string.h> -#include <wx/msgdlg.h> - -namespace -{ -class WorkerThread : public wxThread -{ -public: - WorkerThread(const Async::AsyncProcess& proc, - const boost::shared_ptr<wxMutex>& mainIsListening, - const boost::shared_ptr<wxCondition>& procHasFinished) : - wxThread(wxTHREAD_DETACHED), - proc_(proc), //copy input data by value - mainIsListening_(mainIsListening), // - procHasFinished_(procHasFinished) // - { - if (Create() != wxTHREAD_NO_ERROR) - throw std::runtime_error("Error creating async worker thread!"); - - if (Run() != wxTHREAD_NO_ERROR) - throw std::runtime_error("Error starting async worker thread!"); - } - - ExitCode Entry() - { - try - { - proc_->doWork(); - - //notify that work is done - wxMutexLocker dummy(*mainIsListening_); - procHasFinished_->Signal(); - } - catch (const std::exception& e) //exceptions must be catched per thread - { - wxMessageBox(wxString::FromAscii(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); - } - catch (...) //exceptions must be catched per thread - { - wxMessageBox(wxT("Unknown exception in worker thread"), _("An exception occured!"), wxOK | wxICON_ERROR); - } - - return 0; - } - -private: - Async::AsyncProcess proc_; - boost::shared_ptr<wxMutex> mainIsListening_; //shared pointer is safe to use in MT context (same guarantee like builtin types!) - boost::shared_ptr<wxCondition> procHasFinished_; //http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety -}; -} - - -Async::Result Async::execute(AsyncProcess proc, size_t maxWait) //maxWait = max. wait time in milliseconds -{ - boost::shared_ptr<wxMutex> mainIsListening(new wxMutex); - boost::shared_ptr<wxCondition> procHasFinished(new wxCondition(*mainIsListening)); - wxMutexLocker dummy(*mainIsListening); //the mutex should be initially locked (= "main not listening") - - new WorkerThread(proc, mainIsListening, procHasFinished); - - return procHasFinished->WaitTimeout(static_cast<unsigned long>(maxWait)) == wxCOND_NO_ERROR ? WORK_DONE : TIMEOUT; -} - - -// ------------------------------------------------------ -// |Pattern: workload queue and multiple worker threads | -// ------------------------------------------------------ -//typedef std::vector<DirectoryDescrType*> Workload; -// -//class ThreadSorting : public wxThread -//{ -//public: -// ThreadSorting(wxCriticalSection& syncWorkload, Workload& workload) : -// wxThread(wxTHREAD_JOINABLE), -// syncWorkload_(syncWorkload), -// workload_(workload) -// { -// if (Create() != wxTHREAD_NO_ERROR) -// throw RuntimeException(wxString(wxT("Error creating thread for sorting!"))); -// } -// -// ~ThreadSorting() {} -// -// -// ExitCode Entry() -// { -// while (true) -// { -// DirectoryDescrType* descr = NULL; -// { //see if there is work to do... -// wxCriticalSectionLocker dummy(syncWorkload_); -// if (workload_.empty()) -// return 0; -// else -// { -// descr = workload_.back(); -// workload_.pop_back(); -// } -// } -// //do work -// std::sort(descr->begin(), descr->end()); -// } -// } -// -//private: -// wxCriticalSection& syncWorkload_; -// Workload& workload_; -//}; -// -// -//void DirectoryDescrBuffer::preFillBuffers(const std::vector<FolderPairCfg>& fpConfigFormatted) -//{ -// //assemble workload -// ... -// -// //we use binary search when comparing the directory structures: so sort() first -// const int CPUCount = wxThread::GetCPUCount(); -// if (CPUCount >= 2) //do it the multithreaded way: -// { -// wxCriticalSection syncWorkload; -// -// typedef std::vector<boost::shared_ptr<ThreadSorting> > ThreadContainer; -// ThreadContainer sortThreads; -// sortThreads.reserve(CPUCount); -// -// //start CPUCount worker threads -// for (size_t i = 0; i < std::min(static_cast<size_t>(CPUCount), workload.size()); ++i) -// { -// boost::shared_ptr<ThreadSorting> newWorker(new ThreadSorting(syncWorkload, workload)); -// -// if (newWorker->Run() != wxTHREAD_NO_ERROR) -// throw RuntimeException(wxString(wxT("Error starting thread for sorting!"))); -// -// sortThreads.push_back(newWorker); -// } -// -// //wait until all worker are finished -// for (ThreadContainer::iterator i = sortThreads.begin(); i != sortThreads.end(); ++i) -// { -// if ((*i)->Wait() != 0) -// throw RuntimeException(wxString(wxT("Error waiting for thread (sorting)!"))); -// } -// } -// else //single threaded -// { -// for (Workload::iterator i = workload.begin(); i != workload.end(); ++i) -// std::sort((*i)->begin(), (*i)->end()); -// } -//} diff --git a/shared/parallelCall.h b/shared/parallelCall.h deleted file mode 100644 index b6e6b6ca..00000000 --- a/shared/parallelCall.h +++ /dev/null @@ -1,34 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** -// -#ifndef MULTITHREADING_H_INCLUDED -#define MULTITHREADING_H_INCLUDED - -#include <boost/shared_ptr.hpp> - - -namespace Async -{ -class Procedure -{ -public: - virtual ~Procedure() {} - virtual void doWork() = 0; -}; - -enum Result -{ - TIMEOUT, - WORK_DONE -}; - -typedef boost::shared_ptr<Procedure> AsyncProcess; - -//wait for Procedure to finish in separate thread; shared data (Procedure*) may be accessed after WORK_DONE only! => Beware shared data if TIMEOUT (e.g. ref-counting!) -Result execute(AsyncProcess proc, size_t maxWait); //maxWait = max. wait time in milliseconds -} - -#endif // MULTITHREADING_H_INCLUDED diff --git a/shared/perf.h b/shared/perf.h new file mode 100644 index 00000000..62473259 --- /dev/null +++ b/shared/perf.h @@ -0,0 +1,42 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#include <windows.h> +#include <sstream> + +class Performance +{ +public: + Performance() : resultWasShown(false), startTime(::GetTickCount()) {} + + ~Performance() + { + if (!resultWasShown) + showResult(); + } + + void showResult() + { + resultWasShown = true; + + const DWORD currentTime = ::GetTickCount(); + const DWORD delta = currentTime - startTime; + startTime = currentTime; + + std::ostringstream ss; + ss << delta << " ms"; + + ::MessageBoxA(NULL, ss.str().c_str(), "Timer", 0); + } + +private: + bool resultWasShown; + DWORD startTime; +}; + +//two macros for quick performance measurements +#define PERF_START Performance a; +#define PERF_STOP a.showResult(); diff --git a/shared/recycler.cpp b/shared/recycler.cpp index b9f666f8..1a73e105 100644 --- a/shared/recycler.cpp +++ b/shared/recycler.cpp @@ -5,21 +5,21 @@ // ************************************************************************** // #include "recycler.h" -#include "stringConv.h" +#include "string_conv.h" #include <wx/intl.h> #include <stdexcept> #include <iterator> #ifdef FFS_WIN -#include "dllLoader.h" +#include "dll_loader.h" #include <wx/msw/wrapwin.h> //includes "windows.h" -#include "buildInfo.h" -#include "staticAssert.h" +#include "build_info.h" +#include "assert_static.h" #include <algorithm> #include <functional> #include <vector> -#include "longPathPrefix.h" -#include "IFileOperation/fileOp.h" +#include "long_path_prefix.h" +#include "IFileOperation/file_op.h" #elif defined FFS_LINUX #include <sys/stat.h> @@ -33,11 +33,11 @@ namespace const std::wstring& getRecyclerDllName() { static const std::wstring filename( - Utility::is64BitBuild ? + util::is64BitBuild ? L"FileOperation_x64.dll": L"FileOperation_Win32.dll"); - assert_static(Utility::is32BitBuild || Utility::is64BitBuild); + assert_static(util::is32BitBuild || util::is64BitBuild); return filename; } @@ -73,7 +73,7 @@ Nevertheless, let's use IFileOperation for better error reporting! void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw (FileError) { - using FreeFileSync::FileError; + using ffs3::FileError; if (filesToDelete.empty()) return; @@ -82,25 +82,26 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw ( if (useIFileOperation) //new recycle bin usage: available since Vista { + std::vector<const wchar_t*> fileNames; + std::transform(filesToDelete.begin(), filesToDelete.end(), + std::back_inserter(fileNames), std::mem_fun_ref(&Zstring::c_str)); + using namespace FileOp; static const MoveToRecycleBinFct moveToRecycler = - Utility::loadDllFunction<MoveToRecycleBinFct>(getRecyclerDllName().c_str(), moveToRecycleBinFctName); + util::loadDllFunction<MoveToRecycleBinFct>(getRecyclerDllName().c_str(), moveToRecycleBinFctName); static const GetLastErrorFct getLastError = - Utility::loadDllFunction<GetLastErrorFct>(getRecyclerDllName().c_str(), getLastErrorFctName); + util::loadDllFunction<GetLastErrorFct>(getRecyclerDllName().c_str(), getLastErrorFctName); if (moveToRecycler == NULL || getLastError == NULL) - throw FileError(wxString(_("Could not load a required DLL:")) + wxT(" \"") + getRecyclerDllName().c_str() + wxT("\"")); + throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + fileNames[0] + wxT("\"\n\n") + //report first file only... better than nothing + wxString(_("Could not load a required DLL:")) + wxT(" \"") + getRecyclerDllName().c_str() + wxT("\"")); //#warning moving long file paths to recycler does not work! clarify! // std::vector<Zstring> temp; // std::transform(filesToDelete.begin(), filesToDelete.end(), -// std::back_inserter(temp), std::ptr_fun(FreeFileSync::removeLongPathPrefix)); //::IFileOperation() can't handle \\?\-prefix! - - std::vector<const wchar_t*> fileNames; - std::transform(filesToDelete.begin(), filesToDelete.end(), - std::back_inserter(fileNames), std::mem_fun_ref(&Zstring::c_str)); +// std::back_inserter(temp), std::ptr_fun(ffs3::removeLongPathPrefix)); //::IFileOperation() can't handle \\?\-prefix! if (!(*moveToRecycler)(&fileNames[0], //array must not be empty fileNames.size())) @@ -143,7 +144,7 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw ( } -void FreeFileSync::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileError) +void ffs3::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileError) { #ifdef FFS_WIN const Zstring filenameFmt = applyLongPathPrefix(fileToDelete); @@ -165,7 +166,8 @@ void FreeFileSync::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileE try { if (!fileObj->trash()) - throw std::runtime_error("Recycle Bin failed but did not provide error information!"); + throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(fileToDelete) + wxT("\"\n\n") + + wxT("(") + wxT("unknown error") + wxT(")")); } catch (const Glib::Error& errorObj) { @@ -180,7 +182,7 @@ void FreeFileSync::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileE } -bool FreeFileSync::recycleBinExists() +bool ffs3::recycleBinExists() { #ifdef FFS_WIN return true; diff --git a/shared/recycler.h b/shared/recycler.h index 828e26af..7537e875 100644 --- a/shared/recycler.h +++ b/shared/recycler.h @@ -7,10 +7,10 @@ #ifndef RECYCLER_H_INCLUDED #define RECYCLER_H_INCLUDED -#include "fileError.h" +#include "file_error.h" #include "zstring.h" -namespace FreeFileSync +namespace ffs3 { /* -------------------- diff --git a/shared/serialize.cpp b/shared/serialize.cpp index 63e2037f..cf6d96b1 100644 --- a/shared/serialize.cpp +++ b/shared/serialize.cpp @@ -7,12 +7,12 @@ #include "serialize.h" #include <wx/intl.h> -using namespace Utility; +using namespace util; void ReadInputStream::throwReadError() const //throw FileError() { - throw FreeFileSync::FileError(wxString(_("Error reading from synchronization database:")) + wxT(" \n") + + throw ffs3::FileError(wxString(_("Error reading from synchronization database:")) + wxT(" \n") + wxT("\"") + errorObjName_ + wxT("\"")); } @@ -35,7 +35,7 @@ ReadInputStream::CharArray ReadInputStream::readArrayC() const //-------------------------------------------------------------------------------------------------------- void WriteOutputStream::throwWriteError() const //throw FileError() { - throw FreeFileSync::FileError(wxString(_("Error writing to synchronization database:")) + wxT(" \n") + + throw ffs3::FileError(wxString(_("Error writing to synchronization database:")) + wxT(" \n") + wxT("\"") + errorObjName_ + wxT("\"")); } diff --git a/shared/serialize.h b/shared/serialize.h index 88e6054c..99dd83d5 100644 --- a/shared/serialize.h +++ b/shared/serialize.h @@ -9,11 +9,11 @@ #include "zstring.h" #include <wx/stream.h> -#include "fileError.h" +#include "file_error.h" #include <boost/scoped_array.hpp> #include <boost/shared_ptr.hpp> -namespace Utility +namespace util { template <class T> T readNumber(wxInputStream& stream); diff --git a/shared/shadow.cpp b/shared/shadow.cpp index 3909c37b..b38103de 100644 --- a/shared/shadow.cpp +++ b/shared/shadow.cpp @@ -7,16 +7,21 @@ #include "shadow.h" #include <wx/msw/wrapwin.h> //includes "windows.h" #include <wx/intl.h> -#include "systemConstants.h" -#include "dllLoader.h" +#include "system_constants.h" +#include "dll_loader.h" #include <stdexcept> -#include "staticAssert.h" -#include "buildInfo.h" +#include "assert_static.h" +#include "build_info.h" #include "ShadowCopy\shadow.h" +#include "string_conv.h" -using FreeFileSync::ShadowCopy; +using shadow::ShadowCopy; +using shadow::WaitingForShadow; +using ffs3::FileError; +namespace +{ bool newerThanXP() { OSVERSIONINFO osvi; @@ -41,7 +46,7 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m PBOOL Wow64Process); static const IsWow64ProcessFunc isWow64Process = - Utility::loadDllFunction<IsWow64ProcessFunc>(L"kernel32.dll", "IsWow64Process"); + util::loadDllFunction<IsWow64ProcessFunc>(L"kernel32.dll", "IsWow64Process"); if (isWow64Process) { @@ -54,148 +59,145 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m } -const wxString& getShadowDllName() +const std::wstring& getShadowDllName() { /* distinguish a bunch of VSS builds: we use XP and Server 2003 implementations... VSS version and compatibility overview: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx */ - static const wxString filename( + assert_static(util::is32BitBuild || util::is64BitBuild); + + static const std::wstring filename( newerThanXP() ? - (Utility::is64BitBuild ? - wxT("Shadow_Server2003_x64.dll") : - wxT("Shadow_Server2003_Win32.dll")) : + (util::is64BitBuild ? + L"Shadow_Server2003_x64.dll" : + L"Shadow_Server2003_Win32.dll") : - (Utility::is64BitBuild ? - wxT("Shadow_XP_x64.dll") : - wxT("Shadow_XP_Win32.dll"))); + (util::is64BitBuild ? + L"Shadow_XP_x64.dll" : + L"Shadow_XP_Win32.dll")); - assert_static(Utility::is32BitBuild || Utility::is64BitBuild); return filename; } - +} //############################################################################################################# -ShadowCopy::ShadowCopy() : - backupHandle(NULL) {} +ShadowCopy::ShadowCopy(WaitingForShadow* callback) : callback_(callback) {} +ShadowCopy::~ShadowCopy() {} //std::auto_ptr: keep non-inline +//############################################################################################################# -ShadowCopy::~ShadowCopy() +class ShadowCopy::ShadowVolume { - if (backupHandle != NULL) +public: + ShadowVolume(const Zstring& volumeNameFormatted) : //throw(FileError) + realVol(volumeNameFormatted), + backupHandle(NULL) { - using namespace Shadow; + using namespace shadow; - static const ReleaseShadowCopyFct releaseShadowCopy = - Utility::loadDllFunction<ReleaseShadowCopyFct>(getShadowDllName().c_str(), releaseShadowCopyFctName); + if (!createShadowCopy) + createShadowCopy = util::loadDllFunction<CreateShadowCopyFct>(getShadowDllName(), createShadowCopyFctName); - if (releaseShadowCopy == NULL) - throw std::logic_error("Could not load \"releaseShadowCopy\"!"); //shouldn't arrive here! + if (!releaseShadowCopy) + releaseShadowCopy = util::loadDllFunction<ReleaseShadowCopyFct>(getShadowDllName(), releaseShadowCopyFctName); - releaseShadowCopy(backupHandle); - } -} + //check if shadow copy dll was loaded correctly + if ( createShadowCopy == NULL || + releaseShadowCopy == NULL) + throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + _("Could not load a required DLL:") + wxT(" \"") + getShadowDllName().c_str() + wxT("\"")); + //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003 + //(Reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx) + static const bool wow64Active = runningWOW64(); + if (wow64Active) + throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.")); -Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) -{ - using namespace Shadow; +//--------------------------------------------------------------------------------------------------------- + //start shadow volume copy service: + wchar_t shadowVolName[1000]; + wchar_t errorMessage[1000]; + + if (!createShadowCopy( + volumeNameFormatted.c_str(), + shadowVolName, + 1000, + &backupHandle, + errorMessage, + 1000)) + throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + wxT("(") + errorMessage + wxT(" Volume: \"") + volumeNameFormatted.c_str() + wxT("\")")); - static const CreateShadowCopyFct createShadowCopy = - Utility::loadDllFunction<CreateShadowCopyFct>(getShadowDllName().c_str(), createShadowCopyFctName); + shadowVol = Zstring(shadowVolName) + common::FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash + } - static const ReleaseShadowCopyFct releaseShadowCopy = - Utility::loadDllFunction<ReleaseShadowCopyFct>(getShadowDllName().c_str(), releaseShadowCopyFctName); + ~ShadowVolume() + { + releaseShadowCopy(backupHandle); + } - //check if shadow copy dll was loaded correctly - if ( createShadowCopy == NULL || - releaseShadowCopy == NULL) + Zstring getShadowVolume() const //trailing path separator { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") + - _("Could not load a required DLL:") + wxT(" \"") + getShadowDllName() + wxT("\"")); + return shadowVol; } - //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003 - //(Reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx) - static const bool wow64Active = runningWOW64(); - if (wow64Active) + Zstring getRealVolume() const //trailing path separator { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") + - _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.")); + return realVol; } +private: + ShadowVolume(const ShadowVolume&); + ShadowVolume& operator=(const ShadowVolume&); + + static shadow::CreateShadowCopyFct createShadowCopy; + static shadow::ReleaseShadowCopyFct releaseShadowCopy; + + Zstring shadowVol; + const Zstring realVol; + + void* backupHandle; +}; + + +shadow::CreateShadowCopyFct ShadowCopy::ShadowVolume::createShadowCopy; +shadow::ReleaseShadowCopyFct ShadowCopy::ShadowVolume::releaseShadowCopy; +//############################################################################################################# + + +Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) +{ + using namespace ffs3; -//--------------------------------------------------------------------------------------------------------- wchar_t volumeNameRaw[1000]; if (!::GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName, volumeNameRaw, //__out LPTSTR lpszVolumePathName, 1000)) //__in DWORD cchBufferLength - { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Could not determine volume name for file:") + wxT("\n\"") + inputFile.c_str() + wxT("\"")); - } + throw FileError(wxString(_("Could not determine volume name for file:")) + wxT("\n\"") + zToWx(inputFile) + wxT("\"")); Zstring volumeNameFormatted = volumeNameRaw; - if (!volumeNameFormatted.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) - volumeNameFormatted += globalFunctions::FILE_NAME_SEPARATOR; - - if (volumeNameFormatted != realVolumeLast) - { - //release old shadow copy - if (backupHandle != NULL) - { - releaseShadowCopy(backupHandle); - backupHandle = NULL; - } - realVolumeLast.clear(); //...if next call fails... - shadowVolumeLast.clear(); //...if next call fails... - - //start shadow volume copy service: - wchar_t shadowVolName[1000]; - void* backupHandleTmp = NULL; - wchar_t errorMessage[1000]; - - if (!createShadowCopy( - volumeNameFormatted.c_str(), - shadowVolName, - 1000, - &backupHandleTmp, - errorMessage, - 1000)) - { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") + - wxT("(") + errorMessage + wxT(" Volume: \"") + volumeNameFormatted.c_str() + wxT("\")")); - } - - realVolumeLast = volumeNameFormatted; - shadowVolumeLast = Zstring(shadowVolName) + globalFunctions::FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash - backupHandle = backupHandleTmp; - } + if (!volumeNameFormatted.EndsWith(common::FILE_NAME_SEPARATOR)) + volumeNameFormatted += common::FILE_NAME_SEPARATOR; //input file is always absolute! directory formatting takes care of this! Therefore volume name can always be found. const size_t pos = inputFile.find(volumeNameFormatted); //inputFile needs NOT to begin with volumeNameFormatted: consider for example \\?\ prefix! if (pos == Zstring::npos) { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")); - wxString msg = _("Volume name %x not part of filename %y!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + volumeNameFormatted.c_str() + wxT("\""), false); - msg.Replace(wxT("%y"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\""), false); - throw FileError(errorMsg + wxT("\n\n") + msg); + msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(volumeNameFormatted) + wxT("\""), false); + msg.Replace(wxT("%y"), wxString(wxT("\"")) + zToWx(inputFile) + wxT("\""), false); + throw FileError(msg); } + + if (!shadowVol.get() || shadowVol->getRealVolume() != volumeNameFormatted) + shadowVol.reset(new ShadowVolume(volumeNameFormatted)); //throw (FileError) + //return filename alias on shadow copy volume - return shadowVolumeLast + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length()); + return shadowVol->getShadowVolume() + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length()); } - diff --git a/shared/shadow.h b/shared/shadow.h index ca373e40..60d30bbd 100644 --- a/shared/shadow.h +++ b/shared/shadow.h @@ -12,15 +12,24 @@ use in windows build only! #endif #include "zstring.h" -#include "fileError.h" +#include "file_error.h" +#include <memory> -namespace FreeFileSync +namespace shadow { +struct WaitingForShadow +{ + virtual ~WaitingForShadow() {} + virtual void requestUiRefresh() = 0; //allowed to throw exceptions + virtual void updateStatusText(const Zstring& text) = 0; +}; + + class ShadowCopy //buffer access to Windows Volume Shadow Copy Service { public: - ShadowCopy(); + ShadowCopy(WaitingForShadow* callback); ~ShadowCopy(); Zstring makeShadowCopy(const Zstring& inputFile); //throw(FileError); returns filename on shadow copy @@ -29,9 +38,10 @@ private: ShadowCopy(const ShadowCopy&); ShadowCopy& operator=(const ShadowCopy&); - Zstring realVolumeLast; //buffer last volume name - Zstring shadowVolumeLast; //buffer last created shadow volume - void* backupHandle; + WaitingForShadow* callback_; + + class ShadowVolume; + std::auto_ptr<ShadowVolume> shadowVol; }; } diff --git a/shared/signal_processing.h b/shared/signal_processing.h new file mode 100644 index 00000000..857d0b12 --- /dev/null +++ b/shared/signal_processing.h @@ -0,0 +1,166 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#include <algorithm> +#include <limits> +#include <numeric> + + +namespace util +{ +template <class T> +T abs(T value); + +int round(double d); //little rounding function + +template <class T> +bool isNull(T number); + +//---------------------------------------------------------------------------------- +// smoothen data ranges through a window around each data point | +//---------------------------------------------------------------------------------- +template <class InputIterator, class OutputIterator> +void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize); //default implementation: averaging + +template <class InputIterator, class OutputIterator, class DataProcessor> +void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize, DataProcessor proc); +/* +DataProcessor is an abstraction for data evaluation. A valid implementation needs to support three properties: +- add data entry at window front: operator+=(ValueType value) +- remove data entry at window back: operator-=(ValueType value) +- evaluate smoothed middle value: ValueType operator()(size_t windowSize) +*/ +//---------------------------------------------------------------------------------- + + + + + + + + + + + + + + + + + + + + + + +//################# inline implementation ######################### +template <class T> +inline +T abs(T value) +{ + return value < 0 ? -value : value; +} + + +template <class T> +inline +bool isNull(T value) +{ + return abs(number) <= std::numeric_limits<T>::epsilon(); //epsilon == 0 for integer types, therefore less-equal(!) +} + + +inline +int round(double d) +{ + return static_cast<int>(d < 0 ? d - .5 : d + .5); +} + + +template <class InputIterator, class OutputIterator, class DataProcessor> +inline +void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize, DataProcessor proc) +{ + windowSize = std::min(windowSize, static_cast<size_t>(last - first)); //std::distance() not used to enforce random access iterator requirement + + if (windowSize <= 1) + { + std::copy(first, last, result); + return; + } + + const size_t firstHalf = windowSize / 2; + const size_t secondHalf = windowSize - firstHalf; + + //preparation + for (InputIterator i = first; i != first + secondHalf; ++i) + proc += *i; + + //beginning + for (InputIterator i = first; i != first + firstHalf; ++i) + { + *result++ = proc(i - first + secondHalf); + proc += *(i + secondHalf); + } + + //main + for (InputIterator i = first + firstHalf; i != last - secondHalf; ++i) + { + *result++ = proc(windowSize); + proc += *(i + secondHalf); + proc -= *(i - firstHalf); + } + + //ending + for (InputIterator i = last - secondHalf; i != last; ++i) + { + *result++ = proc(windowSize - (i - last + secondHalf)); + proc -= *(i - firstHalf); + } +} + + +template <class ValueType> +class ProcessorAverage +{ +public: + ProcessorAverage() : valueAcc() {} + + //add front data entry + ProcessorAverage& operator+=(ValueType value) + { + valueAcc += value; + return *this; + } + + //remove rear data entry + ProcessorAverage& operator-=(ValueType value) + { + valueAcc -= value; + return *this; + } + + //evaluate smoothed value + ValueType operator()(size_t windowSize) const + { + return valueAcc / windowSize; + } + +private: + ValueType valueAcc; //accumulated values +}; + + + +template <class InputIterator, class OutputIterator> +inline +void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize) +{ + typedef typename std::iterator_traits<InputIterator>::value_type ValueType; + smoothen(first, last, result, windowSize, ProcessorAverage<ValueType>()); +} + +}
\ No newline at end of file diff --git a/shared/standardPaths.cpp b/shared/standard_paths.cpp index e442c865..2bebe056 100644 --- a/shared/standardPaths.cpp +++ b/shared/standard_paths.cpp @@ -4,33 +4,33 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "standardPaths.h" +#include "standard_paths.h" #include <wx/stdpaths.h> #include <wx/filename.h> -#include "systemConstants.h" -#include "stringConv.h" +#include "system_constants.h" +#include "string_conv.h" -using namespace FreeFileSync; +using namespace ffs3; -bool FreeFileSync::isPortableVersion() +bool ffs3::isPortableVersion() { #ifdef FFS_WIN - static const bool isPortable = !wxFileExists(FreeFileSync::getBinaryDir() + wxT("uninstall.exe")); //this check is a bit lame... + static const bool isPortable = !wxFileExists(ffs3::getBinaryDir() + wxT("uninstall.exe")); //this check is a bit lame... #elif defined FFS_LINUX - static const bool isPortable = !FreeFileSync::getBinaryDir().EndsWith(wxT("/bin/")); //this check is a bit lame... + static const bool isPortable = !ffs3::getBinaryDir().EndsWith(wxT("/bin/")); //this check is a bit lame... #endif return isPortable; } -const wxString& FreeFileSync::getBinaryDir() +const wxString& ffs3::getBinaryDir() { - static wxString instance = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath() + zToWx(globalFunctions::FILE_NAME_SEPARATOR); + static wxString instance = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath() + zToWx(common::FILE_NAME_SEPARATOR); return instance; } -const wxString& FreeFileSync::getResourceDir() +const wxString& ffs3::getResourceDir() { #ifdef FFS_WIN return getBinaryDir(); @@ -48,8 +48,8 @@ const wxString& FreeFileSync::getResourceDir() { resourceDir = wxStandardPathsBase::Get().GetResourcesDir(); - if (!resourceDir.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR))) - resourceDir += zToWx(globalFunctions::FILE_NAME_SEPARATOR); + if (!resourceDir.EndsWith(zToWx(common::FILE_NAME_SEPARATOR))) + resourceDir += zToWx(common::FILE_NAME_SEPARATOR); } } @@ -58,7 +58,7 @@ const wxString& FreeFileSync::getResourceDir() } -const wxString& FreeFileSync::getConfigDir() +const wxString& ffs3::getConfigDir() { static wxString userDirectory; @@ -68,7 +68,7 @@ const wxString& FreeFileSync::getConfigDir() isInitalized = true; if (isPortableVersion()) - //userDirectory = wxString(wxT(".")) + zToWx(globalFunctions::FILE_NAME_SEPARATOR); //use current working directory + //userDirectory = wxString(wxT(".")) + zToWx(common::FILE_NAME_SEPARATOR); //use current working directory userDirectory = getBinaryDir(); //avoid surprises with GlobalSettings.xml being newly created in each working directory else //use OS' standard paths { @@ -77,8 +77,8 @@ const wxString& FreeFileSync::getConfigDir() if (!wxDirExists(userDirectory)) ::wxMkdir(userDirectory); //only top directory needs to be created: no recursion necessary - if (!userDirectory.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR))) - userDirectory += zToWx(globalFunctions::FILE_NAME_SEPARATOR); + if (!userDirectory.EndsWith(zToWx(common::FILE_NAME_SEPARATOR))) + userDirectory += zToWx(common::FILE_NAME_SEPARATOR); } } diff --git a/shared/standardPaths.h b/shared/standard_paths.h index 0ebeebd2..956cf81c 100644 --- a/shared/standardPaths.h +++ b/shared/standard_paths.h @@ -10,7 +10,7 @@ #include <wx/string.h> -namespace FreeFileSync +namespace ffs3 { //------------------------------------------------------------------------------ //global program directories diff --git a/shared/staticAssert.h b/shared/staticAssert.h deleted file mode 100644 index 14f52221..00000000 --- a/shared/staticAssert.h +++ /dev/null @@ -1,24 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** -// -#ifndef STATICASSERT_H_INCLUDED -#define STATICASSERT_H_INCLUDED - -//Reference: Compile-Time Assertions, C/C++ Users Journal November, 2004 (http://pera-software.com/articles/compile-time-assertions.pdf) - -#ifdef NDEBUG -//If not debugging, assert does nothing. -#define assert_static(x) ((void)0) - -#else /* debugging enabled */ - -#define assert_static(e) \ -do { \ -enum { assert_static__ = 1/(static_cast<int>(e)) }; \ -} while (0) -#endif - -#endif // STATICASSERT_H_INCLUDED diff --git a/shared/stringConv.h b/shared/string_conv.h index 454a65f7..bbaef713 100644 --- a/shared/stringConv.h +++ b/shared/string_conv.h @@ -10,7 +10,7 @@ #include <wx/string.h> #include "zstring.h" -namespace FreeFileSync +namespace ffs3 { //conversion from Zstring to wxString wxString zToWx(const Zstring& str); diff --git a/shared/systemConstants.h b/shared/system_constants.h index d686ac50..6877f5c7 100644 --- a/shared/systemConstants.h +++ b/shared/system_constants.h @@ -10,7 +10,7 @@ #include "zstring.h" #include <wx/string.h> -namespace globalFunctions +namespace common { //------------------------------------------------ // GLOBALS diff --git a/shared/systemFunctions.cpp b/shared/system_func.cpp index 41ce9377..71335d71 100644 --- a/shared/systemFunctions.cpp +++ b/shared/system_func.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "systemFunctions.h" +#include "system_func.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -17,7 +17,7 @@ #ifdef FFS_WIN -wxString FreeFileSync::getLastErrorFormatted(unsigned long lastError) //try to get additional Windows error information +wxString ffs3::getLastErrorFormatted(unsigned long lastError) //try to get additional Windows error information { //determine error code if none was specified if (lastError == 0) @@ -28,11 +28,13 @@ wxString FreeFileSync::getLastErrorFormatted(unsigned long lastError) //try to g WCHAR buffer[1001]; if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, lastError, 0, buffer, 1001, NULL) != 0) output += wxString(wxT(": ")) + buffer; + + ::SetLastError(lastError); //restore last error return output; } #elif defined FFS_LINUX -wxString FreeFileSync::getLastErrorFormatted(int lastError) //try to get additional Linux error information +wxString ffs3::getLastErrorFormatted(int lastError) //try to get additional Linux error information { //determine error code if none was specified if (lastError == 0) @@ -40,6 +42,8 @@ wxString FreeFileSync::getLastErrorFormatted(int lastError) //try to get additio wxString output = wxString(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastError); output += wxString(wxT(": ")) + wxString::FromUTF8(::strerror(lastError)); + + errno = lastError; //restore errno return output; } #endif diff --git a/shared/systemFunctions.h b/shared/system_func.h index d197ceb6..b15f4c0c 100644 --- a/shared/systemFunctions.h +++ b/shared/system_func.h @@ -10,7 +10,7 @@ #include <wx/string.h> -namespace FreeFileSync +namespace ffs3 { //evaluate GetLastError()/errno and assemble specific error message #ifdef FFS_WIN diff --git a/shared/taskbar.cpp b/shared/taskbar.cpp index 47681958..61a1841b 100644 --- a/shared/taskbar.cpp +++ b/shared/taskbar.cpp @@ -6,12 +6,12 @@ // #include "taskbar.h" #include "Taskbar_Seven/taskbar.h" -#include "dllLoader.h" -#include "buildInfo.h" -#include "staticAssert.h" +#include "dll_loader.h" +#include "build_info.h" +#include "assert_static.h" #include <wx/msw/wrapwin.h> //includes "windows.h" -using namespace Utility; +using namespace util; namespace @@ -33,14 +33,14 @@ bool windows7TaskbarAvailable() } -const wxString& getTaskBarDllName() +const std::wstring& getTaskBarDllName() { - static const wxString filename( - Utility::is64BitBuild ? - wxT("Taskbar7_x64.dll") : - wxT("Taskbar7_Win32.dll")); + assert_static(util::is32BitBuild || util::is64BitBuild); - assert_static(Utility::is32BitBuild || Utility::is64BitBuild); + static const std::wstring filename( + util::is64BitBuild ? + L"Taskbar7_x64.dll" : + L"Taskbar7_Win32.dll"); return filename; } @@ -71,10 +71,10 @@ TaskbarProgress::TaskbarProgress(const wxTopLevelWindow& window) : pimpl_(new Pi if (!windows7TaskbarAvailable()) throw TaskbarNotAvailable(); - pimpl_->init_ = Utility::loadDllFunction<TaskbarSeven::initFct>( getTaskBarDllName().c_str(), TaskbarSeven::initFctName); - pimpl_->release_ = Utility::loadDllFunction<TaskbarSeven::releaseFct>( getTaskBarDllName().c_str(), TaskbarSeven::releaseFctName); - pimpl_->setProgress_ = Utility::loadDllFunction<TaskbarSeven::setProgressFct>(getTaskBarDllName().c_str(), TaskbarSeven::setProgressFctName); - pimpl_->setStatus_ = Utility::loadDllFunction<TaskbarSeven::setStatusFct>( getTaskBarDllName().c_str(), TaskbarSeven::setStatusFctName); + pimpl_->init_ = util::loadDllFunction<TaskbarSeven::initFct>( getTaskBarDllName(), TaskbarSeven::initFctName); + pimpl_->release_ = util::loadDllFunction<TaskbarSeven::releaseFct>( getTaskBarDllName(), TaskbarSeven::releaseFctName); + pimpl_->setProgress_ = util::loadDllFunction<TaskbarSeven::setProgressFct>(getTaskBarDllName(), TaskbarSeven::setProgressFctName); + pimpl_->setStatus_ = util::loadDllFunction<TaskbarSeven::setStatusFct>( getTaskBarDllName(), TaskbarSeven::setStatusFctName); if ( !pimpl_->init_ || !pimpl_->release_ || diff --git a/shared/taskbar.h b/shared/taskbar.h index 278aca0e..02d7324d 100644 --- a/shared/taskbar.h +++ b/shared/taskbar.h @@ -15,7 +15,7 @@ use in windows build only! #include <memory> -namespace Utility +namespace util { class TaskbarNotAvailable {}; diff --git a/shared/toggleButton.cpp b/shared/toggle_button.cpp index 6a35a85d..2da64ee4 100644 --- a/shared/toggleButton.cpp +++ b/shared/toggle_button.cpp @@ -4,7 +4,7 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "toggleButton.h" +#include "toggle_button.h" void ToggleButton::init(const wxBitmap& activeBmp, const wxString& activeTooltip, diff --git a/shared/toggleButton.h b/shared/toggle_button.h index a67d5fff..a67d5fff 100644 --- a/shared/toggleButton.h +++ b/shared/toggle_button.h diff --git a/shared/util.cpp b/shared/util.cpp index f3013e66..9e0cb9d3 100644 --- a/shared/util.cpp +++ b/shared/util.cpp @@ -10,30 +10,30 @@ #include <wx/combobox.h> #include <wx/filepicker.h> #include "localization.h" -#include "fileHandling.h" -#include "stringConv.h" +#include "file_handling.h" +#include "string_conv.h" #include <stdexcept> -#include "systemFunctions.h" -#include "checkExist.h" +#include "system_func.h" +#include "check_exist.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" #endif -wxString FreeFileSync::formatFilesizeToShortString(const wxLongLong& filesize) +wxString ffs3::formatFilesizeToShortString(const wxLongLong& filesize) { - return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); + return ffs3::formatFilesizeToShortString(filesize.ToDouble()); } -wxString FreeFileSync::formatFilesizeToShortString(const wxULongLong& filesize) +wxString ffs3::formatFilesizeToShortString(const wxULongLong& filesize) { - return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); + return ffs3::formatFilesizeToShortString(filesize.ToDouble()); } -wxString FreeFileSync::formatFilesizeToShortString(double filesize) +wxString ffs3::formatFilesizeToShortString(double filesize) { if (filesize < 0) return _("Error"); @@ -65,7 +65,7 @@ wxString FreeFileSync::formatFilesizeToShortString(double filesize) } } //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111 - const size_t leadDigitCount = globalFunctions::getDigitCount(static_cast<size_t>(filesize)); //number of digits before decimal point + const size_t leadDigitCount = common::getDigitCount(static_cast<size_t>(filesize)); //number of digits before decimal point if (leadDigitCount == 0 || leadDigitCount > 3) return _("Error"); @@ -73,14 +73,14 @@ wxString FreeFileSync::formatFilesizeToShortString(double filesize) } else { - output.Replace(wxT("%x"), globalFunctions::numberToString(static_cast<int>(filesize))); //no decimal places in case of bytes + output.Replace(wxT("%x"), common::numberToString(static_cast<int>(filesize))); //no decimal places in case of bytes } return output; } -wxString FreeFileSync::formatPercentage(const wxLongLong& dividend, const wxLongLong& divisor) +wxString ffs3::formatPercentage(const wxLongLong& dividend, const wxLongLong& divisor) { const double ratio = divisor != 0 ? dividend.ToDouble() * 100 / divisor.ToDouble() : 0; wxString output = _("%x%"); @@ -89,11 +89,11 @@ wxString FreeFileSync::formatPercentage(const wxLongLong& dividend, const wxLong } -wxString FreeFileSync_Impl::includeNumberSeparator(const wxString& number) +wxString ffs_Impl::includeNumberSeparator(const wxString& number) { wxString output(number); for (size_t i = output.size(); i > 3; i -= 3) - output.insert(i - 3, FreeFileSync::getThousandsSeparator()); + output.insert(i - 3, ffs3::getThousandsSeparator()); return output; } @@ -102,30 +102,30 @@ wxString FreeFileSync_Impl::includeNumberSeparator(const wxString& number) template <class T> void setDirectoryNameImpl(const wxString& dirname, T* txtCtrl, wxDirPickerCtrl* dirPicker) { - using namespace FreeFileSync; + using namespace ffs3; txtCtrl->SetValue(dirname); - const Zstring dirFormatted = FreeFileSync::getFormattedDirectoryName(wxToZ(dirname)); + const Zstring dirFormatted = ffs3::getFormattedDirectoryName(wxToZ(dirname)); - if (Utility::dirExists(dirFormatted, 200) == Utility::EXISTING_TRUE) //potentially slow network access: wait 200ms at most + if (util::dirExists(dirFormatted, 200) == util::EXISTING_TRUE) //potentially slow network access: wait 200ms at most dirPicker->SetPath(zToWx(dirFormatted)); } -void FreeFileSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) +void ffs3::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) { setDirectoryNameImpl(dirname, txtCtrl, dirPicker); } -void FreeFileSync::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker) +void ffs3::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker) { txtCtrl->SetSelection(wxNOT_FOUND); setDirectoryNameImpl(dirname, txtCtrl, dirPicker); } -void FreeFileSync::scrollToBottom(wxScrolledWindow* scrWindow) +void ffs3::scrollToBottom(wxScrolledWindow* scrWindow) { int height = 0; scrWindow->GetClientSize(NULL, &height); @@ -172,7 +172,7 @@ void writeFourDigitNumber(size_t number, wxString& string) } } -wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime) +wxString ffs3::utcTimeToLocalString(const wxLongLong& utcTime) { #ifdef FFS_WIN //convert ansi C time to FILETIME diff --git a/shared/util.h b/shared/util.h index 25048132..5023c00b 100644 --- a/shared/util.h +++ b/shared/util.h @@ -10,7 +10,7 @@ #include "../shared/zstring.h" #include <wx/string.h> #include <wx/longlong.h> -#include "../shared/globalFunctions.h" +#include "../shared/global_func.h" class wxComboBox; class wxTextCtrl; @@ -18,7 +18,7 @@ class wxDirPickerCtrl; class wxScrolledWindow; -namespace FreeFileSync +namespace ffs3 { wxString formatFilesizeToShortString(const wxLongLong& filesize); wxString formatFilesizeToShortString(const wxULongLong& filesize); @@ -64,20 +64,20 @@ wxString utcTimeToLocalString(const wxLongLong& utcTime); //throw std::runtime_e //--------------- inline impelementation ------------------------------------------- //helper function! not to be used directly -namespace FreeFileSync_Impl +namespace ffs_Impl { wxString includeNumberSeparator(const wxString& number); } -namespace FreeFileSync +namespace ffs3 { //wxULongLongNative doesn't support operator<<(std::ostream&, wxULongLongNative) template <> inline wxString numberToStringSep(wxULongLongNative number) { - return FreeFileSync_Impl::includeNumberSeparator(number.ToString()); + return ffs_Impl::includeNumberSeparator(number.ToString()); } @@ -85,7 +85,7 @@ template <class NumberType> inline wxString numberToStringSep(NumberType number) { - return FreeFileSync_Impl::includeNumberSeparator(globalFunctions::numberToString(number)); + return ffs_Impl::includeNumberSeparator(common::numberToString(number)); } } diff --git a/shared/xmlBase.cpp b/shared/xml_base.cpp index 42e33016..3213786d 100644 --- a/shared/xmlBase.cpp +++ b/shared/xml_base.cpp @@ -4,15 +4,15 @@ // * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "xmlBase.h" +#include "xml_base.h" #include <wx/intl.h> -#include "fileIO.h" -#include "stringConv.h" -#include "systemConstants.h" +#include "file_io.h" +#include "string_conv.h" +#include "system_constants.h" #include <boost/scoped_array.hpp> -#include "fileHandling.h" +#include "file_handling.h" -using namespace FreeFileSync; +using namespace ffs3; std::string getTypeName(xmlAccess::XmlType type) @@ -79,7 +79,7 @@ void loadRawXmlDocument(const wxString& filename, TiXmlDocument& document) //thr } catch (const FileError& error) //more detailed error messages than with wxWidgets { - throw XmlError(error.show()); + throw XmlError(error.msg()); } //convert (0xD, 0xA) and (0xD) to (0xA): just like in TiXmlDocument::LoadFile(); not sure if actually needed @@ -163,7 +163,7 @@ bool saveNecessary(const Zstring& filename, const std::string& dataToWrite) //th { try { - if (FreeFileSync::getFilesize(filename) != static_cast<unsigned long>(dataToWrite.size())) //throw FileError(); + if (ffs3::getFilesize(filename) != static_cast<unsigned long>(dataToWrite.size())) //throw FileError(); return true; boost::scoped_array<char> inputBuffer(new char[dataToWrite.size() + 1]); //+ 1 in order to test for end of file! @@ -190,7 +190,7 @@ void xmlAccess::saveXmlDocument(const wxString& filename, const TiXmlDocument& d //convert XML into continuous byte sequence TiXmlPrinter printer; - printer.SetLineBreak(wxString(globalFunctions::LINE_BREAK).ToUTF8()); + printer.SetLineBreak(wxString(common::LINE_BREAK).ToUTF8()); document.Accept(&printer); const std::string buffer = printer.Str(); @@ -203,7 +203,7 @@ void xmlAccess::saveXmlDocument(const wxString& filename, const TiXmlDocument& d } catch (const FileError& error) //more detailed error messages than with wxWidgets { - throw XmlError(error.show()); + throw XmlError(error.msg()); } } } @@ -384,7 +384,7 @@ void XmlParser::logError(const std::string& nodeName) } -bool XmlParser::errorsOccured() const +bool XmlParser::errorsOccurred() const { return !failedNodes.empty(); } diff --git a/shared/xmlBase.h b/shared/xml_base.h index 8f7c4aa7..6d342b48 100644 --- a/shared/xmlBase.h +++ b/shared/xml_base.h @@ -8,11 +8,11 @@ #define XMLBASE_H_INCLUDED #include "tinyxml/tinyxml.h" -#include "globalFunctions.h" +#include "global_func.h" #include <string> #include <vector> #include <wx/string.h> -#include "xmlError.h" +#include "xml_error.h" namespace xmlAccess @@ -72,7 +72,7 @@ public: XmlParser(const TiXmlElement* rootElement) : root(rootElement) {} void logError(const std::string& nodeName); - bool errorsOccured() const; + bool errorsOccurred() const; const wxString getErrorMessageFormatted() const; protected: @@ -172,7 +172,7 @@ bool xmlAccess::readXmlElement(const std::string& name, const TiXmlElement* pare if (!readXmlElement(name, parent, temp)) return false; - output = globalFunctions::stringToNumber<T>(temp); + output = common::stringToNumber<T>(temp); return true; } @@ -181,7 +181,7 @@ template <class T> inline void xmlAccess::addXmlElement(const std::string& name, T value, TiXmlElement* parent) { - addXmlElement(name, globalFunctions::numberToString<std::string::value_type>(value), parent); + addXmlElement(name, common::numberToString<std::string::value_type>(value), parent); } @@ -192,7 +192,7 @@ bool xmlAccess::readXmlAttribute(const std::string& name, const TiXmlElement* no std::string dummy; if (readXmlAttribute(name, node, dummy)) { - output = globalFunctions::stringToNumber<T>(dummy); + output = common::stringToNumber<T>(dummy); return true; } else @@ -204,7 +204,7 @@ template <class T> inline void xmlAccess::addXmlAttribute(const std::string& name, T value, TiXmlElement* node) { - addXmlAttribute(name, globalFunctions::numberToString<std::string::value_type>(value), node); + addXmlAttribute(name, common::numberToString<std::string::value_type>(value), node); } #endif // XMLBASE_H_INCLUDED diff --git a/shared/xmlError.h b/shared/xml_error.h index f5f02c6a..bd5153cb 100644 --- a/shared/xmlError.h +++ b/shared/xml_error.h @@ -24,7 +24,7 @@ public: XmlError(const wxString& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {} - const wxString& show() const + const wxString& msg() const { return errorMessage; } diff --git a/shared/zstring.cpp b/shared/zstring.cpp index 6bd0e824..39f1898d 100644 --- a/shared/zstring.cpp +++ b/shared/zstring.cpp @@ -9,16 +9,16 @@ #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" -#include "dllLoader.h" +#include "dll_loader.h" #include <boost/scoped_array.hpp> #endif //FFS_WIN -#ifdef __WXDEBUG__ +#ifndef NDEBUG #include <wx/string.h> #endif -#ifdef __WXDEBUG__ +#ifndef NDEBUG AllocationCount::~AllocationCount() { if (activeStrings.size() > 0) @@ -50,7 +50,7 @@ AllocationCount& AllocationCount::getInstance() static AllocationCount global; return global; } -#endif +#endif //NDEBUG #ifdef FFS_WIN namespace @@ -91,7 +91,7 @@ int compareFilenamesWin32(const wchar_t* a, const wchar_t* b, size_t sizeA, size LPCWSTR lpString2, int cchCount2, BOOL bIgnoreCase); - static const CompareStringOrdinalFunc ordinalCompare = Utility::loadDllFunction<CompareStringOrdinalFunc>(L"kernel32.dll", "CompareStringOrdinal"); + static const CompareStringOrdinalFunc ordinalCompare = util::loadDllFunction<CompareStringOrdinalFunc>(L"kernel32.dll", "CompareStringOrdinal"); if (ordinalCompare != NULL) //this additional test has no noticeable performance impact { @@ -173,22 +173,32 @@ int compareFilenamesWin32(const wchar_t* a, const wchar_t* b, size_t sizeA, size #endif -int Zstring::cmpFileName(const Zstring& other) const +int cmpFileName(const Zstring& lhs, const Zstring& rhs) +{ +#ifdef FFS_WIN + return ::compareFilenamesWin32(lhs.c_str(), rhs.c_str(), lhs.length(), rhs.length()); //way faster than wxString::CmpNoCase() +#elif defined FFS_LINUX + return ::strcmp(lhs.c_str(), rhs.c_str()); +#endif +} + + +int cmpFileName(const Zstring& lhs, const DefaultChar* rhs) { #ifdef FFS_WIN - return ::compareFilenamesWin32(c_str(), other.c_str(), length(), other.length()); //way faster than wxString::CmpNoCase() + return ::compareFilenamesWin32(lhs.c_str(), rhs, lhs.length(), ::wcslen(rhs)); //way faster than wxString::CmpNoCase() #elif defined FFS_LINUX - return defaultCompare(c_str(), other.c_str()); +return ::strcmp(lhs.c_str(), rhs); #endif } -int Zstring::cmpFileName(const DefaultChar* other) const +int cmpFileName(const DefaultChar* lhs, const DefaultChar* rhs) { #ifdef FFS_WIN - return ::compareFilenamesWin32(c_str(), other, length(), ::wcslen(other)); //way faster than wxString::CmpNoCase() + return ::compareFilenamesWin32(lhs, rhs, ::wcslen(lhs), ::wcslen(rhs)); //way faster than wxString::CmpNoCase() #elif defined FFS_LINUX - return defaultCompare(c_str(), other); + return ::strcmp(lhs, rhs); #endif } @@ -569,7 +579,7 @@ void Zstring::reserve(size_t capacityNeeded) //make unshared and check capacity //try to resize the current string (allocate anew if necessary) const size_t newCapacity = getCapacityToAllocate(capacityNeeded); -#ifdef __WXDEBUG__ +#ifndef NDEBUG AllocationCount::getInstance().dec(c_str()); //test Zstring for memory leaks #endif @@ -577,7 +587,7 @@ void Zstring::reserve(size_t capacityNeeded) //make unshared and check capacity if (descr == NULL) throw std::bad_alloc(); -#ifdef __WXDEBUG__ +#ifndef NDEBUG AllocationCount::getInstance().inc(c_str()); //test Zstring for memory leaks #endif diff --git a/shared/zstring.h b/shared/zstring.h index d59126df..7b993fd0 100644 --- a/shared/zstring.h +++ b/shared/zstring.h @@ -13,8 +13,9 @@ #include <vector> #include <sstream> #include <algorithm> //specialize std::swap +#include <functional> -#ifdef __WXDEBUG__ +#ifndef NDEBUG #include <set> #include <wx/thread.h> #endif @@ -40,10 +41,6 @@ public: operator const DefaultChar*() const; //implicit conversion to C string - //Compare filenames: Windows does NOT distinguish between upper/lower-case, while Linux DOES - int cmpFileName(const Zstring& other) const; - int cmpFileName(const DefaultChar* other) const; - //wxWidgets-like functions bool StartsWith(const DefaultChar* begin) const; bool StartsWith(DefaultChar begin) const; @@ -146,6 +143,17 @@ const Zstring operator+(const Zstring& lhs, DefaultChar rhs); template <class T> Zstring numberToZstring(const T& number); //convert number to Zstring +//Compare filenames: Windows does NOT distinguish between upper/lower-case, while Linux DOES +int cmpFileName(const Zstring& lhs, const Zstring& rhs); +int cmpFileName(const Zstring& lhs, const DefaultChar* rhs); +int cmpFileName(const DefaultChar* lhs, const Zstring& rhs); +int cmpFileName(const DefaultChar* lhs, const DefaultChar* rhs); + +struct LessFilename : public std::binary_function<Zstring, Zstring, bool>//case-insensitive on Windows, case-sensitive on Linux +{ + bool operator()(const Zstring& a, const Zstring& b) const; +}; + namespace std { template<> @@ -174,6 +182,15 @@ void swap(Zstring& rhs, Zstring& lhs) + + + + + + + + + //####################################################################################### //begin of implementation @@ -255,8 +272,7 @@ const DefaultChar* Zstring::defaultStrFind(const DefaultChar* str1, const Defaul } //-------------------------------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ +#ifndef NDEBUG class AllocationCount //small test for memory leaks in Zstring { public: @@ -282,7 +298,7 @@ private: wxCriticalSection lockActStrings; std::set<const DefaultChar*> activeStrings; }; -#endif +#endif //NDEBUG inline @@ -307,7 +323,7 @@ Zstring::StringDescriptor* Zstring::allocate(const size_t newLength) newDescr->length = newLength; newDescr->capacity = newCapacity; -#ifdef __WXDEBUG__ +#ifndef NDEBUG AllocationCount::getInstance().inc(reinterpret_cast<DefaultChar*>(newDescr + 1)); //test Zstring for memory leaks #endif return newDescr; @@ -383,7 +399,7 @@ void Zstring::decRef() assert(descr && descr->refCount >= 1); //descr points to the begin of the allocated memory block if (--descr->refCount == 0) { -#ifdef __WXDEBUG__ +#ifndef NDEBUG AllocationCount::getInstance().dec(c_str()); //test Zstring for memory leaks #endif ::free(descr); //beginning of whole memory block @@ -765,4 +781,23 @@ Zstring numberToZstring(const T& number) //convert number to string the C++ way return Zstring(ss.str().c_str()); } + +inline +int cmpFileName(const DefaultChar* lhs, const Zstring& rhs) +{ + return cmpFileName(rhs, lhs); +} + + +inline +bool LessFilename::operator()(const Zstring& a, const Zstring& b) const +{ +// //quick check based on string length +// const size_t aLength = a.data.shortName.length(); +// const size_t bLength = b.data.shortName.length(); +// if (aLength != bLength) +// return aLength < bLength; + return cmpFileName(a, b) < 0; +} + #endif // ZSTRING_H_INCLUDED |