mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
67 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb3f8d37f2 | |||
c72a9f2a05 | |||
9b4ab190e0 | |||
010ed909ec | |||
2b4549a50d | |||
98a329e81b | |||
8090b7c666 | |||
c7d720eaa0 | |||
8320160d73 | |||
ce057b49b8 | |||
a60c989089 | |||
0f6371f0d8 | |||
1a4bbbe09a | |||
4e891dc2a8 | |||
18a77d63c3 | |||
4ea9c6e362 | |||
9d77c192a8 | |||
6d5401d911 | |||
330d6e79f8 | |||
ed58b7a63c | |||
f6853114c1 | |||
8ec7285d32 | |||
c183c0fe89 | |||
38ad8fd27d | |||
de85070e73 | |||
5b8ebd6e1d | |||
db530cb5e5 | |||
7cd4d4faab | |||
2560a513dc | |||
1ee95be5d7 | |||
bd7546559c | |||
d18a2c8b75 | |||
0ebae0adc1 | |||
d70c49ccd0 | |||
5846939116 | |||
f124e74f01 | |||
05abb93e4b | |||
5839d46b7a | |||
bce0d63f7d | |||
14b9f5affc | |||
035a430470 | |||
0af9e46e76 | |||
c4530f1252 | |||
9f78a17583 | |||
eea0b1bc79 | |||
8338a6e066 | |||
ddba49dbea | |||
a6ff8a87de | |||
bf64bcf9ba | |||
8c5d9bda20 | |||
f1ac28b0aa | |||
ff725f931d | |||
31519ba416 | |||
0bca8f851c | |||
acf175da60 | |||
23eac24c84 | |||
0f9ef3bd51 | |||
2bdd54536e | |||
060ebcca0d | |||
b38a89e485 | |||
b5bfeee027 | |||
f36cacaf84 | |||
4278cec465 | |||
151627091b | |||
2ee3f02928 | |||
d77d3ccccf | |||
1e0c91658e |
@ -5,7 +5,23 @@ 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 .NET layer that allows the creation of file systems in managed mode. This is contained in the new `winfsp-msil.dll`. The new .NET layer is being tested with the WinFsp test suites and Microsoft's ifstest.
|
||||
- FUSE for Cygwin is now included with the installer.
|
||||
- FUSE now has a `-ovolname=VOLNAME` parameter that allows setting the volume label. Thanks @samkelly.
|
||||
- A number of other FUSE improvements have been made (see issue #85).
|
||||
|
||||
NOTE: The C++ layer included in the v1.1 beta releases is not part of this release as it is still work in progress. It can be found in `inc/winfsp/winfsp.hpp` in the WinFsp source repository.
|
||||
|
||||
|
||||
v1.1B3 (2017.1 B3)::
|
||||
|
||||
v1.1B2 (2017.1 B2)::
|
||||
|
||||
v1.1B1 (2017.1 BETA)::
|
||||
|
||||
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`. The new .NET layer is being tested with the WinFsp test suites and Microsoft's ifstest.
|
||||
- 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.
|
||||
|
@ -42,7 +42,8 @@ The project source code is organized as follows:
|
||||
* 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.
|
||||
* tst/memfs: Source code to an example file system written in C++ (memfs).
|
||||
* tst/memfs*: Source code to an example file system written in C/C++ (memfs) or C# (memfs-dotnet).
|
||||
* tst/passthrough*: Source code to additional example file systems.
|
||||
* tst/winfsp-tests: WinFsp test suite.
|
||||
|
||||
## Building and Running
|
||||
@ -72,7 +73,7 @@ WinFsp is designed to run on Windows 7 and above. It has been tested on the foll
|
||||
I am looking for help in the following areas:
|
||||
|
||||
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
|
||||
* If you are working with a language other than C/C++ (e.g. Delphi, C#, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
||||
* If you are working with a language other than C/C++ (e.g. Delphi, Java, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
||||
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/billziss-gh/winfsp/issues). Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart.
|
||||
|
||||
In all cases I can provide ideas and/or support.
|
||||
|
1
build/VStudio/.gitignore
vendored
1
build/VStudio/.gitignore
vendored
@ -3,3 +3,4 @@ build
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.vcxproj.user
|
||||
*.csproj.user
|
||||
|
@ -25,6 +25,8 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DocumentationFile>$(BaseIntermediateOutputPath)$(Configuration)\winfsp-msil.xml</DocumentationFile>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@ -36,6 +38,8 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DocumentationFile>$(BaseIntermediateOutputPath)$(Configuration)\winfsp-msil.xml</DocumentationFile>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
@ -92,6 +92,9 @@
|
||||
<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.xml" Guid="1657F707-C112-454C-91AE-0FDEBBF454AB">
|
||||
<File Id="FILE.winfsp_msil.xml" Name="winfsp-msil.xml" 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" />
|
||||
@ -214,6 +217,32 @@
|
||||
</RegistryKey>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<Component Id="C.memfs_dotnet_msil.exe">
|
||||
<File Name="memfs-dotnet-msil.exe" KeyPath="yes" />
|
||||
<RegistryKey
|
||||
Root="HKLM"
|
||||
Key="[P.LauncherRegistryKey]">
|
||||
<RegistryKey
|
||||
Key="memfs-dotnet">
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="Executable"
|
||||
Value="[BINDIR]memfs-dotnet-msil.exe" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="CommandLine"
|
||||
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="Security"
|
||||
Value="D:P(A;;RPWPLC;;;WD)" />
|
||||
<RegistryValue
|
||||
Type="integer"
|
||||
Name="JobControl"
|
||||
Value="1" />
|
||||
</RegistryKey>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="INCDIR" FileSource="..\..\..\inc">
|
||||
<Directory Id="INCDIR.winfsp" Name="winfsp">
|
||||
@ -223,9 +252,9 @@
|
||||
<Component Id="C.winfsp.h">
|
||||
<File Name="winfsp.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.winfsp.hpp">
|
||||
<!--Component Id="C.winfsp.hpp">
|
||||
<File Name="winfsp.hpp" KeyPath="yes" />
|
||||
</Component>
|
||||
</Component-->
|
||||
</Directory>
|
||||
<Directory Id="INCDIR.fuse" Name="fuse">
|
||||
<Component Id="C.fuse.h">
|
||||
@ -272,9 +301,16 @@
|
||||
</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>
|
||||
<Directory Id="OPTDIR.cygfuse.x64" Name="x64">
|
||||
<Component Id="C.fuse.tar.xz.x64">
|
||||
<File Id="FILE.fuse.tar.xz.x64" Name="fuse-2.8-5.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="OPTDIR.cygfuse.x86" Name="x86">
|
||||
<Component Id="C.fuse.tar.xz.x86">
|
||||
<File Id="FILE.fuse.tar.xz.x86" Name="fuse-2.8-5.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Component Id="C.fuse.install.sh">
|
||||
<File Name="install.sh" KeyPath="yes" />
|
||||
</Component>
|
||||
@ -295,6 +331,11 @@
|
||||
<File Name="memfs-main.c" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.memfs_dotnet" Name="memfs-dotnet">
|
||||
<Component Id="C.memfs_dotnet.Program.cs">
|
||||
<File Id="FILE.memfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough" Name="passthrough">
|
||||
<Component Id="C.passthrough.c">
|
||||
<File Name="passthrough.c" KeyPath="yes" />
|
||||
@ -309,7 +350,7 @@
|
||||
<File Name="passthrough.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_cpp" Name="passthrough-cpp">
|
||||
<!--Directory Id="SMPDIR.passthrough_cpp" Name="passthrough-cpp">
|
||||
<Component Id="C.passthrough_cpp.cpp">
|
||||
<File Name="passthrough-cpp.cpp" KeyPath="yes" />
|
||||
</Component>
|
||||
@ -322,7 +363,7 @@
|
||||
<Component Id="C.passthrough_cpp.vcxproj.filters">
|
||||
<File Name="passthrough-cpp.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory-->
|
||||
<Directory Id="SMPDIR.passthrough_fuse" Name="passthrough-fuse">
|
||||
<Component Id="C.passthrough_fuse.c">
|
||||
<File Name="passthrough-fuse.c" KeyPath="yes" />
|
||||
@ -351,7 +392,7 @@
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_dotnet" Name="passthrough-dotnet">
|
||||
<Component Id="C.passthrough_dotnet.Program.cs">
|
||||
<File Name="Program.cs" KeyPath="yes" />
|
||||
<File Id="FILE.passthrough_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_dotnet.sln">
|
||||
<File Name="passthrough-dotnet.sln" KeyPath="yes" />
|
||||
@ -413,7 +454,7 @@
|
||||
<ComponentGroup Id="C.WinFsp.inc">
|
||||
<ComponentRef Id="C.fsctl.h" />
|
||||
<ComponentRef Id="C.winfsp.h" />
|
||||
<ComponentRef Id="C.winfsp.hpp" />
|
||||
<!--ComponentRef Id="C.winfsp.hpp" /-->
|
||||
<ComponentRef Id="C.fuse.h" />
|
||||
<ComponentRef Id="C.fuse_common.h" />
|
||||
<ComponentRef Id="C.fuse_opt.h" />
|
||||
@ -426,7 +467,8 @@
|
||||
<ComponentRef Id="C.fuse_x86.pc" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.opt.fuse">
|
||||
<ComponentRef Id="C.fuse.tar.xz" />
|
||||
<ComponentRef Id="C.fuse.tar.xz.x64" />
|
||||
<ComponentRef Id="C.fuse.tar.xz.x86" />
|
||||
<ComponentRef Id="C.fuse.install.sh" />
|
||||
<ComponentRef Id="C.fuse.uninstall.sh" />
|
||||
</ComponentGroup>
|
||||
@ -440,10 +482,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_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" />
|
||||
@ -467,12 +509,15 @@
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.net">
|
||||
<ComponentRef Id="C.winfsp_msil.dll" />
|
||||
<ComponentRef Id="C.winfsp_msil.xml" />
|
||||
<!--
|
||||
<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.memfs_dotnet_msil.exe" />
|
||||
<ComponentRef Id="C.memfs_dotnet.Program.cs" />
|
||||
<ComponentRef Id="C.passthrough_dotnet.Program.cs" />
|
||||
<ComponentRef Id="C.passthrough_dotnet.sln" />
|
||||
<ComponentRef Id="C.passthrough_dotnet.csproj" />
|
||||
@ -531,7 +576,7 @@
|
||||
Id="F.Cygfuse"
|
||||
Level="1000"
|
||||
Title="FUSE for Cygwin"
|
||||
Description="From a Cygwin prompt change to $InstallDir/opt/cygfuse and run install.sh."
|
||||
Description="From a Cygwin prompt change to <InstallDir>/opt/cygfuse and run install.sh."
|
||||
AllowAdvertise="no"
|
||||
InstallDefault="local"
|
||||
Absent="allow">
|
||||
|
63
build/VStudio/testing/memfs-dotnet.csproj
Normal file
63
build/VStudio/testing/memfs-dotnet.csproj
Normal file
@ -0,0 +1,63 @@
|
||||
<?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>{4920E350-D496-4652-AE98-6C4208AEC1D8}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ProjectName>memfs-dotnet</ProjectName>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>memfs</RootNamespace>
|
||||
<AssemblyName>memfs-dotnet-msil</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\tst\memfs-dotnet\Program.cs">
|
||||
<Link>Program.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\dotnet\winfsp.net.csproj">
|
||||
<Project>{94580219-cc8d-4fe5-a3be-437b0b3481e1}</Project>
|
||||
<Name>winfsp.net</Name>
|
||||
</ProjectReference>
|
||||
</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>
|
@ -17,8 +17,8 @@
|
||||
|
||||
<MyCanonicalVersion>1.1</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2017.1 BETA</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
<MyProductVersion>2017.1</MyProductVersion>
|
||||
<MyProductStage>Gold</MyProductStage>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||
|
@ -61,6 +61,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winfsp.net", "dotnet\winfsp
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{A998CEC4-4B34-43DC-8457-F7761228BA67}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "memfs-dotnet", "testing\memfs-dotnet.csproj", "{4920E350-D496-4652-AE98-6C4208AEC1D8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -259,6 +261,30 @@ Global
|
||||
{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
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x64.Build.0 = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x86.Build.0 = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -273,5 +299,6 @@ Global
|
||||
{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}
|
||||
{4920E350-D496-4652-AE98-6C4208AEC1D8} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -10,6 +10,11 @@ I am running Windows 7 and I am finding that the installed driver is not signed.
|
||||
https://technet.microsoft.com/en-us/library/security/3033929.aspx
|
||||
|
||||
|
||||
Disconnecting (unmapping) a network drive does not work. [@carlreinke]::
|
||||
|
||||
You may have Dokany installed. Dokany installs its own Network Provider DLL that unfortunately interferes with the WinFsp handling of network drives. The solution is to change your system's Network Provider order and ensure that the WinFsp Network Provider runs before the Dokany one. Instructions on how to change the Network Provider order can be found in this http://blogs.interfacett.com/changing-the-network-provider-order-in-windows-10[article].
|
||||
|
||||
|
||||
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.
|
||||
|
@ -5,12 +5,15 @@ This document contains a list of known file systems and file system libraries th
|
||||
== File Systems
|
||||
|
||||
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
||||
- https://github.com/ncw/rclone[rclone] - rsync for cloud storage
|
||||
- https://github.com/hasse69/rar2fs[rar2fs] - FUSE file system for reading RAR archives
|
||||
- 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/billziss-gh/cgofuse[cgofuse] - Cross-platform FUSE library for Go
|
||||
- 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
|
||||
|
@ -38,7 +38,7 @@ For example, the MEMFS sample adds the following registry entries in a 64-bit sy
|
||||
"Security"="D:P(A;;RPWPLC;;;WD)"
|
||||
"JobControl"=dword:00000001
|
||||
|
||||
When the WinFsp.Launcher starts up it creates a named pipe that applications can use to start, stop, get information about and list service instances. A small command line utility (`launchctl`) can be used to issue those commands. The CallNamedPipeW API can be used as well.
|
||||
When the WinFsp.Launcher starts up it creates a named pipe that applications can use to start, stop, get information about and list service instances. A small command line utility (`launchctl`) can be used to issue those commands. The `CallNamedPipeW` API can be used as well.
|
||||
|
||||
One final note regarding security. Notice the `Security` registry value in the example above. This registry value uses SDDL syntax to instruct WinFsp.Launcher to allow Everyone (`WD`) to start (`RP`), stop (`WP`) and get information (`LC`) about the service instance. If the `Security` registry value is missing the default is to allow only LocalSystem and Administrators to control the service instance.
|
||||
|
||||
@ -47,3 +47,13 @@ One final note regarding security. Notice the `Security` registry value in the e
|
||||
WinFsp includes a Network Provider that integrates with Windows and can be used to start and stop user mode file systems from the Windows shell. To achieve this the Network Provider (implemented as part of the WinFsp DLL) works closely with the WinFsp.Launcher service.
|
||||
|
||||
For example, if a user uses the Windows Explorer to map `\\memfs64\share` to the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to start an instance of the memfs64 service with command line `-i -F NTFS -n 65536 -s 67108864 -u \\memfs64\share -m Z:`. When the user disconnects the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to stop the previously started instance of the memfs64 service.
|
||||
|
||||
== File System Credential Support
|
||||
|
||||
Some file systems require credentials in order to allow access and be mounted. Such file systems must add a registry value `Credentials`:
|
||||
|
||||
"Credentials"=dword:00000001
|
||||
|
||||
This will instruct the WinFsp Network Provider to request a password from the user prior to starting the file system. This password will then be securely passed to the WinFsp Launcher which in turn will pass it to the user mode file system on its standard input. The user mode file system must respond `OK` if the password is correct and allows access to the user mode file system. Any other response from the user mode file system (including a timeout without a response) is interpreted as an authentication failure.
|
||||
|
||||
NOTE: During password entry the user may also choose to "remember" the password in which case it will be saved in the Windows Credential Manager.
|
@ -118,6 +118,8 @@ FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_loop_mt)(struct fsp_fuse_env *env,
|
||||
struct fuse *f);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_exit)(struct fsp_fuse_env *env,
|
||||
struct fuse *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env,
|
||||
struct fuse *f);
|
||||
FSP_FUSE_API struct fuse_context *FSP_FUSE_API_NAME(fsp_fuse_get_context)(struct fsp_fuse_env *env);
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
@ -171,6 +173,13 @@ void fuse_exit(struct fuse *f),
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse_exited(struct fuse *f),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse_exited)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse_context *fuse_get_context(void),
|
||||
{
|
||||
|
@ -178,6 +178,7 @@ struct fuse_flock
|
||||
fsp_fuse_daemonize, \
|
||||
fsp_fuse_set_signal_handlers, \
|
||||
0/*conv_to_win_path*/, \
|
||||
{ 0 }, \
|
||||
}
|
||||
#else
|
||||
#define FSP_FUSE_ENV_INIT \
|
||||
@ -187,6 +188,7 @@ struct fuse_flock
|
||||
fsp_fuse_daemonize, \
|
||||
fsp_fuse_set_signal_handlers, \
|
||||
0/*conv_to_win_path*/, \
|
||||
{ 0 }, \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -229,6 +231,7 @@ struct fuse_flock
|
||||
fsp_fuse_daemonize, \
|
||||
fsp_fuse_set_signal_handlers, \
|
||||
fsp_fuse_conv_to_win_path, \
|
||||
{ 0 }, \
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -18,3 +18,11 @@ cygport:
|
||||
> opt/cygfuse/winfsp-work.tar.gz\
|
||||
)
|
||||
CYGPORT_SRC_URI=winfsp-work.tar.gz CYGPORT_SRC_DIR=winfsp-work cygport fuse.cygport download prep compile install package
|
||||
|
||||
dist: cygport
|
||||
case $(shell uname -m) in \
|
||||
x86_64)\
|
||||
cp fuse-*/dist/fuse/fuse-*[0-9].tar.xz dist/x64 ;;\
|
||||
*)\
|
||||
cp fuse-*/dist/fuse/fuse-*[0-9].tar.xz dist/x86 ;;\
|
||||
esac
|
||||
|
@ -17,22 +17,39 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/cygwin.h>
|
||||
|
||||
static void *cygfuse_init_slow(int force);
|
||||
static void *cygfuse_init_winfsp();
|
||||
static void *cygfuse_init_fail();
|
||||
|
||||
static pthread_mutex_t cygfuse_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void *cygfuse_handle = 0;
|
||||
|
||||
static inline void cygfuse_init(int force)
|
||||
static inline void *cygfuse_init_fast(void)
|
||||
{
|
||||
void *handle = cygfuse_handle;
|
||||
__sync_synchronize(); /* memory barrier */
|
||||
if (0 == handle)
|
||||
handle = cygfuse_init_slow(0);
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void *cygfuse_init_slow(int force)
|
||||
{
|
||||
void *handle;
|
||||
pthread_mutex_lock(&cygfuse_mutex);
|
||||
if (force || 0 == cygfuse_handle)
|
||||
cygfuse_handle = cygfuse_init_winfsp();
|
||||
handle = cygfuse_handle;
|
||||
if (force || 0 == handle)
|
||||
{
|
||||
handle = cygfuse_init_winfsp();
|
||||
__sync_synchronize(); /* memory barrier */
|
||||
cygfuse_handle = handle;
|
||||
}
|
||||
pthread_mutex_unlock(&cygfuse_mutex);
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -50,7 +67,7 @@ static inline int cygfuse_daemon(int nochdir, int noclose)
|
||||
return -1;
|
||||
|
||||
/* force reload of WinFsp DLL to workaround fork() problems */
|
||||
cygfuse_init(1);
|
||||
cygfuse_init_slow(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -58,7 +75,7 @@ static inline int cygfuse_daemon(int nochdir, int noclose)
|
||||
|
||||
#define FSP_FUSE_API static
|
||||
#define FSP_FUSE_API_NAME(api) (* pfn_ ## api)
|
||||
#define FSP_FUSE_API_CALL(api) (cygfuse_init(0), pfn_ ## api)
|
||||
#define FSP_FUSE_API_CALL(api) (cygfuse_init_fast(), pfn_ ## api)
|
||||
#define FSP_FUSE_SYM(proto, ...) __attribute__ ((visibility("default"))) proto { __VA_ARGS__ }
|
||||
#include <fuse_common.h>
|
||||
#include <fuse.h>
|
||||
@ -74,6 +91,7 @@ static inline int cygfuse_daemon(int nochdir, int noclose)
|
||||
if (0 == (*(void **)&(pfn_ ## n) = dlsym(h, #n)))\
|
||||
return cygfuse_init_fail();
|
||||
|
||||
static void *cygfuse_init_fail();
|
||||
static void *cygfuse_init_winfsp()
|
||||
{
|
||||
void *h;
|
||||
@ -125,6 +143,7 @@ static void *cygfuse_init_winfsp()
|
||||
CYGFUSE_GET_API(h, fsp_fuse_loop);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_loop_mt);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_exit);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_exited);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_get_context);
|
||||
|
||||
/* fuse_opt.h */
|
||||
@ -141,6 +160,7 @@ static void *cygfuse_init_winfsp()
|
||||
|
||||
static void *cygfuse_init_fail()
|
||||
{
|
||||
abort();
|
||||
fprintf(stderr, "cygfuse: initialization failed: " CYGFUSE_WINFSP_NAME " not found\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
|
BIN
opt/cygfuse/dist/fuse-2.8-4.tar.xz
vendored
BIN
opt/cygfuse/dist/fuse-2.8-4.tar.xz
vendored
Binary file not shown.
9
opt/cygfuse/dist/install.sh
vendored
9
opt/cygfuse/dist/install.sh
vendored
@ -1 +1,8 @@
|
||||
tar -C/ -xaf fuse-2.8-*.tar.xz
|
||||
cd "$(dirname "$0")"
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
tar -C/ -xaf x64/fuse-2.8-*.tar.xz ;;
|
||||
*)
|
||||
tar -C/ -xaf x86/fuse-2.8-*.tar.xz ;;
|
||||
esac
|
||||
echo FUSE for Cygwin installed.
|
||||
|
9
opt/cygfuse/dist/uninstall.sh
vendored
9
opt/cygfuse/dist/uninstall.sh
vendored
@ -1 +1,8 @@
|
||||
tar -taf fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
||||
cd "$(dirname "$0")"
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
tar -taf x64/fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;;
|
||||
*)
|
||||
tar -taf x86/fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;;
|
||||
esac
|
||||
echo FUSE for Cygwin uninstalled.
|
||||
|
BIN
opt/cygfuse/dist/x64/fuse-2.8-5.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x64/fuse-2.8-5.tar.xz
vendored
Normal file
Binary file not shown.
BIN
opt/cygfuse/dist/x86/fuse-2.8-5.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x86/fuse-2.8-5.tar.xz
vendored
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
NAME="fuse"
|
||||
VERSION=2.8
|
||||
RELEASE=4
|
||||
RELEASE=5
|
||||
CATEGORY="Utils"
|
||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||
|
@ -96,8 +96,11 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||
FUSE_OPT_KEY("UNC=", 'U'),
|
||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||
FUSE_OPT_KEY("VolumePrefix=", 'U'),
|
||||
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
||||
FUSE_OPT_KEY("FileSystemName=", 'F'),
|
||||
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
||||
|
||||
FUSE_OPT_END,
|
||||
@ -457,17 +460,27 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
default:
|
||||
return 1;
|
||||
case 'h':
|
||||
/* Note: The limit on FspServiceLog messages is 1024 bytes. This is getting close. */
|
||||
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"
|
||||
" -o VolumeCreationTime=T volume creation time (FILETIME hex format)\n"
|
||||
" -o VolumeSerialNumber=N 32-bit wide\n"
|
||||
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
||||
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
||||
" --FileSystemName=FSN Name of user mode file system\n");
|
||||
" -o umask=MASK set file permissions (octal)\n"
|
||||
" -o uid=N set file owner (-1 for mounting user id)\n"
|
||||
" -o gid=N set file group (-1 for mounting user group)\n"
|
||||
" -o rellinks interpret absolute symlinks as volume relative\n"
|
||||
" -o volname=NAME set volume label\n"
|
||||
" -o VolumePrefix=UNC set UNC prefix (/Server/Share)\n"
|
||||
" --VolumePrefix=UNC set UNC prefix (\\Server\\Share)\n"
|
||||
" -o FileSystemName=NAME set file system name\n"
|
||||
" -o DebugLog=FILE debug log file (requires -d)\n"
|
||||
"\n"
|
||||
FSP_FUSE_LIBRARY_NAME " advanced options:\n"
|
||||
" -o FileInfoTimeout=N metadata timeout (millis, -1 for data caching)\n"
|
||||
" -o SectorSize=N (512-4096, deflt: 4096)\n"
|
||||
" -o SectorsPerAllocationUnit=N (deflt: 1)\n"
|
||||
" -o MaxComponentLength=N (deflt: 255)\n"
|
||||
" -o VolumeCreationTime=T (FILETIME hex format)\n"
|
||||
" -o VolumeSerialNumber=N (32-bit wide)\n"
|
||||
);
|
||||
opt_data->help = 1;
|
||||
return 1;
|
||||
case 'V':
|
||||
@ -488,8 +501,12 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
0);
|
||||
return 0;
|
||||
case 'U':
|
||||
if ('U' == arg[2])
|
||||
if ('U' == arg[0])
|
||||
arg += sizeof "UNC=" - 1;
|
||||
else if ('U' == arg[2])
|
||||
arg += sizeof "--UNC=" - 1;
|
||||
else if ('V' == arg[0])
|
||||
arg += sizeof "VolumePrefix=" - 1;
|
||||
else if ('V' == arg[2])
|
||||
arg += sizeof "--VolumePrefix=" - 1;
|
||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||
@ -497,10 +514,15 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
return -1;
|
||||
opt_data->VolumeParams.Prefix
|
||||
[sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
|
||||
for (PWSTR P = opt_data->VolumeParams.Prefix; *P; P++)
|
||||
if (L'/' == *P)
|
||||
*P = '\\';
|
||||
return 0;
|
||||
case 'F':
|
||||
if ('f' == arg[0])
|
||||
arg += sizeof "fstypename=" - 1;
|
||||
else if ('F' == arg[0])
|
||||
arg += sizeof "FileSystemName=" - 1;
|
||||
else if ('F' == arg[2])
|
||||
arg += sizeof "--FileSystemName=" - 1;
|
||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||
@ -687,6 +709,13 @@ FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env,
|
||||
{
|
||||
if (0 != f->Service)
|
||||
FspServiceStop(f->Service);
|
||||
f->exited = 1;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
return f->exited;
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env)
|
||||
|
@ -50,6 +50,7 @@ struct fuse
|
||||
PWSTR MountPoint;
|
||||
FSP_FILE_SYSTEM *FileSystem;
|
||||
FSP_SERVICE *Service; /* weak */
|
||||
volatile int exited;
|
||||
};
|
||||
|
||||
struct fsp_fuse_context_header
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dotnet/FileSystemBase+Const.cs
|
||||
/*
|
||||
* dotnet/FileSystemBase+Const.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dotnet/FileSystemBase.cs
|
||||
/*
|
||||
* dotnet/FileSystemBase.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -24,6 +24,9 @@ using Fsp.Interop;
|
||||
namespace Fsp
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides the base class that user mode file systems must inherit from.
|
||||
/// </summary>
|
||||
public partial class FileSystemBase
|
||||
{
|
||||
/* types */
|
||||
@ -48,27 +51,73 @@ namespace Fsp
|
||||
}
|
||||
|
||||
/* operations */
|
||||
/// <summary>
|
||||
/// Provides a means to customize the returned status code when an exception happens.
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 ExceptionHandler(Exception ex)
|
||||
{
|
||||
Api.FspDebugLog("%s\n", ex.ToString());
|
||||
return STATUS_UNEXPECTED_IO_ERROR;
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs just before the file system is mounted.
|
||||
/// File systems may override this method to configure the file system host.
|
||||
/// </summary>
|
||||
/// <param name="Host">
|
||||
/// The file system host that is mounting this file system.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Init(Object Host)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs just after the file system is mounted,
|
||||
/// but prior to receiving any file system operation.
|
||||
/// </summary>
|
||||
/// <param name="Host">
|
||||
/// The file system host that is mounting this file system.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Mounted(Object Host)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs just after the file system is unmounted.
|
||||
/// No other file system operations will be received on this file system.
|
||||
/// </summary>
|
||||
/// <param name="Host">
|
||||
/// The file system host that is mounting this file system.
|
||||
/// </param>
|
||||
public virtual void Unmounted(Object Host)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the volume information.
|
||||
/// </summary>
|
||||
/// <param name="VolumeInfo">
|
||||
/// Receives the volume information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 GetVolumeInfo(
|
||||
out VolumeInfo VolumeInfo)
|
||||
{
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the volume label.
|
||||
/// </summary>
|
||||
/// <param name="VolumeLabel">
|
||||
/// The new label for the volume.
|
||||
/// </param>
|
||||
/// <param name="VolumeInfo">
|
||||
/// Receives the updated volume information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 SetVolumeLabel(
|
||||
String VolumeLabel,
|
||||
out VolumeInfo VolumeInfo)
|
||||
@ -76,6 +125,27 @@ namespace Fsp
|
||||
VolumeInfo = default(VolumeInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets file or directory attributes and security descriptor given a file name.
|
||||
/// </summary>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory to get the attributes and security descriptor for.
|
||||
/// </param>
|
||||
/// <param name="FileAttributes">
|
||||
/// Receives the file attributes on successful return.
|
||||
/// If this call returns STATUS_REPARSE, the file system may place here the index of the
|
||||
/// first reparse point within FileName.
|
||||
/// </param>
|
||||
/// <param name="SecurityDescriptor">
|
||||
/// Receives the file security descriptor. If the SecurityDescriptor parameter is null
|
||||
/// on input the file system should not fill this value.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// STATUS_SUCCESS, STATUS_REPARSE or error code.
|
||||
/// STATUS_REPARSE should be returned by file systems that support reparse points when
|
||||
/// they encounter a FileName that contains reparse points anywhere but the final path
|
||||
/// component.
|
||||
/// </returns>
|
||||
public virtual Int32 GetSecurityByName(
|
||||
String FileName,
|
||||
out UInt32 FileAttributes/* or ReparsePointIndex */,
|
||||
@ -84,6 +154,40 @@ namespace Fsp
|
||||
FileAttributes = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a new file or directory.
|
||||
/// </summary>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory to be created.
|
||||
/// </param>
|
||||
/// <param name="CreateOptions">
|
||||
/// Create options for this request.
|
||||
/// </param>
|
||||
/// <param name="GrantedAccess">
|
||||
/// Determines the specific access rights that have been granted for this request.
|
||||
/// </param>
|
||||
/// <param name="FileAttributes">
|
||||
/// File attributes to apply to the newly created file or directory.
|
||||
/// </param>
|
||||
/// <param name="SecurityDescriptor">
|
||||
/// Security descriptor to apply to the newly created file or directory.
|
||||
/// </param>
|
||||
/// <param name="AllocationSize">
|
||||
/// Allocation size for the newly created file.
|
||||
/// </param>
|
||||
/// <param name="FileNode">
|
||||
/// Receives the file node for the newly created file.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// Receives the file descriptor for the newly created file.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the file information for the newly created file.
|
||||
/// </param>
|
||||
/// <param name="NormalizedName">
|
||||
/// Receives the normalized name for the newly created file.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Create(
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
@ -102,6 +206,31 @@ namespace Fsp
|
||||
NormalizedName = default(String);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Opens a file or directory.
|
||||
/// </summary>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory to be opened.
|
||||
/// </param>
|
||||
/// <param name="CreateOptions">
|
||||
/// Create options for this request.
|
||||
/// </param>
|
||||
/// <param name="GrantedAccess">
|
||||
/// Determines the specific access rights that have been granted for this request.
|
||||
/// </param>
|
||||
/// <param name="FileNode">
|
||||
/// Receives the file node for the newly opened file.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// Receives the file descriptor for the newly opened file.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the file information for the newly opened file.
|
||||
/// </param>
|
||||
/// <param name="NormalizedName">
|
||||
/// Receives the normalized name for the newly opened file.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Open(
|
||||
String FileName,
|
||||
UInt32 CreateOptions,
|
||||
@ -117,6 +246,29 @@ namespace Fsp
|
||||
NormalizedName = default(String);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Overwrites a file.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node for the file to be overwritten.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor for the file to be overwritten.
|
||||
/// </param>
|
||||
/// <param name="FileAttributes">
|
||||
/// File attributes to apply to the overwritten file.
|
||||
/// </param>
|
||||
/// <param name="ReplaceFileAttributes">
|
||||
/// When true the existing file attributes should be replaced with the new ones.
|
||||
/// When false the existing file attributes should be merged (or'ed) with the new ones.
|
||||
/// </param>
|
||||
/// <param name="AllocationSize">
|
||||
/// Allocation size for the overwritten file.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the updated file information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Overwrite(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -128,6 +280,64 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Cleans up a file or directory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// When CreateFile is used to open or create a file the kernel creates a kernel mode file
|
||||
/// object (type FILE_OBJECT) and a handle for it, which it returns to user-mode. The handle may
|
||||
/// be duplicated (using DuplicateHandle), but all duplicate handles always refer to the same
|
||||
/// file object. When all handles for a particular file object get closed (using CloseHandle)
|
||||
/// the system sends a Cleanup request to the file system.
|
||||
/// </para><para>
|
||||
/// There will be a Cleanup operation for every Create or Open operation posted to the user mode
|
||||
/// file system. However the Cleanup operation is not the final close operation on a file.
|
||||
/// The file system must be ready to receive additional operations until close time. This is true
|
||||
/// even when the file is being deleted!
|
||||
/// </para><para>
|
||||
/// The Flags parameter contains information about the cleanup operation:
|
||||
/// <list>
|
||||
/// <item>CleanupDelete -
|
||||
/// An important function of the Cleanup operation is to complete a delete operation. Deleting
|
||||
/// a file or directory in Windows is a three-stage process where the file is first opened, then
|
||||
/// tested to see if the delete can proceed and if the answer is positive the file is then
|
||||
/// deleted during Cleanup.
|
||||
/// When this flag is set, this is the last outstanding cleanup for this particular file node.
|
||||
/// </item>
|
||||
/// <item>CleanupSetAllocationSize -
|
||||
/// The NTFS and FAT file systems reset a file's allocation size when they receive the last
|
||||
/// outstanding cleanup for a particular file node. User mode file systems that implement
|
||||
/// allocation size and wish to duplicate the NTFS and FAT behavior can use this flag.
|
||||
/// </item>
|
||||
/// <item>CleanupSetArchiveBit -
|
||||
/// File systems that support the archive bit should set the file node's archive bit when this
|
||||
/// flag is set.
|
||||
/// </item>
|
||||
/// <item>CleanupSetLastAccessTime, CleanupSetLastWriteTime, CleanupSetChangeTime -
|
||||
/// File systems should set the corresponding file time when each one of these flags is set.
|
||||
/// Note that updating the last access time is expensive and a file system may choose to not
|
||||
/// implement it.
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para><para>
|
||||
/// There is no way to report failure of this operation. This is a Windows limitation.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to cleanup.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to cleanup.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory to cleanup. Sent only when a Delete is requested.
|
||||
/// </param>
|
||||
/// <param name="Flags">
|
||||
/// These flags determine whether the file was modified and whether to delete the file.
|
||||
/// </param>
|
||||
/// <seealso cref="CanDelete"/>
|
||||
/// <seealso cref="Close"/>
|
||||
public virtual void Cleanup(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -135,11 +345,42 @@ namespace Fsp
|
||||
UInt32 Flags)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Closes a file or directory.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to close.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to close.
|
||||
/// </param>
|
||||
public virtual void Close(
|
||||
Object FileNode,
|
||||
Object FileDesc)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Reads a file.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file to read.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file to read.
|
||||
/// </param>
|
||||
/// <param name="Buffer">
|
||||
/// Pointer to a buffer that receives the results of the read operation.
|
||||
/// </param>
|
||||
/// <param name="Offset">
|
||||
/// Offset within the file to read from.
|
||||
/// </param>
|
||||
/// <param name="Length">
|
||||
/// Length of data to read.
|
||||
/// </param>
|
||||
/// <param name="BytesTransferred">
|
||||
/// Receives the actual number of bytes read.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Read(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -151,6 +392,38 @@ namespace Fsp
|
||||
BytesTransferred = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes a file.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file to write.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file to write.
|
||||
/// </param>
|
||||
/// <param name="Buffer">
|
||||
/// Pointer to a buffer that receives the results of the write operation.
|
||||
/// </param>
|
||||
/// <param name="Offset">
|
||||
/// Offset within the file to write to.
|
||||
/// </param>
|
||||
/// <param name="Length">
|
||||
/// Length of data to write.
|
||||
/// </param>
|
||||
/// <param name="WriteToEndOfFile">
|
||||
/// When true the file system must write to the current end of file. In this case the Offset
|
||||
/// parameter will contain the value -1.
|
||||
/// </param>
|
||||
/// <param name="ConstrainedIo">
|
||||
/// When true the file system must not extend the file (i.e. change the file size).
|
||||
/// </param>
|
||||
/// <param name="BytesTransferred">
|
||||
/// Receives the actual number of bytes written.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the updated file information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Write(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -166,6 +439,24 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Flushes a file or volume.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that the FSD will also flush all file/volume caches prior to invoking this operation.
|
||||
/// </remarks>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file to flush.
|
||||
/// When this and the FileDesc parameter are null the whole volume is being flushed.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file to flush.
|
||||
/// When this and the FileNode parameter are null the whole volume is being flushed.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the updated file information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Flush(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -174,6 +465,19 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets file or directory information.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file to get information for.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file to get information for.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the file information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 GetFileInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -182,6 +486,39 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets file or directory basic information.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file to set information for.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file to set information for.
|
||||
/// </param>
|
||||
/// <param name="FileAttributes">
|
||||
/// File attributes to apply to the file or directory.
|
||||
/// If the value -1 is sent, the file attributes should not be changed.
|
||||
/// </param>
|
||||
/// <param name="CreationTime">
|
||||
/// Creation time to apply to the file or directory.
|
||||
/// If the value 0 is sent, the creation time should not be changed.
|
||||
/// </param>
|
||||
/// <param name="LastAccessTime">
|
||||
/// Last access time to apply to the file or directory.
|
||||
/// If the value 0 is sent, the last access time should not be changed.
|
||||
/// </param>
|
||||
/// <param name="LastWriteTime">
|
||||
/// Last write time to apply to the file or directory.
|
||||
/// If the value 0 is sent, the last write time should not be changed.
|
||||
/// </param>
|
||||
/// <param name="ChangeTime">
|
||||
/// Change time to apply to the file or directory.
|
||||
/// If the value 0 is sent, the change time should not be changed.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the updated file information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 SetBasicInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -195,6 +532,52 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets file/allocation size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This function is used to change a file's sizes. Windows file systems maintain two kinds
|
||||
/// of sizes: the file size is where the End Of File (EOF) is, and the allocation size is the
|
||||
/// actual size that a file takes up on the "disk".
|
||||
/// </para><para>
|
||||
/// The rules regarding file/allocation size are:
|
||||
/// <list>
|
||||
/// <item>
|
||||
/// Allocation size must always be aligned to the allocation unit boundary. The allocation
|
||||
/// unit is the product SectorSize * SectorsPerAllocationUnit. The FSD will always send
|
||||
/// properly aligned allocation sizes when setting the allocation size.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Allocation size is always greater or equal to the file size.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// A file size of more than the current allocation size will also extend the allocation
|
||||
/// size to the next allocation unit boundary.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// An allocation size of less than the current file size should also truncate the current
|
||||
/// file size.
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file to set the file/allocation size for.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file to set the file/allocation size for.
|
||||
/// </param>
|
||||
/// <param name="NewSize">
|
||||
/// New file/allocation size to apply to the file.
|
||||
/// </param>
|
||||
/// <param name="SetAllocationSize">
|
||||
/// If true, then the allocation size is being set. if false, then the file size is being set.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the updated file information.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 SetFileSize(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -205,6 +588,20 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether a file or directory can be deleted.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to test for deletion.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to test for deletion.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory to test for deletion.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
/// <seealso cref="Cleanup"/>
|
||||
public virtual Int32 CanDelete(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -212,6 +609,37 @@ namespace Fsp
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Renames a file or directory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The kernel mode FSD provides certain guarantees prior to posting a rename operation:
|
||||
/// <list>
|
||||
/// <item>
|
||||
/// A file cannot be renamed if a file with the same name exists and has open handles.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// A directory cannot be renamed if it or any of its subdirectories contains a file that
|
||||
/// has open handles.
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to be renamed.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to be renamed.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The current name of the file or directory to rename.
|
||||
/// </param>
|
||||
/// <param name="NewFileName">
|
||||
/// The new name for the file or directory.
|
||||
/// </param>
|
||||
/// <param name="ReplaceIfExists">
|
||||
/// Whether to replace a file that already exists at NewFileName.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Rename(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -221,6 +649,19 @@ namespace Fsp
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets file or directory security descriptor.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to get the security descriptor for.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to get the security descriptor for.
|
||||
/// </param>
|
||||
/// <param name="SecurityDescriptor">
|
||||
/// Receives the file security descriptor.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 GetSecurity(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -228,6 +669,23 @@ namespace Fsp
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets file or directory security descriptor.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to set the security descriptor for.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to set the security descriptor for.
|
||||
/// </param>
|
||||
/// <param name="Sections">
|
||||
/// Describes what parts of the file or directory security descriptor should be modified.
|
||||
/// </param>
|
||||
/// <param name="SecurityDescriptor">
|
||||
/// Describes the modifications to apply to the file or directory security descriptor.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
/// <seealso cref="ModifySecurityDescriptor"/>
|
||||
public virtual Int32 SetSecurity(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -236,6 +694,10 @@ namespace Fsp
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Reads a directory.
|
||||
/// </summary>
|
||||
/// <seealso cref="ReadDirectoryEntry"/>
|
||||
public virtual Int32 ReadDirectory(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -248,6 +710,36 @@ namespace Fsp
|
||||
return SeekableReadDirectory(FileNode, FileDesc, Pattern, Marker, Buffer, Length,
|
||||
out BytesTransferred);
|
||||
}
|
||||
/// <summary>
|
||||
/// Reads a directory entry.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the directory to be read.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the directory to be read.
|
||||
/// </param>
|
||||
/// <param name="Pattern">
|
||||
/// The pattern to match against files in this directory. Can be null. The file system
|
||||
/// can choose to ignore this parameter as the FSD will always perform its own pattern
|
||||
/// matching on the returned results.
|
||||
/// </param>
|
||||
/// <param name="Marker">
|
||||
/// A file name that marks where in the directory to start reading. Files with names
|
||||
/// that are greater than (not equal to) this marker (in the directory order determined
|
||||
/// by the file system) should be returned. Can be null.
|
||||
/// </param>
|
||||
/// <param name="Context">
|
||||
/// Can be used by the file system to track the ReadDirectory operation.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// Receives the file name for the directory entry.
|
||||
/// </param>
|
||||
/// <param name="FileInfo">
|
||||
/// Receives the file information for the directory entry.
|
||||
/// </param>
|
||||
/// <returns>True if there are additional directory entries to return. False otherwise.</returns>
|
||||
/// <seealso cref="ReadDirectory"/>
|
||||
public virtual Boolean ReadDirectoryEntry(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -261,13 +753,16 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Resolves reparse points.
|
||||
/// </summary>
|
||||
public virtual Int32 ResolveReparsePoints(
|
||||
String FileName,
|
||||
UInt32 ReparsePointIndex,
|
||||
Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock IoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr Size)
|
||||
IntPtr PSize)
|
||||
{
|
||||
GCHandle Handle = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||
try
|
||||
@ -281,49 +776,108 @@ namespace Fsp
|
||||
ResolveLastPathComponent,
|
||||
out IoStatus,
|
||||
Buffer,
|
||||
ref Size);
|
||||
PSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Handle.Free();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a reparse point given a file name.
|
||||
/// </summary>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory to get the reparse point for.
|
||||
/// </param>
|
||||
/// <param name="IsDirectory">
|
||||
/// Determines whether the passed file name is assumed to be a directory.
|
||||
/// </param>
|
||||
/// <param name="ReparseData">
|
||||
/// Receives the reparse data for the file or directory.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 GetReparsePointByName(
|
||||
String FileName,
|
||||
Boolean IsDirectory,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr Size)
|
||||
ref Byte[] ReparseData)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a reparse point.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The file name of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="ReparseData">
|
||||
/// Receives the reparse data for the reparse point.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 GetReparsePoint(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
out UIntPtr Size)
|
||||
ref Byte[] ReparseData)
|
||||
{
|
||||
Size = default(UIntPtr);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets a reparse point.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The file name of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="ReparseData">
|
||||
/// The new reparse data for the reparse point.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 SetReparsePoint(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
Byte[] ReparseData)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Deletes a reparse point.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The file name of the reparse point.
|
||||
/// </param>
|
||||
/// <param name="ReparseData">
|
||||
/// The reparse data for the reparse point.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 DeleteReparsePoint(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
Byte[] ReparseData)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets named streams information.
|
||||
/// </summary>
|
||||
public virtual Int32 GetStreamInfo(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -331,19 +885,108 @@ namespace Fsp
|
||||
UInt32 Length,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
Object Context = null;
|
||||
String StreamName;
|
||||
StreamInfo StreamInfo = default(StreamInfo);
|
||||
BytesTransferred = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
while (GetStreamEntry(FileNode, FileDesc, ref Context,
|
||||
out StreamName, out StreamInfo.StreamSize, out StreamInfo.StreamAllocationSize))
|
||||
{
|
||||
StreamInfo.SetStreamNameBuf(StreamName);
|
||||
if (!Api.FspFileSystemAddStreamInfo(ref StreamInfo, Buffer, Length,
|
||||
out BytesTransferred))
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
Api.FspFileSystemEndStreamInfo(Buffer, Length, out BytesTransferred);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets named streams information entry.
|
||||
/// </summary>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to get stream information for.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to get stream information for.
|
||||
/// </param>
|
||||
/// <param name="Context">
|
||||
/// Can be used by the file system to track the GetStreamInfo operation.
|
||||
/// </param>
|
||||
/// <param name="StreamName">
|
||||
/// Receives the stream name for the stream entry.
|
||||
/// </param>
|
||||
/// <param name="StreamSize">
|
||||
/// Receives the stream size for the stream entry.
|
||||
/// </param>
|
||||
/// <param name="StreamAllocationSize">
|
||||
/// Receives the stream allocation size for the stream entry.
|
||||
/// </param>
|
||||
/// <returns>True if there are additional stream entries to return. False otherwise.</returns>
|
||||
public virtual Boolean GetStreamEntry(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
ref Object Context,
|
||||
out String StreamName,
|
||||
out UInt64 StreamSize,
|
||||
out UInt64 StreamAllocationSize)
|
||||
{
|
||||
StreamName = default(String);
|
||||
StreamSize = default(UInt64);
|
||||
StreamAllocationSize = default(UInt64);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* helpers */
|
||||
/// <summary>
|
||||
/// Converts a Win32 error code to a Windows kernel status code.
|
||||
/// </summary>
|
||||
public static Int32 NtStatusFromWin32(UInt32 Error)
|
||||
{
|
||||
return Api.FspNtStatusFromWin32(Error);
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts a Windows kernel status code to a Win32 error code.
|
||||
/// </summary>
|
||||
public static UInt32 Win32FromNtStatus(Int32 Status)
|
||||
{
|
||||
return Api.FspWin32FromNtStatus(Status);
|
||||
}
|
||||
/// <summary>
|
||||
/// Modifies a security descriptor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a helper for implementing the SetSecurity operation.
|
||||
/// </remarks>
|
||||
/// <param name="SecurityDescriptor">
|
||||
/// The original security descriptor.
|
||||
/// </param>
|
||||
/// <param name="Sections">
|
||||
/// Describes what parts of the file or directory security descriptor should be modified.
|
||||
/// </param>
|
||||
/// <param name="ModificationDescriptor">
|
||||
/// Describes the modifications to apply to the file or directory security descriptor.
|
||||
/// </param>
|
||||
/// <returns>The modified security descriptor.</returns>
|
||||
/// <seealso cref="SetSecurity"/>
|
||||
public static byte[] ModifySecurityDescriptor(
|
||||
Byte[] SecurityDescriptor,
|
||||
AccessControlSections Sections,
|
||||
Byte[] ModificationDescriptor)
|
||||
{
|
||||
UInt32 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*/;
|
||||
return Api.ModifySecurityDescriptor(
|
||||
SecurityDescriptor,
|
||||
SecurityInformation,
|
||||
ModificationDescriptor);
|
||||
}
|
||||
public Int32 SeekableReadDirectory(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -363,8 +1006,9 @@ namespace Fsp
|
||||
DirInfo.SetFileNameBuf(FileName);
|
||||
if (!Api.FspFileSystemAddDirInfo(ref DirInfo, Buffer, Length,
|
||||
out BytesTransferred))
|
||||
break;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
Api.FspFileSystemEndDirInfo(Buffer, Length, out BytesTransferred);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public Int32 BufferedReadDirectory(
|
||||
@ -408,7 +1052,22 @@ namespace Fsp
|
||||
Marker, Buffer, Length, out BytesTransferred);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public Int32 FindReparsePoint(
|
||||
/// <summary>
|
||||
/// Finds a reparse point in file name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a helper for implementing the GetSecurityByName operation in file systems
|
||||
/// that support reparse points.
|
||||
/// </remarks>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory.
|
||||
/// </param>
|
||||
/// <param name="ReparsePointIndex">
|
||||
/// Receives the index of the first reparse point within FileName.
|
||||
/// </param>
|
||||
/// <returns>True if a reparse point was found, false otherwise.</returns>
|
||||
/// <seealso cref="GetSecurityByName"/>
|
||||
public Boolean FindReparsePoint(
|
||||
String FileName,
|
||||
out UInt32 ReparsePointIndex)
|
||||
{
|
||||
@ -427,22 +1086,62 @@ namespace Fsp
|
||||
Handle.Free();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the reparse tag from reparse data.
|
||||
/// </summary>
|
||||
/// <param name="ReparseData">
|
||||
/// The reparse data to extract the reparse tag from.
|
||||
/// </param>
|
||||
/// <returns>The reparse tag.</returns>
|
||||
public static UInt32 GetReparseTag(
|
||||
Byte[] ReparseData)
|
||||
{
|
||||
return BitConverter.ToUInt32(ReparseData, 0);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether reparse data can be replaced.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a helper for implementing the SetReparsePoint/DeleteReparsePoint operation
|
||||
/// in file systems that support reparse points.
|
||||
/// </remarks>
|
||||
/// <param name="CurrentReparseData">
|
||||
/// The current reparse data.
|
||||
/// </param>
|
||||
/// <param name="ReplaceReparseData">
|
||||
/// The replacement reparse data.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
/// <seealso cref="SetReparsePoint"/>
|
||||
/// <seealso cref="DeleteReparsePoint"/>
|
||||
public static Int32 CanReplaceReparsePoint(
|
||||
Byte[] CurrentReparseData,
|
||||
Byte[] ReplaceReparseData)
|
||||
{
|
||||
return Api.FspFileSystemCanReplaceReparsePoint(CurrentReparseData, ReplaceReparseData);
|
||||
}
|
||||
private static Int32 GetReparsePointByName(
|
||||
IntPtr FileSystem,
|
||||
IntPtr Context,
|
||||
String FileName,
|
||||
Boolean IsDirectory,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr Size)
|
||||
IntPtr PSize)
|
||||
{
|
||||
FileSystemBase self = (FileSystemBase)GCHandle.FromIntPtr(Context).Target;
|
||||
try
|
||||
{
|
||||
return self.GetReparsePointByName(
|
||||
Byte[] ReparseData;
|
||||
Int32 Result;
|
||||
ReparseData = null;
|
||||
Result = self.GetReparsePointByName(
|
||||
FileName,
|
||||
IsDirectory,
|
||||
Buffer,
|
||||
ref Size);
|
||||
ref ReparseData);
|
||||
if (0 <= Result)
|
||||
Result = Api.CopyReparsePoint(ReparseData, Buffer, PSize);
|
||||
return Result;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dotnet/FileSystemHost.cs
|
||||
/*
|
||||
* dotnet/FileSystemHost.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -24,9 +24,16 @@ using Fsp.Interop;
|
||||
namespace Fsp
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides a means to host (mount) a file system.
|
||||
/// </summary>
|
||||
public class FileSystemHost : IDisposable
|
||||
{
|
||||
/* ctor/dtor */
|
||||
/// <summary>
|
||||
/// Creates an instance of the FileSystemHost class.
|
||||
/// </summary>
|
||||
/// <param name="FileSystem">The file system to host.</param>
|
||||
public FileSystemHost(FileSystemBase FileSystem)
|
||||
{
|
||||
_VolumeParams.Flags = VolumeParams.UmFileContextIsFullContext;
|
||||
@ -36,6 +43,9 @@ namespace Fsp
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
/// <summary>
|
||||
/// Unmounts the file system and releases all associated resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
@ -56,73 +66,114 @@ namespace Fsp
|
||||
{
|
||||
ExceptionHandler(_FileSystem, ex);
|
||||
}
|
||||
Api.SetUserContext(_FileSystemPtr, null);
|
||||
Api.DisposeUserContext(_FileSystemPtr);
|
||||
Api.FspFileSystemDelete(_FileSystemPtr);
|
||||
_FileSystemPtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/* properties */
|
||||
/// <summary>
|
||||
/// Gets or sets the sector size used by the file system.
|
||||
/// </summary>
|
||||
public UInt16 SectorSize
|
||||
{
|
||||
get { return _VolumeParams.SectorSize; }
|
||||
set { _VolumeParams.SectorSize = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the sectors per allocation unit used by the file system.
|
||||
/// </summary>
|
||||
public UInt16 SectorsPerAllocationUnit
|
||||
{
|
||||
get { return _VolumeParams.SectorsPerAllocationUnit; }
|
||||
set { _VolumeParams.SectorsPerAllocationUnit = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum path component length used by the file system.
|
||||
/// </summary>
|
||||
public UInt16 MaxComponentLength
|
||||
{
|
||||
get { return _VolumeParams.MaxComponentLength; }
|
||||
set { _VolumeParams.MaxComponentLength = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the volume creation time.
|
||||
/// </summary>
|
||||
public UInt64 VolumeCreationTime
|
||||
{
|
||||
get { return _VolumeParams.VolumeCreationTime; }
|
||||
set { _VolumeParams.VolumeCreationTime = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the volume serial number.
|
||||
/// </summary>
|
||||
public UInt32 VolumeSerialNumber
|
||||
{
|
||||
get { return _VolumeParams.VolumeSerialNumber; }
|
||||
set { _VolumeParams.VolumeSerialNumber = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the file information timeout.
|
||||
/// </summary>
|
||||
public UInt32 FileInfoTimeout
|
||||
{
|
||||
get { return _VolumeParams.FileInfoTimeout; }
|
||||
set { _VolumeParams.FileInfoTimeout = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether the file system is case sensitive.
|
||||
/// </summary>
|
||||
public Boolean CaseSensitiveSearch
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.CaseSensitiveSearch); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.CaseSensitiveSearch : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether a case insensitive file system
|
||||
/// preserves case in file names.
|
||||
/// </summary>
|
||||
public Boolean CasePreservedNames
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.CasePreservedNames); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.CasePreservedNames : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether file names support unicode characters.
|
||||
/// </summary>
|
||||
public Boolean UnicodeOnDisk
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.UnicodeOnDisk); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.UnicodeOnDisk : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether the file system supports ACL security.
|
||||
/// </summary>
|
||||
public Boolean PersistentAcls
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PersistentAcls); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PersistentAcls : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether the file system supports reparse points.
|
||||
/// </summary>
|
||||
public Boolean ReparsePoints
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.ReparsePoints); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.ReparsePoints : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether the file system allows creation of
|
||||
/// symbolic links without additional privileges.
|
||||
/// </summary>
|
||||
public Boolean ReparsePointsAccessCheck
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.ReparsePointsAccessCheck); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.ReparsePointsAccessCheck : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines whether the file system supports named streams.
|
||||
/// </summary>
|
||||
public Boolean NamedStreams
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.NamedStreams); }
|
||||
@ -138,11 +189,17 @@ namespace Fsp
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PassQueryDirectoryPattern); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PassQueryDirectoryPattern : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the prefix for a network file system.
|
||||
/// </summary>
|
||||
public String Prefix
|
||||
{
|
||||
get { return _VolumeParams.GetPrefix(); }
|
||||
set { _VolumeParams.SetPrefix(value); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the file system name.
|
||||
/// </summary>
|
||||
public String FileSystemName
|
||||
{
|
||||
get { return _VolumeParams.GetFileSystemName(); }
|
||||
@ -150,12 +207,42 @@ namespace Fsp
|
||||
}
|
||||
|
||||
/* control */
|
||||
/// <summary>
|
||||
/// Checks whether mounting a file system is possible.
|
||||
/// </summary>
|
||||
/// <param name="MountPoint">
|
||||
/// The mount point for the new file system. A value of null means that
|
||||
/// the file system should use the next available drive letter counting
|
||||
/// downwards from Z: as its mount point.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public Int32 Preflight(String MountPoint)
|
||||
{
|
||||
return Api.FspFileSystemPreflight(
|
||||
_VolumeParams.IsPrefixEmpty() ? "WinFsp.Disk" : "WinFsp.Net",
|
||||
MountPoint);
|
||||
}
|
||||
/// <summary>
|
||||
/// Mounts a file system.
|
||||
/// </summary>
|
||||
/// <param name="MountPoint">
|
||||
/// The mount point for the new file system. A value of null means that
|
||||
/// the file system should use the next available drive letter counting
|
||||
/// downwards from Z: as its mount point.
|
||||
/// </param>
|
||||
/// <param name="SecurityDescriptor">
|
||||
/// Security descriptor to use if mounting on (newly created) directory.
|
||||
/// A value of null means the directory should be created with default
|
||||
/// security.
|
||||
/// </param>
|
||||
/// <param name="Synchronized">
|
||||
/// If true file system operations are synchronized using an exclusive lock.
|
||||
/// </param>
|
||||
/// <param name="DebugLog">
|
||||
/// A value of 0 disables all debug logging.
|
||||
/// A value of -1 enables all debug logging.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public Int32 Mount(String MountPoint,
|
||||
Byte[] SecurityDescriptor = null,
|
||||
Boolean Synchronized = false,
|
||||
@ -210,16 +297,23 @@ namespace Fsp
|
||||
}
|
||||
if (0 > Result)
|
||||
{
|
||||
Api.SetUserContext(_FileSystemPtr, null);
|
||||
Api.DisposeUserContext(_FileSystemPtr);
|
||||
Api.FspFileSystemDelete(_FileSystemPtr);
|
||||
_FileSystemPtr = IntPtr.Zero;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Unmounts the file system and releases all associated resources.
|
||||
/// </summary>
|
||||
public void Unmount()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the file system mount point.
|
||||
/// </summary>
|
||||
/// <returns>The file system mount point.</returns>
|
||||
public String MountPoint()
|
||||
{
|
||||
return IntPtr.Zero != _FileSystemPtr ?
|
||||
@ -229,17 +323,28 @@ namespace Fsp
|
||||
{
|
||||
return _FileSystemPtr;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the hosted file system.
|
||||
/// </summary>
|
||||
/// <returns>The hosted file system.</returns>
|
||||
public FileSystemBase FileSystem()
|
||||
{
|
||||
return _FileSystem;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the debug log file to use when debug logging is enabled.
|
||||
/// </summary>
|
||||
/// <param name="FileName">
|
||||
/// The debug log file name. A value of "-" means standard error output.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public static Int32 SetDebugLogFile(String FileName)
|
||||
{
|
||||
return Api.SetDebugLogFile(FileName);
|
||||
}
|
||||
|
||||
/* FSP_FILE_SYSTEM_INTERFACE */
|
||||
private static Byte[] SecurityDescriptorNotNull = new Byte[0];
|
||||
private static Byte[] ByteBufferNotNull = new Byte[0];
|
||||
private static Int32 ExceptionHandler(
|
||||
FileSystemBase FileSystem,
|
||||
Exception ex)
|
||||
@ -301,12 +406,12 @@ namespace Fsp
|
||||
Byte[] SecurityDescriptorBytes = null;
|
||||
Int32 Result;
|
||||
if (IntPtr.Zero != PSecurityDescriptorSize)
|
||||
SecurityDescriptorBytes = SecurityDescriptorNotNull;
|
||||
SecurityDescriptorBytes = ByteBufferNotNull;
|
||||
Result = FileSystem.GetSecurityByName(
|
||||
FileName,
|
||||
out FileAttributes,
|
||||
ref SecurityDescriptorBytes);
|
||||
if (0 <= Result)
|
||||
if (0 <= Result && 260/*STATUS_REPARSE*/ != Result)
|
||||
{
|
||||
if (IntPtr.Zero != PFileAttributes)
|
||||
Marshal.WriteInt32(PFileAttributes, (Int32)FileAttributes);
|
||||
@ -457,7 +562,7 @@ namespace Fsp
|
||||
FileSystem.Close(
|
||||
FileNode,
|
||||
FileDesc);
|
||||
Api.SetFullContext(ref FullContext, null, null);
|
||||
Api.DisposeFullContext(ref FullContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -680,13 +785,15 @@ namespace Fsp
|
||||
Byte[] SecurityDescriptorBytes;
|
||||
Int32 Result;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
SecurityDescriptorBytes = SecurityDescriptorNotNull;
|
||||
SecurityDescriptorBytes = ByteBufferNotNull;
|
||||
Result = FileSystem.GetSecurity(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
ref SecurityDescriptorBytes);
|
||||
return Api.CopySecurityDescriptor(SecurityDescriptorBytes,
|
||||
SecurityDescriptor, PSecurityDescriptorSize);
|
||||
if (0 <= Result)
|
||||
Result = Api.CopySecurityDescriptor(SecurityDescriptorBytes,
|
||||
SecurityDescriptor, PSecurityDescriptorSize);
|
||||
return Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -761,7 +868,7 @@ namespace Fsp
|
||||
Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock PIoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize)
|
||||
IntPtr PSize)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
@ -772,7 +879,7 @@ namespace Fsp
|
||||
ResolveLastPathComponent,
|
||||
out PIoStatus,
|
||||
Buffer,
|
||||
ref PSize);
|
||||
PSize);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -785,23 +892,27 @@ namespace Fsp
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
IntPtr Buffer,
|
||||
out UIntPtr PSize)
|
||||
IntPtr PSize)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Byte[] ReparseData;
|
||||
Object FileNode, FileDesc;
|
||||
Int32 Result;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.GetReparsePoint(
|
||||
ReparseData = null;
|
||||
Result = FileSystem.GetReparsePoint(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Buffer,
|
||||
out PSize);
|
||||
ref ReparseData);
|
||||
if (0 <= Result)
|
||||
Result = Api.CopyReparsePoint(ReparseData, Buffer, PSize);
|
||||
return Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PSize = default(UIntPtr);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
@ -821,8 +932,7 @@ namespace Fsp
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Buffer,
|
||||
Size);
|
||||
Api.MakeReparsePoint(Buffer, Size));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -845,8 +955,7 @@ namespace Fsp
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Buffer,
|
||||
Size);
|
||||
Api.MakeReparsePoint(Buffer, Size));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -913,8 +1022,8 @@ namespace Fsp
|
||||
private static FileSystemInterface _FileSystemInterface;
|
||||
private static IntPtr _FileSystemInterfacePtr;
|
||||
private VolumeParams _VolumeParams;
|
||||
private IntPtr _FileSystemPtr;
|
||||
private FileSystemBase _FileSystem;
|
||||
private IntPtr _FileSystemPtr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dotnet/Interop.cs
|
||||
/*
|
||||
* dotnet/Interop.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -102,16 +102,28 @@ namespace Fsp.Interop
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains volume information about a file system.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct VolumeInfo
|
||||
{
|
||||
internal const int VolumeLabelSize = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Total size of volume in bytes.
|
||||
/// </summary>
|
||||
public UInt64 TotalSize;
|
||||
/// <summary>
|
||||
/// Free size of volume in bytes.
|
||||
/// </summary>
|
||||
public UInt64 FreeSize;
|
||||
internal UInt16 VolumeLabelLength;
|
||||
internal unsafe fixed UInt16 VolumeLabel[VolumeLabelSize];
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume label.
|
||||
/// </summary>
|
||||
public unsafe void SetVolumeLabel(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = VolumeLabel)
|
||||
@ -121,23 +133,59 @@ namespace Fsp.Interop
|
||||
Size = VolumeLabelSize;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
VolumeLabelLength = (UInt16)Size;
|
||||
VolumeLabelLength = (UInt16)(Size * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains metadata information about a file or directory.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct FileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The file or directory attributes.
|
||||
/// </summary>
|
||||
public UInt32 FileAttributes;
|
||||
/// <summary>
|
||||
/// The reparse tag of the file or directory.
|
||||
/// This value is 0 if the file or directory is not a reparse point.
|
||||
/// </summary>
|
||||
public UInt32 ReparseTag;
|
||||
/// <summary>
|
||||
/// The allocation size of the file.
|
||||
/// </summary>
|
||||
public UInt64 AllocationSize;
|
||||
/// <summary>
|
||||
/// The file size of the file (end of file).
|
||||
/// </summary>
|
||||
public UInt64 FileSize;
|
||||
/// <summary>
|
||||
/// The time that the file or directory was created.
|
||||
/// </summary>
|
||||
public UInt64 CreationTime;
|
||||
/// <summary>
|
||||
/// The time that the file or directory was last accessed.
|
||||
/// </summary>
|
||||
public UInt64 LastAccessTime;
|
||||
/// <summary>
|
||||
/// The time that the file or direcotry was last modified.
|
||||
/// </summary>
|
||||
public UInt64 LastWriteTime;
|
||||
/// <summary>
|
||||
/// The time that the file or directory metadata was last modified.
|
||||
/// </summary>
|
||||
public UInt64 ChangeTime;
|
||||
/// <summary>
|
||||
/// A unique identifier that is associated with the file or directory.
|
||||
/// Not all file systems support this value.
|
||||
/// </summary>
|
||||
public UInt64 IndexNumber;
|
||||
/// <summary>
|
||||
/// The number of hard links.
|
||||
/// Not currently implemented. Set to 0.
|
||||
/// </summary>
|
||||
public UInt32 HardLinks;
|
||||
}
|
||||
|
||||
@ -156,7 +204,7 @@ namespace Fsp.Interop
|
||||
Size = NormalizedNameSize;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
NormalizedNameSize = (UInt16)Size;
|
||||
NormalizedNameSize = (UInt16)(Size * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +212,8 @@ namespace Fsp.Interop
|
||||
internal struct DirInfo
|
||||
{
|
||||
internal const int FileNameBufSize = 255;
|
||||
internal static int FileNameBufOffset = (int)Marshal.OffsetOf(typeof(DirInfo), "FileNameBuf");
|
||||
internal static int FileNameBufOffset =
|
||||
(int)Marshal.OffsetOf(typeof(DirInfo), "FileNameBuf");
|
||||
|
||||
internal UInt16 Size;
|
||||
internal FileInfo FileInfo;
|
||||
@ -172,7 +221,7 @@ namespace Fsp.Interop
|
||||
//internal unsafe fixed UInt16 FileNameBuf[];
|
||||
internal unsafe fixed UInt16 FileNameBuf[FileNameBufSize];
|
||||
|
||||
public unsafe void SetFileNameBuf(String Value)
|
||||
internal unsafe void SetFileNameBuf(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = FileNameBuf)
|
||||
{
|
||||
@ -189,10 +238,28 @@ namespace Fsp.Interop
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct StreamInfo
|
||||
{
|
||||
internal const int StreamNameBufSize = 255;
|
||||
internal static int StreamNameBufOffset =
|
||||
(int)Marshal.OffsetOf(typeof(StreamInfo), "StreamNameBuf");
|
||||
|
||||
internal UInt16 Size;
|
||||
internal UInt64 StreamSize;
|
||||
internal UInt64 StreamAllocationSize;
|
||||
//internal unsafe fixed UInt16 StreamNameBuf[];
|
||||
internal unsafe fixed UInt16 StreamNameBuf[StreamNameBufSize];
|
||||
|
||||
internal unsafe void SetStreamNameBuf(String Value)
|
||||
{
|
||||
fixed (UInt16 *P = StreamNameBuf)
|
||||
{
|
||||
int Size = null != Value ? Value.Length : 0;
|
||||
if (Size > StreamNameBufSize)
|
||||
Size = StreamNameBufSize;
|
||||
for (int I = 0; Size > I; I++)
|
||||
P[I] = Value[I];
|
||||
this.Size = (UInt16)(StreamNameBufOffset + Size * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@ -354,14 +421,14 @@ namespace Fsp.Interop
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock PIoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize);
|
||||
IntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 GetReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
IntPtr Buffer,
|
||||
out UIntPtr PSize);
|
||||
IntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 SetReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
@ -471,7 +538,8 @@ namespace Fsp.Interop
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemFindReparsePoint(
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal delegate Boolean FspFileSystemFindReparsePoint(
|
||||
IntPtr FileSystem,
|
||||
GetReparsePointByName GetReparsePointByName,
|
||||
IntPtr Context,
|
||||
@ -487,7 +555,7 @@ namespace Fsp.Interop
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean ResolveLastPathComponent,
|
||||
out IoStatusBlock PIoStatus,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize);
|
||||
IntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspFileSystemCanReplaceReparsePoint(
|
||||
IntPtr CurrentReparseData,
|
||||
@ -526,6 +594,16 @@ namespace Fsp.Interop
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspFileSystemDeleteDirectoryBuffer(
|
||||
ref IntPtr PDirBuffer);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 FspSetSecurityDescriptor(
|
||||
IntPtr InputDescriptor,
|
||||
UInt32 SecurityInformation,
|
||||
IntPtr ModificationDescriptor,
|
||||
out IntPtr PSecurityDescriptor);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspDeleteSecurityDescriptor(
|
||||
IntPtr SecurityDescriptor,
|
||||
IntPtr CreateFunc);
|
||||
|
||||
/* Service */
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
@ -575,6 +653,10 @@ namespace Fsp.Interop
|
||||
internal delegate UInt32 FspWin32FromNtStatus(
|
||||
Int32 Status);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspDebugLog(
|
||||
[MarshalAs(UnmanagedType.LPStr)] String Format,
|
||||
[MarshalAs(UnmanagedType.LPStr)] String Message);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FspDebugLogSetHandle(
|
||||
IntPtr Handle);
|
||||
|
||||
@ -586,7 +668,7 @@ namespace Fsp.Interop
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
[MarshalAs(UnmanagedType.U1)] Boolean IsDirectory,
|
||||
IntPtr Buffer,
|
||||
ref UIntPtr PSize);
|
||||
IntPtr PSize);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 ServiceStart(
|
||||
IntPtr Service,
|
||||
@ -619,13 +701,16 @@ namespace Fsp.Interop
|
||||
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.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.FspSetSecurityDescriptor FspSetSecurityDescriptor;
|
||||
internal static IntPtr _FspSetSecurityDescriptorPtr;
|
||||
internal static Proto.FspDeleteSecurityDescriptor FspDeleteSecurityDescriptor;
|
||||
internal static Proto.FspServiceCreate FspServiceCreate;
|
||||
internal static Proto.FspServiceDelete FspServiceDelete;
|
||||
internal static Proto.FspServiceAllowConsoleMode FspServiceAllowConsoleMode;
|
||||
@ -638,6 +723,7 @@ namespace Fsp.Interop
|
||||
internal static Proto.FspVersion FspVersion;
|
||||
internal static Proto.FspNtStatusFromWin32 FspNtStatusFromWin32;
|
||||
internal static Proto.FspWin32FromNtStatus FspWin32FromNtStatus;
|
||||
internal static Proto.FspDebugLog FspDebugLog;
|
||||
internal static Proto.FspDebugLogSetHandle FspDebugLogSetHandle;
|
||||
|
||||
internal static unsafe Int32 FspFileSystemSetMountPointEx(
|
||||
@ -662,6 +748,29 @@ namespace Fsp.Interop
|
||||
fixed (DirInfo *P = &DirInfo)
|
||||
return _FspFileSystemAddDirInfo((IntPtr)P, Buffer, Length, out PBytesTransferred);
|
||||
}
|
||||
internal static unsafe Boolean FspFileSystemEndDirInfo(
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
return _FspFileSystemAddDirInfo(IntPtr.Zero, Buffer, Length, out PBytesTransferred);
|
||||
}
|
||||
internal static unsafe Boolean FspFileSystemAddStreamInfo(
|
||||
ref StreamInfo StreamInfo,
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
fixed (StreamInfo *P = &StreamInfo)
|
||||
return _FspFileSystemAddStreamInfo((IntPtr)P, Buffer, Length, out PBytesTransferred);
|
||||
}
|
||||
internal static unsafe Boolean FspFileSystemEndStreamInfo(
|
||||
IntPtr Buffer,
|
||||
UInt32 Length,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
return _FspFileSystemAddStreamInfo(IntPtr.Zero, Buffer, Length, out PBytesTransferred);
|
||||
}
|
||||
|
||||
internal unsafe static Object GetUserContext(
|
||||
IntPtr NativePtr)
|
||||
@ -673,61 +782,61 @@ namespace Fsp.Interop
|
||||
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;
|
||||
}
|
||||
internal unsafe static void DisposeUserContext(
|
||||
IntPtr NativePtr)
|
||||
{
|
||||
IntPtr UserContext = *(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr));
|
||||
Debug.Assert(IntPtr.Zero != UserContext);
|
||||
if (IntPtr.Zero != UserContext)
|
||||
{
|
||||
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;
|
||||
}
|
||||
GCHandle.FromIntPtr(UserContext).Free();
|
||||
*(IntPtr *)((Byte *)NativePtr + sizeof(IntPtr)) = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private class FullContextHolder
|
||||
{
|
||||
public Object FileNode;
|
||||
public Object FileDesc;
|
||||
}
|
||||
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;
|
||||
FullContextHolder Holder = 0 != FullContext.UserContext2 ?
|
||||
(FullContextHolder)GCHandle.FromIntPtr((IntPtr)FullContext.UserContext2).Target :
|
||||
null;
|
||||
if (null != Holder)
|
||||
{
|
||||
FileNode = Holder.FileNode;
|
||||
FileDesc = Holder.FileDesc;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileNode = null;
|
||||
FileDesc = null;
|
||||
}
|
||||
}
|
||||
internal static void SetFullContext(ref FullContext FullContext,
|
||||
Object FileNode, Object FileDesc)
|
||||
{
|
||||
if (null != FileNode)
|
||||
Debug.Assert(0 == FullContext.UserContext && 0 == FullContext.UserContext2);
|
||||
FullContextHolder Holder = new FullContextHolder();
|
||||
Holder.FileNode = FileNode;
|
||||
Holder.FileDesc = FileDesc;
|
||||
GCHandle Handle = GCHandle.Alloc(Holder, GCHandleType.Normal);
|
||||
FullContext.UserContext2 = (UInt64)(IntPtr)Handle;
|
||||
}
|
||||
internal static void DisposeFullContext(ref FullContext FullContext)
|
||||
{
|
||||
Debug.Assert(0 == FullContext.UserContext && 0 != FullContext.UserContext2);
|
||||
if (0 != FullContext.UserContext2)
|
||||
{
|
||||
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;
|
||||
}
|
||||
GCHandle.FromIntPtr((IntPtr)FullContext.UserContext2).Free();
|
||||
FullContext.UserContext2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -768,6 +877,67 @@ namespace Fsp.Interop
|
||||
else
|
||||
return null;
|
||||
}
|
||||
internal unsafe static byte[] ModifySecurityDescriptor(
|
||||
Byte[] SecurityDescriptorBytes,
|
||||
UInt32 SecurityInformation,
|
||||
Byte[] ModificationDescriptorBytes)
|
||||
{
|
||||
fixed (Byte *S = SecurityDescriptorBytes)
|
||||
fixed (Byte *M = ModificationDescriptorBytes)
|
||||
{
|
||||
IntPtr SecurityDescriptor;
|
||||
Int32 Result = FspSetSecurityDescriptor(
|
||||
(IntPtr)S, SecurityInformation, (IntPtr)M, out SecurityDescriptor);
|
||||
if (0 > Result)
|
||||
return null;
|
||||
SecurityDescriptorBytes = MakeSecurityDescriptor(SecurityDescriptor);
|
||||
FspDeleteSecurityDescriptor(SecurityDescriptor, _FspSetSecurityDescriptorPtr);
|
||||
return SecurityDescriptorBytes;
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe static Int32 CopyReparsePoint(
|
||||
Byte[] ReparseData,
|
||||
IntPtr Buffer,
|
||||
IntPtr PSize)
|
||||
{
|
||||
if (IntPtr.Zero != Buffer)
|
||||
{
|
||||
if (null != ReparseData)
|
||||
{
|
||||
if (ReparseData.Length > (int)*(UIntPtr *)PSize)
|
||||
return unchecked((Int32)0xc0000023)/*STATUS_BUFFER_TOO_SMALL*/;
|
||||
*(UIntPtr *)PSize = (UIntPtr)ReparseData.Length;
|
||||
Marshal.Copy(ReparseData, 0, Buffer, ReparseData.Length);
|
||||
}
|
||||
else
|
||||
*(UIntPtr *)PSize = UIntPtr.Zero;
|
||||
}
|
||||
return 0/*STATUS_SUCCESS*/;
|
||||
}
|
||||
internal static Byte[] MakeReparsePoint(
|
||||
IntPtr Buffer,
|
||||
UIntPtr Size)
|
||||
{
|
||||
if (IntPtr.Zero != Buffer)
|
||||
{
|
||||
Byte[] ReparseData = new Byte[(int)Size];
|
||||
Marshal.Copy(Buffer, ReparseData, 0, ReparseData.Length);
|
||||
return ReparseData;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
internal unsafe static Int32 FspFileSystemCanReplaceReparsePoint(
|
||||
Byte[] CurrentReparseData,
|
||||
Byte[] ReplaceReparseData)
|
||||
{
|
||||
fixed (Byte *C = CurrentReparseData)
|
||||
fixed (Byte *R = ReplaceReparseData)
|
||||
return _FspFileSystemCanReplaceReparsePoint(
|
||||
(IntPtr)C, (UIntPtr)CurrentReparseData.Length,
|
||||
(IntPtr)R, (UIntPtr)ReplaceReparseData.Length);
|
||||
}
|
||||
|
||||
internal static Int32 SetDebugLogFile(String FileName)
|
||||
{
|
||||
@ -812,17 +982,17 @@ namespace Fsp.Interop
|
||||
}
|
||||
return Module;
|
||||
}
|
||||
private static IntPtr GetEntryPointPtr(IntPtr Module, String Name)
|
||||
{
|
||||
IntPtr Proc = GetProcAddress(Module, Name);
|
||||
if (IntPtr.Zero == Proc)
|
||||
throw new EntryPointNotFoundException("cannot get entry point " + Name);
|
||||
return Proc;
|
||||
}
|
||||
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);
|
||||
}
|
||||
return (T)(object)Marshal.GetDelegateForFunctionPointer(
|
||||
GetEntryPointPtr(Module, typeof(T).Name), typeof(T));
|
||||
}
|
||||
private static void LoadProto(IntPtr Module)
|
||||
{
|
||||
@ -840,13 +1010,16 @@ namespace Fsp.Interop
|
||||
_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);
|
||||
_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);
|
||||
FspSetSecurityDescriptor = GetEntryPoint<Proto.FspSetSecurityDescriptor>(Module);
|
||||
_FspSetSecurityDescriptorPtr = GetEntryPointPtr(Module, "FspSetSecurityDescriptor");
|
||||
FspDeleteSecurityDescriptor = GetEntryPoint<Proto.FspDeleteSecurityDescriptor>(Module);
|
||||
FspServiceCreate = GetEntryPoint<Proto.FspServiceCreate>(Module);
|
||||
FspServiceDelete = GetEntryPoint<Proto.FspServiceDelete>(Module);
|
||||
FspServiceAllowConsoleMode = GetEntryPoint<Proto.FspServiceAllowConsoleMode>(Module);
|
||||
@ -859,6 +1032,7 @@ namespace Fsp.Interop
|
||||
FspVersion = GetEntryPoint<Proto.FspVersion>(Module);
|
||||
FspNtStatusFromWin32 = GetEntryPoint<Proto.FspNtStatusFromWin32>(Module);
|
||||
FspWin32FromNtStatus = GetEntryPoint<Proto.FspWin32FromNtStatus>(Module);
|
||||
FspDebugLog = GetEntryPoint<Proto.FspDebugLog>(Module);
|
||||
FspDebugLogSetHandle = GetEntryPoint<Proto.FspDebugLogSetHandle>(Module);
|
||||
}
|
||||
private static void CheckVersion()
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dotnet/Service.cs
|
||||
/*
|
||||
* dotnet/Service.cs
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -16,13 +16,16 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Fsp.Interop;
|
||||
|
||||
namespace Fsp
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides the base class for a process that can be run as a service,
|
||||
/// command line application or under the control of the WinFsp launcher.
|
||||
/// </summary>
|
||||
public class Service
|
||||
{
|
||||
/* const */
|
||||
@ -31,25 +34,33 @@ namespace Fsp
|
||||
public const UInt32 EVENTLOG_INFORMATION_TYPE = 0x0004;
|
||||
|
||||
/* ctor/dtor */
|
||||
/// <summary>
|
||||
/// Creates an instance of the Service class.
|
||||
/// </summary>
|
||||
/// <param name="ServiceName">The name of the service.</param>
|
||||
public Service(String ServiceName)
|
||||
{
|
||||
Api.FspServiceCreate(ServiceName, _OnStart, _OnStop, null, out _Service);
|
||||
if (IntPtr.Zero != _Service)
|
||||
Api.SetUserContext(_Service, this);
|
||||
Api.FspServiceCreate(ServiceName, _OnStart, _OnStop, null, out _ServicePtr);
|
||||
if (IntPtr.Zero != _ServicePtr)
|
||||
Api.SetUserContext(_ServicePtr, this);
|
||||
}
|
||||
~Service()
|
||||
{
|
||||
if (IntPtr.Zero != _Service)
|
||||
if (IntPtr.Zero != _ServicePtr)
|
||||
{
|
||||
Api.SetUserContext(_Service, null);
|
||||
Api.FspServiceDelete(_Service);
|
||||
Api.DisposeUserContext(_ServicePtr);
|
||||
Api.FspServiceDelete(_ServicePtr);
|
||||
}
|
||||
}
|
||||
|
||||
/* control */
|
||||
/// <summary>
|
||||
/// Runs a service.
|
||||
/// </summary>
|
||||
/// <returns>Service process exit code.</returns>
|
||||
public int Run()
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
if (IntPtr.Zero == _ServicePtr)
|
||||
{
|
||||
const Int32 STATUS_INSUFFICIENT_RESOURCES = unchecked((Int32)0xc000009a);
|
||||
Log(EVENTLOG_ERROR_TYPE,
|
||||
@ -57,9 +68,9 @@ namespace Fsp
|
||||
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);
|
||||
Api.FspServiceAllowConsoleMode(_ServicePtr);
|
||||
Int32 Result = Api.FspServiceLoop(_ServicePtr);
|
||||
int ExitCode = (int)Api.FspServiceGetExitCode(_ServicePtr);
|
||||
if (0 > Result)
|
||||
{
|
||||
Log(EVENTLOG_ERROR_TYPE,
|
||||
@ -69,36 +80,42 @@ namespace Fsp
|
||||
}
|
||||
return ExitCode;
|
||||
}
|
||||
/// <summary>
|
||||
/// Stops a running service.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
if (IntPtr.Zero == _ServicePtr)
|
||||
throw new InvalidOperationException();
|
||||
Api.FspServiceStop(_Service);
|
||||
Api.FspServiceStop(_ServicePtr);
|
||||
}
|
||||
public void RequestTime(UInt32 Time)
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
if (IntPtr.Zero == _ServicePtr)
|
||||
throw new InvalidOperationException();
|
||||
Api.FspServiceRequestTime(_Service, Time);
|
||||
Api.FspServiceRequestTime(_ServicePtr, Time);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the service process exit code.
|
||||
/// </summary>
|
||||
public int ExitCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
if (IntPtr.Zero == _ServicePtr)
|
||||
throw new InvalidOperationException();
|
||||
return (int)Api.FspServiceGetExitCode(_Service);
|
||||
return (int)Api.FspServiceGetExitCode(_ServicePtr);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (IntPtr.Zero == _Service)
|
||||
if (IntPtr.Zero == _ServicePtr)
|
||||
throw new InvalidOperationException();
|
||||
Api.FspServiceSetExitCode(_Service, (UInt32)value);
|
||||
Api.FspServiceSetExitCode(_ServicePtr, (UInt32)value);
|
||||
}
|
||||
}
|
||||
public IntPtr ServiceHandle
|
||||
{
|
||||
get { return _Service; }
|
||||
get { return _ServicePtr; }
|
||||
}
|
||||
public static void Log(UInt32 Type, String Message)
|
||||
{
|
||||
@ -106,13 +123,25 @@ namespace Fsp
|
||||
}
|
||||
|
||||
/* start/stop */
|
||||
/// <summary>
|
||||
/// Provides a means to customize the returned status code when an exception happens.
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
protected virtual Int32 ExceptionHandler(Exception ex)
|
||||
{
|
||||
return unchecked((Int32)0xE0434f4D)/*STATUS_CLR_EXCEPTION*/;
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs when the service starts.
|
||||
/// </summary>
|
||||
/// <param name="Args">Command line arguments passed to the service.</param>
|
||||
protected virtual void OnStart(String[] Args)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs when the service stops.
|
||||
/// </summary>
|
||||
protected virtual void OnStop()
|
||||
{
|
||||
}
|
||||
@ -152,7 +181,7 @@ namespace Fsp
|
||||
|
||||
private static Api.Proto.ServiceStart _OnStart = OnStart;
|
||||
private static Api.Proto.ServiceStop _OnStop = OnStop;
|
||||
private IntPtr _Service;
|
||||
private IntPtr _ServicePtr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,12 +17,16 @@ launchctl-x64 start memfs64 testdsk "" M: >nul
|
||||
launchctl-x64 start memfs64 testnet \memfs64\test N: >nul
|
||||
launchctl-x64 start memfs32 testdsk "" O: >nul
|
||||
launchctl-x64 start memfs32 testnet \memfs32\test P: >nul
|
||||
launchctl-x64 start memfs-dotnet testdsk "" Q: >nul
|
||||
launchctl-x64 start memfs-dotnet testnet \memfs-dotnet\test R: >nul
|
||||
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
cd M: >nul 2>nul || (echo === Unable to find drive M: >&2 & goto fail)
|
||||
cd N: >nul 2>nul || (echo === Unable to find drive N: >&2 & goto fail)
|
||||
cd O: >nul 2>nul || (echo === Unable to find drive O: >&2 & goto fail)
|
||||
cd P: >nul 2>nul || (echo === Unable to find drive P: >&2 & goto fail)
|
||||
cd Q: >nul 2>nul || (echo === Unable to find drive Q: >&2 & goto fail)
|
||||
cd R: >nul 2>nul || (echo === Unable to find drive R: >&2 & goto fail)
|
||||
|
||||
set dfl_tests=^
|
||||
winfsp-tests-x64 ^
|
||||
@ -31,6 +35,7 @@ set dfl_tests=^
|
||||
winfsp-tests-x64-mountpoint-dir ^
|
||||
winfsp-tests-x64-no-traverse ^
|
||||
winfsp-tests-x64-oplock ^
|
||||
winfsp-tests-x64-external ^
|
||||
winfsp-tests-x64-external-share ^
|
||||
fsx-memfs-x64-disk ^
|
||||
fsx-memfs-x64-net ^
|
||||
@ -46,6 +51,7 @@ set dfl_tests=^
|
||||
winfsp-tests-x86-mountpoint-dir ^
|
||||
winfsp-tests-x86-no-traverse ^
|
||||
winfsp-tests-x86-oplock ^
|
||||
winfsp-tests-x86-external ^
|
||||
winfsp-tests-x86-external-share ^
|
||||
fsx-memfs-x86-disk ^
|
||||
fsx-memfs-x86-net ^
|
||||
@ -54,14 +60,19 @@ set dfl_tests=^
|
||||
net-use-memfs-x86 ^
|
||||
winfstest-memfs-x86-disk ^
|
||||
winfstest-memfs-x86-net ^
|
||||
fscrash-x86
|
||||
fscrash-x86 ^
|
||||
winfsp-tests-dotnet-external ^
|
||||
winfsp-tests-dotnet-external-share ^
|
||||
fsx-memfs-dotnet-disk ^
|
||||
fsx-memfs-dotnet-net ^
|
||||
winfstest-memfs-dotnet-disk ^
|
||||
winfstest-memfs-dotnet-net
|
||||
set opt_tests=^
|
||||
ifstest-memfs-x64-disk ^
|
||||
ifstest-memfs-x86-disk ^
|
||||
ifstest-memfs-dotnet-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-dotnet
|
||||
@ -121,6 +132,8 @@ launchctl-x64 stop memfs64 testdsk >nul
|
||||
launchctl-x64 stop memfs64 testnet >nul
|
||||
launchctl-x64 stop memfs32 testdsk >nul
|
||||
launchctl-x64 stop memfs32 testnet >nul
|
||||
launchctl-x64 stop memfs-dotnet testdsk >nul
|
||||
launchctl-x64 stop memfs-dotnet testnet >nul
|
||||
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
|
||||
@ -195,6 +208,12 @@ winfsp-tests-x86 --oplock=filter --resilient
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-external
|
||||
M:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --resilient
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-external-share
|
||||
M:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --share=winfsp-tests-share=M:\ --resilient ^
|
||||
@ -242,6 +261,12 @@ net use L: /delete
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-external
|
||||
O:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" --external --resilient
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-external-share
|
||||
O:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" --external --share=winfsp-tests-share=O:\ --resilient ^
|
||||
@ -351,6 +376,47 @@ fscrash-x86 --huge-alloc-size --cached >nul 2>&1
|
||||
if !ERRORLEVEL! neq 1 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-dotnet-external
|
||||
Q:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --resilient
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-dotnet-external-share
|
||||
Q:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --share=winfsp-tests-share=Q:\ --resilient ^
|
||||
-reparse_symlink*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:fsx-memfs-dotnet-disk
|
||||
Q:
|
||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -f foo -N 5000 test xxxxxx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:fsx-memfs-dotnet-net
|
||||
R:
|
||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -f foo -N 5000 test xxxxxx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfstest-memfs-dotnet-disk
|
||||
Q:
|
||||
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfstest-memfs-dotnet-net
|
||||
R:
|
||||
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:ifstest-memfs-x64-disk
|
||||
call :__ifstest-memfs M: \Device\WinFsp.Disk C:
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
@ -361,6 +427,11 @@ call :__ifstest-memfs O: \Device\WinFsp.Disk C:
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:ifstest-memfs-dotnet-disk
|
||||
call :__ifstest-memfs Q: \Device\WinFsp.Disk C:
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:__ifstest-memfs
|
||||
%1
|
||||
set IfsTestDirectories=^
|
||||
|
0
tools/version-info.bat
Normal file → Executable file
0
tools/version-info.bat
Normal file → Executable file
1156
tst/memfs-dotnet/Program.cs
Normal file
1156
tst/memfs-dotnet/Program.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -192,7 +192,7 @@ typedef struct _MEMFS_FILE_NODE
|
||||
SIZE_T ReparseDataSize;
|
||||
PVOID ReparseData;
|
||||
#endif
|
||||
ULONG RefCount;
|
||||
volatile LONG RefCount;
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
struct _MEMFS_FILE_NODE *MainFileNode;
|
||||
#endif
|
||||
@ -260,13 +260,13 @@ VOID MemfsFileNodeDelete(MEMFS_FILE_NODE *FileNode)
|
||||
static inline
|
||||
VOID MemfsFileNodeReference(MEMFS_FILE_NODE *FileNode)
|
||||
{
|
||||
FileNode->RefCount++;
|
||||
InterlockedIncrement(&FileNode->RefCount);
|
||||
}
|
||||
|
||||
static inline
|
||||
VOID MemfsFileNodeDereference(MEMFS_FILE_NODE *FileNode)
|
||||
{
|
||||
if (0 == --FileNode->RefCount)
|
||||
if (0 == InterlockedDecrement(&FileNode->RefCount))
|
||||
MemfsFileNodeDelete(FileNode);
|
||||
}
|
||||
|
||||
@ -850,14 +850,18 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS Result;
|
||||
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE };
|
||||
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { TRUE };
|
||||
ULONG Index;
|
||||
|
||||
MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode,
|
||||
MemfsFileNodeMapEnumerateFn, &Context);
|
||||
for (Index = 0; Context.Count > Index; Index++)
|
||||
if (1 >= Context.FileNodes[Index]->RefCount)
|
||||
{
|
||||
LONG RefCount = Context.FileNodes[Index]->RefCount;
|
||||
MemoryBarrier();
|
||||
if (2 >= RefCount)
|
||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
|
||||
}
|
||||
MemfsFileNodeMapEnumerateFree(&Context);
|
||||
#endif
|
||||
|
||||
|
@ -316,6 +316,9 @@ static void dirbuf_fill_test(void)
|
||||
|
||||
void dirbuf_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(dirbuf_empty_test);
|
||||
TEST(dirbuf_dots_test);
|
||||
TEST(dirbuf_fill_test);
|
||||
|
@ -31,5 +31,8 @@ void eventlog_test(void)
|
||||
|
||||
void eventlog_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST_OPT(eventlog_test);
|
||||
}
|
||||
|
@ -370,5 +370,8 @@ void fuse_opt_parse_test(void)
|
||||
|
||||
void fuse_opt_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(fuse_opt_parse_test);
|
||||
}
|
||||
|
@ -102,5 +102,8 @@ void memfs_test(void)
|
||||
|
||||
void memfs_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(memfs_test);
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ void mount_preflight_test(void)
|
||||
|
||||
void mount_tests(void)
|
||||
{
|
||||
if (NtfsTests || OptOplock)
|
||||
if (OptExternal || OptOplock)
|
||||
return;
|
||||
|
||||
TEST_OPT(mount_invalid_test);
|
||||
|
@ -126,6 +126,9 @@ void path_suffix_test(void)
|
||||
|
||||
void path_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(path_prefix_test);
|
||||
TEST(path_suffix_test);
|
||||
}
|
||||
|
@ -265,6 +265,9 @@ void posix_map_path_test(void)
|
||||
|
||||
void posix_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(posix_map_sid_test);
|
||||
TEST(posix_map_sd_test);
|
||||
TEST(posix_map_path_test);
|
||||
|
@ -262,7 +262,7 @@ void timeout_transact_test(void)
|
||||
|
||||
void timeout_tests(void)
|
||||
{
|
||||
if (NtfsTests || OptOplock)
|
||||
if (OptExternal || OptOplock)
|
||||
return;
|
||||
|
||||
TEST_OPT(timeout_pending_test);
|
||||
|
@ -38,5 +38,8 @@ static void version_test(void)
|
||||
|
||||
void version_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(version_test);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ int NtfsTests = 0;
|
||||
int WinFspDiskTests = 1;
|
||||
int WinFspNetTests = 1;
|
||||
|
||||
BOOLEAN OptExternal = FALSE;
|
||||
BOOLEAN OptResilient = FALSE;
|
||||
BOOLEAN OptCaseInsensitiveCmp = FALSE;
|
||||
BOOLEAN OptCaseInsensitive = FALSE;
|
||||
@ -211,6 +212,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (0 == strcmp("--ntfs", a) || 0 == strcmp("--external", a))
|
||||
{
|
||||
OptExternal = TRUE;
|
||||
NtfsTests = 1;
|
||||
WinFspDiskTests = 0;
|
||||
WinFspNetTests = 0;
|
||||
|
@ -149,6 +149,7 @@ extern int NtfsTests;
|
||||
extern int WinFspDiskTests;
|
||||
extern int WinFspNetTests;
|
||||
|
||||
extern BOOLEAN OptExternal;
|
||||
extern BOOLEAN OptResilient;
|
||||
extern BOOLEAN OptCaseInsensitiveCmp;
|
||||
extern BOOLEAN OptCaseInsensitive;
|
||||
|
Reference in New Issue
Block a user