summaryrefslogtreecommitdiff
path: root/lib/FindFilePlus
diff options
context:
space:
mode:
Diffstat (limited to 'lib/FindFilePlus')
-rw-r--r--lib/FindFilePlus/FindFilePlus.vcxproj245
-rw-r--r--lib/FindFilePlus/dll_main.cpp30
-rw-r--r--lib/FindFilePlus/find_file_plus.cpp298
-rw-r--r--lib/FindFilePlus/find_file_plus.h78
-rw-r--r--lib/FindFilePlus/init_dll_binding.h16
-rw-r--r--lib/FindFilePlus/load_dll.cpp23
-rw-r--r--lib/FindFilePlus/load_dll.h47
7 files changed, 737 insertions, 0 deletions
diff --git a/lib/FindFilePlus/FindFilePlus.vcxproj b/lib/FindFilePlus/FindFilePlus.vcxproj
new file mode 100644
index 00000000..2c4256a6
--- /dev/null
+++ b/lib/FindFilePlus/FindFilePlus.vcxproj
@@ -0,0 +1,245 @@
+<?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>{70394AEF-5897-4911-AFA1-82EAF0581EFA}</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>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">FindFilePlus_$(Platform)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">FindFilePlus_$(Platform)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">FindFilePlus_$(Platform)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">FindFilePlus_$(Platform)</TargetName>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <BuildLog>
+ <Path>$(IntDir)Build.html</Path>
+ </BuildLog>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_X86_;_DEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4100</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>
+ </ProfileGuidedDatabase>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <BuildLog>
+ <Path>$(IntDir)Build.html</Path>
+ </BuildLog>
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_AMD64_;_DEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>
+ </ProfileGuidedDatabase>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <BuildLog>
+ <Path>$(IntDir)Build.html</Path>
+ </BuildLog>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_X86_;NDEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100</DisableSpecificWarnings>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <ProfileGuidedDatabase>
+ </ProfileGuidedDatabase>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <BuildLog>
+ <Path>$(IntDir)Build.html</Path>
+ </BuildLog>
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100</DisableSpecificWarnings>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <ProfileGuidedDatabase>
+ </ProfileGuidedDatabase>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="dll_main.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </PrecompiledHeader>
+ <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ </PrecompiledHeader>
+ <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </PrecompiledHeader>
+ <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ </PrecompiledHeader>
+ <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
+ </ClCompile>
+ <ClCompile Include="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" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/lib/FindFilePlus/dll_main.cpp b/lib/FindFilePlus/dll_main.cpp
new file mode 100644
index 00000000..aca474bc
--- /dev/null
+++ b/lib/FindFilePlus/dll_main.cpp
@@ -0,0 +1,30 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "init_dll_binding.h"
+
+
+//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/lib/FindFilePlus/find_file_plus.cpp b/lib/FindFilePlus/find_file_plus.cpp
new file mode 100644
index 00000000..becfe553
--- /dev/null
+++ b/lib/FindFilePlus/find_file_plus.cpp
@@ -0,0 +1,298 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#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 <zen/scope_guard.h>
+
+using namespace dll;
+using namespace findplus;
+
+
+namespace
+{
+struct FileError
+{
+ FileError(ULONG errorCode) : win32Error(errorCode) {}
+ ULONG win32Error;
+};
+
+
+//--------------------------------------------------------------------------------------------------------------
+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, //__in dosFileName,
+ PUNICODE_STRING, //__out ntFileName,
+ PCWSTR*, //__out_optFilePart,
+ PRTL_RELATIVE_NAME_U); //__out_opt relativeName
+
+typedef BOOLEAN (NTAPI* RtlDosPathNameToRelativeNtPathName_UFunc)(PCWSTR, //__in dosFileName,
+ PUNICODE_STRING, //__out ntFileName,
+ PCWSTR*, //__out_optFilePart,
+ PRTL_RELATIVE_NAME_U); //__out_opt relativeName
+
+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<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 &&
+ 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 FileError
+ ~FileSearcher();
+
+ void readdir(FileInformation& output); //throw FileError
+
+private:
+ UNICODE_STRING ntPathName; //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!");
+};
+
+
+FileSearcher::FileSearcher(const wchar_t* dirname) :
+ hDir(NULL),
+ nextEntryOffset(0)
+{
+ ntPathName.Buffer = NULL;
+ ntPathName.Length = 0;
+ ntPathName.MaximumLength = 0;
+
+ zen::ScopeGuard guardConstructor = zen::makeGuard([&]() { this->~FileSearcher(); });
+ //--------------------------------------------------------------------------------------------------------------
+
+ //convert dosFileName, e.g. C:\Users or \\?\C:\Users to ntFileName \??\C:\Users
+ //in contrast to ::FindFirstFile() we don't evaluate the relativeName, however tests indicate ntFileName is *always* filled with an absolute name, even if dosFileName is relative
+
+ //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,
+ &ntPathName, //__out ntFileName,
+ NULL, //__out_optFilePart,
+ NULL)) //__out_opt relativeName - empty if dosFileName is absolute
+ throw FileError(rtlNtStatusToDosError(STATUS_OBJECT_PATH_NOT_FOUND)); //translates to ERROR_PATH_NOT_FOUND, same behavior like ::FindFirstFileEx()
+
+ OBJECT_ATTRIBUTES objAttr = {};
+ InitializeObjectAttributes(&objAttr, //[out] POBJECT_ATTRIBUTES initializedAttributes,
+ &ntPathName, //[in] PUNICODE_STRING objectName,
+ OBJ_CASE_INSENSITIVE, //[in] ULONG attributes,
+ NULL, //[in] HANDLE rootDirectory,
+ NULL); //[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 FileError(rtlNtStatusToDosError(rv));
+ }
+
+ guardConstructor.dismiss();
+}
+
+
+inline
+FileSearcher::~FileSearcher()
+{
+ //cleanup in reverse order
+ if (hDir)
+ ntClose(hDir);
+
+ if (ntPathName.Buffer)
+ rtlFreeUnicodeString(&ntPathName); //cleanup identical to ::FindFirstFile()
+ //note that most if this function seems inlined by the linker, so that its assembly looks equivalent to "RtlFreeHeap(GetProcessHeap(), 0, ntPathName.Buffer)"
+}
+
+
+void FileSearcher::readdir(FileInformation& output)
+{
+ //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 noticable 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,
+ NULL, //__in_opt HANDLE event,
+ NULL, //__in_opt PIO_APC_ROUTINE apcRoutine,
+ NULL, //__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,
+ NULL, //__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,
+ NULL, //__in_opt HANDLE event,
+ NULL, //__in_opt PIO_APC_ROUTINE apcRoutine,
+ NULL, //__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
+ FileIdBothDirectoryInformation, //__in FILE_INFORMATION_CLASS fileInformationClass - all XP/Win7/Win8 use "FileBothDirectoryInformation"
+ false, //__in BOOLEAN returnSingleEntry,
+ NULL, //__in_opt PUNICODE_STRING mask,
+ false); //__in BOOLEAN restartScan
+ if (!NT_SUCCESS(rv))
+ throw FileError(rtlNtStatusToDosError(rv)); //throws STATUS_NO_MORE_FILES when finished
+
+ if (status.Information == 0) //except for the first call to call ::NtQueryDirectoryFile():
+ throw FileError(rtlNtStatusToDosError(STATUS_BUFFER_OVERFLOW)); //if buffer size is too small, return value is STATUS_SUCCESS and Information == 0 -> we don't expect this!
+ }
+
+ const FILE_ID_BOTH_DIR_INFORMATION& dirInfo = *reinterpret_cast<FILE_ID_BOTH_DIR_INFORMATION*>(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;
+ };
+
+ output.creationTime = toFileTime(dirInfo.CreationTime);
+ output.lastWriteTime = toFileTime(dirInfo.LastWriteTime);
+ output.fileSize.QuadPart = dirInfo.EndOfFile.QuadPart;
+ output.fileId.QuadPart = dirInfo.FileId.QuadPart;
+ output.fileAttributes = dirInfo.FileAttributes;
+ output.shortNameLength = dirInfo.FileNameLength / sizeof(TCHAR); //FileNameLength is in bytes!
+
+ if (dirInfo.FileNameLength + sizeof(TCHAR) > sizeof(output.shortName)) //this may actually happen if ::NtQueryDirectoryFile() decides to return a
+ throw FileError(rtlNtStatusToDosError(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.fileId) == sizeof(dirInfo.FileId), "dang!");
+ static_assert(sizeof(output.fileAttributes) == sizeof(dirInfo.FileAttributes), "dang!");
+}
+
+
+FindHandle findplus::openDir(const wchar_t* dirname)
+{
+ try
+ {
+ return new FileSearcher(dirname); //throw FileError
+ }
+ catch (const FileError& err)
+ {
+ setWin32Error(err.win32Error);
+ return NULL;
+ }
+}
+
+
+bool findplus::readDir(FindHandle hnd, FileInformation& output)
+{
+ try
+ {
+ hnd->readdir(output); //throw FileError
+ return true;
+ }
+ catch (const FileError& err)
+ {
+ setWin32Error(err.win32Error);
+ return false;
+ }
+}
+
+
+void findplus::closeDir(FindHandle hnd)
+{
+ if (hnd) //play a little "nice"
+ delete hnd;
+}
diff --git a/lib/FindFilePlus/find_file_plus.h b/lib/FindFilePlus/find_file_plus.h
new file mode 100644
index 00000000..aacdf0ea
--- /dev/null
+++ b/lib/FindFilePlus/find_file_plus.h
@@ -0,0 +1,78 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#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;
+ DWORD fileAttributes;
+ DWORD shortNameLength;
+ WCHAR shortName[MAX_PATH + 1]; //shortName is 0-terminated
+}; //no need for #pragma pack -> all members already starting at 4 byte boundary!
+
+class FileSearcher;
+typedef FileSearcher* FindHandle;
+
+DLL_FUNCTION_DECLARATION
+FindHandle openDir(const wchar_t* dirname); //returns NULL on error, call ::GetLastError()
+//note: do NOT place an asterisk at end, e.g. C:\SomeDir\*, as one 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
+
+DLL_FUNCTION_DECLARATION
+void closeDir(FindHandle hnd);
+
+/*----------
+ |typedefs|
+ ----------*/
+typedef FindHandle (*OpenDirFunc )(const wchar_t* dirname);
+typedef bool (*ReadDirFunc )(FindHandle hnd, FileInformation& dirInfo);
+typedef void (*CloseDirFunc)(FindHandle hnd);
+
+/*--------------
+ |symbol names|
+ --------------*/
+//const pointers ensure internal linkage
+const char openDirFuncName [] = "openDir";
+const char readDirFuncName [] = "readDir";
+const char closeDirFuncName[] = "closeDir";
+
+/*---------------
+ |library names|
+ ---------------*/
+inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"FindFilePlus_x64.dll" : L"FindFilePlus_Win32.dll"; }
+}
+
+
+#endif //FIND_FIRST_FILE_PLUS_HEADER_087483434
diff --git a/lib/FindFilePlus/init_dll_binding.h b/lib/FindFilePlus/init_dll_binding.h
new file mode 100644
index 00000000..51b32c99
--- /dev/null
+++ b/lib/FindFilePlus/init_dll_binding.h
@@ -0,0 +1,16 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#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/lib/FindFilePlus/load_dll.cpp b/lib/FindFilePlus/load_dll.cpp
new file mode 100644
index 00000000..7166223b
--- /dev/null
+++ b/lib/FindFilePlus/load_dll.cpp
@@ -0,0 +1,23 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#include "load_dll.h"
+#define WIN32_LEAN_AND_MEAN
+#include <windows.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/lib/FindFilePlus/load_dll.h b/lib/FindFilePlus/load_dll.h
new file mode 100644
index 00000000..149b6efe
--- /dev/null
+++ b/lib/FindFilePlus/load_dll.h
@@ -0,0 +1,47 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#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
+
bgstack15