mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 09:22:57 -05:00
Compare commits
86 Commits
Author | SHA1 | Date | |
---|---|---|---|
bd952253fb | |||
c7780cf7fa | |||
31b54ecc47 | |||
4084448bd5 | |||
4dc1828e1f | |||
79b7b66b62 | |||
612c820630 | |||
e13233ef32 | |||
dd815f3c39 | |||
5faafc4d11 | |||
78e5d031c0 | |||
9ef562df15 | |||
a7cdc815d0 | |||
bd5e15fe24 | |||
214a8406eb | |||
6bd6f0ee35 | |||
f8cebd1f92 | |||
f8f6d0f1bc | |||
b06132cb6b | |||
748c9b6409 | |||
bfc7fc5dec | |||
03f906f966 | |||
4b1111fcc5 | |||
86ddeed129 | |||
e2d4b36057 | |||
ab2908a9ee | |||
fd7b12bb61 | |||
eb2000a194 | |||
e4cabc50c5 | |||
92dc2feecd | |||
43f333e8a6 | |||
59eb40fd9b | |||
d85d36c94f | |||
27b841faf8 | |||
c6967c737a | |||
4ccbd1bdf6 | |||
0a8b8e8444 | |||
352450d538 | |||
7e1861a9f5 | |||
860e9db8a7 | |||
1d435269bd | |||
e58ac1fbde | |||
1f0f2fe094 | |||
d7ec331c74 | |||
938c036387 | |||
16f5bd089d | |||
6afea44e31 | |||
2859355fd8 | |||
75012d1301 | |||
8e1512c067 | |||
fa6b621042 | |||
8ffb359f20 | |||
203873ef04 | |||
e73bda3926 | |||
0186b82fea | |||
db38d2f7f8 | |||
016d015fe6 | |||
87b2d4ca4c | |||
dfd6cbbde1 | |||
6a126da51d | |||
03df0a9c26 | |||
5c3a82a074 | |||
b591015b28 | |||
fb9b798d3d | |||
cc408b71e1 | |||
19a73ca01d | |||
3992b9ebb1 | |||
a46c0610c4 | |||
495fc7a5dc | |||
2ba46fdb71 | |||
7cb56bb132 | |||
687b02c1e6 | |||
218b162d75 | |||
5e13c8750e | |||
2e71d2fe14 | |||
866e4abe10 | |||
7894cc8b7b | |||
0c810c52fa | |||
b06e947e0e | |||
aed134080c | |||
3ce490d405 | |||
76aabecbfb | |||
8eebfe811d | |||
5798527237 | |||
817beebb63 | |||
b7a2b5e17a |
@ -73,4 +73,4 @@ If you wish to discuss WinFsp there are now two options:
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
WinFsp is available under the [AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html) license. If you find the constraints of the AGPLv3 too onerous, 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.
|
||||||
|
Binary file not shown.
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -378,7 +378,7 @@
|
|||||||
</Feature>
|
</Feature>
|
||||||
|
|
||||||
<WixVariable Id="WixUIBannerBmp" Value="wixbanner.bmp" />
|
<WixVariable Id="WixUIBannerBmp" Value="wixbanner.bmp" />
|
||||||
<WixVariable Id="WixUIDialogBmp" Value="wixdialog.bmp" />
|
<WixVariable Id="WixUIDialogBmp" Value="wixdialog-$(var.MyDevStage).bmp" />
|
||||||
<UI Id="FeatureTree">
|
<UI Id="FeatureTree">
|
||||||
<UIRef Id="WixUI_FeatureTree" />
|
<UIRef Id="WixUI_FeatureTree" />
|
||||||
<!-- skip the license agreement dialog; higher Order takes priority (weird) -->
|
<!-- skip the license agreement dialog; higher Order takes priority (weird) -->
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
|
||||||
<DefineConstants>Debug;MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion)</DefineConstants>
|
<DefineConstants>Debug;MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyDevStage=$(MyDevStage);MyVersion=$(MyVersion)</DefineConstants>
|
||||||
<SuppressAllWarnings>False</SuppressAllWarnings>
|
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||||
<Pedantic>True</Pedantic>
|
<Pedantic>True</Pedantic>
|
||||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
|
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
|
||||||
<DefineConstants>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion)</DefineConstants>
|
<DefineConstants>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyDevStage=$(MyDevStage);MyVersion=$(MyVersion)</DefineConstants>
|
||||||
<SuppressAllWarnings>False</SuppressAllWarnings>
|
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||||
<Pedantic>True</Pedantic>
|
<Pedantic>True</Pedantic>
|
||||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 601 KiB After Width: | Height: | Size: 601 KiB |
BIN
build/VStudio/installer/wixdialog-Gold.bmp
Normal file
BIN
build/VStudio/installer/wixdialog-Gold.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 601 KiB |
BIN
build/VStudio/installer/wixdialog-RC.bmp
Normal file
BIN
build/VStudio/installer/wixdialog-RC.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 601 KiB |
@ -105,7 +105,8 @@
|
|||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -125,7 +126,8 @@
|
|||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -146,7 +148,8 @@
|
|||||||
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -169,7 +172,8 @@
|
|||||||
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -105,7 +105,8 @@
|
|||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -126,7 +127,8 @@
|
|||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -148,7 +150,8 @@
|
|||||||
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -172,7 +175,8 @@
|
|||||||
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -196,6 +196,7 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\rdwr-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\rdwr-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\reparse-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\reparse-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
<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\timeout-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -67,6 +67,9 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\hook.c">
|
<ClCompile Include="..\..\..\tst\winfsp-tests\hook.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
<MyDescription>Windows File System Proxy</MyDescription>
|
<MyDescription>Windows File System Proxy</MyDescription>
|
||||||
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
||||||
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
||||||
|
<MyDevStage>Beta</MyDevStage>
|
||||||
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
|
<!-- 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>
|
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
|
||||||
<MyVersion>0.16.$(MyBuildNumber)</MyVersion>
|
<MyVersion>0.17.$(MyBuildNumber)</MyVersion>
|
||||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
|
@ -173,7 +173,8 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
@ -200,7 +201,8 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
@ -228,7 +230,8 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<AdditionalIncludeDirectories>..\..\src;..\..\inc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\inc</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
@ -258,7 +261,8 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<AdditionalIncludeDirectories>..\..\src;..\..\inc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\inc</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<AdditionalOptions>/Gs16384 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v0.17::
|
||||||
|
|
||||||
|
This release brings support for named streams.
|
||||||
|
|
||||||
|
- Named streams (or alternate data streams) are additional streams of data within a file. When a file gets opened the main (default, unnamed) data stream of a file gets accessed. However NTFS (and now WinFsp) supports multiple data streams per file accessible using the `filename:streamname` syntax.
|
||||||
|
- WinFsp handles a lot of the hairy details regarding named streams, including sharing checks, pending delete checks, conflicts between the main and named streams, etc.
|
||||||
|
- User mode file systems that wish to support named streams must set the `FSP_FSCTL_VOLUME_PARAMS::NamedStreams` flag and must also be prepared to handle named streams on `Create`, `Cleanup`, etc. They must also implement the new `FSP_FILE_SYSTEM_INTERFACE::GetStreamInfo` operation. For more information on how to correctly handle named streams refer to the MEMFS sample.
|
||||||
|
|
||||||
|
|
||||||
v0.16::
|
v0.16::
|
||||||
|
|
||||||
This release brings support for reparse points and symbolic links as well as other minor changes.
|
This release brings support for reparse points and symbolic links as well as other minor changes.
|
||||||
|
143
doc/License.txt
143
doc/License.txt
@ -1,12 +1,12 @@
|
|||||||
The WinFsp project is Copyright (C) Bill Zissimopoulos. It is licensed
|
The WinFsp project is Copyright (C) Bill Zissimopoulos. It is licensed
|
||||||
under the terms of the AGPLv3. The full text of this license follows
|
under the terms of the GPLv3. The full text of this license follows
|
||||||
below. Commercial licensing options are also available: Please contact
|
below. Commercial licensing options are also available: Please contact
|
||||||
Bill Zissimopoulos <billziss at navimatics.com>.
|
Bill Zissimopoulos <billziss at navimatics.com>.
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 19 November 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
@ -14,15 +14,17 @@ Bill Zissimopoulos <billziss at navimatics.com>.
|
|||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
The GNU General Public License is a free, copyleft license for
|
||||||
software and other kinds of works, specifically designed to ensure
|
software and other kinds of works.
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
share and change all versions of a program--to make sure it remains free
|
||||||
software for all its users.
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
@ -31,34 +33,44 @@ them if you wish), that you receive source code or can get it if you
|
|||||||
want it, that you can change the software or use pieces of it in new
|
want it, that you can change the software or use pieces of it in new
|
||||||
free programs, and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
To protect your rights, we need to prevent others from denying you
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
you this License which gives you legal permission to copy, distribute
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
and/or modify the software.
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
For example, if you distribute copies of such a program, whether
|
||||||
improvements made in alternate versions of the program, if they
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
receive widespread use, become available for other developers to
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
incorporate. Many developers of free software are heartened and
|
or can get the source code. And you must show them these terms so they
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
know their rights.
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
ensure that, in such cases, the modified source code becomes available
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
to the community. It requires the operator of a network server to
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
that there is no warranty for this free software. For both users' and
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
changed, so that their problems will not be attributed erroneously to
|
||||||
this license.
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
@ -67,7 +79,7 @@ modification follow.
|
|||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
@ -544,45 +556,35 @@ to collect a royalty for further conveying from those to whom you convey
|
|||||||
the Program, the only way you could satisfy both those terms and this
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
under version 3 of the GNU General Public License into a single
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
combined work, and to convey the resulting work. The terms of this
|
||||||
License will continue to apply to the part which is the covered work,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the work with which it is combined will remain governed by version
|
but the special requirements of the GNU Affero General Public License,
|
||||||
3 of the GNU General Public License.
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
the GNU General Public License from time to time. Such new versions will
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
Program specifies that a certain numbered version of the GNU General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
GNU General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
@ -640,29 +642,40 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
Copyright (C) <year> <name of author>
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Affero General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
If the program does terminal interaction, make it output a short
|
||||||
network, you should also make sure that it provides a way for users to
|
notice like this when it starts in an interactive mode:
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
<program> Copyright (C) <year> <name of author>
|
||||||
of the code. There are many ways you could offer source, and different
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
solutions will be better for different programs; see section 13 for the
|
This is free software, and you are welcome to redistribute it
|
||||||
specific requirements.
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
2
ext/test
2
ext/test
Submodule ext/test updated: 60f9f44b87...0059e0a24a
@ -11,9 +11,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -24,12 +24,17 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* static_assert is a C++11 feature, but seems to work with C on MSVC 2015 */
|
||||||
|
#if defined(WINFSP_SYS_INTERNAL) || defined(WINFSP_DLL_INTERNAL)
|
||||||
|
#define FSP_FSCTL_STATIC_ASSERT(e,m) static_assert(e,m)
|
||||||
|
#else
|
||||||
|
#define FSP_FSCTL_STATIC_ASSERT(e,m)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FSP_FSCTL_DRIVER_NAME "WinFsp"
|
#define FSP_FSCTL_DRIVER_NAME "WinFsp"
|
||||||
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
|
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
|
||||||
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
|
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
|
||||||
|
|
||||||
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
|
|
||||||
|
|
||||||
// {6F9D25FA-6DEE-4A9D-80F5-E98E14F35E54}
|
// {6F9D25FA-6DEE-4A9D-80F5-E98E14F35E54}
|
||||||
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid =
|
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid =
|
||||||
{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } };
|
{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } };
|
||||||
@ -55,19 +60,26 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
|||||||
#define FSP_FSCTL_STOP \
|
#define FSP_FSCTL_STOP \
|
||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
|
||||||
|
|
||||||
#define FSP_FSCTL_VOLUME_NAME_SIZE (64 * sizeof(WCHAR))
|
#define FSP_FSCTL_VOLUME_NAME_SIZE (64 * sizeof(WCHAR))
|
||||||
#define FSP_FSCTL_VOLUME_PREFIX_SIZE (64 * sizeof(WCHAR))
|
#define FSP_FSCTL_VOLUME_PREFIX_SIZE (192 * sizeof(WCHAR))
|
||||||
|
#define FSP_FSCTL_VOLUME_FSNAME_SIZE (16 * sizeof(WCHAR))
|
||||||
#define FSP_FSCTL_VOLUME_NAME_SIZEMAX (FSP_FSCTL_VOLUME_NAME_SIZE + FSP_FSCTL_VOLUME_PREFIX_SIZE)
|
#define FSP_FSCTL_VOLUME_NAME_SIZEMAX (FSP_FSCTL_VOLUME_NAME_SIZE + FSP_FSCTL_VOLUME_PREFIX_SIZE)
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
|
||||||
|
"Max volume name size is greater than MAX_PATH.");
|
||||||
|
|
||||||
#define FSP_FSCTL_TRANSACT_PATH_SIZEMAX 2048
|
#define FSP_FSCTL_TRANSACT_PATH_SIZEMAX (1024 * sizeof(WCHAR))
|
||||||
|
|
||||||
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */
|
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (16 * 1024 - 64) /* 64: size for internal request header */
|
||||||
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */
|
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (16 * 1024)
|
||||||
#define FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_REQ_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_REQ))
|
#define FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_REQ_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_REQ))
|
||||||
#define FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_RSP))
|
#define FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_RSP))
|
||||||
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN 16384
|
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN (64 * 1024)
|
||||||
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
|
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
|
||||||
|
|
||||||
|
#define FSP_FSCTL_TRANSACT_USERCONTEXT(s,i) (((PUINT64)&(s).UserContext)[i])
|
||||||
|
|
||||||
/* marshalling */
|
/* marshalling */
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||||
@ -94,6 +106,7 @@ enum
|
|||||||
FspFsctlTransactLockControlKind,
|
FspFsctlTransactLockControlKind,
|
||||||
FspFsctlTransactQuerySecurityKind,
|
FspFsctlTransactQuerySecurityKind,
|
||||||
FspFsctlTransactSetSecurityKind,
|
FspFsctlTransactSetSecurityKind,
|
||||||
|
FspFsctlTransactQueryStreamInformationKind,
|
||||||
FspFsctlTransactKindCount,
|
FspFsctlTransactKindCount,
|
||||||
};
|
};
|
||||||
enum
|
enum
|
||||||
@ -130,11 +143,18 @@ typedef struct
|
|||||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
|
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
|
||||||
UINT32 ReparsePoints:1; /* file system supports reparse points */
|
UINT32 ReparsePoints:1; /* file system supports reparse points */
|
||||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */
|
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */
|
||||||
UINT32 NamedStreams:1; /* file system supports named streams (!!!: unimplemented) */
|
UINT32 NamedStreams:1; /* file system supports named streams */
|
||||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */
|
UINT32 HardLinks:1; /* unimplemented; set to 0 */
|
||||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
|
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
|
||||||
UINT32 ReadOnlyVolume:1;
|
UINT32 ReadOnlyVolume:1;
|
||||||
|
/* kernel-mode flags */
|
||||||
|
UINT32 PostCleanupOnDeleteOnly:1; /* post Cleanup when deleting a file only */
|
||||||
|
UINT32 KmReservedFlags:5;
|
||||||
|
/* user-mode flags */
|
||||||
|
UINT32 UmFileNodeIsUserContext2:1; /* user mode: FileNode parameter is UserContext2 */
|
||||||
|
UINT32 UmReservedFlags:15;
|
||||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */
|
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */
|
||||||
|
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||||
} FSP_FSCTL_VOLUME_PARAMS;
|
} FSP_FSCTL_VOLUME_PARAMS;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -165,6 +185,13 @@ typedef struct
|
|||||||
WCHAR FileNameBuf[];
|
WCHAR FileNameBuf[];
|
||||||
} FSP_FSCTL_DIR_INFO;
|
} FSP_FSCTL_DIR_INFO;
|
||||||
typedef struct
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT16 Size;
|
||||||
|
UINT64 StreamSize;
|
||||||
|
UINT64 StreamAllocationSize;
|
||||||
|
WCHAR StreamNameBuf[];
|
||||||
|
} FSP_FSCTL_STREAM_INFO;
|
||||||
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT16 Offset;
|
UINT16 Offset;
|
||||||
UINT16 Size;
|
UINT16 Size;
|
||||||
@ -191,6 +218,8 @@ typedef struct
|
|||||||
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
||||||
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
|
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
|
||||||
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
||||||
|
UINT32 ReservedFlags:28;
|
||||||
|
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
|
||||||
} Create;
|
} Create;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -313,6 +342,11 @@ typedef struct
|
|||||||
UINT64 AccessToken; /* request access token (HANDLE) */
|
UINT64 AccessToken; /* request access token (HANDLE) */
|
||||||
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
|
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
|
||||||
} SetSecurity;
|
} SetSecurity;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext;
|
||||||
|
UINT64 UserContext2;
|
||||||
|
} QueryStreamInformation;
|
||||||
} Req;
|
} Req;
|
||||||
FSP_FSCTL_TRANSACT_BUF FileName; /* {Create,Cleanup,SetInformation/{...},QueryDirectory} */
|
FSP_FSCTL_TRANSACT_BUF FileName; /* {Create,Cleanup,SetInformation/{...},QueryDirectory} */
|
||||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
||||||
@ -382,6 +416,10 @@ typedef struct
|
|||||||
{
|
{
|
||||||
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* Size==0 means no security descriptor returned */
|
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* Size==0 means no security descriptor returned */
|
||||||
} SetSecurity;
|
} SetSecurity;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Buffer;
|
||||||
|
} QueryStreamInformation;
|
||||||
} Rsp;
|
} Rsp;
|
||||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
||||||
} FSP_FSCTL_TRANSACT_RSP;
|
} FSP_FSCTL_TRANSACT_RSP;
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -318,6 +318,10 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* tested to see if the delete can proceed and if the answer is positive the file is then
|
* tested to see if the delete can proceed and if the answer is positive the file is then
|
||||||
* deleted during Cleanup.
|
* deleted during Cleanup.
|
||||||
*
|
*
|
||||||
|
* As an optimization a file system may specify the FSP_FSCTL_VOLUME_PARAMS ::
|
||||||
|
* PostCleanupOnDeleteOnly flag. In this case the FSD will only post Cleanup requests when a
|
||||||
|
* file is being deleted.
|
||||||
|
*
|
||||||
* @param FileSystem
|
* @param FileSystem
|
||||||
* The file system on which this request is posted.
|
* The file system on which this request is posted.
|
||||||
* @param Request
|
* @param Request
|
||||||
@ -769,21 +773,39 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
PVOID FileNode,
|
PVOID FileNode,
|
||||||
PWSTR FileName, PVOID Buffer, SIZE_T Size);
|
PWSTR FileName, PVOID Buffer, SIZE_T Size);
|
||||||
|
/**
|
||||||
|
* Get named streams information.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param Request
|
||||||
|
* The request posted by the kernel mode FSD.
|
||||||
|
* @param FileNode
|
||||||
|
* The file node of the file or directory to get stream information for.
|
||||||
|
* @param Buffer
|
||||||
|
* Pointer to a buffer that will receive the stream information.
|
||||||
|
* @param Length
|
||||||
|
* Length of buffer.
|
||||||
|
* @param PBytesTransferred [out]
|
||||||
|
* Pointer to a memory location that will receive the actual number of bytes stored.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
* @see
|
||||||
|
* FspFileSystemAddStreamInfo
|
||||||
|
*/
|
||||||
|
NTSTATUS (*GetStreamInfo)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
|
PVOID FileNode, PVOID Buffer, ULONG Length,
|
||||||
|
PULONG PBytesTransferred);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This ensures that this interface will always contain 64 function pointers.
|
* This ensures that this interface will always contain 64 function pointers.
|
||||||
* Please update when changing the interface as it is important for future compatibility.
|
* Please update when changing the interface as it is important for future compatibility.
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*Reserved[41])();
|
NTSTATUS (*Reserved[40])();
|
||||||
} FSP_FILE_SYSTEM_INTERFACE;
|
} FSP_FILE_SYSTEM_INTERFACE;
|
||||||
#if defined(WINFSP_DLL_INTERNAL)
|
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||||
/*
|
|
||||||
* Static_assert is a C++11 feature, but seems to work with C on MSVC 2015.
|
|
||||||
* Use it to verify that FSP_FILE_SYSTEM_INTERFACE has the right size.
|
|
||||||
*/
|
|
||||||
static_assert(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
|
||||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||||
#endif
|
|
||||||
typedef struct _FSP_FILE_SYSTEM
|
typedef struct _FSP_FILE_SYSTEM
|
||||||
{
|
{
|
||||||
UINT16 Version;
|
UINT16 Version;
|
||||||
@ -801,6 +823,7 @@ typedef struct _FSP_FILE_SYSTEM
|
|||||||
UINT32 DebugLog;
|
UINT32 DebugLog;
|
||||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
||||||
SRWLOCK OpGuardLock;
|
SRWLOCK OpGuardLock;
|
||||||
|
BOOLEAN UmFileNodeIsUserContext2;
|
||||||
} FSP_FILE_SYSTEM;
|
} FSP_FILE_SYSTEM;
|
||||||
/**
|
/**
|
||||||
* Create a file system object.
|
* Create a file system object.
|
||||||
@ -1011,6 +1034,8 @@ FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
FSP_API NTSTATUS FspFileSystemOpQueryStreamInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
@ -1151,6 +1176,30 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
||||||
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
|
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
|
||||||
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize);
|
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize);
|
||||||
|
/**
|
||||||
|
* Add named stream information to a buffer.
|
||||||
|
*
|
||||||
|
* This is a helper for implementing the GetStreamInfo operation.
|
||||||
|
*
|
||||||
|
* @param StreamInfo
|
||||||
|
* The stream information to add. A value of NULL acts as an EOF marker for a GetStreamInfo
|
||||||
|
* operation.
|
||||||
|
* @param Buffer
|
||||||
|
* Pointer to a buffer that will receive the stream information. This should contain
|
||||||
|
* the same value passed to the GetStreamInfo Buffer parameter.
|
||||||
|
* @param Length
|
||||||
|
* Length of buffer. This should contain the same value passed to the GetStreamInfo
|
||||||
|
* Length parameter.
|
||||||
|
* @param PBytesTransferred [out]
|
||||||
|
* Pointer to a memory location that will receive the actual number of bytes stored. This should
|
||||||
|
* contain the same value passed to the GetStreamInfo PBytesTransferred parameter.
|
||||||
|
* @return
|
||||||
|
* TRUE if the stream information was added, FALSE if there was not enough space to add it.
|
||||||
|
* @see
|
||||||
|
* GetStreamInfo
|
||||||
|
*/
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Security
|
* Security
|
||||||
@ -1158,7 +1207,7 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
|||||||
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
|
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
|
||||||
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentOrMain, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess/* or ReparsePointIndex */,
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess/* or ReparsePointIndex */,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -1174,11 +1223,11 @@ FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor
|
|||||||
static inline
|
static inline
|
||||||
NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentOrMain, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess)
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess)
|
||||||
{
|
{
|
||||||
return FspAccessCheckEx(FileSystem, Request,
|
return FspAccessCheckEx(FileSystem, Request,
|
||||||
CheckParentDirectory, AllowTraverseCheck,
|
CheckParentOrMain, AllowTraverseCheck,
|
||||||
DesiredAccess, PGrantedAccess,
|
DesiredAccess, PGrantedAccess,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
@ -1420,9 +1469,10 @@ FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error);
|
|||||||
FSP_API DWORD FspWin32FromNtStatus(NTSTATUS Status);
|
FSP_API DWORD FspWin32FromNtStatus(NTSTATUS Status);
|
||||||
FSP_API VOID FspEventLog(ULONG Type, PWSTR Format, ...);
|
FSP_API VOID FspEventLog(ULONG Type, PWSTR Format, ...);
|
||||||
FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap);
|
FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||||
FSP_API VOID FspDebugLog(const char *format, ...);
|
FSP_API VOID FspDebugLogSetHandle(HANDLE Handle);
|
||||||
FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
FSP_API VOID FspDebugLog(const char *Format, ...);
|
||||||
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime);
|
FSP_API VOID FspDebugLogSD(const char *Format, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||||
|
FSP_API VOID FspDebugLogFT(const char *Format, PFILETIME FileTime);
|
||||||
FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request);
|
FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request);
|
||||||
FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -19,6 +19,13 @@
|
|||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
static HANDLE FspDebugLogHandle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
FSP_API VOID FspDebugLogSetHandle(HANDLE Handle)
|
||||||
|
{
|
||||||
|
FspDebugLogHandle = Handle;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API VOID FspDebugLog(const char *format, ...)
|
FSP_API VOID FspDebugLog(const char *format, ...)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -28,6 +35,12 @@ FSP_API VOID FspDebugLog(const char *format, ...)
|
|||||||
wvsprintfA(buf, format, ap);
|
wvsprintfA(buf, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
buf[sizeof buf - 1] = '\0';
|
buf[sizeof buf - 1] = '\0';
|
||||||
|
if (INVALID_HANDLE_VALUE != FspDebugLogHandle)
|
||||||
|
{
|
||||||
|
DWORD bytes;
|
||||||
|
WriteFile(FspDebugLogHandle, buf, lstrlenA(buf), &bytes, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
OutputDebugStringA(buf);
|
OutputDebugStringA(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -99,6 +99,7 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
|||||||
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
|
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
|
||||||
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
|
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
|
||||||
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
|
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
|
||||||
|
FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation;
|
||||||
FileSystem->Interface = Interface;
|
FileSystem->Interface = Interface;
|
||||||
|
|
||||||
FileSystem->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE;
|
FileSystem->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE;
|
||||||
@ -106,6 +107,8 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
|||||||
FileSystem->EnterOperation = FspFileSystemOpEnter;
|
FileSystem->EnterOperation = FspFileSystemOpEnter;
|
||||||
FileSystem->LeaveOperation = FspFileSystemOpLeave;
|
FileSystem->LeaveOperation = FspFileSystemOpLeave;
|
||||||
|
|
||||||
|
FileSystem->UmFileNodeIsUserContext2 = !!VolumeParams->UmFileNodeIsUserContext2;
|
||||||
|
|
||||||
*PFileSystem = FileSystem;
|
*PFileSystem = FileSystem;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -32,7 +32,7 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
PWSTR DeviceRoot;
|
PWSTR DeviceRoot;
|
||||||
SIZE_T DeviceRootSize, DevicePathSize;
|
SIZE_T DeviceRootSize, DevicePathSize;
|
||||||
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr, *DevicePathEnd;
|
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
||||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||||
DWORD Bytes;
|
DWORD Bytes;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
|||||||
VolumeNameBuf[0] = L'\0';
|
VolumeNameBuf[0] = L'\0';
|
||||||
*PVolumeHandle = INVALID_HANDLE_VALUE;
|
*PVolumeHandle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
/* check lengths; everything (including encoded volume params) must fit within MAX_PATH */
|
/* check lengths; everything (including encoded volume params) must fit within DevicePathBuf */
|
||||||
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
|
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
|
||||||
DeviceRootSize = lstrlenW(DeviceRoot) * sizeof(WCHAR);
|
DeviceRootSize = lstrlenW(DeviceRoot) * sizeof(WCHAR);
|
||||||
DevicePathSize = lstrlenW(DevicePath) * sizeof(WCHAR);
|
DevicePathSize = lstrlenW(DevicePath) * sizeof(WCHAR);
|
||||||
|
195
src/dll/fsop.c
195
src/dll/fsop.c
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
|
|
||||||
|
#define USERCONTEXT(s) \
|
||||||
|
FSP_FSCTL_TRANSACT_USERCONTEXT(s, FileSystem->UmFileNodeIsUserContext2)
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
{
|
{
|
||||||
@ -31,7 +34,8 @@ FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
||||||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext))
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
|
0 == Request->Req.FlushBuffers.UserContext2))
|
||||||
{
|
{
|
||||||
AcquireSRWLockExclusive(&FileSystem->OpGuardLock);
|
AcquireSRWLockExclusive(&FileSystem->OpGuardLock);
|
||||||
}
|
}
|
||||||
@ -68,7 +72,8 @@ FSP_API NTSTATUS FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
||||||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext))
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
|
0 == Request->Req.FlushBuffers.UserContext2))
|
||||||
{
|
{
|
||||||
ReleaseSRWLockExclusive(&FileSystem->OpGuardLock);
|
ReleaseSRWLockExclusive(&FileSystem->OpGuardLock);
|
||||||
}
|
}
|
||||||
@ -135,14 +140,27 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
UINT32 GrantedAccess;
|
UINT32 GrantedAccess;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CreateCheck consists of checking the parent directory for the
|
* CreateCheck does different checks depending on whether we are
|
||||||
* FILE_ADD_SUBDIRECTORY or FILE_ADD_FILE rights (depending on whether
|
* creating a new file/directory or a new stream.
|
||||||
* we are creating a file or directory).
|
*
|
||||||
|
* - CreateCheck for a new file consists of checking the parent directory
|
||||||
|
* for the FILE_ADD_SUBDIRECTORY or FILE_ADD_FILE rights (depending on
|
||||||
|
* whether we are creating a file or directory).
|
||||||
*
|
*
|
||||||
* If the access check succeeds and MAXIMUM_ALLOWED has been requested
|
* If the access check succeeds and MAXIMUM_ALLOWED has been requested
|
||||||
* then we go ahead and grant all access to the creator.
|
* then we go ahead and grant all access to the creator.
|
||||||
|
*
|
||||||
|
* - CreateCheck for a new stream consists of checking the main file for
|
||||||
|
* FILE_WRITE_DATA access, unless FILE_DELETE_ON_CLOSE is requested in
|
||||||
|
* which case we also check for DELETE access.
|
||||||
|
*
|
||||||
|
* If the access check succeeds and MAXIMUM_ALLOWED was not requested
|
||||||
|
* then we reset the DELETE and FILE_WRITE_DATA accesses based on whether
|
||||||
|
* they were actually requested in DesiredAccess.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (!Request->Req.Create.NamedStream)
|
||||||
|
{
|
||||||
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
|
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
|
||||||
(Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) ?
|
(Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) ?
|
||||||
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
|
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
|
||||||
@ -154,6 +172,26 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
|
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
|
||||||
FspGetFileGenericMapping()->GenericAll : Request->Req.Create.DesiredAccess;
|
FspGetFileGenericMapping()->GenericAll : Request->Req.Create.DesiredAccess;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*PSecurityDescriptor = 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))
|
||||||
|
{
|
||||||
|
*PGrantedAccess = GrantedAccess;
|
||||||
|
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
|
||||||
|
*PGrantedAccess &= ~(DELETE | FILE_WRITE_DATA) |
|
||||||
|
(Request->Req.Create.DesiredAccess & (DELETE | FILE_WRITE_DATA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -338,7 +376,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
Response->IoStatus.Information = FILE_CREATED;
|
Response->IoStatus.Information = FILE_CREATED;
|
||||||
Response->Rsp.Create.Opened.UserContext = (UINT_PTR)FileNode;
|
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
|
||||||
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
||||||
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -365,7 +403,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
Response->IoStatus.Information = FILE_OPENED;
|
Response->IoStatus.Information = FILE_OPENED;
|
||||||
Response->Rsp.Create.Opened.UserContext = (UINT_PTR)FileNode;
|
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
|
||||||
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
||||||
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -428,7 +466,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OPENED;
|
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OPENED;
|
||||||
Response->Rsp.Create.Opened.UserContext = (UINT_PTR)FileNode;
|
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
|
||||||
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
||||||
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -456,7 +494,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
Response->IoStatus.Information = Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
Response->IoStatus.Information = Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
||||||
Response->Rsp.Create.Opened.UserContext = (UINT_PTR)FileNode;
|
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
|
||||||
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
||||||
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -519,7 +557,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
|
|||||||
}
|
}
|
||||||
|
|
||||||
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OVERWRITTEN;
|
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OVERWRITTEN;
|
||||||
Response->Rsp.Create.Opened.UserContext = (UINT_PTR)FileNode;
|
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
|
||||||
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
||||||
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -558,7 +596,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
|
|||||||
}
|
}
|
||||||
|
|
||||||
Response->IoStatus.Information = Information;
|
Response->IoStatus.Information = Information;
|
||||||
Response->Rsp.Create.Opened.UserContext = (UINT_PTR)FileNode;
|
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
|
||||||
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
|
||||||
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -604,7 +642,7 @@ FSP_API NTSTATUS FspFileSystemOpOverwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
memset(&FileInfo, 0, sizeof FileInfo);
|
memset(&FileInfo, 0, sizeof FileInfo);
|
||||||
Result = FileSystem->Interface->Overwrite(FileSystem, Request,
|
Result = FileSystem->Interface->Overwrite(FileSystem, Request,
|
||||||
(PVOID)Request->Req.Overwrite.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.Overwrite),
|
||||||
Request->Req.Overwrite.FileAttributes,
|
Request->Req.Overwrite.FileAttributes,
|
||||||
Request->Req.Overwrite.Supersede,
|
Request->Req.Overwrite.Supersede,
|
||||||
&FileInfo);
|
&FileInfo);
|
||||||
@ -612,7 +650,7 @@ FSP_API NTSTATUS FspFileSystemOpOverwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
if (0 != FileSystem->Interface->Close)
|
if (0 != FileSystem->Interface->Close)
|
||||||
FileSystem->Interface->Close(FileSystem, Request,
|
FileSystem->Interface->Close(FileSystem, Request,
|
||||||
(PVOID)Request->Req.Overwrite.UserContext);
|
(PVOID)USERCONTEXT(Request->Req.Overwrite));
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +663,7 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
if (0 != FileSystem->Interface->Cleanup)
|
if (0 != FileSystem->Interface->Cleanup)
|
||||||
FileSystem->Interface->Cleanup(FileSystem, Request,
|
FileSystem->Interface->Cleanup(FileSystem, Request,
|
||||||
(PVOID)Request->Req.Cleanup.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.Cleanup),
|
||||||
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
||||||
0 != Request->Req.Cleanup.Delete);
|
0 != Request->Req.Cleanup.Delete);
|
||||||
|
|
||||||
@ -637,7 +675,7 @@ FSP_API NTSTATUS FspFileSystemOpClose(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
if (0 != FileSystem->Interface->Close)
|
if (0 != FileSystem->Interface->Close)
|
||||||
FileSystem->Interface->Close(FileSystem, Request,
|
FileSystem->Interface->Close(FileSystem, Request,
|
||||||
(PVOID)Request->Req.Close.UserContext);
|
(PVOID)USERCONTEXT(Request->Req.Close));
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -653,7 +691,7 @@ FSP_API NTSTATUS FspFileSystemOpRead(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
BytesTransferred = 0;
|
BytesTransferred = 0;
|
||||||
Result = FileSystem->Interface->Read(FileSystem, Request,
|
Result = FileSystem->Interface->Read(FileSystem, Request,
|
||||||
(PVOID)Request->Req.Read.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.Read),
|
||||||
(PVOID)Request->Req.Read.Address,
|
(PVOID)Request->Req.Read.Address,
|
||||||
Request->Req.Read.Offset,
|
Request->Req.Read.Offset,
|
||||||
Request->Req.Read.Length,
|
Request->Req.Read.Length,
|
||||||
@ -679,7 +717,7 @@ FSP_API NTSTATUS FspFileSystemOpWrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
BytesTransferred = 0;
|
BytesTransferred = 0;
|
||||||
Result = FileSystem->Interface->Write(FileSystem, Request,
|
Result = FileSystem->Interface->Write(FileSystem, Request,
|
||||||
(PVOID)Request->Req.Write.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.Write),
|
||||||
(PVOID)Request->Req.Write.Address,
|
(PVOID)Request->Req.Write.Address,
|
||||||
Request->Req.Write.Offset,
|
Request->Req.Write.Offset,
|
||||||
Request->Req.Write.Length,
|
Request->Req.Write.Length,
|
||||||
@ -706,7 +744,7 @@ FSP_API NTSTATUS FspFileSystemOpFlushBuffers(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS; /* liar! */
|
return STATUS_SUCCESS; /* liar! */
|
||||||
|
|
||||||
return FileSystem->Interface->Flush(FileSystem, Request,
|
return FileSystem->Interface->Flush(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FlushBuffers.UserContext);
|
(PVOID)USERCONTEXT(Request->Req.FlushBuffers));
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -720,7 +758,7 @@ FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
memset(&FileInfo, 0, sizeof FileInfo);
|
memset(&FileInfo, 0, sizeof FileInfo);
|
||||||
Result = FileSystem->Interface->GetFileInfo(FileSystem, Request,
|
Result = FileSystem->Interface->GetFileInfo(FileSystem, Request,
|
||||||
(PVOID)Request->Req.QueryInformation.UserContext, &FileInfo);
|
(PVOID)USERCONTEXT(Request->Req.QueryInformation), &FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
@ -741,7 +779,7 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
case 4/*FileBasicInformation*/:
|
case 4/*FileBasicInformation*/:
|
||||||
if (0 != FileSystem->Interface->SetBasicInfo)
|
if (0 != FileSystem->Interface->SetBasicInfo)
|
||||||
Result = FileSystem->Interface->SetBasicInfo(FileSystem, Request,
|
Result = FileSystem->Interface->SetBasicInfo(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetInformation.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.SetInformation),
|
||||||
Request->Req.SetInformation.Info.Basic.FileAttributes,
|
Request->Req.SetInformation.Info.Basic.FileAttributes,
|
||||||
Request->Req.SetInformation.Info.Basic.CreationTime,
|
Request->Req.SetInformation.Info.Basic.CreationTime,
|
||||||
Request->Req.SetInformation.Info.Basic.LastAccessTime,
|
Request->Req.SetInformation.Info.Basic.LastAccessTime,
|
||||||
@ -751,14 +789,14 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
case 19/*FileAllocationInformation*/:
|
case 19/*FileAllocationInformation*/:
|
||||||
if (0 != FileSystem->Interface->SetFileSize)
|
if (0 != FileSystem->Interface->SetFileSize)
|
||||||
Result = FileSystem->Interface->SetFileSize(FileSystem, Request,
|
Result = FileSystem->Interface->SetFileSize(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetInformation.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.SetInformation),
|
||||||
Request->Req.SetInformation.Info.Allocation.AllocationSize, TRUE,
|
Request->Req.SetInformation.Info.Allocation.AllocationSize, TRUE,
|
||||||
&FileInfo);
|
&FileInfo);
|
||||||
break;
|
break;
|
||||||
case 20/*FileEndOfFileInformation*/:
|
case 20/*FileEndOfFileInformation*/:
|
||||||
if (0 != FileSystem->Interface->SetFileSize)
|
if (0 != FileSystem->Interface->SetFileSize)
|
||||||
Result = FileSystem->Interface->SetFileSize(FileSystem, Request,
|
Result = FileSystem->Interface->SetFileSize(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetInformation.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.SetInformation),
|
||||||
Request->Req.SetInformation.Info.EndOfFile.FileSize, FALSE,
|
Request->Req.SetInformation.Info.EndOfFile.FileSize, FALSE,
|
||||||
&FileInfo);
|
&FileInfo);
|
||||||
break;
|
break;
|
||||||
@ -766,7 +804,7 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 != FileSystem->Interface->GetFileInfo)
|
if (0 != FileSystem->Interface->GetFileInfo)
|
||||||
{
|
{
|
||||||
Result = FileSystem->Interface->GetFileInfo(FileSystem, Request,
|
Result = FileSystem->Interface->GetFileInfo(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetInformation.UserContext, &FileInfo);
|
(PVOID)USERCONTEXT(Request->Req.SetInformation), &FileInfo);
|
||||||
if (NT_SUCCESS(Result) && 0 != (FileInfo.FileAttributes & FILE_ATTRIBUTE_READONLY))
|
if (NT_SUCCESS(Result) && 0 != (FileInfo.FileAttributes & FILE_ATTRIBUTE_READONLY))
|
||||||
{
|
{
|
||||||
Result = STATUS_CANNOT_DELETE;
|
Result = STATUS_CANNOT_DELETE;
|
||||||
@ -776,7 +814,7 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 != FileSystem->Interface->CanDelete)
|
if (0 != FileSystem->Interface->CanDelete)
|
||||||
if (Request->Req.SetInformation.Info.Disposition.Delete)
|
if (Request->Req.SetInformation.Info.Disposition.Delete)
|
||||||
Result = FileSystem->Interface->CanDelete(FileSystem, Request,
|
Result = FileSystem->Interface->CanDelete(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetInformation.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.SetInformation),
|
||||||
(PWSTR)Request->Buffer);
|
(PWSTR)Request->Buffer);
|
||||||
else
|
else
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -793,7 +831,7 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Result = FileSystem->Interface->Rename(FileSystem, Request,
|
Result = FileSystem->Interface->Rename(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetInformation.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.SetInformation),
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset),
|
(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset),
|
||||||
0 != Request->Req.SetInformation.Info.Rename.AccessToken);
|
0 != Request->Req.SetInformation.Info.Rename.AccessToken);
|
||||||
@ -862,7 +900,7 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
BytesTransferred = 0;
|
BytesTransferred = 0;
|
||||||
Result = FileSystem->Interface->ReadDirectory(FileSystem, Request,
|
Result = FileSystem->Interface->ReadDirectory(FileSystem, Request,
|
||||||
(PVOID)Request->Req.QueryDirectory.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.QueryDirectory),
|
||||||
(PVOID)Request->Req.QueryDirectory.Address,
|
(PVOID)Request->Req.QueryDirectory.Address,
|
||||||
Request->Req.QueryDirectory.Offset,
|
Request->Req.QueryDirectory.Offset,
|
||||||
Request->Req.QueryDirectory.Length,
|
Request->Req.QueryDirectory.Length,
|
||||||
@ -896,7 +934,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
Size = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
Size = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
||||||
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.FileSystemControl),
|
||||||
(PWSTR)Request->Buffer, ReparseData, &Size);
|
(PWSTR)Request->Buffer, ReparseData, &Size);
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
@ -913,7 +951,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
|
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
|
||||||
|
|
||||||
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.FileSystemControl),
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
ReparseData,
|
ReparseData,
|
||||||
Request->Req.FileSystemControl.Buffer.Size);
|
Request->Req.FileSystemControl.Buffer.Size);
|
||||||
@ -926,7 +964,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
|
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
|
||||||
|
|
||||||
Result = FileSystem->Interface->DeleteReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->DeleteReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.FileSystemControl),
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
ReparseData,
|
ReparseData,
|
||||||
Request->Req.FileSystemControl.Buffer.Size);
|
Request->Req.FileSystemControl.Buffer.Size);
|
||||||
@ -946,9 +984,9 @@ FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == FileSystem->Interface->GetSecurity)
|
if (0 == FileSystem->Interface->GetSecurity)
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
SecurityDescriptorSize = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof *Response;
|
SecurityDescriptorSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
||||||
Result = FileSystem->Interface->GetSecurity(FileSystem, Request,
|
Result = FileSystem->Interface->GetSecurity(FileSystem, Request,
|
||||||
(PVOID)Request->Req.QuerySecurity.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.QuerySecurity),
|
||||||
Response->Buffer, &SecurityDescriptorSize);
|
Response->Buffer, &SecurityDescriptorSize);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_INVALID_SECURITY_DESCR;
|
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_INVALID_SECURITY_DESCR;
|
||||||
@ -966,23 +1004,51 @@ FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
return FileSystem->Interface->SetSecurity(FileSystem, Request,
|
return FileSystem->Interface->SetSecurity(FileSystem, Request,
|
||||||
(PVOID)Request->Req.SetSecurity.UserContext,
|
(PVOID)USERCONTEXT(Request->Req.SetSecurity),
|
||||||
Request->Req.SetSecurity.SecurityInformation,
|
Request->Req.SetSecurity.SecurityInformation,
|
||||||
(PSECURITY_DESCRIPTOR)Request->Buffer);
|
(PSECURITY_DESCRIPTOR)Request->Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API BOOLEAN FspFileSystemAddDirInfo(FSP_FSCTL_DIR_INFO *DirInfo,
|
FSP_API NTSTATUS FspFileSystemOpQueryStreamInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
ULONG BytesTransferred;
|
||||||
|
|
||||||
|
if (0 == FileSystem->Interface->GetStreamInfo)
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
BytesTransferred = 0;
|
||||||
|
Result = FileSystem->Interface->GetStreamInfo(FileSystem, Request,
|
||||||
|
(PVOID)USERCONTEXT(Request->Req.QueryStreamInformation),
|
||||||
|
Response->Buffer,
|
||||||
|
FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX,
|
||||||
|
&BytesTransferred);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
Response->Size = (UINT16)(sizeof *Response + BytesTransferred);
|
||||||
|
Response->Rsp.QueryStreamInformation.Buffer.Offset = 0;
|
||||||
|
Response->Rsp.QueryStreamInformation.Buffer.Size = (UINT16)BytesTransferred;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(
|
||||||
|
sizeof(UINT16) == sizeof ((FSP_FSCTL_DIR_INFO *)0)->Size &&
|
||||||
|
sizeof(UINT16) == sizeof ((FSP_FSCTL_STREAM_INFO *)0)->Size,
|
||||||
|
"FSP_FSCTL_DIR_INFO::Size and FSP_FSCTL_STREAM_INFO::Size: sizeof must be 2.");
|
||||||
|
static BOOLEAN FspFileSystemAddXxxInfo(PVOID Info,
|
||||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
static UINT8 Zero[sizeof DirInfo->Size] = { 0 };
|
static UINT8 Zero[sizeof(UINT16)] = { 0 };
|
||||||
PVOID BufferEnd = (PUINT8)Buffer + Length;
|
PVOID BufferEnd = (PUINT8)Buffer + Length;
|
||||||
PVOID SrcBuffer;
|
PVOID SrcBuffer;
|
||||||
ULONG SrcLength, DstLength;
|
ULONG SrcLength, DstLength;
|
||||||
|
|
||||||
if (0 != DirInfo)
|
if (0 != Info)
|
||||||
{
|
{
|
||||||
SrcBuffer = DirInfo;
|
SrcBuffer = Info;
|
||||||
SrcLength = DirInfo->Size;
|
SrcLength = *(PUINT16)Info;
|
||||||
DstLength = FSP_FSCTL_DEFAULT_ALIGN_UP(SrcLength);
|
DstLength = FSP_FSCTL_DEFAULT_ALIGN_UP(SrcLength);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1002,6 +1068,12 @@ FSP_API BOOLEAN FspFileSystemAddDirInfo(FSP_FSCTL_DIR_INFO *DirInfo,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddDirInfo(FSP_FSCTL_DIR_INFO *DirInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
return FspFileSystemAddXxxInfo(DirInfo, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||||
NTSTATUS (*GetReparsePointByName)(
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||||
@ -1049,23 +1121,18 @@ FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||||
NTSTATUS (*GetReparsePointByName)(
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||||
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
||||||
PVOID Context,
|
PVOID Context,
|
||||||
|
PREPARSE_DATA_BUFFER ReparseData, SIZE_T ReparseDataSize0,
|
||||||
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent0,
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent0,
|
||||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
{
|
{
|
||||||
PREPARSE_DATA_BUFFER OutputReparseData;
|
PREPARSE_DATA_BUFFER OutputReparseData;
|
||||||
PWSTR TargetPath, RemainderPath, LastPathComponent, NewRemainderPath, ReparseTargetPath;
|
PWSTR TargetPath, RemainderPath, LastPathComponent, NewRemainderPath, ReparseTargetPath;
|
||||||
WCHAR RemainderChar;
|
WCHAR RemainderChar;
|
||||||
union
|
|
||||||
{
|
|
||||||
REPARSE_DATA_BUFFER V;
|
|
||||||
UINT8 B[FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX];
|
|
||||||
} ReparseDataBuf;
|
|
||||||
PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V;
|
|
||||||
SIZE_T ReparseDataSize, RemainderPathSize, ReparseTargetPathLength;
|
SIZE_T ReparseDataSize, RemainderPathSize, ReparseTargetPathLength;
|
||||||
BOOLEAN ResolveLastPathComponent;
|
BOOLEAN ResolveLastPathComponent;
|
||||||
ULONG MaxTries = 32;
|
ULONG MaxTries = 32;
|
||||||
@ -1149,7 +1216,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemainderChar = *RemainderPath; *RemainderPath = L'\0';
|
RemainderChar = *RemainderPath; *RemainderPath = L'\0';
|
||||||
ReparseDataSize = sizeof ReparseDataBuf;
|
ReparseDataSize = ReparseDataSize0;
|
||||||
Result = GetReparsePointByName(FileSystem, Context, TargetPath, '\0' != RemainderChar,
|
Result = GetReparsePointByName(FileSystem, Context, TargetPath, '\0' != RemainderChar,
|
||||||
ReparseData, &ReparseDataSize);
|
ReparseData, &ReparseDataSize);
|
||||||
*RemainderPath = RemainderChar;
|
*RemainderPath = RemainderChar;
|
||||||
@ -1238,6 +1305,32 @@ reparse_data_exit:
|
|||||||
return STATUS_REPARSE;
|
return STATUS_REPARSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||||
|
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
||||||
|
PVOID Context,
|
||||||
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent,
|
||||||
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
|
{
|
||||||
|
PREPARSE_DATA_BUFFER ReparseData;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ReparseData = MemAlloc(FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX);
|
||||||
|
if (0 == ReparseData)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
Result = FspFileSystemResolveReparsePointsInternal(FileSystem,
|
||||||
|
GetReparsePointByName, Context,
|
||||||
|
ReparseData, FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX,
|
||||||
|
FileName, ReparsePointIndex, ResolveLastPathComponent,
|
||||||
|
PIoStatus, Buffer, PSize);
|
||||||
|
|
||||||
|
MemFree(ReparseData);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
||||||
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
|
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
|
||||||
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize)
|
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize)
|
||||||
@ -1262,3 +1355,9 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
|||||||
else
|
else
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
return FspFileSystemAddXxxInfo(StreamInfo, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -41,7 +41,6 @@ struct fsp_fuse_core_opt_data
|
|||||||
rellinks;
|
rellinks;
|
||||||
int set_FileInfoTimeout;
|
int set_FileInfoTimeout;
|
||||||
int CaseInsensitiveSearch,
|
int CaseInsensitiveSearch,
|
||||||
NamedStreams,
|
|
||||||
ReadOnlyVolume;
|
ReadOnlyVolume;
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
};
|
};
|
||||||
@ -83,6 +82,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("rellinks", rellinks, 1),
|
FSP_FUSE_CORE_OPT("rellinks", rellinks, 1),
|
||||||
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
||||||
|
|
||||||
|
FUSE_OPT_KEY("fstypename=", 'F'),
|
||||||
|
|
||||||
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
||||||
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
||||||
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
||||||
@ -94,13 +95,14 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||||
FSP_FUSE_CORE_OPT("CaseInsensitiveSearch", CaseInsensitiveSearch, 1),
|
FSP_FUSE_CORE_OPT("CaseInsensitiveSearch", CaseInsensitiveSearch, 1),
|
||||||
FSP_FUSE_CORE_OPT("NamedStreams", NamedStreams, 1),
|
|
||||||
FSP_FUSE_CORE_OPT("ReadOnlyVolume", ReadOnlyVolume, 1),
|
FSP_FUSE_CORE_OPT("ReadOnlyVolume", ReadOnlyVolume, 1),
|
||||||
FUSE_OPT_KEY("ReparsePoints", FUSE_OPT_KEY_DISCARD),
|
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("HardLinks", FUSE_OPT_KEY_DISCARD),
|
||||||
FUSE_OPT_KEY("ExtendedAttributes", FUSE_OPT_KEY_DISCARD),
|
FUSE_OPT_KEY("ExtendedAttributes", FUSE_OPT_KEY_DISCARD),
|
||||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||||
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
||||||
|
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
||||||
|
|
||||||
FUSE_OPT_END,
|
FUSE_OPT_END,
|
||||||
};
|
};
|
||||||
@ -454,9 +456,9 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
" -o VolumeSerialNumber=N 32-bit wide\n"
|
" -o VolumeSerialNumber=N 32-bit wide\n"
|
||||||
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
||||||
" -o CaseInsensitiveSearch file system supports case-insensitive file names\n"
|
" -o CaseInsensitiveSearch file system supports case-insensitive file names\n"
|
||||||
//" -o NamedStreams file system supports named streams\n"
|
|
||||||
//" -o ReadOnlyVolume file system is read only\n"
|
//" -o ReadOnlyVolume file system is read only\n"
|
||||||
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n");
|
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
||||||
|
" --FileSystemName=FSN Name of user mode file system\n");
|
||||||
opt_data->help = 1;
|
opt_data->help = 1;
|
||||||
return 1;
|
return 1;
|
||||||
case 'V':
|
case 'V':
|
||||||
@ -473,6 +475,21 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||||
opt_data->VolumeParams.Prefix, sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR)))
|
opt_data->VolumeParams.Prefix, sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR)))
|
||||||
return -1;
|
return -1;
|
||||||
|
opt_data->VolumeParams.Prefix
|
||||||
|
[sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
return 0;
|
||||||
|
case 'F':
|
||||||
|
if ('f' == arg[0])
|
||||||
|
arg += sizeof "fstypename=" - 1;
|
||||||
|
else if ('F' == arg[2])
|
||||||
|
arg += sizeof "--FileSystemName=" - 1;
|
||||||
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||||
|
opt_data->VolumeParams.FileSystemName + 5,
|
||||||
|
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR)) - 5)
|
||||||
|
return -1;
|
||||||
|
opt_data->VolumeParams.FileSystemName
|
||||||
|
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -504,8 +521,12 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||||
opt_data.VolumeParams.ReparsePoints = TRUE;
|
opt_data.VolumeParams.ReparsePoints = TRUE;
|
||||||
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
||||||
opt_data.VolumeParams.NamedStreams = !!opt_data.NamedStreams;
|
opt_data.VolumeParams.NamedStreams = FALSE;
|
||||||
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
||||||
|
opt_data.VolumeParams.PostCleanupOnDeleteOnly = TRUE;
|
||||||
|
opt_data.VolumeParams.UmFileNodeIsUserContext2 = TRUE;
|
||||||
|
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||||
|
memcpy(opt_data.VolumeParams.FileSystemName, L"FUSE", 5 * sizeof(WCHAR));
|
||||||
|
|
||||||
f = fsp_fuse_obj_alloc(env, sizeof *f);
|
f = fsp_fuse_obj_alloc(env, sizeof *f);
|
||||||
if (0 == f)
|
if (0 == f)
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -32,7 +32,8 @@ VOID fsp_fuse_op_enter_lock(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
||||||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext) ||
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
|
0 == Request->Req.FlushBuffers.UserContext2) ||
|
||||||
/* FSCTL_SET_REPARSE_POINT manipulates namespace */
|
/* FSCTL_SET_REPARSE_POINT manipulates namespace */
|
||||||
(FspFsctlTransactFileSystemControlKind == Request->Kind &&
|
(FspFsctlTransactFileSystemControlKind == Request->Kind &&
|
||||||
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode))
|
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode))
|
||||||
@ -74,7 +75,8 @@ VOID fsp_fuse_op_leave_unlock(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
||||||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext) ||
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
|
0 == Request->Req.FlushBuffers.UserContext2) ||
|
||||||
/* FSCTL_SET_REPARSE_POINT manipulates namespace */
|
/* FSCTL_SET_REPARSE_POINT manipulates namespace */
|
||||||
(FspFsctlTransactFileSystemControlKind == Request->Kind &&
|
(FspFsctlTransactFileSystemControlKind == Request->Kind &&
|
||||||
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode))
|
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode))
|
||||||
@ -223,8 +225,6 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
context->gid = Gid;
|
context->gid = Gid;
|
||||||
|
|
||||||
contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context);
|
contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context);
|
||||||
contexthdr->Request = Request;
|
|
||||||
contexthdr->Response = Response;
|
|
||||||
contexthdr->PosixPath = PosixPath;
|
contexthdr->PosixPath = PosixPath;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -876,7 +876,7 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
*PFileNode = 0;
|
*PFileNode = filedesc;
|
||||||
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
||||||
|
|
||||||
filedesc->PosixPath = contexthdr->PosixPath;
|
filedesc->PosixPath = contexthdr->PosixPath;
|
||||||
@ -887,7 +887,6 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
filedesc->DirBufferSize = 0;
|
filedesc->DirBufferSize = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc;
|
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
@ -996,7 +995,7 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
* Ignore fuse_file_info::nonseekable.
|
* Ignore fuse_file_info::nonseekable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*PFileNode = 0;
|
*PFileNode = filedesc;
|
||||||
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
||||||
|
|
||||||
filedesc->PosixPath = contexthdr->PosixPath;
|
filedesc->PosixPath = contexthdr->PosixPath;
|
||||||
@ -1007,7 +1006,6 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
filedesc->DirBufferSize = 0;
|
filedesc->DirBufferSize = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc;
|
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
@ -1024,8 +1022,7 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.Overwrite.UserContext2;
|
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
int err;
|
int err;
|
||||||
@ -1062,8 +1059,7 @@ static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
|
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.Cleanup.UserContext2;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In Windows a DeleteFile/RemoveDirectory is the sequence of the following:
|
* In Windows a DeleteFile/RemoveDirectory is the sequence of the following:
|
||||||
@ -1100,8 +1096,7 @@ static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PVOID FileNode)
|
PVOID FileNode)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.Close.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
|
|
||||||
memset(&fi, 0, sizeof fi);
|
memset(&fi, 0, sizeof fi);
|
||||||
@ -1136,8 +1131,7 @@ static NTSTATUS fsp_fuse_intf_Read(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PULONG PBytesTransferred)
|
PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.Read.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
int bytes;
|
int bytes;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -1173,8 +1167,7 @@ static NTSTATUS fsp_fuse_intf_Write(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo)
|
PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.Write.UserContext2;
|
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||||
@ -1235,8 +1228,7 @@ static NTSTATUS fsp_fuse_intf_Flush(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PVOID FileNode)
|
PVOID FileNode)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.FlushBuffers.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
int err;
|
int err;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -1277,8 +1269,7 @@ static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.QueryInformation.UserContext2;
|
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
|
|
||||||
@ -1297,8 +1288,7 @@ static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.SetInformation.UserContext2;
|
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||||
@ -1376,8 +1366,7 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.SetInformation.UserContext2;
|
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||||
@ -1460,8 +1449,7 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PVOID FileNode, PWSTR FileName)
|
PVOID FileNode, PWSTR FileName)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.SetInformation.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
struct fuse_dirhandle dh;
|
struct fuse_dirhandle dh;
|
||||||
int err;
|
int err;
|
||||||
@ -1500,8 +1488,7 @@ static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context);
|
struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context);
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.SetInformation.UserContext2;
|
|
||||||
int err;
|
int err;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
@ -1531,8 +1518,7 @@ static NTSTATUS fsp_fuse_intf_GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PSECURITY_DESCRIPTOR SecurityDescriptorBuf, SIZE_T *PSecurityDescriptorSize)
|
PSECURITY_DESCRIPTOR SecurityDescriptorBuf, SIZE_T *PSecurityDescriptorSize)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.QuerySecurity.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
UINT32 FileAttributes;
|
UINT32 FileAttributes;
|
||||||
|
|
||||||
@ -1550,8 +1536,7 @@ static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR Ignored)
|
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR Ignored)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.SetSecurity.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
UINT32 Uid, Gid, Mode, NewUid, NewGid, NewMode;
|
UINT32 Uid, Gid, Mode, NewUid, NewGid, NewMode;
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
@ -1684,8 +1669,7 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PULONG PBytesTransferred)
|
PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.QueryDirectory.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
struct fuse_dirhandle dh;
|
struct fuse_dirhandle dh;
|
||||||
struct fsp_fuse_dirinfo *di;
|
struct fsp_fuse_dirinfo *di;
|
||||||
@ -1891,8 +1875,7 @@ static NTSTATUS fsp_fuse_intf_GetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PVOID FileNode,
|
PVOID FileNode,
|
||||||
PWSTR FileName, PVOID Buffer, PSIZE_T PSize)
|
PWSTR FileName, PVOID Buffer, PSIZE_T PSize)
|
||||||
{
|
{
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.FileSystemControl.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
|
|
||||||
memset(&fi, 0, sizeof fi);
|
memset(&fi, 0, sizeof fi);
|
||||||
@ -1909,8 +1892,7 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fuse_context *context = fsp_fuse_get_context(f->env);
|
struct fuse_context *context = fsp_fuse_get_context(f->env);
|
||||||
struct fsp_fuse_file_desc *filedesc =
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
(PVOID)(UINT_PTR)Request->Req.FileSystemControl.UserContext2;
|
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
UINT32 Uid, Gid, Mode, Dev;
|
UINT32 Uid, Gid, Mode, Dev;
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -51,8 +51,6 @@ struct fuse
|
|||||||
|
|
||||||
struct fsp_fuse_context_header
|
struct fsp_fuse_context_header
|
||||||
{
|
{
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response;
|
|
||||||
char *PosixPath;
|
char *PosixPath;
|
||||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ContextBuf[];
|
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ContextBuf[];
|
||||||
};
|
};
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -63,10 +63,21 @@ static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
|||||||
|
|
||||||
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentOrMain, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess,
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
||||||
{
|
{
|
||||||
|
BOOLEAN CheckParentDirectory, CheckMainFile;
|
||||||
|
|
||||||
|
CheckParentDirectory = CheckMainFile = FALSE;
|
||||||
|
if (CheckParentOrMain)
|
||||||
|
{
|
||||||
|
if (!Request->Req.Create.NamedStream)
|
||||||
|
CheckParentDirectory = TRUE;
|
||||||
|
else
|
||||||
|
CheckMainFile = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
*PGrantedAccess = 0;
|
*PGrantedAccess = 0;
|
||||||
if (0 != PSecurityDescriptor)
|
if (0 != PSecurityDescriptor)
|
||||||
*PSecurityDescriptor = 0;
|
*PSecurityDescriptor = 0;
|
||||||
@ -96,10 +107,16 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PPRIVILEGE_SET PrivilegeSet = (PVOID)PrivilegeSetBuf;
|
PPRIVILEGE_SET PrivilegeSet = (PVOID)PrivilegeSetBuf;
|
||||||
DWORD PrivilegeSetLength = sizeof PrivilegeSetBuf;
|
DWORD PrivilegeSetLength = sizeof PrivilegeSetBuf;
|
||||||
UINT32 TraverseAccess, ParentAccess, DesiredAccess2;
|
UINT32 TraverseAccess, ParentAccess, DesiredAccess2;
|
||||||
|
UINT16 NamedStreamSave;
|
||||||
BOOL AccessStatus;
|
BOOL AccessStatus;
|
||||||
|
|
||||||
if (CheckParentDirectory)
|
if (CheckParentDirectory)
|
||||||
FspPathSuffix((PWSTR)Request->Buffer, &FileName, &Suffix, Root);
|
FspPathSuffix((PWSTR)Request->Buffer, &FileName, &Suffix, Root);
|
||||||
|
else if (CheckMainFile)
|
||||||
|
{
|
||||||
|
((PWSTR)Request->Buffer)[Request->Req.Create.NamedStream / sizeof(WCHAR)] = L'\0';
|
||||||
|
FileName = (PWSTR)Request->Buffer;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
FileName = (PWSTR)Request->Buffer;
|
FileName = (PWSTR)Request->Buffer;
|
||||||
|
|
||||||
@ -212,6 +229,8 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
0 == ((MAXIMUM_ALLOWED | DELETE | FILE_READ_ATTRIBUTES) & DesiredAccess))
|
0 == ((MAXIMUM_ALLOWED | DELETE | FILE_READ_ATTRIBUTES) & DesiredAccess))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
NamedStreamSave = Request->Req.Create.NamedStream;
|
||||||
|
Request->Req.Create.NamedStream = 0;
|
||||||
Result = FspAccessCheck(FileSystem, Request, TRUE, FALSE,
|
Result = FspAccessCheck(FileSystem, Request, TRUE, FALSE,
|
||||||
(MAXIMUM_ALLOWED & DesiredAccess) ? (FILE_DELETE_CHILD | FILE_LIST_DIRECTORY) :
|
(MAXIMUM_ALLOWED & DesiredAccess) ? (FILE_DELETE_CHILD | FILE_LIST_DIRECTORY) :
|
||||||
(
|
(
|
||||||
@ -219,6 +238,7 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
((FILE_READ_ATTRIBUTES & DesiredAccess) ? FILE_LIST_DIRECTORY : 0)
|
((FILE_READ_ATTRIBUTES & DesiredAccess) ? FILE_LIST_DIRECTORY : 0)
|
||||||
),
|
),
|
||||||
&ParentAccess);
|
&ParentAccess);
|
||||||
|
Request->Req.Create.NamedStream = NamedStreamSave;
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
/* any failure just becomes ACCESS DENIED at this point */
|
/* any failure just becomes ACCESS DENIED at this point */
|
||||||
@ -269,6 +289,20 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (CheckMainFile)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We check to see if this is a reparse point and FILE_OPEN_REPARSE_POINT
|
||||||
|
* was not specified, in which case we return STATUS_REPARSE.
|
||||||
|
*/
|
||||||
|
if (0 != (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||||
|
0 == (Request->Req.Create.CreateOptions & FILE_OPEN_REPARSE_POINT))
|
||||||
|
{
|
||||||
|
FileAttributes = FspPathSuffixIndex(FileName);
|
||||||
|
Result = STATUS_REPARSE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -344,6 +378,8 @@ exit:
|
|||||||
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
||||||
Result = STATUS_OBJECT_PATH_NOT_FOUND;
|
Result = STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
else if (CheckMainFile)
|
||||||
|
((PWSTR)Request->Buffer)[Request->Req.Create.NamedStream / sizeof(WCHAR)] = L':';
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -358,6 +394,10 @@ FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (FspFsctlTransactCreateKind != Request->Kind)
|
if (FspFsctlTransactCreateKind != Request->Kind)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/* stream support: return NULL security descriptor when creating named stream */
|
||||||
|
if (Request->Req.Create.NamedStream)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
if (!CreatePrivateObjectSecurity(
|
if (!CreatePrivateObjectSecurity(
|
||||||
ParentDescriptor,
|
ParentDescriptor,
|
||||||
0 != Request->Req.Create.SecurityDescriptor.Offset ?
|
0 != Request->Req.Create.SecurityDescriptor.Offset ?
|
||||||
@ -438,6 +478,10 @@ FSP_API NTSTATUS FspSetSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
|
FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
NTSTATUS (*CreateFunc)())
|
NTSTATUS (*CreateFunc)())
|
||||||
{
|
{
|
||||||
|
/* stream support: allow NULL security descriptors */
|
||||||
|
if (0 == SecurityDescriptor)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc ||
|
if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc ||
|
||||||
(NTSTATUS (*)())FspPosixMapPermissionsToSecurityDescriptor == CreateFunc)
|
(NTSTATUS (*)())FspPosixMapPermissionsToSecurityDescriptor == CreateFunc)
|
||||||
MemFree(SecurityDescriptor);
|
MemFree(SecurityDescriptor);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -26,11 +26,10 @@
|
|||||||
* - "C/C++ > Code Generation > Basic Runtime Checks" must be set to "Default"
|
* - "C/C++ > Code Generation > Basic Runtime Checks" must be set to "Default"
|
||||||
* - "C/C++ > Code Generation > Runtime Library" must be set to "Multi-threaded (/MT)".
|
* - "C/C++ > Code Generation > Runtime Library" must be set to "Multi-threaded (/MT)".
|
||||||
* - "C/C++ > Code Generation > Security Check" must be disabled (/GS-).
|
* - "C/C++ > Code Generation > Security Check" must be disabled (/GS-).
|
||||||
* - "C/C++ > Command Line > Additional Options" add "/Gs16384" to disable __chkstk probes.
|
|
||||||
* - "Linker > Input > Ignore All Default Libraries" must be "Yes".
|
* - "Linker > Input > Ignore All Default Libraries" must be "Yes".
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Update:
|
* Update 1:
|
||||||
*
|
*
|
||||||
* It is possible to have the "Linker > Input > Ignore All Default Libraries"
|
* It is possible to have the "Linker > Input > Ignore All Default Libraries"
|
||||||
* setting to "No" and still eliminate most dependencies on the MSVCRT libraries.
|
* setting to "No" and still eliminate most dependencies on the MSVCRT libraries.
|
||||||
@ -44,6 +43,22 @@
|
|||||||
* that are not required (or worse create a half-baked CRT). For example, the WinFsp
|
* that are not required (or worse create a half-baked CRT). For example, the WinFsp
|
||||||
* DLL ensures this by setting the "Linker > Input > Ignore All Default Libraries"
|
* DLL ensures this by setting the "Linker > Input > Ignore All Default Libraries"
|
||||||
* to "Yes" on 64-bit builds and "No" on 32-bit builds.
|
* to "Yes" on 64-bit builds and "No" on 32-bit builds.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Update 2:
|
||||||
|
*
|
||||||
|
* Using the /Gs[size] compiler option with a large size is a very bad idea.
|
||||||
|
* Turns out that the compiler uses the _chkstk call to ensure that enough
|
||||||
|
* stack space has been committed even when a function accesses locations in
|
||||||
|
* the stack below the guard page.
|
||||||
|
*
|
||||||
|
* The following links explain the problem very well:
|
||||||
|
* - http://stackoverflow.com/questions/8400118/what-is-the-purpose-of-the-chkstk-function#8400171
|
||||||
|
* - https://support.microsoft.com/en-us/kb/100775
|
||||||
|
*
|
||||||
|
* A library/program that does not wish to use the MSVCRT libraries (and hence
|
||||||
|
* does not have _chkstk available) must take care to not use more than a page
|
||||||
|
* (4096 bytes) of stack within a single function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef RtlFillMemory
|
#undef RtlFillMemory
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -116,7 +116,9 @@ NTSTATUS FspAcquireForModWrite(
|
|||||||
Success = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, FALSE);
|
Success = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, FALSE);
|
||||||
if (Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
*ResourceToRelease = FileNode->Header.PagingIoResource;
|
*ResourceToRelease = 0 == FileNode->MainFileNode ?
|
||||||
|
FileNode->Header.PagingIoResource :
|
||||||
|
FileNode->MainFileNode->Header.PagingIoResource;
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -72,6 +72,7 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
@ -87,9 +88,6 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
/* if this is a directory inform the FSRTL Notify mechanism */
|
/* if this is a directory inform the FSRTL Notify mechanism */
|
||||||
if (FileNode->IsDirectory)
|
if (FileNode->IsDirectory)
|
||||||
{
|
{
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
|
||||||
FspFsvolDeviceExtension(FsvolDeviceObject);
|
|
||||||
|
|
||||||
if (DeletePending)
|
if (DeletePending)
|
||||||
FspNotifyDeletePending(
|
FspNotifyDeletePending(
|
||||||
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
||||||
@ -114,14 +112,22 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||||
|
|
||||||
return FSP_STATUS_IOQ_POST_BEST_EFFORT;
|
if (DeletePending || !FsvolDeviceExtension->VolumeParams.PostCleanupOnDeleteOnly)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that it is still possible for this request to not be delivered,
|
* 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
|
* if the volume device Ioq is stopped. But such failures are benign
|
||||||
* from our perspective, because they mean that the file system is going
|
* from our perspective, because they mean that the file system is going
|
||||||
* away and should correctly tear things down.
|
* away and should correctly tear things down.
|
||||||
*/
|
*/
|
||||||
|
return FSP_STATUS_IOQ_POST_BEST_EFFORT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 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! */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolCleanupComplete(
|
NTSTATUS FspFsvolCleanupComplete(
|
||||||
@ -161,12 +167,21 @@ static VOID FspFsvolCleanupRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Co
|
|||||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
HANDLE MainFileHandle;
|
||||||
|
|
||||||
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
FspFileNodeReleaseOwner(FileNode, Pgio, Request);
|
FspFileNodeReleaseOwner(FileNode, Pgio, Request);
|
||||||
|
|
||||||
FspFileNodeCleanupComplete(FileNode, FileObject);
|
FspFileNodeCleanupComplete(FileNode, FileObject);
|
||||||
|
|
||||||
|
MainFileHandle = FileDesc->MainFileHandle;
|
||||||
|
FileDesc->MainFileHandle = 0;
|
||||||
|
|
||||||
FspFileNodeReleaseOwner(FileNode, Main, Request);
|
FspFileNodeReleaseOwner(FileNode, Main, Request);
|
||||||
|
|
||||||
|
FspMainFileClose(MainFileHandle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspCleanup(
|
NTSTATUS FspCleanup(
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -77,7 +77,7 @@ static NTSTATUS FspFsvolClose(
|
|||||||
FspFileNodeClose(FileNode, FileObject);
|
FspFileNodeClose(FileNode, FileObject);
|
||||||
|
|
||||||
/* delete the FileDesc and deref the FileNode; order is important (FileDesc has FileNode ref) */
|
/* delete the FileDesc and deref the FileNode; order is important (FileDesc has FileNode ref) */
|
||||||
FspFileDescDelete(FileDesc);
|
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
||||||
FspFileNodeDereference(FileNode);
|
FspFileNodeDereference(FileNode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
155
src/sys/create.c
155
src/sys/create.c
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -24,7 +24,8 @@ static NTSTATUS FspFsvrtCreate(
|
|||||||
static NTSTATUS FspFsvolCreate(
|
static NTSTATUS FspFsvolCreate(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolCreateNoLock(
|
static NTSTATUS FspFsvolCreateNoLock(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
BOOLEAN MainFileOpen);
|
||||||
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
|
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
|
||||||
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
|
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
|
||||||
@ -109,23 +110,30 @@ static NTSTATUS FspFsvolCreate(
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result = STATUS_SUCCESS;
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
|
BOOLEAN MainFileOpen = FspMainFileOpenCheck(Irp);
|
||||||
|
|
||||||
|
if (!MainFileOpen)
|
||||||
|
{
|
||||||
FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject);
|
FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp);
|
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp, FALSE);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (FSP_STATUS_IOQ_POST != Result)
|
if (FSP_STATUS_IOQ_POST != Result)
|
||||||
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
|
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp, TRUE);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolCreateNoLock(
|
static NTSTATUS FspFsvolCreateNoLock(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
BOOLEAN MainFileOpen)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
@ -162,10 +170,16 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
ULONG Flags = IrpSp->Flags;
|
ULONG Flags = IrpSp->Flags;
|
||||||
KPROCESSOR_MODE RequestorMode =
|
KPROCESSOR_MODE RequestorMode =
|
||||||
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
||||||
|
BOOLEAN CaseSensitiveRequested =
|
||||||
|
BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
|
||||||
|
BOOLEAN CaseSensitive =
|
||||||
|
CaseSensitiveRequested || FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch;
|
||||||
BOOLEAN HasTraversePrivilege =
|
BOOLEAN HasTraversePrivilege =
|
||||||
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE);
|
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE);
|
||||||
FSP_FILE_NODE *FileNode, *RelatedFileNode;
|
FSP_FILE_NODE *FileNode, *RelatedFileNode;
|
||||||
FSP_FILE_DESC *FileDesc;
|
FSP_FILE_DESC *FileDesc;
|
||||||
|
UNICODE_STRING MainFileName = { 0 }, StreamPart = { 0 };
|
||||||
|
ULONG StreamType = FspUnicodePathStreamTypeNone;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
|
||||||
/* cannot open files by fileid */
|
/* cannot open files by fileid */
|
||||||
@ -210,10 +224,6 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
FileName.Buffer++;
|
FileName.Buffer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check filename validity */
|
|
||||||
if (!FspUnicodePathIsValid(&FileName, 0 != FsvolDeviceExtension->VolumeParams.NamedStreams))
|
|
||||||
return STATUS_OBJECT_NAME_INVALID;
|
|
||||||
|
|
||||||
/* is this a relative or absolute open? */
|
/* is this a relative or absolute open? */
|
||||||
if (0 != RelatedFileObject)
|
if (0 != RelatedFileObject)
|
||||||
{
|
{
|
||||||
@ -265,6 +275,28 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
Result = RtlAppendUnicodeStringToString(&FileNode->FileName, &FileName);
|
Result = RtlAppendUnicodeStringToString(&FileNode->FileName, &FileName);
|
||||||
ASSERT(NT_SUCCESS(Result));
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
|
/* check filename validity */
|
||||||
|
if (!FspUnicodePathIsValid(&FileNode->FileName,
|
||||||
|
FsvolDeviceExtension->VolumeParams.NamedStreams ? &StreamPart : 0,
|
||||||
|
&StreamType))
|
||||||
|
{
|
||||||
|
FspFileNodeDereference(FileNode);
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we have a stream part (even non-empty), ensure that FileNode->FileName has single colon */
|
||||||
|
if (0 != StreamPart.Buffer)
|
||||||
|
{
|
||||||
|
ASSERT(
|
||||||
|
(PUINT8)FileNode->FileName.Buffer + sizeof(WCHAR) <= (PUINT8)StreamPart.Buffer &&
|
||||||
|
(PUINT8)StreamPart.Buffer + StreamPart.Length <=
|
||||||
|
(PUINT8)FileNode->FileName.Buffer + FileNode->FileName.Length);
|
||||||
|
|
||||||
|
FileNode->FileName.Length = (USHORT)
|
||||||
|
((PUINT8)StreamPart.Buffer - (PUINT8)FileNode->FileName.Buffer + StreamPart.Length -
|
||||||
|
(0 == StreamPart.Length) * sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
/* check and remove any volume prefix */
|
/* check and remove any volume prefix */
|
||||||
if (0 == RelatedFileObject && 0 < FsvolDeviceExtension->VolumePrefix.Length)
|
if (0 == RelatedFileObject && 0 < FsvolDeviceExtension->VolumePrefix.Length)
|
||||||
{
|
{
|
||||||
@ -301,6 +333,16 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
FileNode->FileName.Length -= sizeof(WCHAR);
|
FileNode->FileName.Length -= sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if a $DATA stream type, this cannot be a directory */
|
||||||
|
if (FspUnicodePathStreamTypeData == StreamType)
|
||||||
|
{
|
||||||
|
if (FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
|
||||||
|
{
|
||||||
|
FspFileNodeDereference(FileNode);
|
||||||
|
return STATUS_NOT_A_DIRECTORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* not all operations allowed on the root directory */
|
/* not all operations allowed on the root directory */
|
||||||
if (sizeof(WCHAR) == FileNode->FileName.Length &&
|
if (sizeof(WCHAR) == FileNode->FileName.Length &&
|
||||||
(FILE_CREATE == CreateDisposition ||
|
(FILE_CREATE == CreateDisposition ||
|
||||||
@ -328,6 +370,71 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fix FileAttributes */
|
||||||
|
ClearFlag(FileAttributes,
|
||||||
|
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
|
||||||
|
if (CreateOptions & FILE_DIRECTORY_FILE)
|
||||||
|
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
|
/* if we have a non-empty stream part, open the main file */
|
||||||
|
if (0 != StreamPart.Length)
|
||||||
|
{
|
||||||
|
/* named streams can never be directories (even when attached to directories) */
|
||||||
|
if (FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
|
||||||
|
{
|
||||||
|
Result = STATUS_NOT_A_DIRECTORY;
|
||||||
|
goto main_stream_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cannot open target directory of a named stream */
|
||||||
|
if (FlagOn(Flags, SL_OPEN_TARGET_DIRECTORY))
|
||||||
|
{
|
||||||
|
Result = STATUS_OBJECT_NAME_INVALID;
|
||||||
|
goto main_stream_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainFileName.Length = MainFileName.MaximumLength = (USHORT)
|
||||||
|
((PUINT8)StreamPart.Buffer - (PUINT8)FileNode->FileName.Buffer - sizeof(WCHAR));
|
||||||
|
MainFileName.Buffer = FileNode->FileName.Buffer;
|
||||||
|
|
||||||
|
Result = FspMainFileOpen(
|
||||||
|
FsvolDeviceObject,
|
||||||
|
FileObject->DeviceObject, /* use as device hint when using MUP */
|
||||||
|
&MainFileName, CaseSensitive,
|
||||||
|
SecurityDescriptor,
|
||||||
|
FileAttributes,
|
||||||
|
CreateDisposition,
|
||||||
|
&FileDesc->MainFileHandle,
|
||||||
|
&FileDesc->MainFileObject);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto main_stream_exit;
|
||||||
|
|
||||||
|
/* check that the main file is one we recognize */
|
||||||
|
if (!FspFileNodeIsValid(FileDesc->MainFileObject->FsContext))
|
||||||
|
{
|
||||||
|
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto main_stream_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cannot set security descriptor or file attributes on named stream */
|
||||||
|
SecurityDescriptor = 0;
|
||||||
|
SecurityDescriptorSize = 0;
|
||||||
|
FileAttributes = 0;
|
||||||
|
|
||||||
|
/* remember the main file node */
|
||||||
|
FileNode->MainFileNode = FileDesc->MainFileObject->FsContext;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
main_stream_exit:
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileDescDelete(FileDesc);
|
||||||
|
FspFileNodeDereference(FileNode);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* create the user-mode file system request */
|
/* create the user-mode file system request */
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, SecurityDescriptorSize,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, SecurityDescriptorSize,
|
||||||
FspFsvolCreateRequestFini, &Request);
|
FspFsvolCreateRequestFini, &Request);
|
||||||
@ -338,24 +445,19 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fix FileAttributes */
|
|
||||||
ClearFlag(FileAttributes,
|
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
|
|
||||||
if (CreateOptions & FILE_DIRECTORY_FILE)
|
|
||||||
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The new request is associated with our IRP. Go ahead and associate our FileNode/FileDesc
|
* The new request is associated with our IRP. Go ahead and associate our FileNode/FileDesc
|
||||||
* with the Request as well. After this is done completing our IRP will automatically
|
* with the Request as well. After this is done completing our IRP will automatically
|
||||||
* delete the Request and any associated resources.
|
* delete the Request and any associated resources.
|
||||||
*/
|
*/
|
||||||
FileDesc->FileNode = FileNode;
|
FileDesc->FileNode = FileNode;
|
||||||
FileDesc->CaseSensitive =
|
FileDesc->CaseSensitive = CaseSensitive;
|
||||||
0 != FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch ||
|
|
||||||
BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
|
|
||||||
FileDesc->HasTraversePrivilege = HasTraversePrivilege;
|
FileDesc->HasTraversePrivilege = HasTraversePrivilege;
|
||||||
|
if (!MainFileOpen)
|
||||||
|
{
|
||||||
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
||||||
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
||||||
|
}
|
||||||
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
||||||
|
|
||||||
/* populate the Create request */
|
/* populate the Create request */
|
||||||
@ -374,7 +476,12 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
||||||
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
||||||
Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
|
Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
|
||||||
Request->Req.Create.CaseSensitive = BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
|
Request->Req.Create.CaseSensitive = CaseSensitiveRequested;
|
||||||
|
Request->Req.Create.NamedStream = MainFileName.Length;
|
||||||
|
|
||||||
|
ASSERT(
|
||||||
|
0 == StreamPart.Length && 0 == MainFileName.Length ||
|
||||||
|
0 != StreamPart.Length && 0 != MainFileName.Length);
|
||||||
|
|
||||||
/* copy the security descriptor (if any) into the request */
|
/* copy the security descriptor (if any) into the request */
|
||||||
if (0 != SecurityDescriptorSize)
|
if (0 != SecurityDescriptorSize)
|
||||||
@ -724,6 +831,8 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
if (FileNode->IsDirectory)
|
if (FileNode->IsDirectory)
|
||||||
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
|
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
|
PVOID RequestDeviceObjectValue = FspIopRequestContext(Request, RequestDeviceObject);
|
||||||
|
|
||||||
/* disassociate the FileDesc momentarily from the Request */
|
/* disassociate the FileDesc momentarily from the Request */
|
||||||
FspIopRequestContext(Request, RequestDeviceObject) = 0;
|
FspIopRequestContext(Request, RequestDeviceObject) = 0;
|
||||||
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
||||||
@ -732,7 +841,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
Request->Kind = FspFsctlTransactOverwriteKind;
|
Request->Kind = FspFsctlTransactOverwriteKind;
|
||||||
RtlZeroMemory(&Request->Req.Create, sizeof Request->Req.Create);
|
RtlZeroMemory(&Request->Req.Create, sizeof Request->Req.Create);
|
||||||
FspIopResetRequest(Request, FspFsvolCreateOverwriteRequestFini);
|
FspIopResetRequest(Request, FspFsvolCreateOverwriteRequestFini);
|
||||||
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
FspIopRequestContext(Request, RequestDeviceObject) = RequestDeviceObjectValue;
|
||||||
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
||||||
FspIopRequestContext(Request, RequestFileObject) = FileObject;
|
FspIopRequestContext(Request, RequestFileObject) = FileObject;
|
||||||
FspIopRequestContext(Request, RequestState) = (PVOID)RequestPending;
|
FspIopRequestContext(Request, RequestState) = (PVOID)RequestPending;
|
||||||
@ -815,7 +924,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
|
|||||||
|
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT FsvolDeviceObject = FspIopRequestContext(Request, RequestDeviceObject);
|
PVOID RequestDeviceObjectValue = FspIopRequestContext(Request, RequestDeviceObject);
|
||||||
|
|
||||||
/* disassociate the FileDesc momentarily from the Request */
|
/* disassociate the FileDesc momentarily from the Request */
|
||||||
Request = FspIrpRequest(Irp);
|
Request = FspIrpRequest(Irp);
|
||||||
@ -825,7 +934,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
|
|||||||
/* reset the Request and reassociate the FileDesc and FileObject with it */
|
/* reset the Request and reassociate the FileDesc and FileObject with it */
|
||||||
Request->Kind = FspFsctlTransactReservedKind;
|
Request->Kind = FspFsctlTransactReservedKind;
|
||||||
FspIopResetRequest(Request, FspFsvolCreateTryOpenRequestFini);
|
FspIopResetRequest(Request, FspFsvolCreateTryOpenRequestFini);
|
||||||
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
FspIopRequestContext(Request, RequestDeviceObject) = RequestDeviceObjectValue;
|
||||||
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
||||||
FspIopRequestContext(Request, RequestFileObject) = FileObject;
|
FspIopRequestContext(Request, RequestFileObject) = FileObject;
|
||||||
FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)FlushImage;
|
FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)FlushImage;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -295,7 +295,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||||
LARGE_INTEGER IrpTimeout;
|
LARGE_INTEGER IrpTimeout;
|
||||||
LARGE_INTEGER SecurityTimeout, DirInfoTimeout;
|
LARGE_INTEGER SecurityTimeout, DirInfoTimeout, StreamInfoTimeout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Volume device initialization is a mess, because of the different ways of
|
* Volume device initialization is a mess, because of the different ways of
|
||||||
@ -347,6 +347,16 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
return Result;
|
return Result;
|
||||||
FsvolDeviceExtension->InitDoneDir = 1;
|
FsvolDeviceExtension->InitDoneDir = 1;
|
||||||
|
|
||||||
|
/* create our stream info meta cache */
|
||||||
|
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||||
|
/* convert millis to nanos */
|
||||||
|
Result = FspMetaCacheCreate(
|
||||||
|
FspFsvolDeviceStreamInfoCacheCapacity, FspFsvolDeviceStreamInfoCacheItemSizeMax, &StreamInfoTimeout,
|
||||||
|
&FsvolDeviceExtension->StreamInfoCache);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
FsvolDeviceExtension->InitDoneStrm = 1;
|
||||||
|
|
||||||
/* initialize the FSRTL Notify mechanism */
|
/* initialize the FSRTL Notify mechanism */
|
||||||
Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync);
|
Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -406,6 +416,10 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
|||||||
FspNotifyUninitializeSync(&FsvolDeviceExtension->NotifySync);
|
FspNotifyUninitializeSync(&FsvolDeviceExtension->NotifySync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* delete the stream info meta cache */
|
||||||
|
if (FsvolDeviceExtension->InitDoneStrm)
|
||||||
|
FspMetaCacheDelete(FsvolDeviceExtension->StreamInfoCache);
|
||||||
|
|
||||||
/* delete the directory meta cache */
|
/* delete the directory meta cache */
|
||||||
if (FsvolDeviceExtension->InitDoneDir)
|
if (FsvolDeviceExtension->InitDoneDir)
|
||||||
FspMetaCacheDelete(FsvolDeviceExtension->DirInfoCache);
|
FspMetaCacheDelete(FsvolDeviceExtension->DirInfoCache);
|
||||||
@ -484,6 +498,7 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
|
|||||||
InterruptTime = KeQueryInterruptTime();
|
InterruptTime = KeQueryInterruptTime();
|
||||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->SecurityCache, InterruptTime);
|
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->SecurityCache, InterruptTime);
|
||||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->DirInfoCache, InterruptTime);
|
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->DirInfoCache, InterruptTime);
|
||||||
|
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->StreamInfoCache, InterruptTime);
|
||||||
FspIoqRemoveExpired(FsvolDeviceExtension->Ioq, InterruptTime);
|
FspIoqRemoveExpired(FsvolDeviceExtension->Ioq, InterruptTime);
|
||||||
|
|
||||||
KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);
|
KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -100,7 +100,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
__VA_ARGS__\
|
__VA_ARGS__\
|
||||||
Info = DestBuf;\
|
Info = DestBuf;\
|
||||||
RtlCopyMemory(Info, &InfoStruct, FIELD_OFFSET(TYPE, FileName));\
|
RtlCopyMemory(Info, &InfoStruct, FIELD_OFFSET(TYPE, FileName));\
|
||||||
RtlCopyMemory(Info->FileName, DirInfo->FileNameBuf, FileName.Length);\
|
RtlMoveMemory(Info->FileName, DirInfo->FileNameBuf, CopyLength);\
|
||||||
} while (0,0)
|
} while (0,0)
|
||||||
#define FILL_INFO(TYPE, ...)\
|
#define FILL_INFO(TYPE, ...)\
|
||||||
FILL_INFO_BASE(TYPE,\
|
FILL_INFO_BASE(TYPE,\
|
||||||
@ -117,6 +117,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer;
|
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer;
|
||||||
BOOLEAN Loop = TRUE, DirectoryOffsetFound = FALSE;
|
BOOLEAN Loop = TRUE, DirectoryOffsetFound = FALSE;
|
||||||
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
|
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
|
||||||
@ -124,7 +125,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
||||||
PUINT8 DestBufEnd = (PUINT8)DestBuf + *PDestLen;
|
PUINT8 DestBufEnd = (PUINT8)DestBuf + *PDestLen;
|
||||||
PVOID PrevDestBuf = 0;
|
PVOID PrevDestBuf = 0;
|
||||||
ULONG BaseInfoLen;
|
ULONG BaseInfoLen, CopyLength;
|
||||||
UNICODE_STRING FileName;
|
UNICODE_STRING FileName;
|
||||||
|
|
||||||
*PDestLen = 0;
|
*PDestLen = 0;
|
||||||
@ -178,17 +179,27 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
|
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
FileName.Buffer = DirInfo->FileNameBuf;
|
FileName.Buffer = DirInfo->FileNameBuf;
|
||||||
|
|
||||||
|
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
||||||
|
CopyLength = FileName.Length;
|
||||||
|
|
||||||
if (MatchAll || FsRtlIsNameInExpression(DirectoryPattern, &FileName, CaseInsensitive, 0))
|
if (MatchAll || FsRtlIsNameInExpression(DirectoryPattern, &FileName, CaseInsensitive, 0))
|
||||||
{
|
{
|
||||||
if ((PUINT8)DestBuf +
|
if ((PUINT8)DestBuf + BaseInfoLen + CopyLength > DestBufEnd)
|
||||||
FSP_FSCTL_ALIGN_UP(BaseInfoLen + FileName.Length, sizeof(LONGLONG)) > DestBufEnd)
|
|
||||||
{
|
{
|
||||||
if (0 == *PDestLen)
|
/* if we have already copied something exit the loop */
|
||||||
{
|
if (0 != *PDestLen)
|
||||||
*PDestLen = BaseInfoLen + FileName.Length;
|
|
||||||
return STATUS_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if ((PUINT8)DestBuf + BaseInfoLen > DestBufEnd)
|
||||||
|
/* buffer is too small, can't copy anything */
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* copy as much of the file name as we can and return STATUS_BUFFER_OVERFLOW */
|
||||||
|
CopyLength = (USHORT)(DestBufEnd - ((PUINT8)DestBuf + BaseInfoLen));
|
||||||
|
Result = STATUS_BUFFER_OVERFLOW;
|
||||||
|
Loop = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != PrevDestBuf)
|
if (0 != PrevDestBuf)
|
||||||
@ -196,7 +207,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
PrevDestBuf = DestBuf;
|
PrevDestBuf = DestBuf;
|
||||||
|
|
||||||
*PDirectoryOffset = DirInfo->NextOffset;
|
*PDirectoryOffset = DirInfo->NextOffset;
|
||||||
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + FileName.Length - DestBufBgn);
|
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
|
||||||
|
|
||||||
switch (FileInformationClass)
|
switch (FileInformationClass)
|
||||||
{
|
{
|
||||||
@ -238,7 +249,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DestBuf = (PVOID)((PUINT8)DestBuf +
|
DestBuf = (PVOID)((PUINT8)DestBuf +
|
||||||
FSP_FSCTL_ALIGN_UP(BaseInfoLen + FileName.Length, sizeof(LONGLONG)));
|
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
|
||||||
|
|
||||||
if (ReturnSingleEntry)
|
if (ReturnSingleEntry)
|
||||||
/* cannot just break, *PDirInfo must be advanced */
|
/* cannot just break, *PDirInfo must be advanced */
|
||||||
@ -250,15 +261,18 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
}
|
}
|
||||||
except (EXCEPTION_EXECUTE_HANDLER)
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
NTSTATUS Result = GetExceptionCode();
|
Result = GetExceptionCode();
|
||||||
if (STATUS_INSUFFICIENT_RESOURCES == Result)
|
if (STATUS_INSUFFICIENT_RESOURCES == Result)
|
||||||
return Result;
|
return Result;
|
||||||
return FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
return FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* our code flow should allow only these two status codes here */
|
||||||
|
ASSERT(STATUS_SUCCESS == Result || STATUS_BUFFER_OVERFLOW == Result);
|
||||||
|
|
||||||
*PDirInfo = DirInfo;
|
*PDirInfo = DirInfo;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return Result;
|
||||||
|
|
||||||
#undef FILL_INFO
|
#undef FILL_INFO
|
||||||
#undef FILL_INFO_BASE
|
#undef FILL_INFO_BASE
|
||||||
@ -604,7 +618,7 @@ static NTSTATUS FspFsvolQueryDirectory(
|
|||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
/* check that FileName is valid (if supplied) */
|
/* check that FileName is valid (if supplied) */
|
||||||
if (0 != FileName && !FspUnicodePathIsValid(FileName, FALSE))
|
if (0 != FileName && !FspUnicodePathIsValidPattern(FileName))
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
/* is this an allowed file information class? */
|
/* is this an allowed file information class? */
|
||||||
@ -857,7 +871,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
|
|
||||||
if (FspFsctlTransactQueryDirectoryKind == Request->Kind)
|
if (FspFsctlTransactQueryDirectoryKind == Request->Kind)
|
||||||
{
|
{
|
||||||
DirInfoChangeNumber = FileNode->DirInfoChangeNumber;
|
DirInfoChangeNumber = FspFileNodeDirInfoChangeNumber(FileNode);
|
||||||
Request->Kind = FspFsctlTransactReservedKind;
|
Request->Kind = FspFsctlTransactReservedKind;
|
||||||
FspIopResetRequest(Request, 0);
|
FspIopResetRequest(Request, 0);
|
||||||
FspIopRequestContext(Request, RequestDirInfoChangeNumber) = (PVOID)DirInfoChangeNumber;
|
FspIopRequestContext(Request, RequestDirInfoChangeNumber) = (PVOID)DirInfoChangeNumber;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
111
src/sys/driver.h
111
src/sys/driver.h
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -417,15 +417,27 @@ BOOLEAN FspExpirationTimeValid(UINT64 ExpirationTime)
|
|||||||
return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (KeQueryInterruptTime() < ExpirationTime);
|
return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (KeQueryInterruptTime() < ExpirationTime);
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
|
BOOLEAN FspExpirationTimeValidEx(UINT64 ExpirationTime, UINT64 CurrentTime)
|
||||||
|
{
|
||||||
|
/* if ExpirationTime is 0 or -1 then ExpirationTime else CurrentTime < ExpirationTime */
|
||||||
|
return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (CurrentTime < ExpirationTime);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime)
|
BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime)
|
||||||
{
|
{
|
||||||
return CurrentTime < ExpirationTime;
|
return CurrentTime < ExpirationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* utility */
|
/* utility */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FspUnicodePathStreamTypeNone = 0,
|
||||||
|
FspUnicodePathStreamTypeData = 1,
|
||||||
|
};
|
||||||
PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag);
|
PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag);
|
||||||
PVOID FspAllocateIrpMustSucceed(CCHAR StackSize);
|
PVOID FspAllocateIrpMustSucceed(CCHAR StackSize);
|
||||||
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams);
|
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PULONG StreamType);
|
||||||
|
BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Pattern);
|
||||||
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
@ -722,6 +734,8 @@ enum
|
|||||||
FspFsvolDeviceSecurityCacheItemSizeMax = 4096,
|
FspFsvolDeviceSecurityCacheItemSizeMax = 4096,
|
||||||
FspFsvolDeviceDirInfoCacheCapacity = 100,
|
FspFsvolDeviceDirInfoCacheCapacity = 100,
|
||||||
FspFsvolDeviceDirInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
FspFsvolDeviceDirInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
||||||
|
FspFsvolDeviceStreamInfoCacheCapacity = 100,
|
||||||
|
FspFsvolDeviceStreamInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
||||||
};
|
};
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -748,7 +762,7 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FSP_DEVICE_EXTENSION Base;
|
FSP_DEVICE_EXTENSION Base;
|
||||||
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1,
|
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1,
|
||||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1;
|
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1;
|
||||||
PDEVICE_OBJECT FsctlDeviceObject;
|
PDEVICE_OBJECT FsctlDeviceObject;
|
||||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||||
@ -760,6 +774,7 @@ typedef struct
|
|||||||
FSP_IOQ *Ioq;
|
FSP_IOQ *Ioq;
|
||||||
FSP_META_CACHE *SecurityCache;
|
FSP_META_CACHE *SecurityCache;
|
||||||
FSP_META_CACHE *DirInfoCache;
|
FSP_META_CACHE *DirInfoCache;
|
||||||
|
FSP_META_CACHE *StreamInfoCache;
|
||||||
KSPIN_LOCK ExpirationLock;
|
KSPIN_LOCK ExpirationLock;
|
||||||
WORK_QUEUE_ITEM ExpirationWorkItem;
|
WORK_QUEUE_ITEM ExpirationWorkItem;
|
||||||
BOOLEAN ExpirationInProgress;
|
BOOLEAN ExpirationInProgress;
|
||||||
@ -888,10 +903,11 @@ typedef struct
|
|||||||
ERESOURCE PagingIoResource;
|
ERESOURCE PagingIoResource;
|
||||||
FAST_MUTEX HeaderFastMutex;
|
FAST_MUTEX HeaderFastMutex;
|
||||||
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
||||||
KSPIN_LOCK DirInfoSpinLock;
|
KSPIN_LOCK NpInfoSpinLock; /* allows to invalidate non-page Info w/o resources acquired */
|
||||||
UINT64 DirInfo; /* allows to invalidate DirInfo w/o resources acquired */
|
UINT64 DirInfo;
|
||||||
|
UINT64 StreamInfo;
|
||||||
} FSP_FILE_NODE_NONPAGED;
|
} FSP_FILE_NODE_NONPAGED;
|
||||||
typedef struct
|
typedef struct FSP_FILE_NODE
|
||||||
{
|
{
|
||||||
FSRTL_ADVANCED_FCB_HEADER Header;
|
FSRTL_ADVANCED_FCB_HEADER Header;
|
||||||
FSP_FILE_NODE_NONPAGED *NonPaged;
|
FSP_FILE_NODE_NONPAGED *NonPaged;
|
||||||
@ -902,22 +918,25 @@ typedef struct
|
|||||||
LONG OpenCount; /* ContextTable ref count */
|
LONG OpenCount; /* ContextTable ref count */
|
||||||
LONG HandleCount; /* HANDLE count (CREATE/CLEANUP) */
|
LONG HandleCount; /* HANDLE count (CREATE/CLEANUP) */
|
||||||
SHARE_ACCESS ShareAccess;
|
SHARE_ACCESS ShareAccess;
|
||||||
|
ULONG MainFileDenyDeleteCount; /* number of times main file is denying delete */
|
||||||
|
ULONG StreamDenyDeleteCount; /* number of times open streams are denying delete */
|
||||||
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage;
|
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage;
|
||||||
/* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource or Header.Resource */
|
/* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource or Header.Resource */
|
||||||
UNICODE_STRING FileName;
|
UNICODE_STRING FileName;
|
||||||
PWSTR ExternalFileName;
|
PWSTR ExternalFileName;
|
||||||
/* locked under Header.Resource */
|
/* locked under Header.Resource */
|
||||||
UINT64 InfoExpirationTime;
|
UINT64 FileInfoExpirationTime, BasicInfoExpirationTime;
|
||||||
UINT32 FileAttributes;
|
UINT32 FileAttributes;
|
||||||
UINT32 ReparseTag;
|
UINT32 ReparseTag;
|
||||||
UINT64 CreationTime;
|
UINT64 CreationTime;
|
||||||
UINT64 LastAccessTime;
|
UINT64 LastAccessTime;
|
||||||
UINT64 LastWriteTime;
|
UINT64 LastWriteTime;
|
||||||
UINT64 ChangeTime;
|
UINT64 ChangeTime;
|
||||||
ULONG InfoChangeNumber;
|
ULONG FileInfoChangeNumber;
|
||||||
UINT64 Security;
|
UINT64 Security;
|
||||||
ULONG SecurityChangeNumber;
|
ULONG SecurityChangeNumber;
|
||||||
ULONG DirInfoChangeNumber;
|
ULONG DirInfoChangeNumber;
|
||||||
|
ULONG StreamInfoChangeNumber;
|
||||||
BOOLEAN TruncateOnClose;
|
BOOLEAN TruncateOnClose;
|
||||||
FILE_LOCK FileLock;
|
FILE_LOCK FileLock;
|
||||||
struct
|
struct
|
||||||
@ -935,6 +954,7 @@ typedef struct
|
|||||||
UINT64 IndexNumber;
|
UINT64 IndexNumber;
|
||||||
BOOLEAN IsDirectory;
|
BOOLEAN IsDirectory;
|
||||||
BOOLEAN IsRootDirectory;
|
BOOLEAN IsRootDirectory;
|
||||||
|
struct FSP_FILE_NODE *MainFileNode; /* this becomes invalid after our last desc close */
|
||||||
WCHAR FileNameBuf[];
|
WCHAR FileNameBuf[];
|
||||||
} FSP_FILE_NODE;
|
} FSP_FILE_NODE;
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -949,6 +969,9 @@ typedef struct
|
|||||||
UINT64 DirectoryOffset;
|
UINT64 DirectoryOffset;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
ULONG DirInfoCacheHint;
|
ULONG DirInfoCacheHint;
|
||||||
|
/* stream support */
|
||||||
|
HANDLE MainFileHandle;
|
||||||
|
PFILE_OBJECT MainFileObject;
|
||||||
} FSP_FILE_DESC;
|
} FSP_FILE_DESC;
|
||||||
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
|
||||||
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
|
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
|
||||||
@ -993,20 +1016,86 @@ VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
|
|||||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
|
BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
|
||||||
const FSP_FSCTL_FILE_INFO *FileInfo, ULONG InfoChangeNumber);
|
const FSP_FSCTL_FILE_INFO *FileInfo, ULONG InfoChangeNumber);
|
||||||
|
static inline
|
||||||
|
ULONG FspFileNodeFileInfoChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
return (FileNode->MainFileNode->FileInfoChangeNumber & 0xfffff) |
|
||||||
|
((FileNode->FileInfoChangeNumber & 0xfff) << 20);
|
||||||
|
else
|
||||||
|
return FileNode->FileInfoChangeNumber & 0xfffff;
|
||||||
|
}
|
||||||
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
|
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
|
||||||
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
||||||
BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG SecurityChangeNumber);
|
ULONG SecurityChangeNumber);
|
||||||
|
static inline
|
||||||
|
ULONG FspFileNodeSecurityChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
return FileNode->SecurityChangeNumber;
|
||||||
|
}
|
||||||
BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
|
BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
|
||||||
VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
||||||
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG DirInfoChangeNumber);
|
ULONG DirInfoChangeNumber);
|
||||||
|
static inline
|
||||||
|
ULONG FspFileNodeDirInfoChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
return FileNode->DirInfoChangeNumber;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
static inline
|
||||||
|
ULONG FspFileNodeStreamInfoChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
return FileNode->StreamInfoChangeNumber;
|
||||||
|
}
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action);
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action);
|
||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
PUNICODE_STRING FileName, BOOLEAN Reset);
|
||||||
|
NTSTATUS FspMainFileOpen(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
|
PUNICODE_STRING MainFileName, BOOLEAN CaseSensitive,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
ULONG FileAttributes,
|
||||||
|
ULONG Disposition,
|
||||||
|
PHANDLE PMainFileHandle,
|
||||||
|
PFILE_OBJECT *PMainFileObject);
|
||||||
|
NTSTATUS FspMainFileClose(
|
||||||
|
HANDLE MainFileHandle,
|
||||||
|
PFILE_OBJECT MainFileObject);
|
||||||
|
static __forceinline
|
||||||
|
BOOLEAN FspMainFileOpenCheck(PIRP Irp)
|
||||||
|
{
|
||||||
|
extern const GUID FspMainFileOpenEcpGuid;
|
||||||
|
NTSTATUS Result;
|
||||||
|
PECP_LIST ExtraCreateParameters = 0;
|
||||||
|
PVOID ExtraCreateParameter = 0;
|
||||||
|
|
||||||
|
Result = FsRtlGetEcpListFromIrp(Irp, &ExtraCreateParameters);
|
||||||
|
if (!NT_SUCCESS(Result) || 0 == ExtraCreateParameters)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Result = FsRtlFindExtraCreateParameter(ExtraCreateParameters,
|
||||||
|
&FspMainFileOpenEcpGuid, &ExtraCreateParameter, 0);
|
||||||
|
if (!NT_SUCCESS(Result) || 0 == ExtraCreateParameter)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (FsRtlIsEcpFromUserMode(ExtraCreateParameter))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
#define FspFileNodeAcquireShared(N,F) FspFileNodeAcquireSharedF(N, FspFileNodeAcquire ## F)
|
#define FspFileNodeAcquireShared(N,F) FspFileNodeAcquireSharedF(N, FspFileNodeAcquire ## F)
|
||||||
#define FspFileNodeTryAcquireShared(N,F) FspFileNodeTryAcquireSharedF(N, FspFileNodeAcquire ## F, FALSE)
|
#define FspFileNodeTryAcquireShared(N,F) FspFileNodeTryAcquireSharedF(N, FspFileNodeAcquire ## F, FALSE)
|
||||||
#define FspFileNodeAcquireExclusive(N,F) FspFileNodeAcquireExclusiveF(N, FspFileNodeAcquire ## F)
|
#define FspFileNodeAcquireExclusive(N,F) FspFileNodeAcquireExclusiveF(N, FspFileNodeAcquire ## F)
|
||||||
@ -1017,6 +1106,7 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
|||||||
#define FspFileNodeReleaseOwner(N,F,P) FspFileNodeReleaseOwnerF(N, FspFileNodeAcquire ## F, P)
|
#define FspFileNodeReleaseOwner(N,F,P) FspFileNodeReleaseOwnerF(N, FspFileNodeAcquire ## F, P)
|
||||||
#define FspFileNodeDereferenceSecurity(P) FspMetaCacheDereferenceItemBuffer(P)
|
#define FspFileNodeDereferenceSecurity(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
#define FspFileNodeDereferenceDirInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
#define FspFileNodeDereferenceDirInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
|
#define FspFileNodeDereferenceStreamInfo(P) FspMetaCacheDereferenceItemBuffer(P)
|
||||||
#define FspFileNodeUnlockAll(N,F,P) FsRtlFastUnlockAll(&(N)->FileLock, F, P, N)
|
#define FspFileNodeUnlockAll(N,F,P) FsRtlFastUnlockAll(&(N)->FileLock, F, P, N)
|
||||||
|
|
||||||
/* multiversion support */
|
/* multiversion support */
|
||||||
@ -1041,6 +1131,7 @@ extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
|||||||
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
||||||
extern ERESOURCE FspDeviceGlobalResource;
|
extern ERESOURCE FspDeviceGlobalResource;
|
||||||
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
|
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
|
||||||
|
extern const GUID FspMainFileOpenEcpGuid;
|
||||||
extern FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
extern FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
||||||
extern ULONG FspMvMdlMappingNoWrite;
|
extern ULONG FspMvMdlMappingNoWrite;
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
520
src/sys/file.c
520
src/sys/file.c
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -57,6 +57,11 @@ VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
|||||||
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG DirInfoChangeNumber);
|
ULONG DirInfoChangeNumber);
|
||||||
static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode);
|
static VOID FspFileNodeInvalidateDirInfo(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);
|
||||||
|
static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
|
||||||
ULONG Filter, ULONG Action);
|
ULONG Filter, ULONG Action);
|
||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
@ -65,6 +70,18 @@ NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
|||||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
PUNICODE_STRING FileName, BOOLEAN Reset);
|
||||||
|
NTSTATUS FspMainFileOpen(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
|
PUNICODE_STRING MainFileName, BOOLEAN CaseSensitive,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
ULONG FileAttributes,
|
||||||
|
ULONG Disposition,
|
||||||
|
PHANDLE PMainFileHandle,
|
||||||
|
PFILE_OBJECT *PMainFileObject);
|
||||||
|
NTSTATUS FspMainFileClose(
|
||||||
|
HANDLE MainFileHandle,
|
||||||
|
PFILE_OBJECT MainFileObject);
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspFileNodeCopyList)
|
#pragma alloc_text(PAGE, FspFileNodeCopyList)
|
||||||
@ -97,12 +114,18 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
|||||||
// !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateDirInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateDirInfo)
|
||||||
|
// !#pragma alloc_text(PAGE, FspFileNodeReferenceStreamInfo)
|
||||||
|
// !#pragma alloc_text(PAGE, FspFileNodeSetStreamInfo)
|
||||||
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetStreamInfo)
|
||||||
|
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeProcessLockIrp)
|
#pragma alloc_text(PAGE, FspFileNodeProcessLockIrp)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
||||||
#pragma alloc_text(PAGE, FspFileDescCreate)
|
#pragma alloc_text(PAGE, FspFileDescCreate)
|
||||||
#pragma alloc_text(PAGE, FspFileDescDelete)
|
#pragma alloc_text(PAGE, FspFileDescDelete)
|
||||||
#pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern)
|
#pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern)
|
||||||
|
#pragma alloc_text(PAGE, FspMainFileOpen)
|
||||||
|
#pragma alloc_text(PAGE, FspMainFileClose)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FSP_FILE_NODE_GET_FLAGS() \
|
#define FSP_FILE_NODE_GET_FLAGS() \
|
||||||
@ -176,7 +199,7 @@ NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
|
|||||||
ExInitializeResourceLite(&NonPaged->Resource);
|
ExInitializeResourceLite(&NonPaged->Resource);
|
||||||
ExInitializeResourceLite(&NonPaged->PagingIoResource);
|
ExInitializeResourceLite(&NonPaged->PagingIoResource);
|
||||||
ExInitializeFastMutex(&NonPaged->HeaderFastMutex);
|
ExInitializeFastMutex(&NonPaged->HeaderFastMutex);
|
||||||
KeInitializeSpinLock(&NonPaged->DirInfoSpinLock);
|
KeInitializeSpinLock(&NonPaged->NpInfoSpinLock);
|
||||||
|
|
||||||
RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize);
|
RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize);
|
||||||
FileNode->Header.NodeTypeCode = FspFileNodeFileKind;
|
FileNode->Header.NodeTypeCode = FspFileNodeFileKind;
|
||||||
@ -211,6 +234,7 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
|
|||||||
|
|
||||||
FsRtlTeardownPerStreamContexts(&FileNode->Header);
|
FsRtlTeardownPerStreamContexts(&FileNode->Header);
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, FileNode->NonPaged->StreamInfo);
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, FileNode->NonPaged->DirInfo);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, FileNode->NonPaged->DirInfo);
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security);
|
||||||
|
|
||||||
@ -230,6 +254,9 @@ VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
||||||
|
|
||||||
@ -246,6 +273,9 @@ BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLE
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
||||||
|
|
||||||
@ -279,6 +309,9 @@ VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
||||||
|
|
||||||
@ -295,6 +328,9 @@ BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BO
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
|
||||||
|
|
||||||
@ -328,6 +364,9 @@ VOID FspFileNodeConvertExclusiveToSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
|
|
||||||
if (Flags & FspFileNodeAcquirePgio)
|
if (Flags & FspFileNodeAcquirePgio)
|
||||||
@ -341,6 +380,9 @@ VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
|
|
||||||
Owner = (PVOID)((UINT_PTR)Owner | 3);
|
Owner = (PVOID)((UINT_PTR)Owner | 3);
|
||||||
@ -356,6 +398,9 @@ VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
FSP_FILE_NODE_ASSERT_FLAGS_SET();
|
FSP_FILE_NODE_ASSERT_FLAGS_SET();
|
||||||
|
|
||||||
@ -372,6 +417,9 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FILE_NODE_GET_FLAGS();
|
FSP_FILE_NODE_GET_FLAGS();
|
||||||
FSP_FILE_NODE_ASSERT_FLAGS_SET();
|
FSP_FILE_NODE_ASSERT_FLAGS_SET();
|
||||||
|
|
||||||
@ -410,12 +458,43 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||||
FSP_FILE_NODE *OpenedFileNode;
|
FSP_FILE_NODE *OpenedFileNode = 0;
|
||||||
BOOLEAN Inserted, DeletePending;
|
BOOLEAN Inserted, DeletePending;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is a named stream we must also check with our main file.
|
||||||
|
* Note that FileNode->MainFileNode and OpenedFileNode->MainFileNode
|
||||||
|
* will always be the same.
|
||||||
|
*/
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
DeletePending = 0 != FileNode->MainFileNode->DeletePending;
|
||||||
|
MemoryBarrier();
|
||||||
|
if (DeletePending)
|
||||||
|
{
|
||||||
|
Result = STATUS_DELETE_PENDING;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sharing violations between main file and streams were determined
|
||||||
|
* through experimentation with NTFS. They may be wrong!
|
||||||
|
*/
|
||||||
|
if (0 < FileNode->MainFileNode->MainFileDenyDeleteCount)
|
||||||
|
{
|
||||||
|
if (!FlagOn(ShareAccess, FILE_SHARE_DELETE) &&
|
||||||
|
FlagOn(GrantedAccess,
|
||||||
|
FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE))
|
||||||
|
{
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OpenedFileNode = FspFsvolDeviceInsertContextByName(FsvolDeviceObject,
|
OpenedFileNode = FspFsvolDeviceInsertContextByName(FsvolDeviceObject,
|
||||||
&FileNode->FileName, FileNode, &FileNode->ContextByNameElementStorage, &Inserted);
|
&FileNode->FileName, FileNode, &FileNode->ContextByNameElementStorage, &Inserted);
|
||||||
ASSERT(0 != OpenedFileNode);
|
ASSERT(0 != OpenedFileNode);
|
||||||
@ -439,6 +518,7 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
* opening a prior FileNode that we found in the table.
|
* opening a prior FileNode that we found in the table.
|
||||||
*/
|
*/
|
||||||
ASSERT(OpenedFileNode != FileNode);
|
ASSERT(OpenedFileNode != FileNode);
|
||||||
|
ASSERT(OpenedFileNode->MainFileNode == FileNode->MainFileNode);
|
||||||
|
|
||||||
DeletePending = 0 != OpenedFileNode->DeletePending;
|
DeletePending = 0 != OpenedFileNode->DeletePending;
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
@ -448,6 +528,22 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sharing violations between main file and streams were determined
|
||||||
|
* through experimentation with NTFS. They may be wrong!
|
||||||
|
*/
|
||||||
|
if (0 < OpenedFileNode->StreamDenyDeleteCount)
|
||||||
|
{
|
||||||
|
/* we must be the main file! */
|
||||||
|
ASSERT(0 == OpenedFileNode->MainFileNode);
|
||||||
|
|
||||||
|
if (FlagOn(GrantedAccess, DELETE))
|
||||||
|
{
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FastFat says to do the following on Vista and above.
|
* FastFat says to do the following on Vista and above.
|
||||||
*
|
*
|
||||||
@ -468,6 +564,33 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
/* share access check */
|
/* share access check */
|
||||||
Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject,
|
Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject,
|
||||||
&OpenedFileNode->ShareAccess, TRUE);
|
&OpenedFileNode->ShareAccess, TRUE);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No more failures allowed at this point!
|
||||||
|
* This is because we have potentially inserted a new FileNode into the Context table.
|
||||||
|
* We also updated OpenedFileNode->ShareAccess in IoSetShareAccess/IoCheckShareAccess.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sharing violations between main file and streams were determined
|
||||||
|
* through experimentation with NTFS. They may be wrong!
|
||||||
|
*/
|
||||||
|
if (0 == OpenedFileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
if (FileObject->DeleteAccess)
|
||||||
|
OpenedFileNode->MainFileDenyDeleteCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((FileObject->ReadAccess || FileObject->WriteAccess || FileObject->DeleteAccess) &&
|
||||||
|
!FileObject->SharedDelete)
|
||||||
|
OpenedFileNode->MainFileNode->StreamDenyDeleteCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -477,7 +600,6 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
|
|
||||||
OpenedFileNode = 0;
|
OpenedFileNode = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != OpenedFileNode)
|
if (0 != OpenedFileNode)
|
||||||
{
|
{
|
||||||
@ -546,6 +668,22 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
|||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sharing violations between main file and streams were determined
|
||||||
|
* through experimentation with NTFS. They may be wrong!
|
||||||
|
*/
|
||||||
|
if (0 == FileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
if (FileObject->DeleteAccess)
|
||||||
|
FileNode->MainFileDenyDeleteCount--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((FileObject->ReadAccess || FileObject->WriteAccess || FileObject->DeleteAccess) &&
|
||||||
|
!FileObject->SharedDelete)
|
||||||
|
FileNode->MainFileNode->StreamDenyDeleteCount--;
|
||||||
|
}
|
||||||
|
|
||||||
IoRemoveShareAccess(FileObject, &FileNode->ShareAccess);
|
IoRemoveShareAccess(FileObject, &FileNode->ShareAccess);
|
||||||
|
|
||||||
if (0 == --FileNode->HandleCount)
|
if (0 == --FileNode->HandleCount)
|
||||||
@ -717,7 +855,14 @@ VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileIn
|
|||||||
FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart;
|
FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart;
|
||||||
FileInfo->FileSize = FileNode->Header.FileSize.QuadPart;
|
FileInfo->FileSize = FileNode->Header.FileSize.QuadPart;
|
||||||
|
|
||||||
FileInfo->FileAttributes = FileNode->FileAttributes;
|
UINT32 FileAttributesMask = ~(UINT32)0;
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfo->FileAttributes = FileNode->FileAttributes & FileAttributesMask;
|
||||||
FileInfo->ReparseTag = FileNode->ReparseTag;
|
FileInfo->ReparseTag = FileNode->ReparseTag;
|
||||||
FileInfo->CreationTime = FileNode->CreationTime;
|
FileInfo->CreationTime = FileNode->CreationTime;
|
||||||
FileInfo->LastAccessTime = FileNode->LastAccessTime;
|
FileInfo->LastAccessTime = FileNode->LastAccessTime;
|
||||||
@ -729,25 +874,20 @@ BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
BOOLEAN Result;
|
UINT64 CurrentTime = KeQueryInterruptTime();
|
||||||
|
|
||||||
if (FspExpirationTimeValid(FileNode->InfoExpirationTime))
|
if (0 != FileNode->MainFileNode)
|
||||||
{
|
{
|
||||||
FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart;
|
/* if this is a stream the main file basic info must have not expired as well! */
|
||||||
FileInfo->FileSize = FileNode->Header.FileSize.QuadPart;
|
if (!FspExpirationTimeValidEx(FileNode->MainFileNode->BasicInfoExpirationTime, CurrentTime))
|
||||||
|
return FALSE;
|
||||||
FileInfo->FileAttributes = FileNode->FileAttributes;
|
|
||||||
FileInfo->ReparseTag = FileNode->ReparseTag;
|
|
||||||
FileInfo->CreationTime = FileNode->CreationTime;
|
|
||||||
FileInfo->LastAccessTime = FileNode->LastAccessTime;
|
|
||||||
FileInfo->LastWriteTime = FileNode->LastWriteTime;
|
|
||||||
FileInfo->ChangeTime = FileNode->ChangeTime;
|
|
||||||
Result = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Result = FALSE;
|
|
||||||
|
|
||||||
return Result;
|
if (!FspExpirationTimeValidEx(FileNode->FileInfoExpirationTime, CurrentTime))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
FspFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
|
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
|
||||||
@ -768,15 +908,29 @@ VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
|
|||||||
FileNode->Header.AllocationSize.QuadPart = AllocationSize;
|
FileNode->Header.AllocationSize.QuadPart = AllocationSize;
|
||||||
FileNode->Header.FileSize.QuadPart = FileInfo->FileSize;
|
FileNode->Header.FileSize.QuadPart = FileInfo->FileSize;
|
||||||
|
|
||||||
FileNode->FileAttributes = FileInfo->FileAttributes;
|
FileNode->FileInfoExpirationTime = FileNode->BasicInfoExpirationTime =
|
||||||
FileNode->ReparseTag = FileInfo->ReparseTag;
|
FspExpirationTimeFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||||
FileNode->CreationTime = FileInfo->CreationTime;
|
FileNode->FileInfoChangeNumber++;
|
||||||
FileNode->LastAccessTime = FileInfo->LastAccessTime;
|
|
||||||
FileNode->LastWriteTime = FileInfo->LastWriteTime;
|
FSP_FILE_NODE *MainFileNode = FileNode;
|
||||||
FileNode->ChangeTime = FileInfo->ChangeTime;
|
UINT32 FileAttributesMask = ~(UINT32)0;
|
||||||
FileNode->InfoExpirationTime = FspExpirationTimeFromMillis(
|
if (0 != FileNode->MainFileNode)
|
||||||
FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
{
|
||||||
FileNode->InfoChangeNumber++;
|
FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
MainFileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
MainFileNode->BasicInfoExpirationTime = FileNode->BasicInfoExpirationTime;
|
||||||
|
MainFileNode->FileInfoChangeNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainFileNode->FileAttributes =
|
||||||
|
(MainFileNode->FileAttributes & ~FileAttributesMask) |
|
||||||
|
(FileInfo->FileAttributes & FileAttributesMask);
|
||||||
|
MainFileNode->ReparseTag = FileInfo->ReparseTag;
|
||||||
|
MainFileNode->CreationTime = FileInfo->CreationTime;
|
||||||
|
MainFileNode->LastAccessTime = FileInfo->LastAccessTime;
|
||||||
|
MainFileNode->LastWriteTime = FileInfo->LastWriteTime;
|
||||||
|
MainFileNode->ChangeTime = FileInfo->ChangeTime;
|
||||||
|
|
||||||
if (0 != CcFileObject)
|
if (0 != CcFileObject)
|
||||||
{
|
{
|
||||||
@ -796,7 +950,7 @@ BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileOb
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
if (FileNode->InfoChangeNumber != InfoChangeNumber)
|
if (FspFileNodeFileInfoChangeNumber(FileNode) != InfoChangeNumber)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo);
|
FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo);
|
||||||
@ -807,6 +961,9 @@ BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, P
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
|
||||||
@ -818,6 +975,9 @@ VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
|
||||||
@ -832,7 +992,7 @@ BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
if (FileNode->SecurityChangeNumber != SecurityChangeNumber)
|
if (FspFileNodeSecurityChangeNumber(FileNode) != SecurityChangeNumber)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
FspFileNodeSetSecurity(FileNode, Buffer, Size);
|
FspFileNodeSetSecurity(FileNode, Buffer, Size);
|
||||||
@ -848,7 +1008,7 @@ BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PU
|
|||||||
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
|
|
||||||
/* no need to acquire the DirInfoSpinLock as the FileNode is acquired */
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
DirInfo = NonPaged->DirInfo;
|
DirInfo = NonPaged->DirInfo;
|
||||||
|
|
||||||
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->DirInfoCache,
|
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->DirInfoCache,
|
||||||
@ -865,7 +1025,7 @@ VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
|||||||
KIRQL Irql;
|
KIRQL Irql;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
|
|
||||||
/* no need to acquire the DirInfoSpinLock as the FileNode is acquired */
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
DirInfo = NonPaged->DirInfo;
|
DirInfo = NonPaged->DirInfo;
|
||||||
|
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo);
|
||||||
@ -873,10 +1033,10 @@ VOID FspFileNodeSetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
|||||||
FspMetaCacheAddItem(FsvolDeviceExtension->DirInfoCache, Buffer, Size) : 0;
|
FspMetaCacheAddItem(FsvolDeviceExtension->DirInfoCache, Buffer, Size) : 0;
|
||||||
FileNode->DirInfoChangeNumber++;
|
FileNode->DirInfoChangeNumber++;
|
||||||
|
|
||||||
/* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeInvalidateDirInfo */
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeInvalidateDirInfo */
|
||||||
KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql);
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
NonPaged->DirInfo = DirInfo;
|
NonPaged->DirInfo = DirInfo;
|
||||||
KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql);
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
@ -884,7 +1044,7 @@ BOOLEAN FspFileNodeTrySetDirInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG S
|
|||||||
{
|
{
|
||||||
// !PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (FileNode->DirInfoChangeNumber != DirInfoChangeNumber)
|
if (FspFileNodeDirInfoChangeNumber(FileNode) != DirInfoChangeNumber)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
FspFileNodeSetDirInfo(FileNode, Buffer, Size);
|
FspFileNodeSetDirInfo(FileNode, Buffer, Size);
|
||||||
@ -901,14 +1061,93 @@ static VOID FspFileNodeInvalidateDirInfo(FSP_FILE_NODE *FileNode)
|
|||||||
KIRQL Irql;
|
KIRQL Irql;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
|
|
||||||
/* acquire the DirInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo */
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeSetDirInfo */
|
||||||
KeAcquireSpinLock(&NonPaged->DirInfoSpinLock, &Irql);
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
DirInfo = NonPaged->DirInfo;
|
DirInfo = NonPaged->DirInfo;
|
||||||
KeReleaseSpinLock(&NonPaged->DirInfoSpinLock, Irql);
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
|
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, DirInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFileNodeReferenceStreamInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
UINT64 StreamInfo;
|
||||||
|
|
||||||
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
|
StreamInfo = NonPaged->StreamInfo;
|
||||||
|
|
||||||
|
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->StreamInfoCache,
|
||||||
|
StreamInfo, PBuffer, PSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspFileNodeSetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
KIRQL Irql;
|
||||||
|
UINT64 StreamInfo;
|
||||||
|
|
||||||
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
|
StreamInfo = NonPaged->StreamInfo;
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, StreamInfo);
|
||||||
|
StreamInfo = 0 != Buffer ?
|
||||||
|
FspMetaCacheAddItem(FsvolDeviceExtension->StreamInfoCache, Buffer, Size) : 0;
|
||||||
|
FileNode->StreamInfoChangeNumber++;
|
||||||
|
|
||||||
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeInvalidateStreamInfo */
|
||||||
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
|
NonPaged->StreamInfo = StreamInfo;
|
||||||
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
|
ULONG StreamInfoChangeNumber)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
if (FspFileNodeStreamInfoChangeNumber(FileNode) != StreamInfoChangeNumber)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
FspFileNodeSetStreamInfo(FileNode, Buffer, Size);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
KIRQL Irql;
|
||||||
|
UINT64 StreamInfo;
|
||||||
|
|
||||||
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeSetStreamInfo */
|
||||||
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
|
StreamInfo = NonPaged->StreamInfo;
|
||||||
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, StreamInfo);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
|
||||||
ULONG Filter, ULONG Action)
|
ULONG Filter, ULONG Action)
|
||||||
{
|
{
|
||||||
@ -946,6 +1185,33 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
if (FlagOn(Filter, FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME))
|
||||||
|
SetFlag(Filter, FILE_NOTIFY_CHANGE_STREAM_NAME);
|
||||||
|
if (FlagOn(Filter, FILE_NOTIFY_CHANGE_SIZE))
|
||||||
|
SetFlag(Filter, FILE_NOTIFY_CHANGE_STREAM_SIZE);
|
||||||
|
/* ???: 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)
|
||||||
FspNotifyReportChange(
|
FspNotifyReportChange(
|
||||||
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList,
|
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList,
|
||||||
&FileNode->FileName,
|
&FileNode->FileName,
|
||||||
@ -1008,6 +1274,8 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FspMainFileClose(FileDesc->MainFileHandle, FileDesc->MainFileObject);
|
||||||
|
|
||||||
if (0 != FileDesc->DirectoryPattern.Buffer &&
|
if (0 != FileDesc->DirectoryPattern.Buffer &&
|
||||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
||||||
{
|
{
|
||||||
@ -1067,4 +1335,172 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMainFileOpen(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
|
PUNICODE_STRING MainFileName, BOOLEAN CaseSensitive,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
ULONG FileAttributes,
|
||||||
|
ULONG Disposition,
|
||||||
|
PHANDLE PMainFileHandle,
|
||||||
|
PFILE_OBJECT *PMainFileObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
UNICODE_STRING FullFileName = { 0 };
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
IO_DRIVER_CREATE_CONTEXT DriverCreateContext = { 0 };
|
||||||
|
PVOID ExtraCreateParameter;
|
||||||
|
HANDLE MainFileHandle;
|
||||||
|
PFILE_OBJECT MainFileObject;
|
||||||
|
|
||||||
|
/* assert that the supplied name is actually a main file name */
|
||||||
|
ASSERT(FspUnicodePathIsValid(MainFileName, 0, 0));
|
||||||
|
|
||||||
|
*PMainFileHandle = 0;
|
||||||
|
*PMainFileObject = 0;
|
||||||
|
|
||||||
|
switch (Disposition)
|
||||||
|
{
|
||||||
|
case FILE_CREATE:
|
||||||
|
case FILE_OPEN_IF:
|
||||||
|
case FILE_OVERWRITE_IF:
|
||||||
|
Disposition = FILE_OPEN_IF;
|
||||||
|
break;
|
||||||
|
case FILE_OPEN:
|
||||||
|
case FILE_OVERWRITE:
|
||||||
|
case FILE_SUPERSEDE:
|
||||||
|
Disposition = FILE_OPEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
FullFileName.Length = 0;
|
||||||
|
FullFileName.MaximumLength =
|
||||||
|
FsvolDeviceExtension->VolumeName.Length +
|
||||||
|
FsvolDeviceExtension->VolumePrefix.Length +
|
||||||
|
MainFileName->Length;
|
||||||
|
FullFileName.Buffer = FspAlloc(FullFileName.MaximumLength);
|
||||||
|
if (0 == FullFileName.Buffer)
|
||||||
|
{
|
||||||
|
IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlAppendUnicodeStringToString(&FullFileName, &FsvolDeviceExtension->VolumeName);
|
||||||
|
RtlAppendUnicodeStringToString(&FullFileName, &FsvolDeviceExtension->VolumePrefix);
|
||||||
|
RtlAppendUnicodeStringToString(&FullFileName, MainFileName);
|
||||||
|
|
||||||
|
InitializeObjectAttributes(
|
||||||
|
&ObjectAttributes,
|
||||||
|
&FullFileName,
|
||||||
|
OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK | (CaseSensitive ? 0 : OBJ_CASE_INSENSITIVE),
|
||||||
|
0/*RootDirectory*/,
|
||||||
|
SecurityDescriptor);
|
||||||
|
|
||||||
|
/* do not use SiloContext field as it is only available on Win10 v1607 and higher */
|
||||||
|
DriverCreateContext.Size =
|
||||||
|
FIELD_OFFSET(IO_DRIVER_CREATE_CONTEXT, TxnParameters) +
|
||||||
|
sizeof(((PIO_DRIVER_CREATE_CONTEXT)0)->TxnParameters);
|
||||||
|
DriverCreateContext.DeviceObjectHint = 0 != FsvolDeviceExtension->FsvrtDeviceObject ?
|
||||||
|
FsvolDeviceObject : DeviceObjectHint;
|
||||||
|
|
||||||
|
IoStatus.Status = FsRtlAllocateExtraCreateParameterList(0,
|
||||||
|
&DriverCreateContext.ExtraCreateParameter);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
IoStatus.Status = FsRtlAllocateExtraCreateParameter(&FspMainFileOpenEcpGuid,
|
||||||
|
sizeof(PVOID),
|
||||||
|
0/*Flags*/,
|
||||||
|
0/*CleanupCallback*/,
|
||||||
|
FSP_ALLOC_INTERNAL_TAG,
|
||||||
|
&ExtraCreateParameter);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
IoStatus.Status = FsRtlInsertExtraCreateParameter(DriverCreateContext.ExtraCreateParameter,
|
||||||
|
ExtraCreateParameter);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
{
|
||||||
|
FsRtlFreeExtraCreateParameter(ExtraCreateParameter);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
IoStatus.Status = IoCreateFileEx(
|
||||||
|
&MainFileHandle,
|
||||||
|
FILE_READ_ATTRIBUTES,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatus,
|
||||||
|
0/*AllocationSize*/,
|
||||||
|
FileAttributes,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
Disposition,
|
||||||
|
FILE_OPEN_REPARSE_POINT,
|
||||||
|
0/*EaBuffer*/,
|
||||||
|
0/*EaLength*/,
|
||||||
|
CreateFileTypeNone,
|
||||||
|
0/*InternalParameters*/,
|
||||||
|
IO_FORCE_ACCESS_CHECK,
|
||||||
|
&DriverCreateContext);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
IoStatus.Status = ObReferenceObjectByHandle(
|
||||||
|
MainFileHandle,
|
||||||
|
0/*DesiredAccess*/,
|
||||||
|
*IoFileObjectType,
|
||||||
|
KernelMode,
|
||||||
|
&MainFileObject,
|
||||||
|
0/*HandleInformation*/);
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status))
|
||||||
|
{
|
||||||
|
ObCloseHandle(MainFileHandle, KernelMode);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PMainFileHandle = MainFileHandle;
|
||||||
|
*PMainFileObject = MainFileObject;
|
||||||
|
|
||||||
|
IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != DriverCreateContext.ExtraCreateParameter)
|
||||||
|
FsRtlFreeExtraCreateParameterList(DriverCreateContext.ExtraCreateParameter);
|
||||||
|
|
||||||
|
if (0 != FullFileName.Buffer)
|
||||||
|
FspFree(FullFileName.Buffer);
|
||||||
|
|
||||||
|
return IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMainFileClose(
|
||||||
|
HANDLE MainFileHandle,
|
||||||
|
PFILE_OBJECT MainFileObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (0 != MainFileObject)
|
||||||
|
ObDereferenceObject(MainFileObject);
|
||||||
|
|
||||||
|
if (0 != MainFileHandle)
|
||||||
|
{
|
||||||
|
Result = ObCloseHandle(MainFileHandle, KernelMode);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
WCHAR FspFileDescDirectoryPatternMatchAll[] = L"*";
|
WCHAR FspFileDescDirectoryPatternMatchAll[] = L"*";
|
||||||
|
|
||||||
|
// {904862B4-EB3F-461E-ACB2-4DF2B3FC898B}
|
||||||
|
const GUID FspMainFileOpenEcpGuid =
|
||||||
|
{ 0x904862b4, 0xeb3f, 0x461e, { 0xac, 0xb2, 0x4d, 0xf2, 0xb3, 0xfc, 0x89, 0x8b } };
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -38,6 +38,13 @@ static NTSTATUS FspFsvolQueryPositionInformation(PFILE_OBJECT FileObject,
|
|||||||
static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd,
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
||||||
|
FSP_FSCTL_STREAM_INFO *StreamInfoBuffer, ULONG StreamInfoBufferSize,
|
||||||
|
PVOID DestBuf, PULONG PDestLen);
|
||||||
|
static NTSTATUS FspFsvolQueryStreamInformation(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
static NTSTATUS FspFsvolQueryStreamInformationSuccess(
|
||||||
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
static NTSTATUS FspFsvolQueryInformation(
|
static NTSTATUS FspFsvolQueryInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
|
||||||
@ -78,6 +85,9 @@ FSP_DRIVER_DISPATCH FspSetInformation;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryPositionInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryPositionInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationCopy)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationSuccess)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInformationComplete)
|
#pragma alloc_text(PAGE, FspFsvolQueryInformationComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini)
|
||||||
@ -349,6 +359,235 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
||||||
|
FSP_FSCTL_STREAM_INFO *StreamInfo, ULONG StreamInfoSize,
|
||||||
|
PVOID DestBuf, PULONG PDestLen)
|
||||||
|
{
|
||||||
|
#define STREAM_TYPE ":$DATA"
|
||||||
|
#define STREAM_TYPE_LENGTH (sizeof L"" STREAM_TYPE - sizeof(WCHAR))
|
||||||
|
#define STREAM_EXTRA_LENGTH (sizeof L":" STREAM_TYPE - sizeof(WCHAR))
|
||||||
|
#define FILL_INFO()\
|
||||||
|
do\
|
||||||
|
{\
|
||||||
|
FILE_STREAM_INFORMATION InfoStruct = { 0 }, *Info = &InfoStruct;\
|
||||||
|
Info->NextEntryOffset = 0;\
|
||||||
|
Info->StreamNameLength = StreamNameLength;\
|
||||||
|
Info->StreamSize.QuadPart = StreamInfo->StreamSize;\
|
||||||
|
Info->StreamAllocationSize.QuadPart = StreamInfo->StreamAllocationSize;\
|
||||||
|
Info = DestBuf;\
|
||||||
|
RtlCopyMemory(Info, &InfoStruct, FIELD_OFFSET(FILE_STREAM_INFORMATION, StreamName));\
|
||||||
|
{\
|
||||||
|
PWSTR StreamName = Info->StreamName;\
|
||||||
|
ULONG Length[3];\
|
||||||
|
Length[0] = 0 < CopyLength ? sizeof(WCHAR) : 0;\
|
||||||
|
Length[1] = Info->StreamNameLength - STREAM_EXTRA_LENGTH < CopyLength - Length[0] ?\
|
||||||
|
Info->StreamNameLength - STREAM_EXTRA_LENGTH : CopyLength - Length[0];\
|
||||||
|
Length[2] = CopyLength - Length[0] - Length[1];\
|
||||||
|
ASSERT(\
|
||||||
|
sizeof(WCHAR) >= Length[0] &&\
|
||||||
|
Info->StreamNameLength - STREAM_EXTRA_LENGTH >= Length[1] &&\
|
||||||
|
STREAM_TYPE_LENGTH >= Length[2]);\
|
||||||
|
RtlCopyMemory(StreamName, L":", Length[0]);\
|
||||||
|
StreamName += Length[0] / sizeof(WCHAR);\
|
||||||
|
RtlCopyMemory(StreamName, StreamInfo->StreamNameBuf, Length[1]);\
|
||||||
|
StreamName += Length[1] / sizeof(WCHAR);\
|
||||||
|
RtlCopyMemory(StreamName, L"" STREAM_TYPE, Length[2]);\
|
||||||
|
}\
|
||||||
|
} while (0,0)
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
|
PUINT8 StreamInfoEnd = (PUINT8)StreamInfo + StreamInfoSize;
|
||||||
|
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
||||||
|
PUINT8 DestBufEnd = (PUINT8)DestBuf + *PDestLen;
|
||||||
|
PVOID PrevDestBuf = 0;
|
||||||
|
ULONG StreamNameLength, CopyLength;
|
||||||
|
ULONG BaseInfoLen = FIELD_OFFSET(FILE_STREAM_INFORMATION, StreamName);
|
||||||
|
|
||||||
|
*PDestLen = 0;
|
||||||
|
|
||||||
|
for (;
|
||||||
|
NT_SUCCESS(Result) && (PUINT8)StreamInfo + sizeof(StreamInfo->Size) <= StreamInfoEnd;
|
||||||
|
StreamInfo = (PVOID)((PUINT8)StreamInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(StreamInfoSize)))
|
||||||
|
{
|
||||||
|
StreamInfoSize = StreamInfo->Size;
|
||||||
|
|
||||||
|
if (sizeof(FSP_FSCTL_STREAM_INFO) > StreamInfoSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
StreamNameLength = StreamInfoSize - sizeof(FSP_FSCTL_STREAM_INFO) + STREAM_EXTRA_LENGTH;
|
||||||
|
|
||||||
|
/* CopyLength is the same as StreamNameLength except on STATUS_BUFFER_OVERFLOW */
|
||||||
|
CopyLength = StreamNameLength;
|
||||||
|
|
||||||
|
/* do we have enough space for this stream info? */
|
||||||
|
if ((PUINT8)DestBuf + BaseInfoLen + CopyLength > DestBufEnd)
|
||||||
|
{
|
||||||
|
/* can we even copy the base info? */
|
||||||
|
if ((PUINT8)DestBuf + BaseInfoLen > DestBufEnd)
|
||||||
|
{
|
||||||
|
if (0 == *PDestLen)
|
||||||
|
/* if we haven't copied anything yet, buffer is too small */
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else
|
||||||
|
/* *PDestLen contains bytes copied so far */
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy as much of the stream name as we can and return STATUS_BUFFER_OVERFLOW */
|
||||||
|
CopyLength = (ULONG)(DestBufEnd - ((PUINT8)DestBuf + BaseInfoLen));
|
||||||
|
Result = STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill in NextEntryOffset */
|
||||||
|
if (0 != PrevDestBuf)
|
||||||
|
*(PULONG)PrevDestBuf = (ULONG)((PUINT8)DestBuf - (PUINT8)PrevDestBuf);
|
||||||
|
PrevDestBuf = DestBuf;
|
||||||
|
|
||||||
|
/* update bytes copied */
|
||||||
|
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
|
||||||
|
|
||||||
|
FILL_INFO();
|
||||||
|
|
||||||
|
/* advance DestBuf; make sure to align properly! */
|
||||||
|
DestBuf = (PVOID)((PUINT8)DestBuf +
|
||||||
|
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* our code flow should allow only these two status codes here */
|
||||||
|
ASSERT(STATUS_SUCCESS == Result || STATUS_BUFFER_OVERFLOW == Result);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
#undef FILL_INFO
|
||||||
|
#undef STREAM_EXTRA_LENGTH
|
||||||
|
#undef STREAM_TYPE_LENGTH
|
||||||
|
#undef STREAM_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryStreamInformation(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (!FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.NamedStreams)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ULONG Length = IrpSp->Parameters.QueryFile.Length;
|
||||||
|
PVOID StreamInfoBuffer;
|
||||||
|
ULONG StreamInfoBufferSize;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
|
||||||
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
|
FspFileNodeAcquireShared(FileNode, Main);
|
||||||
|
if (FspFileNodeReferenceStreamInfo(FileNode, &StreamInfoBuffer, &StreamInfoBufferSize))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
Result = FspFsvolQueryStreamInformationCopy(
|
||||||
|
StreamInfoBuffer, StreamInfoBufferSize, Buffer, &Length);
|
||||||
|
|
||||||
|
FspFileNodeDereferenceStreamInfo(StreamInfoBuffer);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = Length;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeAcquireShared(FileNode, Pgio);
|
||||||
|
|
||||||
|
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolQueryInformationRequestFini, &Request);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request->Kind = FspFsctlTransactQueryStreamInformationKind;
|
||||||
|
Request->Req.QueryStreamInformation.UserContext = FileNode->UserContext;
|
||||||
|
Request->Req.QueryStreamInformation.UserContext2 = FileDesc->UserContext2;
|
||||||
|
|
||||||
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
||||||
|
|
||||||
|
return FSP_STATUS_IOQ_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryStreamInformationSuccess(
|
||||||
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (!FspFsvolDeviceExtension(IoGetCurrentIrpStackLocation(Irp)->DeviceObject)->
|
||||||
|
VolumeParams.NamedStreams)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ULONG Length = IrpSp->Parameters.QueryFile.Length;
|
||||||
|
PVOID StreamInfoBuffer = 0;
|
||||||
|
ULONG StreamInfoBufferSize = 0;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
|
BOOLEAN Success;
|
||||||
|
|
||||||
|
if (0 != FspIopRequestContext(Request, RequestFileNode))
|
||||||
|
{
|
||||||
|
/* check that the stream info we got back is valid */
|
||||||
|
if (Response->Buffer + Response->Rsp.QueryStreamInformation.Buffer.Size >
|
||||||
|
(PUINT8)Response + Response->Size)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_INFO_LENGTH_MISMATCH; /* ???: what is the best code to return here? */
|
||||||
|
}
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestInfoChangeNumber) = (PVOID)
|
||||||
|
FspFileNodeStreamInfoChangeNumber(FileNode);
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||||
|
|
||||||
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = DEBUGTEST(90) && FspFileNodeTryAcquireExclusive(FileNode, Main);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
FspIopRetryCompleteIrp(Irp, Response, &Result);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = !FspFileNodeTrySetStreamInfo(FileNode,
|
||||||
|
Response->Buffer, Response->Rsp.QueryStreamInformation.Buffer.Size,
|
||||||
|
(ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestInfoChangeNumber));
|
||||||
|
Success = Success &&
|
||||||
|
FspFileNodeReferenceStreamInfo(FileNode, &StreamInfoBuffer, &StreamInfoBufferSize);
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
Result = FspFsvolQueryStreamInformationCopy(
|
||||||
|
StreamInfoBuffer, StreamInfoBufferSize, Buffer, &Length);
|
||||||
|
FspFileNodeDereferenceStreamInfo(StreamInfoBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StreamInfoBuffer = (PVOID)Response->Buffer;
|
||||||
|
StreamInfoBufferSize = Response->Rsp.QueryStreamInformation.Buffer.Size;
|
||||||
|
Result = FspFsvolQueryStreamInformationCopy(
|
||||||
|
StreamInfoBuffer, StreamInfoBufferSize, Buffer, &Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = Length;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryInformation(
|
static NTSTATUS FspFsvolQueryInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -358,8 +597,13 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
NTSTATUS Result;
|
|
||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
|
||||||
|
|
||||||
|
/* special case FileStreamInformation */
|
||||||
|
if (FileStreamInformation == FileInformationClass)
|
||||||
|
return FspFsvolQueryStreamInformation(FsvolDeviceObject, Irp, IrpSp);
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
@ -415,9 +659,6 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
case FileStandardInformation:
|
case FileStandardInformation:
|
||||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, 0);
|
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||||
break;
|
break;
|
||||||
case FileStreamInformation:
|
|
||||||
Result = STATUS_INVALID_PARAMETER; /* !!!: no stream support yet! */
|
|
||||||
return Result;
|
|
||||||
default:
|
default:
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
return Result;
|
return Result;
|
||||||
@ -496,6 +737,11 @@ NTSTATUS FspFsvolQueryInformationComplete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
|
||||||
|
|
||||||
|
/* special case FileStreamInformation */
|
||||||
|
if (FileStreamInformation == FileInformationClass)
|
||||||
|
FSP_RETURN(Result = FspFsvolQueryStreamInformationSuccess(Irp, Response));
|
||||||
|
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
|
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
@ -507,7 +753,8 @@ NTSTATUS FspFsvolQueryInformationComplete(
|
|||||||
|
|
||||||
if (0 != FspIopRequestContext(Request, RequestFileNode))
|
if (0 != FspIopRequestContext(Request, RequestFileNode))
|
||||||
{
|
{
|
||||||
FspIopRequestContext(Request, RequestInfoChangeNumber) = (PVOID)FileNode->InfoChangeNumber;
|
FspIopRequestContext(Request, RequestInfoChangeNumber) = (PVOID)
|
||||||
|
FspFileNodeFileInfoChangeNumber(FileNode);
|
||||||
FspIopRequestContext(Request, RequestFileNode) = 0;
|
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||||
|
|
||||||
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
@ -869,7 +1116,7 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
if (FileNode->IsRootDirectory)
|
if (FileNode->IsRootDirectory)
|
||||||
/* cannot rename root directory */
|
/* cannot rename root directory */
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
if (!FspUnicodePathIsValid(&FileNode->FileName, FALSE))
|
if (!FspUnicodePathIsValid(&FileNode->FileName, 0, 0))
|
||||||
/* cannot rename streams (WinFsp limitation) */
|
/* cannot rename streams (WinFsp limitation) */
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
@ -894,7 +1141,7 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
if (L'\\' == Suffix.Buffer[0])
|
if (L'\\' == Suffix.Buffer[0])
|
||||||
FspUnicodePathSuffix(&Suffix, &NewFileName, &Suffix);
|
FspUnicodePathSuffix(&Suffix, &NewFileName, &Suffix);
|
||||||
|
|
||||||
if (!FspUnicodePathIsValid(&Remain, FALSE) || !FspUnicodePathIsValid(&Suffix, FALSE))
|
if (!FspUnicodePathIsValid(&Remain, 0, 0) || !FspUnicodePathIsValid(&Suffix, 0, 0))
|
||||||
{
|
{
|
||||||
/* cannot rename streams (WinFsp limitation) */
|
/* cannot rename streams (WinFsp limitation) */
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -146,7 +146,8 @@ NTSTATUS FspFsvolQuerySecurityComplete(
|
|||||||
FSP_RETURN();
|
FSP_RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
FspIopRequestContext(Request, RequestSecurityChangeNumber) = (PVOID)FileNode->SecurityChangeNumber;
|
FspIopRequestContext(Request, RequestSecurityChangeNumber) = (PVOID)
|
||||||
|
FspFileNodeSecurityChangeNumber(FileNode);
|
||||||
FspIopRequestContext(Request, RequestFileNode) = 0;
|
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||||
|
|
||||||
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
128
src/sys/util.c
128
src/sys/util.c
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -17,7 +17,8 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams);
|
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PULONG StreamType);
|
||||||
|
BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Pattern);
|
||||||
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
@ -88,6 +89,7 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
|||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspUnicodePathIsValid)
|
#pragma alloc_text(PAGE, FspUnicodePathIsValid)
|
||||||
|
#pragma alloc_text(PAGE, FspUnicodePathIsValidPattern)
|
||||||
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
||||||
#pragma alloc_text(PAGE, FspCreateGuid)
|
#pragma alloc_text(PAGE, FspCreateGuid)
|
||||||
#pragma alloc_text(PAGE, FspGetDeviceObjectPointer)
|
#pragma alloc_text(PAGE, FspGetDeviceObjectPointer)
|
||||||
@ -169,32 +171,138 @@ PVOID FspAllocateIrpMustSucceed(CCHAR StackSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams)
|
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PULONG StreamType)
|
||||||
{
|
{
|
||||||
/* this does NOT check if the Path contains invalid file name chars (*, ?, etc.) */
|
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* if StreamPart is not NULL, StreamType must also be not NULL */
|
||||||
|
ASSERT(0 == StreamPart || 0 != StreamType);
|
||||||
|
|
||||||
if (0 != Path->Length % sizeof(WCHAR))
|
if (0 != Path->Length % sizeof(WCHAR))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
PWSTR PathBgn, PathEnd, PathPtr;
|
PWSTR PathBgn, PathEnd, PathPtr, StreamTypeStr = 0;
|
||||||
|
UCHAR Flags = FSRTL_NTFS_LEGAL;
|
||||||
|
ULONG Colons = 0;
|
||||||
|
WCHAR Char;
|
||||||
|
|
||||||
PathBgn = Path->Buffer;
|
PathBgn = Path->Buffer;
|
||||||
PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length);
|
PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length);
|
||||||
PathPtr = PathBgn;
|
PathPtr = PathBgn;
|
||||||
|
|
||||||
while (PathEnd > PathPtr)
|
while (PathEnd > PathPtr)
|
||||||
if (L'\\' == *PathPtr)
|
|
||||||
{
|
{
|
||||||
|
Char = *PathPtr;
|
||||||
|
|
||||||
|
if (L'\\' == Char)
|
||||||
|
{
|
||||||
|
/* stream names can only appear as the last path component */
|
||||||
|
if (0 < Colons)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
PathPtr++;
|
PathPtr++;
|
||||||
|
|
||||||
|
/* don't like multiple backslashes */
|
||||||
if (PathEnd > PathPtr && L'\\' == *PathPtr)
|
if (PathEnd > PathPtr && L'\\' == *PathPtr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (!AllowStreams && L':' == *PathPtr)
|
else if (L':' == Char)
|
||||||
|
{
|
||||||
|
if (0 == StreamPart)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Where are the docs on legal stream names?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* stream characters now allowed */
|
||||||
|
Flags = FSRTL_NTFS_STREAM_LEGAL;
|
||||||
|
|
||||||
|
PathPtr++;
|
||||||
|
Colons++;
|
||||||
|
|
||||||
|
if (1 == Colons)
|
||||||
|
{
|
||||||
|
/* first time through: set up StreamPart */
|
||||||
|
StreamPart->Length = StreamPart->MaximumLength = (USHORT)
|
||||||
|
((PUINT8)PathEnd - (PUINT8)PathPtr);
|
||||||
|
StreamPart->Buffer = PathPtr;
|
||||||
|
}
|
||||||
|
else if (2 == Colons)
|
||||||
|
{
|
||||||
|
/* second time through: fix StreamPart length to not include 2nd colon */
|
||||||
|
StreamPart->Length = (USHORT)
|
||||||
|
((PUINT8)PathPtr - (PUINT8)StreamPart->Buffer - sizeof(WCHAR));
|
||||||
|
|
||||||
|
StreamTypeStr = PathPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (0x80 > Char && !FsRtlTestAnsiCharacter(Char, TRUE, FALSE, Flags))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
PathPtr++;
|
PathPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we had no colons the path is valid */
|
||||||
|
if (0 == Colons)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
ASSERT(0 != StreamPart && 0 != StreamType);
|
||||||
|
|
||||||
|
*StreamType = FspUnicodePathStreamTypeNone;
|
||||||
|
|
||||||
|
/* if we had no stream type the path is valid if there was an actual stream name */
|
||||||
|
if (0 == StreamTypeStr)
|
||||||
|
return 0 != StreamPart->Length;
|
||||||
|
|
||||||
|
/* if we had a stream type the path is valid if the stream type was "$DATA" only */
|
||||||
|
if (StreamTypeStr + 5 == PathEnd &&
|
||||||
|
L'$' == StreamTypeStr[0] &&
|
||||||
|
L'D' == StreamTypeStr[1] &&
|
||||||
|
L'A' == StreamTypeStr[2] &&
|
||||||
|
L'T' == StreamTypeStr[3] &&
|
||||||
|
L'A' == StreamTypeStr[4])
|
||||||
|
{
|
||||||
|
*StreamType = FspUnicodePathStreamTypeData;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Path)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != Path->Length % sizeof(WCHAR))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
PWSTR PathBgn, PathEnd, PathPtr;
|
||||||
|
WCHAR Char;
|
||||||
|
|
||||||
|
PathBgn = Path->Buffer;
|
||||||
|
PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length);
|
||||||
|
PathPtr = PathBgn;
|
||||||
|
|
||||||
|
while (PathEnd > PathPtr)
|
||||||
|
{
|
||||||
|
Char = *PathPtr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A pattern is allowed to have wildcards. It cannot consist of multiple
|
||||||
|
* path components (have a backslash) and it cannot reference a stream (have
|
||||||
|
* a colon).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (L'\\' == Char)
|
||||||
|
return FALSE;
|
||||||
|
else if (L':' == Char)
|
||||||
|
return FALSE;
|
||||||
|
else if (0x80 > Char && !FsRtlTestAnsiCharacter(Char, TRUE, TRUE, FSRTL_NTFS_LEGAL))
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
PathPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -79,6 +79,10 @@ static NTSTATUS FspFsvolQueryFsAttributeInformation(
|
|||||||
PFILE_FS_ATTRIBUTE_INFORMATION Info = (PFILE_FS_ATTRIBUTE_INFORMATION)*PBuffer;
|
PFILE_FS_ATTRIBUTE_INFORMATION Info = (PFILE_FS_ATTRIBUTE_INFORMATION)*PBuffer;
|
||||||
PUINT8 Buffer = (PUINT8)Info->FileSystemName;
|
PUINT8 Buffer = (PUINT8)Info->FileSystemName;
|
||||||
ULONG CopyLength;
|
ULONG CopyLength;
|
||||||
|
UNICODE_STRING FileSystemName;
|
||||||
|
WCHAR FileSystemNameBuf[16 + FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||||
|
|
||||||
|
ASSERT(sizeof FileSystemNameBuf >= sizeof L"" DRIVER_NAME + FSP_FSCTL_VOLUME_FSNAME_SIZE);
|
||||||
|
|
||||||
Info->FileSystemAttributes =
|
Info->FileSystemAttributes =
|
||||||
(FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch ? FILE_CASE_SENSITIVE_SEARCH : 0) |
|
(FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch ? FILE_CASE_SENSITIVE_SEARCH : 0) |
|
||||||
@ -91,15 +95,27 @@ static NTSTATUS FspFsvolQueryFsAttributeInformation(
|
|||||||
//(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) |
|
//(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) |
|
||||||
(FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0);
|
(FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0);
|
||||||
Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength;
|
Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength;
|
||||||
Info->FileSystemNameLength = sizeof L"" DRIVER_NAME - sizeof(WCHAR);
|
|
||||||
|
|
||||||
CopyLength = Info->FileSystemNameLength;
|
RtlInitUnicodeString(&FileSystemName, FsvolDeviceExtension->VolumeParams.FileSystemName);
|
||||||
|
|
||||||
|
CopyLength = sizeof L"" DRIVER_NAME - sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(FileSystemNameBuf, L"" DRIVER_NAME, CopyLength);
|
||||||
|
if (0 != FileSystemName.Length)
|
||||||
|
{
|
||||||
|
FileSystemNameBuf[CopyLength / sizeof(WCHAR)] = L'-';
|
||||||
|
CopyLength += sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(FileSystemNameBuf + CopyLength / sizeof(WCHAR), FileSystemName.Buffer,
|
||||||
|
FileSystemName.Length);
|
||||||
|
CopyLength += FileSystemName.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info->FileSystemNameLength = CopyLength;
|
||||||
if (Buffer + CopyLength > BufferEnd)
|
if (Buffer + CopyLength > BufferEnd)
|
||||||
{
|
{
|
||||||
CopyLength = (ULONG)(BufferEnd - Buffer);
|
CopyLength = (ULONG)(BufferEnd - Buffer);
|
||||||
Result = STATUS_BUFFER_OVERFLOW;
|
Result = STATUS_BUFFER_OVERFLOW;
|
||||||
}
|
}
|
||||||
RtlCopyMemory(Buffer, L"" DRIVER_NAME, CopyLength);
|
RtlCopyMemory(Buffer, FileSystemNameBuf, CopyLength);
|
||||||
Buffer += CopyLength;
|
Buffer += CopyLength;
|
||||||
|
|
||||||
*PBuffer = Buffer;
|
*PBuffer = Buffer;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -169,6 +169,7 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
if (I == PrefixLength)
|
if (I == PrefixLength)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
VolumeParams.FileSystemName[sizeof VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
|
||||||
/* create volume guid */
|
/* create volume guid */
|
||||||
Result = FspCreateGuid(&Guid);
|
Result = FspCreateGuid(&Guid);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
14
tools/ntstatus.bat
Normal file
14
tools/ntstatus.bat
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
if X%1==X (echo usage: %~n0 VALUE >&2 & exit /b 1)
|
||||||
|
|
||||||
|
set RegKey="HKLM\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
||||||
|
set RegVal="KitsRoot10"
|
||||||
|
reg query %RegKey% /v %RegVal% >nul 2>&1 || (echo Cannot find Windows Kit >&2 & exit /b 1)
|
||||||
|
for /f "tokens=2,*" %%i in ('reg query %RegKey% /v %RegVal% ^| findstr %RegVal%') do (
|
||||||
|
set KitRoot=%%j
|
||||||
|
)
|
||||||
|
|
||||||
|
findstr /R /I "\<0*[Xx]*%1[Ll]*\>" "%KitRoot%Include\10.0.10586.0\shared\%~n0.h"
|
@ -75,34 +75,42 @@ exit /b 1
|
|||||||
M:
|
M:
|
||||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -f foo -N 5000 test xxxxxx
|
||||||
|
if errorlevel 1 goto fail
|
||||||
N:
|
N:
|
||||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -f foo -N 5000 test xxxxxx
|
||||||
|
if errorlevel 1 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:fsx-memfs-x86
|
:fsx-memfs-x86
|
||||||
O:
|
O:
|
||||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -f foo -N 5000 test xxxxxx
|
||||||
|
if errorlevel 1 goto fail
|
||||||
P:
|
P:
|
||||||
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -N 5000 test xxxxxx
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
|
"%ProjRoot%\ext\test\fstools\src\fsx\fsx.exe" -f foo -N 5000 test xxxxxx
|
||||||
|
if errorlevel 1 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:winfstest-memfs-x64
|
:winfstest-memfs-x64
|
||||||
M:
|
M:
|
||||||
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat" base reparse
|
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat"
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
N:
|
N:
|
||||||
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat" base reparse
|
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat"
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:winfstest-memfs-x86
|
:winfstest-memfs-x86
|
||||||
O:
|
O:
|
||||||
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat" base reparse
|
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat"
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
P:
|
P:
|
||||||
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat" base reparse
|
call "%ProjRoot%\ext\test\winfstest\run-winfstest.bat"
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
14
tools/winerror.bat
Normal file
14
tools/winerror.bat
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
if X%1==X (echo usage: %~n0 VALUE >&2 & exit /b 1)
|
||||||
|
|
||||||
|
set RegKey="HKLM\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
||||||
|
set RegVal="KitsRoot10"
|
||||||
|
reg query %RegKey% /v %RegVal% >nul 2>&1 || (echo Cannot find Windows Kit >&2 & exit /b 1)
|
||||||
|
for /f "tokens=2,*" %%i in ('reg query %RegKey% /v %RegVal% ^| findstr %RegVal%') do (
|
||||||
|
set KitRoot=%%j
|
||||||
|
)
|
||||||
|
|
||||||
|
findstr /R /I "\<0*[Xx]*%1[Ll]*\>" "%KitRoot%Include\10.0.10586.0\shared\%~n0.h"
|
@ -11,9 +11,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -38,6 +38,7 @@ NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
{
|
{
|
||||||
wchar_t **argp, **arge;
|
wchar_t **argp, **arge;
|
||||||
ULONG DebugFlags = 0;
|
ULONG DebugFlags = 0;
|
||||||
|
PWSTR DebugLogFile = 0;
|
||||||
ULONG Flags = MemfsDisk;
|
ULONG Flags = MemfsDisk;
|
||||||
ULONG FileInfoTimeout = INFINITE;
|
ULONG FileInfoTimeout = INFINITE;
|
||||||
ULONG MaxFileNodes = 1024;
|
ULONG MaxFileNodes = 1024;
|
||||||
@ -45,6 +46,7 @@ NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
PWSTR MountPoint = 0;
|
PWSTR MountPoint = 0;
|
||||||
PWSTR VolumePrefix = 0;
|
PWSTR VolumePrefix = 0;
|
||||||
PWSTR RootSddl = 0;
|
PWSTR RootSddl = 0;
|
||||||
|
HANDLE DebugLogHandle = INVALID_HANDLE_VALUE;
|
||||||
MEMFS *Memfs = 0;
|
MEMFS *Memfs = 0;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
@ -59,6 +61,9 @@ NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
case L'd':
|
case L'd':
|
||||||
argtol(DebugFlags);
|
argtol(DebugFlags);
|
||||||
break;
|
break;
|
||||||
|
case L'D':
|
||||||
|
argtos(DebugLogFile);
|
||||||
|
break;
|
||||||
case L'm':
|
case L'm':
|
||||||
argtos(MountPoint);
|
argtos(MountPoint);
|
||||||
break;
|
break;
|
||||||
@ -90,6 +95,28 @@ NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
if (MemfsDisk == Flags && 0 == MountPoint)
|
if (MemfsDisk == Flags && 0 == MountPoint)
|
||||||
goto usage;
|
goto usage;
|
||||||
|
|
||||||
|
if (0 != DebugLogFile)
|
||||||
|
{
|
||||||
|
if (0 == wcscmp(L"-", DebugLogFile))
|
||||||
|
DebugLogHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
else
|
||||||
|
DebugLogHandle = CreateFileW(
|
||||||
|
DebugLogFile,
|
||||||
|
FILE_APPEND_DATA,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
0,
|
||||||
|
OPEN_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == DebugLogHandle)
|
||||||
|
{
|
||||||
|
fail(L"cannot open debug log file");
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspDebugLogSetHandle(DebugLogHandle);
|
||||||
|
}
|
||||||
|
|
||||||
Result = MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl,
|
Result = MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl,
|
||||||
&Memfs);
|
&Memfs);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -142,6 +169,7 @@ usage:
|
|||||||
"\n"
|
"\n"
|
||||||
"options:\n"
|
"options:\n"
|
||||||
" -d DebugFlags [-1: enable all debug logs]\n"
|
" -d DebugFlags [-1: enable all debug logs]\n"
|
||||||
|
" -D DebugLogFile [file path; use - for stdout]\n"
|
||||||
" -t FileInfoTimeout [millis]\n"
|
" -t FileInfoTimeout [millis]\n"
|
||||||
" -n MaxFileNodes\n"
|
" -n MaxFileNodes\n"
|
||||||
" -s MaxFileSize [bytes]\n"
|
" -s MaxFileSize [bytes]\n"
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
@ -22,6 +22,11 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the MEMFS_NAMED_STREAMS macro to include named streams support.
|
||||||
|
*/
|
||||||
|
#define MEMFS_NAMED_STREAMS
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
||||||
* a check for the Write buffer to ensure that it is read-only.
|
* a check for the Write buffer to ensure that it is read-only.
|
||||||
@ -50,7 +55,16 @@ int MemfsFileNameCompare(PWSTR a, PWSTR b)
|
|||||||
static inline
|
static inline
|
||||||
BOOLEAN MemfsFileNameHasPrefix(PWSTR a, PWSTR b)
|
BOOLEAN MemfsFileNameHasPrefix(PWSTR a, PWSTR b)
|
||||||
{
|
{
|
||||||
return 0 == wcsncmp(a, b, wcslen(b));
|
size_t alen = wcslen(a);
|
||||||
|
size_t blen = wcslen(b);
|
||||||
|
|
||||||
|
return alen >= blen && 0 == memcmp(a, b, blen * sizeof(WCHAR)) &&
|
||||||
|
(alen == blen || (1 == blen && L'\\' == b[0]) ||
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
(L'\\' == a[blen] || L':' == a[blen]));
|
||||||
|
#else
|
||||||
|
(L'\\' == a[blen]));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _MEMFS_FILE_NODE
|
typedef struct _MEMFS_FILE_NODE
|
||||||
@ -63,6 +77,9 @@ typedef struct _MEMFS_FILE_NODE
|
|||||||
SIZE_T ReparseDataSize;
|
SIZE_T ReparseDataSize;
|
||||||
PVOID ReparseData;
|
PVOID ReparseData;
|
||||||
ULONG RefCount;
|
ULONG RefCount;
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
struct _MEMFS_FILE_NODE *MainFileNode;
|
||||||
|
#endif
|
||||||
} MEMFS_FILE_NODE;
|
} MEMFS_FILE_NODE;
|
||||||
|
|
||||||
struct MEMFS_FILE_NODE_LESS
|
struct MEMFS_FILE_NODE_LESS
|
||||||
@ -121,6 +138,25 @@ VOID MemfsFileNodeDelete(MEMFS_FILE_NODE *FileNode)
|
|||||||
free(FileNode);
|
free(FileNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
if (0 == FileNode->MainFileNode)
|
||||||
|
*FileInfo = FileNode->FileInfo;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*FileInfo = FileNode->MainFileNode->FileInfo;
|
||||||
|
FileInfo->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
/* named streams cannot be directories */
|
||||||
|
FileInfo->AllocationSize = FileNode->FileInfo.AllocationSize;
|
||||||
|
FileInfo->FileSize = FileNode->FileInfo.FileSize;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
*FileInfo = FileNode->FileInfo;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
VOID MemfsFileNodeMapDump(MEMFS_FILE_NODE_MAP *FileNodeMap)
|
VOID MemfsFileNodeMapDump(MEMFS_FILE_NODE_MAP *FileNodeMap)
|
||||||
{
|
{
|
||||||
@ -171,6 +207,23 @@ MEMFS_FILE_NODE *MemfsFileNodeMapGet(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR Fil
|
|||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
static inline
|
||||||
|
MEMFS_FILE_NODE *MemfsFileNodeMapGetMain(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0)
|
||||||
|
{
|
||||||
|
WCHAR FileName[MAX_PATH];
|
||||||
|
wcscpy_s(FileName, sizeof FileName / sizeof(WCHAR), FileName0);
|
||||||
|
PWSTR StreamName = wcschr(FileName, L':');
|
||||||
|
if (0 == StreamName)
|
||||||
|
return 0;
|
||||||
|
StreamName[0] = L'\0';
|
||||||
|
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->find(FileName);
|
||||||
|
if (iter == FileNodeMap->end())
|
||||||
|
return 0;
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
MEMFS_FILE_NODE *MemfsFileNodeMapGetParent(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0,
|
MEMFS_FILE_NODE *MemfsFileNodeMapGetParent(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0,
|
||||||
PNTSTATUS PResult)
|
PNTSTATUS PResult)
|
||||||
@ -223,15 +276,21 @@ VOID MemfsFileNodeMapRemove(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *F
|
|||||||
static inline
|
static inline
|
||||||
BOOLEAN MemfsFileNodeMapHasChild(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode)
|
BOOLEAN MemfsFileNodeMapHasChild(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode)
|
||||||
{
|
{
|
||||||
BOOLEAN Result;
|
BOOLEAN Result = FALSE;
|
||||||
WCHAR Root[2] = L"\\";
|
WCHAR Root[2] = L"\\";
|
||||||
PWSTR Remain, Suffix;
|
PWSTR Remain, Suffix;
|
||||||
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName);
|
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName);
|
||||||
if (iter == FileNodeMap->end())
|
for (; FileNodeMap->end() != iter; ++iter)
|
||||||
return FALSE;
|
{
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
if (0 != wcschr(iter->second->FileName, L':'))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root);
|
FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root);
|
||||||
Result = 0 == MemfsFileNameCompare(Remain, FileNode->FileName);
|
Result = 0 == MemfsFileNameCompare(Remain, FileNode->FileName);
|
||||||
FspPathCombine(iter->second->FileName, Suffix);
|
FspPathCombine(iter->second->FileName, Suffix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,15 +301,18 @@ BOOLEAN MemfsFileNodeMapEnumerateChildren(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMF
|
|||||||
WCHAR Root[2] = L"\\";
|
WCHAR Root[2] = L"\\";
|
||||||
PWSTR Remain, Suffix;
|
PWSTR Remain, Suffix;
|
||||||
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName);
|
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName);
|
||||||
BOOLEAN Equal;
|
BOOLEAN IsDirectoryChild;
|
||||||
for (; FileNodeMap->end() != iter; ++iter)
|
for (; FileNodeMap->end() != iter; ++iter)
|
||||||
{
|
{
|
||||||
if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName))
|
if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName))
|
||||||
break;
|
break;
|
||||||
FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root);
|
FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root);
|
||||||
Equal = 0 == MemfsFileNameCompare(Remain, FileNode->FileName);
|
IsDirectoryChild = 0 == MemfsFileNameCompare(Remain, FileNode->FileName);
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
IsDirectoryChild = IsDirectoryChild && 0 == wcschr(Suffix, L':');
|
||||||
|
#endif
|
||||||
FspPathCombine(iter->second->FileName, Suffix);
|
FspPathCombine(iter->second->FileName, Suffix);
|
||||||
if (Equal)
|
if (IsDirectoryChild)
|
||||||
{
|
{
|
||||||
if (!EnumFn(iter->second, Context))
|
if (!EnumFn(iter->second, Context))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -259,6 +321,25 @@ BOOLEAN MemfsFileNodeMapEnumerateChildren(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMF
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
static inline
|
||||||
|
BOOLEAN MemfsFileNodeMapEnumerateNamedStreams(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode,
|
||||||
|
BOOLEAN (*EnumFn)(MEMFS_FILE_NODE *, PVOID), PVOID Context)
|
||||||
|
{
|
||||||
|
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName);
|
||||||
|
for (; FileNodeMap->end() != iter; ++iter)
|
||||||
|
{
|
||||||
|
if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName))
|
||||||
|
break;
|
||||||
|
if (L':' != iter->second->FileName[wcslen(FileNode->FileName)])
|
||||||
|
break;
|
||||||
|
if (!EnumFn(iter->second, Context))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode,
|
BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode,
|
||||||
BOOLEAN (*EnumFn)(MEMFS_FILE_NODE *, PVOID), PVOID Context)
|
BOOLEAN (*EnumFn)(MEMFS_FILE_NODE *, PVOID), PVOID Context)
|
||||||
@ -342,8 +423,20 @@ static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
UINT32 FileAttributesMask = ~(UINT32)0;
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != PFileAttributes)
|
||||||
|
*PFileAttributes = FileNode->FileInfo.FileAttributes & FileAttributesMask;
|
||||||
|
#else
|
||||||
if (0 != PFileAttributes)
|
if (0 != PFileAttributes)
|
||||||
*PFileAttributes = FileNode->FileInfo.FileAttributes;
|
*PFileAttributes = FileNode->FileInfo.FileAttributes;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (0 != PSecurityDescriptorSize)
|
if (0 != PSecurityDescriptorSize)
|
||||||
{
|
{
|
||||||
@ -392,6 +485,10 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
FileNode->FileInfo.FileAttributes = (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
FileNode->FileInfo.FileAttributes = (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
||||||
FileAttributes : FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
FileAttributes : FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
|
||||||
@ -429,7 +526,7 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
FileNode->RefCount++;
|
FileNode->RefCount++;
|
||||||
*PFileNode = FileNode;
|
*PFileNode = FileNode;
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -467,7 +564,7 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
FileNode->RefCount++;
|
FileNode->RefCount++;
|
||||||
*PFileNode = FileNode;
|
*PFileNode = FileNode;
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -489,11 +586,28 @@ NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FileNode->FileInfo.LastWriteTime =
|
FileNode->FileInfo.LastWriteTime =
|
||||||
FileNode->FileInfo.LastAccessTime = MemfsGetSystemTime();
|
FileNode->FileInfo.LastAccessTime = MemfsGetSystemTime();
|
||||||
|
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
typedef struct _MEMFS_CLEANUP_CONTEXT
|
||||||
|
{
|
||||||
|
MEMFS_FILE_NODE **FileNodes;
|
||||||
|
ULONG Count;
|
||||||
|
} MEMFS_CLEANUP_CONTEXT;
|
||||||
|
|
||||||
|
static BOOLEAN CleanupEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
|
||||||
|
{
|
||||||
|
MEMFS_CLEANUP_CONTEXT *Context = (MEMFS_CLEANUP_CONTEXT *)Context0;
|
||||||
|
|
||||||
|
Context->FileNodes[Context->Count++] = FileNode;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
PVOID FileNode0, PWSTR FileName, BOOLEAN Delete)
|
PVOID FileNode0, PWSTR FileName, BOOLEAN Delete)
|
||||||
@ -502,10 +616,27 @@ static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
|
||||||
assert(0 == FileName || 0 == wcscmp(FileNode->FileName, FileName));
|
assert(0 == FileName || 0 == wcscmp(FileNode->FileName, FileName));
|
||||||
|
assert(Delete); /* the new FSP_FSCTL_VOLUME_PARAMS::PostCleanupOnDeleteOnly ensures this */
|
||||||
|
|
||||||
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
||||||
|
{
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
MEMFS_CLEANUP_CONTEXT Context = { 0 };
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
Context.FileNodes = (MEMFS_FILE_NODE **)malloc(Memfs->MaxFileNodes * sizeof Context.FileNodes[0]);
|
||||||
|
if (0 != Context.FileNodes)
|
||||||
|
{
|
||||||
|
MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode, CleanupEnumFn, &Context);
|
||||||
|
for (Index = 0; Context.Count > Index; Index++)
|
||||||
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
|
||||||
|
free(Context.FileNodes);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
@ -585,7 +716,7 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memcpy((PUINT8)FileNode->FileData + Offset, Buffer, (size_t)(EndOffset - Offset));
|
memcpy((PUINT8)FileNode->FileData + Offset, Buffer, (size_t)(EndOffset - Offset));
|
||||||
|
|
||||||
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -605,7 +736,7 @@ static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -618,6 +749,11 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (INVALID_FILE_ATTRIBUTES != FileAttributes)
|
if (INVALID_FILE_ATTRIBUTES != FileAttributes)
|
||||||
FileNode->FileInfo.FileAttributes = FileAttributes;
|
FileNode->FileInfo.FileAttributes = FileAttributes;
|
||||||
if (0 != CreationTime)
|
if (0 != CreationTime)
|
||||||
@ -627,7 +763,7 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 != LastWriteTime)
|
if (0 != LastWriteTime)
|
||||||
FileNode->FileInfo.LastWriteTime = LastWriteTime;
|
FileNode->FileInfo.LastWriteTime = LastWriteTime;
|
||||||
|
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -680,7 +816,7 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*FileInfo = FileNode->FileInfo;
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -814,6 +950,11 @@ static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (FileNode->FileSecuritySize > *PSecurityDescriptorSize)
|
if (FileNode->FileSecuritySize > *PSecurityDescriptorSize)
|
||||||
{
|
{
|
||||||
*PSecurityDescriptorSize = FileNode->FileSecuritySize;
|
*PSecurityDescriptorSize = FileNode->FileSecuritySize;
|
||||||
@ -837,6 +978,11 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SIZE_T FileSecuritySize;
|
SIZE_T FileSecuritySize;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
#endif
|
||||||
|
|
||||||
Result = FspSetSecurityDescriptor(FileSystem, Request, FileNode->FileSecurity,
|
Result = FspSetSecurityDescriptor(FileSystem, Request, FileNode->FileSecurity,
|
||||||
&NewSecurityDescriptor);
|
&NewSecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -1064,6 +1210,72 @@ static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
typedef struct _MEMFS_GET_STREAM_INFO_CONTEXT
|
||||||
|
{
|
||||||
|
PVOID Buffer;
|
||||||
|
ULONG Length;
|
||||||
|
PULONG PBytesTransferred;
|
||||||
|
} MEMFS_GET_STREAM_INFO_CONTEXT;
|
||||||
|
|
||||||
|
static BOOLEAN AddStreamInfo(MEMFS_FILE_NODE *FileNode,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
UINT8 StreamInfoBuf[sizeof(FSP_FSCTL_STREAM_INFO) + sizeof FileNode->FileName];
|
||||||
|
FSP_FSCTL_STREAM_INFO *StreamInfo = (FSP_FSCTL_STREAM_INFO *)StreamInfoBuf;
|
||||||
|
PWSTR StreamName;
|
||||||
|
|
||||||
|
StreamName = wcschr(FileNode->FileName, L':');
|
||||||
|
if (0 != StreamName)
|
||||||
|
StreamName++;
|
||||||
|
else
|
||||||
|
StreamName = L"";
|
||||||
|
|
||||||
|
StreamInfo->Size = (UINT16)(sizeof(FSP_FSCTL_STREAM_INFO) + wcslen(StreamName) * sizeof(WCHAR));
|
||||||
|
StreamInfo->StreamSize = FileNode->FileInfo.FileSize;
|
||||||
|
StreamInfo->StreamAllocationSize = FileNode->FileInfo.AllocationSize;
|
||||||
|
memcpy(StreamInfo->StreamNameBuf, StreamName, StreamInfo->Size - sizeof(FSP_FSCTL_STREAM_INFO));
|
||||||
|
|
||||||
|
return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN GetStreamInfoEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
|
||||||
|
{
|
||||||
|
MEMFS_GET_STREAM_INFO_CONTEXT *Context = (MEMFS_GET_STREAM_INFO_CONTEXT *)Context0;
|
||||||
|
|
||||||
|
return AddStreamInfo(FileNode,
|
||||||
|
Context->Buffer, Context->Length, Context->PBytesTransferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS GetStreamInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
|
PVOID FileNode0, PVOID Buffer, ULONG Length,
|
||||||
|
PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
MEMFS_GET_STREAM_INFO_CONTEXT Context;
|
||||||
|
|
||||||
|
if (0 != FileNode->MainFileNode)
|
||||||
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
|
Context.Buffer = Buffer;
|
||||||
|
Context.Length = Length;
|
||||||
|
Context.PBytesTransferred = PBytesTransferred;
|
||||||
|
|
||||||
|
if (0 == (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
|
!AddStreamInfo(FileNode, Buffer, Length, PBytesTransferred))
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode, GetStreamInfoEnumFn, &Context))
|
||||||
|
FspFileSystemAddStreamInfo(0, Buffer, Length, PBytesTransferred);
|
||||||
|
|
||||||
|
/* ???: how to handle out of response buffer condition? */
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||||
{
|
{
|
||||||
GetVolumeInfo,
|
GetVolumeInfo,
|
||||||
@ -1089,6 +1301,11 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
|||||||
GetReparsePoint,
|
GetReparsePoint,
|
||||||
SetReparsePoint,
|
SetReparsePoint,
|
||||||
DeleteReparsePoint,
|
DeleteReparsePoint,
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
GetStreamInfo,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
NTSTATUS MemfsCreate(
|
NTSTATUS MemfsCreate(
|
||||||
@ -1151,8 +1368,13 @@ NTSTATUS MemfsCreate(
|
|||||||
VolumeParams.PersistentAcls = 1;
|
VolumeParams.PersistentAcls = 1;
|
||||||
VolumeParams.ReparsePoints = 1;
|
VolumeParams.ReparsePoints = 1;
|
||||||
VolumeParams.ReparsePointsAccessCheck = 0;
|
VolumeParams.ReparsePointsAccessCheck = 0;
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
VolumeParams.NamedStreams = 1;
|
||||||
|
#endif
|
||||||
|
VolumeParams.PostCleanupOnDeleteOnly = 1;
|
||||||
if (0 != VolumePrefix)
|
if (0 != VolumePrefix)
|
||||||
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
||||||
|
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR), L"MEMFS");
|
||||||
|
|
||||||
Result = FspFileSystemCreate(DevicePath, &VolumeParams, &MemfsInterface, &Memfs->FileSystem);
|
Result = FspFileSystemCreate(DevicePath, &VolumeParams, &MemfsInterface, &Memfs->FileSystem);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of WinFsp.
|
* This file is part of WinFsp.
|
||||||
*
|
*
|
||||||
* You can redistribute it and/or modify it under the terms of the
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
* GNU Affero General Public License version 3 as published by the
|
* General Public License version 3 as published by the Free Software
|
||||||
* Free Software Foundation.
|
* Foundation.
|
||||||
*
|
*
|
||||||
* Licensees holding a valid commercial license may use this file in
|
* Licensees holding a valid commercial license may use this file in
|
||||||
* accordance with the commercial license agreement provided with the
|
* accordance with the commercial license agreement provided with the
|
||||||
|
@ -68,6 +68,24 @@ void create_dotest(ULONG Flags, PWSTR Prefix)
|
|||||||
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* invalid chars (wildcards) not allowed */
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0*",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||||
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
|
|
||||||
|
/* stream names can only appear as the last path component */
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\DOESNOTEXIST:foo\\file0*",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||||
|
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||||
|
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1",
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1",
|
||||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
@ -226,10 +226,148 @@ void querydir_expire_cache_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _FILE_DIRECTORY_INFORMATION {
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
ULONG FileIndex;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
WCHAR FileName[1];
|
||||||
|
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NtQueryDirectoryFile (
|
||||||
|
_In_ HANDLE FileHandle,
|
||||||
|
_In_opt_ HANDLE Event,
|
||||||
|
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
|
||||||
|
_In_opt_ PVOID ApcContext,
|
||||||
|
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
|
_Out_writes_bytes_(Length) PVOID FileInformation,
|
||||||
|
_In_ ULONG Length,
|
||||||
|
_In_ FILE_INFORMATION_CLASS FileInformationClass,
|
||||||
|
_In_ BOOLEAN ReturnSingleEntry,
|
||||||
|
_In_opt_ PUNICODE_STRING FileName,
|
||||||
|
_In_ BOOLEAN RestartScan
|
||||||
|
);
|
||||||
|
|
||||||
|
static void querydir_buffer_overflow_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOL Success;
|
||||||
|
NTSTATUS Status;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
WCHAR FilePath[MAX_PATH];
|
||||||
|
FILE_DIRECTORY_INFORMATION DirInfo;
|
||||||
|
UNICODE_STRING Pattern;
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
|
||||||
|
Pattern.Length = Pattern.MaximumLength = sizeof L"file0" - sizeof(WCHAR);
|
||||||
|
Pattern.Buffer = L"file0";
|
||||||
|
|
||||||
|
memset(&DirInfo, 0, sizeof DirInfo);
|
||||||
|
Status = NtQueryDirectoryFile(
|
||||||
|
Handle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatus,
|
||||||
|
&DirInfo,
|
||||||
|
0,
|
||||||
|
FileDirectoryInformation,
|
||||||
|
FALSE,
|
||||||
|
&Pattern,
|
||||||
|
FALSE);
|
||||||
|
ASSERT(STATUS_INFO_LENGTH_MISMATCH == Status);
|
||||||
|
|
||||||
|
memset(&DirInfo, 0, sizeof DirInfo);
|
||||||
|
Status = NtQueryDirectoryFile(
|
||||||
|
Handle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatus,
|
||||||
|
&DirInfo,
|
||||||
|
sizeof(FILE_DIRECTORY_INFORMATION),
|
||||||
|
FileDirectoryInformation,
|
||||||
|
FALSE,
|
||||||
|
&Pattern,
|
||||||
|
FALSE);
|
||||||
|
ASSERT(STATUS_BUFFER_OVERFLOW == Status);
|
||||||
|
ASSERT(sizeof(FILE_DIRECTORY_INFORMATION) == IoStatus.Information);
|
||||||
|
ASSERT(Pattern.Length == DirInfo.FileNameLength);
|
||||||
|
|
||||||
|
memset(&DirInfo, 0, sizeof DirInfo);
|
||||||
|
Status = NtQueryDirectoryFile(
|
||||||
|
Handle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatus,
|
||||||
|
&DirInfo,
|
||||||
|
sizeof(FILE_DIRECTORY_INFORMATION),
|
||||||
|
FileDirectoryInformation,
|
||||||
|
TRUE,
|
||||||
|
&Pattern,
|
||||||
|
FALSE);
|
||||||
|
ASSERT(STATUS_BUFFER_OVERFLOW == Status);
|
||||||
|
ASSERT(sizeof(FILE_DIRECTORY_INFORMATION) == IoStatus.Information);
|
||||||
|
ASSERT(Pattern.Length == DirInfo.FileNameLength);
|
||||||
|
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Success = DeleteFileW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void querydir_buffer_overflow_test(void)
|
||||||
|
{
|
||||||
|
if (NtfsTests)
|
||||||
|
{
|
||||||
|
WCHAR DirBuf[MAX_PATH] = L"\\\\?\\";
|
||||||
|
GetCurrentDirectoryW(MAX_PATH - 4, DirBuf + 4);
|
||||||
|
querydir_buffer_overflow_dotest(-1, DirBuf, 0, 0);
|
||||||
|
}
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
{
|
||||||
|
querydir_buffer_overflow_dotest(MemfsDisk, 0, 0, 0);
|
||||||
|
querydir_buffer_overflow_dotest(MemfsDisk, 0, 1000, 0);
|
||||||
|
}
|
||||||
|
if (WinFspNetTests)
|
||||||
|
{
|
||||||
|
querydir_buffer_overflow_dotest(MemfsNet, L"\\\\memfs\\share", 0, 0);
|
||||||
|
querydir_buffer_overflow_dotest(MemfsNet, L"\\\\memfs\\share", 1000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned __stdcall dirnotify_dotest_thread(void *FilePath)
|
static unsigned __stdcall dirnotify_dotest_thread(void *FilePath)
|
||||||
{
|
{
|
||||||
FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath);
|
FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath);
|
||||||
|
|
||||||
|
Sleep(1000); /* wait for ReadDirectoryChangesW */
|
||||||
|
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
Handle = CreateFileW(FilePath,
|
Handle = CreateFileW(FilePath,
|
||||||
GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
@ -330,5 +468,6 @@ void dirctl_tests(void)
|
|||||||
{
|
{
|
||||||
TEST(querydir_test);
|
TEST(querydir_test);
|
||||||
TEST(querydir_expire_cache_test);
|
TEST(querydir_expire_cache_test);
|
||||||
|
TEST(querydir_buffer_overflow_test);
|
||||||
TEST(dirnotify_test);
|
TEST(dirnotify_test);
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,7 @@ void getvolinfo_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
|||||||
ASSERT(255 == MaxComponentLength);
|
ASSERT(255 == MaxComponentLength);
|
||||||
ASSERT(0 != (FileSystemFlags &
|
ASSERT(0 != (FileSystemFlags &
|
||||||
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
||||||
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp"));
|
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp-MEMFS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Success = GetDiskFreeSpaceW(FilePath, &SectorsPerCluster, &BytesPerSector, &FreeClusters, &TotalClusters);
|
Success = GetDiskFreeSpaceW(FilePath, &SectorsPerCluster, &BytesPerSector, &FreeClusters, &TotalClusters);
|
||||||
@ -573,7 +573,7 @@ void setvolinfo_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
|||||||
ASSERT(255 == MaxComponentLength);
|
ASSERT(255 == MaxComponentLength);
|
||||||
ASSERT(0 != (FileSystemFlags &
|
ASSERT(0 != (FileSystemFlags &
|
||||||
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
||||||
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp"));
|
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp-MEMFS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Success = SetVolumeLabelW(FilePath, L"TestLabel");
|
Success = SetVolumeLabelW(FilePath, L"TestLabel");
|
||||||
@ -590,7 +590,7 @@ void setvolinfo_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
|||||||
ASSERT(255 == MaxComponentLength);
|
ASSERT(255 == MaxComponentLength);
|
||||||
ASSERT(0 != (FileSystemFlags &
|
ASSERT(0 != (FileSystemFlags &
|
||||||
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
||||||
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp"));
|
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp-MEMFS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Success = SetVolumeLabelW(FilePath, L"123456789012345678901234567890123");
|
Success = SetVolumeLabelW(FilePath, L"123456789012345678901234567890123");
|
||||||
@ -607,7 +607,7 @@ void setvolinfo_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
|||||||
ASSERT(255 == MaxComponentLength);
|
ASSERT(255 == MaxComponentLength);
|
||||||
ASSERT(0 != (FileSystemFlags &
|
ASSERT(0 != (FileSystemFlags &
|
||||||
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
(FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_PERSISTENT_ACLS)));
|
||||||
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp"));
|
ASSERT(0 == wcscmp(FileSystemNameBuf, L"WinFsp-MEMFS"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2018
tst/winfsp-tests/stream-tests.c
Normal file
2018
tst/winfsp-tests/stream-tests.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@ int main(int argc, char *argv[])
|
|||||||
TESTSUITE(lock_tests);
|
TESTSUITE(lock_tests);
|
||||||
TESTSUITE(dirctl_tests);
|
TESTSUITE(dirctl_tests);
|
||||||
TESTSUITE(reparse_tests);
|
TESTSUITE(reparse_tests);
|
||||||
|
TESTSUITE(stream_tests);
|
||||||
|
|
||||||
tlib_run_tests(argc, argv);
|
tlib_run_tests(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user