Compare commits

..

76 Commits

Author SHA1 Message Date
0002655782 build: update version: 2020 2020-01-27 14:26:45 -08:00
e0e8d74d01 update changelog 2020-01-27 14:25:12 -08:00
e608920679 Merge pull request #272 from pfrejo/hotfix-1.5
Fixed data corruption when overwriting a file on a Fuse v3 filesystem
2020-01-27 14:14:35 -08:00
dbfbcb547d Fixed data corruption when overwriting a file on a Fuse v3 filesystem
When a file of size "s" is overwritten, forcing "O_APPEND" flag
makes the server file offset to be placed "s" bytes in advance.
This caused subsequent write operations to be paded by "s" zeroes,
thus corrupting the file.
2020-01-23 21:31:56 +01:00
b3dfea8303 tools: fix-source-copyright: fix botched script 2020-01-22 14:35:24 -08:00
3ab0e5a3d3 doc: add kernel mode file systems document 2020-01-16 17:04:23 -08:00
d687ef3a67 update Changelog (PR #270) 2020-01-15 13:39:59 -08:00
6df5ff980f Merge branch 'hammerg-track_dir_check' 2020-01-15 13:27:19 -08:00
14ac0f8db9 dll: FspFileSystemOpCreate_FileOpenTargetDirectory 2020-01-15 13:26:29 -08:00
ac306c2ce1 dll: open as directory when file's parent directory should be opened. 2020-01-05 09:09:05 +02:00
aedf01a384 update source copyright for 2020 2020-01-02 17:50:40 -08:00
0ce8b1c254 build: bump version to 2020.1 B1 2020-01-02 17:46:13 -08:00
4e0690e65f update Changelog for v1.5 2019-12-31 16:56:59 -08:00
e7b81e4bac build: bump version to 2019.3 GOLD 2019-12-31 16:55:35 -08:00
9dc774d306 tst: winfsp-tests: ResilientRemoveDirectoryW 2019-12-16 23:07:04 -08:00
26fe1a741b sys: FspPropagateTopFlags: propagate union of flags from top level IRP 2019-12-13 16:42:49 -08:00
efdb6d1c86 build: bump version to 2019.3 B5 2019-12-09 14:36:08 -08:00
b18df6bba8 sys: release rename lock when doing oplock breaks 2019-12-08 14:27:02 -08:00
39aad2b4fa ku: posix: improve kernel mode support 2019-11-18 22:22:32 -08:00
ab1e024965 tools: build.bat: fix winfsp-tests zip file build 2019-11-16 16:05:40 -08:00
5a67c47d0f update changelog 2019-11-16 14:54:10 -08:00
39c189aff7 sys: fsext: FspFsextProviderTransact 2019-11-16 14:02:44 -08:00
3d9fc467ef tools: build.bat: winfsp-tests zip file 2019-11-16 07:26:07 +00:00
23b5c67913 shared: minimal.h: eliminate warning on VS2015 builds 2019-11-07 16:08:41 -08:00
4b5478e50c sys: dirctl: support directory marker as FUSE style next offset 2019-11-05 22:14:16 -08:00
c7fc728ad0 build: bump version 2019-11-04 19:26:45 -08:00
254174b8e9 sys: avoid using FspFsextProvider unnecessarily 2019-11-04 16:30:30 -08:00
5110b3c5a1 sys: dirctl: support directory marker as FUSE style next offset 2019-10-30 16:40:48 -07:00
847eab3da4 tst: memfs-fuse3: #if0 ioctl 2019-10-21 20:21:36 -07:00
5131ed5c01 Merge branch 'bdutro-o_append-fix' 2019-10-21 20:14:02 -07:00
b513128cfe In Windows, Go clears any write-related flags when O_APPEND is
specified. This causes WinFSP to think that any O_APPEND requests are
actually read-only. This adds an additional check for the
FILE_APPEND_DATA flag so that we can ensure the request is sent with at
least O_WRONLY and O_APPEND set.
2019-10-21 18:04:26 -05:00
3fe69f2208 installer: add fsext development files 2019-10-18 16:23:27 -07:00
29fd9bf779 sys: fsext: allow multiple providers (up to 4) 2019-10-18 16:00:31 -07:00
3c391ca711 build: bump version to 2019.3 B3 2019-10-16 12:18:24 -07:00
82a8545d8f tst: memfs-fuse3: fix narrow conversion on x86 builds 2019-10-09 14:42:39 -07:00
79be3e445a tst: memfs-fuse3: accurately compute current time 2019-10-09 11:39:41 -07:00
b04266e0fe tools: run-tests: add memfs-fuse3 testing 2019-10-08 04:35:28 +01:00
25adfaec00 update Changelog 2019-10-08 04:30:30 +01:00
ce20747534 tst: memfs-fuse3: testing 2019-10-07 18:32:25 -07:00
d3d75bf977 tst: add memfs-fuse3 file system 2019-10-07 14:24:18 -07:00
6f1f1cda71 update Changelog 2019-10-07 22:17:07 +01:00
21dfeca124 update Changelog 2019-10-07 22:15:29 +01:00
6f585ce63e Merge pull request #251 from johntyner/feature/remove-fuse-prefix
Remove "FUSE-" prefix from file system name when using FUSE API
2019-10-07 14:05:18 -07:00
8f90305726 add support for setting file system name without 'FUSE-' prefix 2019-10-07 07:05:01 -07:00
490d0577bb Revert "Remove 'FUSE-' prefix from file system name when using fuse interface"
This reverts commit 7d2ff3afeb.
2019-10-07 06:47:02 -07:00
c9d3cb74c7 add John Tyner to contributors 2019-09-25 16:20:50 -07:00
7d2ff3afeb Remove 'FUSE-' prefix from file system name when using fuse interface 2019-09-24 20:04:29 -07:00
c415c87195 dll: FspMountSet, FspMountRemove 2019-09-24 15:34:01 -07:00
d161ca59a7 update Changelog 2019-09-12 05:36:19 +01:00
bc03af3b2a doc: update FAQ, Known File Systems 2019-09-12 04:54:40 +01:00
ed1543665c Merge pull request #248 from JohnOberschelp/master
Airfs cleanup after persistence review
2019-09-10 22:32:58 -07:00
a99fa512d4 Fixed issues noted at the PR review 2019-09-10 16:00:34 -07:00
a6800dd73d Fixed issues noted at the PR review 2019-09-10 15:59:48 -07:00
aa9354773b Fixed issues noted at the PR review 2019-09-10 15:58:35 -07:00
05b37c744b sys,dll: only user mode sends MountManager IOCTL's
(except for cleanup in FspMountdevFini)
2019-09-08 17:45:00 -07:00
1d15c9546b Merge branch 'pvt-sqlfix2' 2019-09-08 11:05:17 -07:00
51b33f02aa Merge pull request #241 from JohnOberschelp/master
Add persistence to Airfs
2019-09-07 17:40:42 -07:00
97ffa741b2 tst: volpath-test: fix silly mistake 2019-09-07 11:56:34 -07:00
073645db3b tst: fix tests broken by new mountmgr func 2019-09-07 11:39:06 -07:00
fd9ac1c9e0 appveyor: WDK 1903 hackfix 2019-09-06 20:56:37 -07:00
62b08c3d1e appveyor: WDK 1903 hackfix 2019-09-07 04:54:39 +01:00
9436fd8402 sys: implement SectorSize queries
- IRP_MJ_QUERY_VOLUME_INFORMATION/FileFsSectorSizeInformation
- IOCTL_STORAGE_QUERY_PROPERTY/StorageAccessAlignmentProperty
2019-09-06 20:52:15 -07:00
de75454d50 sys: FspFsvolDeviceControl: disable mountdev handling on fsvol devices 2019-09-06 15:43:20 -07:00
430d7a5650 sys: FspMountdevMake: use non-repeatable (i.e. non UUIDv5) GUID when non-persistent mountdev 2019-09-06 14:34:33 -07:00
4655926d03 sys, dll: mount manager support 2019-09-06 14:24:00 -07:00
565caebe4c sys,dll: FspFileSystemSetMountPoint: mount manager support 2019-09-05 19:58:14 -07:00
a47f853beb sys: mountdev: mount manager support 2019-09-05 09:54:36 -07:00
89ec3e6733 ku: UUID v5 generation 2019-09-04 13:45:53 -07:00
dbdfaeee1f tst: winfsp-tests: GetVolumePathName testing 2019-08-23 16:00:35 +01:00
2c64d59001 Add common.h & persistence.cpp for Airfs to Product.wxs 2019-08-09 15:58:12 -07:00
af8c74378e appveyor: hack to make WDK 1903 work on VS2015 2019-08-07 22:53:21 -07:00
19c320350f Add persistence.cpp and common.h 2019-08-03 17:55:29 -07:00
d60b1de430 Add persistence.cpp and common.h 2019-08-03 17:54:26 -07:00
6a7b6c77c6 Create common.h 2019-08-03 12:22:57 -07:00
16b1b2b349 Create persistence.cpp
Create persistence.cpp to supply functionality needed for volume persistence within a memory-mapped file:
    memory management
    sorted sets
    offsets that don’t use a pointer
2019-08-03 12:19:56 -07:00
f181593f49 Add persistence to Airfs
Adds persistence to Airfs; stores the volume in a file.
The interface has changed slightly. Pass...
-N VolumeName ( for example C:\Users\foo\Desktop\test.air )
-n MapName    ( for example Local\Airfs )
... in place of the no longer used...
-n MaxFileNodes
2019-08-03 11:52:47 -07:00
189 changed files with 4746 additions and 1526 deletions

View File

@ -1,5 +1,120 @@
= Changelog
v1.6 (2020)::
Changes since v1.5:
* [FIX] Do no pass `O_APPEND` flag to FUSE file systems, which would result in data corruption under some circumstances. (See PR #272. Thanks @pfrejo.)
* [FIX] Fix how rename target directories are opened (use `FILE_DIRECTORY_FILE`). (See PR #270. Thanks @hammerg.)
v1.5 (2019.3)::
Changes since v1.4:
* [GEN] WinFsp file systems can now be used by WSLinux. File systems must enable this support by setting the `FSP_FSCTL_VOLUME_PARAMS::WslFeatures` bit. 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.5B4 (2019.3 B4)::
Changes since v1.4:
* [GEN] WinFsp file systems can now be used by WSLinux. File systems must enable this support by setting the `FSP_FSCTL_VOLUME_PARAMS::WslFeatures` bit. 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.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)::

View File

@ -56,11 +56,15 @@ CONTRIBUTOR LIST
|===
|Ben Rubson |ben.rubson at gmail.com
|Bill Zissimopoulos |billziss at navimatics.com
|Brett Dutro |brett.dutro at gmail.com
|Colin Atkinson (Atakama, https://atakama.com) |colin at atakama.com
|Felix Croes |felix at dworkin.nl
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr
|Fritz Elfert |fritz-github at fritz-elfert.de
|Gal Hammer (Red Hat, https://www.redhat.com) |ghammer at redhat.com
|John Oberschelp |john at oberschelp.net
|John Tyner |jtyner at gmail.com
|Pedro Frejo (Arpa System, https://arpasystem.com) |pedro.frejo at arpasystem.com
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|Santiago Ganis |sganis at gmail.com
|Tobias Urlaub |saibotu at outlook.de

View File

@ -15,6 +15,13 @@ init:
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
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
- appveyor AddMessage "Change boot configuration and reboot" -Category Information
- bcdedit /set testsigning on

View File

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

View File

@ -369,6 +369,23 @@
<File Name="uninstall.sh" KeyPath="yes" />
</Component>
</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 Id="SMPDIR" FileSource="..\..\..\tst">
<Directory Id="SMPDIR.memfs" Name="memfs">
@ -382,6 +399,29 @@
<File Name="memfs-main.c" KeyPath="yes" />
</Component>
</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">
<Component Id="C.memfs_dotnet.Program.cs">
<File Id="FILE.memfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
@ -391,6 +431,12 @@
<Component Id="C.airfs.cpp">
<File Name="airfs.cpp" KeyPath="yes" />
</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">
<File Name="airfs.sln" KeyPath="yes" />
</Component>
@ -580,13 +626,27 @@
<ComponentRef Id="C.fuse.install.sh" />
<ComponentRef Id="C.fuse.uninstall.sh" />
</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">
<ComponentRef Id="C.memfs_x64.exe" />
<ComponentRef Id="C.memfs_x86.exe" />
<ComponentRef Id="C.memfs.h" />
<ComponentRef Id="C.memfs.cpp" />
<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.persistence.cpp" />
<ComponentRef Id="C.common.h" />
<ComponentRef Id="C.airfs.sln" />
<ComponentRef Id="C.airfs.vcxproj" />
<ComponentRef Id="C.airfs.vcxproj.filters" />
@ -694,6 +754,16 @@
<ComponentGroupRef Id="C.WinFsp.smp.net" />
<ComponentGroupRef Id="C.WinFsp.sym" />
</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
Id="F.Cygfuse"
Level="1000"

View File

@ -204,7 +204,9 @@
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-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\wsl-test.c" />
</ItemGroup>

View File

@ -103,6 +103,12 @@
<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>
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">

View File

@ -16,10 +16,10 @@
<MyCompanyName>Navimatics LLC</MyCompanyName>
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
<MyCanonicalVersion>1.5</MyCanonicalVersion>
<MyCanonicalVersion>1.6</MyCanonicalVersion>
<MyProductVersion>2019.3 B2</MyProductVersion>
<MyProductStage>Beta</MyProductStage>
<MyProductVersion>2020</MyProductVersion>
<MyProductStage>Gold</MyProductStage>
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>

View File

@ -51,6 +51,7 @@
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
<ClCompile Include="..\..\src\dll\launch.c" />
<ClCompile Include="..\..\src\dll\mount.c" />
<ClCompile Include="..\..\src\dll\np.c" />
<ClCompile Include="..\..\src\dll\security.c" />
<ClCompile Include="..\..\src\dll\debug.c" />

View File

@ -160,6 +160,9 @@
<ClCompile Include="..\..\src\ku\posix.c">
<Filter>Source\ku</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dll\mount.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\dll\library.def">

View File

@ -105,7 +105,7 @@
<PreprocessorDefinitions> _X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
@ -118,7 +118,7 @@
<PreprocessorDefinitions> _X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
@ -131,7 +131,7 @@
<PreprocessorDefinitions> _WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
@ -144,7 +144,7 @@
<PreprocessorDefinitions> _WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>cng.lib;wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
@ -156,6 +156,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ku\posix.c" />
<ClCompile Include="..\..\src\ku\uuid5.c" />
<ClCompile Include="..\..\src\sys\cleanup.c" />
<ClCompile Include="..\..\src\sys\close.c" />
<ClCompile Include="..\..\src\sys\create.c" />
@ -175,6 +176,7 @@
<ClCompile Include="..\..\src\sys\ioq.c" />
<ClCompile Include="..\..\src\sys\lockctl.c" />
<ClCompile Include="..\..\src\sys\meta.c" />
<ClCompile Include="..\..\src\sys\mountdev.c" />
<ClCompile Include="..\..\src\sys\mup.c" />
<ClCompile Include="..\..\src\sys\name.c" />
<ClCompile Include="..\..\src\sys\psbuffer.c" />

View File

@ -113,6 +113,12 @@
<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>
<ClInclude Include="..\..\src\sys\driver.h">

View File

@ -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.::
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?::
@ -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?::
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.)

View File

@ -12,6 +12,7 @@ The documentation available here discusses various aspects of WinFsp.
- The [[API Reference|WinFsp-API-winfsp.h]] describes the native WinFsp API. This external [[link|http://www.secfs.net/winfsp/apiref/]] may be easier to browse for some people.
- There is also a FUSE compatibility layer for native Windows and Cygwin. See fuse.h in the source repository.
- This [[document|Native-API-vs-FUSE]] discusses the need for both a native API and FUSE and gives some pointers on which one to choose.
- Since release 2019.3 WinFsp supports development of file systems in kernel mode. This [[document|WinFsp-Kernel-Mode-File-Systems]] discusses how to write such file systems.
## Design

View File

@ -5,6 +5,7 @@ This document contains a list of known file systems and file system libraries th
== File Systems
- 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/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
@ -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/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/UtrechtUniversity/YodaDrive[YodaDrive] - Mount a Yoda drive as a local drive
== 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/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/Scille/winfspy[Python: winfspy] - WinFSP binding for Python

View File

@ -0,0 +1,117 @@
= Developing File Systems in Kernel Mode
Since release 2019.3 WinFsp supports development of file systems in kernel mode. Such file systems are implemented as kernel drivers that use WinFsp as the primary FSD (File System Driver) as well as the software library that they interface with to retrieve and service file system requests. This document discusses how to write such file systems.
== Motivation
The primary goal of WinFsp is to enable the easy creation of *user mode* file systems using an easy to use API. There are however legitimate reasons for wanting to develop a file system as a *kernel mode* driver, but the difficulty of doing so often deters people because Windows kernel file system development is notoriously difficult and has many pitfalls.
Some of the reasons that a kernel mode file system may be preferrable to a user mode one:
* A kernel driver may be able to achieve better performance than user mode processes.
* A kernel driver may be able to access advanced OS features that are not easily available to user mode processes.
* A kernel driver may be able to present an alternative interface than the one presented by WinFsp to user mode processes.
Since release 2019.3 WinFsp supports development of file systems as kernel mode drivers. The primary motivation for this work was to support the https://github.com/billziss-gh/winfuse[WinFuse] project, which exposes the FUSE protocol from the Windows kernel in a way that allows FUSE file systems to interface with it, either directly or via https://github.com/libfuse/libfuse[libfuse]. The support was added in such a way that it is generic enough to be used by other kernel mode file systems.
== Overview
A WinFsp "volume" (file system) is typically created using the `FspFsctlCreateVolume` API. This is simply a wrapper around a `CreateFileW` call on one of the WinFsp control devices, either `WinFsp.Disk` or `WinFsp.Net`. The `CreateFileW` call returns a `HANDLE` to the newly created volume, which acts either as a "disk" or a "network" file system, depending on which control device was used to create it.
User mode file systems interact with the WinFsp FSD via `DeviceIoControl/FSP_FSCTL_TRANSACT` messages on the volume `HANDLE`. (This is usually done indirectly via the WinFsp DLL, which hides this detail behind an easy to use API.)
Since release 2019.3 (v1.5) WinFsp supports the following:
* Registration and on-demand loading of a third party driver when a volume that is destined to be handled by the third party driver is created.
* Forwarding of custom `DeviceIoControl` messages to a third party driver. This allows the third party driver to handle custom `FSCTL` requests directed to a WinFsp volume `HANDLE`.
* Kernel-mode API's (called DDI's) that allow a third party driver to register itself with the FSD and interact with its I/O queues.
Such drivers are called within the WinFsp sources and header/library files by the name of "Fsext Providers" (File System Extension Providers). In the text below we will usually refer to them as simply "Providers".
A Provider is a kernel mode driver that uses the FSD as a frontend file system driver to interface with Windows and implement all the complex details that this entails. The Provider fetches I/O requests from the WinFsp I/O queues and may filter them, transform them into a different protocol (as is the case with WinFuse) or use them to fully implement a file system in kernel mode.
== Provider Development
The WinFsp installer includes a "Kernel Developer" feature. When installed this feature adds header and library files in the `opt\fsext` installation subdirectory.
The primary header file used for Provider development is `<winfsp/fsext.h>` and can be found in `opt\fsext\inc`. Additionally the file `<winfsp/fsctl.h>` found in the `inc` installation subdirectory must be in the compiler's include path.
Providers must also be linked with one of the import libraries that can be found in `opt\fsext\lib`. Use the `winfsp-x64.lib` import library when linking the 64-bit version of a Provider and the `winfsp-x86.lib` import library when linking the 32-bit version of a Provider.
=== Provider DDI's
The `<winfsp/fsext.h>` header file includes definitions for the following important DDI's:
* `FspFsextProviderRegister`: This DDI is used by a Provider to register itself with the FSD. Typically the Provider prepares an `FSP_FSEXT_PROVIDER` structure and calls `FspFsextProviderRegister` in its `DriverEntry` routine. The structure's fields are as follows:
** `Version`: Set to `sizeof(FSP_FSEXT_PROVIDER)`.
** `DeviceTransactCode`: The `DeviceIoControl` code that should be forwarded to the Provider.
*** The code must be defined as follows: `CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0xC00 + ProviderSpecific, METHOD_BUFFERED, FILE_ANY_ACCESS)`.
*** Please note that this scheme allows for up to 1024 codes. If you want to define a new Provider code I will appreciate it if you email me at `<billziss at navimatics.com>` so that we can keep track of Provider codes, avoid conflicts and see when we need to extend this scheme.
** `DeviceExtensionSize`: The size of private data that the Provider wants for itself in the `DeviceExtension` of the FSD volume's device object.
** `DeviceInit`: Called when a new volume is created. The `DeviceObject` parameter is the volume's device object. The `VolumeParams` are the initial parameters passed to `FspFsctlCreateVolume` and can be modified by the Provider.
** `DeviceFini`: Called when a volume is going away. This usually happens when the volume `HANDLE` is closed.
** `DeviceExpirationRoutine`: Called once a second as part of the FSD's expiration timer. The FSD uses this timer to expire caches, long-pending IRP's, etc. A Provider can use this call for a similar purpose. The `ExpirationTime` parameter contains the current interrupt time as determined by the FSD.
** `DeviceTransact`: Called whenever the FSD receives a `DeviceIoControl` request with the `DeviceTransactCode`. The `Irp` parameter contains the relevant `IRP_MJ_FILE_SYSTEM_CONTROL`.
** `DeviceExtensionOffset`: Set to `0` on input. On successful return from `FspFsextProviderRegister` it will contain the offset to use for accessing the Provider's private data in the `DeviceExtension` of the FSD volume's device object. Given a `DeviceObject`, the data can be accessed as `(PVOID)((PUINT8)DeviceObject->DeviceExtension + Provider.DeviceExtensionOffset)`.
* `FspFsextProviderTransact`: This DDI is used by a Provider to interact with the FSD I/O queues. The `DeviceObject` is the FSD volume's device object. The `FileObject` is the `FILE_OBJECT` that corresponds to the volume `HANDLE` (created by `FspFsctlCreateVolume`). The `Response` is the response to send and can be `NULL`. The `Request` is a pointer that receives a pointer to a new request from the WinFsp I/O queue and can be `NULL`; if the received pointer is not `NULL` it must be freed with `ExFreePool`.
=== Provider I/O
When the FSD receives a file system IRP it is often able to handle and complete it without help from an external user mode or kernel mode file system. However in most cases the IRP has to be seen and acted upon by an external file system. For this reason the FSD preprocesses the IRP and places it in an I/O queue in the form of a "request". At a later time the external file system retrieves the request, processes it and sends back a "response". The FSD uses the response to locate the original IRP, perform any necessary postprocessing and finally complete the IRP.
Providers typically use the `FspFsextProviderTransact` DDI to receive requests and send back responses. Requests are of type `FSP_FSCTL_TRANSACT_REQ` and responses are of type `FSP_FSCTL_TRANSACT_RSP`. Requests have a `Kind` field which describes what kind of file system operation is being requested. The following request kinds are currently defined in `<winfsp/fsctl.h>`:
```
FspFsctlTransactCreateKind,
FspFsctlTransactOverwriteKind,
FspFsctlTransactCleanupKind,
FspFsctlTransactCloseKind,
FspFsctlTransactReadKind,
FspFsctlTransactWriteKind,
FspFsctlTransactQueryInformationKind,
FspFsctlTransactSetInformationKind,
FspFsctlTransactQueryEaKind,
FspFsctlTransactSetEaKind,
FspFsctlTransactFlushBuffersKind,
FspFsctlTransactQueryVolumeInformationKind,
FspFsctlTransactSetVolumeInformationKind,
FspFsctlTransactQueryDirectoryKind,
FspFsctlTransactFileSystemControlKind,
FspFsctlTransactDeviceControlKind,
FspFsctlTransactShutdownKind,
FspFsctlTransactLockControlKind,
FspFsctlTransactQuerySecurityKind,
FspFsctlTransactSetSecurityKind,
FspFsctlTransactQueryStreamInformationKind,
```
When request processing is complete the Provider must prepare a response and send it to the FSD using `FspFsextProviderTransact` as mentioned above. It is particularly important that the Provider initializes the `Kind` and `Hint` fields by copying the values from the corresponding request.
This document does not describe in detail how each request kind is supposed to be handled. For the full details refer to the implementation for the WinFsp DLL in the WinFsp sources: `src/dll/fsop.c`. Although this implementation is for user mode file systems, similar logic and techniques should be used for Providers.
== Provider Registration
Providers are loaded on demand and must be properly registered:
* A provider must be registered as a kernel driver. This can be achieved by using the command `sc create PROVIDER type=kernel binPath=X:\PATH\TO\PROVIDER.SYS` or by using the Service Control Manager API's (`OpenServiceW`, `CreateServiceW`, etc.). You do not need an INF file or to use the Setup API in order to register a Provider driver.
* A provider must be registered under the registry key `HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Fsext`. Create a string value with name the textual representation of the Provider's transact code (see `DeviceTransactCode`) in `"%08lx"` format and value the Provider's driver name.
For example the WinFuse Provider registers its driver under the name `WinFuse` and adds a registry value of `00093118` -> `WinFuse`.
== Provider Lifetime
Providers are loaded on demand by the FSD during volume creation. This process works as follows:
* During volume creation (e.g. by using `FspFsctlCreateVolume`) a non-zero `FsextControlCode` must be specified in `VolumeParams`.
* If the FSD sees the `FsextControlCode` as non-zero it attempts to find a corresponding Provider driver.
** It first checks an internal mapping of codes to Provider drivers. If the code is found, the FSD proceeds to the `DeviceInit` step below.
** If the code is not found in the internal mapping, the FSD checks the registry under the registry key `HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Fsext`. If the code is not found the volume creation fails.
** If the code is found the FSD loads the Provider driver using `ZwLoadDriver`. The Provider is supposed to register itself with the FSD during `DriverEntry` by calling `FspFsextProviderRegister`.
** Finally the internal mapping of codes to Providers is rechecked. Assuming that everything worked as intended, the corresponding Provider driver is now loaded and we can proceed to the `DeviceInit` step.
* The FSD proceeds to call the `DeviceInit` callback of the Provider. The Provider can use this call to initialize itself in relation to the new volume device object.
* Assuming that the volume device object is created successfully, the FSD will do the following:
** Forward any `FsextControlCode==DeviceTransactCode` requests that it gets in its `IRP_MJ_FILE_SYSTEM_CONTROL` to the Provider via `DeviceTransact`.
** Call the Provider's `DeviceExpirationRoutine` once a second as part of the FSD's expiration process.
* Eventually the volume device object will be torn down (e.g. because the corresponding `HANDLE` is closed). In this case the FSD will call the Provider's `DeviceFini` callback.
Finally note that once loaded a Provider driver cannot be unloaded (without a reboot).

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
* @file fuse3/fuse_opt.h
* WinFsp FUSE3 compatible API.
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -2,7 +2,7 @@
* @file fuse3/winfsp_fuse.h
* WinFsp FUSE3 compatible API.
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file winfsp/fsctl.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -54,6 +54,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
#define FSP_FSCTL_DECLSPEC_ALIGN __declspec(align(FSP_FSCTL_DEFAULT_ALIGNMENT))
/* 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 \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_LIST \
@ -94,7 +96,7 @@ FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
/* marshalling */
#pragma warning(push)
#pragma warning(disable:4200) /* zero-sized array in struct/union */
#pragma warning(disable:4200 4201) /* zero-sized array in struct/union; nameless struct/union */
enum
{
FspFsctlTransactReservedKind = 0,
@ -173,7 +175,8 @@ enum
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
UINT32 WslFeatures:1; /* support features required for WSLinux */\
UINT32 KmReservedFlags:5;\
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
UINT32 KmReservedFlags:4;\
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
@ -240,8 +243,12 @@ typedef struct
{
UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
union
{
UINT64 NextOffset;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
} DUMMYUNIONNAME;
WCHAR FileNameBuf[];
} FSP_FSCTL_DIR_INFO;
FSP_FSCTL_STATIC_ASSERT(104 == sizeof(FSP_FSCTL_DIR_INFO),
@ -598,6 +605,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
PHANDLE PVolumeHandle);
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
BOOLEAN Persistent, GUID *UniqueId);
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,
@ -606,6 +615,20 @@ FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
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
#ifdef __cplusplus

View File

@ -5,7 +5,7 @@
* In order to use the WinFsp Launch API a program must include &lt;winfsp/launch.h&gt;
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -5,7 +5,7 @@
* In order to use the WinFsp API the user mode file system must include &lt;winfsp/winfsp.h&gt;
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -2,7 +2,7 @@
* @file winfsp/winfsp.hpp
* WinFsp C++ Layer.
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file winfsp/fsext.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -53,6 +53,9 @@ typedef struct
FSP_DDI_DEF(NTSTATUS, FspFsextProviderRegister,
FSP_FSEXT_PROVIDER *Provider)
FSP_DDI_DEF(NTSTATUS, FspFsextProviderTransact,
PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
FSP_FSCTL_TRANSACT_RSP *Response, FSP_FSCTL_TRANSACT_REQ **PRequest)
FSP_DDI_DEF(NTSTATUS, FspPosixMapUidToSid,
UINT32 Uid,

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,7 @@
/**
* @file dll/debug.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/dirbuf.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file dll/fs.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -32,35 +32,11 @@ static FSP_FILE_SYSTEM_INTERFACE FspFileSystemNullInterface;
static INIT_ONCE FspFileSystemInitOnce = INIT_ONCE_STATIC_INIT;
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(
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
{
HANDLE Handle;
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;
}
@ -93,7 +69,9 @@ FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
Result = STATUS_SUCCESS;
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) ?
STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
else
@ -196,205 +174,6 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *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)
{
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
@ -406,105 +185,55 @@ FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR
if (0 != FileSystem->MountPoint)
return STATUS_INVALID_PARAMETER;
FSP_MOUNT_DESC Desc;
int Size;
NTSTATUS Result;
HANDLE MountHandle = 0;
memset(&Desc, 0, sizeof Desc);
Desc.VolumeHandle = FileSystem->VolumeHandle;
Desc.VolumeName = FileSystem->VolumeName;
Desc.Security = SecurityDescriptor;
if (0 == MountPoint)
MountPoint = L"*:";
Size = (lstrlenW(MountPoint) + 1) * sizeof(WCHAR);
Desc.MountPoint = MemAlloc(Size);
if (0 == Desc.MountPoint)
{
DWORD Drives;
WCHAR Drive;
MountPoint = MemAlloc(3 * sizeof(WCHAR));
if (0 == MountPoint)
return STATUS_INSUFFICIENT_RESOURCES;
MountPoint[1] = L':';
MountPoint[2] = L'\0';
Drives = GetLogicalDrives();
if (0 != Drives)
{
for (Drive = 'Z'; 'D' <= Drive; Drive--)
if (0 == (Drives & (1 << (Drive - 'A'))))
{
MountPoint[0] = Drive;
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
&MountHandle);
if (NT_SUCCESS(Result))
goto exit;
}
Result = STATUS_NO_SUCH_DEVICE;
}
else
Result = FspNtStatusFromWin32(GetLastError());
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
else
{
PWSTR P;
ULONG L;
memcpy(Desc.MountPoint, MountPoint, Size);
L = (ULONG)((lstrlenW(MountPoint) + 1) * sizeof(WCHAR));
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);
}
Result = FspMountSet(&Desc);
exit:
if (NT_SUCCESS(Result))
{
FileSystem->MountPoint = MountPoint;
FileSystem->MountHandle = MountHandle;
FileSystem->MountPoint = Desc.MountPoint;
FileSystem->MountHandle = Desc.MountHandle;
}
else
MemFree(MountPoint);
MemFree(Desc.MountPoint);
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)
{
if (0 == FileSystem->MountPoint)
return;
if (FspPathIsDrive(FileSystem->MountPoint))
FspFileSystemRemoveMountPoint_Drive(FileSystem->MountPoint, FileSystem->VolumeName,
FileSystem->MountHandle);
else
FspFileSystemRemoveMountPoint_Directory(FileSystem->MountHandle);
FSP_MOUNT_DESC Desc;
memset(&Desc, 0, sizeof Desc);
Desc.VolumeHandle = FileSystem->VolumeHandle;
Desc.VolumeName = FileSystem->VolumeName;
Desc.MountPoint = FileSystem->MountPoint;
Desc.MountHandle = FileSystem->MountHandle;
FspMountRemove(&Desc);
MemFree(FileSystem->MountPoint);
FileSystem->MountPoint = 0;

View File

@ -1,7 +1,7 @@
/**
* @file dll/fsctl.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -107,6 +107,20 @@ exit:
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,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,

View File

@ -1,7 +1,7 @@
/**
* @file dll/fsop.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -760,7 +760,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
NTSTATUS Result;
WCHAR Root[2] = L"\\";
PWSTR Parent, Suffix;
UINT32 GrantedAccess;
UINT32 CreateOptions, GrantedAccess;
FSP_FSCTL_TRANSACT_FULL_CONTEXT FullContext;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
UINT32 Information;
@ -775,8 +775,10 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
FspPathSuffix((PWSTR)Request->Buffer, &Parent, &Suffix, Root);
CreateOptions =
(Request->Req.Create.CreateOptions | FILE_DIRECTORY_FILE) & ~FILE_NON_DIRECTORY_FILE;
Result = FileSystem->Interface->Open(FileSystem,
Parent, Request->Req.Create.CreateOptions, GrantedAccess,
Parent, CreateOptions, GrantedAccess,
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
FspPathCombine((PWSTR)Request->Buffer, Suffix);
if (!NT_SUCCESS(Result))

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -102,6 +102,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
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'),
@ -367,6 +369,18 @@ 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';
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
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;

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse_compat.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse_intf.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -1026,6 +1026,18 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
}
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.
*/
if (GrantedAccess & FILE_APPEND_DATA)
{
if (fi.flags == 0)
fi.flags = 1; /* need O_WRONLY as a bare minimum in order to append */
}
if (0 != f->ops.open)
{
err = f->ops.open(contexthdr->PosixPath, &fi);

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse_loop.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/library.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse3/fuse2to3.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse3/fuse3.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse/fuse3_compat.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/fuse3/library.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file dll/launch.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file dll/library.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -91,6 +91,21 @@ static inline BOOLEAN FspPathIsDrive(PWSTR FileName)
) &&
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) \
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))

612
src/dll/mount.c Normal file
View File

@ -0,0 +1,612 @@
/**
* @file dll/mount.c
*
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#include <dll/library.h>
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);
}

View File

@ -1,7 +1,7 @@
/**
* @file dll/np.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file dll/security.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file dll/wksid.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/*
* dotnet/FileSystemBase+Const.cs
*
* Copyright 2015-2019 Bill Zissimopoulos
* Copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/*
* dotnet/FileSystemBase.cs
*
* Copyright 2015-2019 Bill Zissimopoulos
* Copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/*
* dotnet/FileSystemHost.cs
*
* Copyright 2015-2019 Bill Zissimopoulos
* Copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/*
* dotnet/Interop.cs
*
* Copyright 2015-2019 Bill Zissimopoulos
* Copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/*
* dotnet/Service.cs
*
* Copyright 2015-2019 Bill Zissimopoulos
* Copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file fsptool/fsptool.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file ku/library.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -207,6 +207,11 @@ static inline int FspKuMultiByteToWideChar(
return ByteCount / sizeof(WCHAR);
}
static inline PGENERIC_MAPPING FspGetFileGenericMapping(VOID)
{
return IoGetFileObjectGenericMapping();
}
static inline void *MemAlloc(size_t Size)
{
return FspAlloc(Size);

View File

@ -14,7 +14,7 @@
* [SNAME]
* https://www.cygwin.com/cygwin-ug-net/using-specialnames.html
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -725,6 +725,20 @@ lasterror:
goto exit;
}
static inline ACCESS_MASK FspPosixCanonicalizeAccessMask(ACCESS_MASK AccessMask)
{
PGENERIC_MAPPING Mapping = FspGetFileGenericMapping();
if (AccessMask & GENERIC_READ)
AccessMask |= Mapping->GenericRead;
if (AccessMask & GENERIC_WRITE)
AccessMask |= Mapping->GenericWrite;
if (AccessMask & GENERIC_EXECUTE)
AccessMask |= Mapping->GenericExecute;
if (AccessMask & GENERIC_ALL)
AccessMask |= Mapping->GenericAll;
return AccessMask & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
}
static inline UINT32 FspPosixMapAccessMaskToPermission(ACCESS_MASK AccessMask)
{
/* [PERMS]
@ -749,6 +763,14 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
{
FSP_KU_CODE;
BOOLEAN OwnerOptional = (UINT_PTR)PUid & 1;
PUid = (PVOID)((UINT_PTR)PUid & ~1);
UINT32 OrigUid = *PUid;
BOOLEAN GroupOptional = (UINT_PTR)PGid & 1;
PGid = (PVOID)((UINT_PTR)PGid & ~1);
UINT32 OrigGid = *PGid;
PSID OwnerSid = 0, GroupSid = 0;
BOOL Defaulted, DaclPresent;
PACL Acl = 0;
@ -757,6 +779,7 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
PSID AceSid;
DWORD AceAccessMask;
DWORD OwnerAllow, OwnerDeny, GroupAllow, GroupDeny, WorldAllow, WorldDeny;
UINT32 AceUid = 0;
UINT32 Uid, Gid, Mode;
NTSTATUS Result;
@ -771,13 +794,23 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
if (!GetSecurityDescriptorDacl(SecurityDescriptor, &DaclPresent, &Acl, &Defaulted))
goto lasterror;
Result = FspPosixMapSidToUid(OwnerSid, &Uid);
if (!NT_SUCCESS(Result))
goto exit;
if (0 == OwnerSid && OwnerOptional)
Uid = OrigUid;
else
{
Result = FspPosixMapSidToUid(OwnerSid, &Uid);
if (!NT_SUCCESS(Result))
goto exit;
}
Result = FspPosixMapSidToUid(GroupSid, &Gid);
if (!NT_SUCCESS(Result))
goto exit;
if (0 == GroupSid && GroupOptional)
Gid = OrigGid;
else
{
Result = FspPosixMapSidToUid(GroupSid, &Gid);
if (!NT_SUCCESS(Result))
goto exit;
}
if (0 != Acl)
{
@ -810,6 +843,8 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
else
continue;
AceAccessMask = FspPosixCanonicalizeAccessMask(AceAccessMask);
/* [PERMS]
* If the ACE contains the Authenticated Users SID or the World SID then
* add the allowed or denied access right bits into the "owner", "group"
@ -840,6 +875,9 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
}
else
{
if (0 == OwnerSid || 0 == GroupSid)
FspPosixMapSidToUid(AceSid, &AceUid);
/* [PERMS]
* Note that if the file owner and file group SIDs are the same,
* then the access rights are saved in both the "owner" and "group"
@ -851,7 +889,7 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
* in the "group" collection as appropriate in the corresponding set of
* granted or denied rights (as described above).
*/
if (EqualSid(GroupSid, AceSid))
if (0 != GroupSid ? EqualSid(GroupSid, AceSid) : (Gid == AceUid))
{
if (ACCESS_ALLOWED_ACE_TYPE == Ace->AceType)
GroupAllow |= AceAccessMask & ~GroupDeny;
@ -864,7 +902,7 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
* in the "owner" collection as appropriate in the corresponding set of
* granted or denied rights (as described above).
*/
if (EqualSid(OwnerSid, AceSid))
if (0 != OwnerSid ? EqualSid(OwnerSid, AceSid) : (Uid == AceUid))
{
if (ACCESS_ALLOWED_ACE_TYPE == Ace->AceType)
OwnerAllow |= AceAccessMask & ~OwnerDeny;

134
src/ku/uuid5.c Normal file
View File

@ -0,0 +1,134 @@
/**
* @file dll/uuid5.c
*
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#include <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;
}

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file launcher/ptrans.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file shared/minimal.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -72,7 +72,10 @@ NTSYSAPI VOID NTAPI RtlMoveMemory(VOID *Destination, CONST VOID *Source, DWORD L
#pragma function(memset)
#pragma function(memcpy)
#pragma warning(push)
#pragma warning(disable:4163) /* not available as an intrinsic function */
#pragma function(memmove)
#pragma warning(pop)
static inline
void *memset(void *dst, int val, size_t siz)
{

View File

@ -2,7 +2,7 @@
* @file sys/callbacks.c
* Fast I/O and resource acquisition callbacks.
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -308,7 +308,7 @@ VOID FspPropagateTopFlags(PIRP Irp, PIRP TopLevelIrp)
{
DEBUGBREAK_EX(iorecu);
FspIrpSetTopFlags(Irp, FspIrpFlags(TopLevelIrp));
FspIrpSetTopFlags(Irp, FspIrpTopFlags(TopLevelIrp) | FspIrpFlags(TopLevelIrp));
}
}
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/cleanup.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file sys/create.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file sys/devctl.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -23,6 +23,9 @@
static NTSTATUS FspFsvrtDeviceControl(
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(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
@ -31,6 +34,7 @@ FSP_DRIVER_DISPATCH FspDeviceControl;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvrtDeviceControl)
#pragma alloc_text(PAGE, FspFsvrtDeviceControlStorageQuery)
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
@ -43,10 +47,18 @@ enum
};
static NTSTATUS FspFsvrtDeviceControl(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
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
* and the suggested steps to reproduce and work around the problem goes
@ -64,6 +76,62 @@ static NTSTATUS FspFsvrtDeviceControl(
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(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@ -72,6 +140,15 @@ static NTSTATUS FspFsvolDeviceControl(
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
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? */
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
@ -90,7 +167,6 @@ static NTSTATUS FspFsvolDeviceControl(
if (!FspFileNodeIsValid(FileObject->FsContext))
return STATUS_INVALID_PARAMETER;
NTSTATUS Result;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;

View File

@ -1,7 +1,7 @@
/**
* @file sys/device.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -126,10 +126,12 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
case FspFsvolDeviceExtensionKind:
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
break;
case FspFsvrtDeviceExtensionKind:
DeviceExtensionSize = sizeof(FSP_FSVRT_DEVICE_EXTENSION);
break;
case FspFsmupDeviceExtensionKind:
DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION);
break;
case FspFsvrtDeviceExtensionKind:
case FspFsctlDeviceExtensionKind:
DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION);
break;
@ -184,10 +186,12 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
case FspFsvolDeviceExtensionKind:
Result = FspFsvolDeviceInit(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
Result = STATUS_SUCCESS;
break;
case FspFsmupDeviceExtensionKind:
Result = FspFsmupDeviceInit(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
case FspFsctlDeviceExtensionKind:
Result = STATUS_SUCCESS;
break;
@ -213,10 +217,11 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
case FspFsvolDeviceExtensionKind:
FspFsvolDeviceFini(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
break;
case FspFsmupDeviceExtensionKind:
FspFsmupDeviceFini(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
case FspFsctlDeviceExtensionKind:
break;
default:
@ -335,6 +340,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
Result = Provider->DeviceInit(DeviceObject, &FsvolDeviceExtension->VolumeParams);
if (!NT_SUCCESS(Result))
return Result;
FsvolDeviceExtension->Provider = Provider;
FsvolDeviceExtension->InitDoneFsext = 1;
}
else
@ -520,10 +526,8 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
/* finalize any fsext provider */
if (FsvolDeviceExtension->InitDoneFsext)
{
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
FsvolDeviceExtension->VolumeParams.FsextControlCode, 0);
if (0 != Provider)
Provider->DeviceFini(DeviceObject);
if (0 != FsvolDeviceExtension->Provider)
FsvolDeviceExtension->Provider->DeviceFini(DeviceObject);
}
}
@ -572,13 +576,8 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->DirInfoCache, 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);
}
if (0 != FsvolDeviceExtension->Provider)
FsvolDeviceExtension->Provider->DeviceExpirationRoutine(DeviceObject, InterruptTime);
FspIoqRemoveExpired(FsvolDeviceExtension->Ioq, InterruptTime);
KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);

View File

@ -1,7 +1,7 @@
/**
* @file sys/dirctl.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -24,6 +24,7 @@
static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
PUINT64 DirectoryMarkerAsNextOffset,
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
BOOLEAN ReturnEaSize,
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
@ -88,6 +89,7 @@ enum
static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
PUINT64 DirectoryMarkerAsNextOffset,
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
BOOLEAN ReturnEaSize,
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
@ -130,6 +132,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
PVOID PrevDestBuf = 0;
ULONG BaseInfoLen, CopyLength;
UNICODE_STRING FileName;
UINT64 DirectoryNextOffset;
*PDestLen = 0;
@ -176,12 +179,21 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
FileName.Buffer = DirInfo->FileNameBuf;
DirectoryNextOffset = DirInfo->NextOffset;
if (0 != DirectoryMarker && 0 != DirectoryMarker->Buffer &&
!DirectoryMarkerFound)
{
DirectoryMarkerFound = 0 == FspFileNameCompare(
&FileName, DirectoryMarker, CaseInsensitive, 0);
continue;
if (0 == DirectoryMarkerAsNextOffset)
{
DirectoryMarkerFound = 0 == FspFileNameCompare(
&FileName, DirectoryMarker, CaseInsensitive, 0);
}
else
{
ASSERT(sizeof(UINT64) == DirectoryMarker->Length);
DirectoryMarkerFound = DirectoryNextOffset == *(PUINT64)DirectoryMarker->Buffer;
}
}
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
@ -272,8 +284,17 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
break;
}
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
if (0 == DirectoryMarkerAsNextOffset)
{
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
}
else
{
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = sizeof(UINT64);
DirectoryMarkerOut->Buffer = (PVOID)DirectoryMarkerAsNextOffset;
*DirectoryMarkerAsNextOffset = DirectoryNextOffset;
}
DestBuf = (PVOID)((PUINT8)DestBuf +
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
@ -283,7 +304,16 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
Loop = FALSE;
}
else
*DirectoryMarkerOut = FileName;
{
if (0 == DirectoryMarkerAsNextOffset)
*DirectoryMarkerOut = FileName;
else
{
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = sizeof(UINT64);
DirectoryMarkerOut->Buffer = (PVOID)DirectoryMarkerAsNextOffset;
*DirectoryMarkerAsNextOffset = DirectoryNextOffset;
}
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
@ -323,9 +353,12 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
FileDesc->DirInfo = FileNode->NonPaged->DirInfo;
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
UINT64 DirectoryMarkerAsNextOffset = 0;
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
@ -334,8 +367,10 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
0 != FileDesc->DirInfoCacheHint ? 0 : &FileDesc->DirectoryMarker, &DirectoryMarker,
FsvolDeviceExtension->VolumeParams.DirectoryMarkerAsNextOffset ?
&DirectoryMarkerAsNextOffset : 0,
FileInformationClass, ReturnSingleEntry,
!!FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes,
!!FsvolDeviceExtension->VolumeParams.ExtendedAttributes,
&DirInfo, DirInfoSize,
DestBuf, PDestLen);
@ -366,10 +401,13 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
PAGED_CODE();
NTSTATUS Result;
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
UINT64 DirectoryMarkerAsNextOffset = 0;
FSP_FSCTL_STATIC_ASSERT(
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) >=
@ -378,8 +416,10 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
0, &DirectoryMarker,
FsvolDeviceExtension->VolumeParams.DirectoryMarkerAsNextOffset ?
&DirectoryMarkerAsNextOffset : 0,
FileInformationClass, ReturnSingleEntry,
!!FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes,
!!FsvolDeviceExtension->VolumeParams.ExtendedAttributes,
&DirInfo, DirInfoSize,
DestBuf, PDestLen);

View File

@ -1,7 +1,7 @@
/**
* @file sys/driver.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/driver.h
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -26,6 +26,8 @@
#define POOL_NX_OPTIN 1
#include <ntifs.h>
#include <mountdev.h>
#include <ntddstor.h>
#include <ntstrsafe.h>
#include <wdmsec.h>
#include <winfsp/fsctl.h>
@ -493,6 +495,9 @@ NTSTATUS FspFileNameInExpression(
PWCH UpcaseTable,
PBOOLEAN PResult);
/* UUID5 creation (ku) */
NTSTATUS FspUuid5Make(const UUID *Namespace, const VOID *Buffer, ULONG Size, UUID *Uuid);
/* utility */
PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag);
PVOID FspAllocateIrpMustSucceed(CCHAR StackSize);
@ -510,6 +515,8 @@ NTSTATUS FspSendQuerySecurityIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileO
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 FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress, ULONG ExtraPriorityFlags);
@ -1072,6 +1079,7 @@ typedef struct
PVPB SwapVpb;
FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem;
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
FSP_FSEXT_PROVIDER *Provider;
UNICODE_STRING VolumePrefix;
UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry;
FSP_IOQ *Ioq;
@ -1098,6 +1106,16 @@ typedef struct
FSP_FSCTL_DECLSPEC_ALIGN UINT8 FsextData[];
} FSP_FSVOL_DEVICE_EXTENSION;
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;
UINT32 InitDonePfxTab:1;
@ -1117,6 +1135,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
return DeviceObject->DeviceExtension;
}
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)
{
ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
@ -1221,6 +1245,20 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
}
#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 */
NTSTATUS FspMupRegister(
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
@ -1236,6 +1274,8 @@ VOID FspVolumeDelete(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMakeMountdev(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(

View File

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

View File

@ -1,7 +1,7 @@
/**
* @file sys/file.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -1337,8 +1337,9 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
!MmFlushImageSection(&DescendantFileNode->NonPaged->SectionObjectPointers,
MmFlushForDelete)))
{
/* release the FileNode in case of failure! */
/* release the FileNode and rename lock in case of failure! */
FspFileNodeReleaseF(FileNode, AcquireFlags);
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
Result = STATUS_ACCESS_DENIED;
goto exit;
@ -1441,8 +1442,9 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result || !NT_SUCCESS(Result))
{
/* release the FileNode so that we can safely wait without deadlocks */
/* release the FileNode and rename lock so that we can safely wait without deadlocks */
FspFileNodeReleaseF(FileNode, AcquireFlags);
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
/* wait for oplock breaks to finish */
for (
@ -1488,8 +1490,9 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
if (DescendantFileNode != FileNode && 0 < DescendantFileNode->HandleCount)
{
/* release the FileNode in case of failure! */
/* release the FileNode and rename lock in case of failure! */
FspFileNodeReleaseF(FileNode, AcquireFlags);
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
Result = STATUS_ACCESS_DENIED;
break;

View File

@ -1,7 +1,7 @@
/**
* @file sys/fileinfo.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -1576,8 +1576,8 @@ static NTSTATUS FspFsvolSetRenameInformation(
ASSERT(TargetFileNode->IsDirectory);
}
FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject);
retry:
FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject);
FspFileNodeAcquireExclusive(FileNode, Full);
if (0 == Request)
@ -1651,13 +1651,13 @@ retry:
Result = FspFileNodeRenameCheck(FsvolDeviceObject, Irp,
FileNode, FspFileNodeAcquireFull,
&FileNode->FileName, TRUE);
/* FspFileNodeRenameCheck releases FileNode with STATUS_OPLOCK_BREAK_IN_PROGRESS or failure */
/* FspFileNodeRenameCheck releases FileNode and rename lock on failure */
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result)
goto retry;
if (!NT_SUCCESS(Result))
{
Result = STATUS_ACCESS_DENIED;
goto rename_unlock_exit;
goto exit;
}
if (0 != FspFileNameCompare(&FileNode->FileName, &NewFileName, !FileDesc->CaseSensitive, 0))
@ -1665,13 +1665,13 @@ retry:
Result = FspFileNodeRenameCheck(FsvolDeviceObject, Irp,
FileNode, FspFileNodeAcquireFull,
&NewFileName, FALSE);
/* FspFileNodeRenameCheck releases FileNode with STATUS_OPLOCK_BREAK_IN_PROGRESS or failure */
/* FspFileNodeRenameCheck releases FileNode and rename lock on failure */
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result)
goto retry;
if (!NT_SUCCESS(Result))
{
Result = STATUS_ACCESS_DENIED;
goto rename_unlock_exit;
goto exit;
}
}
else
@ -1713,9 +1713,9 @@ retry:
unlock_exit:
FspFileNodeRelease(FileNode, Full);
rename_unlock_exit:
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
exit:
return Result;
}

View File

@ -1,7 +1,7 @@
/**
* @file sys/flush.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.

View File

@ -1,7 +1,7 @@
/**
* @file sys/fsctl.c
*
* @copyright 2015-2019 Bill Zissimopoulos
* @copyright 2015-2020 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
@ -77,6 +77,10 @@ static NTSTATUS FspFsctlFileSystemControl(
case IRP_MN_USER_FS_REQUEST:
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:
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);

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