Compare commits
1 Commits
v1.0
...
baseline-p
Author | SHA1 | Date | |
---|---|---|---|
56873406e3 |
@ -1,50 +1,11 @@
|
||||
= Changelog
|
||||
|
||||
|
||||
v1.0::
|
||||
|
||||
This is the WinFsp 2017 release! :tada:
|
||||
|
||||
- The API is now *FROZEN*. Breaking API changes will receive a major version update (`2.0`). Incremental API changes will receive a minor version update (`1.x`).
|
||||
- Adds chocolatey package. Try `choco install winfsp` (note: pending approval from chocolatey.org).
|
||||
- FUSE `-d` output now always goes to stderr. There is also a new `-oDebugLog=FILE` switch to specify a debug output file.
|
||||
- FUSE now provides a default `statfs` implementation if a file system does not provide one.
|
||||
- The WinFsp DLL now exports `fuse_*` symbols in addition to the `fsp_fuse_*` symbols. These symbols are for use with programs that use FFI technology such as jnr-fuse and fusepy *ONLY*. They are not supposed to be used by native C/C++ programs. Such programs are supposed to include the `<fuse.h>` headers.
|
||||
|
||||
|
||||
v1.0RC3::
|
||||
|
||||
This is the WinFsp 2017 Release Candidate 3, which should be the last Release Candidate according to the current plan. This release fixes a major issue with some file systems and includes a few smaller changes:
|
||||
|
||||
- Fixes GitHub issue #55. Prior to this fix it was possible for a rogue process (or faulty file system) to crash Windows using WinFsp. For full details read http://www.osronline.com/showthread.cfm?link=282037[this thread].
|
||||
- Introduces the `FspFileSystemSetMountPointEx` API, which allows the specification of a security descriptor when mounting over a directory.
|
||||
- Introduces the `FspVersion` API, which allows the retrieval of the WinFsp DLL version. Currently this reports `0x00010000` (version `1.0`).
|
||||
- Introduces the `FSP_FUSE_CAP_CASE_INSENSITIVE` and `FSP_FUSE_CAP_READDIR_PLUS` WinFsp-FUSE flags. The `FSP_FUSE_CAP_CASE_INSENSITIVE` flag allows a file system to mark itself as case-insensitive. The `FSP_FUSE_CAP_READDIR_PLUS` flag allows a file system to include full `stat` details when responding to the `readdir` operation (thus avoiding extraneous `getattr` calls).
|
||||
- When using WinFsp-FUSE over Cygwin, POSIX paths can be used as mountpoints.
|
||||
- Fixes GitHub issue #45. Prior to this fix, file systems that do not properly implement `Cleanup` (including FUSE file systems) would at times disallow renaming of directories.
|
||||
|
||||
|
||||
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.
|
||||
|
31
License.txt
@ -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
|
||||
|
37
README.md
@ -2,22 +2,17 @@
|
||||
|
||||

|
||||
|
||||
|
||||
<a href="https://github.com/billziss-gh/winfsp/releases"><img src="http://www.secfs.net/winfsp/resources/Download-WinFsp.png" alt="Download WinFsp Installer" width="244" height="34"></a>
|
||||
|
||||
|
||||
|
||||
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/
|
||||
|
||||
@ -45,23 +40,19 @@ The project source code is organized as follows:
|
||||
|
||||
In order to build WinFsp you will need the following:
|
||||
|
||||
* Windows 10
|
||||
* Visual Studio 2015
|
||||
* Windows Driver Kit (WDK) 10
|
||||
* [Wix toolset](http://wixtoolset.org)
|
||||
|
||||
To fully build WinFsp (including the installer) you must use `tools\build.bat`. By default it builds a Release build, but you can choose either the Debug or Release configuration by using the syntax:
|
||||
If you build the driver yourself it will not be signed and Windows will refuse to load it unless you enable "testsigning". You can enable "testsigning" using the command `bcdedit.exe -set testsigning`. For more information see this [document](http://www.secfs.net/winfsp/develop/debug/).
|
||||
|
||||
tools\build.bat CONFIGURATION
|
||||
|
||||
If you build the driver yourself it will not be signed and Windows will refuse to load it unless you enable "testsigning". You can enable "testsigning" using the command `bcdedit.exe -set testsigning on`. For more information see this [document](http://www.secfs.net/winfsp/develop/debug/).
|
||||
|
||||
WinFsp is designed to run on Windows 7 and above. It has been tested on the following platforms:
|
||||
WinFsp is designed to run on Vista and above. It has been tested on the following platforms so far:
|
||||
|
||||
* Windows 7 Enterprise
|
||||
* Windows 8 Pro
|
||||
* Windows Server 2012
|
||||
* Windows 10 Pro
|
||||
* Windows Server 2016
|
||||
* Windows Server 2012
|
||||
|
||||
## How to Help
|
||||
|
||||
@ -69,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.
|
||||
|
||||
@ -82,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.
|
||||
|
@ -2,10 +2,6 @@ version: '{build}'
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- CONFIGURATION: Debug
|
||||
TESTING: Func
|
||||
- CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
- CONFIGURATION: Release
|
||||
TESTING: Perf
|
||||
|
||||
@ -23,15 +19,13 @@ build_script:
|
||||
- tools\build.bat %CONFIGURATION%
|
||||
|
||||
test_script:
|
||||
- choco install winfsp -s build\VStudio\build\%CONFIGURATION% -y
|
||||
- for %%f in ("build\VStudio\build\%CONFIGURATION%\winfsp-*.msi") do start /wait msiexec /i %%f /qn INSTALLLEVEL=1000
|
||||
- if %TESTING%==Func appveyor DownloadFile http://www.secfs.net/winfsp/resources/Test.Filter.Driver.zip && 7z x Test.Filter.Driver.zip
|
||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||
- 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
|
||||
- choco uninstall winfsp -y
|
||||
- if exist %SystemRoot%\memory.dmp exit 1
|
||||
|
||||
on_finish:
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file CustomActions.cpp
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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" />
|
||||
|
@ -182,10 +182,8 @@
|
||||
</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\exec-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\flush-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-opt-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
||||
@ -202,7 +200,6 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -215,9 +212,6 @@
|
||||
<Project>{4a7c0b21-9e10-4c81-92de-1493efcf24eb}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\tst\winfsp-tests\helper\winfsp-tests-helper.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
@ -76,15 +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>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\exec-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||
@ -97,9 +88,4 @@
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\tst\winfsp-tests\helper\winfsp-tests-helper.rc">
|
||||
<Filter>Source</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -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</MyProductVersion>
|
||||
<MyProductStage>Gold</MyProductStage>
|
||||
<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>
|
@ -31,10 +31,8 @@
|
||||
<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_compat.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||
@ -52,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) >$(OutDir)fuse-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(PlatformTarget).pc >nul</Command>
|
||||
@ -80,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">
|
||||
|
@ -103,12 +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>
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
@ -124,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>
|
||||
|
@ -174,11 +174,9 @@
|
||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||
<ClCompile Include="..\..\src\sys\name.c" />
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||
<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" />
|
||||
@ -191,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! >>$(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! >>$(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! >>$(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! >>$(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>
|
||||
|
@ -95,12 +95,6 @@
|
||||
<ClCompile Include="..\..\src\sys\name.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\statistics.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
@ -115,9 +109,4 @@
|
||||
<Filter>Source</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\..\src\sys\driver.inf.in">
|
||||
<Filter>Source</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,36 +0,0 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$packageName = 'winfsp'
|
||||
$softwareName = 'WinFsp*'
|
||||
$installerType = 'msi'
|
||||
$silentArgs = '/qn /norestart'
|
||||
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
|
||||
|
||||
[array]$key = Get-UninstallRegistryKey -SoftwareName $softwareName
|
||||
|
||||
if ($key.Count -eq 1) {
|
||||
$key | % {
|
||||
# The Product Code GUID is all that should be passed for MSI, and very
|
||||
# FIRST, because it comes directly after /x, which is already set in the
|
||||
# Uninstall-ChocolateyPackage msiargs (facepalm).
|
||||
$silentArgs = "$($_.PSChildName) $silentArgs"
|
||||
|
||||
# Don't pass anything for file, it is ignored for msi (facepalm number 2)
|
||||
# Alternatively if you need to pass a path to an msi, determine that and
|
||||
# use it instead of the above in silentArgs, still very first
|
||||
$file = ''
|
||||
|
||||
Uninstall-ChocolateyPackage `
|
||||
-PackageName $packageName `
|
||||
-FileType $installerType `
|
||||
-SilentArgs "$silentArgs" `
|
||||
-ValidExitCodes $validExitCodes `
|
||||
-File "$file"
|
||||
}
|
||||
} elseif ($key.Count -eq 0) {
|
||||
Write-Warning "$packageName has already been uninstalled by other means."
|
||||
} elseif ($key.Count -gt 1) {
|
||||
Write-Warning "Too many matching packages found! Package may not be uninstalled."
|
||||
Write-Warning "Please alert package maintainer the following packages were matched:"
|
||||
$key | % {Write-Warning "- $_"}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
$fileLocation = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||
|
||||
$packageArgs = @{
|
||||
packageName = 'winfsp'
|
||||
fileType = 'msi'
|
||||
file = $fileLocation
|
||||
silentArgs = "/qn /norestart INSTALLLEVEL=1000"
|
||||
validExitCodes = @(0, 3010, 1641)
|
||||
}
|
||||
|
||||
Install-ChocolateyInstallPackage @packageArgs
|
||||
|
||||
Remove-Item -Force $packageArgs.file
|
@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>winfsp</id>
|
||||
<version>$version$</version>
|
||||
<packageSourceUrl>https://github.com/billziss-gh/winfsp/tree/master/build/choco</packageSourceUrl>
|
||||
<owners>Bill Zissimopoulos <billziss at navimatics.com></owners>
|
||||
|
||||
<title>WinFsp</title>
|
||||
<authors>Bill Zissimopoulos <billziss at navimatics.com></authors>
|
||||
<projectUrl>https://github.com/billziss-gh/winfsp</projectUrl>
|
||||
<iconUrl>https://github.com/billziss-gh/winfsp/raw/master/art/winfsp-solid.png</iconUrl>
|
||||
<copyright>Bill Zissimopoulos</copyright>
|
||||
<licenseUrl>https://github.com/billziss-gh/winfsp/blob/master/License.txt</licenseUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<projectSourceUrl>https://github.com/billziss-gh/winfsp</projectSourceUrl>
|
||||
<docsUrl>https://github.com/billziss-gh/winfsp/tree/master/doc</docsUrl>
|
||||
<mailingListUrl>https://groups.google.com/forum/#!forum/winfsp</mailingListUrl>
|
||||
<bugTrackerUrl>https://github.com/billziss-gh/winfsp/issues</bugTrackerUrl>
|
||||
<tags>driver filesystem fuse gplv3 windows-kernel admin</tags>
|
||||
<summary>Windows File System Proxy - FUSE for Windows</summary>
|
||||
<description>
|
||||
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
|
||||
|
||||
Some of the benefits of using WinFsp are listed below:
|
||||
|
||||
* Very well-tested and stable.
|
||||
* Very fast.
|
||||
* Strives for compatibility with NTFS.
|
||||
* Easy to understand but comprehensive API.
|
||||
* FUSE compatibility layer for native Windows and Cygwin.
|
||||
* Signed drivers provided on every release.
|
||||
* Available under the GPLv3 license with a special exception for Free/Libre and Open Source Software.
|
||||
</description>
|
||||
<releaseNotes>https://github.com/billziss-gh/winfsp/blob/master/Changelog.asciidoc</releaseNotes>
|
||||
|
||||
<!--<dependencies>
|
||||
<dependency id="chocolatey-uninstall.extension" />
|
||||
</dependencies>-->
|
||||
</metadata>
|
||||
|
||||
<files>
|
||||
<file src="chocolateyInstall.ps1" target="tools" />
|
||||
<file src="chocolateyBeforeModify.ps1" target="tools" />
|
||||
<file src="winfsp-$version$.msi" target="tools" />
|
||||
</files>
|
||||
</package>
|
@ -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.
|
@ -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.
|
||||
|
Before Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 20 KiB |
@ -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.
|
1785
doc/winfsp.h.markdown
Normal file
2
ext/test
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/callstack.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/callstack.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/callstack.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_CALLSTACK_H_INCLUDED
|
||||
|
@ -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
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/curlfunc.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/injected/curlfunc.h>
|
||||
|
@ -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
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/stdfunc.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/injected/stdfunc.h>
|
||||
|
@ -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
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injection.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/injection.h>
|
||||
|
@ -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.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/testsuite.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/testsuite.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/testsuite.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2015 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_TESTSUITE_H_INCLUDED
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
@ -41,15 +41,6 @@ extern "C" {
|
||||
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
||||
#define FUSE_CAP_BIG_WRITES (1 << 5)
|
||||
#define FUSE_CAP_DONT_MASK (1 << 6)
|
||||
#define FUSE_CAP_ALLOCATE (1 << 27) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_EXCHANGE_DATA (1 << 28) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_CASE_INSENSITIVE (1 << 29) /* file system is case insensitive */
|
||||
#define FUSE_CAP_VOL_RENAME (1 << 30) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_XTIMES (1 << 31) /* reserved (OSXFUSE) */
|
||||
|
||||
#define FSP_FUSE_CAP_READDIR_PLUS (1 << 21) /* file system supports enhanced readdir */
|
||||
#define FSP_FUSE_CAP_READ_ONLY (1 << 22) /* file system is marked read-only */
|
||||
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
|
||||
|
||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
@ -177,7 +177,6 @@ struct fuse_flock
|
||||
MemAlloc, MemFree, \
|
||||
fsp_fuse_daemonize, \
|
||||
fsp_fuse_set_signal_handlers, \
|
||||
0/*conv_to_win_path*/, \
|
||||
}
|
||||
#else
|
||||
#define FSP_FUSE_ENV_INIT \
|
||||
@ -186,7 +185,6 @@ struct fuse_flock
|
||||
malloc, free, \
|
||||
fsp_fuse_daemonize, \
|
||||
fsp_fuse_set_signal_handlers, \
|
||||
0/*conv_to_win_path*/, \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -228,7 +226,6 @@ struct fuse_flock
|
||||
malloc, free, \
|
||||
fsp_fuse_daemonize, \
|
||||
fsp_fuse_set_signal_handlers, \
|
||||
fsp_fuse_conv_to_win_path, \
|
||||
}
|
||||
|
||||
/*
|
||||
@ -247,8 +244,7 @@ struct fsp_fuse_env
|
||||
void (*memfree)(void *);
|
||||
int (*daemonize)(int);
|
||||
int (*set_signal_handlers)(void *);
|
||||
char *(*conv_to_win_path)(const char *);
|
||||
void (*reserved[3])();
|
||||
void (*reserved[4])();
|
||||
};
|
||||
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
||||
@ -352,13 +348,6 @@ static inline int fsp_fuse_set_signal_handlers(void *se)
|
||||
#undef FSP_FUSE_SET_SIGNAL_HANDLER
|
||||
}
|
||||
|
||||
static inline char *fsp_fuse_conv_to_win_path(const char *path)
|
||||
{
|
||||
void *cygwin_create_path(unsigned, const void *);
|
||||
return cygwin_create_path(
|
||||
0/*CCP_POSIX_TO_WIN_A*/ | 0x100/*CCP_RELATIVE*/,
|
||||
path);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -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,10 +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 AlwaysUseDoubleBuffering:1;
|
||||
UINT32 KmReservedFlags:3;
|
||||
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 */
|
||||
@ -187,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;
|
||||
@ -233,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
|
||||
@ -250,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
|
||||
{
|
||||
@ -302,7 +295,6 @@ typedef struct
|
||||
UINT64 CreationTime;
|
||||
UINT64 LastAccessTime;
|
||||
UINT64 LastWriteTime;
|
||||
UINT64 ChangeTime;
|
||||
} Basic;
|
||||
struct
|
||||
{
|
||||
@ -340,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
|
||||
@ -423,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;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* In order to use the WinFsp API the user mode file system must include <winfsp/winfsp.h>
|
||||
* 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.
|
||||
@ -26,10 +26,7 @@
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#include <winternl.h>
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4005) /* macro redefinition */
|
||||
#include <ntstatus.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#if defined(WINFSP_DLL_INTERNAL)
|
||||
#define FSP_API __declspec(dllexport)
|
||||
@ -125,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.
|
||||
@ -334,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.
|
||||
@ -375,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.
|
||||
*
|
||||
@ -455,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.
|
||||
*
|
||||
@ -500,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.
|
||||
@ -511,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.
|
||||
@ -558,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.
|
||||
@ -581,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>
|
||||
@ -650,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
|
||||
@ -671,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.
|
||||
*
|
||||
@ -835,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.
|
||||
*
|
||||
@ -896,8 +857,6 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem);
|
||||
* STATUS_SUCCESS or error code.
|
||||
*/
|
||||
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint);
|
||||
FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||
/**
|
||||
* Remove the mount point for a file system.
|
||||
*
|
||||
@ -1298,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
|
||||
*/
|
||||
@ -1408,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
|
||||
@ -1630,71 +1574,6 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||
PULONG PBytesTransferred, ULONG Timeout,
|
||||
PSID Sid);
|
||||
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
WINADVAPI
|
||||
LSTATUS
|
||||
APIENTRY
|
||||
RegGetValueW(
|
||||
HKEY hkey,
|
||||
LPCWSTR lpSubKey,
|
||||
LPCWSTR lpValue,
|
||||
DWORD dwFlags,
|
||||
LPDWORD pdwType,
|
||||
PVOID pvData,
|
||||
LPDWORD pcbData);
|
||||
|
||||
WCHAR PathBuf[MAX_PATH];
|
||||
DWORD Size;
|
||||
HKEY RegKey;
|
||||
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
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file cygfuse/cygfuse.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,6 +1,6 @@
|
||||
NAME="fuse"
|
||||
VERSION=2.8
|
||||
RELEASE=4
|
||||
RELEASE=3
|
||||
CATEGORY="Utils"
|
||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||
|
@ -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",
|
||||
|
404
src/dll/dirbuf.c
@ -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);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/eventlog.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
262
src/dll/fs.c
@ -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,
|
||||
@ -187,63 +145,20 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
|
||||
MemFree(FileSystem);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
|
||||
PHANDLE PMountHandle)
|
||||
{
|
||||
*PMountHandle = 0;
|
||||
|
||||
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
if (0 != FspNtOpenSymbolicLinkObject)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
WCHAR SymlinkBuf[6];
|
||||
UNICODE_STRING Symlink;
|
||||
OBJECT_ATTRIBUTES Obja;
|
||||
|
||||
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
||||
SymlinkBuf[4] = MountPoint[0];
|
||||
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
||||
Symlink.Buffer = SymlinkBuf;
|
||||
|
||||
memset(&Obja, 0, sizeof Obja);
|
||||
Obja.Length = sizeof Obja;
|
||||
Obja.ObjectName = &Symlink;
|
||||
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
|
||||
Result = FspNtOpenSymbolicLinkObject(PMountHandle, DELETE, &Obja);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
Result = FspNtMakeTemporaryObject(*PMountHandle);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspNtClose(*PMountHandle);
|
||||
*PMountHandle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR VolumeName,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
||||
static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWSTR VolumeName)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
||||
HANDLE DirHandle;
|
||||
BOOL Success;
|
||||
DWORD Backslashes, Bytes;
|
||||
USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
|
||||
PREPARSE_DATA_BUFFER ReparseData = 0;
|
||||
PWSTR P, PathBuffer;
|
||||
|
||||
*PMountHandle = 0;
|
||||
|
||||
/*
|
||||
* Windows does not allow mount points (junctions) to point to network file systems.
|
||||
*
|
||||
* Count how many backslashes our VolumeName has. If it is 3 or more this is a network
|
||||
* Count how many backslashes our VolumeName. If it is 3 or more this is a network
|
||||
* file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED.
|
||||
*/
|
||||
for (P = VolumeName, Backslashes = 0; *P; P++)
|
||||
@ -254,24 +169,25 @@ static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR Vol
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(&SecurityAttributes, 0, sizeof SecurityAttributes);
|
||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||
|
||||
MountHandle = CreateFileW(MountPoint,
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
&SecurityAttributes,
|
||||
CREATE_NEW,
|
||||
FILE_ATTRIBUTE_DIRECTORY |
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||
if (!CreateDirectoryW(MountPoint, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
DirHandle = CreateFileW(MountPoint,
|
||||
FILE_WRITE_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)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto rmdir_and_exit;
|
||||
}
|
||||
|
||||
VolumeNameLength = (USHORT)lstrlenW(VolumeName);
|
||||
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
|
||||
VolumeNameLength *= sizeof(WCHAR);
|
||||
@ -285,7 +201,7 @@ static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR Vol
|
||||
if (0 == ReparseData)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
goto rmdir_and_exit;
|
||||
}
|
||||
|
||||
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
@ -312,35 +228,86 @@ static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR Vol
|
||||
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
||||
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
||||
|
||||
if (!DeviceIoControl(MountHandle, FSCTL_SET_REPARSE_POINT,
|
||||
Success = DeviceIoControl(DirHandle, FSCTL_SET_REPARSE_POINT,
|
||||
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
||||
0, 0,
|
||||
&Bytes, 0))
|
||||
&Bytes, 0);
|
||||
CloseHandle(DirHandle);
|
||||
if (!Success)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
goto rmdir_and_exit;
|
||||
}
|
||||
|
||||
*PMountHandle = MountHandle;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
||||
CloseHandle(MountHandle);
|
||||
|
||||
MemFree(ReparseData);
|
||||
return Result;
|
||||
|
||||
rmdir_and_exit:
|
||||
RemoveDirectoryW(MountPoint);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileSystemSetMountPoint_MakeTemporary(PWSTR MountPoint, PHANDLE PMountHandle)
|
||||
{
|
||||
NTSTATUS Result = STATUS_SUCCESS;
|
||||
HANDLE MountHandle = 0;
|
||||
|
||||
if (FspPathIsDrive(MountPoint))
|
||||
{
|
||||
if (0 != FspNtOpenSymbolicLinkObject)
|
||||
{
|
||||
WCHAR SymlinkBuf[6];
|
||||
UNICODE_STRING Symlink;
|
||||
OBJECT_ATTRIBUTES Obja;
|
||||
|
||||
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
||||
SymlinkBuf[4] = MountPoint[0];
|
||||
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
||||
Symlink.Buffer = SymlinkBuf;
|
||||
|
||||
memset(&Obja, 0, sizeof Obja);
|
||||
Obja.Length = sizeof Obja;
|
||||
Obja.ObjectName = &Symlink;
|
||||
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
|
||||
Result = FspNtOpenSymbolicLinkObject(&MountHandle, DELETE, &Obja);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
Result = FspNtMakeTemporaryObject(MountHandle);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspNtClose(MountHandle);
|
||||
MountHandle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* open the directory for DELETE_ON_CLOSE; closing it will remove the directory */
|
||||
MountHandle = 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 | FILE_FLAG_DELETE_ON_CLOSE,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||
{
|
||||
MountHandle = 0;
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
*PMountHandle = MountHandle;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
||||
{
|
||||
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
if (0 != FileSystem->MountPoint)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
@ -366,10 +333,11 @@ FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR
|
||||
if (0 == (Drives & (1 << (Drive - 'A'))))
|
||||
{
|
||||
MountPoint[0] = Drive;
|
||||
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
|
||||
&MountHandle);
|
||||
if (NT_SUCCESS(Result))
|
||||
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName))
|
||||
{
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
Result = STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
@ -390,16 +358,22 @@ FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR
|
||||
MountPoint = P;
|
||||
|
||||
if (FspPathIsDrive(MountPoint))
|
||||
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
|
||||
&MountHandle);
|
||||
{
|
||||
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName))
|
||||
Result = STATUS_SUCCESS;
|
||||
else
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
else
|
||||
Result = FspFileSystemSetMountPoint_Directory(MountPoint, FileSystem->VolumeName,
|
||||
SecurityDescriptor, &MountHandle);
|
||||
Result = FspFileSystemSetMountPoint_CreateDirectory(MountPoint, FileSystem->VolumeName);
|
||||
}
|
||||
|
||||
exit:
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
FspFileSystemSetMountPoint_MakeTemporary(MountPoint, &MountHandle);
|
||||
/* ignore result; this path always considered successful */
|
||||
|
||||
FileSystem->MountPoint = MountPoint;
|
||||
FileSystem->MountHandle = MountHandle;
|
||||
}
|
||||
@ -409,35 +383,33 @@ exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static VOID FspFileSystemRemoveMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, HANDLE MountHandle)
|
||||
{
|
||||
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||
MountPoint, VolumeName);
|
||||
|
||||
if (0 != MountHandle)
|
||||
FspNtClose(MountHandle);
|
||||
}
|
||||
|
||||
static VOID FspFileSystemRemoveMountPoint_Directory(HANDLE MountHandle)
|
||||
{
|
||||
/* directory is marked DELETE_ON_CLOSE */
|
||||
CloseHandle(MountHandle);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
||||
{
|
||||
BOOLEAN IsDrive;
|
||||
|
||||
if (0 == FileSystem->MountPoint)
|
||||
return;
|
||||
|
||||
if (FspPathIsDrive(FileSystem->MountPoint))
|
||||
FspFileSystemRemoveMountPoint_Drive(FileSystem->MountPoint, FileSystem->VolumeName,
|
||||
FileSystem->MountHandle);
|
||||
IsDrive = FspPathIsDrive(FileSystem->MountPoint);
|
||||
if (IsDrive)
|
||||
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||
FileSystem->MountPoint, FileSystem->VolumeName);
|
||||
else
|
||||
FspFileSystemRemoveMountPoint_Directory(FileSystem->MountHandle);
|
||||
/* nothing to do! directory will be deleted when the MountHandle is closed */;
|
||||
|
||||
MemFree(FileSystem->MountPoint);
|
||||
FileSystem->MountPoint = 0;
|
||||
FileSystem->MountHandle = 0;
|
||||
|
||||
if (0 != FileSystem->MountHandle)
|
||||
{
|
||||
if (IsDrive)
|
||||
FspNtClose(FileSystem->MountHandle);
|
||||
else
|
||||
/* CloseHandle really calls NtClose, but I like being defensive when programming */
|
||||
CloseHandle(FileSystem->MountHandle);
|
||||
|
||||
FileSystem->MountHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fsctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -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;
|
||||
@ -1354,7 +1326,7 @@ FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_API NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS (*GetReparsePointByName)(
|
||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
||||
|
@ -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.
|
||||
@ -32,13 +32,16 @@ struct fsp_fuse_core_opt_data
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
int hard_remove,
|
||||
use_ino, readdir_ino,
|
||||
set_umask, umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks;
|
||||
int set_FileInfoTimeout;
|
||||
int CaseInsensitiveSearch,
|
||||
ReadOnlyVolume;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
};
|
||||
|
||||
@ -53,11 +56,9 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("-d", debug, 1),
|
||||
FSP_FUSE_CORE_OPT("debug", debug, 1),
|
||||
|
||||
FUSE_OPT_KEY("DebugLog=", 'D'),
|
||||
|
||||
FUSE_OPT_KEY("hard_remove", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("use_ino", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("readdir_ino", FUSE_OPT_KEY_DISCARD),
|
||||
FSP_FUSE_CORE_OPT("hard_remove", hard_remove, 1),
|
||||
FSP_FUSE_CORE_OPT("use_ino", use_ino, 1),
|
||||
FSP_FUSE_CORE_OPT("readdir_ino", readdir_ino, 1),
|
||||
FUSE_OPT_KEY("direct_io", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("kernel_cache", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("auto_cache", FUSE_OPT_KEY_DISCARD),
|
||||
@ -88,8 +89,17 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
||||
FSP_FUSE_CORE_OPT("VolumeCreationTime=%lli", VolumeParams.VolumeCreationTime, 0),
|
||||
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
||||
FSP_FUSE_CORE_OPT("TransactTimeout=%u", VolumeParams.TransactTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("IrpTimeout=%u", VolumeParams.IrpTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("IrpCapacity=%u", VolumeParams.IrpCapacity, 0),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("CaseInsensitiveSearch", CaseInsensitiveSearch, 1),
|
||||
FSP_FUSE_CORE_OPT("ReadOnlyVolume", ReadOnlyVolume, 1),
|
||||
FUSE_OPT_KEY("ReparsePoints", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("NamedStreams", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("HardLinks", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("ExtendedAttributes", FUSE_OPT_KEY_DISCARD),
|
||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
||||
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
||||
@ -121,9 +131,6 @@ static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size)
|
||||
|
||||
static inline void fsp_fuse_obj_free(void *obj)
|
||||
{
|
||||
if (0 == obj)
|
||||
return;
|
||||
|
||||
struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr));
|
||||
|
||||
hdr->dtor(hdr);
|
||||
@ -183,55 +190,23 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
||||
const char *mountpoint, struct fuse_args *args)
|
||||
{
|
||||
struct fuse_chan *ch = 0;
|
||||
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH];
|
||||
int Size;
|
||||
|
||||
if (0 == mountpoint || '\0' == mountpoint[0] ||
|
||||
('*' == mountpoint[0] && '\0' == mountpoint[1]))
|
||||
{
|
||||
MountPointBuf[0] = L'*';
|
||||
MountPointBuf[1] = L'\0';
|
||||
Size = 2 * sizeof(WCHAR);
|
||||
}
|
||||
else if (
|
||||
(
|
||||
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
||||
('a' <= mountpoint[0] && mountpoint[0] <= 'z')
|
||||
) &&
|
||||
':' == mountpoint[1] && '\0' == mountpoint[2])
|
||||
{
|
||||
MountPointBuf[0] = mountpoint[0];
|
||||
MountPointBuf[1] = ':';
|
||||
MountPointBuf[2] = '\0';
|
||||
Size = 3 * sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *win_mountpoint = 0;
|
||||
if (0 == mountpoint)
|
||||
mountpoint = "";
|
||||
|
||||
if (0 != env->conv_to_win_path)
|
||||
mountpoint = win_mountpoint = env->conv_to_win_path(mountpoint);
|
||||
Size = MultiByteToWideChar(CP_UTF8, 0, mountpoint, -1, 0, 0);
|
||||
if (0 == Size)
|
||||
goto fail;
|
||||
|
||||
Size = 0;
|
||||
if (0 != mountpoint &&
|
||||
0 != MultiByteToWideChar(CP_UTF8, 0, mountpoint, -1, TempMountPointBuf, MAX_PATH))
|
||||
Size = GetFullPathNameW(TempMountPointBuf, MAX_PATH, MountPointBuf, 0);
|
||||
|
||||
env->memfree(win_mountpoint);
|
||||
|
||||
if (0 == Size || MAX_PATH <= Size)
|
||||
goto fail;
|
||||
|
||||
mountpoint = 0;
|
||||
Size = (Size + 1) * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
ch = fsp_fuse_obj_alloc(env, sizeof *ch + Size);
|
||||
ch = fsp_fuse_obj_alloc(env, sizeof *ch + Size * sizeof(WCHAR));
|
||||
if (0 == ch)
|
||||
goto fail;
|
||||
|
||||
ch->MountPoint = (PVOID)ch->Buffer;
|
||||
memcpy(ch->MountPoint, MountPointBuf, Size);
|
||||
Size = MultiByteToWideChar(CP_UTF8, 0, mountpoint, -1, ch->MountPoint, Size);
|
||||
if (0 == Size)
|
||||
goto fail;
|
||||
|
||||
return ch;
|
||||
|
||||
@ -255,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;
|
||||
@ -286,17 +291,9 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
||||
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
||||
FUSE_CAP_BIG_WRITES |
|
||||
FUSE_CAP_DONT_MASK |
|
||||
FSP_FUSE_CAP_READDIR_PLUS |
|
||||
FSP_FUSE_CAP_READ_ONLY |
|
||||
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
||||
FUSE_CAP_DONT_MASK;
|
||||
if (0 != f->ops.init)
|
||||
{
|
||||
context->private_data = f->data = f->ops.init(&conn);
|
||||
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
||||
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||
f->conn_want = conn.want;
|
||||
}
|
||||
f->fsinit = TRUE;
|
||||
if (0 != f->ops.statfs)
|
||||
{
|
||||
@ -311,12 +308,10 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 == f->VolumeParams.SectorSize && 0 != stbuf.f_frsize)
|
||||
if (stbuf.f_frsize > FSP_FUSE_SECTORSIZE_MAX)
|
||||
stbuf.f_frsize = FSP_FUSE_SECTORSIZE_MAX;
|
||||
if (0 == f->VolumeParams.SectorSize)
|
||||
f->VolumeParams.SectorSize = (UINT16)stbuf.f_frsize;
|
||||
#if 0
|
||||
if (0 == f->VolumeParams.SectorsPerAllocationUnit && 0 != stbuf.f_frsize)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = (UINT16)(stbuf.f_bsize / stbuf.f_frsize);
|
||||
#endif
|
||||
if (0 == f->VolumeParams.MaxComponentLength)
|
||||
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
||||
}
|
||||
@ -348,8 +343,9 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
}
|
||||
|
||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
||||
f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN)
|
||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MIN;
|
||||
if (f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
||||
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
||||
@ -384,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);
|
||||
@ -453,13 +449,14 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
case 'h':
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||
FSP_FUSE_LIBRARY_NAME " options:\n"
|
||||
" -o DebugLog=FILE debug log file (deflt: stderr)\n"
|
||||
" -o SectorSize=N sector size for Windows (512-4096, deflt: 4096)\n"
|
||||
" -o SectorsPerAllocationUnit=N sectors per allocation unit (deflt: 1)\n"
|
||||
" -o SectorSize=N sector size for Windows (512-4096, deflt: 512)\n"
|
||||
" -o SectorsPerAllocationUnit=N allocation unit size (deflt: 1*SectorSize)\n"
|
||||
" -o MaxComponentLength=N max file name component length (deflt: 255)\n"
|
||||
" -o VolumeCreationTime=T volume creation time (FILETIME hex format)\n"
|
||||
" -o VolumeSerialNumber=N 32-bit wide\n"
|
||||
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
||||
" -o CaseInsensitiveSearch file system supports case-insensitive file names\n"
|
||||
//" -o ReadOnlyVolume file system is read only\n"
|
||||
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
||||
" --FileSystemName=FSN Name of user mode file system\n");
|
||||
opt_data->help = 1;
|
||||
@ -470,17 +467,6 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION);
|
||||
opt_data->help = 1;
|
||||
return 1;
|
||||
case 'D':
|
||||
arg += sizeof "DebugLog=" - 1;
|
||||
opt_data->DebugLogHandle = CreateFileA(
|
||||
arg,
|
||||
FILE_APPEND_DATA,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
return 0;
|
||||
case 'U':
|
||||
if ('U' == arg[2])
|
||||
arg += sizeof "--UNC=" - 1;
|
||||
@ -523,55 +509,21 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
opt_data.env = env;
|
||||
opt_data.DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000; /* default FileInfoTimeout for FUSE file systems */
|
||||
|
||||
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
||||
return 0;
|
||||
if (opt_data.help)
|
||||
return 0;
|
||||
|
||||
if (opt_data.debug)
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE == opt_data.DebugLogHandle)
|
||||
{
|
||||
ErrorMessage = L": cannot open debug log file.";
|
||||
goto fail;
|
||||
}
|
||||
FspDebugLogSetHandle(opt_data.DebugLogHandle);
|
||||
}
|
||||
|
||||
if ((opt_data.set_uid && -1 == opt_data.uid) ||
|
||||
(opt_data.set_gid && -1 == opt_data.gid))
|
||||
{
|
||||
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 = TRUE;
|
||||
opt_data.VolumeParams.CaseSensitiveSearch = !opt_data.CaseInsensitiveSearch;
|
||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||
opt_data.VolumeParams.ReparsePoints = TRUE;
|
||||
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
||||
opt_data.VolumeParams.NamedStreams = FALSE;
|
||||
opt_data.VolumeParams.ReadOnlyVolume = FALSE;
|
||||
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
||||
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
||||
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));
|
||||
@ -596,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)
|
||||
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_compat.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
/*
|
||||
* This file provides an implementation of the `fuse_*` symbols. This
|
||||
* implementation is a simple shim that forwards `fuse_*` calls to the
|
||||
* equivalent `fsp_fuse_*` ones using a default `fsp_fuse_env`.
|
||||
*
|
||||
* These symbols should *not* be used by C/C++ programs. For this reason
|
||||
* the `fuse.h` headers only expose the `fsp_fuse_*` symbols, wrapped
|
||||
* with macros. These symbols are for use only from programs using FFI
|
||||
* technology to access FUSE symbols (e.g. fusepy, jnr-fuse).
|
||||
*/
|
||||
|
||||
#define FSP_FUSE_API
|
||||
#define FSP_FUSE_SYM(proto, ...) __declspec(dllexport) proto { __VA_ARGS__ }
|
||||
#include <fuse/fuse_common.h>
|
||||
#include <fuse/fuse.h>
|
||||
#include <fuse/fuse_opt.h>
|
@ -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);
|
||||
|
||||
@ -311,34 +378,28 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
||||
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0, PUid, PGid, PMode, 0, FileInfo)
|
||||
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, PUid, PGid, PMode, 0, FileInfo)
|
||||
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
||||
const char *PosixPath, struct fuse_file_info *fi, const struct fuse_stat *stbufp,
|
||||
const char *PosixPath, struct fuse_file_info *fi,
|
||||
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode, PUINT32 PDev,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
UINT64 AllocationUnit;
|
||||
struct fuse_stat stbuf;
|
||||
int err;
|
||||
|
||||
if (0 != stbufp)
|
||||
memcpy(&stbuf, stbufp, sizeof stbuf);
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
|
||||
if (0 != f->ops.fgetattr && 0 != fi && -1 != fi->fh)
|
||||
err = f->ops.fgetattr(PosixPath, (void *)&stbuf, fi);
|
||||
else if (0 != f->ops.getattr)
|
||||
err = f->ops.getattr(PosixPath, (void *)&stbuf);
|
||||
else
|
||||
{
|
||||
int err;
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
|
||||
if (0 != f->ops.fgetattr && 0 != fi && -1 != fi->fh)
|
||||
err = f->ops.fgetattr(PosixPath, (void *)&stbuf, fi);
|
||||
else if (0 != f->ops.getattr)
|
||||
err = f->ops.getattr(PosixPath, (void *)&stbuf);
|
||||
else
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
if (0 != err)
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
if (0 != err)
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
|
||||
if (f->set_umask)
|
||||
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
||||
@ -519,7 +580,7 @@ static NTSTATUS fsp_fuse_intf_GetReparsePointEx(FSP_FILE_SYSTEM *FileSystem,
|
||||
SIZE_T Size;
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0,
|
||||
Result = fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi,
|
||||
&Uid, &Gid, &Mode, &Dev, &FileInfo);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
@ -636,13 +697,13 @@ static NTSTATUS fsp_fuse_intf_GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
struct fuse_statvfs stbuf;
|
||||
int err;
|
||||
|
||||
if (0 == f->ops.statfs)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
if (0 != f->ops.statfs)
|
||||
{
|
||||
err = f->ops.statfs("/", &stbuf);
|
||||
if (0 != err)
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
err = f->ops.statfs("/", &stbuf);
|
||||
if (0 != err)
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
|
||||
VolumeInfo->TotalSize = (UINT64)stbuf.f_blocks * (UINT64)stbuf.f_frsize;
|
||||
VolumeInfo->FreeSize = (UINT64)stbuf.f_bfree * (UINT64)stbuf.f_frsize;
|
||||
@ -821,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;
|
||||
@ -938,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;
|
||||
@ -987,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;
|
||||
@ -1009,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)
|
||||
@ -1050,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);
|
||||
}
|
||||
@ -1152,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;
|
||||
|
||||
@ -1189,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,
|
||||
@ -1221,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;
|
||||
@ -1396,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
|
||||
@ -1439,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;
|
||||
@ -1547,111 +1591,185 @@ 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));
|
||||
|
||||
if (dh->ReaddirPlus && 0 != stbuf)
|
||||
{
|
||||
UINT32 Uid, Gid, Mode;
|
||||
NTSTATUS Result0;
|
||||
|
||||
Result0 = fsp_fuse_intf_GetFileInfoFunnel(dh->FileSystem, 0, 0, stbuf,
|
||||
&Uid, &Gid, &Mode, 0, &DirInfo->FileInfo);
|
||||
if (NT_SUCCESS(Result0))
|
||||
DirInfo->Padding[0] = 1; /* HACK: remember that the FileInfo is valid */
|
||||
}
|
||||
|
||||
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;
|
||||
char *PosixPath = 0, *PosixName, *PosixPathEnd, SavedPathChar;
|
||||
PWSTR FileName = 0;
|
||||
ULONG Size;
|
||||
int err;
|
||||
NTSTATUS Result;
|
||||
|
||||
SizeA = lstrlenA(filedesc->PosixPath);
|
||||
PosixPath = MemAlloc(SizeA + 1 + 255 + 1);
|
||||
if (0 == PosixPath)
|
||||
if (!filedesc->IsDirectory)
|
||||
return STATUS_ACCESS_DENIED;
|
||||
|
||||
memset(&dh, 0, sizeof dh);
|
||||
|
||||
if (0 == filedesc->DirBuffer)
|
||||
{
|
||||
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 (DirInfo->Padding[0])
|
||||
if (0 != f->ops.readdir)
|
||||
{
|
||||
/* DirInfo has been filled already! */
|
||||
memset(&fi, 0, sizeof fi);
|
||||
fi.flags = filedesc->OpenFlags;
|
||||
fi.fh = filedesc->FileHandle;
|
||||
|
||||
DirInfo->Padding[0] = 0;
|
||||
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)
|
||||
{
|
||||
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfoOld);
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
else
|
||||
Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
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
|
||||
{
|
||||
if (1 == SizeW && L'.' == DirInfo->FileNameBuf[0])
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if ('/' == filedesc->PosixPath[0] && '\0' == filedesc->PosixPath[1])
|
||||
{
|
||||
/* if this is the root directory do not add the dot entries */
|
||||
|
||||
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 (2 == SizeW && L'.' == DirInfo->FileNameBuf[0] && L'.' == DirInfo->FileNameBuf[1])
|
||||
if ('.' == di->PosixNameBuf[0] && '.' == di->PosixNameBuf[1] && '\0' == di->PosixNameBuf[2])
|
||||
{
|
||||
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
|
||||
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
|
||||
@ -1664,91 +1782,58 @@ static NTSTATUS fsp_fuse_intf_FixDirInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
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';
|
||||
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, &DirInfo->FileInfo);
|
||||
&Uid, &Gid, &Mode, &di->FileInfo);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
if (0 != PosixPathEnd)
|
||||
*PosixPathEnd = SavedPathChar;
|
||||
}
|
||||
|
||||
FspPosixDecodeWindowsPath(DirInfo->FileNameBuf, SizeW);
|
||||
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_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;
|
||||
int err;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (FspFileSystemAcquireDirectoryBuffer(&filedesc->DirBuffer, 0 == Marker, &Result))
|
||||
{
|
||||
memset(&dh, 0, sizeof dh);
|
||||
dh.filedesc = filedesc;
|
||||
dh.FileSystem = FileSystem;
|
||||
dh.ReaddirPlus = 0 != (f->conn_want & FSP_FUSE_CAP_READDIR_PLUS);
|
||||
dh.Result = STATUS_SUCCESS;
|
||||
|
||||
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);
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
else if (0 != f->ops.getdir)
|
||||
{
|
||||
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfoOld);
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
else
|
||||
Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
Result = dh.Result;
|
||||
if (NT_SUCCESS(Result))
|
||||
Result = fsp_fuse_intf_FixDirInfo(FileSystem, filedesc);
|
||||
}
|
||||
|
||||
FspFileSystemReleaseDirectoryBuffer(&filedesc->DirBuffer);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
FspFileSystemReadDirectoryBuffer(&filedesc->DirBuffer,
|
||||
Marker, Buffer, Length, PBytesTransferred);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent,
|
||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||
@ -2023,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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
@ -40,13 +40,12 @@ struct fuse
|
||||
int rellinks;
|
||||
struct fuse_operations ops;
|
||||
void *data;
|
||||
unsigned conn_want;
|
||||
BOOLEAN fsinit;
|
||||
UINT32 DebugLog;
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
PWSTR MountPoint;
|
||||
FSP_FILE_SYSTEM *FileSystem;
|
||||
BOOLEAN fsinit;
|
||||
FSP_SERVICE *Service; /* weak */
|
||||
};
|
||||
|
||||
@ -63,19 +62,27 @@ struct fsp_fuse_file_desc
|
||||
int OpenFlags;
|
||||
UINT64 FileHandle;
|
||||
PVOID DirBuffer;
|
||||
ULONG DirBufferSize;
|
||||
};
|
||||
|
||||
struct fuse_dirhandle
|
||||
{
|
||||
/* ReadDirectory */
|
||||
struct fsp_fuse_file_desc *filedesc;
|
||||
FSP_FILE_SYSTEM *FileSystem;
|
||||
BOOLEAN ReaddirPlus;
|
||||
NTSTATUS Result;
|
||||
/* CanDelete */
|
||||
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,
|
||||
@ -83,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
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/library.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -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
|
||||
|
63
src/dll/np.c
@ -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:
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/ntstatus.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/path.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/service.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/util.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -163,47 +163,3 @@ exit:
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspVersion(PUINT32 PVersion)
|
||||
{
|
||||
static UINT32 Version;
|
||||
|
||||
if (0 == Version)
|
||||
{
|
||||
/*
|
||||
* This check is not thread-safe, but that should be ok.
|
||||
* Two threads competing to read the version will read
|
||||
* the same value from the Version resource.
|
||||
*/
|
||||
extern HINSTANCE DllInstance;
|
||||
WCHAR ModuleFileName[MAX_PATH];
|
||||
PVOID VersionInfo;
|
||||
DWORD Size;
|
||||
VS_FIXEDFILEINFO *FixedFileInfo = 0;
|
||||
|
||||
if (0 != GetModuleFileNameW(DllInstance, ModuleFileName, MAX_PATH))
|
||||
{
|
||||
Size = GetFileVersionInfoSizeW(ModuleFileName, &Size/*dummy*/);
|
||||
if (0 < Size)
|
||||
{
|
||||
VersionInfo = MemAlloc(Size);
|
||||
if (0 != VersionInfo &&
|
||||
GetFileVersionInfoW(ModuleFileName, 0, Size, VersionInfo) &&
|
||||
VerQueryValueW(VersionInfo, L"\\", &FixedFileInfo, &Size))
|
||||
{
|
||||
/* 32-bit store should be atomic! */
|
||||
Version = FixedFileInfo->dwFileVersionMS;
|
||||
}
|
||||
|
||||
MemFree(VersionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == FixedFileInfo)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
*PVersion = Version;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file launcher/launchctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/close.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -80,18 +80,8 @@ static NTSTATUS FspFsvolClose(
|
||||
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
||||
FspFileNodeDereference(FileNode);
|
||||
|
||||
/* if we are closing files in the context of a rename make it synchronous */
|
||||
if (FspFsvolDeviceFileRenameIsAcquiredExclusive(FsvolDeviceObject))
|
||||
{
|
||||
/* acquire ownership of the Request */
|
||||
Request->Hint = (UINT_PTR)Irp;
|
||||
FspIrpSetRequest(Irp, Request);
|
||||
|
||||
return FSP_STATUS_IOQ_POST_BEST_EFFORT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Post as a BestEffort WORK request. This allows us to complete our own IRP
|
||||
* Post as a BestEffort work request. This allows us to complete our own IRP
|
||||
* and return immediately.
|
||||
*/
|
||||
FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request);
|
||||
|
104
src/sys/create.c
@ -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;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/debug.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/devctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/device.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -41,14 +41,11 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
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);
|
||||
@ -81,12 +78,10 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameIsAcquiredExclusive)
|
||||
#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)
|
||||
@ -369,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,
|
||||
@ -420,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)
|
||||
{
|
||||
@ -576,15 +560,6 @@ VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Own
|
||||
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
|
||||
}
|
||||
|
||||
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||
|
||||
return ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->FileRenameResource);
|
||||
}
|
||||
|
||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
@ -601,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)
|
||||
{
|
||||
@ -679,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();
|
||||
|
||||
|
303
src/sys/dirctl.c
@ -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,11 +74,13 @@ 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 */
|
||||
RequestIrp = 0,
|
||||
RequestCookie = 1,
|
||||
RequestMdl = 1,
|
||||
RequestAddress = 2,
|
||||
RequestProcess = 3,
|
||||
@ -89,11 +91,10 @@ enum
|
||||
/* DirectoryControlComplete retry */
|
||||
RequestDirInfoChangeNumber = 0,
|
||||
};
|
||||
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestMdl, "");
|
||||
|
||||
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)
|
||||
@ -103,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;\
|
||||
@ -127,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;
|
||||
@ -177,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;
|
||||
|
||||
@ -224,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)
|
||||
@ -265,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)));
|
||||
|
||||
@ -276,7 +273,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
||||
Loop = FALSE;
|
||||
}
|
||||
else
|
||||
*DirectoryMarkerOut = FileName;
|
||||
*PDirectoryOffset = DirInfo->NextOffset;
|
||||
}
|
||||
}
|
||||
except (EXCEPTION_EXECUTE_HANDLER)
|
||||
@ -318,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;
|
||||
|
||||
@ -326,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;
|
||||
@ -360,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(
|
||||
@ -369,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;
|
||||
@ -451,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()\
|
||||
@ -472,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;
|
||||
@ -520,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))
|
||||
{
|
||||
@ -567,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))
|
||||
{
|
||||
@ -581,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);
|
||||
@ -635,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;
|
||||
@ -655,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? */
|
||||
@ -835,67 +815,41 @@ NTSTATUS FspFsvolDirectoryControlPrepare(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (FspQueryDirectoryIrpShouldUseProcessBuffer(Irp, Request->Req.QueryDirectory.Length))
|
||||
NTSTATUS Result;
|
||||
PMDL Mdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
Mdl = IoAllocateMdl(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
Request->Req.QueryDirectory.Length,
|
||||
FALSE, FALSE, 0);
|
||||
if (0 == Mdl)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
MmBuildMdlForNonPagedPool(Mdl);
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(Mdl, &Address, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PVOID Cookie;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
|
||||
Result = FspProcessBufferAcquire(Request->Req.QueryDirectory.Length, &Cookie, &Address);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
/* get a pointer to the current process so that we can release the buffer later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestCookie) = (PVOID)((UINT_PTR)Cookie | 1);
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PMDL Mdl = 0;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
|
||||
Mdl = IoAllocateMdl(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
Request->Req.QueryDirectory.Length,
|
||||
FALSE, FALSE, 0);
|
||||
if (0 == Mdl)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
MmBuildMdlForNonPagedPool(Mdl);
|
||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
/* map the MDL into user-mode */
|
||||
Result = FspMapLockedPagesInUserMode(Mdl, &Address, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
FspIopRequestContext(Request, RequestMdl) = Mdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* get a pointer to the current process so that we can unmap the address later */
|
||||
Process = PsGetCurrentProcess();
|
||||
ObReferenceObject(Process);
|
||||
|
||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||
|
||||
FspIopRequestContext(Request, RequestMdl) = Mdl;
|
||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
@ -928,6 +882,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
BOOLEAN Success;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
ASSERT(Request->Req.QueryDirectory.Offset == FileDesc->DirectoryOffset);
|
||||
|
||||
if (0 == Response->IoStatus.Information)
|
||||
{
|
||||
@ -938,23 +893,6 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
|
||||
if (FspFsctlTransactQueryDirectoryKind == Request->Kind)
|
||||
{
|
||||
if ((UINT_PTR)FspIopRequestContext(Request, RequestCookie) & 1)
|
||||
{
|
||||
PVOID Address = FspIopRequestContext(Request, RequestAddress);
|
||||
|
||||
ASSERT(0 != Address);
|
||||
try
|
||||
{
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Address, Response->IoStatus.Information);
|
||||
}
|
||||
except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Result = GetExceptionCode();
|
||||
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||
FSP_RETURN();
|
||||
}
|
||||
}
|
||||
|
||||
DirInfoChangeNumber = FspFileNodeDirInfoChangeNumber(FileNode);
|
||||
Request->Kind = FspFsctlTransactReservedKind;
|
||||
FspIopResetRequest(Request, 0);
|
||||
@ -972,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,
|
||||
@ -1012,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;
|
||||
@ -1055,56 +975,29 @@ static VOID FspFsvolQueryDirectoryRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, P
|
||||
PAGED_CODE();
|
||||
|
||||
PIRP Irp = Context[RequestIrp];
|
||||
PMDL Mdl = Context[RequestMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if ((UINT_PTR)Context[RequestCookie] & 1)
|
||||
if (0 != Address)
|
||||
{
|
||||
PVOID Cookie = (PVOID)((UINT_PTR)Context[RequestCookie] & ~1);
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, Mdl);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
FspProcessBufferRelease(Cookie, Address);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
else
|
||||
{
|
||||
PMDL Mdl = Context[RequestMdl];
|
||||
PVOID Address = Context[RequestAddress];
|
||||
PEPROCESS Process = Context[RequestProcess];
|
||||
|
||||
if (0 != Address)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
BOOLEAN Attach;
|
||||
|
||||
ASSERT(0 != Process);
|
||||
Attach = Process != PsGetCurrentProcess();
|
||||
|
||||
if (Attach)
|
||||
KeStackAttachProcess(Process, &ApcState);
|
||||
MmUnmapLockedPages(Address, Mdl);
|
||||
if (Attach)
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
}
|
||||
if (0 != Mdl)
|
||||
IoFreeMdl(Mdl);
|
||||
|
||||
if (0 != Irp)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/driver.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -46,10 +46,6 @@ NTSTATUS DriverEntry(
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
FSP_RETURN();
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
|
||||
@ -63,21 +59,14 @@ NTSTATUS DriverEntry(
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
FSP_RETURN(FspDeviceDelete(FspFsctlDiskDeviceObject));
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
@ -187,9 +176,6 @@ NTSTATUS DriverEntry(
|
||||
|
||||
static VOID FspDriverMultiVersionInitialize(VOID)
|
||||
{
|
||||
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
#pragma prefast(suppress:30035, "FspDriverMultiVersionInitialize is called from DriverEntry")
|
||||
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
|
||||
|
||||
if (RtlIsNtDdiVersionAvailable(NTDDI_WIN7))
|
||||
@ -218,8 +204,6 @@ VOID FspUnload(
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
FspDriverObject = 0;
|
||||
|
||||
FspProcessBufferFinalize();
|
||||
|
||||
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
||||
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
||||
&DriverObject->DriverName);
|
||||
@ -232,6 +216,5 @@ PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
|
||||
ULONG FspProcessorCount;
|
||||
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
||||
ULONG FspMvMdlMappingNoWrite = 0;
|
||||
|
116
src/sys/driver.h
@ -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(
|
||||
@ -601,14 +597,6 @@ VOID FspIrpHookReset(PIRP Irp);
|
||||
PVOID FspIrpHookContext(PVOID Context);
|
||||
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||
|
||||
/* process buffers */
|
||||
#define FspProcessBufferSizeMax (64 * 1024)
|
||||
NTSTATUS FspProcessBufferInitialize(VOID);
|
||||
VOID FspProcessBufferFinalize(VOID);
|
||||
VOID FspProcessBufferCollect(HANDLE ProcessId);
|
||||
NTSTATUS FspProcessBufferAcquire(SIZE_T BufferSize, PVOID *PBufferCookie, PVOID *PBuffer);
|
||||
VOID FspProcessBufferRelease(PVOID BufferCookie, PVOID Buffer);
|
||||
|
||||
/* IRP context */
|
||||
#define FspIrpTimestampInfinity ((ULONG)-1L)
|
||||
#define FspIrpTimestamp(Irp) \
|
||||
@ -922,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)
|
||||
{
|
||||
@ -960,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
|
||||
{
|
||||
@ -1016,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;
|
||||
@ -1033,7 +1006,6 @@ typedef struct
|
||||
BOOLEAN ExpirationInProgress;
|
||||
ERESOURCE FileRenameResource;
|
||||
ERESOURCE ContextTableResource;
|
||||
LIST_ENTRY ContextList;
|
||||
RTL_AVL_TABLE ContextByNameTable;
|
||||
PVOID ContextByNameTableElementStorage;
|
||||
UNICODE_STRING VolumeName;
|
||||
@ -1043,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)
|
||||
@ -1072,14 +1043,11 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
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);
|
||||
@ -1114,42 +1082,11 @@ 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 ?\
|
||||
// STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED)
|
||||
|
||||
/* process buffers conditional usage */
|
||||
static inline
|
||||
BOOLEAN FspReadIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
{
|
||||
ASSERT(0 != Irp);
|
||||
#if DBG
|
||||
return DEBUGTEST(50) ||
|
||||
#else
|
||||
return FspProcessBufferSizeMax >= BufferSize ||
|
||||
#endif
|
||||
FspFsvolDeviceExtension(IoGetCurrentIrpStackLocation(Irp)->DeviceObject)->
|
||||
VolumeParams.AlwaysUseDoubleBuffering;
|
||||
}
|
||||
static inline
|
||||
BOOLEAN FspWriteIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
{
|
||||
ASSERT(0 != Irp);
|
||||
#if DBG
|
||||
return DEBUGTEST(50);
|
||||
#else
|
||||
return FspProcessBufferSizeMax >= BufferSize;
|
||||
#endif
|
||||
}
|
||||
static inline
|
||||
BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
{
|
||||
return FspReadIrpShouldUseProcessBuffer(Irp, BufferSize);
|
||||
}
|
||||
|
||||
/* volume management */
|
||||
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
||||
NTSTATUS FspVolumeCreate(
|
||||
@ -1210,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;
|
||||
@ -1254,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,
|
||||
@ -1328,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 */
|
||||
@ -1349,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)
|
||||
{
|
||||
@ -1382,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,
|
||||
@ -1394,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,
|
||||
@ -1558,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;
|
||||
|
||||
|
@ -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
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/ea.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
522
src/sys/file.c
@ -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)
|
||||
{
|
||||
/*
|
||||
@ -1243,50 +1141,6 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
|
||||
}
|
||||
}
|
||||
|
||||
/* flush and purge cleaned up but still open files affected by rename (github issue #45) */
|
||||
{
|
||||
PIRP TopLevelIrp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
/* reset the top-level IRP to avoid deadlock on the FileNodes' resources */
|
||||
TopLevelIrp = IoGetTopLevelIrp();
|
||||
IoSetTopLevelIrp(0);
|
||||
|
||||
/* enumerate in reverse order so that files are flushed before containing directories */
|
||||
for (
|
||||
DescendantFileNodeIndex = DescendantFileNodeCount - 1;
|
||||
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||
DescendantFileNodeIndex--)
|
||||
{
|
||||
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||
HasHandles = (UINT_PTR)DescendantFileNode & 1;
|
||||
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||
|
||||
if (HasHandles)
|
||||
continue;
|
||||
if (CheckingOldName &&
|
||||
(DescendantFileNode->FileName.Length <= FileName->Length ||
|
||||
L'\\' != DescendantFileNode->FileName.Buffer[FileName->Length / sizeof(WCHAR)]))
|
||||
continue;
|
||||
if (MmDoesFileHaveUserWritableReferences(&DescendantFileNode->NonPaged->SectionObjectPointers))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* There are no handles and no writable user mappings. [Ideally we would want to know
|
||||
* that there are no handles and no user mappings, period. Is there an DDI/method to
|
||||
* do that?] There may be a read-only user mapping, but in this case CcFlushCache
|
||||
* should be a no-op and MmForceSectionClosed will fail (which is fine).
|
||||
*/
|
||||
|
||||
ASSERT(DescendantFileNode != FileNode && DescendantFileNode->MainFileNode != FileNode);
|
||||
|
||||
FspCcFlushCache(&DescendantFileNode->NonPaged->SectionObjectPointers, 0, 0, &IoStatus);
|
||||
MmForceSectionClosed(&DescendantFileNode->NonPaged->SectionObjectPointers, FALSE);
|
||||
}
|
||||
|
||||
IoSetTopLevelIrp(TopLevelIrp);
|
||||
}
|
||||
|
||||
/* break any Batch or Handle oplocks on descendants */
|
||||
Result = STATUS_SUCCESS;
|
||||
for (
|
||||
@ -1383,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);
|
||||
@ -1551,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();
|
||||
|
||||
@ -1565,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);
|
||||
@ -1668,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();
|
||||
@ -1794,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();
|
||||
@ -1886,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();
|
||||
|
||||
@ -1907,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 */
|
||||
|
||||
@ -1917,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)
|
||||
{
|
||||
@ -1924,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);
|
||||
@ -2031,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;
|
||||
|
||||
@ -2080,65 +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)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
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;
|
||||
}
|
||||
@ -2165,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;
|
||||
@ -2177,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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
230
src/sys/fsctl.c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/ioq.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2016 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|