mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-04 01:42:58 -05:00
Compare commits
111 Commits
Author | SHA1 | Date | |
---|---|---|---|
847eab3da4 | |||
5131ed5c01 | |||
b513128cfe | |||
3fe69f2208 | |||
29fd9bf779 | |||
3c391ca711 | |||
82a8545d8f | |||
79be3e445a | |||
b04266e0fe | |||
25adfaec00 | |||
ce20747534 | |||
d3d75bf977 | |||
6f1f1cda71 | |||
21dfeca124 | |||
6f585ce63e | |||
8f90305726 | |||
490d0577bb | |||
c9d3cb74c7 | |||
7d2ff3afeb | |||
c415c87195 | |||
d161ca59a7 | |||
bc03af3b2a | |||
ed1543665c | |||
a99fa512d4 | |||
a6800dd73d | |||
aa9354773b | |||
05b37c744b | |||
1d15c9546b | |||
51b33f02aa | |||
97ffa741b2 | |||
073645db3b | |||
fd9ac1c9e0 | |||
62b08c3d1e | |||
9436fd8402 | |||
de75454d50 | |||
430d7a5650 | |||
4655926d03 | |||
565caebe4c | |||
a47f853beb | |||
89ec3e6733 | |||
dbdfaeee1f | |||
2c64d59001 | |||
af8c74378e | |||
19c320350f | |||
d60b1de430 | |||
6a7b6c77c6 | |||
16b1b2b349 | |||
f181593f49 | |||
d2f42f4918 | |||
a73f1b9559 | |||
fb6893968a | |||
c97f2cb660 | |||
3a12d928e5 | |||
8fa337ae54 | |||
7f084787e3 | |||
369c0256f3 | |||
f25983853b | |||
757e23ded6 | |||
ebb9b8b799 | |||
804bcc3354 | |||
f5fde4c0bb | |||
dcf7e4c5a6 | |||
adc759447e | |||
f0d7e5b322 | |||
bfd8dca62d | |||
79b2f38d87 | |||
4ae03629f7 | |||
f4496786e5 | |||
b637a72ec8 | |||
2cd1bddafb | |||
6b83748d89 | |||
ed31a187ac | |||
781deff06f | |||
3902874ac9 | |||
8ad77fe62f | |||
f78b3464ce | |||
02fd6906c2 | |||
ce436fc29a | |||
879fa2464f | |||
af7e5432a7 | |||
1d619e0874 | |||
290896b010 | |||
c01402443d | |||
195f3bf92d | |||
ae86aeb633 | |||
369da895d3 | |||
17adae481c | |||
db34b8c913 | |||
f6212be687 | |||
7af36d8f78 | |||
f6e49a11c8 | |||
01ca9cef35 | |||
7cb29a4db3 | |||
5523320348 | |||
969651f5f6 | |||
a08fdccb17 | |||
859d4250c3 | |||
c6b7b7586e | |||
6406246ce2 | |||
9d8ff57be7 | |||
2b0d204ff1 | |||
851d0758d9 | |||
4f444b412e | |||
e9578b48ce | |||
3c3163c41b | |||
8beb534340 | |||
9dcc04f882 | |||
ce83619728 | |||
04b3675f12 | |||
6a23f28249 | |||
351b4f5294 |
@ -1,6 +1,65 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v1.5B3 (2019.3 B3)::
|
||||||
|
|
||||||
|
Changes since v1.4:
|
||||||
|
|
||||||
|
* [GEN] WinFsp file systems can now be used by WSLinux. Use the command `sudo mount -t drvfs x: /mnt/x` to mount.
|
||||||
|
* [GEN] Extended attribute support has been added for all WinFsp API's: native, .NET, FUSE2 and FUSE3.
|
||||||
|
* [GEN] Mount Manager support has been added and it works for current and new file systems:
|
||||||
|
** If the file system mountpoint is in the syntax `\\.\X:` then the Mount Manager is used.
|
||||||
|
** If the file system mountpoint is in the syntax `X:` then `DefineDosDeviceW` is used (i.e. same as today).
|
||||||
|
** If the file system mountpoint is in the syntax `X:\DIR` then a reparse point is used and the file system is mounted as a directory (i.e. same as today).
|
||||||
|
** Caveats:
|
||||||
|
*** It requires Administrator access. This is because opening the `\\.\MountPointManager` device requires Administrator access.
|
||||||
|
*** It currently works with drives (`\\.\X:`) but not directories (`\\.\X:\DIR`).
|
||||||
|
*** Mount Manager drives created by WinFsp are transient. WinFsp takes various steps to ensure that this is the case.
|
||||||
|
*** Mount Manager drives are global and are visible across Terminal Services sessions (they go into the `\GLOBAL??` portion of the NT namespace).
|
||||||
|
* [FSD] Support for kernel-mode file systems on top of WinFsp has been added. See `FspFsextProvider`. This is in preparation for WinFuse - FUSE for Windows and WSLinux.
|
||||||
|
* [FSD] FastIO support has been added. FastIO operations are enabled on cache-enabled file systems with the notable exception of `FastIoQueryOpen`, which allows opening files in kernel mode; this operation requires the file system to specify the `FSP_FSCTL_VOLUME_PARAMS::AllowOpenInKernelMode` flag.
|
||||||
|
* [FSD] Support for `FileFsSectorSizeInformation` and `IOCTL_STORAGE_QUERY_PROPERTY / StorageAccessAlignmentProperty` has been added.
|
||||||
|
* [DLL] The `FspFileSystemStartDispatcher` default number of threads (`ThreadCount==0`) has been changed. See commit 3902874ac93fe40685d9761f46a96358ba24f24c for more.
|
||||||
|
* [FUSE] FUSE has new `-o UserName=DOMAIN+USERNAME` and `-o GroupName=DOMAIN+GROUPNAME` options. These function like the `-o uid=UID` and `-o gid=GID` options, but accept Windows user and groups names.
|
||||||
|
* [FUSE] FUSE has new `-o dothidden` option that is used to add the Windows hidden file attribute to files that start with a dot.
|
||||||
|
* [FUSE] FUSE has new `-o create_file_umask=nnn` and `-o create_dir_umask=nnn` options that allow for more control than the `-o create_umask=nnn` option.
|
||||||
|
* [FUSE] FUSE has new `--ExactFileSystemName=FSNAME` option that removes the "FUSE-" prefix from the file system name. (Use with caution: see discussion in PR #251.) (Thanks @johntyner.)
|
||||||
|
* [.NET] The .NET API now supports asynchronous handling of `Read`, `Write` and `ReadDirectory`. (Thanks @dworkin.)
|
||||||
|
* [.NET] The .NET API now supports fine-grained timeouts (`VolumeInfoTimeout`, `DirInfoTimeout`, etc).
|
||||||
|
* [.NET] The .NET API has new method `FileSystemHost.MountEx` that adds a `ThreadCount` parameter.
|
||||||
|
* [LAUNCH] The Launcher can now rewrite path arguments passed to file systems during launching using "Path Transformation Language". See commit a73f1b95592617ac7484e16c2e642573a4d65644 for more.
|
||||||
|
* [MEMFS] A new memfs FUSE3 file system written in C++ has been added. See `tst/memfs-fuse3`.
|
||||||
|
* [AIRFS] John Oberschelp has done some fantastic work adding persistence to the airfs file system. (Thanks @JohnOberschelp.)
|
||||||
|
* [FIX] Fixes for very large (> 4GiB) files. (Thanks @dworkin.)
|
||||||
|
* [FIX] A fix for how FUSE handles the return value from `opendir`. (GitHub issue billziss-gh/sshfs-win#54)
|
||||||
|
* [FIX] A fix for an invalid UID to SID mapping on domains with a lot of users. (Thanks @sganis.)
|
||||||
|
* [FIX] A fix on the C++ layer. (Thanks @colatkinson.)
|
||||||
|
* Other fixes and improvements.
|
||||||
|
|
||||||
|
|
||||||
|
v1.5B2 (2019.3 B2)::
|
||||||
|
|
||||||
|
Changes since v1.4:
|
||||||
|
|
||||||
|
* [GEN] WinFsp file systems can now be used by WSLinux. Use the command `sudo mount -t drvfs x: /mnt/x` to mount.
|
||||||
|
* [GEN] Extended attribute support has been added for all WinFsp API's: native, .NET, FUSE2 and FUSE3.
|
||||||
|
* [FSD] Support for kernel-mode file systems on top of WinFsp has been added. See `FspFsextProvider`. This is in preparation for WinFuse - FUSE for Windows and WSLinux.
|
||||||
|
* [FSD] FastIO support has been added. FastIO operations are enabled on cache-enabled file systems with the notable exception of `FastIoQueryOpen`, which allows opening files in kernel mode; this operation requires the file system to specify the `FSP_FSCTL_VOLUME_PARAMS::AllowOpenInKernelMode` flag.
|
||||||
|
* [DLL] The `FspFileSystemStartDispatcher` default number of threads (`ThreadCount==0`) has been changed. See commit 3902874ac93fe40685d9761f46a96358ba24f24c for more.
|
||||||
|
* [FUSE] FUSE has new `-o UserName=DOMAIN\USERNAME` and `-o GroupName=DOMAIN\GROUPNAME` options. These function like the `-o uid=UID` and `-o gid=GID` options, but accept Windows user and groups names.
|
||||||
|
* [FUSE] FUSE has new `-o dothidden` option that is used to add the Windows hidden file attribute to files that start with a dot.
|
||||||
|
* [FUSE] FUSE has new `-o create_file_umask=nnn` and `-o create_dir_umask=nnn` options that allow for more control than the `-o create_umask=nnn` option.
|
||||||
|
* [.NET] The .NET API now supports asynchronous handling of `Read`, `Write` and `ReadDirectory`. (Thanks @dworkin.)
|
||||||
|
* [.NET] The .NET API now supports fine-grained timeouts (`VolumeInfoTimeout`, `DirInfoTimeout`, etc).
|
||||||
|
* [.NET] The .NET API has new method `FileSystemHost.MountEx` that adds a `ThreadCount` parameter.
|
||||||
|
* [LAUNCH] The Launcher can now rewrite path arguments passed to file systems during launching using "Path Transformation Language". See commit a73f1b95592617ac7484e16c2e642573a4d65644 for more.
|
||||||
|
* [FIX] Fixes for very large (> 4GiB) files. (Thanks @dworkin.)
|
||||||
|
* [FIX] A fix for how FUSE handles the return value from `opendir`. (GitHub issue billziss-gh/sshfs-win#54)
|
||||||
|
* [FIX] A fix for an invalid UID to SID mapping on domains with a lot of users. (Thanks @sganis.)
|
||||||
|
* [FIX] A fix on the C++ layer. (Thanks @colatkinson.)
|
||||||
|
* Other fixes and improvements.
|
||||||
|
|
||||||
|
|
||||||
v1.5B1 (2019.3 B1)::
|
v1.5B1 (2019.3 B1)::
|
||||||
|
|
||||||
Changes since v1.4:
|
Changes since v1.4:
|
||||||
@ -11,6 +70,7 @@ Changes since v1.4:
|
|||||||
* A fix for an invalid UID to SID mapping on domains with a lot of users. (Thanks @sganis.)
|
* A fix for an invalid UID to SID mapping on domains with a lot of users. (Thanks @sganis.)
|
||||||
* A fix on the C++ layer. (Thanks @colatkinson.)
|
* A fix on the C++ layer. (Thanks @colatkinson.)
|
||||||
|
|
||||||
|
|
||||||
v1.4.19049 (2019.2)::
|
v1.4.19049 (2019.2)::
|
||||||
|
|
||||||
Changes since v1.3:
|
Changes since v1.3:
|
||||||
|
@ -56,11 +56,13 @@ CONTRIBUTOR LIST
|
|||||||
|===
|
|===
|
||||||
|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
|
||||||
|Colin Atkinson (Atakama, https://atakama.com) |colin at atakama.com
|
|Colin Atkinson (Atakama, https://atakama.com) |colin at atakama.com
|
||||||
|Felix Croes |felix at dworkin.nl
|
|Felix Croes |felix at dworkin.nl
|
||||||
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr
|
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr
|
||||||
|Fritz Elfert |fritz-github at fritz-elfert.de
|
|Fritz Elfert |fritz-github at fritz-elfert.de
|
||||||
|John Oberschelp |john at oberschelp.net
|
|John Oberschelp |john at oberschelp.net
|
||||||
|
|John Tyner |jtyner at gmail.com
|
||||||
|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
|
||||||
|
@ -96,6 +96,7 @@ The project source code is organized as follows:
|
|||||||
* :file_folder: [src/dll/fuse3](src/dll/fuse3): Source code to the FUSE3 compatibility layer.
|
* :file_folder: [src/dll/fuse3](src/dll/fuse3): Source code to the FUSE3 compatibility layer.
|
||||||
* :file_folder: [src/dotnet](src/dotnet): Source code to the .NET layer.
|
* :file_folder: [src/dotnet](src/dotnet): Source code to the .NET layer.
|
||||||
* :file_folder: [src/fsptool](src/fsptool): Source code to fsptool command line utility.
|
* :file_folder: [src/fsptool](src/fsptool): Source code to fsptool command line utility.
|
||||||
|
* :file_folder: [src/ku](src/ku): Source code that can be used from kernel or user mode.
|
||||||
* :file_folder: [src/launcher](src/launcher): Source code to the launcher service and the launchctl utility.
|
* :file_folder: [src/launcher](src/launcher): Source code to the launcher service and the launchctl utility.
|
||||||
* :file_folder: [src/sys](src/sys): Source code to the WinFsp FSD.
|
* :file_folder: [src/sys](src/sys): Source code to the WinFsp FSD.
|
||||||
* :file_folder: [opt/cygfuse](opt/cygfuse): Source code to the FUSE for Cygwin package.
|
* :file_folder: [opt/cygfuse](opt/cygfuse): Source code to the FUSE for Cygwin package.
|
||||||
@ -107,8 +108,12 @@ The project source code is organized as follows:
|
|||||||
|
|
||||||
In order to build WinFsp you will need the following:
|
In order to build WinFsp you will need the following:
|
||||||
|
|
||||||
* Visual Studio 2015
|
* Visual Studio 2015 - 2019
|
||||||
* Windows Driver Kit (WDK) 10
|
* Windows Driver Kit (WDK) 10
|
||||||
|
- **NOTE**: When using the latest WDK (Windows 10.0.18362.1) with Visual Studio 2015 you may get an error about a missing task `ValidateNTTargetVersion`. The fix is to edit the file `\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets` and modify the `UsingTask` line for `ValidateNTTargetVersion` as follows:
|
||||||
|
```
|
||||||
|
<UsingTask TaskName="ValidateNTTargetVersion" AssemblyFile="$(WDKContentRoot)build\bin\Microsoft.DriverKit.Build.Tasks.16.0.dll"/>
|
||||||
|
```
|
||||||
* [Wix toolset](http://wixtoolset.org)
|
* [Wix toolset](http://wixtoolset.org)
|
||||||
|
|
||||||
To fully build WinFsp (including the installer) you must use `tools\build.bat`. By default it builds a Release build, but you can choose either the Debug or Release configuration by using the syntax:
|
To fully build WinFsp (including the installer) you must use `tools\build.bat`. By default it builds a Release build, but you can choose either the Debug or Release configuration by using the syntax:
|
||||||
|
@ -15,6 +15,13 @@ 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:
|
||||||
|
- 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"
|
||||||
|
$usingTask = $targets.ChildNodes[1].UsingTask | ? {$_.TaskName -eq "ValidateNTTargetVersion"}
|
||||||
|
$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")
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- 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
|
||||||
|
3
build/VStudio/.gitignore
vendored
3
build/VStudio/.gitignore
vendored
@ -4,3 +4,6 @@ build
|
|||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
*.csproj.user
|
*.csproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\..\version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -14,18 +15,18 @@
|
|||||||
<ProjectGuid>{95C223E6-B5F1-4FD0-9376-41CDBC824445}</ProjectGuid>
|
<ProjectGuid>{95C223E6-B5F1-4FD0-9376-41CDBC824445}</ProjectGuid>
|
||||||
<RootNamespace>CustomActions</RootNamespace>
|
<RootNamespace>CustomActions</RootNamespace>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
@ -68,7 +69,6 @@
|
|||||||
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(WIX)sdk\VS2015\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(WIX)sdk\VS2015\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
@ -92,7 +92,6 @@
|
|||||||
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(WIX)sdk\VS2015\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(WIX)sdk\VS2015\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
@ -369,6 +369,23 @@
|
|||||||
<File Name="uninstall.sh" KeyPath="yes" />
|
<File Name="uninstall.sh" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
<Directory Id="OPTDIR.fsext" Name="fsext" FileSource="..\..\..\opt\fsext">
|
||||||
|
<Directory Id="OPTDIR.fsext.inc" Name="inc">
|
||||||
|
<Directory Id="OPTDIR.fsext.inc.winfsp" Name="winfsp">
|
||||||
|
<Component Id="C.fsext.h">
|
||||||
|
<File Name="fsext.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="OPTDIR.fsext.lib" Name="lib">
|
||||||
|
<Component Id="C.fsext.winfsp_x64.lib">
|
||||||
|
<File Id="FILE.fsext.winfsp_x64.lib" Name="winfsp-x64.lib" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.fsext.winfsp_x86.lib">
|
||||||
|
<File Id="FILE.fsext.winfsp_x86.lib" Name="winfsp-x86.lib" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="SMPDIR" FileSource="..\..\..\tst">
|
<DirectoryRef Id="SMPDIR" FileSource="..\..\..\tst">
|
||||||
<Directory Id="SMPDIR.memfs" Name="memfs">
|
<Directory Id="SMPDIR.memfs" Name="memfs">
|
||||||
@ -382,6 +399,29 @@
|
|||||||
<File Name="memfs-main.c" KeyPath="yes" />
|
<File Name="memfs-main.c" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.memfs_fuse3" Name="memfs-fuse3">
|
||||||
|
<Component Id="C.memfs_fuse3.cpp">
|
||||||
|
<File Name="memfs-fuse3.cpp" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_fuse3.compat.h">
|
||||||
|
<File Id="F.memfs_fuse3.compat.h" Name="compat.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_fuse3.sln">
|
||||||
|
<File Name="memfs-fuse3.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_fuse3.vcxproj">
|
||||||
|
<File Name="memfs-fuse3.vcxproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_fuse3.vcxproj.filters">
|
||||||
|
<File Name="memfs-fuse3.vcxproj.filters" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_fuse3.Makefile">
|
||||||
|
<File Id="F.memfs_fuse3.Makefile" Name="Makefile" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_fuse3.README.md">
|
||||||
|
<File Id="F.memfsx_fuse3.README.md" Name="README.md" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
<Directory Id="SMPDIR.memfs_dotnet" Name="memfs-dotnet">
|
<Directory Id="SMPDIR.memfs_dotnet" Name="memfs-dotnet">
|
||||||
<Component Id="C.memfs_dotnet.Program.cs">
|
<Component Id="C.memfs_dotnet.Program.cs">
|
||||||
<File Id="FILE.memfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
<File Id="FILE.memfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||||
@ -391,6 +431,12 @@
|
|||||||
<Component Id="C.airfs.cpp">
|
<Component Id="C.airfs.cpp">
|
||||||
<File Name="airfs.cpp" KeyPath="yes" />
|
<File Name="airfs.cpp" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="C.persistence.cpp">
|
||||||
|
<File Name="persistence.cpp" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.common.h">
|
||||||
|
<File Name="common.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
<Component Id="C.airfs.sln">
|
<Component Id="C.airfs.sln">
|
||||||
<File Name="airfs.sln" KeyPath="yes" />
|
<File Name="airfs.sln" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
@ -580,13 +626,27 @@
|
|||||||
<ComponentRef Id="C.fuse.install.sh" />
|
<ComponentRef Id="C.fuse.install.sh" />
|
||||||
<ComponentRef Id="C.fuse.uninstall.sh" />
|
<ComponentRef Id="C.fuse.uninstall.sh" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.opt.fsext">
|
||||||
|
<ComponentRef Id="C.fsext.h" />
|
||||||
|
<ComponentRef Id="C.fsext.winfsp_x64.lib" />
|
||||||
|
<ComponentRef Id="C.fsext.winfsp_x86.lib" />
|
||||||
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="C.WinFsp.smp">
|
<ComponentGroup Id="C.WinFsp.smp">
|
||||||
<ComponentRef Id="C.memfs_x64.exe" />
|
<ComponentRef Id="C.memfs_x64.exe" />
|
||||||
<ComponentRef Id="C.memfs_x86.exe" />
|
<ComponentRef Id="C.memfs_x86.exe" />
|
||||||
<ComponentRef Id="C.memfs.h" />
|
<ComponentRef Id="C.memfs.h" />
|
||||||
<ComponentRef Id="C.memfs.cpp" />
|
<ComponentRef Id="C.memfs.cpp" />
|
||||||
<ComponentRef Id="C.memfs_main.c" />
|
<ComponentRef Id="C.memfs_main.c" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.cpp" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.compat.h" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.sln" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.vcxproj" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.vcxproj.filters" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.Makefile" />
|
||||||
|
<ComponentRef Id="C.memfs_fuse3.README.md" />
|
||||||
<ComponentRef Id="C.airfs.cpp" />
|
<ComponentRef Id="C.airfs.cpp" />
|
||||||
|
<ComponentRef Id="C.persistence.cpp" />
|
||||||
|
<ComponentRef Id="C.common.h" />
|
||||||
<ComponentRef Id="C.airfs.sln" />
|
<ComponentRef Id="C.airfs.sln" />
|
||||||
<ComponentRef Id="C.airfs.vcxproj" />
|
<ComponentRef Id="C.airfs.vcxproj" />
|
||||||
<ComponentRef Id="C.airfs.vcxproj.filters" />
|
<ComponentRef Id="C.airfs.vcxproj.filters" />
|
||||||
@ -694,6 +754,16 @@
|
|||||||
<ComponentGroupRef Id="C.WinFsp.smp.net" />
|
<ComponentGroupRef Id="C.WinFsp.smp.net" />
|
||||||
<ComponentGroupRef Id="C.WinFsp.sym" />
|
<ComponentGroupRef Id="C.WinFsp.sym" />
|
||||||
</Feature>
|
</Feature>
|
||||||
|
<Feature
|
||||||
|
Id="F.KernelDeveloper"
|
||||||
|
Level="1000"
|
||||||
|
Title="Kernel Developer"
|
||||||
|
Description="Additional files needed for in-kernel development."
|
||||||
|
AllowAdvertise="no"
|
||||||
|
InstallDefault="local"
|
||||||
|
Absent="allow">
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.opt.fsext" />
|
||||||
|
</Feature>
|
||||||
<Feature
|
<Feature
|
||||||
Id="F.Cygfuse"
|
Id="F.Cygfuse"
|
||||||
Level="1000"
|
Level="1000"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -22,32 +23,32 @@
|
|||||||
<ProjectGuid>{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}</ProjectGuid>
|
<ProjectGuid>{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>fsbench</RootNamespace>
|
<RootNamespace>fsbench</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -106,7 +107,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -122,7 +122,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -142,7 +141,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -162,7 +160,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -22,32 +23,32 @@
|
|||||||
<ProjectGuid>{10757011-749D-4954-873B-AE38D8145472}</ProjectGuid>
|
<ProjectGuid>{10757011-749D-4954-873B-AE38D8145472}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>fscrash</RootNamespace>
|
<RootNamespace>fscrash</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -106,7 +107,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -122,7 +122,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -142,7 +141,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -162,7 +160,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -22,33 +23,33 @@
|
|||||||
<ProjectGuid>{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}</ProjectGuid>
|
<ProjectGuid>{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>memfs</RootNamespace>
|
<RootNamespace>memfs</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
<ProjectName>memfs</ProjectName>
|
<ProjectName>memfs</ProjectName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -107,7 +108,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -124,7 +124,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -143,7 +142,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
@ -164,7 +162,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -22,32 +23,32 @@
|
|||||||
<ProjectGuid>{262DF8CC-E7A8-4460-A22C-683CBA322C32}</ProjectGuid>
|
<ProjectGuid>{262DF8CC-E7A8-4460-A22C-683CBA322C32}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>winfsptests</RootNamespace>
|
<RootNamespace>winfsptests</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -106,7 +107,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -123,7 +123,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -142,7 +141,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
@ -163,7 +161,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ntdll.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
@ -194,6 +191,7 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\info-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\info-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\launcher-ptrans-test.c" />
|
||||||
<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" />
|
||||||
@ -206,8 +204,11 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\volpath-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\wsl-test.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h" />
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h" />
|
||||||
|
@ -97,6 +97,18 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\ea-test.c">
|
<ClCompile Include="..\..\..\tst\winfsp-tests\ea-test.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\wsl-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\launcher-ptrans-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\volpath-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||||
|
@ -23,32 +23,32 @@
|
|||||||
<ProjectGuid>{1E997BEC-1642-4A5C-B252-852DA094E11E}</ProjectGuid>
|
<ProjectGuid>{1E997BEC-1642-4A5C-B252-852DA094E11E}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>fsptool</RootNamespace>
|
<RootNamespace>fsptool</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -108,7 +108,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
@ -127,7 +126,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
@ -149,7 +147,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
@ -171,7 +168,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -23,32 +23,32 @@
|
|||||||
<ProjectGuid>{264A5D09-126F-4760-A3F1-4B3B95C925AA}</ProjectGuid>
|
<ProjectGuid>{264A5D09-126F-4760-A3F1-4B3B95C925AA}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>launchctl</RootNamespace>
|
<RootNamespace>launchctl</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -110,7 +110,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
@ -131,7 +130,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
@ -155,7 +153,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
@ -179,7 +176,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -23,32 +23,32 @@
|
|||||||
<ProjectGuid>{6CDF9411-B852-4EAC-822D-8F930675F17B}</ProjectGuid>
|
<ProjectGuid>{6CDF9411-B852-4EAC-822D-8F930675F17B}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>launcher</RootNamespace>
|
<RootNamespace>launcher</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -110,7 +110,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
@ -132,7 +131,6 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
@ -157,7 +155,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
@ -182,7 +179,6 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||||
@ -190,6 +186,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\src\launcher\launcher.c" />
|
<ClCompile Include="..\..\..\src\launcher\launcher.c" />
|
||||||
|
<ClCompile Include="..\..\..\src\launcher\ptrans.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\winfsp_dll.vcxproj">
|
<ProjectReference Include="..\winfsp_dll.vcxproj">
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
<ClCompile Include="..\..\..\src\launcher\launcher.c">
|
<ClCompile Include="..\..\..\src\launcher\launcher.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\src\launcher\ptrans.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
|
|
||||||
<MyProductName>WinFsp</MyProductName>
|
<MyProductName>WinFsp</MyProductName>
|
||||||
<MyDescription>Windows File System Proxy</MyDescription>
|
<MyDescription>Windows File System Proxy</MyDescription>
|
||||||
<MyCompanyName>Navimatics Corporation</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.5</MyCanonicalVersion>
|
<MyCanonicalVersion>1.5</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2019.3 B1</MyProductVersion>
|
<MyProductVersion>2019.3 B3</MyProductVersion>
|
||||||
<MyProductStage>Beta</MyProductStage>
|
<MyProductStage>Beta</MyProductStage>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
@ -37,4 +37,17 @@
|
|||||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion)</PreprocessorDefinitions>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(DefaultPlatformToolset)'=='v140'">
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(DefaultPlatformToolset)'!='v140'">
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SpectreMitigation>false</SpectreMitigation>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@ -35,6 +35,7 @@
|
|||||||
<ClInclude Include="..\..\src\dll\fuse3\library.h" />
|
<ClInclude Include="..\..\src\dll\fuse3\library.h" />
|
||||||
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
||||||
<ClInclude Include="..\..\src\dll\library.h" />
|
<ClInclude Include="..\..\src\dll\library.h" />
|
||||||
|
<ClInclude Include="..\..\src\ku\library.h" />
|
||||||
<ClInclude Include="..\..\src\shared\minimal.h" />
|
<ClInclude Include="..\..\src\shared\minimal.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -50,8 +51,8 @@
|
|||||||
<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\mount.c" />
|
||||||
<ClCompile Include="..\..\src\dll\np.c" />
|
<ClCompile Include="..\..\src\dll\np.c" />
|
||||||
<ClCompile Include="..\..\src\dll\posix.c" />
|
|
||||||
<ClCompile Include="..\..\src\dll\security.c" />
|
<ClCompile Include="..\..\src\dll\security.c" />
|
||||||
<ClCompile Include="..\..\src\dll\debug.c" />
|
<ClCompile Include="..\..\src\dll\debug.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fsctl.c" />
|
<ClCompile Include="..\..\src\dll\fsctl.c" />
|
||||||
@ -63,6 +64,7 @@
|
|||||||
<ClCompile Include="..\..\src\dll\service.c" />
|
<ClCompile Include="..\..\src\dll\service.c" />
|
||||||
<ClCompile Include="..\..\src\dll\util.c" />
|
<ClCompile Include="..\..\src\dll\util.c" />
|
||||||
<ClCompile Include="..\..\src\dll\wksid.c" />
|
<ClCompile Include="..\..\src\dll\wksid.c" />
|
||||||
|
<ClCompile Include="..\..\src\ku\posix.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
||||||
@ -126,33 +128,33 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<ProjectGuid>{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}</ProjectGuid>
|
<ProjectGuid>{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>winfspdll</RootNamespace>
|
<RootNamespace>winfspdll</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
<ProjectName>winfsp.dll</ProjectName>
|
<ProjectName>winfsp.dll</ProjectName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -216,7 +218,6 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<GenerateMapFile>true</GenerateMapFile>
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
@ -244,7 +245,6 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<GenerateMapFile>true</GenerateMapFile>
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
@ -273,7 +273,6 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
@ -304,7 +303,6 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
<Filter Include="Source\fuse3">
|
<Filter Include="Source\fuse3">
|
||||||
<UniqueIdentifier>{96091a7b-3923-4a74-9491-3ee230c688f9}</UniqueIdentifier>
|
<UniqueIdentifier>{96091a7b-3923-4a74-9491-3ee230c688f9}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Source\ku">
|
||||||
|
<UniqueIdentifier>{613cce77-2428-4f9a-9187-f37e009253c1}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
||||||
@ -77,6 +80,9 @@
|
|||||||
<ClInclude Include="..\..\src\dll\fuse3\library.h">
|
<ClInclude Include="..\..\src\dll\fuse3\library.h">
|
||||||
<Filter>Source\fuse3</Filter>
|
<Filter>Source\fuse3</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ku\library.h">
|
||||||
|
<Filter>Source\ku</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\dll\library.c">
|
<ClCompile Include="..\..\src\dll\library.c">
|
||||||
@ -124,9 +130,6 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c">
|
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c">
|
||||||
<Filter>Source\fuse</Filter>
|
<Filter>Source\fuse</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\dll\posix.c">
|
|
||||||
<Filter>Source</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c">
|
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c">
|
||||||
<Filter>Source\fuse</Filter>
|
<Filter>Source\fuse</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -154,6 +157,12 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3_compat.c">
|
<ClCompile Include="..\..\src\dll\fuse3\fuse3_compat.c">
|
||||||
<Filter>Source\fuse3</Filter>
|
<Filter>Source\fuse3</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ku\posix.c">
|
||||||
|
<Filter>Source\ku</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\mount.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\library.def">
|
<None Include="..\..\src\dll\library.def">
|
||||||
|
@ -101,11 +101,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>..\..\src;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\opt\fsext\inc;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions> _X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions> _X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<GenerateMapFile>true</GenerateMapFile>
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
@ -114,11 +114,11 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>..\..\src;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\opt\fsext\inc;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions> _X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions> _X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<GenerateMapFile>true</GenerateMapFile>
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
@ -127,11 +127,11 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>..\..\src;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\opt\fsext\inc;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions> _WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions> _WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<GenerateMapFile>true</GenerateMapFile>
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
@ -140,11 +140,11 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>..\..\src;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\opt\fsext\inc;..\..\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions> _WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions> _WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<GenerateMapFile>true</GenerateMapFile>
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
@ -155,6 +155,8 @@
|
|||||||
<FilesToPackage Include="$(TargetPath)" />
|
<FilesToPackage Include="$(TargetPath)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\src\ku\posix.c" />
|
||||||
|
<ClCompile Include="..\..\src\ku\uuid5.c" />
|
||||||
<ClCompile Include="..\..\src\sys\cleanup.c" />
|
<ClCompile Include="..\..\src\sys\cleanup.c" />
|
||||||
<ClCompile Include="..\..\src\sys\close.c" />
|
<ClCompile Include="..\..\src\sys\close.c" />
|
||||||
<ClCompile Include="..\..\src\sys\create.c" />
|
<ClCompile Include="..\..\src\sys\create.c" />
|
||||||
@ -169,10 +171,12 @@
|
|||||||
<ClCompile Include="..\..\src\sys\fileinfo.c" />
|
<ClCompile Include="..\..\src\sys\fileinfo.c" />
|
||||||
<ClCompile Include="..\..\src\sys\flush.c" />
|
<ClCompile Include="..\..\src\sys\flush.c" />
|
||||||
<ClCompile Include="..\..\src\sys\fsctl.c" />
|
<ClCompile Include="..\..\src\sys\fsctl.c" />
|
||||||
|
<ClCompile Include="..\..\src\sys\fsext.c" />
|
||||||
<ClCompile Include="..\..\src\sys\iop.c" />
|
<ClCompile Include="..\..\src\sys\iop.c" />
|
||||||
<ClCompile Include="..\..\src\sys\ioq.c" />
|
<ClCompile Include="..\..\src\sys\ioq.c" />
|
||||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||||
|
<ClCompile Include="..\..\src\sys\mountdev.c" />
|
||||||
<ClCompile Include="..\..\src\sys\mup.c" />
|
<ClCompile Include="..\..\src\sys\mup.c" />
|
||||||
<ClCompile Include="..\..\src\sys\name.c" />
|
<ClCompile Include="..\..\src\sys\name.c" />
|
||||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||||
@ -188,6 +192,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||||
|
<ClInclude Include="..\..\opt\fsext\inc\winfsp\fsext.h" />
|
||||||
|
<ClInclude Include="..\..\src\ku\library.h" />
|
||||||
<ClInclude Include="..\..\src\sys\driver.h" />
|
<ClInclude Include="..\..\src\sys\driver.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -212,7 +218,7 @@ for /f "delims=" %%l in (%(FullPath)) do (
|
|||||||
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
||||||
)
|
)
|
||||||
|
|
||||||
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
||||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
|
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
@ -225,7 +231,7 @@ for /f "delims=" %%l in (%(FullPath)) do (
|
|||||||
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
||||||
)
|
)
|
||||||
|
|
||||||
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
||||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
|
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
@ -238,7 +244,7 @@ for /f "delims=" %%l in (%(FullPath)) do (
|
|||||||
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
||||||
)
|
)
|
||||||
|
|
||||||
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
||||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects>
|
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">set DriverFile=$(TargetFileName)
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">set DriverFile=$(TargetFileName)
|
||||||
set Provider="$(MyCompanyName)"
|
set Provider="$(MyCompanyName)"
|
||||||
@ -251,7 +257,7 @@ for /f "delims=" %%l in (%(FullPath)) do (
|
|||||||
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
echo !line! >>$(OutDir)driver-$(PlatformTarget).inf
|
||||||
)
|
)
|
||||||
|
|
||||||
stampinf -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
stampinf -d * -v $(MyVersion) -f $(OutDir)driver-$(PlatformTarget).inf</Command>
|
||||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
|
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
|
||||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Writing driver-$(PlatformTarget).inf</Message>
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Writing driver-$(PlatformTarget).inf</Message>
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)driver-$(PlatformTarget).inf</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)driver-$(PlatformTarget).inf</Outputs>
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
<Filter Include="Include\winfsp">
|
<Filter Include="Include\winfsp">
|
||||||
<UniqueIdentifier>{904f0df1-2fb8-4f84-aa46-fa929488c39a}</UniqueIdentifier>
|
<UniqueIdentifier>{904f0df1-2fb8-4f84-aa46-fa929488c39a}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Source\ku">
|
||||||
|
<UniqueIdentifier>{235076b8-290c-4dec-b005-71d9b8e8cba7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\sys\driver.c">
|
<ClCompile Include="..\..\src\sys\driver.c">
|
||||||
@ -104,6 +107,18 @@
|
|||||||
<ClCompile Include="..\..\src\sys\mup.c">
|
<ClCompile Include="..\..\src\sys\mup.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\sys\fsext.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ku\posix.c">
|
||||||
|
<Filter>Source\ku</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ku\uuid5.c">
|
||||||
|
<Filter>Source\ku</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\sys\mountdev.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\sys\driver.h">
|
<ClInclude Include="..\..\src\sys\driver.h">
|
||||||
@ -112,6 +127,12 @@
|
|||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
||||||
<Filter>Include\winfsp</Filter>
|
<Filter>Include\winfsp</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\opt\fsext\inc\winfsp\fsext.h">
|
||||||
|
<Filter>Include\winfsp</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ku\library.h">
|
||||||
|
<Filter>Source\ku</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\..\src\sys\version.rc">
|
<ResourceCompile Include="..\..\src\sys\version.rc">
|
||||||
|
@ -18,10 +18,6 @@ Disconnecting (unmapping) a network drive does not work.::
|
|||||||
Case-sensitive file systems do not work properly when mounted as a directory.::
|
Case-sensitive file systems do not work properly when mounted as a directory.::
|
||||||
|
|
||||||
This is fixed as of WinFsp 2018.2 B3.
|
This is fixed as of WinFsp 2018.2 B3.
|
||||||
+
|
|
||||||
Windows and WinFsp support case-sensitive file systems. These file systems work properly when mounted as a drive. Unfortunately when a file system is mounted as a directory over NTFS, Windows expects it to be case-insensitive and will UPPERCASE many of the file names sent to the file system.
|
|
||||||
+
|
|
||||||
This is an unfortunate but well understood Windows limitation. Case-sensitive file systems should only be mounted as drives.
|
|
||||||
|
|
||||||
|
|
||||||
Why is the DLL not installed in the Windows system directories?::
|
Why is the DLL not installed in the Windows system directories?::
|
||||||
@ -68,5 +64,10 @@ With this in mind here are the reasons for the current WinFsp-FUSE behavior:
|
|||||||
WinFsp-FUSE does not have the ability to support multiple file systems from within the same process. Why?::
|
WinFsp-FUSE does not have the ability to support multiple file systems from within the same process. Why?::
|
||||||
|
|
||||||
This is supported as of WinFsp 2018.2 B2.
|
This is supported as of WinFsp 2018.2 B2.
|
||||||
|
|
||||||
|
|
||||||
|
I have problems getting permissions to work properly in a WinFsp-FUSE file system. Can you help?::
|
||||||
|
|
||||||
|
The WinFsp-FUSE layer includes a built-in command line option that can help: `-o uid=-1`. This instructs the WinFsp-FUSE layer to present all file system files as if they are owned by the user that launched the file system.
|
||||||
+
|
+
|
||||||
The core WinFsp layer always supported multiple file systems in the same process either simultaneously or one after another. However this was not the case with WinFsp-FUSE (i.e. the FUSE layer of WinFsp) prior to version 2018.2 B2. This limitation has been rectified as of WinFsp 2018.2 B2.
|
Alternatives include `-o uid=-1,gid=-1`, which presents files as owned by the user *and* group that launched the file system and `-o uid=-1,gid=11`, which presents files as owned by the user that launched the file system and the group "Authenticated Users". (The `fsptool` utility in the `bin` subdirectory of the WinFsp installation directory can be used to convert Windows accounts/SID's to UID's and vice versa.)
|
||||||
|
@ -5,6 +5,7 @@ This document contains a list of known file systems and file system libraries th
|
|||||||
== File Systems
|
== File Systems
|
||||||
|
|
||||||
- https://github.com/vgough/encfs[EncFS] - an Encrypted Filesystem for FUSE
|
- https://github.com/vgough/encfs[EncFS] - an Encrypted Filesystem for FUSE
|
||||||
|
- https://github.com/lowleveldesign/fsmemfs[fsmemfs] - Memory File System written in F#
|
||||||
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
||||||
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
||||||
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
||||||
@ -13,6 +14,7 @@ This document contains a list of known file systems and file system libraries th
|
|||||||
- https://github.com/billziss-gh/redditfs[redditfs] - ls -l /r/programming
|
- https://github.com/billziss-gh/redditfs[redditfs] - ls -l /r/programming
|
||||||
- https://github.com/netheril96/securefs[securefs] - Filesystem in userspace (FUSE) with transparent authenticated encryption
|
- https://github.com/netheril96/securefs[securefs] - Filesystem in userspace (FUSE) with transparent authenticated encryption
|
||||||
- https://github.com/billziss-gh/sshfs-win[sshfs-win] - SSHFS for Windows
|
- https://github.com/billziss-gh/sshfs-win[sshfs-win] - SSHFS for Windows
|
||||||
|
- https://github.com/UtrechtUniversity/YodaDrive[YodaDrive] - Mount a Yoda drive as a local drive
|
||||||
|
|
||||||
== File System Libraries
|
== File System Libraries
|
||||||
|
|
||||||
@ -20,3 +22,4 @@ This document contains a list of known file systems and file system libraries th
|
|||||||
- https://github.com/DuroSoft/fuse-bindings[Nodejs: fuse-bindings] - Fully maintained FUSE bindings for Node that aims to cover the entire FUSE api
|
- https://github.com/DuroSoft/fuse-bindings[Nodejs: fuse-bindings] - Fully maintained FUSE bindings for Node that aims to cover the entire FUSE api
|
||||||
- https://github.com/SerCeMan/jnr-fuse[Java: jnr-fuse] - FUSE implementation in Java using Java Native Runtime (JNR)
|
- https://github.com/SerCeMan/jnr-fuse[Java: jnr-fuse] - FUSE implementation in Java using Java Native Runtime (JNR)
|
||||||
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
||||||
|
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
||||||
|
@ -54,6 +54,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
|||||||
#define FSP_FSCTL_DECLSPEC_ALIGN __declspec(align(FSP_FSCTL_DEFAULT_ALIGNMENT))
|
#define FSP_FSCTL_DECLSPEC_ALIGN __declspec(align(FSP_FSCTL_DEFAULT_ALIGNMENT))
|
||||||
|
|
||||||
/* fsctl device codes */
|
/* fsctl device codes */
|
||||||
|
#define FSP_FSCTL_MOUNTDEV \
|
||||||
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define FSP_FSCTL_VOLUME_NAME \
|
#define FSP_FSCTL_VOLUME_NAME \
|
||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define FSP_FSCTL_VOLUME_LIST \
|
#define FSP_FSCTL_VOLUME_LIST \
|
||||||
@ -65,6 +67,10 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
|||||||
#define FSP_FSCTL_STOP \
|
#define FSP_FSCTL_STOP \
|
||||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
/* fsctl internal device codes (usable only in-kernel) */
|
||||||
|
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
||||||
|
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'I', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
|
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
|
||||||
|
|
||||||
#define FSP_FSCTL_VOLUME_NAME_SIZE (64 * sizeof(WCHAR))
|
#define FSP_FSCTL_VOLUME_NAME_SIZE (64 * sizeof(WCHAR))
|
||||||
@ -83,7 +89,7 @@ FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
|
|||||||
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN (64 * 1024)
|
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN (64 * 1024)
|
||||||
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
|
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
|
||||||
|
|
||||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((T) & 0xffffffff))
|
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((UINT_PTR)((T) & 0xffffffff)))
|
||||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff))
|
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff))
|
||||||
|
|
||||||
#define FSP_FSCTL_DEVICECONTROL_SIZEMAX (4 * 1024) /* must be < FSP_FSCTL_TRANSACT_{REQ,RSP}_SIZEMAX */
|
#define FSP_FSCTL_DEVICECONTROL_SIZEMAX (4 * 1024) /* must be < FSP_FSCTL_TRANSACT_{REQ,RSP}_SIZEMAX */
|
||||||
@ -121,7 +127,7 @@ enum
|
|||||||
{
|
{
|
||||||
FspFsctlTransactTimeoutMinimum = 1000,
|
FspFsctlTransactTimeoutMinimum = 1000,
|
||||||
FspFsctlTransactTimeoutMaximum = 10000,
|
FspFsctlTransactTimeoutMaximum = 10000,
|
||||||
FspFsctlTransactTimeoutDefault = 1000,
|
FspFsctlTransactTimeoutDefault = 1000, /* DEPRECATED: default is unspecified */
|
||||||
FspFsctlIrpTimeoutMinimum = 60000,
|
FspFsctlIrpTimeoutMinimum = 60000,
|
||||||
FspFsctlIrpTimeoutMaximum = 600000,
|
FspFsctlIrpTimeoutMaximum = 600000,
|
||||||
FspFsctlIrpTimeoutDefault = 300000,
|
FspFsctlIrpTimeoutDefault = 300000,
|
||||||
@ -139,7 +145,7 @@ enum
|
|||||||
UINT64 VolumeCreationTime;\
|
UINT64 VolumeCreationTime;\
|
||||||
UINT32 VolumeSerialNumber;\
|
UINT32 VolumeSerialNumber;\
|
||||||
/* I/O timeouts, capacity, etc. */\
|
/* I/O timeouts, capacity, etc. */\
|
||||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */\
|
UINT32 TransactTimeout; /* DEPRECATED: (millis; 1 sec - 10 sec) */\
|
||||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */\
|
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */\
|
||||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/\
|
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/\
|
||||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */\
|
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */\
|
||||||
@ -168,7 +174,8 @@ enum
|
|||||||
/* additional kernel-mode flags */\
|
/* additional kernel-mode flags */\
|
||||||
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
|
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
|
||||||
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
||||||
UINT32 KmReservedFlags:6;\
|
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
||||||
|
UINT32 KmReservedFlags:5;\
|
||||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||||
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
||||||
@ -184,7 +191,8 @@ enum
|
|||||||
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 EaTimeout; /* EA timeout (millis); overrides FileInfoTimeout */\
|
UINT32 EaTimeout; /* EA timeout (millis); overrides FileInfoTimeout */\
|
||||||
UINT32 Reserved32[2];\
|
UINT32 FsextControlCode;\
|
||||||
|
UINT32 Reserved32[1];\
|
||||||
UINT64 Reserved64[2];
|
UINT64 Reserved64[2];
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -277,7 +285,7 @@ typedef struct
|
|||||||
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
||||||
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
||||||
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
|
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
|
||||||
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes buffer */
|
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes or reparse point buffer */
|
||||||
UINT32 UserMode:1; /* request originated in user mode */
|
UINT32 UserMode:1; /* request originated in user mode */
|
||||||
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
||||||
UINT32 HasBackupPrivilege:1; /* requestor has TOKEN_HAS_BACKUP_PRIVILEGE */
|
UINT32 HasBackupPrivilege:1; /* requestor has TOKEN_HAS_BACKUP_PRIVILEGE */
|
||||||
@ -286,6 +294,7 @@ typedef struct
|
|||||||
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
||||||
UINT32 HasTrailingBackslash:1; /* FileName had trailing backslash */
|
UINT32 HasTrailingBackslash:1; /* FileName had trailing backslash */
|
||||||
UINT32 AcceptsSecurityDescriptor:1;
|
UINT32 AcceptsSecurityDescriptor:1;
|
||||||
|
UINT32 EaIsReparsePoint:1; /* Ea buffer is reparse point */
|
||||||
UINT32 ReservedFlags:24;
|
UINT32 ReservedFlags:24;
|
||||||
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
|
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
|
||||||
} Create;
|
} Create;
|
||||||
@ -586,11 +595,13 @@ static inline FSP_FSCTL_TRANSACT_RSP *FspFsctlTransactConsumeResponse(
|
|||||||
return NextResponse <= ResponseBufEnd ? (FSP_FSCTL_TRANSACT_RSP *)NextResponse : 0;
|
return NextResponse <= ResponseBufEnd ? (FSP_FSCTL_TRANSACT_RSP *)NextResponse : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(WINFSP_SYS_INTERNAL)
|
#if !defined(_KERNEL_MODE)
|
||||||
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||||
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
||||||
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
||||||
PHANDLE PVolumeHandle);
|
PHANDLE PVolumeHandle);
|
||||||
|
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||||
|
BOOLEAN Persistent, GUID *UniqueId);
|
||||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||||
@ -599,6 +610,20 @@ FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
|
|||||||
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);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* in */
|
||||||
|
HANDLE VolumeHandle; /* volume handle returned by FspFsctlCreateVolume */
|
||||||
|
PWSTR VolumeName; /* volume name returned by FspFsctlCreateVolume */
|
||||||
|
PSECURITY_DESCRIPTOR Security; /* optional: security descriptor for directories */
|
||||||
|
UINT64 Reserved; /* reserved for future use */
|
||||||
|
/* in/out */
|
||||||
|
PWSTR MountPoint; /* FspMountSet sets drive in buffer when passed "*:" */
|
||||||
|
HANDLE MountHandle; /* FspMountSet sets, FspMountRemove uses */
|
||||||
|
} FSP_MOUNT_DESC;
|
||||||
|
FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc);
|
||||||
|
FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -912,7 +912,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
/**
|
/**
|
||||||
* Create new file or directory.
|
* Create new file or directory.
|
||||||
*
|
*
|
||||||
* This function works like Create, except that it also accepts EA (extended attributes).
|
* This function works like Create, except that it also accepts an extra buffer that
|
||||||
|
* may contain extended attributes or a reparse point.
|
||||||
*
|
*
|
||||||
* NOTE: If both Create and CreateEx are defined, CreateEx takes precedence.
|
* NOTE: If both Create and CreateEx are defined, CreateEx takes precedence.
|
||||||
*
|
*
|
||||||
@ -941,10 +942,12 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* Windows GetSecurityDescriptorLength API. Will be NULL for named streams.
|
* Windows GetSecurityDescriptorLength API. Will be NULL for named streams.
|
||||||
* @param AllocationSize
|
* @param AllocationSize
|
||||||
* Allocation size for the newly created file.
|
* Allocation size for the newly created file.
|
||||||
* @param Ea
|
* @param ExtraBuffer
|
||||||
* Extended attributes buffer.
|
* Extended attributes or reparse point buffer.
|
||||||
* @param EaLength
|
* @param ExtraLength
|
||||||
* Extended attributes buffer length.
|
* Extended attributes or reparse point buffer length.
|
||||||
|
* @param ExtraBufferIsReparsePoint
|
||||||
|
* FALSE: extra buffer is extended attributes; TRUE: extra buffer is reparse point.
|
||||||
* @param PFileContext [out]
|
* @param PFileContext [out]
|
||||||
* Pointer that will receive the file context on successful return from this call.
|
* Pointer that will receive the file context on successful return from this call.
|
||||||
* @param FileInfo [out]
|
* @param FileInfo [out]
|
||||||
@ -956,7 +959,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
NTSTATUS (*CreateEx)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*CreateEx)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
PVOID ExtraBuffer, ULONG ExtraLength, BOOLEAN ExtraBufferIsReparsePoint,
|
||||||
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo);
|
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
/**
|
/**
|
||||||
* Overwrite a file.
|
* Overwrite a file.
|
||||||
|
93
opt/fsext/inc/winfsp/fsext.h
Normal file
93
opt/fsext/inc/winfsp/fsext.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* @file winfsp/fsext.h
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINFSP_FSEXT_H_INCLUDED
|
||||||
|
#define WINFSP_FSEXT_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(_KERNEL_MODE)
|
||||||
|
#error This file can only be included when compiling for kernel mode.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winfsp/fsctl.h>
|
||||||
|
|
||||||
|
#if defined(WINFSP_SYS_INTERNAL)
|
||||||
|
#define FSP_DDI __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define FSP_DDI __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#if !defined(FSP_DDI_DEF)
|
||||||
|
#define FSP_DDI_DEF(RetType, Name, ...) FSP_DDI RetType NTAPI Name ( __VA_ARGS__ );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT32 Version;
|
||||||
|
/* in */
|
||||||
|
UINT32 DeviceTransactCode;
|
||||||
|
UINT32 DeviceExtensionSize;
|
||||||
|
NTSTATUS (*DeviceInit)(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_PARAMS *VolumeParams);
|
||||||
|
VOID (*DeviceFini)(PDEVICE_OBJECT DeviceObject);
|
||||||
|
VOID (*DeviceExpirationRoutine)(PDEVICE_OBJECT DeviceObject, UINT64 ExpirationTime);
|
||||||
|
NTSTATUS (*DeviceTransact)(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||||
|
/* out */
|
||||||
|
UINT32 DeviceExtensionOffset;
|
||||||
|
} FSP_FSEXT_PROVIDER;
|
||||||
|
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspFsextProviderRegister,
|
||||||
|
FSP_FSEXT_PROVIDER *Provider)
|
||||||
|
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspPosixMapUidToSid,
|
||||||
|
UINT32 Uid,
|
||||||
|
PSID *PSid)
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspPosixMapSidToUid,
|
||||||
|
PSID Sid,
|
||||||
|
PUINT32 PUid)
|
||||||
|
FSP_DDI_DEF(VOID, FspDeleteSid,
|
||||||
|
PSID Sid,
|
||||||
|
NTSTATUS (*CreateFunc)())
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspPosixMapPermissionsToSecurityDescriptor,
|
||||||
|
UINT32 Uid,
|
||||||
|
UINT32 Gid,
|
||||||
|
UINT32 Mode,
|
||||||
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspPosixMapSecurityDescriptorToPermissions,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
PUINT32 PUid,
|
||||||
|
PUINT32 PGid,
|
||||||
|
PUINT32 PMode)
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspPosixMapWindowsToPosixPathEx,
|
||||||
|
PWSTR WindowsPath,
|
||||||
|
char **PPosixPath,
|
||||||
|
BOOLEAN Translate)
|
||||||
|
FSP_DDI_DEF(NTSTATUS, FspPosixMapPosixToWindowsPathEx,
|
||||||
|
const char *PosixPath,
|
||||||
|
PWSTR *PWindowsPath,
|
||||||
|
BOOLEAN Translate)
|
||||||
|
FSP_DDI_DEF(VOID, FspPosixDeletePath,
|
||||||
|
void *Path)
|
||||||
|
FSP_DDI_DEF(VOID, FspPosixEncodeWindowsPath,
|
||||||
|
PWSTR WindowsPath,
|
||||||
|
ULONG Size)
|
||||||
|
FSP_DDI_DEF(VOID, FspPosixDecodeWindowsPath,
|
||||||
|
PWSTR WindowsPath,
|
||||||
|
ULONG Size)
|
||||||
|
|
||||||
|
#endif
|
BIN
opt/fsext/lib/winfsp-x64.lib
Normal file
BIN
opt/fsext/lib/winfsp-x64.lib
Normal file
Binary file not shown.
BIN
opt/fsext/lib/winfsp-x86.lib
Normal file
BIN
opt/fsext/lib/winfsp-x86.lib
Normal file
Binary file not shown.
6
opt/fsext/lib/winfsp.impdef
Normal file
6
opt/fsext/lib/winfsp.impdef
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// tools\impdef.bat lib\winfsp.impdef lib\winfsp-x64.lib
|
||||||
|
// tools\impdef.bat lib\winfsp.impdef lib\winfsp-x86.lib
|
||||||
|
|
||||||
|
#define FSP_DDI_DEF(RetType, Name, ...) __declspec(dllexport) RetType NTAPI Name ( __VA_ARGS__ ) {}
|
||||||
|
#include <ntifs.h>
|
||||||
|
#include <winfsp/fsext.h>
|
336
src/dll/fs.c
336
src/dll/fs.c
@ -24,41 +24,19 @@
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
FspFileSystemDispatcherThreadCountMin = 2,
|
FspFileSystemDispatcherThreadCountMin = 2,
|
||||||
|
FspFileSystemDispatcherDefaultThreadCountMin = 4,
|
||||||
|
FspFileSystemDispatcherDefaultThreadCountMax = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
static FSP_FILE_SYSTEM_INTERFACE FspFileSystemNullInterface;
|
static FSP_FILE_SYSTEM_INTERFACE FspFileSystemNullInterface;
|
||||||
|
|
||||||
static INIT_ONCE FspFileSystemInitOnce = INIT_ONCE_STATIC_INIT;
|
static INIT_ONCE FspFileSystemInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
static DWORD FspFileSystemTlsKey = TLS_OUT_OF_INDEXES;
|
static DWORD FspFileSystemTlsKey = TLS_OUT_OF_INDEXES;
|
||||||
static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
|
|
||||||
PHANDLE LinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
|
|
||||||
static NTSTATUS (NTAPI *FspNtMakeTemporaryObject)(
|
|
||||||
HANDLE Handle);
|
|
||||||
static NTSTATUS (NTAPI *FspNtClose)(
|
|
||||||
HANDLE Handle);
|
|
||||||
|
|
||||||
static BOOL WINAPI FspFileSystemInitialize(
|
static BOOL WINAPI FspFileSystemInitialize(
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
{
|
{
|
||||||
HANDLE Handle;
|
|
||||||
|
|
||||||
FspFileSystemTlsKey = TlsAlloc();
|
FspFileSystemTlsKey = TlsAlloc();
|
||||||
|
|
||||||
Handle = GetModuleHandleW(L"ntdll.dll");
|
|
||||||
if (0 != Handle)
|
|
||||||
{
|
|
||||||
FspNtOpenSymbolicLinkObject = (PVOID)GetProcAddress(Handle, "NtOpenSymbolicLinkObject");
|
|
||||||
FspNtMakeTemporaryObject = (PVOID)GetProcAddress(Handle, "NtMakeTemporaryObject");
|
|
||||||
FspNtClose = (PVOID)GetProcAddress(Handle, "NtClose");
|
|
||||||
|
|
||||||
if (0 == FspNtOpenSymbolicLinkObject || 0 == FspNtMakeTemporaryObject || 0 == FspNtClose)
|
|
||||||
{
|
|
||||||
FspNtOpenSymbolicLinkObject = 0;
|
|
||||||
FspNtMakeTemporaryObject = 0;
|
|
||||||
FspNtClose = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +69,9 @@ FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
|
|||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (FspPathIsDrive(MountPoint))
|
if (FspPathIsMountmgrMountPoint(MountPoint))
|
||||||
|
Result = STATUS_SUCCESS; /* cannot check with the mount manager, assume success */
|
||||||
|
else if (FspPathIsDrive(MountPoint))
|
||||||
Result = QueryDosDeviceW(MountPoint, TargetPath, MAX_PATH) ?
|
Result = QueryDosDeviceW(MountPoint, TargetPath, MAX_PATH) ?
|
||||||
STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
|
STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
|
||||||
else
|
else
|
||||||
@ -194,205 +174,6 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
|
|||||||
MemFree(FileSystem);
|
MemFree(FileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFileSystemLauncherDefineDosDevice(
|
|
||||||
WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName)
|
|
||||||
{
|
|
||||||
if (2 != lstrlenW(MountPoint) ||
|
|
||||||
FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= lstrlenW(VolumeName))
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
WCHAR Argv0[4];
|
|
||||||
PWSTR Argv[2];
|
|
||||||
NTSTATUS Result;
|
|
||||||
ULONG ErrorCode;
|
|
||||||
|
|
||||||
Argv0[0] = Sign;
|
|
||||||
Argv0[1] = MountPoint[0];
|
|
||||||
Argv0[2] = MountPoint[1];
|
|
||||||
Argv0[3] = L'\0';
|
|
||||||
|
|
||||||
Argv[0] = Argv0;
|
|
||||||
Argv[1] = VolumeName;
|
|
||||||
|
|
||||||
Result = FspLaunchCallLauncherPipe(FspLaunchCmdDefineDosDevice, 2, Argv, 0, 0, 0, &ErrorCode);
|
|
||||||
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
|
|
||||||
PHANDLE PMountHandle)
|
|
||||||
{
|
|
||||||
NTSTATUS Result;
|
|
||||||
BOOLEAN IsLocalSystem, IsServiceContext;
|
|
||||||
|
|
||||||
*PMountHandle = 0;
|
|
||||||
|
|
||||||
Result = FspServiceContextCheck(0, &IsLocalSystem);
|
|
||||||
IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem;
|
|
||||||
if (IsServiceContext)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If the current process is in the service context but not LocalSystem,
|
|
||||||
* ask the launcher to DefineDosDevice for us. This is because the launcher
|
|
||||||
* runs in the LocalSystem context and can create global drives.
|
|
||||||
*
|
|
||||||
* In this case the launcher will also add DELETE access to the drive symlink
|
|
||||||
* for us, so that we can make it temporary below.
|
|
||||||
*/
|
|
||||||
Result = FspFileSystemLauncherDefineDosDevice(L'+', MountPoint, VolumeName);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != FspNtOpenSymbolicLinkObject)
|
|
||||||
{
|
|
||||||
WCHAR SymlinkBuf[6];
|
|
||||||
UNICODE_STRING Symlink;
|
|
||||||
OBJECT_ATTRIBUTES Obja;
|
|
||||||
|
|
||||||
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
|
||||||
SymlinkBuf[4] = MountPoint[0];
|
|
||||||
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
|
||||||
Symlink.Buffer = SymlinkBuf;
|
|
||||||
|
|
||||||
memset(&Obja, 0, sizeof Obja);
|
|
||||||
Obja.Length = sizeof Obja;
|
|
||||||
Obja.ObjectName = &Symlink;
|
|
||||||
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
|
||||||
|
|
||||||
Result = FspNtOpenSymbolicLinkObject(PMountHandle, DELETE, &Obja);
|
|
||||||
if (NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
Result = FspNtMakeTemporaryObject(*PMountHandle);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
FspNtClose(*PMountHandle);
|
|
||||||
*PMountHandle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HACK:
|
|
||||||
*
|
|
||||||
* Handles do not use the low 2 bits (unless they are console handles).
|
|
||||||
* Abuse this fact to remember that we are running in the service context.
|
|
||||||
*/
|
|
||||||
*PMountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)*PMountHandle | IsServiceContext);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR VolumeName,
|
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
|
||||||
{
|
|
||||||
NTSTATUS Result;
|
|
||||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
|
||||||
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
|
||||||
DWORD Backslashes, Bytes;
|
|
||||||
USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
|
|
||||||
PREPARSE_DATA_BUFFER ReparseData = 0;
|
|
||||||
PWSTR P, PathBuffer;
|
|
||||||
|
|
||||||
*PMountHandle = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Windows does not allow mount points (junctions) to point to network file systems.
|
|
||||||
*
|
|
||||||
* Count how many backslashes our VolumeName has. If it is 3 or more this is a network
|
|
||||||
* file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED.
|
|
||||||
*/
|
|
||||||
for (P = VolumeName, Backslashes = 0; *P; P++)
|
|
||||||
if (L'\\' == *P)
|
|
||||||
if (3 == ++Backslashes)
|
|
||||||
{
|
|
||||||
Result = STATUS_NETWORK_ACCESS_DENIED;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&SecurityAttributes, 0, sizeof SecurityAttributes);
|
|
||||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
|
||||||
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
|
||||||
|
|
||||||
MountHandle = CreateFileW(MountPoint,
|
|
||||||
FILE_WRITE_ATTRIBUTES,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
&SecurityAttributes,
|
|
||||||
CREATE_NEW,
|
|
||||||
FILE_ATTRIBUTE_DIRECTORY |
|
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
|
|
||||||
0);
|
|
||||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
VolumeNameLength = (USHORT)lstrlenW(VolumeName);
|
|
||||||
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
|
|
||||||
VolumeNameLength *= sizeof(WCHAR);
|
|
||||||
BackslashLength *= sizeof(WCHAR);
|
|
||||||
|
|
||||||
ReparseDataLength = (USHORT)(
|
|
||||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
|
|
||||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer)) +
|
|
||||||
2 * (VolumeNameLength + BackslashLength + sizeof(WCHAR));
|
|
||||||
ReparseData = MemAlloc(REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
|
|
||||||
if (0 == ReparseData)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
|
||||||
ReparseData->ReparseDataLength = ReparseDataLength;
|
|
||||||
ReparseData->Reserved = 0;
|
|
||||||
ReparseData->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
|
||||||
ReparseData->MountPointReparseBuffer.SubstituteNameLength =
|
|
||||||
VolumeNameLength + BackslashLength;
|
|
||||||
ReparseData->MountPointReparseBuffer.PrintNameOffset =
|
|
||||||
ReparseData->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
|
|
||||||
ReparseData->MountPointReparseBuffer.PrintNameLength =
|
|
||||||
VolumeNameLength + BackslashLength;
|
|
||||||
|
|
||||||
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer;
|
|
||||||
memcpy(PathBuffer, VolumeName, VolumeNameLength);
|
|
||||||
if (BackslashLength)
|
|
||||||
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
|
||||||
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
|
||||||
|
|
||||||
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer +
|
|
||||||
(ReparseData->MountPointReparseBuffer.PrintNameOffset) / sizeof(WCHAR);
|
|
||||||
memcpy(PathBuffer, VolumeName, VolumeNameLength);
|
|
||||||
if (BackslashLength)
|
|
||||||
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
|
||||||
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
|
||||||
|
|
||||||
if (!DeviceIoControl(MountHandle, FSCTL_SET_REPARSE_POINT,
|
|
||||||
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
|
||||||
0, 0,
|
|
||||||
&Bytes, 0))
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
*PMountHandle = MountHandle;
|
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
|
||||||
CloseHandle(MountHandle);
|
|
||||||
|
|
||||||
MemFree(ReparseData);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
||||||
{
|
{
|
||||||
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
|
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
|
||||||
@ -404,105 +185,55 @@ FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR
|
|||||||
if (0 != FileSystem->MountPoint)
|
if (0 != FileSystem->MountPoint)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
FSP_MOUNT_DESC Desc;
|
||||||
|
int Size;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
HANDLE MountHandle = 0;
|
|
||||||
|
memset(&Desc, 0, sizeof Desc);
|
||||||
|
Desc.VolumeHandle = FileSystem->VolumeHandle;
|
||||||
|
Desc.VolumeName = FileSystem->VolumeName;
|
||||||
|
Desc.Security = SecurityDescriptor;
|
||||||
|
|
||||||
if (0 == MountPoint)
|
if (0 == MountPoint)
|
||||||
{
|
MountPoint = L"*:";
|
||||||
DWORD Drives;
|
|
||||||
WCHAR Drive;
|
|
||||||
|
|
||||||
MountPoint = MemAlloc(3 * sizeof(WCHAR));
|
Size = (lstrlenW(MountPoint) + 1) * sizeof(WCHAR);
|
||||||
if (0 == MountPoint)
|
Desc.MountPoint = MemAlloc(Size);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
if (0 == Desc.MountPoint)
|
||||||
MountPoint[1] = L':';
|
|
||||||
MountPoint[2] = L'\0';
|
|
||||||
|
|
||||||
Drives = GetLogicalDrives();
|
|
||||||
if (0 != Drives)
|
|
||||||
{
|
{
|
||||||
for (Drive = 'Z'; 'D' <= Drive; Drive--)
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (0 == (Drives & (1 << (Drive - 'A'))))
|
|
||||||
{
|
|
||||||
MountPoint[0] = Drive;
|
|
||||||
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
|
|
||||||
&MountHandle);
|
|
||||||
if (NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
Result = STATUS_NO_SUCH_DEVICE;
|
memcpy(Desc.MountPoint, MountPoint, Size);
|
||||||
}
|
|
||||||
else
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PWSTR P;
|
|
||||||
ULONG L;
|
|
||||||
|
|
||||||
L = (ULONG)((lstrlenW(MountPoint) + 1) * sizeof(WCHAR));
|
Result = FspMountSet(&Desc);
|
||||||
|
|
||||||
P = MemAlloc(L);
|
|
||||||
if (0 == P)
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
memcpy(P, MountPoint, L);
|
|
||||||
MountPoint = P;
|
|
||||||
|
|
||||||
if (FspPathIsDrive(MountPoint))
|
|
||||||
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
|
|
||||||
&MountHandle);
|
|
||||||
else
|
|
||||||
Result = FspFileSystemSetMountPoint_Directory(MountPoint, FileSystem->VolumeName,
|
|
||||||
SecurityDescriptor, &MountHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FileSystem->MountPoint = MountPoint;
|
FileSystem->MountPoint = Desc.MountPoint;
|
||||||
FileSystem->MountHandle = MountHandle;
|
FileSystem->MountHandle = Desc.MountHandle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
MemFree(MountPoint);
|
MemFree(Desc.MountPoint);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspFileSystemRemoveMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, HANDLE MountHandle)
|
|
||||||
{
|
|
||||||
BOOLEAN IsServiceContext = 0 != ((DWORD)(UINT_PTR)MountHandle & 1);
|
|
||||||
MountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)MountHandle & ~1);
|
|
||||||
if (IsServiceContext)
|
|
||||||
/*
|
|
||||||
* If the current process is in the service context but not LocalSystem,
|
|
||||||
* ask the launcher to DefineDosDevice for us. This is because the launcher
|
|
||||||
* runs in the LocalSystem context and can remove global drives.
|
|
||||||
*/
|
|
||||||
FspFileSystemLauncherDefineDosDevice(L'-', MountPoint, VolumeName);
|
|
||||||
else
|
|
||||||
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
|
||||||
MountPoint, VolumeName);
|
|
||||||
|
|
||||||
if (0 != MountHandle)
|
|
||||||
FspNtClose(MountHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID FspFileSystemRemoveMountPoint_Directory(HANDLE MountHandle)
|
|
||||||
{
|
|
||||||
/* directory is marked DELETE_ON_CLOSE */
|
|
||||||
CloseHandle(MountHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
||||||
{
|
{
|
||||||
if (0 == FileSystem->MountPoint)
|
if (0 == FileSystem->MountPoint)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (FspPathIsDrive(FileSystem->MountPoint))
|
FSP_MOUNT_DESC Desc;
|
||||||
FspFileSystemRemoveMountPoint_Drive(FileSystem->MountPoint, FileSystem->VolumeName,
|
|
||||||
FileSystem->MountHandle);
|
memset(&Desc, 0, sizeof Desc);
|
||||||
else
|
Desc.VolumeHandle = FileSystem->VolumeHandle;
|
||||||
FspFileSystemRemoveMountPoint_Directory(FileSystem->MountHandle);
|
Desc.VolumeName = FileSystem->VolumeName;
|
||||||
|
Desc.MountPoint = FileSystem->MountPoint;
|
||||||
|
Desc.MountHandle = FileSystem->MountHandle;
|
||||||
|
|
||||||
|
FspMountRemove(&Desc);
|
||||||
|
|
||||||
MemFree(FileSystem->MountPoint);
|
MemFree(FileSystem->MountPoint);
|
||||||
FileSystem->MountPoint = 0;
|
FileSystem->MountPoint = 0;
|
||||||
@ -636,6 +367,11 @@ FSP_API NTSTATUS FspFileSystemStartDispatcher(FSP_FILE_SYSTEM *FileSystem, ULONG
|
|||||||
|
|
||||||
for (ThreadCount = 0; 0 != ProcessMask; ProcessMask >>= 1)
|
for (ThreadCount = 0; 0 != ProcessMask; ProcessMask >>= 1)
|
||||||
ThreadCount += ProcessMask & 1;
|
ThreadCount += ProcessMask & 1;
|
||||||
|
|
||||||
|
if (ThreadCount < FspFileSystemDispatcherDefaultThreadCountMin)
|
||||||
|
ThreadCount = FspFileSystemDispatcherDefaultThreadCountMin;
|
||||||
|
else if (ThreadCount > FspFileSystemDispatcherDefaultThreadCountMax)
|
||||||
|
ThreadCount = FspFileSystemDispatcherDefaultThreadCountMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ThreadCount < FspFileSystemDispatcherThreadCountMin)
|
if (ThreadCount < FspFileSystemDispatcherThreadCountMin)
|
||||||
|
@ -107,6 +107,20 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||||
|
BOOLEAN Persistent, GUID *UniqueId)
|
||||||
|
{
|
||||||
|
DWORD Bytes;
|
||||||
|
|
||||||
|
if (!DeviceIoControl(VolumeHandle,
|
||||||
|
FSP_FSCTL_MOUNTDEV,
|
||||||
|
&Persistent, sizeof Persistent, UniqueId, sizeof *UniqueId,
|
||||||
|
&Bytes, 0))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||||
|
@ -443,6 +443,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
0 != Request->Req.Create.Ea.Size ?
|
0 != Request->Req.Create.Ea.Size ?
|
||||||
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
||||||
Request->Req.Create.Ea.Size,
|
Request->Req.Create.Ea.Size,
|
||||||
|
Request->Req.Create.EaIsReparsePoint,
|
||||||
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
else
|
else
|
||||||
Result = FileSystem->Interface->Create(FileSystem,
|
Result = FileSystem->Interface->Create(FileSystem,
|
||||||
@ -590,6 +591,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
0 != Request->Req.Create.Ea.Size ?
|
0 != Request->Req.Create.Ea.Size ?
|
||||||
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
||||||
Request->Req.Create.Ea.Size,
|
Request->Req.Create.Ea.Size,
|
||||||
|
Request->Req.Create.EaIsReparsePoint,
|
||||||
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
else
|
else
|
||||||
Result = FileSystem->Interface->Create(FileSystem,
|
Result = FileSystem->Interface->Create(FileSystem,
|
||||||
@ -724,6 +726,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
|
|||||||
0 != Request->Req.Create.Ea.Size ?
|
0 != Request->Req.Create.Ea.Size ?
|
||||||
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
|
||||||
Request->Req.Create.Ea.Size,
|
Request->Req.Create.Ea.Size,
|
||||||
|
Request->Req.Create.EaIsReparsePoint,
|
||||||
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
|
||||||
else
|
else
|
||||||
Result = FileSystem->Interface->Create(FileSystem,
|
Result = FileSystem->Interface->Create(FileSystem,
|
||||||
|
@ -54,6 +54,10 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("umask=%o", umask, 0),
|
FSP_FUSE_CORE_OPT("umask=%o", umask, 0),
|
||||||
FSP_FUSE_CORE_OPT("create_umask=", set_create_umask, 1),
|
FSP_FUSE_CORE_OPT("create_umask=", set_create_umask, 1),
|
||||||
FSP_FUSE_CORE_OPT("create_umask=%o", create_umask, 0),
|
FSP_FUSE_CORE_OPT("create_umask=%o", create_umask, 0),
|
||||||
|
FSP_FUSE_CORE_OPT("create_file_umask=", set_create_file_umask, 1),
|
||||||
|
FSP_FUSE_CORE_OPT("create_file_umask=%o", create_file_umask, 0),
|
||||||
|
FSP_FUSE_CORE_OPT("create_dir_umask=", set_create_dir_umask, 1),
|
||||||
|
FSP_FUSE_CORE_OPT("create_dir_umask=%o", create_dir_umask, 0),
|
||||||
FSP_FUSE_CORE_OPT("uid=", set_uid, 1),
|
FSP_FUSE_CORE_OPT("uid=", set_uid, 1),
|
||||||
FSP_FUSE_CORE_OPT("uid=%d", uid, 0),
|
FSP_FUSE_CORE_OPT("uid=%d", uid, 0),
|
||||||
FSP_FUSE_CORE_OPT("gid=", set_gid, 1),
|
FSP_FUSE_CORE_OPT("gid=", set_gid, 1),
|
||||||
@ -71,6 +75,9 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("rellinks", rellinks, 1),
|
FSP_FUSE_CORE_OPT("rellinks", rellinks, 1),
|
||||||
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
||||||
|
|
||||||
|
FSP_FUSE_CORE_OPT("dothidden", dothidden, 1),
|
||||||
|
FSP_FUSE_CORE_OPT("nodothidden", dothidden, 0),
|
||||||
|
|
||||||
FUSE_OPT_KEY("fstypename=", 'F'),
|
FUSE_OPT_KEY("fstypename=", 'F'),
|
||||||
FUSE_OPT_KEY("volname=", 'v'),
|
FUSE_OPT_KEY("volname=", 'v'),
|
||||||
|
|
||||||
@ -95,6 +102,17 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
||||||
FUSE_OPT_KEY("FileSystemName=", 'F'),
|
FUSE_OPT_KEY("FileSystemName=", 'F'),
|
||||||
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
||||||
|
FUSE_OPT_KEY("ExactFileSystemName=", 'E'),
|
||||||
|
FUSE_OPT_KEY("--ExactFileSystemName=", 'E'),
|
||||||
|
|
||||||
|
FSP_FUSE_CORE_OPT("UserName=", set_uid, 1),
|
||||||
|
FUSE_OPT_KEY("UserName=", 'u'),
|
||||||
|
FSP_FUSE_CORE_OPT("--UserName=", set_uid, 1),
|
||||||
|
FUSE_OPT_KEY("--UserName=", 'u'),
|
||||||
|
FSP_FUSE_CORE_OPT("GroupName=", set_gid, 1),
|
||||||
|
FUSE_OPT_KEY("GroupName=", 'g'),
|
||||||
|
FSP_FUSE_CORE_OPT("--GroupName=", set_gid, 1),
|
||||||
|
FUSE_OPT_KEY("--GroupName=", 'g'),
|
||||||
|
|
||||||
FUSE_OPT_END,
|
FUSE_OPT_END,
|
||||||
};
|
};
|
||||||
@ -226,6 +244,43 @@ 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_username_to_uid(const char *username, int *puid)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
|
} SidBuf;
|
||||||
|
char Name[256], Domn[256];
|
||||||
|
DWORD SidSize, NameSize, DomnSize;
|
||||||
|
SID_NAME_USE Use;
|
||||||
|
UINT32 Uid;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*puid = 0;
|
||||||
|
|
||||||
|
NameSize = lstrlenA(username) + 1;
|
||||||
|
if (sizeof Name / sizeof Name[0] < NameSize)
|
||||||
|
return -1;
|
||||||
|
memcpy(Name, username, NameSize);
|
||||||
|
for (PSTR P = Name, EndP = P + NameSize; EndP > P; P++)
|
||||||
|
if ('+' == *P)
|
||||||
|
*P = '\\';
|
||||||
|
|
||||||
|
SidSize = sizeof SidBuf;
|
||||||
|
DomnSize = sizeof Domn / sizeof Domn[0];
|
||||||
|
if (!LookupAccountNameA(0, Name, &SidBuf, &SidSize, Domn, &DomnSize, &Use))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Result = FspPosixMapSidToUid(&SidBuf, &Uid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*puid = Uid;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@ -241,9 +296,12 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
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 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_dir_umask=MASK for directories only\n"
|
||||||
" -o uid=N set file owner (-1 for mounting user id)\n"
|
" -o uid=N set file owner (-1 for mounting user id)\n"
|
||||||
" -o gid=N set file group (-1 for mounting user group)\n"
|
" -o gid=N set file group (-1 for mounting user group)\n"
|
||||||
" -o rellinks interpret absolute symlinks as volume relative\n"
|
" -o rellinks interpret absolute symlinks as volume relative\n"
|
||||||
|
" -o dothidden dot files have the Windows hidden file attrib\n"
|
||||||
" -o volname=NAME set volume label\n"
|
" -o volname=NAME set volume label\n"
|
||||||
" -o VolumePrefix=UNC set UNC prefix (/Server/Share)\n"
|
" -o VolumePrefix=UNC set UNC prefix (/Server/Share)\n"
|
||||||
" --VolumePrefix=UNC set UNC prefix (\\Server\\Share)\n"
|
" --VolumePrefix=UNC set UNC prefix (\\Server\\Share)\n"
|
||||||
@ -311,6 +369,40 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
|
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
|
||||||
return 0;
|
return 0;
|
||||||
|
case 'E':
|
||||||
|
if ('E' == arg[0])
|
||||||
|
arg += sizeof "ExactFileSystemName=" - 1;
|
||||||
|
else if ('E' == arg[2])
|
||||||
|
arg += sizeof "--ExactFileSystemName=" - 1;
|
||||||
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||||
|
opt_data->VolumeParams.FileSystemName,
|
||||||
|
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR)))
|
||||||
|
return -1;
|
||||||
|
opt_data->VolumeParams.FileSystemName
|
||||||
|
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
return 0;
|
||||||
|
case 'u':
|
||||||
|
if ('U' == arg[0])
|
||||||
|
arg += sizeof "UserName=" - 1;
|
||||||
|
else if ('U' == arg[2])
|
||||||
|
arg += sizeof "--UserName=" - 1;
|
||||||
|
if (-1 == fsp_fuse_username_to_uid(arg, &opt_data->uid))
|
||||||
|
{
|
||||||
|
opt_data->username_to_uid_result = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case 'g':
|
||||||
|
if ('G' == arg[0])
|
||||||
|
arg += sizeof "GroupName=" - 1;
|
||||||
|
else if ('G' == arg[2])
|
||||||
|
arg += sizeof "--GroupName=" - 1;
|
||||||
|
if (-1 == fsp_fuse_username_to_uid(arg, &opt_data->gid))
|
||||||
|
{
|
||||||
|
opt_data->username_to_uid_result = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
case 'v':
|
case 'v':
|
||||||
arg += sizeof "volname=" - 1;
|
arg += sizeof "volname=" - 1;
|
||||||
opt_data->VolumeLabelLength = (UINT16)(sizeof(WCHAR) *
|
opt_data->VolumeLabelLength = (UINT16)(sizeof(WCHAR) *
|
||||||
@ -355,7 +447,14 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
||||||
|
|
||||||
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)
|
||||||
|
{
|
||||||
|
ErrorMessage = L": invalid user or group name.";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (opt_data.help)
|
if (opt_data.help)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -422,9 +521,12 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
f->env = env;
|
f->env = env;
|
||||||
f->set_umask = opt_data.set_umask; f->umask = opt_data.umask;
|
f->set_umask = opt_data.set_umask; f->umask = opt_data.umask;
|
||||||
f->set_create_umask = opt_data.set_create_umask; f->create_umask = opt_data.create_umask;
|
f->set_create_umask = opt_data.set_create_umask; f->create_umask = opt_data.create_umask;
|
||||||
|
f->set_create_file_umask = opt_data.set_create_file_umask; f->create_file_umask = opt_data.create_file_umask;
|
||||||
|
f->set_create_dir_umask = opt_data.set_create_dir_umask; f->create_dir_umask = opt_data.create_dir_umask;
|
||||||
f->set_uid = opt_data.set_uid; f->uid = opt_data.uid;
|
f->set_uid = opt_data.set_uid; f->uid = opt_data.uid;
|
||||||
f->set_gid = opt_data.set_gid; f->gid = opt_data.gid;
|
f->set_gid = opt_data.set_gid; f->gid = opt_data.gid;
|
||||||
f->rellinks = opt_data.rellinks;
|
f->rellinks = opt_data.rellinks;
|
||||||
|
f->dothidden = opt_data.dothidden;
|
||||||
f->ThreadCount = opt_data.ThreadCount;
|
f->ThreadCount = opt_data.ThreadCount;
|
||||||
memcpy(&f->ops, ops, opsize);
|
memcpy(&f->ops, ops, opsize);
|
||||||
f->data = data;
|
f->data = data;
|
||||||
|
@ -354,6 +354,7 @@ static inline UINT32 fsp_fuse_intf_MapFlagsToFileAttributes(uint32_t flags)
|
|||||||
return FileAttributes;
|
return FileAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FUSE_FILE_INFO(IsDirectory, fi) ((IsDirectory) ? 0 : (fi))
|
||||||
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
||||||
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0, PUid, PGid, PMode, 0, FileInfo)
|
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0, PUid, PGid, PMode, 0, FileInfo)
|
||||||
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -429,6 +430,15 @@ static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
if (StatEx)
|
if (StatEx)
|
||||||
FileInfo->FileAttributes |= fsp_fuse_intf_MapFlagsToFileAttributes(stbuf.st_flags);
|
FileInfo->FileAttributes |= fsp_fuse_intf_MapFlagsToFileAttributes(stbuf.st_flags);
|
||||||
|
if (f->dothidden)
|
||||||
|
{
|
||||||
|
const char *basename = PosixPath;
|
||||||
|
for (const char *p = PosixPath; '\0' != *p; p++)
|
||||||
|
if ('/' == *p)
|
||||||
|
basename = p + 1;
|
||||||
|
if ('.' == basename[0])
|
||||||
|
FileInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||||
|
}
|
||||||
FileInfo->FileSize = stbuf.st_size;
|
FileInfo->FileSize = stbuf.st_size;
|
||||||
FileInfo->AllocationSize =
|
FileInfo->AllocationSize =
|
||||||
(FileInfo->FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
|
(FileInfo->FileSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
|
||||||
@ -743,7 +753,7 @@ exit:
|
|||||||
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
PVOID ExtraBuffer, ULONG ExtraLength, BOOLEAN ExtraBufferIsReparsePoint,
|
||||||
PVOID *PFileDesc, FSP_FSCTL_FILE_INFO *FileInfo)
|
PVOID *PFileDesc, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
@ -757,7 +767,9 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
int err;
|
int err;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (0 != Ea)
|
if (0 != ExtraBuffer)
|
||||||
|
{
|
||||||
|
if (!ExtraBufferIsReparsePoint)
|
||||||
{
|
{
|
||||||
if (0 == f->ops.listxattr || 0 == f->ops.getxattr ||
|
if (0 == f->ops.listxattr || 0 == f->ops.getxattr ||
|
||||||
0 == f->ops.setxattr || 0 == f->ops.removexattr)
|
0 == f->ops.setxattr || 0 == f->ops.removexattr)
|
||||||
@ -766,6 +778,13 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* !!!: revisit */
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
filedesc = MemAlloc(sizeof *filedesc);
|
filedesc = MemAlloc(sizeof *filedesc);
|
||||||
if (0 == filedesc)
|
if (0 == filedesc)
|
||||||
@ -785,8 +804,22 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
Mode &= ~context->umask;
|
Mode &= ~context->umask;
|
||||||
|
if (CreateOptions & FILE_DIRECTORY_FILE)
|
||||||
|
{
|
||||||
|
if (f->set_create_dir_umask)
|
||||||
|
Mode = 0777 & ~f->create_dir_umask;
|
||||||
|
else
|
||||||
if (f->set_create_umask)
|
if (f->set_create_umask)
|
||||||
Mode = 0777 & ~f->create_umask;
|
Mode = 0777 & ~f->create_umask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (f->set_create_file_umask)
|
||||||
|
Mode = 0777 & ~f->create_file_umask;
|
||||||
|
else
|
||||||
|
if (f->set_create_umask)
|
||||||
|
Mode = 0777 & ~f->create_umask;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&fi, 0, sizeof fi);
|
memset(&fi, 0, sizeof fi);
|
||||||
if ('C' == f->env->environment) /* Cygwin */
|
if ('C' == f->env->environment) /* Cygwin */
|
||||||
@ -866,13 +899,22 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != Ea)
|
if (0 != ExtraBuffer)
|
||||||
|
{
|
||||||
|
if (!ExtraBufferIsReparsePoint)
|
||||||
{
|
{
|
||||||
Result = FspFileSystemEnumerateEa(FileSystem,
|
Result = FspFileSystemEnumerateEa(FileSystem,
|
||||||
fsp_fuse_intf_SetEaEntry, contexthdr->PosixPath, Ea, EaLength);
|
fsp_fuse_intf_SetEaEntry, contexthdr->PosixPath, ExtraBuffer, ExtraLength);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* !!!: revisit: WslFeatures, GetFileInfoFunnel, GetReparsePointEx, SetReparsePoint */
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
||||||
* NOTE: Originally WinFsp dit not support disabling the cache manager
|
* NOTE: Originally WinFsp dit not support disabling the cache manager
|
||||||
@ -881,7 +923,8 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
* Ignore fuse_file_info::nonseekable.
|
* Ignore fuse_file_info::nonseekable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath, &fi,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath,
|
||||||
|
FUSE_FILE_INFO(CreateOptions & FILE_DIRECTORY_FILE, &fi),
|
||||||
&Uid, &Gid, &Mode, &FileInfoBuf);
|
&Uid, &Gid, &Mode, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -983,6 +1026,20 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Some Windows applications (notably Go programs) specify FILE_APPEND_DATA without
|
||||||
|
* FILE_WRITE_DATA when opening files for appending. This caused the WinFsp-FUSE layer
|
||||||
|
* to erroneously pass O_RDONLY to the FUSE file system in such cases. We add a test
|
||||||
|
* for FILE_APPEND_DATA to ensure that either O_WRONLY or O_RDWR is specified and that
|
||||||
|
* the O_APPEND flag is set.
|
||||||
|
*/
|
||||||
|
if (GrantedAccess & FILE_APPEND_DATA)
|
||||||
|
{
|
||||||
|
if (fi.flags == 0)
|
||||||
|
fi.flags = 1; /* need O_WRONLY as a bare minimum in order to append */
|
||||||
|
fi.flags |= 8/*O_APPEND*/;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != f->ops.open)
|
if (0 != f->ops.open)
|
||||||
{
|
{
|
||||||
err = f->ops.open(contexthdr->PosixPath, &fi);
|
err = f->ops.open(contexthdr->PosixPath, &fi);
|
||||||
@ -1096,7 +1153,8 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, FileInfo);
|
&Uid, &Gid, &Mode, FileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1227,7 +1285,8 @@ static NTSTATUS fsp_fuse_intf_Write(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, &FileInfoBuf);
|
&Uid, &Gid, &Mode, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -1307,7 +1366,8 @@ static NTSTATUS fsp_fuse_intf_Flush(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, &FileInfoBuf);
|
&Uid, &Gid, &Mode, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -1330,7 +1390,8 @@ static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, FileInfo);
|
&Uid, &Gid, &Mode, FileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1368,7 +1429,8 @@ static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
if (0 == LastAccessTime || 0 == LastWriteTime)
|
if (0 == LastAccessTime || 0 == LastWriteTime)
|
||||||
{
|
{
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, &FileInfoBuf);
|
&Uid, &Gid, &Mode, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -1415,7 +1477,8 @@ static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, FileInfo);
|
&Uid, &Gid, &Mode, FileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1442,7 +1505,8 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, &FileInfoBuf);
|
&Uid, &Gid, &Mode, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -1589,7 +1653,8 @@ static NTSTATUS fsp_fuse_intf_GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
return fsp_fuse_intf_GetSecurityEx(FileSystem, filedesc->PosixPath, &fi,
|
return fsp_fuse_intf_GetSecurityEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&FileAttributes, SecurityDescriptorBuf, PSecurityDescriptorSize);
|
&FileAttributes, SecurityDescriptorBuf, PSecurityDescriptorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1613,8 +1678,9 @@ static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi, &Uid, &Gid, &Mode,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
&FileInfo);
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
|
&Uid, &Gid, &Mode, &FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -1712,7 +1778,7 @@ int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
|||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
NTSTATUS Result0;
|
NTSTATUS Result0;
|
||||||
|
|
||||||
Result0 = fsp_fuse_intf_GetFileInfoFunnel(dh->FileSystem, 0, 0, stbuf,
|
Result0 = fsp_fuse_intf_GetFileInfoFunnel(dh->FileSystem, name, 0, stbuf,
|
||||||
&Uid, &Gid, &Mode, 0, &DirInfo->FileInfo);
|
&Uid, &Gid, &Mode, 0, &DirInfo->FileInfo);
|
||||||
if (NT_SUCCESS(Result0))
|
if (NT_SUCCESS(Result0))
|
||||||
DirInfo->Padding[0] = 1; /* HACK: remember that the FileInfo is valid */
|
DirInfo->Padding[0] = 1; /* HACK: remember that the FileInfo is valid */
|
||||||
@ -1972,7 +2038,9 @@ static NTSTATUS fsp_fuse_intf_GetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
return fsp_fuse_intf_GetReparsePointEx(FileSystem, filedesc->PosixPath, &fi, Buffer, PSize);
|
return fsp_fuse_intf_GetReparsePointEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
|
Buffer, PSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -2043,7 +2111,8 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, &FileInfo);
|
&Uid, &Gid, &Mode, &FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -2316,7 +2385,8 @@ static NTSTATUS fsp_fuse_intf_SetEa(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath,
|
||||||
|
FUSE_FILE_INFO(filedesc->IsDirectory, &fi),
|
||||||
&Uid, &Gid, &Mode, FileInfo);
|
&Uid, &Gid, &Mode, FileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,11 +216,13 @@ static int fsp_fuse_opt_call_proc(struct fsp_fuse_env *env,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (0 != fullarg)
|
if (0 != fullarg)
|
||||||
env->memfree(fullarg);
|
env->memfree(fullarg);
|
||||||
|
|
||||||
return 0;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
|
static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
|
||||||
|
@ -50,9 +50,12 @@ struct fuse
|
|||||||
struct fsp_fuse_env *env;
|
struct fsp_fuse_env *env;
|
||||||
int set_umask, umask;
|
int set_umask, umask;
|
||||||
int set_create_umask, create_umask;
|
int set_create_umask, create_umask;
|
||||||
|
int set_create_file_umask, create_file_umask;
|
||||||
|
int set_create_dir_umask, create_dir_umask;
|
||||||
int set_uid, uid;
|
int set_uid, uid;
|
||||||
int set_gid, gid;
|
int set_gid, gid;
|
||||||
int rellinks;
|
int rellinks;
|
||||||
|
int dothidden;
|
||||||
unsigned ThreadCount;
|
unsigned ThreadCount;
|
||||||
struct fuse_operations ops;
|
struct fuse_operations ops;
|
||||||
void *data;
|
void *data;
|
||||||
@ -137,10 +140,13 @@ struct fsp_fuse_core_opt_data
|
|||||||
HANDLE DebugLogHandle;
|
HANDLE DebugLogHandle;
|
||||||
int set_umask, umask,
|
int set_umask, umask,
|
||||||
set_create_umask, create_umask,
|
set_create_umask, create_umask,
|
||||||
set_uid, uid,
|
set_create_file_umask, create_file_umask,
|
||||||
|
set_create_dir_umask, create_dir_umask,
|
||||||
|
set_uid, uid, username_to_uid_result,
|
||||||
set_gid, gid,
|
set_gid, gid,
|
||||||
set_attr_timeout, attr_timeout,
|
set_attr_timeout, attr_timeout,
|
||||||
rellinks;
|
rellinks,
|
||||||
|
dothidden;
|
||||||
int set_FileInfoTimeout,
|
int set_FileInfoTimeout,
|
||||||
set_DirInfoTimeout,
|
set_DirInfoTimeout,
|
||||||
set_EaTimeout,
|
set_EaTimeout,
|
||||||
|
@ -91,6 +91,21 @@ static inline BOOLEAN FspPathIsDrive(PWSTR FileName)
|
|||||||
) &&
|
) &&
|
||||||
L':' == FileName[1] && L'\0' == FileName[2];
|
L':' == FileName[1] && L'\0' == FileName[2];
|
||||||
}
|
}
|
||||||
|
static inline BOOLEAN FspPathIsMountmgrMountPoint(PWSTR FileName)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
L'\\' == FileName[0] &&
|
||||||
|
L'\\' == FileName[1] &&
|
||||||
|
(L'?' == FileName[2] || L'.' == FileName[2]) &&
|
||||||
|
L'\\' == FileName[3]
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
(L'A' <= FileName[4] && FileName[4] <= L'Z') ||
|
||||||
|
(L'a' <= FileName[4] && FileName[4] <= L'z')
|
||||||
|
) &&
|
||||||
|
L':' == FileName[5];
|
||||||
|
}
|
||||||
|
|
||||||
#define FSP_NEXT_EA(Ea, EaEnd) \
|
#define FSP_NEXT_EA(Ea, EaEnd) \
|
||||||
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
||||||
|
612
src/dll/mount.c
Normal file
612
src/dll/mount.c
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/mount.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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>
|
||||||
|
|
||||||
|
static INIT_ONCE FspMountInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
|
static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
|
||||||
|
PHANDLE LinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
|
||||||
|
static NTSTATUS (NTAPI *FspNtMakeTemporaryObject)(
|
||||||
|
HANDLE Handle);
|
||||||
|
static NTSTATUS (NTAPI *FspNtClose)(
|
||||||
|
HANDLE Handle);
|
||||||
|
|
||||||
|
static BOOL WINAPI FspMountInitialize(
|
||||||
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
|
{
|
||||||
|
HANDLE Handle;
|
||||||
|
|
||||||
|
Handle = GetModuleHandleW(L"ntdll.dll");
|
||||||
|
if (0 != Handle)
|
||||||
|
{
|
||||||
|
FspNtOpenSymbolicLinkObject = (PVOID)GetProcAddress(Handle, "NtOpenSymbolicLinkObject");
|
||||||
|
FspNtMakeTemporaryObject = (PVOID)GetProcAddress(Handle, "NtMakeTemporaryObject");
|
||||||
|
FspNtClose = (PVOID)GetProcAddress(Handle, "NtClose");
|
||||||
|
|
||||||
|
if (0 == FspNtOpenSymbolicLinkObject || 0 == FspNtMakeTemporaryObject || 0 == FspNtClose)
|
||||||
|
{
|
||||||
|
FspNtOpenSymbolicLinkObject = 0;
|
||||||
|
FspNtMakeTemporaryObject = 0;
|
||||||
|
FspNtClose = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||||
|
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
||||||
|
{
|
||||||
|
HANDLE MgrHandle = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD Bytes = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == POutputBufferLength)
|
||||||
|
POutputBufferLength = &Bytes;
|
||||||
|
|
||||||
|
MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == MgrHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DeviceIoControl(MgrHandle,
|
||||||
|
IoControlCode,
|
||||||
|
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
|
||||||
|
&Bytes, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*POutputBufferLength = Bytes;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != MgrHandle)
|
||||||
|
CloseHandle(MgrHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountSet_Mountmgr(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
|
||||||
|
{
|
||||||
|
/* only support drives for now! (format: \\.\X:) */
|
||||||
|
if (L'\0' != MountPoint[6])
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/* mountmgr.h */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
Disabled = 0,
|
||||||
|
Enabled,
|
||||||
|
} MOUNTMGR_AUTO_MOUNT_STATE;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
|
||||||
|
} MOUNTMGR_QUERY_AUTO_MOUNT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MOUNTMGR_AUTO_MOUNT_STATE NewState;
|
||||||
|
} MOUNTMGR_SET_AUTO_MOUNT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT DeviceNameLength;
|
||||||
|
WCHAR DeviceName[1];
|
||||||
|
} MOUNTMGR_TARGET_NAME;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT SymbolicLinkNameOffset;
|
||||||
|
USHORT SymbolicLinkNameLength;
|
||||||
|
USHORT DeviceNameOffset;
|
||||||
|
USHORT DeviceNameLength;
|
||||||
|
} MOUNTMGR_CREATE_POINT_INPUT;
|
||||||
|
|
||||||
|
GUID UniqueId;
|
||||||
|
MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
|
||||||
|
MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
|
||||||
|
MOUNTMGR_TARGET_NAME *TargetName = 0;
|
||||||
|
MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
|
||||||
|
ULONG VolumeNameSize, QueryAutoMountSize, TargetNameSize, CreatePointInputSize;
|
||||||
|
HKEY RegKey;
|
||||||
|
LONG RegResult;
|
||||||
|
WCHAR RegValueName[MAX_PATH];
|
||||||
|
UINT8 RegValueData[sizeof UniqueId];
|
||||||
|
DWORD RegValueNameSize, RegValueDataSize;
|
||||||
|
DWORD RegType;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/* transform our volume into one that can be used by the MountManager */
|
||||||
|
Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, &UniqueId);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
|
||||||
|
QueryAutoMountSize = sizeof QueryAutoMount;
|
||||||
|
TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeNameSize;
|
||||||
|
CreatePointInputSize = sizeof *CreatePointInput +
|
||||||
|
sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeNameSize;
|
||||||
|
|
||||||
|
TargetName = MemAlloc(TargetNameSize);
|
||||||
|
if (0 == TargetName)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatePointInput = MemAlloc(CreatePointInputSize);
|
||||||
|
if (0 == CreatePointInput)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the current AutoMount value and save it */
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
|
||||||
|
0, 0, &QueryAutoMount, &QueryAutoMountSize);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* disable AutoMount */
|
||||||
|
SetAutoMount.NewState = 0;
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||||
|
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* announce volume arrival */
|
||||||
|
memset(TargetName, 0, sizeof *TargetName);
|
||||||
|
TargetName->DeviceNameLength = (USHORT)VolumeNameSize;
|
||||||
|
memcpy(TargetName->DeviceName,
|
||||||
|
VolumeName, TargetName->DeviceNameLength);
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
|
||||||
|
TargetName, TargetNameSize, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* reset the AutoMount value to the saved one */
|
||||||
|
SetAutoMount.NewState = QueryAutoMount.CurrentState;
|
||||||
|
FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||||
|
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||||
|
#if 0
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* create mount point */
|
||||||
|
memset(CreatePointInput, 0, sizeof *CreatePointInput);
|
||||||
|
CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
|
||||||
|
CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||||
|
CreatePointInput->DeviceNameOffset =
|
||||||
|
CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
|
||||||
|
CreatePointInput->DeviceNameLength = (USHORT)VolumeNameSize;
|
||||||
|
memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
|
||||||
|
L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
|
||||||
|
((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
|
||||||
|
MountPoint[4] & ~0x20;
|
||||||
|
/* convert to uppercase */
|
||||||
|
memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
|
||||||
|
VolumeName, CreatePointInput->DeviceNameLength);
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_CREATE_POINT */
|
||||||
|
CreatePointInput, CreatePointInputSize, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* HACK: delete the MountManager registry entries */
|
||||||
|
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
|
||||||
|
0, KEY_READ | KEY_WRITE, &RegKey);
|
||||||
|
if (ERROR_SUCCESS == RegResult)
|
||||||
|
{
|
||||||
|
for (DWORD I = 0;; I++)
|
||||||
|
{
|
||||||
|
RegValueNameSize = MAX_PATH;
|
||||||
|
RegValueDataSize = sizeof RegValueData;
|
||||||
|
RegResult = RegEnumValueW(RegKey,
|
||||||
|
I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
|
||||||
|
if (ERROR_NO_MORE_ITEMS == RegResult)
|
||||||
|
break;
|
||||||
|
else if (ERROR_SUCCESS != RegResult)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (REG_BINARY == RegType &&
|
||||||
|
sizeof RegValueData == RegValueDataSize &&
|
||||||
|
InlineIsEqualGUID((GUID *)&RegValueData, &UniqueId))
|
||||||
|
{
|
||||||
|
RegResult = RegDeleteValueW(RegKey, RegValueName);
|
||||||
|
if (ERROR_SUCCESS == RegResult)
|
||||||
|
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||||
|
I = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(CreatePointInput);
|
||||||
|
MemFree(TargetName);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountRemove_Mountmgr(PWSTR MountPoint)
|
||||||
|
{
|
||||||
|
/* mountmgr.h */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG SymbolicLinkNameOffset;
|
||||||
|
USHORT SymbolicLinkNameLength;
|
||||||
|
USHORT Reserved1;
|
||||||
|
ULONG UniqueIdOffset;
|
||||||
|
USHORT UniqueIdLength;
|
||||||
|
USHORT Reserved2;
|
||||||
|
ULONG DeviceNameOffset;
|
||||||
|
USHORT DeviceNameLength;
|
||||||
|
USHORT Reserved3;
|
||||||
|
} MOUNTMGR_MOUNT_POINT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG Size;
|
||||||
|
ULONG NumberOfMountPoints;
|
||||||
|
MOUNTMGR_MOUNT_POINT MountPoints[1];
|
||||||
|
} MOUNTMGR_MOUNT_POINTS;
|
||||||
|
|
||||||
|
MOUNTMGR_MOUNT_POINT *Input = 0;
|
||||||
|
MOUNTMGR_MOUNT_POINTS *Output = 0;
|
||||||
|
ULONG InputSize, OutputSize;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||||
|
OutputSize = 4096;
|
||||||
|
|
||||||
|
Input = MemAlloc(InputSize);
|
||||||
|
if (0 == Input)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output = MemAlloc(OutputSize);
|
||||||
|
if (0 == Output)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(Input, 0, sizeof *Input);
|
||||||
|
Input->SymbolicLinkNameOffset = sizeof *Input;
|
||||||
|
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||||
|
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
|
||||||
|
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
|
||||||
|
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] = MountPoint[4] & ~0x20;
|
||||||
|
/* convert to uppercase */
|
||||||
|
Result = FspMountmgrControl(
|
||||||
|
CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||||
|
/* IOCTL_MOUNTMGR_DELETE_POINTS */
|
||||||
|
Input, InputSize, Output, &OutputSize);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(Output);
|
||||||
|
MemFree(Input);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspLauncherDefineDosDevice(
|
||||||
|
WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName)
|
||||||
|
{
|
||||||
|
if (2 != lstrlenW(MountPoint) ||
|
||||||
|
FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= lstrlenW(VolumeName))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
WCHAR Argv0[4];
|
||||||
|
PWSTR Argv[2];
|
||||||
|
NTSTATUS Result;
|
||||||
|
ULONG ErrorCode;
|
||||||
|
|
||||||
|
Argv0[0] = Sign;
|
||||||
|
Argv0[1] = MountPoint[0];
|
||||||
|
Argv0[2] = MountPoint[1];
|
||||||
|
Argv0[3] = L'\0';
|
||||||
|
|
||||||
|
Argv[0] = Argv0;
|
||||||
|
Argv[1] = VolumeName;
|
||||||
|
|
||||||
|
Result = FspLaunchCallLauncherPipe(FspLaunchCmdDefineDosDevice, 2, Argv, 0, 0, 0, &ErrorCode);
|
||||||
|
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PMountHandle)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
BOOLEAN IsLocalSystem, IsServiceContext;
|
||||||
|
|
||||||
|
*PMountHandle = 0;
|
||||||
|
|
||||||
|
Result = FspServiceContextCheck(0, &IsLocalSystem);
|
||||||
|
IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem;
|
||||||
|
if (IsServiceContext)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If the current process is in the service context but not LocalSystem,
|
||||||
|
* ask the launcher to DefineDosDevice for us. This is because the launcher
|
||||||
|
* runs in the LocalSystem context and can create global drives.
|
||||||
|
*
|
||||||
|
* In this case the launcher will also add DELETE access to the drive symlink
|
||||||
|
* for us, so that we can make it temporary below.
|
||||||
|
*/
|
||||||
|
Result = FspLauncherDefineDosDevice(L'+', MountPoint, VolumeName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FspNtOpenSymbolicLinkObject)
|
||||||
|
{
|
||||||
|
WCHAR SymlinkBuf[6];
|
||||||
|
UNICODE_STRING Symlink;
|
||||||
|
OBJECT_ATTRIBUTES Obja;
|
||||||
|
|
||||||
|
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
||||||
|
SymlinkBuf[4] = MountPoint[0];
|
||||||
|
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
||||||
|
Symlink.Buffer = SymlinkBuf;
|
||||||
|
|
||||||
|
memset(&Obja, 0, sizeof Obja);
|
||||||
|
Obja.Length = sizeof Obja;
|
||||||
|
Obja.ObjectName = &Symlink;
|
||||||
|
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
|
||||||
|
Result = FspNtOpenSymbolicLinkObject(PMountHandle, DELETE, &Obja);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = FspNtMakeTemporaryObject(*PMountHandle);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspNtClose(*PMountHandle);
|
||||||
|
*PMountHandle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HACK:
|
||||||
|
*
|
||||||
|
* Handles do not use the low 2 bits (unless they are console handles).
|
||||||
|
* Abuse this fact to remember that we are running in the service context.
|
||||||
|
*/
|
||||||
|
*PMountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)*PMountHandle | IsServiceContext);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountRemove_Drive(PWSTR VolumeName, PWSTR MountPoint, HANDLE MountHandle)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
BOOLEAN IsServiceContext;
|
||||||
|
|
||||||
|
IsServiceContext = 0 != ((DWORD)(UINT_PTR)MountHandle & 1);
|
||||||
|
MountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)MountHandle & ~1);
|
||||||
|
if (IsServiceContext)
|
||||||
|
/*
|
||||||
|
* If the current process is in the service context but not LocalSystem,
|
||||||
|
* ask the launcher to DefineDosDevice for us. This is because the launcher
|
||||||
|
* runs in the LocalSystem context and can remove global drives.
|
||||||
|
*/
|
||||||
|
Result = FspLauncherDefineDosDevice(L'-', MountPoint, VolumeName);
|
||||||
|
else
|
||||||
|
Result = DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||||
|
MountPoint, VolumeName) ? STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
if (0 != MountHandle)
|
||||||
|
FspNtClose(MountHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||||
|
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD Backslashes, Bytes;
|
||||||
|
USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
|
||||||
|
PREPARSE_DATA_BUFFER ReparseData = 0;
|
||||||
|
PWSTR P, PathBuffer;
|
||||||
|
|
||||||
|
*PMountHandle = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Windows does not allow mount points (junctions) to point to network file systems.
|
||||||
|
*
|
||||||
|
* Count how many backslashes our VolumeName has. If it is 3 or more this is a network
|
||||||
|
* file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED.
|
||||||
|
*/
|
||||||
|
for (P = VolumeName, Backslashes = 0; *P; P++)
|
||||||
|
if (L'\\' == *P)
|
||||||
|
if (3 == ++Backslashes)
|
||||||
|
{
|
||||||
|
Result = STATUS_NETWORK_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&SecurityAttributes, 0, sizeof SecurityAttributes);
|
||||||
|
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||||
|
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||||
|
|
||||||
|
MountHandle = CreateFileW(MountPoint,
|
||||||
|
FILE_WRITE_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
&SecurityAttributes,
|
||||||
|
CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY |
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeNameLength = (USHORT)lstrlenW(VolumeName);
|
||||||
|
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
|
||||||
|
VolumeNameLength *= sizeof(WCHAR);
|
||||||
|
BackslashLength *= sizeof(WCHAR);
|
||||||
|
|
||||||
|
ReparseDataLength = (USHORT)(
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer)) +
|
||||||
|
2 * (VolumeNameLength + BackslashLength + sizeof(WCHAR));
|
||||||
|
ReparseData = MemAlloc(REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
|
||||||
|
if (0 == ReparseData)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||||
|
ReparseData->ReparseDataLength = ReparseDataLength;
|
||||||
|
ReparseData->Reserved = 0;
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameLength =
|
||||||
|
VolumeNameLength + BackslashLength;
|
||||||
|
ReparseData->MountPointReparseBuffer.PrintNameOffset =
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
|
||||||
|
ReparseData->MountPointReparseBuffer.PrintNameLength =
|
||||||
|
VolumeNameLength + BackslashLength;
|
||||||
|
|
||||||
|
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer;
|
||||||
|
memcpy(PathBuffer, VolumeName, VolumeNameLength);
|
||||||
|
if (BackslashLength)
|
||||||
|
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
||||||
|
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer +
|
||||||
|
(ReparseData->MountPointReparseBuffer.PrintNameOffset) / sizeof(WCHAR);
|
||||||
|
memcpy(PathBuffer, VolumeName, VolumeNameLength);
|
||||||
|
if (BackslashLength)
|
||||||
|
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
||||||
|
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
if (!DeviceIoControl(MountHandle, FSCTL_SET_REPARSE_POINT,
|
||||||
|
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
||||||
|
0, 0,
|
||||||
|
&Bytes, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PMountHandle = MountHandle;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
||||||
|
CloseHandle(MountHandle);
|
||||||
|
|
||||||
|
MemFree(ReparseData);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspMountRemove_Directory(HANDLE MountHandle)
|
||||||
|
{
|
||||||
|
/* directory is marked DELETE_ON_CLOSE */
|
||||||
|
return CloseHandle(MountHandle) ? STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
||||||
|
{
|
||||||
|
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||||
|
|
||||||
|
Desc->MountHandle = 0;
|
||||||
|
|
||||||
|
if (L'*' == Desc->MountPoint[0] && ':' == Desc->MountPoint[1] && L'\0' == Desc->MountPoint[2])
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
DWORD Drives;
|
||||||
|
WCHAR Drive;
|
||||||
|
|
||||||
|
Drives = GetLogicalDrives();
|
||||||
|
if (0 == Drives)
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
for (Drive = 'Z'; 'D' <= Drive; Drive--)
|
||||||
|
if (0 == (Drives & (1 << (Drive - 'A'))))
|
||||||
|
{
|
||||||
|
Desc->MountPoint[0] = Drive;
|
||||||
|
Result = FspMountSet_Drive(Desc->VolumeName, Desc->MountPoint,
|
||||||
|
&Desc->MountHandle);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
Desc->MountPoint[0] = L'*';
|
||||||
|
return STATUS_NO_SUCH_DEVICE;
|
||||||
|
}
|
||||||
|
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||||
|
return FspMountSet_Mountmgr(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
||||||
|
else if (FspPathIsDrive(Desc->MountPoint))
|
||||||
|
return FspMountSet_Drive(Desc->VolumeName, Desc->MountPoint,
|
||||||
|
&Desc->MountHandle);
|
||||||
|
else
|
||||||
|
return FspMountSet_Directory(Desc->VolumeName, Desc->MountPoint, Desc->Security,
|
||||||
|
&Desc->MountHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
||||||
|
{
|
||||||
|
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||||
|
|
||||||
|
if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||||
|
return FspMountRemove_Mountmgr(Desc->MountPoint);
|
||||||
|
else if (FspPathIsDrive(Desc->MountPoint))
|
||||||
|
return FspMountRemove_Drive(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
|
||||||
|
else
|
||||||
|
return FspMountRemove_Directory(Desc->MountHandle);
|
||||||
|
}
|
@ -1085,8 +1085,9 @@ namespace Fsp
|
|||||||
UInt32 FileAttributes,
|
UInt32 FileAttributes,
|
||||||
Byte[] SecurityDescriptor,
|
Byte[] SecurityDescriptor,
|
||||||
UInt64 AllocationSize,
|
UInt64 AllocationSize,
|
||||||
IntPtr Ea,
|
IntPtr ExtraBuffer,
|
||||||
UInt32 EaLength,
|
UInt32 ExtraLength,
|
||||||
|
Boolean ExtraBufferIsReparsePoint,
|
||||||
out Object FileNode,
|
out Object FileNode,
|
||||||
out Object FileDesc,
|
out Object FileDesc,
|
||||||
out FileInfo FileInfo,
|
out FileInfo FileInfo,
|
||||||
@ -1391,6 +1392,16 @@ namespace Fsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Makes a byte array that contains a reparse point.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The reparse point byte array.</returns>
|
||||||
|
public static Byte[] MakeReparsePoint(
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Size)
|
||||||
|
{
|
||||||
|
return Api.MakeReparsePoint(Buffer, (UIntPtr)Size);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
/// Gets the reparse tag from reparse data.
|
/// Gets the reparse tag from reparse data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ReparseData">
|
/// <param name="ReparseData">
|
||||||
|
@ -40,6 +40,7 @@ namespace Fsp
|
|||||||
/// <param name="FileSystem">The file system to host.</param>
|
/// <param name="FileSystem">The file system to host.</param>
|
||||||
public FileSystemHost(FileSystemBase FileSystem)
|
public FileSystemHost(FileSystemBase FileSystem)
|
||||||
{
|
{
|
||||||
|
_VolumeParams.Version = (UInt16)Marshal.SizeOf(_VolumeParams);
|
||||||
_VolumeParams.Flags = VolumeParams.UmFileContextIsFullContext;
|
_VolumeParams.Flags = VolumeParams.UmFileContextIsFullContext;
|
||||||
_FileSystem = FileSystem;
|
_FileSystem = FileSystem;
|
||||||
}
|
}
|
||||||
@ -126,6 +127,86 @@ namespace Fsp
|
|||||||
set { _VolumeParams.FileInfoTimeout = value; }
|
set { _VolumeParams.FileInfoTimeout = value; }
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Gets or sets the volume information timeout.
|
||||||
|
/// </summary>
|
||||||
|
public UInt32 VolumeInfoTimeout
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.VolumeInfoTimeoutValid) ?
|
||||||
|
_VolumeParams.VolumeInfoTimeout : _VolumeParams.FileInfoTimeout;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_VolumeParams.AdditionalFlags |= VolumeParams.VolumeInfoTimeoutValid;
|
||||||
|
_VolumeParams.VolumeInfoTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the directory information timeout.
|
||||||
|
/// </summary>
|
||||||
|
public UInt32 DirInfoTimeout
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.DirInfoTimeoutValid) ?
|
||||||
|
_VolumeParams.DirInfoTimeout : _VolumeParams.FileInfoTimeout;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_VolumeParams.AdditionalFlags |= VolumeParams.DirInfoTimeoutValid;
|
||||||
|
_VolumeParams.DirInfoTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the security information timeout.
|
||||||
|
/// </summary>
|
||||||
|
public UInt32 SecurityTimeout
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.SecurityTimeoutValid) ?
|
||||||
|
_VolumeParams.SecurityTimeout : _VolumeParams.FileInfoTimeout;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_VolumeParams.AdditionalFlags |= VolumeParams.SecurityTimeoutValid;
|
||||||
|
_VolumeParams.SecurityTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the stream information timeout.
|
||||||
|
/// </summary>
|
||||||
|
public UInt32 StreamInfoTimeout
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.StreamInfoTimeoutValid) ?
|
||||||
|
_VolumeParams.StreamInfoTimeout : _VolumeParams.FileInfoTimeout;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_VolumeParams.AdditionalFlags |= VolumeParams.StreamInfoTimeoutValid;
|
||||||
|
_VolumeParams.StreamInfoTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the EA information timeout.
|
||||||
|
/// </summary>
|
||||||
|
public UInt32 EaTimeout
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.EaTimeoutValid) ?
|
||||||
|
_VolumeParams.EaTimeout : _VolumeParams.FileInfoTimeout;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_VolumeParams.AdditionalFlags |= VolumeParams.EaTimeoutValid;
|
||||||
|
_VolumeParams.EaTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
/// Gets or sets a value that determines whether the file system is case sensitive.
|
/// Gets or sets a value that determines whether the file system is case sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Boolean CaseSensitiveSearch
|
public Boolean CaseSensitiveSearch
|
||||||
@ -221,6 +302,11 @@ namespace Fsp
|
|||||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.AllowOpenInKernelMode); }
|
get { return 0 != (_VolumeParams.Flags & VolumeParams.AllowOpenInKernelMode); }
|
||||||
set { _VolumeParams.Flags |= (value ? VolumeParams.AllowOpenInKernelMode : 0); }
|
set { _VolumeParams.Flags |= (value ? VolumeParams.AllowOpenInKernelMode : 0); }
|
||||||
}
|
}
|
||||||
|
public Boolean WslFeatures
|
||||||
|
{
|
||||||
|
get { return 0 != (_VolumeParams.Flags & VolumeParams.WslFeatures); }
|
||||||
|
set { _VolumeParams.Flags |= (value ? VolumeParams.WslFeatures : 0); }
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the prefix for a network file system.
|
/// Gets or sets the prefix for a network file system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -274,11 +360,44 @@ namespace Fsp
|
|||||||
/// A value of 0 disables all debug logging.
|
/// A value of 0 disables all debug logging.
|
||||||
/// A value of -1 enables all debug logging.
|
/// A value of -1 enables all debug logging.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns></returns>
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
public Int32 Mount(String MountPoint,
|
public Int32 Mount(String MountPoint,
|
||||||
Byte[] SecurityDescriptor = null,
|
Byte[] SecurityDescriptor = null,
|
||||||
Boolean Synchronized = false,
|
Boolean Synchronized = false,
|
||||||
UInt32 DebugLog = 0)
|
UInt32 DebugLog = 0)
|
||||||
|
{
|
||||||
|
return MountEx(MountPoint, 0, SecurityDescriptor, Synchronized, DebugLog);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Mounts a file system.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="MountPoint">
|
||||||
|
/// The mount point for the new file system. A value of null means that
|
||||||
|
/// the file system should use the next available drive letter counting
|
||||||
|
/// downwards from Z: as its mount point.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="ThreadCount">
|
||||||
|
/// Number of threads to use to service file system requests. A value
|
||||||
|
/// of 0 means that the default number of threads should be used.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="SecurityDescriptor">
|
||||||
|
/// Security descriptor to use if mounting on (newly created) directory.
|
||||||
|
/// A value of null means the directory should be created with default
|
||||||
|
/// security.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Synchronized">
|
||||||
|
/// If true file system operations are synchronized using an exclusive lock.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="DebugLog">
|
||||||
|
/// A value of 0 disables all debug logging.
|
||||||
|
/// A value of -1 enables all debug logging.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
|
public Int32 MountEx(String MountPoint,
|
||||||
|
UInt32 ThreadCount,
|
||||||
|
Byte[] SecurityDescriptor = null,
|
||||||
|
Boolean Synchronized = false,
|
||||||
|
UInt32 DebugLog = 0)
|
||||||
{
|
{
|
||||||
Int32 Result;
|
Int32 Result;
|
||||||
try
|
try
|
||||||
@ -315,7 +434,7 @@ namespace Fsp
|
|||||||
}
|
}
|
||||||
if (0 <= Result)
|
if (0 <= Result)
|
||||||
{
|
{
|
||||||
Result = Api.FspFileSystemStartDispatcher(_FileSystemPtr, 0);
|
Result = Api.FspFileSystemStartDispatcher(_FileSystemPtr, ThreadCount);
|
||||||
if (0 > Result)
|
if (0 > Result)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -381,6 +500,83 @@ namespace Fsp
|
|||||||
{
|
{
|
||||||
return Api.GetVersion();
|
return Api.GetVersion();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a RequestHint to reference the current operation asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
public UInt64 GetOperationRequestHint()
|
||||||
|
{
|
||||||
|
return Api.FspFileSystemGetOperationRequestHint();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously complete a Read operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestHint">
|
||||||
|
/// A reference to the operation to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Status">
|
||||||
|
/// STATUS_SUCCESS or error code.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="BytesTransferred">
|
||||||
|
/// Number of bytes read.
|
||||||
|
/// </param>
|
||||||
|
public void SendReadResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
FspFsctlTransactRsp Response = default(FspFsctlTransactRsp);
|
||||||
|
Response.Size = 128;
|
||||||
|
Response.Kind = (UInt32)FspFsctlTransact.ReadKind;
|
||||||
|
Response.Hint = RequestHint;
|
||||||
|
Response.IoStatus.Information = BytesTransferred;
|
||||||
|
Response.IoStatus.Status = (UInt32)Status;
|
||||||
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously complete a Write operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestHint">
|
||||||
|
/// A reference to the operation to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Status">
|
||||||
|
/// STATUS_SUCCESS or error code.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="BytesTransferred">
|
||||||
|
/// The number of bytes written.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="FileInfo">
|
||||||
|
/// Updated file information.
|
||||||
|
/// </param>
|
||||||
|
public void SendWriteResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred, ref FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FspFsctlTransactRsp Response = default(FspFsctlTransactRsp);
|
||||||
|
Response.Size = 128;
|
||||||
|
Response.Kind = (UInt32)FspFsctlTransact.WriteKind;
|
||||||
|
Response.Hint = RequestHint;
|
||||||
|
Response.IoStatus.Information = BytesTransferred;
|
||||||
|
Response.IoStatus.Status = (UInt32)Status;
|
||||||
|
Response.WriteFileInfo = FileInfo;
|
||||||
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously complete a ReadDirectory operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestHint">
|
||||||
|
/// A reference to the operation to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Status">
|
||||||
|
/// STATUS_SUCCESS or error code.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="BytesTransferred">
|
||||||
|
/// Number of bytes read.
|
||||||
|
/// </param>
|
||||||
|
public void SendReadDirectoryResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
FspFsctlTransactRsp Response = default(FspFsctlTransactRsp);
|
||||||
|
Response.Size = 128;
|
||||||
|
Response.Kind = (UInt32)FspFsctlTransact.QueryDirectoryKind;
|
||||||
|
Response.Hint = RequestHint;
|
||||||
|
Response.IoStatus.Information = BytesTransferred;
|
||||||
|
Response.IoStatus.Status = (UInt32)Status;
|
||||||
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
|
}
|
||||||
|
|
||||||
/* FSP_FILE_SYSTEM_INTERFACE */
|
/* FSP_FILE_SYSTEM_INTERFACE */
|
||||||
private static Byte[] ByteBufferNotNull = new Byte[0];
|
private static Byte[] ByteBufferNotNull = new Byte[0];
|
||||||
@ -472,8 +668,9 @@ namespace Fsp
|
|||||||
UInt32 FileAttributes,
|
UInt32 FileAttributes,
|
||||||
IntPtr SecurityDescriptor,
|
IntPtr SecurityDescriptor,
|
||||||
UInt64 AllocationSize,
|
UInt64 AllocationSize,
|
||||||
IntPtr Ea,
|
IntPtr ExtraBuffer,
|
||||||
UInt32 EaLength,
|
UInt32 ExtraLength,
|
||||||
|
Boolean ExtraBufferIsReparsePoint,
|
||||||
ref FullContext FullContext,
|
ref FullContext FullContext,
|
||||||
ref OpenFileInfo OpenFileInfo)
|
ref OpenFileInfo OpenFileInfo)
|
||||||
{
|
{
|
||||||
@ -490,8 +687,9 @@ namespace Fsp
|
|||||||
FileAttributes,
|
FileAttributes,
|
||||||
Api.MakeSecurityDescriptor(SecurityDescriptor),
|
Api.MakeSecurityDescriptor(SecurityDescriptor),
|
||||||
AllocationSize,
|
AllocationSize,
|
||||||
Ea,
|
ExtraBuffer,
|
||||||
EaLength,
|
ExtraLength,
|
||||||
|
ExtraBufferIsReparsePoint,
|
||||||
out FileNode,
|
out FileNode,
|
||||||
out FileDesc,
|
out FileDesc,
|
||||||
out OpenFileInfo.FileInfo,
|
out OpenFileInfo.FileInfo,
|
||||||
|
@ -53,9 +53,16 @@ namespace Fsp.Interop
|
|||||||
internal const UInt32 UmFileContextIsFullContext = 0x00020000;
|
internal const UInt32 UmFileContextIsFullContext = 0x00020000;
|
||||||
internal const UInt32 AllowOpenInKernelMode = 0x01000000;
|
internal const UInt32 AllowOpenInKernelMode = 0x01000000;
|
||||||
internal const UInt32 CasePreservedExtendedAttributes = 0x02000000;
|
internal const UInt32 CasePreservedExtendedAttributes = 0x02000000;
|
||||||
|
internal const UInt32 WslFeatures = 0x04000000;
|
||||||
internal const int PrefixSize = 192;
|
internal const int PrefixSize = 192;
|
||||||
internal const int FileSystemNameSize = 16;
|
internal const int FileSystemNameSize = 16;
|
||||||
|
|
||||||
|
internal const UInt32 VolumeInfoTimeoutValid = 0x00000001;
|
||||||
|
internal const UInt32 DirInfoTimeoutValid = 0x00000002;
|
||||||
|
internal const UInt32 SecurityTimeoutValid = 0x00000004;
|
||||||
|
internal const UInt32 StreamInfoTimeoutValid = 0x00000008;
|
||||||
|
internal const UInt32 EaTimeoutValid = 0x00000010;
|
||||||
|
|
||||||
internal UInt16 Version;
|
internal UInt16 Version;
|
||||||
internal UInt16 SectorSize;
|
internal UInt16 SectorSize;
|
||||||
internal UInt16 SectorsPerAllocationUnit;
|
internal UInt16 SectorsPerAllocationUnit;
|
||||||
@ -69,6 +76,15 @@ namespace Fsp.Interop
|
|||||||
internal UInt32 Flags;
|
internal UInt32 Flags;
|
||||||
internal unsafe fixed UInt16 Prefix[PrefixSize];
|
internal unsafe fixed UInt16 Prefix[PrefixSize];
|
||||||
internal unsafe fixed UInt16 FileSystemName[FileSystemNameSize];
|
internal unsafe fixed UInt16 FileSystemName[FileSystemNameSize];
|
||||||
|
internal UInt32 AdditionalFlags;
|
||||||
|
internal UInt32 VolumeInfoTimeout;
|
||||||
|
internal UInt32 DirInfoTimeout;
|
||||||
|
internal UInt32 SecurityTimeout;
|
||||||
|
internal UInt32 StreamInfoTimeout;
|
||||||
|
internal UInt32 EaTimeout;
|
||||||
|
internal UInt32 FsextControlCode;
|
||||||
|
internal unsafe fixed UInt32 Reserved32[1];
|
||||||
|
internal unsafe fixed UInt64 Reserved64[2];
|
||||||
|
|
||||||
internal unsafe String GetPrefix()
|
internal unsafe String GetPrefix()
|
||||||
{
|
{
|
||||||
@ -354,6 +370,65 @@ namespace Fsp.Interop
|
|||||||
public IntPtr Information;
|
public IntPtr Information;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct IoStatus
|
||||||
|
{
|
||||||
|
internal UInt32 Information;
|
||||||
|
internal UInt32 Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum FspFsctlTransact
|
||||||
|
{
|
||||||
|
ReadKind = 5,
|
||||||
|
WriteKind = 6,
|
||||||
|
QueryDirectoryKind = 14
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal struct FspFsctlTransactReq
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal UInt16 Version;
|
||||||
|
[FieldOffset(2)]
|
||||||
|
internal UInt16 Size;
|
||||||
|
[FieldOffset(4)]
|
||||||
|
internal UInt32 Kind;
|
||||||
|
[FieldOffset(8)]
|
||||||
|
internal UInt64 Hint;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal unsafe fixed Byte Padding[88];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal struct FspFsctlTransactRsp
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal UInt16 Version;
|
||||||
|
[FieldOffset(2)]
|
||||||
|
internal UInt16 Size;
|
||||||
|
[FieldOffset(4)]
|
||||||
|
internal UInt32 Kind;
|
||||||
|
[FieldOffset(8)]
|
||||||
|
internal UInt64 Hint;
|
||||||
|
|
||||||
|
[FieldOffset(16)]
|
||||||
|
internal IoStatus IoStatus;
|
||||||
|
|
||||||
|
[FieldOffset(24)]
|
||||||
|
internal FileInfo WriteFileInfo;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal unsafe fixed Byte Padding[128];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal unsafe struct FspFileSystemOperationContext
|
||||||
|
{
|
||||||
|
internal FspFsctlTransactReq *Request;
|
||||||
|
internal FspFsctlTransactRsp *Response;
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
internal struct FileSystemInterface
|
internal struct FileSystemInterface
|
||||||
{
|
{
|
||||||
@ -557,8 +632,9 @@ namespace Fsp.Interop
|
|||||||
UInt32 FileAttributes,
|
UInt32 FileAttributes,
|
||||||
IntPtr SecurityDescriptor,
|
IntPtr SecurityDescriptor,
|
||||||
UInt64 AllocationSize,
|
UInt64 AllocationSize,
|
||||||
IntPtr Ea,
|
IntPtr ExtraBuffer,
|
||||||
UInt32 EaLength,
|
UInt32 ExtraLength,
|
||||||
|
[MarshalAs(UnmanagedType.U1)] Boolean ExtraBufferIsReparsePoint,
|
||||||
ref FullContext FullContext,
|
ref FullContext FullContext,
|
||||||
ref OpenFileInfo OpenFileInfo);
|
ref OpenFileInfo OpenFileInfo);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
@ -662,6 +738,12 @@ namespace Fsp.Interop
|
|||||||
internal delegate Int32 FspFileSystemStopDispatcher(
|
internal delegate Int32 FspFileSystemStopDispatcher(
|
||||||
IntPtr FileSystem);
|
IntPtr FileSystem);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate void FspFileSystemSendResponse(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
ref FspFsctlTransactRsp Response);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal unsafe delegate FspFileSystemOperationContext *FspFileSystemGetOperationContext();
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
internal delegate IntPtr FspFileSystemMountPointF(
|
internal delegate IntPtr FspFileSystemMountPointF(
|
||||||
IntPtr FileSystem);
|
IntPtr FileSystem);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
@ -846,6 +928,8 @@ namespace Fsp.Interop
|
|||||||
internal static Proto.FspFileSystemRemoveMountPoint FspFileSystemRemoveMountPoint;
|
internal static Proto.FspFileSystemRemoveMountPoint FspFileSystemRemoveMountPoint;
|
||||||
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.FspFileSystemGetOperationContext FspFileSystemGetOperationContext;
|
||||||
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
||||||
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
||||||
internal static Proto.FspFileSystemSetDebugLogF FspFileSystemSetDebugLog;
|
internal static Proto.FspFileSystemSetDebugLogF FspFileSystemSetDebugLog;
|
||||||
@ -892,6 +976,10 @@ namespace Fsp.Interop
|
|||||||
else
|
else
|
||||||
return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, IntPtr.Zero);
|
return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
internal static unsafe UInt64 FspFileSystemGetOperationRequestHint()
|
||||||
|
{
|
||||||
|
return FspFileSystemGetOperationContext()->Request->Hint;
|
||||||
|
}
|
||||||
internal static unsafe Boolean FspFileSystemAddDirInfo(
|
internal static unsafe Boolean FspFileSystemAddDirInfo(
|
||||||
ref DirInfo DirInfo,
|
ref DirInfo DirInfo,
|
||||||
IntPtr Buffer,
|
IntPtr Buffer,
|
||||||
@ -1240,6 +1328,8 @@ namespace Fsp.Interop
|
|||||||
FspFileSystemRemoveMountPoint = GetEntryPoint<Proto.FspFileSystemRemoveMountPoint>(Module);
|
FspFileSystemRemoveMountPoint = GetEntryPoint<Proto.FspFileSystemRemoveMountPoint>(Module);
|
||||||
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);
|
||||||
|
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);
|
||||||
FspFileSystemSetDebugLog = GetEntryPoint<Proto.FspFileSystemSetDebugLogF>(Module);
|
FspFileSystemSetDebugLog = GetEntryPoint<Proto.FspFileSystemSetDebugLogF>(Module);
|
||||||
|
222
src/ku/library.h
Normal file
222
src/ku/library.h
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/**
|
||||||
|
* @file ku/library.h
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINFSP_KU_LIBRARY_H_INCLUDED
|
||||||
|
#define WINFSP_KU_LIBRARY_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(_KERNEL_MODE)
|
||||||
|
|
||||||
|
#include <dll/library.h>
|
||||||
|
#include <aclapi.h>
|
||||||
|
#define _NTDEF_
|
||||||
|
#include <ntsecapi.h>
|
||||||
|
|
||||||
|
#define FSP_KU_CODE ((void)0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
#define FSP_KU_CODE PAGED_CODE(); NTSTATUS fsp_ku_status = STATUS_SUCCESS; (VOID)fsp_ku_status
|
||||||
|
|
||||||
|
#define FSP_API FSP_DDI
|
||||||
|
|
||||||
|
#define BYTE UINT8
|
||||||
|
#define BOOL BOOLEAN
|
||||||
|
#define LPBOOL PBOOLEAN
|
||||||
|
#define UINT ULONG
|
||||||
|
|
||||||
|
#define GetLastError() ((DWORD)fsp_ku_status)
|
||||||
|
#define FspNtStatusFromWin32(Err) ((NTSTATUS)(Err))
|
||||||
|
#define ERROR_INSUFFICIENT_BUFFER STATUS_BUFFER_TOO_SMALL
|
||||||
|
|
||||||
|
#define InitOnceExecuteOnce(I, F, P, C) RtlRunOnceExecuteOnce(I, F, P, C)
|
||||||
|
#define INIT_ONCE RTL_RUN_ONCE
|
||||||
|
#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT
|
||||||
|
|
||||||
|
#define AddAccessAllowedAce(Acl, Rev, Acc, Sid)\
|
||||||
|
(fsp_ku_status = RtlAddAccessAllowedAce(Acl, Rev, Acc, Sid),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define AddAccessDeniedAce(Acl, Rev, Acc, Sid)\
|
||||||
|
(fsp_ku_status = FspKuAddAccessDeniedAce(Acl, Rev, Acc, Sid),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define EqualSid(Sid1, Sid2) (fsp_ku_status = 0, RtlEqualSid(Sid1, Sid2))
|
||||||
|
#define GetAce(Acl, Idx, Ace) (fsp_ku_status = RtlGetAce(Acl, Idx, Ace), NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define GetAclInformation(Acl, Inf, Len, Cls)\
|
||||||
|
(fsp_ku_status = FspKuQueryInformationAcl(Acl, Inf, Len, Cls),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define GetLengthSid(Sid) (fsp_ku_status = 0, RtlLengthSid(Sid))
|
||||||
|
#define GetSecurityDescriptorDacl(Sec, Prs, Dac, Def)\
|
||||||
|
(fsp_ku_status = RtlGetDaclSecurityDescriptor(Sec, Prs, Dac, Def),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define GetSecurityDescriptorGroup(Sec, Grp, Def)\
|
||||||
|
(fsp_ku_status = RtlGetGroupSecurityDescriptor(Sec, Grp, Def),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define GetSecurityDescriptorOwner(Sec, Own, Def)\
|
||||||
|
(fsp_ku_status = RtlGetOwnerSecurityDescriptor(Sec, Own, Def),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define GetSidIdentifierAuthority(Sid) (fsp_ku_status = 0, &((PISID)(Sid))->IdentifierAuthority)
|
||||||
|
#define GetSidSubAuthority(Sid, Sub) (fsp_ku_status = 0, RtlSubAuthoritySid(Sid, Sub))
|
||||||
|
#define GetSidSubAuthorityCount(Sid) (fsp_ku_status = 0, RtlSubAuthorityCountSid(Sid))
|
||||||
|
#define InitializeAcl(Acl, Len, Rev) (fsp_ku_status = RtlCreateAcl(Acl, Len, Rev), NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define InitializeSecurityDescriptor(Sec, Rev)\
|
||||||
|
(fsp_ku_status = RtlCreateSecurityDescriptor(Sec, Rev),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define InitializeSid(Sid, Aut, Cnt) (fsp_ku_status = RtlInitializeSid(Sid, Aut, Cnt), NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define IsValidSid(Sid) (RtlValidSid(Sid) || (fsp_ku_status = STATUS_INVALID_SID, FALSE))
|
||||||
|
#define MakeSelfRelativeSD(Abs, Rel, Len)\
|
||||||
|
(fsp_ku_status = RtlAbsoluteToSelfRelativeSD(Abs, Rel, Len),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define SetSecurityDescriptorControl(Sec, Msk, Bit)\
|
||||||
|
(fsp_ku_status = FspKuSetControlSecurityDescriptor(Sec, Msk, Bit),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define SetSecurityDescriptorDacl(Sec, Prs, Dac, Def)\
|
||||||
|
(fsp_ku_status = RtlSetDaclSecurityDescriptor(Sec, Prs, Dac, Def),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define SetSecurityDescriptorGroup(Sec, Grp, Def)\
|
||||||
|
(fsp_ku_status = RtlSetGroupSecurityDescriptor(Sec, Grp, Def),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
#define SetSecurityDescriptorOwner(Sec, Own, Def)\
|
||||||
|
(fsp_ku_status = RtlSetOwnerSecurityDescriptor(Sec, Own, Def),\
|
||||||
|
NT_SUCCESS(fsp_ku_status))
|
||||||
|
static inline NTSTATUS FspKuAddAccessDeniedAce(
|
||||||
|
PACL Acl,
|
||||||
|
ULONG AceRevision,
|
||||||
|
ACCESS_MASK AccessMask,
|
||||||
|
PSID Sid)
|
||||||
|
{
|
||||||
|
/* We are missing RtlAddAccessDeniedAce. So we need this malarkey! */
|
||||||
|
NTSTATUS Result;
|
||||||
|
PACE_HEADER Ace;
|
||||||
|
Result = RtlAddAccessAllowedAce(Acl, AceRevision, AccessMask, Sid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
Result = RtlGetAce(Acl, Acl->AceCount - 1, &Ace);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
Ace->AceType = ACCESS_DENIED_ACE_TYPE;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
AclRevisionInformation__DO_NOT_USE = 1,
|
||||||
|
AclSizeInformation,
|
||||||
|
} ACL_INFORMATION_CLASS;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD AceCount;
|
||||||
|
DWORD AclBytesInUse__DO_NOT_USE;
|
||||||
|
DWORD AclBytesFree__DO_NOT_USE;
|
||||||
|
} ACL_SIZE_INFORMATION, *PACL_SIZE_INFORMATION;
|
||||||
|
static inline NTSTATUS FspKuQueryInformationAcl(
|
||||||
|
PACL Acl,
|
||||||
|
PVOID AclInformation,
|
||||||
|
ULONG AclInformationLength,
|
||||||
|
ACL_INFORMATION_CLASS AclInformationClass)
|
||||||
|
{
|
||||||
|
ASSERT(AclSizeInformation == AclInformationClass);
|
||||||
|
ASSERT(sizeof(ACL_SIZE_INFORMATION) <= AclInformationLength);
|
||||||
|
((PACL_SIZE_INFORMATION)AclInformation)->AceCount = Acl->AceCount;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
static inline NTSTATUS FspKuSetControlSecurityDescriptor(
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
SECURITY_DESCRIPTOR_CONTROL ControlMask,
|
||||||
|
SECURITY_DESCRIPTOR_CONTROL ControlBits)
|
||||||
|
{
|
||||||
|
((PUSHORT)(SecurityDescriptor))[1] &= ~ControlMask;
|
||||||
|
((PUSHORT)(SecurityDescriptor))[1] |= ControlBits;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WideCharToMultiByte(C, F, W, w, B, b, D, d)\
|
||||||
|
(FspKuWideCharToMultiByte(C, F, W, w, B, b, D, d, &fsp_ku_status))
|
||||||
|
#define MultiByteToWideChar(C, F, B, b, W, w)\
|
||||||
|
(FspKuMultiByteToWideChar(C, F, B, b, W, w, &fsp_ku_status))
|
||||||
|
#define CP_UTF8 65001
|
||||||
|
static inline int FspKuWideCharToMultiByte(
|
||||||
|
UINT CodePage,
|
||||||
|
DWORD dwFlags,
|
||||||
|
LPCWCH lpWideCharStr,
|
||||||
|
int cchWideChar,
|
||||||
|
LPSTR lpMultiByteStr,
|
||||||
|
int cbMultiByte,
|
||||||
|
LPCCH lpDefaultChar,
|
||||||
|
LPBOOL lpUsedDefaultChar,
|
||||||
|
PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
ASSERT(CP_UTF8 == CodePage);
|
||||||
|
ASSERT(0 == dwFlags);
|
||||||
|
ASSERT(0 == lpDefaultChar);
|
||||||
|
ASSERT(0 == lpUsedDefaultChar);
|
||||||
|
NTSTATUS Result;
|
||||||
|
ULONG ByteCount;
|
||||||
|
if (-1 == cchWideChar)
|
||||||
|
cchWideChar = (int)wcslen(lpWideCharStr) + 1;
|
||||||
|
Result = RtlUnicodeToUTF8N(
|
||||||
|
lpMultiByteStr, cbMultiByte, &ByteCount,
|
||||||
|
lpWideCharStr, cchWideChar * sizeof(WCHAR));
|
||||||
|
if (STATUS_SOME_NOT_MAPPED == Result)
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else if (!NT_SUCCESS(Result))
|
||||||
|
return 0;
|
||||||
|
*PResult = Result;
|
||||||
|
return ByteCount;
|
||||||
|
}
|
||||||
|
static inline int FspKuMultiByteToWideChar(
|
||||||
|
UINT CodePage,
|
||||||
|
DWORD dwFlags,
|
||||||
|
LPCCH lpMultiByteStr,
|
||||||
|
int cbMultiByte,
|
||||||
|
LPWSTR lpWideCharStr,
|
||||||
|
int cchWideChar,
|
||||||
|
PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
ASSERT(CP_UTF8 == CodePage);
|
||||||
|
ASSERT(0 == dwFlags);
|
||||||
|
NTSTATUS Result;
|
||||||
|
ULONG ByteCount;
|
||||||
|
if (-1 == cbMultiByte)
|
||||||
|
cbMultiByte = (int)strlen(lpMultiByteStr) + 1;
|
||||||
|
Result = RtlUTF8ToUnicodeN(
|
||||||
|
lpWideCharStr, cchWideChar * sizeof(WCHAR), &ByteCount,
|
||||||
|
lpMultiByteStr, cbMultiByte);
|
||||||
|
if (STATUS_SOME_NOT_MAPPED == Result)
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else if (!NT_SUCCESS(Result))
|
||||||
|
return 0;
|
||||||
|
*PResult = Result;
|
||||||
|
return ByteCount / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *MemAlloc(size_t Size)
|
||||||
|
{
|
||||||
|
return FspAlloc(Size);
|
||||||
|
}
|
||||||
|
static inline void MemFree(void *Pointer)
|
||||||
|
{
|
||||||
|
if (0 != Pointer)
|
||||||
|
FspFree(Pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @file dll/posix.c
|
* @file ku/posix.c
|
||||||
* POSIX Interop.
|
* POSIX Interop.
|
||||||
*
|
*
|
||||||
* This file provides routines for Windows/POSIX interoperability. It is based
|
* This file provides routines for Windows/POSIX interoperability. It is based
|
||||||
@ -32,15 +32,67 @@
|
|||||||
* associated repository.
|
* associated repository.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dll/library.h>
|
#include <ku/library.h>
|
||||||
#include <aclapi.h>
|
|
||||||
#define _NTDEF_
|
|
||||||
#include <ntsecapi.h>
|
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid);
|
||||||
|
FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid);
|
||||||
static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...);
|
static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...);
|
||||||
|
FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)());
|
||||||
|
FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
||||||
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
|
FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode);
|
||||||
|
FSP_API NTSTATUS FspPosixMapWindowsToPosixPathEx(PWSTR WindowsPath, char **PPosixPath,
|
||||||
|
BOOLEAN Translate);
|
||||||
|
FSP_API NTSTATUS FspPosixMapPosixToWindowsPathEx(const char *PosixPath, PWSTR *PWindowsPath,
|
||||||
|
BOOLEAN Translate);
|
||||||
|
FSP_API VOID FspPosixDeletePath(void *Path);
|
||||||
|
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size);
|
||||||
|
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size);
|
||||||
|
|
||||||
static INIT_ONCE FspPosixInitOnce = INIT_ONCE_STATIC_INIT;
|
#if defined(_KERNEL_MODE)
|
||||||
union
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMapUidToSid)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMapSidToUid)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixCreateSid)
|
||||||
|
#pragma alloc_text(PAGE, FspDeleteSid)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMapPermissionsToSecurityDescriptor)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMapSecurityDescriptorToPermissions)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMapWindowsToPosixPathEx)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixMapPosixToWindowsPathEx)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixDeletePath)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixEncodeWindowsPath)
|
||||||
|
#pragma alloc_text(PAGE, FspPosixDecodeWindowsPath)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
||||||
|
} FspWorldSidBuf =
|
||||||
|
{
|
||||||
|
/* S-1-1-0 */
|
||||||
|
.V.Revision = SID_REVISION,
|
||||||
|
.V.SubAuthorityCount = 1,
|
||||||
|
.V.IdentifierAuthority.Value[5] = 1,
|
||||||
|
.V.SubAuthority[0] = 0,
|
||||||
|
};
|
||||||
|
static union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
||||||
|
} FspAuthUsersSidBuf =
|
||||||
|
{
|
||||||
|
/* S-1-5-11 */
|
||||||
|
.V.Revision = SID_REVISION,
|
||||||
|
.V.SubAuthorityCount = 1,
|
||||||
|
.V.IdentifierAuthority.Value[5] = 5,
|
||||||
|
.V.SubAuthority[0] = 11,
|
||||||
|
};
|
||||||
|
static union
|
||||||
{
|
{
|
||||||
SID V;
|
SID V;
|
||||||
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
||||||
@ -52,11 +104,15 @@ union
|
|||||||
.V.IdentifierAuthority.Value[5] = 0,
|
.V.IdentifierAuthority.Value[5] = 0,
|
||||||
.V.SubAuthority[0] = 65534,
|
.V.SubAuthority[0] = 65534,
|
||||||
};
|
};
|
||||||
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
|
||||||
|
|
||||||
|
#define FspWorldSid (&FspWorldSidBuf.V)
|
||||||
|
#define FspAuthUsersSid (&FspAuthUsersSidBuf.V)
|
||||||
#define FspUnmappedSid (&FspUnmappedSidBuf.V)
|
#define FspUnmappedSid (&FspUnmappedSidBuf.V)
|
||||||
#define FspUnmappedUid (65534)
|
#define FspUnmappedUid (65534)
|
||||||
|
|
||||||
|
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
||||||
|
static INIT_ONCE FspPosixInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
|
#if !defined(_KERNEL_MODE)
|
||||||
static BOOL WINAPI FspPosixInitialize(
|
static BOOL WINAPI FspPosixInitialize(
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
{
|
{
|
||||||
@ -120,9 +176,79 @@ VOID FspPosixFinalize(BOOLEAN Dynamic)
|
|||||||
MemFree(FspPrimaryDomainSid);
|
MemFree(FspPrimaryDomainSid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ULONG NTAPI FspPosixInitialize(
|
||||||
|
PRTL_RUN_ONCE RunOnce, PVOID Parameter, PVOID *Context)
|
||||||
|
{
|
||||||
|
static union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
|
} FspAccountDomainSidBuf;
|
||||||
|
static union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
|
} FspPrimaryDomainSidBuf;
|
||||||
|
UNICODE_STRING Path;
|
||||||
|
UNICODE_STRING Name;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
KEY_VALUE_PARTIAL_INFORMATION V;
|
||||||
|
UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + SECURITY_MAX_SID_SIZE];
|
||||||
|
} Value;
|
||||||
|
ULONG Length;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\SECURITY\\Policy\\PolAcDmS");
|
||||||
|
RtlZeroMemory(&Name, sizeof Name);
|
||||||
|
Length = sizeof Value;
|
||||||
|
Result = FspRegistryGetValue(&Path, &Name, &Value.V, &Length);
|
||||||
|
if (NT_SUCCESS(Result) && REG_NONE == Value.V.Type &&
|
||||||
|
sizeof(SID) <= Value.V.DataLength && RtlValidSid((PSID)&Value.V.Data))
|
||||||
|
{
|
||||||
|
RtlCopyMemory(&FspAccountDomainSidBuf.V, &Value.V.Data, Value.V.DataLength);
|
||||||
|
FspAccountDomainSid = &FspAccountDomainSidBuf.V;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\SECURITY\\Policy\\PolPrDmS");
|
||||||
|
RtlZeroMemory(&Name, sizeof Name);
|
||||||
|
Length = sizeof Value;
|
||||||
|
Result = FspRegistryGetValue(&Path, &Name, &Value.V, &Length);
|
||||||
|
if (NT_SUCCESS(Result) && REG_NONE == Value.V.Type &&
|
||||||
|
sizeof(SID) <= Value.V.DataLength && RtlValidSid((PSID)&Value.V.Data))
|
||||||
|
{
|
||||||
|
RtlCopyMemory(&FspPrimaryDomainSidBuf.V, &Value.V.Data, Value.V.DataLength);
|
||||||
|
FspPrimaryDomainSid = &FspPrimaryDomainSidBuf.V;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline BOOLEAN FspPosixIsRelativeSid(PISID Sid1, PISID Sid2)
|
||||||
|
{
|
||||||
|
if (Sid1->Revision != Sid2->Revision)
|
||||||
|
return FALSE;
|
||||||
|
if (Sid1->IdentifierAuthority.Value[0] != Sid2->IdentifierAuthority.Value[0] ||
|
||||||
|
Sid1->IdentifierAuthority.Value[1] != Sid2->IdentifierAuthority.Value[1] ||
|
||||||
|
Sid1->IdentifierAuthority.Value[2] != Sid2->IdentifierAuthority.Value[2] ||
|
||||||
|
Sid1->IdentifierAuthority.Value[3] != Sid2->IdentifierAuthority.Value[3] ||
|
||||||
|
Sid1->IdentifierAuthority.Value[4] != Sid2->IdentifierAuthority.Value[4] ||
|
||||||
|
Sid1->IdentifierAuthority.Value[5] != Sid2->IdentifierAuthority.Value[5])
|
||||||
|
return FALSE;
|
||||||
|
if (Sid1->SubAuthorityCount + 1 != Sid2->SubAuthorityCount)
|
||||||
|
return FALSE;
|
||||||
|
for (ULONG I = 0; Sid1->SubAuthorityCount > I; I++)
|
||||||
|
if (Sid1->SubAuthority[I] != Sid2->SubAuthority[I])
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
InitOnceExecuteOnce(&FspPosixInitOnce, FspPosixInitialize, 0, 0);
|
InitOnceExecuteOnce(&FspPosixInitOnce, FspPosixInitialize, 0, 0);
|
||||||
|
|
||||||
*PSid = 0;
|
*PSid = 0;
|
||||||
@ -221,7 +347,7 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
|||||||
* S-1-X-Y <=> uid/gid: 0x10000 + 0x100 * X + Y
|
* S-1-X-Y <=> uid/gid: 0x10000 + 0x100 * X + Y
|
||||||
*/
|
*/
|
||||||
else if (0x10000 <= Uid && Uid < 0x11000)
|
else if (0x10000 <= Uid && Uid < 0x11000)
|
||||||
*PSid = FspPosixCreateSid((Uid - 0x10000) >> 8, 1, (Uid - 0x10000) & 0xff);
|
*PSid = FspPosixCreateSid((BYTE)((Uid - 0x10000) >> 8), 1, (Uid - 0x10000) & 0xff);
|
||||||
|
|
||||||
/* [IDMAP]
|
/* [IDMAP]
|
||||||
* Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
* Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
||||||
@ -238,13 +364,15 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
|||||||
|
|
||||||
FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
InitOnceExecuteOnce(&FspPosixInitOnce, FspPosixInitialize, 0, 0);
|
InitOnceExecuteOnce(&FspPosixInitOnce, FspPosixInitialize, 0, 0);
|
||||||
|
|
||||||
BYTE Authority;
|
BYTE Authority;
|
||||||
BYTE Count;
|
BYTE Count;
|
||||||
UINT32 SubAuthority0, Rid;
|
UINT32 SubAuthority0, Rid;
|
||||||
|
|
||||||
*PUid = -1;
|
*PUid = (UINT32)-1;
|
||||||
|
|
||||||
if (!IsValidSid(Sid) || 0 == (Count = *GetSidSubAuthorityCount(Sid)))
|
if (!IsValidSid(Sid) || 0 == (Count = *GetSidSubAuthorityCount(Sid)))
|
||||||
return STATUS_INVALID_SID;
|
return STATUS_INVALID_SID;
|
||||||
@ -298,12 +426,11 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
|||||||
* has PrimaryDomainSid == AccountDomainSid.
|
* has PrimaryDomainSid == AccountDomainSid.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL EqualDomains = FALSE;
|
|
||||||
if (0 != FspPrimaryDomainSid &&
|
if (0 != FspPrimaryDomainSid &&
|
||||||
EqualDomainSid(FspPrimaryDomainSid, Sid, &EqualDomains) && EqualDomains)
|
FspPosixIsRelativeSid(FspPrimaryDomainSid, Sid))
|
||||||
*PUid = 0x100000 + Rid;
|
*PUid = 0x100000 + Rid;
|
||||||
else if (0 != FspAccountDomainSid &&
|
else if (0 != FspAccountDomainSid &&
|
||||||
EqualDomainSid(FspAccountDomainSid, Sid, &EqualDomains) && EqualDomains)
|
FspPosixIsRelativeSid(FspAccountDomainSid, Sid))
|
||||||
*PUid = 0x30000 + Rid;
|
*PUid = 0x30000 + Rid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -348,6 +475,8 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
|||||||
|
|
||||||
static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...)
|
static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
PISID Sid;
|
PISID Sid;
|
||||||
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
|
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@ -370,6 +499,8 @@ static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...)
|
|||||||
|
|
||||||
FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)())
|
FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)())
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
if (FspUnmappedSid == Sid)
|
if (FspUnmappedSid == Sid)
|
||||||
;
|
;
|
||||||
else if ((NTSTATUS (*)())FspPosixMapUidToSid == CreateFunc)
|
else if ((NTSTATUS (*)())FspPosixMapUidToSid == CreateFunc)
|
||||||
@ -439,7 +570,9 @@ FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
|||||||
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
UINT32 Uid, UINT32 Gid, UINT32 Mode,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
||||||
{
|
{
|
||||||
PSID OwnerSid = 0, GroupSid = 0, WorldSid = 0;
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
PSID OwnerSid = 0, GroupSid = 0;
|
||||||
UINT32 OwnerPerm, OwnerDeny, GroupPerm, GroupDeny, WorldPerm;
|
UINT32 OwnerPerm, OwnerDeny, GroupPerm, GroupDeny, WorldPerm;
|
||||||
PACL Acl = 0;
|
PACL Acl = 0;
|
||||||
SECURITY_DESCRIPTOR SecurityDescriptor;
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
@ -457,13 +590,6 @@ FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
WorldSid = FspWksidGet(WinWorldSid);
|
|
||||||
if (0 == WorldSid)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnerPerm = (Mode & 0700) >> 6;
|
OwnerPerm = (Mode & 0700) >> 6;
|
||||||
GroupPerm = (Mode & 0070) >> 3;
|
GroupPerm = (Mode & 0070) >> 3;
|
||||||
WorldPerm = (Mode & 0007);
|
WorldPerm = (Mode & 0007);
|
||||||
@ -502,7 +628,7 @@ FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
|||||||
sizeof(ACCESS_DENIED_ACE) * (!!OwnerDeny + !!GroupDeny);
|
sizeof(ACCESS_DENIED_ACE) * (!!OwnerDeny + !!GroupDeny);
|
||||||
Size += GetLengthSid(OwnerSid) - sizeof(DWORD);
|
Size += GetLengthSid(OwnerSid) - sizeof(DWORD);
|
||||||
Size += GetLengthSid(GroupSid) - sizeof(DWORD);
|
Size += GetLengthSid(GroupSid) - sizeof(DWORD);
|
||||||
Size += GetLengthSid(WorldSid) - sizeof(DWORD);
|
Size += GetLengthSid(FspWorldSid) - sizeof(DWORD);
|
||||||
if (OwnerDeny)
|
if (OwnerDeny)
|
||||||
Size += GetLengthSid(OwnerSid) - sizeof(DWORD);
|
Size += GetLengthSid(OwnerSid) - sizeof(DWORD);
|
||||||
if (GroupDeny)
|
if (GroupDeny)
|
||||||
@ -546,7 +672,7 @@ FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
|||||||
|
|
||||||
if (!AddAccessAllowedAce(Acl, ACL_REVISION,
|
if (!AddAccessAllowedAce(Acl, ACL_REVISION,
|
||||||
FspPosixDefaultPerm | FspPosixMapPermissionToAccessMask(Mode, WorldPerm),
|
FspPosixDefaultPerm | FspPosixMapPermissionToAccessMask(Mode, WorldPerm),
|
||||||
WorldSid))
|
FspWorldSid))
|
||||||
goto lasterror;
|
goto lasterror;
|
||||||
|
|
||||||
if (!InitializeSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
|
if (!InitializeSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
|
||||||
@ -621,7 +747,9 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
|||||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode)
|
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode)
|
||||||
{
|
{
|
||||||
PSID OwnerSid = 0, GroupSid = 0, WorldSid = 0, AuthUsersSid = 0;
|
FSP_KU_CODE;
|
||||||
|
|
||||||
|
PSID OwnerSid = 0, GroupSid = 0;
|
||||||
BOOL Defaulted, DaclPresent;
|
BOOL Defaulted, DaclPresent;
|
||||||
PACL Acl = 0;
|
PACL Acl = 0;
|
||||||
ACL_SIZE_INFORMATION AclSizeInfo;
|
ACL_SIZE_INFORMATION AclSizeInfo;
|
||||||
@ -653,20 +781,6 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
|||||||
|
|
||||||
if (0 != Acl)
|
if (0 != Acl)
|
||||||
{
|
{
|
||||||
WorldSid = FspWksidGet(WinWorldSid);
|
|
||||||
if (0 == WorldSid)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthUsersSid = FspWksidGet(WinAuthenticatedUserSid);
|
|
||||||
if (0 == AuthUsersSid)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnerAllow = OwnerDeny = GroupAllow = GroupDeny = WorldAllow = WorldDeny = 0;
|
OwnerAllow = OwnerDeny = GroupAllow = GroupDeny = WorldAllow = WorldDeny = 0;
|
||||||
|
|
||||||
if (!GetAclInformation(Acl, &AclSizeInfo, sizeof AclSizeInfo, AclSizeInformation))
|
if (!GetAclInformation(Acl, &AclSizeInfo, sizeof AclSizeInfo, AclSizeInformation))
|
||||||
@ -701,7 +815,7 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
|||||||
* add the allowed or denied access right bits into the "owner", "group"
|
* add the allowed or denied access right bits into the "owner", "group"
|
||||||
* and "other" collections.
|
* and "other" collections.
|
||||||
*/
|
*/
|
||||||
if (EqualSid(WorldSid, AceSid) || EqualSid(AuthUsersSid, AceSid))
|
if (EqualSid(FspWorldSid, AceSid) || EqualSid(FspAuthUsersSid, AceSid))
|
||||||
{
|
{
|
||||||
/* [PERMS]
|
/* [PERMS]
|
||||||
* If this is an access-denied ACE, then add each access right to the set
|
* If this is an access-denied ACE, then add each access right to the set
|
||||||
@ -812,6 +926,8 @@ static UINT32 FspPosixInvalidPathChars[4] =
|
|||||||
FSP_API NTSTATUS FspPosixMapWindowsToPosixPathEx(PWSTR WindowsPath, char **PPosixPath,
|
FSP_API NTSTATUS FspPosixMapWindowsToPosixPathEx(PWSTR WindowsPath, char **PPosixPath,
|
||||||
BOOLEAN Translate)
|
BOOLEAN Translate)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
char *PosixPath = 0, *p, *q;
|
char *PosixPath = 0, *p, *q;
|
||||||
@ -874,6 +990,8 @@ lasterror:
|
|||||||
FSP_API NTSTATUS FspPosixMapPosixToWindowsPathEx(const char *PosixPath, PWSTR *PWindowsPath,
|
FSP_API NTSTATUS FspPosixMapPosixToWindowsPathEx(const char *PosixPath, PWSTR *PWindowsPath,
|
||||||
BOOLEAN Translate)
|
BOOLEAN Translate)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
PWSTR WindowsPath = 0, p;
|
PWSTR WindowsPath = 0, p;
|
||||||
@ -925,11 +1043,15 @@ lasterror:
|
|||||||
|
|
||||||
FSP_API VOID FspPosixDeletePath(void *Path)
|
FSP_API VOID FspPosixDeletePath(void *Path)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
MemFree(Path);
|
MemFree(Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
|
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
|
||||||
{
|
{
|
||||||
WCHAR c = *p;
|
WCHAR c = *p;
|
||||||
@ -944,6 +1066,8 @@ FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
|||||||
|
|
||||||
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
||||||
{
|
{
|
||||||
|
FSP_KU_CODE;
|
||||||
|
|
||||||
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
|
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
|
||||||
{
|
{
|
||||||
WCHAR c = *p;
|
WCHAR c = *p;
|
134
src/ku/uuid5.c
Normal file
134
src/ku/uuid5.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/uuid5.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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 <ku/library.h>
|
||||||
|
#include <bcrypt.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This module is used to create UUID v5 identifiers. UUID v5 identifiers
|
||||||
|
* are effectively SHA1 hashes that are modified to fit within the UUID
|
||||||
|
* format. The resulting identifiers use version 5 and variant 2. The hash
|
||||||
|
* is taken over the concatenation of a namespace ID and a name; the namespace
|
||||||
|
* ID is another UUID and the name can be any string of bytes ("octets").
|
||||||
|
*
|
||||||
|
* For details see RFC 4122: https://tools.ietf.org/html/rfc4122
|
||||||
|
*/
|
||||||
|
|
||||||
|
NTSTATUS FspUuid5Make(const UUID *Namespace, const VOID *Buffer, ULONG Size, UUID *Uuid)
|
||||||
|
{
|
||||||
|
BCRYPT_ALG_HANDLE ProvHandle = 0;
|
||||||
|
BCRYPT_HASH_HANDLE HashHandle = 0;
|
||||||
|
UINT8 Temp[20];
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Windows UUID's are encoded in little-endian format. RFC 4122 specifies that for
|
||||||
|
* UUID v5 computation, UUID's must be converted to/from big-endian.
|
||||||
|
*
|
||||||
|
* Note that Windows is always little-endian:
|
||||||
|
* https://community.osr.com/discussion/comment/146810/#Comment_146810
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* copy Namespace to local buffer in network byte order (big-endian) */
|
||||||
|
Temp[ 0] = ((PUINT8)Namespace)[ 3];
|
||||||
|
Temp[ 1] = ((PUINT8)Namespace)[ 2];
|
||||||
|
Temp[ 2] = ((PUINT8)Namespace)[ 1];
|
||||||
|
Temp[ 3] = ((PUINT8)Namespace)[ 0];
|
||||||
|
Temp[ 4] = ((PUINT8)Namespace)[ 5];
|
||||||
|
Temp[ 5] = ((PUINT8)Namespace)[ 4];
|
||||||
|
Temp[ 6] = ((PUINT8)Namespace)[ 7];
|
||||||
|
Temp[ 7] = ((PUINT8)Namespace)[ 6];
|
||||||
|
Temp[ 8] = ((PUINT8)Namespace)[ 8];
|
||||||
|
Temp[ 9] = ((PUINT8)Namespace)[ 9];
|
||||||
|
Temp[10] = ((PUINT8)Namespace)[10];
|
||||||
|
Temp[11] = ((PUINT8)Namespace)[11];
|
||||||
|
Temp[12] = ((PUINT8)Namespace)[12];
|
||||||
|
Temp[13] = ((PUINT8)Namespace)[13];
|
||||||
|
Temp[14] = ((PUINT8)Namespace)[14];
|
||||||
|
Temp[15] = ((PUINT8)Namespace)[15];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unfortunately we cannot reuse the hashing object, because BCRYPT_HASH_REUSABLE_FLAG
|
||||||
|
* is available in Windows 8 and later. (WinFsp currently supports Windows 7 or later).
|
||||||
|
*/
|
||||||
|
|
||||||
|
Result = BCryptOpenAlgorithmProvider(&ProvHandle, BCRYPT_SHA1_ALGORITHM, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = BCryptCreateHash(ProvHandle, &HashHandle, 0, 0, 0, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = BCryptHashData(HashHandle, (PVOID)Temp, 16, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = BCryptHashData(HashHandle, (PVOID)Buffer, Size, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = BCryptFinishHash(HashHandle, Temp, 20, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* copy local buffer to Uuid in host byte order (little-endian) */
|
||||||
|
((PUINT8)Uuid)[ 0] = Temp[ 3];
|
||||||
|
((PUINT8)Uuid)[ 1] = Temp[ 2];
|
||||||
|
((PUINT8)Uuid)[ 2] = Temp[ 1];
|
||||||
|
((PUINT8)Uuid)[ 3] = Temp[ 0];
|
||||||
|
((PUINT8)Uuid)[ 4] = Temp[ 5];
|
||||||
|
((PUINT8)Uuid)[ 5] = Temp[ 4];
|
||||||
|
((PUINT8)Uuid)[ 6] = Temp[ 7];
|
||||||
|
((PUINT8)Uuid)[ 7] = Temp[ 6];
|
||||||
|
((PUINT8)Uuid)[ 8] = Temp[ 8];
|
||||||
|
((PUINT8)Uuid)[ 9] = Temp[ 9];
|
||||||
|
((PUINT8)Uuid)[10] = Temp[10];
|
||||||
|
((PUINT8)Uuid)[11] = Temp[11];
|
||||||
|
((PUINT8)Uuid)[12] = Temp[12];
|
||||||
|
((PUINT8)Uuid)[13] = Temp[13];
|
||||||
|
((PUINT8)Uuid)[14] = Temp[14];
|
||||||
|
((PUINT8)Uuid)[15] = Temp[15];
|
||||||
|
|
||||||
|
/* [RFC 4122 Section 4.3]
|
||||||
|
* Set the four most significant bits (bits 12 through 15) of the
|
||||||
|
* time_hi_and_version field to the appropriate 4-bit version number
|
||||||
|
* from Section 4.1.3.
|
||||||
|
*/
|
||||||
|
Uuid->Data3 = (5 << 12) | (Uuid->Data3 & 0x0fff);
|
||||||
|
|
||||||
|
/* [RFC 4122 Section 4.3]
|
||||||
|
* Set the two most significant bits (bits 6 and 7) of the
|
||||||
|
* clock_seq_hi_and_reserved to zero and one, respectively.
|
||||||
|
*/
|
||||||
|
Uuid->Data4[0] = (2 << 6) | (Uuid->Data4[0] & 0x3f);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != HashHandle)
|
||||||
|
BCryptDestroyHash(HashHandle);
|
||||||
|
|
||||||
|
if (0 != ProvHandle)
|
||||||
|
BCryptCloseAlgorithmProvider(ProvHandle, 0);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
@ -503,24 +503,19 @@ static SVC_INSTANCE *SvcInstanceLookup(PWSTR ClassName, PWSTR InstanceName)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG SvcInstanceArgumentLength(PWSTR Arg)
|
static inline ULONG SvcInstanceArgumentLength(PWSTR Arg, PWSTR Pattern)
|
||||||
{
|
{
|
||||||
ULONG Length;
|
PWSTR PathTransform(PWSTR Dest, PWSTR Arg, PWSTR Pattern);
|
||||||
|
|
||||||
Length = 2; /* for beginning and ending quotes */
|
return 2 + (ULONG)(UINT_PTR)PathTransform(0, Arg, Pattern);
|
||||||
for (PWSTR P = Arg; *P; P++)
|
|
||||||
if (L'"' != *P)
|
|
||||||
Length++;
|
|
||||||
|
|
||||||
return Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PWSTR SvcInstanceArgumentCopy(PWSTR Dest, PWSTR Arg)
|
static inline PWSTR SvcInstanceArgumentCopy(PWSTR Dest, PWSTR Arg, PWSTR Pattern)
|
||||||
{
|
{
|
||||||
|
PWSTR PathTransform(PWSTR Dest, PWSTR Arg, PWSTR Pattern);
|
||||||
|
|
||||||
*Dest++ = L'"';
|
*Dest++ = L'"';
|
||||||
for (PWSTR P = Arg; *P; P++)
|
Dest = PathTransform(Dest, Arg, Pattern);
|
||||||
if (L'"' != *P)
|
|
||||||
*Dest++ = *P;
|
|
||||||
*Dest++ = L'"';
|
*Dest++ = L'"';
|
||||||
|
|
||||||
return Dest;
|
return Dest;
|
||||||
@ -532,6 +527,7 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
|||||||
PWSTR NewString = 0, P, Q;
|
PWSTR NewString = 0, P, Q;
|
||||||
PWSTR EmptyArg = L"";
|
PWSTR EmptyArg = L"";
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
|
PWSTR Pattern;
|
||||||
|
|
||||||
*PNewString = 0;
|
*PNewString = 0;
|
||||||
|
|
||||||
@ -541,24 +537,36 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
|||||||
switch (*P)
|
switch (*P)
|
||||||
{
|
{
|
||||||
case L'%':
|
case L'%':
|
||||||
|
Pattern = 0;
|
||||||
P++;
|
P++;
|
||||||
|
if (L'\\' == *P)
|
||||||
|
{
|
||||||
|
Pattern = ++P;
|
||||||
|
while (!(L'\0' == *P ||
|
||||||
|
(L'0' <= *P && *P <= '9') ||
|
||||||
|
(L'A' <= *P && *P <= 'Z')))
|
||||||
|
P++;
|
||||||
|
}
|
||||||
if (L'0' <= *P && *P <= '9')
|
if (L'0' <= *P && *P <= '9')
|
||||||
{
|
{
|
||||||
if (Argc > (ULONG)(*P - L'0'))
|
if (Argc > (ULONG)(*P - L'0'))
|
||||||
Length += SvcInstanceArgumentLength(Argv[*P - L'0']);
|
Length += SvcInstanceArgumentLength(Argv[*P - L'0'], Pattern);
|
||||||
else
|
else
|
||||||
Length += SvcInstanceArgumentLength(EmptyArg);
|
Length += SvcInstanceArgumentLength(EmptyArg, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (L'U' == *P)
|
if (L'U' == *P)
|
||||||
{
|
{
|
||||||
if (0 != SvcInstanceUserName())
|
if (0 != SvcInstanceUserName())
|
||||||
Length += SvcInstanceArgumentLength(SvcInstanceUserName());
|
Length += SvcInstanceArgumentLength(SvcInstanceUserName(), Pattern);
|
||||||
else
|
else
|
||||||
Length += SvcInstanceArgumentLength(EmptyArg);
|
Length += SvcInstanceArgumentLength(EmptyArg, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if (*P)
|
||||||
Length++;
|
Length++;
|
||||||
|
else
|
||||||
|
P--;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Length++;
|
Length++;
|
||||||
@ -575,24 +583,36 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
|||||||
switch (*P)
|
switch (*P)
|
||||||
{
|
{
|
||||||
case L'%':
|
case L'%':
|
||||||
|
Pattern = 0;
|
||||||
P++;
|
P++;
|
||||||
|
if (L'\\' == *P)
|
||||||
|
{
|
||||||
|
Pattern = ++P;
|
||||||
|
while (!(L'\0' == *P ||
|
||||||
|
(L'0' <= *P && *P <= '9') ||
|
||||||
|
(L'A' <= *P && *P <= 'Z')))
|
||||||
|
P++;
|
||||||
|
}
|
||||||
if (L'0' <= *P && *P <= '9')
|
if (L'0' <= *P && *P <= '9')
|
||||||
{
|
{
|
||||||
if (Argc > (ULONG)(*P - L'0'))
|
if (Argc > (ULONG)(*P - L'0'))
|
||||||
Q = SvcInstanceArgumentCopy(Q, Argv[*P - L'0']);
|
Q = SvcInstanceArgumentCopy(Q, Argv[*P - L'0'], Pattern);
|
||||||
else
|
else
|
||||||
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
Q = SvcInstanceArgumentCopy(Q, EmptyArg, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (L'U' == *P)
|
if (L'U' == *P)
|
||||||
{
|
{
|
||||||
if (0 != SvcInstanceUserName())
|
if (0 != SvcInstanceUserName())
|
||||||
Q = SvcInstanceArgumentCopy(Q, SvcInstanceUserName());
|
Q = SvcInstanceArgumentCopy(Q, SvcInstanceUserName(), Pattern);
|
||||||
else
|
else
|
||||||
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
Q = SvcInstanceArgumentCopy(Q, EmptyArg, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if (*P)
|
||||||
*Q++ = *P;
|
*Q++ = *P;
|
||||||
|
else
|
||||||
|
P--;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*Q++ = *P;
|
*Q++ = *P;
|
||||||
|
182
src/launcher/ptrans.c
Normal file
182
src/launcher/ptrans.c
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/**
|
||||||
|
* @file launcher/ptrans.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path Transformation Language
|
||||||
|
*
|
||||||
|
* Syntax:
|
||||||
|
* PERCENT BACKLASH replace-sep *(*sep component) [*sep UNDERSCORE] arg
|
||||||
|
*
|
||||||
|
* Arg:
|
||||||
|
* The command line argument that a rule is applied on. These are denoted
|
||||||
|
* by digits [0-9] or a capital letter (A-Z).
|
||||||
|
*
|
||||||
|
* Component:
|
||||||
|
* A path component denoted by a small letter (a-z). The letter a denotes
|
||||||
|
* the first path component, the letter b the second path component, etc.
|
||||||
|
*
|
||||||
|
* UNDERSCORE:
|
||||||
|
* The UNDERSCORE (_) denotes the "rest of the path". This is any path
|
||||||
|
* left after any path components explicitly mentioned by using small
|
||||||
|
* letters (a-z).
|
||||||
|
*
|
||||||
|
* Sep:
|
||||||
|
* A separator symbol that is used to separated components.
|
||||||
|
* E.g. slash (/), colon (:), etc.
|
||||||
|
*
|
||||||
|
* Replace-sep:
|
||||||
|
* A separator symbol that replaces the backslash (\) separator in the
|
||||||
|
* "rest of the path" (UNDERSCORE). E.g. slash (/), colon (:), etc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* - %\/b:_1
|
||||||
|
* - Transforms \rclone\REMOTE\PATH\TO\FILES to REMOTE:PATH/TO/FILES
|
||||||
|
* - %\/b:/_1
|
||||||
|
* - Transforms \rclone\REMOTE\PATH\TO\FILES to REMOTE:/PATH/TO/FILES
|
||||||
|
* - %\/_1
|
||||||
|
* - Transforms \P1\P2\P3 to /P1/P2/P3
|
||||||
|
* - %\+_1
|
||||||
|
* - Transforms \P1\P2\P3 to +P1+P2+P3
|
||||||
|
* - %\\_1
|
||||||
|
* - Transforms \P1\P2\P3 to \\P1\\P2\\P3
|
||||||
|
* (Backslash is doubled up when used as a replacement separator!)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/launch.h>
|
||||||
|
#include <shared/minimal.h>
|
||||||
|
|
||||||
|
static PWSTR PathCopy(PWSTR Dest, PWSTR Arg, PWSTR ArgEnd, BOOLEAN WriteDest, WCHAR Replacement)
|
||||||
|
{
|
||||||
|
if (0 != Replacement)
|
||||||
|
{
|
||||||
|
for (PWSTR P = Arg, EndP = (0 != ArgEnd ? ArgEnd : (PWSTR)(UINT_PTR)~0); EndP > P && *P; P++)
|
||||||
|
if (L'\\' == *P)
|
||||||
|
{
|
||||||
|
if (L'\\' == Replacement)
|
||||||
|
{
|
||||||
|
if (WriteDest)
|
||||||
|
*Dest = Replacement;
|
||||||
|
Dest++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WriteDest)
|
||||||
|
*Dest = Replacement;
|
||||||
|
Dest++;
|
||||||
|
}
|
||||||
|
else if (L'"' != *P)
|
||||||
|
{
|
||||||
|
if (WriteDest)
|
||||||
|
*Dest = *P;
|
||||||
|
Dest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (PWSTR P = Arg, EndP = (0 != ArgEnd ? ArgEnd : (PWSTR)(UINT_PTR)~0); EndP > P && *P; P++)
|
||||||
|
if (L'"' != *P)
|
||||||
|
{
|
||||||
|
if (WriteDest)
|
||||||
|
*Dest = *P;
|
||||||
|
Dest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN PatternEnd(WCHAR C)
|
||||||
|
{
|
||||||
|
return L'\0' == C ||
|
||||||
|
(L'0' <= C && C <= '9') ||
|
||||||
|
(L'A' <= C && C <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
PWSTR PathTransform(PWSTR Dest, PWSTR Arg, PWSTR Pattern)
|
||||||
|
{
|
||||||
|
BOOLEAN WriteDest = 0 != Dest;
|
||||||
|
WCHAR Replacement;
|
||||||
|
PWSTR Components[26][2];
|
||||||
|
PWSTR Remainder = Arg;
|
||||||
|
ULONG RemainderIndex = 0;
|
||||||
|
PWSTR P;
|
||||||
|
|
||||||
|
if (0 == Pattern)
|
||||||
|
return PathCopy(Dest, Arg, 0, WriteDest, 0);
|
||||||
|
|
||||||
|
for (ULONG I = 0; 26 > I; I++)
|
||||||
|
Components[I][0] = 0;
|
||||||
|
|
||||||
|
Replacement = *Pattern++;
|
||||||
|
if (PatternEnd(Replacement))
|
||||||
|
return Dest;
|
||||||
|
|
||||||
|
while (!PatternEnd(*Pattern))
|
||||||
|
{
|
||||||
|
if (L'a' <= *Pattern && *Pattern <= 'z')
|
||||||
|
{
|
||||||
|
ULONG I = *Pattern - 'a', J;
|
||||||
|
if (0 == Components[I][0])
|
||||||
|
{
|
||||||
|
P = Remainder;
|
||||||
|
J = RemainderIndex;
|
||||||
|
|
||||||
|
while (L'\\' == *P)
|
||||||
|
P++;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Components[J][0] = P;
|
||||||
|
while (*P && L'\\' != *P)
|
||||||
|
P++;
|
||||||
|
Components[J][1] = P;
|
||||||
|
|
||||||
|
while (L'\\' == *P)
|
||||||
|
P++;
|
||||||
|
|
||||||
|
if (I == J)
|
||||||
|
{
|
||||||
|
Remainder = P;
|
||||||
|
RemainderIndex = I + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
J++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dest = PathCopy(Dest, Components[I][0], Components[I][1], WriteDest, Replacement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (L'_' == *Pattern)
|
||||||
|
Dest = PathCopy(Dest, Remainder, 0, WriteDest, Replacement);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (WriteDest)
|
||||||
|
*Dest = *Pattern;
|
||||||
|
Dest++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dest;
|
||||||
|
}
|
@ -72,6 +72,7 @@ NTSYSAPI VOID NTAPI RtlMoveMemory(VOID *Destination, CONST VOID *Source, DWORD L
|
|||||||
|
|
||||||
#pragma function(memset)
|
#pragma function(memset)
|
||||||
#pragma function(memcpy)
|
#pragma function(memcpy)
|
||||||
|
#pragma function(memmove)
|
||||||
static inline
|
static inline
|
||||||
void *memset(void *dst, int val, size_t siz)
|
void *memset(void *dst, int val, size_t siz)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ static NTSTATUS FspFsvolCreate(
|
|||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolCreateNoLock(
|
static NTSTATUS FspFsvolCreateNoLock(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
BOOLEAN MainFileOpen);
|
BOOLEAN MainFileOpen, PFSP_ATOMIC_CREATE_ECP_CONTEXT AtomicCreateEcp);
|
||||||
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
|
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
|
||||||
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
|
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
|
||||||
@ -144,6 +144,7 @@ static NTSTATUS FspFsvolCreate(
|
|||||||
PECP_LIST ExtraCreateParameters;
|
PECP_LIST ExtraCreateParameters;
|
||||||
PVOID ExtraCreateParameter;
|
PVOID ExtraCreateParameter;
|
||||||
BOOLEAN MainFileOpen = FALSE;
|
BOOLEAN MainFileOpen = FALSE;
|
||||||
|
PFSP_ATOMIC_CREATE_ECP_CONTEXT AtomicCreateEcp = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the IRP has ECP's.
|
* Check if the IRP has ECP's.
|
||||||
@ -219,6 +220,21 @@ static NTSTATUS FspFsvolCreate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.WslFeatures)
|
||||||
|
{
|
||||||
|
// {4720bd83-52ac-4104-a130-d1ec6a8cc8e5}
|
||||||
|
static const GUID FspAtomicCreateEcpGuid =
|
||||||
|
{ 0x4720bd83, 0x52ac, 0x4104, { 0xa1, 0x30, 0xd1, 0xec, 0x6a, 0x8c, 0xc8, 0xe5 } };
|
||||||
|
|
||||||
|
ExtraCreateParameter = 0;
|
||||||
|
AtomicCreateEcp =
|
||||||
|
NT_SUCCESS(FsRtlFindExtraCreateParameter(ExtraCreateParameters,
|
||||||
|
&FspAtomicCreateEcpGuid, &ExtraCreateParameter, 0)) &&
|
||||||
|
0 != ExtraCreateParameter &&
|
||||||
|
!FsRtlIsEcpFromUserMode(ExtraCreateParameter) ?
|
||||||
|
ExtraCreateParameter : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MainFileOpen)
|
if (!MainFileOpen)
|
||||||
@ -226,7 +242,8 @@ static NTSTATUS FspFsvolCreate(
|
|||||||
FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject);
|
FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp, FALSE);
|
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp,
|
||||||
|
MainFileOpen, AtomicCreateEcp);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -235,14 +252,15 @@ static NTSTATUS FspFsvolCreate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp, TRUE);
|
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp,
|
||||||
|
MainFileOpen, AtomicCreateEcp);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolCreateNoLock(
|
static NTSTATUS FspFsvolCreateNoLock(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
BOOLEAN MainFileOpen)
|
BOOLEAN MainFileOpen, PFSP_ATOMIC_CREATE_ECP_CONTEXT AtomicCreateEcp)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
@ -279,6 +297,8 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
|
USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
|
||||||
PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
|
PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
ULONG EaLength = IrpSp->Parameters.Create.EaLength;
|
ULONG EaLength = IrpSp->Parameters.Create.EaLength;
|
||||||
|
PVOID ExtraBuffer = 0;
|
||||||
|
ULONG ExtraLength = 0;
|
||||||
ULONG Flags = IrpSp->Flags;
|
ULONG Flags = IrpSp->Flags;
|
||||||
KPROCESSOR_MODE RequestorMode =
|
KPROCESSOR_MODE RequestorMode =
|
||||||
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
||||||
@ -292,6 +312,7 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
BOOLEAN HasRestorePrivilege =
|
BOOLEAN HasRestorePrivilege =
|
||||||
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_RESTORE_PRIVILEGE);
|
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_RESTORE_PRIVILEGE);
|
||||||
BOOLEAN HasTrailingBackslash = FALSE;
|
BOOLEAN HasTrailingBackslash = FALSE;
|
||||||
|
BOOLEAN EaIsReparsePoint = FALSE;
|
||||||
FSP_FILE_NODE *FileNode, *RelatedFileNode;
|
FSP_FILE_NODE *FileNode, *RelatedFileNode;
|
||||||
FSP_FILE_DESC *FileDesc;
|
FSP_FILE_DESC *FileDesc;
|
||||||
UNICODE_STRING MainFileName = { 0 }, StreamPart = { 0 };
|
UNICODE_STRING MainFileName = { 0 }, StreamPart = { 0 };
|
||||||
@ -302,6 +323,36 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
|
if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
/* is there an AtomicCreateEcp attached? */
|
||||||
|
if (0 != AtomicCreateEcp)
|
||||||
|
{
|
||||||
|
if ((FILE_CREATE != CreateDisposition && FILE_OPEN_IF != CreateDisposition) ||
|
||||||
|
0 != EaBuffer ||
|
||||||
|
RTL_SIZEOF_THROUGH_FIELD(FSP_ATOMIC_CREATE_ECP_CONTEXT, ReparseBuffer) >
|
||||||
|
AtomicCreateEcp->Size ||
|
||||||
|
/* !!!: revisit: FlagOn*/
|
||||||
|
!FlagOn(AtomicCreateEcp->InFlags,
|
||||||
|
ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT |
|
||||||
|
ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED))
|
||||||
|
return STATUS_INVALID_PARAMETER; /* docs do not say what to return on failure! */
|
||||||
|
|
||||||
|
if (FlagOn(AtomicCreateEcp->InFlags,
|
||||||
|
ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED))
|
||||||
|
{
|
||||||
|
Result = FsRtlValidateReparsePointBuffer(AtomicCreateEcp->ReparseBufferLength,
|
||||||
|
AtomicCreateEcp->ReparseBuffer);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
/* mark that we satisfied the reparse point request, although we may fail it later! */
|
||||||
|
AtomicCreateEcp->OutFlags = ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET;
|
||||||
|
|
||||||
|
ExtraBuffer = AtomicCreateEcp->ReparseBuffer;
|
||||||
|
ExtraLength = AtomicCreateEcp->ReparseBufferLength;
|
||||||
|
EaIsReparsePoint = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* was an EA buffer specified? */
|
/* was an EA buffer specified? */
|
||||||
if (0 != EaBuffer)
|
if (0 != EaBuffer)
|
||||||
{
|
{
|
||||||
@ -318,6 +369,9 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
EaBuffer, EaLength, (PULONG)&Irp->IoStatus.Information);
|
EaBuffer, EaLength, (PULONG)&Irp->IoStatus.Information);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
|
ExtraBuffer = EaBuffer;
|
||||||
|
ExtraLength = EaLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cannot open a paging file */
|
/* cannot open a paging file */
|
||||||
@ -555,9 +609,9 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
SecurityDescriptorSize = 0;
|
SecurityDescriptorSize = 0;
|
||||||
FileAttributes = 0;
|
FileAttributes = 0;
|
||||||
|
|
||||||
/* cannot set EA on named stream */
|
/* cannot set extra buffer on named stream */
|
||||||
EaBuffer = 0;
|
ExtraBuffer = 0;
|
||||||
EaLength = 0;
|
ExtraLength = 0;
|
||||||
|
|
||||||
/* remember the main file node */
|
/* remember the main file node */
|
||||||
ASSERT(0 == FileNode->MainFileNode);
|
ASSERT(0 == FileNode->MainFileNode);
|
||||||
@ -577,8 +631,8 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
|
|
||||||
/* create the user-mode file system request */
|
/* create the user-mode file system request */
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
|
||||||
0 != EaBuffer ?
|
0 != ExtraBuffer ?
|
||||||
FSP_FSCTL_DEFAULT_ALIGN_UP(SecurityDescriptorSize) + EaLength : SecurityDescriptorSize,
|
FSP_FSCTL_DEFAULT_ALIGN_UP(SecurityDescriptorSize) + ExtraLength : SecurityDescriptorSize,
|
||||||
FspFsvolCreateRequestFini, &Request);
|
FspFsvolCreateRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
@ -616,10 +670,10 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
Request->Req.Create.DesiredAccess = DesiredAccess;
|
Request->Req.Create.DesiredAccess = DesiredAccess;
|
||||||
Request->Req.Create.GrantedAccess = GrantedAccess;
|
Request->Req.Create.GrantedAccess = GrantedAccess;
|
||||||
Request->Req.Create.ShareAccess = ShareAccess;
|
Request->Req.Create.ShareAccess = ShareAccess;
|
||||||
Request->Req.Create.Ea.Offset = 0 != EaBuffer ?
|
Request->Req.Create.Ea.Offset = 0 != ExtraBuffer ?
|
||||||
(0 != Request->Req.Create.SecurityDescriptor.Offset ?
|
(0 != Request->Req.Create.SecurityDescriptor.Offset ?
|
||||||
NEXTOFS(Request->Req.Create.SecurityDescriptor) : NEXTOFS(Request->FileName)) : 0;
|
NEXTOFS(Request->Req.Create.SecurityDescriptor) : NEXTOFS(Request->FileName)) : 0;
|
||||||
Request->Req.Create.Ea.Size = 0 != EaBuffer ? (UINT16)EaLength : 0;
|
Request->Req.Create.Ea.Size = 0 != ExtraBuffer ? (UINT16)ExtraLength : 0;
|
||||||
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
||||||
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
||||||
Request->Req.Create.HasBackupPrivilege = HasBackupPrivilege;
|
Request->Req.Create.HasBackupPrivilege = HasBackupPrivilege;
|
||||||
@ -628,10 +682,10 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
Request->Req.Create.CaseSensitive = CaseSensitive;
|
Request->Req.Create.CaseSensitive = CaseSensitive;
|
||||||
Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash;
|
Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash;
|
||||||
Request->Req.Create.NamedStream = MainFileName.Length;
|
Request->Req.Create.NamedStream = MainFileName.Length;
|
||||||
#undef NEXTOFS
|
|
||||||
|
|
||||||
Request->Req.Create.AcceptsSecurityDescriptor = 0 == Request->Req.Create.NamedStream &&
|
Request->Req.Create.AcceptsSecurityDescriptor = 0 == Request->Req.Create.NamedStream &&
|
||||||
!!FsvolDeviceExtension->VolumeParams.AllowOpenInKernelMode;
|
!!FsvolDeviceExtension->VolumeParams.AllowOpenInKernelMode;
|
||||||
|
Request->Req.Create.EaIsReparsePoint = EaIsReparsePoint;
|
||||||
|
#undef NEXTOFS
|
||||||
|
|
||||||
ASSERT(
|
ASSERT(
|
||||||
0 == StreamPart.Length && 0 == MainFileName.Length ||
|
0 == StreamPart.Length && 0 == MainFileName.Length ||
|
||||||
@ -642,10 +696,10 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
|
RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
|
||||||
SecurityDescriptor, SecurityDescriptorSize);
|
SecurityDescriptor, SecurityDescriptorSize);
|
||||||
|
|
||||||
/* copy the EA buffer (if any) into the request */
|
/* copy the extra buffer (if any) into the request */
|
||||||
if (0 != EaBuffer)
|
if (0 != ExtraBuffer)
|
||||||
RtlCopyMemory(Request->Buffer + Request->Req.Create.Ea.Offset,
|
RtlCopyMemory(Request->Buffer + Request->Req.Create.Ea.Offset,
|
||||||
EaBuffer, EaLength);
|
ExtraBuffer, ExtraLength);
|
||||||
|
|
||||||
/* fix FileNode->FileName if we are doing SL_OPEN_TARGET_DIRECTORY */
|
/* fix FileNode->FileName if we are doing SL_OPEN_TARGET_DIRECTORY */
|
||||||
if (Request->Req.Create.OpenTargetDirectory)
|
if (Request->Req.Create.OpenTargetDirectory)
|
||||||
|
@ -252,6 +252,8 @@ const char *FileInformationClassSym(FILE_INFORMATION_CLASS FileInformationClass)
|
|||||||
SYM(FileReplaceCompletionInformation)
|
SYM(FileReplaceCompletionInformation)
|
||||||
SYM(FileHardLinkFullIdInformation)
|
SYM(FileHardLinkFullIdInformation)
|
||||||
SYM(FileIdExtdBothDirectoryInformation)
|
SYM(FileIdExtdBothDirectoryInformation)
|
||||||
|
case 68: return "FileStatInformation";
|
||||||
|
case 70: return "FileStatLxInformation";
|
||||||
default:
|
default:
|
||||||
return "FILE_INFORMATION_CLASS:Unknown";
|
return "FILE_INFORMATION_CLASS:Unknown";
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
static NTSTATUS FspFsvrtDeviceControl(
|
static NTSTATUS FspFsvrtDeviceControl(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
static BOOLEAN FspFsvrtDeviceControlStorageQuery(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
PNTSTATUS PResult);
|
||||||
static NTSTATUS FspFsvolDeviceControl(
|
static NTSTATUS FspFsvolDeviceControl(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
|
||||||
@ -31,6 +34,7 @@ FSP_DRIVER_DISPATCH FspDeviceControl;
|
|||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspFsvrtDeviceControl)
|
#pragma alloc_text(PAGE, FspFsvrtDeviceControl)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvrtDeviceControlStorageQuery)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
|
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
|
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
|
||||||
@ -43,10 +47,18 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
static NTSTATUS FspFsvrtDeviceControl(
|
static NTSTATUS FspFsvrtDeviceControl(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (FspFsvrtDeviceControlStorageQuery(FsvrtDeviceObject, Irp, IrpSp, &Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
if (FspMountdevDeviceControl(FsvrtDeviceObject, Irp, IrpSp, &Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fix GitHub issue #177. All credit for the investigation of this issue
|
* Fix GitHub issue #177. All credit for the investigation of this issue
|
||||||
* and the suggested steps to reproduce and work around the problem goes
|
* and the suggested steps to reproduce and work around the problem goes
|
||||||
@ -64,6 +76,62 @@ static NTSTATUS FspFsvrtDeviceControl(
|
|||||||
return STATUS_UNRECOGNIZED_VOLUME;
|
return STATUS_UNRECOGNIZED_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOLEAN FspFsvrtDeviceControlStorageQuery(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SQL Server insists on sending us storage level IOCTL's even though
|
||||||
|
* WinFsp file systems are not on top of a real disk. So bite the bullet
|
||||||
|
* and implement some of those storage IOCTL's to make SQL Server happy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (IOCTL_STORAGE_QUERY_PROPERTY != IrpSp->Parameters.DeviceIoControl.IoControlCode ||
|
||||||
|
sizeof(STORAGE_PROPERTY_QUERY) > IrpSp->Parameters.DeviceIoControl.InputBufferLength)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
PSTORAGE_PROPERTY_QUERY Query = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
switch (Query->PropertyId)
|
||||||
|
{
|
||||||
|
case StorageAccessAlignmentProperty:
|
||||||
|
if (PropertyExistsQuery == Query->QueryType)
|
||||||
|
*PResult = STATUS_SUCCESS;
|
||||||
|
else if (PropertyStandardQuery == Query->QueryType)
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR Descriptor = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
|
||||||
|
if (sizeof(STORAGE_DESCRIPTOR_HEADER) > OutputBufferLength)
|
||||||
|
*PResult = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else if (sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR) > OutputBufferLength)
|
||||||
|
{
|
||||||
|
Descriptor->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
|
||||||
|
Descriptor->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
|
||||||
|
Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
|
||||||
|
*PResult = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlZeroMemory(Descriptor, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));
|
||||||
|
Descriptor->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
|
||||||
|
Descriptor->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
|
||||||
|
Descriptor->BytesPerLogicalSector = FsvrtDeviceExtension->SectorSize;
|
||||||
|
Descriptor->BytesPerPhysicalSector = FsvrtDeviceExtension->SectorSize;
|
||||||
|
Irp->IoStatus.Information = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
|
||||||
|
*PResult = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*PResult = STATUS_NOT_SUPPORTED;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolDeviceControl(
|
static NTSTATUS FspFsvolDeviceControl(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -72,6 +140,15 @@ static NTSTATUS FspFsvolDeviceControl(
|
|||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possibly forward the IOCTL request to the user mode file system. The rules are:
|
||||||
|
*
|
||||||
|
* - File system must support DeviceControl.
|
||||||
|
* - Only IOCTL with custom devices (see DEVICE_TYPE_FROM_CTL_CODE) and
|
||||||
|
* METHOD_BUFFERED will be forwarded.
|
||||||
|
*/
|
||||||
|
|
||||||
/* do we support DeviceControl? */
|
/* do we support DeviceControl? */
|
||||||
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
|
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
|
||||||
@ -90,7 +167,6 @@ static NTSTATUS FspFsvolDeviceControl(
|
|||||||
if (!FspFileNodeIsValid(FileObject->FsContext))
|
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
NTSTATUS Result;
|
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
@ -126,10 +126,12 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
|||||||
case FspFsvolDeviceExtensionKind:
|
case FspFsvolDeviceExtensionKind:
|
||||||
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
|
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
|
||||||
break;
|
break;
|
||||||
|
case FspFsvrtDeviceExtensionKind:
|
||||||
|
DeviceExtensionSize = sizeof(FSP_FSVRT_DEVICE_EXTENSION);
|
||||||
|
break;
|
||||||
case FspFsmupDeviceExtensionKind:
|
case FspFsmupDeviceExtensionKind:
|
||||||
DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION);
|
DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION);
|
||||||
break;
|
break;
|
||||||
case FspFsvrtDeviceExtensionKind:
|
|
||||||
case FspFsctlDeviceExtensionKind:
|
case FspFsctlDeviceExtensionKind:
|
||||||
DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION);
|
DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION);
|
||||||
break;
|
break;
|
||||||
@ -184,10 +186,12 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
|||||||
case FspFsvolDeviceExtensionKind:
|
case FspFsvolDeviceExtensionKind:
|
||||||
Result = FspFsvolDeviceInit(DeviceObject);
|
Result = FspFsvolDeviceInit(DeviceObject);
|
||||||
break;
|
break;
|
||||||
|
case FspFsvrtDeviceExtensionKind:
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
case FspFsmupDeviceExtensionKind:
|
case FspFsmupDeviceExtensionKind:
|
||||||
Result = FspFsmupDeviceInit(DeviceObject);
|
Result = FspFsmupDeviceInit(DeviceObject);
|
||||||
break;
|
break;
|
||||||
case FspFsvrtDeviceExtensionKind:
|
|
||||||
case FspFsctlDeviceExtensionKind:
|
case FspFsctlDeviceExtensionKind:
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
@ -213,10 +217,11 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
|||||||
case FspFsvolDeviceExtensionKind:
|
case FspFsvolDeviceExtensionKind:
|
||||||
FspFsvolDeviceFini(DeviceObject);
|
FspFsvolDeviceFini(DeviceObject);
|
||||||
break;
|
break;
|
||||||
|
case FspFsvrtDeviceExtensionKind:
|
||||||
|
break;
|
||||||
case FspFsmupDeviceExtensionKind:
|
case FspFsmupDeviceExtensionKind:
|
||||||
FspFsmupDeviceFini(DeviceObject);
|
FspFsmupDeviceFini(DeviceObject);
|
||||||
break;
|
break;
|
||||||
case FspFsvrtDeviceExtensionKind:
|
|
||||||
case FspFsctlDeviceExtensionKind:
|
case FspFsctlDeviceExtensionKind:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -325,6 +330,22 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
* to track what has been initialized!
|
* to track what has been initialized!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* initialize any fsext provider */
|
||||||
|
if (0 != FsvolDeviceExtension->VolumeParams.FsextControlCode)
|
||||||
|
{
|
||||||
|
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||||
|
FsvolDeviceExtension->VolumeParams.FsextControlCode, 0);
|
||||||
|
if (0 != Provider)
|
||||||
|
{
|
||||||
|
Result = Provider->DeviceInit(DeviceObject, &FsvolDeviceExtension->VolumeParams);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
FsvolDeviceExtension->InitDoneFsext = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
/* is there a virtual disk? */
|
/* is there a virtual disk? */
|
||||||
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
||||||
{
|
{
|
||||||
@ -500,6 +521,15 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
|||||||
if (0 != FsvolDeviceExtension->SwapVpb)
|
if (0 != FsvolDeviceExtension->SwapVpb)
|
||||||
FspFreeExternal(FsvolDeviceExtension->SwapVpb);
|
FspFreeExternal(FsvolDeviceExtension->SwapVpb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* finalize any fsext provider */
|
||||||
|
if (FsvolDeviceExtension->InitDoneFsext)
|
||||||
|
{
|
||||||
|
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||||
|
FsvolDeviceExtension->VolumeParams.FsextControlCode, 0);
|
||||||
|
if (0 != Provider)
|
||||||
|
Provider->DeviceFini(DeviceObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspFsvolDeviceTimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
|
static VOID FspFsvolDeviceTimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
|
||||||
@ -546,6 +576,14 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
|
|||||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->SecurityCache, InterruptTime);
|
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->SecurityCache, InterruptTime);
|
||||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->DirInfoCache, InterruptTime);
|
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->DirInfoCache, InterruptTime);
|
||||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->StreamInfoCache, InterruptTime);
|
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->StreamInfoCache, InterruptTime);
|
||||||
|
/* run any fsext provider expiration routine */
|
||||||
|
if (0 != FsvolDeviceExtension->VolumeParams.FsextControlCode)
|
||||||
|
{
|
||||||
|
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||||
|
FsvolDeviceExtension->VolumeParams.FsextControlCode, 0);
|
||||||
|
if (0 != Provider)
|
||||||
|
Provider->DeviceExpirationRoutine(DeviceObject, InterruptTime);
|
||||||
|
}
|
||||||
FspIoqRemoveExpired(FsvolDeviceExtension->Ioq, InterruptTime);
|
FspIoqRemoveExpired(FsvolDeviceExtension->Ioq, InterruptTime);
|
||||||
|
|
||||||
KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);
|
KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);
|
||||||
|
137
src/sys/driver.h
137
src/sys/driver.h
@ -26,9 +26,12 @@
|
|||||||
|
|
||||||
#define POOL_NX_OPTIN 1
|
#define POOL_NX_OPTIN 1
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
|
#include <mountdev.h>
|
||||||
|
#include <ntddstor.h>
|
||||||
#include <ntstrsafe.h>
|
#include <ntstrsafe.h>
|
||||||
#include <wdmsec.h>
|
#include <wdmsec.h>
|
||||||
#include <winfsp/fsctl.h>
|
#include <winfsp/fsctl.h>
|
||||||
|
#include <winfsp/fsext.h>
|
||||||
|
|
||||||
/* disable warnings */
|
/* disable warnings */
|
||||||
#pragma warning(disable:4100) /* unreferenced formal parameter */
|
#pragma warning(disable:4100) /* unreferenced formal parameter */
|
||||||
@ -36,6 +39,12 @@
|
|||||||
|
|
||||||
#define DRIVER_NAME FSP_FSCTL_DRIVER_NAME
|
#define DRIVER_NAME FSP_FSCTL_DRIVER_NAME
|
||||||
|
|
||||||
|
#if _WIN64
|
||||||
|
#define FSP_REGKEY "\\Registry\\Machine\\Software\\WOW6432Node\\WinFsp"
|
||||||
|
#else
|
||||||
|
#define FSP_REGKEY "\\Registry\\Machine\\Software\\WinFsp"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* IoCreateDeviceSecure default SDDL's */
|
/* IoCreateDeviceSecure default SDDL's */
|
||||||
#define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)"
|
#define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)"
|
||||||
/* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ */
|
/* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ */
|
||||||
@ -486,14 +495,28 @@ NTSTATUS FspFileNameInExpression(
|
|||||||
PWCH UpcaseTable,
|
PWCH UpcaseTable,
|
||||||
PBOOLEAN PResult);
|
PBOOLEAN PResult);
|
||||||
|
|
||||||
|
/* UUID5 creation (ku) */
|
||||||
|
NTSTATUS FspUuid5Make(const UUID *Namespace, const VOID *Buffer, ULONG Size, UUID *Uuid);
|
||||||
|
|
||||||
/* utility */
|
/* utility */
|
||||||
PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag);
|
PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag);
|
||||||
PVOID FspAllocateIrpMustSucceed(CCHAR StackSize);
|
PVOID FspAllocateIrpMustSucceed(CCHAR StackSize);
|
||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
||||||
|
NTSTATUS FspRegistryGetValue(PUNICODE_STRING Path, PUNICODE_STRING ValueName,
|
||||||
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInformation, PULONG PValueInformationLength);
|
||||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||||
|
NTSTATUS FspSendQuerySecurityIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
SECURITY_INFORMATION SecurityInformation,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
PULONG PLength);
|
||||||
|
NTSTATUS FspSendQueryEaIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, PULONG PEaLength);
|
||||||
|
NTSTATUS FspSendMountmgrDeviceControlIrp(ULONG IoControlCode,
|
||||||
|
PVOID SystemBuffer, ULONG InputBufferLength, PULONG POutputBufferLength);
|
||||||
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||||
NTSTATUS FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
NTSTATUS FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||||
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress, ULONG ExtraPriorityFlags);
|
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress, ULONG ExtraPriorityFlags);
|
||||||
@ -1048,7 +1071,8 @@ typedef struct
|
|||||||
{
|
{
|
||||||
FSP_DEVICE_EXTENSION Base;
|
FSP_DEVICE_EXTENSION Base;
|
||||||
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1, InitDoneEa:1,
|
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1, InitDoneEa:1,
|
||||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1,
|
||||||
|
InitDoneFsext;
|
||||||
PDEVICE_OBJECT FsctlDeviceObject;
|
PDEVICE_OBJECT FsctlDeviceObject;
|
||||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||||
PDEVICE_OBJECT FsvolDeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject;
|
||||||
@ -1078,8 +1102,19 @@ typedef struct
|
|||||||
PNOTIFY_SYNC NotifySync;
|
PNOTIFY_SYNC NotifySync;
|
||||||
LIST_ENTRY NotifyList;
|
LIST_ENTRY NotifyList;
|
||||||
FSP_STATISTICS *Statistics;
|
FSP_STATISTICS *Statistics;
|
||||||
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 FsextData[];
|
||||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||||
typedef struct
|
typedef struct
|
||||||
|
{
|
||||||
|
FSP_DEVICE_EXTENSION Base;
|
||||||
|
UINT16 SectorSize;
|
||||||
|
LONG IsMountdev;
|
||||||
|
BOOLEAN Persistent;
|
||||||
|
GUID UniqueId;
|
||||||
|
UNICODE_STRING VolumeName;
|
||||||
|
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||||
|
} FSP_FSVRT_DEVICE_EXTENSION;
|
||||||
|
typedef struct
|
||||||
{
|
{
|
||||||
FSP_DEVICE_EXTENSION Base;
|
FSP_DEVICE_EXTENSION Base;
|
||||||
UINT32 InitDonePfxTab:1;
|
UINT32 InitDonePfxTab:1;
|
||||||
@ -1099,6 +1134,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
|||||||
return DeviceObject->DeviceExtension;
|
return DeviceObject->DeviceExtension;
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FspFsvrtDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
ASSERT(FspFsvrtDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||||
|
return DeviceObject->DeviceExtension;
|
||||||
|
}
|
||||||
|
static inline
|
||||||
FSP_FSMUP_DEVICE_EXTENSION *FspFsmupDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
FSP_FSMUP_DEVICE_EXTENSION *FspFsmupDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||||
@ -1169,6 +1210,9 @@ VOID FspDeviceGlobalUnlock(VOID)
|
|||||||
//(FILE_DEVICE_DISK_FILE_SYSTEM == (DeviceObject)->DeviceType ?\
|
//(FILE_DEVICE_DISK_FILE_SYSTEM == (DeviceObject)->DeviceType ?\
|
||||||
// STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED)
|
// STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED)
|
||||||
|
|
||||||
|
/* fsext */
|
||||||
|
FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 FsextControlCode, PNTSTATUS PLoadResult);
|
||||||
|
|
||||||
/* process buffers conditional usage */
|
/* process buffers conditional usage */
|
||||||
static inline
|
static inline
|
||||||
BOOLEAN FspReadIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
BOOLEAN FspReadIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||||
@ -1200,6 +1244,20 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* mountdev */
|
||||||
|
NTSTATUS FspMountdevQueryDeviceName(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspMountdevQueryUniqueId(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
BOOLEAN FspMountdevDeviceControl(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
PNTSTATUS PResult);
|
||||||
|
NTSTATUS FspMountdevMake(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
BOOLEAN Persistent);
|
||||||
|
VOID FspMountdevFini(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||||
|
|
||||||
/* fsmup */
|
/* fsmup */
|
||||||
NTSTATUS FspMupRegister(
|
NTSTATUS FspMupRegister(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
@ -1209,19 +1267,22 @@ NTSTATUS FspMupHandleIrp(
|
|||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||||
|
|
||||||
/* volume management */
|
/* volume management */
|
||||||
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
|
||||||
NTSTATUS FspVolumeCreate(
|
NTSTATUS FspVolumeCreate(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
VOID FspVolumeDelete(
|
VOID FspVolumeDelete(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeMount(
|
NTSTATUS FspVolumeMount(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeMakeMountdev(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetName(
|
NTSTATUS FspVolumeGetName(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetNameList(
|
NTSTATUS FspVolumeGetNameList(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeTransact(
|
NTSTATUS FspVolumeTransact(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeTransactFsext(
|
||||||
|
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 FspVolumeWork(
|
NTSTATUS FspVolumeWork(
|
||||||
@ -1571,7 +1632,7 @@ NTSTATUS FspFileNodeOplockCheckAsyncEx(
|
|||||||
CompletionRoutine,
|
CompletionRoutine,
|
||||||
PostIrpRoutine);
|
PostIrpRoutine);
|
||||||
#if DBG
|
#if DBG
|
||||||
if (STATUS_SUCCESS == Result && DEBUGTEST(10))
|
if (DEBUGTEST_EX(STATUS_SUCCESS == Result, 10, FALSE))
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
@ -1636,4 +1697,74 @@ LOGICAL RtlEqualMemory(const VOID *Source1, const VOID *Source2, SIZE_T Length)
|
|||||||
return Length == RtlCompareMemory(Source1, Source2, Length);
|
return Length == RtlCompareMemory(Source1, Source2, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FILE_STAT_INFORMATION and FILE_STAT_LX_INFORMATION are missings on some WDK's. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
LARGE_INTEGER FileId;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG ReparseTag;
|
||||||
|
ULONG NumberOfLinks;
|
||||||
|
ACCESS_MASK EffectiveAccess;
|
||||||
|
} FSP_FILE_STAT_INFORMATION, *PFSP_FILE_STAT_INFORMATION;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
LARGE_INTEGER FileId;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG ReparseTag;
|
||||||
|
ULONG NumberOfLinks;
|
||||||
|
ACCESS_MASK EffectiveAccess;
|
||||||
|
ULONG LxFlags;
|
||||||
|
ULONG LxUid;
|
||||||
|
ULONG LxGid;
|
||||||
|
ULONG LxMode;
|
||||||
|
ULONG LxDeviceIdMajor;
|
||||||
|
ULONG LxDeviceIdMinor;
|
||||||
|
} FSP_FILE_STAT_LX_INFORMATION, *PFSP_FILE_STAT_LX_INFORMATION;
|
||||||
|
|
||||||
|
/* ATOMIC_CREATE_ECP_CONTEXT is missing on some WDK's */
|
||||||
|
#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED 0x0002
|
||||||
|
#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET 0x0002
|
||||||
|
#define ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT 0x0100
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
} FSP_FILE_TIMESTAMPS, *PFSP_FILE_TIMESTAMPS;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT Size;
|
||||||
|
USHORT InFlags;
|
||||||
|
USHORT OutFlags;
|
||||||
|
USHORT ReparseBufferLength;
|
||||||
|
PREPARSE_DATA_BUFFER ReparseBuffer;
|
||||||
|
LONGLONG FileSize;
|
||||||
|
LONGLONG ValidDataLength;
|
||||||
|
PFSP_FILE_TIMESTAMPS FileTimestamps;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG UsnSourceInfo;
|
||||||
|
USN Usn;
|
||||||
|
ULONG SuppressFileAttributeInheritanceMask;
|
||||||
|
ULONG InOpFlags;
|
||||||
|
ULONG OutOpFlags;
|
||||||
|
ULONG InGenFlags;
|
||||||
|
ULONG OutGenFlags;
|
||||||
|
ULONG CaseSensitiveFlagsMask;
|
||||||
|
ULONG InCaseSensitiveFlags;
|
||||||
|
ULONG OutCaseSensitiveFlags;
|
||||||
|
} FSP_ATOMIC_CREATE_ECP_CONTEXT, *PFSP_ATOMIC_CREATE_ECP_CONTEXT;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,6 +55,7 @@ FSP_DRIVER_DISPATCH FspSetEa;
|
|||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaGetCopy)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaGetCopy)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaIndexCopy)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaIndexCopy)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryEaCopy)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEa)
|
#pragma alloc_text(PAGE, FspFsvolQueryEa)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaComplete)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaRequestFini)
|
||||||
|
@ -45,6 +45,15 @@ static NTSTATUS FspFsvolQueryPositionInformation(PFILE_OBJECT FileObject,
|
|||||||
static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd,
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryStatBaseInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryStatLxBaseInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryStatLxEaInformation(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd);
|
||||||
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
||||||
FSP_FSCTL_STREAM_INFO *StreamInfoBuffer, ULONG StreamInfoBufferSize,
|
FSP_FSCTL_STREAM_INFO *StreamInfoBuffer, ULONG StreamInfoBufferSize,
|
||||||
PVOID DestBuf, PULONG PDestLen);
|
PVOID DestBuf, PULONG PDestLen);
|
||||||
@ -52,6 +61,9 @@ static NTSTATUS FspFsvolQueryStreamInformation(
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolQueryStreamInformationSuccess(
|
static NTSTATUS FspFsvolQueryStreamInformationSuccess(
|
||||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
static NTSTATUS FspFsvolQueryInformationEffectiveAccess(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PACCESS_MASK PEffectiveAccess);
|
||||||
static NTSTATUS FspFsvolQueryInformation(
|
static NTSTATUS FspFsvolQueryInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
|
||||||
@ -97,9 +109,13 @@ FAST_IO_QUERY_OPEN FspFastIoQueryOpen;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryPositionInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryPositionInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryStatBaseInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryStatLxBaseInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryStatLxEaInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationCopy)
|
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationCopy)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationSuccess)
|
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationSuccess)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryInformationEffectiveAccess)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInformationComplete)
|
#pragma alloc_text(PAGE, FspFsvolQueryInformationComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini)
|
||||||
@ -301,7 +317,7 @@ static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject,
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
|
||||||
if ((PVOID)(Info + 1) > BufferEnd)
|
if ((PVOID)((PUINT8)Info + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName)) > BufferEnd)
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
FspFileNodeAcquireShared(FileNode, Main);
|
FspFileNodeAcquireShared(FileNode, Main);
|
||||||
@ -417,6 +433,187 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryStatBaseInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
|
const FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PFSP_FILE_STAT_INFORMATION Info = (PFSP_FILE_STAT_INFORMATION)*PBuffer;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
if (0 == FileInfo)
|
||||||
|
{
|
||||||
|
if ((PVOID)(Info + 1) > BufferEnd)
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info->FileId.QuadPart = FileNode->IndexNumber;
|
||||||
|
Info->CreationTime.QuadPart = FileInfo->CreationTime;
|
||||||
|
Info->LastAccessTime.QuadPart = FileInfo->LastAccessTime;
|
||||||
|
Info->LastWriteTime.QuadPart = FileInfo->LastWriteTime;
|
||||||
|
Info->ChangeTime.QuadPart = FileInfo->ChangeTime;
|
||||||
|
Info->AllocationSize.QuadPart = FileInfo->AllocationSize;
|
||||||
|
Info->EndOfFile.QuadPart = FileInfo->FileSize;
|
||||||
|
Info->FileAttributes = 0 != FileInfo->FileAttributes ?
|
||||||
|
FileInfo->FileAttributes : FILE_ATTRIBUTE_NORMAL;
|
||||||
|
Info->ReparseTag = FileInfo->ReparseTag;
|
||||||
|
Info->NumberOfLinks = 1;
|
||||||
|
|
||||||
|
*PBuffer = (PVOID)(Info + 1);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryStatLxBaseInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
|
const FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PFSP_FILE_STAT_LX_INFORMATION Info = (PFSP_FILE_STAT_LX_INFORMATION)*PBuffer;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
|
||||||
|
if (0 == FileInfo)
|
||||||
|
{
|
||||||
|
if ((PVOID)(Info + 1) > BufferEnd)
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info->FileId.QuadPart = FileNode->IndexNumber;
|
||||||
|
Info->CreationTime.QuadPart = FileInfo->CreationTime;
|
||||||
|
Info->LastAccessTime.QuadPart = FileInfo->LastAccessTime;
|
||||||
|
Info->LastWriteTime.QuadPart = FileInfo->LastWriteTime;
|
||||||
|
Info->ChangeTime.QuadPart = FileInfo->ChangeTime;
|
||||||
|
Info->AllocationSize.QuadPart = FileInfo->AllocationSize;
|
||||||
|
Info->EndOfFile.QuadPart = FileInfo->FileSize;
|
||||||
|
Info->FileAttributes = 0 != FileInfo->FileAttributes ?
|
||||||
|
FileInfo->FileAttributes : FILE_ATTRIBUTE_NORMAL;
|
||||||
|
Info->ReparseTag = FileInfo->ReparseTag;
|
||||||
|
Info->NumberOfLinks = 1;
|
||||||
|
|
||||||
|
*PBuffer = (PVOID)(Info + 1);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryStatLxEaInformation(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd)
|
||||||
|
{
|
||||||
|
#define ADD_GET_EA(Name, End) \
|
||||||
|
GetEa->NextEntryOffset = (ULONG)(End ? 0 :\
|
||||||
|
FSP_FSCTL_ALIGN_UP( \
|
||||||
|
FIELD_OFFSET(FILE_GET_EA_INFORMATION, EaName) + sizeof("" Name),\
|
||||||
|
sizeof(ULONG))); \
|
||||||
|
GetEa->EaNameLength = (UCHAR)(sizeof("" Name) - 1);\
|
||||||
|
RtlCopyMemory(GetEa->EaName, "" Name, sizeof("" Name));\
|
||||||
|
GetEaLength = (ULONG)((PUINT8)GetEa - (PUINT8)&GetEaBuf.V +\
|
||||||
|
FIELD_OFFSET(FILE_GET_EA_INFORMATION, EaName) + sizeof("" Name));\
|
||||||
|
GetEa = (PVOID)((PUINT8)GetEa + GetEa->NextEntryOffset);
|
||||||
|
#define EQUAL_EA_NAME(Name) \
|
||||||
|
CmpName.Length = \
|
||||||
|
CmpName.MaximumLength = sizeof("" Name) - 1,\
|
||||||
|
CmpName.Buffer = "" Name, \
|
||||||
|
RtlEqualString(&CmpName, &EaName, TRUE/* always case-insensitive */)
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PFSP_FILE_STAT_LX_INFORMATION Info = (PFSP_FILE_STAT_LX_INFORMATION)*PBuffer;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FILE_GET_EA_INFORMATION V;
|
||||||
|
UINT8 B[64];
|
||||||
|
} GetEaBuf;
|
||||||
|
PFILE_GET_EA_INFORMATION GetEa = &GetEaBuf.V;
|
||||||
|
ULONG GetEaLength = 0;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FILE_FULL_EA_INFORMATION V;
|
||||||
|
UINT8 B[128];
|
||||||
|
} EaBuf;
|
||||||
|
ULONG EaLength = sizeof EaBuf;
|
||||||
|
STRING EaName, CmpName;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Info->LxFlags = 0;
|
||||||
|
Info->LxUid = 0;
|
||||||
|
Info->LxGid = 0;
|
||||||
|
Info->LxMode = 0;
|
||||||
|
Info->LxDeviceIdMajor = 0;
|
||||||
|
Info->LxDeviceIdMinor = 0;
|
||||||
|
|
||||||
|
if (!FsvolDeviceExtension->VolumeParams.ExtendedAttributes)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
ADD_GET_EA("$LXUID", 0);
|
||||||
|
ADD_GET_EA("$LXGID", 0);
|
||||||
|
ADD_GET_EA("$LXMOD", 0);
|
||||||
|
ADD_GET_EA("$LXDEV", 1);
|
||||||
|
|
||||||
|
Result = FspSendQueryEaIrp(FsvolDeviceObject/* bypass filters */, FileObject,
|
||||||
|
&GetEaBuf.V, GetEaLength,
|
||||||
|
&EaBuf.V, &EaLength);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
for (PFILE_FULL_EA_INFORMATION Ea = &EaBuf.V, EaEnd = (PVOID)((PUINT8)Ea + EaLength);
|
||||||
|
EaEnd > Ea; Ea = FSP_NEXT_EA(Ea, EaEnd))
|
||||||
|
{
|
||||||
|
EaName.Length =
|
||||||
|
EaName.MaximumLength = Ea->EaNameLength,
|
||||||
|
EaName.Buffer = Ea->EaName;
|
||||||
|
|
||||||
|
if (EQUAL_EA_NAME("$LXUID"))
|
||||||
|
{
|
||||||
|
if (sizeof(ULONG) == Ea->EaValueLength)
|
||||||
|
{
|
||||||
|
Info->LxFlags |= 0x1/*LX_FILE_METADATA_HAS_UID*/;
|
||||||
|
Info->LxUid = *(PULONG)(Ea->EaName + sizeof "$LXUID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (EQUAL_EA_NAME("$LXGID"))
|
||||||
|
{
|
||||||
|
if (sizeof(ULONG) == Ea->EaValueLength)
|
||||||
|
{
|
||||||
|
Info->LxFlags |= 0x2/*LX_FILE_METADATA_HAS_GID*/;
|
||||||
|
Info->LxGid = *(PULONG)(Ea->EaName + sizeof "$LXGID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (EQUAL_EA_NAME("$LXMOD"))
|
||||||
|
{
|
||||||
|
if (sizeof(ULONG) == Ea->EaValueLength)
|
||||||
|
{
|
||||||
|
Info->LxFlags |= 0x4/*LX_FILE_METADATA_HAS_MODE*/;
|
||||||
|
Info->LxMode = *(PULONG)(Ea->EaName + sizeof "$LXMOD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (EQUAL_EA_NAME("$LXDEV"))
|
||||||
|
{
|
||||||
|
if (sizeof(UINT64) == Ea->EaValueLength)
|
||||||
|
{
|
||||||
|
Info->LxFlags |= 0x8/*LX_FILE_METADATA_HAS_DEVICE_ID*/;
|
||||||
|
UINT64 Dev = *(PUINT64)(Ea->EaName + sizeof "$LXDEV");
|
||||||
|
Info->LxDeviceIdMajor = (Dev >> 32) & 0xffffffff;
|
||||||
|
Info->LxDeviceIdMinor = Dev & 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
#undef EQUAL_EA_NAME
|
||||||
|
#undef ADD_GET_EA
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
||||||
FSP_FSCTL_STREAM_INFO *StreamInfo, ULONG StreamInfoSize,
|
FSP_FSCTL_STREAM_INFO *StreamInfo, ULONG StreamInfoSize,
|
||||||
PVOID DestBuf, PULONG PDestLen)
|
PVOID DestBuf, PULONG PDestLen)
|
||||||
@ -646,6 +843,71 @@ static NTSTATUS FspFsvolQueryStreamInformationSuccess(
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryInformationEffectiveAccess(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PACCESS_MASK PEffectiveAccess)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SECURITY_DESCRIPTOR V;
|
||||||
|
UINT8 B[256];
|
||||||
|
} SecurityDescriptorBuf;
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor = &SecurityDescriptorBuf.V;
|
||||||
|
ULONG Length;
|
||||||
|
SECURITY_SUBJECT_CONTEXT SecuritySubjectContext;
|
||||||
|
ACCESS_MASK EffectiveAccess;
|
||||||
|
NTSTATUS Result;
|
||||||
|
BOOLEAN AccessResult;
|
||||||
|
|
||||||
|
*PEffectiveAccess = 0;
|
||||||
|
|
||||||
|
Length = sizeof SecurityDescriptorBuf;
|
||||||
|
Result = FspSendQuerySecurityIrp(FsvolDeviceObject/* bypass filters */, FileObject,
|
||||||
|
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||||
|
SecurityDescriptor, &Length);
|
||||||
|
if (STATUS_BUFFER_OVERFLOW == Result)
|
||||||
|
{
|
||||||
|
SecurityDescriptor = FspAlloc(Length);
|
||||||
|
if (0 == SecurityDescriptor)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspSendQuerySecurityIrp(FsvolDeviceObject/* bypass filters */, FileObject,
|
||||||
|
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||||
|
SecurityDescriptor, &Length);
|
||||||
|
}
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
SeCaptureSubjectContext(&SecuritySubjectContext);
|
||||||
|
|
||||||
|
AccessResult = SeAccessCheck(
|
||||||
|
SecurityDescriptor,
|
||||||
|
&SecuritySubjectContext,
|
||||||
|
FALSE,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
IoGetFileObjectGenericMapping(),
|
||||||
|
UserMode,
|
||||||
|
&EffectiveAccess,
|
||||||
|
&Result);
|
||||||
|
if (!AccessResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*PEffectiveAccess = EffectiveAccess;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (&SecurityDescriptorBuf.V != SecurityDescriptor && 0 != SecurityDescriptor)
|
||||||
|
FspFree(SecurityDescriptor);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryInformation(
|
static NTSTATUS FspFsvolQueryInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -720,6 +982,18 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
case FileStandardInformation:
|
case FileStandardInformation:
|
||||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, 0);
|
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||||
break;
|
break;
|
||||||
|
case 68/*FileStatInformation*/:
|
||||||
|
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.WslFeatures)
|
||||||
|
Result = FspFsvolQueryStatBaseInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||||
|
else
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
case 70/*FileStatLxInformation*/:
|
||||||
|
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.WslFeatures)
|
||||||
|
Result = FspFsvolQueryStatLxBaseInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||||
|
else
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
return Result;
|
return Result;
|
||||||
@ -729,6 +1003,26 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
FspFileNodeAcquireShared(FileNode, Main);
|
FspFileNodeAcquireShared(FileNode, Main);
|
||||||
|
|
||||||
|
switch (FileInformationClass)
|
||||||
|
{
|
||||||
|
case 68/*FileStatInformation*/:
|
||||||
|
FspFsvolQueryInformationEffectiveAccess(
|
||||||
|
FsvolDeviceObject, FileObject, &((FSP_FILE_STAT_INFORMATION *)Buffer)->EffectiveAccess);
|
||||||
|
break;
|
||||||
|
case 70/*FileStatLxInformation*/:
|
||||||
|
FspFsvolQueryInformationEffectiveAccess(
|
||||||
|
FsvolDeviceObject, FileObject, &((FSP_FILE_STAT_LX_INFORMATION *)Buffer)->EffectiveAccess);
|
||||||
|
Result = FspFsvolQueryStatLxEaInformation(
|
||||||
|
FsvolDeviceObject, FileObject, &Buffer, BufferEnd);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (FspFileNodeTryGetFileInfo(FileNode, &FileInfoBuf))
|
if (FspFileNodeTryGetFileInfo(FileNode, &FileInfoBuf))
|
||||||
{
|
{
|
||||||
FspFileNodeRelease(FileNode, Main);
|
FspFileNodeRelease(FileNode, Main);
|
||||||
@ -755,6 +1049,12 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
case FileStandardInformation:
|
case FileStandardInformation:
|
||||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
break;
|
break;
|
||||||
|
case 68/*FileStatInformation*/:
|
||||||
|
Result = FspFsvolQueryStatBaseInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
|
break;
|
||||||
|
case 70/*FileStatLxInformation*/:
|
||||||
|
Result = FspFsvolQueryStatLxBaseInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
@ -865,6 +1165,12 @@ NTSTATUS FspFsvolQueryInformationComplete(
|
|||||||
case FileStandardInformation:
|
case FileStandardInformation:
|
||||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
||||||
break;
|
break;
|
||||||
|
case 68/*FileStatInformation*/:
|
||||||
|
Result = FspFsvolQueryStatBaseInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
||||||
|
break;
|
||||||
|
case 70/*FileStatLxInformation*/:
|
||||||
|
Result = FspFsvolQueryStatLxBaseInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
@ -1813,7 +2119,7 @@ BOOLEAN FspFastIoQueryBasicInfo(
|
|||||||
if (Result)
|
if (Result)
|
||||||
{
|
{
|
||||||
PVOID Buffer = Info;
|
PVOID Buffer = Info;
|
||||||
PVOID BufferEnd = (PUINT8)Info + sizeof Info;
|
PVOID BufferEnd = (PUINT8)Info + sizeof *Info;
|
||||||
NTSTATUS Result0 = FspFsvolQueryBasicInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
NTSTATUS Result0 = FspFsvolQueryBasicInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result0))
|
if (!NT_SUCCESS(Result0))
|
||||||
FSP_RETURN(Result = FALSE);
|
FSP_RETURN(Result = FALSE);
|
||||||
@ -1851,7 +2157,7 @@ BOOLEAN FspFastIoQueryStandardInfo(
|
|||||||
if (Result)
|
if (Result)
|
||||||
{
|
{
|
||||||
PVOID Buffer = Info;
|
PVOID Buffer = Info;
|
||||||
PVOID BufferEnd = (PUINT8)Info + sizeof Info;
|
PVOID BufferEnd = (PUINT8)Info + sizeof *Info;
|
||||||
NTSTATUS Result0 = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
NTSTATUS Result0 = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result0))
|
if (!NT_SUCCESS(Result0))
|
||||||
FSP_RETURN(Result = FALSE);
|
FSP_RETURN(Result = FALSE);
|
||||||
@ -1889,7 +2195,7 @@ BOOLEAN FspFastIoQueryNetworkOpenInfo(
|
|||||||
if (Result)
|
if (Result)
|
||||||
{
|
{
|
||||||
PVOID Buffer = Info;
|
PVOID Buffer = Info;
|
||||||
PVOID BufferEnd = (PUINT8)Info + sizeof Info;
|
PVOID BufferEnd = (PUINT8)Info + sizeof *Info;
|
||||||
NTSTATUS Result0 = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
NTSTATUS Result0 = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result0))
|
if (!NT_SUCCESS(Result0))
|
||||||
FSP_RETURN(Result = FALSE);
|
FSP_RETURN(Result = FALSE);
|
||||||
@ -1933,7 +2239,7 @@ BOOLEAN FspFastIoQueryOpen(
|
|||||||
if (Result)
|
if (Result)
|
||||||
{
|
{
|
||||||
PVOID Buffer = Info;
|
PVOID Buffer = Info;
|
||||||
PVOID BufferEnd = (PUINT8)Info + sizeof Info;
|
PVOID BufferEnd = (PUINT8)Info + sizeof *Info;
|
||||||
NTSTATUS Result0 = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
NTSTATUS Result0 = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||||
if (!NT_SUCCESS(Result0))
|
if (!NT_SUCCESS(Result0))
|
||||||
FSP_RETURN(Result = FALSE);
|
FSP_RETURN(Result = FALSE);
|
||||||
|
@ -77,6 +77,10 @@ static NTSTATUS FspFsctlFileSystemControl(
|
|||||||
case IRP_MN_USER_FS_REQUEST:
|
case IRP_MN_USER_FS_REQUEST:
|
||||||
switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
|
switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
|
||||||
{
|
{
|
||||||
|
case FSP_FSCTL_MOUNTDEV:
|
||||||
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
|
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
|
||||||
|
break;
|
||||||
case FSP_FSCTL_VOLUME_NAME:
|
case FSP_FSCTL_VOLUME_NAME:
|
||||||
if (0 != IrpSp->FileObject->FsContext2)
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
|
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
|
||||||
@ -86,6 +90,7 @@ static NTSTATUS FspFsctlFileSystemControl(
|
|||||||
break;
|
break;
|
||||||
case FSP_FSCTL_TRANSACT:
|
case FSP_FSCTL_TRANSACT:
|
||||||
case FSP_FSCTL_TRANSACT_BATCH:
|
case FSP_FSCTL_TRANSACT_BATCH:
|
||||||
|
case FSP_FSCTL_TRANSACT_INTERNAL:
|
||||||
if (0 != IrpSp->FileObject->FsContext2)
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
Result = FspVolumeTransact(FsctlDeviceObject, Irp, IrpSp);
|
Result = FspVolumeTransact(FsctlDeviceObject, Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
@ -93,6 +98,14 @@ 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;
|
||||||
|
default:
|
||||||
|
if (CTL_CODE(0, 0xC00, 0, 0) ==
|
||||||
|
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))
|
||||||
|
{
|
||||||
|
if (0 != IrpSp->FileObject->FsContext2)
|
||||||
|
Result = FspVolumeTransactFsext(FsctlDeviceObject, Irp, IrpSp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IRP_MN_MOUNT_VOLUME:
|
case IRP_MN_MOUNT_VOLUME:
|
||||||
|
148
src/sys/fsext.c
Normal file
148
src/sys/fsext.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/**
|
||||||
|
* @file sys/fsext.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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>
|
||||||
|
#include <winfsp/fsext.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number of allowed fsext providers. This must be kept small,
|
||||||
|
* because we do a linear search to find the provider. If this changes
|
||||||
|
* the data structure used to store providers (currently 2 parallel
|
||||||
|
* arrays) must be revisited.
|
||||||
|
*/
|
||||||
|
#define FSP_FSEXT_PROVIDER_COUNTMAX 4
|
||||||
|
|
||||||
|
static KSPIN_LOCK FsextSpinLock = 0;
|
||||||
|
static UINT32 FsextControlCodes[FSP_FSEXT_PROVIDER_COUNTMAX];
|
||||||
|
static FSP_FSEXT_PROVIDER *FsextProviders[FSP_FSEXT_PROVIDER_COUNTMAX];
|
||||||
|
|
||||||
|
static inline
|
||||||
|
FSP_FSEXT_PROVIDER *FspFsextProviderGet(UINT32 FsextControlCode)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
for (ULONG I = 0; FSP_FSEXT_PROVIDER_COUNTMAX > I; I++)
|
||||||
|
if (FsextControlCode == FsextControlCodes[I])
|
||||||
|
return FsextProviders[I];
|
||||||
|
#else
|
||||||
|
/* unroll by hand */
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(4 == FSP_FSEXT_PROVIDER_COUNTMAX,
|
||||||
|
"unrolled loop expects FsextProviders to have 4 elements");
|
||||||
|
if (FsextControlCode == FsextControlCodes[0])
|
||||||
|
return FsextProviders[0];
|
||||||
|
if (FsextControlCode == FsextControlCodes[1])
|
||||||
|
return FsextProviders[1];
|
||||||
|
if (FsextControlCode == FsextControlCodes[2])
|
||||||
|
return FsextProviders[2];
|
||||||
|
if (FsextControlCode == FsextControlCodes[3])
|
||||||
|
return FsextProviders[3];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 FsextControlCode, PNTSTATUS PLoadResult)
|
||||||
|
{
|
||||||
|
FSP_FSEXT_PROVIDER *Provider;
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FsextSpinLock, &Irql);
|
||||||
|
Provider = FspFsextProviderGet(FsextControlCode);
|
||||||
|
KeReleaseSpinLock(&FsextSpinLock, Irql);
|
||||||
|
ASSERT(0 == Provider || FsextControlCode == Provider->DeviceTransactCode);
|
||||||
|
|
||||||
|
if (0 != PLoadResult)
|
||||||
|
{
|
||||||
|
if (0 == Provider)
|
||||||
|
{
|
||||||
|
WCHAR Buf[64 + 256];
|
||||||
|
UNICODE_STRING Path;
|
||||||
|
UNICODE_STRING Name;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
KEY_VALUE_PARTIAL_INFORMATION V;
|
||||||
|
UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + 256];
|
||||||
|
} Value;
|
||||||
|
ULONG Length;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&Path, L"" FSP_REGKEY "\\Fsext");
|
||||||
|
RtlInitEmptyUnicodeString(&Name, Buf, sizeof Buf);
|
||||||
|
Result = RtlUnicodeStringPrintf(&Name, L"%08x", FsextControlCode);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
Length = sizeof Value;
|
||||||
|
Result = FspRegistryGetValue(&Path, &Name, &Value.V, &Length);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
*PLoadResult = Result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (REG_SZ != Value.V.Type)
|
||||||
|
{
|
||||||
|
*PLoadResult = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitEmptyUnicodeString(&Path, Buf, sizeof Buf);
|
||||||
|
Result = RtlUnicodeStringPrintf(&Path,
|
||||||
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s", (PWSTR)Value.V.Data);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
|
||||||
|
Result = ZwLoadDriver(&Path);
|
||||||
|
if (!NT_SUCCESS(Result) && STATUS_IMAGE_ALREADY_LOADED != Result)
|
||||||
|
{
|
||||||
|
*PLoadResult = Result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FsextSpinLock, &Irql);
|
||||||
|
Provider = FspFsextProviderGet(FsextControlCode);
|
||||||
|
KeReleaseSpinLock(&FsextSpinLock, Irql);
|
||||||
|
ASSERT(0 == Provider || FsextControlCode == Provider->DeviceTransactCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
*PLoadResult = 0 != Provider ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFsextProviderRegister(FSP_FSEXT_PROVIDER *Provider)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FsextSpinLock, &Irql);
|
||||||
|
|
||||||
|
Result = STATUS_TOO_LATE;
|
||||||
|
for (ULONG I = 0; FSP_FSEXT_PROVIDER_COUNTMAX > I; I++)
|
||||||
|
if (0 == FsextControlCodes[I])
|
||||||
|
{
|
||||||
|
Provider->DeviceExtensionOffset = FIELD_OFFSET(FSP_FSVOL_DEVICE_EXTENSION, FsextData);
|
||||||
|
FsextControlCodes[I] = Provider->DeviceTransactCode;
|
||||||
|
FsextProviders[I] = Provider;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&FsextSpinLock, Irql);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
@ -688,6 +688,12 @@ BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult)
|
|||||||
Result = FspCsqInsertIrpEx(&Ioq->RetriedIoCsq, Irp, 0, 0);
|
Result = FspCsqInsertIrpEx(&Ioq->RetriedIoCsq, Irp, 0, 0);
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
|
/* wake up a waiter */
|
||||||
|
KIRQL Irql;
|
||||||
|
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
|
||||||
|
FspIoqEventSet(&Ioq->PendingIrpEvent);
|
||||||
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
|
||||||
if (0 != PResult)
|
if (0 != PResult)
|
||||||
*PResult = STATUS_PENDING;
|
*PResult = STATUS_PENDING;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -103,7 +103,7 @@ static inline FSP_META_CACHE_ITEM *FspMetaCacheRemoveExpiredItemAtDpcLevel(FSP_M
|
|||||||
if (Head == Entry)
|
if (Head == Entry)
|
||||||
return 0;
|
return 0;
|
||||||
FSP_META_CACHE_ITEM *Item = CONTAINING_RECORD(Entry, FSP_META_CACHE_ITEM, ListEntry);
|
FSP_META_CACHE_ITEM *Item = CONTAINING_RECORD(Entry, FSP_META_CACHE_ITEM, ListEntry);
|
||||||
if (!FspExpirationTimeValid2(Item->ExpirationTime, ExpirationTime))
|
if (FspExpirationTimeValid2(Item->ExpirationTime, ExpirationTime))
|
||||||
return 0;
|
return 0;
|
||||||
ULONG HashIndex = Item->ItemIndex % MetaCache->ItemBucketCount;
|
ULONG HashIndex = Item->ItemIndex % MetaCache->ItemBucketCount;
|
||||||
for (FSP_META_CACHE_ITEM **P = (PVOID)&MetaCache->ItemBuckets[HashIndex]; *P; P = &(*P)->DictNext)
|
for (FSP_META_CACHE_ITEM **P = (PVOID)&MetaCache->ItemBuckets[HashIndex]; *P; P = &(*P)->DictNext)
|
||||||
@ -202,7 +202,7 @@ UINT64 FspMetaCacheAddItem(FSP_META_CACHE *MetaCache, PCVOID Buffer, ULONG Size)
|
|||||||
{
|
{
|
||||||
if (0 == MetaCache)
|
if (0 == MetaCache)
|
||||||
return 0;
|
return 0;
|
||||||
FSP_META_CACHE_ITEM *Item;
|
FSP_META_CACHE_ITEM *Item, *ExpiredItem = 0;
|
||||||
FSP_META_CACHE_ITEM_BUFFER *ItemBuffer;
|
FSP_META_CACHE_ITEM_BUFFER *ItemBuffer;
|
||||||
UINT64 ItemIndex = 0;
|
UINT64 ItemIndex = 0;
|
||||||
KIRQL Irql;
|
KIRQL Irql;
|
||||||
@ -236,12 +236,14 @@ UINT64 FspMetaCacheAddItem(FSP_META_CACHE *MetaCache, PCVOID Buffer, ULONG Size)
|
|||||||
}
|
}
|
||||||
KeAcquireSpinLock(&MetaCache->SpinLock, &Irql);
|
KeAcquireSpinLock(&MetaCache->SpinLock, &Irql);
|
||||||
if (MetaCache->ItemCount >= MetaCache->MetaCapacity)
|
if (MetaCache->ItemCount >= MetaCache->MetaCapacity)
|
||||||
FspMetaCacheRemoveExpiredItemAtDpcLevel(MetaCache, (UINT64)-1LL);
|
ExpiredItem = FspMetaCacheRemoveExpiredItemAtDpcLevel(MetaCache, (UINT64)-1LL);
|
||||||
ItemIndex = MetaCache->ItemIndex;
|
ItemIndex = MetaCache->ItemIndex;
|
||||||
ItemIndex = (UINT64)-1LL == ItemIndex ? 1 : ItemIndex + 1;
|
ItemIndex = (UINT64)-1LL == ItemIndex ? 1 : ItemIndex + 1;
|
||||||
MetaCache->ItemIndex = Item->ItemIndex = ItemIndex;
|
MetaCache->ItemIndex = Item->ItemIndex = ItemIndex;
|
||||||
FspMetaCacheAddItemAtDpcLevel(MetaCache, Item);
|
FspMetaCacheAddItemAtDpcLevel(MetaCache, Item);
|
||||||
KeReleaseSpinLock(&MetaCache->SpinLock, Irql);
|
KeReleaseSpinLock(&MetaCache->SpinLock, Irql);
|
||||||
|
if (0 != ExpiredItem)
|
||||||
|
FspMetaCacheDereferenceItem(ExpiredItem);
|
||||||
return ItemIndex;
|
return ItemIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
232
src/sys/mountdev.c
Normal file
232
src/sys/mountdev.c
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
/**
|
||||||
|
* @file sys/mountdev.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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>
|
||||||
|
|
||||||
|
NTSTATUS FspMountdevQueryDeviceName(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspMountdevQueryUniqueId(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
BOOLEAN FspMountdevDeviceControl(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
PNTSTATUS PResult);
|
||||||
|
NTSTATUS FspMountdevMake(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
BOOLEAN Persistent);
|
||||||
|
VOID FspMountdevFini(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||||
|
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspMountdevQueryDeviceName)
|
||||||
|
#pragma alloc_text(PAGE, FspMountdevQueryUniqueId)
|
||||||
|
#pragma alloc_text(PAGE, FspMountdevDeviceControl)
|
||||||
|
#pragma alloc_text(PAGE, FspMountdevMake)
|
||||||
|
#pragma alloc_text(PAGE, FspMountdevFini)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NTSTATUS FspMountdevQueryDeviceName(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
PMOUNTDEV_NAME OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
if (sizeof(MOUNTDEV_NAME) > OutputBufferLength)
|
||||||
|
/* NOTE: Windows storage samples also set: Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME) */
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
RtlZeroMemory(OutputBuffer, sizeof(MOUNTDEV_NAME));
|
||||||
|
OutputBuffer->NameLength = FsvrtDeviceExtension->VolumeName.Length;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information =
|
||||||
|
FIELD_OFFSET(MOUNTDEV_NAME, Name) + OutputBuffer->NameLength;
|
||||||
|
if (Irp->IoStatus.Information > OutputBufferLength)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(OutputBuffer->Name,
|
||||||
|
FsvrtDeviceExtension->VolumeName.Buffer, OutputBuffer->NameLength);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMountdevQueryUniqueId(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
PMOUNTDEV_UNIQUE_ID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
if (sizeof(MOUNTDEV_UNIQUE_ID) > OutputBufferLength)
|
||||||
|
/* NOTE: Windows storage samples also set: Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID) */
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
RtlZeroMemory(OutputBuffer, sizeof(MOUNTDEV_UNIQUE_ID));
|
||||||
|
OutputBuffer->UniqueIdLength = sizeof FsvrtDeviceExtension->UniqueId;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information =
|
||||||
|
FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + OutputBuffer->UniqueIdLength;
|
||||||
|
if (Irp->IoStatus.Information > OutputBufferLength)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(OutputBuffer->UniqueId,
|
||||||
|
&FsvrtDeviceExtension->UniqueId, OutputBuffer->UniqueIdLength);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspMountdevDeviceControl(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||||
|
PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (0 != FsvrtDeviceObject)
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
if (0 != InterlockedCompareExchange(&FsvrtDeviceExtension->IsMountdev, 0, 0))
|
||||||
|
{
|
||||||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
||||||
|
*PResult = FspMountdevQueryDeviceName(FsvrtDeviceObject, Irp, IrpSp);
|
||||||
|
return TRUE;
|
||||||
|
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
||||||
|
*PResult = FspMountdevQueryUniqueId(FsvrtDeviceObject, Irp, IrpSp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspMountdevMake(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
BOOLEAN Persistent)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function converts the fsvrt device into a mountdev device that
|
||||||
|
* responds to MountManager IOCTL's. This allows the fsvrt device to
|
||||||
|
* be mounted using the MountManager.
|
||||||
|
*
|
||||||
|
* This function requires protection against concurrency. In general this
|
||||||
|
* is achieved by acquiring the GlobalDeviceLock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
UNICODE_STRING String;
|
||||||
|
WCHAR StringBuf[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR) + 18];
|
||||||
|
GUID Guid;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ASSERT(FsvolDeviceExtension->FsvrtDeviceObject == FsvrtDeviceObject);
|
||||||
|
|
||||||
|
if (0 != InterlockedCompareExchange(&FsvrtDeviceExtension->IsMountdev, 0, 0))
|
||||||
|
return Persistent == FsvrtDeviceExtension->Persistent ?
|
||||||
|
STATUS_TOO_LATE : STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
FsvrtDeviceExtension->Persistent = Persistent;
|
||||||
|
|
||||||
|
if (Persistent)
|
||||||
|
{
|
||||||
|
/* make UUID v5 from the fsvrt device GUID and a unique string derived from VolumeParams */
|
||||||
|
RtlInitEmptyUnicodeString(&String, StringBuf, sizeof StringBuf);
|
||||||
|
Result = RtlUnicodeStringPrintf(&String,
|
||||||
|
L"%s:%08lx:%08lx",
|
||||||
|
FsvolDeviceExtension->VolumeParams.FileSystemName,
|
||||||
|
FsvolDeviceExtension->VolumeParams.VolumeSerialNumber,
|
||||||
|
FsvolDeviceExtension->VolumeParams.VolumeCreationTime);
|
||||||
|
ASSERT(NT_SUCCESS(Result));
|
||||||
|
Result = FspUuid5Make(&FspFsvrtDeviceClassGuid, String.Buffer, String.Length, &Guid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* create volume guid */
|
||||||
|
Result = FspCreateGuid(&Guid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* initialize the fsvrt device extension */
|
||||||
|
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
|
||||||
|
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||||
|
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||||
|
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||||
|
|
||||||
|
/* mark the fsvrt device as initialized */
|
||||||
|
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspMountdevFini(
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||||
|
PVOID Buffer = 0;
|
||||||
|
ULONG Length = 4096;
|
||||||
|
MOUNTMGR_MOUNT_POINT *MountPoint;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == InterlockedCompareExchange(&FsvrtDeviceExtension->IsMountdev, 0, 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (FsvrtDeviceExtension->Persistent)
|
||||||
|
/* if the mountdev is marked as persistent do not purge the MountManager */
|
||||||
|
return;
|
||||||
|
|
||||||
|
Buffer = FspAllocNonPaged(Length);
|
||||||
|
if (0 == Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MountPoint = Buffer;
|
||||||
|
RtlZeroMemory(MountPoint, sizeof *MountPoint);
|
||||||
|
MountPoint->UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||||
|
MountPoint->UniqueIdLength = sizeof FsvrtDeviceExtension->UniqueId;
|
||||||
|
RtlCopyMemory((PUINT8)MountPoint + MountPoint->UniqueIdOffset,
|
||||||
|
&FsvrtDeviceExtension->UniqueId, MountPoint->UniqueIdLength);
|
||||||
|
|
||||||
|
Result = FspSendMountmgrDeviceControlIrp(IOCTL_MOUNTMGR_DELETE_POINTS,
|
||||||
|
Buffer, MountPoint->UniqueIdOffset + MountPoint->UniqueIdLength, &Length);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != Buffer)
|
||||||
|
FspFree(Buffer);
|
||||||
|
}
|
@ -275,6 +275,7 @@ NTSTATUS FspMupHandleIrp(
|
|||||||
if (FspFileNodeIsValid(FileObject->FsContext))
|
if (FspFileNodeIsValid(FileObject->FsContext))
|
||||||
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
||||||
else if (0 != FileObject->FsContext2 &&
|
else if (0 != FileObject->FsContext2 &&
|
||||||
|
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
||||||
3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||||
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||||
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||||
|
210
src/sys/util.c
210
src/sys/util.c
@ -24,9 +24,20 @@
|
|||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
||||||
|
NTSTATUS FspRegistryGetValue(PUNICODE_STRING Path, PUNICODE_STRING ValueName,
|
||||||
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInformation, PULONG PValueInformationLength);
|
||||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||||
static NTSTATUS FspSendSetInformationIrpCompletion(
|
NTSTATUS FspSendQuerySecurityIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
SECURITY_INFORMATION SecurityInformation,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
PULONG PLength);
|
||||||
|
NTSTATUS FspSendQueryEaIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, PULONG PEaLength);
|
||||||
|
NTSTATUS FspSendMountmgrDeviceControlIrp(ULONG IoControlCode,
|
||||||
|
PVOID SystemBuffer, ULONG InputBufferLength, PULONG POutputBufferLength);
|
||||||
|
static NTSTATUS FspSendIrpCompletion(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context0);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context0);
|
||||||
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||||
NTSTATUS FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
NTSTATUS FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||||
@ -123,7 +134,11 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
|||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspCreateGuid)
|
#pragma alloc_text(PAGE, FspCreateGuid)
|
||||||
#pragma alloc_text(PAGE, FspGetDeviceObjectPointer)
|
#pragma alloc_text(PAGE, FspGetDeviceObjectPointer)
|
||||||
|
#pragma alloc_text(PAGE, FspRegistryGetValue)
|
||||||
#pragma alloc_text(PAGE, FspSendSetInformationIrp)
|
#pragma alloc_text(PAGE, FspSendSetInformationIrp)
|
||||||
|
#pragma alloc_text(PAGE, FspSendQuerySecurityIrp)
|
||||||
|
#pragma alloc_text(PAGE, FspSendQueryEaIrp)
|
||||||
|
#pragma alloc_text(PAGE, FspSendMountmgrDeviceControlIrp)
|
||||||
#pragma alloc_text(PAGE, FspBufferUserBuffer)
|
#pragma alloc_text(PAGE, FspBufferUserBuffer)
|
||||||
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
||||||
#pragma alloc_text(PAGE, FspMapLockedPagesInUserMode)
|
#pragma alloc_text(PAGE, FspMapLockedPagesInUserMode)
|
||||||
@ -271,11 +286,43 @@ NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK Desir
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspRegistryGetValue(PUNICODE_STRING Path, PUNICODE_STRING ValueName,
|
||||||
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInformation, PULONG PValueInformationLength)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
HANDLE Handle = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
Path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
|
||||||
|
|
||||||
|
Result = ZwOpenKey(&Handle, KEY_QUERY_VALUE, &ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = ZwQueryValueKey(Handle, ValueName,
|
||||||
|
KeyValuePartialInformation, ValueInformation,
|
||||||
|
*PValueInformationLength, PValueInformationLength);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
/* NOTE: also converts STATUS_BUFFER_OVERFLOW to STATUS_SUCCESS */
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != Handle)
|
||||||
|
ZwClose(Handle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
} FSP_SEND_SET_INFORMATION_IRP_CONTEXT;
|
} FSP_SEND_IRP_CONTEXT;
|
||||||
|
|
||||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length)
|
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length)
|
||||||
@ -289,7 +336,7 @@ NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT File
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
FSP_SEND_SET_INFORMATION_IRP_CONTEXT Context;
|
FSP_SEND_IRP_CONTEXT Context;
|
||||||
|
|
||||||
if (0 == DeviceObject)
|
if (0 == DeviceObject)
|
||||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
@ -304,24 +351,165 @@ NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT File
|
|||||||
IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
|
IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
|
||||||
IrpSp->FileObject = FileObject;
|
IrpSp->FileObject = FileObject;
|
||||||
IrpSp->Parameters.SetFile.FileInformationClass = FileInformationClass;
|
IrpSp->Parameters.SetFile.FileInformationClass = FileInformationClass;
|
||||||
IrpSp->Parameters.SetFile.Length = FileInformationClass;
|
IrpSp->Parameters.SetFile.Length = Length;
|
||||||
|
|
||||||
IoSetCompletionRoutine(Irp, FspSendSetInformationIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
|
||||||
|
|
||||||
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
||||||
|
IoSetCompletionRoutine(Irp, FspSendIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
Result = IoCallDriver(DeviceObject, Irp);
|
Result = IoCallDriver(DeviceObject, Irp);
|
||||||
if (STATUS_PENDING == Result)
|
if (STATUS_PENDING == Result)
|
||||||
KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, 0);
|
KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, 0);
|
||||||
|
|
||||||
return NT_SUCCESS(Result) ? Context.IoStatus.Status : Result;
|
return Context.IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspSendSetInformationIrpCompletion(
|
NTSTATUS FspSendQuerySecurityIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
SECURITY_INFORMATION SecurityInformation,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
PULONG PLength)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IrpSp;
|
||||||
|
FSP_SEND_IRP_CONTEXT Context;
|
||||||
|
ULONG Length = *PLength;
|
||||||
|
|
||||||
|
*PLength = 0;
|
||||||
|
|
||||||
|
if (0 == DeviceObject)
|
||||||
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
|
|
||||||
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
if (0 == Irp)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||||
|
Irp->RequestorMode = KernelMode;
|
||||||
|
Irp->AssociatedIrp.SystemBuffer = SecurityDescriptor;
|
||||||
|
Irp->UserBuffer = SecurityDescriptor;
|
||||||
|
IrpSp->MajorFunction = IRP_MJ_QUERY_SECURITY;
|
||||||
|
IrpSp->FileObject = FileObject;
|
||||||
|
IrpSp->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
|
||||||
|
IrpSp->Parameters.QuerySecurity.Length = Length;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
||||||
|
IoSetCompletionRoutine(Irp, FspSendIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
Result = IoCallDriver(DeviceObject, Irp);
|
||||||
|
if (STATUS_PENDING == Result)
|
||||||
|
KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, 0);
|
||||||
|
|
||||||
|
*PLength = (ULONG)Context.IoStatus.Information;
|
||||||
|
return Context.IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspSendQueryEaIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
|
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||||
|
PFILE_FULL_EA_INFORMATION Ea, PULONG PEaLength)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IrpSp;
|
||||||
|
FSP_SEND_IRP_CONTEXT Context;
|
||||||
|
ULONG EaLength = *PEaLength;
|
||||||
|
|
||||||
|
*PEaLength = 0;
|
||||||
|
|
||||||
|
if (0 == DeviceObject)
|
||||||
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
|
|
||||||
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
if (0 == Irp)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||||
|
Irp->RequestorMode = KernelMode;
|
||||||
|
Irp->AssociatedIrp.SystemBuffer = Ea;
|
||||||
|
Irp->UserBuffer = Ea;
|
||||||
|
IrpSp->MajorFunction = IRP_MJ_QUERY_EA;
|
||||||
|
IrpSp->FileObject = FileObject;
|
||||||
|
IrpSp->Parameters.QueryEa.Length = EaLength;
|
||||||
|
IrpSp->Parameters.QueryEa.EaList = GetEa;
|
||||||
|
IrpSp->Parameters.QueryEa.EaListLength = GetEaLength;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
||||||
|
IoSetCompletionRoutine(Irp, FspSendIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
Result = IoCallDriver(DeviceObject, Irp);
|
||||||
|
if (STATUS_PENDING == Result)
|
||||||
|
KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, 0);
|
||||||
|
|
||||||
|
*PEaLength = (ULONG)Context.IoStatus.Information;
|
||||||
|
return Context.IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspSendMountmgrDeviceControlIrp(ULONG IoControlCode,
|
||||||
|
PVOID SystemBuffer, ULONG InputBufferLength, PULONG POutputBufferLength)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(METHOD_BUFFERED == (IoControlCode & 3));
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IrpSp;
|
||||||
|
FSP_SEND_IRP_CONTEXT Context;
|
||||||
|
ULONG OutputBufferLength = 0;
|
||||||
|
|
||||||
|
if (0 == POutputBufferLength)
|
||||||
|
POutputBufferLength = &OutputBufferLength;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&DeviceName, MOUNTMGR_DEVICE_NAME);
|
||||||
|
Result = IoGetDeviceObjectPointer(&DeviceName, FILE_READ_ATTRIBUTES,
|
||||||
|
&FileObject, &DeviceObject);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
if (0 == Irp)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||||
|
Irp->RequestorMode = KernelMode;
|
||||||
|
Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
|
||||||
|
IrpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
|
||||||
|
IrpSp->Parameters.DeviceIoControl.OutputBufferLength = *POutputBufferLength;
|
||||||
|
IrpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
|
||||||
|
IrpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
||||||
|
IoSetCompletionRoutine(Irp, FspSendIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
Result = IoCallDriver(DeviceObject, Irp);
|
||||||
|
if (STATUS_PENDING == Result)
|
||||||
|
KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, 0);
|
||||||
|
|
||||||
|
*POutputBufferLength = (ULONG)Context.IoStatus.Information;
|
||||||
|
Result = Context.IoStatus.Status;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != FileObject)
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspSendIrpCompletion(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context0)
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context0)
|
||||||
{
|
{
|
||||||
// !PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
FSP_SEND_SET_INFORMATION_IRP_CONTEXT *Context = Context0;
|
FSP_SEND_IRP_CONTEXT *Context = Context0;
|
||||||
|
|
||||||
Context->IoStatus = Irp->IoStatus;
|
Context->IoStatus = Irp->IoStatus;
|
||||||
KeSetEvent(&Context->Event, 1, FALSE);
|
KeSetEvent(&Context->Event, 1, FALSE);
|
||||||
@ -633,6 +821,10 @@ NTSTATUS FspEaBufferFromFileSystemValidate(
|
|||||||
|
|
||||||
*PErrorOffset = 0;
|
*PErrorOffset = 0;
|
||||||
|
|
||||||
|
/* EA buffers from the user mode file system are allowed to have zero length */
|
||||||
|
if (0 == Length)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
/* EA buffers from the user mode file system are allowed to end with NextEntryOffset != 0 */
|
/* EA buffers from the user mode file system are allowed to end with NextEntryOffset != 0 */
|
||||||
for (PFILE_FULL_EA_INFORMATION Ea = Buffer, EaEnd = (PVOID)((PUINT8)Ea + Length);
|
for (PFILE_FULL_EA_INFORMATION Ea = Buffer, EaEnd = (PVOID)((PUINT8)Ea + Length);
|
||||||
EaEnd > Ea; Ea = FSP_NEXT_EA(Ea, EaEnd))
|
EaEnd > Ea; Ea = FSP_NEXT_EA(Ea, EaEnd))
|
||||||
|
@ -28,6 +28,9 @@ static NTSTATUS FspFsvolQueryFsDeviceInformation(
|
|||||||
static NTSTATUS FspFsvolQueryFsFullSizeInformation(
|
static NTSTATUS FspFsvolQueryFsFullSizeInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
||||||
const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryFsSectorSizeInformation(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
||||||
|
const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||||
static NTSTATUS FspFsvolQueryFsSizeInformation(
|
static NTSTATUS FspFsvolQueryFsSizeInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
||||||
const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||||
@ -50,6 +53,7 @@ FSP_DRIVER_DISPATCH FspSetVolumeInformation;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolQueryFsAttributeInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryFsAttributeInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryFsDeviceInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryFsDeviceInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryFsFullSizeInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryFsFullSizeInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryFsSectorSizeInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryFsSizeInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryFsSizeInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryFsVolumeInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryFsVolumeInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryVolumeInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryVolumeInformation)
|
||||||
@ -186,6 +190,35 @@ static NTSTATUS FspFsvolQueryFsFullSizeInformation(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryFsSectorSizeInformation(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
||||||
|
const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (*PBuffer + sizeof(FILE_FS_SECTOR_SIZE_INFORMATION) > BufferEnd)
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PFILE_FS_SECTOR_SIZE_INFORMATION Info = (PFILE_FS_SECTOR_SIZE_INFORMATION)*PBuffer;
|
||||||
|
|
||||||
|
Info->LogicalBytesPerSector =
|
||||||
|
Info->PhysicalBytesPerSectorForAtomicity =
|
||||||
|
Info->PhysicalBytesPerSectorForPerformance =
|
||||||
|
Info->FileSystemEffectivePhysicalBytesPerSectorForAtomicity =
|
||||||
|
FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||||
|
Info->Flags =
|
||||||
|
SSINFO_FLAGS_ALIGNED_DEVICE |
|
||||||
|
SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE |
|
||||||
|
SSINFO_FLAGS_NO_SEEK_PENALTY;
|
||||||
|
Info->ByteOffsetForSectorAlignment = 0;
|
||||||
|
Info->ByteOffsetForPartitionAlignment = 0;
|
||||||
|
|
||||||
|
*PBuffer += sizeof(FILE_FS_SECTOR_SIZE_INFORMATION);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryFsSizeInformation(
|
static NTSTATUS FspFsvolQueryFsSizeInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
|
||||||
const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
|
const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
|
||||||
@ -255,7 +288,7 @@ static NTSTATUS FspFsvolQueryVolumeInformation(
|
|||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer;
|
PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length;
|
PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryVolume.Length;
|
||||||
|
|
||||||
switch (IrpSp->Parameters.QueryVolume.FsInformationClass)
|
switch (IrpSp->Parameters.QueryVolume.FsInformationClass)
|
||||||
{
|
{
|
||||||
@ -268,6 +301,9 @@ static NTSTATUS FspFsvolQueryVolumeInformation(
|
|||||||
case FileFsFullSizeInformation:
|
case FileFsFullSizeInformation:
|
||||||
Result = FspFsvolQueryFsFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
|
Result = FspFsvolQueryFsFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
|
||||||
break;
|
break;
|
||||||
|
case FileFsSectorSizeInformation:
|
||||||
|
Result = FspFsvolQueryFsSectorSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
|
||||||
|
break;
|
||||||
case FileFsSizeInformation:
|
case FileFsSizeInformation:
|
||||||
Result = FspFsvolQueryFsSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
|
Result = FspFsvolQueryFsSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
|
||||||
break;
|
break;
|
||||||
@ -310,7 +346,7 @@ NTSTATUS FspFsvolQueryVolumeInformationComplete(
|
|||||||
|
|
||||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
|
||||||
PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer;
|
PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length;
|
PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryVolume.Length;
|
||||||
|
|
||||||
FspFsvolDeviceSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.QueryVolumeInformation.VolumeInfo);
|
FspFsvolDeviceSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.QueryVolumeInformation.VolumeInfo);
|
||||||
|
|
||||||
|
173
src/sys/volume.c
173
src/sys/volume.c
@ -34,6 +34,8 @@ NTSTATUS FspVolumeMount(
|
|||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspVolumeMountNoLock(
|
static NTSTATUS FspVolumeMountNoLock(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeMakeMountdev(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetName(
|
NTSTATUS FspVolumeGetName(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeGetNameList(
|
NTSTATUS FspVolumeGetNameList(
|
||||||
@ -42,6 +44,8 @@ static NTSTATUS FspVolumeGetNameListNoLock(
|
|||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
NTSTATUS FspVolumeTransact(
|
NTSTATUS FspVolumeTransact(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
|
NTSTATUS FspVolumeTransactFsext(
|
||||||
|
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 FspVolumeWork(
|
NTSTATUS FspVolumeWork(
|
||||||
@ -55,10 +59,12 @@ NTSTATUS FspVolumeWork(
|
|||||||
// ! #pragma alloc_text(PAGE, FspVolumeDeleteDelayed)
|
// ! #pragma alloc_text(PAGE, FspVolumeDeleteDelayed)
|
||||||
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
||||||
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
||||||
|
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
|
||||||
#pragma alloc_text(PAGE, FspVolumeGetName)
|
#pragma alloc_text(PAGE, FspVolumeGetName)
|
||||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||||
#pragma alloc_text(PAGE, FspVolumeTransact)
|
#pragma alloc_text(PAGE, FspVolumeTransact)
|
||||||
|
#pragma alloc_text(PAGE, FspVolumeTransactFsext)
|
||||||
#pragma alloc_text(PAGE, FspVolumeStop)
|
#pragma alloc_text(PAGE, FspVolumeStop)
|
||||||
#pragma alloc_text(PAGE, FspVolumeWork)
|
#pragma alloc_text(PAGE, FspVolumeWork)
|
||||||
#endif
|
#endif
|
||||||
@ -100,6 +106,7 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
UNICODE_STRING VolumeName;
|
UNICODE_STRING VolumeName;
|
||||||
UNICODE_STRING FsmupDeviceName;
|
UNICODE_STRING FsmupDeviceName;
|
||||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||||
|
FSP_FSEXT_PROVIDER *Provider = 0;
|
||||||
PDEVICE_OBJECT FsvolDeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject;
|
||||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
||||||
@ -132,7 +139,9 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
VolumeParams.SectorsPerAllocationUnit = 1;
|
VolumeParams.SectorsPerAllocationUnit = 1;
|
||||||
if (0 == VolumeParams.MaxComponentLength)
|
if (0 == VolumeParams.MaxComponentLength)
|
||||||
VolumeParams.MaxComponentLength = 255;
|
VolumeParams.MaxComponentLength = 255;
|
||||||
if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
|
if (0 == VolumeParams.TransactTimeout)
|
||||||
|
VolumeParams.TransactTimeout = 24 * 60 * 60 * 1000; /* 1 day */
|
||||||
|
else if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
|
||||||
VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
|
VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
|
||||||
VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;
|
VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;
|
||||||
if (FspFsctlIrpTimeoutMinimum > VolumeParams.IrpTimeout ||
|
if (FspFsctlIrpTimeoutMinimum > VolumeParams.IrpTimeout ||
|
||||||
@ -207,6 +216,14 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* load any fsext provider */
|
||||||
|
if (0 != VolumeParams.FsextControlCode)
|
||||||
|
{
|
||||||
|
Provider = FspFsextProvider(VolumeParams.FsextControlCode, &Result);
|
||||||
|
if (0 == Provider)
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/* create volume guid */
|
/* create volume guid */
|
||||||
Result = FspCreateGuid(&Guid);
|
Result = FspCreateGuid(&Guid);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -224,7 +241,8 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
VolumeName.MaximumLength = VolumeName.Length;
|
VolumeName.MaximumLength = VolumeName.Length;
|
||||||
|
|
||||||
/* create the volume (and virtual disk) device(s) */
|
/* create the volume (and virtual disk) device(s) */
|
||||||
Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0,
|
Result = FspDeviceCreate(FspFsvolDeviceExtensionKind,
|
||||||
|
0 == Provider ? 0 : Provider->DeviceExtensionSize,
|
||||||
FsctlDeviceObject->DeviceType,
|
FsctlDeviceObject->DeviceType,
|
||||||
FILE_DEVICE_DISK_FILE_SYSTEM == FsctlDeviceObject->DeviceType ? 0 : FILE_REMOTE_DEVICE,
|
FILE_DEVICE_DISK_FILE_SYSTEM == FsctlDeviceObject->DeviceType ? 0 : FILE_REMOTE_DEVICE,
|
||||||
&FsvolDeviceObject);
|
&FsvolDeviceObject);
|
||||||
@ -263,13 +281,18 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != FsvrtDeviceObject)
|
if (0 != FsvrtDeviceObject)
|
||||||
|
{
|
||||||
|
FspFsvrtDeviceExtension(FsvrtDeviceObject)->SectorSize =
|
||||||
|
FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||||
Result = FspDeviceInitialize(FsvrtDeviceObject);
|
Result = FspDeviceInitialize(FsvrtDeviceObject);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != FsvrtDeviceObject)
|
if (0 != FsvrtDeviceObject)
|
||||||
FspDeviceDereference(FsvrtDeviceObject);
|
FspDeviceDereference(FsvrtDeviceObject);
|
||||||
FspDeviceDereference(FsvolDeviceObject);
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do we need to register with fsmup? */
|
/* do we need to register with fsmup? */
|
||||||
@ -305,10 +328,22 @@ VOID FspVolumeDelete(
|
|||||||
// !PAGED_CODE();
|
// !PAGED_CODE();
|
||||||
|
|
||||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||||
FSP_FILE_NODE **FileNodes;
|
FSP_FILE_NODE **FileNodes;
|
||||||
ULONG FileNodeCount, Index;
|
ULONG FileNodeCount, Index;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have an fsvrt that is a mountdev, finalize it now! Finalizing a mountdev
|
||||||
|
* involves interaction with the MountManager, which tries to open our devices.
|
||||||
|
* So if we delay this interaction and we do it during final fsvrt teardown (i.e.
|
||||||
|
* FspDeviceDelete time) we will fail such opens with STATUS_CANCELLED, which will
|
||||||
|
* confuse the MountManager.
|
||||||
|
*/
|
||||||
|
if (0 != FsvrtDeviceObject)
|
||||||
|
FspMountdevFini(FsvrtDeviceObject);
|
||||||
|
|
||||||
FspDeviceReference(FsvolDeviceObject);
|
FspDeviceReference(FsvolDeviceObject);
|
||||||
|
|
||||||
FspDeviceGlobalLock();
|
FspDeviceGlobalLock();
|
||||||
@ -527,6 +562,50 @@ static NTSTATUS FspVolumeMountNoLock(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspVolumeMakeMountdev(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||||
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||||
|
ASSERT(FSP_FSCTL_MOUNTDEV == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||||
|
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||||
|
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||||
|
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||||
|
BOOLEAN Persistent = 0 < InputBufferLength ? !!*(PBOOLEAN)Irp->AssociatedIrp.SystemBuffer : FALSE;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == FsvrtDeviceObject)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
if (sizeof(GUID) > OutputBufferLength)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
FspDeviceGlobalLock();
|
||||||
|
|
||||||
|
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (STATUS_TOO_LATE != Result)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||||
|
&FspFsvrtDeviceExtension(FsvrtDeviceObject)->UniqueId, sizeof(GUID));
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = sizeof(GUID);
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
FspDeviceGlobalUnlock();
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspVolumeGetName(
|
NTSTATUS FspVolumeGetName(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -650,10 +729,8 @@ NTSTATUS FspVolumeTransact(
|
|||||||
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||||
ASSERT(
|
ASSERT(
|
||||||
FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||||
FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||||
ASSERT(
|
FSP_FSCTL_TRANSACT_INTERNAL == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||||
METHOD_BUFFERED == (IrpSp->Parameters.FileSystemControl.FsControlCode & 3) ||
|
|
||||||
METHOD_OUT_DIRECT == (IrpSp->Parameters.FileSystemControl.FsControlCode & 3));
|
|
||||||
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||||
|
|
||||||
/* check parameters */
|
/* check parameters */
|
||||||
@ -661,8 +738,21 @@ NTSTATUS FspVolumeTransact(
|
|||||||
ULONG ControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
ULONG ControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
||||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||||
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||||
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
PVOID InputBuffer = 0;
|
||||||
PVOID OutputBuffer = 0;
|
PVOID OutputBuffer = 0;
|
||||||
|
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||||
|
{
|
||||||
|
InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
|
||||||
|
if (KernelMode != Irp->RequestorMode)
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
ASSERT(0 == InputBufferLength ||
|
||||||
|
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) <= InputBufferLength);
|
||||||
|
ASSERT(0 == OutputBufferLength ||
|
||||||
|
sizeof(PVOID) <= OutputBufferLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
if (0 != InputBufferLength &&
|
if (0 != InputBufferLength &&
|
||||||
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength)
|
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
@ -672,6 +762,7 @@ NTSTATUS FspVolumeTransact(
|
|||||||
(FSP_FSCTL_TRANSACT_BATCH == ControlCode &&
|
(FSP_FSCTL_TRANSACT_BATCH == ControlCode &&
|
||||||
FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN > OutputBufferLength)))
|
FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN > OutputBufferLength)))
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!FspDeviceReference(FsvolDeviceObject))
|
if (!FspDeviceReference(FsvolDeviceObject))
|
||||||
return STATUS_CANCELLED;
|
return STATUS_CANCELLED;
|
||||||
@ -681,6 +772,7 @@ NTSTATUS FspVolumeTransact(
|
|||||||
PUINT8 BufferEnd;
|
PUINT8 BufferEnd;
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
||||||
|
PVOID InternalBuffer = 0;
|
||||||
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
|
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
|
||||||
ULONG LoopCount;
|
ULONG LoopCount;
|
||||||
LARGE_INTEGER Timeout;
|
LARGE_INTEGER Timeout;
|
||||||
@ -749,6 +841,9 @@ NTSTATUS FspVolumeTransact(
|
|||||||
/* were we sent an output buffer? */
|
/* were we sent an output buffer? */
|
||||||
switch (ControlCode & 3)
|
switch (ControlCode & 3)
|
||||||
{
|
{
|
||||||
|
case METHOD_NEITHER:
|
||||||
|
OutputBuffer = Irp->UserBuffer;
|
||||||
|
break;
|
||||||
case METHOD_OUT_DIRECT:
|
case METHOD_OUT_DIRECT:
|
||||||
if (0 != Irp->MdlAddress)
|
if (0 != Irp->MdlAddress)
|
||||||
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||||
@ -770,17 +865,17 @@ NTSTATUS FspVolumeTransact(
|
|||||||
|
|
||||||
/* wait for an IRP to arrive */
|
/* wait for an IRP to arrive */
|
||||||
KeQuerySystemTime(&Timeout);
|
KeQuerySystemTime(&Timeout);
|
||||||
Timeout.QuadPart += 0 == RepostedIrp ?
|
Timeout.QuadPart += FsvolDeviceExtension->VolumeParams.TransactTimeout * 10000ULL;
|
||||||
FsvolDeviceExtension->VolumeParams.TransactTimeout * 10000ULL :
|
|
||||||
FspVolumeTransactEarlyTimeout;
|
|
||||||
/* convert millis to nanos and add to absolute time */
|
/* convert millis to nanos and add to absolute time */
|
||||||
while (0 == (PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, 0, &Timeout, Irp)))
|
if (0 == (PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, 0, &Timeout, Irp)))
|
||||||
{
|
{
|
||||||
if (FspIoqStopped(FsvolDeviceExtension->Ioq))
|
if (FspIoqStopped(FsvolDeviceExtension->Ioq))
|
||||||
{
|
{
|
||||||
Result = STATUS_CANCELLED;
|
Result = STATUS_CANCELLED;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PendingIrp = FspIoqTimeout;
|
||||||
}
|
}
|
||||||
if (FspIoqTimeout == PendingIrp || FspIoqCancelled == PendingIrp)
|
if (FspIoqTimeout == PendingIrp || FspIoqCancelled == PendingIrp)
|
||||||
{
|
{
|
||||||
@ -793,7 +888,9 @@ NTSTATUS FspVolumeTransact(
|
|||||||
RepostedIrp = 0;
|
RepostedIrp = 0;
|
||||||
Request = OutputBuffer;
|
Request = OutputBuffer;
|
||||||
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
||||||
ASSERT(FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode ?
|
||||||
|
TRUE :
|
||||||
|
FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
||||||
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
|
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -813,9 +910,19 @@ NTSTATUS FspVolumeTransact(
|
|||||||
else if (!NT_SUCCESS(Result))
|
else if (!NT_SUCCESS(Result))
|
||||||
FspIopCompleteIrp(PendingIrp, Result);
|
FspIopCompleteIrp(PendingIrp, Result);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||||
|
{
|
||||||
|
InternalBuffer = FspAllocatePoolMustSucceed(
|
||||||
|
PagedPool, PendingIrpRequest->Size, FSP_ALLOC_EXTERNAL_TAG);
|
||||||
|
RtlCopyMemory(InternalBuffer, PendingIrpRequest, PendingIrpRequest->Size);
|
||||||
|
*(PVOID *)OutputBuffer = InternalBuffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size);
|
RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size);
|
||||||
Request = FspFsctlTransactProduceRequest(Request, PendingIrpRequest->Size);
|
Request = FspFsctlTransactProduceRequest(Request, PendingIrpRequest->Size);
|
||||||
|
}
|
||||||
|
|
||||||
if (!FspIoqStartProcessingIrp(FsvolDeviceExtension->Ioq, PendingIrp))
|
if (!FspIoqStartProcessingIrp(FsvolDeviceExtension->Ioq, PendingIrp))
|
||||||
{
|
{
|
||||||
@ -826,12 +933,24 @@ NTSTATUS FspVolumeTransact(
|
|||||||
* also cancel the PendingIrp we have in our hands.
|
* also cancel the PendingIrp we have in our hands.
|
||||||
*/
|
*/
|
||||||
ASSERT(FspIoqStopped(FsvolDeviceExtension->Ioq));
|
ASSERT(FspIoqStopped(FsvolDeviceExtension->Ioq));
|
||||||
|
if (0 != InternalBuffer)
|
||||||
|
{
|
||||||
|
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode);
|
||||||
|
FspFree(InternalBuffer);
|
||||||
|
}
|
||||||
FspIopCompleteCanceledIrp(PendingIrp);
|
FspIopCompleteCanceledIrp(PendingIrp);
|
||||||
Result = STATUS_CANCELLED;
|
Result = STATUS_CANCELLED;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* are we doing single request or batch mode? */
|
/* are we doing single request or batch mode? */
|
||||||
|
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = sizeof(PVOID);
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
if (FSP_FSCTL_TRANSACT == ControlCode)
|
if (FSP_FSCTL_TRANSACT == ControlCode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -858,6 +977,36 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspVolumeTransactFsext(
|
||||||
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||||
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||||
|
ASSERT(CTL_CODE(0, 0xC00, 0, 0) ==
|
||||||
|
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)));
|
||||||
|
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||||
|
if (!FspDeviceReference(FsvolDeviceObject))
|
||||||
|
return STATUS_CANCELLED;
|
||||||
|
|
||||||
|
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
if (IrpSp->Parameters.FileSystemControl.FsControlCode ==
|
||||||
|
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FsextControlCode)
|
||||||
|
{
|
||||||
|
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||||
|
IrpSp->Parameters.FileSystemControl.FsControlCode, 0);
|
||||||
|
if (0 != Provider)
|
||||||
|
Result = Provider->DeviceTransact(FsvolDeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspDeviceDereference(FsvolDeviceObject);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspVolumeStop(
|
NTSTATUS FspVolumeStop(
|
||||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ setlocal EnableDelayedExpansion
|
|||||||
set MsiName="WinFsp - Windows File System Proxy"
|
set MsiName="WinFsp - Windows File System Proxy"
|
||||||
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
||||||
set Issuer="DigiCert"
|
set Issuer="DigiCert"
|
||||||
set Subject="Navimatics Corporation"
|
set Subject="Navimatics LLC"
|
||||||
|
|
||||||
set Configuration=Release
|
set Configuration=Release
|
||||||
set SignedPackage=
|
set SignedPackage=
|
||||||
|
@ -4,7 +4,7 @@ setlocal
|
|||||||
|
|
||||||
set DebugWorkspace=winfsp
|
set DebugWorkspace=winfsp
|
||||||
set DebugPort=50000
|
set DebugPort=50000
|
||||||
set DebugKey=win8.debug.net.key
|
set DebugKey=1.1.1.1
|
||||||
|
|
||||||
set RegKey="HKLM\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
set RegKey="HKLM\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
||||||
set RegVal="KitsRoot10"
|
set RegVal="KitsRoot10"
|
||||||
|
@ -5,6 +5,7 @@ setlocal
|
|||||||
set CONFIG=Debug
|
set CONFIG=Debug
|
||||||
set SUFFIX=x64
|
set SUFFIX=x64
|
||||||
set TARGET_MACHINE=WIN8DBG
|
set TARGET_MACHINE=WIN8DBG
|
||||||
|
if not X%1==X set TARGET_MACHINE=%1
|
||||||
set TARGET_ACCOUNT=\Users\%USERNAME%\Downloads\winfsp\
|
set TARGET_ACCOUNT=\Users\%USERNAME%\Downloads\winfsp\
|
||||||
set TARGET=\\%TARGET_MACHINE%%TARGET_ACCOUNT%
|
set TARGET=\\%TARGET_MACHINE%%TARGET_ACCOUNT%
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ for %%f in (winfsp-%SUFFIX%.sys winfsp-%SUFFIX%.dll winfsp-tests-%SUFFIX%.exe fs
|
|||||||
copy build\VStudio\build\%CONFIG%\%%f %TARGET% >nul
|
copy build\VStudio\build\%CONFIG%\%%f %TARGET% >nul
|
||||||
)
|
)
|
||||||
copy tools\ifstest.bat %TARGET% >nul
|
copy tools\ifstest.bat %TARGET% >nul
|
||||||
echo sc create WinFsp type=filesys binPath=%%~dp0%DRIVER% >%TARGET%sc-create.bat
|
echo sc create WinFsp type=filesys binPath=%%~dp0winfsp-%SUFFIX%.sys >%TARGET%sc-create.bat
|
||||||
echo sc start WinFsp >%TARGET%sc-start.bat
|
echo sc start WinFsp >%TARGET%sc-start.bat
|
||||||
echo sc stop WinFsp >%TARGET%sc-stop.bat
|
echo sc stop WinFsp >%TARGET%sc-stop.bat
|
||||||
echo sc delete WinFsp >%TARGET%sc-delete.bat
|
echo sc delete WinFsp >%TARGET%sc-delete.bat
|
||||||
|
44
tools/impdef.bat
Normal file
44
tools/impdef.bat
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
if X%1==X goto usage
|
||||||
|
if X%2==X goto usage
|
||||||
|
set infile=%1
|
||||||
|
set infile=%infile:/=\%
|
||||||
|
set outfile=%2
|
||||||
|
set outfile=%outfile:/=\%
|
||||||
|
set workdir=!infile!.work
|
||||||
|
set workbase=!workdir!\%~n2
|
||||||
|
set outarch=%~n2
|
||||||
|
set outarch=%outarch:~-3%
|
||||||
|
|
||||||
|
set arch=x64
|
||||||
|
set cdef=/D_AMD64_
|
||||||
|
if /i X%outarch%==Xx86 set arch=x86
|
||||||
|
if /i X%outarch%==Xx86 set cdef=/D_X86_
|
||||||
|
|
||||||
|
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" !arch!
|
||||||
|
set INCLUDE=%~dp0..\opt\fsext\inc;%~dp0..\inc;!WindowsSdkDir!Include\!WindowsSDKVersion!km\crt;!WindowsSdkDir!Include\!WindowsSDKVersion!km;!WindowsSdkDir!Include\!WindowsSDKVersion!km\shared;!INCLUDE!
|
||||||
|
|
||||||
|
if exist !workdir! rmdir /s/q !workdir!
|
||||||
|
mkdir !workdir!
|
||||||
|
|
||||||
|
type !infile! >>!workbase!.c
|
||||||
|
cl /LD /Fe!workbase!.sys /Fo!workbase!.obj !cdef! /D_KERNEL_MODE /wd4716 !workbase!.c
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
|
||||||
|
copy !workbase!.lib !outfile!
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
|
||||||
|
rmdir /s/q !workdir!
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:usage
|
||||||
|
echo usage: impdef.bat infile.impdef outfile.lib 1>&2
|
||||||
|
exit /b 2
|
@ -71,12 +71,17 @@ set dfl_tests=^
|
|||||||
winfsp-tests-dotnet-external-share ^
|
winfsp-tests-dotnet-external-share ^
|
||||||
fsx-memfs-dotnet-disk ^
|
fsx-memfs-dotnet-disk ^
|
||||||
fsx-memfs-dotnet-net ^
|
fsx-memfs-dotnet-net ^
|
||||||
|
fsx-memfs-dotnet-slowio ^
|
||||||
winfstest-memfs-dotnet-disk ^
|
winfstest-memfs-dotnet-disk ^
|
||||||
winfstest-memfs-dotnet-net
|
winfstest-memfs-dotnet-net
|
||||||
set opt_tests=^
|
set opt_tests=^
|
||||||
ifstest-memfs-x64-disk ^
|
ifstest-memfs-x64-disk ^
|
||||||
ifstest-memfs-x86-disk ^
|
ifstest-memfs-x86-disk ^
|
||||||
ifstest-memfs-dotnet-disk ^
|
ifstest-memfs-dotnet-disk ^
|
||||||
|
sample-memfs-fuse3-x64 ^
|
||||||
|
sample-fsx-memfs-fuse3-x64 ^
|
||||||
|
sample-memfs-fuse3-x86 ^
|
||||||
|
sample-fsx-memfs-fuse3-x86 ^
|
||||||
sample-airfs-x64 ^
|
sample-airfs-x64 ^
|
||||||
sample-airfs-x86 ^
|
sample-airfs-x86 ^
|
||||||
sample-passthrough-x64 ^
|
sample-passthrough-x64 ^
|
||||||
@ -498,6 +503,11 @@ call :__run_fsx_memfs_slowio_test memfs32-slowio memfs-x86
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:fsx-memfs-dotnet-slowio
|
||||||
|
call :__run_fsx_memfs_slowio_test memfs.net-slowio memfs-dotnet-msil
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:__run_fsx_memfs_slowio_test
|
:__run_fsx_memfs_slowio_test
|
||||||
set RunSampleTestExit=0
|
set RunSampleTestExit=0
|
||||||
call "%ProjRoot%\tools\fsreg" %1 "%ProjRoot%\build\VStudio\build\%Configuration%\%2.exe" "-u %%%%1 -m %%%%2 -M 50 -P 10 -R 5" "D:P(A;;RPWPLC;;;WD)"
|
call "%ProjRoot%\tools\fsreg" %1 "%ProjRoot%\build\VStudio\build\%Configuration%\%2.exe" "-u %%%%1 -m %%%%2 -M 50 -P 10 -R 5" "D:P(A;;RPWPLC;;;WD)"
|
||||||
@ -669,6 +679,28 @@ for /F "delims=" %%l in ('call "%ProjRoot%\tools\ifstest.bat" %* /v ^| findstr /
|
|||||||
if not X!IfsTestFound!==XYES set IfsTestExit=1
|
if not X!IfsTestFound!==XYES set IfsTestExit=1
|
||||||
exit /b !IfsTestExit!
|
exit /b !IfsTestExit!
|
||||||
|
|
||||||
|
:sample-memfs-fuse3-x64
|
||||||
|
call :__run_sample_fuse_test memfs-fuse3 x64 memfs-fuse3-x64 winfsp-tests-x64 ^
|
||||||
|
"-create_fileattr_test -create_readonlydir_test -setfileinfo_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-memfs-fuse3-x86
|
||||||
|
call :__run_sample_fuse_test memfs-fuse3 x86 memfs-fuse3-x86 winfsp-tests-x86 ^
|
||||||
|
"-create_fileattr_test -create_readonlydir_test -setfileinfo_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-fsx-memfs-fuse3-x64
|
||||||
|
call :__run_sample_fsx_fuse_test memfs-fuse3 x64 memfs-fuse3-x64 fsx
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-fsx-memfs-fuse3-x86
|
||||||
|
call :__run_sample_fsx_fuse_test memfs-fuse3 x86 memfs-fuse3-x86 fsx
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:sample-airfs-x64
|
:sample-airfs-x64
|
||||||
call :__run_sample_disk_test airfs x64 airfs-x64 winfsp-tests-x64 NOEXCL
|
call :__run_sample_disk_test airfs x64 airfs-x64 winfsp-tests-x64 NOEXCL
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
3
tst/airfs/.gitignore
vendored
3
tst/airfs/.gitignore
vendored
@ -3,3 +3,6 @@ build
|
|||||||
*.suo
|
*.suo
|
||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
|
1283
tst/airfs/airfs.cpp
1283
tst/airfs/airfs.cpp
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
@ -22,32 +22,32 @@
|
|||||||
<ProjectGuid>{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}</ProjectGuid>
|
<ProjectGuid>{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>airfs</RootNamespace>
|
<RootNamespace>airfs</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -171,6 +171,10 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="airfs.cpp" />
|
<ClCompile Include="airfs.cpp" />
|
||||||
|
<ClCompile Include="persistence.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="common.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Source">
|
<Filter Include="Source">
|
||||||
@ -10,5 +10,13 @@
|
|||||||
<ClCompile Include="airfs.cpp">
|
<ClCompile Include="airfs.cpp">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="persistence.cpp">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="common.h">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
210
tst/airfs/common.h
Normal file
210
tst/airfs/common.h
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* @file common.h
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Airfs is based on Memfs with changes contributed by John Oberschelp.
|
||||||
|
* The contributed changes are under joint copyright by Bill Zissimopoulos
|
||||||
|
* and John Oberschelp per the Contributor Agreement found at the
|
||||||
|
* root of this project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PROGNAME "airfs"
|
||||||
|
#define ROUND_UP( bytes, units ) (((bytes) + (units) - 1) / (units) * (units))
|
||||||
|
#define ROUND_DOWN( bytes, units ) (((bytes) ) / (units) * (units))
|
||||||
|
#define MINIMUM_ALLOCSIZE 196
|
||||||
|
#define MAXIMUM_ALLOCSIZE ROUND_DOWN(10*1024*1024, MINIMUM_ALLOCSIZE)
|
||||||
|
#define SECTOR_SIZE 512
|
||||||
|
#define SECTORS_PER_ALLOCATION_UNIT 1
|
||||||
|
#define ALLOCATION_UNIT ( SECTOR_SIZE * SECTORS_PER_ALLOCATION_UNIT )
|
||||||
|
#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__)
|
||||||
|
#define AIRFS_MAX_PATH 512
|
||||||
|
#define FILEBLOCK_OVERHEAD 40 // size of ( P + E + L + R + FileOffset ) = 8 * 5 = 40
|
||||||
|
#define ARG_TO_S(v) if (arge > ++argp) v = *argp; else goto usage
|
||||||
|
#define ARG_TO_4(v) if (arge > ++argp) v = (int32_t) wcstoll_default(*argp, v); else goto usage
|
||||||
|
#define ARG_TO_8(v) if (arge > ++argp) v = wcstoll_default(*argp, v); else goto usage
|
||||||
|
|
||||||
|
enum StorageFileAccessType {ZERO=0,READ,WRITE};
|
||||||
|
enum Neighbor {LT=-2,LE=-1,EQ=0,GE=1,GT=2};
|
||||||
|
|
||||||
|
struct NODE;
|
||||||
|
typedef NODE* NODE_;
|
||||||
|
|
||||||
|
typedef int CompareFunction (void* key, NODE_);
|
||||||
|
|
||||||
|
inline NTSTATUS GetLastErrorAsStatus()
|
||||||
|
{
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UINT64 SystemTime()
|
||||||
|
{
|
||||||
|
FILETIME FileTime;
|
||||||
|
GetSystemTimeAsFileTime(&FileTime);
|
||||||
|
return ((PLARGE_INTEGER)&FileTime)->QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t wcstoll_default(wchar_t *w, int64_t deflt)
|
||||||
|
{
|
||||||
|
wchar_t *endp;
|
||||||
|
int64_t i = wcstoll(w, &endp, 0);
|
||||||
|
return L'\0' != w[0] && L'\0' == *endp ? i : deflt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Where<T> Class: This class manages an offset within our memory-mapped
|
||||||
|
// volume to another location within our memory-mapped volume. Because it is
|
||||||
|
// a self-relative offset, this delta is constant regardless of where in
|
||||||
|
// memory the file system is mapped, so we can always reobtain its address.
|
||||||
|
// A delta of 0 is the special case for "null".
|
||||||
|
//
|
||||||
|
|
||||||
|
template <class T> class Where
|
||||||
|
{
|
||||||
|
int64_t delta;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Where() = default;
|
||||||
|
~Where() = default;
|
||||||
|
Where(T t) : delta( t ?( (char*)t -(char*)this ):0) {}
|
||||||
|
Where(Where& w) : delta( w.delta?( ((char*)&w+w.delta)-(char*)this ):0) {}
|
||||||
|
|
||||||
|
operator bool () { return delta != 0; }
|
||||||
|
operator T () { return (T) ( delta?( (char*)this+delta ):0); }
|
||||||
|
T operator -> () { return (T) ( delta?( (char*)this+delta ):0); }
|
||||||
|
operator void* () { return (void*)( delta?( (char*)this+delta ):0); }
|
||||||
|
|
||||||
|
bool operator == (Where& rhs) { return (char*)this+delta == (char*)&rhs+rhs.delta; }
|
||||||
|
bool operator != (Where& rhs) { return (char*)this+delta != (char*)&rhs+rhs.delta; }
|
||||||
|
bool operator == (T rhs) { return (char*)this+delta == (char*)rhs; }
|
||||||
|
bool operator != (T rhs) { return (char*)this+delta != (char*)rhs; }
|
||||||
|
|
||||||
|
Where& operator = (Where& rhs) { delta = rhs.delta?( ((char*)&rhs+rhs.delta) - ((char*)this) ):0; return *this; }
|
||||||
|
Where& operator = (void* rhs) { delta = rhs ?( (char*)rhs - ((char*)this) ):0; return *this; }
|
||||||
|
|
||||||
|
char* Address () { return (char*)this+delta; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// The header for an Airfs volume
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char Signature[8]; // Airfs\0\0\0
|
||||||
|
char MapFormatVersion[4]; // Major.Minor.Patch.Build
|
||||||
|
char filler[4];
|
||||||
|
Where<NODE_> Root;
|
||||||
|
Where<NODE_> Available;
|
||||||
|
UINT64 VolumeSize;
|
||||||
|
UINT64 FreeSize;
|
||||||
|
WCHAR VolumeLabel[32];
|
||||||
|
UINT16 VolumeLabelLength;
|
||||||
|
UINT16 filler1,filler2,filler3;
|
||||||
|
UINT32 CaseInsensitive;
|
||||||
|
UINT32 filler4;
|
||||||
|
int64_t VolumeLength;
|
||||||
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
|
HANDLE MapFileHandle;
|
||||||
|
HANDLE MapHandle;
|
||||||
|
} AIRFS, *AIRFS_;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Information per file or directory
|
||||||
|
//
|
||||||
|
struct NODE
|
||||||
|
{
|
||||||
|
Where<NODE_> P,L,R,E; // Sorted sibling tree: Parent, Left, Right, and Equal
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Where<WCHAR*> Name;
|
||||||
|
int64_t FileOffset;
|
||||||
|
};
|
||||||
|
Where<NODE_> Parent;
|
||||||
|
Where<NODE_> Children;
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
uint64_t SecurityDescriptorSize;
|
||||||
|
Where<char*> SecurityDescriptor;
|
||||||
|
Where<NODE_> FileBlocks;
|
||||||
|
uint64_t ReparseDataSize;
|
||||||
|
Where<char*> ReparseData;
|
||||||
|
volatile LONG RefCount;
|
||||||
|
Where<NODE_> Streams;
|
||||||
|
BOOLEAN IsAStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SpinLock
|
||||||
|
{
|
||||||
|
LONG C; // Counter
|
||||||
|
HANDLE S; // Semaphore
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SpinLock() { C = 0; S = CreateSemaphore(NULL, 0, 1, NULL); }
|
||||||
|
~SpinLock() { CloseHandle(S); }
|
||||||
|
|
||||||
|
void Acquire() { if (_InterlockedIncrement(&C) > 1) WaitForSingleObject(S, INFINITE); }
|
||||||
|
void Release() { if (_InterlockedDecrement(&C) > 0) ReleaseSemaphore(S, 1, NULL); }
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Airprint (const char * format, ...);
|
||||||
|
|
||||||
|
int SizeCmp (void* key, NODE_);
|
||||||
|
int ExactNameCmp (void* key, NODE_);
|
||||||
|
int CaselessNameCmp (void* key, NODE_);
|
||||||
|
|
||||||
|
NODE_ Find (Where<NODE_> &root, void* key, CompareFunction);
|
||||||
|
NODE_ Near (Where<NODE_> &root, void* key, CompareFunction, Neighbor);
|
||||||
|
void Attach (Where<NODE_> &root, NODE_ attach, CompareFunction, void* key);
|
||||||
|
void Detach (Where<NODE_> &root, NODE_ detach);
|
||||||
|
NODE_ First (NODE_ start);
|
||||||
|
NODE_ Last (NODE_ start);
|
||||||
|
NODE_ Next (NODE_);
|
||||||
|
NODE_ Prev (NODE_);
|
||||||
|
|
||||||
|
NTSTATUS StorageStartup (AIRFS_ &, WCHAR* MapName, WCHAR* StorageFileName, int64_t Length);
|
||||||
|
NTSTATUS StorageShutdown (AIRFS_);
|
||||||
|
void* StorageAllocate (AIRFS_, int64_t RequestedSize);
|
||||||
|
void* StorageReallocate (AIRFS_, void* Reallocate, int64_t RequestedSize);
|
||||||
|
void StorageFree (AIRFS_, void* Release);
|
||||||
|
NTSTATUS StorageSetFileCapacity (AIRFS_, NODE_, int64_t MinimumRequiredCapacity);
|
||||||
|
void StorageAccessFile (StorageFileAccessType, NODE_, int64_t Offset, int64_t NumBytes, char* Address);
|
||||||
|
|
||||||
|
static_assert(AIRFS_MAX_PATH > MAX_PATH, "AIRFS_MAX_PATH must be greater than MAX_PATH.");
|
||||||
|
static_assert(sizeof NODE + sizeof int32_t == MINIMUM_ALLOCSIZE, "MINIMUM_ALLOCSIZE should be 196.");
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
594
tst/airfs/persistence.cpp
Normal file
594
tst/airfs/persistence.cpp
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
/**
|
||||||
|
* @file persistence.cpp
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Airfs is based on Memfs with changes contributed by John Oberschelp.
|
||||||
|
* The contributed changes are under joint copyright by Bill Zissimopoulos
|
||||||
|
* and John Oberschelp per the Contributor Agreement found at the
|
||||||
|
* root of this project.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Airfs uses a memory-mapped file per volume to achieve persistence.
|
||||||
|
* The primary advantage of this is that volume loads and saves are automatic.
|
||||||
|
* The two primary disadvantages, and our workarounds are:
|
||||||
|
* 1. We can't use standard containers or memory management,
|
||||||
|
* so the below Rubbertree and Storage functions are used instead.
|
||||||
|
* 2. Each process will map the volume to an arbitrary address,
|
||||||
|
* so Where<T> offsets are used in place of pointers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
SpinLock StorageLock, AirprintLock, SetLock;
|
||||||
|
|
||||||
|
int SizeCmp ( void* key, NODE_ x)
|
||||||
|
{
|
||||||
|
return *(int32_t*)key - ((int32_t*)x)[-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int BlockCmp ( void* key, NODE_ x)
|
||||||
|
{
|
||||||
|
int64_t left = *(int64_t*)key;
|
||||||
|
int64_t right = x->FileOffset;
|
||||||
|
return left == right ? 0 : (left < right ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CaselessNameCmp ( void* key, NODE_ x)
|
||||||
|
{
|
||||||
|
WCHAR* c1 = (WCHAR*) key;
|
||||||
|
WCHAR* c2 = x->Name;
|
||||||
|
return _wcsicmp(c1,c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExactNameCmp ( void* key, NODE_ x)
|
||||||
|
{
|
||||||
|
WCHAR* c1 = (WCHAR*) key;
|
||||||
|
WCHAR* c2 = x->Name;
|
||||||
|
return wcscmp(c1,c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Airprint (const char * format, ...)
|
||||||
|
{
|
||||||
|
AirprintLock.Acquire();
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
char szBuffer[512];
|
||||||
|
sprintf_s(szBuffer, 511, "Airfs %5.5f ----", SystemTime() / 10'000'000.0);
|
||||||
|
vsnprintf(szBuffer+25, 511-25, format, args);
|
||||||
|
OutputDebugStringA(szBuffer);
|
||||||
|
va_end(args);
|
||||||
|
AirprintLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Rubbertree (because it is flexible!)
|
||||||
|
// Implements a sorted set of elements, using a binary tree.
|
||||||
|
// Has a function, Near, that finds nodes at or adjacent to a key.
|
||||||
|
// Attach, Find, and Near use splay to improve random access times.
|
||||||
|
// First, Last, Next, and Prev do not, to improve sequential access times.
|
||||||
|
// Replacing each Where<NODE_> with NODE_ would make this a pointer-based tree.
|
||||||
|
// In addition to Left, Right, and Parent references, each node has an Equal
|
||||||
|
// reference that may be used to keep "equivalent" nodes. This is used by
|
||||||
|
// our memory heap manager's tree of available memory blocks, sorted by size.
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline void rotateL(Where<NODE_> &root, NODE_ x)
|
||||||
|
{
|
||||||
|
NODE_ y = x->R, p = x->P;
|
||||||
|
if (x->R = y->L) y->L->P = x;
|
||||||
|
if (!(y->P = p))
|
||||||
|
root = y;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x == p->L) p->L = y;
|
||||||
|
else p->R = y;
|
||||||
|
}
|
||||||
|
(y->L = x)->P = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline void rotateR(Where<NODE_> &root, NODE_ y)
|
||||||
|
{
|
||||||
|
NODE_ x = y->L, p = y->P;
|
||||||
|
if (y->L = x->R) x->R->P = y;
|
||||||
|
if (!(x->P = p))
|
||||||
|
root = x;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (y == p->L) p->L = x;
|
||||||
|
else p->R = x;
|
||||||
|
}
|
||||||
|
(x->R = y)->P = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
static void splay(Where<NODE_> &root, NODE_ x)
|
||||||
|
{
|
||||||
|
while (NODE_ p = x->P)
|
||||||
|
{
|
||||||
|
if (!p->P)
|
||||||
|
{
|
||||||
|
if (p->L == x) rotateR(root, p);
|
||||||
|
else rotateL(root, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p == p->P->R)
|
||||||
|
{
|
||||||
|
if (p->R == x) rotateL(root, p->P);
|
||||||
|
else rotateR(root, p);
|
||||||
|
rotateL(root, x->P);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p->L == x) rotateR(root, p->P);
|
||||||
|
else rotateL(root, p);
|
||||||
|
rotateR(root, x->P);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline int seek(Where<NODE_> &root, NODE_ &x, void* key, CompareFunction CMP)
|
||||||
|
{
|
||||||
|
x = root;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int diff = CMP(key, x);
|
||||||
|
if (diff < 0)
|
||||||
|
{
|
||||||
|
if (!x->L) return -1;
|
||||||
|
x = x->L;
|
||||||
|
}
|
||||||
|
else if (diff > 0)
|
||||||
|
{
|
||||||
|
if (!x->R) return 1;
|
||||||
|
x = x->R;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline NODE_ next(NODE_ x)
|
||||||
|
{
|
||||||
|
if (x->R) { x = x->R; while (x->L) x = x->L; return x; }
|
||||||
|
NODE_ p = x->P;
|
||||||
|
while (p && x == p->R) { x = p; p = p->P; }
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline NODE_ prev(NODE_ x)
|
||||||
|
{
|
||||||
|
if (x->L) { x = x->L; while (x->R) x = x->R; return x; }
|
||||||
|
NODE_ p = x->P;
|
||||||
|
while (p && x == p->L) { x = p; p = p->P; }
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NODE_ First(NODE_ x)
|
||||||
|
{
|
||||||
|
SetLock.Acquire();
|
||||||
|
if (x) while (x->L) x = x->L;
|
||||||
|
SetLock.Release();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NODE_ Last(NODE_ x)
|
||||||
|
{
|
||||||
|
SetLock.Acquire();
|
||||||
|
if (x) while (x->R) x = x->R;
|
||||||
|
SetLock.Release();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NODE_ Next(NODE_ x)
|
||||||
|
{
|
||||||
|
SetLock.Acquire();
|
||||||
|
x = next(x);
|
||||||
|
SetLock.Release();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NODE_ Prev(NODE_ x)
|
||||||
|
{
|
||||||
|
SetLock.Acquire();
|
||||||
|
x = prev(x);
|
||||||
|
SetLock.Release();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NODE_ Near(Where<NODE_> &root, void* key, CompareFunction CMP, Neighbor want)
|
||||||
|
{
|
||||||
|
// Return a node relative to (just <, <=, ==, >=, or >) a key.
|
||||||
|
if (!root) return 0;
|
||||||
|
SetLock.Acquire();
|
||||||
|
NODE_ x;
|
||||||
|
int dir = seek(root, x, key, CMP);
|
||||||
|
if ((dir == 0 && want == GT) || (dir > 0 && want >= GE)) x = next(x);
|
||||||
|
else
|
||||||
|
if ((dir == 0 && want == LT) || (dir < 0 && want <= LE)) x = prev(x);
|
||||||
|
else
|
||||||
|
if (dir != 0 && want == EQ) x = 0;
|
||||||
|
if (x) splay(root, x);
|
||||||
|
SetLock.Release();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NODE_ Find(Where<NODE_> &root, void* key, CompareFunction CMP)
|
||||||
|
{
|
||||||
|
if (!root) return 0;
|
||||||
|
SetLock.Acquire();
|
||||||
|
NODE_ x;
|
||||||
|
int direction = seek(root, x, key, CMP);
|
||||||
|
splay(root, x);
|
||||||
|
SetLock.Release();
|
||||||
|
return direction?0:x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Attach(Where<NODE_> &root, NODE_ x, CompareFunction CMP, void* key)
|
||||||
|
{
|
||||||
|
SetLock.Acquire();
|
||||||
|
if (!root)
|
||||||
|
{
|
||||||
|
root = x;
|
||||||
|
x->P = x->L = x->R = x->E = 0;
|
||||||
|
SetLock.Release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NODE_ f;
|
||||||
|
int diff = seek(root, f, key, CMP);
|
||||||
|
if (!diff)
|
||||||
|
{
|
||||||
|
if (x->L = f->L) x->L->P = x;
|
||||||
|
if (x->R = f->R) x->R->P = x;
|
||||||
|
NODE_ p = f->P;
|
||||||
|
if (x->P = p) { if (p->L == f) p->L = x; else p->R = x; }
|
||||||
|
else root = x;
|
||||||
|
(x->E = f)->P = x;
|
||||||
|
f->L = f->R = 0;
|
||||||
|
splay(root, x);
|
||||||
|
SetLock.Release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (diff < 0) f->L = x; else f->R = x;
|
||||||
|
x->P = f;
|
||||||
|
x->L = x->R = x->E = 0;
|
||||||
|
splay(root, x);
|
||||||
|
SetLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Detach(Where<NODE_> &root, NODE_ x)
|
||||||
|
{
|
||||||
|
SetLock.Acquire();
|
||||||
|
NODE_ e = x->E, p = x->P;
|
||||||
|
if (p && p->E == x) { if (p->E = e) e->P = p; }
|
||||||
|
else if (e)
|
||||||
|
{
|
||||||
|
if (e->L = x->L) e->L->P = e;
|
||||||
|
if (e->R = x->R) e->R->P = e;
|
||||||
|
if (e->P = p) { if (p->L == x) p->L = e; else p->R = e; }
|
||||||
|
else root = e;
|
||||||
|
}
|
||||||
|
else if (!x->L)
|
||||||
|
{
|
||||||
|
if (p) { if ( p->L == x) p->L = x->R; else p->R = x->R; }
|
||||||
|
else root = x->R;
|
||||||
|
if (x->R) x->R->P = p;
|
||||||
|
}
|
||||||
|
else if (!x->R)
|
||||||
|
{
|
||||||
|
if (p) { if ( p->L == x) p->L = x->L; else p->R = x->L; }
|
||||||
|
else root = x->L;
|
||||||
|
if (x->L) x->L->P = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e = x->L;
|
||||||
|
if (e->R)
|
||||||
|
{
|
||||||
|
do { e = e->R; } while (e->R);
|
||||||
|
if (e->P->R = e->L) e->L->P = e->P;
|
||||||
|
(e->L = x->L)->P = e;
|
||||||
|
}
|
||||||
|
(e->R = x->R)->P = e;
|
||||||
|
if (e->P = x->P) { if (e->P->L == x) e->P->L = e; else e->P->R = e; }
|
||||||
|
else root = e;
|
||||||
|
}
|
||||||
|
SetLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Storage Functions for our memory-mapped file-based persistent volumes
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void* StorageAllocate(AIRFS_ Airfs, int64_t RequestedSize)
|
||||||
|
{
|
||||||
|
if (!RequestedSize) return 0;
|
||||||
|
if (RequestedSize + sizeof int32_t > MAXIMUM_ALLOCSIZE) return 0;
|
||||||
|
|
||||||
|
StorageLock.Acquire();
|
||||||
|
int32_t RoundedSize = (int32_t) ROUND_UP(RequestedSize, MINIMUM_ALLOCSIZE - sizeof int32_t);
|
||||||
|
int32_t SplitableSize = RoundedSize + MINIMUM_ALLOCSIZE;
|
||||||
|
|
||||||
|
// See if we have a freed node of the size we requested.
|
||||||
|
NODE_ NewItem = Near(Airfs->Available, &RoundedSize, SizeCmp, GE);
|
||||||
|
if (NewItem)
|
||||||
|
{
|
||||||
|
int32_t FoundSize = ((int32_t*)NewItem)[-1];
|
||||||
|
if (FoundSize < SplitableSize)
|
||||||
|
{
|
||||||
|
Detach(Airfs->Available, NewItem);
|
||||||
|
Airfs->FreeSize -= FoundSize;
|
||||||
|
StorageLock.Release();
|
||||||
|
return NewItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not, see if we can downsize a larger freed element.
|
||||||
|
NewItem = Near(Airfs->Available, &SplitableSize, SizeCmp, GE);
|
||||||
|
if (NewItem)
|
||||||
|
{
|
||||||
|
int32_t FoundSize = ((int32_t*)NewItem)[-1];
|
||||||
|
Detach(Airfs->Available, NewItem);
|
||||||
|
Airfs->FreeSize -= FoundSize;
|
||||||
|
char* Addr = (char*)NewItem + RoundedSize + sizeof int32_t;
|
||||||
|
NODE_ Remainder = (NODE_) Addr;
|
||||||
|
int32_t RemainderSize = FoundSize - (RoundedSize + sizeof int32_t);
|
||||||
|
((int32_t*)Remainder)[-1] = RemainderSize;
|
||||||
|
Attach(Airfs->Available, Remainder, SizeCmp, &RemainderSize);
|
||||||
|
Airfs->FreeSize += RemainderSize;
|
||||||
|
((int32_t*)NewItem)[-1] = RoundedSize;
|
||||||
|
StorageLock.Release();
|
||||||
|
return NewItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not, give up.
|
||||||
|
StorageLock.Release();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void* StorageReallocate(AIRFS_ Airfs, void* OldAlloc, int64_t RequestedSize)
|
||||||
|
{
|
||||||
|
if (!OldAlloc)
|
||||||
|
{
|
||||||
|
return StorageAllocate(Airfs, RequestedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RequestedSize)
|
||||||
|
{
|
||||||
|
StorageFree(Airfs, OldAlloc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t OldSize = ((int32_t*)OldAlloc)[-1];
|
||||||
|
void* NewAlloc = StorageAllocate(Airfs, RequestedSize);
|
||||||
|
if (!NewAlloc) return 0;
|
||||||
|
memcpy(NewAlloc, OldAlloc, min(RequestedSize, OldSize));
|
||||||
|
StorageFree(Airfs, OldAlloc);
|
||||||
|
return NewAlloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void StorageFree(AIRFS_ Airfs, void* r)
|
||||||
|
{
|
||||||
|
if (!r) return;
|
||||||
|
StorageLock.Acquire();
|
||||||
|
NODE_ release = (NODE_) r;
|
||||||
|
int32_t Size = ((int32_t*)r)[-1];
|
||||||
|
Attach(Airfs->Available, release, SizeCmp, &Size);
|
||||||
|
Airfs->FreeSize += Size;
|
||||||
|
StorageLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void StorageAccessFile(StorageFileAccessType Type, NODE_ Node, int64_t AccessOffset, int64_t NumBytes, char* MemoryAddress)
|
||||||
|
{
|
||||||
|
StorageLock.Acquire();
|
||||||
|
|
||||||
|
NODE_ Block = Near(Node->FileBlocks, &AccessOffset, BlockCmp, LE);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int32_t BlockSize = ((int32_t*)Block)[-1];
|
||||||
|
int64_t BlockOffset = Block->FileOffset;
|
||||||
|
int64_t BlockIndex = AccessOffset - BlockOffset + FILEBLOCK_OVERHEAD;
|
||||||
|
int64_t BlockNum = min(BlockSize-BlockIndex, NumBytes);
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case ZERO : { memset((char*)Block + BlockIndex, 0, BlockNum); break; }
|
||||||
|
case READ : { memcpy(MemoryAddress, (char*)Block + BlockIndex, BlockNum); break; }
|
||||||
|
case WRITE : { memcpy((char*)Block + BlockIndex, MemoryAddress, BlockNum); break; }
|
||||||
|
}
|
||||||
|
NumBytes -= BlockNum;
|
||||||
|
if (!NumBytes) break;
|
||||||
|
MemoryAddress += BlockNum;
|
||||||
|
AccessOffset += BlockNum;
|
||||||
|
Block = Next(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NTSTATUS StorageSetFileCapacity(AIRFS_ Airfs, NODE_ Node, int64_t minimumRequiredCapacity)
|
||||||
|
{
|
||||||
|
StorageLock.Acquire();
|
||||||
|
|
||||||
|
int64_t TargetCapacity = ROUND_UP(minimumRequiredCapacity, ALLOCATION_UNIT);
|
||||||
|
NODE_ Block = Last(Node->FileBlocks);
|
||||||
|
int32_t BlockSize = Block ? ((int32_t*)Block)[-1] : 0;
|
||||||
|
int64_t CurrentCapacity = Block ? Block->FileOffset + BlockSize - FILEBLOCK_OVERHEAD: 0;
|
||||||
|
int64_t Add = TargetCapacity - CurrentCapacity;
|
||||||
|
|
||||||
|
while (Add > 0)
|
||||||
|
{
|
||||||
|
// Add a block if we can, preferably as large or larger than we need.
|
||||||
|
Add += FILEBLOCK_OVERHEAD;
|
||||||
|
Block = Near(Airfs->Available, &Add, SizeCmp, GE);
|
||||||
|
if (!Block) Block = Near(Airfs->Available, &Add, SizeCmp, LT);
|
||||||
|
Add -= FILEBLOCK_OVERHEAD;
|
||||||
|
if (Block)
|
||||||
|
{
|
||||||
|
Detach(Airfs->Available, Block);
|
||||||
|
BlockSize = ((int32_t*)Block)[-1];
|
||||||
|
Airfs->FreeSize -= BlockSize;
|
||||||
|
Block->FileOffset = CurrentCapacity;
|
||||||
|
Attach(Node->FileBlocks, Block, BlockCmp, &CurrentCapacity);
|
||||||
|
CurrentCapacity += BlockSize - FILEBLOCK_OVERHEAD;
|
||||||
|
Add -= BlockSize - FILEBLOCK_OVERHEAD;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageLock.Release();
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw away any trailing blocks that are no longer needed.
|
||||||
|
while (Add < 0)
|
||||||
|
{
|
||||||
|
Block = Last(Node->FileBlocks);
|
||||||
|
BlockSize = ((int32_t*)Block)[-1];
|
||||||
|
if (BlockSize - FILEBLOCK_OVERHEAD > -Add) break;
|
||||||
|
Add += BlockSize - FILEBLOCK_OVERHEAD;
|
||||||
|
Detach(Node->FileBlocks, Block);
|
||||||
|
Attach(Airfs->Available, Block, SizeCmp, &BlockSize);
|
||||||
|
Airfs->FreeSize += BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possibly downsize the last block.
|
||||||
|
if (Add < 0)
|
||||||
|
{
|
||||||
|
Block = Last(Node->FileBlocks);
|
||||||
|
int32_t OldBlockSize = ((int32_t*)Block)[-1];
|
||||||
|
int32_t NewBlockSize = OldBlockSize - (int32_t) ROUND_DOWN(-Add, MINIMUM_ALLOCSIZE);
|
||||||
|
if (NewBlockSize < MINIMUM_ALLOCSIZE) NewBlockSize = MINIMUM_ALLOCSIZE;
|
||||||
|
int32_t RemainderBlockSize = OldBlockSize - NewBlockSize - sizeof int32_t;
|
||||||
|
if (RemainderBlockSize >= MINIMUM_ALLOCSIZE) // i.e. if not too near the end
|
||||||
|
{
|
||||||
|
char* Addr = (char*)Block + NewBlockSize + sizeof int32_t;
|
||||||
|
NODE_ Remainder = (NODE_) Addr;
|
||||||
|
((int32_t*)Remainder)[-1] = RemainderBlockSize;
|
||||||
|
Attach(Airfs->Available, Remainder, SizeCmp, &RemainderBlockSize);
|
||||||
|
Airfs->FreeSize += RemainderBlockSize;
|
||||||
|
((int32_t*)Block)[-1] = NewBlockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageLock.Release();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NTSTATUS StorageStartup(AIRFS_ &Airfs, WCHAR* MapName, WCHAR* StorageFileName, int64_t VolumeLength)
|
||||||
|
{
|
||||||
|
HANDLE MapFileHandle = INVALID_HANDLE_VALUE;
|
||||||
|
Airfs = 0;
|
||||||
|
|
||||||
|
// Open.
|
||||||
|
if (*StorageFileName)
|
||||||
|
{
|
||||||
|
MapFileHandle = CreateFileW(StorageFileName, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, OPEN_ALWAYS, NULL, NULL);
|
||||||
|
if (MapFileHandle == INVALID_HANDLE_VALUE) return GetLastErrorAsStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map.
|
||||||
|
HANDLE MapHandle = CreateFileMappingW(MapFileHandle, NULL, PAGE_EXECUTE_READWRITE, VolumeLength>>32, VolumeLength & 0xFFFFFFFF, MapName);
|
||||||
|
if (!MapHandle) return GetLastErrorAsStatus();
|
||||||
|
|
||||||
|
// Point.
|
||||||
|
char* MappedAddress = (char*) MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, VolumeLength);
|
||||||
|
if (!MappedAddress) return GetLastErrorAsStatus();
|
||||||
|
|
||||||
|
// Keep.
|
||||||
|
Airfs = (AIRFS_) MappedAddress;
|
||||||
|
Airfs->MapFileHandle = MapFileHandle;
|
||||||
|
Airfs->MapHandle = MapHandle;
|
||||||
|
Airfs->VolumeLength = VolumeLength;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NTSTATUS StorageShutdown(AIRFS_ Airfs)
|
||||||
|
{
|
||||||
|
BOOL Ok;
|
||||||
|
NTSTATUS Result = 0;
|
||||||
|
HANDLE M = Airfs->MapHandle;
|
||||||
|
HANDLE F = Airfs->MapFileHandle;
|
||||||
|
|
||||||
|
Ok = FlushViewOfFile(Airfs, 0); if (!Ok && !Result) Result = GetLastErrorAsStatus();
|
||||||
|
if (F != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
Ok = FlushFileBuffers(F); if (!Ok && !Result) Result = GetLastErrorAsStatus();
|
||||||
|
// TODO: Set and write a flag something like Airfs->UpdatesCompleted here?
|
||||||
|
}
|
||||||
|
Ok = UnmapViewOfFile(Airfs); if (!Ok && !Result) Result = GetLastErrorAsStatus();
|
||||||
|
|
||||||
|
if (M)
|
||||||
|
{
|
||||||
|
Ok = CloseHandle(M); if (!Ok && !Result) Result = GetLastErrorAsStatus();
|
||||||
|
}
|
||||||
|
if (F != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
Ok = CloseHandle(F); if (!Ok && !Result) Result = GetLastErrorAsStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
35
tst/launcher-tests/echo.c
Normal file
35
tst/launcher-tests/echo.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Compile:
|
||||||
|
* - cl -I"%ProgramFiles(x86)%\WinFsp\inc" "%ProgramFiles(x86)%\WinFsp\lib\winfsp-x64.lib" echo.c
|
||||||
|
*
|
||||||
|
* Register:
|
||||||
|
* - echo.reg (fix Executable path first)
|
||||||
|
*
|
||||||
|
* Run:
|
||||||
|
* - launchctl-x64 start echo 1 \foo\bar\baz
|
||||||
|
*
|
||||||
|
* Expect:
|
||||||
|
* - "\foo\bar\baz" "bar:baz" "DOMAIN\\USERNAME"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t *argv[])
|
||||||
|
{
|
||||||
|
WCHAR buf[512], *bufp;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
bufp = buf;
|
||||||
|
for (int i = 0; argc > i; i++)
|
||||||
|
{
|
||||||
|
len = lstrlenW(argv[i]);
|
||||||
|
memcpy(bufp, argv[i], len * sizeof(WCHAR));
|
||||||
|
bufp += len;
|
||||||
|
*bufp++ = '\n';
|
||||||
|
}
|
||||||
|
*bufp = '\0';
|
||||||
|
|
||||||
|
FspServiceLog(EVENTLOG_INFORMATION_TYPE, L"%s", buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
tst/launcher-tests/echo.reg
Normal file
BIN
tst/launcher-tests/echo.reg
Normal file
Binary file not shown.
BIN
tst/launcher-tests/secret.reg
Normal file
BIN
tst/launcher-tests/secret.reg
Normal file
Binary file not shown.
@ -19,12 +19,17 @@
|
|||||||
* associated repository.
|
* associated repository.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MEMFS_SLOWIO
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.AccessControl;
|
using System.Security.AccessControl;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
#endif
|
||||||
|
|
||||||
using Fsp;
|
using Fsp;
|
||||||
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
||||||
@ -232,15 +237,20 @@ namespace memfs
|
|||||||
|
|
||||||
class Memfs : FileSystemBase
|
class Memfs : FileSystemBase
|
||||||
{
|
{
|
||||||
|
private FileSystemHost Host;
|
||||||
public const UInt16 MEMFS_SECTOR_SIZE = 512;
|
public const UInt16 MEMFS_SECTOR_SIZE = 512;
|
||||||
public const UInt16 MEMFS_SECTORS_PER_ALLOCATION_UNIT = 1;
|
public const UInt16 MEMFS_SECTORS_PER_ALLOCATION_UNIT = 1;
|
||||||
|
|
||||||
public Memfs(
|
public Memfs(
|
||||||
Boolean CaseInsensitive, UInt32 MaxFileNodes, UInt32 MaxFileSize, String RootSddl)
|
Boolean CaseInsensitive, UInt32 MaxFileNodes, UInt32 MaxFileSize, String RootSddl,
|
||||||
|
UInt64 SlowioMaxDelay, UInt64 SlowioPercentDelay, UInt64 SlowioRarefyDelay)
|
||||||
{
|
{
|
||||||
this.FileNodeMap = new FileNodeMap(CaseInsensitive);
|
this.FileNodeMap = new FileNodeMap(CaseInsensitive);
|
||||||
this.MaxFileNodes = MaxFileNodes;
|
this.MaxFileNodes = MaxFileNodes;
|
||||||
this.MaxFileSize = MaxFileSize;
|
this.MaxFileSize = MaxFileSize;
|
||||||
|
this.SlowioMaxDelay = SlowioMaxDelay;
|
||||||
|
this.SlowioPercentDelay = SlowioPercentDelay;
|
||||||
|
this.SlowioRarefyDelay = SlowioRarefyDelay;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create root directory.
|
* Create root directory.
|
||||||
@ -259,7 +269,7 @@ namespace memfs
|
|||||||
|
|
||||||
public override Int32 Init(Object Host0)
|
public override Int32 Init(Object Host0)
|
||||||
{
|
{
|
||||||
FileSystemHost Host = (FileSystemHost)Host0;
|
Host = (FileSystemHost)Host0;
|
||||||
Host.SectorSize = Memfs.MEMFS_SECTOR_SIZE;
|
Host.SectorSize = Memfs.MEMFS_SECTOR_SIZE;
|
||||||
Host.SectorsPerAllocationUnit = Memfs.MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
Host.SectorsPerAllocationUnit = Memfs.MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
||||||
Host.VolumeCreationTime = (UInt64)DateTime.Now.ToFileTimeUtc();
|
Host.VolumeCreationTime = (UInt64)DateTime.Now.ToFileTimeUtc();
|
||||||
@ -274,9 +284,24 @@ namespace memfs
|
|||||||
Host.PostCleanupWhenModifiedOnly = true;
|
Host.PostCleanupWhenModifiedOnly = true;
|
||||||
Host.PassQueryDirectoryFileName = true;
|
Host.PassQueryDirectoryFileName = true;
|
||||||
Host.ExtendedAttributes = true;
|
Host.ExtendedAttributes = true;
|
||||||
|
Host.WslFeatures = true;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
public override int Mounted(object Host)
|
||||||
|
{
|
||||||
|
SlowioTasksRunning = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Unmounted(object Host)
|
||||||
|
{
|
||||||
|
while (SlowioTasksRunning != 0)
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public override Int32 GetVolumeInfo(
|
public override Int32 GetVolumeInfo(
|
||||||
out VolumeInfo VolumeInfo)
|
out VolumeInfo VolumeInfo)
|
||||||
{
|
{
|
||||||
@ -331,8 +356,9 @@ namespace memfs
|
|||||||
UInt32 FileAttributes,
|
UInt32 FileAttributes,
|
||||||
Byte[] SecurityDescriptor,
|
Byte[] SecurityDescriptor,
|
||||||
UInt64 AllocationSize,
|
UInt64 AllocationSize,
|
||||||
IntPtr Ea,
|
IntPtr ExtraBuffer,
|
||||||
UInt32 EaLength,
|
UInt32 ExtraLength,
|
||||||
|
Boolean ExtraBufferIsReparsePoint,
|
||||||
out Object FileNode0,
|
out Object FileNode0,
|
||||||
out Object FileDesc,
|
out Object FileDesc,
|
||||||
out FileInfo FileInfo,
|
out FileInfo FileInfo,
|
||||||
@ -369,12 +395,22 @@ namespace memfs
|
|||||||
FileNode.FileInfo.FileAttributes = 0 != (FileAttributes & (UInt32)System.IO.FileAttributes.Directory) ?
|
FileNode.FileInfo.FileAttributes = 0 != (FileAttributes & (UInt32)System.IO.FileAttributes.Directory) ?
|
||||||
FileAttributes : FileAttributes | (UInt32)System.IO.FileAttributes.Archive;
|
FileAttributes : FileAttributes | (UInt32)System.IO.FileAttributes.Archive;
|
||||||
FileNode.FileSecurity = SecurityDescriptor;
|
FileNode.FileSecurity = SecurityDescriptor;
|
||||||
if (IntPtr.Zero != Ea)
|
if (IntPtr.Zero != ExtraBuffer)
|
||||||
{
|
{
|
||||||
Result = SetEaEntries(FileNode, null, Ea, EaLength);
|
if (!ExtraBufferIsReparsePoint)
|
||||||
|
{
|
||||||
|
Result = SetEaEntries(FileNode, null, ExtraBuffer, ExtraLength);
|
||||||
if (0 > Result)
|
if (0 > Result)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Byte[] ReparseData = MakeReparsePoint(ExtraBuffer, ExtraLength);
|
||||||
|
FileNode.FileInfo.FileAttributes |= (UInt32)System.IO.FileAttributes.ReparsePoint;
|
||||||
|
FileNode.FileInfo.ReparseTag = GetReparseTag(ReparseData);
|
||||||
|
FileNode.ReparseData = ReparseData;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (0 != AllocationSize)
|
if (0 != AllocationSize)
|
||||||
{
|
{
|
||||||
Result = SetFileSizeInternal(FileNode, AllocationSize, true);
|
Result = SetFileSizeInternal(FileNode, AllocationSize, true);
|
||||||
@ -549,6 +585,93 @@ namespace memfs
|
|||||||
Interlocked.Decrement(ref FileNode.OpenCount);
|
Interlocked.Decrement(ref FileNode.OpenCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
private UInt64 Hash(UInt64 X)
|
||||||
|
{
|
||||||
|
X = (X ^ (X >> 30)) * 0xbf58476d1ce4e5b9ul;
|
||||||
|
X = (X ^ (X >> 27)) * 0x94d049bb133111ebul;
|
||||||
|
X = X ^ (X >> 31);
|
||||||
|
return X;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Spin = 0;
|
||||||
|
|
||||||
|
private UInt64 PseudoRandom(UInt64 To)
|
||||||
|
{
|
||||||
|
/* John Oberschelp's PRNG */
|
||||||
|
Interlocked.Increment(ref Spin);
|
||||||
|
return Hash((UInt64)Spin) % To;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SlowioReturnPending()
|
||||||
|
{
|
||||||
|
if (0 == SlowioMaxDelay)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return PseudoRandom(100) < SlowioPercentDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioSnooze()
|
||||||
|
{
|
||||||
|
double Millis = PseudoRandom(SlowioMaxDelay + 1) >> (int) PseudoRandom(SlowioRarefyDelay + 1);
|
||||||
|
Thread.Sleep(TimeSpan.FromMilliseconds(Millis));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioReadTask(
|
||||||
|
Object FileNode0,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt64 EndOffset,
|
||||||
|
UInt64 RequestHint)
|
||||||
|
{
|
||||||
|
SlowioSnooze();
|
||||||
|
|
||||||
|
UInt32 BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
|
FileNode FileNode = (FileNode)FileNode0;
|
||||||
|
Marshal.Copy(FileNode.FileData, (int)Offset, Buffer, (int)BytesTransferred);
|
||||||
|
|
||||||
|
Host.SendReadResponse(RequestHint, STATUS_SUCCESS, BytesTransferred);
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioWriteTask(
|
||||||
|
Object FileNode0,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt64 EndOffset,
|
||||||
|
UInt64 RequestHint)
|
||||||
|
{
|
||||||
|
SlowioSnooze();
|
||||||
|
|
||||||
|
UInt32 BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
|
FileNode FileNode = (FileNode)FileNode0;
|
||||||
|
FileInfo FileInfo = FileNode.GetFileInfo();
|
||||||
|
Marshal.Copy(Buffer, FileNode.FileData, (int)Offset, (int)BytesTransferred);
|
||||||
|
|
||||||
|
Host.SendWriteResponse(RequestHint, STATUS_SUCCESS, BytesTransferred, ref FileInfo);
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioReadDirectoryTask(
|
||||||
|
Object FileNode0,
|
||||||
|
Object FileDesc,
|
||||||
|
String Pattern,
|
||||||
|
String Marker,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Length,
|
||||||
|
UInt64 RequestHint)
|
||||||
|
{
|
||||||
|
SlowioSnooze();
|
||||||
|
|
||||||
|
UInt32 BytesTransferred;
|
||||||
|
var Status = SeekableReadDirectory(FileNode0, FileDesc, Pattern, Marker, Buffer, Length, out BytesTransferred);
|
||||||
|
|
||||||
|
Host.SendReadDirectoryResponse(RequestHint, Status, BytesTransferred);
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public override Int32 Read(
|
public override Int32 Read(
|
||||||
Object FileNode0,
|
Object FileNode0,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -570,6 +693,25 @@ namespace memfs
|
|||||||
if (EndOffset > FileNode.FileInfo.FileSize)
|
if (EndOffset > FileNode.FileInfo.FileSize)
|
||||||
EndOffset = FileNode.FileInfo.FileSize;
|
EndOffset = FileNode.FileInfo.FileSize;
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
if (SlowioReturnPending())
|
||||||
|
{
|
||||||
|
var Hint = Host.GetOperationRequestHint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref SlowioTasksRunning);
|
||||||
|
Task.Run(() => SlowioReadTask(FileNode0, Buffer, Offset, EndOffset, Hint)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
BytesTransferred = 0;
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BytesTransferred = (UInt32)(EndOffset - Offset);
|
BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
Marshal.Copy(FileNode.FileData, (int)Offset, Buffer, (int)BytesTransferred);
|
Marshal.Copy(FileNode.FileData, (int)Offset, Buffer, (int)BytesTransferred);
|
||||||
|
|
||||||
@ -619,6 +761,26 @@ namespace memfs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
if (SlowioReturnPending())
|
||||||
|
{
|
||||||
|
var hint = Host.GetOperationRequestHint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref SlowioTasksRunning);
|
||||||
|
Task.Run(() => SlowioWriteTask(FileNode0, Buffer, Offset, EndOffset, hint)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
BytesTransferred = 0;
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BytesTransferred = (UInt32)(EndOffset - Offset);
|
BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
Marshal.Copy(Buffer, FileNode.FileData, (int)Offset, (int)BytesTransferred);
|
Marshal.Copy(Buffer, FileNode.FileData, (int)Offset, (int)BytesTransferred);
|
||||||
|
|
||||||
@ -902,6 +1064,37 @@ namespace memfs
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
public override int ReadDirectory(
|
||||||
|
Object FileNode0,
|
||||||
|
Object FileDesc,
|
||||||
|
String Pattern,
|
||||||
|
String Marker,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Length,
|
||||||
|
out UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
if (SlowioReturnPending())
|
||||||
|
{
|
||||||
|
var Hint = Host.GetOperationRequestHint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref SlowioTasksRunning);
|
||||||
|
Task.Run(() => SlowioReadDirectoryTask(FileNode0, FileDesc, Pattern, Marker, Buffer, Length, Hint));
|
||||||
|
BytesTransferred = 0;
|
||||||
|
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SeekableReadDirectory(FileNode0, FileDesc, Pattern, Marker, Buffer, Length, out BytesTransferred);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public override int GetDirInfoByName(
|
public override int GetDirInfoByName(
|
||||||
Object ParentNode0,
|
Object ParentNode0,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -1140,6 +1333,10 @@ namespace memfs
|
|||||||
private FileNodeMap FileNodeMap;
|
private FileNodeMap FileNodeMap;
|
||||||
private UInt32 MaxFileNodes;
|
private UInt32 MaxFileNodes;
|
||||||
private UInt32 MaxFileSize;
|
private UInt32 MaxFileSize;
|
||||||
|
private UInt64 SlowioMaxDelay;
|
||||||
|
private UInt64 SlowioPercentDelay;
|
||||||
|
private UInt64 SlowioRarefyDelay;
|
||||||
|
private volatile Int32 SlowioTasksRunning;
|
||||||
private String VolumeLabel;
|
private String VolumeLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,6 +1367,9 @@ namespace memfs
|
|||||||
UInt32 FileInfoTimeout = unchecked((UInt32)(-1));
|
UInt32 FileInfoTimeout = unchecked((UInt32)(-1));
|
||||||
UInt32 MaxFileNodes = 1024;
|
UInt32 MaxFileNodes = 1024;
|
||||||
UInt32 MaxFileSize = 16 * 1024 * 1024;
|
UInt32 MaxFileSize = 16 * 1024 * 1024;
|
||||||
|
UInt32 SlowioMaxDelay = 0;
|
||||||
|
UInt32 SlowioPercentDelay = 0;
|
||||||
|
UInt32 SlowioRarefyDelay = 0;
|
||||||
String FileSystemName = null;
|
String FileSystemName = null;
|
||||||
String VolumePrefix = null;
|
String VolumePrefix = null;
|
||||||
String MountPoint = null;
|
String MountPoint = null;
|
||||||
@ -1202,9 +1402,18 @@ namespace memfs
|
|||||||
case 'm':
|
case 'm':
|
||||||
argtos(Args, ref I, ref MountPoint);
|
argtos(Args, ref I, ref MountPoint);
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
argtol(Args, ref I, ref SlowioMaxDelay);
|
||||||
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
argtol(Args, ref I, ref MaxFileNodes);
|
argtol(Args, ref I, ref MaxFileNodes);
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
argtol(Args, ref I, ref SlowioPercentDelay);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
argtol(Args, ref I, ref SlowioRarefyDelay);
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
argtos(Args, ref I, ref RootSddl);
|
argtos(Args, ref I, ref RootSddl);
|
||||||
break;
|
break;
|
||||||
@ -1233,7 +1442,8 @@ namespace memfs
|
|||||||
throw new CommandLineUsageException("cannot open debug log file");
|
throw new CommandLineUsageException("cannot open debug log file");
|
||||||
|
|
||||||
Host = new FileSystemHost(Memfs = new Memfs(
|
Host = new FileSystemHost(Memfs = new Memfs(
|
||||||
CaseInsensitive, MaxFileNodes, MaxFileSize, RootSddl));
|
CaseInsensitive, MaxFileNodes, MaxFileSize, RootSddl,
|
||||||
|
SlowioMaxDelay, SlowioPercentDelay, SlowioRarefyDelay));
|
||||||
Host.FileInfoTimeout = FileInfoTimeout;
|
Host.FileInfoTimeout = FileInfoTimeout;
|
||||||
Host.Prefix = VolumePrefix;
|
Host.Prefix = VolumePrefix;
|
||||||
Host.FileSystemName = null != FileSystemName ? FileSystemName : "-MEMFS";
|
Host.FileSystemName = null != FileSystemName ? FileSystemName : "-MEMFS";
|
||||||
@ -1262,6 +1472,9 @@ namespace memfs
|
|||||||
" -t FileInfoTimeout [millis]\n" +
|
" -t FileInfoTimeout [millis]\n" +
|
||||||
" -n MaxFileNodes\n" +
|
" -n MaxFileNodes\n" +
|
||||||
" -s MaxFileSize [bytes]\n" +
|
" -s MaxFileSize [bytes]\n" +
|
||||||
|
" -M MaxDelay [maximum slow IO delay in millis]\n" +
|
||||||
|
" -P PercentDelay [percent of slow IO to make pending]\n" +
|
||||||
|
" -R RarefyDelay [adjust the rarity of pending slow IO]\n" +
|
||||||
" -F FileSystemName\n" +
|
" -F FileSystemName\n" +
|
||||||
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n" +
|
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n" +
|
||||||
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
||||||
|
10
tst/memfs-fuse3/.gitignore
vendored
Normal file
10
tst/memfs-fuse3/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
build
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.vcproj.*
|
||||||
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
|
*.exe
|
||||||
|
*.install
|
18
tst/memfs-fuse3/Makefile
Normal file
18
tst/memfs-fuse3/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
usage:
|
||||||
|
@echo "make cygfuse3|winfsp-fuse3" 1>&2
|
||||||
|
@echo "" 1>&2
|
||||||
|
@echo " cygfuse3 Link with CYGFUSE3" 1>&2
|
||||||
|
@echo " winfsp-fuse3 Link with WinFsp-FUSE3" 1>&2
|
||||||
|
@exit 2
|
||||||
|
|
||||||
|
cygfuse3: memfs-cygfuse3
|
||||||
|
|
||||||
|
winfsp-fuse3: memfs-winfsp-fuse3
|
||||||
|
|
||||||
|
memfs-cygfuse3: memfs-fuse3.cpp
|
||||||
|
g++ $^ -o $@ -g -Wall `pkg-config fuse3 --cflags --libs`
|
||||||
|
|
||||||
|
memfs-winfsp-fuse3: export PKG_CONFIG_PATH=$(PWD)/winfsp.install/lib
|
||||||
|
memfs-winfsp-fuse3: memfs-fuse3.cpp
|
||||||
|
ln -nsf "`regtool --wow32 get '/HKLM/Software/WinFsp/InstallDir' | cygpath -au -f -`" winfsp.install
|
||||||
|
g++ $^ -o $@ -g -Wall `pkg-config fuse3 --cflags --libs`
|
7
tst/memfs-fuse3/README.md
Normal file
7
tst/memfs-fuse3/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
`Memfs-fuse3` is an in-memory FUSE3 file system.
|
||||||
|
|
||||||
|
It can be built with the following tools:
|
||||||
|
|
||||||
|
- Using Visual Studio (`memfs-fuse3.sln`).
|
||||||
|
- Using Cygwin GCC and linking directly with the WinFsp DLL (`make winfsp-fuse3`).
|
||||||
|
- Using Cygwin GCC and linking to CYGFUSE3 (`make cygfuse3`).
|
104
tst/memfs-fuse3/compat.h
Normal file
104
tst/memfs-fuse3/compat.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* @file compat.h
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMPAT_H_INCLUDED
|
||||||
|
#define COMPAT_H_INCLUDED
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(FSP_FUSE_SYM)
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#undef fuse_main
|
||||||
|
#define fuse_main(argc, argv, ops, data)\
|
||||||
|
(FspLoad(0), fuse_main_real(argc, argv, ops, sizeof *(ops), data))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_WIN32) && !defined(fuse_stat)
|
||||||
|
|
||||||
|
#define fuse_uid_t uid_t
|
||||||
|
#define fuse_gid_t gid_t
|
||||||
|
#define fuse_pid_t pid_t
|
||||||
|
|
||||||
|
#define fuse_dev_t dev_t
|
||||||
|
#define fuse_mode_t mode_t
|
||||||
|
#define fuse_nlink_t nlink_t
|
||||||
|
#define fuse_off_t off_t
|
||||||
|
|
||||||
|
#define fuse_fsblkcnt_t fsblkcnt_t
|
||||||
|
#define fuse_fsfilcnt_t fsfilcnt_t
|
||||||
|
#define fuse_blksize_t blksize_t
|
||||||
|
#define fuse_blkcnt_t blkcnt_t
|
||||||
|
|
||||||
|
#define fuse_timespec timespec
|
||||||
|
|
||||||
|
#define fuse_stat stat
|
||||||
|
|
||||||
|
#define fuse_statvfs statvfs
|
||||||
|
|
||||||
|
#define fuse_flock flock
|
||||||
|
|
||||||
|
#define fuse_iovec iovec
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(S_IFMT)
|
||||||
|
#define S_IFMT 0170000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFDIR)
|
||||||
|
#define S_IFDIR 0040000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFCHR)
|
||||||
|
#define S_IFCHR 0020000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFBLK)
|
||||||
|
#define S_IFBLK 0060000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFREG)
|
||||||
|
#define S_IFREG 0100000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFLNK)
|
||||||
|
#define S_IFLNK 0120000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFSOCK)
|
||||||
|
#define S_IFSOCK 0140000
|
||||||
|
#endif
|
||||||
|
#if !defined(S_IFIFO)
|
||||||
|
#define S_IFIFO 0010000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define st_atim st_atimespec
|
||||||
|
#define st_ctim st_ctimespec
|
||||||
|
#define st_mtim st_mtimespec
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__) || defined(__linux__) || defined(__CYGWIN__)
|
||||||
|
#include <sys/xattr.h>
|
||||||
|
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(_WIN32)
|
||||||
|
#define XATTR_CREATE 1
|
||||||
|
#define XATTR_REPLACE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(ENOATTR)
|
||||||
|
#define ENOATTR ENODATA
|
||||||
|
#elif !defined(ENODATA)
|
||||||
|
#define ENODATA ENOATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
619
tst/memfs-fuse3/memfs-fuse3.cpp
Normal file
619
tst/memfs-fuse3/memfs-fuse3.cpp
Normal file
@ -0,0 +1,619 @@
|
|||||||
|
/**
|
||||||
|
* @file memfs-fuse3.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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 <cerrno>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
class memfs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
memfs() : _ino(1), _root(std::make_shared<node_t>(_ino, S_IFDIR | 00777, 0, 0))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
static fuse_operations ops =
|
||||||
|
{
|
||||||
|
getattr,
|
||||||
|
readlink,
|
||||||
|
mknod,
|
||||||
|
mkdir,
|
||||||
|
unlink,
|
||||||
|
rmdir,
|
||||||
|
symlink,
|
||||||
|
rename,
|
||||||
|
link,
|
||||||
|
chmod,
|
||||||
|
chown,
|
||||||
|
truncate,
|
||||||
|
open,
|
||||||
|
read,
|
||||||
|
write,
|
||||||
|
statfs,
|
||||||
|
flush,
|
||||||
|
release,
|
||||||
|
0, // fsync
|
||||||
|
setxattr,
|
||||||
|
getxattr,
|
||||||
|
listxattr,
|
||||||
|
removexattr,
|
||||||
|
opendir,
|
||||||
|
readdir,
|
||||||
|
releasedir,
|
||||||
|
0, // fsyncdir
|
||||||
|
init,
|
||||||
|
0, // destroy
|
||||||
|
0, // access
|
||||||
|
0, // create
|
||||||
|
0, // lock
|
||||||
|
utimens,
|
||||||
|
0, // bmap
|
||||||
|
#if 0
|
||||||
|
ioctl,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
return fuse_main(argc, argv, &ops, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct node_t
|
||||||
|
{
|
||||||
|
node_t(fuse_ino_t ino, fuse_mode_t mode, fuse_uid_t uid, fuse_gid_t gid, fuse_dev_t dev = 0)
|
||||||
|
: stat()
|
||||||
|
{
|
||||||
|
stat.st_ino = ino;
|
||||||
|
stat.st_mode = mode;
|
||||||
|
stat.st_nlink = 1;
|
||||||
|
stat.st_uid = uid;
|
||||||
|
stat.st_gid = gid;
|
||||||
|
stat.st_rdev = dev;
|
||||||
|
stat.st_atim = stat.st_mtim = stat.st_ctim = now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t size, bool capacity)
|
||||||
|
{
|
||||||
|
if (capacity)
|
||||||
|
{
|
||||||
|
const size_t unit = 64 * 1024;
|
||||||
|
size_t newcap = (size + unit - 1) / unit * unit;
|
||||||
|
size_t oldcap = data.capacity();
|
||||||
|
if (newcap > oldcap)
|
||||||
|
data.reserve(newcap);
|
||||||
|
else if (newcap < oldcap)
|
||||||
|
{
|
||||||
|
data.resize(newcap);
|
||||||
|
data.shrink_to_fit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.resize(size);
|
||||||
|
stat.st_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fuse_stat stat;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<node_t>> childmap;
|
||||||
|
std::unordered_map<std::string, std::vector<uint8_t>> xattrmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
static fuse_timespec now()
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
auto now = system_clock::now();
|
||||||
|
auto sec = floor<seconds>(now);
|
||||||
|
auto nsec = floor<nanoseconds>(now) - floor<nanoseconds>(sec);
|
||||||
|
return fuse_timespec
|
||||||
|
{
|
||||||
|
static_cast<decltype(fuse_timespec::tv_sec)>(sec.time_since_epoch().count()),
|
||||||
|
/* std::chrono epoch is UNIX epoch in C++20 */
|
||||||
|
static_cast<decltype(fuse_timespec::tv_nsec)>(nsec.count()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static memfs *getself()
|
||||||
|
{
|
||||||
|
return static_cast<memfs *>(fuse_get_context()->private_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
*stbuf = node->stat;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int readlink(const char *path, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (S_IFLNK != (node->stat.st_mode & S_IFMT))
|
||||||
|
return EINVAL;
|
||||||
|
size = (std::min)(size - 1, node->data.size());
|
||||||
|
std::memcpy(buf, node->data.data(), size);
|
||||||
|
buf[size] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mknod(const char *path, fuse_mode_t mode, fuse_dev_t dev)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->make_node(path, mode, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mkdir(const char *path, fuse_mode_t mode)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->make_node(path, S_IFDIR | (mode & 07777), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unlink(const char *path)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->remove_node(path, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rmdir(const char *path)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->remove_node(path, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int symlink(const char *dstpath, const char *srcpath)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->make_node(srcpath, S_IFLNK | 00777, 0, dstpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rename(const char *oldpath, const char *newpath, unsigned int flags)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto oldlookup = self->lookup_node(oldpath);
|
||||||
|
auto oldprnt = std::get<0>(oldlookup);
|
||||||
|
auto oldname = std::get<1>(oldlookup);
|
||||||
|
auto oldnode = std::get<2>(oldlookup);
|
||||||
|
if (!oldnode)
|
||||||
|
return -ENOENT;
|
||||||
|
auto newlookup = self->lookup_node(newpath);
|
||||||
|
auto newprnt = std::get<0>(newlookup);
|
||||||
|
auto newname = std::get<1>(newlookup);
|
||||||
|
auto newnode = std::get<2>(newlookup);
|
||||||
|
if (!newprnt)
|
||||||
|
return -ENOENT;
|
||||||
|
if (newname.empty())
|
||||||
|
// guard against directory loop creation
|
||||||
|
return -EINVAL;
|
||||||
|
if (oldprnt == newprnt && oldname == newname)
|
||||||
|
return 0;
|
||||||
|
if (newnode)
|
||||||
|
{
|
||||||
|
if (int errc = self->remove_node(newpath, S_IFDIR == (oldnode->stat.st_mode & S_IFMT)))
|
||||||
|
return errc;
|
||||||
|
}
|
||||||
|
oldprnt->childmap.erase(oldname);
|
||||||
|
newprnt->childmap[newname] = oldnode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int link(const char *oldpath, const char *newpath)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto oldlookup = self->lookup_node(oldpath);
|
||||||
|
auto oldnode = std::get<2>(oldlookup);
|
||||||
|
if (!oldnode)
|
||||||
|
return -ENOENT;
|
||||||
|
auto newlookup = self->lookup_node(newpath);
|
||||||
|
auto newprnt = std::get<0>(newlookup);
|
||||||
|
auto newname = std::get<1>(newlookup);
|
||||||
|
auto newnode = std::get<2>(newlookup);
|
||||||
|
if (!newprnt)
|
||||||
|
return -ENOENT;
|
||||||
|
if (newnode)
|
||||||
|
return -EEXIST;
|
||||||
|
oldnode->stat.st_nlink++;
|
||||||
|
newprnt->childmap[newname] = oldnode;
|
||||||
|
oldnode->stat.st_ctim = newprnt->stat.st_ctim = newprnt->stat.st_mtim = now();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int chmod(const char *path, fuse_mode_t mode,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
node->stat.st_mode = (node->stat.st_mode & S_IFMT) | (mode & 07777);
|
||||||
|
node->stat.st_ctim = now();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int chown(const char *path, fuse_uid_t uid, fuse_gid_t gid,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (-1 != uid)
|
||||||
|
node->stat.st_uid = uid;
|
||||||
|
if (-1 != gid)
|
||||||
|
node->stat.st_gid = gid;
|
||||||
|
node->stat.st_ctim = now();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int truncate(const char *path, fuse_off_t size,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (SIZE_MAX < size)
|
||||||
|
return -EFBIG;
|
||||||
|
node->resize(static_cast<size_t>(size), true);
|
||||||
|
node->stat.st_ctim = node->stat.st_mtim = now();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open(const char *path, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->open_node(path, false, fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read(const char *path, char *buf, size_t size, fuse_off_t off,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
fuse_off_t endoff = (std::min)(
|
||||||
|
off + static_cast<fuse_off_t>(size), static_cast<fuse_off_t>(node->data.size()));
|
||||||
|
if (off > endoff)
|
||||||
|
return 0;
|
||||||
|
std::memcpy(buf, node->data.data() + off, static_cast<int>(endoff - off));
|
||||||
|
node->stat.st_atim = now();
|
||||||
|
return static_cast<int>(endoff - off);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write(const char *path, const char *buf, size_t size, fuse_off_t off,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
fuse_off_t endoff = off + static_cast<fuse_off_t>(size);
|
||||||
|
if (SIZE_MAX < endoff)
|
||||||
|
return -EFBIG;
|
||||||
|
if (node->data.size() < endoff)
|
||||||
|
node->resize(static_cast<size_t>(endoff), true);
|
||||||
|
std::memcpy(node->data.data() + off, buf, static_cast<int>(endoff - off));
|
||||||
|
node->stat.st_ctim = node->stat.st_mtim = now();
|
||||||
|
return static_cast<int>(endoff - off);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int statfs(const char *path, struct fuse_statvfs *stbuf)
|
||||||
|
{
|
||||||
|
std::memset(stbuf, 0, sizeof *stbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flush(const char *path, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int release(const char *path, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->close_node(fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setxattr(const char *path, const char *name0, const char *value, size_t size,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (0 == std::strcmp("com.apple.ResourceFork", name0))
|
||||||
|
return -ENOTSUP;
|
||||||
|
std::string name = name0;
|
||||||
|
if (XATTR_CREATE == flags)
|
||||||
|
{
|
||||||
|
if (node->xattrmap.end() != node->xattrmap.find(name))
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
else if (XATTR_REPLACE == flags)
|
||||||
|
{
|
||||||
|
if (node->xattrmap.end() == node->xattrmap.find(name))
|
||||||
|
return -ENOATTR;
|
||||||
|
}
|
||||||
|
node->xattrmap[name].assign(value, value + size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getxattr(const char *path, const char *name0, char *value, size_t size)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (0 == std::strcmp("com.apple.ResourceFork", name0))
|
||||||
|
return -ENOTSUP;
|
||||||
|
std::string name = name0;
|
||||||
|
auto iter = node->xattrmap.find(name);
|
||||||
|
if (node->xattrmap.end() == iter)
|
||||||
|
return -ENOATTR;
|
||||||
|
if (0 != size)
|
||||||
|
{
|
||||||
|
if (iter->second.size() > size)
|
||||||
|
return -ERANGE;
|
||||||
|
std::memcpy(value, iter->second.data(), iter->second.size());
|
||||||
|
}
|
||||||
|
return static_cast<int>(iter->second.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int listxattr(const char *path, char *namebuf, size_t size)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
size_t copysize = 0;
|
||||||
|
for (auto elem : node->xattrmap)
|
||||||
|
{
|
||||||
|
size_t namesize = elem.first.size() + 1;
|
||||||
|
if (0 != size)
|
||||||
|
{
|
||||||
|
if (copysize + namesize > size)
|
||||||
|
return -ERANGE;
|
||||||
|
std::memcpy(namebuf + copysize, elem.first.c_str(), namesize);
|
||||||
|
copysize += namesize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return static_cast<int>(copysize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int removexattr(const char *path, const char *name0)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (0 == std::strcmp("com.apple.ResourceFork", name0))
|
||||||
|
return -ENOTSUP;
|
||||||
|
std::string name = name0;
|
||||||
|
return node->xattrmap.erase(name) ? 0 : -ENOATTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int opendir(const char *path, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->open_node(path, true, fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
|
||||||
|
struct fuse_file_info *fi, enum fuse_readdir_flags)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
filler(buf, ".", &node->stat, 0, FUSE_FILL_DIR_PLUS);
|
||||||
|
filler(buf, "..", nullptr, 0, FUSE_FILL_DIR_PLUS);
|
||||||
|
for (auto elem : node->childmap)
|
||||||
|
if (0 != filler(buf, elem.first.c_str(), &elem.second->stat, 0, FUSE_FILL_DIR_PLUS))
|
||||||
|
break;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int releasedir(const char *path, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
return self->close_node(fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *init(struct fuse_conn_info *conn,
|
||||||
|
struct fuse_config *conf)
|
||||||
|
{
|
||||||
|
conn->want |= (conn->capable & FUSE_CAP_READDIRPLUS);
|
||||||
|
return getself();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int utimens(const char *path, const struct fuse_timespec tmsp[2],
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto self = getself();
|
||||||
|
std::lock_guard<std::mutex> lock(self->_mutex);
|
||||||
|
auto node = self->get_node(path, fi);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (tmsp)
|
||||||
|
{
|
||||||
|
node->stat.st_ctim = now();
|
||||||
|
node->stat.st_atim = tmsp[0];
|
||||||
|
node->stat.st_mtim = tmsp[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
node->stat.st_ctim = node->stat.st_atim = node->stat.st_mtim = now();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int ioctl(const char *path, int cmd, void *arg, struct fuse_file_info *fi,
|
||||||
|
unsigned int flags, void *data)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::tuple<std::shared_ptr<node_t>, std::string, std::shared_ptr<node_t>>
|
||||||
|
lookup_node(const char *path, node_t *ancestor = nullptr)
|
||||||
|
{
|
||||||
|
auto prnt = _root;
|
||||||
|
std::string name;
|
||||||
|
auto node = prnt;
|
||||||
|
for (const char *part = path, *p; *part; part = p + !!(*p))
|
||||||
|
{
|
||||||
|
for (p = part; *p && '/' != *p; p++)
|
||||||
|
;
|
||||||
|
if (part == p)
|
||||||
|
continue;
|
||||||
|
prnt = node;
|
||||||
|
if (!node)
|
||||||
|
break;
|
||||||
|
name.assign(part, p);
|
||||||
|
auto iter = node->childmap.find(name);
|
||||||
|
node = node->childmap.end() != iter ? iter->second : nullptr;
|
||||||
|
if (ancestor && node.get() == ancestor)
|
||||||
|
{
|
||||||
|
name.assign(""); // special case loop condition
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::make_tuple(prnt, name, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
int make_node(const char *path, fuse_mode_t mode, fuse_dev_t dev, const char *data = nullptr)
|
||||||
|
{
|
||||||
|
auto lookup = lookup_node(path);
|
||||||
|
auto prnt = std::get<0>(lookup);
|
||||||
|
auto name = std::get<1>(lookup);
|
||||||
|
auto node = std::get<2>(lookup);
|
||||||
|
if (!prnt)
|
||||||
|
return -ENOENT;
|
||||||
|
if (node)
|
||||||
|
return -EEXIST;
|
||||||
|
fuse_context *context = fuse_get_context();
|
||||||
|
node = std::make_shared<node_t>(++_ino, mode, context->uid, context->gid, dev);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
node->resize(std::strlen(data), false);
|
||||||
|
std::memcpy(node->data.data(), data, node->data.size());
|
||||||
|
}
|
||||||
|
prnt->childmap[name] = node;
|
||||||
|
prnt->stat.st_ctim = prnt->stat.st_mtim = node->stat.st_ctim;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove_node(const char *path, bool dir)
|
||||||
|
{
|
||||||
|
auto lookup = lookup_node(path);
|
||||||
|
auto prnt = std::get<0>(lookup);
|
||||||
|
auto name = std::get<1>(lookup);
|
||||||
|
auto node = std::get<2>(lookup);
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (!dir && S_IFDIR == (node->stat.st_mode & S_IFMT))
|
||||||
|
return -EISDIR;
|
||||||
|
if (dir && S_IFDIR != (node->stat.st_mode & S_IFMT))
|
||||||
|
return -ENOTDIR;
|
||||||
|
if (0 < node->childmap.size())
|
||||||
|
return -ENOTEMPTY;
|
||||||
|
node->stat.st_nlink--;
|
||||||
|
prnt->childmap.erase(name);
|
||||||
|
node->stat.st_ctim = prnt->stat.st_ctim = prnt->stat.st_mtim = now();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_node(const char *path, bool dir, struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
auto node = std::get<2>(lookup_node(path));
|
||||||
|
if (!node)
|
||||||
|
return -ENOENT;
|
||||||
|
if (!dir && S_IFDIR == (node->stat.st_mode & S_IFMT))
|
||||||
|
return -EISDIR;
|
||||||
|
if (dir && S_IFDIR != (node->stat.st_mode & S_IFMT))
|
||||||
|
return -ENOTDIR;
|
||||||
|
// A file descriptor is a raw pointer to a shared_ptr.
|
||||||
|
// This has the effect of incrementing the shared_ptr
|
||||||
|
// refcount, thus keeping an open node around even
|
||||||
|
// if the node is unlinked.
|
||||||
|
fi->fh = (uint64_t)(uintptr_t)new std::shared_ptr<node_t>(node);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close_node(struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
delete (std::shared_ptr<node_t> *)(uintptr_t)fi->fh;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<node_t> get_node(const char *path, struct fuse_file_info *fi = nullptr)
|
||||||
|
{
|
||||||
|
if (!fi)
|
||||||
|
return std::get<2>(lookup_node(path));
|
||||||
|
else
|
||||||
|
return *(std::shared_ptr<node_t> *)(uintptr_t)fi->fh;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex _mutex;
|
||||||
|
fuse_ino_t _ino;
|
||||||
|
std::shared_ptr<node_t> _root;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return memfs().main(argc, argv);
|
||||||
|
}
|
28
tst/memfs-fuse3/memfs-fuse3.sln
Normal file
28
tst/memfs-fuse3/memfs-fuse3.sln
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 14
|
||||||
|
VisualStudioVersion = 14.0.25420.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memfs-fuse3", "memfs-fuse3.vcxproj", "{CF538F42-C714-4653-B351-E72FD7B0B217}"
|
||||||
|
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
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Release|x64.Build.0 = Release|x64
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{CF538F42-C714-4653-B351-E72FD7B0B217}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
189
tst/memfs-fuse3/memfs-fuse3.vcxproj
Normal file
189
tst/memfs-fuse3/memfs-fuse3.vcxproj
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" 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">
|
||||||
|
<ProjectGuid>{CF538F42-C714-4653-B351-E72FD7B0B217}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>memfsfuse3</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)'=='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|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)'=='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>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
|
||||||
|
</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)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
|
||||||
|
</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>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
|
||||||
|
</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)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
|
||||||
|
</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>
|
||||||
|
<ClInclude Include="compat.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="memfs-fuse3.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
19
tst/memfs-fuse3/memfs-fuse3.vcxproj.filters
Normal file
19
tst/memfs-fuse3/memfs-fuse3.vcxproj.filters
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?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;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="compat.h">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="memfs-fuse3.cpp">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -69,6 +69,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
|||||||
*/
|
*/
|
||||||
#define MEMFS_EA
|
#define MEMFS_EA
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the MEMFS_WSL macro to include WSLinux support.
|
||||||
|
*/
|
||||||
|
#define MEMFS_WSL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
||||||
* a check for the Write buffer to ensure that it is read-only.
|
* a check for the Write buffer to ensure that it is read-only.
|
||||||
@ -1047,8 +1052,8 @@ static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
#if defined(MEMFS_EA)
|
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
|
||||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
PVOID ExtraBuffer, ULONG ExtraLength, BOOLEAN ExtraBufferIsReparsePoint,
|
||||||
#endif
|
#endif
|
||||||
PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
@ -1129,10 +1134,14 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MEMFS_EA)
|
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
|
||||||
if (0 != Ea)
|
if (0 != ExtraBuffer)
|
||||||
{
|
{
|
||||||
Result = FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode, Ea, EaLength);
|
#if defined(MEMFS_EA)
|
||||||
|
if (!ExtraBufferIsReparsePoint)
|
||||||
|
{
|
||||||
|
Result = FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode,
|
||||||
|
(PFILE_FULL_EA_INFORMATION)ExtraBuffer, ExtraLength);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
@ -1140,6 +1149,30 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MEMFS_WSL)
|
||||||
|
if (ExtraBufferIsReparsePoint)
|
||||||
|
{
|
||||||
|
#if defined(MEMFS_REPARSE_POINTS)
|
||||||
|
FileNode->ReparseDataSize = ExtraLength;
|
||||||
|
FileNode->ReparseData = malloc(ExtraLength);
|
||||||
|
if (0 == FileNode->ReparseData && 0 != ExtraLength)
|
||||||
|
{
|
||||||
|
MemfsFileNodeDelete(FileNode);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
|
||||||
|
FileNode->FileInfo.ReparseTag = *(PULONG)ExtraBuffer;
|
||||||
|
/* the first field in a reparse buffer is the reparse tag */
|
||||||
|
memcpy(FileNode->ReparseData, ExtraBuffer, ExtraLength);
|
||||||
|
#else
|
||||||
|
MemfsFileNodeDelete(FileNode);
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
FileNode->FileInfo.AllocationSize = AllocationSize;
|
FileNode->FileInfo.AllocationSize = AllocationSize;
|
||||||
if (0 != FileNode->FileInfo.AllocationSize)
|
if (0 != FileNode->FileInfo.AllocationSize)
|
||||||
@ -2189,7 +2222,7 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
|||||||
GetVolumeInfo,
|
GetVolumeInfo,
|
||||||
SetVolumeLabel,
|
SetVolumeLabel,
|
||||||
GetSecurityByName,
|
GetSecurityByName,
|
||||||
#if defined(MEMFS_EA)
|
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
|
||||||
0,
|
0,
|
||||||
#else
|
#else
|
||||||
Create,
|
Create,
|
||||||
@ -2240,8 +2273,10 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
|||||||
0,
|
0,
|
||||||
#endif
|
#endif
|
||||||
0,
|
0,
|
||||||
#if defined(MEMFS_EA)
|
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
|
||||||
Create,
|
Create,
|
||||||
|
#endif
|
||||||
|
#if defined(MEMFS_EA)
|
||||||
Overwrite,
|
Overwrite,
|
||||||
GetEa,
|
GetEa,
|
||||||
SetEa
|
SetEa
|
||||||
@ -2347,6 +2382,9 @@ NTSTATUS MemfsCreateFunnel(
|
|||||||
#endif
|
#endif
|
||||||
#if defined(MEMFS_EA)
|
#if defined(MEMFS_EA)
|
||||||
VolumeParams.ExtendedAttributes = 1;
|
VolumeParams.ExtendedAttributes = 1;
|
||||||
|
#endif
|
||||||
|
#if defined(MEMFS_WSL)
|
||||||
|
VolumeParams.WslFeatures = 1;
|
||||||
#endif
|
#endif
|
||||||
VolumeParams.AllowOpenInKernelMode = 1;
|
VolumeParams.AllowOpenInKernelMode = 1;
|
||||||
if (0 != VolumePrefix)
|
if (0 != VolumePrefix)
|
||||||
|
3
tst/passthrough-cpp/.gitignore
vendored
3
tst/passthrough-cpp/.gitignore
vendored
@ -3,3 +3,6 @@ build
|
|||||||
*.suo
|
*.suo
|
||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
|
@ -22,32 +22,32 @@
|
|||||||
<ProjectGuid>{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}</ProjectGuid>
|
<ProjectGuid>{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>passthroughcpp</RootNamespace>
|
<RootNamespace>passthroughcpp</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
3
tst/passthrough-dotnet/.gitignore
vendored
3
tst/passthrough-dotnet/.gitignore
vendored
@ -4,3 +4,6 @@ build
|
|||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
*.csproj.user
|
*.csproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
|
3
tst/passthrough-fuse/.gitignore
vendored
3
tst/passthrough-fuse/.gitignore
vendored
@ -3,5 +3,8 @@ build
|
|||||||
*.suo
|
*.suo
|
||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
*.exe
|
*.exe
|
||||||
*.install
|
*.install
|
||||||
|
@ -22,32 +22,32 @@
|
|||||||
<ProjectGuid>{C753851C-142F-4AAD-B2F7-CBF905C2A600}</ProjectGuid>
|
<ProjectGuid>{C753851C-142F-4AAD-B2F7-CBF905C2A600}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>passthroughfuse</RootNamespace>
|
<RootNamespace>passthroughfuse</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
3
tst/passthrough-fuse3/.gitignore
vendored
3
tst/passthrough-fuse3/.gitignore
vendored
@ -3,5 +3,8 @@ build
|
|||||||
*.suo
|
*.suo
|
||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
*.exe
|
*.exe
|
||||||
*.install
|
*.install
|
||||||
|
@ -22,32 +22,32 @@
|
|||||||
<ProjectGuid>{5E99498C-D30C-48EF-A04A-7977C0305FAC}</ProjectGuid>
|
<ProjectGuid>{5E99498C-D30C-48EF-A04A-7977C0305FAC}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>passthroughfuse3</RootNamespace>
|
<RootNamespace>passthroughfuse3</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
3
tst/passthrough/.gitignore
vendored
3
tst/passthrough/.gitignore
vendored
@ -3,3 +3,6 @@ build
|
|||||||
*.suo
|
*.suo
|
||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
|
*.VC.db
|
||||||
|
*.VC.opendb
|
||||||
|
.vs
|
||||||
|
@ -25,32 +25,32 @@
|
|||||||
<ProjectGuid>{9E0E5997-7316-4818-A130-00B3AF1AD354}</ProjectGuid>
|
<ProjectGuid>{9E0E5997-7316-4818-A130-00B3AF1AD354}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>passthrough</RootNamespace>
|
<RootNamespace>passthrough</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
Binary file not shown.
112
tst/winfsp-tests/launcher-ptrans-test.c
Normal file
112
tst/winfsp-tests/launcher-ptrans-test.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/**
|
||||||
|
* @file launcher-ptrans-test.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2019 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/launch.h>
|
||||||
|
#include <tlib/testsuite.h>
|
||||||
|
|
||||||
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
|
#include <launcher/ptrans.c>
|
||||||
|
|
||||||
|
static void launcher_ptrans_test(void)
|
||||||
|
{
|
||||||
|
PWSTR ipaths[] =
|
||||||
|
{
|
||||||
|
L"", 0,
|
||||||
|
L"\\foo\\bar", 0,
|
||||||
|
L"", L"",
|
||||||
|
L"\\foo\\bar", L"",
|
||||||
|
L"\\foo\\bar", L"/",
|
||||||
|
L"\\foo\\bar", L"/_",
|
||||||
|
L"\\foo\\bar", L"/_1",
|
||||||
|
L"\\foo\\bar", L"\\_",
|
||||||
|
L"\\foo\\bar", L"\\_A",
|
||||||
|
L"\\foo\\bar", L"/a",
|
||||||
|
L"\\foo\\bar", L"/b",
|
||||||
|
L"\\foo\\bar", L"/c",
|
||||||
|
L"\\foo\\bar", L"/d",
|
||||||
|
L"\\foo\\bar", L"/a:b",
|
||||||
|
L"\\foo\\bar", L"/a:b&c!d",
|
||||||
|
L"\\foo\\bar", L"/b:a",
|
||||||
|
L"\\foo\\bar", L"/d!c&b:a",
|
||||||
|
L"\\foo\\bar", L"/a:_",
|
||||||
|
L"\\foo\\bar", L"/b:_",
|
||||||
|
L"\\foo\\bar", L"/c:_",
|
||||||
|
L"\\foo\\bar\\baz", L"/b:_",
|
||||||
|
L"\\foo\\bar\\baz\\bag", L"/b:_",
|
||||||
|
L"\\foo\\bar\\baz", L"/b:/_",
|
||||||
|
L"\\foo\\bar\\baz\\bag", L"/b:/_",
|
||||||
|
L"\\foo\\bar\\baz\\bag", L"/a:_:b:_",
|
||||||
|
L"\\foo\\bar\\baz\\bag", L"/_:_",
|
||||||
|
};
|
||||||
|
PWSTR opaths[] =
|
||||||
|
{
|
||||||
|
L"",
|
||||||
|
L"\\foo\\bar",
|
||||||
|
L"",
|
||||||
|
L"",
|
||||||
|
L"",
|
||||||
|
L"/foo/bar",
|
||||||
|
L"/foo/bar",
|
||||||
|
L"\\\\foo\\\\bar",
|
||||||
|
L"\\\\foo\\\\bar",
|
||||||
|
L"foo",
|
||||||
|
L"bar",
|
||||||
|
L"",
|
||||||
|
L"",
|
||||||
|
L"foo:bar",
|
||||||
|
L"foo:bar&!",
|
||||||
|
L"bar:foo",
|
||||||
|
L"!&bar:foo",
|
||||||
|
L"foo:bar",
|
||||||
|
L"bar:",
|
||||||
|
L":",
|
||||||
|
L"bar:baz",
|
||||||
|
L"bar:baz/bag",
|
||||||
|
L"bar:/baz",
|
||||||
|
L"bar:/baz/bag",
|
||||||
|
L"foo:bar/baz/bag:bar:baz/bag",
|
||||||
|
L"/foo/bar/baz/bag:/foo/bar/baz/bag",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; sizeof ipaths / (sizeof ipaths[0] * 2) > i; i++)
|
||||||
|
{
|
||||||
|
WCHAR Buf[1024];
|
||||||
|
ULONG Length;
|
||||||
|
PWSTR Dest;
|
||||||
|
|
||||||
|
Length = (ULONG)(UINT_PTR)PathTransform(0, ipaths[2 * i + 0], ipaths[2 * i + 1]);
|
||||||
|
ASSERT(Length == wcslen(opaths[i]) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
Dest = PathTransform(Buf, ipaths[2 * i + 0], ipaths[2 * i + 1]);
|
||||||
|
*Dest = L'\0';
|
||||||
|
ASSERT(Dest == Buf + wcslen(opaths[i]));
|
||||||
|
ASSERT(0 == wcscmp(Buf, opaths[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void launcher_ptrans_tests(void)
|
||||||
|
{
|
||||||
|
if (OptExternal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TEST_OPT(launcher_ptrans_test);
|
||||||
|
}
|
@ -319,6 +319,15 @@ void mount_preflight_dotest(PWSTR DeviceName)
|
|||||||
MountPoint[2] = L'\0';
|
MountPoint[2] = L'\0';
|
||||||
|
|
||||||
GetTestDirectory(DirBuf);
|
GetTestDirectory(DirBuf);
|
||||||
|
/*
|
||||||
|
* Mount points starting with \\?\X: or \\.\X: are now considered MountManager mountpoints.
|
||||||
|
* So skip the \\?\ prefix to avoid this problem.
|
||||||
|
*/
|
||||||
|
if (L'\\' == DirBuf[0] &&
|
||||||
|
L'\\' == DirBuf[1] &&
|
||||||
|
(L'?' == DirBuf[2] || L'.' == DirBuf[2]) &&
|
||||||
|
L'\\' == DirBuf[3])
|
||||||
|
memmove(DirBuf, DirBuf + 4, (wcslen(DirBuf + 4) + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
Drives = GetLogicalDrives();
|
Drives = GetLogicalDrives();
|
||||||
ASSERT(0 != Drives);
|
ASSERT(0 != Drives);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user