mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
64 Commits
release/1.
...
release/1.
Author | SHA1 | Date | |
---|---|---|---|
9d76495340 | |||
41c604b0fd | |||
28a9534a65 | |||
b87c907af8 | |||
9d5efe5f98 | |||
c5b850be35 | |||
0af0bfbe7c | |||
1dbcae3985 | |||
a5726c820b | |||
870c54253a | |||
f9cbbea386 | |||
a939d9997b | |||
c803ef24f8 | |||
2d5d058d2f | |||
a372c6ee40 | |||
c8a5f52fb1 | |||
40052b143e | |||
8006763367 | |||
7ed9c56005 | |||
12fd8942f7 | |||
3eb1f48174 | |||
ac26bde9ee | |||
6421dd92a9 | |||
b05d5e286e | |||
2d0df701e3 | |||
2f1a5b98e2 | |||
21a636aaae | |||
3b90908e01 | |||
90e86d4592 | |||
b3058a5e3e | |||
3bda3d754e | |||
8109b005be | |||
bd0d6638b0 | |||
912703cd77 | |||
90bc12132e | |||
f1cf020272 | |||
2f65a77d34 | |||
4578414a2c | |||
f0fd53e3f3 | |||
1cc42c9d70 | |||
28ac5a1cfe | |||
e1b1284153 | |||
5014e8bd35 | |||
1b7a78edff | |||
6340811974 | |||
cd21d26b93 | |||
d5ab701e3c | |||
8269f57282 | |||
e59a49992a | |||
10c8c440f9 | |||
f3375fc17f | |||
c1e4b00aa7 | |||
1bb0580a6a | |||
e54c2288f7 | |||
6b4b1dff6c | |||
92b7989999 | |||
f2e2d83b72 | |||
3687df53c6 | |||
a004e4be10 | |||
88edf5723e | |||
7f360827f6 | |||
01f91c771d | |||
844fb7171e | |||
489081b8c2 |
1
.github/workflows/avm.yml
vendored
1
.github/workflows/avm.yml
vendored
@ -13,3 +13,4 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.6/winfsp-1.6.20027.msi
|
https://github.com/billziss-gh/winfsp/releases/download/v1.6/winfsp-1.6.20027.msi
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.7B1/winfsp-1.7.20038.msi
|
https://github.com/billziss-gh/winfsp/releases/download/v1.7B1/winfsp-1.7.20038.msi
|
||||||
|
https://github.com/billziss-gh/winfsp/releases/download/v1.8/winfsp-1.8.20304.msi
|
||||||
|
@ -1,6 +1,66 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v1.9 (2021)::
|
||||||
|
|
||||||
|
Changes since v1.8:
|
||||||
|
|
||||||
|
* [NEW] WinFsp now supports file change notifications and cache invalidations. This functionality is offered via the following new API's:
|
||||||
|
** Native API: `FspFileSystemNotify`
|
||||||
|
** FUSE API: `fuse_notify`
|
||||||
|
** .NET API: `FileSystemHost.Notify`
|
||||||
|
|
||||||
|
* [NEW] A native file system (notifyfs) and a .NET file system (notifyfs-dotnet) have been added to showcase the new file change notification API.
|
||||||
|
|
||||||
|
* [NEW] A new WinFsp-FUSE option `FileSecurity` has been added that allows the complete specification of file security descriptors using SDDL. (See GitHub issue https://github.com/rclone/rclone/issues/4717#issuecomment-767723287.)
|
||||||
|
|
||||||
|
* [FIX] The FSD now correctly handles a rare situation where receiving too many CLOSE calls from the OS (e.g. when caching thousands of files) could result in a bogus "insufficient resources" error. (See commit 0af0bfbe7c45e353d693a2a45965d99fa81f2163.)
|
||||||
|
|
||||||
|
* [FIX] WinFsp-FUSE correctly maps SID's from trusted domains to POSIX UID's in a multi-domain environment (using the "trustPosixOffset" attribute). Previously WinFsp-FUSE only handled SID's from the primary domain correctly.
|
||||||
|
|
||||||
|
* [FIX] WinFsp-FUSE options such as `volname`, `VolumePrefix`, `FileSystemName`, `ExactFileSystemName` are now truncated when too long. (See GitHub issue #311.)
|
||||||
|
|
||||||
|
* [FIX] The WinFsp driver is now started in a thread-safe manner if it is not already running. (See GitHub issue billziss-gh/cgofuse#51.)
|
||||||
|
|
||||||
|
* [FIX] Credentials entered in the Credentials dialog (when mapping network drives) are no longer saved by default. (See GitHub PR #342. Thanks @gaotxg.)
|
||||||
|
|
||||||
|
|
||||||
|
v1.9B2 (2021 Beta2)::
|
||||||
|
|
||||||
|
Changes since v1.8:
|
||||||
|
|
||||||
|
* [NEW] WinFsp now supports file change notifications and cache invalidations. This functionality is offered via the following new API's:
|
||||||
|
** Native API: `FspFileSystemNotify`
|
||||||
|
** FUSE API: `fuse_notify`
|
||||||
|
** .NET API: `FileSystemHost.Notify`
|
||||||
|
|
||||||
|
* [NEW] A native file system (notifyfs) and a .NET file system (notifyfs-dotnet) have been added to showcase the new file change notification API.
|
||||||
|
|
||||||
|
* [NEW] A new WinFsp-FUSE option `FileSecurity` has been added that allows the complete specification of file security descriptors using SDDL. (See GitHub issue https://github.com/rclone/rclone/issues/4717#issuecomment-767723287.)
|
||||||
|
|
||||||
|
* [FIX] The FSD now correctly handles a rare situation where receiving too many CLOSE calls from the OS (e.g. when caching thousands of files) could result in a bogus "insufficient resources" error. (See commit 0af0bfbe7c45e353d693a2a45965d99fa81f2163.)
|
||||||
|
|
||||||
|
* [FIX] WinFsp-FUSE correctly maps SID's from trusted domains to POSIX UID's in a multi-domain environment (using the "trustPosixOffset" attribute). Previously WinFsp-FUSE only handled SID's from the primary domain correctly.
|
||||||
|
|
||||||
|
* [FIX] WinFsp-FUSE options such as `volname`, `VolumePrefix`, `FileSystemName`, `ExactFileSystemName` are now truncated when too long. (See GitHub issue #311.)
|
||||||
|
|
||||||
|
* [FIX] The WinFsp driver is now started in a thread-safe manner if it is not already running. (See GitHub issue billziss-gh/cgofuse#51.)
|
||||||
|
|
||||||
|
* [FIX] Credentials entered in the Credentials dialog (when mapping network drives) are no longer saved by default. (See GitHub PR #342. Thanks @gaotxg.)
|
||||||
|
|
||||||
|
|
||||||
|
v1.9B1 (2021 Beta1)::
|
||||||
|
|
||||||
|
Changes since v1.8:
|
||||||
|
|
||||||
|
* [NEW] WinFsp now supports file change notifications and cache invalidations. This functionality is offered via the following new API's:
|
||||||
|
** Native API: `FspFileSystemNotify`
|
||||||
|
** FUSE API: `fuse_notify`
|
||||||
|
** .NET API: `FileSystemHost.Notify`
|
||||||
|
|
||||||
|
* [FIX] WinFsp-FUSE correctly maps SID's from trusted domains to POSIX UID's in a multi-domain environment (using the "trustPosixOffset" attribute). Previously WinFsp-FUSE only handled SID's from the primary domain correctly.
|
||||||
|
|
||||||
|
|
||||||
v1.8 (2020.2)::
|
v1.8 (2020.2)::
|
||||||
|
|
||||||
Changes since v1.7:
|
Changes since v1.7:
|
||||||
|
@ -54,6 +54,7 @@ This CONTRIBUTOR AGREEMENT applies to any contribution that you make to the WinF
|
|||||||
CONTRIBUTOR LIST
|
CONTRIBUTOR LIST
|
||||||
----------------
|
----------------
|
||||||
|===
|
|===
|
||||||
|
|Alberto Alonso |alberto at alonso.xyz
|
||||||
|Ben Rubson |ben.rubson at gmail.com
|
|Ben Rubson |ben.rubson at gmail.com
|
||||||
|Bill Zissimopoulos |billziss at navimatics.com
|
|Bill Zissimopoulos |billziss at navimatics.com
|
||||||
|Brett Dutro |brett.dutro at gmail.com
|
|Brett Dutro |brett.dutro at gmail.com
|
||||||
@ -68,4 +69,5 @@ CONTRIBUTOR LIST
|
|||||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||||
|Santiago Ganis |sganis at gmail.com
|
|Santiago Ganis |sganis at gmail.com
|
||||||
|Tobias Urlaub |saibotu at outlook.de
|
|Tobias Urlaub |saibotu at outlook.de
|
||||||
|
|Victor Gao |victgm at outlook.com
|
||||||
|===
|
|===
|
||||||
|
21
appveyor.yml
21
appveyor.yml
@ -1,6 +1,8 @@
|
|||||||
version: '{build}'
|
version: '{build}'
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
# Disable the winfsp-tests built-in exception filter to allow WER to collect dumps.
|
||||||
|
WINFSP_TESTS_EXCEPTION_FILTER_DISABLE: 1
|
||||||
matrix:
|
matrix:
|
||||||
- CONFIGURATION: Debug
|
- CONFIGURATION: Debug
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
@ -15,18 +17,25 @@ init:
|
|||||||
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
# Hack to make WDK 1903 work on VS2015.
|
||||||
|
# See https://github.com/appveyor-tests/WDK-10.0.14393.0/blob/31cf12217fe0c92b218c70d7027dfe145be4f4cb/appveyor.yml#L7
|
||||||
- ps: |
|
- ps: |
|
||||||
# Hack to make WDK 1903 work on VS2015.
|
|
||||||
# See https://github.com/appveyor-tests/WDK-10.0.14393.0/blob/31cf12217fe0c92b218c70d7027dfe145be4f4cb/appveyor.yml#L7
|
|
||||||
[xml]$targets = get-content "C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets"
|
[xml]$targets = get-content "C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets"
|
||||||
$usingTask = $targets.ChildNodes[1].UsingTask | ? {$_.TaskName -eq "ValidateNTTargetVersion"}
|
$usingTask = $targets.ChildNodes[1].UsingTask | ? {$_.TaskName -eq "ValidateNTTargetVersion"}
|
||||||
$usingTask.AssemblyFile = '$(WDKContentRoot)build\bin\Microsoft.DriverKit.Build.Tasks.16.0.dll'
|
$usingTask.AssemblyFile = '$(WDKContentRoot)build\bin\Microsoft.DriverKit.Build.Tasks.16.0.dll'
|
||||||
$targets.Save("C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets")
|
$targets.Save("C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets")
|
||||||
|
# Submodules
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
|
# Kernel and user mode dumps
|
||||||
|
- if exist %SystemRoot%\memory.dmp del %SystemRoot%\memory.dmp
|
||||||
|
- if exist C:\projects\LocalDumps rmdir /s/q C:\projects\LocalDumps
|
||||||
|
- mkdir C:\projects\LocalDumps
|
||||||
|
- reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpFolder /t REG_EXPAND_SZ /d C:\projects\LocalDumps /f
|
||||||
|
- reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpType /t REG_DWORD /d 2 /f
|
||||||
|
# Boot configuration
|
||||||
- appveyor AddMessage "Change boot configuration and reboot" -Category Information
|
- appveyor AddMessage "Change boot configuration and reboot" -Category Information
|
||||||
- bcdedit /set testsigning on
|
- bcdedit /set testsigning on
|
||||||
- if %TESTING%==Func verifier /standard /driver winfsp-x64.sys
|
- if %TESTING%==Func verifier /standard /driver winfsp-x64.sys
|
||||||
- if exist %SystemRoot%\memory.dmp del %SystemRoot%\memory.dmp
|
|
||||||
- ps: Restart-Computer -Force
|
- ps: Restart-Computer -Force
|
||||||
- ps: Start-Sleep -s 60
|
- ps: Start-Sleep -s 60
|
||||||
|
|
||||||
@ -53,9 +62,11 @@ test_script:
|
|||||||
- if %TESTING%==Avast tools\run-tests.bat %CONFIGURATION% avast-tests
|
- if %TESTING%==Avast tools\run-tests.bat %CONFIGURATION% avast-tests
|
||||||
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
||||||
- choco uninstall winfsp -y
|
- choco uninstall winfsp -y
|
||||||
- if exist %SystemRoot%\memory.dmp exit 1
|
|
||||||
|
|
||||||
on_finish:
|
on_finish:
|
||||||
- if exist %SystemRoot%\memory.dmp (7z a memory.dmp.zip %SystemRoot%\memory.dmp && appveyor PushArtifact memory.dmp.zip)
|
|
||||||
- verifier /query
|
- verifier /query
|
||||||
|
- if exist %SystemRoot%\memory.dmp (7z a km.dmp.zip %SystemRoot%\memory.dmp && appveyor PushArtifact km.dmp.zip)
|
||||||
|
- dir /a/b C:\projects\LocalDumps | findstr "^" && (7z a um.dmp.zip C:\projects\LocalDumps && appveyor PushArtifact um.dmp.zip) || ver>nul
|
||||||
|
- if exist *.dmp.zip (7z a sym.pdb.zip build\VStudio\build\%CONFIGURATION%\*.pdb && appveyor PushArtifact sym.pdb.zip)
|
||||||
|
- if exist *.dmp.zip exit 1
|
||||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
|
@ -538,6 +538,31 @@
|
|||||||
<File Name="passthrough-dotnet.csproj" KeyPath="yes" />
|
<File Name="passthrough-dotnet.csproj" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.notifyfs" Name="notifyfs">
|
||||||
|
<Component Id="C.notifyfs.c">
|
||||||
|
<File Name="notifyfs.c" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.notifyfs.sln">
|
||||||
|
<File Name="notifyfs.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.notifyfs.vcxproj">
|
||||||
|
<File Name="notifyfs.vcxproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.notifyfs.vcxproj.filters">
|
||||||
|
<File Name="notifyfs.vcxproj.filters" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.notifyfs_dotnet" Name="notifyfs-dotnet">
|
||||||
|
<Component Id="C.notifyfs_dotnet.Program.cs">
|
||||||
|
<File Id="FILE.notifyfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.notifyfs_dotnet.sln">
|
||||||
|
<File Name="notifyfs-dotnet.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.notifyfs_dotnet.csproj">
|
||||||
|
<File Name="notifyfs-dotnet.csproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="SYMDIR">
|
<DirectoryRef Id="SYMDIR">
|
||||||
<Component Id="C.winfsp_x64.sys.pdb">
|
<Component Id="C.winfsp_x64.sys.pdb">
|
||||||
@ -674,6 +699,10 @@
|
|||||||
<ComponentRef Id="C.passthrough_fuse3.vcxproj.filters" />
|
<ComponentRef Id="C.passthrough_fuse3.vcxproj.filters" />
|
||||||
<ComponentRef Id="C.passthrough_fuse3.Makefile" />
|
<ComponentRef Id="C.passthrough_fuse3.Makefile" />
|
||||||
<ComponentRef Id="C.passthrough_fuse3.README.md" />
|
<ComponentRef Id="C.passthrough_fuse3.README.md" />
|
||||||
|
<ComponentRef Id="C.notifyfs.c" />
|
||||||
|
<ComponentRef Id="C.notifyfs.sln" />
|
||||||
|
<ComponentRef Id="C.notifyfs.vcxproj" />
|
||||||
|
<ComponentRef Id="C.notifyfs.vcxproj.filters" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="C.WinFsp.sym">
|
<ComponentGroup Id="C.WinFsp.sym">
|
||||||
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
|
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
|
||||||
@ -703,6 +732,9 @@
|
|||||||
<ComponentRef Id="C.passthrough_dotnet.Program.cs" />
|
<ComponentRef Id="C.passthrough_dotnet.Program.cs" />
|
||||||
<ComponentRef Id="C.passthrough_dotnet.sln" />
|
<ComponentRef Id="C.passthrough_dotnet.sln" />
|
||||||
<ComponentRef Id="C.passthrough_dotnet.csproj" />
|
<ComponentRef Id="C.passthrough_dotnet.csproj" />
|
||||||
|
<ComponentRef Id="C.notifyfs_dotnet.Program.cs" />
|
||||||
|
<ComponentRef Id="C.notifyfs_dotnet.sln" />
|
||||||
|
<ComponentRef Id="C.notifyfs_dotnet.csproj" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
|
|
||||||
<Feature
|
<Feature
|
||||||
|
@ -107,7 +107,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -123,7 +123,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -143,7 +143,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -163,7 +163,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -195,6 +195,7 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\lock-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\lock-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\memfs-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\memfs-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\mount-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\mount-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\notify-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\oplock-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\oplock-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\path-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\path-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\posix-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\posix-test.c" />
|
||||||
|
@ -109,6 +109,9 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c">
|
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\notify-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
<MyCompanyName>Navimatics LLC</MyCompanyName>
|
<MyCompanyName>Navimatics LLC</MyCompanyName>
|
||||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||||
|
|
||||||
<MyCanonicalVersion>1.8</MyCanonicalVersion>
|
<MyCanonicalVersion>1.9</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2020.2</MyProductVersion>
|
<MyProductVersion>2021</MyProductVersion>
|
||||||
<MyProductStage>Gold</MyProductStage>
|
<MyProductStage>Gold</MyProductStage>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||||
<ClCompile Include="..\..\src\dll\launch.c" />
|
<ClCompile Include="..\..\src\dll\launch.c" />
|
||||||
|
<ClCompile Include="..\..\src\dll\ldap.c" />
|
||||||
<ClCompile Include="..\..\src\dll\mount.c" />
|
<ClCompile Include="..\..\src\dll\mount.c" />
|
||||||
<ClCompile Include="..\..\src\dll\np.c" />
|
<ClCompile Include="..\..\src\dll\np.c" />
|
||||||
<ClCompile Include="..\..\src\dll\security.c" />
|
<ClCompile Include="..\..\src\dll\security.c" />
|
||||||
@ -224,7 +225,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -251,7 +252,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -281,7 +282,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
@ -312,7 +313,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -169,6 +169,9 @@
|
|||||||
<ClCompile Include="..\..\src\shared\ku\posix.c">
|
<ClCompile Include="..\..\src\shared\ku\posix.c">
|
||||||
<Filter>Source\shared\ku</Filter>
|
<Filter>Source\shared\ku</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\ldap.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\library.def">
|
<None Include="..\..\src\dll\library.def">
|
||||||
|
@ -187,6 +187,7 @@
|
|||||||
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
||||||
<ClCompile Include="..\..\src\sys\silo.c" />
|
<ClCompile Include="..\..\src\sys\silo.c" />
|
||||||
<ClCompile Include="..\..\src\sys\statistics.c" />
|
<ClCompile Include="..\..\src\sys\statistics.c" />
|
||||||
|
<ClCompile Include="..\..\src\sys\trace.c" />
|
||||||
<ClCompile Include="..\..\src\sys\util.c" />
|
<ClCompile Include="..\..\src\sys\util.c" />
|
||||||
<ClCompile Include="..\..\src\sys\volinfo.c" />
|
<ClCompile Include="..\..\src\sys\volinfo.c" />
|
||||||
<ClCompile Include="..\..\src\sys\volume.c" />
|
<ClCompile Include="..\..\src\sys\volume.c" />
|
||||||
|
@ -125,6 +125,9 @@
|
|||||||
<ClCompile Include="..\..\src\sys\silo.c">
|
<ClCompile Include="..\..\src\sys\silo.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\sys\trace.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\sys\driver.h">
|
<ClInclude Include="..\..\src\sys\driver.h">
|
||||||
|
@ -152,6 +152,8 @@ FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_exit)(struct fsp_fuse_env *env,
|
|||||||
struct fuse *f);
|
struct fuse *f);
|
||||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env,
|
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env,
|
||||||
struct fuse *f);
|
struct fuse *f);
|
||||||
|
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_notify)(struct fsp_fuse_env *env,
|
||||||
|
struct fuse *f, const char *path, uint32_t action);
|
||||||
FSP_FUSE_API struct fuse_context *FSP_FUSE_API_NAME(fsp_fuse_get_context)(struct fsp_fuse_env *env);
|
FSP_FUSE_API struct fuse_context *FSP_FUSE_API_NAME(fsp_fuse_get_context)(struct fsp_fuse_env *env);
|
||||||
|
|
||||||
FSP_FUSE_SYM(
|
FSP_FUSE_SYM(
|
||||||
@ -212,6 +214,13 @@ int fuse_exited(struct fuse *f),
|
|||||||
(fsp_fuse_env(), f);
|
(fsp_fuse_env(), f);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
FSP_FUSE_SYM(
|
||||||
|
int fuse_notify(struct fuse *f, const char *path, uint32_t action),
|
||||||
|
{
|
||||||
|
return FSP_FUSE_API_CALL(fsp_fuse_notify)
|
||||||
|
(fsp_fuse_env(), f, path, action);
|
||||||
|
})
|
||||||
|
|
||||||
FSP_FUSE_SYM(
|
FSP_FUSE_SYM(
|
||||||
struct fuse_context *fuse_get_context(void),
|
struct fuse_context *fuse_get_context(void),
|
||||||
{
|
{
|
||||||
@ -236,9 +245,8 @@ int fuse_interrupted(void),
|
|||||||
FSP_FUSE_SYM(
|
FSP_FUSE_SYM(
|
||||||
int fuse_invalidate(struct fuse *f, const char *path),
|
int fuse_invalidate(struct fuse *f, const char *path),
|
||||||
{
|
{
|
||||||
(void)f;
|
return FSP_FUSE_API_CALL(fsp_fuse_notify)
|
||||||
(void)path;
|
(fsp_fuse_env(), f, path, 0);
|
||||||
return -EINVAL;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
FSP_FUSE_SYM(
|
FSP_FUSE_SYM(
|
||||||
|
@ -79,6 +79,17 @@ extern "C" {
|
|||||||
#define UF_ARCHIVE FSP_FUSE_UF_ARCHIVE
|
#define UF_ARCHIVE FSP_FUSE_UF_ARCHIVE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* notify extension */
|
||||||
|
#define FSP_FUSE_NOTIFY_MKDIR 0x0001
|
||||||
|
#define FSP_FUSE_NOTIFY_RMDIR 0x0002
|
||||||
|
#define FSP_FUSE_NOTIFY_CREATE 0x0004
|
||||||
|
#define FSP_FUSE_NOTIFY_UNLINK 0x0008
|
||||||
|
#define FSP_FUSE_NOTIFY_CHMOD 0x0010
|
||||||
|
#define FSP_FUSE_NOTIFY_CHOWN 0x0020
|
||||||
|
#define FSP_FUSE_NOTIFY_UTIME 0x0040
|
||||||
|
#define FSP_FUSE_NOTIFY_CHFLAGS 0x0080
|
||||||
|
#define FSP_FUSE_NOTIFY_TRUNCATE 0x0100
|
||||||
|
|
||||||
struct fuse_file_info
|
struct fuse_file_info
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -66,6 +66,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
|||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 't', METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 't', METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||||
#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_NOTIFY \
|
||||||
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'n', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
/* fsctl internal device codes (usable only in-kernel) */
|
/* fsctl internal device codes (usable only in-kernel) */
|
||||||
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
||||||
@ -268,6 +270,15 @@ typedef struct
|
|||||||
FSP_FSCTL_STATIC_ASSERT(24 == sizeof(FSP_FSCTL_STREAM_INFO),
|
FSP_FSCTL_STATIC_ASSERT(24 == sizeof(FSP_FSCTL_STREAM_INFO),
|
||||||
"sizeof(FSP_FSCTL_STREAM_INFO) must be exactly 24.");
|
"sizeof(FSP_FSCTL_STREAM_INFO) must be exactly 24.");
|
||||||
typedef struct
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT16 Size;
|
||||||
|
UINT32 Filter;
|
||||||
|
UINT32 Action;
|
||||||
|
WCHAR FileNameBuf[];
|
||||||
|
} FSP_FSCTL_NOTIFY_INFO;
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(12 == sizeof(FSP_FSCTL_NOTIFY_INFO),
|
||||||
|
"sizeof(FSP_FSCTL_NOTIFY_INFO) must be exactly 12.");
|
||||||
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
@ -617,6 +628,8 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
|||||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||||
BOOLEAN Batch);
|
BOOLEAN Batch);
|
||||||
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
|
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
|
||||||
|
FSP_API NTSTATUS FspFsctlNotify(HANDLE VolumeHandle,
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo, SIZE_T Size);
|
||||||
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
||||||
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
|
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
|
||||||
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
|
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
|
||||||
|
@ -1186,6 +1186,72 @@ FSP_API VOID FspFileSystemStopDispatcher(FSP_FILE_SYSTEM *FileSystem);
|
|||||||
*/
|
*/
|
||||||
FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
/**
|
||||||
|
* Begin notifying Windows that the file system has file changes.
|
||||||
|
*
|
||||||
|
* A file system that wishes to notify Windows about file changes must
|
||||||
|
* first issue an FspFileSystemBegin call, followed by 0 or more
|
||||||
|
* FspFileSystemNotify calls, followed by an FspFileSystemNotifyEnd call.
|
||||||
|
*
|
||||||
|
* This operation blocks concurrent file rename operations. File rename
|
||||||
|
* operations may interfere with file notification, because a file being
|
||||||
|
* notified may also be concurrently renamed. After all file change
|
||||||
|
* notifications have been issued, you must make sure to call
|
||||||
|
* FspFileSystemNotifyEnd to allow file rename operations to proceed.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system object.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code. The error code STATUS_CANT_WAIT means that
|
||||||
|
* a file rename operation is currently in progress and the operation must be
|
||||||
|
* retried at a later time.
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspFileSystemNotifyBegin(FSP_FILE_SYSTEM *FileSystem, ULONG Timeout);
|
||||||
|
/**
|
||||||
|
* End notifying Windows that the file system has file changes.
|
||||||
|
*
|
||||||
|
* A file system that wishes to notify Windows about file changes must
|
||||||
|
* first issue an FspFileSystemBegin call, followed by 0 or more
|
||||||
|
* FspFileSystemNotify calls, followed by an FspFileSystemNotifyEnd call.
|
||||||
|
*
|
||||||
|
* This operation allows any blocked file rename operations to proceed.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system object.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspFileSystemNotifyEnd(FSP_FILE_SYSTEM *FileSystem);
|
||||||
|
/**
|
||||||
|
* Notify Windows that the file system has file changes.
|
||||||
|
*
|
||||||
|
* A file system that wishes to notify Windows about file changes must
|
||||||
|
* first issue an FspFileSystemBegin call, followed by 0 or more
|
||||||
|
* FspFileSystemNotify calls, followed by an FspFileSystemNotifyEnd call.
|
||||||
|
*
|
||||||
|
* Note that FspFileSystemNotify requires file names to be normalized. A
|
||||||
|
* normalized file name is one that contains the correct case of all characters
|
||||||
|
* in the file name.
|
||||||
|
*
|
||||||
|
* For case-sensitive file systems all file names are normalized by definition.
|
||||||
|
* For case-insensitive file systems that implement file name normalization,
|
||||||
|
* a normalized file name is the one that the file system specifies in the
|
||||||
|
* response to Create or Open (see also FspFileSystemGetOpenFileInfo). For
|
||||||
|
* case-insensitive file systems that do not implement file name normalization
|
||||||
|
* a normalized file name is the upper case version of the file name used
|
||||||
|
* to open the file.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system object.
|
||||||
|
* @param NotifyInfo
|
||||||
|
* Buffer containing information about file changes.
|
||||||
|
* @param Size
|
||||||
|
* Size of buffer.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspFileSystemNotify(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo, SIZE_T Size);
|
||||||
/**
|
/**
|
||||||
* Get the current operation context.
|
* Get the current operation context.
|
||||||
*
|
*
|
||||||
@ -1645,6 +1711,28 @@ UINT32 FspFileSystemGetEaPackedSize(PFILE_FULL_EA_INFORMATION SingleEa)
|
|||||||
/* magic computations are courtesy of NTFS */
|
/* magic computations are courtesy of NTFS */
|
||||||
return 5 + SingleEa->EaNameLength + SingleEa->EaValueLength;
|
return 5 + SingleEa->EaNameLength + SingleEa->EaValueLength;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Add notify information to a buffer.
|
||||||
|
*
|
||||||
|
* This is a helper for filling a buffer to use with FspFileSystemNotify.
|
||||||
|
*
|
||||||
|
* @param NotifyInfo
|
||||||
|
* The notify information to add.
|
||||||
|
* @param Buffer
|
||||||
|
* Pointer to a buffer that will receive the notify information.
|
||||||
|
* @param Length
|
||||||
|
* Length of buffer.
|
||||||
|
* @param PBytesTransferred [out]
|
||||||
|
* Pointer to a memory location that will receive the actual number of bytes stored. This should
|
||||||
|
* be initialized to 0 prior to the first call to FspFileSystemAddNotifyInfo for a particular
|
||||||
|
* buffer.
|
||||||
|
* @return
|
||||||
|
* TRUE if the notify information was added, FALSE if there was not enough space to add it.
|
||||||
|
* @see
|
||||||
|
* FspFileSystemNotify
|
||||||
|
*/
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Directory buffering
|
* Directory buffering
|
||||||
@ -1738,6 +1826,10 @@ FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)());
|
|||||||
FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
||||||
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
|
FSP_API NTSTATUS FspPosixMergePermissionsToSecurityDescriptor(
|
||||||
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
|
PSECURITY_DESCRIPTOR ExistingSecurityDescriptor,
|
||||||
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode);
|
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode);
|
||||||
|
52
src/dll/fs.c
52
src/dll/fs.c
@ -432,6 +432,58 @@ FSP_API FSP_FILE_SYSTEM_OPERATION_CONTEXT *FspFileSystemGetOperationContext(VOID
|
|||||||
return (FSP_FILE_SYSTEM_OPERATION_CONTEXT *)TlsGetValue(FspFileSystemTlsKey);
|
return (FSP_FILE_SYSTEM_OPERATION_CONTEXT *)TlsGetValue(FspFileSystemTlsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemNotifyBegin(FSP_FILE_SYSTEM *FileSystem, ULONG Timeout)
|
||||||
|
{
|
||||||
|
static const ULONG Delays[] =
|
||||||
|
{
|
||||||
|
10/*ms*/,
|
||||||
|
10/*ms*/,
|
||||||
|
50/*ms*/,
|
||||||
|
50/*ms*/,
|
||||||
|
100/*ms*/,
|
||||||
|
100/*ms*/,
|
||||||
|
300/*ms*/,
|
||||||
|
};
|
||||||
|
ULONG Total = 0, Delay;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
for (ULONG i = 0, n = sizeof(Delays) / sizeof(Delays[0]);; i++)
|
||||||
|
{
|
||||||
|
Result = FspFsctlNotify(FileSystem->VolumeHandle, 0, 0);
|
||||||
|
if (STATUS_CANT_WAIT != Result)
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
Delay = n > i ? Delays[i] : Delays[n - 1];
|
||||||
|
if (INFINITE == Timeout)
|
||||||
|
Sleep(Delay);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Total >= Timeout)
|
||||||
|
break;
|
||||||
|
if (Total + Delay > Timeout)
|
||||||
|
Delay = Timeout - Total;
|
||||||
|
Total += Delay;
|
||||||
|
Sleep(Delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemNotifyEnd(FSP_FILE_SYSTEM *FileSystem)
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO NotifyInfo;
|
||||||
|
|
||||||
|
memset(&NotifyInfo, 0, sizeof NotifyInfo);
|
||||||
|
return FspFsctlNotify(FileSystem->VolumeHandle, &NotifyInfo, sizeof NotifyInfo.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemNotify(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo, SIZE_T Size)
|
||||||
|
{
|
||||||
|
return FspFsctlNotify(FileSystem->VolumeHandle, NotifyInfo, Size);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Out-of-Line
|
* Out-of-Line
|
||||||
*/
|
*/
|
||||||
|
@ -161,6 +161,25 @@ FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFsctlNotify(HANDLE VolumeHandle,
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo, SIZE_T Size)
|
||||||
|
{
|
||||||
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
|
DWORD Bytes = 0;
|
||||||
|
|
||||||
|
if (!DeviceIoControl(VolumeHandle,
|
||||||
|
FSP_FSCTL_NOTIFY,
|
||||||
|
NotifyInfo, (DWORD)Size, 0, 0,
|
||||||
|
&Bytes, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
||||||
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize)
|
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize)
|
||||||
{
|
{
|
||||||
@ -235,6 +254,7 @@ FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath)
|
|||||||
|
|
||||||
static NTSTATUS FspFsctlStartService(VOID)
|
static NTSTATUS FspFsctlStartService(VOID)
|
||||||
{
|
{
|
||||||
|
static SRWLOCK Lock = SRWLOCK_INIT;
|
||||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||||
SC_HANDLE ScmHandle = 0;
|
SC_HANDLE ScmHandle = 0;
|
||||||
SC_HANDLE SvcHandle = 0;
|
SC_HANDLE SvcHandle = 0;
|
||||||
@ -242,6 +262,8 @@ static NTSTATUS FspFsctlStartService(VOID)
|
|||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
AcquireSRWLockExclusive(&Lock);
|
||||||
|
|
||||||
/* Determine if we are running inside container.
|
/* Determine if we are running inside container.
|
||||||
*
|
*
|
||||||
* See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
|
* See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
|
||||||
@ -312,6 +334,8 @@ exit:
|
|||||||
if (0 != ScmHandle)
|
if (0 != ScmHandle)
|
||||||
CloseServiceHandle(ScmHandle);
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
|
ReleaseSRWLockExclusive(&Lock);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1866,3 +1866,9 @@ FSP_API BOOLEAN FspFileSystemAddEa(PFILE_FULL_EA_INFORMATION SingleEa,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
return FspFileSystemAddXxxInfo(NotifyInfo, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dll/fuse/library.h>
|
#include <dll/fuse/library.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
|
||||||
struct fuse_chan
|
struct fuse_chan
|
||||||
{
|
{
|
||||||
@ -105,6 +106,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FUSE_OPT_KEY("ExactFileSystemName=", 'E'),
|
FUSE_OPT_KEY("ExactFileSystemName=", 'E'),
|
||||||
FUSE_OPT_KEY("--ExactFileSystemName=", 'E'),
|
FUSE_OPT_KEY("--ExactFileSystemName=", 'E'),
|
||||||
|
|
||||||
|
FUSE_OPT_KEY("FileSecurity=", 's'),
|
||||||
|
FUSE_OPT_KEY("--FileSecurity=", 's'),
|
||||||
FSP_FUSE_CORE_OPT("UserName=", set_uid, 1),
|
FSP_FUSE_CORE_OPT("UserName=", set_uid, 1),
|
||||||
FUSE_OPT_KEY("UserName=", 'u'),
|
FUSE_OPT_KEY("UserName=", 'u'),
|
||||||
FSP_FUSE_CORE_OPT("--UserName=", set_uid, 1),
|
FSP_FUSE_CORE_OPT("--UserName=", set_uid, 1),
|
||||||
@ -184,6 +187,28 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
|||||||
MountPointBuf[1] = L'\0';
|
MountPointBuf[1] = L'\0';
|
||||||
Size = 2 * sizeof(WCHAR);
|
Size = 2 * sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
(
|
||||||
|
'\\' == mountpoint[0] &&
|
||||||
|
'\\' == mountpoint[1] &&
|
||||||
|
('?' == mountpoint[2] || '.' == mountpoint[2]) &&
|
||||||
|
'\\' == mountpoint[3]
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
('A' <= mountpoint[4] && mountpoint[4] <= 'Z') ||
|
||||||
|
('a' <= mountpoint[4] && mountpoint[4] <= 'z')
|
||||||
|
) &&
|
||||||
|
':' == mountpoint[5] && '\0' == mountpoint[6])
|
||||||
|
{
|
||||||
|
MountPointBuf[0] = '\\';
|
||||||
|
MountPointBuf[1] = '\\';
|
||||||
|
MountPointBuf[2] = mountpoint[2];
|
||||||
|
MountPointBuf[3] = '\\';
|
||||||
|
MountPointBuf[4] = mountpoint[4];
|
||||||
|
MountPointBuf[5] = ':';
|
||||||
|
MountPointBuf[6] = '\0';
|
||||||
|
Size = 7 * sizeof(WCHAR);
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
(
|
(
|
||||||
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
||||||
@ -244,6 +269,29 @@ FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env,
|
|||||||
return fsp_fuse_opt_match(env, fsp_fuse_core_opts, opt);
|
return fsp_fuse_opt_match(env, fsp_fuse_core_opts, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_sddl_to_security(const char *Sddl, PUINT8 Security, PULONG PSecuritySize)
|
||||||
|
{
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
|
ULONG SecurityDescriptorSize;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
if (ConvertStringSecurityDescriptorToSecurityDescriptorA(
|
||||||
|
Sddl, SDDL_REVISION_1, &SecurityDescriptor, &SecurityDescriptorSize))
|
||||||
|
{
|
||||||
|
if (*PSecuritySize >= SecurityDescriptorSize)
|
||||||
|
{
|
||||||
|
memcpy(Security, SecurityDescriptor, SecurityDescriptorSize);
|
||||||
|
*PSecuritySize = SecurityDescriptorSize;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFree(SecurityDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int fsp_fuse_username_to_uid(const char *username, int *puid)
|
static int fsp_fuse_username_to_uid(const char *username, int *puid)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
@ -281,6 +329,63 @@ static int fsp_fuse_username_to_uid(const char *username, int *puid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_utf8towcs_trunc(
|
||||||
|
const char *Str, int StrLen,
|
||||||
|
PWSTR Wcs, int WcsLen)
|
||||||
|
{
|
||||||
|
if (0 == StrLen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int Size = MultiByteToWideChar(CP_UTF8, 0, Str, StrLen, Wcs, WcsLen);
|
||||||
|
if (0 != Size)
|
||||||
|
return Size;
|
||||||
|
|
||||||
|
if (0 == WcsLen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PWSTR Buf = 0;
|
||||||
|
|
||||||
|
Size = MultiByteToWideChar(CP_UTF8, 0, Str, StrLen, 0, 0);
|
||||||
|
if (0 == Size)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Buf = MemAlloc(Size * sizeof(WCHAR));
|
||||||
|
if (0 == Buf)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||||
|
Size = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = MultiByteToWideChar(CP_UTF8, 0, Str, StrLen, Buf, Size);
|
||||||
|
if (0 == Size)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (-1 == StrLen)
|
||||||
|
{
|
||||||
|
if (Size >= WcsLen)
|
||||||
|
{
|
||||||
|
Size = WcsLen - 1;
|
||||||
|
memcpy(Wcs, Buf, Size * sizeof(WCHAR));
|
||||||
|
Wcs[Size] = L'\0';
|
||||||
|
Size++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy(Wcs, Buf, Size * sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Size >= WcsLen)
|
||||||
|
Size = WcsLen;
|
||||||
|
memcpy(Wcs, Buf, Size * sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(Buf);
|
||||||
|
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||||
struct fuse_args *outargs)
|
struct fuse_args *outargs)
|
||||||
{
|
{
|
||||||
@ -295,6 +400,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||||
FSP_FUSE_LIBRARY_NAME " options:\n"
|
FSP_FUSE_LIBRARY_NAME " options:\n"
|
||||||
" -o umask=MASK set file permissions (octal)\n"
|
" -o umask=MASK set file permissions (octal)\n"
|
||||||
|
" -o FileSecurity=SDDL set file DACL (SDDL format)\n"
|
||||||
" -o create_umask=MASK set newly created file permissions (octal)\n"
|
" -o create_umask=MASK set newly created file permissions (octal)\n"
|
||||||
" -o create_file_umask=MASK for files only\n"
|
" -o create_file_umask=MASK for files only\n"
|
||||||
" -o create_dir_umask=MASK for directories only\n"
|
" -o create_dir_umask=MASK for directories only\n"
|
||||||
@ -345,7 +451,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
arg += sizeof "VolumePrefix=" - 1;
|
arg += sizeof "VolumePrefix=" - 1;
|
||||||
else if ('V' == arg[2])
|
else if ('V' == arg[2])
|
||||||
arg += sizeof "--VolumePrefix=" - 1;
|
arg += sizeof "--VolumePrefix=" - 1;
|
||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == fsp_fuse_utf8towcs_trunc(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
|
opt_data->VolumeParams.Prefix
|
||||||
@ -361,7 +467,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
arg += sizeof "FileSystemName=" - 1;
|
arg += sizeof "FileSystemName=" - 1;
|
||||||
else if ('F' == arg[2])
|
else if ('F' == arg[2])
|
||||||
arg += sizeof "--FileSystemName=" - 1;
|
arg += sizeof "--FileSystemName=" - 1;
|
||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == fsp_fuse_utf8towcs_trunc(arg, -1,
|
||||||
opt_data->VolumeParams.FileSystemName + 5,
|
opt_data->VolumeParams.FileSystemName + 5,
|
||||||
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 5))
|
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 5))
|
||||||
return -1;
|
return -1;
|
||||||
@ -374,13 +480,25 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
arg += sizeof "ExactFileSystemName=" - 1;
|
arg += sizeof "ExactFileSystemName=" - 1;
|
||||||
else if ('E' == arg[2])
|
else if ('E' == arg[2])
|
||||||
arg += sizeof "--ExactFileSystemName=" - 1;
|
arg += sizeof "--ExactFileSystemName=" - 1;
|
||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == fsp_fuse_utf8towcs_trunc(arg, -1,
|
||||||
opt_data->VolumeParams.FileSystemName,
|
opt_data->VolumeParams.FileSystemName,
|
||||||
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR)))
|
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR)))
|
||||||
return -1;
|
return -1;
|
||||||
opt_data->VolumeParams.FileSystemName
|
opt_data->VolumeParams.FileSystemName
|
||||||
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
return 0;
|
return 0;
|
||||||
|
case 's':
|
||||||
|
if ('F' == arg[0])
|
||||||
|
arg += sizeof "FileSecurity=" - 1;
|
||||||
|
else if ('F' == arg[2])
|
||||||
|
arg += sizeof "--FileSecurity=" - 1;
|
||||||
|
opt_data->FileSecuritySize = sizeof opt_data->FileSecurityBuf;
|
||||||
|
if (-1 == fsp_fuse_sddl_to_security(arg, opt_data->FileSecurityBuf, &opt_data->FileSecuritySize))
|
||||||
|
{
|
||||||
|
opt_data->FileSecuritySize = (ULONG)-1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
case 'u':
|
case 'u':
|
||||||
if ('U' == arg[0])
|
if ('U' == arg[0])
|
||||||
arg += sizeof "UserName=" - 1;
|
arg += sizeof "UserName=" - 1;
|
||||||
@ -406,7 +524,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
case 'v':
|
case 'v':
|
||||||
arg += sizeof "volname=" - 1;
|
arg += sizeof "volname=" - 1;
|
||||||
opt_data->VolumeLabelLength = (UINT16)(sizeof(WCHAR) *
|
opt_data->VolumeLabelLength = (UINT16)(sizeof(WCHAR) *
|
||||||
MultiByteToWideChar(CP_UTF8, 0, arg, lstrlenA(arg),
|
fsp_fuse_utf8towcs_trunc(arg, lstrlenA(arg),
|
||||||
opt_data->VolumeLabel, sizeof opt_data->VolumeLabel / sizeof(WCHAR)));
|
opt_data->VolumeLabel, sizeof opt_data->VolumeLabel / sizeof(WCHAR)));
|
||||||
if (0 == opt_data->VolumeLabelLength)
|
if (0 == opt_data->VolumeLabelLength)
|
||||||
return -1;
|
return -1;
|
||||||
@ -448,7 +566,12 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
|
|
||||||
if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1))
|
if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1))
|
||||||
{
|
{
|
||||||
if (-1 == opt_data.username_to_uid_result)
|
if ((ULONG)-1 == opt_data.FileSecuritySize)
|
||||||
|
{
|
||||||
|
ErrorMessage = L": invalid file security.";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else if (-1 == opt_data.username_to_uid_result)
|
||||||
{
|
{
|
||||||
ErrorMessage = L": invalid user or group name.";
|
ErrorMessage = L": invalid user or group name.";
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -517,7 +640,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||||
memcpy(opt_data.VolumeParams.FileSystemName, L"FUSE", 5 * sizeof(WCHAR));
|
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 + opt_data.FileSecuritySize);
|
||||||
if (0 == f)
|
if (0 == f)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -537,6 +660,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
memcpy(&f->VolumeParams, &opt_data.VolumeParams, sizeof opt_data.VolumeParams);
|
memcpy(&f->VolumeParams, &opt_data.VolumeParams, sizeof opt_data.VolumeParams);
|
||||||
f->VolumeLabelLength = opt_data.VolumeLabelLength;
|
f->VolumeLabelLength = opt_data.VolumeLabelLength;
|
||||||
memcpy(&f->VolumeLabel, &opt_data.VolumeLabel, opt_data.VolumeLabelLength);
|
memcpy(&f->VolumeLabel, &opt_data.VolumeLabel, opt_data.VolumeLabelLength);
|
||||||
|
if (0 != opt_data.FileSecuritySize)
|
||||||
|
{
|
||||||
|
memcpy(f->FileSecurityBuf, opt_data.FileSecurityBuf, opt_data.FileSecuritySize);
|
||||||
|
f->FileSecurity = f->FileSecurityBuf;
|
||||||
|
}
|
||||||
|
|
||||||
Size = (lstrlenW(ch->MountPoint) + 1) * sizeof(WCHAR);
|
Size = (lstrlenW(ch->MountPoint) + 1) * sizeof(WCHAR);
|
||||||
f->MountPoint = fsp_fuse_obj_alloc(env, Size);
|
f->MountPoint = fsp_fuse_obj_alloc(env, Size);
|
||||||
@ -610,6 +738,115 @@ FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env,
|
|||||||
return f->exited;
|
return f->exited;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_FUSE_API int fsp_fuse_notify(struct fsp_fuse_env *env,
|
||||||
|
struct fuse *f, const char *path, uint32_t action)
|
||||||
|
{
|
||||||
|
PWSTR Path = 0;
|
||||||
|
int PathLength;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[sizeof(FSP_FSCTL_NOTIFY_INFO) + FSP_FSCTL_TRANSACT_PATH_SIZEMAX];
|
||||||
|
} NotifyInfo;
|
||||||
|
NTSTATUS Result;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
Result = FspPosixMapPosixToWindowsPath(path, &Path);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
result = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathLength = lstrlenW(Path);
|
||||||
|
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR) <= PathLength)
|
||||||
|
{
|
||||||
|
result = -ENAMETOOLONG;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + PathLength * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = 0;
|
||||||
|
NotifyInfo.V.Action = 0;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, Path, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Case-insensitive FUSE file systems do not normalize open file names, which means
|
||||||
|
* that the FSD automatically normalizes file names internally by uppercasing them.
|
||||||
|
*
|
||||||
|
* The FspFileSystemNotify API requires normalized names, so upper case the file name
|
||||||
|
* here in the case of case-insensitive file systems.
|
||||||
|
*/
|
||||||
|
CharUpperBuffW(NotifyInfo.V.FileNameBuf, PathLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action & FSP_FUSE_NOTIFY_MKDIR)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_DIR_NAME;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_ADDED;
|
||||||
|
}
|
||||||
|
else if (action & FSP_FUSE_NOTIFY_RMDIR)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_DIR_NAME;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_REMOVED;
|
||||||
|
}
|
||||||
|
else if (action & FSP_FUSE_NOTIFY_CREATE)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_ADDED;
|
||||||
|
}
|
||||||
|
else if (action & FSP_FUSE_NOTIFY_UNLINK)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action & (FSP_FUSE_NOTIFY_CHMOD | FSP_FUSE_NOTIFY_CHOWN))
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter |= FILE_NOTIFY_CHANGE_SECURITY;
|
||||||
|
if (0 == NotifyInfo.V.Action)
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action & FSP_FUSE_NOTIFY_UTIME)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter |= FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
if (0 == NotifyInfo.V.Action)
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action & FSP_FUSE_NOTIFY_CHFLAGS)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
||||||
|
if (0 == NotifyInfo.V.Action)
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action & FSP_FUSE_NOTIFY_TRUNCATE)
|
||||||
|
{
|
||||||
|
NotifyInfo.V.Filter |= FILE_NOTIFY_CHANGE_SIZE;
|
||||||
|
if (0 == NotifyInfo.V.Action)
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspFileSystemNotify(f->FileSystem, &NotifyInfo.V, NotifyInfo.V.Size);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
result = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != Path)
|
||||||
|
FspPosixDeletePath(Path);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env)
|
FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env)
|
||||||
{
|
{
|
||||||
struct fuse_context *context;
|
struct fuse_context *context;
|
||||||
|
@ -472,7 +472,8 @@ static NTSTATUS fsp_fuse_intf_GetSecurityEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (0 != PSecurityDescriptorSize)
|
if (0 != PSecurityDescriptorSize)
|
||||||
{
|
{
|
||||||
Result = FspPosixMapPermissionsToSecurityDescriptor(Uid, Gid, Mode, &SecurityDescriptor);
|
Result = FspPosixMergePermissionsToSecurityDescriptor(Uid, Gid, Mode, f->FileSecurity,
|
||||||
|
&SecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -498,7 +499,7 @@ static NTSTATUS fsp_fuse_intf_GetSecurityEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
exit:
|
exit:
|
||||||
if (0 != SecurityDescriptor)
|
if (0 != SecurityDescriptor)
|
||||||
FspDeleteSecurityDescriptor(SecurityDescriptor,
|
FspDeleteSecurityDescriptor(SecurityDescriptor,
|
||||||
FspPosixMapPermissionsToSecurityDescriptor);
|
FspPosixMergePermissionsToSecurityDescriptor);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -1682,7 +1683,8 @@ static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
Result = FspPosixMapPermissionsToSecurityDescriptor(Uid, Gid, Mode, &SecurityDescriptor);
|
Result = FspPosixMergePermissionsToSecurityDescriptor(Uid, Gid, Mode, f->FileSecurity,
|
||||||
|
&SecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -1729,7 +1731,7 @@ exit:
|
|||||||
|
|
||||||
if (0 != SecurityDescriptor)
|
if (0 != SecurityDescriptor)
|
||||||
FspDeleteSecurityDescriptor(SecurityDescriptor,
|
FspDeleteSecurityDescriptor(SecurityDescriptor,
|
||||||
FspPosixMapPermissionsToSecurityDescriptor);
|
FspPosixMergePermissionsToSecurityDescriptor);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -30,60 +30,6 @@
|
|||||||
#define fsp_fuse_opt_match_exact ((const char *)1) /* exact option match */
|
#define fsp_fuse_opt_match_exact ((const char *)1) /* exact option match */
|
||||||
#define fsp_fuse_opt_match_next ((const char *)2) /* option match, value is next arg */
|
#define fsp_fuse_opt_match_next ((const char *)2) /* option match, value is next arg */
|
||||||
|
|
||||||
static long long strtoint(const char *p, int base, int is_signed)
|
|
||||||
{
|
|
||||||
long long v;
|
|
||||||
int maxdig, maxalp, sign = +1;
|
|
||||||
|
|
||||||
if (is_signed)
|
|
||||||
{
|
|
||||||
if ('+' == *p)
|
|
||||||
p++;
|
|
||||||
else if ('-' == *p)
|
|
||||||
p++, sign = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == base)
|
|
||||||
{
|
|
||||||
if ('0' == *p)
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
if ('x' == *p || 'X' == *p)
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
base = 16;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
base = 8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
base = 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maxdig = 10 < base ? '9' : (base - 1) + '0';
|
|
||||||
maxalp = 10 < base ? (base - 1 - 10) + 'a' : 0;
|
|
||||||
|
|
||||||
for (v = 0; *p; p++)
|
|
||||||
{
|
|
||||||
int c = *p;
|
|
||||||
|
|
||||||
if ('0' <= c && c <= maxdig)
|
|
||||||
v = base * v + (c - '0');
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c |= 0x20;
|
|
||||||
if ('a' <= c && c <= maxalp)
|
|
||||||
v = base * v + (c - 'a') + 10;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign * v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsp_fuse_opt_match_templ(
|
static void fsp_fuse_opt_match_templ(
|
||||||
const char *templ, const char **pspec,
|
const char *templ, const char **pspec,
|
||||||
const char **parg)
|
const char **parg)
|
||||||
@ -281,19 +227,19 @@ static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
|
|||||||
z++;
|
z++;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
llv = strtoint(argl, 10, 1);
|
llv = strtollint(argl, 0, 10, 1);
|
||||||
goto ivar;
|
goto ivar;
|
||||||
case 'i':
|
case 'i':
|
||||||
llv = strtoint(argl, 0, 1);
|
llv = strtollint(argl, 0, 0, 1);
|
||||||
goto ivar;
|
goto ivar;
|
||||||
case 'o':
|
case 'o':
|
||||||
llv = strtoint(argl, 8, 0);
|
llv = strtollint(argl, 0, 8, 0);
|
||||||
goto ivar;
|
goto ivar;
|
||||||
case 'u':
|
case 'u':
|
||||||
llv = strtoint(argl, 10, 0);
|
llv = strtollint(argl, 0, 10, 0);
|
||||||
goto ivar;
|
goto ivar;
|
||||||
case 'x': case 'X':
|
case 'x': case 'X':
|
||||||
llv = strtoint(argl, 16, 0);
|
llv = strtollint(argl, 0, 16, 0);
|
||||||
ivar:
|
ivar:
|
||||||
if (z)
|
if (z)
|
||||||
VAR(data, opt, size_t) = (size_t)llv;
|
VAR(data, opt, size_t) = (size_t)llv;
|
||||||
|
@ -72,6 +72,8 @@ struct fuse
|
|||||||
FSP_FILE_SYSTEM *FileSystem;
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
volatile int exited;
|
volatile int exited;
|
||||||
struct fuse3 *fuse3;
|
struct fuse3 *fuse3;
|
||||||
|
PSECURITY_DESCRIPTOR FileSecurity;
|
||||||
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 FileSecurityBuf[];
|
||||||
};
|
};
|
||||||
struct fsp_fuse_context_header
|
struct fsp_fuse_context_header
|
||||||
{
|
{
|
||||||
@ -156,6 +158,8 @@ struct fsp_fuse_core_opt_data
|
|||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
UINT16 VolumeLabelLength;
|
UINT16 VolumeLabelLength;
|
||||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||||
|
ULONG FileSecuritySize;
|
||||||
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 FileSecurityBuf[1024];
|
||||||
};
|
};
|
||||||
FSP_FSCTL_STATIC_ASSERT(
|
FSP_FSCTL_STATIC_ASSERT(
|
||||||
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
||||||
|
157
src/dll/ldap.c
Normal file
157
src/dll/ldap.c
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/ldap.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2020 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dll/library.h>
|
||||||
|
#include <winldap.h>
|
||||||
|
|
||||||
|
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap)
|
||||||
|
{
|
||||||
|
LDAP *Ldap = 0;
|
||||||
|
ULONG LdapResult;
|
||||||
|
|
||||||
|
*PLdap = 0;
|
||||||
|
|
||||||
|
Ldap = ldap_initW(HostName, LDAP_PORT);
|
||||||
|
if (0 == Ldap)
|
||||||
|
{
|
||||||
|
LdapResult = LdapGetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable signing and encryption */
|
||||||
|
ldap_set_optionW(Ldap, LDAP_OPT_SIGN, LDAP_OPT_ON);
|
||||||
|
ldap_set_optionW(Ldap, LDAP_OPT_ENCRYPT, LDAP_OPT_ON);
|
||||||
|
|
||||||
|
LdapResult = ldap_bind_sW(Ldap, 0, 0, LDAP_AUTH_NEGOTIATE);
|
||||||
|
if (LDAP_SUCCESS != LdapResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*PLdap = Ldap;
|
||||||
|
LdapResult = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (LDAP_SUCCESS != LdapResult)
|
||||||
|
{
|
||||||
|
if (0 != Ldap)
|
||||||
|
ldap_unbind(Ldap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LdapResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspLdapClose(PVOID Ldap0)
|
||||||
|
{
|
||||||
|
LDAP *Ldap = Ldap0;
|
||||||
|
|
||||||
|
ldap_unbind(Ldap);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG FspLdapGetValue(PVOID Ldap0, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
|
||||||
|
PWSTR *PValue)
|
||||||
|
{
|
||||||
|
LDAP *Ldap = Ldap0;
|
||||||
|
PWSTR Attributes[2];
|
||||||
|
LDAPMessage *Message = 0, *Entry;
|
||||||
|
PWSTR *Values = 0;
|
||||||
|
int Size;
|
||||||
|
PWSTR Value;
|
||||||
|
ULONG LdapResult;
|
||||||
|
|
||||||
|
*PValue = 0;
|
||||||
|
|
||||||
|
Attributes[0] = Attribute;
|
||||||
|
Attributes[1] = 0;
|
||||||
|
LdapResult = ldap_search_sW(Ldap, Base, Scope, Filter, Attributes, 0, &Message);
|
||||||
|
if (LDAP_SUCCESS != LdapResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Entry = ldap_first_entry(Ldap, Message);
|
||||||
|
if (0 == Entry)
|
||||||
|
{
|
||||||
|
LdapResult = LDAP_OTHER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Values = ldap_get_valuesW(Ldap, Entry, Attributes[0]);
|
||||||
|
if (0 == Values || 0 == ldap_count_valuesW(Values))
|
||||||
|
{
|
||||||
|
LdapResult = LDAP_OTHER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = (lstrlenW(Values[0]) + 1) * sizeof(WCHAR);
|
||||||
|
Value = MemAlloc(Size);
|
||||||
|
if (0 == Value)
|
||||||
|
{
|
||||||
|
LdapResult = LDAP_NO_MEMORY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
memcpy(Value, Values[0], Size);
|
||||||
|
|
||||||
|
*PValue = Value;
|
||||||
|
LdapResult = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != Values)
|
||||||
|
ldap_value_freeW(Values);
|
||||||
|
if (0 != Message)
|
||||||
|
ldap_msgfree(Message);
|
||||||
|
|
||||||
|
return LdapResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue)
|
||||||
|
{
|
||||||
|
return FspLdapGetValue(Ldap, 0, LDAP_SCOPE_BASE, L"(objectClass=*)", L"defaultNamingContext",
|
||||||
|
PValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue)
|
||||||
|
{
|
||||||
|
WCHAR Base[1024];
|
||||||
|
WCHAR Filter[512];
|
||||||
|
BOOLEAN IsFlatName;
|
||||||
|
|
||||||
|
*PValue = 0;
|
||||||
|
|
||||||
|
if (sizeof Base / sizeof Base[0] - 64 < lstrlenW(Context) ||
|
||||||
|
sizeof Filter / sizeof Filter[0] - 64 < lstrlenW(Domain))
|
||||||
|
return LDAP_OTHER;
|
||||||
|
|
||||||
|
IsFlatName = TRUE;
|
||||||
|
for (PWSTR P = Domain; *P; P++)
|
||||||
|
if (L'.' == *P)
|
||||||
|
{
|
||||||
|
IsFlatName = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsprintfW(Base,
|
||||||
|
L"CN=System,%s",
|
||||||
|
Context);
|
||||||
|
wsprintfW(Filter,
|
||||||
|
IsFlatName ?
|
||||||
|
L"(&(objectClass=trustedDomain)(flatName=%s))" :
|
||||||
|
L"(&(objectClass=trustedDomain)(name=%s))",
|
||||||
|
Domain);
|
||||||
|
|
||||||
|
return FspLdapGetValue(Ldap, Base, LDAP_SCOPE_ONELEVEL, Filter, L"trustPosixOffset", PValue);
|
||||||
|
}
|
@ -64,6 +64,13 @@ NTSTATUS FspEventLogUnregister(VOID);
|
|||||||
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
||||||
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
||||||
|
|
||||||
|
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap);
|
||||||
|
VOID FspLdapClose(PVOID Ldap);
|
||||||
|
ULONG FspLdapGetValue(PVOID Ldap, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
|
||||||
|
PWSTR *PValue);
|
||||||
|
ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue);
|
||||||
|
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue);
|
||||||
|
|
||||||
PWSTR FspDiagIdent(VOID);
|
PWSTR FspDiagIdent(VOID);
|
||||||
|
|
||||||
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
||||||
|
@ -742,7 +742,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
DWORD AuthPackage, CredentialsKind;
|
DWORD AuthPackage, CredentialsKind;
|
||||||
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
|
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
|
||||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
BOOL Save = TRUE;
|
BOOL Save = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//dwFlags |= CONNECT_INTERACTIVE | CONNECT_PROMPT; /* TESTING ONLY! */
|
//dwFlags |= CONNECT_INTERACTIVE | CONNECT_PROMPT; /* TESTING ONLY! */
|
||||||
|
@ -46,6 +46,7 @@ case ERROR_CANT_ACCESS_FILE: return STATUS_IO_REPARSE_TAG_NOT_H
|
|||||||
case ERROR_CANT_DISABLE_MANDATORY: return STATUS_CANT_DISABLE_MANDATORY;
|
case ERROR_CANT_DISABLE_MANDATORY: return STATUS_CANT_DISABLE_MANDATORY;
|
||||||
case ERROR_CANT_OPEN_ANONYMOUS: return STATUS_CANT_OPEN_ANONYMOUS;
|
case ERROR_CANT_OPEN_ANONYMOUS: return STATUS_CANT_OPEN_ANONYMOUS;
|
||||||
case ERROR_CANT_RESOLVE_FILENAME: return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
case ERROR_CANT_RESOLVE_FILENAME: return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
case ERROR_CANT_WAIT: return STATUS_CANT_WAIT;
|
||||||
case ERROR_CHILD_MUST_BE_VOLATILE: return STATUS_CHILD_MUST_BE_VOLATILE;
|
case ERROR_CHILD_MUST_BE_VOLATILE: return STATUS_CHILD_MUST_BE_VOLATILE;
|
||||||
case ERROR_CLEANER_CARTRIDGE_INSTALLED: return STATUS_CLEANER_CARTRIDGE_INSTALLED;
|
case ERROR_CLEANER_CARTRIDGE_INSTALLED: return STATUS_CLEANER_CARTRIDGE_INSTALLED;
|
||||||
case ERROR_CLUSTER_INVALID_NETWORK: return STATUS_CLUSTER_INVALID_NETWORK;
|
case ERROR_CLUSTER_INVALID_NETWORK: return STATUS_CLUSTER_INVALID_NETWORK;
|
||||||
|
@ -488,7 +488,8 @@ FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc ||
|
if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc ||
|
||||||
(NTSTATUS (*)())FspPosixMapPermissionsToSecurityDescriptor == CreateFunc)
|
(NTSTATUS (*)())FspPosixMapPermissionsToSecurityDescriptor == CreateFunc ||
|
||||||
|
(NTSTATUS (*)())FspPosixMergePermissionsToSecurityDescriptor == CreateFunc)
|
||||||
MemFree(SecurityDescriptor);
|
MemFree(SecurityDescriptor);
|
||||||
else
|
else
|
||||||
if ((NTSTATUS (*)())FspCreateSecurityDescriptor == CreateFunc ||
|
if ((NTSTATUS (*)())FspCreateSecurityDescriptor == CreateFunc ||
|
||||||
|
@ -582,6 +582,75 @@ namespace Fsp
|
|||||||
Response.IoStatus.Status = (UInt32)Status;
|
Response.IoStatus.Status = (UInt32)Status;
|
||||||
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Begin notifying Windows that the file system has file changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// A file system that wishes to notify Windows about file changes must
|
||||||
|
/// first issue an FspFileSystemBegin call, followed by 0 or more
|
||||||
|
/// FspFileSystemNotify calls, followed by an FspFileSystemNotifyEnd call.
|
||||||
|
/// </para><para>
|
||||||
|
/// This operation blocks concurrent file rename operations. File rename
|
||||||
|
/// operations may interfere with file notification, because a file being
|
||||||
|
/// notified may also be concurrently renamed. After all file change
|
||||||
|
/// notifications have been issued, you must make sure to call
|
||||||
|
/// FspFileSystemNotifyEnd to allow file rename operations to proceed.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// STATUS_SUCCESS or error code. The error code STATUS_CANT_WAIT means that
|
||||||
|
/// a file rename operation is currently in progress and the operation must be
|
||||||
|
/// retried at a later time.
|
||||||
|
/// </returns>
|
||||||
|
public Int32 NotifyBegin(UInt32 Timeout)
|
||||||
|
{
|
||||||
|
return Api.FspFileSystemNotifyBegin(_FileSystemPtr, Timeout);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// End notifying Windows that the file system has file changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// A file system that wishes to notify Windows about file changes must
|
||||||
|
/// first issue an FspFileSystemBegin call, followed by 0 or more
|
||||||
|
/// FspFileSystemNotify calls, followed by an FspFileSystemNotifyEnd call.
|
||||||
|
/// </para><para>
|
||||||
|
/// This operation allows any blocked file rename operations to proceed.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
|
public Int32 NotifyEnd()
|
||||||
|
{
|
||||||
|
return Api.FspFileSystemNotifyEnd(_FileSystemPtr);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Notify Windows that the file system has file changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// A file system that wishes to notify Windows about file changes must
|
||||||
|
/// first issue an FspFileSystemBegin call, followed by 0 or more
|
||||||
|
/// FspFileSystemNotify calls, followed by an FspFileSystemNotifyEnd call.
|
||||||
|
/// </para><para>
|
||||||
|
/// Note that FspFileSystemNotify requires file names to be normalized. A
|
||||||
|
/// normalized file name is one that contains the correct case of all characters
|
||||||
|
/// in the file name.
|
||||||
|
/// </para><para>
|
||||||
|
/// For case-sensitive file systems all file names are normalized by definition.
|
||||||
|
/// For case-insensitive file systems that implement file name normalization,
|
||||||
|
/// a normalized file name is the one that the file system specifies in the
|
||||||
|
/// response to Create or Open (see also FspFileSystemGetOpenFileInfo). For
|
||||||
|
/// case-insensitive file systems that do not implement file name normalization
|
||||||
|
/// a normalized file name is the upper case version of the file name used
|
||||||
|
/// to open the file.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
|
public Int32 Notify(NotifyInfo[] NotifyInfoArray)
|
||||||
|
{
|
||||||
|
return Api.FspFileSystemNotify(_FileSystemPtr, NotifyInfoArray);
|
||||||
|
}
|
||||||
|
|
||||||
/* FSP_FILE_SYSTEM_INTERFACE */
|
/* FSP_FILE_SYSTEM_INTERFACE */
|
||||||
private static Byte[] ByteBufferNotNull = new Byte[0];
|
private static Byte[] ByteBufferNotNull = new Byte[0];
|
||||||
|
@ -310,6 +310,85 @@ namespace Fsp.Interop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct NotifyInfoInternal
|
||||||
|
{
|
||||||
|
internal const int FileNameBufSize = 1024 * 2/*FSP_FSCTL_TRANSACT_PATH_SIZEMAX*/;
|
||||||
|
internal static int FileNameBufOffset =
|
||||||
|
(int)Marshal.OffsetOf(typeof(NotifyInfoInternal), "FileNameBuf");
|
||||||
|
|
||||||
|
internal UInt16 Size;
|
||||||
|
internal UInt32 Filter;
|
||||||
|
internal UInt32 Action;
|
||||||
|
//internal unsafe fixed UInt16 FileNameBuf[];
|
||||||
|
internal unsafe fixed UInt16 FileNameBuf[FileNameBufSize];
|
||||||
|
|
||||||
|
internal unsafe void SetFileNameBuf(String Value)
|
||||||
|
{
|
||||||
|
fixed (UInt16 *P = FileNameBuf)
|
||||||
|
{
|
||||||
|
int Size = null != Value ? Value.Length : 0;
|
||||||
|
if (Size > FileNameBufSize)
|
||||||
|
Size = FileNameBufSize;
|
||||||
|
for (int I = 0; Size > I; I++)
|
||||||
|
P[I] = Value[I];
|
||||||
|
this.Size = (UInt16)(FileNameBufOffset + Size * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumeration of all the possible values for NotifyInfo.Action
|
||||||
|
/// </summary>
|
||||||
|
public enum NotifyAction : UInt32
|
||||||
|
{
|
||||||
|
Added = 1,
|
||||||
|
Removed = 2,
|
||||||
|
Modified = 3,
|
||||||
|
RenamedOldName = 4,
|
||||||
|
RenamedNewName = 5,
|
||||||
|
AddedStream = 6,
|
||||||
|
RemovedStream = 7,
|
||||||
|
ModifiedStream = 8,
|
||||||
|
RemovedByDelete = 9,
|
||||||
|
IdNotTunnelled = 10,
|
||||||
|
TunnelledIdCollision = 11,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumeration of all the possible values for NotifyInfo.Filter
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum NotifyFilter : UInt32
|
||||||
|
{
|
||||||
|
None = 0x00000,
|
||||||
|
ChangeFileName = 0x00001,
|
||||||
|
ChangeDirName = 0x00002,
|
||||||
|
ChangeName = ChangeFileName | ChangeDirName,
|
||||||
|
ChangeAttributes = 0x00004,
|
||||||
|
ChangeSize = 0x00008,
|
||||||
|
ChangeLastWrite = 0x00010,
|
||||||
|
ChangeLastAccess = 0x00020,
|
||||||
|
ChangeCreation = 0x00040,
|
||||||
|
ChangeEa = 0x00080,
|
||||||
|
ChangeSecurity = 0x00100,
|
||||||
|
ChangeStreamName = 0x00200,
|
||||||
|
ChangeStreamSize = 0x00400,
|
||||||
|
ChangeStreamWrite = 0x00800,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains file change notification information.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NotifyInfo
|
||||||
|
{
|
||||||
|
public String FileName;
|
||||||
|
public NotifyAction Action;
|
||||||
|
public NotifyFilter Filter;
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
internal struct FullEaInformation
|
internal struct FullEaInformation
|
||||||
{
|
{
|
||||||
@ -743,6 +822,18 @@ namespace Fsp.Interop
|
|||||||
IntPtr FileSystem,
|
IntPtr FileSystem,
|
||||||
ref FspFsctlTransactRsp Response);
|
ref FspFsctlTransactRsp Response);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate Int32 FspFileSystemNotifyBegin(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
UInt32 Timeout);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate Int32 FspFileSystemNotifyEnd(
|
||||||
|
IntPtr FileSystem);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate Int32 FspFileSystemNotify(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
IntPtr NotifyInfo,
|
||||||
|
UIntPtr Size);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
internal unsafe delegate FspFileSystemOperationContext *FspFileSystemGetOperationContext();
|
internal unsafe delegate FspFileSystemOperationContext *FspFileSystemGetOperationContext();
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
internal delegate IntPtr FspFileSystemMountPointF(
|
internal delegate IntPtr FspFileSystemMountPointF(
|
||||||
@ -805,6 +896,13 @@ namespace Fsp.Interop
|
|||||||
out UInt32 PBytesTransferred);
|
out UInt32 PBytesTransferred);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
[return: MarshalAs(UnmanagedType.U1)]
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
internal delegate Boolean FspFileSystemAddNotifyInfo(
|
||||||
|
IntPtr NotifyInfo,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Length,
|
||||||
|
out UInt32 PBytesTransferred);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
internal delegate Boolean FspFileSystemAcquireDirectoryBuffer(
|
internal delegate Boolean FspFileSystemAcquireDirectoryBuffer(
|
||||||
ref IntPtr PDirBuffer,
|
ref IntPtr PDirBuffer,
|
||||||
[MarshalAs(UnmanagedType.U1)] Boolean Reset,
|
[MarshalAs(UnmanagedType.U1)] Boolean Reset,
|
||||||
@ -930,6 +1028,9 @@ namespace Fsp.Interop
|
|||||||
internal static Proto.FspFileSystemStartDispatcher FspFileSystemStartDispatcher;
|
internal static Proto.FspFileSystemStartDispatcher FspFileSystemStartDispatcher;
|
||||||
internal static Proto.FspFileSystemStopDispatcher FspFileSystemStopDispatcher;
|
internal static Proto.FspFileSystemStopDispatcher FspFileSystemStopDispatcher;
|
||||||
internal static Proto.FspFileSystemSendResponse FspFileSystemSendResponse;
|
internal static Proto.FspFileSystemSendResponse FspFileSystemSendResponse;
|
||||||
|
internal static Proto.FspFileSystemNotifyBegin FspFileSystemNotifyBegin;
|
||||||
|
internal static Proto.FspFileSystemNotifyEnd FspFileSystemNotifyEnd;
|
||||||
|
internal static Proto.FspFileSystemNotify _FspFileSystemNotify;
|
||||||
internal static Proto.FspFileSystemGetOperationContext FspFileSystemGetOperationContext;
|
internal static Proto.FspFileSystemGetOperationContext FspFileSystemGetOperationContext;
|
||||||
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
||||||
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
||||||
@ -941,6 +1042,7 @@ namespace Fsp.Interop
|
|||||||
internal static Proto.FspFileSystemCanReplaceReparsePoint _FspFileSystemCanReplaceReparsePoint;
|
internal static Proto.FspFileSystemCanReplaceReparsePoint _FspFileSystemCanReplaceReparsePoint;
|
||||||
internal static Proto.FspFileSystemAddStreamInfo _FspFileSystemAddStreamInfo;
|
internal static Proto.FspFileSystemAddStreamInfo _FspFileSystemAddStreamInfo;
|
||||||
internal static Proto.FspFileSystemAddEa _FspFileSystemAddEa;
|
internal static Proto.FspFileSystemAddEa _FspFileSystemAddEa;
|
||||||
|
internal static Proto.FspFileSystemAddNotifyInfo _FspFileSystemAddNotifyInfo;
|
||||||
internal static Proto.FspFileSystemAcquireDirectoryBuffer FspFileSystemAcquireDirectoryBuffer;
|
internal static Proto.FspFileSystemAcquireDirectoryBuffer FspFileSystemAcquireDirectoryBuffer;
|
||||||
internal static Proto.FspFileSystemFillDirectoryBuffer FspFileSystemFillDirectoryBuffer;
|
internal static Proto.FspFileSystemFillDirectoryBuffer FspFileSystemFillDirectoryBuffer;
|
||||||
internal static Proto.FspFileSystemReleaseDirectoryBuffer FspFileSystemReleaseDirectoryBuffer;
|
internal static Proto.FspFileSystemReleaseDirectoryBuffer FspFileSystemReleaseDirectoryBuffer;
|
||||||
@ -1013,6 +1115,15 @@ namespace Fsp.Interop
|
|||||||
{
|
{
|
||||||
return _FspFileSystemAddStreamInfo(IntPtr.Zero, Buffer, Length, out PBytesTransferred);
|
return _FspFileSystemAddStreamInfo(IntPtr.Zero, Buffer, Length, out PBytesTransferred);
|
||||||
}
|
}
|
||||||
|
internal static unsafe Boolean FspFileSystemAddNotifyInfo(
|
||||||
|
ref NotifyInfoInternal NotifyInfo,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Length,
|
||||||
|
out UInt32 PBytesTransferred)
|
||||||
|
{
|
||||||
|
fixed (NotifyInfoInternal *P = &NotifyInfo)
|
||||||
|
return _FspFileSystemAddNotifyInfo((IntPtr)P, Buffer, Length, out PBytesTransferred);
|
||||||
|
}
|
||||||
|
|
||||||
internal delegate Int32 EnumerateEa(
|
internal delegate Int32 EnumerateEa(
|
||||||
Object FileNode,
|
Object FileNode,
|
||||||
@ -1070,6 +1181,35 @@ namespace Fsp.Interop
|
|||||||
return _FspFileSystemAddEa(IntPtr.Zero, Buffer, Length, out PBytesTransferred);
|
return _FspFileSystemAddEa(IntPtr.Zero, Buffer, Length, out PBytesTransferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static unsafe Int32 FspFileSystemNotify(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
NotifyInfo[] NotifyInfoArray)
|
||||||
|
{
|
||||||
|
int Length = 0;
|
||||||
|
for (int I = 0; NotifyInfoArray.Length > I; I++)
|
||||||
|
{
|
||||||
|
Length += NotifyInfoInternal.FileNameBufOffset +
|
||||||
|
NotifyInfoArray[I].FileName.Length * 2;
|
||||||
|
Length = (Length + 7) & ~7; // align to next qword boundary
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte[] Buffer = new Byte[Length];
|
||||||
|
UInt32 BytesTransferred = default(UInt32);
|
||||||
|
fixed (Byte *P = Buffer)
|
||||||
|
{
|
||||||
|
for (int I = 0; NotifyInfoArray.Length > I; I++)
|
||||||
|
{
|
||||||
|
NotifyInfoInternal Internal = default(NotifyInfoInternal);
|
||||||
|
Internal.Action = (UInt32)NotifyInfoArray[I].Action;
|
||||||
|
Internal.Filter = (UInt32)NotifyInfoArray[I].Filter;
|
||||||
|
Internal.SetFileNameBuf(NotifyInfoArray[I].FileName);
|
||||||
|
FspFileSystemAddNotifyInfo(
|
||||||
|
ref Internal, (IntPtr)P, (UInt32)Length, out BytesTransferred);
|
||||||
|
}
|
||||||
|
return _FspFileSystemNotify(FileSystem, (IntPtr)P, (UIntPtr)BytesTransferred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal unsafe static Object GetUserContext(
|
internal unsafe static Object GetUserContext(
|
||||||
IntPtr NativePtr)
|
IntPtr NativePtr)
|
||||||
{
|
{
|
||||||
@ -1330,6 +1470,9 @@ namespace Fsp.Interop
|
|||||||
FspFileSystemStartDispatcher = GetEntryPoint<Proto.FspFileSystemStartDispatcher>(Module);
|
FspFileSystemStartDispatcher = GetEntryPoint<Proto.FspFileSystemStartDispatcher>(Module);
|
||||||
FspFileSystemStopDispatcher = GetEntryPoint<Proto.FspFileSystemStopDispatcher>(Module);
|
FspFileSystemStopDispatcher = GetEntryPoint<Proto.FspFileSystemStopDispatcher>(Module);
|
||||||
FspFileSystemSendResponse = GetEntryPoint<Proto.FspFileSystemSendResponse>(Module);
|
FspFileSystemSendResponse = GetEntryPoint<Proto.FspFileSystemSendResponse>(Module);
|
||||||
|
FspFileSystemNotifyBegin = GetEntryPoint<Proto.FspFileSystemNotifyBegin>(Module);
|
||||||
|
FspFileSystemNotifyEnd = GetEntryPoint<Proto.FspFileSystemNotifyEnd>(Module);
|
||||||
|
_FspFileSystemNotify = GetEntryPoint<Proto.FspFileSystemNotify>(Module);
|
||||||
FspFileSystemGetOperationContext = GetEntryPoint<Proto.FspFileSystemGetOperationContext>(Module);
|
FspFileSystemGetOperationContext = GetEntryPoint<Proto.FspFileSystemGetOperationContext>(Module);
|
||||||
FspFileSystemMountPoint = GetEntryPoint<Proto.FspFileSystemMountPointF>(Module);
|
FspFileSystemMountPoint = GetEntryPoint<Proto.FspFileSystemMountPointF>(Module);
|
||||||
FspFileSystemSetOperationGuardStrategy = GetEntryPoint<Proto.FspFileSystemSetOperationGuardStrategyF>(Module);
|
FspFileSystemSetOperationGuardStrategy = GetEntryPoint<Proto.FspFileSystemSetOperationGuardStrategyF>(Module);
|
||||||
@ -1341,6 +1484,7 @@ namespace Fsp.Interop
|
|||||||
_FspFileSystemCanReplaceReparsePoint = GetEntryPoint<Proto.FspFileSystemCanReplaceReparsePoint>(Module);
|
_FspFileSystemCanReplaceReparsePoint = GetEntryPoint<Proto.FspFileSystemCanReplaceReparsePoint>(Module);
|
||||||
_FspFileSystemAddStreamInfo = GetEntryPoint<Proto.FspFileSystemAddStreamInfo>(Module);
|
_FspFileSystemAddStreamInfo = GetEntryPoint<Proto.FspFileSystemAddStreamInfo>(Module);
|
||||||
_FspFileSystemAddEa = GetEntryPoint<Proto.FspFileSystemAddEa>(Module);
|
_FspFileSystemAddEa = GetEntryPoint<Proto.FspFileSystemAddEa>(Module);
|
||||||
|
_FspFileSystemAddNotifyInfo = GetEntryPoint<Proto.FspFileSystemAddNotifyInfo>(Module);
|
||||||
FspFileSystemAcquireDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemAcquireDirectoryBuffer>(Module);
|
FspFileSystemAcquireDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemAcquireDirectoryBuffer>(Module);
|
||||||
FspFileSystemFillDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemFillDirectoryBuffer>(Module);
|
FspFileSystemFillDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemFillDirectoryBuffer>(Module);
|
||||||
FspFileSystemReleaseDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemReleaseDirectoryBuffer>(Module);
|
FspFileSystemReleaseDirectoryBuffer = GetEntryPoint<Proto.FspFileSystemReleaseDirectoryBuffer>(Module);
|
||||||
|
@ -55,36 +55,6 @@ static void printlog(HANDLE h, const char *format, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned wcstoint(const wchar_t *p, const wchar_t **endp, int base)
|
|
||||||
{
|
|
||||||
unsigned v;
|
|
||||||
int maxdig, maxalp;
|
|
||||||
|
|
||||||
maxdig = 10 < base ? '9' : (base - 1) + '0';
|
|
||||||
maxalp = 10 < base ? (base - 1 - 10) + 'a' : 0;
|
|
||||||
|
|
||||||
for (v = 0; *p; p++)
|
|
||||||
{
|
|
||||||
int c = *p;
|
|
||||||
|
|
||||||
if ('0' <= c && c <= maxdig)
|
|
||||||
v = base * v + (c - '0');
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c |= 0x20;
|
|
||||||
if ('a' <= c && c <= maxalp)
|
|
||||||
v = base * v + (c - 'a') + 10;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != endp)
|
|
||||||
*endp = (wchar_t *)p;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fatal(ERROR_INVALID_PARAMETER,
|
fatal(ERROR_INVALID_PARAMETER,
|
||||||
@ -380,7 +350,7 @@ static NTSTATUS id_uid(PWSTR UidStr)
|
|||||||
UINT32 Uid;
|
UINT32 Uid;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Uid = wcstoint(UidStr, &UidStr, 10);
|
Uid = wcstouint(UidStr, &UidStr, 10, 0);
|
||||||
if (L'\0' != *UidStr)
|
if (L'\0' != *UidStr)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
@ -525,13 +495,13 @@ static NTSTATUS perm_mode(PWSTR PermStr)
|
|||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Uid = wcstoint(PermStr, &PermStr, 10);
|
Uid = wcstouint(PermStr, &PermStr, 10, 0);
|
||||||
if (L':' != *PermStr)
|
if (L':' != *PermStr)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
Gid = wcstoint(PermStr + 1, &PermStr, 10);
|
Gid = wcstouint(PermStr + 1, &PermStr, 10, 0);
|
||||||
if (L':' != *PermStr)
|
if (L':' != *PermStr)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
Mode = wcstoint(PermStr + 1, &PermStr, 8);
|
Mode = wcstouint(PermStr + 1, &PermStr, 8, 0);
|
||||||
if (L'\0' != *PermStr)
|
if (L'\0' != *PermStr)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
#include <aclapi.h>
|
#include <aclapi.h>
|
||||||
|
#include <dsgetdc.h>
|
||||||
|
#include <lm.h>
|
||||||
#define _NTDEF_
|
#define _NTDEF_
|
||||||
#include <ntsecapi.h>
|
#include <ntsecapi.h>
|
||||||
|
|
||||||
|
@ -41,6 +41,10 @@ FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)());
|
|||||||
FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
||||||
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
|
FSP_API NTSTATUS FspPosixMergePermissionsToSecurityDescriptor(
|
||||||
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
|
PSECURITY_DESCRIPTOR ExistingSecurityDescriptor,
|
||||||
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode);
|
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode);
|
||||||
@ -59,6 +63,7 @@ FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size);
|
|||||||
#pragma alloc_text(PAGE, FspPosixCreateSid)
|
#pragma alloc_text(PAGE, FspPosixCreateSid)
|
||||||
#pragma alloc_text(PAGE, FspDeleteSid)
|
#pragma alloc_text(PAGE, FspDeleteSid)
|
||||||
#pragma alloc_text(PAGE, FspPosixMapPermissionsToSecurityDescriptor)
|
#pragma alloc_text(PAGE, FspPosixMapPermissionsToSecurityDescriptor)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMergePermissionsToSecurityDescriptor)
|
||||||
#pragma alloc_text(PAGE, FspPosixMapSecurityDescriptorToPermissions)
|
#pragma alloc_text(PAGE, FspPosixMapSecurityDescriptorToPermissions)
|
||||||
#pragma alloc_text(PAGE, FspPosixMapWindowsToPosixPathEx)
|
#pragma alloc_text(PAGE, FspPosixMapWindowsToPosixPathEx)
|
||||||
#pragma alloc_text(PAGE, FspPosixMapPosixToWindowsPathEx)
|
#pragma alloc_text(PAGE, FspPosixMapPosixToWindowsPathEx)
|
||||||
@ -111,8 +116,59 @@ static union
|
|||||||
#define FspUnmappedUid (65534)
|
#define FspUnmappedUid (65534)
|
||||||
|
|
||||||
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
PSID DomainSid;
|
||||||
|
PWSTR NetbiosDomainName;
|
||||||
|
PWSTR DnsDomainName;
|
||||||
|
ULONG TrustPosixOffset;
|
||||||
|
} *FspTrustedDomains;
|
||||||
|
ULONG FspTrustedDomainCount;
|
||||||
static INIT_ONCE FspPosixInitOnce = INIT_ONCE_STATIC_INIT;
|
static INIT_ONCE FspPosixInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
#if !defined(_KERNEL_MODE)
|
#if !defined(_KERNEL_MODE)
|
||||||
|
static ULONG FspPosixInitializeTrustPosixOffsets(VOID)
|
||||||
|
{
|
||||||
|
PVOID Ldap = 0;
|
||||||
|
PWSTR DefaultNamingContext = 0;
|
||||||
|
PWSTR TrustPosixOffsetString = 0;
|
||||||
|
ULONG LdapResult;
|
||||||
|
|
||||||
|
LdapResult = FspLdapConnect(0/* default LDAP server */, &Ldap);
|
||||||
|
if (0 != LdapResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
LdapResult = FspLdapGetDefaultNamingContext(Ldap, &DefaultNamingContext);
|
||||||
|
if (0 != LdapResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* get the "trustPosixOffset" for each trusted domain */
|
||||||
|
for (ULONG I = 0; FspTrustedDomainCount > I; I++)
|
||||||
|
{
|
||||||
|
MemFree(TrustPosixOffsetString);
|
||||||
|
LdapResult = FspLdapGetTrustPosixOffset(Ldap,
|
||||||
|
DefaultNamingContext, FspTrustedDomains[I].DnsDomainName, &TrustPosixOffsetString);
|
||||||
|
if (0 == LdapResult)
|
||||||
|
FspTrustedDomains[I].TrustPosixOffset = wcstouint(TrustPosixOffsetString, 0, 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LdapResult = 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(TrustPosixOffsetString);
|
||||||
|
MemFree(DefaultNamingContext);
|
||||||
|
if (0 != Ldap)
|
||||||
|
FspLdapClose(Ldap);
|
||||||
|
|
||||||
|
/* if the "trustPosixOffset" looks wrong, fix it up using Cygwin magic value 0xfe500000 */
|
||||||
|
for (ULONG I = 0; FspTrustedDomainCount > I; I++)
|
||||||
|
{
|
||||||
|
if (0x100000 > FspTrustedDomains[I].TrustPosixOffset)
|
||||||
|
FspTrustedDomains[I].TrustPosixOffset = 0xfe500000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LdapResult;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL WINAPI FspPosixInitialize(
|
static BOOL WINAPI FspPosixInitialize(
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
{
|
{
|
||||||
@ -120,8 +176,10 @@ static BOOL WINAPI FspPosixInitialize(
|
|||||||
LSA_HANDLE PolicyHandle = 0;
|
LSA_HANDLE PolicyHandle = 0;
|
||||||
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = 0;
|
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = 0;
|
||||||
PPOLICY_DNS_DOMAIN_INFO PrimaryDomainInfo = 0;
|
PPOLICY_DNS_DOMAIN_INFO PrimaryDomainInfo = 0;
|
||||||
|
PDS_DOMAIN_TRUSTSW TrustedDomains = 0;
|
||||||
|
ULONG TrustedDomainCount, RealTrustedDomainCount;
|
||||||
BYTE Count;
|
BYTE Count;
|
||||||
ULONG Size;
|
ULONG Size, Temp;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Result = LsaOpenPolicy(0, &Obja, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
|
Result = LsaOpenPolicy(0, &Obja, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
|
||||||
@ -148,9 +206,104 @@ static BOOL WINAPI FspPosixInitialize(
|
|||||||
FspPrimaryDomainSid = MemAlloc(Size);
|
FspPrimaryDomainSid = MemAlloc(Size);
|
||||||
if (0 != FspPrimaryDomainSid)
|
if (0 != FspPrimaryDomainSid)
|
||||||
memcpy(FspPrimaryDomainSid, PrimaryDomainInfo->Sid, Size);
|
memcpy(FspPrimaryDomainSid, PrimaryDomainInfo->Sid, Size);
|
||||||
|
|
||||||
|
if (ERROR_SUCCESS == DsEnumerateDomainTrustsW(
|
||||||
|
0, DS_DOMAIN_DIRECT_INBOUND | DS_DOMAIN_DIRECT_OUTBOUND | DS_DOMAIN_IN_FOREST,
|
||||||
|
&TrustedDomains, &TrustedDomainCount))
|
||||||
|
{
|
||||||
|
Size = 0;
|
||||||
|
RealTrustedDomainCount = 0;
|
||||||
|
for (ULONG I = 0; TrustedDomainCount > I; I++)
|
||||||
|
{
|
||||||
|
if (0 == TrustedDomains[I].DomainSid ||
|
||||||
|
(0 == TrustedDomains[I].NetbiosDomainName &&
|
||||||
|
0 == TrustedDomains[I].DnsDomainName) ||
|
||||||
|
EqualSid(TrustedDomains[I].DomainSid, FspPrimaryDomainSid))
|
||||||
|
continue;
|
||||||
|
if (0 != TrustedDomains[I].DomainSid)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_DEFAULT_ALIGN_UP(Size);
|
||||||
|
Size += GetLengthSid(TrustedDomains[I].DomainSid);
|
||||||
|
}
|
||||||
|
if (0 != TrustedDomains[I].NetbiosDomainName)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_ALIGN_UP(Size, sizeof(WCHAR));
|
||||||
|
Size += (lstrlenW(TrustedDomains[I].NetbiosDomainName) + 1) * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
if (0 != TrustedDomains[I].DnsDomainName)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_ALIGN_UP(Size, sizeof(WCHAR));
|
||||||
|
Size += (lstrlenW(TrustedDomains[I].DnsDomainName) + 1) * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
RealTrustedDomainCount++;
|
||||||
|
}
|
||||||
|
Size = FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof FspTrustedDomains[0] * RealTrustedDomainCount) + Size;
|
||||||
|
if (0 < RealTrustedDomainCount)
|
||||||
|
{
|
||||||
|
FspTrustedDomains = MemAlloc(Size);
|
||||||
|
if (0 != FspTrustedDomains)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof FspTrustedDomains[0] * RealTrustedDomainCount);
|
||||||
|
for (ULONG I = 0, J = 0; TrustedDomainCount > I; I++)
|
||||||
|
{
|
||||||
|
if (0 == TrustedDomains[I].DomainSid ||
|
||||||
|
(0 == TrustedDomains[I].NetbiosDomainName &&
|
||||||
|
0 == TrustedDomains[I].DnsDomainName) ||
|
||||||
|
EqualSid(TrustedDomains[I].DomainSid, FspPrimaryDomainSid))
|
||||||
|
continue;
|
||||||
|
FspTrustedDomains[J].DomainSid = 0;
|
||||||
|
FspTrustedDomains[J].NetbiosDomainName = 0;
|
||||||
|
FspTrustedDomains[J].DnsDomainName = 0;
|
||||||
|
FspTrustedDomains[J].TrustPosixOffset = 0;
|
||||||
|
if (0 != TrustedDomains[I].DomainSid)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_DEFAULT_ALIGN_UP(Size);
|
||||||
|
FspTrustedDomains[J].DomainSid =
|
||||||
|
(PVOID)((PUINT8)FspTrustedDomains + Size);
|
||||||
|
Size += (Temp = GetLengthSid(TrustedDomains[I].DomainSid));
|
||||||
|
memcpy(FspTrustedDomains[J].DomainSid,
|
||||||
|
TrustedDomains[I].DomainSid, Temp);
|
||||||
|
}
|
||||||
|
if (0 != TrustedDomains[I].NetbiosDomainName)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_ALIGN_UP(Size, sizeof(WCHAR));
|
||||||
|
FspTrustedDomains[J].NetbiosDomainName =
|
||||||
|
(PVOID)((PUINT8)FspTrustedDomains + Size);
|
||||||
|
Size += (Temp = (lstrlenW(TrustedDomains[I].NetbiosDomainName) + 1) * sizeof(WCHAR));
|
||||||
|
memcpy(FspTrustedDomains[J].NetbiosDomainName,
|
||||||
|
TrustedDomains[I].NetbiosDomainName, Temp);
|
||||||
|
}
|
||||||
|
if (0 != TrustedDomains[I].DnsDomainName)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_ALIGN_UP(Size, sizeof(WCHAR));
|
||||||
|
FspTrustedDomains[J].DnsDomainName =
|
||||||
|
(PVOID)((PUINT8)FspTrustedDomains + Size);
|
||||||
|
Size += (Temp = (lstrlenW(TrustedDomains[I].DnsDomainName) + 1) * sizeof(WCHAR));
|
||||||
|
memcpy(FspTrustedDomains[J].DnsDomainName,
|
||||||
|
TrustedDomains[I].DnsDomainName, Temp);
|
||||||
|
}
|
||||||
|
if (0 == FspTrustedDomains[J].NetbiosDomainName)
|
||||||
|
FspTrustedDomains[J].NetbiosDomainName =
|
||||||
|
FspTrustedDomains[J].DnsDomainName;
|
||||||
|
else
|
||||||
|
if (0 == FspTrustedDomains[J].DnsDomainName)
|
||||||
|
FspTrustedDomains[J].DnsDomainName =
|
||||||
|
FspTrustedDomains[J].NetbiosDomainName;
|
||||||
|
J++;
|
||||||
|
}
|
||||||
|
FspTrustedDomainCount = RealTrustedDomainCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 < FspTrustedDomainCount)
|
||||||
|
FspPosixInitializeTrustPosixOffsets();
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
if (0 != TrustedDomains)
|
||||||
|
NetApiBufferFree(TrustedDomains);
|
||||||
|
|
||||||
if (0 != PrimaryDomainInfo)
|
if (0 != PrimaryDomainInfo)
|
||||||
LsaFreeMemory(PrimaryDomainInfo);
|
LsaFreeMemory(PrimaryDomainInfo);
|
||||||
|
|
||||||
@ -172,6 +325,7 @@ VOID FspPosixFinalize(BOOLEAN Dynamic)
|
|||||||
|
|
||||||
if (Dynamic)
|
if (Dynamic)
|
||||||
{
|
{
|
||||||
|
MemFree(FspTrustedDomains);
|
||||||
MemFree(FspAccountDomainSid);
|
MemFree(FspAccountDomainSid);
|
||||||
MemFree(FspPrimaryDomainSid);
|
MemFree(FspPrimaryDomainSid);
|
||||||
}
|
}
|
||||||
@ -318,7 +472,8 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
|||||||
}
|
}
|
||||||
else if (0x100000 <= Uid && Uid < 0xff000000)
|
else if (0x100000 <= Uid && Uid < 0xff000000)
|
||||||
{
|
{
|
||||||
if (0 != FspPrimaryDomainSid &&
|
if ((Uid < 0x300000 || 0 == FspTrustedDomainCount) &&
|
||||||
|
0 != FspPrimaryDomainSid &&
|
||||||
5 == FspPrimaryDomainSid->IdentifierAuthority.Value[5] &&
|
5 == FspPrimaryDomainSid->IdentifierAuthority.Value[5] &&
|
||||||
4 == FspPrimaryDomainSid->SubAuthorityCount)
|
4 == FspPrimaryDomainSid->SubAuthorityCount)
|
||||||
{
|
{
|
||||||
@ -329,11 +484,30 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
|||||||
FspPrimaryDomainSid->SubAuthority[3],
|
FspPrimaryDomainSid->SubAuthority[3],
|
||||||
Uid - 0x100000);
|
Uid - 0x100000);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PISID DomainSid = 0;
|
||||||
|
ULONG TrustPosixOffset = 0;
|
||||||
|
for (ULONG I = 0; FspTrustedDomainCount > I; I++)
|
||||||
|
{
|
||||||
|
if (FspTrustedDomains[I].TrustPosixOffset <= Uid &&
|
||||||
|
FspTrustedDomains[I].TrustPosixOffset > TrustPosixOffset)
|
||||||
|
{
|
||||||
|
DomainSid = FspTrustedDomains[I].DomainSid;
|
||||||
|
TrustPosixOffset = FspTrustedDomains[I].TrustPosixOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 != DomainSid)
|
||||||
|
{
|
||||||
|
*PSid = FspPosixCreateSid(5, 5,
|
||||||
|
21,
|
||||||
|
DomainSid->SubAuthority[1],
|
||||||
|
DomainSid->SubAuthority[2],
|
||||||
|
DomainSid->SubAuthority[3],
|
||||||
|
Uid - TrustPosixOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* I am sorry, I am not going to bother with all that trustPosixOffset stuff.
|
|
||||||
* But if you need it, I accept patches :)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* [IDMAP]
|
/* [IDMAP]
|
||||||
* Mandatory Labels:
|
* Mandatory Labels:
|
||||||
@ -432,11 +606,15 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
|||||||
else if (0 != FspAccountDomainSid &&
|
else if (0 != FspAccountDomainSid &&
|
||||||
FspPosixIsRelativeSid(FspAccountDomainSid, Sid))
|
FspPosixIsRelativeSid(FspAccountDomainSid, Sid))
|
||||||
*PUid = 0x30000 + Rid;
|
*PUid = 0x30000 + Rid;
|
||||||
|
else
|
||||||
/*
|
for (ULONG I = 0; FspTrustedDomainCount > I; I++)
|
||||||
* I am sorry, I am not going to bother with all that trustPosixOffset stuff.
|
{
|
||||||
* But if you need it, I accept patches :)
|
if (FspPosixIsRelativeSid(FspTrustedDomains[I].DomainSid, Sid))
|
||||||
*/
|
{
|
||||||
|
*PUid = FspTrustedDomains[I].TrustPosixOffset + Rid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [IDMAP]
|
/* [IDMAP]
|
||||||
@ -725,6 +903,101 @@ lasterror:
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspPosixMergePermissionsToSecurityDescriptor(
|
||||||
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
|
PSECURITY_DESCRIPTOR ExistingSecurityDescriptor,
|
||||||
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
||||||
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
if (0 == ExistingSecurityDescriptor)
|
||||||
|
return FspPosixMapPermissionsToSecurityDescriptor(Uid, Gid, Mode, PSecurityDescriptor);
|
||||||
|
|
||||||
|
PSID ExistingOwnerSid = 0, ExistingGroupSid = 0;
|
||||||
|
BOOL Defaulted, ExistingDaclPresent;
|
||||||
|
PACL ExistingAcl = 0;
|
||||||
|
PSID OwnerSid = 0, GroupSid = 0;
|
||||||
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
|
PSECURITY_DESCRIPTOR RelativeSecurityDescriptor = 0;
|
||||||
|
ULONG Size;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PSecurityDescriptor = 0;
|
||||||
|
|
||||||
|
if (!GetSecurityDescriptorOwner(ExistingSecurityDescriptor, &ExistingOwnerSid, &Defaulted))
|
||||||
|
goto lasterror;
|
||||||
|
if (!GetSecurityDescriptorGroup(ExistingSecurityDescriptor, &ExistingGroupSid, &Defaulted))
|
||||||
|
goto lasterror;
|
||||||
|
if (!GetSecurityDescriptorDacl(ExistingSecurityDescriptor, &ExistingDaclPresent, &ExistingAcl, &Defaulted))
|
||||||
|
goto lasterror;
|
||||||
|
|
||||||
|
if (0 == ExistingOwnerSid)
|
||||||
|
{
|
||||||
|
Result = FspPosixMapUidToSid(Uid, &OwnerSid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
ExistingOwnerSid = OwnerSid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == ExistingGroupSid)
|
||||||
|
{
|
||||||
|
Result = FspPosixMapUidToSid(Gid, &GroupSid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
ExistingGroupSid = GroupSid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InitializeSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
|
||||||
|
goto lasterror;
|
||||||
|
|
||||||
|
if (!SetSecurityDescriptorOwner(&SecurityDescriptor, ExistingOwnerSid, FALSE))
|
||||||
|
goto lasterror;
|
||||||
|
if (!SetSecurityDescriptorGroup(&SecurityDescriptor, ExistingGroupSid, FALSE))
|
||||||
|
goto lasterror;
|
||||||
|
if (0 != ExistingAcl)
|
||||||
|
{
|
||||||
|
if (!SetSecurityDescriptorControl(&SecurityDescriptor, SE_DACL_PROTECTED, SE_DACL_PROTECTED))
|
||||||
|
goto lasterror;
|
||||||
|
if (!SetSecurityDescriptorDacl(&SecurityDescriptor, TRUE, ExistingAcl, FALSE))
|
||||||
|
goto lasterror;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = 0;
|
||||||
|
if (!MakeSelfRelativeSD(&SecurityDescriptor, 0, &Size) &&
|
||||||
|
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
goto lasterror;
|
||||||
|
|
||||||
|
RelativeSecurityDescriptor = MemAlloc(Size);
|
||||||
|
if (0 == RelativeSecurityDescriptor)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MakeSelfRelativeSD(&SecurityDescriptor, RelativeSecurityDescriptor, &Size))
|
||||||
|
goto lasterror;
|
||||||
|
|
||||||
|
*PSecurityDescriptor = RelativeSecurityDescriptor;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
MemFree(RelativeSecurityDescriptor);
|
||||||
|
|
||||||
|
if (0 != GroupSid)
|
||||||
|
FspDeleteSid(GroupSid, FspPosixMapUidToSid);
|
||||||
|
|
||||||
|
if (0 != OwnerSid)
|
||||||
|
FspDeleteSid(OwnerSid, FspPosixMapUidToSid);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
lasterror:
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
static inline ACCESS_MASK FspPosixCanonicalizeAccessMask(ACCESS_MASK AccessMask)
|
static inline ACCESS_MASK FspPosixCanonicalizeAccessMask(ACCESS_MASK AccessMask)
|
||||||
{
|
{
|
||||||
PGENERIC_MAPPING Mapping = FspGetFileGenericMapping();
|
PGENERIC_MAPPING Mapping = FspGetFileGenericMapping();
|
||||||
|
@ -130,6 +130,62 @@ WINFSP_SHARED_MINIMAL_STRNCMP(invariant_wcsnicmp, wchar_t, invariant_toupper)
|
|||||||
#undef WINFSP_SHARED_MINIMAL_STRCMP
|
#undef WINFSP_SHARED_MINIMAL_STRCMP
|
||||||
#undef WINFSP_SHARED_MINIMAL_STRNCMP
|
#undef WINFSP_SHARED_MINIMAL_STRNCMP
|
||||||
|
|
||||||
|
#define WINFSP_SHARED_MINIMAL_STRTOINT(NAME, CTYPE, ITYPE)\
|
||||||
|
static inline\
|
||||||
|
ITYPE NAME(const CTYPE *p, const CTYPE **endp, int base, int is_signed)\
|
||||||
|
{\
|
||||||
|
ITYPE v;\
|
||||||
|
int maxdig, maxalp, sign = +1;\
|
||||||
|
if (is_signed)\
|
||||||
|
{\
|
||||||
|
if ('+' == *p)\
|
||||||
|
p++;\
|
||||||
|
else if ('-' == *p)\
|
||||||
|
p++, sign = -1;\
|
||||||
|
}\
|
||||||
|
if (0 == base)\
|
||||||
|
{\
|
||||||
|
if ('0' == *p)\
|
||||||
|
{\
|
||||||
|
p++;\
|
||||||
|
if ('x' == *p || 'X' == *p)\
|
||||||
|
{\
|
||||||
|
p++;\
|
||||||
|
base = 16;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
base = 8;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
base = 10;\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
maxdig = 10 < base ? '9' : (base - 1) + '0';\
|
||||||
|
maxalp = 10 < base ? (base - 1 - 10) + 'a' : 0;\
|
||||||
|
for (v = 0; *p; p++)\
|
||||||
|
{\
|
||||||
|
int c = *p;\
|
||||||
|
if ('0' <= c && c <= maxdig)\
|
||||||
|
v = base * v + (c - '0');\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
c |= 0x20;\
|
||||||
|
if ('a' <= c && c <= maxalp)\
|
||||||
|
v = base * v + (c - 'a') + 10;\
|
||||||
|
else\
|
||||||
|
break;\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
if (0 != endp)\
|
||||||
|
*endp = (CTYPE *)p;\
|
||||||
|
return sign * v;\
|
||||||
|
}
|
||||||
|
WINFSP_SHARED_MINIMAL_STRTOINT(strtouint, char, unsigned int)
|
||||||
|
WINFSP_SHARED_MINIMAL_STRTOINT(strtollint, char, long long int)
|
||||||
|
WINFSP_SHARED_MINIMAL_STRTOINT(wcstouint, wchar_t, unsigned int)
|
||||||
|
WINFSP_SHARED_MINIMAL_STRTOINT(wcstollint, wchar_t, long long int)
|
||||||
|
|
||||||
static inline void *MemAlloc(size_t Size)
|
static inline void *MemAlloc(size_t Size)
|
||||||
{
|
{
|
||||||
return HeapAlloc(GetProcessHeap(), 0, Size);
|
return HeapAlloc(GetProcessHeap(), 0, Size);
|
||||||
|
@ -84,8 +84,9 @@ static NTSTATUS FspFsvolClose(
|
|||||||
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
||||||
FspFileNodeDereference(FileNode);
|
FspFileNodeDereference(FileNode);
|
||||||
|
|
||||||
/* if we are closing files in the context of a rename make it synchronous */
|
/* if closing in the context of a rename or IOQ is above the watermark make it synchronous */
|
||||||
if (FspFsvolDeviceFileRenameIsAcquiredExclusive(FsvolDeviceObject))
|
if (FspFsvolDeviceFileRenameIsAcquiredExclusive(FsvolDeviceObject) ||
|
||||||
|
FspIoqPendingAboveWatermark(FspFsvolDeviceExtension(FsvolDeviceObject)->Ioq, 50))
|
||||||
{
|
{
|
||||||
/* acquire ownership of the Request */
|
/* acquire ownership of the Request */
|
||||||
Request->Hint = (UINT_PTR)Irp;
|
Request->Hint = (UINT_PTR)Irp;
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
#if DBG
|
#if DBG
|
||||||
|
|
||||||
|
#undef STATUS_INSUFFICIENT_RESOURCES
|
||||||
|
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
|
||||||
|
|
||||||
#define SYM(x) case x: return #x;
|
#define SYM(x) case x: return #x;
|
||||||
#define SYMBRC(x) case x: return "[" #x "]";
|
#define SYMBRC(x) case x: return "[" #x "]";
|
||||||
|
|
||||||
@ -330,4 +334,5 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result)
|
|||||||
NtStatusSym(Result),
|
NtStatusSym(Result),
|
||||||
(LONGLONG)Irp->IoStatus.Information);
|
(LONGLONG)Irp->IoStatus.Information);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,7 +41,9 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject);
|
|||||||
static IO_TIMER_ROUTINE FspFsvolDeviceTimerRoutine;
|
static IO_TIMER_ROUTINE FspFsvolDeviceTimerRoutine;
|
||||||
static WORKER_THREAD_ROUTINE FspFsvolDeviceExpirationRoutine;
|
static WORKER_THREAD_ROUTINE FspFsvolDeviceExpirationRoutine;
|
||||||
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
@ -83,7 +85,9 @@ VOID FspDeviceDeleteAll(VOID);
|
|||||||
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireShared)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireShared)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameTryAcquireShared)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireExclusive)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireExclusive)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameTryAcquireExclusive)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
||||||
@ -411,10 +415,11 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
return Result;
|
return Result;
|
||||||
FsvolDeviceExtension->InitDoneEa = 1;
|
FsvolDeviceExtension->InitDoneEa = 1;
|
||||||
|
|
||||||
/* initialize the FSRTL Notify mechanism */
|
/* initialize the Volume Notify and FSRTL Notify mechanisms */
|
||||||
Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync);
|
Result = FspNotifyInitializeSync(&FsvolDeviceExtension->NotifySync);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
FspWgroupInitialize(&FsvolDeviceExtension->VolumeNotifyWgroup);
|
||||||
InitializeListHead(&FsvolDeviceExtension->NotifyList);
|
InitializeListHead(&FsvolDeviceExtension->NotifyList);
|
||||||
FsvolDeviceExtension->InitDoneNotify = 1;
|
FsvolDeviceExtension->InitDoneNotify = 1;
|
||||||
|
|
||||||
@ -473,7 +478,7 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
|||||||
if (FsvolDeviceExtension->InitDoneStat)
|
if (FsvolDeviceExtension->InitDoneStat)
|
||||||
FspStatisticsDelete(FsvolDeviceExtension->Statistics);
|
FspStatisticsDelete(FsvolDeviceExtension->Statistics);
|
||||||
|
|
||||||
/* uninitialize the FSRTL Notify mechanism */
|
/* uninitialize the Volume Notify and FSRTL Notify mechanisms */
|
||||||
if (FsvolDeviceExtension->InitDoneNotify)
|
if (FsvolDeviceExtension->InitDoneNotify)
|
||||||
{
|
{
|
||||||
FspNotifyCleanupAll(
|
FspNotifyCleanupAll(
|
||||||
@ -596,6 +601,15 @@ VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject)
|
|||||||
ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
|
ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
return ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject)
|
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -605,6 +619,15 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject)
|
|||||||
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
|
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
return ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -38,6 +38,8 @@ NTSTATUS DriverEntry(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_DRV();
|
FSP_ENTER_DRV();
|
||||||
|
|
||||||
|
FSP_TRACE_INIT();
|
||||||
|
|
||||||
/* setup the driver object */
|
/* setup the driver object */
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
|
||||||
@ -157,6 +159,8 @@ exit:
|
|||||||
FspSiloFinalize();
|
FspSiloFinalize();
|
||||||
if (InitDoneGRes)
|
if (InitDoneGRes)
|
||||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||||
|
|
||||||
|
FSP_TRACE_FINI();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
|
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
|
||||||
|
@ -147,6 +147,40 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result);
|
|||||||
#define DEBUGTEST_EX(C, Percent, Deflt) (Deflt)
|
#define DEBUGTEST_EX(C, Percent, Deflt) (Deflt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* trace */
|
||||||
|
#if FSP_TRACE_ENABLED
|
||||||
|
VOID FspTraceInitialize(VOID);
|
||||||
|
VOID FspTraceFinalize(VOID);
|
||||||
|
VOID FspTrace(const char *file, int line, const char *func);
|
||||||
|
VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Status);
|
||||||
|
#define FSP_TRACE_INIT() \
|
||||||
|
FspTraceInitialize()
|
||||||
|
#define FSP_TRACE_FINI() \
|
||||||
|
FspTraceFinalize()
|
||||||
|
#define FSP_TRACE() \
|
||||||
|
FspTrace( \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
__FUNCTION__)
|
||||||
|
#define FSP_TRACE_NTSTATUS(Status) \
|
||||||
|
FspTraceNtStatus( \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
__FUNCTION__, \
|
||||||
|
Status)
|
||||||
|
#else
|
||||||
|
#define FSP_TRACE_INIT() \
|
||||||
|
((VOID)0)
|
||||||
|
#define FSP_TRACE_FINI() \
|
||||||
|
((VOID)0)
|
||||||
|
#define FSP_TRACE() \
|
||||||
|
((VOID)0)
|
||||||
|
#define FSP_TRACE_NTSTATUS(Result) \
|
||||||
|
((VOID)0)
|
||||||
|
#endif
|
||||||
|
#undef STATUS_INSUFFICIENT_RESOURCES
|
||||||
|
#define STATUS_INSUFFICIENT_RESOURCES (FSP_TRACE_NTSTATUS(0xC000009AL), (NTSTATUS)0xC000009AL)
|
||||||
|
|
||||||
/* FSP_ENTER/FSP_LEAVE */
|
/* FSP_ENTER/FSP_LEAVE */
|
||||||
#if DBG
|
#if DBG
|
||||||
#define FSP_DEBUGLOG_(fmt, rfmt, ...) \
|
#define FSP_DEBUGLOG_(fmt, rfmt, ...) \
|
||||||
@ -652,6 +686,28 @@ VOID FspIrpHookReset(PIRP Irp);
|
|||||||
PVOID FspIrpHookContext(PVOID Context);
|
PVOID FspIrpHookContext(PVOID Context);
|
||||||
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||||
|
|
||||||
|
/* utility: wait groups
|
||||||
|
*
|
||||||
|
* A Wait Group is a synchronization primitive that encapsulates a counter.
|
||||||
|
* A Wait Group is considered signaled when the counter is 0 and non-signaled
|
||||||
|
* when the counter is non-0. (Wait Group functionality is similar to Golang's
|
||||||
|
* sync.WaitGroup.)
|
||||||
|
*
|
||||||
|
* Wait Groups must always be allocated in non-paged storage.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
KEVENT Event;
|
||||||
|
LONG Count;
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
} FSP_WGROUP;
|
||||||
|
VOID FspWgroupInitialize(FSP_WGROUP *Wgroup);
|
||||||
|
VOID FspWgroupIncrement(FSP_WGROUP *Wgroup);
|
||||||
|
VOID FspWgroupDecrement(FSP_WGROUP *Wgroup);
|
||||||
|
VOID FspWgroupSignalPermanently(FSP_WGROUP *Wgroup);
|
||||||
|
NTSTATUS FspWgroupWait(FSP_WGROUP *Wgroup,
|
||||||
|
KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER PTimeout);
|
||||||
|
|
||||||
/* silos */
|
/* silos */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -897,6 +953,7 @@ BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN BestEffort, NTSTATUS *PR
|
|||||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout,
|
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout,
|
||||||
PIRP CancellableIrp);
|
PIRP CancellableIrp);
|
||||||
ULONG FspIoqPendingIrpCount(FSP_IOQ *Ioq);
|
ULONG FspIoqPendingIrpCount(FSP_IOQ *Ioq);
|
||||||
|
BOOLEAN FspIoqPendingAboveWatermark(FSP_IOQ *Ioq, ULONG Watermark);
|
||||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||||
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
||||||
ULONG FspIoqProcessIrpCount(FSP_IOQ *Ioq);
|
ULONG FspIoqProcessIrpCount(FSP_IOQ *Ioq);
|
||||||
@ -1124,6 +1181,8 @@ typedef struct
|
|||||||
KSPIN_LOCK InfoSpinLock;
|
KSPIN_LOCK InfoSpinLock;
|
||||||
UINT64 InfoExpirationTime;
|
UINT64 InfoExpirationTime;
|
||||||
FSP_FSCTL_VOLUME_INFO VolumeInfo;
|
FSP_FSCTL_VOLUME_INFO VolumeInfo;
|
||||||
|
LONG VolumeNotifyLock;
|
||||||
|
FSP_WGROUP VolumeNotifyWgroup;
|
||||||
PNOTIFY_SYNC NotifySync;
|
PNOTIFY_SYNC NotifySync;
|
||||||
LIST_ENTRY NotifyList;
|
LIST_ENTRY NotifyList;
|
||||||
FSP_STATISTICS *Statistics;
|
FSP_STATISTICS *Statistics;
|
||||||
@ -1182,7 +1241,9 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
|||||||
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
@ -1328,6 +1389,8 @@ NTSTATUS FspVolumeTransactFsext(
|
|||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeStop(
|
NTSTATUS FspVolumeStop(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeNotify(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeWork(
|
NTSTATUS FspVolumeWork(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
|
||||||
@ -1359,8 +1422,10 @@ typedef struct
|
|||||||
FAST_MUTEX HeaderFastMutex;
|
FAST_MUTEX HeaderFastMutex;
|
||||||
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
||||||
KSPIN_LOCK NpInfoSpinLock; /* allows to invalidate non-page Info w/o resources acquired */
|
KSPIN_LOCK NpInfoSpinLock; /* allows to invalidate non-page Info w/o resources acquired */
|
||||||
|
UINT64 Security;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
UINT64 StreamInfo;
|
UINT64 StreamInfo;
|
||||||
|
UINT64 Ea;
|
||||||
} FSP_FILE_NODE_NONPAGED;
|
} FSP_FILE_NODE_NONPAGED;
|
||||||
typedef struct FSP_FILE_NODE
|
typedef struct FSP_FILE_NODE
|
||||||
{
|
{
|
||||||
@ -1391,11 +1456,9 @@ typedef struct FSP_FILE_NODE
|
|||||||
UINT64 ChangeTime;
|
UINT64 ChangeTime;
|
||||||
UINT32 EaSize;
|
UINT32 EaSize;
|
||||||
ULONG FileInfoChangeNumber;
|
ULONG FileInfoChangeNumber;
|
||||||
UINT64 Security;
|
|
||||||
ULONG SecurityChangeNumber;
|
ULONG SecurityChangeNumber;
|
||||||
ULONG DirInfoChangeNumber;
|
ULONG DirInfoChangeNumber;
|
||||||
ULONG StreamInfoChangeNumber;
|
ULONG StreamInfoChangeNumber;
|
||||||
UINT64 Ea;
|
|
||||||
ULONG EaChangeNumber;
|
ULONG EaChangeNumber;
|
||||||
ULONG EaChangeCount;
|
ULONG EaChangeCount;
|
||||||
BOOLEAN TruncateOnClose;
|
BOOLEAN TruncateOnClose;
|
||||||
@ -1540,6 +1603,7 @@ BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, P
|
|||||||
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);
|
||||||
|
VOID FspFileNodeInvalidateSecurity(FSP_FILE_NODE *FileNode);
|
||||||
static inline
|
static inline
|
||||||
ULONG FspFileNodeSecurityChangeNumber(FSP_FILE_NODE *FileNode)
|
ULONG FspFileNodeSecurityChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
{
|
{
|
||||||
@ -1573,6 +1637,7 @@ BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG
|
|||||||
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
||||||
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG EaChangeNumber);
|
ULONG EaChangeNumber);
|
||||||
|
VOID FspFileNodeInvalidateEa(FSP_FILE_NODE *FileNode);
|
||||||
static inline
|
static inline
|
||||||
ULONG FspFileNodeEaChangeNumber(FSP_FILE_NODE *FileNode)
|
ULONG FspFileNodeEaChangeNumber(FSP_FILE_NODE *FileNode)
|
||||||
{
|
{
|
||||||
@ -1582,6 +1647,9 @@ ULONG FspFileNodeEaChangeNumber(FSP_FILE_NODE *FileNode)
|
|||||||
}
|
}
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||||
BOOLEAN InvalidateCaches);
|
BOOLEAN InvalidateCaches);
|
||||||
|
VOID FspFileNodeInvalidateCachesAndNotifyChangeByName(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PUNICODE_STRING FileName, ULONG Filter, ULONG Action,
|
||||||
|
BOOLEAN InvalidateParentCaches);
|
||||||
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);
|
||||||
|
224
src/sys/file.c
224
src/sys/file.c
@ -76,6 +76,7 @@ BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, P
|
|||||||
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);
|
||||||
|
VOID FspFileNodeInvalidateSecurity(FSP_FILE_NODE *FileNode);
|
||||||
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,
|
||||||
@ -93,8 +94,12 @@ BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG
|
|||||||
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
|
||||||
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG EaChangeNumber);
|
ULONG EaChangeNumber);
|
||||||
|
VOID FspFileNodeInvalidateEa(FSP_FILE_NODE *FileNode);
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||||
BOOLEAN InvalidateCaches);
|
BOOLEAN InvalidateCaches);
|
||||||
|
VOID FspFileNodeInvalidateCachesAndNotifyChangeByName(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PUNICODE_STRING FileName, ULONG Filter, ULONG Action,
|
||||||
|
BOOLEAN InvalidateParentCaches);
|
||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
||||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||||
@ -149,9 +154,10 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
|||||||
#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfoAndSecurityOnOpen)
|
#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfoAndSecurityOnOpen)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfo)
|
#pragma alloc_text(PAGE, FspFileNodeTrySetFileInfo)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeInvalidateFileInfo)
|
#pragma alloc_text(PAGE, FspFileNodeInvalidateFileInfo)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeReferenceSecurity)
|
// !#pragma alloc_text(PAGE, FspFileNodeReferenceSecurity)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeSetSecurity)
|
// !#pragma alloc_text(PAGE, FspFileNodeSetSecurity)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeTrySetSecurity)
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetSecurity)
|
||||||
|
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateSecurity)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeReferenceDirInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeReferenceDirInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeSetDirInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetDirInfo)
|
||||||
@ -162,10 +168,12 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
|||||||
// !#pragma alloc_text(PAGE, FspFileNodeSetStreamInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeSetStreamInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeTrySetStreamInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetStreamInfo)
|
||||||
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeReferenceEa)
|
// !#pragma alloc_text(PAGE, FspFileNodeReferenceEa)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeSetEa)
|
// !#pragma alloc_text(PAGE, FspFileNodeSetEa)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeTrySetEa)
|
// !#pragma alloc_text(PAGE, FspFileNodeTrySetEa)
|
||||||
|
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateEa)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
||||||
|
#pragma alloc_text(PAGE, FspFileNodeInvalidateCachesAndNotifyChangeByName)
|
||||||
#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)
|
||||||
@ -368,10 +376,10 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
|
|||||||
|
|
||||||
FsRtlTeardownPerStreamContexts(&FileNode->Header);
|
FsRtlTeardownPerStreamContexts(&FileNode->Header);
|
||||||
|
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, FileNode->Ea);
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, FileNode->NonPaged->Ea);
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, FileNode->NonPaged->StreamInfo);
|
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->NonPaged->Security);
|
||||||
|
|
||||||
FspDeviceDereference(FileNode->FsvolDeviceObject);
|
FspDeviceDereference(FileNode->FsvolDeviceObject);
|
||||||
|
|
||||||
@ -1905,38 +1913,54 @@ VOID FspFileNodeInvalidateFileInfo(FSP_FILE_NODE *FileNode)
|
|||||||
|
|
||||||
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (0 != FileNode->MainFileNode)
|
if (0 != FileNode->MainFileNode)
|
||||||
FileNode = FileNode->MainFileNode;
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
UINT64 Security;
|
||||||
|
|
||||||
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
|
Security = NonPaged->Security;
|
||||||
|
|
||||||
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->SecurityCache,
|
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->SecurityCache,
|
||||||
FileNode->Security, PBuffer, PSize);
|
Security, PBuffer, PSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (0 != FileNode->MainFileNode)
|
if (0 != FileNode->MainFileNode)
|
||||||
FileNode = FileNode->MainFileNode;
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
KIRQL Irql;
|
||||||
|
UINT64 Security;
|
||||||
|
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security);
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
FileNode->Security = 0 != Buffer ?
|
Security = NonPaged->Security;
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, Security);
|
||||||
|
Security = 0 != Buffer ?
|
||||||
FspMetaCacheAddItem(FsvolDeviceExtension->SecurityCache, Buffer, Size) : 0;
|
FspMetaCacheAddItem(FsvolDeviceExtension->SecurityCache, Buffer, Size) : 0;
|
||||||
FileNode->SecurityChangeNumber++;
|
FileNode->SecurityChangeNumber++;
|
||||||
|
|
||||||
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeInvalidateSecurity */
|
||||||
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
|
NonPaged->Security = Security;
|
||||||
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG SecurityChangeNumber)
|
ULONG SecurityChangeNumber)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (FspFileNodeSecurityChangeNumber(FileNode) != SecurityChangeNumber)
|
if (FspFileNodeSecurityChangeNumber(FileNode) != SecurityChangeNumber)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -1945,6 +1969,27 @@ BOOLEAN FspFileNodeTrySetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID FspFileNodeInvalidateSecurity(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 Security;
|
||||||
|
|
||||||
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeSetSecurity */
|
||||||
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
|
Security = NonPaged->Security;
|
||||||
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, Security);
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
||||||
{
|
{
|
||||||
// !PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
@ -2130,38 +2175,54 @@ VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode)
|
|||||||
|
|
||||||
BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
BOOLEAN FspFileNodeReferenceEa(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (0 != FileNode->MainFileNode)
|
if (0 != FileNode->MainFileNode)
|
||||||
FileNode = FileNode->MainFileNode;
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
UINT64 Ea;
|
||||||
|
|
||||||
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
|
Ea = NonPaged->Ea;
|
||||||
|
|
||||||
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->EaCache,
|
return FspMetaCacheReferenceItemBuffer(FsvolDeviceExtension->EaCache,
|
||||||
FileNode->Ea, PBuffer, PSize);
|
Ea, PBuffer, PSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
VOID FspFileNodeSetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (0 != FileNode->MainFileNode)
|
if (0 != FileNode->MainFileNode)
|
||||||
FileNode = FileNode->MainFileNode;
|
FileNode = FileNode->MainFileNode;
|
||||||
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
|
||||||
|
FSP_FILE_NODE_NONPAGED *NonPaged = FileNode->NonPaged;
|
||||||
|
KIRQL Irql;
|
||||||
|
UINT64 Ea;
|
||||||
|
|
||||||
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, FileNode->Ea);
|
/* no need to acquire the NpInfoSpinLock as the FileNode is acquired */
|
||||||
FileNode->Ea = 0 != Buffer ?
|
Ea = NonPaged->Ea;
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, Ea);
|
||||||
|
Ea = 0 != Buffer ?
|
||||||
FspMetaCacheAddItem(FsvolDeviceExtension->EaCache, Buffer, Size) : 0;
|
FspMetaCacheAddItem(FsvolDeviceExtension->EaCache, Buffer, Size) : 0;
|
||||||
FileNode->EaChangeNumber++;
|
FileNode->EaChangeNumber++;
|
||||||
|
|
||||||
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeInvalidateEa */
|
||||||
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
|
NonPaged->Ea = Ea;
|
||||||
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
||||||
ULONG EaChangeNumber)
|
ULONG EaChangeNumber)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
if (FspFileNodeEaChangeNumber(FileNode) != EaChangeNumber)
|
if (FspFileNodeEaChangeNumber(FileNode) != EaChangeNumber)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -2170,6 +2231,27 @@ BOOLEAN FspFileNodeTrySetEa(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID FspFileNodeInvalidateEa(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 Ea;
|
||||||
|
|
||||||
|
/* acquire the NpInfoSpinLock to protect against concurrent FspFileNodeSetEa */
|
||||||
|
KeAcquireSpinLock(&NonPaged->NpInfoSpinLock, &Irql);
|
||||||
|
Ea = NonPaged->Ea;
|
||||||
|
KeReleaseSpinLock(&NonPaged->NpInfoSpinLock, Irql);
|
||||||
|
|
||||||
|
FspMetaCacheInvalidateItem(FsvolDeviceExtension->EaCache, Ea);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||||
BOOLEAN InvalidateCaches)
|
BOOLEAN InvalidateCaches)
|
||||||
{
|
{
|
||||||
@ -2232,6 +2314,108 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID FspFileNodeInvalidateCachesAndNotifyChangeByName(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PUNICODE_STRING FileName, ULONG Filter, ULONG Action,
|
||||||
|
BOOLEAN InvalidateParentCaches)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FILE_NODE *FileNode;
|
||||||
|
|
||||||
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
FileNode = FspFsvolDeviceLookupContextByName(FsvolDeviceObject, FileName);
|
||||||
|
if (0 != FileNode)
|
||||||
|
FspFileNodeReference(FileNode);
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
if (0 != FileNode)
|
||||||
|
{
|
||||||
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
|
if (0 != FileNode->NonPaged->SectionObjectPointers.DataSectionObject)
|
||||||
|
{
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
FspCcFlushCache(&FileNode->NonPaged->SectionObjectPointers, 0, 0, &IoStatus);
|
||||||
|
if (NT_SUCCESS(IoStatus.Status))
|
||||||
|
CcPurgeCacheSection(&FileNode->NonPaged->SectionObjectPointers, 0, 0, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeInvalidateFileInfo(FileNode);
|
||||||
|
FspFileNodeInvalidateSecurity(FileNode);
|
||||||
|
FspFileNodeInvalidateDirInfo(FileNode);
|
||||||
|
FspFileNodeInvalidateStreamInfo(FileNode);
|
||||||
|
FspFileNodeInvalidateEa(FileNode);
|
||||||
|
|
||||||
|
FspFileNodeNotifyChange(FileNode, Filter, Action, InvalidateParentCaches);
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
|
||||||
|
FspFileNodeDereference(FileNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
UNICODE_STRING Parent, Suffix;
|
||||||
|
BOOLEAN IsStream;
|
||||||
|
|
||||||
|
IsStream = FALSE;
|
||||||
|
for (PWSTR P = FileName->Buffer, EndP = P + FileName->Length / sizeof(WCHAR); EndP > P; P++)
|
||||||
|
if (L':' == *P)
|
||||||
|
{
|
||||||
|
IsStream = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsStream)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (FlagOn(Filter, FILE_NOTIFY_CHANGE_LAST_WRITE))
|
||||||
|
SetFlag(Filter, FILE_NOTIFY_CHANGE_STREAM_WRITE);
|
||||||
|
ClearFlag(Filter, ~(FILE_NOTIFY_CHANGE_STREAM_NAME | FILE_NOTIFY_CHANGE_STREAM_SIZE |
|
||||||
|
FILE_NOTIFY_CHANGE_STREAM_WRITE));
|
||||||
|
|
||||||
|
switch (Action)
|
||||||
|
{
|
||||||
|
case FILE_ACTION_ADDED:
|
||||||
|
Action = FILE_ACTION_ADDED_STREAM;
|
||||||
|
break;
|
||||||
|
case FILE_ACTION_REMOVED:
|
||||||
|
Action = FILE_ACTION_REMOVED_STREAM;
|
||||||
|
break;
|
||||||
|
case FILE_ACTION_MODIFIED:
|
||||||
|
Action = FILE_ACTION_MODIFIED_STREAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != Filter)
|
||||||
|
{
|
||||||
|
FspFileNameSuffix(FileName, &Parent, &Suffix);
|
||||||
|
|
||||||
|
if (InvalidateParentCaches)
|
||||||
|
{
|
||||||
|
FspFsvolDeviceInvalidateVolumeInfo(FsvolDeviceObject);
|
||||||
|
if (!IsStream)
|
||||||
|
{
|
||||||
|
if (sizeof(WCHAR) == FileName->Length && L'\\' == FileName->Buffer[0])
|
||||||
|
; /* root does not have a parent */
|
||||||
|
else
|
||||||
|
FspFileNodeInvalidateDirInfoByName(FsvolDeviceObject, &Parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FspNotifyReportChange(
|
||||||
|
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList,
|
||||||
|
FileName,
|
||||||
|
(USHORT)((PUINT8)Suffix.Buffer - (PUINT8)FileName->Buffer),
|
||||||
|
0, Filter, Action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp)
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -98,6 +98,10 @@ static NTSTATUS FspFsctlFileSystemControl(
|
|||||||
if (0 != IrpSp->FileObject->FsContext2)
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
Result = FspVolumeStop(FsctlDeviceObject, Irp, IrpSp);
|
Result = FspVolumeStop(FsctlDeviceObject, Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
|
case FSP_FSCTL_NOTIFY:
|
||||||
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
|
Result = FspVolumeNotify(FsctlDeviceObject, Irp, IrpSp);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (CTL_CODE(0, 0xC00, 0, 0) ==
|
if (CTL_CODE(0, 0xC00, 0, 0) ==
|
||||||
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))
|
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))
|
||||||
|
@ -643,6 +643,16 @@ ULONG FspIoqPendingIrpCount(FSP_IOQ *Ioq)
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspIoqPendingAboveWatermark(FSP_IOQ *Ioq, ULONG Watermark)
|
||||||
|
{
|
||||||
|
BOOLEAN Result;
|
||||||
|
KIRQL Irql;
|
||||||
|
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
|
||||||
|
Result = Watermark < 100 * Ioq->PendingIrpCount / Ioq->PendingIrpCapacity;
|
||||||
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
|
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
146
src/sys/trace.c
Normal file
146
src/sys/trace.c
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/**
|
||||||
|
* @file sys/trace.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2020 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
#if FSP_TRACE_ENABLED
|
||||||
|
|
||||||
|
#undef STATUS_INSUFFICIENT_RESOURCES
|
||||||
|
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
HANDLE Handle;
|
||||||
|
PKEVENT Event;
|
||||||
|
} FspLowMemoryCondition, FspLowNonPagedPoolCondition, FspLowPagedPoolCondition;
|
||||||
|
|
||||||
|
VOID FspTrace(const char *file, int line, const char *func)
|
||||||
|
{
|
||||||
|
for (const char *p = file; '\0' != *p; p++)
|
||||||
|
if ('\\' == *p)
|
||||||
|
file = p + 1;
|
||||||
|
|
||||||
|
ASSERT(DISPATCH_LEVEL >= KeGetCurrentIrql());
|
||||||
|
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_TRACE_LEVEL,
|
||||||
|
DRIVER_NAME ": %s[%s:%d]\n", func, file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Status)
|
||||||
|
{
|
||||||
|
for (const char *p = file; '\0' != *p; p++)
|
||||||
|
if ('\\' == *p)
|
||||||
|
file = p + 1;
|
||||||
|
|
||||||
|
ASSERT(DISPATCH_LEVEL >= KeGetCurrentIrql());
|
||||||
|
BOOLEAN LowMemoryCondition, LowNonPagedPoolCondition, LowPagedPoolCondition;
|
||||||
|
switch (Status)
|
||||||
|
{
|
||||||
|
case STATUS_INSUFFICIENT_RESOURCES:
|
||||||
|
LowMemoryCondition = 0 != FspLowMemoryCondition.Event &&
|
||||||
|
!!KeReadStateEvent(FspLowMemoryCondition.Event);
|
||||||
|
LowNonPagedPoolCondition = 0 != FspLowNonPagedPoolCondition.Event &&
|
||||||
|
!!KeReadStateEvent(FspLowNonPagedPoolCondition.Event);
|
||||||
|
LowPagedPoolCondition = 0 != FspLowPagedPoolCondition.Event &&
|
||||||
|
!!KeReadStateEvent(FspLowPagedPoolCondition.Event);
|
||||||
|
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_TRACE_LEVEL,
|
||||||
|
DRIVER_NAME ": %s[%s:%d]: STATUS_INSUFFICIENT_RESOURCES (Memory=%c%c%c)\n",
|
||||||
|
func, file, line,
|
||||||
|
LowMemoryCondition ? 'M' : '-',
|
||||||
|
LowNonPagedPoolCondition ? 'N' : '-',
|
||||||
|
LowPagedPoolCondition ? 'P' : '-');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_TRACE_LEVEL,
|
||||||
|
DRIVER_NAME ": %s[%s:%d]: Status=%lx\n",
|
||||||
|
func, file, line,
|
||||||
|
Status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PKEVENT FspOpenEvent(PWSTR Name, PHANDLE PHandle)
|
||||||
|
{
|
||||||
|
UNICODE_STRING ObjectName;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
HANDLE Handle;
|
||||||
|
PKEVENT Event;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PHandle = 0;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ObjectName, Name);
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ObjectName, OBJ_KERNEL_HANDLE, 0, 0);
|
||||||
|
Result = ZwOpenEvent(&Handle,
|
||||||
|
EVENT_ALL_ACCESS, &ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Result = ObReferenceObjectByHandle(Handle,
|
||||||
|
0, *ExEventObjectType, KernelMode, &Event, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
ZwClose(Handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PHandle = Handle;
|
||||||
|
|
||||||
|
return Event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspCloseEvent(PKEVENT Event, HANDLE Handle)
|
||||||
|
{
|
||||||
|
if (0 != Event)
|
||||||
|
ObDereferenceObject(Event);
|
||||||
|
|
||||||
|
if (0 != Handle)
|
||||||
|
ZwClose(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspTraceInitialize(VOID)
|
||||||
|
{
|
||||||
|
#define OPEN_EVENT(NAME) \
|
||||||
|
(Fsp ## NAME.Event = FspOpenEvent(L"\\KernelObjects\\" #NAME, &Fsp ## NAME.Handle))
|
||||||
|
|
||||||
|
OPEN_EVENT(LowMemoryCondition);
|
||||||
|
OPEN_EVENT(LowNonPagedPoolCondition);
|
||||||
|
OPEN_EVENT(LowPagedPoolCondition);
|
||||||
|
|
||||||
|
#undef OPEN_EVENT
|
||||||
|
|
||||||
|
FSP_TRACE();
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspTraceFinalize(VOID)
|
||||||
|
{
|
||||||
|
FSP_TRACE();
|
||||||
|
|
||||||
|
#define CLOSE_EVENT(NAME) \
|
||||||
|
(FspCloseEvent(Fsp ## NAME.Event, Fsp ## NAME.Handle), Fsp ## NAME.Event = 0, Fsp ## NAME.Handle = 0)
|
||||||
|
|
||||||
|
CLOSE_EVENT(LowMemoryCondition);
|
||||||
|
CLOSE_EVENT(LowNonPagedPoolCondition);
|
||||||
|
CLOSE_EVENT(LowPagedPoolCondition);
|
||||||
|
|
||||||
|
#undef CLOSE_EVENT
|
||||||
|
}
|
||||||
|
#endif
|
@ -131,6 +131,12 @@ NTSTATUS FspIrpHook(PIRP Irp, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID Ow
|
|||||||
VOID FspIrpHookReset(PIRP Irp);
|
VOID FspIrpHookReset(PIRP Irp);
|
||||||
PVOID FspIrpHookContext(PVOID Context);
|
PVOID FspIrpHookContext(PVOID Context);
|
||||||
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||||
|
VOID FspWgroupInitialize(FSP_WGROUP *Wgroup);
|
||||||
|
VOID FspWgroupIncrement(FSP_WGROUP *Wgroup);
|
||||||
|
VOID FspWgroupDecrement(FSP_WGROUP *Wgroup);
|
||||||
|
VOID FspWgroupSignalPermanently(FSP_WGROUP *Wgroup);
|
||||||
|
NTSTATUS FspWgroupWait(FSP_WGROUP *Wgroup,
|
||||||
|
KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER PTimeout);
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspIsNtDdiVersionAvailable)
|
#pragma alloc_text(PAGE, FspIsNtDdiVersionAvailable)
|
||||||
@ -176,6 +182,11 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
|||||||
#pragma alloc_text(PAGE, FspIrpHookReset)
|
#pragma alloc_text(PAGE, FspIrpHookReset)
|
||||||
// !#pragma alloc_text(PAGE, FspIrpHookContext)
|
// !#pragma alloc_text(PAGE, FspIrpHookContext)
|
||||||
// !#pragma alloc_text(PAGE, FspIrpHookNext)
|
// !#pragma alloc_text(PAGE, FspIrpHookNext)
|
||||||
|
// !#pragma alloc_text(PAGE, FspWgroupInitialize)
|
||||||
|
// !#pragma alloc_text(PAGE, FspWgroupIncrement)
|
||||||
|
// !#pragma alloc_text(PAGE, FspWgroupDecrement)
|
||||||
|
// !#pragma alloc_text(PAGE, FspWgroupSignalPermanently)
|
||||||
|
// !#pragma alloc_text(PAGE, FspWgroupWait)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const LONG Delays[] =
|
static const LONG Delays[] =
|
||||||
@ -597,6 +608,13 @@ NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation)
|
|||||||
if (0 == Length || 0 != Irp->AssociatedIrp.SystemBuffer)
|
if (0 == Length || 0 != Irp->AssociatedIrp.SystemBuffer)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (KernelMode == Irp->RequestorMode &&
|
||||||
|
(PUINT8)MM_SYSTEM_RANGE_START <= (PUINT8)Irp->UserBuffer)
|
||||||
|
{
|
||||||
|
Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
PVOID SystemBuffer = FspAllocNonPagedExternal(Length);
|
PVOID SystemBuffer = FspAllocNonPagedExternal(Length);
|
||||||
if (0 == SystemBuffer)
|
if (0 == SystemBuffer)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
@ -1488,3 +1506,56 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
|
|||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID FspWgroupInitialize(FSP_WGROUP *Wgroup)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
KeInitializeEvent(&Wgroup->Event, NotificationEvent, TRUE);
|
||||||
|
Wgroup->Count = 0;
|
||||||
|
KeInitializeSpinLock(&Wgroup->SpinLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspWgroupIncrement(FSP_WGROUP *Wgroup)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Wgroup->SpinLock, &Irql);
|
||||||
|
if (0 <= Wgroup->Count && 1 == ++Wgroup->Count)
|
||||||
|
KeClearEvent(&Wgroup->Event);
|
||||||
|
KeReleaseSpinLock(&Wgroup->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspWgroupDecrement(FSP_WGROUP *Wgroup)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Wgroup->SpinLock, &Irql);
|
||||||
|
if (0 < Wgroup->Count && 0 == --Wgroup->Count)
|
||||||
|
KeSetEvent(&Wgroup->Event, 1, FALSE);
|
||||||
|
KeReleaseSpinLock(&Wgroup->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspWgroupSignalPermanently(FSP_WGROUP *Wgroup)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Wgroup->SpinLock, &Irql);
|
||||||
|
Wgroup->Count = -1;
|
||||||
|
KeSetEvent(&Wgroup->Event, 1, FALSE);
|
||||||
|
KeReleaseSpinLock(&Wgroup->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspWgroupWait(FSP_WGROUP *Wgroup,
|
||||||
|
KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER PTimeout)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
return KeWaitForSingleObject(&Wgroup->Event, Executive, WaitMode, Alertable, PTimeout);
|
||||||
|
}
|
||||||
|
229
src/sys/volume.c
229
src/sys/volume.c
@ -50,6 +50,11 @@ NTSTATUS FspVolumeTransactFsext(
|
|||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeStop(
|
NTSTATUS FspVolumeStop(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeNotify(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
static NTSTATUS FspVolumeNotifyLock(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
|
static WORKER_THREAD_ROUTINE FspVolumeNotifyWork;
|
||||||
NTSTATUS FspVolumeWork(
|
NTSTATUS FspVolumeWork(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
|
||||||
@ -68,6 +73,9 @@ NTSTATUS FspVolumeWork(
|
|||||||
#pragma alloc_text(PAGE, FspVolumeTransact)
|
#pragma alloc_text(PAGE, FspVolumeTransact)
|
||||||
#pragma alloc_text(PAGE, FspVolumeTransactFsext)
|
#pragma alloc_text(PAGE, FspVolumeTransactFsext)
|
||||||
#pragma alloc_text(PAGE, FspVolumeStop)
|
#pragma alloc_text(PAGE, FspVolumeStop)
|
||||||
|
#pragma alloc_text(PAGE, FspVolumeNotify)
|
||||||
|
#pragma alloc_text(PAGE, FspVolumeNotifyLock)
|
||||||
|
#pragma alloc_text(PAGE, FspVolumeNotifyWork)
|
||||||
#pragma alloc_text(PAGE, FspVolumeWork)
|
#pragma alloc_text(PAGE, FspVolumeWork)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -468,6 +476,11 @@ static VOID FspVolumeDeleteNoLock(
|
|||||||
FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
|
FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* release the volume notify lock if held (so that any pending rename will abort) */
|
||||||
|
FspWgroupSignalPermanently(&FsvolDeviceExtension->VolumeNotifyWgroup);
|
||||||
|
if (1 == InterlockedCompareExchange(&FsvolDeviceExtension->VolumeNotifyLock, 0, 1))
|
||||||
|
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, FsvolDeviceObject);
|
||||||
|
|
||||||
/* release the volume device object */
|
/* release the volume device object */
|
||||||
FspDeviceDereference(FsvolDeviceObject);
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
}
|
}
|
||||||
@ -1054,6 +1067,222 @@ NTSTATUS FspVolumeStop(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WORK_QUEUE_ITEM WorkItem;
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject;
|
||||||
|
ULONG InputBufferLength;
|
||||||
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 InputBuffer[];
|
||||||
|
} FSP_VOLUME_NOTIFY_WORK_ITEM;
|
||||||
|
|
||||||
|
NTSTATUS FspVolumeNotify(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FspVolumeNotify processing requires multiple locks that cannot be acquired
|
||||||
|
* synchronously or deadlocks are possible. (The reason is that FspVolumeNotify
|
||||||
|
* may be called by the user mode file system while servicing a request that
|
||||||
|
* has already acquired one of the required locks.)
|
||||||
|
*
|
||||||
|
* For this reason FspVolumeNotify does its processing asynchronously; it ships
|
||||||
|
* its payload as a work item to a system worker thread, which will perform the
|
||||||
|
* actual processing. See FspVolumeNotifyWork.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||||
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||||
|
ASSERT(FSP_FSCTL_NOTIFY == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||||
|
ASSERT(METHOD_NEITHER == (IrpSp->Parameters.FileSystemControl.FsControlCode & 3));
|
||||||
|
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PVOID InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
|
||||||
|
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||||
|
FSP_VOLUME_NOTIFY_WORK_ITEM *NotifyWorkItem = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == InputBufferLength)
|
||||||
|
return FspVolumeNotifyLock(FsvolDeviceObject);
|
||||||
|
|
||||||
|
if (!FspDeviceReference(FsvolDeviceObject))
|
||||||
|
return STATUS_CANCELLED;
|
||||||
|
|
||||||
|
NotifyWorkItem = FspAllocNonPaged(
|
||||||
|
FIELD_OFFSET(FSP_VOLUME_NOTIFY_WORK_ITEM, InputBuffer) + InputBufferLength);
|
||||||
|
if (0 == NotifyWorkItem)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProbeForRead(InputBuffer, InputBufferLength, 1);
|
||||||
|
RtlCopyMemory(NotifyWorkItem->InputBuffer, InputBuffer, InputBufferLength);
|
||||||
|
NotifyWorkItem->InputBufferLength = InputBufferLength;
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Result = GetExceptionCode();
|
||||||
|
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExInitializeWorkItem(&NotifyWorkItem->WorkItem, FspVolumeNotifyWork, NotifyWorkItem);
|
||||||
|
NotifyWorkItem->FsvolDeviceObject = FsvolDeviceObject;
|
||||||
|
|
||||||
|
FspWgroupIncrement(&FsvolDeviceExtension->VolumeNotifyWgroup);
|
||||||
|
ExQueueWorkItem(&NotifyWorkItem->WorkItem, DelayedWorkQueue);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (0 != NotifyWorkItem)
|
||||||
|
FspFree(NotifyWorkItem);
|
||||||
|
|
||||||
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspVolumeNotifyLock(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (!FspDeviceReference(FsvolDeviceObject))
|
||||||
|
return STATUS_CANCELLED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Acquire the rename lock shared to disallow concurrent RENAME's.
|
||||||
|
*
|
||||||
|
* This guards against the race where a file that we want to invalidate
|
||||||
|
* is being concurrently renamed to a different name. Thus we may think
|
||||||
|
* that the file is not open and not invalidate its caches, whereas the
|
||||||
|
* file has simply changed name.
|
||||||
|
*/
|
||||||
|
Result = STATUS_CANT_WAIT;
|
||||||
|
if (FspFsvolDeviceFileRenameTryAcquireShared(FsvolDeviceObject))
|
||||||
|
{
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
|
||||||
|
if (0 == InterlockedCompareExchange(&FsvolDeviceExtension->VolumeNotifyLock, 1, 0))
|
||||||
|
{
|
||||||
|
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, FsvolDeviceObject);
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FsRtlEnterFileSystem();
|
||||||
|
IoSetTopLevelIrp(0);
|
||||||
|
|
||||||
|
FSP_VOLUME_NOTIFY_WORK_ITEM *NotifyWorkItem = NotifyWorkItem0;
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = NotifyWorkItem->FsvolDeviceObject;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo = (PVOID)NotifyWorkItem->InputBuffer;
|
||||||
|
PUINT8 NotifyInfoEnd = (PUINT8)NotifyInfo + NotifyWorkItem->InputBufferLength;
|
||||||
|
ULONG NotifyInfoSize;
|
||||||
|
UNICODE_STRING FileName = { 0 }, StreamPart = { 0 }, AbsFileName = { 0 }, FullFileName = { 0 };
|
||||||
|
ULONG StreamType = FspFileNameStreamTypeNone;
|
||||||
|
BOOLEAN Unlock = FALSE;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/* iterate over notify information and invalidate/notify each file */
|
||||||
|
for (; (PUINT8)NotifyInfo + sizeof(NotifyInfo->Size) <= NotifyInfoEnd;
|
||||||
|
NotifyInfo = (PVOID)((PUINT8)NotifyInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(NotifyInfoSize)))
|
||||||
|
{
|
||||||
|
NotifyInfoSize = NotifyInfo->Size;
|
||||||
|
|
||||||
|
if (sizeof(FSP_FSCTL_NOTIFY_INFO) > NotifyInfoSize)
|
||||||
|
{
|
||||||
|
Unlock = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileName.Length =
|
||||||
|
FileName.MaximumLength = (USHORT)(NotifyInfoSize - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FileName.Buffer = NotifyInfo->FileNameBuf;
|
||||||
|
if (sizeof(WCHAR) * 2/* not empty or root */ <= FileName.Length &&
|
||||||
|
L'\\' == FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1])
|
||||||
|
FileName.Length -= sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!FspFileNameIsValid(&FileName, FsvolDeviceExtension->VolumeParams.MaxComponentLength,
|
||||||
|
FsvolDeviceExtension->VolumeParams.NamedStreams ? &StreamPart : 0,
|
||||||
|
&StreamType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sizeof(WCHAR) <= FileName.Length && L'\\' == FileName.Buffer[0])
|
||||||
|
{
|
||||||
|
/* absolute file names are used as-is */
|
||||||
|
|
||||||
|
AbsFileName = FileName;
|
||||||
|
|
||||||
|
FspFileNodeInvalidateCachesAndNotifyChangeByName(FsvolDeviceObject,
|
||||||
|
&FileName, NotifyInfo->Filter, NotifyInfo->Action,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
else if (0 != AbsFileName.Length)
|
||||||
|
{
|
||||||
|
/* relative file names are considered relative to the last absolute file name */
|
||||||
|
|
||||||
|
if (0 == FullFileName.Buffer)
|
||||||
|
{
|
||||||
|
FullFileName.Buffer = FspAllocatePoolMustSucceed(
|
||||||
|
NonPagedPool, FSP_FSCTL_TRANSACT_PATH_SIZEMAX, FSP_ALLOC_INTERNAL_TAG);
|
||||||
|
FullFileName.MaximumLength = FSP_FSCTL_TRANSACT_PATH_SIZEMAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
FullFileName.Length = 0;
|
||||||
|
Result = RtlAppendUnicodeStringToString(&FullFileName, &AbsFileName);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (sizeof(WCHAR) * 2/* not empty or root */ <= AbsFileName.Length)
|
||||||
|
Result = RtlAppendUnicodeToString(&FullFileName, L"\\");
|
||||||
|
}
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
Result = RtlAppendUnicodeStringToString(&FullFileName, &FileName);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
FspFileNodeInvalidateCachesAndNotifyChangeByName(FsvolDeviceObject,
|
||||||
|
&FullFileName, NotifyInfo->Filter, NotifyInfo->Action,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FullFileName.Buffer)
|
||||||
|
FspFree(FullFileName.Buffer);
|
||||||
|
|
||||||
|
FspFree(NotifyWorkItem);
|
||||||
|
|
||||||
|
FspWgroupDecrement(&FsvolDeviceExtension->VolumeNotifyWgroup);
|
||||||
|
if (Unlock)
|
||||||
|
{
|
||||||
|
FspWgroupWait(&FsvolDeviceExtension->VolumeNotifyWgroup, KernelMode, FALSE, 0);
|
||||||
|
if (1 == InterlockedCompareExchange(&FsvolDeviceExtension->VolumeNotifyLock, 0, 1))
|
||||||
|
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, FsvolDeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
|
||||||
|
FsRtlExitFileSystem();
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspVolumeWork(
|
NTSTATUS FspVolumeWork(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
|
@ -347,6 +347,7 @@ STATUS_BAD_VALIDATION_CLASS ERROR_BAD_VALIDATION_CLASS
|
|||||||
STATUS_BAD_TOKEN_TYPE ERROR_BAD_TOKEN_TYPE
|
STATUS_BAD_TOKEN_TYPE ERROR_BAD_TOKEN_TYPE
|
||||||
STATUS_BAD_MASTER_BOOT_RECORD ERROR_INVALID_PARAMETER
|
STATUS_BAD_MASTER_BOOT_RECORD ERROR_INVALID_PARAMETER
|
||||||
STATUS_NO_SECURITY_ON_OBJECT ERROR_NO_SECURITY_ON_OBJECT
|
STATUS_NO_SECURITY_ON_OBJECT ERROR_NO_SECURITY_ON_OBJECT
|
||||||
|
STATUS_CANT_WAIT ERROR_CANT_WAIT
|
||||||
STATUS_CANT_ACCESS_DOMAIN_INFO ERROR_CANT_ACCESS_DOMAIN_INFO
|
STATUS_CANT_ACCESS_DOMAIN_INFO ERROR_CANT_ACCESS_DOMAIN_INFO
|
||||||
STATUS_INVALID_SERVER_STATE ERROR_INVALID_SERVER_STATE
|
STATUS_INVALID_SERVER_STATE ERROR_INVALID_SERVER_STATE
|
||||||
STATUS_INVALID_DOMAIN_STATE ERROR_INVALID_DOMAIN_STATE
|
STATUS_INVALID_DOMAIN_STATE ERROR_INVALID_DOMAIN_STATE
|
||||||
|
@ -37,6 +37,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
||||||
winfsp-tests-x64-no-traverse ^
|
winfsp-tests-x64-no-traverse ^
|
||||||
winfsp-tests-x64-oplock ^
|
winfsp-tests-x64-oplock ^
|
||||||
|
winfsp-tests-x64-notify ^
|
||||||
winfsp-tests-x64-external ^
|
winfsp-tests-x64-external ^
|
||||||
winfsp-tests-x64-external-share ^
|
winfsp-tests-x64-external-share ^
|
||||||
fsx-memfs-x64-disk ^
|
fsx-memfs-x64-disk ^
|
||||||
@ -56,6 +57,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||||
winfsp-tests-x86-no-traverse ^
|
winfsp-tests-x86-no-traverse ^
|
||||||
winfsp-tests-x86-oplock ^
|
winfsp-tests-x86-oplock ^
|
||||||
|
winfsp-tests-x86-notify ^
|
||||||
winfsp-tests-x86-external ^
|
winfsp-tests-x86-external ^
|
||||||
winfsp-tests-x86-external-share ^
|
winfsp-tests-x86-external-share ^
|
||||||
fsx-memfs-x86-disk ^
|
fsx-memfs-x86-disk ^
|
||||||
@ -214,6 +216,11 @@ winfsp-tests-x64 --oplock=filter --resilient * +ea*
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-notify
|
||||||
|
winfsp-tests-x64 --notify --resilient * +ea*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x86
|
:winfsp-tests-x86
|
||||||
winfsp-tests-x86 +*
|
winfsp-tests-x86 +*
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
@ -254,6 +261,11 @@ winfsp-tests-x86 --oplock=filter --resilient * +ea*
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-notify
|
||||||
|
winfsp-tests-x86 --notify --resilient * +ea*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x64-external
|
:winfsp-tests-x64-external
|
||||||
M:
|
M:
|
||||||
fltmc instances -v M: | findstr aswSnx >nul
|
fltmc instances -v M: | findstr aswSnx >nul
|
||||||
|
9
tst/notifyfs-dotnet/.gitignore
vendored
Normal file
9
tst/notifyfs-dotnet/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
build
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.vcproj.*
|
||||||
|
*.vcxproj.user
|
||||||
|
*.csproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
394
tst/notifyfs-dotnet/Program.cs
Normal file
394
tst/notifyfs-dotnet/Program.cs
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
/**
|
||||||
|
* @file Program.cs
|
||||||
|
*
|
||||||
|
* @copyright 2015-2020 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.AccessControl;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using Fsp;
|
||||||
|
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
||||||
|
using FileInfo = Fsp.Interop.FileInfo;
|
||||||
|
using NotifyInfo = Fsp.Interop.NotifyInfo;
|
||||||
|
using NotifyAction = Fsp.Interop.NotifyAction;
|
||||||
|
using NotifyFilter = Fsp.Interop.NotifyFilter;
|
||||||
|
|
||||||
|
namespace notifyfs
|
||||||
|
{
|
||||||
|
class Notifyfs : FileSystemBase
|
||||||
|
{
|
||||||
|
public override Int32 Init(Object Host)
|
||||||
|
{
|
||||||
|
_Host = (FileSystemHost)Host;
|
||||||
|
_Host.SectorSize = ALLOCATION_UNIT;
|
||||||
|
_Host.SectorsPerAllocationUnit = 1;
|
||||||
|
_Host.FileInfoTimeout = 1000;
|
||||||
|
_Host.CaseSensitiveSearch = false;
|
||||||
|
_Host.CasePreservedNames = true;
|
||||||
|
_Host.UnicodeOnDisk = true;
|
||||||
|
_Host.PersistentAcls = false;
|
||||||
|
_Host.PostCleanupWhenModifiedOnly = true;
|
||||||
|
_Host.VolumeCreationTime = 0;
|
||||||
|
_Host.VolumeSerialNumber = 0;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 Mounted(Object Host)
|
||||||
|
{
|
||||||
|
_Timer = new Timer(this.Tick, null, 0, 1000);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override void Unmounted(Object Host)
|
||||||
|
{
|
||||||
|
WaitHandle Event = new ManualResetEvent(false);
|
||||||
|
_Timer.Dispose(Event);
|
||||||
|
Event.WaitOne();
|
||||||
|
}
|
||||||
|
public override Int32 GetVolumeInfo(
|
||||||
|
out VolumeInfo VolumeInfo)
|
||||||
|
{
|
||||||
|
VolumeInfo = default(VolumeInfo);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 GetSecurityByName(
|
||||||
|
String FileName,
|
||||||
|
out UInt32 FileAttributes/* or ReparsePointIndex */,
|
||||||
|
ref Byte[] SecurityDescriptor)
|
||||||
|
{
|
||||||
|
int Index = FileLookup(FileName);
|
||||||
|
if (-1 == Index)
|
||||||
|
{
|
||||||
|
FileAttributes = default(UInt32);
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAttributes = 0 == Index ? (UInt32)System.IO.FileAttributes.Directory : 0;
|
||||||
|
if (null != SecurityDescriptor)
|
||||||
|
SecurityDescriptor = DefaultSecurity;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 Open(
|
||||||
|
String FileName,
|
||||||
|
UInt32 CreateOptions,
|
||||||
|
UInt32 GrantedAccess,
|
||||||
|
out Object FileNode,
|
||||||
|
out Object FileDesc,
|
||||||
|
out FileInfo FileInfo,
|
||||||
|
out String NormalizedName)
|
||||||
|
{
|
||||||
|
FileNode = default(Object);
|
||||||
|
FileDesc = default(Object);
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
NormalizedName = default(String);
|
||||||
|
|
||||||
|
int Index = FileLookup(FileName);
|
||||||
|
if (-1 == Index)
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
FileNode = Index;
|
||||||
|
FillFileInfo(Index, out FileInfo);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 Read(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt32 Length,
|
||||||
|
out UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
int Index = (int)FileNode;
|
||||||
|
UInt64 EndOffset;
|
||||||
|
Byte[] Contents = FileContents(Index);
|
||||||
|
|
||||||
|
if (Offset >= (UInt64)Contents.Length)
|
||||||
|
{
|
||||||
|
BytesTransferred = 0;
|
||||||
|
return STATUS_END_OF_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndOffset = Offset + Length;
|
||||||
|
if (EndOffset > (UInt64)Contents.Length)
|
||||||
|
EndOffset = (UInt64)Contents.Length;
|
||||||
|
|
||||||
|
BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
|
Marshal.Copy(Contents, (int)Offset, Buffer, (int)BytesTransferred);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 GetFileInfo(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
int Index = (int)FileNode;
|
||||||
|
|
||||||
|
FillFileInfo(Index, out FileInfo);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Boolean ReadDirectoryEntry(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc,
|
||||||
|
String Pattern,
|
||||||
|
String Marker,
|
||||||
|
ref Object Context,
|
||||||
|
out String FileName,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
IEnumerator<String> Enumerator = (IEnumerator<String>)Context;
|
||||||
|
|
||||||
|
if (null == Enumerator)
|
||||||
|
{
|
||||||
|
List<String> ChildrenFileNames = new List<String>();
|
||||||
|
for (int Index = 1, Count = FileCount(); Count >= Index; Index++)
|
||||||
|
ChildrenFileNames.Add(String.Format("{0}", Index));
|
||||||
|
Context = Enumerator = ChildrenFileNames.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
FileName = Enumerator.Current;
|
||||||
|
FillFileInfo(int.Parse(FileName), out FileInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileName = default(String);
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int CountFromTicks(int Ticks)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The formula below produces the periodic sequence:
|
||||||
|
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
||||||
|
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
int div10 = (Ticks % 20) / 10;
|
||||||
|
int mod10 = Ticks % 10;
|
||||||
|
int mdv10 = 1 - div10;
|
||||||
|
int mmd10 = 10 - mod10;
|
||||||
|
return mdv10 * mod10 + div10 * mmd10;
|
||||||
|
}
|
||||||
|
private int FileCount()
|
||||||
|
{
|
||||||
|
int Ticks = Thread.VolatileRead(ref _Ticks);
|
||||||
|
return CountFromTicks(Ticks);
|
||||||
|
}
|
||||||
|
private int FileLookup(String FileName)
|
||||||
|
{
|
||||||
|
FileName = FileName.Substring(1);
|
||||||
|
if ("" == FileName)
|
||||||
|
return 0; /* root */
|
||||||
|
int Count = FileCount();
|
||||||
|
Boolean Valid = int.TryParse(FileName, out int Index);
|
||||||
|
if (!Valid || 0 >= Index || Index > Count)
|
||||||
|
return -1; /* not found */
|
||||||
|
return Index; /* regular file named 1, 2, ..., Count */
|
||||||
|
}
|
||||||
|
private static Byte[] FileContents(int Index)
|
||||||
|
{
|
||||||
|
if (0 == Index)
|
||||||
|
return EmptyByteArray;
|
||||||
|
return Encoding.UTF8.GetBytes(String.Format("{0}\n", Index));
|
||||||
|
}
|
||||||
|
private static void FillFileInfo(int Index, out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
FileInfo.FileAttributes = 0 == Index ? (UInt32)System.IO.FileAttributes.Directory : 0;
|
||||||
|
FileInfo.FileSize = (UInt64)FileContents(Index).Length;
|
||||||
|
FileInfo.AllocationSize = (FileInfo.FileSize + ALLOCATION_UNIT - 1)
|
||||||
|
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
|
||||||
|
FileInfo.CreationTime =
|
||||||
|
FileInfo.LastAccessTime =
|
||||||
|
FileInfo.LastWriteTime =
|
||||||
|
FileInfo.ChangeTime = (UInt64)DateTime.Now.ToFileTimeUtc();
|
||||||
|
}
|
||||||
|
private void Tick(Object Context)
|
||||||
|
{
|
||||||
|
int Ticks = Interlocked.Increment(ref _Ticks);
|
||||||
|
int OldCount = CountFromTicks(Ticks - 1);
|
||||||
|
int NewCount = CountFromTicks(Ticks);
|
||||||
|
NotifyInfo[] NotifyInfo = new NotifyInfo[1];
|
||||||
|
|
||||||
|
if (OldCount < NewCount)
|
||||||
|
{
|
||||||
|
NotifyInfo[0].FileName = String.Format("\\{0}", NewCount);
|
||||||
|
NotifyInfo[0].Action = NotifyAction.Added;
|
||||||
|
NotifyInfo[0].Filter = NotifyFilter.ChangeFileName;
|
||||||
|
Console.Error.WriteLine("CREATE \\{0}", NewCount);
|
||||||
|
}
|
||||||
|
else if (OldCount > NewCount)
|
||||||
|
{
|
||||||
|
NotifyInfo[0].FileName = String.Format("\\{0}", OldCount);
|
||||||
|
NotifyInfo[0].Action = NotifyAction.Removed;
|
||||||
|
NotifyInfo[0].Filter = NotifyFilter.ChangeFileName;
|
||||||
|
Console.Error.WriteLine("REMOVE \\{0}", OldCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OldCount != NewCount)
|
||||||
|
{
|
||||||
|
if (STATUS_SUCCESS == _Host.NotifyBegin(500))
|
||||||
|
{
|
||||||
|
_Host.Notify(NotifyInfo);
|
||||||
|
_Host.NotifyEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Notifyfs()
|
||||||
|
{
|
||||||
|
RawSecurityDescriptor RootSecurityDescriptor = new RawSecurityDescriptor(
|
||||||
|
"O:BAG:BAD:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;WD)");
|
||||||
|
DefaultSecurity = new Byte[RootSecurityDescriptor.BinaryLength];
|
||||||
|
RootSecurityDescriptor.GetBinaryForm(DefaultSecurity, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int ALLOCATION_UNIT = 4096;
|
||||||
|
private static readonly Byte[] EmptyByteArray = new Byte[0];
|
||||||
|
private static readonly Byte[] DefaultSecurity;
|
||||||
|
private FileSystemHost _Host;
|
||||||
|
private Timer _Timer;
|
||||||
|
private int _Ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotifyfsService : Service
|
||||||
|
{
|
||||||
|
private class CommandLineUsageException : Exception
|
||||||
|
{
|
||||||
|
public CommandLineUsageException(String Message = null) : base(Message)
|
||||||
|
{
|
||||||
|
HasMessage = null != Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private const String PROGNAME = "notifyfs-dotnet";
|
||||||
|
|
||||||
|
public NotifyfsService() : base("NotifyfsService")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart(String[] Args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String VolumePrefix = null;
|
||||||
|
String MountPoint = null;
|
||||||
|
FileSystemHost Host = null;
|
||||||
|
Notifyfs Notifyfs = null;
|
||||||
|
int I;
|
||||||
|
|
||||||
|
for (I = 1; Args.Length > I; I++)
|
||||||
|
{
|
||||||
|
String Arg = Args[I];
|
||||||
|
if ('-' != Arg[0])
|
||||||
|
break;
|
||||||
|
switch (Arg[1])
|
||||||
|
{
|
||||||
|
case '?':
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
case 'm':
|
||||||
|
argtos(Args, ref I, ref MountPoint);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
argtos(Args, ref I, ref VolumePrefix);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Args.Length > I)
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
|
||||||
|
if (null == MountPoint)
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
|
||||||
|
FileSystemHost.SetDebugLogFile("-");
|
||||||
|
|
||||||
|
Host = new FileSystemHost(Notifyfs = new Notifyfs());
|
||||||
|
Host.Prefix = VolumePrefix;
|
||||||
|
if (0 > Host.Mount(MountPoint))
|
||||||
|
throw new IOException("cannot mount file system");
|
||||||
|
MountPoint = Host.MountPoint();
|
||||||
|
_Host = Host;
|
||||||
|
|
||||||
|
Log(EVENTLOG_INFORMATION_TYPE, String.Format("{0}{1}{2} -m {3}",
|
||||||
|
PROGNAME,
|
||||||
|
null != VolumePrefix && 0 < VolumePrefix.Length ? " -u " : "",
|
||||||
|
null != VolumePrefix && 0 < VolumePrefix.Length ? VolumePrefix : "",
|
||||||
|
MountPoint));
|
||||||
|
}
|
||||||
|
catch (CommandLineUsageException ex)
|
||||||
|
{
|
||||||
|
Log(EVENTLOG_ERROR_TYPE, String.Format(
|
||||||
|
"{0}" +
|
||||||
|
"usage: {1} OPTIONS\n" +
|
||||||
|
"\n" +
|
||||||
|
"options:\n" +
|
||||||
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
||||||
|
" -m MountPoint [X:|*|directory]\n",
|
||||||
|
ex.HasMessage ? ex.Message + "\n" : "",
|
||||||
|
PROGNAME));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log(EVENTLOG_ERROR_TYPE, String.Format("{0}", ex.Message));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected override void OnStop()
|
||||||
|
{
|
||||||
|
_Host.Unmount();
|
||||||
|
_Host = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void argtos(String[] Args, ref int I, ref String V)
|
||||||
|
{
|
||||||
|
if (Args.Length > ++I)
|
||||||
|
V = Args[I];
|
||||||
|
else
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileSystemHost _Host;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Environment.ExitCode = new NotifyfsService().Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
tst/notifyfs-dotnet/notifyfs-dotnet.csproj
Normal file
77
tst/notifyfs-dotnet/notifyfs-dotnet.csproj
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{DA7C383A-D10F-4FB0-BDCB-E7A7C5D068AA}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>notifyfs</RootNamespace>
|
||||||
|
<AssemblyName>notifyfs-dotnet</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="winfsp-msil">
|
||||||
|
<HintPath>$(MSBuildProgramFiles32)\WinFsp\bin\winfsp-msil.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
25
tst/notifyfs-dotnet/notifyfs-dotnet.sln
Normal file
25
tst/notifyfs-dotnet/notifyfs-dotnet.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30717.126
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "notifyfs-dotnet", "notifyfs-dotnet.csproj", "{DA7C383A-D10F-4FB0-BDCB-E7A7C5D068AA}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{DA7C383A-D10F-4FB0-BDCB-E7A7C5D068AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DA7C383A-D10F-4FB0-BDCB-E7A7C5D068AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DA7C383A-D10F-4FB0-BDCB-E7A7C5D068AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DA7C383A-D10F-4FB0-BDCB-E7A7C5D068AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {18D87005-09CA-40CF-9B51-139B486AB8D0}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
8
tst/notifyfs/.gitignore
vendored
Normal file
8
tst/notifyfs/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
build
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.vcproj.*
|
||||||
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
508
tst/notifyfs/notifyfs.c
Normal file
508
tst/notifyfs/notifyfs.c
Normal file
@ -0,0 +1,508 @@
|
|||||||
|
/**
|
||||||
|
* @file notifyfs.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2020 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
|
||||||
|
#define DEBUGFLAGS 0
|
||||||
|
//#define DEBUGFLAGS -1
|
||||||
|
|
||||||
|
#define PROGNAME "notifyfs"
|
||||||
|
#define ALLOCATION_UNIT 4096
|
||||||
|
|
||||||
|
#define info(format, ...) FspServiceLog(EVENTLOG_INFORMATION_TYPE, format, __VA_ARGS__)
|
||||||
|
#define warn(format, ...) FspServiceLog(EVENTLOG_WARNING_TYPE, format, __VA_ARGS__)
|
||||||
|
#define fail(format, ...) FspServiceLog(EVENTLOG_ERROR_TYPE, format, __VA_ARGS__)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
|
PTP_TIMER Timer;
|
||||||
|
UINT32 Ticks;
|
||||||
|
} NOTIFYFS;
|
||||||
|
|
||||||
|
static PSECURITY_DESCRIPTOR DefaultSecurity;
|
||||||
|
static ULONG DefaultSecuritySize;
|
||||||
|
|
||||||
|
static UINT32 CountFromTicks(UINT32 Ticks)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The formula below produces the periodic sequence:
|
||||||
|
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
||||||
|
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
UINT32 div10 = (Ticks % 20) / 10;
|
||||||
|
UINT32 mod10 = Ticks % 10;
|
||||||
|
UINT32 mdv10 = 1 - div10;
|
||||||
|
UINT32 mmd10 = 10 - mod10;
|
||||||
|
return mdv10 * mod10 + div10 * mmd10;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT32 FileCount(NOTIFYFS *Notifyfs)
|
||||||
|
{
|
||||||
|
UINT32 Ticks = InterlockedOr(&Notifyfs->Ticks, 0);
|
||||||
|
return CountFromTicks(Ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT32 FileLookup(NOTIFYFS *Notifyfs, PWSTR FileName)
|
||||||
|
{
|
||||||
|
FileName++;
|
||||||
|
PWSTR Endp;
|
||||||
|
UINT32 Count = FileCount(Notifyfs);
|
||||||
|
UINT32 Index = wcstoul(FileName, &Endp, 10);
|
||||||
|
if ('\0' != *Endp || (FileName != Endp && (0 == Index || Index > Count)))
|
||||||
|
return -1; /* not found */
|
||||||
|
if (FileName == Endp)
|
||||||
|
return 0; /* root */
|
||||||
|
return Index; /* regular file named 1, 2, ..., Count */
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT32 FileContents(UINT32 Index, WCHAR P[32])
|
||||||
|
{
|
||||||
|
WCHAR Buffer[32];
|
||||||
|
if (0 == P)
|
||||||
|
P = Buffer;
|
||||||
|
if (0 == Index)
|
||||||
|
P[0] = '\0';
|
||||||
|
else
|
||||||
|
wsprintfW(P, L"%u\n", (unsigned)Index);
|
||||||
|
return lstrlenW(P);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FillFileInfo(UINT32 Index, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
FILETIME SystemTime;
|
||||||
|
|
||||||
|
GetSystemTimeAsFileTime(&SystemTime);
|
||||||
|
|
||||||
|
memset(FileInfo, 0, sizeof FileInfo);
|
||||||
|
FileInfo->FileAttributes = 0 == Index ? FILE_ATTRIBUTE_DIRECTORY : 0;
|
||||||
|
FileInfo->FileSize = FileContents(Index, 0);
|
||||||
|
FileInfo->AllocationSize = (FileInfo->FileSize + ALLOCATION_UNIT - 1)
|
||||||
|
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
|
||||||
|
FileInfo->CreationTime =
|
||||||
|
FileInfo->LastAccessTime =
|
||||||
|
FileInfo->LastWriteTime =
|
||||||
|
FileInfo->ChangeTime = *(PUINT64)&SystemTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN AddDirInfo(PWSTR FileName, UINT32 Index,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
FSP_FSCTL_DIR_INFO D;
|
||||||
|
} DirInfoBuf;
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D;
|
||||||
|
|
||||||
|
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
||||||
|
if (0 != FileName)
|
||||||
|
lstrcpyW(DirInfo->FileNameBuf, FileName);
|
||||||
|
else
|
||||||
|
wsprintfW(DirInfo->FileNameBuf, L"%u", (unsigned)Index);
|
||||||
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(DirInfo->FileNameBuf) * sizeof(WCHAR));
|
||||||
|
FillFileInfo(Index, &DirInfo->FileInfo);
|
||||||
|
|
||||||
|
return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_VOLUME_INFO *VolumeInfo)
|
||||||
|
{
|
||||||
|
memset(VolumeInfo, 0, sizeof *VolumeInfo);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PWSTR FileName, PUINT32 PFileAttributes,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = (NOTIFYFS *)FileSystem->UserContext;
|
||||||
|
UINT32 Index;
|
||||||
|
|
||||||
|
Index = FileLookup(Notifyfs, FileName);
|
||||||
|
if (-1 == Index)
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
if (0 != PFileAttributes)
|
||||||
|
*PFileAttributes = 0 == Index ? FILE_ATTRIBUTE_DIRECTORY : 0;
|
||||||
|
|
||||||
|
if (0 != PSecurityDescriptorSize)
|
||||||
|
{
|
||||||
|
if (DefaultSecuritySize > *PSecurityDescriptorSize)
|
||||||
|
{
|
||||||
|
*PSecurityDescriptorSize = DefaultSecuritySize;
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PSecurityDescriptorSize = DefaultSecuritySize;
|
||||||
|
if (0 != SecurityDescriptor)
|
||||||
|
memcpy(SecurityDescriptor, DefaultSecurity, DefaultSecuritySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
|
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
|
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = (NOTIFYFS *)FileSystem->UserContext;
|
||||||
|
FSP_FSCTL_TRANSACT_FULL_CONTEXT *FullContext = (PVOID)PFileContext;
|
||||||
|
UINT32 Index;
|
||||||
|
|
||||||
|
Index = FileLookup(Notifyfs, FileName);
|
||||||
|
if (-1 == Index)
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
FullContext->UserContext = Index;
|
||||||
|
FullContext->UserContext2 = 0;
|
||||||
|
|
||||||
|
FillFileInfo(Index, FileInfo);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize,
|
||||||
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length,
|
||||||
|
PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = (NOTIFYFS *)FileSystem->UserContext;
|
||||||
|
FSP_FSCTL_TRANSACT_FULL_CONTEXT *FullContext = FileContext;
|
||||||
|
UINT32 Index = (UINT32)FullContext->UserContext;
|
||||||
|
UINT64 EndOffset;
|
||||||
|
WCHAR ContentBuf[32];
|
||||||
|
UINT32 ContentLen;
|
||||||
|
|
||||||
|
ContentLen = FileContents(Index, ContentBuf);
|
||||||
|
|
||||||
|
if (Offset >= ContentLen)
|
||||||
|
return STATUS_END_OF_FILE;
|
||||||
|
|
||||||
|
EndOffset = Offset + Length;
|
||||||
|
if (EndOffset > ContentLen)
|
||||||
|
EndOffset = ContentLen;
|
||||||
|
|
||||||
|
memcpy(Buffer, (PUINT8)ContentBuf + Offset, (size_t)(EndOffset - Offset));
|
||||||
|
|
||||||
|
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext,
|
||||||
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = (NOTIFYFS *)FileSystem->UserContext;
|
||||||
|
FSP_FSCTL_TRANSACT_FULL_CONTEXT *FullContext = FileContext;
|
||||||
|
UINT32 Index = (UINT32)FullContext->UserContext;
|
||||||
|
|
||||||
|
FillFileInfo(Index, FileInfo);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext, PWSTR Pattern, PWSTR Marker,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = (NOTIFYFS *)FileSystem->UserContext;
|
||||||
|
UINT32 Count = FileCount(Notifyfs);
|
||||||
|
UINT32 Index;
|
||||||
|
|
||||||
|
Index = 0 == Marker ? 1 : wcstoul(Marker, 0, 10) + 1;
|
||||||
|
for (; Count >= Index; Index++)
|
||||||
|
if (!AddDirInfo(0, Index, Buffer, Length, PBytesTransferred))
|
||||||
|
break;
|
||||||
|
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FSP_FILE_SYSTEM_INTERFACE NotifyfsInterface =
|
||||||
|
{
|
||||||
|
.GetVolumeInfo = GetVolumeInfo,
|
||||||
|
.GetSecurityByName = GetSecurityByName,
|
||||||
|
.Create = Create,
|
||||||
|
.Open = Open,
|
||||||
|
.Overwrite = Overwrite,
|
||||||
|
.Read = Read,
|
||||||
|
.GetFileInfo = GetFileInfo,
|
||||||
|
.ReadDirectory = ReadDirectory,
|
||||||
|
};
|
||||||
|
|
||||||
|
static VOID CALLBACK NotifyfsTick(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_TIMER Timer)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = Context;
|
||||||
|
UINT32 Ticks = InterlockedIncrement(&Notifyfs->Ticks);
|
||||||
|
UINT32 OldCount = CountFromTicks(Ticks - 1);
|
||||||
|
UINT32 NewCount = CountFromTicks(Ticks);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT8 B[FIELD_OFFSET(FSP_FSCTL_NOTIFY_INFO, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
} NotifyInfoBuf;
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo = &NotifyInfoBuf.V;
|
||||||
|
|
||||||
|
memset(NotifyInfo, 0, sizeof NotifyInfo);
|
||||||
|
if (OldCount < NewCount)
|
||||||
|
{
|
||||||
|
wsprintfW(NotifyInfo->FileNameBuf, L"\\%u", (unsigned)NewCount);
|
||||||
|
NotifyInfo->Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) +
|
||||||
|
wcslen(NotifyInfo->FileNameBuf) * sizeof(WCHAR));
|
||||||
|
NotifyInfo->Action = FILE_ACTION_ADDED;
|
||||||
|
NotifyInfo->Filter = FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
FspDebugLog("CREATE \\%u\n", (unsigned)NewCount);
|
||||||
|
}
|
||||||
|
else if (OldCount > NewCount)
|
||||||
|
{
|
||||||
|
wsprintfW(NotifyInfo->FileNameBuf, L"\\%u", (unsigned)OldCount);
|
||||||
|
NotifyInfo->Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) +
|
||||||
|
wcslen(NotifyInfo->FileNameBuf) * sizeof(WCHAR));
|
||||||
|
NotifyInfo->Action = FILE_ACTION_REMOVED;
|
||||||
|
NotifyInfo->Filter = FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
FspDebugLog("REMOVE \\%u\n", (unsigned)OldCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OldCount != NewCount)
|
||||||
|
{
|
||||||
|
if (STATUS_SUCCESS == FspFileSystemNotifyBegin(Notifyfs->FileSystem, 500))
|
||||||
|
{
|
||||||
|
FspFileSystemNotify(Notifyfs->FileSystem, NotifyInfo, NotifyInfo->Size);
|
||||||
|
FspFileSystemNotifyEnd(Notifyfs->FileSystem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID NotifyfsDelete(NOTIFYFS *Notifyfs);
|
||||||
|
|
||||||
|
static NTSTATUS NotifyfsCreate(PWSTR VolumePrefix, PWSTR MountPoint, NOTIFYFS **PNotifyfs)
|
||||||
|
{
|
||||||
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
|
NOTIFYFS *Notifyfs = 0;
|
||||||
|
INT64 TimerDue;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PNotifyfs = 0;
|
||||||
|
|
||||||
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||||
|
L"O:BAG:BAD:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;WD)", SDDL_REVISION_1,
|
||||||
|
&DefaultSecurity, &DefaultSecuritySize))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Notifyfs = malloc(sizeof *Notifyfs);
|
||||||
|
if (0 == Notifyfs)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
memset(Notifyfs, 0, sizeof *Notifyfs);
|
||||||
|
|
||||||
|
memset(&VolumeParams, 0, sizeof VolumeParams);
|
||||||
|
VolumeParams.SectorSize = ALLOCATION_UNIT;
|
||||||
|
VolumeParams.SectorsPerAllocationUnit = 1;
|
||||||
|
VolumeParams.VolumeCreationTime = 0;
|
||||||
|
VolumeParams.VolumeSerialNumber = 0;
|
||||||
|
VolumeParams.FileInfoTimeout = 1000;
|
||||||
|
VolumeParams.CaseSensitiveSearch = 0;
|
||||||
|
VolumeParams.CasePreservedNames = 1;
|
||||||
|
VolumeParams.UnicodeOnDisk = 1;
|
||||||
|
VolumeParams.PersistentAcls = 0;
|
||||||
|
VolumeParams.PostCleanupWhenModifiedOnly = 1;
|
||||||
|
VolumeParams.UmFileContextIsFullContext = 1;
|
||||||
|
if (0 != VolumePrefix)
|
||||||
|
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
||||||
|
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),
|
||||||
|
L"" PROGNAME);
|
||||||
|
|
||||||
|
Result = FspFileSystemCreate(
|
||||||
|
VolumeParams.Prefix[0] ? L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
|
||||||
|
&VolumeParams,
|
||||||
|
&NotifyfsInterface,
|
||||||
|
&Notifyfs->FileSystem);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
Notifyfs->FileSystem->UserContext = Notifyfs;
|
||||||
|
|
||||||
|
FspFileSystemSetDebugLog(Notifyfs->FileSystem, DEBUGFLAGS);
|
||||||
|
|
||||||
|
Result = FspFileSystemSetMountPoint(Notifyfs->FileSystem, MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Notifyfs->Timer = CreateThreadpoolTimer(NotifyfsTick, Notifyfs, 0);
|
||||||
|
if (0 == Notifyfs->Timer)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerDue = -1000;
|
||||||
|
SetThreadpoolTimer(Notifyfs->Timer, (PVOID)&TimerDue, 1000, 0);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
*PNotifyfs = Notifyfs;
|
||||||
|
else if (0 != Notifyfs)
|
||||||
|
NotifyfsDelete(Notifyfs);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID NotifyfsDelete(NOTIFYFS *Notifyfs)
|
||||||
|
{
|
||||||
|
if (0 != Notifyfs->Timer)
|
||||||
|
{
|
||||||
|
SetThreadpoolTimer(Notifyfs->Timer, 0, 0, 0);
|
||||||
|
WaitForThreadpoolTimerCallbacks(Notifyfs->Timer, TRUE);
|
||||||
|
CloseThreadpoolTimer(Notifyfs->Timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != Notifyfs->FileSystem)
|
||||||
|
FspFileSystemDelete(Notifyfs->FileSystem);
|
||||||
|
|
||||||
|
free(Notifyfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||||
|
{
|
||||||
|
#define argtos(v) if (arge > ++argp) v = *argp; else goto usage
|
||||||
|
|
||||||
|
wchar_t **argp, **arge;
|
||||||
|
PWSTR VolumePrefix = 0;
|
||||||
|
PWSTR MountPoint = 0;
|
||||||
|
NOTIFYFS *Notifyfs = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
for (argp = argv + 1, arge = argv + argc; arge > argp; argp++)
|
||||||
|
{
|
||||||
|
if (L'-' != argp[0][0])
|
||||||
|
break;
|
||||||
|
switch (argp[0][1])
|
||||||
|
{
|
||||||
|
case L'?':
|
||||||
|
goto usage;
|
||||||
|
case L'm':
|
||||||
|
argtos(MountPoint);
|
||||||
|
break;
|
||||||
|
case L'u':
|
||||||
|
argtos(VolumePrefix);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arge > argp)
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
if (0 == MountPoint)
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
FspDebugLogSetHandle(GetStdHandle(STD_ERROR_HANDLE));
|
||||||
|
|
||||||
|
Result = NotifyfsCreate(VolumePrefix, MountPoint, &Notifyfs);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
fail(L"cannot create file system");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspFileSystemStartDispatcher(Notifyfs->FileSystem, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
fail(L"cannot start file system");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MountPoint = FspFileSystemMountPoint(Notifyfs->FileSystem);
|
||||||
|
|
||||||
|
info(L"%s%s%s -m %s",
|
||||||
|
L"" PROGNAME,
|
||||||
|
0 != VolumePrefix && L'\0' != VolumePrefix[0] ? L" -u " : L"",
|
||||||
|
0 != VolumePrefix && L'\0' != VolumePrefix[0] ? VolumePrefix : L"",
|
||||||
|
MountPoint);
|
||||||
|
|
||||||
|
Service->UserContext = Notifyfs;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result) && 0 != Notifyfs)
|
||||||
|
NotifyfsDelete(Notifyfs);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
usage:;
|
||||||
|
static wchar_t usage[] = L""
|
||||||
|
"usage: %s OPTIONS\n"
|
||||||
|
"\n"
|
||||||
|
"options:\n"
|
||||||
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n"
|
||||||
|
" -m MountPoint [X:|*|directory]\n";
|
||||||
|
|
||||||
|
fail(usage, L"" PROGNAME);
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
#undef argtos
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS SvcStop(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
NOTIFYFS *Notifyfs = Service->UserContext;
|
||||||
|
|
||||||
|
FspFileSystemStopDispatcher(Notifyfs->FileSystem);
|
||||||
|
NotifyfsDelete(Notifyfs);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
if (!NT_SUCCESS(FspLoad(0)))
|
||||||
|
return ERROR_DELAY_LOAD_FAILED;
|
||||||
|
|
||||||
|
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
||||||
|
}
|
31
tst/notifyfs/notifyfs.sln
Normal file
31
tst/notifyfs/notifyfs.sln
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30717.126
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notifyfs", "notifyfs.vcxproj", "{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Release|x64.Build.0 = Release|x64
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{4BA1DED0-4268-408A-A4E2-8E1A6D55A99C}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {3CD0763B-2BFD-4D73-9539-13273788C41E}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
175
tst/notifyfs/notifyfs.vcxproj
Normal file
175
tst/notifyfs/notifyfs.vcxproj
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{4ba1ded0-4268-408a-a4e2-8e1a6d55a99c}</ProjectGuid>
|
||||||
|
<RootNamespace>notifyfs</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="notifyfs.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
14
tst/notifyfs/notifyfs.vcxproj.filters
Normal file
14
tst/notifyfs/notifyfs.vcxproj.filters
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="notifyfs.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#define WINFSP_TESTS_NO_HOOKS
|
#define WINFSP_TESTS_NO_HOOKS
|
||||||
#include "winfsp-tests.h"
|
#include "winfsp-tests.h"
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
|
||||||
#define FILENAMEBUF_SIZE 1024
|
#define FILENAMEBUF_SIZE 1024
|
||||||
|
|
||||||
@ -107,6 +108,75 @@ static VOID PrepareFileName(PCWSTR FileName, PWSTR FileNameBuf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HANDLE VolumeHandle;
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo;
|
||||||
|
} MAYBE_NOTIFY_DATA;
|
||||||
|
|
||||||
|
static DWORD WINAPI MaybeNotifyRoutine(PVOID Context)
|
||||||
|
{
|
||||||
|
MAYBE_NOTIFY_DATA *NotifyData = Context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The supplied VolumeHandle may be invalid or refer to the wrong object.
|
||||||
|
* This is ok because:
|
||||||
|
*
|
||||||
|
* - If the VolumeHandle is invalid, Windows will catch it and will fail the operation.
|
||||||
|
* - If the VolumeHandle refers to the wrong object, the FspFsctlNotify "should" fail
|
||||||
|
* because of an unknown DeviceIoControl code.
|
||||||
|
* - If the VolumeHandle refers to the wrong file system, it is still ok if we send an
|
||||||
|
* extraneous notify.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FspFsctlNotify(NotifyData->VolumeHandle,
|
||||||
|
NotifyData->NotifyInfo, NotifyData->NotifyInfo->Size);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, NotifyData->NotifyInfo);
|
||||||
|
HeapFree(GetProcessHeap(), 0, NotifyData);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID MaybeNotify(PWSTR FileName, ULONG Filter, ULONG Action)
|
||||||
|
{
|
||||||
|
static WCHAR DevicePrefix[] =
|
||||||
|
L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}";
|
||||||
|
static WCHAR MemfsSharePrefix[] =
|
||||||
|
L"\\\\memfs\\share";
|
||||||
|
MAYBE_NOTIFY_DATA *NotifyData;
|
||||||
|
FSP_FSCTL_NOTIFY_INFO *NotifyInfo;
|
||||||
|
size_t L;
|
||||||
|
|
||||||
|
if (!OptNotify || OptExternal || 0 == memfs_handle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (0 == wcsncmp(FileName, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix))
|
||||||
|
FileName += wcslen(DevicePrefix);
|
||||||
|
else if (0 == mywcscmp(
|
||||||
|
FileName, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix)))
|
||||||
|
FileName += wcslen(MemfsSharePrefix);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
L = wcslen(FileName);
|
||||||
|
NotifyData = HeapAlloc(GetProcessHeap(), 0, sizeof *NotifyData);
|
||||||
|
NotifyInfo = HeapAlloc(GetProcessHeap(), 0, sizeof *NotifyInfo + L * sizeof(WCHAR));
|
||||||
|
if (0 == NotifyData || 0 == NotifyInfo)
|
||||||
|
ABORT("cannot malloc notify data");
|
||||||
|
|
||||||
|
NotifyInfo->Size = (UINT16)(sizeof *NotifyInfo + L * sizeof(WCHAR));
|
||||||
|
NotifyInfo->Filter = Filter;
|
||||||
|
NotifyInfo->Action = Action;
|
||||||
|
memcpy(NotifyInfo->FileNameBuf, FileName, L * sizeof(WCHAR));
|
||||||
|
|
||||||
|
NotifyData->VolumeHandle = memfs_handle;
|
||||||
|
NotifyData->NotifyInfo = NotifyInfo;
|
||||||
|
|
||||||
|
if (!QueueUserWorkItem(MaybeNotifyRoutine, NotifyData, 0))
|
||||||
|
ABORT("cannot queue notify data");
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE File;
|
HANDLE File;
|
||||||
@ -210,6 +280,9 @@ HANDLE WINAPI HookCreateFileW(
|
|||||||
|
|
||||||
PrepareFileName(lpFileName, FileNameBuf);
|
PrepareFileName(lpFileName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeRequestOplock(FileNameBuf);
|
MaybeRequestOplock(FileNameBuf);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
@ -241,6 +314,9 @@ BOOL WINAPI HookSetFileAttributesW(
|
|||||||
|
|
||||||
PrepareFileName(lpFileName, FileNameBuf);
|
PrepareFileName(lpFileName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Success = SetFileAttributesW(FileNameBuf, dwFileAttributes);
|
Success = SetFileAttributesW(FileNameBuf, dwFileAttributes);
|
||||||
MaybeAdjustTraversePrivilege(TRUE);
|
MaybeAdjustTraversePrivilege(TRUE);
|
||||||
@ -256,6 +332,9 @@ BOOL WINAPI HookCreateDirectoryW(
|
|||||||
|
|
||||||
PrepareFileName(lpPathName, FileNameBuf);
|
PrepareFileName(lpPathName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Success = CreateDirectoryW(FileNameBuf, lpSecurityAttributes);
|
Success = CreateDirectoryW(FileNameBuf, lpSecurityAttributes);
|
||||||
MaybeAdjustTraversePrivilege(TRUE);
|
MaybeAdjustTraversePrivilege(TRUE);
|
||||||
@ -270,6 +349,9 @@ BOOL WINAPI HookDeleteFileW(
|
|||||||
|
|
||||||
PrepareFileName(lpFileName, FileNameBuf);
|
PrepareFileName(lpFileName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeRequestOplock(FileNameBuf);
|
MaybeRequestOplock(FileNameBuf);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
@ -287,6 +369,9 @@ BOOL WINAPI HookRemoveDirectoryW(
|
|||||||
|
|
||||||
PrepareFileName(lpPathName, FileNameBuf);
|
PrepareFileName(lpPathName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Success = (OptResilient ? ResilientRemoveDirectoryW : RemoveDirectoryW)(
|
Success = (OptResilient ? ResilientRemoveDirectoryW : RemoveDirectoryW)(
|
||||||
FileNameBuf);
|
FileNameBuf);
|
||||||
@ -306,6 +391,13 @@ BOOL WINAPI HookMoveFileExW(
|
|||||||
PrepareFileName(lpExistingFileName, OldFileNameBuf);
|
PrepareFileName(lpExistingFileName, OldFileNameBuf);
|
||||||
PrepareFileName(lpNewFileName, NewFileNameBuf);
|
PrepareFileName(lpNewFileName, NewFileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(OldFileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
if (OptCaseInsensitive ?
|
||||||
|
_wcsicmp(OldFileNameBuf, NewFileNameBuf) : wcscmp(OldFileNameBuf, NewFileNameBuf))
|
||||||
|
MaybeNotify(NewFileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeRequestOplock(OldFileNameBuf);
|
MaybeRequestOplock(OldFileNameBuf);
|
||||||
if (OptCaseInsensitive ?
|
if (OptCaseInsensitive ?
|
||||||
_wcsicmp(OldFileNameBuf, NewFileNameBuf) : wcscmp(OldFileNameBuf, NewFileNameBuf))
|
_wcsicmp(OldFileNameBuf, NewFileNameBuf) : wcscmp(OldFileNameBuf, NewFileNameBuf))
|
||||||
@ -326,6 +418,9 @@ HANDLE WINAPI HookFindFirstFileW(
|
|||||||
|
|
||||||
PrepareFileName(lpFileName, FileNameBuf);
|
PrepareFileName(lpFileName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Handle = FindFirstFileW(FileNameBuf, lpFindFileData);
|
Handle = FindFirstFileW(FileNameBuf, lpFindFileData);
|
||||||
MaybeAdjustTraversePrivilege(TRUE);
|
MaybeAdjustTraversePrivilege(TRUE);
|
||||||
@ -343,6 +438,9 @@ HANDLE WINAPI HookFindFirstStreamW(
|
|||||||
|
|
||||||
PrepareFileName(lpFileName, FileNameBuf);
|
PrepareFileName(lpFileName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Handle = FindFirstStreamW(FileNameBuf, InfoLevel, lpFindStreamData, dwFlags);
|
Handle = FindFirstStreamW(FileNameBuf, InfoLevel, lpFindStreamData, dwFlags);
|
||||||
MaybeAdjustTraversePrivilege(TRUE);
|
MaybeAdjustTraversePrivilege(TRUE);
|
||||||
@ -426,6 +524,9 @@ BOOL WINAPI HookSetCurrentDirectoryW(
|
|||||||
|
|
||||||
PrepareFileName(lpPathName, FileNameBuf);
|
PrepareFileName(lpPathName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Success = SetCurrentDirectoryW(FileNameBuf);
|
Success = SetCurrentDirectoryW(FileNameBuf);
|
||||||
MaybeAdjustTraversePrivilege(TRUE);
|
MaybeAdjustTraversePrivilege(TRUE);
|
||||||
@ -449,6 +550,9 @@ BOOL WINAPI HookCreateProcessW(
|
|||||||
|
|
||||||
PrepareFileName(lpApplicationName, FileNameBuf);
|
PrepareFileName(lpApplicationName, FileNameBuf);
|
||||||
|
|
||||||
|
MaybeNotify(FileNameBuf,
|
||||||
|
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
|
||||||
|
|
||||||
MaybeAdjustTraversePrivilege(FALSE);
|
MaybeAdjustTraversePrivilege(FALSE);
|
||||||
Success = CreateProcessW(FileNameBuf,
|
Success = CreateProcessW(FileNameBuf,
|
||||||
lpCommandLine, /* we should probably change this as well */
|
lpCommandLine, /* we should probably change this as well */
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "winfsp-tests.h"
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
int memfs_running;
|
int memfs_running;
|
||||||
|
HANDLE memfs_handle;
|
||||||
|
|
||||||
void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
||||||
{
|
{
|
||||||
@ -66,6 +67,7 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
|||||||
ASSERT(NT_SUCCESS(Result));
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
memfs_running = 1;
|
memfs_running = 1;
|
||||||
|
memfs_handle = MemfsFileSystem(Memfs)->VolumeHandle;
|
||||||
|
|
||||||
return Memfs;
|
return Memfs;
|
||||||
}
|
}
|
||||||
@ -77,6 +79,7 @@ void *memfs_start(ULONG Flags)
|
|||||||
|
|
||||||
void memfs_stop(void *data)
|
void memfs_stop(void *data)
|
||||||
{
|
{
|
||||||
|
memfs_handle = 0;
|
||||||
memfs_running = 0;
|
memfs_running = 0;
|
||||||
|
|
||||||
if (0 == data)
|
if (0 == data)
|
||||||
|
460
tst/winfsp-tests/notify-test.c
Normal file
460
tst/winfsp-tests/notify-test.c
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
/**
|
||||||
|
* @file notify-test.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2020 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License version 3 as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this software
|
||||||
|
* in accordance with the commercial license agreement provided in
|
||||||
|
* conjunction with the software. The terms and conditions of any such
|
||||||
|
* commercial license agreement shall govern, supersede, and render
|
||||||
|
* ineffective any application of the GPLv3 license to this software,
|
||||||
|
* notwithstanding of any reference thereto in the software or
|
||||||
|
* associated repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <tlib/testsuite.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#include "memfs.h"
|
||||||
|
|
||||||
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_abandon_dotest(ULONG Flags)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start(Flags);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFsctlNotify(FileSystem->VolumeHandle, 0, 0);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
Result = FspFsctlNotify(FileSystem->VolumeHandle, 0, 0);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_abandon_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
notify_abandon_dotest(MemfsDisk);
|
||||||
|
if (WinFspNetTests)
|
||||||
|
notify_abandon_dotest(MemfsNet);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
unsigned __stdcall notify_abandon_rename_dotest_thread(void *FilePath)
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath);
|
||||||
|
|
||||||
|
WCHAR NewFilePath[MAX_PATH];
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOL Success;
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Handle)
|
||||||
|
return GetLastError();
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
StringCbPrintfW(NewFilePath, sizeof NewFilePath, L"%s.new", FilePath);
|
||||||
|
Success = MoveFileExW(FilePath, NewFilePath, 0);
|
||||||
|
|
||||||
|
return Success ? 0 : GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_abandon_rename_dotest(ULONG Flags, PWSTR Prefix)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start(Flags);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
WCHAR FilePath[MAX_PATH];
|
||||||
|
HANDLE Thread;
|
||||||
|
DWORD ExitCode;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFsctlNotify(FileSystem->VolumeHandle, 0, 0);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Thread = (HANDLE)_beginthreadex(0, 0, notify_abandon_rename_dotest_thread, FilePath, 0, 0);
|
||||||
|
ASSERT(0 != Thread);
|
||||||
|
|
||||||
|
Sleep(1000);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
|
||||||
|
WaitForSingleObject(Thread, INFINITE);
|
||||||
|
GetExitCodeThread(Thread, &ExitCode);
|
||||||
|
CloseHandle(Thread);
|
||||||
|
ASSERT(ERROR_OPERATION_ABORTED == ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_abandon_rename_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
notify_abandon_rename_dotest(MemfsDisk, 0);
|
||||||
|
if (WinFspNetTests)
|
||||||
|
notify_abandon_rename_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_timeout_dotest(ULONG Flags)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start(Flags);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFsctlNotify(FileSystem->VolumeHandle, 0, 0);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 0);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 9);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 10);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 11);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 20);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 1000);
|
||||||
|
ASSERT(STATUS_CANT_WAIT == Result);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_timeout_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
notify_timeout_dotest(MemfsDisk);
|
||||||
|
if (WinFspNetTests)
|
||||||
|
notify_timeout_dotest(MemfsNet);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_change_dotest(ULONG Flags)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start(Flags);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[1024];
|
||||||
|
} Buffer;
|
||||||
|
ULONG Length = 0;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[sizeof(FSP_FSCTL_NOTIFY_INFO) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
} NotifyInfo;
|
||||||
|
PWSTR FileName;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 0);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
FileName = L"\\";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"bar";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"baz";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"\\foo";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"bar";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"baz";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"\\foo\\";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"bar";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
FileName = L"baz";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
FspFileSystemAddNotifyInfo(&NotifyInfo.V, &Buffer, sizeof Buffer, &Length);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotify(FileSystem, &Buffer.V, Length);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyEnd(FileSystem);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_change_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
notify_change_dotest(MemfsDisk);
|
||||||
|
if (WinFspNetTests)
|
||||||
|
notify_change_dotest(MemfsNet);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_open_change_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
|
||||||
|
HANDLE DirHandle, FileHandle;
|
||||||
|
WCHAR FilePath[MAX_PATH];
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[sizeof(FSP_FSCTL_NOTIFY_INFO) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
} NotifyInfo;
|
||||||
|
PWSTR FileName;
|
||||||
|
BOOL Success;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Success = CreateDirectoryW(FilePath, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
DirHandle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != DirHandle);
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1\\file0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
FileHandle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != FileHandle);
|
||||||
|
|
||||||
|
//DWORD Bytes;
|
||||||
|
//Success = WriteFile(FileHandle, "foobar", 6, &Bytes, 0);
|
||||||
|
//ASSERT(Success);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyBegin(FileSystem, 1000);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
FileName = L"\\dir1";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
Result = FspFileSystemNotify(FileSystem, &NotifyInfo.V, NotifyInfo.V.Size);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
FileName = L"\\dir1\\file0";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_MODIFIED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
Result = FspFileSystemNotify(FileSystem, &NotifyInfo.V, NotifyInfo.V.Size);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
Result = FspFileSystemNotifyEnd(FileSystem);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
CloseHandle(FileHandle);
|
||||||
|
|
||||||
|
CloseHandle(DirHandle);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_open_change_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
{
|
||||||
|
notify_open_change_dotest(MemfsDisk, 0, 0);
|
||||||
|
notify_open_change_dotest(MemfsDisk, 0, 1000);
|
||||||
|
notify_open_change_dotest(MemfsDisk, 0, INFINITE);
|
||||||
|
}
|
||||||
|
if (WinFspNetTests)
|
||||||
|
{
|
||||||
|
notify_open_change_dotest(MemfsNet, L"\\\\memfs\\share", 0);
|
||||||
|
notify_open_change_dotest(MemfsNet, L"\\\\memfs\\share", 1000);
|
||||||
|
notify_open_change_dotest(MemfsNet, L"\\\\memfs\\share", INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
unsigned __stdcall notify_dirnotify_dotest_thread(void *FileSystem0)
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ "\n");
|
||||||
|
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = FileSystem0;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FSP_FSCTL_NOTIFY_INFO V;
|
||||||
|
UINT8 B[sizeof(FSP_FSCTL_NOTIFY_INFO) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
} NotifyInfo;
|
||||||
|
PWSTR FileName;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Sleep(1000); /* wait for ReadDirectoryChangesW */
|
||||||
|
|
||||||
|
FileName = L"\\Directory\\Subdirectory\\file0";
|
||||||
|
NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
|
NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
NotifyInfo.V.Action = FILE_ACTION_ADDED;
|
||||||
|
memcpy(NotifyInfo.V.FileNameBuf, FileName, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO));
|
||||||
|
Result = FspFileSystemNotify(FileSystem, &NotifyInfo.V, NotifyInfo.V.Size);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_dirnotify_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
FSP_FILE_SYSTEM *FileSystem = MemfsFileSystem(memfs);
|
||||||
|
|
||||||
|
WCHAR FilePath[MAX_PATH];
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOL Success;
|
||||||
|
HANDLE Thread;
|
||||||
|
DWORD ExitCode;
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
PFILE_NOTIFY_INFORMATION NotifyInfo;
|
||||||
|
|
||||||
|
NotifyInfo = malloc(4096);
|
||||||
|
ASSERT(0 != NotifyInfo);
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\Directory",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Success = CreateDirectoryW(FilePath, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
FILE_LIST_DIRECTORY, FILE_SHARE_READ, 0, OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
|
||||||
|
Thread = (HANDLE)_beginthreadex(0, 0, notify_dirnotify_dotest_thread, FileSystem, 0, 0);
|
||||||
|
ASSERT(0 != Thread);
|
||||||
|
|
||||||
|
Success = ReadDirectoryChangesW(Handle,
|
||||||
|
NotifyInfo, 4096, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME, &BytesTransferred, 0, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
ASSERT(0 < BytesTransferred);
|
||||||
|
|
||||||
|
ASSERT(FILE_ACTION_ADDED == NotifyInfo->Action);
|
||||||
|
ASSERT(wcslen(L"Subdirectory\\file0") * sizeof(WCHAR) == NotifyInfo->FileNameLength);
|
||||||
|
ASSERT(0 == mywcscmp(L"Subdirectory\\file0", -1,
|
||||||
|
NotifyInfo->FileName, NotifyInfo->FileNameLength / sizeof(WCHAR)));
|
||||||
|
|
||||||
|
ASSERT(0 == NotifyInfo->NextEntryOffset);
|
||||||
|
|
||||||
|
WaitForSingleObject(Thread, INFINITE);
|
||||||
|
GetExitCodeThread(Thread, &ExitCode);
|
||||||
|
CloseHandle(Thread);
|
||||||
|
ASSERT(STATUS_SUCCESS == ExitCode);
|
||||||
|
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
Success = RemoveDirectoryW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
free(NotifyInfo);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void notify_dirnotify_test(void)
|
||||||
|
{
|
||||||
|
if (WinFspDiskTests &&
|
||||||
|
!OptNoTraverseToken /* WinFsp does not support change notifications w/o traverse privilege */ &&
|
||||||
|
!OptCaseRandomize)
|
||||||
|
{
|
||||||
|
notify_dirnotify_dotest(MemfsDisk, 0, 0);
|
||||||
|
notify_dirnotify_dotest(MemfsDisk, 0, 1000);
|
||||||
|
notify_dirnotify_dotest(MemfsDisk, 0, INFINITE);
|
||||||
|
}
|
||||||
|
if (WinFspNetTests &&
|
||||||
|
!OptNoTraverseToken /* WinFsp does not support change notifications w/o traverse privilege */ &&
|
||||||
|
!OptCaseRandomize)
|
||||||
|
{
|
||||||
|
notify_dirnotify_dotest(MemfsNet, L"\\\\memfs\\share", 0);
|
||||||
|
notify_dirnotify_dotest(MemfsNet, L"\\\\memfs\\share", 1000);
|
||||||
|
notify_dirnotify_dotest(MemfsNet, L"\\\\memfs\\share", INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify_tests(void)
|
||||||
|
{
|
||||||
|
if (OptExternal || OptNotify)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TEST(notify_abandon_test);
|
||||||
|
TEST(notify_abandon_rename_test);
|
||||||
|
TEST(notify_timeout_test);
|
||||||
|
TEST(notify_change_test);
|
||||||
|
TEST(notify_open_change_test);
|
||||||
|
TEST(notify_dirnotify_test);
|
||||||
|
}
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "winfsp-tests.h"
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
void posix_map_sid_test(void)
|
static void posix_map_sid_test(void)
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -171,7 +171,7 @@ void posix_map_sid_test(void)
|
|||||||
LocalFree(map[sizeof map / sizeof map[0] - 1].SidStr);
|
LocalFree(map[sizeof map / sizeof map[0] - 1].SidStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void posix_map_sd_test(void)
|
static void posix_map_sd_test(void)
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -237,7 +237,93 @@ void posix_map_sd_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void posix_map_path_test(void)
|
static void posix_merge_sd_test(void)
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UINT32 Uid, Gid, Mode;
|
||||||
|
PWSTR ExistingSddl;
|
||||||
|
PWSTR Sddl;
|
||||||
|
} map[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
0,
|
||||||
|
L"O:SYG:BAD:P(A;;0x1f0198;;;SY)(A;;0x120088;;;BA)(A;;0x120088;;;WD)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"",
|
||||||
|
L"O:SYG:BA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"O:WD",
|
||||||
|
L"O:WDG:BA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"G:WD",
|
||||||
|
L"O:SYG:WD"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"O:WDG:WD",
|
||||||
|
L"O:WDG:WD"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"D:P",
|
||||||
|
L"O:SYG:BAD:P"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"D:P(A;;FA;;;SY)",
|
||||||
|
L"O:SYG:BAD:P(A;;FA;;;SY)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
18, 544, 00000,
|
||||||
|
L"O:WDG:WDD:P(A;;FA;;;SY)",
|
||||||
|
L"O:WDG:WDD:P(A;;FA;;;SY)"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
NTSTATUS Result;
|
||||||
|
BOOL Success;
|
||||||
|
PSECURITY_DESCRIPTOR ExistingSecurityDescriptor, SecurityDescriptor;
|
||||||
|
PWSTR Sddl;
|
||||||
|
|
||||||
|
for (size_t i = 0; sizeof map / sizeof map[0] > i; i++)
|
||||||
|
{
|
||||||
|
if (0 != map[i].ExistingSddl)
|
||||||
|
{
|
||||||
|
Success = ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||||
|
map[i].ExistingSddl, SDDL_REVISION_1,
|
||||||
|
&ExistingSecurityDescriptor, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ExistingSecurityDescriptor = 0;
|
||||||
|
|
||||||
|
Result = FspPosixMergePermissionsToSecurityDescriptor(
|
||||||
|
map[i].Uid, map[i].Gid, map[i].Mode, ExistingSecurityDescriptor, &SecurityDescriptor);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
|
Success = ConvertSecurityDescriptorToStringSecurityDescriptorW(
|
||||||
|
SecurityDescriptor, SDDL_REVISION_1,
|
||||||
|
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||||
|
&Sddl, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
ASSERT(0 == wcscmp(map[i].Sddl, Sddl));
|
||||||
|
LocalFree(Sddl);
|
||||||
|
|
||||||
|
FspDeleteSecurityDescriptor(SecurityDescriptor,
|
||||||
|
FspPosixMergePermissionsToSecurityDescriptor);
|
||||||
|
|
||||||
|
LocalFree(ExistingSecurityDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void posix_map_path_test(void)
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -274,5 +360,6 @@ void posix_tests(void)
|
|||||||
|
|
||||||
TEST(posix_map_sid_test);
|
TEST(posix_map_sid_test);
|
||||||
TEST(posix_map_sd_test);
|
TEST(posix_map_sd_test);
|
||||||
|
TEST(posix_merge_sd_test);
|
||||||
TEST(posix_map_path_test);
|
TEST(posix_map_path_test);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
#include <lm.h>
|
#include <lm.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <tlib/testsuite.h>
|
#include <tlib/testsuite.h>
|
||||||
@ -38,6 +39,7 @@ BOOLEAN OptCaseInsensitiveCmp = FALSE;
|
|||||||
BOOLEAN OptCaseInsensitive = FALSE;
|
BOOLEAN OptCaseInsensitive = FALSE;
|
||||||
BOOLEAN OptCaseRandomize = FALSE;
|
BOOLEAN OptCaseRandomize = FALSE;
|
||||||
BOOLEAN OptFlushAndPurgeOnCleanup = FALSE;
|
BOOLEAN OptFlushAndPurgeOnCleanup = FALSE;
|
||||||
|
BOOLEAN OptNotify = FALSE;
|
||||||
WCHAR OptOplock = 0;
|
WCHAR OptOplock = 0;
|
||||||
WCHAR OptMountPointBuf[MAX_PATH], *OptMountPoint;
|
WCHAR OptMountPointBuf[MAX_PATH], *OptMountPoint;
|
||||||
WCHAR OptShareNameBuf[MAX_PATH], *OptShareName, *OptShareTarget;
|
WCHAR OptShareNameBuf[MAX_PATH], *OptShareName, *OptShareTarget;
|
||||||
@ -174,6 +176,37 @@ static void abort_handler(int sig)
|
|||||||
|
|
||||||
LONG WINAPI UnhandledExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
LONG WINAPI UnhandledExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
||||||
{
|
{
|
||||||
|
if (0 != ExceptionInfo && 0 != ExceptionInfo->ExceptionRecord)
|
||||||
|
{
|
||||||
|
static CHAR OutBuf[128];
|
||||||
|
static union
|
||||||
|
{
|
||||||
|
SYMBOL_INFO V;
|
||||||
|
UINT8 Buf[sizeof(SYMBOL_INFO) + 64];
|
||||||
|
} Info;
|
||||||
|
LARGE_INTEGER Large;
|
||||||
|
Info.V.SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
Info.V.MaxNameLen = 64;
|
||||||
|
if (SymFromAddr(GetCurrentProcess(),
|
||||||
|
(DWORD64)ExceptionInfo->ExceptionRecord->ExceptionAddress,
|
||||||
|
&Large.QuadPart,
|
||||||
|
&Info.V))
|
||||||
|
{
|
||||||
|
wsprintfA(OutBuf, "\nEXCEPTION 0x%lX at %s+0x%lX(0x%p)\n",
|
||||||
|
ExceptionInfo->ExceptionRecord->ExceptionCode,
|
||||||
|
Info.V.Name,
|
||||||
|
Large.LowPart,
|
||||||
|
ExceptionInfo->ExceptionRecord->ExceptionAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wsprintfA(OutBuf, "\nEXCEPTION 0x%lX at 0x%p\n",
|
||||||
|
ExceptionInfo->ExceptionRecord->ExceptionCode,
|
||||||
|
ExceptionInfo->ExceptionRecord->ExceptionAddress);
|
||||||
|
}
|
||||||
|
WriteFile(GetStdHandle(STD_ERROR_HANDLE), OutBuf, lstrlenA(OutBuf), &Large.LowPart, 0);
|
||||||
|
}
|
||||||
|
|
||||||
exiting();
|
exiting();
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
@ -211,12 +244,17 @@ int main(int argc, char *argv[])
|
|||||||
TESTSUITE(ea_tests);
|
TESTSUITE(ea_tests);
|
||||||
TESTSUITE(stream_tests);
|
TESTSUITE(stream_tests);
|
||||||
TESTSUITE(oplock_tests);
|
TESTSUITE(oplock_tests);
|
||||||
|
TESTSUITE(notify_tests);
|
||||||
TESTSUITE(wsl_tests);
|
TESTSUITE(wsl_tests);
|
||||||
TESTSUITE(volpath_tests);
|
TESTSUITE(volpath_tests);
|
||||||
|
|
||||||
|
SymInitialize(GetCurrentProcess(), 0, TRUE);
|
||||||
|
|
||||||
atexit(exiting);
|
atexit(exiting);
|
||||||
signal(SIGABRT, abort_handler);
|
signal(SIGABRT, abort_handler);
|
||||||
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
#pragma warning(suppress: 4996)
|
||||||
|
if (0 == getenv("WINFSP_TESTS_EXCEPTION_FILTER_DISABLE"))
|
||||||
|
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
||||||
|
|
||||||
for (int argi = 1; argc > argi; argi++)
|
for (int argi = 1; argc > argi; argi++)
|
||||||
{
|
{
|
||||||
@ -258,6 +296,11 @@ int main(int argc, char *argv[])
|
|||||||
OptFlushAndPurgeOnCleanup = TRUE;
|
OptFlushAndPurgeOnCleanup = TRUE;
|
||||||
rmarg(argv, argc, argi);
|
rmarg(argv, argc, argi);
|
||||||
}
|
}
|
||||||
|
else if (0 == strcmp("--notify", a))
|
||||||
|
{
|
||||||
|
OptNotify = TRUE;
|
||||||
|
rmarg(argv, argc, argi);
|
||||||
|
}
|
||||||
else if (0 == strcmp("--oplock=batch", a))
|
else if (0 == strcmp("--oplock=batch", a))
|
||||||
{
|
{
|
||||||
OptOplock = 'B';
|
OptOplock = 'B';
|
||||||
|
@ -159,6 +159,7 @@ extern BOOLEAN OptCaseInsensitiveCmp;
|
|||||||
extern BOOLEAN OptCaseInsensitive;
|
extern BOOLEAN OptCaseInsensitive;
|
||||||
extern BOOLEAN OptCaseRandomize;
|
extern BOOLEAN OptCaseRandomize;
|
||||||
extern BOOLEAN OptFlushAndPurgeOnCleanup;
|
extern BOOLEAN OptFlushAndPurgeOnCleanup;
|
||||||
|
extern BOOLEAN OptNotify;
|
||||||
extern WCHAR OptOplock;
|
extern WCHAR OptOplock;
|
||||||
extern WCHAR OptMountPointBuf[], *OptMountPoint;
|
extern WCHAR OptMountPointBuf[], *OptMountPoint;
|
||||||
extern WCHAR OptShareNameBuf[], *OptShareName, *OptShareTarget;
|
extern WCHAR OptShareNameBuf[], *OptShareName, *OptShareTarget;
|
||||||
@ -168,3 +169,4 @@ extern HANDLE OptNoTraverseToken;
|
|||||||
extern LUID OptNoTraverseLuid;
|
extern LUID OptNoTraverseLuid;
|
||||||
|
|
||||||
extern int memfs_running;
|
extern int memfs_running;
|
||||||
|
extern HANDLE memfs_handle;
|
||||||
|
Reference in New Issue
Block a user