summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
Diffstat (limited to 'zen')
-rw-r--r--zen/FindFilePlus/FindFilePlus.vcxproj173
-rw-r--r--zen/FindFilePlus/dll_main.cpp66
-rw-r--r--zen/FindFilePlus/find_file_plus.cpp452
-rw-r--r--zen/FindFilePlus/find_file_plus.h92
-rw-r--r--zen/FindFilePlus/init_dll_binding.h16
-rw-r--r--zen/FindFilePlus/load_dll.cpp23
-rw-r--r--zen/FindFilePlus/load_dll.h45
-rw-r--r--zen/IFileOperation/FileOperation.vcxproj179
-rw-r--r--zen/IFileOperation/file_op.cpp541
-rw-r--r--zen/IFileOperation/file_op.h87
-rw-r--r--zen/base64.h157
-rw-r--r--zen/com_error.h227
-rw-r--r--zen/com_ptr.h120
-rw-r--r--zen/com_util.h121
-rw-r--r--zen/debug_log.h94
-rw-r--r--zen/debug_memory_leaks.cpp30
-rw-r--r--zen/debug_minidump.cpp143
-rw-r--r--zen/debug_minidump.h38
-rw-r--r--zen/file_handling.cpp23
-rw-r--r--zen/file_traverser.cpp4
-rw-r--r--zen/i18n.h2
-rw-r--r--zen/read_txt.cpp99
-rw-r--r--zen/read_txt.h32
-rw-r--r--zen/recycler.cpp14
-rw-r--r--zen/recycler.h4
-rw-r--r--zen/scroll_window_under_cursor.cpp72
-rw-r--r--zen/stl_tools.h2
-rw-r--r--zen/string_base.h2
-rw-r--r--zen/xml_io.cpp88
-rw-r--r--zen/xml_io.h27
30 files changed, 149 insertions, 2824 deletions
diff --git a/zen/FindFilePlus/FindFilePlus.vcxproj b/zen/FindFilePlus/FindFilePlus.vcxproj
deleted file mode 100644
index eb5c672e..00000000
--- a/zen/FindFilePlus/FindFilePlus.vcxproj
+++ /dev/null
@@ -1,173 +0,0 @@
-<?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">
- <ProjectGuid>{814047ED-7701-494D-BBAF-AFEDF43EDC4E}</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>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <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>
- <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName)_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName)_$(Platform)</TargetName>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Data\C++\WinDDK\inc\ddk;C:\Data\C++\WinDDK\inc\api;C:\Data\C++\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Data\C++\WinDDK\inc\ddk;C:\Data\C++\WinDDK\inc\api;C:\Data\C++\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\Data\C++\WinDDK\inc\ddk;C:\Data\C++\WinDDK\inc\api;C:\Data\C++\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Data\C++\WinDDK\inc\ddk;C:\Data\C++\WinDDK\inc\api;C:\Data\C++\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_X86_;_DEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>C:\Data\Projects;</AdditionalIncludeDirectories>
- <SmallerTypeCheck>true</SmallerTypeCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_AMD64_;_DEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>C:\Data\Projects;</AdditionalIncludeDirectories>
- <SmallerTypeCheck>true</SmallerTypeCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <PreprocessorDefinitions>_X86_;NDEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <AdditionalIncludeDirectories>C:\Data\Projects;</AdditionalIncludeDirectories>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <PreprocessorDefinitions>_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <AdditionalIncludeDirectories>C:\Data\Projects;</AdditionalIncludeDirectories>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\debug_memory_leaks.cpp" />
- <ClCompile Include="dll_main.cpp" />
- <ClCompile Include="find_file_plus.cpp" />
- <ClCompile Include="load_dll.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="find_file_plus.h" />
- <ClInclude Include="load_dll.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project> \ No newline at end of file
diff --git a/zen/FindFilePlus/dll_main.cpp b/zen/FindFilePlus/dll_main.cpp
deleted file mode 100644
index caa5930d..00000000
--- a/zen/FindFilePlus/dll_main.cpp
+++ /dev/null
@@ -1,66 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#define WIN32_LEAN_AND_MEAN
-#include <zen/win.h>
-
-#include "init_dll_binding.h"
-
-/*
-http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx
-"DllMain is called while the loader-lock is held. [...] You cannot call any function in
-DllMain that directly or indirectly tries to acquire the loader lock. Otherwise, you will
-introduce the possibility that your application deadlocks or crashes."
-
-it's even worse: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
-"If your DLL is linked with the C run-time library (CRT), the entry point provided by the CRT calls the constructors
-and destructors for global and static C++ objects. Therefore, these restrictions for DllMain also apply to constructors
-and destructors and any code that is called from them."
-
-Example: http://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/
-
-Empirical study on DLL initialization order
--------------------------------------------
-I. statically linked DLL:
- DLL, static object constructors
- DLL, DllMain(): DLL_PROCESS_ATTACH
- main thread, static object constructors
- main thread, enter main()
- DLL, DllMain(): DLL_THREAD_ATTACH
- DLL, DllMain(): DLL_THREAD_DETACH
- main thread, exit main()
- main thread, static object destructors
- DLL, DllMain(): DLL_PROCESS_DETACH
- DLL, static object destructors
-
-II. dynamically linked DLL (living in main()):
- main thread, static object constructors
- main thread, main(): LoadLibrary
- DLL, static object constructors
- DLL, DllMain(): DLL_PROCESS_ATTACH
- main thread, main(): FreeLibrary
- DLL, DllMain(): DLL_PROCESS_DETACH
- DLL, static object destructors
- main thread, static object destructors
-*/
-
-//optional: add init/teardown logic here
-BOOL APIENTRY DllMain(HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved)
-{
- switch (fdwReason)
- {
- case DLL_PROCESS_ATTACH:
- if (!findplus::initDllBinding())
- return false;
- case DLL_PROCESS_DETACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return true;
-}
diff --git a/zen/FindFilePlus/find_file_plus.cpp b/zen/FindFilePlus/find_file_plus.cpp
deleted file mode 100644
index 247b916c..00000000
--- a/zen/FindFilePlus/find_file_plus.cpp
+++ /dev/null
@@ -1,452 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "find_file_plus.h"
-#include "init_dll_binding.h"
-//#include <windows.h> //these two don't play nice with each other
-#include "load_dll.h"
-#include <new>
-
-using namespace dll;
-using namespace findplus;
-
-
-namespace
-{
-struct NtFileError //exception class
-{
- NtFileError(NTSTATUS errorCode) : ntError(errorCode) {}
- NTSTATUS ntError;
-};
-
-
-//--------------------------------------------------------------------------------------------------------------
-typedef NTSTATUS (NTAPI* NtOpenFileFunc)(PHANDLE fileHandle,
- ACCESS_MASK desiredAccess,
- POBJECT_ATTRIBUTES objectAttributes,
- PIO_STATUS_BLOCK ioStatusBlock,
- ULONG shareAccess,
- ULONG openOptions);
-
-typedef NTSTATUS (NTAPI* NtCloseFunc)(HANDLE handle);
-
-typedef NTSTATUS (NTAPI* NtQueryDirectoryFileFunc)(HANDLE fileHandle,
- HANDLE event,
- PIO_APC_ROUTINE apcRoutine,
- PVOID apcContext,
- PIO_STATUS_BLOCK ioStatusBlock,
- PVOID fileInformation,
- ULONG length,
- FILE_INFORMATION_CLASS fileInformationClass,
- BOOLEAN ReturnSingleEntry,
- PUNICODE_STRING fileMask,
- BOOLEAN restartScan);
-
-typedef ULONG (NTAPI* RtlNtStatusToDosErrorFunc)(NTSTATUS /*__in status*/);
-
-typedef struct _RTL_RELATIVE_NAME_U
-{
- UNICODE_STRING RelativeName;
- HANDLE ContainingDirectory;
- PVOID /*PRTLP_CURDIR_REF*/ CurDirRef;
-} RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U;
-
-typedef BOOLEAN (NTAPI* RtlDosPathNameToNtPathName_UFunc)(PCWSTR dosFileName, //__in
- PUNICODE_STRING ntFileName, //__out
- PCWSTR* filePart, //__out
- PRTL_RELATIVE_NAME_U relativeName); //__out
-
-typedef BOOLEAN (NTAPI* RtlDosPathNameToRelativeNtPathName_UFunc)(PCWSTR dosFileName, //__in
- PUNICODE_STRING ntFileName, //__out
- PCWSTR* filePart, //__out
- PRTL_RELATIVE_NAME_U relativeName); //__out
-
-typedef BOOLEAN (NTAPI* RtlCreateUnicodeStringFunc)(PUNICODE_STRING DestinationString, //_Out_
- PCWSTR SourceString); //_In_
-
-typedef VOID (NTAPI* RtlFreeUnicodeStringFunc)(PUNICODE_STRING); //__inout unicodeString
-
-//--------------------------------------------------------------------------------------------------------------
-
-//it seems we cannot use any of the ntoskrnl.lib files in WinDDK as they produce access violations
-//fortunately dynamic binding works fine:
-const SysDllFun<NtOpenFileFunc> ntOpenFile (L"ntdll.dll", "NtOpenFile");
-const SysDllFun<NtCloseFunc> ntClose (L"ntdll.dll", "NtClose");
-const SysDllFun<NtQueryDirectoryFileFunc> ntQueryDirectoryFile (L"ntdll.dll", "NtQueryDirectoryFile");
-const SysDllFun<RtlNtStatusToDosErrorFunc> rtlNtStatusToDosError (L"ntdll.dll", "RtlNtStatusToDosError");
-const SysDllFun<RtlCreateUnicodeStringFunc> rtlCreateUnicodeString (L"ntdll.dll", "RtlCreateUnicodeString");
-const SysDllFun<RtlFreeUnicodeStringFunc> rtlFreeUnicodeString (L"ntdll.dll", "RtlFreeUnicodeString");
-const SysDllFun<RtlDosPathNameToNtPathName_UFunc> rtlDosPathNameToNtPathName_U(SysDllFun<RtlDosPathNameToRelativeNtPathName_UFunc>(L"ntdll.dll", "RtlDosPathNameToRelativeNtPathName_U") ?
- SysDllFun<RtlDosPathNameToRelativeNtPathName_UFunc>(L"ntdll.dll", "RtlDosPathNameToRelativeNtPathName_U") : //use the newer version if available
- SysDllFun<RtlDosPathNameToNtPathName_UFunc>(L"ntdll.dll", "RtlDosPathNameToNtPathName_U")); //fallback for XP
-//global constants only -> preserve thread safety!
-}
-
-
-bool findplus::initDllBinding() //evaluate in ::DllMain() when attaching process
-{
- //NT/ZwXxx Routines
- //http://msdn.microsoft.com/en-us/library/ff567122(v=VS.85).aspx
-
- //Run-Time Library (RTL) Routines
- //http://msdn.microsoft.com/en-us/library/ff563638(v=VS.85).aspx
-
- //verify dynamic dll binding
- return ntOpenFile &&
- ntClose &&
- ntQueryDirectoryFile &&
- rtlNtStatusToDosError &&
- rtlCreateUnicodeString &&
- rtlFreeUnicodeString &&
- rtlDosPathNameToNtPathName_U;
-
- //this may become handy some time: nt status code STATUS_ORDINAL_NOT_FOUND maps to win32 code ERROR_INVALID_ORDINAL
-}
-
-
-class findplus::FileSearcher
-{
-public:
- FileSearcher(const wchar_t* dirname); //throw NtFileError
- ~FileSearcher();
-
- bool readDir(FileInformation& output); //throw NtFileError; returns false if "no more files"
-
-private:
- template <class QueryPolicy> bool readDirImpl(FileInformation& output); //throw NtFileError
-
- UNICODE_STRING dirnameNt; //it seems hDir implicitly keeps a reference to this, at least ::FindFirstFile() does no cleanup before ::FindClose()!
- HANDLE hDir;
-
- ULONG nextEntryOffset; //!= 0 if entry is waiting in buffer
- //::FindNextFileW() uses 0x1000 = 4096 = sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(TCHAR) * 2000
- //=> let's use the same, even if our header is 16 byte larger; maybe there is some packet size advantage for networks? Note that larger buffers seem to degrade performance.
- static const ULONG BUFFER_SIZE = 4096;
- LONGLONG buffer[BUFFER_SIZE / sizeof(LONGLONG)]; //buffer needs to be aligned at LONGLONG boundary
-
- static_assert(BUFFER_SIZE % sizeof(LONGLONG) == 0, "ups, our buffer is trimmed!");
-};
-
-
-//a simple scope guard without <utility>, <type_traits>, <cassert> dependencies:
-template <typename F>
-class ScopeGuardLean
-{
-public:
- explicit ScopeGuardLean(F fun) : dismissed_(false), fun_(fun) {}
- ScopeGuardLean(ScopeGuardLean&& other) : dismissed_(other.dismissed_), fun_(std::move(other.fun_)) { other.dismiss(); }
-
- void dismiss() { dismissed_ = true; }
-
- ~ScopeGuardLean()
- {
- if (!dismissed_)
- try { fun_(); }
- catch (...) {}
- }
-
-private:
- ScopeGuardLean (const ScopeGuardLean&); // = delete
- ScopeGuardLean& operator=(const ScopeGuardLean&); //
-
- bool dismissed_;
- F fun_;
-};
-
-template <class F> inline
-ScopeGuardLean<F> makeGuard(F fun) { return ScopeGuardLean<F>(fun); }
-
-
-FileSearcher::FileSearcher(const wchar_t* dirname) :
- dirnameNt(), //[!]
- hDir(nullptr),
- nextEntryOffset(0)
-{
- auto guardConstructor = makeGuard([&] { this->~FileSearcher(); });
- //--------------------------------------------------------------------------------------------------------------
-
- //convert dosFileName, e.g. C:\Users or \\?\C:\Users to ntFileName \??\C:\Users
- //in contrast to ::FindFirstFile() implementation we don't evaluate the relativeName,
- //however tests indicate ntFileName is *always* filled with an absolute name, even if dosFileName is relative
-
- PCWSTR filePart = nullptr;
- RTL_RELATIVE_NAME_U relativeName = {};
-
- //NOTE: RtlDosPathNameToNtPathName_U may be used on all XP/Win7/Win8 for compatibility
- // RtlDosPathNameToNtPathName_U: used by Windows XP available with OS version 3.51 (Windows NT) and higher
- // RtlDosPathNameToRelativeNtPathName_U: used by Win7/Win8 available with OS version 5.2 (Windows Server 2003) and higher
- if (!rtlDosPathNameToNtPathName_U(dirname, //__in dosFileName,
- &dirnameNt, //__out ntFileName,
- &filePart, //__out FilePart - points into ntFileName
- &relativeName)) //__out relativeName - points into ntFileName; empty if dosFileName is absolute
- throw NtFileError(STATUS_OBJECT_PATH_NOT_FOUND); //translates to ERROR_PATH_NOT_FOUND, same behavior like ::FindFirstFileEx()
- //note 1: internally it distinguishes between "quick path" == \\?\ and "slow path" handling!
- //http://doxygen.reactos.org/d9/d6e/lib_2rtl_2path_8c_a11c87ad0f7752999b0b8972af6165d7a.html#a11c87ad0f7752999b0b8972af6165d7a
-
- //note 2: without \\?\, i.e. slow path handling it calls RtlGetFullPathName_Ustr() which removes trailing spaces!!!
- //http://doxygen.reactos.org/d9/d6e/lib_2rtl_2path_8c_a8624b864678ca64b031f5fc273e022af.html#a8624b864678ca64b031f5fc273e022af
- //FindFirstFile() gets lucky because it passes "<dirname>\*" which never has trailing space chars! >:(
-
- OBJECT_ATTRIBUTES objAttr = {};
- if (relativeName.RelativeName.Length == 0) //absolute name
- {
- InitializeObjectAttributes(&objAttr, //[out] POBJECT_ATTRIBUTES initializedAttributes,
- &dirnameNt, //[in] PUNICODE_STRING objectName,
- OBJ_CASE_INSENSITIVE, //[in] ULONG attributes,
- nullptr, //[in] HANDLE rootDirectory,
- nullptr); //[in, optional] PSECURITY_DESCRIPTOR securityDescriptor
- }
- else //relative name (it seems we alternatively could also use dirnameNt here?)
- {
- InitializeObjectAttributes(&objAttr, //[out] POBJECT_ATTRIBUTES initializedAttributes,
- &relativeName.RelativeName, //[in] PUNICODE_STRING objectName,
- OBJ_CASE_INSENSITIVE, //[in] ULONG attributes,
- relativeName.ContainingDirectory, //[in] HANDLE rootDirectory,
- nullptr); //[in, optional] PSECURITY_DESCRIPTOR securityDescriptor
- }
-
- {
- IO_STATUS_BLOCK status = {};
- NTSTATUS rv = ntOpenFile(&hDir, //__out PHANDLE FileHandle,
- FILE_LIST_DIRECTORY | SYNCHRONIZE, //__in ACCESS_MASK desiredAccess, - 100001 used by ::FindFirstFile() on all XP/Win7/Win8
- &objAttr, //__in POBJECT_ATTRIBUTES objectAttributes,
- &status, //__out PIO_STATUS_BLOCK ioStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //__in ULONG shareAccess, - 7 on Win7/Win8, 3 on XP
- FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); //__in ULONG openOptions - 4021 used on all XP/Win7/Win8
- if (!NT_SUCCESS(rv))
- throw NtFileError(rv);
- }
-
- guardConstructor.dismiss();
-}
-
-
-inline
-FileSearcher::~FileSearcher()
-{
- //cleanup in reverse order
- if (hDir)
- ntClose(hDir);
-
- if (dirnameNt.Buffer)
- rtlFreeUnicodeString(&dirnameNt); //cleanup identical to ::FindFirstFile()
- //note that most of this function seems inlined by the linker, so that its assembly looks equivalent to "RtlFreeHeap(RtlGetProcessHeap(), 0, ntPathName.Buffer)"
-}
-
-
-namespace
-{
-/*
-Common C-style policy handling directory traversal:
-
-struct QueryPolicy
-{
- typedef ... RawFileInfo;
- static const FILE_INFORMATION_CLASS fileInformationClass = ...;
- static void extractFileId(const RawFileInfo& rawInfo, FileInformation& fileInfo);
-};
-*/
-
-struct DirQueryDefault //as implemented in Win32 FindFirstFile()/FindNextFile()
-{
- typedef FILE_BOTH_DIR_INFORMATION RawFileInfo;
- static const FILE_INFORMATION_CLASS fileInformationClass = FileBothDirectoryInformation;
- static void extractFileId(const RawFileInfo& rawInfo, FileInformation& fileInfo) { fileInfo.fileId.QuadPart = 0; }
-};
-
-struct DirQueryFileId
-{
- typedef FILE_ID_BOTH_DIR_INFORMATION RawFileInfo;
- static const FILE_INFORMATION_CLASS fileInformationClass = FileIdBothDirectoryInformation;
- static void extractFileId(const RawFileInfo& rawInfo, FileInformation& fileInfo)
- {
- fileInfo.fileId.QuadPart = rawInfo.FileId.QuadPart; //may be 0 even in this context, e.g. for mapped FTP drive!
- static_assert(sizeof(fileInfo.fileId) == sizeof(rawInfo.FileId), "dang!");
- }
-};
-}
-
-
-inline
-bool FileSearcher::readDir(FileInformation& output) { return readDirImpl<DirQueryFileId>(output); } //throw NtFileError
-
-
-template <class QueryPolicy>
-bool FileSearcher::readDirImpl(FileInformation& output) //throw NtFileError; returns false if "no more files"
-{
- //although FILE_ID_FULL_DIR_INFORMATION should suffice for our purposes, there are problems on Windows XP for certain directories, e.g. "\\Vboxsvr\build"
- //making NtQueryDirectoryFile() return with STATUS_INVALID_PARAMETER while other directories, e.g. "C:\" work fine for some reason
- //FILE_ID_BOTH_DIR_INFORMATION on the other hand works on XP/Win7/Win8
- //performance: there is no noticeable difference between FILE_ID_BOTH_DIR_INFORMATION and FILE_ID_FULL_DIR_INFORMATION
-
- /* corresponding first access in ::FindFirstFileW()
-
- NTSTATUS rv = ntQueryDirectoryFile(hDir, //__in HANDLE fileHandle,
- nullptr, //__in_opt HANDLE event,
- nullptr, //__in_opt PIO_APC_ROUTINE apcRoutine,
- nullptr, //__in_opt PVOID apcContext,
- &status, //__out PIO_STATUS_BLOCK ioStatusBlock,
- &buffer, //__out_bcount(Length) PVOID fileInformation,
- BUFFER_SIZE, //__in ULONG length, ::FindFirstFileW() on all XP/Win7/Win8 uses sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(TCHAR) * MAX_PATH == 0x268
- FileIdBothDirectoryInformation, //__in FILE_INFORMATION_CLASS fileInformationClass - all XP/Win7/Win8 use "FileBothDirectoryInformation"
- true, //__in BOOLEAN returnSingleEntry,
- nullptr, //__in_opt PUNICODE_STRING mask,
- false); //__in BOOLEAN restartScan
- */
-
- //analog to ::FindNextFileW() with performance optimized access (in contrast to first access in ::FindFirstFileW())
- if (nextEntryOffset == 0)
- {
- IO_STATUS_BLOCK status = {};
- NTSTATUS rv = ntQueryDirectoryFile(hDir, //__in HANDLE fileHandle,
- nullptr, //__in_opt HANDLE event,
- nullptr, //__in_opt PIO_APC_ROUTINE apcRoutine,
- nullptr, //__in_opt PVOID apcContext,
- &status, //__out PIO_STATUS_BLOCK ioStatusBlock,
- &buffer, //__out_bcount(Length) PVOID fileInformation,
- BUFFER_SIZE, //__in ULONG length, ::FindNextFileW() on all XP/Win7/Win8 uses sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(TCHAR) * 2000 == 0x1000
- QueryPolicy::fileInformationClass, //__in FILE_INFORMATION_CLASS fileInformationClass - all XP/Win7/Win8 use "FileBothDirectoryInformation"
- false, //__in BOOLEAN returnSingleEntry,
- nullptr, //__in_opt PUNICODE_STRING mask,
- false); //__in BOOLEAN restartScan
- if (!NT_SUCCESS(rv))
- {
- /*
- fallback to default directory query method, if FileIdBothDirectoryInformation is not properly implemented
- this is required for NetDrive mounted Webdav, e.g. www.box.net and NT4, 2000 remote drives, et al.
-
- NT status code | Win32 error code
- --------------------------------|------------------------
- STATUS_INVALID_LEVEL | ERROR_INVALID_LEVEL
- STATUS_NOT_SUPPORTED | ERROR_NOT_SUPPORTED
- STATUS_UNEXPECTED_NETWORK_ERROR | ERROR_UNEXP_NET_ERR -> traverse network drive hosted by Win98
- STATUS_INVALID_PARAMETER | ERROR_INVALID_PARAMETER
- STATUS_INVALID_NETWORK_RESPONSE | ERROR_BAD_NET_RESP
- STATUS_INVALID_INFO_CLASS | ERROR_INVALID_PARAMETER
- STATUS_UNSUCCESSFUL | ERROR_GEN_FAILURE
- STATUS_ACCESS_VIOLATION | ERROR_NOACCESS ->FileIdBothDirectoryInformation on XP accessing UDF
- STATUS_NO_SUCH_FILE | ERROR_FILE_NOT_FOUND
-
- rv == STATUS_NO_SUCH_FILE:
- failure to find a file on first call returns STATUS_NO_SUCH_FILE, while subsequent accesses return STATUS_NO_MORE_FILES
- note: not all directories contain ".", ".." entries! E.g. a drive's root directory or NetDrive + ftp.gnu.org\CRYPTO.README"
- -> addon: this is NOT a directory, it looks like one in NetDrive, but it's a file in Opera
- STATUS_NO_SUCH_FILE is abused by some citrix shares instead of "STATUS_INVALID_PARAMETER" so we treat it as such!
- => since the directory is "truly empty" a fallback won't hurt
- */
- if (rv == STATUS_NO_MORE_FILES) //perf: don't throw an exception in this common case! => 8% perf boost for FFS comparison phase!
- return false;
-
- if (rv == STATUS_NOT_SUPPORTED ||
- rv == STATUS_INVALID_LEVEL ||
- rv == STATUS_NO_SUCH_FILE || //[!]
- rv == STATUS_UNEXPECTED_NETWORK_ERROR ||
- rv == STATUS_INVALID_PARAMETER ||
- rv == STATUS_INVALID_NETWORK_RESPONSE ||
- rv == STATUS_INVALID_INFO_CLASS ||
- //rv == STATUS_NOT_IMPLEMENTED || -> first confirm that these codes
- //rv == STATUS_INVALID_DEVICE_REQUEST || -> are in fact used!
- rv == STATUS_UNSUCCESSFUL ||
- rv == STATUS_ACCESS_VIOLATION)
- rv = STATUS_NOT_SUPPORTED;
-
- throw NtFileError(rv); //throws STATUS_NO_MORE_FILES when finished
- }
-
- // for (NTSTATUS i = 0xC0000000L; i != -1; ++i)
- // {
- // if (rtlNtStatusToDosError(i) == 59) //ERROR_UNEXP_NET_ERR
- // __debugbreak(); //__asm int 3;
- // }
-
- if (status.Information == 0) //except for the first call to call ::NtQueryDirectoryFile():
- throw NtFileError(STATUS_BUFFER_OVERFLOW); //if buffer size is too small, return value is STATUS_SUCCESS and Information == 0 -> we don't expect this!
- }
-
- typedef typename QueryPolicy::RawFileInfo RawFileInfo;
- const RawFileInfo& dirInfo = *reinterpret_cast<RawFileInfo*>(reinterpret_cast<char*>(buffer) + nextEntryOffset);
-
- if (dirInfo.NextEntryOffset == 0)
- nextEntryOffset = 0; //our offset is relative to the beginning of the buffer
- else
- nextEntryOffset += dirInfo.NextEntryOffset;
-
-
- auto toFileTime = [](const LARGE_INTEGER& rawTime) -> FILETIME
- {
- FILETIME tmp = { rawTime.LowPart, rawTime.HighPart };
- return tmp;
- };
-
- QueryPolicy::extractFileId(dirInfo, output);
-
- output.creationTime = toFileTime(dirInfo.CreationTime);
- output.lastWriteTime = toFileTime(dirInfo.LastWriteTime); //the similar field "ChangeTime" refers to changes to metadata in addition to write accesses
- output.fileSize.QuadPart = dirInfo.EndOfFile.QuadPart;
- output.fileAttributes = dirInfo.FileAttributes;
- output.shortNameLength = dirInfo.FileNameLength / sizeof(TCHAR); //FileNameLength is in bytes!
-
- if (dirInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) //analog to FindFirstFile(), confirmed for Win XP and Win 7
- output.reparseTag = dirInfo.EaSize; //
- else
- output.reparseTag = 0;
-
- if (dirInfo.FileNameLength + sizeof(TCHAR) > sizeof(output.shortName)) //this may actually happen if ::NtQueryDirectoryFile() decides to return a
- throw NtFileError(STATUS_BUFFER_OVERFLOW); //short name of length MAX_PATH + 1, 0-termination is not required!
-
- ::memcpy(output.shortName, dirInfo.FileName, dirInfo.FileNameLength);
- output.shortName[output.shortNameLength] = 0; //NOTE: FILE_ID_BOTH_DIR_INFORMATION::FileName in general is NOT 0-terminated! It is on XP/Win7, but NOT on Win8!
-
- static_assert(sizeof(output.creationTime) == sizeof(dirInfo.CreationTime), "dang!");
- static_assert(sizeof(output.lastWriteTime) == sizeof(dirInfo.LastWriteTime), "dang!");
- static_assert(sizeof(output.fileSize) == sizeof(dirInfo.EndOfFile), "dang!");
- static_assert(sizeof(output.fileAttributes) == sizeof(dirInfo.FileAttributes), "dang!");
- return true;
-}
-
-
-FindHandle findplus::openDir(const wchar_t* dirname)
-{
- try
- {
- return new FileSearcher(dirname); //throw NtFileError, std::bad_alloc
- }
- catch (const NtFileError& e)
- {
- setWin32Error(rtlNtStatusToDosError(e.ntError));
- return nullptr;
- }
- catch (const std::bad_alloc&) //not unlikely in file sync context! => handle!
- {
- setWin32Error(rtlNtStatusToDosError(STATUS_NO_MEMORY));
- return nullptr;
- }
-}
-
-
-bool findplus::readDir(FindHandle hnd, FileInformation& output)
-{
- try
- {
- if (!hnd->readDir(output)) //throw NtFileError
- {
- setWin32Error(rtlNtStatusToDosError(STATUS_NO_MORE_FILES));
- return false;
- }
- return true;
- }
- catch (const NtFileError& e)
- {
- setWin32Error(rtlNtStatusToDosError(e.ntError));
- return false;
- }
-}
-
-
-void findplus::closeDir(FindHandle hnd)
-{
- delete hnd;
-}
diff --git a/zen/FindFilePlus/find_file_plus.h b/zen/FindFilePlus/find_file_plus.h
deleted file mode 100644
index a26bdeb3..00000000
--- a/zen/FindFilePlus/find_file_plus.h
+++ /dev/null
@@ -1,92 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef FIND_FIRST_FILE_PLUS_HEADER_087483434
-#define FIND_FIRST_FILE_PLUS_HEADER_087483434
-
-#ifdef FIND_FILE_PLUS_DLL_EXPORTS
-#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport)
-#else
-#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport)
-#endif
-
-
-#ifdef FIND_FILE_PLUS_DLL_EXPORTS
-#include <Ntifs.h> //driver level headers must be included *before* windows api headers!
-#endif
-#include <windef.h> //
-#undef min
-#undef max
-
-#include <zen/build_info.h>
-
-namespace findplus
-{
-/*--------------
- |declarations|
- --------------*/
-
-struct FileInformation
-{
- FILETIME creationTime;
- FILETIME lastWriteTime;
- ULARGE_INTEGER fileSize;
- ULARGE_INTEGER fileId; //optional: may be 0 if not supported
- DWORD fileAttributes;
- DWORD reparseTag; //set if "fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT"
- DWORD shortNameLength;
- WCHAR shortName[MAX_PATH + 1]; //shortName is 0-terminated
-}; //no need for #pragma pack -> all members are perfectly 4, 8 byte aligned!
-
-class FileSearcher;
-typedef FileSearcher* FindHandle;
-
-DLL_FUNCTION_DECLARATION
-FindHandle openDir(const wchar_t* dirname); //returns nullptr on error, call ::GetLastError()
-//note: do NOT place an asterisk at end, e.g. C:\SomeDir\*, as you would do for ::FindFirstFile()
-
-DLL_FUNCTION_DECLARATION
-bool readDir(FindHandle hnd, FileInformation& output); //returns false on error or if there are no more files; ::GetLastError() returns ERROR_NO_MORE_FILES in this case
-/*
-warning: may also return with ERROR_NOT_SUPPORTED if "FileIdBothDirectoryInformation" is not supported! We need a fallback:
-
- sometimes it's *not* sufficient to use fallback for NtQueryDirectoryFile() alone, we need to reset "hDir", since it may be fucked up by some poor file system layer implementation:
- - Samba before v3.0.22 (Mar 30, 2006) seems to have a bug which sucessfully returns 128 elements via NtQueryDirectoryFile() and FileIdBothDirectoryInformation,
- then fails with STATUS_INVALID_LEVEL. Fallback to FileBothDirectoryInformation will return STATUS_NO_MORE_FILES, even if there *are* more files
- - NtQueryDirectoryFile() may *not* respect "restartScan" for some weird Win2000 file system drivers, so we cannot rely on this as a replacement for a "hDir" reset
- - Windows 7 Remote Desktop sharing does not work unless "hDir" is reset!
- => let's assume worst case in general and do a reset!
- perf note: implementing this reset at a folder level is possible, but a huge perf-killer (additional open/close handle), therefore fallback must apply to a complete folder (sub-)tree!
- => caller needs to handle this and implement FindFirstFile()/FindNextFile() fallback!
-*/
-
-DLL_FUNCTION_DECLARATION
-void closeDir(FindHandle hnd);
-
-/*----------
- |typedefs|
- ----------*/
-typedef FindHandle (*FunType_openDir )(const wchar_t* dirname);
-typedef bool (*FunType_readDir )(FindHandle hnd, FileInformation& dirInfo);
-typedef void (*FunType_closeDir)(FindHandle hnd);
-
-/*--------------
- |symbol names|
- --------------*/
-//const pointers ensure internal linkage
-const char funName_openDir [] = "openDir";
-const char funName_readDir [] = "readDir";
-const char funName_closeDir[] = "closeDir";
-
-/*---------------
- |library names|
- ---------------*/
-inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"FindFilePlus_x64.dll" : L"FindFilePlus_Win32.dll"; }
-}
-
-#undef DLL_FUNCTION_DECLARATION
-
-#endif //FIND_FIRST_FILE_PLUS_HEADER_087483434
diff --git a/zen/FindFilePlus/init_dll_binding.h b/zen/FindFilePlus/init_dll_binding.h
deleted file mode 100644
index 44591ab4..00000000
--- a/zen/FindFilePlus/init_dll_binding.h
+++ /dev/null
@@ -1,16 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef INIT_DLL_BINDING_HEADER_ß018356031467832145
-#define INIT_DLL_BINDING_HEADER_ß018356031467832145
-
-namespace findplus
-{
-//load and check dll binding at startup
-bool initDllBinding(); //evaluate in ::DllMain() when attaching process
-}
-
-#endif //INIT_DLL_BINDING_HEADER_ß018356031467832145
diff --git a/zen/FindFilePlus/load_dll.cpp b/zen/FindFilePlus/load_dll.cpp
deleted file mode 100644
index c9396f6d..00000000
--- a/zen/FindFilePlus/load_dll.cpp
+++ /dev/null
@@ -1,23 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "load_dll.h"
-#define WIN32_LEAN_AND_MEAN
-#include <zen/win.h>
-
-void* /*FARPROC*/ dll::loadSymbol(const wchar_t* libraryName, const char* functionName)
-{
- return ::GetProcAddress(::GetModuleHandle(libraryName), functionName);
- //cleanup neither required nor allowed (::FreeLibrary())
-
-}
-//note: void* and FARPROC function pointer have same binary size on Windows
-
-
-void dll::setWin32Error(unsigned long lastError)
-{
- ::SetLastError(lastError);
-}
diff --git a/zen/FindFilePlus/load_dll.h b/zen/FindFilePlus/load_dll.h
deleted file mode 100644
index d661c4b9..00000000
--- a/zen/FindFilePlus/load_dll.h
+++ /dev/null
@@ -1,45 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef LOAD_DLL_HEADER_0312463214872163832174
-#define LOAD_DLL_HEADER_0312463214872163832174
-
-namespace dll
-{
-void setWin32Error(unsigned long lastError);
-
-//NOTE: uses ::GetModuleHandle => call for system DLLs only!
-template <class Func>
-class SysDllFun
-{
-public:
- SysDllFun(const wchar_t* systemLibrary, const char* functionName) :
- fun(reinterpret_cast<Func>(loadSymbol(systemLibrary, functionName))) {}
-
- operator Func() const { return fun; }
-
-private:
- Func fun;
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-void* /*FARPROC*/ loadSymbol(const wchar_t* libraryName, const char* functionName);
-}
-
-#endif //LOAD_DLL_HEADER_0312463214872163832174
diff --git a/zen/IFileOperation/FileOperation.vcxproj b/zen/IFileOperation/FileOperation.vcxproj
deleted file mode 100644
index 3f6923f3..00000000
--- a/zen/IFileOperation/FileOperation.vcxproj
+++ /dev/null
@@ -1,179 +0,0 @@
-<?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>FileOperation</ProjectName>
- <ProjectGuid>{F6D3A51C-15EF-4710-BB67-3FCE9C0B5D92}</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>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120_xp</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <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>
- <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\FreeFileSync\Build\Bin\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\FreeFileSync\Obj\$(ProjectName)_VCPP_$(PlatformName)_$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName)_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName)_$(Platform)</TargetName>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WXINTL_NO_GETTEXT_MACRO;ZEN_WIN;_DEBUG;_WINDOWS;_USRDLL;FILE_OP_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>C:\Data\Projects;C:\Data\C++\boost</AdditionalIncludeDirectories>
- <SmallerTypeCheck>true</SmallerTypeCheck>
- <ForcedIncludeFiles>zen/warn_static.h</ForcedIncludeFiles>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <AdditionalLibraryDirectories>C:\Data\C++\Boost\stage\lib</AdditionalLibraryDirectories>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WXINTL_NO_GETTEXT_MACRO;ZEN_WIN;_DEBUG;_WINDOWS;_USRDLL;FILE_OP_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>C:\Data\Projects;C:\Data\C++\boost</AdditionalIncludeDirectories>
- <SmallerTypeCheck>true</SmallerTypeCheck>
- <ForcedIncludeFiles>zen/warn_static.h</ForcedIncludeFiles>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <AdditionalLibraryDirectories>C:\Data\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <PreprocessorDefinitions>WXINTL_NO_GETTEXT_MACRO;ZEN_WIN;NDEBUG;_WINDOWS;_USRDLL;FILE_OP_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>C:\Data\Projects;C:\Data\C++\boost</AdditionalIncludeDirectories>
- <ForcedIncludeFiles>zen/warn_static.h</ForcedIncludeFiles>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- <AdditionalLibraryDirectories>C:\Data\C++\Boost\stage\lib</AdditionalLibraryDirectories>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <PreprocessorDefinitions>WXINTL_NO_GETTEXT_MACRO;ZEN_WIN;NDEBUG;_WINDOWS;_USRDLL;FILE_OP_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <DisableSpecificWarnings>4100;4996;4512</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>C:\Data\Projects;C:\Data\C++\boost</AdditionalIncludeDirectories>
- <ForcedIncludeFiles>zen/warn_static.h</ForcedIncludeFiles>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- <AdditionalLibraryDirectories>C:\Data\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\debug_memory_leaks.cpp" />
- <ClCompile Include="..\dst_hack.cpp" />
- <ClCompile Include="..\file_handling.cpp" />
- <ClCompile Include="..\file_traverser.cpp" />
- <ClCompile Include="..\privilege.cpp" />
- <ClCompile Include="..\zstring.cpp" />
- <ClCompile Include="file_op.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="file_op.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project> \ No newline at end of file
diff --git a/zen/IFileOperation/file_op.cpp b/zen/IFileOperation/file_op.cpp
deleted file mode 100644
index 27a2565b..00000000
--- a/zen/IFileOperation/file_op.cpp
+++ /dev/null
@@ -1,541 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "file_op.h"
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#define WIN32_LEAN_AND_MEAN
-#include <zen/com_ptr.h>
-#include <zen/com_error.h>
-#include <zen/scope_guard.h>
-#include <zen/stl_tools.h>
-#include <zen/file_handling.h>
-
-#include <boost/thread/tss.hpp>
-
-#include <RestartManager.h>
-#pragma comment(lib, "Rstrtmgr.lib")
-
-#define STRICT_TYPED_ITEMIDS //better type safety for IDLists
-#include <Shlobj.h>
-#include <shobjidl.h>
-#include <shellapi.h> //shell constants such as FO_* values
-
-using namespace zen;
-
-
-namespace
-{
-std::vector<std::wstring> getLockingProcesses(const wchar_t* filename); //throw SysError
-
-
-class RecyclerProgressCallback : public IFileOperationProgressSink
-{
- //Sample implementation: %ProgramFiles%\Microsoft SDKs\Windows\v7.1\Samples\winui\shell\appplatform\FileOperationProgressSink
-
- ~RecyclerProgressCallback() {} //private: do not allow stack usage "thanks" to IUnknown lifetime management!
-
-public:
- RecyclerProgressCallback(fileop::RecyclerCallback callback, void* sink) :
- cancellationRequested(false),
- callback_(callback),
- sink_(sink),
- refCount(1) {}
-
- //IUnknown: reference implementation according to: http://msdn.microsoft.com/en-us/library/office/cc839627.aspx
- virtual ULONG STDMETHODCALLTYPE AddRef()
- {
- return ::InterlockedIncrement(&refCount);
- }
-
- virtual ULONG STDMETHODCALLTYPE Release()
- {
- ULONG newRefCount = ::InterlockedDecrement(&refCount);
- if (newRefCount == 0) //race condition caveat: do NOT check refCount, which might have changed already!
- delete this;
- return newRefCount;
- }
-
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR* __RPC_FAR* ppvObject)
- {
- if (!ppvObject)
- return E_INVALIDARG;
-
- if (riid == IID_IUnknown || riid == IID_IFileOperationProgressSink)
- {
- *ppvObject = this;
- AddRef();
- return S_OK;
- }
- *ppvObject = NULL;
- return E_NOINTERFACE;
- }
-
- //IFileOperationProgressSink
- virtual HRESULT STDMETHODCALLTYPE StartOperations() { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT hrResult) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PreRenameItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiItem, __RPC__in_opt_string LPCWSTR pszNewName) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PostRenameItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiItem, __RPC__in_string LPCWSTR pszNewName, HRESULT hrRename, __RPC__in_opt IShellItem* psiNewlyCreated) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PreMoveItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiItem, __RPC__in_opt IShellItem* psiDestinationFolder, __RPC__in_opt_string LPCWSTR pszNewName) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PostMoveItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiItem, __RPC__in_opt IShellItem* psiDestinationFolder, __RPC__in_opt_string LPCWSTR pszNewName, HRESULT hrMove, __RPC__in_opt IShellItem* psiNewlyCreated) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PreCopyItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiItem, __RPC__in_opt IShellItem* psiDestinationFolder, __RPC__in_opt_string LPCWSTR pszNewName) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PostCopyItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiItem, __RPC__in_opt IShellItem* psiDestinationFolder, __RPC__in_opt_string LPCWSTR pszNewName, HRESULT hrCopy, __RPC__in_opt IShellItem* psiNewlyCreated) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PreNewItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiDestinationFolder, __RPC__in_opt_string LPCWSTR pszNewName) { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PostNewItem (DWORD dwFlags, __RPC__in_opt IShellItem* psiDestinationFolder, __RPC__in_opt_string LPCWSTR pszNewName, __RPC__in_opt_string LPCWSTR pszTemplateName, DWORD dwFileAttributes, HRESULT hrNew, __RPC__in_opt IShellItem* psiNewItem) { return S_OK; }
-
- virtual HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD dwFlags, __RPC__in_opt IShellItem* psiItem)
- {
- if (psiItem)
- {
- LPWSTR itemPath = nullptr;
- if (SUCCEEDED(psiItem->GetDisplayName(SIGDN_FILESYSPATH, &itemPath))) //will fail for long file paths > MAX_PATH!
- {
- ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(itemPath));
- currentItem = itemPath;
- }
- else if (SUCCEEDED(psiItem->GetDisplayName(SIGDN_NORMALDISPLAY, &itemPath))) //short name only; should work even for long file paths!
- {
- ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(itemPath));
- currentItem = itemPath;
- }
- else
- currentItem = L"<unknown file>"; //give some indication that file name determination failed (rather than leaving the name empty!)
- }
- //"Returns S_OK if successful, or an error value otherwise. In the case of an error value, the delete operation
- //and all subsequent operations pending from the call to IFileOperation are canceled."
- return cancellationRequested ? HRESULT_FROM_WIN32(ERROR_CANCELLED) : S_OK;
- }
-
- virtual HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD dwFlags,
- __RPC__in_opt IShellItem* psiItem,
- HRESULT hrDelete,
- __RPC__in_opt IShellItem* psiNewlyCreated)
- {
- if (FAILED(hrDelete))
- lastError = make_unique<std::pair<std::wstring, HRESULT>>(currentItem, hrDelete);
-
- currentItem.clear();
- //"Returns S_OK if successful, or an error value otherwise. In the case of an error value,
- //all subsequent operations pending from the call to IFileOperation are canceled."
- return cancellationRequested ? HRESULT_FROM_WIN32(ERROR_CANCELLED) : S_OK;
- }
-
- virtual HRESULT STDMETHODCALLTYPE UpdateProgress(UINT iWorkTotal, UINT iWorkSoFar)
- {
- if (callback_)
- try
- {
- if (!callback_(currentItem.c_str(), sink_)) //should not throw!
- cancellationRequested = true;
- }
- catch (...) { return E_UNEXPECTED; }
- //"If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code."
- //-> this probably means, we cannot rely on returning a custom error code here and have IFileOperation::PerformOperations() fail with same
- //=> defer cancellation to PreDeleteItem()/PostDeleteItem()
- return S_OK;
- }
- virtual HRESULT STDMETHODCALLTYPE ResetTimer () { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE PauseTimer () { return S_OK; }
- virtual HRESULT STDMETHODCALLTYPE ResumeTimer() { return S_OK; }
-
- //call after IFileOperation::PerformOperations()
- const std::pair<std::wstring, HRESULT>* getLastError() const { return lastError.get(); } //(file path, error code)
-
-private:
- std::wstring currentItem;
- bool cancellationRequested;
-
- std::unique_ptr<std::pair<std::wstring, HRESULT>> lastError;
-
- //file_op user callback
- fileop::RecyclerCallback callback_;
- void* sink_;
-
- //support IUnknown
- LONG refCount;
-};
-
-
-void moveToRecycleBin(const wchar_t* fileNames[], //throw SysError
- size_t fileCount,
- fileop::RecyclerCallback callback,
- void* sink)
-{
- ComPtr<IFileOperation> fileOp;
- ZEN_COM_CHECK(::CoCreateInstance(CLSID_FileOperation, //throw SysError
- nullptr,
- 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.
- ZEN_COM_CHECK(fileOp->SetOperationFlags(FOF_ALLOWUNDO |
- FOF_NOCONFIRMATION |
- FOF_SILENT | //no progress dialog box
- FOF_NOERRORUI |
- FOFX_EARLYFAILURE |
- //without FOFX_EARLYFAILURE, IFileOperationProgressSink::PostDeleteItem() will always report success, even if deletion failed!!? WTF!?
- //PerformOperations() will still succeed but set the uselessly generic GetAnyOperationsAborted() instead :(((
- //=> always set FOFX_EARLYFAILURE since we prefer good error messages over "doing as much as possible"
- //luckily for FreeFileSync we don't expect failures on individual files anyway: FreeFileSync moves files to be
- //deleted to a temporary folder first, so there is no reason why a second move (the recycling itself) should fail
- FOF_NO_CONNECTED_ELEMENTS));
- //use FOFX_RECYCLEONDELETE when Windows 8 is available!?
-
- ComPtr<RecyclerProgressCallback> opProgress;
- *opProgress.init() = new (std::nothrow) RecyclerProgressCallback(callback, sink);
- if (!opProgress)
- throw SysError(formatComError(L"Error creating RecyclerProgressCallback.", E_OUTOFMEMORY));
-
- DWORD callbackID = 0;
- ZEN_COM_CHECK(fileOp->Advise(opProgress.get(), &callbackID));
- ZEN_ON_SCOPE_EXIT(fileOp->Unadvise(callbackID)); //RecyclerProgressCallback might outlive current scope, so cut access to "callback, sink"
-
- int operationCount = 0;
-
- for (size_t i = 0; i < fileCount; ++i)
- {
- //SHCreateItemFromParsingName() physically checks file existence => callback
- if (callback)
- {
- bool continueExecution = false;
- try
- {
- continueExecution = callback(fileNames[i], sink); //should not throw!
- }
- catch (...) { throw SysError(formatComError(L"Unexpected exception in callback.", E_UNEXPECTED)); }
-
- if (!continueExecution)
- throw SysError(formatComError(L"Operation cancelled.", HRESULT_FROM_WIN32(ERROR_CANCELLED)));
- }
-
- //create file/folder item object
- ComPtr<IShellItem> psiFile;
- HRESULT hr = ::SHCreateItemFromParsingName(fileNames[i],
- nullptr,
- 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))
- {
- //make sure the file really is not there: Win32 by default strips trailing spaces, so we might end up here in error!
- //on the other hand, shell layer does not support \\?\ prefix to prevent this!
- if (!somethingExists(fileNames[i]))
- continue;
- }
- throw SysError(formatComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for file:\n") + L"\"" + fileNames[i] + L"\".", hr));
- }
-
- ZEN_COM_CHECK(fileOp->DeleteItem(psiFile.get(), nullptr));
-
- ++operationCount;
- }
-
- if (operationCount == 0) //calling PerformOperations() without anything to do would yield E_UNEXPECTED
- return;
-
- //perform planned operations
- try
- {
- ZEN_COM_CHECK(fileOp->PerformOperations());
- }
- catch (const SysError&)
- {
- //first let's check if we have more detailed error information available
- if (const std::pair<std::wstring, HRESULT>* lastError = opProgress->getLastError())
- {
- std::vector<std::wstring> processes; //create an even better error message if we detect a locking issue:
- try { processes = getLockingProcesses(lastError->first.c_str()); /*throw SysError*/ }
- catch (const SysError&) {}
-
- if (!processes.empty())
- {
- std::wstring errorMsg = L"The file \"" + lastError->first + L"\" is locked by another process:";
- std::for_each(processes.begin(), processes.end(), [&](const std::wstring& proc) { errorMsg += L'\n'; errorMsg += proc; });
- throw SysError(errorMsg); //message is descriptive enough, no need to evaluate HRESULT!
- }
- throw SysError(formatComError(std::wstring(L"Error during \"PerformOperations\" for file:\n") + L"\"" + lastError->first + L"\".", lastError->second));
- }
- throw;
- }
-
- //if FOF_NOERRORUI without FOFX_EARLYFAILURE is set, PerformOperations() can return with success despite errors, but sets the following "aborted" flag instead
- BOOL pfAnyOperationsAborted = FALSE;
- ZEN_COM_CHECK(fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted));
-
- if (pfAnyOperationsAborted == TRUE)
- throw SysError(L"Operation did not complete successfully.");
-}
-
-
-void copyFile(const wchar_t* sourceFile, //throw SysError
- const wchar_t* targetFile)
-{
- ComPtr<IFileOperation> fileOp;
- ZEN_COM_CHECK(::CoCreateInstance(CLSID_FileOperation, //throw SysError
- nullptr,
- 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.
- ZEN_COM_CHECK(fileOp->SetOperationFlags(FOF_NOCONFIRMATION | //throw SysError
- FOF_SILENT |
- FOFX_EARLYFAILURE |
- FOF_NOERRORUI));
- //create source object
- ComPtr<IShellItem> psiSourceFile;
- {
- HRESULT hr = ::SHCreateItemFromParsingName(sourceFile,
- nullptr,
- IID_PPV_ARGS(psiSourceFile.init()));
- if (FAILED(hr))
- throw SysError(formatComError(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)
- throw SysError(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;
- {
- HRESULT hr = ::SHCreateItemFromParsingName(targetFolder.c_str(),
- nullptr,
- IID_PPV_ARGS(psiTargetFolder.init()));
- if (FAILED(hr))
- throw SysError(formatComError(std::wstring(L"Error calling \"SHCreateItemFromParsingName\" for folder:\n") + L"\"" + targetFolder + L"\".", hr));
- }
-
- //schedule file copy operation
- ZEN_COM_CHECK(fileOp->CopyItem(psiSourceFile.get(), psiTargetFolder.get(), targetFileNameShort.c_str(), nullptr));
-
- //perform actual operations
- ZEN_COM_CHECK(fileOp->PerformOperations());
-
- //check if errors occured: if FOFX_EARLYFAILURE is not used, PerformOperations() can return with success despite errors!
- BOOL pfAnyOperationsAborted = FALSE;
- ZEN_COM_CHECK(fileOp->GetAnyOperationsAborted(&pfAnyOperationsAborted));
-
- if (pfAnyOperationsAborted == TRUE)
- throw SysError(L"Operation did not complete successfully.");
-}
-
-
-void getFolderClsid(const wchar_t* dirname, CLSID& pathCLSID) //throw SysError
-{
- ComPtr<IShellFolder> desktopFolder;
- ZEN_COM_CHECK(::SHGetDesktopFolder(desktopFolder.init())); //throw SysError
-
- PIDLIST_RELATIVE pidlFolder = nullptr;
- ZEN_COM_CHECK(desktopFolder->ParseDisplayName(nullptr, // [in] HWND hwnd,
- nullptr, // [in] IBindCtx *pbc,
- const_cast<LPWSTR>(dirname), // [in] LPWSTR pszDisplayName,
- nullptr, // [out] ULONG *pchEaten,
- &pidlFolder, // [out] PIDLIST_RELATIVE* ppidl,
- nullptr)); // [in, out] ULONG *pdwAttributes
- ZEN_ON_SCOPE_EXIT(::ILFree(pidlFolder)); //older version: ::CoTaskMemFree
-
- ComPtr<IPersist> persistFolder;
- ZEN_COM_CHECK(desktopFolder->BindToObject(pidlFolder, // [in] PCUIDLIST_RELATIVE pidl,
- nullptr, // [in] IBindCtx *pbc,
- IID_PPV_ARGS(persistFolder.init()))); //throw SysError
-
- ZEN_COM_CHECK(persistFolder->GetClassID(&pathCLSID)); //throw SysError
-}
-
-
-std::vector<std::wstring> getLockingProcesses(const wchar_t* filename) //throw SysError
-{
- DWORD sessionHandle = 0;
- {
- wchar_t sessionKey[CCH_RM_SESSION_KEY + 1] = {}; //fixes two bugs: http://blogs.msdn.com/b/oldnewthing/archive/2012/02/17/10268840.aspx
- DWORD rv1 = ::RmStartSession(&sessionHandle, //__out DWORD *pSessionHandle,
- 0, //__reserved DWORD dwSessionFlags,
- sessionKey); //__out WCHAR strSessionKey[ ]
- if (rv1 != ERROR_SUCCESS)
- throw SysError(formatSystemError(L"RmStartSession", rv1));
- }
- ZEN_ON_SCOPE_EXIT(::RmEndSession(sessionHandle));
-
- {
- DWORD rv2 = ::RmRegisterResources(sessionHandle, //__in DWORD dwSessionHandle,
- 1, //__in UINT nFiles,
- &filename, //__in_opt LPCWSTR rgsFilenames[ ],
- 0, //__in UINT nApplications,
- nullptr, //__in_opt RM_UNIQUE_PROCESS rgApplications[ ],
- 0, //__in UINT nServices,
- nullptr); //__in_opt LPCWSTR rgsServiceNames[ ]
- if (rv2 != ERROR_SUCCESS)
- throw SysError(formatSystemError(L"RmRegisterResources", rv2));
- }
-
- std::vector<RM_PROCESS_INFO> procInfo;
- {
- UINT procInfoSize = 0;
- UINT procInfoSizeNeeded = 0;
- DWORD rebootReasons = 0;
- DWORD rv3 = ::RmGetList(sessionHandle, &procInfoSizeNeeded, &procInfoSize, nullptr, &rebootReasons); //get procInfoSizeNeeded
- if (rv3 == ERROR_SUCCESS)
- return std::vector<std::wstring>();
- if (rv3 != ERROR_MORE_DATA)
- throw SysError(formatSystemError(L"RmGetList", rv3));
- //C:\pagefile.sys fails with ERROR_SHARING_VIOLATION!
-
- if (procInfoSizeNeeded == 0)
- return std::vector<std::wstring>();
-
- procInfoSize = procInfoSizeNeeded;
- procInfo.resize(procInfoSizeNeeded);
-
- rv3 = ::RmGetList(sessionHandle, //__in DWORD dwSessionHandle,
- &procInfoSizeNeeded, //__out UINT *pnProcInfoNeeded,
- &procInfoSize, //__inout UINT *pnProcInfo,
- &procInfo[0], //__inout_opt RM_PROCESS_INFO rgAffectedApps[ ],
- &rebootReasons); //__out LPDWORD lpdwRebootReasons
- if (rv3 != ERROR_SUCCESS)
- throw SysError(formatSystemError(L"RmGetList", rv3));
- procInfo.resize(procInfoSize);
- }
-
- std::vector<std::wstring> output;
- for (auto iter = procInfo.begin(); iter != procInfo.end(); ++iter)
- {
- std::wstring processName = iter->strAppName;
-
- //try to get process path
- HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, //__in DWORD dwDesiredAccess,
- false, //__in BOOL bInheritHandle,
- iter->Process.dwProcessId); //__in DWORD dwProcessId
- if (hProcess)
- {
- ZEN_ON_SCOPE_EXIT(::CloseHandle(hProcess));
-
- FILETIME creationTime = {};
- FILETIME exitTime = {};
- FILETIME kernelTime = {};
- FILETIME userTime = {};
- if (::GetProcessTimes(hProcess, //__in HANDLE hProcess,
- &creationTime, //__out LPFILETIME lpCreationTime,
- &exitTime, //__out LPFILETIME lpExitTime,
- &kernelTime, //__out LPFILETIME lpKernelTime,
- &userTime)) //__out LPFILETIME lpUserTime
- if (::CompareFileTime(&iter->Process.ProcessStartTime, &creationTime) == 0)
- {
- DWORD bufferSize = MAX_PATH;
- std::vector<wchar_t> buffer(bufferSize);
- if (::QueryFullProcessImageName(hProcess, //__in HANDLE hProcess,
- 0, //__in DWORD dwFlags,
- &buffer[0], //__out LPTSTR lpExeName,
- &bufferSize)) //__inout PDWORD lpdwSize
- if (bufferSize < buffer.size())
- processName += std::wstring(L", ") + L"\"" + &buffer[0] + L"\"";
- }
- }
- output.push_back(processName);
- }
- return output;
-}
-
-
-boost::thread_specific_ptr<std::wstring> lastErrorMessage; //use "thread_local" in C++11
-}
-
-
-bool fileop::moveToRecycleBin(const wchar_t* fileNames[],
- size_t fileCount,
- RecyclerCallback callback,
- void* sink)
-{
- try
- {
- ::moveToRecycleBin(fileNames, fileCount, callback, sink); //throw SysError
- return true;
- }
- catch (const SysError& e)
- {
- lastErrorMessage.reset(new std::wstring(e.toString()));
- return false;
- }
-}
-
-
-bool fileop::copyFile(const wchar_t* sourceFile,
- const wchar_t* targetFile)
-{
- try
- {
- ::copyFile(sourceFile, targetFile); //throw SysError
- return true;
- }
- catch (const SysError& e)
- {
- lastErrorMessage.reset(new std::wstring(e.toString()));
- return false;
- }
-}
-
-
-bool fileop::checkRecycler(const wchar_t* dirname, bool& isRecycler)
-{
- try
- {
- CLSID clsid = {};
- getFolderClsid(dirname, clsid); //throw SysError
- isRecycler = ::IsEqualCLSID(clsid, CLSID_RecycleBin) == TRUE; //silence perf warning
- return true;
- }
- catch (const SysError& e)
- {
- lastErrorMessage.reset(new std::wstring(e.toString()));
- return false;
- }
-}
-
-
-const wchar_t* fileop::getLastError()
-{
- return !lastErrorMessage.get() ? L"" : lastErrorMessage->c_str();
-}
-
-
-bool fileop::getLockingProcesses(const wchar_t* filename, const wchar_t*& procList)
-{
- try
- {
- std::vector<std::wstring> processes = ::getLockingProcesses(filename); //throw SysError
-
- std::wstring buffer;
- std::for_each(processes.begin(), processes.end(), [&](const std::wstring& proc) { buffer += proc; buffer += L'\n'; });
- if (!processes.empty())
- buffer.resize(buffer.size() - 1); //remove last line break
-
- auto tmp = new wchar_t [buffer.size() + 1]; //bad_alloc ?
- ::wmemcpy(tmp, buffer.c_str(), buffer.size() + 1); //include 0-termination
- procList = tmp; //ownership passed
-
- return true;
- }
- catch (const SysError& e)
- {
- lastErrorMessage.reset(new std::wstring(e.toString()));
- return false;
- }
-}
-
-
-void fileop::freeString(const wchar_t* str)
-{
- delete [] str;
-}
diff --git a/zen/IFileOperation/file_op.h b/zen/IFileOperation/file_op.h
deleted file mode 100644
index 2f5d6f30..00000000
--- a/zen/IFileOperation/file_op.h
+++ /dev/null
@@ -1,87 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef RECYCLER_DLL_H
-#define RECYCLER_DLL_H
-
-#ifdef FILE_OP_DLL_EXPORTS
-#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport)
-#else
-#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport)
-#endif
-
-#include <zen/build_info.h>
-
-
-namespace fileop
-{
-/*--------------
- |declarations|
- --------------*/
-
-//COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize
-//minimum OS: Windows Vista or later
-
-//return false to abort operation
-typedef bool (*RecyclerCallback)(const wchar_t* filename, //current item; may be empty string!
- void* sink); //virtual function mechanism is not guaranteed to be compatible between different compilers, therefore we go the C-way
-
-DLL_FUNCTION_DECLARATION
-bool moveToRecycleBin(const wchar_t* fileNames[],
- size_t fileCount, //size of fileNames array
- RecyclerCallback callback, //optional
- void* sink); //
-
-DLL_FUNCTION_DECLARATION
-bool copyFile(const wchar_t* sourceFile,
- const wchar_t* targetFile);
-
-DLL_FUNCTION_DECLARATION
-bool checkRecycler(const wchar_t* dirname, bool& isRecycler); //returns false on error
-
-DLL_FUNCTION_DECLARATION
-bool getLockingProcesses(const wchar_t* filename, const wchar_t*& procList); //get list of processes as single string, call freeString(procList) after use!
-
-DLL_FUNCTION_DECLARATION
-void freeString(const wchar_t* str);
-
-//get last error message if any of the functions above fail
-DLL_FUNCTION_DECLARATION
-const wchar_t* getLastError(); //no nullptr check required!
-
-/*----------
- |typedefs|
- ----------*/
-typedef bool (*FunType_moveToRecycleBin)(const wchar_t* fileNames[],
- size_t fileCount,
- RecyclerCallback callback,
- void* sink);
-typedef bool (*FunType_copyFile)(const wchar_t* sourceFile, const wchar_t* targetFile);
-typedef bool (*FunType_checkRecycler)(const wchar_t* dirname, bool& isRecycler);
-typedef bool (*FunType_getLockingProcesses)(const wchar_t* filename, const wchar_t*& procList);
-typedef void (*FunType_freeString)(const wchar_t* str);
-typedef const wchar_t* (*FunType_getLastError)();
-
-/*--------------
- |symbol names|
- --------------*/
-//(use const pointers to ensure internal linkage)
-const char funName_moveToRecycleBin [] = "moveToRecycleBin";
-const char funName_copyFile [] = "copyFile";
-const char funName_checkRecycler [] = "checkRecycler";
-const char funName_getLockingProcesses[] = "getLockingProcesses";
-const char funName_freeString [] = "freeString";
-const char funName_getLastError [] = "getLastError";
-
-/*---------------
- |library names|
- ---------------*/
-inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"FileOperation_x64.dll" : L"FileOperation_Win32.dll"; }
-}
-
-#undef DLL_FUNCTION_DECLARATION
-
-#endif //RECYCLER_DLL_H
diff --git a/zen/base64.h b/zen/base64.h
deleted file mode 100644
index ae896e70..00000000
--- a/zen/base64.h
+++ /dev/null
@@ -1,157 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef BASE64_HEADER_08473021856321840873021487213453214
-#define BASE64_HEADER_08473021856321840873021487213453214
-
-#ifndef NDEBUG //no release build dependencies!
-#include <iterator>
-#include <cassert>
-#endif
-
-namespace zen
-{
-//http://en.wikipedia.org/wiki/Base64
-/*
-Usage:
- const std::string input = "Sample text";
- std::string output;
- zen::encodeBase64(input.begin(), input.end(), std::back_inserter(output));
- //output contains "U2FtcGxlIHRleHQ="
-*/
-template <class InputIterator, class OutputIterator>
-OutputIterator encodeBase64(InputIterator first, InputIterator last, OutputIterator result); //nothrow!
-
-template <class InputIterator, class OutputIterator>
-OutputIterator decodeBase64(InputIterator first, InputIterator last, OutputIterator result); //nothrow!
-
-
-
-
-
-
-
-
-
-
-
-
-//------------------------- implementation -------------------------------
-namespace implementation
-{
-//64 chars for base64 encoding + padding char
-const char ENCODING_MIME[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-const signed char DECODING_MIME[] =
-{
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 64, -1, -1,
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
-};
-const unsigned char INDEX_PAD = 64; //"="
-}
-
-
-//http://en.wikipedia.org/wiki/Base64
-template <class InputIterator, class OutputIterator> inline
-OutputIterator encodeBase64(InputIterator first, InputIterator last, OutputIterator result)
-{
- using namespace implementation;
- static_assert(sizeof(typename std::iterator_traits<InputIterator>::value_type) == 1, "");
- static_assert(sizeof(ENCODING_MIME) == 65 + 1, "");
-
- while (first != last)
- {
- const unsigned char a = static_cast<unsigned char>(*first++);
- *result++ = ENCODING_MIME[a >> 2];
-
- if (first == last)
- {
- *result++ = ENCODING_MIME[((a & 0x3) << 4)];
- *result++ = ENCODING_MIME[INDEX_PAD];
- *result++ = ENCODING_MIME[INDEX_PAD];
- break;
- }
- const unsigned char b = static_cast<unsigned char>(*first++);
- *result++ = ENCODING_MIME[((a & 0x3) << 4) | (b >> 4)];
-
- if (first == last)
- {
- *result++ = ENCODING_MIME[((b & 0xf) << 2)];
- *result++ = ENCODING_MIME[INDEX_PAD];
- break;
- }
- const unsigned char c = static_cast<unsigned char>(*first++);
- *result++ = ENCODING_MIME[((b & 0xf) << 2) | (c >> 6)];
- *result++ = ENCODING_MIME[c & 0x3f];
- }
-
- return result;
-}
-
-
-template <class InputIterator, class OutputIterator> inline
-OutputIterator decodeBase64(InputIterator first, InputIterator last, OutputIterator result)
-{
- using namespace implementation;
- static_assert(sizeof(typename std::iterator_traits<InputIterator>::value_type) == 1, "");
- static_assert(sizeof(DECODING_MIME) == 128, "");
-
- const unsigned char INDEX_END = INDEX_PAD + 1;
-
- auto readIndex = [&]() -> unsigned char //return index within [0, 64] or INDEX_END if end of input
- {
- while (true)
- {
- if (first == last)
- return INDEX_END;
-
- const unsigned char ch = static_cast<unsigned char>(*first++);
- if (ch < 128) //we're in lower ASCII table half
- {
- const int index = implementation::DECODING_MIME[ch];
- if (0 <= index && index <= static_cast<int>(INDEX_PAD)) //skip all unknown characters (including carriage return, line-break, tab)
- return index;
- }
- }
- };
-
- for (;;)
- {
- const unsigned char index1 = readIndex();
- const unsigned char index2 = readIndex();
- if (index1 >= INDEX_PAD || index2 >= INDEX_PAD)
- {
- assert(index1 == INDEX_END && index2 == INDEX_END);
- break;
- }
- *result++ = static_cast<char>((index1 << 2) | (index2 >> 4));
-
- const unsigned char index3 = readIndex();
- if (index3 >= INDEX_PAD) //padding
- {
- assert(index3 == INDEX_PAD);
- break;
- }
- *result++ = static_cast<char>(((index2 & 0xf) << 4) | (index3 >> 2));
-
- const unsigned char index4 = readIndex();
- if (index4 >= INDEX_PAD) //padding
- {
- assert(index4 == INDEX_PAD);
- break;
- }
- *result++ = static_cast<char>(((index3 & 0x3) << 6) | index4);
- }
- return result;
-}
-}
-
-#endif //BASE64_HEADER_08473021856321840873021487213453214
diff --git a/zen/com_error.h b/zen/com_error.h
deleted file mode 100644
index 5eb7611d..00000000
--- a/zen/com_error.h
+++ /dev/null
@@ -1,227 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef COM_ERROR_HEADER_88425703425254
-#define COM_ERROR_HEADER_88425703425254
-
-#include <cstdio>
-#include "sys_error.h"
-
-namespace zen
-{
-std::wstring formatComError(const std::wstring& msg, HRESULT hr);
-
-//Convenience Macros checking for COM errors:
-
-#define ZEN_COM_CHECK(func) ZEN_COM_CHECK_IMPL(func, #func) //throw SysError
-/*
-Example: ZEN_COM_CHECK(backupComp->InitializeForBackup());
-
-Equivalent to:
-{
- HRESULT hrInternal = backupComp->InitializeForBackup();
- if (FAILED(hrInternal))
- throw SysError(formatComError(L"Error calling \"backupComp->InitializeForBackup()\".", hrInternal));
-}
-*/
-
-#define ZEN_COM_ASSERT(obj) ZEN_COM_ASSERT_IMPL(obj, #obj) //throw SysError
-/*
-Example: ZEN_COM_ASSERT(obj);
-
-Equivalent to:
- if (!obj)
- throw SysError(formatComError(L"Assertion failed: \"obj\".", E_FAIL));
-*/
-
-
-
-
-
-
-//################# implementation #####################
-namespace impl
-{
-inline
-std::wstring formatWin32Message(DWORD dwMessageId) //return empty string on error
-{
- LPWSTR buffer = nullptr;
- if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_MAX_WIDTH_MASK |
- FORMAT_MESSAGE_IGNORE_INSERTS | //important: without this flag ::FormatMessage() will fail if message contains placeholders
- FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, dwMessageId, 0, reinterpret_cast<LPWSTR>(&buffer), 0, nullptr) != 0)
- if (buffer) //just to be sure
- {
- ZEN_ON_SCOPE_EXIT(::LocalFree(buffer));
- return buffer;
- }
- return std::wstring();
-}
-
-
-inline
-std::wstring numberToHexString(long number)
-{
- wchar_t buffer[100] = {};
- const int charsWritten = ::swprintf(buffer, 100, L"0x%08x", static_cast<int>(number));
- return charsWritten > 0 ? std::wstring(buffer, charsWritten) : std::wstring();
-}
-
-
-namespace
-{
-std::wstring formatFacility(HRESULT hr)
-{
- switch (HRESULT_FACILITY(hr))
- {
- case FACILITY_XPS:
- return L"XPS";
- case FACILITY_WINRM:
- return L"Windows Resource Manager";
- case FACILITY_WINDOWSUPDATE:
- return L"Windows Update";
- case FACILITY_WINDOWS_DEFENDER:
- return L"Windows Defender Component";
- case FACILITY_WINDOWS_CE:
- return L"Windows CE";
- case FACILITY_WINDOWS:
- return L"Windows Subsystem";
- case FACILITY_USERMODE_VOLMGR:
- return L"User Mode Volume Manager";
- case FACILITY_USERMODE_VIRTUALIZATION:
- return L"User Mode Virtualization Subsystem";
- case FACILITY_USERMODE_VHD:
- return L"User Mode Virtual Hard Disk Support";
- case FACILITY_URT:
- return L".NET CLR";
- case FACILITY_UMI:
- return L"Ubiquitous Memoryintrospection Service";
- case FACILITY_UI:
- return L"UI";
- case FACILITY_TPM_SOFTWARE:
- return L"Trusted Platform Module Applications";
- case FACILITY_TPM_SERVICES:
- return L"Trusted Platform Module Services";
- case FACILITY_SXS:
- return L"Side-by-side Servicing";
- case FACILITY_STORAGE:
- return L"OLE Storage";
- case FACILITY_STATE_MANAGEMENT:
- return L"State Management Services";
- case FACILITY_SCARD:
- return L"Smart-card Subsystem";
- case FACILITY_SHELL:
- return L"User Shell";
- case FACILITY_SETUPAPI:
- return L"Setup API";
- case FACILITY_SECURITY:
- return L"Security API Layer";
- case FACILITY_SDIAG:
- return L"System Diagnostics";
- case FACILITY_RPC:
- return L"RPC Subsystem";
- case FACILITY_RAS:
- return L"RAS";
- case FACILITY_PLA:
- return L"Performance Logs and Alerts";
- case FACILITY_OPC:
- return L"Open Connectivity Service";
- case FACILITY_WIN32:
- return L"Win32";
- case FACILITY_CONTROL:
- return L"Control Mechanism";
- case FACILITY_WEBSERVICES:
- return L"Web Services";
- case FACILITY_NDIS:
- return L"Network Driver Interface";
- case FACILITY_METADIRECTORY:
- return L"Microsoft Identity Server";
- case FACILITY_MSMQ:
- return L"Microsoft Message Queue";
- case FACILITY_MEDIASERVER:
- return L"Windows Media Server";
- case FACILITY_MBN:
- return L"MBN";
- case FACILITY_INTERNET:
- return L"Wininet";
- case FACILITY_ITF:
- return L"COM/OLE Interface Management";
- case FACILITY_USERMODE_HYPERVISOR:
- return L"Usermode Hypervisor Components";
- case FACILITY_HTTP:
- return L"HTTP Support";
- case FACILITY_GRAPHICS:
- return L"Graphics Drivers";
- case FACILITY_FWP:
- return L"Firewall Platform";
- case FACILITY_FVE:
- return L"Full volume encryption";
- case FACILITY_USERMODE_FILTER_MANAGER:
- return L"User Mode Filter Manager";
- case FACILITY_DPLAY:
- return L"Direct Play";
- case FACILITY_DISPATCH:
- return L"COM Dispatch";
- case FACILITY_DIRECTORYSERVICE:
- return L"Active Directory";
- case FACILITY_CONFIGURATION:
- return L"Configuration Services";
- case FACILITY_COMPLUS:
- return L"COM+";
- case FACILITY_USERMODE_COMMONLOG:
- return L"Common Logging Support";
- case FACILITY_CMI:
- return L"Configuration Management Infrastructure";
- case FACILITY_CERT:
- return L"Certificate";
- case FACILITY_BCD:
- return L"Boot Configuration Database";
- case FACILITY_BACKGROUNDCOPY:
- return L"Background Copy Control";
- case FACILITY_ACS:
- return L"Audit Collection Service";
- case FACILITY_AAF:
- return L"Microsoft Agent";
- default:
- return L"Unknown";
- }
-}
-}
-}
-
-
-std::wstring formatComError(const std::wstring& msg, long long hr); //not implemented! intentional overload ambiguity to catch usage errors with HRESULT!
-
-
-inline
-std::wstring formatComError(const std::wstring& msg, HRESULT hr)
-{
- std::wstring output(msg);
- output += L"\n";
-
- //don't use _com_error(hr).ErrorMessage(): internally this is nothing more than a call to ::FormatMessage()
- std::wstring win32Msg = impl::formatWin32Message(hr);
- if (!win32Msg.empty()) //empty string on error
- output += win32Msg + L"\n" + L"HRESULT: " + impl::numberToHexString(hr);
- else
- output += L"HRESULT: " + impl::numberToHexString(hr) + L", " + L"Facility: " + impl::formatFacility(hr);
- //don't bluntly interpret as Win32 error code HRESULT_CODE(hr), too often misleading!
- //http://blogs.msdn.com/b/oldnewthing/archive/2006/11/03/942851.aspx
-
- return output;
-}
-
-
-#define ZEN_COM_CHECK_IMPL(func, txt) \
- { \
- HRESULT hrInternal = func; \
- if (FAILED(hrInternal)) \
- throw zen::SysError(formatComError(std::wstring(L"Error calling \"") + L ## txt + L"\".", hrInternal)); \
- }
-
-#define ZEN_COM_ASSERT_IMPL(obj, txt) if (!(obj)) throw zen::SysError(formatComError(std::wstring(L"Assertion failed: \"") + L ## txt + L"\".", E_FAIL));
-}
-#endif //COM_ERROR_HEADER_88425703425254
diff --git a/zen/com_ptr.h b/zen/com_ptr.h
deleted file mode 100644
index 6fb9f2cd..00000000
--- a/zen/com_ptr.h
+++ /dev/null
@@ -1,120 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef SMART_COM_PTR_H
-#define SMART_COM_PTR_H
-
-#include <algorithm>
-#include "win.h" //includes "windows.h" -> always include before other headers that also might include "windows.h"!
-#include <Objbase.h>
-
-namespace zen
-{
-/*
-ComPtr: RAII class handling COM objects
-
-Example:
---------
- ComPtr<IUPnPDeviceFinder> devFinder;
- if (FAILED(::CoCreateInstance(CLSID_UPnPDeviceFinder,
- nullptr,
- 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() : ptr(nullptr) {} //
- ComPtr(const ComPtr& other) : ptr(other.ptr) { if (ptr) ptr->AddRef(); } //noexcept in C++11
- ComPtr( ComPtr&& tmp ) : ptr(tmp.release()) {} //
- ~ComPtr() { if (ptr) ptr->Release(); } //has exception spec of compiler-generated destructor by default
-
- ComPtr& operator=(const ComPtr& other) { ComPtr(other).swap(*this); return *this; } //noexcept in C++11
- ComPtr& operator=(ComPtr&& tmp) { swap(tmp); return *this; } //
- //don't use unifying assignment but save one move-construction in the r-value case instead!
-
- void swap(ComPtr& rhs) { std::swap(ptr, rhs.ptr); } //noexcept in C++11
-
- T** init() //get pointer for use with ::CoCreateInstance()
- {
- ComPtr<T>().swap(*this);
- return &ptr;
- }
-
- T* get() const { return ptr; }
-
- T* operator->() const { return ptr; }
- T& operator* () const { return *ptr; }
-
- T* release() //noexcept in C++11
- {
- T* tmp = ptr;
- ptr = nullptr;
- return tmp;
- }
-
-private:
- T* ptr;
-
- struct ConversionToBool { int dummy; };
-public:
- //use member pointer as implicit conversion to bool (C++ Templates - Vandevoorde/Josuttis; chapter 20)
- operator int ConversionToBool::* () const { return ptr != nullptr ? &ConversionToBool::dummy : nullptr; }
-};
-
-
-template <class S, class T>
-ComPtr<S> com_dynamic_cast(const ComPtr<T>& other); //noexcept in C++11
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//################# implementation #############################
-
-//we cannot partially 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(zen::ComPtr<T>& lhs, zen::ComPtr<T>& rhs)
-{
- lhs.swap(rhs);
-}
-
-
-template <class S, class T> inline
-ComPtr<S> com_dynamic_cast(const ComPtr<T>& other) //noexcept in C++11
-{
- 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/zen/com_util.h b/zen/com_util.h
deleted file mode 100644
index 5189b48e..00000000
--- a/zen/com_util.h
+++ /dev/null
@@ -1,121 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef COM_UTILITY_HEADER
-#define COM_UTILITY_HEADER
-
-#include "com_ptr.h"
-#include <string>
-#include <cassert>
-
-namespace zen
-{
-//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) { str_ = ::SysAllocStringLen(str.data(), str.length()); } //string::data() returns unmodified string potentially containing 0-values
- ~Bstring() { if (str_) ::SysFreeString(str_); }
-
- const BSTR get() const { return str_; }
-
-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(), nullptr) == 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 = nullptr;
- if (FAILED((comObj.get()->*memFun)(&bstr)))
- return std::wstring();
-
- if (bstr) //nullptr means "no text"
- {
- text = std::wstring(bstr, ::SysStringLen(bstr)); //correctly copy 0-characters
- ::SysFreeString(bstr);
- }
- }
- return text;
-}
-}
-
-
-#endif //COM_UTILITY_HEADER
diff --git a/zen/debug_log.h b/zen/debug_log.h
deleted file mode 100644
index ad27b66e..00000000
--- a/zen/debug_log.h
+++ /dev/null
@@ -1,94 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef DEBUG_LOG_HEADER_017324601673246392184621895740256342
-#define DEBUG_LOG_HEADER_017324601673246392184621895740256342
-
-#include <string>
-#include <cstdio>
-#include <memory>
-#include "deprecate.h"
-#include "string_tools.h"
-#include "time.h"
-
-
-//small macro for writing debug information into a logfile
-#define WRITE_LOG(x) globalLogFile().write(__FILE__, __LINE__, x);
-
-//speed alternative: wxLogDebug(wxT("text")) + DebugView
-
-
-namespace zen
-{
-#ifdef ZEN_WIN
-const char ZEN_FILE_NAME_SEPARATOR = '\\';
-#elif defined ZEN_LINUX || defined ZEN_MAC
-const char ZEN_FILE_NAME_SEPARATOR = '/';
-#endif
-
-class DebugLog
-{
-public:
- class LogError {};
-
- ZEN_DEPRECATE
- DebugLog(const std::string& filePrefix = std::string()) :
- filename(filePrefix + "DEBUG_" + formatTime<std::string>("%Y-%m-%d %H%M%S") + ".log"),
- rowCount(0),
- handle(std::fopen(filename.c_str(), "w")) //Windows: non binary mode: automatically convert "\n" to "\r\n"; Linux: binary is default!
- {
- if (!handle)
- throw LogError();
- }
-
- ~DebugLog() { std::fclose(handle); }
-
- void write(const std::string& sourceFile,
- int sourceRow,
- const std::string& message)
- {
- const std::string logEntry = "[" + formatTime<std::string>(FORMAT_TIME) + "] " + afterLast(sourceFile, ZEN_FILE_NAME_SEPARATOR) +
- " (" + numberTo<std::string>(sourceRow) + "): " + message + "\n";
-
- const size_t bytesWritten = ::fwrite(logEntry.c_str(), 1, logEntry.size(), handle);
- if (std::ferror(handle) != 0 || bytesWritten != logEntry.size())
- throw LogError();
-
- if (std::fflush(handle) != 0)
- throw LogError();
-
- ++rowCount;
- }
-
- size_t getRows() const { return rowCount; }
-
- std::string getFileName() const { return filename; }
-
-private:
- std::string filename;
- size_t rowCount;
- FILE* handle;
-};
-
-
-inline
-DebugLog& globalLogFile()
-{
- static std::unique_ptr<DebugLog> inst(new DebugLog); //external linkage despite header definition!
-
- if (inst->getRows() > 50000) //prevent logfile from becoming too big
- {
- const std::string oldName = inst->getFileName();
- inst.reset();
- std::remove(oldName.c_str()); //unchecked deletion!
- inst.reset(new DebugLog);
- }
-
- return *inst;
-}
-}
-
-#endif //DEBUG_LOG_HEADER_017324601673246392184621895740256342
diff --git a/zen/debug_memory_leaks.cpp b/zen/debug_memory_leaks.cpp
deleted file mode 100644
index 2359b6ef..00000000
--- a/zen/debug_memory_leaks.cpp
+++ /dev/null
@@ -1,30 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-//-----------Memory Leak Detection--------------------------
-//Usage: just include this file into a Visual Studio project
-
-
-#ifdef _DEBUG //When _DEBUG is not defined, calls to _CrtSetDbgFlag are removed during preprocessing.
-#define _CRTDBG_MAP_ALLOC //
-#include <stdlib.h> //keep this order: "The #include statements must be in the order shown here. If you change the order, the functions you use may not work properly."
-#include <crtdbg.h> //overwrites "operator new" ect; no need to include this in every compilation unit!
-//http://msdn.microsoft.com/en-us/library/e5ewb1h3(v=vs.80).aspx
-
-namespace
-{
-struct OnStartup
-{
- OnStartup()
- {
- //note: wxWidgets also activates leak detection in "src/common/init.cpp" using a macro that is equivalent to:
- int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
- _CrtSetDbgFlag(flags | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
- }
-
-} dummy;
-}
-#endif //_DEBUG \ No newline at end of file
diff --git a/zen/debug_minidump.cpp b/zen/debug_minidump.cpp
deleted file mode 100644
index 29500ae4..00000000
--- a/zen/debug_minidump.cpp
+++ /dev/null
@@ -1,143 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "debug_minidump.h"
-#include <string>
-#include <sstream>
-#include <cassert>
-#include <cstdlib> //malloc(), free()
-#include <zen/file_error.h>
-#include <zen/scope_guard.h>
-#include <zen/time.h>
-#include "win.h" //includes "windows.h"
-#include "DbgHelp.h" //available for MSC only
-#pragma comment(lib, "Dbghelp.lib")
-
-using namespace zen;
-
-
-namespace
-{
-LONG WINAPI writeDumpOnException(EXCEPTION_POINTERS* pExceptionInfo) //blocks showing message boxes on success and error!
-{
- assert(false);
-
- const Zstring filename = L"CrashDump " + formatTime<Zstring>(L"%Y-%m-%d %H%M%S") + L".dmp";
-
- {
- HANDLE hFile = ::CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile == INVALID_HANDLE_VALUE)
- {
- ::MessageBox(nullptr, (replaceCpy<std::wstring>(L"Cannot write file %x.", L"%x", fmtFileName(filename)) + L"\n\n" + formatSystemError(L"CreateFile", ::GetLastError())).c_str(), L"Application Crash", MB_SERVICE_NOTIFICATION | MB_ICONERROR);
- std::terminate();
- }
- ZEN_ON_SCOPE_EXIT(::CloseHandle(hFile));
-
- MINIDUMP_EXCEPTION_INFORMATION exInfo = {};
- exInfo.ThreadId = ::GetCurrentThreadId();
- exInfo.ExceptionPointers = pExceptionInfo;
- exInfo.ClientPointers = FALSE;
-
- MINIDUMP_EXCEPTION_INFORMATION* exceptParam = pExceptionInfo ? &exInfo : nullptr;
-
- if (!::MiniDumpWriteDump(::GetCurrentProcess (), //__in HANDLE hProcess,
- ::GetCurrentProcessId(), //__in DWORD ProcessId,
- hFile, //__in HANDLE hFile,
- MiniDumpWithDataSegs, //__in MINIDUMP_TYPE DumpType, ->Standard: MiniDumpNormal, Medium: MiniDumpWithDataSegs, Full: MiniDumpWithFullMemory
- exceptParam, //__in PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
- nullptr, //__in PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
- nullptr)) //__in PMINIDUMP_CALLBACK_INFORMATION CallbackParam
- {
- ::MessageBox(nullptr, (replaceCpy<std::wstring>(L"Cannot write file %x.", L"%x", fmtFileName(filename)) + L"\n\n" + formatSystemError(L"MiniDumpWriteDump", ::GetLastError())).c_str(), L"Application Crash", MB_SERVICE_NOTIFICATION | MB_ICONERROR);
- std::terminate();
- }
- } //close file before showing success message
-
- //attention: the app has not yet officially crashed! => use MB_SERVICE_NOTIFICATION to avoid Win32 GUI callbacks while message box is shown!
- ::MessageBox(nullptr, replaceCpy<std::wstring>(L"Crash dump file %x written!", L"%x", fmtFileName(filename)).c_str(), L"Application Crash", MB_SERVICE_NOTIFICATION | MB_ICONERROR);
- std::terminate();
-
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-//ensure that a dump-file is written for uncaught exceptions
-struct OnStartup {
- OnStartup()
- {
- /*LPTOP_LEVEL_EXCEPTION_FILTER oldFilter = */ ::SetUnhandledExceptionFilter(writeDumpOnException);
- //oldFilter == &__CxxUnhandledExceptionFilter() by default!
- }} dummy;
-}
-
-
-void debug_tools::writeMinidump()
-{
- //force exception to catch the state of this thread and hopefully get a valid call stack
- __try
- {
- ::RaiseException(EXCEPTION_BREAKPOINT, 0, 0, nullptr);
- }
- __except (writeDumpOnException(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {}
- //don't use EXCEPTION_CONTINUE_EXECUTION: although used in most minidump examples this resulted in an infinite loop in tests
- //although it really should not: http://msdn.microsoft.com/en-us/library/c34eyfac.aspx
-}
-
-
-/*
-No need to include the "operator new" declarations into every compilation unit:
-
-[basic.stc.dynamic]
-"A C++ program shall provide at most one definition of a replaceable allocation or deallocation function.
-Any such function definition replaces the default version provided in the library (17.6.4.6).
-The following allocation and deallocation functions (18.6) are implicitly declared in global scope in each translation unit of a program.
-void* operator new(std::size_t);
-void* operator new[](std::size_t);
-void operator delete(void*);
-void operator delete[](void*);"
-*/
-
-namespace
-{
-class BadAllocDetailed : public std::bad_alloc
-{
-public:
- explicit BadAllocDetailed(size_t allocSize)
- {
- errorMsg = "Memory allocation failed: ";
- errorMsg += numberToString(allocSize);
- }
-
- virtual const char* what() const throw()
- {
- return errorMsg.c_str();
- }
-
-private:
- template <class T>
- static std::string numberToString(const T& number) //convert number to string the (slow) C++ way
- {
- std::ostringstream ss;
- ss << number;
- return ss.str();
- }
-
- std::string errorMsg;
-};
-}
-
-void* operator new(size_t size)
-{
- if (void* ptr = ::malloc(size))
- return ptr;
-
- debug_tools::writeMinidump();
- throw ::BadAllocDetailed(size);
-}
-
-void operator delete(void* ptr) { ::free(ptr); }
-
-void* operator new[](size_t size) { return operator new(size); }
-void operator delete[](void* ptr) { operator delete(ptr); }
diff --git a/zen/debug_minidump.h b/zen/debug_minidump.h
deleted file mode 100644
index 2ef43039..00000000
--- a/zen/debug_minidump.h
+++ /dev/null
@@ -1,38 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef DEBUGNEW_H_INCLUDED
-#define DEBUGNEW_H_INCLUDED
-
-#ifndef _MSC_VER
-#error currently for use with MSC only
-#endif
-
-/*
-Better std::bad_alloc
----------------------
-overwrite "operator new" to automatically write mini dump and get info about bytes requested:
-1. Compile "debug_minidump.cpp"
-
-Minidumps http://msdn.microsoft.com/en-us/library/windows/desktop/ee416349(v=vs.85).aspx
-----------------------------------------------------------------------------------------
-1. Compile "debug_minidump.cpp"
-2. Compile "release" build with:
- - C/C++ -> General: Debug Information Format: "Program Database" (/Zi).
- - C/C++ -> Optimization: Omit Frame Pointers: No (/Oy-) - avoid call stack mess up!
- - Linker -> Debugging: Generate Debug Info: Yes (/DEBUG)
- - Linker -> Optimization: References: Yes (/OPT:REF).
- - Linker -> Optimization: Enable COMDAT Folding: Yes (/OPT:ICF).
-Optional:
- - C/C++ -> Optimization: Disabled (/Od)
-*/
-
-namespace debug_tools
-{
-void writeMinidump();
-}
-
-#endif // DEBUGNEW_H_INCLUDED
diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp
index 563a07ce..e7503dad 100644
--- a/zen/file_handling.cpp
+++ b/zen/file_handling.cpp
@@ -106,8 +106,23 @@ bool zen::somethingExists(const Zstring& objname)
const DWORD attr = ::GetFileAttributes(applyLongPathPrefix(objname).c_str());
if (attr != INVALID_FILE_ATTRIBUTES)
return true;
- if (::GetLastError() == ERROR_SHARING_VIOLATION) //"C:\pagefile.sys"
- return true;
+ const ErrorCode lastError = getLastError();
+
+ //handle obscure file permission problem where ::GetFileAttributes() fails with ERROR_ACCESS_DENIED or ERROR_SHARING_VIOLATION
+ //while parent directory traversal is successful: e.g. "C:\pagefile.sys"
+ if (lastError != ERROR_PATH_NOT_FOUND && //perf: short circuit for common "not existing" error codes
+ lastError != ERROR_FILE_NOT_FOUND && //
+ lastError != ERROR_BAD_NETPATH && //
+ lastError != ERROR_BAD_NET_NAME) //
+ {
+ WIN32_FIND_DATA fileInfo = {};
+ const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(objname).c_str(), &fileInfo);
+ if (searchHandle != INVALID_HANDLE_VALUE)
+ {
+ ::FindClose(searchHandle);
+ return true;
+ }
+ }
#elif defined ZEN_LINUX || defined ZEN_MAC
struct ::stat fileInfo = {};
@@ -238,7 +253,7 @@ bool zen::removeFile(const Zstring& filename) //throw FileError
}
#endif
if (!somethingExists(filename)) //warning: changes global error code!!
- return false; //neither file nor any other object (e.g. broken symlink) with that name existing
+ return false; //neither file nor any other object (e.g. broken symlink) with that name existing - caveat: what if "access is denied"!?!??!?!?
//begin of "regular" error reporting
const std::wstring errorMsg = replaceCpy(_("Cannot delete file %x."), L"%x", fmtFileName(filename));
@@ -2006,7 +2021,7 @@ void copyFileWindowsDefault(const Zstring& sourceFile,
if (lastError == ERROR_PATH_NOT_FOUND)
{
guardTarget.dismiss(); //not relevant
- throw ErrorTargetPathMissing(errorMsg, errorDescr);
+ throw ErrorTargetPathMissing(errorMsg, errorDescr); //could this also be source path missing!?
}
try //add more meaningful message
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index 70593d1d..389833f2 100644
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -353,8 +353,8 @@ private:
typename Trav::DirHandle searchHandle;
- if (!tryReportingDirError([&] { Trav::create(dirname, searchHandle); /*throw FileError*/ }, sink))
- return; //ignored error
+ if (!tryReportingDirError([&] { Trav::create(dirname, searchHandle); /*throw FileError*/ }, sink))
+ return; //ignored error
ZEN_ON_SCOPE_EXIT(Trav::destroy(searchHandle));
typename Trav::FindData findData = {};
diff --git a/zen/i18n.h b/zen/i18n.h
index 6b8cf142..5aedc41c 100644
--- a/zen/i18n.h
+++ b/zen/i18n.h
@@ -14,9 +14,11 @@
//minimal layer enabling text translation - without platform/library dependencies!
+#ifdef __WXMSW__ //we have wxWidgets
#ifndef WXINTL_NO_GETTEXT_MACRO
#error WXINTL_NO_GETTEXT_MACRO must be defined to deactivate wxWidgets underscore macro
#endif
+#endif
#define ZEN_TRANS_CONCAT_SUB(X, Y) X ## Y
#define _(s) zen::implementation::translate(ZEN_TRANS_CONCAT_SUB(L, s))
diff --git a/zen/read_txt.cpp b/zen/read_txt.cpp
deleted file mode 100644
index 23649846..00000000
--- a/zen/read_txt.cpp
+++ /dev/null
@@ -1,99 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "read_txt.h"
-
-using namespace zen;
-
-
-namespace
-{
-warn_static("superfluous method")
-std::string detectLineBreak(const Zstring& filename) //throw FileError
-{
- //read a (hopefully) significant portion of data
- zen::FileInput input(filename);
-
- std::vector<char> buffer(64 * 1024);
- size_t bytesRead = input.read(&buffer[0], buffer.size()); //throw FileError
- buffer.resize(bytesRead);
-
- //detect line break
- std::string linebreakChars = "\r\n";
- std::vector<char>::iterator iter = std::find_first_of(buffer.begin(), buffer.end(),
- linebreakChars.begin(), linebreakChars.end());
- if (iter != buffer.end())
- {
- if (*iter == '\r')
- {
- ++iter;
- if (iter != buffer.end())
- {
-
- if (*iter == '\n')
- return "\r\n"; //Windows
- else
- return "\r"; //Mac
- }
- }
- else if (*iter == '\n')
- return "\n"; //Linux
- }
- //fallback
- return "\n";
-}
-}
-
-
-LineExtractor::LineExtractor(const Zstring& filename, const std::string& lineBreak) : //throw FileError
- inputStream(filename), bufferLogBegin(buffer.begin()), lineBreak_(lineBreak)
-{
- if (lineBreak.empty())
- lineBreak_ = detectLineBreak(filename); //throw FileError
-}
-
-
-bool LineExtractor::getLine(std::string& output) //throw FileError
-{
- warn_static("don't use lineBreak, but support any of r, n, rn!!!")
- for (;;)
- {
- //check if full line is in buffer
- std::vector<char>::iterator iter = std::search(bufferLogBegin, buffer.end(), lineBreak_.begin(), lineBreak_.end());
- if (iter != buffer.end())
- {
- output.assign(bufferLogBegin, iter);
- bufferLogBegin = iter + lineBreak_.size();
- return true;
- }
-
- buffer.erase(buffer.begin(), bufferLogBegin);
- bufferLogBegin = buffer.begin();
-
- //if done: cleanup
- if (inputStream.eof())
- {
- if (buffer.empty())
- return false;
-
- output.assign(buffer.begin(), buffer.end());
- buffer.clear();
- return true;
- }
-
- //read next block
- const size_t BLOCK_SIZE = 512 * 1024;
- buffer.resize(buffer.size() + BLOCK_SIZE);
-
- size_t bytesRead = inputStream.read(&buffer[0] + buffer.size() - BLOCK_SIZE, BLOCK_SIZE); //throw FileError
- assert(bytesRead <= BLOCK_SIZE); //promised by FileInput()
-
- if (bytesRead < BLOCK_SIZE)
- buffer.resize(buffer.size() - (BLOCK_SIZE - bytesRead));
-
- bufferLogBegin = buffer.begin();
- }
-}
diff --git a/zen/read_txt.h b/zen/read_txt.h
deleted file mode 100644
index 92892716..00000000
--- a/zen/read_txt.h
+++ /dev/null
@@ -1,32 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef PARSE_TXT_H_INCLUDED
-#define PARSE_TXT_H_INCLUDED
-
-#include "file_io.h"
-#include <vector>
-#include <string>
-
-namespace zen
-{
-class LineExtractor
-{
-public:
- LineExtractor(const Zstring& filename, const std::string& lineBreak = std::string()); //throw FileError
- bool getLine(std::string& output); //throw FileError
-
-private:
- zen::FileInput inputStream;
- std::vector<char> buffer;
- std::vector<char>::iterator bufferLogBegin;
- std::string lineBreak_;
-};
-
-}
-
-
-#endif // PARSE_TXT_H_INCLUDED
diff --git a/zen/recycler.cpp b/zen/recycler.cpp
index 16c2ac11..11b599d4 100644
--- a/zen/recycler.cpp
+++ b/zen/recycler.cpp
@@ -103,13 +103,13 @@ void zen::recycleOrDelete(const std::vector<Zstring>& filenames, const std::func
if (!moveToRecycler(&cNames[0], cNames.size(), recyclerCallback, &cbd))
{
if (cbd.exceptionInUserCallback)
- try
- {
- assert(notifyDeletionStatus);
- notifyDeletionStatus(Zstring()); //should throw again!!!
- assert(false);
- }
- catch (...) { throw; }
+ try
+ {
+ assert(notifyDeletionStatus);
+ notifyDeletionStatus(Zstring()); //should throw again!!!
+ assert(false);
+ }
+ catch (...) { throw; }
std::wstring filenameFmt = fmtFileName(filenames[0]); //probably not the correct file name for file lists larger than 1!
if (filenames.size() > 1)
diff --git a/zen/recycler.h b/zen/recycler.h
index 80b31160..8068c4ec 100644
--- a/zen/recycler.h
+++ b/zen/recycler.h
@@ -46,8 +46,8 @@ StatusRecycler recycleBinStatus(const Zstring& pathName); //test existence of Re
//Win: blocks heavily if recycle bin is really full and drive is slow!!!
void recycleOrDelete(const std::vector<Zstring>& filenames, //throw FileError, return "true" if file/dir was actually deleted
- //may throw: first exception is swallowed, updateStatus() is then called again where it should throw again and the exception will propagate as expected
- const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus); //optional; currentItem may be empty
+ //may throw: first exception is swallowed, updateStatus() is then called again where it should throw again and the exception will propagate as expected
+ const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus); //optional; currentItem may be empty
#endif
}
diff --git a/zen/scroll_window_under_cursor.cpp b/zen/scroll_window_under_cursor.cpp
deleted file mode 100644
index 76a5ab4a..00000000
--- a/zen/scroll_window_under_cursor.cpp
+++ /dev/null
@@ -1,72 +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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-//redirect mouse wheel events directly to window under cursor rather than window having input focus
-//implementing new Windows Vista UI guidelines: http://msdn.microsoft.com/en-us/library/bb545459.aspx#wheel
-//this is confirmed to be required for at least Windows 2000 to Windows 8
-//on Ubuntu Linux, this is already the default behavior
-
-//Usage: just include this file into a Windows project
-
-#include <cassert>
-#include "win.h" //includes "windows.h"
-#include <Windowsx.h> //WM_MOUSEWHEEL
-
-
-namespace
-{
-LRESULT CALLBACK mouseInputHook(int nCode, WPARAM wParam, LPARAM lParam)
-{
- //"if nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function
- //without further processing and should return the value returned by CallNextHookEx"
- if (nCode == HC_ACTION) //the only valid value for this hook type
- {
- MSG& msgInfo = *reinterpret_cast<MSG*>(lParam);
-
- if (msgInfo.message == WM_MOUSEWHEEL ||
- msgInfo.message == WM_MOUSEHWHEEL)
- {
- POINT pt = {};
- pt.x = GET_X_LPARAM(msgInfo.lParam); //yes, there's also msgInfo.pt, but let's not take chances
- pt.y = GET_Y_LPARAM(msgInfo.lParam); //
-
- //visible child window directly under cursor; attention: not necessarily from our process!
- if (HWND hWin = ::WindowFromPoint(pt)) //http://blogs.msdn.com/b/oldnewthing/archive/2010/12/30/10110077.aspx
- if (msgInfo.hwnd != hWin && ::GetCapture() == nullptr)
- {
- DWORD winProcessId = 0;
- ::GetWindowThreadProcessId( //no-fail!
- hWin, //_In_ HWND hWnd,
- &winProcessId); //_Out_opt_ LPDWORD lpdwProcessId
- if (winProcessId == ::GetCurrentProcessId()) //no-fail!
- msgInfo.hwnd = hWin; //it would be a bug to set handle from another process here
- }
- }
- }
- return ::CallNextHookEx(nullptr, nCode, wParam, lParam);
-}
-
-struct InstallMouseHook
-{
- InstallMouseHook()
- {
- hHook = ::SetWindowsHookEx(WH_GETMESSAGE, //__in int idHook,
- mouseInputHook, //__in HOOKPROC lpfn,
- nullptr, //__in HINSTANCE hMod,
- ::GetCurrentThreadId()); //__in DWORD dwThreadId
- assert(hHook);
- }
-
- ~InstallMouseHook()
- {
- if (hHook)
- ::UnhookWindowsHookEx(hHook);
- }
-
-private:
- HHOOK hHook;
-} dummy;
-}
diff --git a/zen/stl_tools.h b/zen/stl_tools.h
index 92cd86ad..38752e67 100644
--- a/zen/stl_tools.h
+++ b/zen/stl_tools.h
@@ -94,7 +94,7 @@ void vector_remove_if(V& vec, Predicate p)
template <class V, class W> inline
void vector_append(V& vec, W& vec2)
{
-vec.insert(vec.end(), vec2.begin(), vec2.end());
+ vec.insert(vec.end(), vec2.begin(), vec2.end());
}
diff --git a/zen/string_base.h b/zen/string_base.h
index 0e3bbdd3..c134a6fc 100644
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -171,7 +171,7 @@ private:
Descriptor(int rc, size_t len, size_t cap) :
length (static_cast<std::uint32_t>(len)),
capacity(static_cast<std::uint32_t>(cap)),
- refCount(rc) { assert_static(ATOMIC_INT_LOCK_FREE == 2); } //2: "the types are always lock-free"
+ refCount(rc) { assert_static(ATOMIC_INT_LOCK_FREE == 2); } //2: "the types are always lock-free"
std::uint32_t length;
std::uint32_t capacity; //allocated size without null-termination
diff --git a/zen/xml_io.cpp b/zen/xml_io.cpp
new file mode 100644
index 00000000..4b9abc29
--- /dev/null
+++ b/zen/xml_io.cpp
@@ -0,0 +1,88 @@
+// **************************************************************************
+// * 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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+#include "xml_io.h"
+#include <zen/file_handling.h>
+#include <zen/file_io.h>
+#include <zen/serialize.h>
+
+using namespace zen;
+
+
+XmlDoc zen::loadXmlDocument(const Zstring& filename) //throw FileError
+{
+ //can't simply use zen::loadBinStream() due to the short-circuit xml-validation below!
+
+ std::string stream;
+
+ FileInput inputFile(filename); //throw FileError
+ {
+ //quick test whether input is an XML: avoid loading large binary files up front!
+ const std::string xmlBegin = "<?xml version=";
+ stream.resize(strLength(BYTE_ORDER_MARK_UTF8) + xmlBegin.size());
+
+ const size_t bytesRead = inputFile.read(&stream[0], stream.size()); //throw FileError
+ stream.resize(bytesRead);
+
+ if (!startsWith(stream, xmlBegin) &&
+ !startsWith(stream, BYTE_ORDER_MARK_UTF8 + xmlBegin)) //respect BOM!
+ throw FileError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtFileName(filename)));
+ }
+
+ const size_t blockSize = 128 * 1024;
+ do
+ {
+ stream.resize(stream.size() + blockSize);
+
+ const size_t bytesRead = inputFile.read(&*stream.begin() + stream.size() - blockSize, blockSize); //throw FileError
+ if (bytesRead < blockSize)
+ stream.resize(stream.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics
+ }
+ while (!inputFile.eof());
+
+ try
+ {
+ return parse(stream); //throw XmlParsingError
+ }
+ catch (const XmlParsingError& e)
+ {
+ throw FileError(
+ replaceCpy(replaceCpy(replaceCpy(_("Error parsing file %x, row %y, column %z."),
+ L"%x", fmtFileName(filename)),
+ L"%y", numberTo<std::wstring>(e.row + 1)),
+ L"%z", numberTo<std::wstring>(e.col + 1)));
+ }
+}
+
+
+void zen::saveXmlDocument(const XmlDoc& doc, const Zstring& filename) //throw FileError
+{
+ std::string stream = serialize(doc); //noexcept
+
+ try
+ {
+ if (getFilesize(filename) == stream.size()) //throw FileError
+ if (loadBinStream<std::string>(filename) == stream) //throw FileError
+ return;
+ }
+ catch (FileError&) {}
+
+ FileOutput outputFile(filename, FileOutput::ACC_OVERWRITE); //throw FileError
+ outputFile.write(stream.c_str(), stream.length()); //
+}
+
+
+void zen::checkForMappingErrors(const XmlIn& xmlInput, const Zstring& filename) //throw FileError
+{
+ if (xmlInput.errorsOccured())
+ {
+ std::wstring msg = _("Cannot read the following XML elements:") + L"\n";
+ for (const std::wstring& elem : xmlInput.getErrorsAs<std::wstring>())
+ msg += L"\n" + elem;
+
+ throw FileError(replaceCpy(_("Configuration file %x loaded partially only."), L"%x", fmtFileName(filename)) + L"\n\n" + msg);
+ }
+}
diff --git a/zen/xml_io.h b/zen/xml_io.h
new file mode 100644
index 00000000..b53a5ef4
--- /dev/null
+++ b/zen/xml_io.h
@@ -0,0 +1,27 @@
+// **************************************************************************
+// * 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) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+#ifndef XMLBASE_H_INCLUDED
+#define XMLBASE_H_INCLUDED
+
+#include <zenxml/xml.h>
+#include <zen/zstring.h>
+#include <zen/file_error.h>
+
+//combine zen::Xml and zen file i/o
+//-> loadXmlDocument vs loadStream:
+//1. better error reporting
+//2. quick exit if (potentially large) input file is not an XML
+
+namespace zen
+{
+XmlDoc loadXmlDocument(const Zstring& filename); //throw FileError
+void checkForMappingErrors(const XmlIn& xmlInput, const Zstring& filename); //throw FileError
+
+void saveXmlDocument(const XmlDoc& doc, const Zstring& filename); //throw FileError
+}
+
+#endif // XMLBASE_H_INCLUDED
bgstack15