mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
Compare commits
145 Commits
Author | SHA1 | Date | |
---|---|---|---|
568096b560 | |||
b2e175a991 | |||
757c4f151d | |||
8b71e18972 | |||
4e7f988371 | |||
eb04d7ab90 | |||
d6c3b7304d | |||
1ee563cd13 | |||
8787f2c528 | |||
4c102ab57c | |||
bf87c539fd | |||
d5802f3a5f | |||
c144d4d303 | |||
9770efde14 | |||
197ce7c30a | |||
5d8384a508 | |||
8bb46a5f86 | |||
a3087cb696 | |||
92b1a8c00d | |||
bbf641e721 | |||
539ab9ce63 | |||
a29390412b | |||
739eb80cfb | |||
f9a470a0f0 | |||
44358e118c | |||
2a7ee146f1 | |||
0ddeb02235 | |||
26d8ea1c1c | |||
fa4aaf2fb7 | |||
7645a0185b | |||
dcf38cdf08 | |||
c7ca500dd5 | |||
d9fcc8ca1c | |||
259f2bf1c1 | |||
67711082b0 | |||
f2d98bbf25 | |||
e40505adb5 | |||
ac7b7f4a1b | |||
aa53b1e5ef | |||
c4b73c8eda | |||
332bce6322 | |||
5ef1de2647 | |||
de60e76b1d | |||
8f8e8fe086 | |||
0ac9a83026 | |||
b8c97caec0 | |||
f9b8bfc020 | |||
f938bf5e3f | |||
a0df9babf9 | |||
0d9d8ef5a2 | |||
668948ebc1 | |||
83c9351d38 | |||
aa1e32494c | |||
6365a553dc | |||
1245a29be6 | |||
c79785c2db | |||
f117a89697 | |||
33f5b8c05b | |||
9a02a46cf4 | |||
4d6fc3c848 | |||
964f2eed69 | |||
b45cff2881 | |||
f219885939 | |||
0cfc730745 | |||
a3643f8b02 | |||
de61eaf6b8 | |||
075a2b6e4c | |||
37affbf572 | |||
20b3ecd0cd | |||
c782c4d668 | |||
d545b8df26 | |||
08e520e0ec | |||
a5db7a2cca | |||
74c2494bbd | |||
858f77cdf7 | |||
30dae34700 | |||
36d50facd7 | |||
55dd8797d8 | |||
27114184d2 | |||
1980f511ce | |||
4cbee05849 | |||
f2391d99d5 | |||
fa9ff37de9 | |||
39b60c1348 | |||
5bc15a7e54 | |||
81bc200fe7 | |||
89324d2327 | |||
47b81a8025 | |||
02cec420e7 | |||
8e7e959d8a | |||
fc51b7cc22 | |||
ff5850847f | |||
ab462fb546 | |||
a5eadc50a7 | |||
afe7f8d728 | |||
c137d49dcd | |||
b70337bac3 | |||
c9b5f25ffc | |||
96f6c28885 | |||
deb8aed91f | |||
fac270e596 | |||
0189adac8f | |||
af772d7a86 | |||
96554cc0ca | |||
ddb3698c89 | |||
9657ae31c3 | |||
0795774e9e | |||
763f256e1f | |||
367f450e30 | |||
7afdee7c01 | |||
87c5f19ce1 | |||
00d1a3176e | |||
6318e7b0ef | |||
5d23b1fef8 | |||
44fe02d2fd | |||
1f0de20b7f | |||
bfd2e106ac | |||
b1848e963f | |||
a29611fa2a | |||
8a369bd48a | |||
9ca7424d27 | |||
4f640755bc | |||
c085a91991 | |||
83cd3cab99 | |||
67dff84a13 | |||
c702a86fbf | |||
f335a990af | |||
ba68ab845b | |||
db0566701e | |||
433e62f813 | |||
6777de6569 | |||
63ee24235b | |||
c3eb46813e | |||
bee0fa79b2 | |||
d907bf2769 | |||
38bcece5ce | |||
193de36301 | |||
c080e86f11 | |||
79811a2faa | |||
b1e287727d | |||
2def18e271 | |||
3ddc2249f6 | |||
709ead9e06 | |||
7c574da261 | |||
0980365082 |
@ -1,6 +1,27 @@
|
||||
= Changelog
|
||||
|
||||
|
||||
v1.1 (2017.1)::
|
||||
|
||||
This release brings some major new components and improvements.
|
||||
|
||||
- A .NET layer that allows the creation of file systems in managed mode. This is contained in the new `winfsp-msil.dll`.
|
||||
- A simple C++ layer can be found in `inc/winfsp/winfsp.hpp`.
|
||||
- FUSE for Cygwin is now included with the installer.
|
||||
- FUSE now has a `-ovolname=VOLNAME` parameter that allows setting the volume label. Thanks @samkelly.
|
||||
|
||||
|
||||
v1.0::
|
||||
|
||||
This is the WinFsp 2017 release! :tada:
|
||||
|
||||
- The API is now *FROZEN*. Breaking API changes will receive a major version update (`2.0`). Incremental API changes will receive a minor version update (`1.x`).
|
||||
- Adds chocolatey package. Try `choco install winfsp` (note: pending approval from chocolatey.org).
|
||||
- FUSE `-d` output now always goes to stderr. There is also a new `-oDebugLog=FILE` switch to specify a debug output file.
|
||||
- FUSE now provides a default `statfs` implementation if a file system does not provide one.
|
||||
- The WinFsp DLL now exports `fuse_*` symbols in addition to the `fsp_fuse_*` symbols. These symbols are for use with programs that use FFI technology such as jnr-fuse and fusepy *ONLY*. They are not supposed to be used by native C/C++ programs. Such programs are supposed to include the `<fuse.h>` headers.
|
||||
|
||||
|
||||
v1.0RC3::
|
||||
|
||||
This is the WinFsp 2017 Release Candidate 3, which should be the last Release Candidate according to the current plan. This release fixes a major issue with some file systems and includes a few smaller changes:
|
||||
|
@ -54,5 +54,6 @@ This CONTRIBUTOR AGREEMENT applies to any contribution that you make to the WinF
|
||||
CONTRIBUTOR LIST
|
||||
----------------
|
||||
|===
|
||||
|Bill Zissimopoulos |billziss at navimatics.com
|
||||
|Bill Zissimopoulos |billziss at navimatics.com
|
||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||
|===
|
||||
|
@ -6,7 +6,7 @@ permissions to Free/Libre and Open Source Software ("FLOSS") without requiring
|
||||
that such software is covered by the GPLv3.
|
||||
|
||||
1. Permission to link with a platform specific version of the WinFsp DLL
|
||||
(currently winfsp-x64.dll or winfsp-x86.dll).
|
||||
(one of: winfsp-x64.dll, winfsp-x86.dll, winfsp-msil.dll).
|
||||
|
||||
2. Permission to distribute unmodified binary releases of the WinFsp
|
||||
installer (as released by the WinFsp project).
|
||||
|
@ -3,7 +3,9 @@
|
||||

|
||||
|
||||
|
||||
<a href="https://github.com/billziss-gh/winfsp/releases"><img src="http://www.secfs.net/winfsp/resources/Download-WinFsp.png" alt="Download WinFsp Installer" width="244" height="34"></a>
|
||||
<a href="https://github.com/billziss-gh/winfsp/releases/latest"><img src="http://www.secfs.net/winfsp/resources/Download-WinFsp.png" alt="Download WinFsp Installer" width="244" height="34"></a>
|
||||
 
|
||||
<a href="https://chocolatey.org/packages/winfsp"><img src="http://www.secfs.net/winfsp/resources/Choco-WinFsp.png" alt="choco install winfsp" width="244" height="34"></a>
|
||||
|
||||
|
||||
|
||||
@ -16,6 +18,7 @@ Some of the benefits of using WinFsp are listed below:
|
||||
* Strives for compatibility with NTFS. Read about its [Compatibility](doc/NTFS-Compatibility.asciidoc ).
|
||||
* Easy to understand but comprehensive API. Consult the [API Reference](http://www.secfs.net/winfsp/apiref/). There is also a simple [Tutorial](doc/WinFsp-Tutorial.asciidoc).
|
||||
* FUSE compatibility layer for native Windows and Cygwin. See [fuse.h](inc/fuse/fuse.h).
|
||||
* .NET layer for managed development. See [src/dotnet](src/dotnet).
|
||||
* Signed drivers provided on every release.
|
||||
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
|
||||
|
||||
@ -35,6 +38,7 @@ The project source code is organized as follows:
|
||||
* inc/fuse: Public headers for the FUSE compatibility layer.
|
||||
* src/dll: Source code to the WinFsp DLL.
|
||||
* src/dll/fuse: Source code to the FUSE compatibility layer.
|
||||
* src/dotnet: Source code to the .NET layer.
|
||||
* src/launcher: Source code to the launcher service and the launchctl utility.
|
||||
* src/sys: Source code to the WinFsp FSD.
|
||||
* opt/cygfuse: Source code for the Cygwin FUSE package.
|
||||
|
@ -23,7 +23,7 @@ build_script:
|
||||
- tools\build.bat %CONFIGURATION%
|
||||
|
||||
test_script:
|
||||
- for %%f in ("build\VStudio\build\%CONFIGURATION%\winfsp-*.msi") do start /wait msiexec /i %%f /qn INSTALLLEVEL=1000
|
||||
- choco install winfsp -s build\VStudio\build\%CONFIGURATION% -y
|
||||
- if %TESTING%==Func appveyor DownloadFile http://www.secfs.net/winfsp/resources/Test.Filter.Driver.zip && 7z x Test.Filter.Driver.zip
|
||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||
@ -31,6 +31,7 @@ test_script:
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
|
||||
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
||||
- choco uninstall winfsp -y
|
||||
- if exist %SystemRoot%\memory.dmp exit 1
|
||||
|
||||
on_finish:
|
||||
|
109
build/VStudio/dotnet/winfsp.net.csproj
Normal file
109
build/VStudio/dotnet/winfsp.net.csproj
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\version.properties" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{94580219-CC8D-4FE5-A3BE-437B0B3481E1}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<ProjectName>winfsp.net</ProjectName>
|
||||
<RootNamespace>Fsp</RootNamespace>
|
||||
<AssemblyName>winfsp-msil</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>winfsp.net.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\src\dotnet\FileSystemBase+Const.cs">
|
||||
<Link>FileSystemBase+Const.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\src\dotnet\FileSystemBase.cs">
|
||||
<Link>FileSystemBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\src\dotnet\FileSystemHost.cs">
|
||||
<Link>FileSystemHost.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\src\dotnet\Interop.cs">
|
||||
<Link>Interop.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\src\dotnet\Service.cs">
|
||||
<Link>Service.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="winfsp.net.snk" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<Target Name="BeforeBuild">
|
||||
<ItemGroup>
|
||||
<AssemblyInfo Include="using System.Reflection%3b" />
|
||||
<AssemblyInfo Include="[assembly: AssemblyProduct("$(MyProductName)")]" />
|
||||
<AssemblyInfo Include="[assembly: AssemblyTitle("$(MyDescription)")]" />
|
||||
<AssemblyInfo Include="[assembly: AssemblyCompany("$(MyCompanyName)")]" />
|
||||
<AssemblyInfo Include="[assembly: AssemblyCopyright("$(MyCopyright)")]" />
|
||||
<AssemblyInfo Include="[assembly: AssemblyVersion("$(MyAssemblyVersion)")]" />
|
||||
<AssemblyInfo Include="[assembly: AssemblyFileVersion("$(MyVersion)")]" />
|
||||
</ItemGroup>
|
||||
<MakeDir Directories="$(IntermediateOutputPath)" />
|
||||
<WriteLinesToFile File="$(IntermediateOutputPath)AssemblyInfo.cs" Lines="@(AssemblyInfo)" Overwrite="true" />
|
||||
<ItemGroup>
|
||||
<Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
|
||||
<FileWrites Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>exit /b 0
|
||||
|
||||
set TargetName=$(TargetName)
|
||||
set MyAssemblyPolicyVersion=$(MyAssemblyPolicyVersion)
|
||||
set MyAssemblyVersion=$(MyAssemblyVersion)
|
||||
|
||||
setlocal EnableDelayedExpansion
|
||||
if exist $(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config del $(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config
|
||||
for /f "delims=" %25%25l in ($(ProjectDir)winfsp.net.policy.config) do (
|
||||
set line=%25%25l
|
||||
echo !line! >>$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config
|
||||
)
|
||||
|
||||
"$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.0A\Bin\al.exe" /product:"$(MyProductName)" /title:"$(MyDescription)" /company:"$(MyCompanyName)" /copyright:"$(MyCopyright)" /version:"$(MyAssemblyPolicyVersion)" /fileversion:"$(MyVersion)" /link:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config /out:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).dll /keyfile:$(ProjectDir)$(ProjectName).snk
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
10
build/VStudio/dotnet/winfsp.net.policy.config
Normal file
10
build/VStudio/dotnet/winfsp.net.policy.config
Normal file
@ -0,0 +1,10 @@
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="!TargetName!" publicKeyToken="b099876d8fa9b1f3" culture="neutral" />
|
||||
<bindingRedirect oldVersion="!MyAssemblyPolicyVersion!.0.0-!MyAssemblyVersion!" newVersion="!MyAssemblyVersion!" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
BIN
build/VStudio/dotnet/winfsp.net.snk
Normal file
BIN
build/VStudio/dotnet/winfsp.net.snk
Normal file
Binary file not shown.
@ -39,6 +39,7 @@
|
||||
<Directory Id="BINDIR" Name="bin" />
|
||||
<Directory Id="INCDIR" Name="inc" />
|
||||
<Directory Id="LIBDIR" Name="lib" />
|
||||
<Directory Id="OPTDIR" Name="opt" />
|
||||
<Directory Id="SMPDIR" Name="samples" />
|
||||
<Directory Id="SYMDIR" Name="sym" />
|
||||
</Directory>
|
||||
@ -87,6 +88,20 @@
|
||||
<Condition>NOT VersionNT64</Condition>
|
||||
</Component>
|
||||
|
||||
<!-- install assembly -->
|
||||
<Component Id="C.winfsp_msil.dll" Guid="0D8BA6AE-9F87-402B-AE1A-95B0AE3BE179">
|
||||
<File Id="FILE.winfsp_msil.dll" Name="winfsp-msil.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<!--
|
||||
<Component Id="C.winfsp_msil.dll.GAC" Guid="6469467D-8C90-4889-8138-4028F9DA6E85">
|
||||
<File Id="FILE.winfsp_msil.dll.GAC" Name="winfsp-msil.dll" KeyPath="yes" Assembly=".net" />
|
||||
</Component>
|
||||
<Component Id="C.policy.winfsp_msil.dll.GAC">
|
||||
<File Name="policy.1.0.winfsp-msil.dll" KeyPath="yes" Assembly=".net" />
|
||||
<File Name="policy.1.0.winfsp-msil.config" KeyPath="no" />
|
||||
</Component>
|
||||
-->
|
||||
|
||||
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
||||
<Component Id="C.launcher_x64.exe.svcinst">
|
||||
<File Id="launcher_x64.exe.svcinst" Name="launcher-x64.exe" KeyPath="yes" />
|
||||
@ -208,6 +223,9 @@
|
||||
<Component Id="C.winfsp.h">
|
||||
<File Name="winfsp.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.winfsp.hpp">
|
||||
<File Name="winfsp.hpp" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="INCDIR.fuse" Name="fuse">
|
||||
<Component Id="C.fuse.h">
|
||||
@ -252,6 +270,19 @@
|
||||
<Condition>NOT VersionNT64</Condition>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="OPTDIR">
|
||||
<Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist">
|
||||
<Component Id="C.fuse.tar.xz">
|
||||
<File Name="fuse-2.8-4.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse.install.sh">
|
||||
<File Name="install.sh" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse.uninstall.sh">
|
||||
<File Name="uninstall.sh" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SMPDIR" FileSource="..\..\..\tst">
|
||||
<Directory Id="SMPDIR.memfs" Name="memfs">
|
||||
<Component Id="C.memfs.h">
|
||||
@ -278,6 +309,20 @@
|
||||
<File Name="passthrough.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_cpp" Name="passthrough-cpp">
|
||||
<Component Id="C.passthrough_cpp.cpp">
|
||||
<File Name="passthrough-cpp.cpp" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_cpp.sln">
|
||||
<File Name="passthrough-cpp.sln" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_cpp.vcxproj">
|
||||
<File Name="passthrough-cpp.vcxproj" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_cpp.vcxproj.filters">
|
||||
<File Name="passthrough-cpp.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_fuse" Name="passthrough-fuse">
|
||||
<Component Id="C.passthrough_fuse.c">
|
||||
<File Name="passthrough-fuse.c" KeyPath="yes" />
|
||||
@ -304,6 +349,17 @@
|
||||
<File Name="README.md" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_dotnet" Name="passthrough-dotnet">
|
||||
<Component Id="C.passthrough_dotnet.Program.cs">
|
||||
<File Name="Program.cs" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_dotnet.sln">
|
||||
<File Name="passthrough-dotnet.sln" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_dotnet.csproj">
|
||||
<File Name="passthrough-dotnet.csproj" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SYMDIR">
|
||||
<Component Id="C.winfsp_x64.sys.pdb">
|
||||
@ -357,6 +413,7 @@
|
||||
<ComponentGroup Id="C.WinFsp.inc">
|
||||
<ComponentRef Id="C.fsctl.h" />
|
||||
<ComponentRef Id="C.winfsp.h" />
|
||||
<ComponentRef Id="C.winfsp.hpp" />
|
||||
<ComponentRef Id="C.fuse.h" />
|
||||
<ComponentRef Id="C.fuse_common.h" />
|
||||
<ComponentRef Id="C.fuse_opt.h" />
|
||||
@ -368,6 +425,11 @@
|
||||
<ComponentRef Id="C.fuse_x64.pc" />
|
||||
<ComponentRef Id="C.fuse_x86.pc" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.opt.fuse">
|
||||
<ComponentRef Id="C.fuse.tar.xz" />
|
||||
<ComponentRef Id="C.fuse.install.sh" />
|
||||
<ComponentRef Id="C.fuse.uninstall.sh" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.smp">
|
||||
<ComponentRef Id="C.memfs_x64.exe" />
|
||||
<ComponentRef Id="C.memfs_x86.exe" />
|
||||
@ -378,6 +440,10 @@
|
||||
<ComponentRef Id="C.passthrough.sln" />
|
||||
<ComponentRef Id="C.passthrough.vcxproj" />
|
||||
<ComponentRef Id="C.passthrough.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough_cpp.cpp" />
|
||||
<ComponentRef Id="C.passthrough_cpp.sln" />
|
||||
<ComponentRef Id="C.passthrough_cpp.vcxproj" />
|
||||
<ComponentRef Id="C.passthrough_cpp.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough_fuse.c" />
|
||||
<ComponentRef Id="C.passthrough_fuse.winposix.c" />
|
||||
<ComponentRef Id="C.passthrough_fuse.winposix.h" />
|
||||
@ -399,6 +465,18 @@
|
||||
<ComponentRef Id="C.memfs_x64.pdb" />
|
||||
<ComponentRef Id="C.memfs_x86.pdb" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.net">
|
||||
<ComponentRef Id="C.winfsp_msil.dll" />
|
||||
<!--
|
||||
<ComponentRef Id="C.winfsp_msil.dll.GAC" />
|
||||
<ComponentRef Id="C.policy.winfsp_msil.dll.GAC" />
|
||||
-->
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.smp.net">
|
||||
<ComponentRef Id="C.passthrough_dotnet.Program.cs" />
|
||||
<ComponentRef Id="C.passthrough_dotnet.sln" />
|
||||
<ComponentRef Id="C.passthrough_dotnet.csproj" />
|
||||
</ComponentGroup>
|
||||
|
||||
<Feature
|
||||
Id="F.Main"
|
||||
@ -421,7 +499,20 @@
|
||||
InstallDefault="local"
|
||||
Absent="disallow">
|
||||
<ComponentGroupRef Id="C.WinFsp.bin" />
|
||||
<ComponentGroupRef Id="C.WinFsp.net" />
|
||||
</Feature>
|
||||
<!--
|
||||
<Feature
|
||||
Id="F.Net"
|
||||
Level="10"
|
||||
Title=".NET"
|
||||
Description="The managed $(var.MyProductName) files."
|
||||
AllowAdvertise="no"
|
||||
InstallDefault="local"
|
||||
Absent="allow">
|
||||
<ComponentGroupRef Id="C.WinFsp.net" />
|
||||
</Feature>
|
||||
-->
|
||||
<Feature
|
||||
Id="F.Developer"
|
||||
Level="1000"
|
||||
@ -433,8 +524,19 @@
|
||||
<ComponentGroupRef Id="C.WinFsp.inc" />
|
||||
<ComponentGroupRef Id="C.WinFsp.lib" />
|
||||
<ComponentGroupRef Id="C.WinFsp.smp" />
|
||||
<ComponentGroupRef Id="C.WinFsp.smp.net" />
|
||||
<ComponentGroupRef Id="C.WinFsp.sym" />
|
||||
</Feature>
|
||||
<Feature
|
||||
Id="F.Cygfuse"
|
||||
Level="1000"
|
||||
Title="FUSE for Cygwin"
|
||||
Description="From a Cygwin prompt change to $InstallDir/opt/cygfuse and run install.sh."
|
||||
AllowAdvertise="no"
|
||||
InstallDefault="local"
|
||||
Absent="allow">
|
||||
<ComponentGroupRef Id="C.WinFsp.opt.fuse" />
|
||||
</Feature>
|
||||
</Feature>
|
||||
|
||||
<WixVariable Id="WixUIBannerBmp" Value="wixbanner.bmp" />
|
||||
|
@ -15,14 +15,17 @@
|
||||
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||
|
||||
<MyCanonicalVersion>1.0</MyCanonicalVersion>
|
||||
<MyCanonicalVersion>1.1</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2017 RC3</MyProductVersion>
|
||||
<MyProductStage>RC</MyProductStage>
|
||||
<MyProductVersion>2017.1 BETA</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||
<MyFullVersion>$(MyCanonicalVersion).$(MyBuildNumber).$(MyGitRevision)</MyFullVersion>
|
||||
|
||||
<MyAssemblyPolicyVersion>$(MyCanonicalVersion.Substring(0,$(MyVersion.IndexOf('.')))).0</MyAssemblyPolicyVersion>
|
||||
<MyAssemblyVersion>$(MyAssemblyPolicyVersion).0.0</MyAssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
|
@ -53,146 +53,212 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fscrash", "testing\fscrash.
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsbench", "testing\fsbench.vcxproj", "{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winfsp.net", "dotnet\winfsp.net.csproj", "{94580219-CC8D-4FE5-A3BE-437B0B3481E1}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB} = {4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332} = {C85C26BA-8C22-4D30-83DA-46C3548E6332}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{A998CEC4-4B34-43DC-8457-F7761228BA67}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Installer.Debug|Any CPU = Installer.Debug|Any CPU
|
||||
Installer.Debug|x64 = Installer.Debug|x64
|
||||
Installer.Debug|x86 = Installer.Debug|x86
|
||||
Installer.Release|Any CPU = Installer.Release|Any CPU
|
||||
Installer.Release|x64 = Installer.Release|x64
|
||||
Installer.Release|x86 = Installer.Release|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.Build.0 = Debug|x64
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.ActiveCfg = Release|x64
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.Build.0 = Release|x64
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.Build.0 = Release|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.Build.0 = Debug|x64
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.ActiveCfg = Release|x64
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.Build.0 = Release|x64
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.Build.0 = Release|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.Build.0 = Debug|x64
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.Build.0 = Debug|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.ActiveCfg = Release|x64
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.Build.0 = Release|x64
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.ActiveCfg = Release|Win32
|
||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.Build.0 = Release|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.Build.0 = Debug|x64
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.Build.0 = Debug|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.ActiveCfg = Release|x64
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.Build.0 = Release|x64
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.ActiveCfg = Release|Win32
|
||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.Build.0 = Release|Win32
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x64.ActiveCfg = Debug|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|Any CPU.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|Any CPU.Build.0 = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.Build.0 = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.ActiveCfg = Debug|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.Build.0 = Debug|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|Any CPU.Build.0 = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.Build.0 = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.Build.0 = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x64.ActiveCfg = Release|x86
|
||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x86.ActiveCfg = Release|x86
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|Any CPU.Build.0 = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.Build.0 = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.Build.0 = Debug|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|Any CPU.Build.0 = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.Build.0 = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.Build.0 = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x64.ActiveCfg = Release|Win32
|
||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.Build.0 = Debug|x64
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.ActiveCfg = Release|x64
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.Build.0 = Release|x64
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.Build.0 = Release|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.Build.0 = Debug|x64
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.Build.0 = Debug|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.ActiveCfg = Release|x64
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.Build.0 = Release|x64
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.ActiveCfg = Release|Win32
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.Build.0 = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x64.Build.0 = Debug|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x86.Build.0 = Debug|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x64.Build.0 = Debug|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x86.Build.0 = Debug|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x64.Build.0 = Release|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x86.Build.0 = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x64.ActiveCfg = Release|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x64.Build.0 = Release|x64
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x86.ActiveCfg = Release|Win32
|
||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x86.Build.0 = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x64.Build.0 = Debug|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x64.Build.0 = Debug|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x86.Build.0 = Debug|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x64.Build.0 = Release|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x86.Build.0 = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x64.ActiveCfg = Release|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x64.Build.0 = Release|x64
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x86.Build.0 = Release|Win32
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -206,5 +272,6 @@ Global
|
||||
{73EAAEDA-557B-48D5-A137-328934720FB4} = {FD28A504-431E-49B9-BB8C-DCA0E7019F66}
|
||||
{10757011-749D-4954-873B-AE38D8145472} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||
{94580219-CC8D-4FE5-A3BE-437B0B3481E1} = {A998CEC4-4B34-43DC-8457-F7761228BA67}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -26,6 +26,7 @@
|
||||
<ClInclude Include="..\..\inc\fuse\winfsp_fuse.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp" />
|
||||
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
||||
<ClInclude Include="..\..\src\dll\library.h" />
|
||||
<ClInclude Include="..\..\src\shared\minimal.h" />
|
||||
@ -34,6 +35,7 @@
|
||||
<ClCompile Include="..\..\src\dll\dirbuf.c" />
|
||||
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||
|
@ -50,6 +50,9 @@
|
||||
<ClInclude Include="..\..\src\dll\fuse\library.h">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp">
|
||||
<Filter>Include\winfsp</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\library.c">
|
||||
@ -106,6 +109,9 @@
|
||||
<ClCompile Include="..\..\src\dll\dirbuf.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
|
4
build/choco/LICENSE.txt
Normal file
4
build/choco/LICENSE.txt
Normal file
@ -0,0 +1,4 @@
|
||||
From: https://github.com/billziss-gh/winfsp/blob/master/License.txt
|
||||
|
||||
LICENSE
|
||||
|
15
build/choco/VERIFICATION.txt
Normal file
15
build/choco/VERIFICATION.txt
Normal file
@ -0,0 +1,15 @@
|
||||
VERIFICATION
|
||||
Verification is intended to assist the Chocolatey moderators and community
|
||||
in verifying that this package's contents are trustworthy.
|
||||
|
||||
WinFsp GitHub repository: https://github.com/billziss-gh/winfsp
|
||||
WinFsp MSI releases : https://github.com/billziss-gh/winfsp/releases
|
||||
|
||||
You may use the Windows certutil utility to confirm the hash of the MSI
|
||||
included in this package against the WinFsp MSI release of the same version.
|
||||
For example, for WinFsp version 1.0.17072 the command line to use is:
|
||||
|
||||
certutil -hashfile winfsp-1.0.17072.msi SHA256
|
||||
|
||||
The certutil output of the MSI in this package is included below.
|
||||
|
36
build/choco/chocolateyBeforeModify.ps1
Normal file
36
build/choco/chocolateyBeforeModify.ps1
Normal file
@ -0,0 +1,36 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$packageName = 'winfsp'
|
||||
$softwareName = 'WinFsp*'
|
||||
$installerType = 'msi'
|
||||
$silentArgs = '/qn /norestart'
|
||||
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
|
||||
|
||||
[array]$key = Get-UninstallRegistryKey -SoftwareName $softwareName
|
||||
|
||||
if ($key.Count -eq 1) {
|
||||
$key | % {
|
||||
# The Product Code GUID is all that should be passed for MSI, and very
|
||||
# FIRST, because it comes directly after /x, which is already set in the
|
||||
# Uninstall-ChocolateyPackage msiargs (facepalm).
|
||||
$silentArgs = "$($_.PSChildName) $silentArgs"
|
||||
|
||||
# Don't pass anything for file, it is ignored for msi (facepalm number 2)
|
||||
# Alternatively if you need to pass a path to an msi, determine that and
|
||||
# use it instead of the above in silentArgs, still very first
|
||||
$file = ''
|
||||
|
||||
Uninstall-ChocolateyPackage `
|
||||
-PackageName $packageName `
|
||||
-FileType $installerType `
|
||||
-SilentArgs "$silentArgs" `
|
||||
-ValidExitCodes $validExitCodes `
|
||||
-File "$file"
|
||||
}
|
||||
} elseif ($key.Count -eq 0) {
|
||||
Write-Warning "$packageName has already been uninstalled by other means."
|
||||
} elseif ($key.Count -gt 1) {
|
||||
Write-Warning "Too many matching packages found! Package may not be uninstalled."
|
||||
Write-Warning "Please alert package maintainer the following packages were matched:"
|
||||
$key | % {Write-Warning "- $_"}
|
||||
}
|
16
build/choco/chocolateyInstall.ps1
Normal file
16
build/choco/chocolateyInstall.ps1
Normal file
@ -0,0 +1,16 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
$fileLocation = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||
|
||||
$packageArgs = @{
|
||||
packageName = 'winfsp'
|
||||
fileType = 'msi'
|
||||
file = $fileLocation
|
||||
silentArgs = "/qn /norestart INSTALLLEVEL=1000"
|
||||
validExitCodes = @(0, 3010, 1641)
|
||||
}
|
||||
|
||||
Install-ChocolateyInstallPackage @packageArgs
|
||||
|
||||
Remove-Item -Force $packageArgs.file
|
56
build/choco/winfsp.nuspec
Normal file
56
build/choco/winfsp.nuspec
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>winfsp</id>
|
||||
<version>$version$</version>
|
||||
<packageSourceUrl>https://github.com/billziss-gh/winfsp/tree/master/build/choco</packageSourceUrl>
|
||||
<owners>Bill Zissimopoulos</owners>
|
||||
|
||||
<title>WinFsp</title>
|
||||
<authors>Bill Zissimopoulos</authors>
|
||||
<projectUrl>https://github.com/billziss-gh/winfsp</projectUrl>
|
||||
<iconUrl>https://github.com/billziss-gh/winfsp/raw/master/art/winfsp-solid.png</iconUrl>
|
||||
<copyright>Bill Zissimopoulos</copyright>
|
||||
<licenseUrl>https://github.com/billziss-gh/winfsp/blob/master/License.txt</licenseUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<projectSourceUrl>https://github.com/billziss-gh/winfsp</projectSourceUrl>
|
||||
<docsUrl>https://github.com/billziss-gh/winfsp/tree/master/doc</docsUrl>
|
||||
<mailingListUrl>https://groups.google.com/forum/#!forum/winfsp</mailingListUrl>
|
||||
<bugTrackerUrl>https://github.com/billziss-gh/winfsp/issues</bugTrackerUrl>
|
||||
<tags>driver filesystem fuse gplv3 windows-kernel admin</tags>
|
||||
<summary>Windows File System Proxy - FUSE for Windows</summary>
|
||||
<description>
|
||||
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
|
||||
|
||||
Some of the benefits of using WinFsp are listed below:
|
||||
|
||||
* Very well-tested and stable.
|
||||
* Very fast.
|
||||
* Strives for compatibility with NTFS.
|
||||
* Easy to understand but comprehensive API.
|
||||
* FUSE compatibility layer for native Windows and Cygwin.
|
||||
* Signed drivers provided on every release.
|
||||
* Available under the GPLv3 license with a special exception for Free/Libre and Open Source Software.
|
||||
|
||||
To verify installation:
|
||||
|
||||
* For 64-bit Windows: `net use m: \\memfs64\share` from the command prompt.
|
||||
* For 32-bit Windows: `net use m: \\memfs32\share`
|
||||
* For Cygwin: `net use m: '\\memfs64\share'`
|
||||
* To delete the drive: `net use m: /delete`
|
||||
</description>
|
||||
<releaseNotes>https://github.com/billziss-gh/winfsp/blob/master/Changelog.asciidoc</releaseNotes>
|
||||
|
||||
<!--<dependencies>
|
||||
<dependency id="chocolatey-uninstall.extension" />
|
||||
</dependencies>-->
|
||||
</metadata>
|
||||
|
||||
<files>
|
||||
<file src="LICENSE.txt" target="tools" />
|
||||
<file src="VERIFICATION.txt" target="tools" />
|
||||
<file src="chocolateyInstall.ps1" target="tools" />
|
||||
<file src="chocolateyBeforeModify.ps1" target="tools" />
|
||||
<file src="winfsp-$version$.msi" target="tools" />
|
||||
</files>
|
||||
</package>
|
51
doc/Frequently-Asked-Questions.asciidoc
Normal file
51
doc/Frequently-Asked-Questions.asciidoc
Normal file
@ -0,0 +1,51 @@
|
||||
= Frequently Asked Questions
|
||||
|
||||
== General
|
||||
|
||||
[qanda]
|
||||
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed. [@efeat]::
|
||||
|
||||
Your Windows 7 OS is missing SHA-2 Code Signing Support. You need to install the following security advisory that will rectify the problem:
|
||||
https://technet.microsoft.com/en-us/library/security/3033929.aspx
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories? [@netheril96]::
|
||||
|
||||
It is true that this would make it convenient to load the DLL, because the Windows loader looks into the Windows system directories when it loads DLL's. However, in the opinion of the WinFsp author, software that does not ship with the OS should not be installing components in the system directories.
|
||||
+
|
||||
There are a few alternative methods to overcome this problem. WinFsp recommends marking the WinFsp DLL as "delay load" and then using `FspLoad` to dynamically load the DLL during process initialization. For more information see the WinFsp Tutorial.
|
||||
|
||||
|
||||
Does WinFsp provide debugging symbols? [@netheril96]::
|
||||
|
||||
Public debugging symbols are already included in the installer. You need to install the "Developer" feature; the symbols can be found in the `sym` directory under the WinFsp installation directory.
|
||||
|
||||
|
||||
Is there a maximum number of concurrent file systems? [@efeat]::
|
||||
|
||||
WinFsp does not have a hard limit of how many file systems can be created or how many processes can create file systems.
|
||||
+
|
||||
As of the commits required to fix issue #55, there is however a hash table inside the FSD that uses PID's (Process ID's) as keys. This hash table currently expects that in general there will not be more than 50 processes creating file systems. However this is not a hard limit.
|
||||
|
||||
|
||||
== FUSE
|
||||
|
||||
[qanda]
|
||||
|
||||
Which version of FUSE does WinFsp-FUSE support?::
|
||||
|
||||
Currently it supports FUSE 2.8.
|
||||
|
||||
|
||||
FUSE on UNIX systems mounts file systems over an existing directory. When mounting a WinFsp-FUSE file system on a directory, the directory is created and later deleted when the file system goes away. What is the reason for this incompatibility? [@efeat]::
|
||||
|
||||
It would be preferrable if WinFsp-FUSE behaved like FUSE on UNIX in this instance. However there are a number of reasons that this is not the case.
|
||||
+
|
||||
When mounting over directories in Windows, WinFsp-FUSE uses a special construct called a reparse point. Reparse points are a general mechanism for adding special behavior to files and directories. One of the possible reparse points is the "mountpoint" reparse point (often called "junction"), which converts a directory into a mount point.
|
||||
+
|
||||
With this in mind here are the reasons for the current WinFsp-FUSE behavior:
|
||||
+
|
||||
- Symmetry with mounting on a drive. On Windows drives are created when the file system comes into existence and deleted when it is gone.
|
||||
- Inability to mount over a non-empty directory on Windows. On FUSE/UNIX this is possible, but not on Windows because NTFS disallows the creation of (mountpoint) reparse points on non-empty directories.
|
||||
- Most importantly: inability to guarantee that the mount point will cease to exist if the file system crashes. WinFsp attempts to guarantee that all resources used by a file system will get cleaned up. This is certainly true for the kernel-mode FSD, but an attempt is made to do so also in user mode. For this reason, drive symbolic links are marked as temporary and (importantly for our discussion) mount directories are opened with `FILE_FLAG_DELETE_ON_CLOSE`. There is no way to guarantee the removal of a reparse point in the same way.
|
32
doc/Home.md
Normal file
32
doc/Home.md
Normal file
@ -0,0 +1,32 @@
|
||||
# WinFsp - Windows File System Proxy
|
||||
|
||||
[[WinFsp-Icon.png]]
|
||||
|
||||
Developing file systems is a challenging proposition. Developing file systems for Windows is an order of magnitude more difficult. WinFsp eases the task of writing a new file system for Windows. WinFsp file systems are user mode programs and they can be written in a variety of languages and frameworks.
|
||||
|
||||
The documentation available here discusses various aspects of WinFsp.
|
||||
|
||||
## Programming
|
||||
|
||||
- The [[Tutorial|WinFsp-Tutorial]] describes how to create a simple, but complete file system in C/C++.
|
||||
- The [[API Reference|winfsp.h]] describes the native WinFsp API. This external [[link|http://www.secfs.net/winfsp/apiref/]] may be easier to browse for some people.
|
||||
- There is also a FUSE compatibility layer for native Windows and Cygwin. See fuse.h in the source repository.
|
||||
- This [[document|Native-API-vs-FUSE]] discusses the need for both a native API and FUSE and gives some pointers on which one to choose.
|
||||
|
||||
## Design
|
||||
|
||||
- The [[Design|WinFsp-Design]] document describes the high-level design of WinFsp.
|
||||
- The [[IPC|WinFsp-as-an-IPC-Mechanism]] document offers insights into the WinFsp Inter-Process Communication mechanism.
|
||||
- The [[Service Architecture|WinFsp-Service-Architecture]] document discusses how to intergrate a file system into Windows as a service and the reasons to do so.
|
||||
- The [[SSHFS Port Case Study|SSHFS-Port-Case-Study]] document chronicles the creation of the WinFsp-FUSE compatibility layer and the decisions that led to its design.
|
||||
|
||||
## Testing
|
||||
|
||||
- The [[Testing|WinFsp-Testing]] document discusses the WinFsp testing strategy and how WinFsp achieves correctness and stability.
|
||||
- The [[Performance|WinFsp-Performance-Testing]] document compares WinFsp performance against other file systems.
|
||||
|
||||
## Compatibility
|
||||
|
||||
- The [[Compatibility|NTFS-Compatibility]] document discusses current WinFsp compatibility with NTFS.
|
||||
|
||||
WinFsp is available under the GPLv3 license with a special exception for Free/Libre and Open Source Software.
|
17
doc/Known-File-Systems.asciidoc
Normal file
17
doc/Known-File-Systems.asciidoc
Normal file
@ -0,0 +1,17 @@
|
||||
= Known File Systems and File System Libraries
|
||||
|
||||
This document contains a list of known file systems and file system libraries that run on WinFsp. Please contact the WinFsp project to have your file system solution added to this list.
|
||||
|
||||
== File Systems
|
||||
|
||||
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
||||
- https://github.com/billziss-gh/redditfs[redditfs] - ls -l /r/programming
|
||||
- https://github.com/netheril96/securefs[securefs] - Filesystem in userspace (FUSE) with transparent authenticated encryption
|
||||
- https://github.com/billziss-gh/sshfs-win[sshfs-win] - SSHFS for Windows
|
||||
|
||||
== File System Libraries
|
||||
|
||||
- https://github.com/DuroSoft/fuse-bindings[fuse-bindings] - Fully maintained FUSE bindings for Node that aims to cover the entire FUSE api
|
||||
- https://github.com/ui4j/fuse-jna[fuse-jna] - No-nonsense, actually-working Java bindings to FUSE using JNA
|
||||
- https://github.com/billziss-gh/fusepy[fusepy] - Simple ctypes bindings for FUSE
|
||||
- https://github.com/yogendersolanki91/winfsp[WinFsp fork with .NET Layer] - by @yogendersolanki91
|
BIN
doc/WinFsp-Icon.png
Normal file
BIN
doc/WinFsp-Icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
@ -112,7 +112,7 @@ usage: passthrough OPTIONS
|
||||
|
||||
options:
|
||||
-d DebugFlags [-1: enable all debug logs]
|
||||
-D DebugLogFile [file path; use - for stdout]
|
||||
-D DebugLogFile [file path; use - for stderr]
|
||||
-u \Server\Share [UNC prefix (single backslash)]
|
||||
-p Directory [directory to expose as pass through file system]
|
||||
-m MountPoint [X:|*|directory]
|
||||
@ -138,7 +138,7 @@ The variable `DebugLogFile` is used to control the WinFsp debug logging mechanis
|
||||
if (0 != DebugLogFile)
|
||||
{
|
||||
if (0 == wcscmp(L"-", DebugLogFile))
|
||||
DebugLogHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
else
|
||||
DebugLogHandle = CreateFileW(
|
||||
DebugLogFile,
|
||||
|
@ -26,7 +26,10 @@
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#include <winternl.h>
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4005) /* macro redefinition */
|
||||
#include <ntstatus.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#if defined(WINFSP_DLL_INTERNAL)
|
||||
#define FSP_API __declspec(dllexport)
|
||||
@ -958,11 +961,14 @@ FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
||||
* The current operation context.
|
||||
*/
|
||||
FSP_API FSP_FILE_SYSTEM_OPERATION_CONTEXT *FspFileSystemGetOperationContext(VOID);
|
||||
FSP_API PWSTR FspFileSystemMountPointF(FSP_FILE_SYSTEM *FileSystem);
|
||||
static inline
|
||||
PWSTR FspFileSystemMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
||||
{
|
||||
return FileSystem->MountPoint;
|
||||
}
|
||||
FSP_API NTSTATUS FspFileSystemEnterOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
static inline
|
||||
NTSTATUS FspFileSystemEnterOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
@ -972,6 +978,8 @@ NTSTATUS FspFileSystemEnterOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
return FileSystem->EnterOperation(FileSystem, Request, Response);
|
||||
}
|
||||
FSP_API NTSTATUS FspFileSystemLeaveOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
static inline
|
||||
NTSTATUS FspFileSystemLeaveOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
@ -981,6 +989,9 @@ NTSTATUS FspFileSystemLeaveOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
return FileSystem->LeaveOperation(FileSystem, Request, Response);
|
||||
}
|
||||
FSP_API VOID FspFileSystemSetOperationGuardF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD *LeaveOperation);
|
||||
static inline
|
||||
VOID FspFileSystemSetOperationGuard(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
||||
@ -999,12 +1010,17 @@ VOID FspFileSystemSetOperationGuard(FSP_FILE_SYSTEM *FileSystem,
|
||||
* @see
|
||||
* FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY
|
||||
*/
|
||||
FSP_API VOID FspFileSystemSetOperationGuardStrategyF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy);
|
||||
static inline
|
||||
VOID FspFileSystemSetOperationGuardStrategy(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy)
|
||||
{
|
||||
FileSystem->OpGuardStrategy = GuardStrategy;
|
||||
}
|
||||
FSP_API VOID FspFileSystemSetOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||
ULONG Index,
|
||||
FSP_FILE_SYSTEM_OPERATION *Operation);
|
||||
static inline
|
||||
VOID FspFileSystemSetOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||
ULONG Index,
|
||||
@ -1012,6 +1028,8 @@ VOID FspFileSystemSetOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||
{
|
||||
FileSystem->Operations[Index] = Operation;
|
||||
}
|
||||
FSP_API VOID FspFileSystemGetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS *PDispatcherResult);
|
||||
static inline
|
||||
VOID FspFileSystemGetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS *PDispatcherResult)
|
||||
@ -1020,6 +1038,8 @@ VOID FspFileSystemGetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
||||
*PDispatcherResult = FileSystem->DispatcherResult;
|
||||
MemoryBarrier();
|
||||
}
|
||||
FSP_API VOID FspFileSystemSetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS DispatcherResult);
|
||||
static inline
|
||||
VOID FspFileSystemSetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS DispatcherResult)
|
||||
@ -1028,12 +1048,15 @@ VOID FspFileSystemSetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
||||
return;
|
||||
InterlockedCompareExchange(&FileSystem->DispatcherResult, DispatcherResult, 0);
|
||||
}
|
||||
FSP_API VOID FspFileSystemSetDebugLogF(FSP_FILE_SYSTEM *FileSystem,
|
||||
UINT32 DebugLog);
|
||||
static inline
|
||||
VOID FspFileSystemSetDebugLog(FSP_FILE_SYSTEM *FileSystem,
|
||||
UINT32 DebugLog)
|
||||
{
|
||||
FileSystem->DebugLog = DebugLog;
|
||||
}
|
||||
FSP_API BOOLEAN FspFileSystemIsOperationCaseSensitiveF(VOID);
|
||||
static inline
|
||||
BOOLEAN FspFileSystemIsOperationCaseSensitive(VOID)
|
||||
{
|
||||
@ -1642,6 +1665,18 @@ NTSTATUS FspLoad(PVOID *PModule)
|
||||
#endif
|
||||
#define FSP_DLLPATH "bin\\" FSP_DLLNAME
|
||||
|
||||
WINADVAPI
|
||||
LSTATUS
|
||||
APIENTRY
|
||||
RegGetValueW(
|
||||
HKEY hkey,
|
||||
LPCWSTR lpSubKey,
|
||||
LPCWSTR lpValue,
|
||||
DWORD dwFlags,
|
||||
LPDWORD pdwType,
|
||||
PVOID pvData,
|
||||
LPDWORD pcbData);
|
||||
|
||||
WCHAR PathBuf[MAX_PATH];
|
||||
DWORD Size;
|
||||
HKEY RegKey;
|
||||
|
1308
inc/winfsp/winfsp.hpp
Normal file
1308
inc/winfsp/winfsp.hpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
opt/cygfuse/dist/fuse-2.8-4.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/fuse-2.8-4.tar.xz
vendored
Normal file
Binary file not shown.
1
opt/cygfuse/dist/install.sh
vendored
Normal file
1
opt/cygfuse/dist/install.sh
vendored
Normal file
@ -0,0 +1 @@
|
||||
tar -C/ -xaf fuse-2.8-*.tar.xz
|
1
opt/cygfuse/dist/uninstall.sh
vendored
Normal file
1
opt/cygfuse/dist/uninstall.sh
vendored
Normal file
@ -0,0 +1 @@
|
||||
tar -taf fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
64
src/dll/fs.c
64
src/dll/fs.c
@ -619,3 +619,67 @@ FSP_API FSP_FILE_SYSTEM_OPERATION_CONTEXT *FspFileSystemGetOperationContext(VOID
|
||||
{
|
||||
return (FSP_FILE_SYSTEM_OPERATION_CONTEXT *)TlsGetValue(FspFileSystemTlsKey);
|
||||
}
|
||||
|
||||
/*
|
||||
* Out-of-Line
|
||||
*/
|
||||
|
||||
FSP_API PWSTR FspFileSystemMountPointF(FSP_FILE_SYSTEM *FileSystem)
|
||||
{
|
||||
return FspFileSystemMountPoint(FileSystem);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemEnterOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
return FspFileSystemEnterOperation(FileSystem, Request, Response);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemLeaveOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
return FspFileSystemLeaveOperation(FileSystem, Request, Response);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemSetOperationGuardF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD *LeaveOperation)
|
||||
{
|
||||
FspFileSystemSetOperationGuard(FileSystem, EnterOperation, LeaveOperation);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemSetOperationGuardStrategyF(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy)
|
||||
{
|
||||
FspFileSystemSetOperationGuardStrategy(FileSystem, GuardStrategy);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemSetOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||
ULONG Index,
|
||||
FSP_FILE_SYSTEM_OPERATION *Operation)
|
||||
{
|
||||
FspFileSystemSetOperation(FileSystem, Index, Operation);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemGetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS *PDispatcherResult)
|
||||
{
|
||||
FspFileSystemGetDispatcherResult(FileSystem, PDispatcherResult);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemSetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS DispatcherResult)
|
||||
{
|
||||
FspFileSystemSetDispatcherResult(FileSystem, DispatcherResult);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemSetDebugLogF(FSP_FILE_SYSTEM *FileSystem,
|
||||
UINT32 DebugLog)
|
||||
{
|
||||
FspFileSystemSetDebugLog(FileSystem, DebugLog);
|
||||
}
|
||||
|
||||
FSP_API BOOLEAN FspFileSystemIsOperationCaseSensitiveF(VOID)
|
||||
{
|
||||
return FspFileSystemIsOperationCaseSensitive();
|
||||
}
|
||||
|
@ -355,10 +355,18 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
{
|
||||
LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
|
||||
if (0 != LastError)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(LastError);
|
||||
goto exit;
|
||||
}
|
||||
/*
|
||||
* Apparently GetEffectiveRightsFromAclW can fail with ERROR_CIRCULAR_DEPENDENCY
|
||||
* in some rare circumstances. Calling GetEffectiveRightsFromAclW is not essential
|
||||
* in this instance. It is only done to check whether the "Everyone/World" SID
|
||||
* already has the access required to start the FSD; if it does not have those
|
||||
* rights already they are added. It is probably safe to just assume that the
|
||||
* required rights are not there if GetEffectiveRightsFromAclW fails; the worst
|
||||
* that can happen is that the rights get added twice (which is benign).
|
||||
*
|
||||
* See https://github.com/billziss-gh/winfsp/issues/62
|
||||
*/
|
||||
AccessRights = 0;
|
||||
}
|
||||
|
||||
/* do we have the required access rights? */
|
||||
|
@ -1354,7 +1354,7 @@ FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||
static NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS (*GetReparsePointByName)(
|
||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
||||
|
@ -32,6 +32,7 @@ struct fsp_fuse_core_opt_data
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
@ -39,7 +40,12 @@ struct fsp_fuse_core_opt_data
|
||||
rellinks;
|
||||
int set_FileInfoTimeout;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
};
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
||||
"fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same.");
|
||||
|
||||
static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
{
|
||||
@ -52,6 +58,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("-d", debug, 1),
|
||||
FSP_FUSE_CORE_OPT("debug", debug, 1),
|
||||
|
||||
FUSE_OPT_KEY("DebugLog=", 'D'),
|
||||
|
||||
FUSE_OPT_KEY("hard_remove", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("use_ino", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("readdir_ino", FUSE_OPT_KEY_DISCARD),
|
||||
@ -79,6 +87,7 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
||||
|
||||
FUSE_OPT_KEY("fstypename=", 'F'),
|
||||
FUSE_OPT_KEY("volname=", 'v'),
|
||||
|
||||
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
||||
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
||||
@ -450,6 +459,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
case 'h':
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||
FSP_FUSE_LIBRARY_NAME " options:\n"
|
||||
" -o DebugLog=FILE debug log file (deflt: stderr)\n"
|
||||
" -o SectorSize=N sector size for Windows (512-4096, deflt: 4096)\n"
|
||||
" -o SectorsPerAllocationUnit=N sectors per allocation unit (deflt: 1)\n"
|
||||
" -o MaxComponentLength=N max file name component length (deflt: 255)\n"
|
||||
@ -466,6 +476,17 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION);
|
||||
opt_data->help = 1;
|
||||
return 1;
|
||||
case 'D':
|
||||
arg += sizeof "DebugLog=" - 1;
|
||||
opt_data->DebugLogHandle = CreateFileA(
|
||||
arg,
|
||||
FILE_APPEND_DATA,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
return 0;
|
||||
case 'U':
|
||||
if ('U' == arg[2])
|
||||
arg += sizeof "--UNC=" - 1;
|
||||
@ -484,12 +505,20 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
arg += sizeof "--FileSystemName=" - 1;
|
||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||
opt_data->VolumeParams.FileSystemName + 5,
|
||||
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR)) - 5)
|
||||
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 5))
|
||||
return -1;
|
||||
opt_data->VolumeParams.FileSystemName
|
||||
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
|
||||
return 0;
|
||||
case 'v':
|
||||
arg += sizeof "volname=" - 1;
|
||||
opt_data->VolumeLabelLength = (UINT16)(sizeof(WCHAR) *
|
||||
MultiByteToWideChar(CP_UTF8, 0, arg, lstrlenA(arg),
|
||||
opt_data->VolumeLabel, sizeof opt_data->VolumeLabel / sizeof(WCHAR)));
|
||||
if (0 == opt_data->VolumeLabelLength)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,6 +537,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
opt_data.env = env;
|
||||
opt_data.DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000; /* default FileInfoTimeout for FUSE file systems */
|
||||
|
||||
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
||||
@ -515,6 +545,16 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
if (opt_data.help)
|
||||
return 0;
|
||||
|
||||
if (opt_data.debug)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == opt_data.DebugLogHandle)
|
||||
{
|
||||
ErrorMessage = L": cannot open debug log file.";
|
||||
goto fail;
|
||||
}
|
||||
FspDebugLogSetHandle(opt_data.DebugLogHandle);
|
||||
}
|
||||
|
||||
if ((opt_data.set_uid && -1 == opt_data.uid) ||
|
||||
(opt_data.set_gid && -1 == opt_data.gid))
|
||||
{
|
||||
@ -563,6 +603,8 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
f->data = data;
|
||||
f->DebugLog = opt_data.debug ? -1 : 0;
|
||||
memcpy(&f->VolumeParams, &opt_data.VolumeParams, sizeof opt_data.VolumeParams);
|
||||
f->VolumeLabelLength = opt_data.VolumeLabelLength;
|
||||
memcpy(&f->VolumeLabel, &opt_data.VolumeLabel, opt_data.VolumeLabelLength);
|
||||
|
||||
Size = (lstrlenW(ch->MountPoint) + 1) * sizeof(WCHAR);
|
||||
f->MountPoint = fsp_fuse_obj_alloc(env, Size);
|
||||
|
35
src/dll/fuse/fuse_compat.c
Normal file
35
src/dll/fuse/fuse_compat.c
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_compat.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
/*
|
||||
* This file provides an implementation of the `fuse_*` symbols. This
|
||||
* implementation is a simple shim that forwards `fuse_*` calls to the
|
||||
* equivalent `fsp_fuse_*` ones using a default `fsp_fuse_env`.
|
||||
*
|
||||
* These symbols should *not* be used by C/C++ programs. For this reason
|
||||
* the `fuse.h` headers only expose the `fsp_fuse_*` symbols, wrapped
|
||||
* with macros. These symbols are for use only from programs using FFI
|
||||
* technology to access FUSE symbols (e.g. fusepy, jnr-fuse).
|
||||
*/
|
||||
|
||||
#define FSP_FUSE_API
|
||||
#define FSP_FUSE_SYM(proto, ...) __declspec(dllexport) proto { __VA_ARGS__ }
|
||||
#include <fuse/fuse_common.h>
|
||||
#include <fuse/fuse.h>
|
||||
#include <fuse/fuse_opt.h>
|
@ -636,18 +636,18 @@ static NTSTATUS fsp_fuse_intf_GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
struct fuse_statvfs stbuf;
|
||||
int err;
|
||||
|
||||
if (0 == f->ops.statfs)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
err = f->ops.statfs("/", &stbuf);
|
||||
if (0 != err)
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (0 != f->ops.statfs)
|
||||
{
|
||||
err = f->ops.statfs("/", &stbuf);
|
||||
if (0 != err)
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
|
||||
VolumeInfo->TotalSize = (UINT64)stbuf.f_blocks * (UINT64)stbuf.f_frsize;
|
||||
VolumeInfo->FreeSize = (UINT64)stbuf.f_bfree * (UINT64)stbuf.f_frsize;
|
||||
VolumeInfo->VolumeLabelLength = 0;
|
||||
VolumeInfo->VolumeLabel[0] = L'\0';
|
||||
VolumeInfo->VolumeLabelLength = f->VolumeLabelLength;
|
||||
memcpy(&VolumeInfo->VolumeLabel, &f->VolumeLabel, f->VolumeLabelLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ struct fuse
|
||||
UINT32 DebugLog;
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
PWSTR MountPoint;
|
||||
FSP_FILE_SYSTEM *FileSystem;
|
||||
FSP_SERVICE *Service; /* weak */
|
||||
|
@ -79,7 +79,7 @@ FSP_API ULONG FspServiceRunEx(PWSTR ServiceName,
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"The service %s cannot be created (Status=%lx).", Service->ServiceName, Result);
|
||||
L"The service %s cannot be created (Status=%lx).", ServiceName, Result);
|
||||
return FspWin32FromNtStatus(Result);
|
||||
}
|
||||
Service->UserContext = UserContext;
|
||||
@ -92,7 +92,7 @@ FSP_API ULONG FspServiceRunEx(PWSTR ServiceName,
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"The service %s has failed to run (Status=%lx).", Service->ServiceName, Result);
|
||||
L"The service %s has failed to run (Status=%lx).", ServiceName, Result);
|
||||
return FspWin32FromNtStatus(Result);
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,8 @@ FSP_API NTSTATUS FspVersion(PUINT32 PVersion)
|
||||
* Two threads competing to read the version will read
|
||||
* the same value from the Version resource.
|
||||
*/
|
||||
*PVersion = 0;
|
||||
|
||||
extern HINSTANCE DllInstance;
|
||||
WCHAR ModuleFileName[MAX_PATH];
|
||||
PVOID VersionInfo;
|
||||
|
2364
src/dotnet/FileSystemBase+Const.cs
Normal file
2364
src/dotnet/FileSystemBase+Const.cs
Normal file
File diff suppressed because it is too large
Load Diff
454
src/dotnet/FileSystemBase.cs
Normal file
454
src/dotnet/FileSystemBase.cs
Normal file
@ -0,0 +1,454 @@
|
||||
/**
|
||||
* @file dotnet/FileSystemBase.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
using Fsp.Interop;
|
||||
|
||||
namespace Fsp
|
||||
{
|
||||
|
||||
public partial class FileSystemBase
|
||||
{
|
||||
/* types */
|
||||
public class DirectoryBuffer : IDisposable
|
||||
{
|
||||
~DirectoryBuffer()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(true);
|
||||
}
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
Api.FspFileSystemDeleteDirectoryBuffer(ref DirBuffer);
|
||||
}
|
||||
|
||||
internal IntPtr DirBuffer;
|
||||
}
|
||||
|
||||
/* operations */
|
||||
public virtual Int32 ExceptionHandler(Exception ex)
|
||||
{
|
||||
return STATUS_UNEXPECTED_IO_ERROR;
|
||||
}
|
||||
public virtual Int32 Init(Object Host)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public virtual Int32 Mounted(Object Host)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public virtual void Unmounted(Object Host)
|
||||
{
|
||||
}
|
||||
public virtual Int32 GetVolumeInfo(
|
||||
out VolumeInfo VolumeInfo)
|
||||
{
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 SetVolumeLabel(
|
||||
String VolumeLabel,
|
||||
out VolumeInfo VolumeInfo)
|
||||
{
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 GetSecurityByName(
|
||||
String FileName,
|
||||
out UInt32 FileAttributes/* or ReparsePointIndex */,
|
||||
ref Byte[] SecurityDescriptor)
|
||||
{
|
||||
FileAttributes = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 Create(
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
UInt32 FileAttributes,
|
||||
Byte[] SecurityDescriptor,
|
||||
UInt64 AllocationSize,
|
||||
out Object FileNode,
|
||||
out Object FileDesc,
|
||||
out FileInfo FileInfo,
|
||||
out String NormalizedName)
|
||||
{
|
||||
FileNode = default(Object);
|
||||
FileDesc = default(Object);
|
||||
FileInfo = default(FileInfo);
|
||||
NormalizedName = default(String);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 Open(
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
out Object FileNode,
|
||||
out Object FileDesc,
|
||||
out FileInfo FileInfo,
|
||||
out String NormalizedName)
|
||||
{
|
||||
FileNode = default(Object);
|
||||
FileDesc = default(Object);
|
||||
FileInfo = default(FileInfo);
|
||||
NormalizedName = default(String);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 Overwrite(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
UInt32 FileAttributes,
|
||||
Boolean ReplaceFileAttributes,
|
||||
UInt64 AllocationSize,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual void Cleanup(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
UInt32 Flags)
|
||||
{
|
||||
}
|
||||
public virtual void Close(
|
||||
Object FileNode,
|
||||
Object FileDesc)
|
||||
{
|
||||
}
|
||||
public virtual Int32 Read(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
BytesTransferred = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 Write(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
Boolean WriteToEndOfFile,
|
||||
Boolean ConstrainedIo,
|
||||
out UInt32 BytesTransferred,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
BytesTransferred = default(UInt32);
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 Flush(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 GetFileInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 SetBasicInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
UInt32 FileAttributes,
|
||||
UInt64 CreationTime,
|
||||
UInt64 LastAccessTime,
|
||||
UInt64 LastWriteTime,
|
||||
UInt64 ChangeTime,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 SetFileSize(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
UInt64 NewSize,
|
||||
Boolean SetAllocationSize,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 CanDelete(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 Rename(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
String NewFileName,
|
||||
Boolean ReplaceIfExists)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 GetSecurity(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
ref Byte[] SecurityDescriptor)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 SetSecurity(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
AccessControlSections Sections,
|
||||
Byte[] SecurityDescriptor)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 ReadDirectory(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String Pattern,
|
||||
String Marker,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
return SeekableReadDirectory(FileNode, FileDesc, Pattern, Marker, Buffer, Length,
|
||||
out BytesTransferred);
|
||||
}
|
||||
public virtual Boolean ReadDirectoryEntry(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String Pattern,
|
||||
String Marker,
|
||||
ref Object Context,
|
||||
out String FileName,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileName = default(String);
|
||||
FileInfo = default(FileInfo);
|
||||
return false;
|
||||
}
|
||||
public virtual Int32 ResolveReparsePoints(
|
||||
String FileName,
|
||||
UInt32 ReparsePointIndex,
|
||||
Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock IoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr Size)
|
||||
{
|
||||
GCHandle Handle = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||
try
|
||||
{
|
||||
return Api.FspFileSystemResolveReparsePoints(
|
||||
IntPtr.Zero,
|
||||
GetReparsePointByName,
|
||||
(IntPtr)Handle,
|
||||
FileName,
|
||||
ReparsePointIndex,
|
||||
ResolveLastPathComponent,
|
||||
out IoStatus,
|
||||
Buffer,
|
||||
ref Size);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Handle.Free();
|
||||
}
|
||||
}
|
||||
public virtual Int32 GetReparsePointByName(
|
||||
String FileName,
|
||||
Boolean IsDirectory,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr Size)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 GetReparsePoint(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
out UIntPtr Size)
|
||||
{
|
||||
Size = default(UIntPtr);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 SetReparsePoint(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 DeleteReparsePoint(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
public virtual Int32 GetStreamInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
BytesTransferred = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
/* helpers */
|
||||
public static Int32 NtStatusFromWin32(UInt32 Error)
|
||||
{
|
||||
return Api.FspNtStatusFromWin32(Error);
|
||||
}
|
||||
public static UInt32 Win32FromNtStatus(Int32 Status)
|
||||
{
|
||||
return Api.FspWin32FromNtStatus(Status);
|
||||
}
|
||||
public Int32 SeekableReadDirectory(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String Pattern,
|
||||
String Marker,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
Object Context = null;
|
||||
String FileName;
|
||||
DirInfo DirInfo = default(DirInfo);
|
||||
BytesTransferred = default(UInt32);
|
||||
while (ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker,
|
||||
ref Context, out FileName, out DirInfo.FileInfo))
|
||||
{
|
||||
DirInfo.SetFileNameBuf(FileName);
|
||||
if (!Api.FspFileSystemAddDirInfo(ref DirInfo, Buffer, Length,
|
||||
out BytesTransferred))
|
||||
break;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public Int32 BufferedReadDirectory(
|
||||
DirectoryBuffer DirectoryBuffer,
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String Pattern,
|
||||
String Marker,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
Object Context = null;
|
||||
String FileName;
|
||||
DirInfo DirInfo = default(DirInfo);
|
||||
Int32 DirBufferResult = STATUS_SUCCESS;
|
||||
BytesTransferred = default(UInt32);
|
||||
if (Api.FspFileSystemAcquireDirectoryBuffer(ref DirectoryBuffer.DirBuffer, null == Marker,
|
||||
out DirBufferResult))
|
||||
try
|
||||
{
|
||||
while (ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker,
|
||||
ref Context, out FileName, out DirInfo.FileInfo))
|
||||
{
|
||||
DirInfo.SetFileNameBuf(FileName);
|
||||
if (!Api.FspFileSystemFillDirectoryBuffer(
|
||||
ref DirectoryBuffer.DirBuffer, ref DirInfo, out DirBufferResult))
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Api.FspFileSystemReleaseDirectoryBuffer(ref DirectoryBuffer.DirBuffer);
|
||||
}
|
||||
if (0 > DirBufferResult)
|
||||
{
|
||||
BytesTransferred = default(UInt32);
|
||||
return DirBufferResult;
|
||||
}
|
||||
Api.FspFileSystemReadDirectoryBuffer(ref DirectoryBuffer.DirBuffer,
|
||||
Marker, Buffer, Length, out BytesTransferred);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public Int32 FindReparsePoint(
|
||||
String FileName,
|
||||
out UInt32 ReparsePointIndex)
|
||||
{
|
||||
GCHandle Handle = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||
try
|
||||
{
|
||||
return Api.FspFileSystemFindReparsePoint(
|
||||
IntPtr.Zero,
|
||||
GetReparsePointByName,
|
||||
(IntPtr)Handle,
|
||||
FileName,
|
||||
out ReparsePointIndex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Handle.Free();
|
||||
}
|
||||
}
|
||||
private static Int32 GetReparsePointByName(
|
||||
IntPtr FileSystem,
|
||||
IntPtr Context,
|
||||
String FileName,
|
||||
Boolean IsDirectory,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr Size)
|
||||
{
|
||||
FileSystemBase self = (FileSystemBase)GCHandle.FromIntPtr(Context).Target;
|
||||
try
|
||||
{
|
||||
return self.GetReparsePointByName(
|
||||
FileName,
|
||||
IsDirectory,
|
||||
Buffer,
|
||||
ref Size);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return self.ExceptionHandler(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
920
src/dotnet/FileSystemHost.cs
Normal file
920
src/dotnet/FileSystemHost.cs
Normal file
@ -0,0 +1,920 @@
|
||||
/**
|
||||
* @file dotnet/FileSystemHost.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
using Fsp.Interop;
|
||||
|
||||
namespace Fsp
|
||||
{
|
||||
|
||||
public class FileSystemHost : IDisposable
|
||||
{
|
||||
/* ctor/dtor */
|
||||
public FileSystemHost(FileSystemBase FileSystem)
|
||||
{
|
||||
_VolumeParams.Flags = VolumeParams.UmFileContextIsFullContext;
|
||||
_FileSystem = FileSystem;
|
||||
}
|
||||
~FileSystemHost()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(true);
|
||||
}
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (IntPtr.Zero != _FileSystemPtr)
|
||||
{
|
||||
Api.FspFileSystemStopDispatcher(_FileSystemPtr);
|
||||
if (disposing)
|
||||
try
|
||||
{
|
||||
_FileSystem.Unmounted(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionHandler(_FileSystem, ex);
|
||||
}
|
||||
Api.SetUserContext(_FileSystemPtr, null);
|
||||
Api.FspFileSystemDelete(_FileSystemPtr);
|
||||
_FileSystemPtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/* properties */
|
||||
public UInt16 SectorSize
|
||||
{
|
||||
get { return _VolumeParams.SectorSize; }
|
||||
set { _VolumeParams.SectorSize = value; }
|
||||
}
|
||||
public UInt16 SectorsPerAllocationUnit
|
||||
{
|
||||
get { return _VolumeParams.SectorsPerAllocationUnit; }
|
||||
set { _VolumeParams.SectorsPerAllocationUnit = value; }
|
||||
}
|
||||
public UInt16 MaxComponentLength
|
||||
{
|
||||
get { return _VolumeParams.MaxComponentLength; }
|
||||
set { _VolumeParams.MaxComponentLength = value; }
|
||||
}
|
||||
public UInt64 VolumeCreationTime
|
||||
{
|
||||
get { return _VolumeParams.VolumeCreationTime; }
|
||||
set { _VolumeParams.VolumeCreationTime = value; }
|
||||
}
|
||||
public UInt32 VolumeSerialNumber
|
||||
{
|
||||
get { return _VolumeParams.VolumeSerialNumber; }
|
||||
set { _VolumeParams.VolumeSerialNumber = value; }
|
||||
}
|
||||
public UInt32 FileInfoTimeout
|
||||
{
|
||||
get { return _VolumeParams.FileInfoTimeout; }
|
||||
set { _VolumeParams.FileInfoTimeout = value; }
|
||||
}
|
||||
public Boolean CaseSensitiveSearch
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.CaseSensitiveSearch); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.CaseSensitiveSearch : 0); }
|
||||
}
|
||||
public Boolean CasePreservedNames
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.CasePreservedNames); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.CasePreservedNames : 0); }
|
||||
}
|
||||
public Boolean UnicodeOnDisk
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.UnicodeOnDisk); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.UnicodeOnDisk : 0); }
|
||||
}
|
||||
public Boolean PersistentAcls
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PersistentAcls); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PersistentAcls : 0); }
|
||||
}
|
||||
public Boolean ReparsePoints
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.ReparsePoints); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.ReparsePoints : 0); }
|
||||
}
|
||||
public Boolean ReparsePointsAccessCheck
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.ReparsePointsAccessCheck); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.ReparsePointsAccessCheck : 0); }
|
||||
}
|
||||
public Boolean NamedStreams
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.NamedStreams); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.NamedStreams : 0); }
|
||||
}
|
||||
public Boolean PostCleanupWhenModifiedOnly
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PostCleanupWhenModifiedOnly); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PostCleanupWhenModifiedOnly : 0); }
|
||||
}
|
||||
public Boolean PassQueryDirectoryPattern
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PassQueryDirectoryPattern); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PassQueryDirectoryPattern : 0); }
|
||||
}
|
||||
public String Prefix
|
||||
{
|
||||
get { return _VolumeParams.GetPrefix(); }
|
||||
set { _VolumeParams.SetPrefix(value); }
|
||||
}
|
||||
public String FileSystemName
|
||||
{
|
||||
get { return _VolumeParams.GetFileSystemName(); }
|
||||
set { _VolumeParams.SetFileSystemName(value); }
|
||||
}
|
||||
|
||||
/* control */
|
||||
public Int32 Preflight(String MountPoint)
|
||||
{
|
||||
return Api.FspFileSystemPreflight(
|
||||
_VolumeParams.IsPrefixEmpty() ? "WinFsp.Disk" : "WinFsp.Net",
|
||||
MountPoint);
|
||||
}
|
||||
public Int32 Mount(String MountPoint,
|
||||
Byte[] SecurityDescriptor = null,
|
||||
Boolean Synchronized = false,
|
||||
UInt32 DebugLog = 0)
|
||||
{
|
||||
Int32 Result;
|
||||
try
|
||||
{
|
||||
Result = _FileSystem.Init(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Result = ExceptionHandler(_FileSystem, ex);
|
||||
}
|
||||
if (0 > Result)
|
||||
return Result;
|
||||
Result = Api.FspFileSystemCreate(
|
||||
_VolumeParams.IsPrefixEmpty() ? "WinFsp.Disk" : "WinFsp.Net",
|
||||
ref _VolumeParams, _FileSystemInterfacePtr, out _FileSystemPtr);
|
||||
if (0 > Result)
|
||||
return Result;
|
||||
Api.SetUserContext(_FileSystemPtr, _FileSystem);
|
||||
Api.FspFileSystemSetOperationGuardStrategy(_FileSystemPtr, Synchronized ?
|
||||
1/*FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE*/ :
|
||||
0/*FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE*/);
|
||||
Api.FspFileSystemSetDebugLog(_FileSystemPtr, DebugLog);
|
||||
Result = Api.FspFileSystemSetMountPointEx(_FileSystemPtr, MountPoint,
|
||||
SecurityDescriptor);
|
||||
if (0 <= Result)
|
||||
{
|
||||
try
|
||||
{
|
||||
Result = _FileSystem.Mounted(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Result = ExceptionHandler(_FileSystem, ex);
|
||||
}
|
||||
if (0 <= Result)
|
||||
{
|
||||
Result = Api.FspFileSystemStartDispatcher(_FileSystemPtr, 0);
|
||||
if (0 > Result)
|
||||
try
|
||||
{
|
||||
_FileSystem.Unmounted(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionHandler(_FileSystem, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0 > Result)
|
||||
{
|
||||
Api.SetUserContext(_FileSystemPtr, null);
|
||||
Api.FspFileSystemDelete(_FileSystemPtr);
|
||||
_FileSystemPtr = IntPtr.Zero;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
public void Unmount()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
public String MountPoint()
|
||||
{
|
||||
return IntPtr.Zero != _FileSystemPtr ?
|
||||
Marshal.PtrToStringUni(Api.FspFileSystemMountPoint(_FileSystemPtr)) : null;
|
||||
}
|
||||
public IntPtr FileSystemHandle()
|
||||
{
|
||||
return _FileSystemPtr;
|
||||
}
|
||||
public FileSystemBase FileSystem()
|
||||
{
|
||||
return _FileSystem;
|
||||
}
|
||||
public static Int32 SetDebugLogFile(String FileName)
|
||||
{
|
||||
return Api.SetDebugLogFile(FileName);
|
||||
}
|
||||
|
||||
/* FSP_FILE_SYSTEM_INTERFACE */
|
||||
private static Byte[] SecurityDescriptorNotNull = new Byte[0];
|
||||
private static Int32 ExceptionHandler(
|
||||
FileSystemBase FileSystem,
|
||||
Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return FileSystem.ExceptionHandler(ex);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return unchecked((Int32)0xc00000e9)/*STATUS_UNEXPECTED_IO_ERROR*/;
|
||||
}
|
||||
}
|
||||
private static Int32 GetVolumeInfo(
|
||||
IntPtr FileSystemPtr,
|
||||
out VolumeInfo VolumeInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
return FileSystem.GetVolumeInfo(
|
||||
out VolumeInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 SetVolumeLabel(
|
||||
IntPtr FileSystemPtr,
|
||||
String VolumeLabel,
|
||||
out VolumeInfo VolumeInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
return FileSystem.SetVolumeLabel(
|
||||
VolumeLabel,
|
||||
out VolumeInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 GetSecurityByName(
|
||||
IntPtr FileSystemPtr,
|
||||
String FileName,
|
||||
IntPtr PFileAttributes/* or ReparsePointIndex */,
|
||||
IntPtr SecurityDescriptor,
|
||||
IntPtr PSecurityDescriptorSize)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
UInt32 FileAttributes;
|
||||
Byte[] SecurityDescriptorBytes = null;
|
||||
Int32 Result;
|
||||
if (IntPtr.Zero != PSecurityDescriptorSize)
|
||||
SecurityDescriptorBytes = SecurityDescriptorNotNull;
|
||||
Result = FileSystem.GetSecurityByName(
|
||||
FileName,
|
||||
out FileAttributes,
|
||||
ref SecurityDescriptorBytes);
|
||||
if (0 <= Result)
|
||||
{
|
||||
if (IntPtr.Zero != PFileAttributes)
|
||||
Marshal.WriteInt32(PFileAttributes, (Int32)FileAttributes);
|
||||
Result = Api.CopySecurityDescriptor(SecurityDescriptorBytes,
|
||||
SecurityDescriptor, PSecurityDescriptorSize);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Create(
|
||||
IntPtr FileSystemPtr,
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
UInt32 FileAttributes,
|
||||
IntPtr SecurityDescriptor,
|
||||
UInt64 AllocationSize,
|
||||
ref FullContext FullContext,
|
||||
ref OpenFileInfo OpenFileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
String NormalizedName;
|
||||
Int32 Result;
|
||||
Result = FileSystem.Create(
|
||||
FileName,
|
||||
CreateOptions,
|
||||
GrantedAccess,
|
||||
FileAttributes,
|
||||
Api.MakeSecurityDescriptor(SecurityDescriptor),
|
||||
AllocationSize,
|
||||
out FileNode,
|
||||
out FileDesc,
|
||||
out OpenFileInfo.FileInfo,
|
||||
out NormalizedName);
|
||||
if (0 <= Result)
|
||||
{
|
||||
if (null != NormalizedName)
|
||||
OpenFileInfo.SetNormalizedName(NormalizedName);
|
||||
Api.SetFullContext(ref FullContext, FileNode, FileDesc);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Open(
|
||||
IntPtr FileSystemPtr,
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
ref FullContext FullContext,
|
||||
ref OpenFileInfo OpenFileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
String NormalizedName;
|
||||
Int32 Result;
|
||||
Result = FileSystem.Open(
|
||||
FileName,
|
||||
CreateOptions,
|
||||
GrantedAccess,
|
||||
out FileNode,
|
||||
out FileDesc,
|
||||
out OpenFileInfo.FileInfo,
|
||||
out NormalizedName);
|
||||
if (0 <= Result)
|
||||
{
|
||||
if (null != NormalizedName)
|
||||
OpenFileInfo.SetNormalizedName(NormalizedName);
|
||||
Api.SetFullContext(ref FullContext, FileNode, FileDesc);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Overwrite(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
UInt32 FileAttributes,
|
||||
Boolean ReplaceFileAttributes,
|
||||
UInt64 AllocationSize,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Overwrite(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileAttributes,
|
||||
ReplaceFileAttributes,
|
||||
AllocationSize,
|
||||
out FileInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static void Cleanup(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
UInt32 Flags)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
FileSystem.Cleanup(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Flags);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static void Close(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
FileSystem.Close(
|
||||
FileNode,
|
||||
FileDesc);
|
||||
Api.SetFullContext(ref FullContext, null, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Read(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Read(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
Buffer,
|
||||
Offset,
|
||||
Length,
|
||||
out PBytesTransferred);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PBytesTransferred = default(UInt32);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Write(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
Boolean WriteToEndOfFile,
|
||||
Boolean ConstrainedIo,
|
||||
out UInt32 PBytesTransferred,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Write(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
Buffer,
|
||||
Offset,
|
||||
Length,
|
||||
WriteToEndOfFile,
|
||||
ConstrainedIo,
|
||||
out PBytesTransferred,
|
||||
out FileInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PBytesTransferred = default(UInt32);
|
||||
FileInfo = default(FileInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Flush(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Flush(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
out FileInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 GetFileInfo(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.GetFileInfo(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
out FileInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 SetBasicInfo(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
UInt32 FileAttributes,
|
||||
UInt64 CreationTime,
|
||||
UInt64 LastAccessTime,
|
||||
UInt64 LastWriteTime,
|
||||
UInt64 ChangeTime,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.SetBasicInfo(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileAttributes,
|
||||
CreationTime,
|
||||
LastAccessTime,
|
||||
LastWriteTime,
|
||||
ChangeTime,
|
||||
out FileInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 SetFileSize(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
UInt64 NewSize,
|
||||
Boolean SetAllocationSize,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.SetFileSize(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
NewSize,
|
||||
SetAllocationSize,
|
||||
out FileInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileInfo = default(FileInfo);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 CanDelete(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.CanDelete(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Rename(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
String NewFileName,
|
||||
Boolean ReplaceIfExists)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Rename(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
NewFileName,
|
||||
ReplaceIfExists);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 GetSecurity(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
IntPtr SecurityDescriptor,
|
||||
IntPtr PSecurityDescriptorSize)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Byte[] SecurityDescriptorBytes;
|
||||
Int32 Result;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
SecurityDescriptorBytes = SecurityDescriptorNotNull;
|
||||
Result = FileSystem.GetSecurity(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
ref SecurityDescriptorBytes);
|
||||
return Api.CopySecurityDescriptor(SecurityDescriptorBytes,
|
||||
SecurityDescriptor, PSecurityDescriptorSize);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 SetSecurity(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
UInt32 SecurityInformation,
|
||||
IntPtr ModificationDescriptor)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
AccessControlSections Sections;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
Sections = AccessControlSections.None;
|
||||
if (0 != (SecurityInformation & 1/*OWNER_SECURITY_INFORMATION*/))
|
||||
Sections |= AccessControlSections.Owner;
|
||||
if (0 != (SecurityInformation & 2/*GROUP_SECURITY_INFORMATION*/))
|
||||
Sections |= AccessControlSections.Group;
|
||||
if (0 != (SecurityInformation & 4/*DACL_SECURITY_INFORMATION*/))
|
||||
Sections |= AccessControlSections.Access;
|
||||
if (0 != (SecurityInformation & 8/*SACL_SECURITY_INFORMATION*/))
|
||||
Sections |= AccessControlSections.Audit;
|
||||
return FileSystem.SetSecurity(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
Sections,
|
||||
Api.MakeSecurityDescriptor(ModificationDescriptor));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 ReadDirectory(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String Pattern,
|
||||
String Marker,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.ReadDirectory(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
Pattern,
|
||||
Marker,
|
||||
Buffer,
|
||||
Length,
|
||||
out PBytesTransferred);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PBytesTransferred = default(UInt32);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 ResolveReparsePoints(
|
||||
IntPtr FileSystemPtr,
|
||||
String FileName,
|
||||
UInt32 ReparsePointIndex,
|
||||
Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock PIoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
return FileSystem.ResolveReparsePoints(
|
||||
FileName,
|
||||
ReparsePointIndex,
|
||||
ResolveLastPathComponent,
|
||||
out PIoStatus,
|
||||
Buffer,
|
||||
ref PSize);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PIoStatus = default(IoStatusBlock);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 GetReparsePoint(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
out UIntPtr PSize)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.GetReparsePoint(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Buffer,
|
||||
out PSize);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PSize = default(UIntPtr);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 SetReparsePoint(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.SetReparsePoint(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Buffer,
|
||||
Size);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 DeleteReparsePoint(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.DeleteReparsePoint(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Buffer,
|
||||
Size);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 GetStreamInfo(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.GetStreamInfo(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
Buffer,
|
||||
Length,
|
||||
out PBytesTransferred);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PBytesTransferred = default(UInt32);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
|
||||
static FileSystemHost()
|
||||
{
|
||||
_FileSystemInterface.GetVolumeInfo = GetVolumeInfo;
|
||||
_FileSystemInterface.SetVolumeLabel = SetVolumeLabel;
|
||||
_FileSystemInterface.GetSecurityByName = GetSecurityByName;
|
||||
_FileSystemInterface.Create = Create;
|
||||
_FileSystemInterface.Open = Open;
|
||||
_FileSystemInterface.Overwrite = Overwrite;
|
||||
_FileSystemInterface.Cleanup = Cleanup;
|
||||
_FileSystemInterface.Close = Close;
|
||||
_FileSystemInterface.Read = Read;
|
||||
_FileSystemInterface.Write = Write;
|
||||
_FileSystemInterface.Flush = Flush;
|
||||
_FileSystemInterface.GetFileInfo = GetFileInfo;
|
||||
_FileSystemInterface.SetBasicInfo = SetBasicInfo;
|
||||
_FileSystemInterface.SetFileSize = SetFileSize;
|
||||
_FileSystemInterface.CanDelete = CanDelete;
|
||||
_FileSystemInterface.Rename = Rename;
|
||||
_FileSystemInterface.GetSecurity = GetSecurity;
|
||||
_FileSystemInterface.SetSecurity = SetSecurity;
|
||||
_FileSystemInterface.ReadDirectory = ReadDirectory;
|
||||
_FileSystemInterface.ResolveReparsePoints = ResolveReparsePoints;
|
||||
_FileSystemInterface.GetReparsePoint = GetReparsePoint;
|
||||
_FileSystemInterface.SetReparsePoint = SetReparsePoint;
|
||||
_FileSystemInterface.DeleteReparsePoint = DeleteReparsePoint;
|
||||
_FileSystemInterface.GetStreamInfo = GetStreamInfo;
|
||||
|
||||
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
||||
Marshal.StructureToPtr(_FileSystemInterface, _FileSystemInterfacePtr, false);
|
||||
}
|
||||
|
||||
private static FileSystemInterface _FileSystemInterface;
|
||||
private static IntPtr _FileSystemInterfacePtr;
|
||||
private VolumeParams _VolumeParams;
|
||||
private IntPtr _FileSystemPtr;
|
||||
private FileSystemBase _FileSystem;
|
||||
}
|
||||
|
||||
}
|
907
src/dotnet/Interop.cs
Normal file
907
src/dotnet/Interop.cs
Normal file
@ -0,0 +1,907 @@
|
||||
/**
|
||||
* @file dotnet/Interop.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
namespace Fsp.Interop
|
||||
{
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct VolumeParams
|
||||
{
|
||||
internal const UInt32 CaseSensitiveSearch = 0x00000001;
|
||||
internal const UInt32 CasePreservedNames = 0x00000002;
|
||||
internal const UInt32 UnicodeOnDisk = 0x00000004;
|
||||
internal const UInt32 PersistentAcls = 0x00000008;
|
||||
internal const UInt32 ReparsePoints = 0x00000010;
|
||||
internal const UInt32 ReparsePointsAccessCheck = 0x00000020;
|
||||
internal const UInt32 NamedStreams = 0x00000040;
|
||||
internal const UInt32 HardLinks = 0x00000080;
|
||||
internal const UInt32 ExtendedAttributes = 0x00000100;
|
||||
internal const UInt32 ReadOnlyVolume = 0x00000200;
|
||||
internal const UInt32 PostCleanupWhenModifiedOnly = 0x00000400;
|
||||
internal const UInt32 PassQueryDirectoryPattern = 0x00000800;
|
||||
internal const UInt32 AlwaysUseDoubleBuffering = 0x00001000;
|
||||
internal const UInt32 UmFileContextIsUserContext2 = 0x00010000;
|
||||
internal const UInt32 UmFileContextIsFullContext = 0x00020000;
|
||||
internal const int PrefixSize = 192;
|
||||
internal const int FileSystemNameSize = 16;
|
||||
|
||||
internal UInt16 Version;
|
||||
internal UInt16 SectorSize;
|
||||
internal UInt16 SectorsPerAllocationUnit;
|
||||
internal UInt16 MaxComponentLength;
|
||||
internal UInt64 VolumeCreationTime;
|
||||
internal UInt32 VolumeSerialNumber;
|
||||
internal UInt32 TransactTimeout;
|
||||
internal UInt32 IrpTimeout;
|
||||
internal UInt32 IrpCapacity;
|
||||
internal UInt32 FileInfoTimeout;
|
||||
internal UInt32 Flags;
|
||||
internal unsafe fixed UInt16 Prefix[PrefixSize];
|
||||
internal unsafe fixed UInt16 FileSystemName[FileSystemNameSize];
|
||||
|
||||
internal unsafe String GetPrefix()
|
||||
{
|
||||
fixed (UInt16 *P = Prefix)
|
||||
return Marshal.PtrToStringUni((IntPtr)P);
|
||||
}
|
||||
internal unsafe void SetPrefix(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = Prefix)
|
||||
{
|
||||
int Size = null != Value ? Value.Length : 0;
|
||||
if (Size > PrefixSize - 1)
|
||||
Size = PrefixSize - 1;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
P[Size] = 0;
|
||||
}
|
||||
}
|
||||
internal unsafe String GetFileSystemName()
|
||||
{
|
||||
fixed (UInt16 *P = FileSystemName)
|
||||
return Marshal.PtrToStringUni((IntPtr)P);
|
||||
}
|
||||
internal unsafe void SetFileSystemName(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = FileSystemName)
|
||||
{
|
||||
int Size = null != Value ? Value.Length : 0;
|
||||
if (Size > FileSystemNameSize - 1)
|
||||
Size = FileSystemNameSize - 1;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
P[Size] = 0;
|
||||
}
|
||||
}
|
||||
internal unsafe Boolean IsPrefixEmpty()
|
||||
{
|
||||
fixed (UInt16 *P = Prefix)
|
||||
return 0 == *P;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct VolumeInfo
|
||||
{
|
||||
internal const int VolumeLabelSize = 32;
|
||||
|
||||
public UInt64 TotalSize;
|
||||
public UInt64 FreeSize;
|
||||
internal UInt16 VolumeLabelLength;
|
||||
internal unsafe fixed UInt16 VolumeLabel[VolumeLabelSize];
|
||||
|
||||
public unsafe void SetVolumeLabel(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = VolumeLabel)
|
||||
{
|
||||
int Size = null != Value ? Value.Length : 0;
|
||||
if (Size > VolumeLabelSize)
|
||||
Size = VolumeLabelSize;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
VolumeLabelLength = (UInt16)Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct FileInfo
|
||||
{
|
||||
public UInt32 FileAttributes;
|
||||
public UInt32 ReparseTag;
|
||||
public UInt64 AllocationSize;
|
||||
public UInt64 FileSize;
|
||||
public UInt64 CreationTime;
|
||||
public UInt64 LastAccessTime;
|
||||
public UInt64 LastWriteTime;
|
||||
public UInt64 ChangeTime;
|
||||
public UInt64 IndexNumber;
|
||||
public UInt32 HardLinks;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct OpenFileInfo
|
||||
{
|
||||
internal FileInfo FileInfo;
|
||||
internal IntPtr NormalizedName;
|
||||
internal UInt16 NormalizedNameSize;
|
||||
|
||||
internal unsafe void SetNormalizedName(String Value)
|
||||
{
|
||||
UInt16 *P = (UInt16 *)NormalizedName;
|
||||
int Size = Value.Length;
|
||||
if (Size > NormalizedNameSize)
|
||||
Size = NormalizedNameSize;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
NormalizedNameSize = (UInt16)Size;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct DirInfo
|
||||
{
|
||||
internal const int FileNameBufSize = 255;
|
||||
internal static int FileNameBufOffset = (int)Marshal.OffsetOf(typeof(DirInfo), "FileNameBuf");
|
||||
|
||||
internal UInt16 Size;
|
||||
internal FileInfo FileInfo;
|
||||
internal unsafe fixed Byte Padding[24];
|
||||
//internal unsafe fixed UInt16 FileNameBuf[];
|
||||
internal unsafe fixed UInt16 FileNameBuf[FileNameBufSize];
|
||||
|
||||
public unsafe void SetFileNameBuf(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = FileNameBuf)
|
||||
{
|
||||
int Size = null != Value ? Value.Length : 0;
|
||||
if (Size > FileNameBufSize)
|
||||
Size = FileNameBufSize;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
this.Size = (UInt16)(FileNameBufOffset + Size * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct StreamInfo
|
||||
{
|
||||
internal UInt16 Size;
|
||||
internal UInt64 StreamSize;
|
||||
internal UInt64 StreamAllocationSize;
|
||||
//internal unsafe fixed UInt16 StreamNameBuf[];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct FullContext
|
||||
{
|
||||
internal UInt64 UserContext;
|
||||
internal UInt64 UserContext2;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IoStatusBlock
|
||||
{
|
||||
public IntPtr Status;
|
||||
public IntPtr Information;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct FileSystemInterface
|
||||
{
|
||||
internal struct Proto
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetVolumeInfo(
|
||||
IntPtr FileSystem,
|
||||
out VolumeInfo VolumeInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 SetVolumeLabel(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String VolumeLabel,
|
||||
out VolumeInfo VolumeInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetSecurityByName(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
IntPtr PFileAttributes/* or ReparsePointIndex */,
|
||||
IntPtr SecurityDescriptor,
|
||||
IntPtr PSecurityDescriptorSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Create(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
UInt32 FileAttributes,
|
||||
IntPtr SecurityDescriptor,
|
||||
UInt64 AllocationSize,
|
||||
ref FullContext FullContext,
|
||||
ref OpenFileInfo OpenFileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Open(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
ref FullContext FullContext,
|
||||
ref OpenFileInfo OpenFileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Overwrite(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
UInt32 FileAttributes,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ReplaceFileAttributes,
|
||||
UInt64 AllocationSize,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void Cleanup(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
UInt32 Flags);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void Close(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Read(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Write(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean WriteToEndOfFile,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ConstrainedIo,
|
||||
out UInt32 PBytesTransferred,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Flush(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetFileInfo(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 SetBasicInfo(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
UInt32 FileAttributes,
|
||||
UInt64 CreationTime,
|
||||
UInt64 LastAccessTime,
|
||||
UInt64 LastWriteTime,
|
||||
UInt64 ChangeTime,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 SetFileSize(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
UInt64 NewSize,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean SetAllocationSize,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 CanDelete(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Rename(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String NewFileName,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ReplaceIfExists);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetSecurity(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
IntPtr SecurityDescriptor,
|
||||
IntPtr PSecurityDescriptorSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 SetSecurity(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
UInt32 SecurityInformation,
|
||||
IntPtr ModificationDescriptor);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 ReadDirectory(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String Pattern,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String Marker,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 ResolveReparsePoints(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
UInt32 ReparsePointIndex,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock PIoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
IntPtr Buffer,
|
||||
out UIntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 SetReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 DeleteReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetStreamInfo(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
}
|
||||
|
||||
internal static int Size = IntPtr.Size * 64;
|
||||
|
||||
internal Proto.GetVolumeInfo GetVolumeInfo;
|
||||
internal Proto.SetVolumeLabel SetVolumeLabel;
|
||||
internal Proto.GetSecurityByName GetSecurityByName;
|
||||
internal Proto.Create Create;
|
||||
internal Proto.Open Open;
|
||||
internal Proto.Overwrite Overwrite;
|
||||
internal Proto.Cleanup Cleanup;
|
||||
internal Proto.Close Close;
|
||||
internal Proto.Read Read;
|
||||
internal Proto.Write Write;
|
||||
internal Proto.Flush Flush;
|
||||
internal Proto.GetFileInfo GetFileInfo;
|
||||
internal Proto.SetBasicInfo SetBasicInfo;
|
||||
internal Proto.SetFileSize SetFileSize;
|
||||
internal Proto.CanDelete CanDelete;
|
||||
internal Proto.Rename Rename;
|
||||
internal Proto.GetSecurity GetSecurity;
|
||||
internal Proto.SetSecurity SetSecurity;
|
||||
internal Proto.ReadDirectory ReadDirectory;
|
||||
internal Proto.ResolveReparsePoints ResolveReparsePoints;
|
||||
internal Proto.GetReparsePoint GetReparsePoint;
|
||||
internal Proto.SetReparsePoint SetReparsePoint;
|
||||
internal Proto.DeleteReparsePoint DeleteReparsePoint;
|
||||
internal Proto.GetStreamInfo GetStreamInfo;
|
||||
/* NTSTATUS (*Reserved[40])(); */
|
||||
}
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
internal static class Api
|
||||
{
|
||||
internal struct Proto
|
||||
{
|
||||
/* FileSystem */
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemPreflight(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String DevicePath,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String MountPoint);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemCreate(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String DevicePath,
|
||||
ref VolumeParams VolumeParams,
|
||||
IntPtr Interface,
|
||||
out IntPtr PFileSystem);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemDelete(
|
||||
IntPtr FileSystem);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemSetMountPoint(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String MountPoint);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemSetMountPointEx(
|
||||
IntPtr FileSystem,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String MountPoint,
|
||||
IntPtr SecurityDescriptor);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemRemoveMountPoint(
|
||||
IntPtr FileSystem);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemStartDispatcher(
|
||||
IntPtr FileSystem,
|
||||
UInt32 ThreadCount);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemStopDispatcher(
|
||||
IntPtr FileSystem);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate IntPtr FspFileSystemMountPointF(
|
||||
IntPtr FileSystem);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemSetOperationGuardStrategyF(
|
||||
IntPtr FileSystem,
|
||||
Int32 GuardStrategy);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemSetDebugLogF(
|
||||
IntPtr FileSystem,
|
||||
UInt32 DebugLog);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal delegate Boolean FspFileSystemAddDirInfo(
|
||||
IntPtr DirInfo,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemFindReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
GetReparsePointByName GetReparsePointByName,
|
||||
IntPtr Context,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
out UInt32 PReparsePointIndex);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemResolveReparsePoints(
|
||||
IntPtr FileSystem,
|
||||
GetReparsePointByName GetReparsePointByName,
|
||||
IntPtr Context,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
UInt32 ReparsePointIndex,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock PIoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemCanReplaceReparsePoint(
|
||||
IntPtr CurrentReparseData,
|
||||
UIntPtr CurrentReparseDataSize,
|
||||
IntPtr ReplaceReparseData,
|
||||
UIntPtr ReplaceReparseDataSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal delegate Boolean FspFileSystemAddStreamInfo(
|
||||
IntPtr StreamInfo,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal delegate Boolean FspFileSystemAcquireDirectoryBuffer(
|
||||
ref IntPtr PDirBuffer,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean Reset,
|
||||
out Int32 PResult);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal delegate Boolean FspFileSystemFillDirectoryBuffer(
|
||||
ref IntPtr PDirBuffer,
|
||||
ref DirInfo DirInfo,
|
||||
out Int32 PResult);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemReleaseDirectoryBuffer(
|
||||
ref IntPtr PDirBuffer);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemReadDirectoryBuffer(
|
||||
ref IntPtr PDirBuffer,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String Marker,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemDeleteDirectoryBuffer(
|
||||
ref IntPtr PDirBuffer);
|
||||
|
||||
/* Service */
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspServiceCreate(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String ServiceName,
|
||||
ServiceStart OnStart,
|
||||
ServiceStop OnStop,
|
||||
ServiceControl OnControl,
|
||||
out IntPtr PService);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspServiceDelete(
|
||||
IntPtr Service);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspServiceAllowConsoleMode(
|
||||
IntPtr Service);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspServiceRequestTime(
|
||||
IntPtr Service,
|
||||
UInt32 Time);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspServiceSetExitCode(
|
||||
IntPtr Service,
|
||||
UInt32 ExitCode);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate UInt32 FspServiceGetExitCode(
|
||||
IntPtr Service);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspServiceLoop(
|
||||
IntPtr Service);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspServiceStop(
|
||||
IntPtr Service);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspServiceLog(
|
||||
UInt32 Type,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String Format,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String Message);
|
||||
|
||||
/* utility */
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspVersion(
|
||||
out UInt32 PVersion);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspNtStatusFromWin32(
|
||||
UInt32 Error);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate UInt32 FspWin32FromNtStatus(
|
||||
Int32 Status);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspDebugLogSetHandle(
|
||||
IntPtr Handle);
|
||||
|
||||
/* callbacks */
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetReparsePointByName(
|
||||
IntPtr FileSystem,
|
||||
IntPtr Context,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean IsDirectory,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 ServiceStart(
|
||||
IntPtr Service,
|
||||
UInt32 Argc,
|
||||
[MarshalAs(UnmanagedType.LPArray,
|
||||
ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)]
|
||||
String[] Argv);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 ServiceStop(
|
||||
IntPtr Service);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 ServiceControl(
|
||||
IntPtr Service,
|
||||
UInt32 Control,
|
||||
UInt32 EventType,
|
||||
IntPtr EventData);
|
||||
}
|
||||
|
||||
internal static Proto.FspFileSystemPreflight FspFileSystemPreflight;
|
||||
internal static Proto.FspFileSystemCreate FspFileSystemCreate;
|
||||
internal static Proto.FspFileSystemDelete FspFileSystemDelete;
|
||||
internal static Proto.FspFileSystemSetMountPoint FspFileSystemSetMountPoint;
|
||||
internal static Proto.FspFileSystemSetMountPointEx _FspFileSystemSetMountPointEx;
|
||||
internal static Proto.FspFileSystemRemoveMountPoint FspFileSystemRemoveMountPoint;
|
||||
internal static Proto.FspFileSystemStartDispatcher FspFileSystemStartDispatcher;
|
||||
internal static Proto.FspFileSystemStopDispatcher FspFileSystemStopDispatcher;
|
||||
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
||||
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
||||
internal static Proto.FspFileSystemSetDebugLogF FspFileSystemSetDebugLog;
|
||||
internal static Proto.FspFileSystemAddDirInfo _FspFileSystemAddDirInfo;
|
||||
internal static Proto.FspFileSystemFindReparsePoint FspFileSystemFindReparsePoint;
|
||||
internal static Proto.FspFileSystemResolveReparsePoints FspFileSystemResolveReparsePoints;
|
||||
internal static Proto.FspFileSystemCanReplaceReparsePoint FspFileSystemCanReplaceReparsePoint;
|
||||
internal static Proto.FspFileSystemAddStreamInfo FspFileSystemAddStreamInfo;
|
||||
internal static Proto.FspFileSystemAcquireDirectoryBuffer FspFileSystemAcquireDirectoryBuffer;
|
||||
internal static Proto.FspFileSystemFillDirectoryBuffer FspFileSystemFillDirectoryBuffer;
|
||||
internal static Proto.FspFileSystemReleaseDirectoryBuffer FspFileSystemReleaseDirectoryBuffer;
|
||||
internal static Proto.FspFileSystemReadDirectoryBuffer FspFileSystemReadDirectoryBuffer;
|
||||
internal static Proto.FspFileSystemDeleteDirectoryBuffer FspFileSystemDeleteDirectoryBuffer;
|
||||
internal static Proto.FspServiceCreate FspServiceCreate;
|
||||
internal static Proto.FspServiceDelete FspServiceDelete;
|
||||
internal static Proto.FspServiceAllowConsoleMode FspServiceAllowConsoleMode;
|
||||
internal static Proto.FspServiceRequestTime FspServiceRequestTime;
|
||||
internal static Proto.FspServiceSetExitCode FspServiceSetExitCode;
|
||||
internal static Proto.FspServiceGetExitCode FspServiceGetExitCode;
|
||||
internal static Proto.FspServiceLoop FspServiceLoop;
|
||||
internal static Proto.FspServiceStop FspServiceStop;
|
||||
internal static Proto.FspServiceLog FspServiceLog;
|
||||
internal static Proto.FspVersion FspVersion;
|
||||
internal static Proto.FspNtStatusFromWin32 FspNtStatusFromWin32;
|
||||
internal static Proto.FspWin32FromNtStatus FspWin32FromNtStatus;
|
||||
internal static Proto.FspDebugLogSetHandle FspDebugLogSetHandle;
|
||||
|
||||
internal static unsafe Int32 FspFileSystemSetMountPointEx(
|
||||
IntPtr FileSystem,
|
||||
String MountPoint,
|
||||
Byte[] SecurityDescriptor)
|
||||
{
|
||||
if (null != SecurityDescriptor)
|
||||
{
|
||||
fixed (Byte *P = SecurityDescriptor)
|
||||
return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, (IntPtr)P);
|
||||
}
|
||||
else
|
||||
return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, IntPtr.Zero);
|
||||
}
|
||||
internal static unsafe Boolean FspFileSystemAddDirInfo(
|
||||
ref DirInfo DirInfo,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
fixed (DirInfo *P = &DirInfo)
|
||||
return _FspFileSystemAddDirInfo((IntPtr)P, Buffer, Length, out PBytesTransferred);
|
||||
}
|
||||
|
||||
internal unsafe static Object GetUserContext(
|
||||
IntPtr NativePtr)
|
||||
{
|
||||
IntPtr UserContext = *(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr));
|
||||
return IntPtr.Zero != UserContext ? GCHandle.FromIntPtr(UserContext).Target : null;
|
||||
}
|
||||
internal unsafe static void SetUserContext(
|
||||
IntPtr NativePtr,
|
||||
Object Obj)
|
||||
{
|
||||
if (null != Obj)
|
||||
{
|
||||
Debug.Assert(IntPtr.Zero == *(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr)));
|
||||
GCHandle Handle = GCHandle.Alloc(Obj, GCHandleType.Weak);
|
||||
*(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr)) = (IntPtr)Handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
IntPtr UserContext = *(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr));
|
||||
if (IntPtr.Zero != UserContext)
|
||||
{
|
||||
GCHandle.FromIntPtr(UserContext).Free();
|
||||
*(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr)) = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void GetFullContext(ref FullContext FullContext,
|
||||
out Object FileNode, out Object FileDesc)
|
||||
{
|
||||
FileNode = 0 != FullContext.UserContext ?
|
||||
GCHandle.FromIntPtr((IntPtr)FullContext.UserContext).Target : null;
|
||||
FileDesc = 0 != FullContext.UserContext2 ?
|
||||
GCHandle.FromIntPtr((IntPtr)FullContext.UserContext2).Target : null;
|
||||
}
|
||||
internal static void SetFullContext(ref FullContext FullContext,
|
||||
Object FileNode, Object FileDesc)
|
||||
{
|
||||
if (null != FileNode)
|
||||
{
|
||||
Debug.Assert(0 == FullContext.UserContext);
|
||||
GCHandle Handle = GCHandle.Alloc(FileNode, GCHandleType.Normal);
|
||||
FullContext.UserContext = (UInt64)(IntPtr)Handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != FullContext.UserContext)
|
||||
{
|
||||
GCHandle.FromIntPtr((IntPtr)FullContext.UserContext).Free();
|
||||
FullContext.UserContext = 0;
|
||||
}
|
||||
}
|
||||
if (null != FileDesc)
|
||||
{
|
||||
Debug.Assert(0 == FullContext.UserContext2);
|
||||
GCHandle Handle = GCHandle.Alloc(FileDesc, GCHandleType.Normal);
|
||||
FullContext.UserContext2 = (UInt64)(IntPtr)Handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != FullContext.UserContext2)
|
||||
{
|
||||
GCHandle.FromIntPtr((IntPtr)FullContext.UserContext2).Free();
|
||||
FullContext.UserContext2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe static Int32 CopySecurityDescriptor(
|
||||
Byte[] SecurityDescriptorBytes,
|
||||
IntPtr SecurityDescriptor,
|
||||
IntPtr PSecurityDescriptorSize)
|
||||
{
|
||||
if (IntPtr.Zero != PSecurityDescriptorSize)
|
||||
{
|
||||
if (null != SecurityDescriptorBytes)
|
||||
{
|
||||
if (SecurityDescriptorBytes.Length > (int)*(IntPtr *)PSecurityDescriptorSize)
|
||||
{
|
||||
*(IntPtr *)PSecurityDescriptorSize = (IntPtr)SecurityDescriptorBytes.Length;
|
||||
return unchecked((Int32)0x80000005)/*STATUS_BUFFER_OVERFLOW*/;
|
||||
}
|
||||
*(IntPtr *)PSecurityDescriptorSize = (IntPtr)SecurityDescriptorBytes.Length;
|
||||
if (IntPtr.Zero != SecurityDescriptor)
|
||||
Marshal.Copy(SecurityDescriptorBytes, 0,
|
||||
SecurityDescriptor, SecurityDescriptorBytes.Length);
|
||||
}
|
||||
else
|
||||
*(IntPtr *)PSecurityDescriptorSize = IntPtr.Zero;
|
||||
}
|
||||
return 0/*STATUS_SUCCESS*/;
|
||||
}
|
||||
internal static Byte[] MakeSecurityDescriptor(
|
||||
IntPtr SecurityDescriptor)
|
||||
{
|
||||
if (IntPtr.Zero != SecurityDescriptor)
|
||||
{
|
||||
Byte[] SecurityDescriptorBytes = new Byte[GetSecurityDescriptorLength(SecurityDescriptor)];
|
||||
Marshal.Copy(SecurityDescriptor,
|
||||
SecurityDescriptorBytes, 0, SecurityDescriptorBytes.Length);
|
||||
return SecurityDescriptorBytes;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static Int32 SetDebugLogFile(String FileName)
|
||||
{
|
||||
IntPtr Handle;
|
||||
if ("-" == FileName)
|
||||
Handle = GetStdHandle(unchecked((UInt32)(-12))/*STD_ERROR_HANDLE*/);
|
||||
else
|
||||
Handle = CreateFileW(
|
||||
FileName,
|
||||
(UInt32)FileSystemRights.AppendData,
|
||||
(UInt32)(FileShare.Read | FileShare.Write),
|
||||
IntPtr.Zero,
|
||||
(UInt32)FileMode.OpenOrCreate,
|
||||
(UInt32)FileAttributes.Normal,
|
||||
IntPtr.Zero);
|
||||
if ((IntPtr)(-1) == Handle)
|
||||
return FspNtStatusFromWin32((UInt32)Marshal.GetLastWin32Error());
|
||||
Api.FspDebugLogSetHandle(Handle);
|
||||
return 0/*STATUS_SUCCESS*/;
|
||||
}
|
||||
|
||||
/* initialization */
|
||||
private static IntPtr LoadDll()
|
||||
{
|
||||
String DllPath = null;
|
||||
String DllName = 8 == IntPtr.Size ? "winfsp-x64.dll" : "winfsp-x86.dll";
|
||||
String KeyName = 8 == IntPtr.Size ?
|
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\WinFsp" :
|
||||
"HKEY_LOCAL_MACHINE\\Software\\WinFsp";
|
||||
IntPtr Module;
|
||||
Module = LoadLibraryW(DllName);
|
||||
if (IntPtr.Zero == Module)
|
||||
{
|
||||
DllPath = Microsoft.Win32.Registry.GetValue(KeyName, "InstallDir", null) as String;
|
||||
if (null != DllPath)
|
||||
{
|
||||
DllPath = Path.Combine(DllPath, Path.Combine("bin", DllName));
|
||||
Module = LoadLibraryW(DllPath);
|
||||
}
|
||||
if (IntPtr.Zero == Module)
|
||||
throw new DllNotFoundException("cannot load " + DllName);
|
||||
}
|
||||
return Module;
|
||||
}
|
||||
private static T GetEntryPoint<T>(IntPtr Module)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)(object)Marshal.GetDelegateForFunctionPointer(
|
||||
GetProcAddress(Module, typeof(T).Name), typeof(T));
|
||||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
throw new EntryPointNotFoundException("cannot get entry point " + typeof(T).Name);
|
||||
}
|
||||
}
|
||||
private static void LoadProto(IntPtr Module)
|
||||
{
|
||||
FspFileSystemPreflight = GetEntryPoint<Proto.FspFileSystemPreflight>(Module);
|
||||
FspFileSystemCreate = GetEntryPoint<Proto.FspFileSystemCreate>(Module);
|
||||
FspFileSystemDelete = GetEntryPoint<Proto.FspFileSystemDelete>(Module);
|
||||
FspFileSystemSetMountPoint = GetEntryPoint<Proto.FspFileSystemSetMountPoint>(Module);
|
||||
_FspFileSystemSetMountPointEx = GetEntryPoint<Proto.FspFileSystemSetMountPointEx>(Module);
|
||||
FspFileSystemRemoveMountPoint = GetEntryPoint<Proto.FspFileSystemRemoveMountPoint>(Module);
|
||||
FspFileSystemStartDispatcher = GetEntryPoint<Proto.FspFileSystemStartDispatcher>(Module);
|
||||
FspFileSystemStopDispatcher = GetEntryPoint<Proto.FspFileSystemStopDispatcher>(Module);
|
||||
FspFileSystemMountPoint = GetEntryPoint<Proto.FspFileSystemMountPointF>(Module);
|
||||
FspFileSystemSetOperationGuardStrategy = GetEntryPoint<Proto.FspFileSystemSetOperationGuardStrategyF>(Module);
|
||||
FspFileSystemSetDebugLog = GetEntryPoint<Proto.FspFileSystemSetDebugLogF>(Module);
|
||||
_FspFileSystemAddDirInfo = GetEntryPoint<Proto.FspFileSystemAddDirInfo>(Module);
|
||||
FspFileSystemFindReparsePoint = GetEntryPoint<Proto.FspFileSystemFindReparsePoint>(Module);
|
||||
FspFileSystemResolveReparsePoints = GetEntryPoint<Proto.FspFileSystemResolveReparsePoints>(Module);
|
||||
FspFileSystemCanReplaceReparsePoint = GetEntryPoint<Proto.FspFileSystemCanReplaceReparsePoint>(Module);
|
||||
FspFileSystemAddStreamInfo = GetEntryPoint<Proto.FspFileSystemAddStreamInfo>(Module);
|
||||
FspFileSystemAcquireDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemAcquireDirectoryBuffer>(Module);
|
||||
FspFileSystemFillDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemFillDirectoryBuffer>(Module);
|
||||
FspFileSystemReleaseDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemReleaseDirectoryBuffer>(Module);
|
||||
FspFileSystemReadDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemReadDirectoryBuffer>(Module);
|
||||
FspFileSystemDeleteDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemDeleteDirectoryBuffer>(Module);
|
||||
FspServiceCreate = GetEntryPoint<Proto.FspServiceCreate>(Module);
|
||||
FspServiceDelete = GetEntryPoint<Proto.FspServiceDelete>(Module);
|
||||
FspServiceAllowConsoleMode = GetEntryPoint<Proto.FspServiceAllowConsoleMode>(Module);
|
||||
FspServiceRequestTime = GetEntryPoint<Proto.FspServiceRequestTime>(Module);
|
||||
FspServiceSetExitCode = GetEntryPoint<Proto.FspServiceSetExitCode>(Module);
|
||||
FspServiceGetExitCode = GetEntryPoint<Proto.FspServiceGetExitCode>(Module);
|
||||
FspServiceLoop = GetEntryPoint<Proto.FspServiceLoop>(Module);
|
||||
FspServiceStop = GetEntryPoint<Proto.FspServiceStop>(Module);
|
||||
FspServiceLog = GetEntryPoint<Proto.FspServiceLog>(Module);
|
||||
FspVersion = GetEntryPoint<Proto.FspVersion>(Module);
|
||||
FspNtStatusFromWin32 = GetEntryPoint<Proto.FspNtStatusFromWin32>(Module);
|
||||
FspWin32FromNtStatus = GetEntryPoint<Proto.FspWin32FromNtStatus>(Module);
|
||||
FspDebugLogSetHandle = GetEntryPoint<Proto.FspDebugLogSetHandle>(Module);
|
||||
}
|
||||
private static void CheckVersion()
|
||||
{
|
||||
FileVersionInfo Info;
|
||||
UInt32 Version = 0, VersionMajor, VersionMinor;
|
||||
Info = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||
FspVersion(out Version); VersionMajor = Version >> 16; VersionMinor = Version & 0xFFFF;
|
||||
if (Info.FileMajorPart != VersionMajor || Info.FileMinorPart > VersionMinor)
|
||||
throw new TypeLoadException(String.Format(
|
||||
"incorrect dll version (need {0}.{1}, have {2}.{3})",
|
||||
Info.FileMajorPart, Info.FileMinorPart, VersionMajor, VersionMinor));
|
||||
}
|
||||
static Api()
|
||||
{
|
||||
#if false //DEBUG
|
||||
if (Debugger.IsAttached)
|
||||
Debugger.Break();
|
||||
#endif
|
||||
LoadProto(LoadDll());
|
||||
CheckVersion();
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
private static extern IntPtr LoadLibraryW(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String DllName);
|
||||
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
private static extern IntPtr GetProcAddress(
|
||||
IntPtr hModule,
|
||||
[MarshalAs(UnmanagedType.LPStr)] String lpProcName);
|
||||
[DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern UInt32 GetSecurityDescriptorLength(IntPtr SecurityDescriptor);
|
||||
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
private static extern IntPtr GetStdHandle(UInt32 nStdHandle);
|
||||
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
private static extern IntPtr CreateFileW(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String lpFileName,
|
||||
UInt32 dwDesiredAccess,
|
||||
UInt32 dwShareMode,
|
||||
IntPtr lpSecurityAttributes,
|
||||
UInt32 dwCreationDisposition,
|
||||
UInt32 dwFlagsAndAttributes,
|
||||
IntPtr hTemplateFile);
|
||||
}
|
||||
|
||||
}
|
158
src/dotnet/Service.cs
Normal file
158
src/dotnet/Service.cs
Normal file
@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @file dotnet/Service.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Fsp.Interop;
|
||||
|
||||
namespace Fsp
|
||||
{
|
||||
|
||||
public class Service
|
||||
{
|
||||
/* const */
|
||||
public const UInt32 EVENTLOG_ERROR_TYPE = 0x0001;
|
||||
public const UInt32 EVENTLOG_WARNING_TYPE = 0x0002;
|
||||
public const UInt32 EVENTLOG_INFORMATION_TYPE = 0x0004;
|
||||
|
||||
/* ctor/dtor */
|
||||
public Service(String ServiceName)
|
||||
{
|
||||
Api.FspServiceCreate(ServiceName, _OnStart, _OnStop, null, out _Service);
|
||||
if (IntPtr.Zero != _Service)
|
||||
Api.SetUserContext(_Service, this);
|
||||
}
|
||||
~Service()
|
||||
{
|
||||
if (IntPtr.Zero != _Service)
|
||||
{
|
||||
Api.SetUserContext(_Service, null);
|
||||
Api.FspServiceDelete(_Service);
|
||||
}
|
||||
}
|
||||
|
||||
/* control */
|
||||
public int Run()
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
{
|
||||
const Int32 STATUS_INSUFFICIENT_RESOURCES = unchecked((Int32)0xc000009a);
|
||||
Log(EVENTLOG_ERROR_TYPE,
|
||||
String.Format("The service {0} cannot be created (Status={1:X}).",
|
||||
GetType().FullName, STATUS_INSUFFICIENT_RESOURCES));
|
||||
return (int)Api.FspWin32FromNtStatus(STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
Api.FspServiceAllowConsoleMode(_Service);
|
||||
Int32 Result = Api.FspServiceLoop(_Service);
|
||||
int ExitCode = (int)Api.FspServiceGetExitCode(_Service);
|
||||
if (0 > Result)
|
||||
{
|
||||
Log(EVENTLOG_ERROR_TYPE,
|
||||
String.Format("The service {0} has failed to run (Status={1:X}).",
|
||||
GetType().FullName, Result));
|
||||
return (int)Api.FspWin32FromNtStatus(Result);
|
||||
}
|
||||
return ExitCode;
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
throw new InvalidOperationException();
|
||||
Api.FspServiceStop(_Service);
|
||||
}
|
||||
public void RequestTime(UInt32 Time)
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
throw new InvalidOperationException();
|
||||
Api.FspServiceRequestTime(_Service, Time);
|
||||
}
|
||||
public int ExitCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
throw new InvalidOperationException();
|
||||
return (int)Api.FspServiceGetExitCode(_Service);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
throw new InvalidOperationException();
|
||||
Api.FspServiceSetExitCode(_Service, (UInt32)value);
|
||||
}
|
||||
}
|
||||
public IntPtr ServiceHandle
|
||||
{
|
||||
get { return _Service; }
|
||||
}
|
||||
public static void Log(UInt32 Type, String Message)
|
||||
{
|
||||
Api.FspServiceLog(Type, "%s", Message);
|
||||
}
|
||||
|
||||
/* start/stop */
|
||||
protected virtual Int32 ExceptionHandler(Exception ex)
|
||||
{
|
||||
return unchecked((Int32)0xE0434f4D)/*STATUS_CLR_EXCEPTION*/;
|
||||
}
|
||||
protected virtual void OnStart(String[] Args)
|
||||
{
|
||||
}
|
||||
protected virtual void OnStop()
|
||||
{
|
||||
}
|
||||
|
||||
/* callbacks */
|
||||
private static Int32 OnStart(
|
||||
IntPtr Service,
|
||||
UInt32 Argc,
|
||||
String[] Argv)
|
||||
{
|
||||
Service self = (Service)Api.GetUserContext(Service);
|
||||
try
|
||||
{
|
||||
self.OnStart(
|
||||
Argv);
|
||||
return 0/*STATUS_SUCCESS*/;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return self.ExceptionHandler(ex);
|
||||
}
|
||||
}
|
||||
private static Int32 OnStop(
|
||||
IntPtr Service)
|
||||
{
|
||||
Service self = (Service)Api.GetUserContext(Service);
|
||||
try
|
||||
{
|
||||
self.OnStop();
|
||||
return 0/*STATUS_SUCCESS*/;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return self.ExceptionHandler(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Api.Proto.ServiceStart _OnStart = OnStart;
|
||||
private static Api.Proto.ServiceStop _OnStop = OnStop;
|
||||
private IntPtr _Service;
|
||||
}
|
||||
|
||||
}
|
@ -12,20 +12,26 @@ if X!ProjDir!==X (echo usage: build-sample Config Arch Sample ProjDir >&2 & goto
|
||||
|
||||
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x64
|
||||
|
||||
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||
set RegVal="InstallDir"
|
||||
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||
if !ERRORLEVEL! equ 0 (
|
||||
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||
set InstallDir=%%j
|
||||
)
|
||||
if X!FSP_SAMPLE_DIR!==X (
|
||||
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||
set RegVal="InstallDir"
|
||||
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||
if !ERRORLEVEL! equ 0 (
|
||||
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||
set InstallDir=%%j
|
||||
)
|
||||
)
|
||||
if not exist "!InstallDir!" (echo cannot find WinFsp installation >&2 & goto fail)
|
||||
if not exist "!InstallDir!samples\!Sample!" (echo cannot find WinFsp sample !Sample! >&2 & goto fail)
|
||||
|
||||
set SampleDir=!InstallDir!samples
|
||||
) else (
|
||||
set SampleDir=!FSP_SAMPLE_DIR!
|
||||
)
|
||||
if not exist "!InstallDir!" (echo cannot find WinFsp installation >&2 & goto fail)
|
||||
if not exist "!InstallDir!samples\!Sample!" (echo cannot find WinFsp sample !Sample! >&2 & goto fail)
|
||||
|
||||
if exist "!ProjDir!" rmdir /s/q "!ProjDir!"
|
||||
mkdir "!ProjDir!"
|
||||
xcopy /s/e/q/y "!InstallDir!samples\!Sample!" "!ProjDir!"
|
||||
xcopy /s/e/q/y "!SampleDir!\!Sample!" "!ProjDir!"
|
||||
|
||||
devenv "!ProjDir!\!Sample!.sln" /build "!Config!|!Arch!"
|
||||
if !ERRORLEVEL! neq 0 goto :fail
|
||||
|
@ -1,6 +1,7 @@
|
||||
@echo off
|
||||
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
set MsiName="WinFsp - Windows File System Proxy"
|
||||
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
||||
@ -19,6 +20,7 @@ if not X%SignedPackage%==X (
|
||||
if not exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp-*.msi" (echo previous build not found >&2 & exit /b 1)
|
||||
if not exist "%SignedPackage%" (echo signed package not found >&2 & exit /b 1)
|
||||
del "%~dp0..\build\VStudio\build\%Configuration%\winfsp-*.msi"
|
||||
if exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg" del "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg"
|
||||
for /R "%SignedPackage%" %%f in (*.sys) do (
|
||||
copy "%%f" "%~dp0..\build\VStudio\build\%Configuration%" >nul
|
||||
)
|
||||
@ -81,6 +83,18 @@ for %%f in (build\%Configuration%\winfsp-*.msi) do (
|
||||
|
||||
if not %signfail%==0 echo SIGNING FAILED! The product has been successfully built, but not signed.
|
||||
|
||||
where /q choco.exe
|
||||
if %ERRORLEVEL% equ 0 (
|
||||
for %%f in (build\%Configuration%\winfsp-*.msi) do set Version=%%~nf
|
||||
set Version=!Version:winfsp-=!
|
||||
|
||||
copy ..\choco\* build\%Configuration%
|
||||
copy ..\choco\LICENSE.TXT /B + ..\..\License.txt /B build\%Configuration%\LICENSE.txt /B
|
||||
certutil -hashfile build\%Configuration%\winfsp-!Version!.msi SHA256 >>build\%Configuration%\VERIFICATION.txt
|
||||
choco pack build\%Configuration%\winfsp.nuspec --version=!Version! --outputdirectory=build\%Configuration%
|
||||
if errorlevel 1 goto fail
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
|
||||
:fail
|
||||
|
@ -60,8 +60,11 @@ set opt_tests=^
|
||||
ifstest-memfs-x86-disk ^
|
||||
sample-passthrough-x64 ^
|
||||
sample-passthrough-x86 ^
|
||||
sample-passthrough-cpp-x64 ^
|
||||
sample-passthrough-cpp-x86 ^
|
||||
sample-passthrough-fuse-x64 ^
|
||||
sample-passthrough-fuse-x86
|
||||
sample-passthrough-fuse-x86 ^
|
||||
sample-passthrough-dotnet
|
||||
|
||||
set tests=
|
||||
for %%f in (%dfl_tests%) do (
|
||||
@ -361,20 +364,20 @@ exit /b 0
|
||||
:__ifstest-memfs
|
||||
%1
|
||||
set IfsTestDirectories=^
|
||||
securit^
|
||||
opcreatg^
|
||||
opcreatp^
|
||||
closedel^
|
||||
volinfo^
|
||||
fileinfo^
|
||||
dirinfo^
|
||||
filelock^
|
||||
oplocks^
|
||||
chgnotif^
|
||||
readwr^
|
||||
seccache^
|
||||
reparspt^
|
||||
estream
|
||||
securit^
|
||||
opcreatg^
|
||||
opcreatp^
|
||||
closedel^
|
||||
volinfo^
|
||||
fileinfo^
|
||||
dirinfo^
|
||||
filelock^
|
||||
oplocks^
|
||||
chgnotif^
|
||||
readwr^
|
||||
seccache^
|
||||
reparspt^
|
||||
estream
|
||||
set IfsTestMemfsExit=0
|
||||
call :__ifstest %1 /g Security
|
||||
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
|
||||
@ -418,7 +421,7 @@ rem StreamEnhancements.StreamNotifyNameTest: WinFsp does not notify when streams
|
||||
call :__ifstest %1 /g StreamEnhancements -t StreamRenameTest -t StreamNotifyNameTest
|
||||
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
|
||||
for %%d in (!IfsTestDirectories!) do (
|
||||
if exist %%d (echo :ifstest directory %%d still exists & set IfsTestMemfsExit=1)
|
||||
if exist %%d (echo :ifstest directory %%d still exists & set IfsTestMemfsExit=1)
|
||||
)
|
||||
exit /b !IfsTestMemfsExit!
|
||||
|
||||
@ -482,82 +485,94 @@ if not X!IfsTestFound!==XYES set IfsTestExit=1
|
||||
exit /b !IfsTestExit!
|
||||
|
||||
:sample-passthrough-x64
|
||||
call :__sample-passthrough x64
|
||||
call :__run_sample_test passthrough x64 passthrough-x64 winfsp-tests-x64
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-x86
|
||||
call :__sample-passthrough x86
|
||||
call :__run_sample_test passthrough x86 passthrough-x86 winfsp-tests-x86
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:__sample-passthrough
|
||||
set SamplePassthroughExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %1 passthrough "%TMP%\passthrough-%1"
|
||||
:sample-passthrough-cpp-x64
|
||||
call :__run_sample_test passthrough-cpp x64 passthrough-cpp-x64 winfsp-tests-x64
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
mkdir "%TMP%\passthrough-%1\test"
|
||||
call "%ProjRoot%\tools\fsreg" passthrough "%TMP%\passthrough-%1\build\%Configuration%\passthrough-%1.exe" "-u %%%%1 -m %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||
echo net use L: "\\passthrough\%TMP::=$%\passthrough-%1\test"
|
||||
net use L: "\\passthrough\%TMP::=$%\passthrough-%1\test"
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-cpp-x86
|
||||
call :__run_sample_test passthrough-cpp x86 passthrough-cpp-x86 winfsp-tests-x86
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
echo net use ^| findstr L:
|
||||
net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
exit /b 0
|
||||
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-%1.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\passthrough\%TMP::=$%\passthrough-%1\test" ^
|
||||
-create_allocation_test -getfileinfo_name_test -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if !ERRORLEVEL! neq 0 set SamplePassthroughExit=1
|
||||
|
||||
popd
|
||||
echo net use L: /delete
|
||||
net use L: /delete
|
||||
call "%ProjRoot%\tools\fsreg" -u passthrough
|
||||
rmdir /s/q "%TMP%\passthrough-%1"
|
||||
exit /b !SamplePassthroughExit!
|
||||
:sample-passthrough-dotnet
|
||||
call :__run_sample_test passthrough-dotnet anycpu passthrough-dotnet winfsp-tests-x64 ^
|
||||
"-create_backup_test -create_restore_test -create_namelen_test -delete_access_test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-fuse-x64
|
||||
call :__sample-passthrough-fuse x64
|
||||
call :__run_sample_fuse_test passthrough-fuse x64 passthrough-fuse-x64 winfsp-tests-x64
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-fuse-x86
|
||||
call :__sample-passthrough-fuse x86
|
||||
call :__run_sample_fuse_test passthrough-fuse x86 passthrough-fuse-x86 winfsp-tests-x86
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:__sample-passthrough-fuse
|
||||
set SamplePassthroughExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %1 passthrough-fuse "%TMP%\passthrough-fuse-%1"
|
||||
:__run_sample_test
|
||||
set RunSampleTestExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
mkdir "%TMP%\passthrough-fuse-%1\test"
|
||||
call "%ProjRoot%\tools\fsreg" passthrough-fuse "%TMP%\passthrough-fuse-%1\build\%Configuration%\passthrough-fuse-%1.exe" ^
|
||||
"-ouid=65792,gid=65792 --VolumePrefix=%%%%1 %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||
echo net use L: "\\passthrough-fuse\%TMP::=$%\passthrough-fuse-%1\test"
|
||||
net use L: "\\passthrough-fuse\%TMP::=$%\passthrough-fuse-%1\test"
|
||||
mkdir "%TMP%\%1\test"
|
||||
call "%ProjRoot%\tools\fsreg" %1 "%TMP%\%1\build\%Configuration%\%3.exe" "-u %%%%1 -m %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||
echo net use L: "\\%1\%TMP::=$%\%1\test"
|
||||
net use L: "\\%1\%TMP::=$%\%1\test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
echo net use ^| findstr L:
|
||||
net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-%1.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\passthrough-fuse\%TMP::=$%\passthrough-fuse-%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if !ERRORLEVEL! neq 0 set SamplePassthroughExit=1
|
||||
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -getfileinfo_name_test -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test ^
|
||||
-reparse* -stream* %~5
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo net use L: /delete
|
||||
net use L: /delete
|
||||
call "%ProjRoot%\tools\fsreg" -u passthrough-fuse
|
||||
rmdir /s/q "%TMP%\passthrough-fuse-%1"
|
||||
exit /b !SamplePassthroughExit!
|
||||
call "%ProjRoot%\tools\fsreg" -u %1
|
||||
rmdir /s/q "%TMP%\%1"
|
||||
exit /b !RunSampleTestExit!
|
||||
|
||||
:__run_sample_fuse_test
|
||||
set RunSampleTestExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
mkdir "%TMP%\%1\test"
|
||||
call "%ProjRoot%\tools\fsreg" %1 "%TMP%\%1\build\%Configuration%\%3.exe" ^
|
||||
"-ouid=11,gid=65792 --VolumePrefix=%%%%1 %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||
echo net use L: "\\%1\%TMP::=$%\%1\test"
|
||||
net use L: "\\%1\%TMP::=$%\%1\test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
echo net use ^| findstr L:
|
||||
net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo net use L: /delete
|
||||
net use L: /delete
|
||||
call "%ProjRoot%\tools\fsreg" -u %1
|
||||
rmdir /s/q "%TMP%\%1"
|
||||
exit /b !RunSampleTestExit!
|
||||
|
||||
:leak-test
|
||||
for /F "tokens=1,2 delims=:" %%i in ('verifier /query ^| findstr ^
|
||||
|
15
tools/version-info.bat
Normal file
15
tools/version-info.bat
Normal file
@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
for %%f in (%*) do (
|
||||
set file="%%~f"
|
||||
if exist !file! (
|
||||
echo version-info: !file!
|
||||
powershell -command "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(""!file!"") | fl -property ProductName, ProductVersion, ProductVersionRaw, LegalCopyright, CompanyName, FileDescription, FileVersionRaw, FileVersion"
|
||||
powershell -command "try { [System.Reflection.AssemblyName]::GetAssemblyName(""!file!"") | fl -property FullName, Version } catch {}"
|
||||
) else (
|
||||
echo version-info: file !file! not found
|
||||
)
|
||||
)
|
@ -106,7 +106,7 @@ NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 != DebugLogFile)
|
||||
{
|
||||
if (0 == wcscmp(L"-", DebugLogFile))
|
||||
DebugLogHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
else
|
||||
DebugLogHandle = CreateFileW(
|
||||
DebugLogFile,
|
||||
@ -184,7 +184,7 @@ usage:
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -d DebugFlags [-1: enable all debug logs]\n"
|
||||
" -D DebugLogFile [file path; use - for stdout]\n"
|
||||
" -D DebugLogFile [file path; use - for stderr]\n"
|
||||
" -i [case insensitive file system]\n"
|
||||
" -t FileInfoTimeout [millis]\n"
|
||||
" -n MaxFileNodes\n"
|
||||
|
5
tst/passthrough-cpp/.gitignore
vendored
Normal file
5
tst/passthrough-cpp/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
build
|
||||
*.ncb
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.vcxproj.user
|
1016
tst/passthrough-cpp/passthrough-cpp.cpp
Normal file
1016
tst/passthrough-cpp/passthrough-cpp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
tst/passthrough-cpp/passthrough-cpp.sln
Normal file
28
tst/passthrough-cpp/passthrough-cpp.sln
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "passthrough-cpp", "passthrough-cpp.vcxproj", "{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x64.Build.0 = Debug|x64
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x64.ActiveCfg = Release|x64
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x64.Build.0 = Release|x64
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
178
tst/passthrough-cpp/passthrough-cpp.vcxproj
Normal file
178
tst/passthrough-cpp/passthrough-cpp.vcxproj
Normal file
@ -0,0 +1,178 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.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="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>passthroughcpp</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="passthrough-cpp.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
14
tst/passthrough-cpp/passthrough-cpp.vcxproj.filters
Normal file
14
tst/passthrough-cpp/passthrough-cpp.vcxproj.filters
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="passthrough-cpp.cpp">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
6
tst/passthrough-dotnet/.gitignore
vendored
Normal file
6
tst/passthrough-dotnet/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
build
|
||||
*.ncb
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.vcxproj.user
|
||||
*.csproj.user
|
845
tst/passthrough-dotnet/Program.cs
Normal file
845
tst/passthrough-dotnet/Program.cs
Normal file
@ -0,0 +1,845 @@
|
||||
/**
|
||||
* @file Program.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
using Fsp;
|
||||
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
||||
using FileInfo = Fsp.Interop.FileInfo;
|
||||
|
||||
namespace passthrough
|
||||
{
|
||||
class Ptfs : FileSystemBase
|
||||
{
|
||||
protected const int ALLOCATION_UNIT = 4096;
|
||||
|
||||
protected static void ThrowIoExceptionWithHResult(Int32 HResult)
|
||||
{
|
||||
throw new IOException(null, HResult);
|
||||
}
|
||||
protected static void ThrowIoExceptionWithWin32(Int32 Error)
|
||||
{
|
||||
ThrowIoExceptionWithHResult(unchecked((Int32)(0x80070000 | Error)));
|
||||
}
|
||||
protected static void ThrowIoExceptionWithNtStatus(Int32 Status)
|
||||
{
|
||||
ThrowIoExceptionWithWin32((Int32)Win32FromNtStatus(Status));
|
||||
}
|
||||
|
||||
protected class FileDesc
|
||||
{
|
||||
public FileStream Stream;
|
||||
public DirectoryInfo DirInfo;
|
||||
public DictionaryEntry[] FileSystemInfos;
|
||||
|
||||
public FileDesc(FileStream Stream)
|
||||
{
|
||||
this.Stream = Stream;
|
||||
}
|
||||
public FileDesc(DirectoryInfo DirInfo)
|
||||
{
|
||||
this.DirInfo = DirInfo;
|
||||
}
|
||||
public static void GetFileInfoFromFileSystemInfo(
|
||||
FileSystemInfo Info,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileInfo.FileAttributes = (UInt32)Info.Attributes;
|
||||
FileInfo.ReparseTag = 0;
|
||||
FileInfo.FileSize = Info is System.IO.FileInfo ?
|
||||
(UInt64)((System.IO.FileInfo)Info).Length : 0;
|
||||
FileInfo.AllocationSize = (FileInfo.FileSize + ALLOCATION_UNIT - 1)
|
||||
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
|
||||
FileInfo.CreationTime = (UInt64)Info.CreationTimeUtc.ToFileTimeUtc();
|
||||
FileInfo.LastAccessTime = (UInt64)Info.LastAccessTimeUtc.ToFileTimeUtc();
|
||||
FileInfo.LastWriteTime = (UInt64)Info.LastWriteTimeUtc.ToFileTimeUtc();
|
||||
FileInfo.ChangeTime = FileInfo.LastWriteTime;
|
||||
FileInfo.IndexNumber = 0;
|
||||
FileInfo.HardLinks = 0;
|
||||
}
|
||||
public Int32 GetFileInfo(out FileInfo FileInfo)
|
||||
{
|
||||
if (null != Stream)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION Info;
|
||||
if (!GetFileInformationByHandle(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||
out Info))
|
||||
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||
FileInfo.FileAttributes = Info.dwFileAttributes;
|
||||
FileInfo.ReparseTag = 0;
|
||||
FileInfo.FileSize = (UInt64)Stream.Length;
|
||||
FileInfo.AllocationSize = (FileInfo.FileSize + ALLOCATION_UNIT - 1)
|
||||
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
|
||||
FileInfo.CreationTime = Info.ftCreationTime;
|
||||
FileInfo.LastAccessTime = Info.ftLastAccessTime;
|
||||
FileInfo.LastWriteTime = Info.ftLastWriteTime;
|
||||
FileInfo.ChangeTime = FileInfo.LastWriteTime;
|
||||
FileInfo.IndexNumber = 0;
|
||||
FileInfo.HardLinks = 0;
|
||||
}
|
||||
else
|
||||
GetFileInfoFromFileSystemInfo(DirInfo, out FileInfo);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public void SetBasicInfo(
|
||||
UInt32 FileAttributes,
|
||||
UInt64 CreationTime,
|
||||
UInt64 LastAccessTime,
|
||||
UInt64 LastWriteTime)
|
||||
{
|
||||
if (0 == FileAttributes)
|
||||
FileAttributes = (UInt32)System.IO.FileAttributes.Normal;
|
||||
if (null != Stream)
|
||||
{
|
||||
FILE_BASIC_INFO Info = default(FILE_BASIC_INFO);
|
||||
if (unchecked((UInt32)(-1)) != FileAttributes)
|
||||
Info.FileAttributes = FileAttributes;
|
||||
if (0 != CreationTime)
|
||||
Info.CreationTime = CreationTime;
|
||||
if (0 != LastAccessTime)
|
||||
Info.LastAccessTime = LastAccessTime;
|
||||
if (0 != LastWriteTime)
|
||||
Info.LastWriteTime = LastWriteTime;
|
||||
if (!SetFileInformationByHandle(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||
0/*FileBasicInfo*/, ref Info, (UInt32)Marshal.SizeOf(Info)))
|
||||
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unchecked((UInt32)(-1)) != FileAttributes)
|
||||
DirInfo.Attributes = (System.IO.FileAttributes)FileAttributes;
|
||||
if (0 != CreationTime)
|
||||
DirInfo.CreationTimeUtc = DateTime.FromFileTimeUtc((Int64)CreationTime);
|
||||
if (0 != LastAccessTime)
|
||||
DirInfo.LastAccessTimeUtc = DateTime.FromFileTimeUtc((Int64)LastAccessTime);
|
||||
if (0 != LastWriteTime)
|
||||
DirInfo.LastWriteTimeUtc = DateTime.FromFileTimeUtc((Int64)LastWriteTime);
|
||||
}
|
||||
}
|
||||
public UInt32 GetFileAttributes()
|
||||
{
|
||||
FileInfo FileInfo;
|
||||
GetFileInfo(out FileInfo);
|
||||
return FileInfo.FileAttributes;
|
||||
}
|
||||
public void SetFileAttributes(UInt32 FileAttributes)
|
||||
{
|
||||
SetBasicInfo(FileAttributes, 0, 0, 0);
|
||||
}
|
||||
public Byte[] GetSecurityDescriptor()
|
||||
{
|
||||
if (null != Stream)
|
||||
return Stream.GetAccessControl().GetSecurityDescriptorBinaryForm();
|
||||
else
|
||||
return DirInfo.GetAccessControl().GetSecurityDescriptorBinaryForm();
|
||||
}
|
||||
public void SetSecurityDescriptor(AccessControlSections Sections, Byte[] SecurityDescriptor)
|
||||
{
|
||||
Int32 SecurityInformation = 0;
|
||||
if (0 != (Sections & AccessControlSections.Owner))
|
||||
SecurityInformation |= 1/*OWNER_SECURITY_INFORMATION*/;
|
||||
if (0 != (Sections & AccessControlSections.Group))
|
||||
SecurityInformation |= 2/*GROUP_SECURITY_INFORMATION*/;
|
||||
if (0 != (Sections & AccessControlSections.Access))
|
||||
SecurityInformation |= 4/*DACL_SECURITY_INFORMATION*/;
|
||||
if (0 != (Sections & AccessControlSections.Audit))
|
||||
SecurityInformation |= 8/*SACL_SECURITY_INFORMATION*/;
|
||||
if (null != Stream)
|
||||
{
|
||||
if (!SetKernelObjectSecurity(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||
SecurityInformation, SecurityDescriptor))
|
||||
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!SetFileSecurityW(DirInfo.FullName,
|
||||
SecurityInformation, SecurityDescriptor))
|
||||
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||
}
|
||||
}
|
||||
public void SetDisposition(Boolean Safe)
|
||||
{
|
||||
if (null != Stream)
|
||||
{
|
||||
FILE_DISPOSITION_INFO Info;
|
||||
Info.DeleteFile = true;
|
||||
if (!SetFileInformationByHandle(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||
4/*FileDispositionInfo*/, ref Info, (UInt32)Marshal.SizeOf(Info)))
|
||||
if (!Safe)
|
||||
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
DirInfo.Delete();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!Safe)
|
||||
ThrowIoExceptionWithHResult(ex.HResult);
|
||||
}
|
||||
}
|
||||
public static void Rename(String FileName, String NewFileName, Boolean ReplaceIfExists)
|
||||
{
|
||||
if (!MoveFileExW(FileName, NewFileName, ReplaceIfExists ? 1U/*MOVEFILE_REPLACE_EXISTING*/ : 0))
|
||||
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
/* interop */
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
private struct BY_HANDLE_FILE_INFORMATION
|
||||
{
|
||||
public UInt32 dwFileAttributes;
|
||||
public UInt64 ftCreationTime;
|
||||
public UInt64 ftLastAccessTime;
|
||||
public UInt64 ftLastWriteTime;
|
||||
public UInt32 dwVolumeSerialNumber;
|
||||
public UInt32 nFileSizeHigh;
|
||||
public UInt32 nFileSizeLow;
|
||||
public UInt32 nNumberOfLinks;
|
||||
public UInt32 nFileIndexHigh;
|
||||
public UInt32 nFileIndexLow;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct FILE_BASIC_INFO
|
||||
{
|
||||
public UInt64 CreationTime;
|
||||
public UInt64 LastAccessTime;
|
||||
public UInt64 LastWriteTime;
|
||||
public UInt64 ChangeTime;
|
||||
public UInt32 FileAttributes;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct FILE_DISPOSITION_INFO
|
||||
{
|
||||
public Boolean DeleteFile;
|
||||
}
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern Boolean GetFileInformationByHandle(
|
||||
IntPtr hFile,
|
||||
out BY_HANDLE_FILE_INFORMATION lpFileInformation);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern Boolean SetFileInformationByHandle(
|
||||
IntPtr hFile,
|
||||
Int32 FileInformationClass,
|
||||
ref FILE_BASIC_INFO lpFileInformation,
|
||||
UInt32 dwBufferSize);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern Boolean SetFileInformationByHandle(
|
||||
IntPtr hFile,
|
||||
Int32 FileInformationClass,
|
||||
ref FILE_DISPOSITION_INFO lpFileInformation,
|
||||
UInt32 dwBufferSize);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern Boolean MoveFileExW(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String lpExistingFileName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String lpNewFileName,
|
||||
UInt32 dwFlags);
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
private static extern Boolean SetFileSecurityW(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
Int32 SecurityInformation,
|
||||
Byte[] SecurityDescriptor);
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
private static extern Boolean SetKernelObjectSecurity(
|
||||
IntPtr Handle,
|
||||
Int32 SecurityInformation,
|
||||
Byte[] SecurityDescriptor);
|
||||
}
|
||||
|
||||
private class DirectoryEntryComparer : IComparer
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
return String.Compare(
|
||||
(String)((DictionaryEntry)x).Key,
|
||||
(String)((DictionaryEntry)y).Key);
|
||||
}
|
||||
}
|
||||
private static DirectoryEntryComparer _DirectoryEntryComparer =
|
||||
new DirectoryEntryComparer();
|
||||
|
||||
public Ptfs(String Path0)
|
||||
{
|
||||
_Path = Path.GetFullPath(Path0);
|
||||
if (_Path.EndsWith("\\"))
|
||||
_Path = _Path.Substring(0, _Path.Length - 1);
|
||||
}
|
||||
public String ConcatPath(String FileName)
|
||||
{
|
||||
return _Path + FileName;
|
||||
}
|
||||
public override Int32 ExceptionHandler(Exception ex)
|
||||
{
|
||||
Int32 HResult = ex.HResult; /* needs Framework 4.5 */
|
||||
if (0x80070000 == (HResult & 0xFFFF0000))
|
||||
return NtStatusFromWin32((UInt32)HResult & 0xFFFF);
|
||||
return STATUS_UNEXPECTED_IO_ERROR;
|
||||
}
|
||||
public override Int32 Init(Object Host0)
|
||||
{
|
||||
FileSystemHost Host = (FileSystemHost)Host0;
|
||||
Host.SectorSize = ALLOCATION_UNIT;
|
||||
Host.SectorsPerAllocationUnit = 1;
|
||||
Host.MaxComponentLength = 255;
|
||||
Host.FileInfoTimeout = 1000;
|
||||
Host.CaseSensitiveSearch = false;
|
||||
Host.CasePreservedNames = true;
|
||||
Host.UnicodeOnDisk = true;
|
||||
Host.PersistentAcls = true;
|
||||
Host.PostCleanupWhenModifiedOnly = true;
|
||||
Host.PassQueryDirectoryPattern = true;
|
||||
Host.VolumeCreationTime = (UInt64)File.GetCreationTimeUtc(_Path).ToFileTimeUtc();
|
||||
Host.VolumeSerialNumber = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 GetVolumeInfo(
|
||||
out VolumeInfo VolumeInfo)
|
||||
{
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
try
|
||||
{
|
||||
DriveInfo Info = new DriveInfo(_Path);
|
||||
VolumeInfo.TotalSize = (UInt64)Info.TotalSize;
|
||||
VolumeInfo.FreeSize = (UInt64)Info.TotalFreeSpace;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
/*
|
||||
* DriveInfo only supports drives and does not support UNC paths.
|
||||
* It would be better to use GetDiskFreeSpaceEx here.
|
||||
*/
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 GetSecurityByName(
|
||||
String FileName,
|
||||
out UInt32 FileAttributes/* or ReparsePointIndex */,
|
||||
ref Byte[] SecurityDescriptor)
|
||||
{
|
||||
FileName = ConcatPath(FileName);
|
||||
System.IO.FileInfo Info = new System.IO.FileInfo(FileName);
|
||||
FileAttributes = (UInt32)Info.Attributes;
|
||||
if (null != SecurityDescriptor)
|
||||
SecurityDescriptor = Info.GetAccessControl().GetSecurityDescriptorBinaryForm();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 Create(
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
UInt32 FileAttributes,
|
||||
Byte[] SecurityDescriptor,
|
||||
UInt64 AllocationSize,
|
||||
out Object FileNode,
|
||||
out Object FileDesc0,
|
||||
out FileInfo FileInfo,
|
||||
out String NormalizedName)
|
||||
{
|
||||
FileDesc FileDesc = null;
|
||||
try
|
||||
{
|
||||
FileName = ConcatPath(FileName);
|
||||
if (0 == (CreateOptions & FILE_DIRECTORY_FILE))
|
||||
{
|
||||
FileSecurity Security = null;
|
||||
if (null != SecurityDescriptor)
|
||||
{
|
||||
Security = new FileSecurity();
|
||||
Security.SetSecurityDescriptorBinaryForm(SecurityDescriptor);
|
||||
}
|
||||
FileDesc = new FileDesc(
|
||||
new FileStream(
|
||||
FileName,
|
||||
FileMode.CreateNew,
|
||||
(FileSystemRights)GrantedAccess | FileSystemRights.WriteAttributes,
|
||||
FileShare.Read | FileShare.Write | FileShare.Delete,
|
||||
4096,
|
||||
0,
|
||||
Security));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Directory.Exists(FileName))
|
||||
ThrowIoExceptionWithNtStatus(STATUS_OBJECT_NAME_COLLISION);
|
||||
DirectorySecurity Security = null;
|
||||
if (null != SecurityDescriptor)
|
||||
{
|
||||
Security = new DirectorySecurity();
|
||||
Security.SetSecurityDescriptorBinaryForm(SecurityDescriptor);
|
||||
}
|
||||
FileDesc = new FileDesc(
|
||||
Directory.CreateDirectory(FileName, Security));
|
||||
}
|
||||
FileDesc.SetFileAttributes(FileAttributes);
|
||||
FileNode = default(Object);
|
||||
FileDesc0 = FileDesc;
|
||||
NormalizedName = default(String);
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (null != FileDesc && null != FileDesc.Stream)
|
||||
FileDesc.Stream.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public override Int32 Open(
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
UInt32 GrantedAccess,
|
||||
out Object FileNode,
|
||||
out Object FileDesc0,
|
||||
out FileInfo FileInfo,
|
||||
out String NormalizedName)
|
||||
{
|
||||
FileDesc FileDesc = null;
|
||||
try
|
||||
{
|
||||
FileName = ConcatPath(FileName);
|
||||
if (!Directory.Exists(FileName))
|
||||
{
|
||||
FileDesc = new FileDesc(
|
||||
new FileStream(
|
||||
FileName,
|
||||
FileMode.Open,
|
||||
(FileSystemRights)GrantedAccess,
|
||||
FileShare.Read | FileShare.Write | FileShare.Delete,
|
||||
4096,
|
||||
0));
|
||||
}
|
||||
else
|
||||
{
|
||||
FileDesc = new FileDesc(
|
||||
new DirectoryInfo(FileName));
|
||||
}
|
||||
FileNode = default(Object);
|
||||
FileDesc0 = FileDesc;
|
||||
NormalizedName = default(String);
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (null != FileDesc && null != FileDesc.Stream)
|
||||
FileDesc.Stream.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public override Int32 Overwrite(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
UInt32 FileAttributes,
|
||||
Boolean ReplaceFileAttributes,
|
||||
UInt64 AllocationSize,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (ReplaceFileAttributes)
|
||||
FileDesc.SetFileAttributes(FileAttributes);
|
||||
else if (0 != FileAttributes)
|
||||
FileDesc.SetFileAttributes(FileDesc.GetFileAttributes() | FileAttributes);
|
||||
FileDesc.Stream.SetLength(0);
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
public override void Cleanup(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
String FileName,
|
||||
UInt32 Flags)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (0 != (Flags & CleanupDelete))
|
||||
{
|
||||
FileDesc.SetDisposition(true);
|
||||
if (null != FileDesc.Stream)
|
||||
FileDesc.Stream.Dispose();
|
||||
}
|
||||
}
|
||||
public override void Close(
|
||||
Object FileNode,
|
||||
Object FileDesc0)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (null != FileDesc.Stream)
|
||||
FileDesc.Stream.Dispose();
|
||||
}
|
||||
public override Int32 Read(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (Offset >= (UInt64)FileDesc.Stream.Length)
|
||||
ThrowIoExceptionWithNtStatus(STATUS_END_OF_FILE);
|
||||
Byte[] Bytes = new byte[Length];
|
||||
FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin);
|
||||
PBytesTransferred = (UInt32)FileDesc.Stream.Read(Bytes, 0, Bytes.Length);
|
||||
Marshal.Copy(Bytes, 0, Buffer, Bytes.Length);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 Write(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
IntPtr Buffer,
|
||||
UInt64 Offset,
|
||||
UInt32 Length,
|
||||
Boolean WriteToEndOfFile,
|
||||
Boolean ConstrainedIo,
|
||||
out UInt32 PBytesTransferred,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (ConstrainedIo)
|
||||
{
|
||||
if (Offset >= (UInt64)FileDesc.Stream.Length)
|
||||
{
|
||||
PBytesTransferred = default(UInt32);
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if (Offset + Length > (UInt64)FileDesc.Stream.Length)
|
||||
Length = (UInt32)((UInt64)FileDesc.Stream.Length - Offset);
|
||||
}
|
||||
Byte[] Bytes = new byte[Length];
|
||||
Marshal.Copy(Buffer, Bytes, 0, Bytes.Length);
|
||||
if (!WriteToEndOfFile)
|
||||
FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin);
|
||||
FileDesc.Stream.Write(Bytes, 0, Bytes.Length);
|
||||
PBytesTransferred = (UInt32)Bytes.Length;
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
public override Int32 Flush(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (null == FileDesc)
|
||||
{
|
||||
/* we do not flush the whole volume, so just return SUCCESS */
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
FileDesc.Stream.Flush(true);
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
public override Int32 GetFileInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
public override Int32 SetBasicInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
UInt32 FileAttributes,
|
||||
UInt64 CreationTime,
|
||||
UInt64 LastAccessTime,
|
||||
UInt64 LastWriteTime,
|
||||
UInt64 ChangeTime,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
FileDesc.SetBasicInfo(FileAttributes, CreationTime, LastAccessTime, LastWriteTime);
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
public override Int32 SetFileSize(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
UInt64 NewSize,
|
||||
Boolean SetAllocationSize,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (!SetAllocationSize || (UInt64)FileDesc.Stream.Length > NewSize)
|
||||
{
|
||||
/*
|
||||
* "FileInfo.FileSize > NewSize" explanation:
|
||||
* Ptfs does not support allocation size. However if the new AllocationSize
|
||||
* is less than the current FileSize we must truncate the file.
|
||||
*/
|
||||
FileDesc.Stream.SetLength((Int64)NewSize);
|
||||
}
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
public override Int32 CanDelete(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
String FileName)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
FileDesc.SetDisposition(false);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 Rename(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
String FileName,
|
||||
String NewFileName,
|
||||
Boolean ReplaceIfExists)
|
||||
{
|
||||
FileName = ConcatPath(FileName);
|
||||
NewFileName = ConcatPath(NewFileName);
|
||||
FileDesc.Rename(FileName, NewFileName, ReplaceIfExists);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 GetSecurity(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
ref Byte[] SecurityDescriptor)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
SecurityDescriptor = FileDesc.GetSecurityDescriptor();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 SetSecurity(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
AccessControlSections Sections,
|
||||
Byte[] SecurityDescriptor)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
FileDesc.SetSecurityDescriptor(Sections, SecurityDescriptor);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Boolean ReadDirectoryEntry(
|
||||
Object FileNode,
|
||||
Object FileDesc0,
|
||||
String Pattern,
|
||||
String Marker,
|
||||
ref Object Context,
|
||||
out String FileName,
|
||||
out FileInfo FileInfo)
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (null == FileDesc.FileSystemInfos)
|
||||
{
|
||||
IEnumerable Enum = FileDesc.DirInfo.EnumerateFileSystemInfos(
|
||||
null != Pattern ? Pattern : "*");
|
||||
SortedList List = new SortedList();
|
||||
List.Add(".", FileDesc.DirInfo);
|
||||
List.Add("..", FileDesc.DirInfo.Parent);
|
||||
foreach (FileSystemInfo Info in Enum)
|
||||
List.Add(Info.Name, Info);
|
||||
FileDesc.FileSystemInfos = new DictionaryEntry[List.Count];
|
||||
List.CopyTo(FileDesc.FileSystemInfos, 0);
|
||||
}
|
||||
int Index;
|
||||
if (null == Context)
|
||||
{
|
||||
Index = 0;
|
||||
if (null != Marker)
|
||||
{
|
||||
Index = Array.BinarySearch(FileDesc.FileSystemInfos,
|
||||
new DictionaryEntry(Marker, null),
|
||||
_DirectoryEntryComparer);
|
||||
if (0 <= Index)
|
||||
Index++;
|
||||
else
|
||||
Index = ~Index;
|
||||
}
|
||||
}
|
||||
else
|
||||
Index = (int)Context;
|
||||
if (FileDesc.FileSystemInfos.Length > Index)
|
||||
{
|
||||
Context = Index + 1;
|
||||
FileName = (String)FileDesc.FileSystemInfos[Index].Key;
|
||||
FileDesc.GetFileInfoFromFileSystemInfo(
|
||||
(FileSystemInfo)FileDesc.FileSystemInfos[Index].Value,
|
||||
out FileInfo);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = default(String);
|
||||
FileInfo = default(FileInfo);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String _Path;
|
||||
}
|
||||
|
||||
class PtfsService : Service
|
||||
{
|
||||
private class CommandLineUsageException : Exception
|
||||
{
|
||||
public CommandLineUsageException(String Message = null) : base(Message)
|
||||
{
|
||||
HasMessage = null != Message;
|
||||
}
|
||||
|
||||
public bool HasMessage;
|
||||
}
|
||||
|
||||
private const String PROGNAME = "passthrough-dotnet";
|
||||
|
||||
public PtfsService() : base("PtfsService")
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnStart(String[] Args)
|
||||
{
|
||||
try
|
||||
{
|
||||
String DebugLogFile = null;
|
||||
UInt32 DebugFlags = 0;
|
||||
String VolumePrefix = null;
|
||||
String PassThrough = null;
|
||||
String MountPoint = null;
|
||||
IntPtr DebugLogHandle = (IntPtr)(-1);
|
||||
FileSystemHost Host = null;
|
||||
Ptfs Ptfs = null;
|
||||
int I;
|
||||
|
||||
for (I = 1; Args.Length > I; I++)
|
||||
{
|
||||
String Arg = Args[I];
|
||||
if ('-' != Arg[0])
|
||||
break;
|
||||
switch (Arg[1])
|
||||
{
|
||||
case '?':
|
||||
throw new CommandLineUsageException();
|
||||
case 'd':
|
||||
argtol(Args, ref I, ref DebugFlags);
|
||||
break;
|
||||
case 'D':
|
||||
argtos(Args, ref I, ref DebugLogFile);
|
||||
break;
|
||||
case 'm':
|
||||
argtos(Args, ref I, ref MountPoint);
|
||||
break;
|
||||
case 'p':
|
||||
argtos(Args, ref I, ref PassThrough);
|
||||
break;
|
||||
case 'u':
|
||||
argtos(Args, ref I, ref VolumePrefix);
|
||||
break;
|
||||
default:
|
||||
throw new CommandLineUsageException();
|
||||
}
|
||||
}
|
||||
|
||||
if (Args.Length > I)
|
||||
throw new CommandLineUsageException();
|
||||
|
||||
if (null == PassThrough && null != VolumePrefix)
|
||||
{
|
||||
I = VolumePrefix.IndexOf('\\');
|
||||
if (-1 != I && VolumePrefix.Length > I && '\\' != VolumePrefix[I + 1])
|
||||
{
|
||||
I = VolumePrefix.IndexOf('\\', I + 1);
|
||||
if (-1 != I &&
|
||||
VolumePrefix.Length > I + 1 &&
|
||||
(
|
||||
('A' <= VolumePrefix[I + 1] && VolumePrefix[I + 1] <= 'Z') ||
|
||||
('a' <= VolumePrefix[I + 1] && VolumePrefix[I + 1] <= 'z')
|
||||
) &&
|
||||
'$' == VolumePrefix[I + 2])
|
||||
{
|
||||
PassThrough = String.Format("{0}:{1}", VolumePrefix[I + 1], VolumePrefix.Substring(I + 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null == PassThrough || null == MountPoint)
|
||||
throw new CommandLineUsageException();
|
||||
|
||||
if (null != DebugLogFile)
|
||||
if (0 > FileSystemHost.SetDebugLogFile(DebugLogFile))
|
||||
throw new CommandLineUsageException("cannot open debug log file");
|
||||
|
||||
Host = new FileSystemHost(Ptfs = new Ptfs(PassThrough));
|
||||
Host.Prefix = VolumePrefix;
|
||||
if (0 > Host.Mount(MountPoint, null, true, DebugFlags))
|
||||
throw new IOException("cannot mount file system");
|
||||
MountPoint = Host.MountPoint();
|
||||
_Host = Host;
|
||||
|
||||
Log(EVENTLOG_INFORMATION_TYPE, String.Format("{0}{1}{2} -p {3} -m {4}",
|
||||
PROGNAME,
|
||||
null != VolumePrefix && 0 < VolumePrefix.Length ? " -u " : "",
|
||||
null != VolumePrefix && 0 < VolumePrefix.Length ? VolumePrefix : "",
|
||||
PassThrough,
|
||||
MountPoint));
|
||||
}
|
||||
catch (CommandLineUsageException ex)
|
||||
{
|
||||
Log(EVENTLOG_ERROR_TYPE, String.Format(
|
||||
"{0}" +
|
||||
"usage: {1} OPTIONS\n" +
|
||||
"\n" +
|
||||
"options:\n" +
|
||||
" -d DebugFlags [-1: enable all debug logs]\n" +
|
||||
" -D DebugLogFile [file path; use - for stderr]\n" +
|
||||
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
||||
" -p Directory [directory to expose as pass through file system]\n" +
|
||||
" -m MountPoint [X:|*|directory]\n",
|
||||
ex.HasMessage ? ex.Message + "\n" : "",
|
||||
PROGNAME));
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log(EVENTLOG_ERROR_TYPE, String.Format("{0}", ex.Message));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
protected override void OnStop()
|
||||
{
|
||||
_Host.Unmount();
|
||||
_Host = null;
|
||||
}
|
||||
|
||||
private static void argtos(String[] Args, ref int I, ref String V)
|
||||
{
|
||||
if (Args.Length > ++I)
|
||||
V = Args[I];
|
||||
else
|
||||
throw new CommandLineUsageException();
|
||||
}
|
||||
private static void argtol(String[] Args, ref int I, ref UInt32 V)
|
||||
{
|
||||
Int32 R;
|
||||
if (Args.Length > ++I)
|
||||
V = Int32.TryParse(Args[I], out R) ? (UInt32)R : V;
|
||||
else
|
||||
throw new CommandLineUsageException();
|
||||
}
|
||||
|
||||
private FileSystemHost _Host;
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Environment.ExitCode = new PtfsService().Run();
|
||||
}
|
||||
}
|
||||
}
|
84
tst/passthrough-dotnet/passthrough-dotnet.csproj
Normal file
84
tst/passthrough-dotnet/passthrough-dotnet.csproj
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>passthrough</RootNamespace>
|
||||
<AssemblyName>passthrough-dotnet</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="winfsp-msil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b099876d8fa9b1f3, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>$(MSBuildProgramFiles32)\WinFsp\bin\winfsp-msil.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
22
tst/passthrough-dotnet/passthrough-dotnet.sln
Normal file
22
tst/passthrough-dotnet/passthrough-dotnet.sln
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "passthrough-dotnet", "passthrough-dotnet.csproj", "{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -846,7 +846,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 != DebugLogFile)
|
||||
{
|
||||
if (0 == wcscmp(L"-", DebugLogFile))
|
||||
DebugLogHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
else
|
||||
DebugLogHandle = CreateFileW(
|
||||
DebugLogFile,
|
||||
@ -903,7 +903,7 @@ usage:
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -d DebugFlags [-1: enable all debug logs]\n"
|
||||
" -D DebugLogFile [file path; use - for stdout]\n"
|
||||
" -D DebugLogFile [file path; use - for stderr]\n"
|
||||
" -u \\Server\\Share [UNC prefix (single backslash)]\n"
|
||||
" -p Directory [directory to expose as pass through file system]\n"
|
||||
" -m MountPoint [X:|*|directory]\n";
|
||||
|
Reference in New Issue
Block a user