diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:39 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:39 +0200 |
commit | d2854834e18443876c8f75e0a7f3b88d1d549fc4 (patch) | |
tree | e967b628081e50abc7c34cd264e6586271c7e728 /lib | |
parent | 4.1 (diff) | |
download | FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.tar.gz FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.tar.bz2 FreeFileSync-d2854834e18443876c8f75e0a7f3b88d1d549fc4.zip |
4.2
Diffstat (limited to 'lib')
32 files changed, 716 insertions, 520 deletions
diff --git a/lib/FindFilePlus/dll_main.cpp b/lib/FindFilePlus/dll_main.cpp index aca474bc..5d64181b 100644 --- a/lib/FindFilePlus/dll_main.cpp +++ b/lib/FindFilePlus/dll_main.cpp @@ -6,7 +6,7 @@ #define WIN32_LEAN_AND_MEAN -#include <windows.h> +#include <zen/win.h> #include "init_dll_binding.h" diff --git a/lib/FindFilePlus/load_dll.cpp b/lib/FindFilePlus/load_dll.cpp index 7166223b..20d9a5fe 100644 --- a/lib/FindFilePlus/load_dll.cpp +++ b/lib/FindFilePlus/load_dll.cpp @@ -6,7 +6,7 @@ #include "load_dll.h" #define WIN32_LEAN_AND_MEAN -#include <windows.h> +#include <zen/win.h> void* /*FARPROC*/ dll::loadSymbol(const wchar_t* libraryName, const char* functionName) { diff --git a/lib/FindFilePlus/load_dll.h b/lib/FindFilePlus/load_dll.h index 149b6efe..350de9f8 100644 --- a/lib/FindFilePlus/load_dll.h +++ b/lib/FindFilePlus/load_dll.h @@ -44,4 +44,3 @@ void* /*FARPROC*/ loadSymbol(const wchar_t* libraryName, const char* functionNam } #endif //LOAD_DLL_HEADER_0312463214872163832174 - diff --git a/lib/IFileOperation/file_op.cpp b/lib/IFileOperation/file_op.cpp index 10eac5de..fca802f0 100644 --- a/lib/IFileOperation/file_op.cpp +++ b/lib/IFileOperation/file_op.cpp @@ -5,69 +5,38 @@ // ************************************************************************** #include "file_op.h" +#include <algorithm> +#include <string> #define WIN32_LEAN_AND_MEAN -#include <zen/win.h> #include <zen/com_ptr.h> #include <zen/com_error.h> -#include <Shellapi.h> // Included for shell constants such as FO_* values -#include <shobjidl.h> // Required for necessary shell dependencies -#include <algorithm> -#include <string> +#include <shellapi.h> //shell constants such as FO_* values +#include <shobjidl.h> using namespace zen; -namespace fileop +namespace { -inline -void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize) +void moveToRecycleBin(const wchar_t* fileNames[], //throw ComError + size_t fileNo) //size of fileNames array { - if (bufferSize > 0) - { - //size_t endPos = input.copy(buffer, bufferSize - 1); - //buffer[endPos] = 0; - const size_t maxSize = std::min(input.length(), bufferSize - 1); - std::copy(input.begin(), input.begin() + maxSize, buffer); - buffer[maxSize] = 0; - } -} - -std::wstring lastErrorMessage; //this should really be thread-local!!! -} - - -bool fileop::moveToRecycleBin(const wchar_t* fileNames[], - size_t fileNo) //size of fileNames array -{ - HRESULT hr; - - // Create the IFileOperation interface ComPtr<IFileOperation> fileOp; - hr = ::CoCreateInstance(CLSID_FileOperation, - NULL, - CLSCTX_ALL, - IID_PPV_ARGS(fileOp.init())); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr); - return false; - } + ZEN_CHECK_COM(::CoCreateInstance(CLSID_FileOperation, //throw ComError + NULL, + CLSCTX_ALL, + IID_PPV_ARGS(fileOp.init()))); // Set the operation flags. Turn off all UI // from being shown to the user during the // operation. This includes error, confirmation // and progress dialogs. - hr = fileOp->SetOperationFlags(FOF_ALLOWUNDO | - FOF_NOCONFIRMATION | - FOF_SILENT | - FOFX_EARLYFAILURE | - FOF_NOERRORUI); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"SetOperationFlags\".", hr); - return false; - } + ZEN_CHECK_COM(fileOp->SetOperationFlags(FOF_ALLOWUNDO | //throw ComError + FOF_NOCONFIRMATION | + FOF_SILENT | + FOFX_EARLYFAILURE | + FOF_NOERRORUI)); int operationCount = 0; @@ -75,161 +44,142 @@ bool fileop::moveToRecycleBin(const wchar_t* fileNames[], { //create file/folder item object ComPtr<IShellItem> psiFile; - hr = ::SHCreateItemFromParsingName(fileNames[i], - NULL, - IID_PPV_ARGS(psiFile.init())); + HRESULT hr = ::SHCreateItemFromParsingName(fileNames[i], + NULL, + IID_PPV_ARGS(psiFile.init())); if (FAILED(hr)) { if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || //file not existing anymore hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) continue; - - std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for file:\n"); - message += std::wstring(L"\"") + fileNames[i] + L"\"."; - - lastErrorMessage = generateErrorMsg(message, hr); - return false; + throw ComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for file:\n") + L"\"" + fileNames[i] + L"\".", hr); } - hr = fileOp->DeleteItem(psiFile.get(), NULL); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"DeleteItem\".", hr); - return false; - } + ZEN_CHECK_COM(fileOp->DeleteItem(psiFile.get(), NULL)); ++operationCount; } - if (operationCount == 0) //calling PerformOperations() without anything to do results in E_UNEXPECTED - return true; + if (operationCount == 0) //calling PerformOperations() without anything to do would result in E_UNEXPECTED + return; //perform actual operations - hr = fileOp->PerformOperations(); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"PerformOperations\".", hr); - return false; - } + ZEN_CHECK_COM(fileOp->PerformOperations()); //check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors! BOOL pfAnyOperationsAborted = FALSE; - hr = fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"GetAnyOperationsAborted\".", hr); - return false; - } + ZEN_CHECK_COM(fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted)); if (pfAnyOperationsAborted == TRUE) - { - lastErrorMessage = L"Operation did not complete successfully."; - return false; - } - - return true; + throw ComError(L"Operation did not complete successfully."); } -bool fileop::copyFile(const wchar_t* sourceFile, - const wchar_t* targetFile) +void copyFile(const wchar_t* sourceFile, //throw ComError + const wchar_t* targetFile) { - HRESULT hr; - - // Create the IFileOperation interface ComPtr<IFileOperation> fileOp; - hr = ::CoCreateInstance(CLSID_FileOperation, - NULL, - CLSCTX_ALL, - IID_PPV_ARGS(fileOp.init())); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"CoCreateInstance\".", hr); - return false; - } + ZEN_CHECK_COM(::CoCreateInstance(CLSID_FileOperation, //throw ComError + NULL, + CLSCTX_ALL, + IID_PPV_ARGS(fileOp.init()))); // Set the operation flags. Turn off all UI // from being shown to the user during the // operation. This includes error, confirmation // and progress dialogs. - hr = fileOp->SetOperationFlags(FOF_NOCONFIRMATION | - FOF_SILENT | - FOFX_EARLYFAILURE | - FOF_NOERRORUI); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"SetOperationFlags\".", hr); - return false; - } - + ZEN_CHECK_COM(fileOp->SetOperationFlags(FOF_NOCONFIRMATION | //throw ComError + FOF_SILENT | + FOFX_EARLYFAILURE | + FOF_NOERRORUI)); //create source object ComPtr<IShellItem> psiSourceFile; - hr = ::SHCreateItemFromParsingName(sourceFile, - NULL, - IID_PPV_ARGS(psiSourceFile.init())); - if (FAILED(hr)) { - std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for file:\n"); - message += std::wstring(L"\"") + sourceFile + L"\"."; - lastErrorMessage = generateErrorMsg(message, hr); - return false; + HRESULT hr = ::SHCreateItemFromParsingName(sourceFile, + NULL, + IID_PPV_ARGS(psiSourceFile.init())); + if (FAILED(hr)) + throw ComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for file:\n") + L"\"" + sourceFile + L"\".", hr); } const size_t pos = std::wstring(targetFile).find_last_of(L'\\'); if (pos == std::wstring::npos) - { - lastErrorMessage = L"Target filename does not contain a path separator."; - return false; - } + throw ComError(L"Target filename does not contain a path separator."); const std::wstring targetFolder(targetFile, pos); const std::wstring targetFileNameShort = targetFile + pos + 1; //create target folder object ComPtr<IShellItem> psiTargetFolder; - hr = ::SHCreateItemFromParsingName(targetFolder.c_str(), - NULL, - IID_PPV_ARGS(psiTargetFolder.init())); - if (FAILED(hr)) { - std::wstring message(L"Error calling \"SHCreateItemFromParsingName\" for folder:\n"); - message += std::wstring(L"\"") + targetFolder + L"\"."; - lastErrorMessage = generateErrorMsg(message, hr); - return false; + HRESULT hr = ::SHCreateItemFromParsingName(targetFolder.c_str(), + NULL, + IID_PPV_ARGS(psiTargetFolder.init())); + if (FAILED(hr)) + throw ComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for folder:\n") + L"\"" + targetFolder + L"\".", hr); } //schedule file copy operation - hr = fileOp->CopyItem(psiSourceFile.get(), psiTargetFolder.get(), targetFileNameShort.c_str(), NULL); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"CopyItem\".", hr); - return false; - } + ZEN_CHECK_COM(fileOp->CopyItem(psiSourceFile.get(), psiTargetFolder.get(), targetFileNameShort.c_str(), NULL)); //perform actual operations - hr = fileOp->PerformOperations(); - if (FAILED(hr)) - { - lastErrorMessage = generateErrorMsg(L"Error calling \"PerformOperations\".", hr); - return false; - } + ZEN_CHECK_COM(fileOp->PerformOperations()); //check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors! BOOL pfAnyOperationsAborted = FALSE; - hr = fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted); - if (FAILED(hr)) + ZEN_CHECK_COM(fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted)); + + if (pfAnyOperationsAborted == TRUE) + throw ComError(L"Operation did not complete successfully."); +} + + +inline +void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize) +{ + if (bufferSize > 0) { - lastErrorMessage = generateErrorMsg(L"Error calling \"GetAnyOperationsAborted\".", hr); - return false; + //size_t endPos = input.copy(buffer, bufferSize - 1); + //buffer[endPos] = 0; + const size_t maxSize = std::min(input.length(), bufferSize - 1); + std::copy(input.begin(), input.begin() + maxSize, buffer); + buffer[maxSize] = 0; } +} - if (pfAnyOperationsAborted == TRUE) +std::wstring lastErrorMessage; //this should really be thread-local!!! +} + + +bool fileop::moveToRecycleBin(const wchar_t* fileNames[], + size_t fileNo) //size of fileNames array +{ + try + { + ::moveToRecycleBin(fileNames, fileNo); //throw ComError + return true; + } + catch (const zen::ComError& e) { - lastErrorMessage = L"Operation did not complete successfully."; + lastErrorMessage = e.toString(); return false; } +} + - return true; +bool fileop::copyFile(const wchar_t* sourceFile, + const wchar_t* targetFile) +{ + try + { + ::copyFile(sourceFile, targetFile); //throw ComError + return true; + } + catch (const zen::ComError& e) + { + lastErrorMessage = e.toString(); + return false; + } } diff --git a/lib/ShadowCopy/Shadow_2003.vcxproj b/lib/ShadowCopy/Shadow_Server2003.vcxproj index a893a389..a893a389 100644 --- a/lib/ShadowCopy/Shadow_2003.vcxproj +++ b/lib/ShadowCopy/Shadow_Server2003.vcxproj diff --git a/lib/ShadowCopy/Shadow_Windows7.vcxproj b/lib/ShadowCopy/Shadow_Windows7.vcxproj new file mode 100644 index 00000000..2392fa99 --- /dev/null +++ b/lib/ShadowCopy/Shadow_Windows7.vcxproj @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectName>Windows7</ProjectName> + <ProjectGuid>{7E217D76-90A5-4B03-A6F8-E7C3ADD22901}</ProjectGuid> + <RootNamespace>ShadowDll</RootNamespace> + <Keyword>Win32Proj</Keyword> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <WholeProgramOptimization>true</WholeProgramOptimization> + <UseOfAtl>false</UseOfAtl> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Shadow_$(ProjectName)_$(Platform)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Shadow_$(ProjectName)_$(Platform)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shadow_$(ProjectName)_$(Platform)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Shadow_$(ProjectName)_$(Platform)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <ClCompile> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <Midl> + <TargetEnvironment>X64</TargetEnvironment> + </Midl> + <ClCompile> + <Optimization>Disabled</Optimization> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX64</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>false</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <Midl> + <TargetEnvironment>X64</TargetEnvironment> + </Midl> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>false</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX64</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="dll_main.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged> + </ClCompile> + <ClCompile Include="shadow.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="shadow.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/lib/ShadowCopy/shadow.cpp b/lib/ShadowCopy/shadow.cpp index 12e9fa60..5047a698 100644 --- a/lib/ShadowCopy/shadow.cpp +++ b/lib/ShadowCopy/shadow.cpp @@ -7,12 +7,9 @@ #include "shadow.h" #include <algorithm> #include <string> -#include <comdef.h> #include <zen/com_ptr.h> #include <zen/com_error.h> - -#define WIN32_LEAN_AND_MEAN -#include "windows.h" +#include <zen/scope_guard.h> #ifdef USE_SHADOW_XP #include "xp/inc/vss.h" @@ -23,13 +20,30 @@ #include "Server 2003/inc/vss.h" #include "Server 2003/inc/vswriter.h" #include "Server 2003/inc/vsbackup.h" + +#elif defined USE_SHADOW_WINDOWS7 +#include <vss.h> // +#include <vswriter.h> //part of Windows SDK for Windows 7 +#include <vsbackup.h> // +#pragma comment(lib, "VssApi.lib") + #else -adapt! +#error adapt! #endif using namespace zen; +struct shadow::ShadowData +{ + ShadowData(const ComPtr<IVssBackupComponents>& backupComp, + const std::wstring& shadowVolume) : backupComp_(backupComp), shadowVolume_(shadowVolume) {} + + ComPtr<IVssBackupComponents> backupComp_; + std::wstring shadowVolume_; +}; + + namespace { inline @@ -45,143 +59,99 @@ void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize) } } -inline -void writeErrorMsg(const wchar_t* input, HRESULT hr, wchar_t* output, unsigned int outputLen) -{ - copyString(generateErrorMsg(input, hr), output, outputLen); -} -} - -bool shadow::createShadowCopy(const wchar_t* volumeName, - wchar_t* shadowVolName, - unsigned int shadowBufferLen, - ShadowHandle* handle, - wchar_t* errorMessage, - unsigned int errorBufferLen) +shadow::ShadowData createShadowCopy(const wchar_t* volumeName) //throw ComError { - //MessageBox(0, L"backup err", L"", 0); */ - *handle = 0; - HRESULT hr = NULL; - 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); - else - writeErrorMsg(L"Error calling \"CreateVssBackupComponents\".", hr, errorMessage, errorBufferLen); - return false; + HRESULT hr = ::CreateVssBackupComponents(backupComp.init()); + if (FAILED(hr)) + { + if (hr == E_ACCESSDENIED) + throw ComError(L"The caller does not have sufficient backup privileges or is not an administrator.", hr); + throw ComError(L"Error calling \"CreateVssBackupComponents\".", hr); + } } - if (FAILED(hr = backupComp->InitializeForBackup())) - { - writeErrorMsg(L"Error calling \"InitializeForBackup\".", hr, errorMessage, errorBufferLen); - return false; - } + ZEN_CHECK_COM(backupComp->InitializeForBackup()); //throw ComError + ZEN_CHECK_COM(backupComp->SetBackupState(false, false, VSS_BT_FULL)); //throw ComError - if (FAILED(hr = backupComp->SetBackupState(false, false, VSS_BT_FULL))) + auto waitForComFuture = [](IVssAsync& fut) { - writeErrorMsg(L"Error calling \"SetBackupState\".", hr, errorMessage, errorBufferLen); - return false; - } + ZEN_CHECK_COM(fut.Wait()); - 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; - } + HRESULT hr = S_OK; + ZEN_CHECK_COM(fut.QueryStatus(&hr, NULL)); //check if the async operation succeeded... + if (FAILED(hr)) + throw ComError(L"Error calling \"fut->QueryStatus\".", hr); + }; - //wait for shadow copy writers to complete - if (FAILED(hr = vssWriters->Wait())) - { - writeErrorMsg(L"Error calling \"vssWriters->Wait\".", hr, errorMessage, errorBufferLen); - return false; - } + ComPtr<IVssAsync> gatherAsync; + ZEN_CHECK_COM(backupComp->GatherWriterMetadata(gatherAsync.init())); + waitForComFuture(*gatherAsync); //failure can happen if XP-version of VSS is used on Windows Vista (which needs at least VSS-Server2003 build) - 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 = {}; + ZEN_CHECK_COM(backupComp->StartSnapshotSet(&snapshotSetId)); + ScopeGuard guardSnapShot = makeGuard([&]() { backupComp->AbortBackup(); }); + //Quote: "This method must be called if a backup operation terminates after the creation of a + //shadow copy set with "StartSnapshotSet" and before "DoSnapshotSet" returns." - VSS_ID snapshotSetId = {0}; - if (FAILED(hr = backupComp->StartSnapshotSet(&snapshotSetId))) + VSS_ID SnapShotId = {}; { - writeErrorMsg(L"Error calling \"StartSnapshotSet\".", hr, errorMessage, errorBufferLen); - return false; + HRESULT hr = backupComp->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId); + if (FAILED(hr)) + { + if (hr == VSS_E_VOLUME_NOT_SUPPORTED) + throw ComError(L"Volume Shadow Copy Service is not supported on this volume!"); + throw ComError(L"Error calling \"backupComp->AddToSnapshotSet\".", hr); + } } - VSS_ID SnapShotId = {0}; - if (FAILED(hr = backupComp->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId))) - { - writeErrorMsg(L"Error calling \"AddToSnapshotSet\".", hr, errorMessage, errorBufferLen); - return false; - } + ComPtr<IVssAsync> prepareAsync; + ZEN_CHECK_COM(backupComp->PrepareForBackup(prepareAsync.init())); + waitForComFuture(*prepareAsync); - ComPtr<IVssAsync> vssPrepare; - if (FAILED(hr = backupComp->PrepareForBackup(vssPrepare.init()))) - { - writeErrorMsg(L"Error calling \"PrepareForBackup\".", hr, errorMessage, errorBufferLen); - return false; - } + ComPtr<IVssAsync> snapshotAsync; + ZEN_CHECK_COM(backupComp->DoSnapshotSet(snapshotAsync.init())); + guardSnapShot.dismiss(); + waitForComFuture(*snapshotAsync); - if (FAILED(hr = vssPrepare->Wait())) - { - writeErrorMsg(L"Error calling \"vssPrepare->Wait\".", hr, errorMessage, errorBufferLen); - return false; - } + VSS_SNAPSHOT_PROP props = {}; + ZEN_CHECK_COM(backupComp->GetSnapshotProperties(SnapShotId, &props)); + ZEN_ON_BLOCK_EXIT(::VssFreeSnapshotProperties(&props)); - vssPrepare->QueryStatus(&hr, NULL); //check if the async operation succeeded... - if (FAILED(hr)) - { - writeErrorMsg(L"Error calling \"vssPrepare->QueryStatus\".", hr, errorMessage, errorBufferLen); - return false; - } - - ComPtr<IVssAsync> vssDoShadowCopy; - if (FAILED(hr = backupComp->DoSnapshotSet(vssDoShadowCopy.init()))) - { - writeErrorMsg(L"Error calling \"DoSnapshotSet\".", hr, errorMessage, errorBufferLen); - return false; - } + //finally: write volume name of newly created shadow copy + return shadow::ShadowData(backupComp, props.m_pwszSnapshotDeviceObject); +} +} - if (FAILED(hr = vssDoShadowCopy->Wait())) - { - writeErrorMsg(L"Error calling \"vssDoShadowCopy->Wait\".", hr, errorMessage, errorBufferLen); - return false; - } - vssDoShadowCopy->QueryStatus(&hr, NULL); //check if the async operation succeeded... - if (FAILED(hr)) +shadow::ShadowHandle shadow::createShadowCopy(const wchar_t* volumeName, + wchar_t* errorMessage, + unsigned int errorBufferLen) +{ + try { - writeErrorMsg(L"Error calling \"vssDoShadowCopy->QueryStatus\".", hr, errorMessage, errorBufferLen); - return false; + ShadowData result = ::createShadowCopy(volumeName); //shadow handle owned by caller! throw ComError + return new ShadowData(result); } - - VSS_SNAPSHOT_PROP props; - if (FAILED(hr = backupComp->GetSnapshotProperties(SnapShotId, &props))) + catch (const zen::ComError& e) { - writeErrorMsg(L"Error calling \"GetSnapshotProperties\".", hr, errorMessage, errorBufferLen); - return false; + copyString(e.toString(), errorMessage, errorBufferLen); + return nullptr; } +} - //finally: write volume name of newly created shadow copy - copyString(props.m_pwszSnapshotDeviceObject, shadowVolName, shadowBufferLen); - - VssFreeSnapshotProperties(&props); - - *handle = backupComp.release(); - return true; +void shadow::getShadowVolume(shadow::ShadowHandle handle, + wchar_t* buffer, + unsigned int bufferLen) +{ + copyString(handle->shadowVolume_, buffer, bufferLen); } void shadow::releaseShadowCopy(ShadowHandle handle) { - if (handle) - handle->Release(); + delete handle; } diff --git a/lib/ShadowCopy/shadow.h b/lib/ShadowCopy/shadow.h index 0dfd39a9..68b7141f 100644 --- a/lib/ShadowCopy/shadow.h +++ b/lib/ShadowCopy/shadow.h @@ -26,23 +26,23 @@ namespace shadow --------------*/ //COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize +struct ShadowData; +typedef ShadowData* ShadowHandle; -typedef IVssBackupComponents* ShadowHandle; - -//volumeName must end with "\", while shadowVolName does not end with "\" +//volumeName *must* end with "\" SHADOWDLL_API -bool createShadowCopy(const wchar_t* volumeName, // in - wchar_t* shadowVolName, // out - unsigned int shadowBufferLen, // in - ShadowHandle* handle, // out - wchar_t* errorMessage, // out - unsigned int errorBufferLen); // in - +ShadowHandle createShadowCopy(const wchar_t* volumeName, // in Returns nullptr on failure! + wchar_t* errorMessage, // out + unsigned int errorBufferLen); // in //don't forget to release the backupHandle after shadow copy is not needed anymore! SHADOWDLL_API void releaseShadowCopy(ShadowHandle handle); +SHADOWDLL_API +void getShadowVolume(ShadowHandle handle, //shadowVolName does *not* end with "\" + wchar_t* buffer, + unsigned int bufferLen); //########################################################################################## @@ -50,21 +50,24 @@ void releaseShadowCopy(ShadowHandle handle); /*---------- |typedefs| ----------*/ -typedef bool (*CreateShadowCopyFct)(const wchar_t* volumeName, - wchar_t* shadowVolName, - unsigned int shadowBufferLen, - ShadowHandle* handle, - wchar_t* errorMessage, - unsigned int errorBufferLen); +typedef ShadowHandle (*CreateShadowCopyFct)(const wchar_t* volumeName, + wchar_t* errorMessage, + unsigned int errorBufferLen); typedef void (*ReleaseShadowCopyFct)(ShadowHandle handle); +typedef void (*GetShadowVolumeFct)(ShadowHandle handle, + wchar_t* buffer, + unsigned int bufferLen); + + /*-------------- |symbol names| --------------*/ //(use const pointers to ensure internal linkage) -const char createShadowCopyFctName[] = "createShadowCopy"; +const char createShadowCopyFctName [] = "createShadowCopy"; const char releaseShadowCopyFctName[] = "releaseShadowCopy"; +const char getShadowVolumeFctName [] = "getShadowVolume"; /*--------------- |library names| @@ -73,21 +76,24 @@ const char releaseShadowCopyFctName[] = "releaseShadowCopy"; inline const wchar_t* getDllName() { - /* - 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 - */ - return zen::winServer2003orLater() ? - (zen::is64BitBuild ? - L"Shadow_Server2003_x64.dll" : - L"Shadow_Server2003_Win32.dll") : - - (zen::is64BitBuild ? - L"Shadow_XP_x64.dll" : - L"Shadow_XP_Win32.dll"); + // distinguish a bunch of VSS builds: we use XP, Server 2003 and Server 2008 R2 implementations... + // VSS version and compatibility overview: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx + + if (zen::win7OrLater()) //Windows Server 2008 R2 or Windows 7 + return zen::is64BitBuild ? + L"Shadow_Windows7_x64.dll" : + L"Shadow_Windows7_Win32.dll"; + //else if (vistaOrLater()) -> skip Windows Server 2008 and Windows Vista + // ; + else if (zen::winServer2003orLater()) //Windows Server 2003 and Windows Server 2003 R2 + return zen::is64BitBuild ? + L"Shadow_Server2003_x64.dll" : + L"Shadow_Server2003_Win32.dll"; + else //Windows XP + return zen::is64BitBuild ? + L"Shadow_XP_x64.dll" : + L"Shadow_XP_Win32.dll"; } } - - #endif //SHADOWCOPY_H diff --git a/lib/Thumbnail/thumbnail.cpp b/lib/Thumbnail/thumbnail.cpp index b8d00c38..c3d22cbd 100644 --- a/lib/Thumbnail/thumbnail.cpp +++ b/lib/Thumbnail/thumbnail.cpp @@ -5,9 +5,10 @@ // ************************************************************************** #include "thumbnail.h" +#include <string> #define WIN32_LEAN_AND_MEAN -#include "windows.h" +#include <zen/win.h> #define STRICT_TYPED_ITEMIDS //better type safety for IDLists #include <Shlobj.h> @@ -16,12 +17,12 @@ #include <CommonControls.h> #include <zen/com_ptr.h> #include <zen/string_tools.h> -#include <string> #include <zen/scope_guard.h> using namespace zen; + thumb::HICON thumb::getThumbnail(const wchar_t* filename, int requestedSize) //return 0 on failure, caller takes ownership! { const std::wstring filenameStr(filename); diff --git a/lib/cmp_filetime.h b/lib/cmp_filetime.h index e8cd6f50..afc97b9d 100644 --- a/lib/cmp_filetime.h +++ b/lib/cmp_filetime.h @@ -18,8 +18,8 @@ bool sameFileTime(const Int64& a, const Int64& b, size_t tolerance) //--------------------------------------------------------------------------------------------------------------- //number of seconds since Jan 1st 1970 + 1 year (needn't be too precise) -static const long oneYearFromNow = wxGetUTCTime() + 365 * 24 * 3600; //init at program startup -> avoid MT issues - +static const long oneYearFromNow = wxGetUTCTime() + 365 * 24 * 3600; //init at program startup alas in *each* compilation untit -> avoid MT issues +//refactor when C++11 thread-safe static initialization is availalbe in VS (already in GCC) class CmpFileTime { @@ -37,19 +37,16 @@ public: Result getResult(const Int64& lhs, const Int64& rhs) const { - if (lhs == rhs) + if (sameFileTime(lhs, rhs, tolerance_)) //last write time may differ by up to 2 seconds (NTFS vs FAT32) return TIME_EQUAL; - //check for erroneous dates (but only if dates are not (EXACTLY) the same) + //check for erroneous dates if (lhs < 0 || lhs > oneYearFromNow) //earlier than Jan 1st 1970 or more than one year in future return TIME_LEFT_INVALID; if (rhs < 0 || rhs > oneYearFromNow) return TIME_RIGHT_INVALID; - if (sameFileTime(lhs, rhs, tolerance_)) //last write time may differ by up to 2 seconds (NTFS vs FAT32) - return TIME_EQUAL; - //regular time comparison if (lhs < rhs) return TIME_RIGHT_NEWER; diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp index 6da8b275..97db1676 100644 --- a/lib/custom_grid.cpp +++ b/lib/custom_grid.cpp @@ -1375,15 +1375,15 @@ void CustomGridRim::setTooltip(const wxMouseEvent& event) virtual void visit(const FileMapping& fileObj) { - tipMsg_ = toWx(fileObj.getRelativeName<side>()) + "\n" + - _("Size") + ": " + zen::filesizeToShortString(fileObj.getFileSize<side>()) + "\n" + - _("Date") + ": " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()); + tipMsg_ = copyStringTo<wxString>(std::wstring() + fileObj.getRelativeName<side>() + L"\n" + + _("Size") + L": " + zen::filesizeToShortString(fileObj.getFileSize<side>()) + L"\n" + + _("Date") + L": " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>())); } virtual void visit(const SymLinkMapping& linkObj) { - tipMsg_ = toWx(linkObj.getRelativeName<side>()) + "\n" + - _("Date") + ": " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()); + tipMsg_ = copyStringTo<wxString>(std::wstring() + linkObj.getRelativeName<side>() + L"\n" + + _("Date") + L": " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>())); } virtual void visit(const DirMapping& dirObj) diff --git a/lib/db_file.cpp b/lib/db_file.cpp index 757a95d7..faee4c8a 100644 --- a/lib/db_file.cpp +++ b/lib/db_file.cpp @@ -63,7 +63,7 @@ public: Read(formatDescr, sizeof(formatDescr)); //throw FileError if (!std::equal(FILE_FORMAT_DESCR, FILE_FORMAT_DESCR + sizeof(FILE_FORMAT_DESCR), formatDescr)) - throw FileError(_("Incompatible synchronization database format:") + " \n" + "\"" + filename + "\""); + throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\""); } private: @@ -89,7 +89,7 @@ private: class ReadDirInfo : public zen::ReadInputStream { public: - ReadDirInfo(wxInputStream& stream, const wxString& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName) + ReadDirInfo(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName) { //|------------------------------------------------------------------------------------- //| ensure 32/64 bit portability: use fixed size data types only e.g. boost::uint32_t | @@ -163,7 +163,7 @@ typedef std::map<UniqueId, MemoryStreamPtr> StreamMapping; //list of streams class ReadFileStream : public zen::ReadInputStream { public: - ReadFileStream(wxInputStream& stream, const wxString& filename, StreamMapping& streamList) : ReadInputStream(stream, filename) + ReadFileStream(wxInputStream& stream, const Zstring& filename, StreamMapping& streamList) : ReadInputStream(stream, filename) { //|------------------------------------------------------------------------------------- //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t | @@ -172,7 +172,7 @@ public: std::int32_t version = readNumberC<std::int32_t>(); if (version != FILE_FORMAT_VER) //read file format version - throw FileError(_("Incompatible synchronization database format:") + " \n" + "\"" + filename.c_str() + "\""); + throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\""); streamList.clear(); @@ -195,9 +195,9 @@ namespace StreamMapping loadStreams(const Zstring& filename) //throw FileError { if (!zen::fileExists(filename)) - throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + " \n\n" + - _("One of the FreeFileSync database files is not yet existing:") + " \n" + - "\"" + filename + "\""); + throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" + + _("One of the FreeFileSync database files is not yet existing:") + L" \n" + + L"\"" + filename + L"\""); try { @@ -207,12 +207,12 @@ StreamMapping loadStreams(const Zstring& filename) //throw FileError wxZlibInputStream input(uncompressed, wxZLIB_ZLIB); StreamMapping streamList; - ReadFileStream(input, toWx(filename), streamList); + ReadFileStream(input, filename, streamList); return streamList; } catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file { - throw FileError(_("Error reading from synchronization database:") + " (bad_alloc)"); + throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)"); } } @@ -224,12 +224,12 @@ DirInfoPtr parseStream(const std::vector<char>& stream, const Zstring& fileName) //read streams into DirInfo auto dirInfo = std::make_shared<DirInformation>(); wxMemoryInputStream buffer(&stream[0], stream.size()); //convert char-array to inputstream: no copying, ownership not transferred - ReadDirInfo(buffer, toWx(fileName), *dirInfo); //throw FileError + ReadDirInfo(buffer, fileName, *dirInfo); //throw FileError return dirInfo; } catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file { - throw FileError(_("Error reading from synchronization database:") + " (bad_alloc)"); + throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)"); } } } @@ -262,10 +262,10 @@ std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMa streamRight == streamListRight.end() || !streamLeft ->second.get() || !streamRight->second.get()) - throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + " \n\n" + - _("Database files do not share a common synchronization session:") + " \n" + - "\"" + fileNameLeft + "\"\n" + - "\"" + fileNameRight + "\""); + throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" + + _("Database files do not share a common synchronization session:") + L" \n" + + L"\"" + fileNameLeft + L"\"\n" + + L"\"" + fileNameRight + L"\""); //read streams into DirInfo DirInfoPtr dirInfoLeft = parseStream(*streamLeft ->second, fileNameLeft); //throw FileError DirInfoPtr dirInfoRight = parseStream(*streamRight->second, fileNameRight); //throw FileError @@ -279,7 +279,7 @@ template <SelectedSide side> class SaveDirInfo : public WriteOutputStream { public: - SaveDirInfo(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const wxString& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream) + SaveDirInfo(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream) { //save filter settings baseMapping.getFilter()->saveFilter(getStream()); @@ -422,7 +422,7 @@ private: class WriteFileStream : public WriteOutputStream { public: - WriteFileStream(const StreamMapping& streamList, const wxString& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) + WriteFileStream(const StreamMapping& streamList, const Zstring& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) { //save file format version writeNumberC<std::int32_t>(FILE_FORMAT_VER); @@ -456,7 +456,7 @@ void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw 6 1,77 MB - 613 ms 9 (maximal compression) 1,74 MB - 3330 ms */ - WriteFileStream(streamList, toWx(filename), output); + WriteFileStream(streamList, filename, output); } //(try to) hide database file #ifdef FFS_WIN @@ -542,7 +542,7 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError { wxMemoryOutputStream buffer; const DirContainer* oldDir = oldDirInfoLeft.get() ? &oldDirInfoLeft->baseDirContainer : NULL; - SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, toWx(dbNameLeft), buffer); + SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, dbNameLeft, buffer); newStreamLeft->resize(buffer.GetSize()); //convert output stream to char-array buffer.CopyTo(&(*newStreamLeft)[0], buffer.GetSize()); // } @@ -551,7 +551,7 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError { wxMemoryOutputStream buffer; const DirContainer* oldDir = oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL; - SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, toWx(dbNameRight), buffer); + SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, dbNameRight, buffer); newStreamRight->resize(buffer.GetSize()); //convert output stream to char-array buffer.CopyTo(&(*newStreamRight)[0], buffer.GetSize()); // } diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp index 29c7ffc6..735fd7b6 100644 --- a/lib/dir_lock.cpp +++ b/lib/dir_lock.cpp @@ -5,7 +5,6 @@ #include <wx/log.h> #include <wx/msgdlg.h> #include <memory> -#include <boost/weak_ptr.hpp> #include <wx+/string_conv.h> #include <zen/last_error.h> #include <zen/thread.h> //includes <boost/thread.hpp> @@ -63,7 +62,7 @@ public: } catch (const std::exception& e) //exceptions must be catched per thread { - wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Dirlock)"), wxString::FromAscii(e.what())); //simple wxMessageBox won't do for threads + wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Dirlock)"), utf8CvrtTo<wxString>(e.what())); //simple wxMessageBox won't do for threads } } @@ -127,7 +126,7 @@ UInt64 getLockFileSize(const Zstring& filename) //throw FileError, ErrorNotExist { const DWORD lastError = ::GetLastError(); - std::wstring errorMessage = _("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error reading file attributes:") + L"\n\"" + filename + L"\"" + L"\n\n" + getLastErrorFormatted(lastError); if (lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_PATH_NOT_FOUND || @@ -148,7 +147,7 @@ UInt64 getLockFileSize(const Zstring& filename) //throw FileError, ErrorNotExist { const int lastError = errno; - std::wstring errorMessage = _("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error reading file attributes:") + L"\n\"" + filename + L"\"" + L"\n\n" + getLastErrorFormatted(lastError); if (lastError == ENOENT) throw ErrorNotExisting(errorMessage); @@ -201,9 +200,9 @@ std::string getComputerId() //returns empty string on error const wxString fhn = ::wxGetFullHostName(); if (fhn.empty()) return std::string(); #ifdef FFS_WIN - return "Windows " + std::string(fhn.ToUTF8()); + return "Windows " + utf8CvrtTo<std::string>(fhn); #elif defined FFS_LINUX - return "Linux " + std::string(fhn.ToUTF8()); + return "Linux " + utf8CvrtTo<std::string>(fhn); #endif } @@ -342,7 +341,7 @@ std::string retrieveLockId(const Zstring& lockfilename) //throw FileError, Error void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //throw FileError { std::wstring infoMsg = _("Waiting while directory is locked (%x)..."); - replace(infoMsg, L"%x", std::wstring(L"\"") + lockfilename + "\""); + replace(infoMsg, L"%x", std::wstring(L"\"") + lockfilename + L"\""); if (callback) callback->reportInfo(infoMsg); //--------------------------------------------------------------- @@ -411,7 +410,7 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr std::wstring remSecMsg = _P("1 sec", "%x sec", remainingSeconds); replace(remSecMsg, L"%x", toString<std::wstring>(remainingSeconds)); - callback->reportInfo(infoMsg + " " + remSecMsg); + callback->reportInfo(infoMsg + L" " + remSecMsg); } else callback->reportInfo(infoMsg); //emit a message in any case (might clear other one) @@ -455,7 +454,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError if (::GetLastError() == ERROR_FILE_EXISTS) return false; else - throw FileError(_("Error setting directory lock:") + "\n\"" + lockfilename + "\"" + "\n\n" + getLastErrorFormatted()); + throw FileError(_("Error setting directory lock:") + L"\n\"" + lockfilename + L"\"" + L"\n\n" + getLastErrorFormatted()); } ::CloseHandle(fileHandle); @@ -468,7 +467,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError if (errno == EEXIST) return false; else - throw FileError(_("Error setting directory lock:") + "\n\"" + lockfilename + "\"" + "\n\n" + getLastErrorFormatted()); + throw FileError(_("Error setting directory lock:") + L"\n\"" + lockfilename + L"\"" + L"\n\n" + getLastErrorFormatted()); } ::close(fileHandle); #endif @@ -566,8 +565,7 @@ private: { UuidToLockMap::const_iterator iterLock = uuidToLock.find(lockId); return iterLock != uuidToLock.end() ? - iterLock->second.lock() : //try to get shared_ptr; throw() - std::shared_ptr<SharedDirLock>(); + iterLock->second.lock() : nullptr; //try to get shared_ptr; throw() } typedef std::weak_ptr<SharedDirLock> SharedLock; diff --git a/lib/dir_name.cpp b/lib/dir_name.cpp index 010fb218..71a3e9ef 100644 --- a/lib/dir_name.cpp +++ b/lib/dir_name.cpp @@ -124,7 +124,7 @@ void DirectoryName<NameControl>::OnFilesDropped(FFSFileDropEvent& event) setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_); else { - wxString parentName = beforeLast(fileName, FILE_NAME_SEPARATOR); //returns empty string if ch not found + wxString parentName = beforeLast(fileName, utf8CvrtTo<wxString>(FILE_NAME_SEPARATOR)); //returns empty string if ch not found #ifdef FFS_WIN if (endsWith(parentName, L":")) //volume name parentName += FILE_NAME_SEPARATOR; diff --git a/lib/error_log.cpp b/lib/error_log.cpp index fe423479..67584dea 100644 --- a/lib/error_log.cpp +++ b/lib/error_log.cpp @@ -5,7 +5,7 @@ // ************************************************************************** #include "error_log.h" -#include <wx/datetime.h> +#include <zen/time.h> #include <zen/i18n.h> #include <algorithm> @@ -16,7 +16,7 @@ void ErrorLogging::logMsg(const wxString& message, zen::MessageType type) { Entry newEntry; newEntry.type = type; - newEntry.time = wxDateTime::GetTimeNow(); + newEntry.time = std::time(NULL); newEntry.message = message; messages.push_back(newEntry); @@ -76,11 +76,11 @@ wxString ErrorLogging::formatMessage(const Entry& msg) break; } - const wxString prefix = wxString(L"[") + wxDateTime(msg.time).FormatTime() + L"] " + typeName + L": "; + const wxString prefix = L"[" + formatTime<wxString>(FORMAT_TIME, localTime(msg.time)) + L"] " + typeName + L": "; wxString formattedText = prefix; - for (auto i = msg.message.begin(); i != msg.message.end(); ++i) - if (*i == wxChar('\n')) + for (auto iter = msg.message.begin(); iter != msg.message.end(); ) + if (*iter == L'\n') { formattedText += L'\n'; @@ -88,12 +88,14 @@ wxString ErrorLogging::formatMessage(const Entry& msg) blanks.resize(prefix.size(), L' '); formattedText += blanks; - while (*++i == L'\n') //remove duplicate newlines - ; - --i; + do //remove duplicate newlines + { + ++iter; + } + while (iter != msg.message.end() && *iter == L'\n'); } else - formattedText += *i; + formattedText += *iter++; return formattedText; } diff --git a/lib/ffs_paths.h b/lib/ffs_paths.h index faecd2e2..0ad02b15 100644 --- a/lib/ffs_paths.h +++ b/lib/ffs_paths.h @@ -9,6 +9,7 @@ #include <wx/stdpaths.h> #include <zen/zstring.h> +#include <zen/file_handling.h> #include <wx+/string_conv.h> namespace zen @@ -16,11 +17,11 @@ namespace zen //------------------------------------------------------------------------------ //global program directories //------------------------------------------------------------------------------ -wxString getResourceDir(); //resource directory WITH path separator at end -wxString getConfigDir(); //config directory WITH path separator at end +Zstring getResourceDir(); //resource directory WITH path separator at end +Zstring getConfigDir(); //config directory WITH path separator at end //------------------------------------------------------------------------------ -wxString getLauncher(); //full path to application launcher C:\...\FreeFileSync.exe +Zstring getLauncher(); //full path to application launcher C:\...\FreeFileSync.exe bool isPortableVersion(); @@ -34,21 +35,22 @@ bool isPortableVersion(); + //---------------- implementation ---------------- namespace impl { inline -const wxString& getBinaryDir() //directory containing executable WITH path separator at end +const Zstring& getBinaryDir() //directory containing executable WITH path separator at end { - static wxString instance = beforeLast(wxStandardPaths::Get().GetExecutablePath(), FILE_NAME_SEPARATOR) + toWx(Zstring(FILE_NAME_SEPARATOR)); //extern linkage! + static Zstring instance = beforeLast(toZ(wxStandardPaths::Get().GetExecutablePath()), FILE_NAME_SEPARATOR) + Zstring(FILE_NAME_SEPARATOR); //extern linkage! return instance; } #ifdef FFS_WIN inline -wxString getInstallDir() //root install directory WITH path separator at end +Zstring getInstallDir() //root install directory WITH path separator at end { - return getBinaryDir().BeforeLast(FILE_NAME_SEPARATOR).BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR; + return beforeLast(beforeLast(getBinaryDir(), FILE_NAME_SEPARATOR), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR; } #endif } @@ -58,25 +60,27 @@ inline bool isPortableVersion() { #ifdef FFS_WIN - static const bool isPortable = !wxFileExists(impl::getInstallDir() + wxT("uninstall.exe")); //this check is a bit lame... + static const bool isPortable = !fileExists(impl::getInstallDir() + L"uninstall.exe"); //this check is a bit lame... + #elif defined FFS_LINUX - static const bool isPortable = !impl::getBinaryDir().EndsWith(wxT("/bin/")); //this check is a bit lame... + static const bool isPortable = !endsWith(impl::getBinaryDir(), "/bin/"); //this check is a bit lame... #endif return isPortable; } inline -wxString getResourceDir() +Zstring getResourceDir() { #ifdef FFS_WIN return impl::getInstallDir(); + #elif defined FFS_LINUX if (isPortableVersion()) return impl::getBinaryDir(); else //use OS' standard paths { - wxString resourceDir = wxStandardPathsBase::Get().GetResourcesDir(); + Zstring resourceDir = toZ(wxStandardPathsBase::Get().GetResourcesDir()); if (!endsWith(resourceDir, FILE_NAME_SEPARATOR)) resourceDir += FILE_NAME_SEPARATOR; @@ -88,7 +92,7 @@ wxString getResourceDir() inline -wxString getConfigDir() +Zstring getConfigDir() { if (isPortableVersion()) #ifdef FFS_WIN @@ -100,10 +104,14 @@ wxString getConfigDir() #endif else //use OS' standard paths { - wxString userDirectory = wxStandardPathsBase::Get().GetUserDataDir(); + Zstring userDirectory = toZ(wxStandardPathsBase::Get().GetUserDataDir()); - if (!wxDirExists(userDirectory)) - ::wxMkdir(userDirectory); //only top directory needs to be created: no recursion necessary + if (!dirExists(userDirectory)) + try + { + createDirectory(userDirectory); //only top directory needs to be created: no recursion necessary + } + catch (const FileError&) {} if (!endsWith(userDirectory, FILE_NAME_SEPARATOR)) userDirectory += FILE_NAME_SEPARATOR; @@ -114,12 +122,12 @@ wxString getConfigDir() inline -wxString getLauncher() +Zstring getLauncher() { #ifdef FFS_WIN - return impl::getInstallDir() + wxT("FreeFileSync.exe"); + return impl::getInstallDir() + Zstr("FreeFileSync.exe"); #elif defined FFS_LINUX - return impl::getBinaryDir() + wxT("FreeFileSync"); + return impl::getBinaryDir() + Zstr("FreeFileSync"); #endif } } diff --git a/lib/help_provider.h b/lib/help_provider.h index 9baf9303..094084b2 100644 --- a/lib/help_provider.h +++ b/lib/help_provider.h @@ -35,7 +35,7 @@ wxHelpController& getHelpCtrl() if (!initialized) { initialized = true; - controller.Initialize(zen::getResourceDir() + + controller.Initialize(toWx(zen::getResourceDir()) + #ifdef FFS_WIN L"FreeFileSync.chm"); #elif defined FFS_LINUX diff --git a/lib/icon_buffer.cpp b/lib/icon_buffer.cpp index bb75a538..4e05e642 100644 --- a/lib/icon_buffer.cpp +++ b/lib/icon_buffer.cpp @@ -12,7 +12,6 @@ #include <boost/thread/once.hpp> #ifdef FFS_WIN -#include <zen/win.h> //includes "windows.h" #include <zen/dll.h> #include "Thumbnail/thumbnail.h" #include <zen/win_ver.h> @@ -26,22 +25,24 @@ using namespace zen; +namespace +{ const size_t BUFFER_SIZE_MAX = 800; //maximum number of icons to buffer -int zen::IconBuffer::cvrtSize(IconSize sz) //get size in pixel +int cvrtSize(IconBuffer::IconSize sz) //get size in pixel { switch (sz) { - case SIZE_SMALL: + case IconBuffer::SIZE_SMALL: #ifdef FFS_WIN return 16; #elif defined FFS_LINUX return 24; #endif - case SIZE_MEDIUM: + case IconBuffer::SIZE_MEDIUM: return 48; - case SIZE_LARGE: + case IconBuffer::SIZE_LARGE: return 128; } assert(false); @@ -69,9 +70,11 @@ public: #endif ) {} - IconHolder& operator=(const IconHolder& other) + IconHolder(IconHolder&& other) : handle_(other.handle_) { other.handle_ = NULL; } + + IconHolder& operator=(IconHolder other) //unifying assignment: no need for r-value reference optimization! { - IconHolder(other).swap(*this); + other.swap(*this); return *this; } @@ -112,7 +115,7 @@ public: &bmpInfo) != 0) // __out LPVOID lpvObject { const int maxExtent = std::max(bmpInfo.bmWidth, bmpInfo.bmHeight); - if (maxExtent > expectedSize) + if (0 < expectedSize && expectedSize < maxExtent) { bmpInfo.bmWidth = bmpInfo.bmWidth * expectedSize / maxExtent; //scale those Vista jumbo 256x256 icons down! bmpInfo.bmHeight = bmpInfo.bmHeight * expectedSize / maxExtent; // @@ -142,8 +145,6 @@ public: #ifdef FFS_WIN -namespace -{ Zstring getFileExtension(const Zstring& filename) { const Zstring shortName = afterLast(filename, Zchar('\\')); //warning: using windows file name separator! @@ -175,17 +176,11 @@ bool isCheapExtension(const Zstring& extension) } -bool wereVistaOrLater = false; -boost::once_flag initVistaFlagOnce = BOOST_ONCE_INIT; +const bool wereVistaOrLater = vistaOrLater(); //thread-safety: init at startup int getShilIconType(IconBuffer::IconSize sz) { - boost::call_once(initVistaFlagOnce, []() - { - wereVistaOrLater = vistaOrLater(); - }); - switch (sz) { case IconBuffer::SIZE_SMALL: @@ -234,8 +229,8 @@ IconHolder getAssociatedIconByExt(const Zstring& extension, IconBuffer::IconSize DllFun<thumb::GetThumbnailFct> getThumbnailIcon; boost::once_flag initThumbnailOnce = BOOST_ONCE_INIT; -} #endif +} //################################################################################################################################################ @@ -265,6 +260,51 @@ IconHolder getThumbnail(const Zstring& filename, int requestedSize) //return 0 o } +const char* mimeFileIcons[] = +{ + "application-x-zerosize", //Kubuntu: /usr/share/icons/oxygen/48x48/mimetypes + "empty", // + "gtk-file", //Ubuntu: /usr/share/icons/Humanity/mimes/48 + "gnome-fs-regular", // +}; + + +IconHolder getGenericFileIcon(IconBuffer::IconSize sz) +{ +#ifdef FFS_WIN + return getIconByAttribute(L"dummy", FILE_ATTRIBUTE_NORMAL, sz); + +#elif defined FFS_LINUX + const int requestedSize = cvrtSize(sz); + try + { + Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default(); + if (iconTheme) + { + Glib::RefPtr<Gdk::Pixbuf> iconPixbuf; + std::find_if(mimeFileIcons, mimeFileIcons + sizeof(mimeFileIcons) / sizeof(mimeFileIcons[0]), + [&](const char* mimeName) -> bool + { + try + { + iconPixbuf = iconTheme->load_icon(mimeName, requestedSize, Gtk::ICON_LOOKUP_USE_BUILTIN); + } + catch (const Glib::Error&) { return false; } + + return iconPixbuf; + } + ); + if (iconPixbuf) + return IconHolder(iconPixbuf->gobj_copy()); // transfer ownership!! + } + } + catch (const Glib::Error&) {} + + return IconHolder(); +#endif +} + + IconHolder getAssociatedIcon(const Zstring& filename, IconBuffer::IconSize sz) { //1. try to load thumbnails @@ -275,7 +315,7 @@ IconHolder getAssociatedIcon(const Zstring& filename, IconBuffer::IconSize sz) case IconBuffer::SIZE_MEDIUM: case IconBuffer::SIZE_LARGE: { - IconHolder ico = getThumbnail(filename, IconBuffer::cvrtSize(sz)); + IconHolder ico = getThumbnail(filename, cvrtSize(sz)); if (ico) return ico; //else: fallback to non-thumbnail icon @@ -314,7 +354,7 @@ IconHolder getAssociatedIcon(const Zstring& filename, IconBuffer::IconSize sz) return getIconByIndex ? static_cast<HICON>(getIconByIndex(fileInfo.iIcon, getShilIconType(sz))) : NULL; #elif defined FFS_LINUX - const int requestedSize = IconBuffer::cvrtSize(sz); + const int requestedSize = cvrtSize(sz); //call Gtk::Main::init_gtkmm_internals() on application startup!! try { @@ -341,27 +381,23 @@ IconHolder getAssociatedIcon(const Zstring& filename, IconBuffer::IconSize sz) } catch (const Glib::Error&) {} - try //fallback: icon lookup may fail because some icons are currently not present on system - { - Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default(); - if (iconTheme) - { - Glib::RefPtr<Gdk::Pixbuf> iconPixbuf = iconTheme->load_icon("misc", requestedSize, Gtk::ICON_LOOKUP_USE_BUILTIN); - if (!iconPixbuf) - iconPixbuf = iconTheme->load_icon("text-x-generic", requestedSize, Gtk::ICON_LOOKUP_USE_BUILTIN); - if (iconPixbuf) - return IconHolder(iconPixbuf->gobj_copy()); //copy and pass icon ownership (may be 0) - } - } - catch (const Glib::Error&) {} - - //fallback fallback - return IconHolder(); + //fallback: icon lookup may fail because some icons are currently not present on system + return ::getGenericFileIcon(sz); #endif } +/* Dependency Diagram: -IconHolder getDirectoryIcon(IconBuffer::IconSize sz) +getGenericFileIcon() + /|\ + | +getAssociatedIcon() + /|\ + | +getGenericDirectoryIcon() +*/ + +IconHolder getGenericDirectoryIcon(IconBuffer::IconSize sz) { #ifdef FFS_WIN return getIconByAttribute(L"dummy", //Windows 7 doesn't like this parameter to be an empty string! @@ -372,29 +408,6 @@ IconHolder getDirectoryIcon(IconBuffer::IconSize sz) } -IconHolder getFileIcon(IconBuffer::IconSize sz) -{ -#ifdef FFS_WIN - return getIconByAttribute(L"dummy", FILE_ATTRIBUTE_NORMAL, sz); -#elif defined FFS_LINUX - const int requestedSize = IconBuffer::cvrtSize(sz); - try - { - Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default(); - if (iconTheme) - { - Glib::RefPtr<Gdk::Pixbuf> iconPixbuf = iconTheme->load_icon("misc", requestedSize, Gtk::ICON_LOOKUP_USE_BUILTIN); - if (!iconPixbuf) - iconPixbuf = iconTheme->load_icon("text-x-generic", requestedSize, Gtk::ICON_LOOKUP_USE_BUILTIN); - if (iconPixbuf) - return IconHolder(iconPixbuf->gobj_copy()); // transfer ownership!! - } - } - catch (const Glib::Error&) {} - - return IconHolder(); -#endif -} //################################################################################################################################################ @@ -546,8 +559,8 @@ struct IconBuffer::Pimpl IconBuffer::IconBuffer(IconSize sz) : pimpl(new Pimpl), icoSize(sz), - genDirIcon(::getDirectoryIcon(sz).toWxIcon(cvrtSize(icoSize))), - genFileIcon(::getFileIcon(sz).toWxIcon(cvrtSize(icoSize))) + genDirIcon(::getGenericDirectoryIcon(sz).toWxIcon(cvrtSize(icoSize))), + genFileIcon(::getGenericFileIcon(sz).toWxIcon(cvrtSize(icoSize))) { pimpl->worker = boost::thread(WorkerThread(pimpl->workload, pimpl->buffer, sz)); } @@ -561,6 +574,12 @@ IconBuffer::~IconBuffer() } +int IconBuffer::getSize() const +{ + return cvrtSize(icoSize); +} + + bool IconBuffer::requestFileIcon(const Zstring& filename, wxIcon* icon) { auto getIcon = [&](const Zstring& entryName) -> bool diff --git a/lib/icon_buffer.h b/lib/icon_buffer.h index be8a02d8..a13ad3cd 100644 --- a/lib/icon_buffer.h +++ b/lib/icon_buffer.h @@ -27,16 +27,14 @@ public: IconBuffer(IconSize sz); ~IconBuffer(); - int getSize() const { return cvrtSize(icoSize); } //*maximum* icon size in pixel - - const wxIcon& genericDirIcon () { return genDirIcon; } const wxIcon& genericFileIcon() { return genFileIcon; } + const wxIcon& genericDirIcon () { return genDirIcon; } + + int getSize() const; //*maximum* icon size in pixel bool requestFileIcon(const Zstring& filename, wxIcon* icon = NULL); //returns false if icon is not in buffer void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved; - static int cvrtSize(IconSize sz); - private: struct Pimpl; std::unique_ptr<Pimpl> pimpl; diff --git a/lib/localization.cpp b/lib/localization.cpp index 774ee9ec..e8ff6040 100644 --- a/lib/localization.cpp +++ b/lib/localization.cpp @@ -132,7 +132,7 @@ public: } virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) {} - virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName) { return Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); } + virtual std::shared_ptr<TraverseCallback> onDir(const Zchar* shortName, const Zstring& fullName) { return nullptr; } virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } //errors are not really critical in this context private: @@ -180,7 +180,7 @@ ExistingTranslations::ExistingTranslations() std::vector<Zstring> lngFiles; FindLngfiles traverseCallback(lngFiles); - traverseFolder(toZ(zen::getResourceDir() + wxT("Languages")), //throw(); + traverseFolder(zen::getResourceDir() + Zstr("Languages"), //throw(); false, //don't follow symlinks traverseCallback); @@ -193,6 +193,10 @@ ExistingTranslations::ExistingTranslations() lngfile::TransHeader lngHeader; lngfile::parseHeader(stream, lngHeader); //throw ParsingError + /* + There is some buggy behavior in wxWidgets which maps "zh_TW" to simplified chinese. + Fortunately locales can be also entered as description. I changed to "Chinese (Traditional)" which works fine. + */ const wxLanguageInfo* locInfo = wxLocale::FindLanguageInfo(utf8CvrtTo<wxString>(lngHeader.localeName)); if (locInfo) { @@ -374,10 +378,11 @@ void zen::setLanguage(int language) { //(try to) retrieve language file wxString languageFile; - for (std::vector<ExistingTranslations::Entry>::const_iterator i = ExistingTranslations::get().begin(); i != ExistingTranslations::get().end(); ++i) - if (i->languageID == language) + + for (auto iter = ExistingTranslations::get().begin(); iter != ExistingTranslations::get().end(); ++iter) + if (iter->languageID == language) { - languageFile = i->languageFile; + languageFile = iter->languageFile; break; } diff --git a/lib/lock_holder.h b/lib/lock_holder.h index a7cf3436..d94b0fd6 100644 --- a/lib/lock_holder.h +++ b/lib/lock_holder.h @@ -45,7 +45,7 @@ public: catch (const FileError& e) { bool dummy = false; //this warning shall not be shown but logged only - procCallback.reportWarning(e.msg(), dummy); //may throw! + procCallback.reportWarning(e.toString(), dummy); //may throw! } } diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp index 29d87ee7..96b167b8 100644 --- a/lib/parallel_scan.cpp +++ b/lib/parallel_scan.cpp @@ -171,7 +171,7 @@ std::vector<std::set<DirectoryKey>> separateByDistinctDisk(const std::set<Direct typedef Zbase<wchar_t, StorageRefCountThreadSafe> BasicWString; //thread safe string class for UI texts -class AsyncCallback +class AsyncCallback //actor pattern { public: AsyncCallback() : @@ -207,7 +207,7 @@ public: boost::lock_guard<boost::mutex> dummy(lockErrorMsg); if (!errorMsg.empty() && !errorResponse.get()) { - FillBufferCallback::HandleError rv = callback.reportError(cvrtString<std::wstring>(errorMsg)); //throw! + FillBufferCallback::HandleError rv = callback.reportError(copyStringTo<std::wstring>(errorMsg)); //throw! errorResponse.reset(new FillBufferCallback::HandleError(rv)); //dummy.unlock(); @@ -244,12 +244,12 @@ public: if (!currentFile.empty()) filename = utf8CvrtTo<std::wstring>(currentFile); else if (!currentStatus.empty()) - statusMsg = cvrtString<std::wstring>(currentStatus); + statusMsg = copyStringTo<std::wstring>(currentStatus); } if (!filename.empty()) { - std::wstring statusText = cvrtString<std::wstring>(textScanning); + std::wstring statusText = copyStringTo<std::wstring>(textScanning); const long activeCount = activeWorker; if (activeCount >= 2) { @@ -293,8 +293,6 @@ private: }; //------------------------------------------------------------------------------------------------- -class DirCallback; - struct TraverserShared { public: @@ -309,9 +307,6 @@ public: acb_(acb), threadID_(threadID) {} - typedef std::shared_ptr<DirCallback> CallbackPointer; - std::vector<CallbackPointer> callBackBox; //collection of callback pointers to handle ownership - const SymLinkHandling handleSymlinks_; const HardFilter::FilterRef filterInstance; //always bound! @@ -332,10 +327,11 @@ public: relNameParentPf_(relNameParentPf), output_(output) {} - virtual void onFile (const Zchar* shortName, const Zstring& fullName, const FileInfo& details); - virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details); - virtual ReturnValDir onDir (const Zchar* shortName, const Zstring& fullName); - virtual HandleError onError (const std::wstring& errorText); + virtual std::shared_ptr<TraverseCallback> + onDir (const Zchar* shortName, const Zstring& fullName); + virtual void onFile (const Zchar* shortName, const Zstring& fullName, const FileInfo& details); + virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details); + virtual HandleError onError (const std::wstring& errorText); private: TraverserShared& cfg; @@ -405,7 +401,7 @@ void DirCallback::onSymlink(const Zchar* shortName, const Zstring& fullName, con } -TraverseCallback::ReturnValDir DirCallback::onDir(const Zchar* shortName, const Zstring& fullName) +std::shared_ptr<TraverseCallback> DirCallback::onDir(const Zchar* shortName, const Zstring& fullName) { boost::this_thread::interruption_point(); @@ -419,16 +415,14 @@ TraverseCallback::ReturnValDir DirCallback::onDir(const Zchar* shortName, const bool subObjMightMatch = true; const bool passFilter = cfg.filterInstance->passDirFilter(relName, &subObjMightMatch); if (!passFilter && !subObjMightMatch) - return Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //do NOT traverse subdirs + return nullptr; //do NOT traverse subdirs //else: attention! ensure directory filtering is applied later to exclude actually filtered directories DirContainer& subDir = output_.addSubDir(shortName); if (passFilter) cfg.acb_.incItemsScanned(); //add 1 element to the progress indicator - TraverserShared::CallbackPointer subDirCallback = std::make_shared<DirCallback>(cfg, relName + FILE_NAME_SEPARATOR, subDir); - cfg.callBackBox.push_back(subDirCallback); //handle lifetime - return ReturnValDir(Int2Type<ReturnValDir::TRAVERSING_DIR_CONTINUE>(), *subDirCallback); + return std::make_shared<DirCallback>(cfg, relName + FILE_NAME_SEPARATOR, subDir); } diff --git a/lib/parse_plural.h b/lib/parse_plural.h index 847bec35..960172fa 100644 --- a/lib/parse_plural.h +++ b/lib/parse_plural.h @@ -112,7 +112,7 @@ struct NumberN : public Expr<int> }; -typedef Zbase<char> Wstring; +typedef zen::Zbase<char> Wstring; class PluralForm diff --git a/lib/process_xml.cpp b/lib/process_xml.cpp index 777c3ed6..78e14ff5 100644 --- a/lib/process_xml.cpp +++ b/lib/process_xml.cpp @@ -74,7 +74,7 @@ void setXmlType(XmlDoc& doc, XmlType type) //throw() wxString xmlAccess::getGlobalConfigFile() { - return zen::getConfigDir() + wxT("GlobalSettings.xml"); + return toWx(zen::getConfigDir()) + wxT("GlobalSettings.xml"); } @@ -810,6 +810,7 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) inShared["CopyFilePermissions" ](config.copyFilePermissions); inShared["TransactionalFileCopy"](config.transactionalFileCopy); inShared["VerifyCopiedFiles" ](config.verifyFileCopy); + inShared["RunWithBackgroundPriority"](config.runWithBackgroundPriority); //max. allowed file time deviation inShared["FileTimeTolerance"](config.fileTimeTolerance); @@ -888,13 +889,13 @@ void readConfig(const Zstring& filename, XmlType type, ConfigType& config) loadXmlDocument(filename, doc); //throw FfsXmlError if (getXmlType(doc) != type) //throw() - throw FfsXmlError(_("Error parsing configuration file:") + "\n\"" + filename + "\""); + throw FfsXmlError(_("Error parsing configuration file:") + L"\n\"" + filename + L"\""); XmlIn in(doc); ::readConfig(in, config); if (in.errorsOccured()) - throw FfsXmlError(_("Error parsing configuration file:") + "\n\"" + filename + "\"\n\n" + + throw FfsXmlError(_("Error parsing configuration file:") + L"\n\"" + filename + L"\"\n\n" + getErrorMessageFormatted(in), FfsXmlError::WARNING); } } @@ -1067,6 +1068,7 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out) outShared["CopyFilePermissions" ](config.copyFilePermissions); outShared["TransactionalFileCopy"](config.transactionalFileCopy); outShared["VerifyCopiedFiles" ](config.verifyFileCopy); + outShared["RunWithBackgroundPriority"](config.runWithBackgroundPriority); //max. allowed file time deviation outShared["FileTimeTolerance"](config.fileTimeTolerance); diff --git a/lib/process_xml.h b/lib/process_xml.h index 5f1dfb93..7f8b273b 100644 --- a/lib/process_xml.h +++ b/lib/process_xml.h @@ -142,6 +142,7 @@ struct XmlGlobalSettings programLanguage(zen::retrieveSystemLanguage()), copyLockedFiles(true), copyFilePermissions(false), + runWithBackgroundPriority(false), fileTimeTolerance(2), //default 2s: FAT vs NTFS verifyFileCopy(false), transactionalFileCopy(true) {} @@ -150,6 +151,8 @@ struct XmlGlobalSettings bool copyLockedFiles; //VSS usage bool copyFilePermissions; + bool runWithBackgroundPriority; + size_t fileTimeTolerance; //max. allowed file time deviation bool verifyFileCopy; //verify copied files bool transactionalFileCopy; @@ -174,7 +177,7 @@ struct XmlGlobalSettings #elif defined FFS_LINUX textSearchRespectCase(true), #endif - iconSize(ICON_SIZE_MEDIUM), + iconSize(ICON_SIZE_SMALL), lastUpdateCheck(0) { //default external apps will be translated "on the fly"!!! diff --git a/lib/recycler.cpp b/lib/recycler.cpp index 30083701..abe63a3e 100644 --- a/lib/recycler.cpp +++ b/lib/recycler.cpp @@ -65,8 +65,8 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw F const DllFun<GetLastErrorFct> getLastError (getDllName(), getLastErrorFctName); if (!moveToRecycler || !getLastError) - throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileNames[0] + "\"" + //report first file only... better than nothing - "\n\n" + _("Could not load a required DLL:") + " \"" + getDllName() + "\""); + throw FileError(_("Error moving to Recycle Bin:") + L"\n\"" + fileNames[0] + L"\"" + //report first file only... better than nothing + L"\n\n" + _("Could not load a required DLL:") + L" \"" + getDllName() + L"\""); //#warning moving long file paths to recycler does not work! clarify! // std::vector<Zstring> temp; @@ -78,8 +78,8 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw F { wchar_t errorMessage[2000]; getLastError(errorMessage, 2000); - throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileNames[0] + "\"" + //report first file only... better than nothing - "\n\n" + "(" + errorMessage + ")"); + throw FileError(_("Error moving to Recycle Bin:") + L"\n\"" + fileNames[0] + L"\"" + //report first file only... better than nothing + L"\n\n" + L"(" + errorMessage + L")"); } } else //regular recycle bin usage: available since XP @@ -106,7 +106,7 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw F if (::SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted) { - throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filenameDoubleNull + "\""); //report first file only... better than nothing + throw FileError(_("Error moving to Recycle Bin:") + L"\n\"" + filenameDoubleNull + L"\""); //report first file only... better than nothing } } } @@ -132,8 +132,8 @@ bool zen::moveToRecycleBin(const Zstring& filename) //throw FileError try { if (!fileObj->trash()) - throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filename + "\"" + - "\n\n" + "(unknown error)"); + throw FileError(_("Error moving to Recycle Bin:") + L"\n\"" + filename + L"\"" + + L"\n\n" + L"(unknown error)"); } catch (const Glib::Error& errorObj) { @@ -152,11 +152,11 @@ bool zen::moveToRecycleBin(const Zstring& filename) //throw FileError } //assemble error message - const std::wstring errorMessage = L"Glib Error Code " + toString<std::wstring>(errorObj.code()) + /* ", " + - g_quark_to_string(errorObj.domain()) + */ ": " + errorObj.what(); + const std::wstring errorMessage = L"Glib Error Code " + toString<std::wstring>(errorObj.code()) + /* L", " + + g_quark_to_string(errorObj.domain()) + */ L": " + utf8CvrtTo<std::wstring>(errorObj.what()); - throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filename + "\"" + - "\n\n" + "(" + errorMessage + ")"); + throw FileError(_("Error moving to Recycle Bin:") + L"\n\"" + filename + L"\"" + + L"\n\n" + L"(" + errorMessage + L")"); } #endif return true; diff --git a/lib/resolve_path.cpp b/lib/resolve_path.cpp index 14ad690e..feeb98e3 100644 --- a/lib/resolve_path.cpp +++ b/lib/resolve_path.cpp @@ -1,6 +1,6 @@ #include "resolve_path.h" #include <wx/utils.h> -#include <wx/datetime.h> +#include <zen/time.h> #include <wx+/string_conv.h> #include <map> #include <set> @@ -178,14 +178,13 @@ bool replaceMacro(wxString& macro) //macro without %-characters, return true if //there are equally named environment variables %TIME%, %DATE% existing, so replace these first! if (macro.CmpNoCase(wxT("time")) == 0) { - macro = wxDateTime::Now().FormatISOTime(); - macro.Replace(wxT(":"), wxT("")); + macro = formatTime<wxString>(L"%H%M%S"); return true; } if (macro.CmpNoCase(wxT("date")) == 0) { - macro = wxDateTime::Now().FormatISODate(); + macro = formatTime<wxString>(FORMAT_ISO_DATE); return true; } @@ -193,7 +192,8 @@ bool replaceMacro(wxString& macro) //macro without %-characters, return true if { if (macro.CmpNoCase(phrase) != 0) return false; - macro = wxDateTime::Now().Format(format); + + macro = formatTime<wxString>(format); return true; }; @@ -272,10 +272,10 @@ public: virtual void onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details) {} virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) {} - virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName) + virtual std::shared_ptr<TraverseCallback> onDir(const Zchar* shortName, const Zstring& fullName) { devices_.insert(std::make_pair(shortName, fullName)); - return Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //DON'T traverse into subdirs + return nullptr; //DON'T traverse into subdirs } virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } @@ -379,18 +379,20 @@ void expandVolumeName(Zstring& text) // [volname]:\folder [volname]\folde { //this would be a nice job for a C++11 regex... - size_t posStart = text.find(Zstr("[")); - if (posStart != Zstring::npos) + + //we only expect the [.*] pattern at the beginning => do not touch dir names like "C:\somedir\[stuff]" + trim(text, true, false); + + if (startsWith(text, Zstr("["))) { - size_t posEnd = text.find(Zstr("]"), posStart); + size_t posEnd = text.find(Zstr("]")); if (posEnd != Zstring::npos) { - Zstring before = Zstring(text.c_str(), posStart); - Zstring volname = Zstring(text.c_str() + posStart + 1, posEnd - posStart - 1); + Zstring volname = Zstring(text.c_str() + 1, posEnd - 1); Zstring after = Zstring(text.c_str() + posEnd + 1); - if (startsWith(after, ':')) - after = afterFirst(after, ':'); + if (startsWith(after, Zstr(':'))) + after = afterFirst(after, Zstr(':')); if (startsWith(after, FILE_NAME_SEPARATOR)) after = afterFirst(after, FILE_NAME_SEPARATOR); @@ -403,7 +405,7 @@ void expandVolumeName(Zstring& text) // [volname]:\folder [volname]\folde if (!endsWith(volPath, FILE_NAME_SEPARATOR)) volPath += FILE_NAME_SEPARATOR; - text = before + volPath + after; + text = volPath + after; //successfully replaced pattern return; } diff --git a/lib/resources.cpp b/lib/resources.cpp index da407920..01a046b1 100644 --- a/lib/resources.cpp +++ b/lib/resources.cpp @@ -46,7 +46,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation& anim) GlobalResources::GlobalResources() { - wxFFileInputStream input(zen::getResourceDir() + wxT("Resources.zip")); + wxFFileInputStream input(toWx(zen::getResourceDir()) + wxT("Resources.zip")); if (input.IsOk()) //if not... we don't want to react too harsh here { //activate support for .png files diff --git a/lib/shadow.cpp b/lib/shadow.cpp index 73a2e8f7..9bc17aff 100644 --- a/lib/shadow.cpp +++ b/lib/shadow.cpp @@ -44,33 +44,32 @@ public: ShadowVolume(const Zstring& volumeNameFormatted) : //throw(FileError) createShadowCopy (getDllName(), createShadowCopyFctName), releaseShadowCopy(getDllName(), releaseShadowCopyFctName), - backupHandle(0) + getShadowVolume (getDllName(), getShadowVolumeFctName), + backupHandle(nullptr) { //check if shadow copy dll was loaded correctly - if (!createShadowCopy || !releaseShadowCopy) - throw FileError(_("Error accessing Volume Shadow Copy Service!") + "\n" + - _("Could not load a required DLL:") + " \"" + getDllName() + "\""); + if (!createShadowCopy || !releaseShadowCopy || !getShadowVolume) + throw FileError(_("Error accessing Volume Shadow Copy Service!") + L"\n" + + _("Could not load a required DLL:") + L" \"" + getDllName() + L"\""); //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) if (runningWOW64()) - throw FileError(_("Error accessing Volume Shadow Copy Service!") + "\n" + + throw FileError(_("Error accessing Volume Shadow Copy Service!") + L"\n" + _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.")); //--------------------------------------------------------------------------------------------------------- //start shadow volume copy service: - wchar_t shadowVolName[1000]; wchar_t errorMessage[1000]; + backupHandle = createShadowCopy(volumeNameFormatted.c_str(), + errorMessage, + 1000); + if (!backupHandle) + throw FileError(_("Error accessing Volume Shadow Copy Service!") + L"\n" + + L"(" + errorMessage + L" Volume: \"" + volumeNameFormatted + L"\")"); - if (!createShadowCopy(volumeNameFormatted.c_str(), - shadowVolName, - 1000, - &backupHandle, - errorMessage, - 1000)) - throw FileError(_("Error accessing Volume Shadow Copy Service!") + "\n" + - "(" + errorMessage + " Volume: \"" + volumeNameFormatted + "\")"); - + wchar_t shadowVolName[1000]; + getShadowVolume(backupHandle, shadowVolName, 1000); shadowVol = Zstring(shadowVolName) + FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash } @@ -79,7 +78,7 @@ public: releaseShadowCopy(backupHandle); //fast! no performance optimization necessary } - Zstring getShadowVolume() const //trailing path separator + Zstring getShadowVolumeName() const //trailing path separator { return shadowVol; } @@ -90,6 +89,7 @@ private: const DllFun<CreateShadowCopyFct> createShadowCopy; const DllFun<ReleaseShadowCopyFct> releaseShadowCopy; + const DllFun<GetShadowVolumeFct> getShadowVolume; Zstring shadowVol; @@ -105,7 +105,7 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) if (!::GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName, volumeNameRaw, //__out LPTSTR lpszVolumePathName, 1000)) //__in DWORD cchBufferLength - throw FileError(_("Could not determine volume name for file:") + "\n\"" + inputFile + "\""); + throw FileError(_("Could not determine volume name for file:") + L"\n\"" + inputFile + L"\""); Zstring volumeNameFormatted = volumeNameRaw; if (!endsWith(volumeNameFormatted, FILE_NAME_SEPARATOR)) @@ -116,8 +116,8 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) if (pos == Zstring::npos) { std::wstring msg = _("Volume name %x not part of filename %y!"); - replace(msg, L"%x", std::wstring(L"\"") + volumeNameFormatted + "\"", false); - replace(msg, L"%y", std::wstring(L"\"") + inputFile + "\"", false); + replace(msg, L"%x", std::wstring(L"\"") + volumeNameFormatted + L"\"", false); + replace(msg, L"%y", std::wstring(L"\"") + inputFile + L"\"", false); throw FileError(msg); } @@ -130,5 +130,5 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) } //return filename alias on shadow copy volume - return iter->second->getShadowVolume() + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length()); + return iter->second->getShadowVolumeName() + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length()); } diff --git a/lib/statistics.h b/lib/statistics.h index 8f974aae..718e4f19 100644 --- a/lib/statistics.h +++ b/lib/statistics.h @@ -13,11 +13,12 @@ #include <wx/defs.h> #include <wx/string.h> #include <wx/stopwatch.h> +#include <zen/deprecate.h> class RetrieveStatistics { public: - wxDEPRECATED(~RetrieveStatistics()); //generate compiler warnings as a reminder to remove code after measurements + ZEN_DEPRECATE ~RetrieveStatistics(); //remove code after measurements! void writeEntry(double value, int objects); private: diff --git a/lib/xml_base.cpp b/lib/xml_base.cpp index b4887dc0..26176776 100644 --- a/lib/xml_base.cpp +++ b/lib/xml_base.cpp @@ -31,7 +31,7 @@ void xmlAccess::loadXmlDocument(const Zstring& filename, XmlDoc& doc) //throw Ff if (!startsWith(fileBegin, xmlBegin) && !startsWith(fileBegin, zen::BYTE_ORDER_MARK_UTF8 + xmlBegin)) //respect BOM! - throw FfsXmlError(_("Error parsing configuration file:") + "\n\"" + filename + "\""); + throw FfsXmlError(_("Error parsing configuration file:") + L"\n\"" + filename + L"\""); } const zen::UInt64 fs = zen::getFilesize(filename); //throw FileError @@ -40,14 +40,14 @@ void xmlAccess::loadXmlDocument(const Zstring& filename, XmlDoc& doc) //throw Ff FileInput inputFile(filename); //throw FileError const size_t bytesRead = inputFile.read(&stream[0], stream.size()); //throw FileError if (bytesRead < to<size_t>(fs)) - throw FfsXmlError(_("Error reading file:") + "\n\"" + filename + "\""); + throw FfsXmlError(_("Error reading file:") + L"\n\"" + filename + L"\""); } catch (const FileError& error) { if (!fileExists(filename)) - throw FfsXmlError(_("File does not exist:") + "\n\"" + filename+ "\""); + throw FfsXmlError(_("File does not exist:") + L"\n\"" + filename+ L"\""); - throw FfsXmlError(error.msg()); + throw FfsXmlError(error.toString()); } try @@ -56,14 +56,14 @@ void xmlAccess::loadXmlDocument(const Zstring& filename, XmlDoc& doc) //throw Ff } catch (const XmlParsingError&) { - throw FfsXmlError(_("Error parsing configuration file:") + "\n\"" + filename + "\""); + throw FfsXmlError(_("Error parsing configuration file:") + L"\n\"" + filename + L"\""); } } const std::wstring xmlAccess::getErrorMessageFormatted(const XmlIn& in) { - std::wstring errorMessage = _("Could not read values for the following XML nodes:") + "\n"; + std::wstring errorMessage = _("Could not read values for the following XML nodes:") + L"\n"; std::vector<std::wstring> failedNodes = in.getErrorsAs<std::wstring>(); std::for_each(failedNodes.begin(), failedNodes.end(), @@ -98,6 +98,6 @@ void xmlAccess::saveXmlDocument(const zen::XmlDoc& doc, const Zstring& filename) } catch (const FileError& error) //more detailed error messages than with wxWidgets { - throw FfsXmlError(error.msg()); + throw FfsXmlError(error.toString()); } } diff --git a/lib/xml_base.h b/lib/xml_base.h index 4614615e..dc534dc5 100644 --- a/lib/xml_base.h +++ b/lib/xml_base.h @@ -24,9 +24,9 @@ public: FATAL }; - FfsXmlError(const std::wstring& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {} + explicit FfsXmlError(const std::wstring& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {} - const std::wstring& msg() const { return errorMessage; } + const std::wstring& toString() const { return errorMessage; } Severity getSeverity() const { return m_severity; } private: const std::wstring errorMessage; |