Compare commits

..

1 Commits

Author SHA1 Message Date
56873406e3 appveyor: run-perf-tests 2017-01-04 16:04:43 -08:00
158 changed files with 1160 additions and 7864 deletions

View File

@ -1,27 +1,11 @@
= Changelog
v1.0RC2::
This is the WinFsp 2017 Release Candidate 2. Some important changes included below:
- WinFsp is now available under the GPLv3 with a special exception for Free/Libre and Open Source Software.
- The location of the WinFsp launcher registry entries is now `HKEY_LOCAL_MACHINE\Software\WinFsp\Services`. [On Win64 the actual location is `HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services`.] This change was necessary to avoid loss of third party file system registry entries during WinFsp uninstallation. [See GitHub issue #31.]
- Despite stating in the previous release that the API has been finalized the `ReadDirectory` `FSP_FILE_SYSTEM_INTERFACE` operation has been changed. Extensive testing with multiple file systems has shown that `ReadDirectory` was hard to implement correctly. The new definition should make implementation easier for most file systems. [See GitHub issue #34.]
- Some API's to facilitate `ReadDirectory` implementation have been added. Look for `FspFileSystem*DirectoryBuffer` symbols.
- The installer now (optionally) installs a sample file system called "passthrough". This is a simple file system that passes all operations to an underlying file system. There is also a tutorial for this file system (in the doc directory).
- The installer now (optionally) installs a sample file system called "passthrough-fuse". This file system performs the same function as the "passthrough" file system, but uses the FUSE compatibility layer. It builds and runs on both Windows and Cygwin.
v1.0RC1::
This is the WinFsp 2017 Release Candidate 1. It has been tested extensively in a variety of scenarios for stability and correct file system semantics. Some of the more important changes:
This is the first Release Candidate. It has been tested for robustness and correct file system semantics in a variety of scenarios. Some of the more important changes:
- API has been polished and finalized.
- Extensively tested against multiple test suites including Microsoft's IfsTest.
- WinFsp I/O Queues (the fundamental WinFsp IPC mechanism) have been improved to work similar to I/O Completion Ports.
- Opportunistic locks have been implemented.
- File system statistics have been implemented.
- Sharing a (disk) file system over the network is supported.
- Case insensitive file systems are supported.
- Directories are supported as mount points.

View File

@ -1,35 +1,8 @@
The WinFsp project is Copyright (C) Bill Zissimopoulos. It is licensed
under the terms of the GPLv3.
As a special exception to GPLv3, Bill Zissimopoulos grants additional
permissions to Free/Libre and Open Source Software ("FLOSS") without requiring
that such software is covered by the GPLv3.
1. Permission to link with a platform specific version of the WinFsp DLL
(currently winfsp-x64.dll or winfsp-x86.dll).
2. Permission to distribute unmodified binary releases of the WinFsp
installer (as released by the WinFsp project).
These permissions (and no other) are granted provided that the software:
1. Is distributed under a license that satisfies the Free Software
Definition Version 1.141 (https://www.gnu.org/philosophy/free-sw.en.html)
or the Open Source Definition Version 1.9 (https://opensource.org/osd).
2. Includes the copyright notice "WinFsp - Windows File System Proxy,
Copyright (C) Bill Zissimopoulos" and a link to the WinFsp repository in
its user-interface and any user-facing documentation.
3. Is not linked or distributed with proprietary (non-FLOSS) software.
[You cannot mix FLOSS and proprietary software while using WinFsp under
this special exception.]
Commercial licensing options are also available: Please contact
under the terms of the GPLv3. The full text of this license follows
below. Commercial licensing options are also available: Please contact
Bill Zissimopoulos <billziss at navimatics.com>.
The full text of the GPLv3 license follows below.
-----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE

View File

@ -2,22 +2,17 @@
![WinFsp Demo](http://www.secfs.net/winfsp/files/cap.gif)
<a href="https://github.com/billziss-gh/winfsp/releases/download/v1.0RC1/winfsp-1.0.17009.msi"><img src="http://www.secfs.net/winfsp/resources/Download-WinFsp.png" alt="Download WinFsp Installer" width="244" height="34"></a>
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
Some of the benefits of using WinFsp are listed below:
Some of the benefits and features of using WinFsp are listed below:
* Very well-tested and stable. Read about its [Testing Strategy](doc/WinFsp-Testing.asciidoc).
* Very fast. Read about its [Performance](doc/WinFsp-Performance-Testing.asciidoc).
* Strives for compatibility with NTFS. Read about its [Compatibility](doc/NTFS-Compatibility.asciidoc ).
* Easy to understand but comprehensive API. Consult the [API Reference](http://www.secfs.net/winfsp/apiref/). There is also a simple [Tutorial](doc/WinFsp-Tutorial.asciidoc).
* FUSE compatibility layer for native Windows and Cygwin. See [fuse.h](inc/fuse/fuse.h).
* Signed drivers provided on every release.
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
* Allows for easy development of file systems in user mode. There are no restrictions on what a process can do in order to implement a file system (other than respond in a timely manner to file system requests).
* Support for disk and network based file systems.
* Support for NTFS level security and access control.
* Support for memory mapped files, cached files and the NT cache manager.
* Support for file change notifications.
* Support for file locking.
* Correct NT semantics with respect to file sharing, file deletion and renaming.
To learn more about WinFsp, please visit its website: http://www.secfs.net/winfsp/
@ -58,7 +53,6 @@ WinFsp is designed to run on Vista and above. It has been tested on the followin
* Windows 8 Pro
* Windows 10 Pro
* Windows Server 2012
* Windows Server 2016
## How to Help
@ -66,7 +60,7 @@ 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.
* 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.
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/billziss-gh/winfsp/issues) ~~[BitBucket repository](https://bitbucket.org/billziss/winfsp/issues?status=new&status=open)~~. 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. If you decide to tackle any of those please coordinate with me as I am actively working on that issue list.
In all cases I can provide ideas and/or support.
@ -79,4 +73,4 @@ If you wish to discuss WinFsp there are now two options:
## License
WinFsp is available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software. A commercial license is also available. Please contact Bill Zissimopoulos \<billziss at navimatics.com> for more details.
WinFsp is available under the [GPLv3](http://www.gnu.org/licenses/gpl-3.0.html) license. If you find the constraints of the GPLv3 too onerous, a commercial license is also available. Please contact Bill Zissimopoulos <billziss at navimatics.com> for more details.

View File

@ -2,10 +2,6 @@ version: '{build}'
environment:
matrix:
- CONFIGURATION: Debug
TESTING: Func
- CONFIGURATION: Release
TESTING: Func
- CONFIGURATION: Release
TESTING: Perf
@ -29,7 +25,6 @@ test_script:
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
- if exist %SystemRoot%\memory.dmp exit 1

View File

@ -1,7 +1,7 @@
/**
* @file CustomActions.cpp
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -22,7 +22,7 @@
<Media Id="1" Cabinet="WinFsp.cab" EmbedCab="yes" />
<Property Id="P.LauncherName">$(var.MyProductName).Launcher</Property>
<Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property>
<Property Id="P.LauncherRegistryKey">SYSTEM\\CurrentControlSet\\Services\\$(var.MyProductName).Launcher\\Services</Property>
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
<Property Id="INSTALLDIR">
<RegistrySearch
@ -55,9 +55,6 @@
Value="[INSTALLDIR]"
KeyPath="yes" />
</Component>
<Component Id="C.License.txt">
<File Name="License.txt" Source="..\..\..\License.txt" KeyPath="yes" />
</Component>
</DirectoryRef>
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
<Component Id="C.winfsp_x64.sys">
@ -143,9 +140,6 @@
<Component Id="C.diag.bat">
<File Name="diag.bat" Source="..\..\..\tools\diag.bat" KeyPath="yes" />
</Component>
<Component Id="C.fsreg.bat">
<File Name="fsreg.bat" Source="..\..\..\tools\fsreg.bat" KeyPath="yes" />
</Component>
<Component Id="C.memfs_x64.exe">
<File Name="memfs-x64.exe" KeyPath="yes" />
@ -161,7 +155,7 @@
<RegistryValue
Type="string"
Name="CommandLine"
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
Value="-i -n 65536 -s 67108864 -u %1 -m %2" />
<RegistryValue
Type="string"
Name="Security"
@ -187,7 +181,7 @@
<RegistryValue
Type="string"
Name="CommandLine"
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
Value="-i -n 65536 -s 67108864 -u %1 -m %2" />
<RegistryValue
Type="string"
Name="Security"
@ -264,46 +258,6 @@
<File Name="memfs-main.c" KeyPath="yes" />
</Component>
</Directory>
<Directory Id="SMPDIR.passthrough" Name="passthrough">
<Component Id="C.passthrough.c">
<File Name="passthrough.c" KeyPath="yes" />
</Component>
<Component Id="C.passthrough.sln">
<File Name="passthrough.sln" KeyPath="yes" />
</Component>
<Component Id="C.passthrough.vcxproj">
<File Name="passthrough.vcxproj" KeyPath="yes" />
</Component>
<Component Id="C.passthrough.vcxproj.filters">
<File Name="passthrough.vcxproj.filters" KeyPath="yes" />
</Component>
</Directory>
<Directory Id="SMPDIR.passthrough_fuse" Name="passthrough-fuse">
<Component Id="C.passthrough_fuse.c">
<File Name="passthrough-fuse.c" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.winposix.c">
<File Name="winposix.c" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.winposix.h">
<File Name="winposix.h" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.sln">
<File Name="passthrough-fuse.sln" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.vcxproj">
<File Name="passthrough-fuse.vcxproj" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.vcxproj.filters">
<File Name="passthrough-fuse.vcxproj.filters" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.Makefile">
<File Name="Makefile" KeyPath="yes" />
</Component>
<Component Id="C.passthrough_fuse.README.md">
<File Name="README.md" KeyPath="yes" />
</Component>
</Directory>
</DirectoryRef>
<DirectoryRef Id="SYMDIR">
<Component Id="C.winfsp_x64.sys.pdb">
@ -352,7 +306,6 @@
<ComponentRef Id="C.launchctl_x64.exe" />
<ComponentRef Id="C.launchctl_x86.exe" />
<ComponentRef Id="C.diag.bat" />
<ComponentRef Id="C.fsreg.bat" />
</ComponentGroup>
<ComponentGroup Id="C.WinFsp.inc">
<ComponentRef Id="C.fsctl.h" />
@ -374,18 +327,6 @@
<ComponentRef Id="C.memfs.h" />
<ComponentRef Id="C.memfs.cpp" />
<ComponentRef Id="C.memfs_main.c" />
<ComponentRef Id="C.passthrough.c" />
<ComponentRef Id="C.passthrough.sln" />
<ComponentRef Id="C.passthrough.vcxproj" />
<ComponentRef Id="C.passthrough.vcxproj.filters" />
<ComponentRef Id="C.passthrough_fuse.c" />
<ComponentRef Id="C.passthrough_fuse.winposix.c" />
<ComponentRef Id="C.passthrough_fuse.winposix.h" />
<ComponentRef Id="C.passthrough_fuse.sln" />
<ComponentRef Id="C.passthrough_fuse.vcxproj" />
<ComponentRef Id="C.passthrough_fuse.vcxproj.filters" />
<ComponentRef Id="C.passthrough_fuse.Makefile" />
<ComponentRef Id="C.passthrough_fuse.README.md" />
</ComponentGroup>
<ComponentGroup Id="C.WinFsp.sym">
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
@ -411,7 +352,6 @@
InstallDefault="local"
Absent="disallow">
<ComponentRef Id="C.INSTALLDIR" />
<ComponentRef Id="C.License.txt" />
<Feature
Id="F.User"
Level="1"

View File

@ -16,7 +16,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
<DefineConstants>Debug;MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyFullVersion=$(MyFullVersion)</DefineConstants>
<DefineConstants>Debug;MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion)</DefineConstants>
<SuppressAllWarnings>False</SuppressAllWarnings>
<Pedantic>True</Pedantic>
<SuppressPdbOutput>True</SuppressPdbOutput>
@ -25,7 +25,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
<DefineConstants>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyFullVersion=$(MyFullVersion)</DefineConstants>
<DefineConstants>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion)</DefineConstants>
<SuppressAllWarnings>False</SuppressAllWarnings>
<Pedantic>True</Pedantic>
<SuppressPdbOutput>True</SuppressPdbOutput>

View File

@ -193,10 +193,10 @@
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\src\launcher\launchctl-version.rc">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<ItemGroup>

View File

@ -202,10 +202,10 @@
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\src\launcher\launcher-version.rc">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -182,7 +182,6 @@
</ClCompile>
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\flush-test.c" />

View File

@ -76,9 +76,6 @@
<ClCompile Include="..\..\..\tst\winfsp-tests\oplock-test.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">

View File

@ -1,15 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
<!-- git revision -->
<MyGitRoot>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), .git/HEAD))</MyGitRoot>
<MyGitHead>$([System.IO.File]::ReadAllText($(MyGitRoot)/.git/HEAD).Trim())</MyGitHead>
<MyGitRevision Condition="$(MyGitHead.StartsWith(ref: ))">$([System.IO.File]::ReadAllText($(MyGitRoot)/.git/$(MyGitHead.Substring(5))).Trim().Substring(0, 7))</MyGitRevision>
<MyGitRevision Condition="!$(MyGitHead.StartsWith(ref: ))">$(MyGitHead.Substring(0, 7))</MyGitRevision>
<MyProductName>WinFsp</MyProductName>
<MyDescription>Windows File System Proxy</MyDescription>
<MyCompanyName>Navimatics Corporation</MyCompanyName>
@ -17,20 +8,19 @@
<MyCanonicalVersion>1.0</MyCanonicalVersion>
<MyProductVersion>2017 RC2</MyProductVersion>
<MyProductVersion>$(MyCanonicalVersion) RC1</MyProductVersion>
<MyProductStage>RC</MyProductStage>
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
<MyFullVersion>$(MyCanonicalVersion).$(MyBuildNumber).$(MyGitRevision)</MyFullVersion>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601</PreprocessorDefinitions>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
</Project>

View File

@ -31,7 +31,6 @@
<ClInclude Include="..\..\src\shared\minimal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\dll\dirbuf.c" />
<ClCompile Include="..\..\src\dll\eventlog.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
@ -51,7 +50,7 @@
<ClCompile Include="..\..\src\dll\util.c" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo arch=$(PlatformTarget) &gt;$(OutDir)fuse-$(PlatformTarget).pc
copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(PlatformTarget).pc &gt;nul</Command>
@ -79,10 +78,10 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
<ItemGroup>
<ResourceCompile Include="..\..\src\dll\eventlog\eventlog.rc" />
<ResourceCompile Include="..\..\src\dll\version.rc">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<PropertyGroup Label="Globals">

View File

@ -103,9 +103,6 @@
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c">
<Filter>Source\fuse</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dll\dirbuf.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\dll\library.def">
@ -121,7 +118,7 @@
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc">
<Filter>Source\fuse</Filter>
</CustomBuild>
</ItemGroup>

View File

@ -177,7 +177,6 @@
<ClCompile Include="..\..\src\sys\read.c" />
<ClCompile Include="..\..\src\sys\security.c" />
<ClCompile Include="..\..\src\sys\shutdown.c" />
<ClCompile Include="..\..\src\sys\statistics.c" />
<ClCompile Include="..\..\src\sys\util.c" />
<ClCompile Include="..\..\src\sys\volinfo.c" />
<ClCompile Include="..\..\src\sys\volume.c" />
@ -190,77 +189,12 @@
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\src\sys\version.rc">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_WIN64;_AMD64_=1;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WIN64;_AMD64_=1;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_WIN64;_AMD64_=1;AMD64;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WIN64;_AMD64_=1;AMD64;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\sys\driver.inf.in">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">set DriverFile=$(TargetFileName)
set Provider="$(MyCompanyName)"
set CatalogFile=driver-$(PlatformTarget).cat
setlocal EnableDelayedExpansion
if exist $(OutDir)driver-$(PlatformTarget).inf del $(OutDir)driver-$(PlatformTarget).inf
for /f "delims=" %%l in (%(FullPath)) do (
set line=%%l
echo !line! &gt;&gt;$(OutDir)driver-$(PlatformTarget).inf
)
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">set DriverFile=$(TargetFileName)
set Provider="$(MyCompanyName)"
set CatalogFile=driver-$(PlatformTarget).cat
setlocal EnableDelayedExpansion
if exist $(OutDir)driver-$(PlatformTarget).inf del $(OutDir)driver-$(PlatformTarget).inf
for /f "delims=" %%l in (%(FullPath)) do (
set line=%%l
echo !line! &gt;&gt;$(OutDir)driver-$(PlatformTarget).inf
)
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">set DriverFile=$(TargetFileName)
set Provider="$(MyCompanyName)"
set CatalogFile=driver-$(PlatformTarget).cat
setlocal EnableDelayedExpansion
if exist $(OutDir)driver-$(PlatformTarget).inf del $(OutDir)driver-$(PlatformTarget).inf
for /f "delims=" %%l in (%(FullPath)) do (
set line=%%l
echo !line! &gt;&gt;$(OutDir)driver-$(PlatformTarget).inf
)
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">set DriverFile=$(TargetFileName)
set Provider="$(MyCompanyName)"
set CatalogFile=driver-$(PlatformTarget).cat
setlocal EnableDelayedExpansion
if exist $(OutDir)driver-$(PlatformTarget).inf del $(OutDir)driver-$(PlatformTarget).inf
for /f "delims=" %%l in (%(FullPath)) do (
set line=%%l
echo !line! &gt;&gt;$(OutDir)driver-$(PlatformTarget).inf
)
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Writing driver-$(PlatformTarget).inf</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)driver-$(PlatformTarget).inf</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Writing driver-$(PlatformTarget).inf</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)driver-$(PlatformTarget).inf</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Writing driver-$(PlatformTarget).inf</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)driver-$(PlatformTarget).inf</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Writing driver-$(PlatformTarget).inf</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)driver-$(PlatformTarget).inf</Outputs>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -95,9 +95,6 @@
<ClCompile Include="..\..\src\sys\name.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\..\src\sys\statistics.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\sys\driver.h">
@ -112,9 +109,4 @@
<Filter>Source</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\sys\driver.inf.in">
<Filter>Source</Filter>
</CustomBuild>
</ItemGroup>
</Project>

View File

@ -1,46 +0,0 @@
= NTFS Compatibility
WinFsp enables the creation of user mode file systems that behave similar to NTFS or FAT. Generic Windows applications that access files on a WinFsp file system cannot and should not be able to determine that it is not a native Windows file system. However specialized applications that access NTFS or FAT specific extensions (such as Defrag) will not work properly on WinFsp file systems.
== Supported features
WinFsp supports the following NTFS features:
- Query and set volume information.
- Open, create, close, delete files and directories.
- Query and set file and directory information.
- Query and set security information (ACL's).
- Read and write files.
- Memory mapped I/O.
- Directory change notifications.
- Lock and unlock files.
- Opportunistic locks.
- Open, create, close, delete, query named streams.
- Reparse points with special support for symbolic links.
== Unsupported features
WinFsp does not support the following NTFS features:
- Hard links. Rather rarely used on Windows. However it might be worthwhile to implement them for WinFsp.
- Extended attributes. Although popular with POSIX file systems, they are severely hampered and rarely used on Windows. They are also not exposed via the Win32 API.
- Short file names. Short file names are a relic of the past. WinFsp made a conscious decision not to support them.
- Paging files. Providing paging file support via a user mode file system is impossible for a number of reasons.
- Object ID's. Opening files by ID (+FILE_OPEN_BY_FILE_ID+) is not supported.
- Volume access. Volume handles can be opened and closed, but volumes cannot be read or written. Such an operation makes little sense for most user mode file systems, that do not store information on disks.
- Sparse files. A user mode file system is free to implement sparse files. However WinFsp does not support any sparse file related FSCTL or information class codes.
- Compressed files. A user mode file system is free to implement compressed files. However WinFsp does not support any compression related FSCTL or information class codes.
- Encrypted files. A user mode file system is free to implement encrypted files. However WinFsp does not support any encryption related FSCTL or information class codes.
- Quotas.
- The Change Journal.
- Defragmentation support.
== Incompatibilities
This section lists incompatibilites with NTFS in those features that they both support:
- WinFsp supports case sensitive and case insensitive file systems. However it does not support case sensitive lookups on a case insensitive file system (+SL_CASE_SENSITIVE+).
- NTFS updates the file size information in the directory entry when a file is cleaned up. WinFsp file systems do not (and probably should not attempt to) replicate this behavior. [Related article: https://blogs.msdn.microsoft.com/oldnewthing/20111226-00/?p=8813]
- NTFS supports change notifications on streams (these are mostly undocumented). WinFsp supports them as well but it differs from NTFS in that it issues a single notification when a file with streams is deleted; NTFS appears to issue one notification per deleted stream.
- WinFsp does not support renaming a stream.
- NTFS allows for enumeration and change notifications of all reparse points by opening a special NTFS-only "directory" that "contains" all reparse points (+\$Extend\$Reparse:$R:$INDEX_ALLOCATION+). WinFsp does not support this feature.

View File

@ -20,21 +20,19 @@ In order to overcome the issue with launching multiple instances of a particular
Services that wish to be controlled by the WinFsp.Launcher must add themselves under the following registry key:
HKEY_LOCAL_MACHINE\Software\WinFsp\Services
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services
NOTE: Please note that in a 64-bit system the actual location is `HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services`.
For example, the MEMFS sample adds the following registry entries under this key:
For example, the MEMFS sample adds the following registry entries in a 64-bit system:
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services\memfs32]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services\memfs32]
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x86.exe"
"CommandLine"="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2"
"CommandLine"="-u %1 -m %2"
"Security"="D:P(A;;RPWPLC;;;WD)"
"JobControl"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services\memfs64]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services\memfs64]
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x64.exe"
"CommandLine"="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2"
"CommandLine"="-u %1 -m %2"
"Security"="D:P(A;;RPWPLC;;;WD)"
"JobControl"=dword:00000001
@ -46,4 +44,4 @@ 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.
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 `-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 diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -16,21 +16,17 @@ WinFsp currently has the following test suites:
+
This test suite is developed together with WinFsp. It is written in C/C++ and provides a form of gray box testing.
- *Winfstest*: This is another test suite that verifies general file system functionality. It is not WinFsp specific and all its tests pass on NTFS.
- *Winfstest*: This is a file system test suite that was originally developed for the secfs.test collection of file system test programs by the WinFsp author. However none of its tests are WinFsp specific and all its tests pass on NTFS. Winfstest is used for testing by other Windows file systems.
+
This test suite is written in Python and C and was originally developed for the secfs.test collection of file system test programs by the WinFsp author. It provides a form of black box testing.
This test suite is written in Python and C. It provides a form of black box testing.
- *IfsTest*: This is Microsoft's Installable File System Test Suite. It is used to verify that WinFsp behavior closely resembles that of NTFS.
+
This test suite is part of the Windows Hardware Lab Kit (HLK). It provides a form of black box testing.
- *FSX*: This is Apple's FSX ported to Windows by the WinFsp author. FSX is very good at finding problems with read/write and memory-mapped I/O.
- *FSX*: This is Apple's FSX ported to Windows by the WinFsp author. This FSX port is not WinFsp specific and is used for testing by other Windows file systems.
- *Fscrash*: This is a tool that simulates a faulty or crashing user mode file system. It is used to test the fault tolerance of WinFsp.
+
This test is developed together with WinFsp. It is written in C/C++.
This test is WinFsp specific and is developed together with WinFsp. It is written in C/C++.
- *Fsbench*: This is a tool that can be used to test the performance of Windows file systems under different scenarios. It can work with any Windows file system and is not specific to WinFsp.
- *Fsbench*: This is a tool that can be used to test the performance of Windows file systems under different scenarios. It is not WinFsp specific.
+
This tool is currently developed together with WinFsp. It is written in C.
@ -38,7 +34,7 @@ These test suites and a few smaller tests are run through Continuous Integration
=== Test File System
WinFsp includes a test user mode file system called *MEMFS*. This is a simple in memory file system written in C/C++. MEMFS implements all file system features that WinFsp supports. MEMFS also performs various user mode file system checks during testing, for example, it checks that the buffer received during WRITE calls is read-only.
WinFsp includes a test user mode file system called *MEMFS*. This is a simple in memory file system written in C/C++. MEMFS attempts to achieve parity with NTFS (barring a few WinFsp limitations -- notably no support for hard links). MEMFS also performs some user mode file system checks during testing, for example, it checks that the buffer received during WRITE calls is read-only.
== Tested Scenarios
@ -95,12 +91,6 @@ if (!Success)
In Release builds the +DEBUGTEST(90)+ macro will evaluate to +TRUE+ and the Cache Manager will be asked directly via +CcCanIWrite+ whether a WRITE should be deferred. In Debug builds the +DEBUGTEST(90)+ macro will evaluate to +FALSE+ sometimes (10% of the time) and the WRITE will be deferred, thus allowing us to test the retry code path.
== Compatibility Testing
WinFsp allows the creation of user mode file systems that exhibit behavior similar to NTFS. This means that Windows applications that use such a file system should not be able to tell the difference between NTFS and the WinFsp-based file system. OTOH specialized applications (such as Defrag) will not work properly on WinFsp file systems.
WinFsp uses the winfsp-tests, winfstest and ifstest test suites for compatibility testing. These test suites verify that WinFsp and NTFS have very similar behavior. There is a separate document that examines the differences between WinFsp and NTFS in more detail.
== Fault Tolerance Testing
User mode file systems are normal user mode processes and as such they may fail in a variety of conditions. For example, a user mode file system may trigger an access violation while servicing a file operation. As another example, the developer of a user mode file system may terminate the file system process forcefully from within a debugger.

View File

@ -215,7 +215,7 @@ not need to perform access checks, but may performs tasks such as check for empt
directories, etc.
This function should **NEVER** delete the file or directory in question. Deletion should
happen during Cleanup with the FspCleanupDelete flag set.
happen during Cleanup with Delete==TRUE.
This function gets called when Win32 API's such as DeleteFile or RemoveDirectory are used.
It does not get called when a file or directory is opened with FILE\_DELETE\_ON\_CLOSE.
@ -233,14 +233,16 @@ It does not get called when a file or directory is opened with FILE\_DELETE\_ON\
FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext,
PWSTR FileName,
ULONG Flags);
BOOLEAN Delete);
**Parameters**
- _FileSystem_ \- The file system on which this request is posted.
- _FileContext_ \- The file context of the file or directory to cleanup.
- _FileName_ \- The name of the file or directory to cleanup. Sent only when a Delete is requested.
- _Flags_ \- These flags determine whether the file was modified and whether to delete the file.
- _Delete_ \- Determines whether to delete the file. Note that there is no way to report failure of
this operation. Also note that when this parameter is TRUE this is the last outstanding
cleanup for this particular file node.
**Discussion**
@ -251,43 +253,18 @@ file object. When all handles for a particular file object get closed (using Clo
the system sends a Cleanup request to the file system.
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
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!
The Flags parameter contains information about the cleanup operation:
- FspCleanupDelete -
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.
- FspCleanupSetAllocationSize -
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.
- FspCleanupSetArchiveBit -
File systems that support the archive bit should set the file node's archive bit when this
flag is set.
- FspCleanupSetLastAccessTime, FspCleanupSetLastWriteTime, FspCleanupSetChangeTime - 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.
There is no way to report failure of this operation. This is a Windows limitation.
As an optimization a file system may specify the FSP\_FSCTL\_VOLUME\_PARAMS ::
PostCleanupWhenModifiedOnly flag. In this case the FSD will only post Cleanup requests when
the file was modified/deleted.
PostCleanupOnDeleteOnly flag. In this case the FSD will only post Cleanup requests when a
file is being deleted.
**See Also**
@ -385,17 +362,12 @@ STATUS\_SUCCESS or error code.
:::c
NTSTATUS ( *Flush)(
FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext,
FSP_FSCTL_FILE_INFO *FileInfo);
PVOID FileContext);
**Parameters**
- _FileSystem_ \- The file system on which this request is posted.
- _FileContext_ \- The file context of the file to be flushed. When NULL the whole volume is being flushed.
- _FileInfo_ \- [out]
Pointer to a structure that will receive the file information on successful return
from this call. This information includes file attributes, file times, etc. Used when
flushing file (not volume).
**Return Value**
@ -616,8 +588,7 @@ STATUS\_SUCCESS or error code.
FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext,
UINT32 FileAttributes,
BOOLEAN ReplaceFileAttributes,
UINT64 AllocationSize,
BOOLEAN ReplaceFileAttributes,
FSP_FSCTL_FILE_INFO *FileInfo);
**Parameters**
@ -627,7 +598,6 @@ STATUS\_SUCCESS or error code.
- _FileAttributes_ \- File attributes to apply to the overwritten file.
- _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.
- _AllocationSize_ \- Allocation size for the overwritten file.
- _FileInfo_ \- [out]
Pointer to a structure that will receive the file information on successful return
from this call. This information includes file attributes, file times, etc.
@ -688,16 +658,6 @@ which is used solely by the file system to locate directory entries. However the
special value 0 indicates that the read should start from the first entries. The first
two entries returned by ReadDirectory should always be the "." and ".." entries,
except for the root directory which does not have these entries.
This parameter is used by the WinFsp FSD to break directory listings into chunks.
In this case all 64-bits of the Offset are valid. In some cases the Windows kernel
(NTOS) may also use this parameter. In this case only the lower 32-bits of this
parameter will be valid. This is an unfortunate limitation of Windows (for more
information see the documentation for IRP\_MJ\_DIRECTORY\_CONTROL and the flag
SL\_INDEX\_SPECIFIED).
In practice this means that you should only rely on the lower 32-bits of this value
to be valid.
- _Length_ \- Length of data to read.
- _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
@ -742,6 +702,10 @@ STATUS\_SUCCESS or error code.
The kernel mode FSD provides certain guarantees prior to posting a rename operation:
- A file cannot be renamed if it has any open handles, other than the one used to perform
the rename.
- A file cannot be renamed if a file with the same name exists and has open handles.
@ -811,8 +775,7 @@ should be returned to the FSD with status STATUS\_REPARSE/IO\_REPARSE.
UINT32 FileAttributes,
UINT64 CreationTime,
UINT64 LastAccessTime,
UINT64 LastWriteTime,
UINT64 ChangeTime,
UINT64 LastWriteTime,
FSP_FSCTL_FILE_INFO *FileInfo);
**Parameters**
@ -827,8 +790,6 @@ time should not be changed.
access time should not be changed.
- _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.
- _ChangeTime_ \- Change time to apply to the file or directory. If the value 0 is sent, the change time
should not be changed.
- _FileInfo_ \- [out]
Pointer to a structure that will receive the file information on successful return
from this call. This information includes file attributes, file times, etc.
@ -925,7 +886,8 @@ STATUS\_SUCCESS or error code.
FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR ModificationDescriptor);
PSECURITY_DESCRIPTOR ModificationDescriptor,
HANDLE AccessToken);
**Parameters**
@ -934,6 +896,8 @@ STATUS\_SUCCESS or error code.
- _SecurityInformation_ \- Describes what parts of the file or directory security descriptor should
be modified.
- _ModificationDescriptor_ \- Describes the modifications to apply to the file or directory security descriptor.
- _AccessToken_ \- A handle to a token that can be used to verify whether the requested modifications
are allowed.
**Return Value**
@ -1499,6 +1463,7 @@ file system requests from the kernel.
PSECURITY_DESCRIPTOR InputDescriptor,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR ModificationDescriptor,
HANDLE AccessToken,
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
**Parameters**
@ -1508,6 +1473,9 @@ file system requests from the kernel.
the same value passed to the SetSecurity SecurityInformation parameter.
- _ModificationDescriptor_ \- Describes the modifications to apply to the InputDescriptor. This should contain
the same value passed to the SetSecurity ModificationDescriptor parameter.
- _AccessToken_ \- A handle to a token that can be used to verify whether the requested modifications
are allowed. This should contain the same value passed to the SetSecurity AccessToken
parameter.
- _PSecurityDescriptor_ \- [out]
Pointer to a memory location that will receive the resulting security descriptor.
This security descriptor can be later freed using FspDeleteSecurityDescriptor.

View File

@ -1,7 +1,7 @@
/**
* @file tlib/callstack.c
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#include <tlib/callstack.h>

View File

@ -1,7 +1,7 @@
/**
* @file tlib/callstack.h
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#ifndef TLIB_CALLSTACK_H_INCLUDED

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injected/allfunc.h
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#ifndef TLIB_INJECTED_ALLFUNC_H_INCLUDED

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injected/curlfunc.c
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#include <tlib/injected/curlfunc.h>

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injected/curlfunc.h
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#ifndef TLIB_INJECTED_CURLFUNC_H_INCLUDED

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injected/stdfunc.c
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#include <tlib/injected/stdfunc.h>

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injected/stdfunc.h
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#ifndef TLIB_INJECTED_STDFUNC_H_INCLUDED

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injection.c
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#include <tlib/injection.h>

View File

@ -1,7 +1,7 @@
/**
* @file tlib/injection.h
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
/* NOTE: This header may usefully be included multiple times.

View File

@ -1,7 +1,7 @@
/**
* @file tlib/testsuite.c
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#include <tlib/testsuite.h>

View File

@ -1,7 +1,7 @@
/**
* @file tlib/testsuite.h
*
* @copyright 2014-2017 Bill Zissimopoulos
* @copyright 2014-2015 Bill Zissimopoulos
*/
#ifndef TLIB_TESTSUITE_H_INCLUDED

View File

@ -6,7 +6,7 @@
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -6,7 +6,7 @@
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -6,7 +6,7 @@
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -2,7 +2,7 @@
* @file fuse/winfsp_fuse.h
* WinFsp FUSE compatible API.
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file winfsp/fsctl.h
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -146,9 +146,8 @@ typedef struct
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
UINT32 ReadOnlyVolume:1;
/* kernel-mode flags */
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */
UINT32 KmReservedFlags:4;
UINT32 PostCleanupOnDeleteOnly:1; /* post Cleanup when deleting a file only */
UINT32 KmReservedFlags:5;
/* user-mode flags */
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
@ -186,7 +185,8 @@ typedef struct
{
UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo;
UINT8 Padding[24];
UINT64 NextOffset;
UINT8 Padding[16];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
WCHAR FileNameBuf[];
} FSP_FSCTL_DIR_INFO;
@ -232,8 +232,7 @@ typedef struct
UINT32 HasRestorePrivilege:1; /* requestor has TOKEN_HAS_RESTORE_PRIVILEGE */
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
UINT32 HasTrailingBackslash:1; /* FileName had trailing backslash */
UINT32 ReservedFlags:25;
UINT32 ReservedFlags:26;
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
} Create;
struct
@ -249,11 +248,6 @@ typedef struct
UINT64 UserContext;
UINT64 UserContext2;
UINT32 Delete:1; /* file must be deleted */
UINT32 SetAllocationSize:1;
UINT32 SetArchiveBit:1;
UINT32 SetLastAccessTime:1;
UINT32 SetLastWriteTime:1;
UINT32 SetChangeTime:1;
} Cleanup;
struct
{
@ -301,7 +295,6 @@ typedef struct
UINT64 CreationTime;
UINT64 LastAccessTime;
UINT64 LastWriteTime;
UINT64 ChangeTime;
} Basic;
struct
{
@ -339,9 +332,9 @@ typedef struct
UINT64 UserContext;
UINT64 UserContext2;
UINT64 Address;
UINT64 Offset;
UINT32 Length;
FSP_FSCTL_TRANSACT_BUF Pattern;
FSP_FSCTL_TRANSACT_BUF Marker;
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
} QueryDirectory;
struct
@ -422,10 +415,6 @@ typedef struct
FSP_FSCTL_FILE_INFO FileInfo; /* valid: File{Allocation,Basic,EndOfFile}Information */
} SetInformation;
struct
{
FSP_FSCTL_FILE_INFO FileInfo; /* valid when flushing file (not volume) */
} FlushBuffers;
struct
{
FSP_FSCTL_VOLUME_INFO VolumeInfo;
} QueryVolumeInformation;

View File

@ -5,7 +5,7 @@
* In order to use the WinFsp API the user mode file system must include &lt;winfsp/winfsp.h&gt;
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -122,15 +122,6 @@ typedef enum
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE = 0,
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE,
} FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY;
enum
{
FspCleanupDelete = 0x01,
FspCleanupSetAllocationSize = 0x02,
FspCleanupSetArchiveBit = 0x10,
FspCleanupSetLastAccessTime = 0x20,
FspCleanupSetLastWriteTime = 0x40,
FspCleanupSetChangeTime = 0x80,
};
/**
* @class FSP_FILE_SYSTEM
* File system interface.
@ -331,40 +322,18 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* the system sends a Cleanup request to the file system.
*
* There will be a Cleanup operation for every Create or Open operation posted to the user mode
* file system. However the Cleanup operation is <b>not</b> the final close operation on a file.
* The file system must be ready to receive additional operations until close time. This is true
* file system. However the Cleanup operation is <b>not</b> 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!
*
* The Flags parameter contains information about the cleanup operation:
* <ul>
* <li>FspCleanupDelete -
* 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.
* </li>
* <li>FspCleanupSetAllocationSize -
* 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.
* </li>
* <li>
* FspCleanupSetArchiveBit -
* File systems that support the archive bit should set the file node's archive bit when this
* flag is set.
* </li>
* <li>FspCleanupSetLastAccessTime, FspCleanupSetLastWriteTime, FspCleanupSetChangeTime - 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.
* </ul>
*
* There is no way to report failure of this operation. This is a Windows limitation.
*
* As an optimization a file system may specify the FSP_FSCTL_VOLUME_PARAMS ::
* PostCleanupWhenModifiedOnly flag. In this case the FSD will only post Cleanup requests when
* the file was modified/deleted.
* PostCleanupOnDeleteOnly flag. In this case the FSD will only post Cleanup requests when a
* file is being deleted.
*
* @param FileSystem
* The file system on which this request is posted.
@ -372,14 +341,16 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* The file context of the file or directory to cleanup.
* @param FileName
* The name of the file or directory to cleanup. Sent only when a Delete is requested.
* @param Flags
* These flags determine whether the file was modified and whether to delete the file.
* @param Delete
* Determines whether to delete the file. Note that there is no way to report failure of
* this operation. Also note that when this parameter is TRUE this is the last outstanding
* cleanup for this particular file node.
* @see
* Close
* CanDelete
*/
VOID (*Cleanup)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, PWSTR FileName, ULONG Flags);
PVOID FileContext, PWSTR FileName, BOOLEAN Delete);
/**
* Close a file.
*
@ -452,16 +423,11 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* The file system on which this request is posted.
* @param FileContext
* The file context of the file to be flushed. When NULL the whole volume is being flushed.
* @param FileInfo [out]
* Pointer to a structure that will receive the file information on successful return
* from this call. This information includes file attributes, file times, etc. Used when
* flushing file (not volume).
* @return
* STATUS_SUCCESS or error code.
*/
NTSTATUS (*Flush)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext,
FSP_FSCTL_FILE_INFO *FileInfo);
PVOID FileContext);
/**
* Get file or directory information.
*
@ -497,9 +463,6 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* @param 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 ChangeTime
* Change time to apply to the file or directory. If the value 0 is sent, the change time
* should not be changed.
* @param FileInfo [out]
* Pointer to a structure that will receive the file information on successful return
* from this call. This information includes file attributes, file times, etc.
@ -508,7 +471,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
*/
NTSTATUS (*SetBasicInfo)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, UINT32 FileAttributes,
UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime,
UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime,
FSP_FSCTL_FILE_INFO *FileInfo);
/**
* Set file/allocation size.
@ -555,7 +518,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* directories, etc.
*
* This function should <b>NEVER</b> delete the file or directory in question. Deletion should
* happen during Cleanup with the FspCleanupDelete flag set.
* happen during Cleanup with Delete==TRUE.
*
* This function gets called when Win32 API's such as DeleteFile or RemoveDirectory are used.
* It does not get called when a file or directory is opened with FILE_DELETE_ON_CLOSE.
@ -578,6 +541,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
*
* The kernel mode FSD provides certain guarantees prior to posting a rename operation:
* <ul>
* <li>A file cannot be renamed if it has any open handles, other than the one used to perform
* the rename.</li>
* <li>A file cannot be renamed if a file with the same name exists and has open handles.</li>
* <li>A directory cannot be renamed if it or any of its subdirectories contains a file that
* has open handles.</li>
@ -647,18 +612,30 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* The file system on which this request is posted.
* @param FileContext
* The file context of the directory to be read.
* @param Buffer
* Pointer to a buffer that will receive the results of the read operation.
* @param Offset
* Offset within the directory to read from. The kernel does not interpret this value
* which is used solely by the file system to locate directory entries. However the
* special value 0 indicates that the read should start from the first entries. The first
* two entries returned by ReadDirectory should always be the "." and ".." entries,
* except for the root directory which does not have these entries.
*
* This parameter is used by the WinFsp FSD to break directory listings into chunks.
* In this case all 64-bits of the Offset are valid. In some cases the Windows kernel
* (NTOS) may also use this parameter. In this case only the lower 32-bits of this
* parameter will be valid. This is an unfortunate limitation of Windows (for more
* information see the documentation for IRP_MJ_DIRECTORY_CONTROL and the flag
* SL_INDEX_SPECIFIED).
*
* In practice this means that you should only rely on the lower 32-bits of this value
* to be valid.
* @param Length
* Length of data to read.
* @param 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 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 Buffer
* Pointer to a buffer that will receive the results of the read operation.
* @param Length
* Length of data to read.
* @param PBytesTransferred [out]
* Pointer to a memory location that will receive the actual number of bytes read.
* @return
@ -668,8 +645,9 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* FspFileSystemAddDirInfo
*/
NTSTATUS (*ReadDirectory)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, PWSTR Pattern, PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length,
PWSTR Pattern,
PULONG PBytesTransferred);
/**
* Resolve reparse points.
*
@ -832,20 +810,6 @@ typedef struct _FSP_FILE_SYSTEM_OPERATION_CONTEXT
FSP_FSCTL_TRANSACT_REQ *Request;
FSP_FSCTL_TRANSACT_RSP *Response;
} FSP_FILE_SYSTEM_OPERATION_CONTEXT;
/**
* Check whether creating a file system object is possible.
*
* @param DevicePath
* The name of the control device for this file system. This must be either
* FSP_FSCTL_DISK_DEVICE_NAME or FSP_FSCTL_NET_DEVICE_NAME.
* @param 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.
* @return
* STATUS_SUCCESS or error code.
*/
FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
PWSTR MountPoint);
/**
* Create a file system object.
*
@ -1293,19 +1257,6 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
/*
* Directory buffering
*/
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
BOOLEAN Reset, PNTSTATUS PResult);
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult);
FSP_API VOID FspFileSystemReleaseDirectoryBuffer(PVOID *PDirBuffer);
FSP_API VOID FspFileSystemReadDirectoryBuffer(PVOID *PDirBuffer,
PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
FSP_API VOID FspFileSystemDeleteDirectoryBuffer(PVOID *PDirBuffer);
/*
* Security
*/
@ -1403,8 +1354,6 @@ NTSTATUS FspPosixMapPosixToWindowsPath(const char *PosixPath, PWSTR *PWindowsPat
return FspPosixMapPosixToWindowsPathEx(PosixPath, PWindowsPath, TRUE);
}
FSP_API VOID FspPosixDeletePath(void *Path);
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size);
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size);
/*
* Path Handling
@ -1626,58 +1575,6 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
PULONG PBytesTransferred, ULONG Timeout,
PSID Sid);
/*
* Delay load
*/
static inline
NTSTATUS FspLoad(PVOID *PModule)
{
#if defined(_WIN64)
#define FSP_DLLNAME "winfsp-x64.dll"
#else
#define FSP_DLLNAME "winfsp-x86.dll"
#endif
#define FSP_DLLPATH "bin\\" FSP_DLLNAME
WCHAR PathBuf[MAX_PATH];
DWORD Size;
HKEY RegKey;
LONG Result;
HMODULE Module;
if (0 != PModule)
*PModule = 0;
Module = LoadLibraryW(L"" FSP_DLLNAME);
if (0 == Module)
{
Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\WinFsp",
0, KEY_READ | KEY_WOW64_32KEY, &RegKey);
if (ERROR_SUCCESS == Result)
{
Size = sizeof PathBuf - sizeof L"" FSP_DLLPATH + sizeof(WCHAR);
Result = RegGetValueW(RegKey, 0, L"InstallDir",
RRF_RT_REG_SZ, 0, PathBuf, &Size);
RegCloseKey(RegKey);
}
if (ERROR_SUCCESS != Result)
return STATUS_OBJECT_NAME_NOT_FOUND;
RtlCopyMemory(PathBuf + (Size / sizeof(WCHAR) - 1), L"" FSP_DLLPATH, sizeof L"" FSP_DLLPATH);
Module = LoadLibraryW(PathBuf);
if (0 == Module)
return STATUS_DLL_NOT_FOUND;
}
if (0 != PModule)
*PModule = Module;
return STATUS_SUCCESS;
#undef FSP_DLLNAME
#undef FSP_DLLPATH
}
#ifdef __cplusplus
}
#endif

View File

@ -1,7 +1,7 @@
/**
* @file cygfuse/cygfuse.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/debug.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -106,7 +106,7 @@ static const char *FspDebugLogDispositionString(UINT32 CreateOptions)
static const char *FspDebugLogUserContextString(UINT64 UserContext, UINT64 UserContext2, char *Buf)
{
wsprintfA(Buf, 0 == UserContext2 ? "%p" : "%p:%p", (PVOID)UserContext, (PVOID)UserContext2);
wsprintfA(Buf, 0 == UserContext2 ? "%p" : "%p:%p", UserContext, UserContext2);
return Buf;
}
@ -269,13 +269,13 @@ static const char *FspDebugLogReparseDataString(PVOID ReparseData0, char *Buf)
static VOID FspDebugLogRequestVoid(FSP_FSCTL_TRANSACT_REQ *Request, const char *Name)
{
FspDebugLog("%S[TID=%04lx]: %p: >>%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint, Name);
FspDiagIdent(), GetCurrentThreadId(), Request->Hint, Name);
}
static VOID FspDebugLogResponseStatus(FSP_FSCTL_TRANSACT_RSP *Response, const char *Name)
{
FspDebugLog("%S[TID=%04lx]: %p: <<%s IoStatus=%lx[%ld]\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint, Name,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint, Name,
Response->IoStatus.Status, Response->IoStatus.Information);
}
@ -304,7 +304,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
"AllocationSize=%lx:%lx, "
"AccessToken=%p, DesiredAccess=%lx, GrantedAccess=%lx, "
"ShareAccess=%lx\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->Req.Create.UserMode ? 'U' : 'K',
Request->Req.Create.HasTraversePrivilege ? 'T' : '-',
Request->Req.Create.HasBackupPrivilege ? 'B' : '-',
@ -328,7 +328,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case FspFsctlTransactOverwriteKind:
FspDebugLog("%S[TID=%04lx]: %p: >>Overwrite%s %s%S%s%s, "
"FileAttributes=%lx\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->Req.Overwrite.Supersede ? " [Supersede]" : "",
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
@ -340,7 +340,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
case FspFsctlTransactCleanupKind:
FspDebugLog("%S[TID=%04lx]: %p: >>Cleanup%s %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->Req.Cleanup.Delete ? " [Delete]" : "",
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
@ -351,7 +351,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
case FspFsctlTransactCloseKind:
FspDebugLog("%S[TID=%04lx]: %p: >>Close %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -362,14 +362,14 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case FspFsctlTransactReadKind:
FspDebugLog("%S[TID=%04lx]: %p: >>Read %s%S%s%s, "
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
FspDebugLogUserContextString(
Request->Req.Read.UserContext, Request->Req.Read.UserContext2,
UserContextBuf),
(PVOID)Request->Req.Read.Address,
Request->Req.Read.Address,
MAKE_UINT32_PAIR(Request->Req.Read.Offset),
Request->Req.Read.Length,
Request->Req.Read.Key);
@ -377,7 +377,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case FspFsctlTransactWriteKind:
FspDebugLog("%S[TID=%04lx]: %p: >>Write%s %s%S%s%s, "
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->Req.Write.ConstrainedIo ? " [C]" : "",
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
@ -385,14 +385,14 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
FspDebugLogUserContextString(
Request->Req.Write.UserContext, Request->Req.Write.UserContext2,
UserContextBuf),
(PVOID)Request->Req.Write.Address,
Request->Req.Write.Address,
MAKE_UINT32_PAIR(Request->Req.Write.Offset),
Request->Req.Write.Length,
Request->Req.Write.Key);
break;
case FspFsctlTransactQueryInformationKind:
FspDebugLog("%S[TID=%04lx]: %p: >>QueryInformation %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -406,7 +406,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case 4/*FileBasicInformation*/:
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Basic] %s%S%s%s, "
"FileAttributes=%lx, CreationTime=%s, LastAccessTime=%s, LastWriteTime=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -424,7 +424,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case 19/*FileAllocationInformation*/:
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Allocation] %s%S%s%s, "
"AllocationSize=%lx:%lx\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -436,7 +436,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case 20/*FileEndOfFileInformation*/:
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [EndOfFile] %s%S%s%s, "
"FileSize = %lx:%lx\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -448,7 +448,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case 13/*FileDispositionInformation*/:
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Disposition] %s%S%s%s, "
"%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -460,7 +460,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case 10/*FileRenameInformation*/:
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Rename] %s%S%s%s, "
"NewFileName=\"%S\", AccessToken=%p\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -472,7 +472,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
default:
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [INVALID] %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -490,7 +490,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
case FspFsctlTransactFlushBuffersKind:
FspDebugLog("%S[TID=%04lx]: %p: >>FlushBuffers %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -507,42 +507,39 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case 2/*FileFsLabelInformation*/:
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [FsLabel] "
"Label=\"%S\"\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
(PWSTR)Request->Buffer);
break;
default:
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [INVALID]\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint);
FspDiagIdent(), GetCurrentThreadId(), Request->Hint);
break;
}
break;
case FspFsctlTransactQueryDirectoryKind:
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
"Address=%p, Length=%ld, Pattern=%s%S%s, Marker=%s%S%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
"Address=%p, Offset=%lx:%lx, Length=%ld, Pattern=%s%S%s\n",
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
FspDebugLogUserContextString(
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
UserContextBuf),
(PVOID)Request->Req.QueryDirectory.Address,
Request->Req.QueryDirectory.Address,
MAKE_UINT32_PAIR(Request->Req.QueryDirectory.Offset),
Request->Req.QueryDirectory.Length,
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
Request->Req.QueryDirectory.Pattern.Size ?
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
Request->Req.QueryDirectory.Marker.Size ? "\"" : "",
Request->Req.QueryDirectory.Marker.Size ?
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : L"NULL",
Request->Req.QueryDirectory.Marker.Size ? "\"" : "");
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "");
break;
case FspFsctlTransactFileSystemControlKind:
switch (Request->Req.FileSystemControl.FsControlCode)
{
case FSCTL_GET_REPARSE_POINT:
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [FSCTL_GET_REPARSE_POINT] %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -554,7 +551,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
case FSCTL_DELETE_REPARSE_POINT:
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [%s] %s%S%s%s "
"ReparseData=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode ?
"FSCTL_SET_REPARSE_POINT" : "FSCTL_DELETE_REPARSE_POINT",
Request->FileName.Size ? "\"" : "",
@ -568,7 +565,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
default:
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [INVALID] %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -589,7 +586,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
case FspFsctlTransactQuerySecurityKind:
FspDebugLog("%S[TID=%04lx]: %p: >>QuerySecurity %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -607,7 +604,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
&Sddl, 0);
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
"SecurityInformation=%lx, Security=%s%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -622,7 +619,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
break;
case FspFsctlTransactQueryStreamInformationKind:
FspDebugLog("%S[TID=%04lx]: %p: >>QueryStreamInformation %s%S%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
Request->FileName.Size ? "\"" : "",
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
Request->FileName.Size ? "\", " : "",
@ -658,7 +655,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
if (0/*IO_REPARSE*/ == Response->IoStatus.Information)
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
"Reparse.FileName=\"%s\"\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogWideCharBufferString(
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
@ -669,7 +666,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
"Reparse.Data=\"%s\"\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogReparseDataString(
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
@ -678,7 +675,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
"UserContext=%s, GrantedAccess=%lx, FileInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogUserContextString(
Response->Rsp.Create.Opened.UserContext, Response->Rsp.Create.Opened.UserContext2,
@ -692,7 +689,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<Overwrite IoStatus=%lx[%ld] "
"FileInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogFileInfoString(&Response->Rsp.Overwrite.FileInfo, InfoBuf));
break;
@ -711,7 +708,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<Write IoStatus=%lx[%ld] "
"FileInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogFileInfoString(&Response->Rsp.Write.FileInfo, InfoBuf));
break;
@ -721,7 +718,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<QueryInformation IoStatus=%lx[%ld] "
"FileInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogFileInfoString(&Response->Rsp.QueryInformation.FileInfo, InfoBuf));
break;
@ -731,7 +728,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<SetInformation IoStatus=%lx[%ld] "
"FileInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogFileInfoString(&Response->Rsp.SetInformation.FileInfo, InfoBuf));
break;
@ -750,7 +747,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<QueryVolumeInformation IoStatus=%lx[%ld] "
"VolumeInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogVolumeInfoString(&Response->Rsp.QueryVolumeInformation.VolumeInfo, InfoBuf));
break;
@ -760,7 +757,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<SetVolumeInformation IoStatus=%lx[%ld] "
"VolumeInfo=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogVolumeInfoString(&Response->Rsp.SetVolumeInformation.VolumeInfo, InfoBuf));
break;
@ -774,7 +771,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
else
FspDebugLog("%S[TID=%04lx]: %p: <<FileSystemControl IoStatus=%lx[%ld] "
"ReparseData=%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
FspDebugLogReparseDataString(Response->Buffer + Response->Rsp.FileSystemControl.Buffer.Offset,
InfoBuf));
@ -802,7 +799,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
&Sddl, 0);
FspDebugLog("%S[TID=%04lx]: %p: <<QuerySecurity IoStatus=%lx[%ld] "
"Security=%s%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
Sddl ? "\"" : "",
Sddl ? Sddl : "NULL",
@ -824,7 +821,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
&Sddl, 0);
FspDebugLog("%S[TID=%04lx]: %p: <<SetSecurity IoStatus=%lx[%ld] "
"Security=%s%s%s\n",
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
Response->IoStatus.Status, Response->IoStatus.Information,
Sddl ? "\"" : "",
Sddl ? Sddl : "NULL",

View File

@ -1,404 +0,0 @@
/**
* @file dll/dirbuf.c
*
* @copyright 2015-2017 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*/
#include <dll/library.h>
#define RETURN(R, B) \
do \
{ \
if (0 != PResult) \
*PResult = R; \
return B; \
} while (0,0)
typedef struct
{
SRWLOCK Lock;
ULONG Capacity, LoMark, HiMark;
PUINT8 Buffer;
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
static int FspFileSystemDirectoryBufferFileNameCmp(PWSTR a, int alen, PWSTR b, int blen)
{
int len, res;
if (-1 == alen)
alen = (int)lstrlenW(a);
if (-1 == blen)
blen = (int)lstrlenW(b);
len = alen < blen ? alen : blen;
/* order "." and ".." first */
switch (alen)
{
case 1:
if (L'.' == a[0])
a = L"\1";
break;
case 2:
if (L'.' == a[0] && L'.' == a[1])
a = L"\1\1";
break;
}
/* order "." and ".." first */
switch (blen)
{
case 1:
if (L'.' == b[0])
b = L"\1";
break;
case 2:
if (L'.' == b[0] && L'.' == b[1])
b = L"\1\1";
break;
}
res = invariant_wcsncmp(a, b, len);
if (0 == res)
res = alen - blen;
return res;
}
/*
* Binary search
* "I wish I had the standard library!"
*/
static BOOLEAN FspFileSystemSearchDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer,
PWSTR Marker, int MarkerLen, PULONG PIndexNum)
{
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
FSP_FSCTL_DIR_INFO *DirInfo;
int Lo = 0, Hi = Count - 1, Mi;
int CmpResult;
while (Lo <= Hi)
{
Mi = (unsigned)(Lo + Hi) >> 1;
DirInfo = (PVOID)(DirBuffer->Buffer + Index[Mi]);
CmpResult = FspFileSystemDirectoryBufferFileNameCmp(
DirInfo->FileNameBuf, (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR),
Marker, MarkerLen);
if (0 > CmpResult)
Lo = Mi + 1;
else if (0 < CmpResult)
Hi = Mi - 1;
else
{
*PIndexNum = Mi;
return TRUE;
}
}
*PIndexNum = Lo;
return FALSE;
}
/*
* Quick sort
* "I wish I had the standard library!"
*
* Based on Sedgewick's Algorithms in C++; multiple editions.
*
* Implements a non-recursive quicksort with tail-end recursion eliminated
* and median-of-three partitioning.
*/
#define less(a, b) FspFileSystemDirectoryBufferLess(Buffer, a, b)
#define exch(a, b) { ULONG t = a; a = b; b = t; }
#define compexch(a, b) if (less(b, a)) exch(a, b)
#define push(i) (stack[stackpos++] = (i))
#define pop() (stack[--stackpos])
static __forceinline
int FspFileSystemDirectoryBufferLess(PUINT8 Buffer, int a, int b)
{
FSP_FSCTL_DIR_INFO *DirInfoA = (FSP_FSCTL_DIR_INFO *)(Buffer + a);
FSP_FSCTL_DIR_INFO *DirInfoB = (FSP_FSCTL_DIR_INFO *)(Buffer + b);
return 0 > FspFileSystemDirectoryBufferFileNameCmp(
DirInfoA->FileNameBuf, (DirInfoA->Size - sizeof *DirInfoA) / sizeof(WCHAR),
DirInfoB->FileNameBuf, (DirInfoB->Size - sizeof *DirInfoB) / sizeof(WCHAR));
}
static __forceinline
int FspFileSystemPartitionDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l, int r)
{
int i = l - 1, j = r;
ULONG v = Index[r];
for (;;)
{
while (less(Index[++i], v))
;
while (less(v, Index[--j]))
if (j == l)
break;
if (i >= j)
break;
exch(Index[i], Index[j]);
}
exch(Index[i], Index[r]);
return i;
}
static VOID FspFileSystemQSortDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l, int r)
{
int stack[64], stackpos = 0;
int i;
for (;;)
{
while (r > l)
{
#if 0
exch(Index[(l + r) / 2], Index[r - 1]);
compexch(Index[l], Index[r - 1]);
compexch(Index[l], Index[r]);
compexch(Index[r - 1], Index[r]);
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l + 1, r - 1);
#else
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l, r);
#endif
if (i - l > r - i)
{
push(l); push(i - 1);
l = i + 1;
}
else
{
push(i + 1); push(r);
r = i - 1;
}
}
if (0 == stackpos)
break;
r = pop(); l = pop();
}
}
#undef push
#undef pop
#undef less
#undef compexch
#undef exch
static inline VOID FspFileSystemSortDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer)
{
PUINT8 Buffer = DirBuffer->Buffer;
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
FspFileSystemQSortDirectoryBuffer(Buffer, Index, 0, Count - 1);
}
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
BOOLEAN Reset, PNTSTATUS PResult)
{
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 == DirBuffer)
{
static SRWLOCK CreateLock = SRWLOCK_INIT;
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *NewDirBuffer;
NewDirBuffer = MemAlloc(sizeof *NewDirBuffer);
if (0 == NewDirBuffer)
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
memset(NewDirBuffer, 0, sizeof *NewDirBuffer);
InitializeSRWLock(&NewDirBuffer->Lock);
AcquireSRWLockExclusive(&NewDirBuffer->Lock);
AcquireSRWLockExclusive(&CreateLock);
DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 == DirBuffer)
*PDirBuffer = DirBuffer = NewDirBuffer;
ReleaseSRWLockExclusive(&CreateLock);
if (DirBuffer == NewDirBuffer)
RETURN(STATUS_SUCCESS, TRUE);
ReleaseSRWLockExclusive(&NewDirBuffer->Lock);
MemFree(NewDirBuffer);
}
if (Reset)
{
AcquireSRWLockExclusive(&DirBuffer->Lock);
DirBuffer->LoMark = 0;
DirBuffer->HiMark = DirBuffer->Capacity;
RETURN(STATUS_SUCCESS, TRUE);
}
RETURN(STATUS_SUCCESS, FALSE);
}
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult)
{
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
ULONG Capacity, LoMark, HiMark;
PUINT8 Buffer;
if (0 == DirInfo)
RETURN(STATUS_INVALID_PARAMETER, FALSE);
for (;;)
{
LoMark = DirBuffer->LoMark;
HiMark = DirBuffer->HiMark;
Buffer = DirBuffer->Buffer;
if (FspFileSystemAddDirInfo(DirInfo,
Buffer,
HiMark > sizeof(ULONG) ? HiMark - sizeof(ULONG)/*space for new index entry*/ : HiMark,
&LoMark))
{
HiMark -= sizeof(ULONG);
*(PULONG)(Buffer + HiMark) = DirBuffer->LoMark;
DirBuffer->LoMark = LoMark;
DirBuffer->HiMark = HiMark;
RETURN (STATUS_SUCCESS, TRUE);
}
if (0 == Buffer)
{
Buffer = MemAlloc(Capacity = 512);
if (0 == Buffer)
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
HiMark = Capacity;
}
else
{
Buffer = MemRealloc(Buffer, Capacity = DirBuffer->Capacity * 2);
if (0 == Buffer)
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
ULONG IndexSize = DirBuffer->Capacity - HiMark;
ULONG NewHiMark = Capacity - IndexSize;
memmove(Buffer + NewHiMark, Buffer + HiMark, IndexSize);
HiMark = NewHiMark;
}
DirBuffer->Capacity = Capacity;
DirBuffer->LoMark = LoMark;
DirBuffer->HiMark = HiMark;
DirBuffer->Buffer = Buffer;
}
}
FSP_API VOID FspFileSystemReleaseDirectoryBuffer(PVOID *PDirBuffer)
{
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
FspFileSystemSortDirectoryBuffer(DirBuffer);
ReleaseSRWLockExclusive(&DirBuffer->Lock);
}
FSP_API VOID FspFileSystemReadDirectoryBuffer(PVOID *PDirBuffer,
PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 != DirBuffer)
{
AcquireSRWLockShared(&DirBuffer->Lock);
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
ULONG IndexNum;
FSP_FSCTL_DIR_INFO *DirInfo;
if (0 == Marker)
IndexNum = 0;
else
{
FspFileSystemSearchDirectoryBuffer(DirBuffer,
Marker, lstrlenW(Marker),
&IndexNum);
IndexNum++;
}
for (; IndexNum < Count; IndexNum++)
{
DirInfo = (PVOID)(DirBuffer->Buffer + Index[IndexNum]);
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
{
ReleaseSRWLockShared(&DirBuffer->Lock);
return;
}
}
ReleaseSRWLockShared(&DirBuffer->Lock);
}
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
}
FSP_API VOID FspFileSystemDeleteDirectoryBuffer(PVOID *PDirBuffer)
{
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 != DirBuffer)
{
MemFree(DirBuffer->Buffer);
MemFree(DirBuffer);
*PDirBuffer = 0;
}
}
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount)
{
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
*PBuffer = DirBuffer->Buffer;
*PIndex = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
*PCount = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
}

View File

@ -1,7 +1,7 @@
/**
* @file dll/eventlog.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fs.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -72,48 +72,6 @@ VOID FspFileSystemFinalize(BOOLEAN Dynamic)
TlsFree(FspFileSystemTlsKey);
}
FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
PWSTR MountPoint)
{
NTSTATUS Result;
WCHAR TargetPath[MAX_PATH];
HANDLE DirHandle;
Result = FspFsctlPreflight(DevicePath);
if (!NT_SUCCESS(Result))
return Result;
if (0 == MountPoint)
Result = STATUS_SUCCESS;
else
{
if (FspPathIsDrive(MountPoint))
Result = QueryDosDeviceW(MountPoint, TargetPath, MAX_PATH) ?
STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
else
{
DirHandle = CreateFileW(MountPoint,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
0);
if (INVALID_HANDLE_VALUE != DirHandle)
{
CloseHandle(DirHandle);
Result = STATUS_OBJECT_NAME_COLLISION;
}
else if (ERROR_FILE_NOT_FOUND != GetLastError())
Result = STATUS_OBJECT_NAME_INVALID;
else
Result = STATUS_SUCCESS;
}
}
return Result;
}
FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
const FSP_FILE_SYSTEM_INTERFACE *Interface,

View File

@ -1,7 +1,7 @@
/**
* @file dll/fsctl.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fsop.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -189,16 +189,9 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
ParentDesiredAccess = FILE_ADD_SUBDIRECTORY;
else
ParentDesiredAccess = FILE_ADD_FILE;
if (Request->Req.Create.HasTrailingBackslash &&
!(Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE))
Result = STATUS_OBJECT_NAME_INVALID;
else if ((Request->Req.Create.FileAttributes & FILE_ATTRIBUTE_READONLY) &&
(Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE))
Result = STATUS_CANNOT_DELETE;
else
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
ParentDesiredAccess,
&GrantedAccess, PSecurityDescriptor);
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
ParentDesiredAccess,
&GrantedAccess, PSecurityDescriptor);
if (STATUS_REPARSE == Result)
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
else if (NT_SUCCESS(Result))
@ -212,14 +205,11 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
{
*PSecurityDescriptor = 0;
if (Request->Req.Create.HasTrailingBackslash)
Result = STATUS_OBJECT_NAME_INVALID;
else
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
Request->Req.Create.DesiredAccess |
FILE_WRITE_DATA |
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
&GrantedAccess, 0);
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
Request->Req.Create.DesiredAccess |
FILE_WRITE_DATA |
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
&GrantedAccess, 0);
if (STATUS_REPARSE == Result)
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
else if (NT_SUCCESS(Result))
@ -556,6 +546,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
UINT32 GrantedAccess;
FSP_FSCTL_TRANSACT_FULL_CONTEXT FullContext;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
Result = FspFileSystemOverwriteCheck(FileSystem, Request, Response, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
@ -579,7 +570,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = FILE_OVERWRITTEN;
Response->IoStatus.Information = Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
SetFileContext(Response->Rsp.Create.Opened, FullContext);
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo,
@ -595,7 +586,6 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
PSECURITY_DESCRIPTOR ParentDescriptor, ObjectDescriptor;
FSP_FSCTL_TRANSACT_FULL_CONTEXT FullContext;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
BOOLEAN Create = FALSE;
Result = FspFileSystemOverwriteCheck(FileSystem, Request, Response, TRUE, &GrantedAccess);
@ -657,8 +647,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = Create ? FILE_CREATED :
(Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN);
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OVERWRITTEN;
SetFileContext(Response->Rsp.Create.Opened, FullContext);
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo,
@ -827,10 +816,10 @@ FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem,
Result = FspFileSystemOpCreate_FileOpenIf(FileSystem, Request, Response);
break;
case FILE_OVERWRITE:
case FILE_SUPERSEDE:
Result = FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, Response);
break;
case FILE_OVERWRITE_IF:
case FILE_SUPERSEDE:
Result = FspFileSystemOpCreate_FileOverwriteIf(FileSystem, Request, Response);
break;
default:
@ -881,12 +870,7 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
FileSystem->Interface->Cleanup(FileSystem,
(PVOID)ValOfFileContext(Request->Req.Cleanup),
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
(0 != Request->Req.Cleanup.Delete ? FspCleanupDelete : 0) |
(0 != Request->Req.Cleanup.SetAllocationSize ? FspCleanupSetAllocationSize : 0) |
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0));
0 != Request->Req.Cleanup.Delete);
return STATUS_SUCCESS;
}
@ -961,21 +945,11 @@ FSP_API NTSTATUS FspFileSystemOpWrite(FSP_FILE_SYSTEM *FileSystem,
FSP_API NTSTATUS FspFileSystemOpFlushBuffers(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{
NTSTATUS Result;
FSP_FSCTL_FILE_INFO FileInfo;
memset(&FileInfo, 0, sizeof FileInfo);
if (0 == FileSystem->Interface->Flush)
Result = FileSystem->Interface->GetFileInfo(FileSystem,
(PVOID)ValOfFileContext(Request->Req.FlushBuffers), &FileInfo);
else
Result = FileSystem->Interface->Flush(FileSystem,
(PVOID)ValOfFileContext(Request->Req.FlushBuffers), &FileInfo);
if (!NT_SUCCESS(Result))
return Result;
return STATUS_SUCCESS; /* liar! */
memcpy(&Response->Rsp.FlushBuffers.FileInfo, &FileInfo, sizeof FileInfo);
return STATUS_SUCCESS;
return FileSystem->Interface->Flush(FileSystem,
(PVOID)ValOfFileContext(Request->Req.FlushBuffers));
}
FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem,
@ -1015,7 +989,6 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
Request->Req.SetInformation.Info.Basic.CreationTime,
Request->Req.SetInformation.Info.Basic.LastAccessTime,
Request->Req.SetInformation.Info.Basic.LastWriteTime,
Request->Req.SetInformation.Info.Basic.ChangeTime,
&FileInfo);
break;
case 19/*FileAllocationInformation*/:
@ -1133,12 +1106,11 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem,
BytesTransferred = 0;
Result = FileSystem->Interface->ReadDirectory(FileSystem,
(PVOID)ValOfFileContext(Request->Req.QueryDirectory),
(PVOID)Request->Req.QueryDirectory.Address,
Request->Req.QueryDirectory.Offset,
Request->Req.QueryDirectory.Length,
0 != Request->Req.QueryDirectory.Pattern.Size ?
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0,
0 != Request->Req.QueryDirectory.Marker.Size ?
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : 0,
(PVOID)Request->Req.QueryDirectory.Address,
Request->Req.QueryDirectory.Length,
&BytesTransferred);
if (!NT_SUCCESS(Result))
return Result;

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -230,6 +230,36 @@ FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env,
static void fsp_fuse_cleanup(struct fuse *f);
static NTSTATUS fsp_fuse_preflight(struct fuse *f)
{
NTSTATUS Result;
Result = FspFsctlPreflight(f->VolumeParams.Prefix[0] ?
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME);
if (!NT_SUCCESS(Result))
return Result;
if (L'\0' != f->MountPoint)
{
if ((
(L'A' <= f->MountPoint[0] && f->MountPoint[0] <= L'Z') ||
(L'a' <= f->MountPoint[0] && f->MountPoint[0] <= L'z')
) &&
L':' == f->MountPoint[1] || L'\0' == f->MountPoint[2])
{
if (GetLogicalDrives() & (1 << ((f->MountPoint[0] & ~0x20) - 'a')))
return STATUS_OBJECT_NAME_COLLISION;
}
else
if (L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1])
;
else
return STATUS_OBJECT_NAME_INVALID;
}
return STATUS_SUCCESS;
}
static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
{
struct fuse *f = Service->UserContext;
@ -350,7 +380,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
if (0 != f->MountPoint)
if (L'\0' != f->MountPoint)
{
Result = FspFileSystemSetMountPoint(f->FileSystem,
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
@ -485,28 +515,6 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
if (opt_data.help)
return 0;
if ((opt_data.set_uid && -1 == opt_data.uid) ||
(opt_data.set_gid && -1 == opt_data.gid))
{
HANDLE Token;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
{
fsp_fuse_get_token_uidgid(Token, TokenUser,
opt_data.set_uid && -1 == opt_data.uid ? &opt_data.uid : 0,
opt_data.set_gid && -1 == opt_data.gid ? &opt_data.gid : 0);
CloseHandle(Token);
}
if ((opt_data.set_uid && -1 == opt_data.uid) ||
(opt_data.set_gid && -1 == opt_data.gid))
{
ErrorMessage = L": unknown user/group.";
goto fail;
}
}
if (!opt_data.set_FileInfoTimeout && opt_data.set_attr_timeout)
opt_data.VolumeParams.FileInfoTimeout = opt_data.set_attr_timeout * 1000;
opt_data.VolumeParams.CaseSensitiveSearch = !opt_data.CaseInsensitiveSearch;
@ -515,7 +523,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
opt_data.VolumeParams.NamedStreams = FALSE;
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
opt_data.VolumeParams.PostCleanupOnDeleteOnly = TRUE;
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
memcpy(opt_data.VolumeParams.FileSystemName, L"FUSE", 5 * sizeof(WCHAR));
@ -540,9 +548,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
goto fail;
memcpy(f->MountPoint, ch->MountPoint, Size);
Result = FspFileSystemPreflight(
f->VolumeParams.Prefix[0] ? L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
'*' != f->MountPoint[0] || '\0' != f->MountPoint[1] ? f->MountPoint : 0);
Result = fsp_fuse_preflight(f);
if (!NT_SUCCESS(Result))
{
switch (Result)

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse_intf.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -116,6 +116,19 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName = 0, Suffix;
WCHAR Root[2] = L"\\";
HANDLE Token = 0;
union
{
TOKEN_USER V;
UINT8 B[128];
} UserInfoBuf;
PTOKEN_USER UserInfo = &UserInfoBuf.V;
union
{
TOKEN_PRIMARY_GROUP V;
UINT8 B[128];
} GroupInfoBuf;
PTOKEN_PRIMARY_GROUP GroupInfo = &GroupInfoBuf.V;
DWORD Size;
NTSTATUS Result;
if (FspFsctlTransactCreateKind == Request->Kind)
@ -144,7 +157,55 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
if (0 != Token)
{
Result = fsp_fuse_get_token_uidgid(Token, TokenUser, &Uid, &Gid);
if (!GetTokenInformation(Token, TokenUser, UserInfo, sizeof UserInfoBuf, &Size))
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
UserInfo = MemAlloc(Size);
if (0 == UserInfo)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (!GetTokenInformation(Token, TokenUser, UserInfo, Size, &Size))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, sizeof GroupInfoBuf, &Size))
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
GroupInfo = MemAlloc(Size);
if (0 == UserInfo)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, Size, &Size))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
Result = FspPosixMapSidToUid(UserInfo->User.Sid, &Uid);
if (!NT_SUCCESS(Result))
goto exit;
Result = FspPosixMapSidToUid(GroupInfo->PrimaryGroup, &Gid);
if (!NT_SUCCESS(Result))
goto exit;
}
@ -169,6 +230,12 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
Result = STATUS_SUCCESS;
exit:
if (UserInfo != &UserInfoBuf.V)
MemFree(UserInfo);
if (GroupInfo != &GroupInfoBuf.V)
MemFree(GroupInfo);
if (!NT_SUCCESS(Result) && 0 != PosixPath)
FspPosixDeletePath(PosixPath);
@ -815,6 +882,7 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
filedesc->OpenFlags = fi.flags;
filedesc->FileHandle = fi.fh;
filedesc->DirBuffer = 0;
filedesc->DirBufferSize = 0;
contexthdr->PosixPath = 0;
Result = STATUS_SUCCESS;
@ -932,6 +1000,7 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
filedesc->OpenFlags = fi.flags;
filedesc->FileHandle = fi.fh;
filedesc->DirBuffer = 0;
filedesc->DirBufferSize = 0;
contexthdr->PosixPath = 0;
Result = STATUS_SUCCESS;
@ -981,7 +1050,7 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
}
static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode, PWSTR FileName, ULONG Flags)
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
{
struct fuse *f = FileSystem->UserContext;
struct fsp_fuse_file_desc *filedesc = FileNode;
@ -1003,7 +1072,7 @@ static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
* FUSE option and can safely remove the file at this time.
*/
if (Flags & FspCleanupDelete)
if (Delete)
if (filedesc->IsDirectory && !filedesc->IsReparsePoint)
{
if (0 != f->ops.rmdir)
@ -1044,7 +1113,7 @@ static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
f->ops.release(filedesc->PosixPath, &fi);
}
FspFileSystemDeleteDirectoryBuffer(&filedesc->DirBuffer);
MemFree(filedesc->DirBuffer);
MemFree(filedesc->PosixPath);
MemFree(filedesc);
}
@ -1146,14 +1215,11 @@ success:
}
static NTSTATUS fsp_fuse_intf_Flush(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode,
FSP_FSCTL_FILE_INFO *FileInfo)
PVOID FileNode)
{
struct fuse *f = FileSystem->UserContext;
struct fsp_fuse_file_desc *filedesc = FileNode;
UINT32 Uid, Gid, Mode;
struct fuse_file_info fi;
FSP_FSCTL_FILE_INFO FileInfoBuf;
int err;
NTSTATUS Result;
@ -1183,17 +1249,8 @@ static NTSTATUS fsp_fuse_intf_Flush(FSP_FILE_SYSTEM *FileSystem,
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
}
}
if (!NT_SUCCESS(Result))
return Result;
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
&Uid, &Gid, &Mode, &FileInfoBuf);
if (!NT_SUCCESS(Result))
return Result;
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
return STATUS_SUCCESS;
return Result;
}
static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
@ -1215,7 +1272,7 @@ static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode, UINT32 FileAttributes,
UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime,
UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime,
FSP_FSCTL_FILE_INFO *FileInfo)
{
struct fuse *f = FileSystem->UserContext;
@ -1390,13 +1447,7 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
memset(&dh, 0, sizeof dh);
if (0 != f->ops.readdir)
{
memset(&fi, 0, sizeof fi);
fi.flags = filedesc->OpenFlags;
fi.fh = filedesc->FileHandle;
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfo, 0, &fi);
}
else if (0 != f->ops.getdir)
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfoOld);
else
@ -1433,8 +1484,7 @@ static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
STATUS_OBJECT_PATH_NOT_FOUND != Result)
return Result;
if (NT_SUCCESS(Result) &&
(f->VolumeParams.CaseSensitiveSearch || 0 != invariant_wcsicmp(FileName, NewFileName)))
if (NT_SUCCESS(Result))
{
if (!ReplaceIfExists)
return STATUS_OBJECT_NAME_COLLISION;
@ -1541,157 +1591,101 @@ exit:
return Result;
}
static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
const struct fuse_stat *stbuf, fuse_off_t off)
{
struct fuse_dirhandle *dh = buf;
struct fsp_fuse_file_desc *filedesc = dh->filedesc;
struct fsp_fuse_dirinfo *di;
ULONG len, xfersize;
len = lstrlenA(name);
if (len > 255)
len = 255;
di = (PVOID)((PUINT8)dh->Buffer + dh->BytesTransferred);
xfersize = FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(struct fsp_fuse_dirinfo) + len + 1);
if ((PUINT8)di + xfersize > (PUINT8)dh->Buffer + dh->Length)
{
PVOID Buffer;
ULONG Length = dh->Length;
if (0 == Length)
Length = 16 * 1024;
else if (Length < 16 * 1024 * 1024)
Length *= 2;
else
return 1;
Buffer = MemAlloc(Length);
if (0 == Buffer)
return 1;
memcpy(Buffer, dh->Buffer, dh->BytesTransferred);
MemFree(dh->Buffer);
dh->Buffer = Buffer;
dh->Length = Length;
di = (PVOID)((PUINT8)dh->Buffer + dh->BytesTransferred);
}
dh->BytesTransferred += xfersize;
dh->NonZeroOffset = dh->NonZeroOffset || 0 != off;
di->Size = (UINT16)(sizeof(struct fsp_fuse_dirinfo) + len + 1);
di->FileInfoValid = FALSE;
di->NextOffset = 0 != off ? off : dh->BytesTransferred;
memcpy(di->PosixNameBuf, name, len);
di->PosixNameBuf[len] = '\0';
return 0;
}
int fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
int type, fuse_ino_t ino)
{
return fsp_fuse_intf_AddDirInfo(dh, name, 0, 0) ? -ENOMEM : 0;
}
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length,
PWSTR Pattern,
PULONG PBytesTransferred)
{
struct fuse *f = FileSystem->UserContext;
struct fsp_fuse_file_desc *filedesc = FileNode;
struct fuse_file_info fi;
struct fuse_dirhandle dh;
struct fsp_fuse_dirinfo *di;
PUINT8 diend;
union
{
FSP_FSCTL_DIR_INFO V;
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + 255 * sizeof(WCHAR)];
} DirInfoBuf;
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.V;
ULONG SizeA, SizeW;
if ('/' == filedesc->PosixPath[0] && '\0' == filedesc->PosixPath[1])
{
/* if this is the root directory do not add the dot entries */
if ('.' == name[0] && ('\0' == name[1] ||
('.' == name[1] && '\0' == name[2])))
return 0;
}
SizeA = lstrlenA(name);
if (SizeA > 255)
/* ignore bad filenames; should we return error code? */
return 0;
SizeW = MultiByteToWideChar(CP_UTF8, 0, name, SizeA, DirInfo->FileNameBuf, 255);
if (0 == SizeW)
/* ignore bad filenames; should we return error code? */
return 0;
memset(DirInfo, 0, sizeof *DirInfo);
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + SizeW * sizeof(WCHAR));
return !FspFileSystemFillDirectoryBuffer(&filedesc->DirBuffer, DirInfo, &dh->Result);
}
static int fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
int type, fuse_ino_t ino)
{
return fsp_fuse_intf_AddDirInfo(dh, name, 0, 0) ? -ENOMEM : 0;
}
static NTSTATUS fsp_fuse_intf_FixDirInfo(FSP_FILE_SYSTEM *FileSystem,
struct fsp_fuse_file_desc *filedesc)
{
char *PosixPath = 0, *PosixName, *PosixPathEnd, SavedPathChar;
ULONG SizeA, SizeW;
PUINT8 Buffer;
PULONG Index, IndexEnd;
ULONG Count;
FSP_FSCTL_DIR_INFO *DirInfo;
UINT32 Uid, Gid, Mode;
NTSTATUS Result;
SizeA = lstrlenA(filedesc->PosixPath);
PosixPath = MemAlloc(SizeA + 1 + 255 + 1);
if (0 == PosixPath)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
memcpy(PosixPath, filedesc->PosixPath, SizeA);
if (1 < SizeA)
/* if not root */
PosixPath[SizeA++] = '/';
PosixPath[SizeA] = '\0';
PosixName = PosixPath + SizeA;
FspFileSystemPeekInDirectoryBuffer(&filedesc->DirBuffer, &Buffer, &Index, &Count);
for (IndexEnd = Index + Count; IndexEnd > Index; Index++)
{
DirInfo = (FSP_FSCTL_DIR_INFO *)(Buffer + *Index);
SizeW = (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR);
if (1 == SizeW && L'.' == DirInfo->FileNameBuf[0])
{
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 1 : PosixName;
SavedPathChar = *PosixPathEnd;
*PosixPathEnd = '\0';
}
else
if (2 == SizeW && L'.' == DirInfo->FileNameBuf[0] && L'.' == DirInfo->FileNameBuf[1])
{
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
PosixPathEnd--;
if (PosixPath == PosixPathEnd)
PosixPathEnd++;
SavedPathChar = *PosixPathEnd;
*PosixPathEnd = '\0';
}
else
{
PosixPathEnd = 0;
SizeA = WideCharToMultiByte(CP_UTF8, 0, DirInfo->FileNameBuf, SizeW, PosixName, 255, 0, 0);
if (0 == SizeA)
{
/* this should never happen because we just converted using MultiByteToWideChar */
Result = STATUS_OBJECT_NAME_INVALID;
goto exit;
}
PosixName[SizeA] = '\0';
}
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, 0,
&Uid, &Gid, &Mode, &DirInfo->FileInfo);
if (!NT_SUCCESS(Result))
goto exit;
if (0 != PosixPathEnd)
*PosixPathEnd = SavedPathChar;
FspPosixDecodeWindowsPath(DirInfo->FileNameBuf, SizeW);
}
Result = STATUS_SUCCESS;
exit:
MemFree(PosixPath);
return Result;
}
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode, PWSTR Pattern, PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
struct fuse *f = FileSystem->UserContext;
struct fsp_fuse_file_desc *filedesc = FileNode;
struct fuse_dirhandle dh;
struct fuse_file_info fi;
char *PosixPath = 0, *PosixName, *PosixPathEnd, SavedPathChar;
PWSTR FileName = 0;
ULONG Size;
int err;
NTSTATUS Result;
if (FspFileSystemAcquireDirectoryBuffer(&filedesc->DirBuffer, 0 == Marker, &Result))
{
memset(&dh, 0, sizeof dh);
dh.filedesc = filedesc;
dh.Result = STATUS_SUCCESS;
if (!filedesc->IsDirectory)
return STATUS_ACCESS_DENIED;
memset(&dh, 0, sizeof dh);
if (0 == filedesc->DirBuffer)
{
if (0 != f->ops.readdir)
{
memset(&fi, 0, sizeof fi);
fi.flags = filedesc->OpenFlags;
fi.fh = filedesc->FileHandle;
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, 0, &fi);
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, Offset, &fi);
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
}
else if (0 != f->ops.getdir)
@ -1702,23 +1696,142 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
else
Result = STATUS_INVALID_DEVICE_REQUEST;
if (NT_SUCCESS(Result))
{
Result = dh.Result;
if (NT_SUCCESS(Result))
Result = fsp_fuse_intf_FixDirInfo(FileSystem, filedesc);
}
if (!NT_SUCCESS(Result))
goto exit;
FspFileSystemReleaseDirectoryBuffer(&filedesc->DirBuffer);
if (0 == dh.BytesTransferred)
{
/* EOF */
*PBytesTransferred = 0;
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
goto success;
}
else if (dh.NonZeroOffset)
{
di = (PVOID)((PUINT8)dh.Buffer + 0);
diend = (PUINT8)dh.Buffer + dh.BytesTransferred;
}
else
{
di = (PVOID)((PUINT8)dh.Buffer + Offset);
diend = (PUINT8)dh.Buffer + dh.BytesTransferred;
filedesc->DirBuffer = dh.Buffer;
filedesc->DirBufferSize = dh.BytesTransferred;
dh.Buffer = 0;
}
}
else
{
di = (PVOID)((PUINT8)filedesc->DirBuffer + Offset);
diend = (PUINT8)filedesc->DirBuffer + filedesc->DirBufferSize;
}
if (!NT_SUCCESS(Result))
return Result;
for (;
(PUINT8)di + sizeof(di->Size) <= diend;
di = (PVOID)((PUINT8)di + FSP_FSCTL_DEFAULT_ALIGN_UP(di->Size)))
{
if (sizeof(struct fsp_fuse_dirinfo) > di->Size)
break;
FspFileSystemReadDirectoryBuffer(&filedesc->DirBuffer,
Marker, Buffer, Length, PBytesTransferred);
if ('/' == filedesc->PosixPath[0] && '\0' == filedesc->PosixPath[1])
{
/* if this is the root directory do not add the dot entries */
return STATUS_SUCCESS;
if ('.' == di->PosixNameBuf[0] && ('\0' == di->PosixNameBuf[1] ||
('.' == di->PosixNameBuf[1] && '\0' == di->PosixNameBuf[2])))
continue;
}
if (!di->FileInfoValid)
{
if (0 == PosixPath)
{
Size = lstrlenA(filedesc->PosixPath);
PosixPath = MemAlloc(Size + 1 + 255 + 1);
if (0 == PosixPath)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
memcpy(PosixPath, filedesc->PosixPath, Size);
if (1 < Size)
/* if not root */
PosixPath[Size++] = '/';
PosixPath[Size] = '\0';
PosixName = PosixPath + Size;
}
if ('.' == di->PosixNameBuf[0] && '\0' == di->PosixNameBuf[1])
{
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 1 : PosixName;
SavedPathChar = *PosixPathEnd;
*PosixPathEnd = '\0';
}
else
if ('.' == di->PosixNameBuf[0] && '.' == di->PosixNameBuf[1] && '\0' == di->PosixNameBuf[2])
{
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
PosixPathEnd--;
if (PosixPath == PosixPathEnd)
PosixPathEnd++;
SavedPathChar = *PosixPathEnd;
*PosixPathEnd = '\0';
}
else
{
PosixPathEnd = 0;
Size = lstrlenA(di->PosixNameBuf);
if (Size > 255)
Size = 255;
memcpy(PosixName, di->PosixNameBuf, Size);
PosixName[Size] = '\0';
}
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, 0,
&Uid, &Gid, &Mode, &di->FileInfo);
if (!NT_SUCCESS(Result))
goto exit;
if (0 != PosixPathEnd)
*PosixPathEnd = SavedPathChar;
di->FileInfoValid = TRUE;
}
memcpy(&DirInfo->FileInfo, &di->FileInfo, sizeof di->FileInfo);
Result = FspPosixMapPosixToWindowsPath(di->PosixNameBuf, &FileName);
if (!NT_SUCCESS(Result))
goto exit;
Size = lstrlenW(FileName);
if (Size > 255)
Size = 255;
Size *= sizeof(WCHAR);
memcpy(DirInfo->FileNameBuf, FileName, Size);
FspPosixDeletePath(FileName);
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + Size);
DirInfo->NextOffset = di->NextOffset;
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
break;
}
if ((PUINT8)di + sizeof(di->Size) > diend)
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
success:
Result = STATUS_SUCCESS;
exit:
MemFree(PosixPath);
MemFree(dh.Buffer);
return Result;
}
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
@ -1995,140 +2108,3 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
fsp_fuse_intf_SetReparsePoint,
fsp_fuse_intf_DeleteReparsePoint,
};
/*
* Utility
*/
NTSTATUS fsp_fuse_get_token_uidgid(
HANDLE Token,
TOKEN_INFORMATION_CLASS UserOrOwnerClass, /* TokenUser|TokenOwner */
PUINT32 PUid, PUINT32 PGid)
{
UINT32 Uid, Gid;
union
{
TOKEN_USER V;
UINT8 B[128];
} UserInfoBuf;
PTOKEN_USER UserInfo = &UserInfoBuf.V;
union
{
TOKEN_OWNER V;
UINT8 B[128];
} OwnerInfoBuf;
PTOKEN_OWNER OwnerInfo = &OwnerInfoBuf.V;
union
{
TOKEN_PRIMARY_GROUP V;
UINT8 B[128];
} GroupInfoBuf;
PTOKEN_PRIMARY_GROUP GroupInfo = &GroupInfoBuf.V;
DWORD Size;
NTSTATUS Result;
if (0 != PUid && TokenUser == UserOrOwnerClass)
{
if (!GetTokenInformation(Token, TokenUser, UserInfo, sizeof UserInfoBuf, &Size))
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
UserInfo = MemAlloc(Size);
if (0 == UserInfo)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (!GetTokenInformation(Token, TokenUser, UserInfo, Size, &Size))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
Result = FspPosixMapSidToUid(UserInfo->User.Sid, &Uid);
if (!NT_SUCCESS(Result))
goto exit;
}
else if (0 != PUid && TokenOwner == UserOrOwnerClass)
{
if (!GetTokenInformation(Token, TokenOwner, OwnerInfo, sizeof OwnerInfoBuf, &Size))
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
OwnerInfo = MemAlloc(Size);
if (0 == OwnerInfo)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (!GetTokenInformation(Token, TokenOwner, OwnerInfo, Size, &Size))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
Result = FspPosixMapSidToUid(OwnerInfo->Owner, &Uid);
if (!NT_SUCCESS(Result))
goto exit;
}
if (0 != PGid)
{
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, sizeof GroupInfoBuf, &Size))
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
GroupInfo = MemAlloc(Size);
if (0 == GroupInfo)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, Size, &Size))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
Result = FspPosixMapSidToUid(GroupInfo->PrimaryGroup, &Gid);
if (!NT_SUCCESS(Result))
goto exit;
}
if (0 != PUid)
*PUid = Uid;
if (0 != PGid)
*PGid = Gid;
Result = STATUS_SUCCESS;
exit:
if (UserInfo != &UserInfoBuf.V)
MemFree(UserInfo);
if (OwnerInfo != &OwnerInfoBuf.V)
MemFree(OwnerInfo);
if (GroupInfo != &GroupInfoBuf.V)
MemFree(GroupInfo);
return Result;
}

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse_main.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse_opt.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/library.h
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -62,15 +62,27 @@ struct fsp_fuse_file_desc
int OpenFlags;
UINT64 FileHandle;
PVOID DirBuffer;
ULONG DirBufferSize;
};
struct fuse_dirhandle
{
struct fsp_fuse_file_desc *filedesc;
NTSTATUS Result;
PVOID Buffer;
ULONG Length;
ULONG BytesTransferred;
BOOLEAN NonZeroOffset;
BOOLEAN DotFiles, HasChild;
};
struct fsp_fuse_dirinfo
{
UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo;
BOOLEAN FileInfoValid;
UINT64 NextOffset;
char PosixNameBuf[]; /* includes term-0 (unlike FSP_FSCTL_DIR_INFO) */
};
NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
@ -78,11 +90,6 @@ NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf;
NTSTATUS fsp_fuse_get_token_uidgid(
HANDLE Token,
TOKEN_INFORMATION_CLASS UserOrOwnerClass, /* TokenUser|TokenOwner */
PUINT32 PUid, PUINT32 PGid);
/* NFS reparse points */
#define NFS_SPECFILE_FIFO 0x000000004F464946

View File

@ -1,7 +1,7 @@
/**
* @file dll/library.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/library.h
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -51,9 +51,6 @@ NTSTATUS FspEventLogUnregister(VOID);
PWSTR FspDiagIdent(VOID);
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount);
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
static inline ULONG FspPathSuffixIndex(PWSTR FileName)
@ -76,7 +73,7 @@ static inline BOOLEAN FspPathIsDrive(PWSTR FileName)
(L'A' <= FileName[0] && FileName[0] <= L'Z') ||
(L'a' <= FileName[0] && FileName[0] <= L'z')
) &&
L':' == FileName[1] && L'\0' == FileName[2];
L':' == FileName[1] || L'\0' == FileName[2];
}
#endif

View File

@ -1,7 +1,7 @@
/**
* @file dll/np.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -22,7 +22,6 @@
#define FSP_NP_NAME LIBRARY_NAME ".Np"
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
#define FSP_NP_ADDCONNECTION_TIMEOUT 15000
/*
* Define the following macro to use CredUIPromptForWindowsCredentials.
@ -284,8 +283,7 @@ static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
ClassNameBuf[ClassNameLen] = '\0';
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY, 0, KEY_READ, &RegKey);
if (ERROR_SUCCESS != NpResult)
goto exit;
@ -585,63 +583,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
switch (NpResult)
{
case WN_SUCCESS:
/*
* The Launcher is reporting success. Wait until we can access the new volume
* root directory. If we see it report success, otherwise report error.
*/
{
WCHAR RemoteNameBuf[9 + sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
HANDLE Handle;
if (L'\0' != LocalNameBuf[0])
{
P = RemoteNameBuf;
*P++ = L'\\'; *P++ = L'\\'; *P++ = L'?'; *P++ = L'\\';
*P++ = LocalNameBuf[0]; *P++ = L':'; *P++ = L'\\';
*P++ = L'\0';
}
else
{
P = RemoteNameBuf;
*P++ = L'\\'; *P++ = L'\\'; *P++ = L'?'; *P++ = L'\\';
*P++ = L'U'; *P++ = L'N'; *P++ = L'C'; *P++ = L'\\';
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\\';
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\\';
*P++ = L'\0';
}
NpResult = WN_NO_NETWORK; /* timeout error */
for (ULONG I = 0, N = 1 + FSP_NP_ADDCONNECTION_TIMEOUT / 500; N > I; I++)
{
if (0 != I)
Sleep(500);
Handle = CreateFileW(RemoteNameBuf,
FILE_READ_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (INVALID_HANDLE_VALUE != Handle)
{
/* the file system is up and running */
CloseHandle(Handle);
NpResult = WN_SUCCESS;
break;
}
P = PipeBuf;
*P++ = LauncherSvcInstanceInfo;
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
if (WN_SUCCESS != FspNpCallLauncherPipe(
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE))
{
/* looks like the file system is gone! */
NpResult = WN_NO_NETWORK;
break;
}
}
}
break;
case WN_ACCESS_DENIED:
break;
case ERROR_ALREADY_EXISTS:

View File

@ -1,7 +1,7 @@
/**
* @file dll/ntstatus.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/path.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -14,7 +14,7 @@
* [SNAME]
* https://www.cygwin.com/cygwin-ug-net/using-specialnames.html
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -923,30 +923,3 @@ FSP_API VOID FspPosixDeletePath(void *Path)
{
MemFree(Path);
}
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size)
{
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
{
WCHAR c = *p;
if (L'\\' == c)
*p = L'/';
/* encode characters in the Unicode private use area: U+F0XX -> XX */
else if (0xf000 <= c && c <= 0xf0ff)
*p &= ~0xf000;
}
}
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size)
{
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
{
WCHAR c = *p;
if (L'/' == c)
*p = L'\\';
else if (128 > c && (FspPosixInvalidPathChars[c >> 5] & (0x80000000 >> (c & 0x1f))))
*p |= 0xf000;
}
}

View File

@ -1,7 +1,7 @@
/**
* @file dll/security.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -191,13 +191,6 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
goto exit;
if (!CheckParentOrMain && Request->Req.Create.HasTrailingBackslash &&
!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
Result = STATUS_OBJECT_NAME_INVALID;
goto exit;
}
if (Request->Req.Create.UserMode && 0 < SecurityDescriptorSize)
{
if (0 == DesiredAccess)

View File

@ -1,7 +1,7 @@
/**
* @file dll/service.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/util.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -22,7 +22,7 @@ BEGIN
BEGIN
VALUE "CompanyName", STR(MyCompanyName)
VALUE "FileDescription", STR(MyDescription)
VALUE "FileVersion", STR(MyFullVersion)
VALUE "FileVersion", STR(MyVersion)
VALUE "InternalName", "winfsp.dll"
VALUE "LegalCopyright", STR(MyCopyright)
VALUE "OriginalFilename", "winfsp.dll"

View File

@ -22,7 +22,7 @@ BEGIN
BEGIN
VALUE "CompanyName", STR(MyCompanyName)
VALUE "FileDescription", STR(MyDescription)
VALUE "FileVersion", STR(MyFullVersion)
VALUE "FileVersion", STR(MyVersion)
VALUE "InternalName", "launchctl.exe"
VALUE "LegalCopyright", STR(MyCopyright)
VALUE "OriginalFilename", "launchctl.exe"

View File

@ -1,7 +1,7 @@
/**
* @file launcher/launchctl.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -22,7 +22,7 @@ BEGIN
BEGIN
VALUE "CompanyName", STR(MyCompanyName)
VALUE "FileDescription", STR(MyDescription)
VALUE "FileVersion", STR(MyFullVersion)
VALUE "FileVersion", STR(MyVersion)
VALUE "InternalName", "launcher.exe"
VALUE "LegalCopyright", STR(MyCopyright)
VALUE "OriginalFilename", "launcher.exe"

View File

@ -1,7 +1,7 @@
/**
* @file launcher/launcher.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -19,6 +19,7 @@
#include <sddl.h>
#define PROGNAME "WinFsp.Launcher"
#define REGKEY LAUNCHER_REGKEY
BOOL CreateOverlappedPipe(
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
@ -440,8 +441,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
goto exit;
}
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" REGKEY, 0, KEY_READ, &RegKey);
if (ERROR_SUCCESS != RegResult)
{
Result = FspNtStatusFromWin32(RegResult);

View File

@ -1,7 +1,7 @@
/**
* @file launcher/launcher.h
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -21,8 +21,7 @@
#include <winfsp/winfsp.h>
#include <shared/minimal.h>
#define LAUNCHER_REGKEY "Software\\WinFsp\\Services"
#define LAUNCHER_REGKEY_WOW64 KEY_WOW64_32KEY
#define LAUNCHER_REGKEY "SYSTEM\\CurrentControlSet\\Services\\WinFsp.Launcher\\Services"
#define LAUNCHER_STOP_TIMEOUT 5500
#define LAUNCHER_KILL_TIMEOUT 5000

View File

@ -1,7 +1,7 @@
/**
* @file shared/minimal.h
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -126,10 +126,6 @@ static inline void *MemAlloc(size_t Size)
{
return HeapAlloc(GetProcessHeap(), 0, Size);
}
static inline void *MemRealloc(void *Pointer, size_t Size)
{
return HeapReAlloc(GetProcessHeap(), 0, Pointer, Size);
}
static inline void MemFree(void *Pointer)
{
if (0 != Pointer)

View File

@ -2,7 +2,7 @@
* @file sys/callbacks.c
* Fast I/O and resource acquisition callbacks.
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/cleanup.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -77,17 +77,13 @@ static NTSTATUS FspFsvolCleanup(
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
FSP_FSCTL_TRANSACT_REQ *Request;
ULONG CleanupFlags;
BOOLEAN DeletePending, SetAllocationSize, FileModified;
BOOLEAN DeletePending;
ASSERT(FileNode == FileDesc->FileNode);
FspFileNodeAcquireExclusive(FileNode, Main);
FspFileNodeCleanup(FileNode, FileObject, &CleanupFlags);
DeletePending = CleanupFlags & 1;
SetAllocationSize = !!(CleanupFlags & 2);
FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
FspFileNodeCleanup(FileNode, FileObject, &DeletePending);
/* if this is a directory inform the FSRTL Notify mechanism */
if (FileNode->IsDirectory)
@ -110,25 +106,13 @@ static NTSTATUS FspFsvolCleanup(
Request->Req.Cleanup.UserContext = FileNode->UserContext;
Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2;
Request->Req.Cleanup.Delete = DeletePending;
Request->Req.Cleanup.SetAllocationSize = SetAllocationSize;
Request->Req.Cleanup.SetArchiveBit = (FileModified || FileDesc->DidSetSecurity) &&
!FileDesc->DidSetFileAttributes;
Request->Req.Cleanup.SetLastAccessTime = !FileDesc->DidSetLastAccessTime;
Request->Req.Cleanup.SetLastWriteTime = FileModified && !FileDesc->DidSetLastWriteTime;
Request->Req.Cleanup.SetChangeTime = (FileModified || FileDesc->DidSetMetadata) &&
!FileDesc->DidSetChangeTime;
FspFileNodeAcquireExclusive(FileNode, Pgio);
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
if (Request->Req.Cleanup.Delete ||
Request->Req.Cleanup.SetAllocationSize ||
Request->Req.Cleanup.SetArchiveBit ||
Request->Req.Cleanup.SetLastWriteTime ||
Request->Req.Cleanup.SetChangeTime ||
!FsvolDeviceExtension->VolumeParams.PostCleanupWhenModifiedOnly)
if (DeletePending || !FsvolDeviceExtension->VolumeParams.PostCleanupOnDeleteOnly)
/*
* Note that it is still possible for this request to not be delivered,
* if the volume device Ioq is stopped. But such failures are benign
@ -138,13 +122,9 @@ static NTSTATUS FspFsvolCleanup(
return FSP_STATUS_IOQ_POST_BEST_EFFORT;
else
{
if (FileDesc->DidSetMetadata)
{
if (0 == FileNode->MainFileNode)
FspFileNodeInvalidateParentDirInfo(FileNode);
else
FspFileNodeInvalidateStreamInfo(FileNode);
}
/* if the file is being resized invalidate the volume info */
if (FileNode->TruncateOnClose)
FspFsvolDeviceInvalidateVolumeInfo(IrpSp->DeviceObject);
return STATUS_SUCCESS; /* FspFsvolCleanupRequestFini will take care of the rest! */
}
@ -158,51 +138,15 @@ NTSTATUS FspFsvolCleanupComplete(
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
ULONG NotifyFilter, NotifyAction;
ASSERT(FileNode == FileDesc->FileNode);
/* send the appropriate notification; also invalidate dirinfo/etc. caches */
/* if the file is being deleted do a change notification */
if (Request->Req.Cleanup.Delete)
{
NotifyFilter = FileNode->IsDirectory ?
FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME;
NotifyAction = FILE_ACTION_REMOVED;
}
else
{
/* send notification for any metadata changes */
NotifyFilter = 0;
#if 0
/* do not send notification when resetting the allocation size */
if (Request->Req.Cleanup.SetAllocationSize)
NotifyFilter |= FILE_NOTIFY_CHANGE_SIZE;
#endif
if (Request->Req.Cleanup.SetArchiveBit)
NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
#if 0
/* do not send notification for implicit LastAccessTime changes */
if (Request->Req.Cleanup.SetLastAccessTime)
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
#endif
if (Request->Req.Cleanup.SetLastWriteTime)
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
NotifyAction = FILE_ACTION_MODIFIED;
}
if (0 != NotifyFilter)
FspFileNodeNotifyChange(FileNode, NotifyFilter, NotifyAction, TRUE);
else
{
if (FileDesc->DidSetMetadata)
{
if (0 == FileNode->MainFileNode)
FspFileNodeInvalidateParentDirInfo(FileNode);
else
FspFileNodeInvalidateStreamInfo(FileNode);
}
}
FspFileNodeNotifyChange(FileNode,
FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_REMOVED);
/* if the file is being resized invalidate the volume info */
else if (FileNode->TruncateOnClose)
FspFsvolDeviceInvalidateVolumeInfo(IrpSp->DeviceObject);
FSP_LEAVE_IOC("FileObject=%p", IrpSp->FileObject);
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/close.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/create.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -193,7 +193,6 @@ static NTSTATUS FspFsvolCreateNoLock(
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_BACKUP_PRIVILEGE);
BOOLEAN HasRestorePrivilege =
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_RESTORE_PRIVILEGE);
BOOLEAN HasTrailingBackslash = FALSE;
FSP_FILE_NODE *FileNode, *RelatedFileNode;
FSP_FILE_DESC *FileDesc;
UNICODE_STRING MainFileName = { 0 }, StreamPart = { 0 };
@ -217,12 +216,6 @@ static NTSTATUS FspFsvolCreateNoLock(
FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
return STATUS_INVALID_PARAMETER;
/* do not allow the temporary bit on a directory */
if (FlagOn(CreateOptions, FILE_DIRECTORY_FILE) &&
FlagOn(FileAttributes, FILE_ATTRIBUTE_TEMPORARY) &&
(FILE_CREATE == CreateDisposition || FILE_OPEN_IF == CreateDisposition))
return STATUS_INVALID_PARAMETER;
/* check security descriptor validity */
if (0 != SecurityDescriptor)
{
@ -264,7 +257,7 @@ static NTSTATUS FspFsvolCreateNoLock(
/* must be a relative path */
if (sizeof(WCHAR) <= FileName.Length && L'\\' == FileName.Buffer[0])
return STATUS_INVALID_PARAMETER; /* IFSTEST */
return STATUS_OBJECT_NAME_INVALID;
BOOLEAN AppendBackslash =
sizeof(WCHAR) * 2/* not empty or root */ <= RelatedFileNode->FileName.Length &&
@ -300,7 +293,7 @@ static NTSTATUS FspFsvolCreateNoLock(
ASSERT(NT_SUCCESS(Result));
/* check filename validity */
if (!FspFileNameIsValid(&FileNode->FileName, FsvolDeviceExtension->VolumeParams.MaxComponentLength,
if (!FspFileNameIsValid(&FileNode->FileName,
FsvolDeviceExtension->VolumeParams.NamedStreams ? &StreamPart : 0,
&StreamType))
{
@ -351,7 +344,12 @@ static NTSTATUS FspFsvolCreateNoLock(
if (sizeof(WCHAR) * 2/* not empty or root */ <= FileNode->FileName.Length &&
L'\\' == FileNode->FileName.Buffer[FileNode->FileName.Length / sizeof(WCHAR) - 1])
{
HasTrailingBackslash = TRUE;
if (!FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
{
FspFileNodeDereference(FileNode);
return STATUS_OBJECT_NAME_INVALID;
}
FileNode->FileName.Length -= sizeof(WCHAR);
}
@ -444,9 +442,7 @@ static NTSTATUS FspFsvolCreateNoLock(
FileAttributes = 0;
/* remember the main file node */
ASSERT(0 == FileNode->MainFileNode);
FileNode->MainFileNode = FileDesc->MainFileObject->FsContext;
FspFileNodeReference(FileNode->MainFileNode);
Result = STATUS_SUCCESS;
@ -505,7 +501,6 @@ static NTSTATUS FspFsvolCreateNoLock(
Request->Req.Create.HasRestorePrivilege = HasRestorePrivilege;
Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
Request->Req.Create.CaseSensitive = CaseSensitive;
Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash;
Request->Req.Create.NamedStream = MainFileName.Length;
ASSERT(
@ -808,16 +803,6 @@ NTSTATUS FspFsvolCreateComplete(
}
/* populate the FileNode/FileDesc fields from the Response */
FileNode->UserContext = Response->Rsp.Create.Opened.UserContext;
FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber;
FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,
FILE_ATTRIBUTE_DIRECTORY);
FileNode->IsRootDirectory = FileNode->IsDirectory &&
sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0];
FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2;
FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);
/* handle normalized names */
if (!FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch)
{
/* is there a normalized file name as part of the response? */
@ -833,10 +818,7 @@ NTSTATUS FspFsvolCreateComplete(
if (Response->Buffer + Response->Rsp.Create.Opened.FileName.Size >
(PUINT8)Response + Response->Size)
{
FspFsvolCreatePostClose(FileDesc);
FSP_RETURN(Result = STATUS_OBJECT_NAME_INVALID);
}
NormalizedName.Length = NormalizedName.MaximumLength =
Response->Rsp.Create.Opened.FileName.Size;
@ -844,15 +826,20 @@ NTSTATUS FspFsvolCreateComplete(
/* normalized file name can only differ in case from requested one */
if (0 != FspFileNameCompare(&FileNode->FileName, &NormalizedName, TRUE, 0))
{
FspFsvolCreatePostClose(FileDesc);
FSP_RETURN(Result = STATUS_OBJECT_NAME_INVALID);
}
ASSERT(FileNode->FileName.Length == NormalizedName.Length);
RtlCopyMemory(FileNode->FileName.Buffer, NormalizedName.Buffer, NormalizedName.Length);
}
}
FileNode->UserContext = Response->Rsp.Create.Opened.UserContext;
FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber;
FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,
FILE_ATTRIBUTE_DIRECTORY);
FileNode->IsRootDirectory = FileNode->IsDirectory &&
sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0];
FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2;
FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);
/* open the FileNode */
Result = FspFileNodeOpen(FileNode, FileObject,
@ -878,7 +865,8 @@ NTSTATUS FspFsvolCreateComplete(
Result = FspFsvolCreateSharingViolationOplock(
FsvolDeviceObject, Irp, IrpSp, FALSE);
FSP_RETURN();
if (STATUS_PENDING == Result)
FSP_RETURN();
}
else
{
@ -904,7 +892,6 @@ NTSTATUS FspFsvolCreateComplete(
/* set up the AccessState */
AccessState->RemainingDesiredAccess = 0;
AccessState->PreviouslyGrantedAccess = Response->Rsp.Create.Opened.GrantedAccess;
FileDesc->GrantedAccess = Response->Rsp.Create.Opened.GrantedAccess;
/* set up the FileObject */
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
@ -914,13 +901,6 @@ NTSTATUS FspFsvolCreateComplete(
FileObject->PrivateCacheMap = 0;
FileObject->FsContext = FileNode;
FileObject->FsContext2 = FileDesc;
if (!FileNode->IsDirectory)
{
/* properly set temporary bit for lazy writer */
if (FlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,
FILE_ATTRIBUTE_TEMPORARY))
SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
}
if (FspTimeoutInfinity32 == FsvolDeviceExtension->VolumeParams.FileInfoTimeout &&
!FlagOn(IrpSp->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING) &&
!Response->Rsp.Create.Opened.DisableCache)
@ -959,19 +939,6 @@ NTSTATUS FspFsvolCreateComplete(
if (FileNode->IsDirectory)
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
/* overwrite/supersede operations must have the correct hidden/system attributes set */
if ((FlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes, FILE_ATTRIBUTE_HIDDEN) &&
!FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
(FlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes, FILE_ATTRIBUTE_SYSTEM) &&
!FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM)))
{
FspFsvolCreatePostClose(FileDesc);
FspFileNodeClose(FileNode, FileObject, TRUE);
Result = STATUS_ACCESS_DENIED;
FSP_RETURN();
}
PVOID RequestDeviceObjectValue = FspIopRequestContext(Request, RequestDeviceObject);
/* disassociate the FileDesc momentarily from the Request */
@ -1031,11 +998,10 @@ NTSTATUS FspFsvolCreateComplete(
/* file was successfully overwritten/superseded */
if (0 == FileNode->MainFileNode)
FspFileNodeOverwriteStreams(FileNode);
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Overwrite.FileInfo, TRUE);
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Overwrite.FileInfo);
FspFileNodeNotifyChange(FileNode,
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE,
FILE_ACTION_MODIFIED,
FALSE);
FILE_ACTION_MODIFIED);
FspFileNodeReleaseOwner(FileNode, Full, Request);
@ -1098,8 +1064,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
return Result;
}
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Create.Opened.FileInfo,
FILE_CREATED == Response->IoStatus.Information);
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Create.Opened.FileInfo);
if (FlushImage)
{
@ -1126,8 +1091,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
if (FILE_CREATED == Response->IoStatus.Information)
FspFileNodeNotifyChange(FileNode,
FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_ADDED,
TRUE);
FILE_ACTION_ADDED);
FspFileNodeRelease(FileNode, Main);
@ -1316,7 +1280,6 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
FSP_FSCTL_TRANSACT_RSP *Response;
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
ULONG SharingViolationReason = (ULONG)Irp->IoStatus.Information;
NTSTATUS Result;
@ -1353,12 +1316,6 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
return FspWqRepostIrpWorkItem(Irp,
FspFsvolCreateSharingViolationOplock, FspFsvolCreateRequestFini);
FspFileNodeClose(ExtraFileNode, 0, TRUE);
FspFileNodeDereference(ExtraFileNode);
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
FspFsvolCreatePostClose(FileDesc);
Irp->IoStatus.Information = 0;
return STATUS_SHARING_VIOLATION;
}
@ -1377,6 +1334,7 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
* stream.
*/
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
/* break Batch oplocks on the main file and this stream */
@ -1432,14 +1390,14 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
Response = FspIopIrpResponse(Irp);
FspFileNodeClose(ExtraFileNode, 0, TRUE);
FspFileNodeDereference(ExtraFileNode);
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
if (STATUS_SUCCESS != Result)
if (STATUS_SUCCESS == Result)
{
FspFileNodeClose(ExtraFileNode, 0, TRUE);
FspFileNodeDereference(ExtraFileNode);
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
}
else
{
FspFsvolCreatePostClose(FileDesc);
Response->IoStatus.Status = (UINT32)Result;
Response->IoStatus.Information = (UINT32)Irp->IoStatus.Information;
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/debug.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/devctl.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/device.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -43,11 +43,9 @@ VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount);
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount);
VOID FspFsvolDeviceDeleteContextList(PVOID *Contexts, ULONG ContextCount);
VOID FspFsvolDeviceDeleteContextByNameList(PVOID *Contexts, ULONG ContextCount);
PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName,
BOOLEAN NextFlag, FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY *RestartKey);
PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName);
@ -82,9 +80,8 @@ VOID FspDeviceDeleteAll(VOID);
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextByNameList)
#pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextList)
#pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextByNameList)
#pragma alloc_text(PAGE, FspFsvolDeviceEnumerateContextByName)
#pragma alloc_text(PAGE, FspFsvolDeviceLookupContextByName)
#pragma alloc_text(PAGE, FspFsvolDeviceInsertContextByName)
@ -367,16 +364,9 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
InitializeListHead(&FsvolDeviceExtension->NotifyList);
FsvolDeviceExtension->InitDoneNotify = 1;
/* create file system statistics */
Result = FspStatisticsCreate(&FsvolDeviceExtension->Statistics);
if (!NT_SUCCESS(Result))
return Result;
FsvolDeviceExtension->InitDoneStat = 1;
/* initialize our context table */
ExInitializeResourceLite(&FsvolDeviceExtension->FileRenameResource);
ExInitializeResourceLite(&FsvolDeviceExtension->ContextTableResource);
InitializeListHead(&FsvolDeviceExtension->ContextList);
RtlInitializeGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable,
FspFsvolDeviceCompareContextByName,
FspFsvolDeviceAllocateContextByName,
@ -418,10 +408,6 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
if (FsvolDeviceExtension->InitDoneTimer)
IoStopTimer(DeviceObject);
/* delete the file system statistics */
if (FsvolDeviceExtension->InitDoneStat)
FspStatisticsDelete(FsvolDeviceExtension->Statistics);
/* uninitialize the FSRTL Notify mechanism */
if (FsvolDeviceExtension->InitDoneNotify)
{
@ -590,50 +576,6 @@ VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject)
ExReleaseResourceLite(&FsvolDeviceExtension->ContextTableResource);
}
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
PVOID *Contexts;
ULONG ContextCount, Index;
*PContexts = 0;
*PContextCount = 0;
ContextCount = 0;
for (
PLIST_ENTRY Head = &FsvolDeviceExtension->ContextList, Entry = Head->Flink;
Head != Entry;
Entry = Entry->Flink)
{
ContextCount++;
}
/* if ContextCount == 0 allocate an empty Context list */
Contexts = FspAlloc(sizeof(PVOID) * (0 != ContextCount ? ContextCount : 1));
if (0 == Contexts)
return STATUS_INSUFFICIENT_RESOURCES;
Index = 0;
for (
PLIST_ENTRY Head = &FsvolDeviceExtension->ContextList, Entry = Head->Flink;
Head != Entry;
Entry = Entry->Flink)
{
ASSERT(Index < ContextCount);
Contexts[Index++] = CONTAINING_RECORD(Entry, FSP_FILE_NODE, ActiveEntry);
/* assume that Contexts can only be FSP_FILE_NODE's */
}
ASSERT(Index == ContextCount);
*PContexts = Contexts;
*PContextCount = Index;
return STATUS_SUCCESS;
}
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount)
{
@ -668,7 +610,7 @@ NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
return STATUS_SUCCESS;
}
VOID FspFsvolDeviceDeleteContextList(PVOID *Contexts, ULONG ContextCount)
VOID FspFsvolDeviceDeleteContextByNameList(PVOID *Contexts, ULONG ContextCount)
{
PAGED_CODE();

View File

@ -1,7 +1,7 @@
/**
* @file sys/dirctl.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -28,7 +28,7 @@
static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
UINT64 DirectoryOffset, PUINT64 PDirectoryOffset,
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
PVOID DestBuf, PULONG PDestLen);
@ -74,6 +74,9 @@ FSP_DRIVER_DISPATCH FspDirectoryControl;
#pragma alloc_text(PAGE, FspDirectoryControl)
#endif
#define FILE_INDEX_FROM_OFFSET(v) ((ULONG)(v))
#define OFFSET_FROM_FILE_INDEX(v) ((UINT64)(v))
enum
{
/* QueryDirectory */
@ -91,7 +94,7 @@ enum
static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
UINT64 DirectoryOffset, PUINT64 PDirectoryOffset,
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
PVOID DestBuf, PULONG PDestLen)
@ -101,7 +104,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
{\
TYPE InfoStruct = { 0 }, *Info = &InfoStruct;\
Info->NextEntryOffset = 0;\
Info->FileIndex = 0;\
Info->FileIndex = FILE_INDEX_FROM_OFFSET(DirInfo->NextOffset);\
Info->FileNameLength = FileName.Length;\
__VA_ARGS__\
Info = DestBuf;\
@ -125,7 +128,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
NTSTATUS Result = STATUS_SUCCESS;
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer, Match;
BOOLEAN Loop = TRUE, DirectoryMarkerFound = FALSE;
BOOLEAN Loop = TRUE, DirectoryOffsetFound = FALSE;
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
PUINT8 DestBufBgn = (PUINT8)DestBuf;
@ -175,18 +178,16 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
break;
}
if (0 != DirectoryOffset && !DirectoryOffsetFound)
{
DirectoryOffsetFound = DirInfo->NextOffset == DirectoryOffset;
continue;
}
FileName.Length =
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
FileName.Buffer = DirInfo->FileNameBuf;
if (0 != DirectoryMarker && 0 != DirectoryMarker->Buffer &&
!DirectoryMarkerFound)
{
DirectoryMarkerFound = 0 == FspFileNameCompare(
&FileName, DirectoryMarker, CaseInsensitive, 0);
continue;
}
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
CopyLength = FileName.Length;
@ -222,6 +223,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
*(PULONG)PrevDestBuf = (ULONG)((PUINT8)DestBuf - (PUINT8)PrevDestBuf);
PrevDestBuf = DestBuf;
*PDirectoryOffset = DirInfo->NextOffset;
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
switch (FileInformationClass)
@ -263,9 +265,6 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
break;
}
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
DestBuf = (PVOID)((PUINT8)DestBuf +
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
@ -274,7 +273,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
Loop = FALSE;
}
else
*DirectoryMarkerOut = FileName;
*PDirectoryOffset = DirInfo->NextOffset;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
@ -316,7 +315,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
NTSTATUS Result;
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
UINT64 DirectoryOffset = FileDesc->DirectoryOffset;
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
@ -324,20 +323,17 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
DirInfoSize = (ULONG)(DirInfoEnd - (PUINT8)DirInfo);
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
0 != FileDesc->DirInfoCacheHint ? 0 : &FileDesc->DirectoryMarker, &DirectoryMarker,
0 != FileDesc->DirInfoCacheHint ? 0 : DirectoryOffset, &DirectoryOffset,
FileInformationClass, ReturnSingleEntry,
&DirInfo, DirInfoSize,
DestBuf, PDestLen);
if (NT_SUCCESS(Result))
{
Result = FspFileDescSetDirectoryMarker(FileDesc, &DirectoryMarker);
if (NT_SUCCESS(Result))
{
if (0 != *PDestLen)
FileDesc->DirectoryHasSuchFile = TRUE;
FileDesc->DirInfoCacheHint = (ULONG)((PUINT8)DirInfo - DirInfoBgn);
}
if (0 != *PDestLen)
FileDesc->DirectoryHasSuchFile = TRUE;
FileDesc->DirectoryOffset = DirectoryOffset;
FileDesc->DirInfoCacheHint = (ULONG)((PUINT8)DirInfo - DirInfoBgn);
}
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
Result = STATUS_NO_SUCH_FILE;
@ -358,7 +354,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
NTSTATUS Result;
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
UINT64 DirectoryOffset = FileDesc->DirectoryOffset;
ASSERT(DirInfo == DestBuf);
FSP_FSCTL_STATIC_ASSERT(
@ -367,19 +363,16 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
"FSP_FSCTL_DIR_INFO must be bigger than FILE_ID_BOTH_DIR_INFORMATION");
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
0, &DirectoryMarker,
0, &DirectoryOffset,
FileInformationClass, ReturnSingleEntry,
&DirInfo, DirInfoSize,
DestBuf, PDestLen);
if (NT_SUCCESS(Result))
{
Result = FspFileDescSetDirectoryMarker(FileDesc, &DirectoryMarker);
if (NT_SUCCESS(Result))
{
if (0 != *PDestLen)
FileDesc->DirectoryHasSuchFile = TRUE;
}
if (0 != *PDestLen)
FileDesc->DirectoryHasSuchFile = TRUE;
FileDesc->DirectoryOffset = DirectoryOffset;
}
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
Result = STATUS_NO_SUCH_FILE;
@ -449,7 +442,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
* counter-productive to try to read more than we need.
*/
#define GetSystemBufferLengthMaybeCached()\
(0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryMarker.Buffer) ||\
(0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryOffset) ||\
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?\
FspFsvolDeviceDirInfoCacheItemSizeMax : Length
#define GetSystemBufferLengthNonCached()\
@ -470,7 +463,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
BOOLEAN ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
PUNICODE_STRING FileName = IrpSp->Parameters.QueryDirectory.FileName;
//ULONG FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
ULONG FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
PVOID Buffer = 0 != Irp->AssociatedIrp.SystemBuffer ?
Irp->AssociatedIrp.SystemBuffer : Irp->UserBuffer;
ULONG Length = IrpSp->Parameters.QueryDirectory.Length;
@ -518,14 +511,26 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
Request = 0;
}
/* reset the FileDesc */
Result = FspFileDescResetDirectory(FileDesc, FileName, RestartScan, IndexSpecified);
/* set the DirectoryPattern in the FileDesc */
Result = FspFileDescResetDirectoryPattern(FileDesc, FileName, RestartScan);
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;
}
/* determine where to (re)start */
if (IndexSpecified)
{
FileDesc->DirectoryHasSuchFile = FALSE;
FileDesc->DirectoryOffset = OFFSET_FROM_FILE_INDEX(FileIndex);
}
else if (RestartScan)
{
FileDesc->DirectoryHasSuchFile = FALSE;
FileDesc->DirectoryOffset = 0;
}
/* see if the required information is still in the cache and valid! */
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
{
@ -565,10 +570,8 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
/* create request */
Result = FspIopCreateRequestEx(Irp, 0,
(FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern &&
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?
FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0) +
(FsvolDeviceExtension->VolumeParams.MaxComponentLength + 1) * sizeof(WCHAR),
FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0,
FspFsvolQueryDirectoryRequestFini, &Request);
if (!NT_SUCCESS(Result))
{
@ -579,38 +582,19 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
Request->Kind = FspFsctlTransactQueryDirectoryKind;
Request->Req.QueryDirectory.UserContext = FileNode->UserContext;
Request->Req.QueryDirectory.UserContext2 = FileDesc->UserContext2;
Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset;
Request->Req.QueryDirectory.Length = SystemBufferLength;
Request->Req.QueryDirectory.CaseSensitive = FileDesc->CaseSensitive;
if (FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern &&
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
if (FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
{
Request->Req.QueryDirectory.Pattern.Offset =
Request->FileName.Size;
Request->Req.QueryDirectory.Pattern.Offset = Request->FileName.Size;
Request->Req.QueryDirectory.Pattern.Size =
FileDesc->DirectoryPattern.Length + sizeof(WCHAR);
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset,
RtlCopyMemory(Request->Buffer + Request->FileName.Size,
FileDesc->DirectoryPattern.Buffer, FileDesc->DirectoryPattern.Length);
*(PWSTR)(Request->Buffer +
Request->Req.QueryDirectory.Pattern.Offset +
FileDesc->DirectoryPattern.Length) = L'\0';
}
if (0 != FileDesc->DirectoryMarker.Buffer)
{
ASSERT(
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
FileDesc->DirectoryMarker.Length);
Request->Req.QueryDirectory.Marker.Offset =
Request->FileName.Size + Request->Req.QueryDirectory.Pattern.Size;
Request->Req.QueryDirectory.Marker.Size =
FileDesc->DirectoryMarker.Length + sizeof(WCHAR);
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset,
FileDesc->DirectoryMarker.Buffer, FileDesc->DirectoryMarker.Length);
*(PWSTR)(Request->Buffer +
Request->Req.QueryDirectory.Marker.Offset +
FileDesc->DirectoryMarker.Length) = L'\0';
*(PWSTR)(Request->Buffer + Request->FileName.Size + FileDesc->DirectoryPattern.Length) =
L'\0';
}
FspFileNodeSetOwner(FileNode, Full, Request);
@ -633,7 +617,6 @@ static NTSTATUS FspFsvolQueryDirectory(
return STATUS_INVALID_DEVICE_REQUEST;
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
@ -653,8 +636,7 @@ static NTSTATUS FspFsvolQueryDirectory(
return STATUS_INVALID_PARAMETER;
/* check that FileName is valid (if supplied) */
if (0 != FileName &&
!FspFileNameIsValidPattern(FileName, FsvolDeviceExtension->VolumeParams.MaxComponentLength))
if (0 != FileName && !FspFileNameIsValidPattern(FileName))
return STATUS_INVALID_PARAMETER;
/* is this an allowed file information class? */
@ -900,6 +882,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
BOOLEAN Success;
ASSERT(FileNode == FileDesc->FileNode);
ASSERT(Request->Req.QueryDirectory.Offset == FileDesc->DirectoryOffset);
if (0 == Response->IoStatus.Information)
{
@ -927,8 +910,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
FSP_RETURN();
}
if (0 == Request->Req.QueryDirectory.Pattern.Size &&
0 == Request->Req.QueryDirectory.Marker.Size &&
if (0 == FileDesc->DirectoryOffset &&
FspFileNodeTrySetDirInfo(FileNode,
Irp->AssociatedIrp.SystemBuffer,
(ULONG)Response->IoStatus.Information,
@ -967,24 +949,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
FspIopResetRequest(Request, FspFsvolQueryDirectoryRequestFini);
Request->Req.QueryDirectory.Address = 0;
Request->Req.QueryDirectory.Marker.Offset = 0;
Request->Req.QueryDirectory.Marker.Size = 0;
if (0 != FileDesc->DirectoryMarker.Buffer)
{
ASSERT(
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
FileDesc->DirectoryMarker.Length);
Request->Req.QueryDirectory.Marker.Offset =
Request->FileName.Size + Request->Req.QueryDirectory.Pattern.Size;
Request->Req.QueryDirectory.Marker.Size =
FileDesc->DirectoryMarker.Length + sizeof(WCHAR);
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset,
FileDesc->DirectoryMarker.Buffer, FileDesc->DirectoryMarker.Length);
*(PWSTR)(Request->Buffer +
Request->Req.QueryDirectory.Marker.Offset +
FileDesc->DirectoryMarker.Length) = L'\0';
}
Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset;
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;

View File

@ -1,7 +1,7 @@
/**
* @file sys/driver.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -176,8 +176,6 @@ NTSTATUS DriverEntry(
static VOID FspDriverMultiVersionInitialize(VOID)
{
FspProcessorCount = KeQueryActiveProcessorCount(0);
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
if (RtlIsNtDdiVersionAvailable(NTDDI_WIN7))
@ -218,6 +216,5 @@ PDEVICE_OBJECT FspFsctlNetDeviceObject;
FAST_IO_DISPATCH FspFastIoDispatch;
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
ULONG FspProcessorCount;
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
ULONG FspMvMdlMappingNoWrite = 0;

View File

@ -1,7 +1,7 @@
/**
* @file sys/driver.h
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -40,7 +40,6 @@
/* private NTSTATUS codes */
#define FSP_STATUS_PRIVATE_BIT (0x20000000)
#define FSP_STATUS_IGNORE_BIT (0x10000000)
#define FSP_STATUS_IOQ_POST (FSP_STATUS_PRIVATE_BIT | 0x0000)
#define FSP_STATUS_IOQ_POST_BEST_EFFORT (FSP_STATUS_PRIVATE_BIT | 0x0001)
@ -199,7 +198,7 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result);
} while (0,0)
#define FSP_LEAVE_MJ(fmt, ...) \
FSP_LEAVE_( \
if (STATUS_PENDING != Result && !(FSP_STATUS_IGNORE_BIT & Result))\
if (STATUS_PENDING != Result) \
{ \
ASSERT(0 == (FSP_STATUS_PRIVATE_BIT & Result) ||\
FSP_STATUS_IOQ_POST == Result || FSP_STATUS_IOQ_POST_BEST_EFFORT == Result);\
@ -226,8 +225,6 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result);
else \
FspIopCompleteIrpEx(Irp, Result, fsp_device_deref);\
} \
else \
Result &= ~FSP_STATUS_IGNORE_BIT;\
IoSetTopLevelIrp(fsp_top_level_irp);\
); \
return Result
@ -440,9 +437,8 @@ enum
FspFileNameStreamTypeNone = 0,
FspFileNameStreamTypeData = 1,
};
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
PUNICODE_STRING StreamPart, PULONG StreamType);
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern, ULONG MaxComponentLength);
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PULONG StreamType);
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern);
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
#if 0
NTSTATUS FspFileNameUpcase(
@ -914,7 +910,7 @@ BOOLEAN FspIopRetryCompleteIrp(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
VOID FspIopSetIrpResponse(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
FSP_FSCTL_TRANSACT_RSP *FspIopIrpResponse(PIRP Irp);
NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request);
NTSTATUS FspIopDispatchComplete(PIRP Irp, FSP_FSCTL_TRANSACT_RSP *Response);
NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
static inline
VOID FspIrpDeleteRequest(PIRP Irp)
{
@ -952,21 +948,6 @@ VOID FspWqPostIrpWorkItem(PIRP Irp);
#define FspWqRepostIrpWorkItem(I, RW, RF)\
FspWqCreateAndPostIrpWorkItem(I, RW, RF, TRUE)
/* file system statistics */
typedef struct
{
FILESYSTEM_STATISTICS Base;
FAT_STATISTICS Specific; /* pretend that we are FAT when it comes to stats */
/* align to 64 bytes */
__declspec(align(64)) UINT8 EndOfStruct[];
} FSP_STATISTICS;
NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics);
VOID FspStatisticsDelete(FSP_STATISTICS *Statistics);
NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLength);
#define FspStatistics(S) (&(S)[KeGetCurrentProcessorNumber() % FspProcessorCount])
#define FspStatisticsInc(S,F) ((S)->F++)
#define FspStatisticsAdd(S,F,V) ((S)->F += (V))
/* device management */
enum
{
@ -1008,7 +989,7 @@ typedef struct
{
FSP_DEVICE_EXTENSION Base;
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1,
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1;
PDEVICE_OBJECT FsctlDeviceObject;
PDEVICE_OBJECT FsvrtDeviceObject;
HANDLE MupHandle;
@ -1025,7 +1006,6 @@ typedef struct
BOOLEAN ExpirationInProgress;
ERESOURCE FileRenameResource;
ERESOURCE ContextTableResource;
LIST_ENTRY ContextList;
RTL_AVL_TABLE ContextByNameTable;
PVOID ContextByNameTableElementStorage;
UNICODE_STRING VolumeName;
@ -1035,7 +1015,6 @@ typedef struct
FSP_FSCTL_VOLUME_INFO VolumeInfo;
PNOTIFY_SYNC NotifySync;
LIST_ENTRY NotifyList;
FSP_STATISTICS *Statistics;
} FSP_FSVOL_DEVICE_EXTENSION;
static inline
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
@ -1066,11 +1045,9 @@ VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount);
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount);
VOID FspFsvolDeviceDeleteContextList(PVOID *Contexts, ULONG ContextCount);
VOID FspFsvolDeviceDeleteContextByNameList(PVOID *Contexts, ULONG ContextCount);
PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName,
BOOLEAN NextFlag, FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY *RestartKey);
PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName);
@ -1105,8 +1082,6 @@ VOID FspDeviceGlobalUnlock(VOID)
extern ERESOURCE FspDeviceGlobalResource;
ExReleaseResourceLite(&FspDeviceGlobalResource);
}
#define FspFsvolDeviceStatistics(DeviceObject)\
FspStatistics(FspFsvolDeviceExtension(DeviceObject)->Statistics)
#define FspFsvolDeviceStoppedStatus(DeviceObject)\
STATUS_VOLUME_DISMOUNTED
//(FILE_DEVICE_DISK_FILE_SYSTEM == (DeviceObject)->DeviceType ?\
@ -1172,13 +1147,11 @@ typedef struct FSP_FILE_NODE
LONG RefCount;
UINT32 DeletePending;
/* locked under FSP_FSVOL_DEVICE_EXTENSION::ContextTableResource */
LONG ActiveCount; /* CREATE w/o CLOSE count */
LONG OpenCount; /* ContextTable ref count */
LONG HandleCount; /* HANDLE count (CREATE/CLEANUP) */
SHARE_ACCESS ShareAccess;
ULONG MainFileDenyDeleteCount; /* number of times main file is denying delete */
ULONG StreamDenyDeleteCount; /* number of times open streams are denying delete */
LIST_ENTRY ActiveEntry;
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage;
/* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource or Header.Resource */
UNICODE_STRING FileName;
@ -1216,31 +1189,26 @@ typedef struct FSP_FILE_NODE
UINT64 IndexNumber;
BOOLEAN IsDirectory;
BOOLEAN IsRootDirectory;
struct FSP_FILE_NODE *MainFileNode;
struct FSP_FILE_NODE *MainFileNode; /* this becomes invalid after our last desc close */
WCHAR FileNameBuf[];
} FSP_FILE_NODE;
typedef struct
{
FSP_FILE_NODE *FileNode;
UINT64 UserContext2;
UINT32 GrantedAccess;
UINT32
CaseSensitive:1, HasTraversePrivilege:1, DeleteOnClose:1,
DidSetMetadata:1,
DidSetFileAttributes:1, DidSetReparsePoint:1, DidSetSecurity:1,
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
DirectoryHasSuchFile:1;
BOOLEAN CaseSensitive;
BOOLEAN HasTraversePrivilege;
BOOLEAN DeleteOnClose;
BOOLEAN DirectoryHasSuchFile;
UNICODE_STRING DirectoryPattern;
UNICODE_STRING DirectoryMarker;
UINT64 DirectoryOffset;
UINT64 DirInfo;
ULONG DirInfoCacheHint;
/* stream support */
HANDLE MainFileHandle;
PFILE_OBJECT MainFileObject;
} FSP_FILE_DESC;
NTSTATUS FspFileNodeCopyActiveList(PDEVICE_OBJECT DeviceObject,
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
NTSTATUS FspFileNodeCopyOpenList(PDEVICE_OBJECT DeviceObject,
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
VOID FspFileNodeDeleteList(FSP_FILE_NODE **FileNodes, ULONG FileNodeCount);
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
@ -1290,7 +1258,8 @@ VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode)
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess,
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending);
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
PFILE_OBJECT FileObject, /* non-0 to remove share access */
@ -1311,10 +1280,9 @@ VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose);
const FSP_FSCTL_FILE_INFO *FileInfo);
BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
const FSP_FSCTL_FILE_INFO *FileInfo, ULONG InfoChangeNumber);
VOID FspFileNodeInvalidateFileInfo(FSP_FILE_NODE *FileNode);
static inline
ULONG FspFileNodeFileInfoChangeNumber(FSP_FILE_NODE *FileNode)
{
@ -1344,7 +1312,6 @@ ULONG FspFileNodeDirInfoChangeNumber(FSP_FILE_NODE *FileNode)
{
return FileNode->DirInfoChangeNumber;
}
VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode);
BOOLEAN FspFileNodeReferenceStreamInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
VOID FspFileNodeSetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
@ -1356,16 +1323,12 @@ ULONG FspFileNodeStreamInfoChangeNumber(FSP_FILE_NODE *FileNode)
FileNode = FileNode->MainFileNode;
return FileNode->StreamInfoChangeNumber;
}
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
BOOLEAN InvalidateCaches);
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action);
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified);
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName);
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName, BOOLEAN Reset);
NTSTATUS FspMainFileOpen(
PDEVICE_OBJECT FsvolDeviceObject,
PDEVICE_OBJECT DeviceObjectHint,
@ -1520,7 +1483,6 @@ extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
extern ERESOURCE FspDeviceGlobalResource;
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
extern const GUID FspMainFileOpenEcpGuid;
extern ULONG FspProcessorCount;
extern FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
extern ULONG FspMvMdlMappingNoWrite;

View File

@ -1,21 +0,0 @@
[Version]
Signature = "$WINDOWS NT$"
Class = Volume
ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
CatalogFile = !CatalogFile!
Provider = !Provider!
[DestinationDirs]
DefaultDestDir = 12
[DefaultInstall]
CopyFiles = Driver.CopyFiles
[Driver.CopyFiles]
!DriverFile!
[SourceDisksFiles]
!DriverFile! = 1
[SourceDisksNames]
1 = Disk1

View File

@ -1,7 +1,7 @@
/**
* @file sys/ea.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/file.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -17,9 +17,7 @@
#include <sys/driver.h>
NTSTATUS FspFileNodeCopyActiveList(PDEVICE_OBJECT DeviceObject,
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
NTSTATUS FspFileNodeCopyOpenList(PDEVICE_OBJECT DeviceObject,
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
VOID FspFileNodeDeleteList(FSP_FILE_NODE **FileNodes, ULONG FileNodeCount);
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
@ -36,7 +34,8 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess,
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending);
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
PFILE_OBJECT FileObject, /* non-0 to remove share access */
@ -57,10 +56,9 @@ VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose);
const FSP_FSCTL_FILE_INFO *FileInfo);
BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
const FSP_FSCTL_FILE_INFO *FileInfo, ULONG InfoChangeNumber);
VOID FspFileNodeInvalidateFileInfo(FSP_FILE_NODE *FileNode);
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
@ -70,24 +68,19 @@ VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
ULONG DirInfoChangeNumber);
static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode);
static VOID FspFileNodeInvalidateDirInfoByName(PDEVICE_OBJECT FsvolDeviceObject,
PUNICODE_STRING FileName);
VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode);
BOOLEAN FspFileNodeReferenceStreamInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
VOID FspFileNodeSetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
ULONG StreamInfoChangeNumber);
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
BOOLEAN InvalidateCaches);
static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
ULONG Filter, ULONG Action);
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified);
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName);
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName, BOOLEAN Reset);
NTSTATUS FspMainFileOpen(
PDEVICE_OBJECT FsvolDeviceObject,
PDEVICE_OBJECT DeviceObjectHint,
@ -104,8 +97,7 @@ VOID FspFileNodeOplockPrepare(PVOID Context, PIRP Irp);
VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFileNodeCopyActiveList)
#pragma alloc_text(PAGE, FspFileNodeCopyOpenList)
#pragma alloc_text(PAGE, FspFileNodeCopyList)
#pragma alloc_text(PAGE, FspFileNodeDeleteList)
#pragma alloc_text(PAGE, FspFileNodeCreate)
#pragma alloc_text(PAGE, FspFileNodeDelete)
@ -130,7 +122,6 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
#pragma alloc_text(PAGE, FspFileNodeTryGetFileInfo)
#pragma alloc_text(PAGE, FspFileNodeSetFileInfo)
#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfo)
#pragma alloc_text(PAGE, FspFileNodeInvalidateFileInfo)
#pragma alloc_text(PAGE, FspFileNodeReferenceSecurity)
#pragma alloc_text(PAGE, FspFileNodeSetSecurity)
#pragma alloc_text(PAGE, FspFileNodeTrySetSecurity)
@ -138,8 +129,6 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
// !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo)
// !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo)
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateDirInfo)
#pragma alloc_text(PAGE, FspFileNodeInvalidateDirInfoByName)
#pragma alloc_text(PAGE, FspFileNodeInvalidateParentDirInfo)
// !#pragma alloc_text(PAGE, FspFileNodeReferenceStreamInfo)
// !#pragma alloc_text(PAGE, FspFileNodeSetStreamInfo)
// !#pragma alloc_text(PAGE, FspFileNodeTrySetStreamInfo)
@ -149,8 +138,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
#pragma alloc_text(PAGE, FspFileDescCreate)
#pragma alloc_text(PAGE, FspFileDescDelete)
#pragma alloc_text(PAGE, FspFileDescResetDirectory)
#pragma alloc_text(PAGE, FspFileDescSetDirectoryMarker)
#pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern)
#pragma alloc_text(PAGE, FspMainFileOpen)
#pragma alloc_text(PAGE, FspMainFileClose)
#pragma alloc_text(PAGE, FspFileNodeOplockPrepare)
@ -174,86 +162,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
if (IrpValid) \
FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3))
#define GATHER_DESCENDANTS(FILENAME, REFERENCE, ...)\
FSP_FILE_NODE *DescendantFileNode;\
FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;\
ULONG DescendantFileNodeCount, DescendantFileNodeIndex;\
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY RestartKey;\
DescendantFileNodes = DescendantFileNodeArray;\
DescendantFileNodeCount = 0;\
memset(&RestartKey, 0, sizeof RestartKey);\
for (;;) \
{ \
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
FILENAME, FALSE, &RestartKey);\
if (0 == DescendantFileNode) \
break; \
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
__VA_ARGS__; \
if (REFERENCE) \
FspFileNodeReference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\
if (ARRAYSIZE(DescendantFileNodeArray) > DescendantFileNodeCount)\
DescendantFileNodes[DescendantFileNodeCount] = DescendantFileNode;\
DescendantFileNodeCount++; \
} \
if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount ||\
DEBUGTEST_EX(0 != DescendantFileNodeCount, 10, FALSE)) \
{ \
DescendantFileNodes = FspAllocMustSucceed(DescendantFileNodeCount * sizeof(FSP_FILE_NODE *));\
DescendantFileNodeIndex = 0; \
memset(&RestartKey, 0, sizeof RestartKey);\
for (;;) \
{ \
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
FILENAME, FALSE, &RestartKey);\
if (0 == DescendantFileNode)\
break; \
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
__VA_ARGS__; \
DescendantFileNodes[DescendantFileNodeIndex] = DescendantFileNode;\
DescendantFileNodeIndex++; \
ASSERT(DescendantFileNodeCount >= DescendantFileNodeIndex);\
} \
ASSERT(DescendantFileNodeCount == DescendantFileNodeIndex);\
} \
((VOID)0)
#define SCATTER_DESCENDANTS(REFERENCE) \
if (REFERENCE) \
{ \
for ( \
DescendantFileNodeIndex = 0;\
DescendantFileNodeCount > DescendantFileNodeIndex;\
DescendantFileNodeIndex++) \
{ \
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];\
FspFileNodeDereference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\
} \
} \
if (DescendantFileNodeArray != DescendantFileNodes)\
FspFree(DescendantFileNodes); \
((VOID)0)
NTSTATUS FspFileNodeCopyActiveList(PDEVICE_OBJECT DeviceObject,
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount)
{
PAGED_CODE();
NTSTATUS Result;
ULONG Index;
FspFsvolDeviceLockContextTable(DeviceObject);
Result = FspFsvolDeviceCopyContextList(DeviceObject, PFileNodes, PFileNodeCount);
if (NT_SUCCESS(Result))
{
for (Index = 0; *PFileNodeCount > Index; Index++)
FspFileNodeReference((*PFileNodes)[Index]);
}
FspFsvolDeviceUnlockContextTable(DeviceObject);
return Result;
}
NTSTATUS FspFileNodeCopyOpenList(PDEVICE_OBJECT DeviceObject,
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount)
{
PAGED_CODE();
@ -282,7 +191,7 @@ VOID FspFileNodeDeleteList(FSP_FILE_NODE **FileNodes, ULONG FileNodeCount)
for (Index = 0; FileNodeCount > Index; Index++)
FspFileNodeDereference(FileNodes[Index]);
FspFsvolDeviceDeleteContextList(FileNodes, FileNodeCount);
FspFsvolDeviceDeleteContextByNameList(FileNodes, FileNodeCount);
}
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
@ -339,9 +248,6 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
if (0 != FileNode->MainFileNode)
FspFileNodeDereference(FileNode->MainFileNode);
FsRtlUninitializeOplock(FspFileNodeAddrOfOplock(FileNode));
FsRtlUninitializeFileLock(&FileNode->FileLock);
@ -718,14 +624,6 @@ exit:
if (0 != OpenedFileNode)
{
FspFileNodeReference(OpenedFileNode);
ASSERT(0 <= OpenedFileNode->ActiveCount);
ASSERT(0 <= OpenedFileNode->OpenCount);
ASSERT(0 <= OpenedFileNode->HandleCount);
if (0 == OpenedFileNode->ActiveCount++)
InsertTailList(&FspFsvolDeviceExtension(FsvolDeviceObject)->ContextList,
&FileNode->ActiveEntry);
OpenedFileNode->OpenCount++;
OpenedFileNode->HandleCount++;
}
@ -737,7 +635,8 @@ exit:
return Result;
}
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags)
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending)
{
/*
* Determine whether a FileNode should be deleted. Note that when FileNode->DeletePending
@ -751,7 +650,7 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
BOOLEAN DeletePending, SetAllocationSize, SingleHandle;
BOOLEAN DeletePending, SingleHandle;
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
@ -760,13 +659,12 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG
DeletePending = 0 != FileNode->DeletePending;
MemoryBarrier();
SetAllocationSize = !DeletePending && FileNode->TruncateOnClose;
SingleHandle = 1 == FileNode->HandleCount;
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
*PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0;
if (0 != PDeletePending)
*PDeletePending = SingleHandle && DeletePending;
}
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
@ -786,7 +684,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
LARGE_INTEGER TruncateSize = { 0 }, *PTruncateSize = 0;
BOOLEAN DeletePending;
BOOLEAN DeletedFromContextTable = FALSE;
@ -810,7 +708,6 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
IoRemoveShareAccess(FileObject, &FileNode->ShareAccess);
ASSERT(0 < FileNode->HandleCount);
if (0 == --FileNode->HandleCount)
{
DeletePending = 0 != FileNode->DeletePending;
@ -818,72 +715,23 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
if (DeletePending)
{
PTruncateSize = &TruncateSize;
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,
&DeletedFromContextTable);
ASSERT(DeletedFromContextTable);
FileNode->OpenCount = 0;
FileNode->Header.FileSize.QuadPart = 0;
/*
* We now have to deal with the scenario where there are cleaned up,
* but unclosed streams for this file still in the context table.
*/
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.NamedStreams &&
0 == FileNode->MainFileNode)
{
BOOLEAN StreamDeletedFromContextTable;
USHORT FileNameLength = FileNode->FileName.Length;
GATHER_DESCENDANTS(&FileNode->FileName, FALSE,
if (DescendantFileNode->FileName.Length > FileNameLength &&
L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)])
break;
ASSERT(FileNode != DescendantFileNode);
ASSERT(0 != DescendantFileNode->OpenCount);
ASSERT(0 == DescendantFileNode->HandleCount);
);
for (
DescendantFileNodeIndex = 0;
DescendantFileNodeCount > DescendantFileNodeIndex;
DescendantFileNodeIndex++)
{
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &DescendantFileNode->FileName,
&StreamDeletedFromContextTable);
if (StreamDeletedFromContextTable)
{
DescendantFileNode->OpenCount = 0;
FspFileNodeDereference(DescendantFileNode);
}
}
SCATTER_DESCENDANTS(FALSE);
}
}
if (DeletePending || FileNode->TruncateOnClose)
else if (FileNode->TruncateOnClose && FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FsvolDeviceObject);
UINT64 AllocationUnit =
FsvolDeviceExtension->VolumeParams.SectorSize *
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
/*
* Even when the FileInfo is expired, this is the best guess for a file size
* without asking the user-mode file system.
*/
TruncateSize = FileNode->Header.FileSize;
PTruncateSize = &TruncateSize;
FileNode->Header.AllocationSize.QuadPart = (TruncateSize.QuadPart + AllocationUnit - 1)
/ AllocationUnit * AllocationUnit;
}
FileNode->TruncateOnClose = FALSE;
}
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
@ -943,15 +791,6 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
ASSERT(DeletedFromContextTable);
}
ASSERT(0 < FileNode->ActiveCount);
if (0 == --FileNode->ActiveCount)
{
ASSERT(0 == FileNode->OpenCount);
ASSERT(0 == FileNode->HandleCount);
RemoveEntryList(&FileNode->ActiveEntry);
}
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
if (DeletedFromContextTable)
@ -1015,6 +854,65 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
return IoStatus.Status;
}
#define GATHER_DESCENDANTS(FILENAME, REFERENCE, ...)\
FSP_FILE_NODE *DescendantFileNode;\
FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;\
ULONG DescendantFileNodeCount, DescendantFileNodeIndex;\
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY RestartKey;\
DescendantFileNodes = DescendantFileNodeArray;\
DescendantFileNodeCount = 0;\
memset(&RestartKey, 0, sizeof RestartKey);\
for (;;) \
{ \
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
FILENAME, FALSE, &RestartKey);\
if (0 == DescendantFileNode) \
break; \
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
__VA_ARGS__; \
if (REFERENCE) \
FspFileNodeReference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\
if (ARRAYSIZE(DescendantFileNodeArray) > DescendantFileNodeCount)\
DescendantFileNodes[DescendantFileNodeCount] = DescendantFileNode;\
DescendantFileNodeCount++; \
} \
if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount ||\
DEBUGTEST_EX(0 != DescendantFileNodeCount, 10, FALSE)) \
{ \
DescendantFileNodes = FspAllocMustSucceed(DescendantFileNodeCount * sizeof(FSP_FILE_NODE *));\
DescendantFileNodeIndex = 0; \
memset(&RestartKey, 0, sizeof RestartKey);\
for (;;) \
{ \
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
FILENAME, FALSE, &RestartKey);\
if (0 == DescendantFileNode)\
break; \
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
__VA_ARGS__; \
DescendantFileNodes[DescendantFileNodeIndex] = DescendantFileNode;\
DescendantFileNodeIndex++; \
ASSERT(DescendantFileNodeCount >= DescendantFileNodeIndex);\
} \
ASSERT(DescendantFileNodeCount == DescendantFileNodeIndex);\
} \
((VOID)0)
#define SCATTER_DESCENDANTS(REFERENCE) \
if (REFERENCE) \
{ \
for ( \
DescendantFileNodeIndex = 0;\
DescendantFileNodeCount > DescendantFileNodeIndex;\
DescendantFileNodeIndex++) \
{ \
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];\
FspFileNodeDereference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\
} \
} \
if (DescendantFileNodeArray != DescendantFileNodes)\
FspFree(DescendantFileNodes); \
((VOID)0)
VOID FspFileNodeOverwriteStreams(FSP_FILE_NODE *FileNode)
{
/*
@ -1339,7 +1237,8 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
if (0 == DescendantFileNode)
break;
if (DescendantFileNode != FileNode && 0 < DescendantFileNode->HandleCount)
/* if this is the FileNode being renamed then HandleCount must be 1, else 0 */
if ((DescendantFileNode == FileNode) < DescendantFileNode->HandleCount)
{
/* release the FileNode in case of failure! */
FspFileNodeReleaseF(FileNode, AcquireFlags);
@ -1507,7 +1406,7 @@ BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *
}
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
const FSP_FSCTL_FILE_INFO *FileInfo, BOOLEAN TruncateOnClose)
const FSP_FSCTL_FILE_INFO *FileInfo)
{
PAGED_CODE();
@ -1521,20 +1420,8 @@ VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
AllocationSize = (AllocationSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
if (TruncateOnClose)
{
if ((UINT64)FileNode->Header.AllocationSize.QuadPart != AllocationSize ||
(UINT64)FileNode->Header.FileSize.QuadPart != FileInfo->FileSize)
FileNode->TruncateOnClose = TRUE;
FileNode->Header.AllocationSize.QuadPart = AllocationSize;
FileNode->Header.FileSize.QuadPart = FileInfo->FileSize;
}
else
{
FileNode->Header.AllocationSize.QuadPart = AllocationSize;
FileNode->Header.FileSize.QuadPart = FileInfo->FileSize;
}
FileNode->Header.AllocationSize.QuadPart = AllocationSize;
FileNode->Header.FileSize.QuadPart = FileInfo->FileSize;
FileNode->FileInfoExpirationTime = FileNode->BasicInfoExpirationTime =
FspExpirationTimeFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
@ -1624,20 +1511,10 @@ BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileOb
if (FspFileNodeFileInfoChangeNumber(FileNode) != InfoChangeNumber)
return FALSE;
FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo, FALSE);
FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo);
return TRUE;
}
VOID FspFileNodeInvalidateFileInfo(FSP_FILE_NODE *FileNode)
{
PAGED_CODE();
FileNode->FileInfoExpirationTime = FileNode->BasicInfoExpirationTime = 0;
if (0 != FileNode->MainFileNode)
FileNode->MainFileNode->BasicInfoExpirationTime = 0;
}
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
{
PAGED_CODE();
@ -1750,40 +1627,6 @@ static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode)
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo);
}
static VOID FspFileNodeInvalidateDirInfoByName(PDEVICE_OBJECT FsvolDeviceObject,
PUNICODE_STRING FileName)
{
PAGED_CODE();
FSP_FILE_NODE *FileNode;
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
FileNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, FileName);
if (0 != FileNode)
FspFileNodeReference(FileNode);
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
if (0 != FileNode)
{
FspFileNodeInvalidateDirInfo(FileNode);
FspFileNodeDereference(FileNode);
}
}
VOID FspFileNodeInvalidateParentDirInfo(FSP_FILE_NODE *FileNode)
{
PAGED_CODE();
if (sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0])
return; /* root does not have a parent */
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
UNICODE_STRING Parent, Suffix;
FspFileNameSuffix(&FileNode->FileName, &Parent, &Suffix);
FspFileNodeInvalidateDirInfoByName(FsvolDeviceObject, &Parent);
}
BOOLEAN FspFileNodeReferenceStreamInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
{
// !PAGED_CODE();
@ -1842,7 +1685,7 @@ BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULON
return TRUE;
}
VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode)
static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode)
{
// !PAGED_CODE();
@ -1863,8 +1706,8 @@ VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode)
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, StreamInfo);
}
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
BOOLEAN InvalidateCaches)
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
ULONG Filter, ULONG Action)
{
/* FileNode must be acquired (exclusive or shared) Main */
@ -1873,6 +1716,32 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
UNICODE_STRING Parent, Suffix;
FSP_FILE_NODE *ParentNode;
FspFileNameSuffix(&FileNode->FileName, &Parent, &Suffix);
switch (Action)
{
case FILE_ACTION_ADDED:
case FILE_ACTION_REMOVED:
//case FILE_ACTION_MODIFIED:
case FILE_ACTION_RENAMED_OLD_NAME:
case FILE_ACTION_RENAMED_NEW_NAME:
FspFsvolDeviceInvalidateVolumeInfo(FsvolDeviceObject);
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
ParentNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &Parent);
if (0 != ParentNode)
FspFileNodeReference(ParentNode);
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
if (0 != ParentNode)
{
FspFileNodeInvalidateDirInfo(ParentNode);
FspFileNodeDereference(ParentNode);
}
break;
}
if (0 != FileNode->MainFileNode)
{
@ -1880,78 +1749,65 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action
SetFlag(Filter, FILE_NOTIFY_CHANGE_STREAM_NAME);
if (FlagOn(Filter, FILE_NOTIFY_CHANGE_SIZE))
SetFlag(Filter, FILE_NOTIFY_CHANGE_STREAM_SIZE);
if (FlagOn(Filter, FILE_NOTIFY_CHANGE_LAST_WRITE))
SetFlag(Filter, FILE_NOTIFY_CHANGE_STREAM_WRITE);
ClearFlag(Filter, ~(FILE_NOTIFY_CHANGE_STREAM_NAME | FILE_NOTIFY_CHANGE_STREAM_SIZE |
FILE_NOTIFY_CHANGE_STREAM_WRITE));
/* ???: what about FILE_NOTIFY_CHANGE_STREAM_WRITE */
ClearFlag(Filter, ~(FILE_NOTIFY_CHANGE_STREAM_NAME | FILE_NOTIFY_CHANGE_STREAM_SIZE));
switch (Action)
{
case FILE_ACTION_ADDED:
Action = FILE_ACTION_ADDED_STREAM;
FspFileNodeInvalidateStreamInfo(FileNode);
break;
case FILE_ACTION_REMOVED:
Action = FILE_ACTION_REMOVED_STREAM;
FspFileNodeInvalidateStreamInfo(FileNode);
break;
case FILE_ACTION_MODIFIED:
Action = FILE_ACTION_MODIFIED_STREAM;
//FspFileNodeInvalidateStreamInfo(FileNode);
break;
}
}
if (0 != Filter)
{
FspFileNameSuffix(&FileNode->FileName, &Parent, &Suffix);
if (InvalidateCaches)
{
FspFsvolDeviceInvalidateVolumeInfo(FsvolDeviceObject);
if (0 == FileNode->MainFileNode)
{
if (sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0])
; /* root does not have a parent */
else
FspFileNodeInvalidateDirInfoByName(FsvolDeviceObject, &Parent);
}
else
FspFileNodeInvalidateStreamInfo(FileNode);
}
FspNotifyReportChange(
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList,
&FileNode->FileName,
(USHORT)((PUINT8)Suffix.Buffer - (PUINT8)FileNode->FileName.Buffer),
0, Filter, Action);
}
}
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp)
{
PAGED_CODE();
NTSTATUS Result;
IoMarkIrpPending(Irp);
FspFileNodeSetOwnerF(FileNode, FspIrpFlags(Irp), Irp);
try
{
Result = FsRtlProcessFileLock(&FileNode->FileLock, Irp, FileNode);
FsRtlProcessFileLock(&FileNode->FileLock, Irp, FileNode);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
Irp->IoStatus.Status = GetExceptionCode();
Irp->IoStatus.Information = 0;
Result = FspFileNodeCompleteLockIrp(FileNode, Irp);
FspFileNodeCompleteLockIrp(FileNode, Irp);
}
return Result;
return STATUS_PENDING;
}
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp)
{
PAGED_CODE();
FSP_FILE_NODE *FileNode = Context;
NTSTATUS Result = Irp->IoStatus.Status;
FspFileNodeReleaseOwnerF(FileNode, FspIrpFlags(Irp), Irp);
DEBUGLOGIRP(Irp, Result);
FspIopCompleteIrp(Irp, Result);
@ -1987,19 +1843,15 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc)
RtlFreeUnicodeString(&FileDesc->DirectoryPattern);
}
if (0 != FileDesc->DirectoryMarker.Buffer)
FspFree(FileDesc->DirectoryMarker.Buffer);
FspFree(FileDesc);
}
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified)
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName, BOOLEAN Reset)
{
PAGED_CODE();
if (0 == FileDesc->DirectoryPattern.Buffer ||
(RestartScan && 0 != FileName && 0 != FileName->Length))
if (Reset || 0 == FileDesc->DirectoryPattern.Buffer)
{
UNICODE_STRING DirectoryPattern;
@ -2036,63 +1888,7 @@ NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
}
FileDesc->DirectoryPattern = DirectoryPattern;
FileDesc->DirectoryHasSuchFile = FALSE;
if (0 != FileDesc->DirectoryMarker.Buffer)
{
FspFree(FileDesc->DirectoryMarker.Buffer);
FileDesc->DirectoryMarker.Buffer = 0;
}
}
else if (RestartScan)
{
ASSERT(0 == FileName || 0 == FileName->Length);
FileDesc->DirectoryHasSuchFile = FALSE;
if (0 != FileDesc->DirectoryMarker.Buffer)
{
FspFree(FileDesc->DirectoryMarker.Buffer);
FileDesc->DirectoryMarker.Buffer = 0;
}
}
else if (IndexSpecified && 0 != FileName && 0 != FileName->Length)
{
NTSTATUS Result;
Result = FspFileDescSetDirectoryMarker(FileDesc, FileName);
if (!NT_SUCCESS(Result))
return Result;
FileDesc->DirectoryHasSuchFile = FALSE;
}
return STATUS_SUCCESS;
}
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
PUNICODE_STRING FileName)
{
if (&FileDesc->DirectoryMarker == FileName)
return STATUS_SUCCESS;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FileDesc->FileNode->FsvolDeviceObject);
UNICODE_STRING DirectoryMarker;
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength < FileName->Length)
return STATUS_OBJECT_NAME_INVALID;
DirectoryMarker.Length = DirectoryMarker.MaximumLength = FileName->Length;
DirectoryMarker.Buffer = FspAlloc(FileName->Length);
if (0 == DirectoryMarker.Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(DirectoryMarker.Buffer, FileName->Buffer, FileName->Length);
if (0 != FileDesc->DirectoryMarker.Buffer)
FspFree(FileDesc->DirectoryMarker.Buffer);
FileDesc->DirectoryMarker = DirectoryMarker;
return STATUS_SUCCESS;
}
@ -2119,9 +1915,7 @@ NTSTATUS FspMainFileOpen(
PFILE_OBJECT MainFileObject;
/* assert that the supplied name is actually a main file name */
ASSERT(FspFileNameIsValid(MainFileName,
FsvolDeviceExtension->VolumeParams.MaxComponentLength,
0, 0));
ASSERT(FspFileNameIsValid(MainFileName, 0, 0));
*PMainFileHandle = 0;
*PMainFileObject = 0;
@ -2131,11 +1925,11 @@ NTSTATUS FspMainFileOpen(
case FILE_CREATE:
case FILE_OPEN_IF:
case FILE_OVERWRITE_IF:
case FILE_SUPERSEDE:
Disposition = FILE_OPEN_IF;
break;
case FILE_OPEN:
case FILE_OVERWRITE:
case FILE_SUPERSEDE:
Disposition = FILE_OPEN;
break;
default:

View File

@ -1,7 +1,7 @@
/**
* @file sys/fileinfo.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -134,7 +134,6 @@ static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject,
PFILE_ALL_INFORMATION Info = (PFILE_ALL_INFORMATION)*PBuffer;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
BOOLEAN DeletePending;
if (0 == FileInfo)
{
@ -145,9 +144,6 @@ static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject,
return FspFsvolQueryNameInformation(FileObject, PBuffer, BufferEnd);
}
DeletePending = 0 != FileNode->DeletePending;
MemoryBarrier();
Info->BasicInformation.CreationTime.QuadPart = FileInfo->CreationTime;
Info->BasicInformation.LastAccessTime.QuadPart = FileInfo->LastAccessTime;
Info->BasicInformation.LastWriteTime.QuadPart = FileInfo->LastWriteTime;
@ -158,7 +154,7 @@ static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject,
Info->StandardInformation.AllocationSize.QuadPart = FileInfo->AllocationSize;
Info->StandardInformation.EndOfFile.QuadPart = FileInfo->FileSize;
Info->StandardInformation.NumberOfLinks = 1;
Info->StandardInformation.DeletePending = DeletePending || FileObject->DeletePending;
Info->StandardInformation.DeletePending = FileObject->DeletePending;
Info->StandardInformation.Directory = FileNode->IsDirectory;
Info->InternalInformation.IndexNumber.QuadPart = FileNode->IndexNumber;
@ -367,7 +363,6 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
PFILE_STANDARD_INFORMATION Info = (PFILE_STANDARD_INFORMATION)*PBuffer;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
BOOLEAN DeletePending;
if (0 == FileInfo)
{
@ -377,13 +372,10 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
return STATUS_SUCCESS;
}
DeletePending = 0 != FileNode->DeletePending;
MemoryBarrier();
Info->AllocationSize.QuadPart = FileInfo->AllocationSize;
Info->EndOfFile.QuadPart = FileInfo->FileSize;
Info->NumberOfLinks = 1;
Info->DeletePending = DeletePending || FileObject->DeletePending;
Info->DeletePending = FileObject->DeletePending;
Info->Directory = FileNode->IsDirectory;
*PBuffer = (PVOID)(Info + 1);
@ -627,7 +619,7 @@ static NTSTATUS FspFsvolQueryInformation(
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_DEVICE_REQUEST;
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
@ -671,7 +663,7 @@ static NTSTATUS FspFsvolQueryInformation(
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
return Result;
case FileHardLinkInformation:
Result = STATUS_NOT_SUPPORTED; /* no hard link support */
Result = STATUS_INVALID_PARAMETER; /* no hard link support */
return Result;
case FileInternalInformation:
Result = FspFsvolQueryInternalInformation(FileObject, &Buffer, BufferEnd);
@ -682,9 +674,6 @@ static NTSTATUS FspFsvolQueryInformation(
Result = FspFsvolQueryNameInformation(FileObject, &Buffer, BufferEnd);
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
return Result;
case FileAlternateNameInformation:
Result = STATUS_OBJECT_NAME_NOT_FOUND; /* WinFsp does not support short names */
return Result;
case FileNetworkOpenInformation:
Result = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, 0);
break;
@ -904,12 +893,13 @@ static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject,
{
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.SetInformation.FileInfo, TRUE);
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.SetInformation.FileInfo);
FileNode->TruncateOnClose = TRUE;
/* mark the file object as modified */
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED, FALSE);
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
}
return STATUS_SUCCESS;
@ -925,15 +915,6 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject,
{
if (sizeof(FILE_BASIC_INFORMATION) > Length)
return STATUS_INVALID_PARAMETER;
PFILE_BASIC_INFORMATION Info = (PFILE_BASIC_INFORMATION)Buffer;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
UINT32 FileAttributes = Info->FileAttributes;
/* do not allow the temporary bit on a directory */
if (FileNode->IsDirectory &&
FlagOn(FileAttributes, FILE_ATTRIBUTE_TEMPORARY))
return STATUS_INVALID_PARAMETER;
}
else if (0 == Response)
{
@ -954,53 +935,23 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject,
Request->Req.SetInformation.Info.Basic.CreationTime = Info->CreationTime.QuadPart;
Request->Req.SetInformation.Info.Basic.LastAccessTime = Info->LastAccessTime.QuadPart;
Request->Req.SetInformation.Info.Basic.LastWriteTime = Info->LastWriteTime.QuadPart;
Request->Req.SetInformation.Info.Basic.ChangeTime = Info->ChangeTime.QuadPart;
}
else
{
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
ULONG NotifyFilter = 0;
ASSERT(FileNode == FileDesc->FileNode);
if (!FileNode->IsDirectory)
{
/* properly set temporary bit for lazy writer */
if (FlagOn(Response->Rsp.SetInformation.FileInfo.FileAttributes,
FILE_ATTRIBUTE_TEMPORARY))
SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
else
ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
}
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.SetInformation.FileInfo, FALSE);
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.SetInformation.FileInfo);
if ((UINT32)-1 != Request->Req.SetInformation.Info.Basic.FileAttributes)
{
FileDesc->DidSetFileAttributes = TRUE;
NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
}
if (0 != Request->Req.SetInformation.Info.Basic.CreationTime)
{
FileDesc->DidSetCreationTime = TRUE;
NotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
}
if (0 != Request->Req.SetInformation.Info.Basic.LastAccessTime)
{
FileDesc->DidSetLastAccessTime = TRUE;
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
if (0 != Request->Req.SetInformation.Info.Basic.LastWriteTime)
{
FileDesc->DidSetLastWriteTime = TRUE;
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
}
if (0 != Request->Req.SetInformation.Info.Basic.ChangeTime)
FileDesc->DidSetChangeTime = TRUE;
FileDesc->DidSetMetadata = TRUE;
FspFileNodeNotifyChange(FileNode, NotifyFilter, FILE_ACTION_MODIFIED, TRUE/*FALSE*/);
FspFileNodeNotifyChange(FileNode, NotifyFilter, FILE_ACTION_MODIFIED);
}
return STATUS_SUCCESS;
@ -1045,12 +996,13 @@ static NTSTATUS FspFsvolSetEndOfFileInformation(PFILE_OBJECT FileObject,
{
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.SetInformation.FileInfo, TRUE);
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.SetInformation.FileInfo);
FileNode->TruncateOnClose = TRUE;
/* mark the file object as modified -- FastFat does this only for Allocation though! */
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED, FALSE);
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
}
return STATUS_SUCCESS;
@ -1199,7 +1151,6 @@ static NTSTATUS FspFsvolSetRenameInformation(
PAGED_CODE();
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
PFILE_OBJECT TargetFileObject = IrpSp->Parameters.SetFile.FileObject;
BOOLEAN ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
@ -1225,9 +1176,7 @@ static NTSTATUS FspFsvolSetRenameInformation(
if (FileNode->IsRootDirectory)
/* cannot rename root directory */
return STATUS_INVALID_PARAMETER;
if (!FspFileNameIsValid(&FileNode->FileName,
FsvolDeviceExtension->VolumeParams.MaxComponentLength,
0, 0))
if (!FspFileNameIsValid(&FileNode->FileName, 0, 0))
/* cannot rename streams (WinFsp limitation) */
return STATUS_INVALID_PARAMETER;
@ -1261,12 +1210,7 @@ retry:
}
Suffix.MaximumLength = Suffix.Length;
if (!FspFileNameIsValid(&Remain,
FsvolDeviceExtension->VolumeParams.MaxComponentLength,
0, 0) ||
!FspFileNameIsValid(&Suffix,
FsvolDeviceExtension->VolumeParams.MaxComponentLength,
0, 0))
if (!FspFileNameIsValid(&Remain, 0, 0) || !FspFileNameIsValid(&Suffix, 0, 0))
{
/* cannot rename streams (WinFsp limitation) */
Result = STATUS_INVALID_PARAMETER;
@ -1397,8 +1341,7 @@ static NTSTATUS FspFsvolSetRenameInformationSuccess(
/* fastfat has some really arcane rules on rename notifications; simplify! */
FspFileNodeNotifyChange(FileNode,
FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_RENAMED_OLD_NAME,
TRUE);
FILE_ACTION_RENAMED_OLD_NAME);
NewFileName.Length = NewFileName.MaximumLength =
Request->Req.SetInformation.Info.Rename.NewFileName.Size - sizeof(WCHAR);
@ -1409,8 +1352,7 @@ static NTSTATUS FspFsvolSetRenameInformationSuccess(
/* fastfat has some really arcane rules on rename notifications; simplify! */
FspFileNodeNotifyChange(FileNode,
FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_RENAMED_NEW_NAME,
TRUE);
FILE_ACTION_RENAMED_NEW_NAME);
FspIopRequestContext(Request, RequestFileNode) = 0;
FspIopRequestContext(Request, RequestDeviceObject) = 0;
@ -1429,7 +1371,7 @@ static NTSTATUS FspFsvolSetInformation(
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_DEVICE_REQUEST;
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
@ -1460,7 +1402,7 @@ static NTSTATUS FspFsvolSetInformation(
Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, 0, 0);
break;
case FileLinkInformation:
Result = STATUS_NOT_SUPPORTED; /* no hard link support */
Result = STATUS_INVALID_PARAMETER; /* no hard link support */
return Result;
case FilePositionInformation:
Result = FspFsvolSetPositionInformation(FileObject, Buffer, Length);

View File

@ -1,7 +1,7 @@
/**
* @file sys/flush.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -58,7 +58,7 @@ static NTSTATUS FspFsvolFlushBuffers(
*/
if (!FspFileNodeIsValid(FileNode) || FileNode->IsRootDirectory)
{
Result = FspFileNodeCopyOpenList(FsvolDeviceObject, &FileNodes, &FileNodeCount);
Result = FspFileNodeCopyList(FsvolDeviceObject, &FileNodes, &FileNodeCount);
if (!NT_SUCCESS(Result))
return Result;
@ -149,21 +149,7 @@ NTSTATUS FspFsvolFlushBuffersComplete(
else if (!NT_SUCCESS(FlushResult))
Result = FlushResult;
else
{
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
/*
* A flush request on the volume (or the root directory according to FastFat)
* is a request to flush the whole volume.
*/
if (!FspFileNodeIsValid(FileNode) || FileNode->IsRootDirectory)
;
else
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.FlushBuffers.FileInfo, TRUE);
Result = STATUS_SUCCESS;
}
FSP_LEAVE_IOC("FileObject=%p",
IrpSp->FileObject);

View File

@ -1,7 +1,7 @@
/**
* @file sys/fsctl.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -29,12 +29,6 @@ static NTSTATUS FspFsvolFileSystemControlOplock(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static IO_COMPLETION_ROUTINE FspFsvolFileSystemControlOplockCompletion;
static WORKER_THREAD_ROUTINE FspFsvolFileSystemControlOplockCompletionWork;
static NTSTATUS FspFsvolFileSystemControlQueryPersistentVolumeState(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolFileSystemControlGetStatistics(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolFileSystemControlGetRetrievalPointers(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolFileSystemControl(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete;
@ -48,9 +42,6 @@ FSP_DRIVER_DISPATCH FspFileSystemControl;
#pragma alloc_text(PAGE, FspFsvolFileSystemControlOplock)
// !#pragma alloc_text(PAGE, FspFsvolFileSystemControlOplockCompletion)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlOplockCompletionWork)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlQueryPersistentVolumeState)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlGetStatistics)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlGetRetrievalPointers)
#pragma alloc_text(PAGE, FspFsvolFileSystemControl)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlComplete)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlRequestFini)
@ -114,7 +105,7 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(FileObject->FsContext))
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_DEVICE_REQUEST;
NTSTATUS Result;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
@ -134,51 +125,17 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
if (IsWrite)
{
ASSERT(
FSCTL_SET_REPARSE_POINT == FsControlCode ||
FSCTL_DELETE_REPARSE_POINT == FsControlCode);
if (0 == InputBuffer || 0 == InputBufferLength)
return STATUS_INVALID_BUFFER_SIZE;
if (0 != OutputBufferLength)
if (0 == InputBuffer || 0 == InputBufferLength ||
FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX - (FileNode->FileName.Length + sizeof(WCHAR)) <
InputBufferLength)
return STATUS_INVALID_PARAMETER;
Result = FsRtlValidateReparsePointBuffer(InputBufferLength, InputBuffer);
if (!NT_SUCCESS(Result))
return Result;
ReparseData = (PREPARSE_DATA_BUFFER)InputBuffer;
if (FSCTL_SET_REPARSE_POINT == FsControlCode)
{
if (FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX - (FileNode->FileName.Length + sizeof(WCHAR)) <
InputBufferLength)
return STATUS_IO_REPARSE_DATA_INVALID;
Result = FsRtlValidateReparsePointBuffer(InputBufferLength, InputBuffer);
if (!NT_SUCCESS(Result))
return Result;
}
else
{
if ((ULONG)FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) != InputBufferLength &&
(ULONG)FIELD_OFFSET(REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer) != InputBufferLength)
return STATUS_IO_REPARSE_DATA_INVALID;
if (0 != ReparseData->ReparseDataLength)
return STATUS_IO_REPARSE_DATA_INVALID;
if (IO_REPARSE_TAG_RESERVED_ZERO == ReparseData->ReparseTag ||
IO_REPARSE_TAG_RESERVED_ONE == ReparseData->ReparseTag)
return STATUS_IO_REPARSE_TAG_INVALID;
if (!IsReparseTagMicrosoft(ReparseData->ReparseTag) &&
(ULONG)FIELD_OFFSET(REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer) != InputBufferLength)
return STATUS_IO_REPARSE_DATA_INVALID;
}
/* NTFS seems to require one of these rights to allow FSCTL_{SET,DELETE}_REPARSE_POINT */
if (!FlagOn(FileDesc->GrantedAccess,
FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES))
return STATUS_ACCESS_DENIED;
if (IO_REPARSE_TAG_SYMLINK == ReparseData->ReparseTag)
{
/* NTFS severely limits symbolic links; we will not do that unless our file system asks */
@ -272,13 +229,8 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
}
else
{
ASSERT(FSCTL_GET_REPARSE_POINT == FsControlCode);
if (0 != InputBufferLength)
return STATUS_INVALID_PARAMETER;
if (0 == OutputBuffer || 0 == OutputBufferLength)
return STATUS_INVALID_USER_BUFFER;
return STATUS_INVALID_PARAMETER;
/*
* NtFsControlFile (IopXxxControlFile) will setup Irp->AssociatedIrp.SystemBuffer
@ -324,21 +276,7 @@ static NTSTATUS FspFsvolFileSystemControlReparsePointComplete(
PAGED_CODE();
if (IsWrite)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = IrpSp->FileObject->FsContext2;
ASSERT(FileNode == FileDesc->FileNode);
FspFileNodeInvalidateFileInfo(FileNode);
FileDesc->DidSetReparsePoint = TRUE;
FileDesc->DidSetMetadata = TRUE;
return STATUS_SUCCESS;
}
NTSTATUS Result;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
@ -495,15 +433,18 @@ static NTSTATUS FspFsvolFileSystemControlOplock(
/*
* FspOplockFsctrl takes ownership of the IRP under all circumstances.
*
* We mark the IRP pending so that we can safely return STATUS_PENDING.
*/
IoSetTopLevelIrp(0);
IoMarkIrpPending(Irp);
Result = FspFileNodeOplockFsctl(FileNode, Irp, OplockCount);
FspFileNodeRelease(FileNode, Main);
return Result | FSP_STATUS_IGNORE_BIT;
return STATUS_PENDING;
unlock_exit:
FspFileNodeRelease(FileNode, Main);
@ -532,140 +473,6 @@ static VOID FspFsvolFileSystemControlOplockCompletionWork(PVOID Context)
FspFree(CompletionContext);
}
static NTSTATUS FspFsvolFileSystemControlQueryPersistentVolumeState(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
PFILE_FS_PERSISTENT_VOLUME_INFORMATION Info;
if (0 == Buffer)
return STATUS_INVALID_PARAMETER;
if (sizeof(FILE_FS_PERSISTENT_VOLUME_INFORMATION) > InputBufferLength ||
sizeof(FILE_FS_PERSISTENT_VOLUME_INFORMATION) > OutputBufferLength)
return STATUS_BUFFER_TOO_SMALL;
Info = Buffer;
if (1 != Info->Version ||
!FlagOn(Info->FlagMask, PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED))
return STATUS_INVALID_PARAMETER;
RtlZeroMemory(Info, sizeof(FILE_FS_PERSISTENT_VOLUME_INFORMATION));
Info->VolumeFlags = PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED;
Irp->IoStatus.Information = sizeof(FILE_FS_PERSISTENT_VOLUME_INFORMATION);
return STATUS_SUCCESS;
}
static NTSTATUS FspFsvolFileSystemControlGetStatistics(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
ULONG Length = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
Result = FspStatisticsCopy(FsvolDeviceExtension->Statistics, Buffer, &Length);
Irp->IoStatus.Information = Length;
return Result;
}
static NTSTATUS FspFsvolFileSystemControlGetRetrievalPointers(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
/*
* FSCTL_GET_RETRIEVAL_POINTERS is normally used for defragmentation support,
* which WinFsp does NOT support. However some tools (notably IFSTEST) use it
* to determine whether files are "resident" or "non-resident" which is an NTFS
* concept. To support such tools we respond in a manner that indicates that
* WinFsp files are always non-resident.
*/
PAGED_CODE();
PFILE_OBJECT FileObject = IrpSp->FileObject;
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(FileObject->FsContext))
return STATUS_INVALID_DEVICE_REQUEST;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
FSP_FILE_NODE *FileNode = FileObject->FsContext;
PSTARTING_VCN_INPUT_BUFFER InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
PRETRIEVAL_POINTERS_BUFFER OutputBuffer = Irp->UserBuffer;
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
STARTING_VCN_INPUT_BUFFER StartingVcn;
RETRIEVAL_POINTERS_BUFFER RetrievalPointers;
UINT64 AllocationUnit;
if (0 == InputBuffer || 0 == OutputBuffer)
return STATUS_INVALID_PARAMETER;
if (sizeof(STARTING_VCN_INPUT_BUFFER) > InputBufferLength ||
sizeof(RETRIEVAL_POINTERS_BUFFER) > OutputBufferLength)
return STATUS_BUFFER_TOO_SMALL;
if (UserMode == Irp->RequestorMode)
{
try
{
ProbeForRead(InputBuffer, InputBufferLength, sizeof(UCHAR)/*FastFat*/);
StartingVcn = *InputBuffer;
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
else
StartingVcn = *InputBuffer;
RetrievalPointers.ExtentCount = 1;
RetrievalPointers.StartingVcn.QuadPart = 0;
RetrievalPointers.Extents[0].NextVcn.QuadPart = 0;
RetrievalPointers.Extents[0].Lcn.QuadPart = -1LL;
AllocationUnit = FsvolDeviceExtension->VolumeParams.SectorSize *
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
FspFileNodeAcquireShared(FileNode, Main);
RetrievalPointers.Extents[0].NextVcn.QuadPart =
FileNode->Header.AllocationSize.QuadPart / AllocationUnit;
FspFileNodeRelease(FileNode, Main);
if (StartingVcn.StartingVcn.QuadPart > RetrievalPointers.Extents[0].NextVcn.QuadPart)
return STATUS_END_OF_FILE;
if (UserMode == Irp->RequestorMode)
{
try
{
ProbeForWrite(OutputBuffer, OutputBufferLength, sizeof(UCHAR)/*FastFat*/);
*OutputBuffer = RetrievalPointers;
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
else
*OutputBuffer = RetrievalPointers;
Irp->IoStatus.Information = sizeof RetrievalPointers;
return STATUS_SUCCESS;
}
static NTSTATUS FspFsvolFileSystemControl(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@ -699,15 +506,6 @@ static NTSTATUS FspFsvolFileSystemControl(
case FSCTL_REQUEST_OPLOCK:
Result = FspFsvolFileSystemControlOplock(FsvolDeviceObject, Irp, IrpSp);
break;
case FSCTL_QUERY_PERSISTENT_VOLUME_STATE:
Result = FspFsvolFileSystemControlQueryPersistentVolumeState(FsvolDeviceObject, Irp, IrpSp);
break;
case FSCTL_FILESYSTEM_GET_STATISTICS:
Result = FspFsvolFileSystemControlGetStatistics(FsvolDeviceObject, Irp, IrpSp);
break;
case FSCTL_GET_RETRIEVAL_POINTERS:
Result = FspFsvolFileSystemControlGetRetrievalPointers(FsvolDeviceObject, Irp, IrpSp);
break;
}
break;
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/iop.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -33,7 +33,7 @@ BOOLEAN FspIopRetryCompleteIrp(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
VOID FspIopSetIrpResponse(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
FSP_FSCTL_TRANSACT_RSP *FspIopIrpResponse(PIRP Irp);
NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request);
NTSTATUS FspIopDispatchComplete(PIRP Irp, FSP_FSCTL_TRANSACT_RSP *Response);
NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspIopCreateRequestFunnel)
@ -281,32 +281,6 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference)
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
/*
* HACK:
*
* We update the Create statistics here to avoid doing it in multiple places.
*/
if (IRP_MJ_CREATE == IrpSp->MajorFunction)
{
/* only update statistics if we actually have a reference to the DeviceObject */
if (DeviceDereference)
{
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
if (FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)
{
FSP_STATISTICS *Statistics = FspStatistics(
((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Statistics);
FspStatisticsInc(Statistics, Specific.CreateHits);
if (STATUS_SUCCESS == Result)
FspStatisticsInc(Statistics, Specific.SuccessfulCreates);
else
FspStatisticsInc(Statistics, Specific.FailedCreates);
}
}
}
else
/*
* HACK:
*
@ -448,7 +422,7 @@ NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
return STATUS_SUCCESS;
}
NTSTATUS FspIopDispatchComplete(PIRP Irp, FSP_FSCTL_TRANSACT_RSP *Response)
NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
{
PAGED_CODE();
@ -457,9 +431,6 @@ NTSTATUS FspIopDispatchComplete(PIRP Irp, FSP_FSCTL_TRANSACT_RSP *Response)
ASSERT(IRP_MJ_MAXIMUM_FUNCTION >= IrpSp->MajorFunction);
ASSERT(0 != FspIopCompleteFunction[IrpSp->MajorFunction]);
if (STATUS_PENDING == Response->IoStatus.Status ||
FlagOn(Response->IoStatus.Status, FSP_STATUS_PRIVATE_BIT | FSP_STATUS_IGNORE_BIT))
Response->IoStatus.Status = (UINT32)STATUS_INTERNAL_ERROR;
return FspIopCompleteFunction[IrpSp->MajorFunction](Irp, Response);
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/ioq.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/lockctl.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -61,15 +61,10 @@ static NTSTATUS FspFsvolLockControlRetry(
return Result;
}
ULONG IrpFlags = FspIrpFlags(Irp);
IoSetTopLevelIrp(0);
/* let the FSRTL package handle this one! */
Result = FspFileNodeProcessLockIrp(FileNode, Irp);
FspFileNodeReleaseF(FileNode, IrpFlags);
return Result | FSP_STATUS_IGNORE_BIT;
return Result;
}
static NTSTATUS FspFsvolLockControl(

View File

@ -1,7 +1,7 @@
/**
* @file sys/meta.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/name.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -17,9 +17,8 @@
#include <sys/driver.h>
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
PUNICODE_STRING StreamPart, PULONG StreamType);
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern, ULONG MaxComponentLength);
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PULONG StreamType);
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern);
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
NTSTATUS FspFileNameInExpression(
PUNICODE_STRING Expression,
@ -35,8 +34,7 @@ NTSTATUS FspFileNameInExpression(
#pragma alloc_text(PAGE, FspFileNameInExpression)
#endif
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
PUNICODE_STRING StreamPart, PULONG StreamType)
BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PULONG StreamType)
{
PAGED_CODE();
@ -46,7 +44,7 @@ BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
if (0 == Path->Length || 0 != Path->Length % sizeof(WCHAR))
return FALSE;
PWSTR PathBgn, PathEnd, PathPtr, ComponentPtr, StreamTypeStr = 0;
PWSTR PathBgn, PathEnd, PathPtr, StreamTypeStr = 0;
UCHAR Flags = FSRTL_NTFS_LEGAL;
ULONG Colons = 0;
WCHAR Char;
@ -54,7 +52,6 @@ BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
PathBgn = Path->Buffer;
PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length);
PathPtr = PathBgn;
ComponentPtr = PathPtr;
while (PathEnd > PathPtr)
{
@ -66,12 +63,7 @@ BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
if (0 < Colons)
return FALSE;
/* path component cannot be longer than MaxComponentLength */
if ((ULONG)(PathPtr - ComponentPtr) > MaxComponentLength)
return FALSE;
PathPtr++;
ComponentPtr = PathPtr;
/* don't like multiple backslashes */
if (PathEnd > PathPtr && L'\\' == *PathPtr)
@ -114,10 +106,6 @@ BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
PathPtr++;
}
/* path component cannot be longer than MaxComponentLength */
if ((ULONG)(PathPtr - ComponentPtr) > MaxComponentLength)
return FALSE;
/* if we had no colons the path is valid */
if (0 == Colons)
return TRUE;
@ -145,20 +133,19 @@ BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, ULONG MaxComponentLength,
return FALSE;
}
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Path, ULONG MaxComponentLength)
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Path)
{
PAGED_CODE();
if (0 != Path->Length % sizeof(WCHAR))
return FALSE;
PWSTR PathBgn, PathEnd, PathPtr, ComponentPtr;
PWSTR PathBgn, PathEnd, PathPtr;
WCHAR Char;
PathBgn = Path->Buffer;
PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length);
PathPtr = PathBgn;
ComponentPtr = PathPtr;
while (PathEnd > PathPtr)
{
@ -180,10 +167,6 @@ BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Path, ULONG MaxComponentLength
PathPtr++;
}
/* path component cannot be longer than MaxComponentLength */
if ((ULONG)(PathPtr - ComponentPtr) > MaxComponentLength)
return FALSE;
return TRUE;
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/read.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -324,20 +324,6 @@ static NTSTATUS FspFsvolReadNonCached(
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
FSP_STATISTICS *Statistics = FspFsvolDeviceStatistics(FsvolDeviceObject);
if (PagingIo)
{
FspStatisticsInc(Statistics, Base.UserFileReads);
FspStatisticsAdd(Statistics, Base.UserFileReadBytes, ReadLength);
FspStatisticsInc(Statistics, Base.UserDiskReads);
}
else
{
FspStatisticsInc(Statistics, Specific.NonCachedReads);
FspStatisticsAdd(Statistics, Specific.NonCachedReadBytes, ReadLength);
FspStatisticsInc(Statistics, Specific.NonCachedDiskReads);
}
return FSP_STATUS_IOQ_POST;
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/security.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -254,11 +254,8 @@ NTSTATUS FspFsvolSetSecurityComplete(
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
ASSERT(FileNode == FileDesc->FileNode);
/* if the security descriptor that we got back is valid */
if (0 < Response->Rsp.SetSecurity.SecurityDescriptor.Size &&
Response->Buffer + Response->Rsp.SetSecurity.SecurityDescriptor.Size <=
@ -276,11 +273,6 @@ NTSTATUS FspFsvolSetSecurityComplete(
FspFileNodeSetSecurity(FileNode, 0, 0);
}
FileDesc->DidSetSecurity = TRUE;
FileDesc->DidSetMetadata = TRUE;
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SECURITY, FILE_ACTION_MODIFIED, FALSE);
FspIopRequestContext(Request, RequestFileNode) = 0;
FspFileNodeReleaseOwner(FileNode, Full, Request);

View File

@ -1,7 +1,7 @@
/**
* @file sys/shutdown.c
*
* @copyright 2015-2017 Bill Zissimopoulos
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

Some files were not shown because too many files have changed in this diff Show More