diff options
Diffstat (limited to 'zen/FindFilePlus')
-rw-r--r-- | zen/FindFilePlus/FindFilePlus.vcxproj | 173 | ||||
-rw-r--r-- | zen/FindFilePlus/dll_main.cpp | 66 | ||||
-rw-r--r-- | zen/FindFilePlus/find_file_plus.cpp | 452 | ||||
-rw-r--r-- | zen/FindFilePlus/find_file_plus.h | 92 | ||||
-rw-r--r-- | zen/FindFilePlus/init_dll_binding.h | 16 | ||||
-rw-r--r-- | zen/FindFilePlus/load_dll.cpp | 23 | ||||
-rw-r--r-- | zen/FindFilePlus/load_dll.h | 45 |
7 files changed, 0 insertions, 867 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 |