mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-02 17:02:57 -05:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
e1b2e77df0 | |||
4783902d1d | |||
4cd2b8c612 | |||
dacaff41e4 | |||
be27a82879 | |||
b9ca46694e | |||
e50d7adc50 | |||
7f73192f8d | |||
d71049225e | |||
c15006cce8 | |||
53b44dcb5c | |||
a3765d6360 | |||
6c6dd8abcc | |||
16dd729fc7 | |||
a2d49a1ded | |||
9ede097e73 | |||
2c3800077f | |||
84b3f98d38 | |||
16734bf37a | |||
ea189c5b68 | |||
7735506cc7 | |||
ca3170c293 | |||
ba13995d10 | |||
deee7edded | |||
f41f410546 | |||
a2dc40fe3a | |||
637e8bb8c2 | |||
ec832b45ff | |||
fc03b485f3 | |||
651e45c3ba | |||
95c2fadce0 | |||
b4453c89cc | |||
5483dcbd73 | |||
f1cfe758ec | |||
e9143a73a6 | |||
264450f627 | |||
a731f0e5d8 | |||
d7450d740e | |||
5251dcbce9 | |||
dd3adf34ef | |||
b8a6a8efed | |||
d67acf3b3a | |||
3b104723af | |||
699278a7ed | |||
e070cdd6be | |||
fbbca110fb |
83
Changelog.md
83
Changelog.md
@ -1,6 +1,89 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## v1.12 (2022.2)
|
||||
|
||||
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||
|
||||
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||
|
||||
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||
|
||||
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||
|
||||
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||
|
||||
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||
|
||||
|
||||
## v1.12B2 (2022.2 Beta2)
|
||||
|
||||
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||
|
||||
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||
|
||||
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||
|
||||
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||
|
||||
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||
|
||||
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||
|
||||
|
||||
## v1.12B1 (2022.2 Beta1)
|
||||
|
||||
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||
|
||||
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||
|
||||
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||
|
||||
|
||||
## v1.11 (2022+ARM64)
|
||||
|
||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||
|
||||
- [NEW] A new file system operation has been added to the FUSE API:
|
||||
|
||||
```C
|
||||
int (*getpath)(const char *path, char *buf, size_t size,
|
||||
struct fuse_file_info *fi);
|
||||
```
|
||||
|
||||
The `getpath` operation allows a case-insensitive file system to report the correct case of a file path. For example, `getpath` can be used to report that the actual path of a file opened as `/PATH/TO/FILE` is really `/Path/To/File`. This capability is important for some Windows file system scenarios and can sometimes result in a performance improvement.
|
||||
|
||||
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
|
||||
|
||||
- [NEW] Many performance improvements:
|
||||
|
||||
- A new `PostDispositionForDirOnly` setting has been added to `FSP_FSCTL_VOLUME_PARAMS`. This allows a file system to declare that it does not want to see `SetInformation/Disposition` requests for files (such requests will still be sent for directories, because a file system is supposed to check if a directory is empty before deletion). This makes file (not directory) deletion faster. This optimization should be safe to enable for most file systems. FUSE file systems get this optimization for free.
|
||||
|
||||
- The FSD now implements "fast I/O" reads and writes. Fast I/O is a technique for doing I/O without using IRP's (I/O Request Packets) and can only work for file systems using the cache manager (`FileInfoTimeout==-1`). This results in significant improvement in read/write scenarios.
|
||||
|
||||
- The FSD now implements "fast I/O" for "transact" messages. Transact messages are used in the communication protocol between the kernel-mode FSD and the user-mode file system. Fast I/O speeds this communication protocol by as much as 10% in some scenarios. (Fast I/O for transact messages is enabled only when using the new `FSP_IOCTL_TRANSACT` control code, but does not require any other special configuration to be enabled.)
|
||||
|
||||
- The FSD per directory cache limit has been increased from 16K to 64K. This should allow for more directory data to be maintained in kernel and reduce round-trips to the user mode file system.
|
||||
|
||||
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
|
||||
|
||||
- [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountBroadcastDriveChange` has been introduced, which if set to 1 will broadcast an additional "drive change" message to all top-level windows (including Explorer) during mounting and unmounting.
|
||||
|
||||
- Normally the Windows infrastructure broadcasts a `WM_DEVICECHANGE` message whenever a drive gets added/removed. In some rare systems it is possible for this message to get lost or stalled. The workaround for these rare systems is to enable this registry setting, in which case WinFsp will broadcast the `WM_DEVICECHANGE` using a slightly different but more reliable method than the one Windows uses.
|
||||
|
||||
- For more details see source code comments at [`FspMountBroadcastDriveChange`](https://github.com/winfsp/winfsp/blob/v1.11B3/src/dll/mount.c#L390-L406).
|
||||
|
||||
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
|
||||
|
||||
- [FIX] WinFsp-FUSE now supports Azure AD accounts when specifying the `-o uid=-1` option. In addition a new option `-o uidmap=UID:SID` allows the specification of arbitrary UID<->SID or UID<->UserName mappings.
|
||||
|
||||
- [FIX] All executables (`*.exe,*.dll,*.sys`) in the WinFsp installation `bin` folder are now signed.
|
||||
|
||||
- [FIX] The default value for the registry setting `DistinctPermsForSameOwnerGroup` has been changed from 0 to 1.
|
||||
|
||||
- [BUILD] Product configuration (`MyProductName`, etc.) is done by the file `build.version.props` located in `build\VStudio`. This file was previously named `version.properties`.
|
||||
|
||||
|
||||
## v1.11RC1 (2022+ARM64 RC1)
|
||||
|
||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||
|
@ -58,6 +58,7 @@ CONTRIBUTOR LIST
|
||||
|Ben Rubson |ben.rubson at gmail.com
|
||||
|Bill Zissimopoulos |billziss at navimatics.com
|
||||
|Brett Dutro |brett.dutro at gmail.com
|
||||
|Changjian Gao (Juicedata, https://juicefs.com) |gcj at juicedata.io
|
||||
|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
|
||||
@ -67,6 +68,7 @@ CONTRIBUTOR LIST
|
||||
|John Tyner |jtyner at gmail.com
|
||||
|Paweł Wegner (Google LLC, https://google.com) |lemourin at google.com
|
||||
|Pedro Frejo (Arpa System, https://arpasystem.com) |pedro.frejo at arpasystem.com
|
||||
|Ronny Chan |ronny at ronnychan.ca
|
||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||
|Santiago Ganis |sganis at gmail.com
|
||||
|Tobias Urlaub |saibotu at outlook.de
|
||||
|
14
README.md
14
README.md
@ -10,18 +10,12 @@
|
||||
<a href="https://winfsp.dev"><b>winfsp.dev</b></a>
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="https://github.com/winfsp/winfsp/releases/latest">
|
||||
<img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/>
|
||||
</a>
|
||||
<a href="https://github.com/winfsp/winfsp/releases">
|
||||
<img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/>
|
||||
</a>
|
||||
<a href="https://chocolatey.org/packages/winfsp">
|
||||
<img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://github.com/winfsp/winfsp/releases/latest"><img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/></a>
|
||||
<a href="https://github.com/winfsp/winfsp/releases"><img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/></a>
|
||||
<a href="https://chocolatey.org/packages/winfsp"><img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/></a>
|
||||
<br/>
|
||||
<br/>
|
||||
<img src="doc/cap.gif" height="450"/>
|
||||
<img src="doc/cap.gif" width="75%" height="75%"/>
|
||||
<br/>
|
||||
<br/>
|
||||
</p>
|
||||
|
12
appveyor.yml
12
appveyor.yml
@ -17,19 +17,25 @@ environment:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CONFIGURATION: Debug
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: None
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: None
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: None
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: Func
|
||||
#- CONFIGURATION: Release
|
||||
# TESTING: Avast
|
||||
# DOCKER_TESTING: None
|
||||
#- CONFIGURATION: Release
|
||||
# TESTING: Perf
|
||||
# DOCKER_TESTING: None
|
||||
|
||||
init:
|
||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
@ -80,7 +86,8 @@ test_script:
|
||||
- if %TESTING%==Func 7z x Test.Filter.Driver.zip.001
|
||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||
- ps: . "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /k +spp *
|
||||
#- ps: . "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /k +spp *
|
||||
- if %DOCKER_TESTING%==Func docker run -d --name=Container0 --isolation=process "-vC:\Program Files (x86)\WinFsp:C:\Program Files (x86)\WinFsp:RO" "-vC:\projects:C:\projects:RO" mcr.microsoft.com/windows/servercore:ltsc2019 cmd.exe /c waitfor 7BF47D72F6664550B03248ECFE77C7DD
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
|
||||
@ -88,6 +95,9 @@ test_script:
|
||||
- if %TESTING%==Avast choco install avastfreeantivirus && fltmc instances -v "C:"
|
||||
- if %TESTING%==Avast tools\run-tests.bat %CONFIGURATION% avast-tests
|
||||
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
||||
- if %DOCKER_TESTING%==Func docker exec Container0 cmd.exe /c C:\projects\winfsp\build\VStudio\build\%CONFIGURATION%\winfsp-tests-x64.exe +*
|
||||
#- if %DOCKER_TESTING%==Func docker run -d --name=Container1 --isolation=process "-vC:\Program Files (x86)\WinFsp:C:\Program Files (x86)\WinFsp:RO" "-vC:\projects:C:\projects:RO" mcr.microsoft.com/windows/servercore:ltsc2019 cmd.exe /c waitfor 7BF47D72F6664550B03248ECFE77C7DD
|
||||
#- if %DOCKER_TESTING%==Func docker exec Container1 cmd.exe /c C:\projects\winfsp\build\VStudio\build\%CONFIGURATION%\winfsp-tests-x64.exe +*
|
||||
- choco uninstall winfsp -y
|
||||
|
||||
on_finish:
|
||||
|
@ -3,10 +3,10 @@
|
||||
<Import Project="$(MsbuildThisFileDirectory)\build.version.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid);MyFsctlRegisterPath=$(MyFsctlRegisterPath);MyNpRegisterPath=$(MyNpRegisterPath);MyEventLogRegisterPath=$(MyEventLogRegisterPath)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid);MyFsctlRegisterPath=$(MyFsctlRegisterPath);MyNpRegisterPath=$(MyNpRegisterPath);MyEventLogRegisterPath=$(MyEventLogRegisterPath)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(IsKernelModeToolset)'=='true'">
|
||||
|
@ -18,12 +18,12 @@
|
||||
<MyCompanyName>Navimatics LLC</MyCompanyName>
|
||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||
|
||||
<MyCanonicalVersion>1.11</MyCanonicalVersion>
|
||||
<MyCanonicalVersion>1.12</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2022+ARM64 RC1</MyProductVersion>
|
||||
<MyProductStage>RC</MyProductStage>
|
||||
<MyProductVersion>2022.2</MyProductVersion>
|
||||
<MyProductStage>Gold</MyProductStage>
|
||||
|
||||
<MyCrossCert>DigiCert High Assurance EV Root CA.crt</MyCrossCert>
|
||||
<MyCrossCert>DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer</MyCrossCert>
|
||||
<MyCertIssuer>DigiCert</MyCertIssuer>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
@ -40,5 +40,37 @@
|
||||
<!-- When rebranding WinFsp you MUST change the following GUIDs - use VS "Create GUID" tool -->
|
||||
<MyFspFsctlDeviceClassGuid>{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } }</MyFspFsctlDeviceClassGuid>
|
||||
<MyFspFsvrtDeviceClassGuid>{ 0xb48171c3, 0xdd50, 0x4852, { 0x83, 0xa3, 0x34, 0x4c, 0x50, 0xd9, 0x3b, 0x17 } }</MyFspFsvrtDeviceClassGuid>
|
||||
|
||||
<!--
|
||||
Configure paths used for registration via DllRegisterServer:
|
||||
|
||||
- MyFsctlRegisterPath: File System Driver registration path
|
||||
- MyNpRegisterPath: Network Provider registration path
|
||||
- MyEventLogRegisterPath: Event Log registration path
|
||||
|
||||
These paths are assumed to be relative to the location of the WinFsp DLL during
|
||||
registration: during DLLRegisterServer the DLL uses PathCombineW to combine its own
|
||||
location with these paths to produce the final locations to be used for registration.
|
||||
|
||||
For example, if the DLL location is `C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll`:
|
||||
|
||||
- Combining with the path "." will produce the original DLL location:
|
||||
`C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll`
|
||||
|
||||
- Combining with the path "..\\NetworkProvider.dll" will produce:
|
||||
`C:\Program Files (x86)\WinFsp\bin\NetworkProvider.dll`
|
||||
|
||||
- For Network Provider registrations only it is allowed to use environment variables
|
||||
in the path. For example combining the above DLL location with the path
|
||||
"..\\NetworkProvider-\x25PROCESSOR_ARCHITECTURE\x25.dll" will produce:
|
||||
`C:\Program Files (x86)\WinFsp\bin\NetworkProvider-%PROCESSOR_ARCHITECTURE%.dll`
|
||||
|
||||
(Note that the \x25 escape sequence must be used otherwise the VS build system will
|
||||
try to interpret the string %PROCESSOR_ARCHITECTURE% as an environment variable during
|
||||
the build.)
|
||||
-->
|
||||
<MyFsctlRegisterPath>"."</MyFsctlRegisterPath>
|
||||
<MyNpRegisterPath>"."</MyNpRegisterPath>
|
||||
<MyEventLogRegisterPath>"."</MyEventLogRegisterPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -75,6 +75,7 @@
|
||||
<ClCompile Include="..\..\src\dll\service.c" />
|
||||
<ClCompile Include="..\..\src\dll\util.c" />
|
||||
<ClCompile Include="..\..\src\dll\wksid.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -287,7 +288,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -314,7 +315,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -341,7 +342,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -371,7 +372,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
@ -402,7 +403,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
@ -433,7 +434,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
|
@ -175,6 +175,9 @@
|
||||
<ClCompile Include="..\..\src\dll\debug.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c">
|
||||
<Filter>Source\shared\ku</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
|
@ -228,6 +228,7 @@
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\uuid5.c" />
|
||||
<ClCompile Include="..\..\src\sys\cleanup.c" />
|
||||
|
@ -131,6 +131,9 @@
|
||||
<ClCompile Include="..\..\src\sys\devtimer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c">
|
||||
<Filter>Source\shared\ku</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -11,6 +11,7 @@ This document contains a list of known open-source file systems and file system
|
||||
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
||||
- https://github.com/sganis/golddrive[golddrive] - Windows ssh network drive
|
||||
- https://github.com/winfsp/hubfs[hubfs] - File system for GitHub
|
||||
- https://github.com/juicedata/juicefs[JuiceFS] - a distributed POSIX file system built on top of Redis and S3
|
||||
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
||||
- https://github.com/winfsp/nfs-win[nfs-win] - NFS for Windows
|
||||
- https://github.com/winfsp/objfs[objfs] - Object Storage File System
|
||||
@ -33,3 +34,4 @@ This document contains a list of known open-source file systems and file system
|
||||
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
||||
- https://github.com/pleiszenburg/refuse[Python: refuse] - Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
||||
- https://github.com/SnowflakePowered/winfsp-rs[Rust: winfsp-rs] - WinFSP binding for Rust
|
||||
|
@ -71,6 +71,8 @@ Primary registry key used to store WinFsp settings. On a 64-bit system (x64 or A
|
||||
|
||||
* `MountDoNotUseLauncher (REG_DWORD)`: A value of 1 disallows the use of the Launcher for drive mounting. The default value of 0 allows use of the Launcher for drive mounting when necessary. In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.
|
||||
|
||||
* `MountUseMountmgrFromFSD (REG_DWORD)`: A value of 1 instructs WinFsp to use the Mount Manager from the FSD (File System Driver) which runs in kernel mode. The default value of 0 instructs WinFsp to use the Mount Manager from the DLL which runs in user mode. Using the Mount Manager from user mode requires Administrator access and this setting allows a file system to circumvent the Administrator access requirement. This setting is not recommended for general use.
|
||||
|
||||
</blockquote>
|
||||
</details>
|
||||
|
||||
|
@ -538,7 +538,8 @@ static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo
|
||||
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
||||
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
||||
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
||||
FileInfo->IndexNumber = 0;
|
||||
FileInfo->IndexNumber =
|
||||
((UINT64)ByHandleFileInfo.nFileIndexHigh << 32) | (UINT64)ByHandleFileInfo.nFileIndexLow;
|
||||
FileInfo->HardLinks = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -91,6 +91,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
/* fsctl device codes */
|
||||
#define FSP_FSCTL_MOUNTDEV \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_MOUNTMGR \
|
||||
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 \
|
||||
@ -226,7 +228,7 @@ enum
|
||||
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
||||
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
||||
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
||||
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
||||
UINT32 RejectIrpPriorToTransact0:1; /* DEPRECATED: reject IRP's prior to FspFsctlTransact0 */\
|
||||
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
||||
UINT32 PostDispositionWhenNecessaryOnly:1; /* post Disposition for dirs or READONLY attr check */\
|
||||
UINT32 KmReservedFlags:1;\
|
||||
@ -679,6 +681,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
PHANDLE PVolumeHandle);
|
||||
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||
BOOLEAN Persistent, GUID *UniqueId);
|
||||
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
|
||||
PWSTR MountPoint);
|
||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||
|
@ -100,9 +100,11 @@ NTSTATUS FspEventLogRegister(VOID)
|
||||
WCHAR Path[MAX_PATH];
|
||||
DWORD RegResult, DwordValue;
|
||||
HKEY RegKey;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
Result = FspGetModuleFileName(DllInstance, Path, MAX_PATH, L"" MyEventLogRegisterPath);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
RegResult = RegCreateKeyExW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" FSP_EVENTLOG_NAME,
|
||||
|
@ -130,6 +130,22 @@ FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
|
||||
PWSTR MountPoint)
|
||||
{
|
||||
DWORD Bytes;
|
||||
|
||||
Bytes = 0 != MountPoint ? lstrlenW(MountPoint) * sizeof(WCHAR) : 0;
|
||||
|
||||
if (!DeviceIoControl(VolumeHandle,
|
||||
FSP_FSCTL_MOUNTMGR,
|
||||
MountPoint, Bytes, 0, 0,
|
||||
&Bytes, 0))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||
@ -568,8 +584,9 @@ NTSTATUS FspFsctlRegister(VOID)
|
||||
SERVICE_DESCRIPTION ServiceDescription;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, DriverPath, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
Result = FspGetModuleFileName(DllInstance, DriverPath, MAX_PATH, L"" MyFsctlRegisterPath);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
Size = lstrlenW(DriverPath);
|
||||
if (4 < Size &&
|
||||
@ -583,6 +600,14 @@ NTSTATUS FspFsctlRegister(VOID)
|
||||
DriverPath[Size - 2] = L'y';
|
||||
DriverPath[Size - 1] = L's';
|
||||
}
|
||||
else if (4 < Size &&
|
||||
(L'.' == DriverPath[Size - 4]) &&
|
||||
(L'S' == DriverPath[Size - 3] || L's' == DriverPath[Size - 3]) &&
|
||||
(L'Y' == DriverPath[Size - 2] || L'y' == DriverPath[Size - 2]) &&
|
||||
(L'S' == DriverPath[Size - 1] || L's' == DriverPath[Size - 1]) &&
|
||||
(L'\0' == DriverPath[Size]))
|
||||
{
|
||||
}
|
||||
else
|
||||
/* should not happen! */
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
|
@ -180,7 +180,7 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
||||
const char *mountpoint, struct fuse_args *args)
|
||||
{
|
||||
struct fuse_chan *ch = 0;
|
||||
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH];
|
||||
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH + 4];
|
||||
int Size;
|
||||
|
||||
if (0 == mountpoint || '\0' == mountpoint[0] ||
|
||||
@ -212,6 +212,33 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
||||
MountPointBuf[6] = '\0';
|
||||
Size = 7 * sizeof(WCHAR);
|
||||
}
|
||||
else if (
|
||||
(
|
||||
'\\' == mountpoint[0] &&
|
||||
'\\' == mountpoint[1] &&
|
||||
('?' == mountpoint[2] || '.' == mountpoint[2]) &&
|
||||
'\\' == mountpoint[3]
|
||||
) &&
|
||||
(
|
||||
('A' <= mountpoint[4] && mountpoint[4] <= 'Z') ||
|
||||
('a' <= mountpoint[4] && mountpoint[4] <= 'z')
|
||||
) &&
|
||||
':' == mountpoint[5] && '\\' == mountpoint[6])
|
||||
{
|
||||
MountPointBuf[0] = '\\';
|
||||
MountPointBuf[1] = '\\';
|
||||
MountPointBuf[2] = mountpoint[2];
|
||||
MountPointBuf[3] = '\\';
|
||||
|
||||
Size = 0;
|
||||
if (0 != MultiByteToWideChar(CP_UTF8, 0, mountpoint + 4, -1, TempMountPointBuf, MAX_PATH))
|
||||
Size = GetFullPathNameW(TempMountPointBuf, MAX_PATH, MountPointBuf + 4, 0);
|
||||
|
||||
if (0 == Size || MAX_PATH <= Size)
|
||||
goto fail;
|
||||
|
||||
Size = (Size + 4 + 1) * sizeof(WCHAR);
|
||||
}
|
||||
else if (
|
||||
(
|
||||
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
||||
|
@ -73,6 +73,15 @@ NTSTATUS FspEventLogUnregister(VOID);
|
||||
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
||||
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
||||
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
|
||||
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap);
|
||||
VOID FspLdapClose(PVOID Ldap);
|
||||
ULONG FspLdapGetValue(PVOID Ldap, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
|
||||
@ -81,7 +90,18 @@ ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue);
|
||||
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue);
|
||||
|
||||
PWSTR FspDiagIdent(VOID);
|
||||
HANDLE FspCreateDirectoryFileW(
|
||||
PWSTR FileName,
|
||||
DWORD DesiredAccess,
|
||||
DWORD ShareAccess,
|
||||
PSECURITY_ATTRIBUTES SecurityAttributes,
|
||||
DWORD FlagsAndAttributes);
|
||||
NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion);
|
||||
NTSTATUS FspGetModuleFileName(
|
||||
HMODULE Module,
|
||||
PWSTR FileName,
|
||||
ULONG Size,
|
||||
PWSTR RelativePath);
|
||||
|
||||
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
||||
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||
@ -126,6 +146,12 @@ static inline BOOLEAN FspPathIsMountmgrMountPoint(PWSTR FileName)
|
||||
) &&
|
||||
L':' == FileName[5];
|
||||
}
|
||||
static inline BOOLEAN FspPathIsMountmgrDrive(PWSTR FileName)
|
||||
{
|
||||
return
|
||||
FspPathIsMountmgrMountPoint(FileName) &&
|
||||
L'\0' == FileName[6];
|
||||
}
|
||||
|
||||
#define FSP_NEXT_EA(Ea, EaEnd) \
|
||||
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
||||
|
366
src/dll/mount.c
366
src/dll/mount.c
@ -31,6 +31,7 @@ static NTSTATUS (NTAPI *FspNtClose)(
|
||||
HANDLE Handle);
|
||||
static BOOLEAN FspMountDoNotUseLauncherValue;
|
||||
static BOOLEAN FspMountBroadcastDriveChangeValue;
|
||||
static BOOLEAN FspMountUseMountmgrFromFSDValue;
|
||||
|
||||
static VOID FspMountInitializeFromRegistry(VOID)
|
||||
{
|
||||
@ -53,6 +54,14 @@ static VOID FspMountInitializeFromRegistry(VOID)
|
||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||
if (ERROR_SUCCESS == Result)
|
||||
FspMountBroadcastDriveChangeValue = !!Value;
|
||||
|
||||
Value = 0;
|
||||
Size = sizeof Value;
|
||||
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||
L"MountUseMountmgrFromFSD",
|
||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||
if (ERROR_SUCCESS == Result)
|
||||
FspMountUseMountmgrFromFSDValue = !!Value;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspMountInitialize(
|
||||
@ -80,93 +89,17 @@ static BOOL WINAPI FspMountInitialize(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
||||
static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle);
|
||||
static NTSTATUS FspMountRemove_Directory(HANDLE MountHandle);
|
||||
|
||||
static NTSTATUS FspMountSet_MountmgrDrive(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
|
||||
{
|
||||
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;
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
/* use MountManager from FSD and exit */
|
||||
return FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
|
||||
|
||||
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 */
|
||||
@ -174,190 +107,115 @@ static NTSTATUS FspMountSet_Mountmgr(HANDLE VolumeHandle, PWSTR VolumeName, PWST
|
||||
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);
|
||||
/* use the MountManager to create the drive */
|
||||
UNICODE_STRING UVolumeName, UMountPoint;
|
||||
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||
UVolumeName.Buffer = VolumeName;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
Result = FspMountmgrCreateDrive(&UVolumeName, &UniqueId, &UMountPoint);
|
||||
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 FspMountSet_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
||||
{
|
||||
GUID UniqueId;
|
||||
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PMountHandle = 0;
|
||||
|
||||
/* create the directory mount point */
|
||||
Result = FspMountSet_Directory(VolumeName, MountPoint + 4, SecurityDescriptor, &MountHandle);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
{
|
||||
/* use MountManager from FSD and exit */
|
||||
Result = FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
*PMountHandle = MountHandle;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* transform our volume into one that can be used by the MountManager */
|
||||
Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, &UniqueId);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* notify the MountManager about the created directory mount point */
|
||||
UNICODE_STRING UVolumeName, UMountPoint;
|
||||
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||
UVolumeName.Buffer = VolumeName;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
Result = FspMountmgrNotifyCreateDirectory(&UVolumeName, &UniqueId, &UMountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
*PMountHandle = MountHandle;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
||||
FspMountRemove_Directory(MountHandle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountRemove_Mountmgr(PWSTR MountPoint)
|
||||
static NTSTATUS FspMountRemove_MountmgrDrive(HANDLE VolumeHandle, 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;
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
/* use MountManager from FSD and exit */
|
||||
return FspFsctlUseMountmgr(VolumeHandle, 0);
|
||||
|
||||
MOUNTMGR_MOUNT_POINT *Input = 0;
|
||||
MOUNTMGR_MOUNT_POINTS *Output = 0;
|
||||
ULONG InputSize, OutputSize;
|
||||
/* use the MountManager to delete the drive */
|
||||
UNICODE_STRING UMountPoint;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
return FspMountmgrDeleteDrive(&UMountPoint);
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountRemove_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
|
||||
HANDLE MountHandle)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
|
||||
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
OutputSize = 4096;
|
||||
|
||||
Input = MemAlloc(InputSize);
|
||||
if (0 == Input)
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
/* use MountManager from FSD, but do not exit; additional processing is required below */
|
||||
FspFsctlUseMountmgr(VolumeHandle, 0);
|
||||
else
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
/* notify the MountManager about the deleted directory mount point */
|
||||
UNICODE_STRING UVolumeName, UMountPoint;
|
||||
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||
UVolumeName.Buffer = VolumeName;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
FspMountmgrNotifyDeleteDirectory(&UVolumeName, &UMountPoint);
|
||||
}
|
||||
|
||||
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);
|
||||
/* delete the directory mount point */
|
||||
Result = FspMountRemove_Directory(MountHandle);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(Output);
|
||||
MemFree(Input);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -630,14 +488,12 @@ static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||
|
||||
MountHandle = CreateFileW(MountPoint,
|
||||
MountHandle = FspCreateDirectoryFileW(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);
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE);
|
||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
@ -740,8 +596,11 @@ FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
||||
Desc->MountPoint[0] = L'*';
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
else if (FspPathIsMountmgrDrive(Desc->MountPoint))
|
||||
return FspMountSet_MountmgrDrive(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
||||
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||
return FspMountSet_Mountmgr(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
||||
return FspMountSet_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
|
||||
Desc->Security, &Desc->MountHandle);
|
||||
else if (FspPathIsDrive(Desc->MountPoint))
|
||||
return FspMountSet_Drive(Desc->VolumeName, Desc->MountPoint,
|
||||
&Desc->MountHandle);
|
||||
@ -754,8 +613,11 @@ FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||
|
||||
if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||
return FspMountRemove_Mountmgr(Desc->MountPoint);
|
||||
if (FspPathIsMountmgrDrive(Desc->MountPoint))
|
||||
return FspMountRemove_MountmgrDrive(Desc->VolumeHandle, Desc->MountPoint);
|
||||
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||
return FspMountRemove_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
|
||||
Desc->MountHandle);
|
||||
else if (FspPathIsDrive(Desc->MountPoint))
|
||||
return FspMountRemove_Drive(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
|
||||
else
|
||||
|
32
src/dll/np.c
32
src/dll/np.c
@ -1152,15 +1152,34 @@ DWORD APIENTRY NPCloseEnum(HANDLE hEnum)
|
||||
NTSTATUS FspNpRegister(VOID)
|
||||
{
|
||||
extern HINSTANCE DllInstance;
|
||||
WCHAR ProviderPath[MAX_PATH];
|
||||
WCHAR DllPath[MAX_PATH], ProviderPath[MAX_PATH];
|
||||
PWSTR VersionInfoPath;
|
||||
BOOLEAN HasPercent;
|
||||
WCHAR RegBuffer[1024];
|
||||
PWSTR P, Part;
|
||||
DWORD RegResult, RegType, RegBufferSize, RegBufferOffset;
|
||||
HKEY RegKey;
|
||||
BOOLEAN FoundProvider;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, ProviderPath, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
VersionInfoPath = ProviderPath;
|
||||
HasPercent = FALSE;
|
||||
for (P = L"" MyNpRegisterPath; *P; P++)
|
||||
if ('%' == *P)
|
||||
{
|
||||
HasPercent = TRUE;
|
||||
break;
|
||||
}
|
||||
if (HasPercent)
|
||||
{
|
||||
VersionInfoPath = DllPath;
|
||||
if (0 == GetModuleFileNameW(DllInstance, DllPath, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
Result = FspGetModuleFileName(DllInstance, ProviderPath, MAX_PATH, L"" MyNpRegisterPath);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
RegResult = RegCreateKeyExW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME,
|
||||
@ -1187,12 +1206,12 @@ NTSTATUS FspNpRegister(VOID)
|
||||
DWORD Size;
|
||||
PWSTR Description;
|
||||
|
||||
Size = GetFileVersionInfoSizeW(ProviderPath, &Size/*dummy*/);
|
||||
Size = GetFileVersionInfoSizeW(VersionInfoPath, &Size/*dummy*/);
|
||||
if (0 < Size)
|
||||
{
|
||||
VersionInfo = MemAlloc(Size);
|
||||
if (0 != VersionInfo &&
|
||||
GetFileVersionInfoW(ProviderPath, 0, Size, VersionInfo) &&
|
||||
GetFileVersionInfoW(VersionInfoPath, 0, Size, VersionInfo) &&
|
||||
VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription",
|
||||
&Description, &Size))
|
||||
{
|
||||
@ -1208,7 +1227,8 @@ NTSTATUS FspNpRegister(VOID)
|
||||
goto close_and_exit;
|
||||
|
||||
RegResult = RegSetValueExW(RegKey,
|
||||
L"ProviderPath", 0, REG_SZ, (PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
|
||||
L"ProviderPath", 0, HasPercent ? REG_EXPAND_SZ : REG_SZ,
|
||||
(PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
|
170
src/dll/util.c
170
src/dll/util.c
@ -21,6 +21,7 @@
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <aclapi.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
static INIT_ONCE FspDiagIdentInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static WCHAR FspDiagIdentBuf[20] = L"UNKNOWN";
|
||||
@ -63,6 +64,145 @@ PWSTR FspDiagIdent(VOID)
|
||||
return FspDiagIdentBuf;
|
||||
}
|
||||
|
||||
static INIT_ONCE FspCreateDirectoryFileInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static NTSTATUS (NTAPI *FspNtCreateFile)(
|
||||
PHANDLE FileHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PLARGE_INTEGER AllocationSize,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PVOID EaBuffer,
|
||||
ULONG EaLength);
|
||||
|
||||
static BOOL WINAPI FspCreateDirectoryFileInitialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
HANDLE Handle;
|
||||
|
||||
Handle = GetModuleHandleW(L"ntdll.dll");
|
||||
if (0 != Handle)
|
||||
FspNtCreateFile = (PVOID)GetProcAddress(Handle, "NtCreateFile");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE FspCreateDirectoryFileW(
|
||||
PWSTR FileName,
|
||||
DWORD DesiredAccess,
|
||||
DWORD ShareAccess,
|
||||
PSECURITY_ATTRIBUTES SecurityAttributes,
|
||||
DWORD FlagsAndAttributes)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspCreateDirectoryFileInitOnce, FspCreateDirectoryFileInitialize, 0, 0);
|
||||
if (0 == FspNtCreateFile)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FUNCTION);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE Handle = INVALID_HANDLE_VALUE, ParentHandle = INVALID_HANDLE_VALUE;
|
||||
PWSTR FullFileName = 0;
|
||||
WCHAR *FilePart, FilePartChar;
|
||||
DWORD Length;
|
||||
UNICODE_STRING UFullFileName;
|
||||
OBJECT_ATTRIBUTES Obja;
|
||||
ULONG CreateFlags;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
Length = GetFullPathNameW(FileName, 0, 0, 0);
|
||||
if (0 == Length)
|
||||
goto exit;
|
||||
|
||||
FullFileName = MemAlloc((Length + 1) * sizeof(WCHAR));
|
||||
if (0 == FullFileName)
|
||||
{
|
||||
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Length = GetFullPathNameW(FileName, Length + 1, FullFileName, &FilePart);
|
||||
if (0 == Length)
|
||||
goto exit;
|
||||
|
||||
FilePartChar = *FilePart;
|
||||
*FilePart = L'\0';
|
||||
|
||||
ParentHandle = CreateFileW(
|
||||
FullFileName,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == ParentHandle)
|
||||
goto exit;
|
||||
|
||||
*FilePart = FilePartChar;
|
||||
|
||||
UFullFileName.Length = UFullFileName.MaximumLength = (USHORT)(lstrlenW(FilePart) * sizeof(WCHAR));
|
||||
UFullFileName.Buffer = FilePart;
|
||||
|
||||
memset(&Obja, 0, sizeof Obja);
|
||||
Obja.Length = sizeof Obja;
|
||||
Obja.ObjectName = &UFullFileName;
|
||||
Obja.Attributes =
|
||||
(!(FlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS) ? OBJ_CASE_INSENSITIVE : 0) |
|
||||
(SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0);
|
||||
Obja.RootDirectory = ParentHandle;
|
||||
Obja.SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
|
||||
|
||||
DesiredAccess |=
|
||||
SYNCHRONIZE |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
((FlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) ? DELETE : 0);
|
||||
|
||||
CreateFlags =
|
||||
FILE_DIRECTORY_FILE |
|
||||
((FlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_OVERLAPPED) ? FILE_SYNCHRONOUS_IO_NONALERT : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_NO_BUFFERING) ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) ? FILE_RANDOM_ACCESS : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) ? FILE_SEQUENTIAL_ONLY : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) ? FILE_DELETE_ON_CLOSE : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) ? FILE_OPEN_FOR_BACKUP_INTENT : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) ? FILE_OPEN_REPARSE_POINT : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) ? FILE_OPEN_NO_RECALL : 0);
|
||||
|
||||
IoStatus.Status = FspNtCreateFile(
|
||||
&Handle,
|
||||
DesiredAccess,
|
||||
&Obja,
|
||||
&IoStatus,
|
||||
0,
|
||||
FlagsAndAttributes & (0x7fff & ~FILE_ATTRIBUTE_DIRECTORY),
|
||||
ShareAccess,
|
||||
FILE_CREATE,
|
||||
CreateFlags,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
{
|
||||
SetLastError(FspWin32FromNtStatus(IoStatus.Status));
|
||||
Handle = INVALID_HANDLE_VALUE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != ParentHandle)
|
||||
CloseHandle(ParentHandle);
|
||||
|
||||
MemFree(FullFileName);
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||
PULONG PBytesTransferred, ULONG Timeout,
|
||||
@ -248,3 +388,33 @@ NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion)
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspGetModuleFileName(
|
||||
HMODULE Module,
|
||||
PWSTR FileName,
|
||||
ULONG Size,
|
||||
PWSTR RelativePath)
|
||||
{
|
||||
if (MAX_PATH > Size)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (0 != RelativePath &&
|
||||
L'\0' != RelativePath[0] &&
|
||||
(L'.' != RelativePath[0] || L'\0' != RelativePath[1]))
|
||||
{
|
||||
WCHAR Temp[MAX_PATH];
|
||||
|
||||
if (0 == GetModuleFileNameW(Module, Temp, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
if (0 == PathCombineW(FileName, Temp, RelativePath))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 == GetModuleFileNameW(Module, FileName, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
599
src/shared/ku/mountmgr.c
Normal file
599
src/shared/ku/mountmgr.c
Normal file
@ -0,0 +1,599 @@
|
||||
/**
|
||||
* @file shared/ku/mountmgr.c
|
||||
*
|
||||
* @copyright 2015-2022 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 <shared/ku/library.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4459) /* declaration of 'identifier' hides global declaration */
|
||||
|
||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength);
|
||||
static NTSTATUS FspMountmgrNotifyVolumeArrival(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId);
|
||||
static NTSTATUS FspMountmgrNotifyMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created);
|
||||
static NTSTATUS FspMountmgrCreateMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
static NTSTATUS FspMountmgrDeleteMountPoint(
|
||||
PUNICODE_STRING MountPoint);
|
||||
static VOID FspMountmgrDeleteRegistry(
|
||||
GUID *UniqueId);
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspMountmgrControl)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyVolumeArrival)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyMountPoint)
|
||||
#pragma alloc_text(PAGE, FspMountmgrCreateMountPoint)
|
||||
#pragma alloc_text(PAGE, FspMountmgrDeleteMountPoint)
|
||||
#pragma alloc_text(PAGE, FspMountmgrCreateDrive)
|
||||
#pragma alloc_text(PAGE, FspMountmgrDeleteDrive)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyCreateDirectory)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyDeleteDirectory)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
||||
{
|
||||
#if defined(_KERNEL_MODE)
|
||||
FSP_KU_CODE;
|
||||
|
||||
UNICODE_STRING DeviceName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
HANDLE MgrHandle = 0;
|
||||
ULONG Bytes = 0;
|
||||
|
||||
if (0 == POutputBufferLength)
|
||||
POutputBufferLength = &Bytes;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\MountPointManager");
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&DeviceName,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
0/*RootDirectory*/,
|
||||
0);
|
||||
|
||||
IoStatus.Status = ZwOpenFile(
|
||||
&MgrHandle,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_SYNCHRONOUS_IO_ALERT);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
goto exit;
|
||||
|
||||
IoStatus.Status = ZwDeviceIoControlFile(
|
||||
MgrHandle,
|
||||
0, 0, 0,
|
||||
&IoStatus,
|
||||
IoControlCode,
|
||||
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
goto exit;
|
||||
|
||||
*POutputBufferLength = (ULONG)IoStatus.Information;
|
||||
IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != MgrHandle)
|
||||
ZwClose(MgrHandle);
|
||||
|
||||
return IoStatus.Status;
|
||||
#else
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrNotifyVolumeArrival(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* 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;
|
||||
|
||||
MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
|
||||
MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
|
||||
MOUNTMGR_TARGET_NAME *TargetName = 0;
|
||||
ULONG QueryAutoMountSize, TargetNameSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
QueryAutoMountSize = sizeof QueryAutoMount;
|
||||
TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeName->Length;
|
||||
|
||||
TargetName = MemAlloc(TargetNameSize);
|
||||
if (0 == TargetName)
|
||||
{
|
||||
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 = VolumeName->Length;
|
||||
memcpy(TargetName->DeviceName, VolumeName->Buffer, VolumeName->Length);
|
||||
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);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(TargetName);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrNotifyMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef struct
|
||||
{
|
||||
USHORT SourceVolumeNameOffset;
|
||||
USHORT SourceVolumeNameLength;
|
||||
USHORT TargetVolumeNameOffset;
|
||||
USHORT TargetVolumeNameLength;
|
||||
} MOUNTMGR_VOLUME_MOUNT_POINT;
|
||||
|
||||
MOUNTMGR_VOLUME_MOUNT_POINT *VolumeMountPoint = 0;
|
||||
ULONG VolumeMountPointSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
VolumeMountPointSize = sizeof *VolumeMountPoint +
|
||||
sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length + VolumeName->Length;
|
||||
|
||||
VolumeMountPoint = MemAlloc(VolumeMountPointSize);
|
||||
if (0 == VolumeMountPoint)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* notify volume mount point created/deleted */
|
||||
memset(VolumeMountPoint, 0, sizeof *VolumeMountPoint);
|
||||
VolumeMountPoint->SourceVolumeNameOffset = sizeof *VolumeMountPoint;
|
||||
VolumeMountPoint->SourceVolumeNameLength = (USHORT)(
|
||||
sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length);
|
||||
VolumeMountPoint->TargetVolumeNameOffset =
|
||||
VolumeMountPoint->SourceVolumeNameOffset + VolumeMountPoint->SourceVolumeNameLength;
|
||||
VolumeMountPoint->TargetVolumeNameLength = VolumeName->Length;
|
||||
memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset,
|
||||
L"\\DosDevices\\", sizeof L"\\DosDevices\\" - sizeof(WCHAR));
|
||||
memcpy((PUINT8)VolumeMountPoint +
|
||||
VolumeMountPoint->SourceVolumeNameOffset + (sizeof L"\\DosDevices\\" - sizeof(WCHAR)),
|
||||
MountPoint->Buffer, MountPoint->Length);
|
||||
memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset,
|
||||
VolumeName->Buffer, VolumeName->Length);
|
||||
Result = FspMountmgrControl(
|
||||
Created ?
|
||||
CTL_CODE('m', 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) :
|
||||
/* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED */
|
||||
CTL_CODE('m', 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED */
|
||||
VolumeMountPoint, VolumeMountPointSize, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(VolumeMountPoint);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrCreateMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef struct
|
||||
{
|
||||
USHORT SymbolicLinkNameOffset;
|
||||
USHORT SymbolicLinkNameLength;
|
||||
USHORT DeviceNameOffset;
|
||||
USHORT DeviceNameLength;
|
||||
} MOUNTMGR_CREATE_POINT_INPUT;
|
||||
|
||||
MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
|
||||
ULONG CreatePointInputSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
CreatePointInputSize = sizeof *CreatePointInput +
|
||||
sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeName->Length;
|
||||
|
||||
CreatePointInput = MemAlloc(CreatePointInputSize);
|
||||
if (0 == CreatePointInput)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* 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 = VolumeName->Length;
|
||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
|
||||
L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
|
||||
((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
|
||||
MountPoint->Buffer[0] & ~0x20;
|
||||
/* convert to uppercase */
|
||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
|
||||
VolumeName->Buffer, VolumeName->Length);
|
||||
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;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(CreatePointInput);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrDeleteMountPoint(
|
||||
PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* delete mount point */
|
||||
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->Buffer[0] & ~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 VOID FspMountmgrDeleteRegistry(GUID *UniqueId)
|
||||
{
|
||||
#if defined(_KERNEL_MODE)
|
||||
FSP_KU_CODE;
|
||||
|
||||
UNICODE_STRING Path;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE Handle = 0;
|
||||
union
|
||||
{
|
||||
KEY_VALUE_FULL_INFORMATION V;
|
||||
UINT8 B[FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) + 255 + sizeof *UniqueId];
|
||||
} FullInformation;
|
||||
ULONG FullInformationLength;
|
||||
UNICODE_STRING ValueName;
|
||||
NTSTATUS Result;
|
||||
|
||||
RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\System\\MountedDevices");
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&Path,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
0/*RootDirectory*/,
|
||||
0);
|
||||
|
||||
Result = ZwOpenKey(&Handle, KEY_QUERY_VALUE, &ObjectAttributes);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
for (ULONG I = 0;; I++)
|
||||
{
|
||||
Result = ZwEnumerateValueKey(Handle,
|
||||
I, KeyValueFullInformation, &FullInformation,
|
||||
sizeof FullInformation, &FullInformationLength);
|
||||
if (STATUS_NO_MORE_ENTRIES == Result)
|
||||
break;
|
||||
else if (!NT_SUCCESS(Result))
|
||||
continue;
|
||||
|
||||
if (REG_BINARY == FullInformation.V.Type &&
|
||||
sizeof *UniqueId == FullInformation.V.DataLength &&
|
||||
InlineIsEqualGUID((GUID *)((PUINT8)&FullInformation.V + FullInformation.V.DataOffset),
|
||||
UniqueId))
|
||||
{
|
||||
ValueName.Length = ValueName.MaximumLength = (USHORT)FullInformation.V.NameLength;
|
||||
ValueName.Buffer = FullInformation.V.Name;
|
||||
Result = ZwDeleteValueKey(Handle, &ValueName);
|
||||
if (NT_SUCCESS(Result))
|
||||
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||
I = (ULONG)-1;
|
||||
}
|
||||
}
|
||||
|
||||
ZwClose(Handle);
|
||||
}
|
||||
#else
|
||||
HKEY RegKey;
|
||||
LONG RegResult;
|
||||
WCHAR RegValueName[MAX_PATH];
|
||||
UINT8 RegValueData[sizeof *UniqueId];
|
||||
DWORD RegValueNameSize, RegValueDataSize;
|
||||
DWORD RegType;
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
/* notify the MountManager about the new volume */
|
||||
Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* use the MountManager to create the drive */
|
||||
Result = FspMountmgrCreateMountPoint(VolumeName, MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* HACK: delete the MountManager registry entries */
|
||||
FspMountmgrDeleteRegistry(UniqueId);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
/* use the MountManager to delete the drive */
|
||||
Result = FspMountmgrDeleteMountPoint(MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
/* notify the MountManager about the new volume */
|
||||
Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* notify the MountManager about the created directory mount point */
|
||||
Result = FspMountmgrNotifyMountPoint(VolumeName, MountPoint, TRUE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* HACK: delete the MountManager registry entries */
|
||||
FspMountmgrDeleteRegistry(UniqueId);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* notify the MountManager about the deleted directory mount point */
|
||||
return FspMountmgrNotifyMountPoint(VolumeName, MountPoint, FALSE);
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
@ -59,6 +59,8 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I
|
||||
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
|
||||
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
@ -84,6 +86,8 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
||||
@ -171,7 +175,7 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
||||
Result = FspFsvolDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
Result = STATUS_SUCCESS;
|
||||
Result = FspFsvrtDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
Result = FspFsmupDeviceInit(DeviceObject);
|
||||
@ -202,6 +206,7 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||
FspFsvolDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
FspFsvrtDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
FspFsmupDeviceFini(DeviceObject);
|
||||
@ -848,6 +853,27 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
|
||||
ExInitializeFastMutex(&FsvrtDeviceExtension->MountMutex);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
|
||||
if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
@ -150,6 +150,10 @@ NTSTATUS DriverEntry(
|
||||
goto exit;
|
||||
InitDoneDevices = TRUE;
|
||||
|
||||
Result = FspSiloPostInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
|
@ -754,6 +754,7 @@ NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals);
|
||||
VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals);
|
||||
VOID FspSiloGetContainerId(GUID *ContainerId);
|
||||
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
||||
NTSTATUS FspSiloPostInitialize(VOID);
|
||||
VOID FspSiloFinalize(VOID);
|
||||
|
||||
/* process buffers */
|
||||
@ -1181,7 +1182,6 @@ typedef struct
|
||||
KSPIN_LOCK SpinLock;
|
||||
LONG RefCount;
|
||||
UINT32 Kind;
|
||||
GUID SiloContainerId;
|
||||
/* IoTimer emulation */
|
||||
FSP_DEVICE_TIMER DeviceTimer;
|
||||
} FSP_DEVICE_EXTENSION;
|
||||
@ -1232,13 +1232,18 @@ typedef struct
|
||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
/* read-only after creation (and insertion in the ContextTable) */
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT16 SectorSize;
|
||||
LONG IsMountdev;
|
||||
BOOLEAN Persistent;
|
||||
GUID UniqueId;
|
||||
UNICODE_STRING VolumeName;
|
||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||
FAST_MUTEX MountMutex;
|
||||
/* interlocked access */
|
||||
LONG IsMountdev;
|
||||
/* protected under MountMutex */
|
||||
BOOLEAN Persistent;
|
||||
GUID UniqueId;
|
||||
UNICODE_STRING MountPoint;
|
||||
} FSP_FSVRT_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
@ -1435,6 +1440,18 @@ BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE
|
||||
TRUE);
|
||||
}
|
||||
static inline
|
||||
VOID FspFsvrtDeviceLockMount(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
ExAcquireFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
|
||||
}
|
||||
static inline
|
||||
VOID FspFsvrtDeviceUnlockMount(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
ExReleaseFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
|
||||
}
|
||||
static inline
|
||||
VOID FspFsmupDeviceLockPrefixTable(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||
@ -1524,6 +1541,16 @@ NTSTATUS FspMountdevMake(
|
||||
VOID FspMountdevFini(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||
|
||||
/* mountmgr */
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
|
||||
/* fsmup */
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
@ -1543,6 +1570,8 @@ NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMakeMountdev(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeUseMountmgr(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
|
@ -1475,7 +1475,7 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
|
||||
{
|
||||
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||
(PVOID)((UINT_PTR)DescendantFileNode | 2);
|
||||
(PVOID)((UINT_PTR)DescendantFileNode | 4);
|
||||
}
|
||||
else
|
||||
Result = STATUS_ACCESS_DENIED;
|
||||
|
@ -81,6 +81,10 @@ static NTSTATUS FspFsctlFileSystemControl(
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case FSP_FSCTL_MOUNTMGR:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeUseMountmgr(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case FSP_FSCTL_VOLUME_NAME:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
|
||||
|
@ -138,7 +138,7 @@ NTSTATUS FspMountdevMake(
|
||||
* be mounted using the MountManager.
|
||||
*
|
||||
* This function requires protection against concurrency. In general this
|
||||
* is achieved by acquiring the GlobalDeviceLock.
|
||||
* is achieved by the caller acquiring the MountMutex.
|
||||
*/
|
||||
|
||||
PAGED_CODE();
|
||||
@ -178,11 +178,6 @@ NTSTATUS FspMountdevMake(
|
||||
|
||||
/* initialize the fsvrt device extension */
|
||||
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
|
||||
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||
|
||||
/* mark the fsvrt device as initialized */
|
||||
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
@ -22,9 +22,11 @@
|
||||
#include <sys/driver.h>
|
||||
|
||||
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
||||
NTSTATUS FspSiloPostInitialize(VOID);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT, FspSiloInitialize)
|
||||
#pragma alloc_text(INIT, FspSiloPostInitialize)
|
||||
#endif
|
||||
|
||||
typedef PEJOB FSP_PESILO;
|
||||
@ -293,15 +295,11 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = CALL(PsStartSiloMonitor)(Monitor);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
FspSiloMonitor = Monitor;
|
||||
FspSiloInitCallback = Init;
|
||||
FspSiloFiniCallback = Fini;
|
||||
|
||||
FspSiloInitDone = TRUE;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
@ -316,10 +314,23 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspSiloPostInitialize(VOID)
|
||||
{
|
||||
if (!FspSiloInitDone)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
return CALL(PsStartSiloMonitor)(FspSiloMonitor);
|
||||
}
|
||||
|
||||
VOID FspSiloFinalize(VOID)
|
||||
{
|
||||
if (!FspSiloInitDone)
|
||||
return;
|
||||
|
||||
CALL(PsUnregisterSiloMonitor)(FspSiloMonitor);
|
||||
|
||||
FspSiloMonitor = 0;
|
||||
FspSiloInitCallback = 0;
|
||||
FspSiloFiniCallback = 0;
|
||||
FspSiloInitDone = FALSE;
|
||||
}
|
||||
|
211
src/sys/volume.c
211
src/sys/volume.c
@ -38,6 +38,8 @@ static NTSTATUS FspVolumeMountNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMakeMountdev(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeUseMountmgr(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -76,6 +78,7 @@ NTSTATUS FspVolumeWork(
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
|
||||
#pragma alloc_text(PAGE, FspVolumeUseMountmgr)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetName)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||
@ -110,6 +113,57 @@ NTSTATUS FspVolumeCreate(
|
||||
|
||||
FspSiloDereferenceGlobals(Globals);
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
/*
|
||||
* If we have an fsvrt device, mount it NOW via opening the volume. This ensures
|
||||
* that the fsvrt is mounted by the correct fsvol device early on and remedies
|
||||
* a rare case where NTFS crashes the system when it attempts to mount our fsvrt.
|
||||
*
|
||||
* We use IoCreateFileEx with FILE_READ_DATA to ensure that the I/O Manager will
|
||||
* mount the fsvrt device.
|
||||
*
|
||||
* We ignore the IoCreateFileEx return code as it is only used for its side effect
|
||||
* of mounting the fsvrt. In the unlikely event that IoCreateFileEx fails, the
|
||||
* system will retry the mount when a file is accessed, etc.
|
||||
*/
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
HANDLE Handle;
|
||||
|
||||
if (0 != FsvrtDeviceObject)
|
||||
{
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&FsvolDeviceExtension->VolumeName,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
0/*RootDirectory*/,
|
||||
0/*SecurityDescriptor*/);
|
||||
IoStatus.Status = IoCreateFileEx(
|
||||
&Handle,
|
||||
FILE_READ_DATA,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
0/*AllocationSize*/,
|
||||
0/*FileAttributes*/,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
0/*CreateOptions*/,
|
||||
0/*EaBuffer*/,
|
||||
0/*EaLength*/,
|
||||
CreateFileTypeNone,
|
||||
0/*InternalParameters*/,
|
||||
0/*Options*/,
|
||||
0/*DriverContext*/);
|
||||
if (NT_SUCCESS(IoStatus.Status))
|
||||
ObCloseHandle(Handle, KernelMode);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -246,6 +300,11 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hardcode the RejectIrpPriorToTransact0 = 1 setting.
|
||||
*/
|
||||
VolumeParams.RejectIrpPriorToTransact0 = 1;
|
||||
|
||||
/* load any fsext provider */
|
||||
if (0 != VolumeParams.FsextControlCode)
|
||||
{
|
||||
@ -316,8 +375,12 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
{
|
||||
if (0 != FsvrtDeviceObject)
|
||||
{
|
||||
FspFsvrtDeviceExtension(FsvrtDeviceObject)->SectorSize =
|
||||
FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
FsvrtDeviceExtension->SectorSize = FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||
|
||||
Result = FspDeviceInitialize(FsvrtDeviceObject);
|
||||
}
|
||||
}
|
||||
@ -638,7 +701,7 @@ NTSTATUS FspVolumeMakeMountdev(
|
||||
if (sizeof(GUID) > OutputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
FspDeviceGlobalLock();
|
||||
FspFsvrtDeviceLockMount(FsvrtDeviceObject);
|
||||
|
||||
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||
if (!NT_SUCCESS(Result))
|
||||
@ -654,7 +717,147 @@ NTSTATUS FspVolumeMakeMountdev(
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
FspDeviceGlobalUnlock();
|
||||
FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeUseMountmgr(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||
ASSERT(FSP_FSCTL_MOUNTMGR == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == FsvrtDeviceObject)
|
||||
return STATUS_INVALID_PARAMETER; /* cannot only use fsvrt with mount manager */
|
||||
if (1024 * sizeof(WCHAR) < InputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER; /* disallow very long paths */
|
||||
|
||||
FspFsvrtDeviceLockMount(FsvrtDeviceObject);
|
||||
|
||||
if (0 < InputBufferLength)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
PWCHAR MountPointBuf = Irp->AssociatedIrp.SystemBuffer;
|
||||
UNICODE_STRING RegPath;
|
||||
UNICODE_STRING RegName;
|
||||
union
|
||||
{
|
||||
KEY_VALUE_PARTIAL_INFORMATION V;
|
||||
UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
|
||||
} RegValue;
|
||||
ULONG RegLength;
|
||||
BOOLEAN Persistent = FALSE;
|
||||
|
||||
if (!(
|
||||
2 * sizeof(WCHAR) <= InputBufferLength &&
|
||||
(
|
||||
(L'A' <= MountPointBuf[0] && MountPointBuf[0] <= L'Z') ||
|
||||
(L'a' <= MountPointBuf[0] && MountPointBuf[0] <= L'z')
|
||||
) &&
|
||||
L':' == MountPointBuf[1]
|
||||
))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&RegPath, L"" FSP_REGKEY);
|
||||
RtlInitUnicodeString(&RegName, L"MountUseMountmgrFromFSD");
|
||||
RegLength = sizeof RegValue;
|
||||
Result = FspRegistryGetValue(&RegPath, &RegName, &RegValue.V, &RegLength);
|
||||
if (!NT_SUCCESS(Result) || REG_DWORD != RegValue.V.Type || 1 != *(PULONG)&RegValue.V.Data)
|
||||
{
|
||||
Result = STATUS_ACCESS_DENIED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (STATUS_TOO_LATE != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
FsvrtDeviceExtension->MountPoint.Buffer = FspAllocNonPaged(InputBufferLength);
|
||||
if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
FsvrtDeviceExtension->MountPoint.Length =
|
||||
FsvrtDeviceExtension->MountPoint.MaximumLength = (USHORT)InputBufferLength;
|
||||
RtlCopyMemory(FsvrtDeviceExtension->MountPoint.Buffer, MountPointBuf, InputBufferLength);
|
||||
|
||||
if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
|
||||
Result = FspMountmgrCreateDrive(
|
||||
&FsvrtDeviceExtension->VolumeName,
|
||||
&FsvrtDeviceExtension->UniqueId,
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
else
|
||||
Result = FspMountmgrNotifyCreateDirectory(
|
||||
&FsvrtDeviceExtension->VolumeName,
|
||||
&FsvrtDeviceExtension->UniqueId,
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||
FsvrtDeviceExtension->MountPoint.Buffer = 0;
|
||||
FsvrtDeviceExtension->MountPoint.Length =
|
||||
FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
|
||||
if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
|
||||
Result = FspMountmgrDeleteDrive(
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
else
|
||||
Result = FspMountmgrNotifyDeleteDirectory(
|
||||
&FsvrtDeviceExtension->VolumeName,
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
/* ignore Result */
|
||||
|
||||
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||
FsvrtDeviceExtension->MountPoint.Buffer = 0;
|
||||
FsvrtDeviceExtension->MountPoint.Length =
|
||||
FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
exit:
|
||||
FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFOzCCAyOgAwIBAgIKYSBNtAAAAAAAJzANBgkqhkiG9w0BAQUFADB/MQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
|
||||
MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv
|
||||
ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUxOTQ1MzNaFw0yMTA0
|
||||
MTUxOTU1MzNaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
|
||||
GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhp
|
||||
Z2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD1ZQ0Z6IKHLBfaaZAscS3
|
||||
so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80ltcZF+Y7arpl/DpIT4T2JR
|
||||
vvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46OFBbdzEbjbPHJEWap6xt
|
||||
ABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZdHFMsfpjNGgYWpGhz0DQE
|
||||
E1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdmt4i3ePLKCqg4qwpkwr9m
|
||||
XZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjgcswgcgwEQYDVR0gBAowCDAG
|
||||
BgRVHSAAMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSx
|
||||
PsNpA/i/RwHUmCYaCALvY2QrwzAfBgNVHSMEGDAWgBRi+wohW39DbhHaCVRQa/XS
|
||||
lnHxnjBVBgNVHR8ETjBMMEqgSKBGhkRodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
|
||||
cGtpL2NybC9wcm9kdWN0cy9NaWNyb3NvZnRDb2RlVmVyaWZSb290LmNybDANBgkq
|
||||
hkiG9w0BAQUFAAOCAgEAIIzBWe1vnGstwUo+dR1FTEFQHL2A6tmwkosGKhM/Uxae
|
||||
VjlqimO2eCR59X24uUehCpbC9su9omafBuGs0nkJDv083KwCDHCvPxvseH7U60sF
|
||||
YCbZc2GRIe2waGPglxKrb6AS7dmf0tonPLPkVvnR1IEPcb1CfKaJ3M3VvZWiq/GT
|
||||
EX3orDEpqF1mcEGd/HXJ1bMaOSrQhQVQi6yRysSTy3GlnaSUb1gM+m4gxAgxtYWd
|
||||
foH50j3KWxiFbAqG7CIJG6V0NE9/KLyVSqsdtpiwXQmkd3Z+76eOXYT2GCTL0W2m
|
||||
w6GcwhB1gP+dMv3mz0M6gvfOj+FyKptit1/tlRo5XC+UbUi3AV8zL7vcLXM0iQRC
|
||||
ChyLefmj+hfv+qEaEN/gssGV61wMBZc7NT4YiE3bbL8kiY3Ivdifezk6JKDV39Hz
|
||||
ShqX9qZveh+wkKmzrAE5kdNht2TxPlc4A6/OetK1kPWu3DmZ1bY8l+2myxbHfWsq
|
||||
TJCU5kxU/R7NIOzOaJyHWOlhYL7rDsnVGX2f6Xi9DqwhdQePqW7gjGoqa5zj52W8
|
||||
vC08bdwE3GdFNjKvBIG8qABuYUyVxVzUjo6fL8EydL29EWUDB83vt14CV9qG1Boo
|
||||
NK+ISbLPpd2CVm9oqhTiWVT+/+ru7+qScCJggeMlI8CfzA9JsjWqWMM6w9kWlBA=
|
||||
-----END CERTIFICATE-----
|
BIN
tools/DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer
Normal file
BIN
tools/DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer
Normal file
Binary file not shown.
@ -7,7 +7,8 @@ set Config=Debug
|
||||
set Suffix=x64
|
||||
set Deploy=C:\Deploy\winfsp
|
||||
set Target=Win10DBG
|
||||
set Chkpnt=winfsp
|
||||
set Chkpnt=docker+winfsp
|
||||
set CImage=mcr.microsoft.com/windows/servercore:1909
|
||||
if not X%1==X set Target=%1
|
||||
if not X%2==X set Chkpnt=%2
|
||||
|
||||
@ -15,6 +16,10 @@ if not X%2==X set Chkpnt=%2
|
||||
echo regsvr32 /s winfsp-x64.dll
|
||||
) > %~dp0..\build\VStudio\build\%Config%\deploy-setup.bat
|
||||
|
||||
(
|
||||
echo docker run -it --rm --isolation=process -v%Deploy%:%Deploy%:RW %CImage% cmd.exe /k cd %Deploy%
|
||||
) > %~dp0..\build\VStudio\build\%Config%\docker-run.bat
|
||||
|
||||
set Files=
|
||||
for %%f in (
|
||||
%~dp0..\build\VStudio\build\%Config%\
|
||||
@ -23,6 +28,7 @@ for %%f in (
|
||||
winfsp-tests-%Suffix%.exe
|
||||
memfs-%Suffix%.exe
|
||||
deploy-setup.bat
|
||||
docker-run.bat
|
||||
) do (
|
||||
set File=%%~f
|
||||
if [!File:~-1!] == [\] (
|
||||
|
341
tools/make-release.ps1
Normal file
341
tools/make-release.ps1
Normal file
@ -0,0 +1,341 @@
|
||||
param (
|
||||
[string]$StateFile = "release.state"
|
||||
)
|
||||
|
||||
function Write-Stdout ($Message) {
|
||||
[System.Console]::WriteLine($Message)
|
||||
}
|
||||
|
||||
function Write-Stderr ($Message) {
|
||||
[System.Console]::Error.WriteLine($Message)
|
||||
}
|
||||
|
||||
function Git-Describe {
|
||||
$GitDesc = git describe --long --dirty
|
||||
if ($GitDesc -match "^(.+)-([0-9]+)-g([0-9A-Fa-f]+)-?(dirty)?$") {
|
||||
$matches[1]
|
||||
$matches[2]
|
||||
$matches[3]
|
||||
$matches[4]
|
||||
}
|
||||
}
|
||||
|
||||
function Git-Dirty {
|
||||
$Dirty = $False
|
||||
git status --porcelain=v2 2>$null | ForEach-Object {
|
||||
$Dirty = $True
|
||||
}
|
||||
return $Dirty
|
||||
}
|
||||
|
||||
function Git-LogGrep ($Tag) {
|
||||
git log -n 1 --grep $Tag
|
||||
}
|
||||
|
||||
function Get-ReleaseInfo ($Tag) {
|
||||
$Found = 0
|
||||
$ReleaseInfo = [PSCustomObject]@{
|
||||
Tag = ""
|
||||
ProductVersion = ""
|
||||
Prerelease = $False
|
||||
PreviousTag = ""
|
||||
PreviousProductVersion = ""
|
||||
Text = @()
|
||||
}
|
||||
foreach ($Line in Get-Content "$ProjectRoot\Changelog.md") {
|
||||
if ($Line -match "^## (v[^ ]+) *\(([^)]+)\)") {
|
||||
if ($Found) {
|
||||
$Found = 2
|
||||
$PreviousTag = $matches[1]
|
||||
$PreviousProductVersion = $matches[2]
|
||||
if ($PreviousTag -match "^v[0-9.]+$") {
|
||||
$ReleaseInfo.PreviousTag = $PreviousTag
|
||||
$ReleaseInfo.PreviousProductVersion = $PreviousProductVersion
|
||||
break
|
||||
}
|
||||
} elseif ($Tag -eq $matches[1]) {
|
||||
$Found = 1
|
||||
$ReleaseInfo.Tag = $matches[1]
|
||||
$ReleaseInfo.ProductVersion = $matches[2]
|
||||
$ReleaseInfo.Prerelease = !($ReleaseInfo.Tag -match "^v[0-9.]+$")
|
||||
}
|
||||
} elseif (1 -eq $Found) {
|
||||
$ReleaseInfo.Text += $Line
|
||||
}
|
||||
}
|
||||
if ($Found) {
|
||||
return $ReleaseInfo
|
||||
}
|
||||
}
|
||||
|
||||
function Get-FileVersion ($FileName) {
|
||||
return [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FileName).FileVersion
|
||||
}
|
||||
|
||||
function Task ($ScriptBlock) {
|
||||
$Name = (Get-PSCallStack)[1].FunctionName
|
||||
if ($State -contains $Name) {
|
||||
return
|
||||
}
|
||||
|
||||
Write-Stdout $Name
|
||||
Invoke-Command -ScriptBlock $ScriptBlock
|
||||
Write-Stdout "$Name COMPLETE"
|
||||
|
||||
Add-Content $StateFile -Value $Name
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
function Check-Prerequisites {
|
||||
$Name = (Get-PSCallStack)[0].FunctionName
|
||||
|
||||
# check git.exe
|
||||
if (!(Get-Command "git.exe" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find git.exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check gh.exe
|
||||
if (!(Get-Command "gh.exe" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find gh.exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check choco.exe
|
||||
if (!(Get-Command "choco.exe" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find choco.exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check git tag
|
||||
$Tag, $CommitCount, $Commit, $_ = Git-Describe
|
||||
if ("0" -ne $CommitCount) {
|
||||
Write-Stderr "error: cannot find clean git tag"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check release info
|
||||
$script:ReleaseInfo = Get-ReleaseInfo $Tag
|
||||
if (!$script:ReleaseInfo) {
|
||||
Write-Stderr "error: cannot get release info for tag $Tag"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp.sym
|
||||
if (!(Test-Path "$ProjectRoot\..\winfsp.sym" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp.sym repository"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp.sym git status
|
||||
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||
$SymDirty = Git-Dirty
|
||||
Pop-Location
|
||||
if ($SymDirty) {
|
||||
Write-Stderr "error: winfsp.sym repository is dirty"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($State -contains $Name) {
|
||||
if (!($State -contains "$Tag-$CommitCount-g$Commit")) {
|
||||
Write-Stderr "error: invalid state for tag $Tag"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Add-Content $StateFile -Value $Name
|
||||
Add-Content $StateFile -Value "$Tag-$CommitCount-g$Commit"
|
||||
}
|
||||
}
|
||||
|
||||
function Check-Assets {
|
||||
# check winfsp.msi
|
||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp*.msi"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp-tests.zip
|
||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp-tests*.zip" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp-tests*.zip"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp.nupkg
|
||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.nupkg" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp*.nupkg"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp signature
|
||||
if ("Valid" -ne (Get-AuthenticodeSignature "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys" -ErrorAction SilentlyContinue).Status) {
|
||||
Write-Stderr "error: invalid winfsp signature"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
function Build-AssetsPhase1 {
|
||||
Task -ScriptBlock {
|
||||
Push-Location "$ProjectRoot"
|
||||
tools\build.bat Release
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot build assets"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Upload file driver.cab to Microsoft Partner Center for attestation signing.
|
||||
When the file has been signed, download and extract to ~\Downloads\drivers
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function Build-AssetsPhase2 {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
# check signed drivers folder
|
||||
if (!(Test-Path ~\Downloads\drivers -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find ~\Downloads\drivers"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$SignedPackage = Resolve-Path ~\Downloads\drivers
|
||||
|
||||
$VerX64 = Get-FileVersion "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys"
|
||||
if ($VerX64 -ne (Get-FileVersion "$SignedPackage\x64\winfsp-x64.sys")) {
|
||||
Write-Stderr "error: incompatible versions in ~\Downloads\drivers"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Push-Location "$ProjectRoot"
|
||||
tools\build.bat Release $SignedPackage
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot build assets"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Assets have been built and signed. You may want to perform some smoke testing.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function Make-GitHubRelease {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
if ((Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi") -match "\\winfsp-(.+)\.msi") {
|
||||
$Version = $matches[1]
|
||||
}
|
||||
|
||||
$DownloadColor = "blue"
|
||||
$PrereleaseOpt = ""
|
||||
if ($ReleaseInfo.Prerelease) {
|
||||
$DownloadColor = "e52e4b"
|
||||
$PrereleaseOpt = "-p"
|
||||
}
|
||||
|
||||
$ReleaseNotes = @"
|
||||
[](https://github.com/billziss-gh/winfsp/releases/download/$($ReleaseInfo.Tag)/winfsp-$Version.msi)
|
||||
|
||||
[VirusTotal Scan Results]()
|
||||
|
||||
## CHANGES SINCE WINFSP $($ReleaseInfo.PreviousProductVersion)
|
||||
$($ReleaseInfo.Text -join "`n")
|
||||
"@
|
||||
|
||||
gh release create $ReleaseInfo.Tag --draft --title "WinFsp $($ReleaseInfo.ProductVersion)" --notes "$ReleaseNotes" $PrereleaseOpt (Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi") (Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp-tests*.zip")
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot create GitHub release"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Draft GitHub release for tag $($ReleaseInfo.Tag) has been created.
|
||||
Publish the release on GitHub and update the VirusTotal link.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function Upload-Symbols {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
# check winfsp.sym git log
|
||||
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||
$SymHasTag = Git-LogGrep $ReleaseInfo.Tag
|
||||
Pop-Location
|
||||
if ($SymHasTag) {
|
||||
Write-Stderr "warning: winfsp.sym repository already has commit for tag $($ReleaseInfo.Tag)"
|
||||
} else {
|
||||
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||
.\tools\symadd.ps1 ..\winfsp\build\VStudio\build\Release -PdbKind Private
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot add files to winfsp.sym repository"
|
||||
exit 1
|
||||
}
|
||||
git add .
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot add files to winfsp.sym repository staging area"
|
||||
exit 1
|
||||
}
|
||||
git commit -m $ReleaseInfo.Tag
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot commit files to winfsp.sym repository"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Commit for $($ReleaseInfo.Tag) symbols has been created.
|
||||
Push the winfsp.sym repository to GitHub.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Make-ChocoRelease {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
Push-Location "$ProjectRoot\build\VStudio\build\Release"
|
||||
choco push
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot push to Chocolatey"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Chocolatey release for $($ReleaseInfo.Tag) has been pushed.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
$ProjectRoot = Split-Path $PSScriptRoot
|
||||
$StateFile = Join-Path $pwd $StateFile
|
||||
|
||||
Write-Stdout "Using state file $StateFile"
|
||||
$State = @(Get-Content $StateFile -ErrorAction Ignore)
|
||||
|
||||
Check-Prerequisites
|
||||
|
||||
# Workflow tasks
|
||||
Build-AssetsPhase1
|
||||
Build-AssetsPhase2
|
||||
Make-GitHubRelease
|
||||
Upload-Symbols
|
||||
Make-ChocoRelease
|
@ -36,6 +36,10 @@ set dfl_tests=^
|
||||
winfsp-tests-x64-mountpoint-drive ^
|
||||
winfsp-tests-x64-mountpoint-dir ^
|
||||
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
||||
winfsp-tests-x64-mountmgr-drive ^
|
||||
winfsp-tests-x64-mountmgr-dir ^
|
||||
winfsp-tests-x64-mountmgrfsd-drive ^
|
||||
winfsp-tests-x64-mountmgrfsd-dir ^
|
||||
winfsp-tests-x64-no-traverse ^
|
||||
winfsp-tests-x64-oplock ^
|
||||
winfsp-tests-x64-notify ^
|
||||
@ -43,28 +47,32 @@ set dfl_tests=^
|
||||
winfsp-tests-x64-external-share ^
|
||||
memfs-x64-disk-fsx ^
|
||||
memfs-x64-net-fsx ^
|
||||
memfs-x64-disk-standby ^
|
||||
memfs-x64-net-standby ^
|
||||
RETIRED-memfs-x64-disk-standby ^
|
||||
RETIRED-memfs-x64-net-standby ^
|
||||
memfs-x64-net-use ^
|
||||
memfs-x64-disk-winfstest ^
|
||||
memfs-x64-net-winfstest ^
|
||||
fscrash-x64 ^
|
||||
winfsp-tests-x86 ^
|
||||
winfsp-tests-x86-case-randomize ^
|
||||
winfsp-tests-x86-flushpurge ^
|
||||
winfsp-tests-x86-legacy-unlink-rename ^
|
||||
winfsp-tests-x86-mountpoint-drive ^
|
||||
winfsp-tests-x86-mountpoint-dir ^
|
||||
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||
winfsp-tests-x86-no-traverse ^
|
||||
winfsp-tests-x86-oplock ^
|
||||
winfsp-tests-x86-notify ^
|
||||
RETIRED-winfsp-tests-x86-case-randomize ^
|
||||
RETIRED-winfsp-tests-x86-flushpurge ^
|
||||
RETIRED-winfsp-tests-x86-legacy-unlink-rename ^
|
||||
RETIRED-winfsp-tests-x86-mountpoint-drive ^
|
||||
RETIRED-winfsp-tests-x86-mountpoint-dir ^
|
||||
RETIRED-winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||
RETIRED-winfsp-tests-x86-mountmgr-drive ^
|
||||
RETIRED-winfsp-tests-x86-mountmgr-dir ^
|
||||
RETIRED-winfsp-tests-x86-mountmgrfsd-drive ^
|
||||
RETIRED-winfsp-tests-x86-mountmgrfsd-dir ^
|
||||
RETIRED-winfsp-tests-x86-no-traverse ^
|
||||
RETIRED-winfsp-tests-x86-oplock ^
|
||||
RETIRED-winfsp-tests-x86-notify ^
|
||||
winfsp-tests-x86-external ^
|
||||
winfsp-tests-x86-external-share ^
|
||||
memfs-x86-disk-fsx ^
|
||||
memfs-x86-net-fsx ^
|
||||
memfs-x86-disk-standby ^
|
||||
memfs-x86-net-standby ^
|
||||
RETIRED-memfs-x86-disk-standby ^
|
||||
RETIRED-memfs-x86-net-standby ^
|
||||
memfs-x86-net-use ^
|
||||
memfs-x86-disk-winfstest ^
|
||||
memfs-x86-net-winfstest ^
|
||||
@ -115,19 +123,24 @@ set opt_tests=^
|
||||
|
||||
set tests=
|
||||
for %%f in (%dfl_tests%) do (
|
||||
if X%2==X (
|
||||
set tests=!tests! %%f
|
||||
) else (
|
||||
set test=%%f
|
||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||
set test=%%f
|
||||
if NOT "XRETIRED-!test:RETIRED-=!"=="X!test!" (
|
||||
if X%2==X (
|
||||
set tests=!tests! %%f
|
||||
) else (
|
||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||
)
|
||||
)
|
||||
)
|
||||
for %%f in (%opt_tests%) do (
|
||||
if X%2==X (
|
||||
rem
|
||||
) else (
|
||||
set test=%%f
|
||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||
set test=%%f
|
||||
if NOT "XRETIRED-!test:RETIRED-=!"=="X!test!" (
|
||||
if X%2==X (
|
||||
rem
|
||||
) else (
|
||||
set test=%%f
|
||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@ -151,11 +164,12 @@ for %%f in (%tests%) do (
|
||||
set "endtimecalc=!endtime:%time:~8,1%=%%100)*100+1!" & set "begtimecalc=!begtime:%time:~8,1%=%%100)*100+1!"
|
||||
set /A "duration=((((10!endtimecalc:%time:~2,1%=%%100)*60+1!%%100)-((((10!begtimecalc:%time:~2,1%=%%100)*60+1!%%100), duration-=(duration>>31)*24*60*60*100"
|
||||
set /A "duration=10*duration"
|
||||
set /A "durationSec=duration/1000"
|
||||
|
||||
if !ERRORLEVEL_save! neq 0 (
|
||||
set /a testfail=testfail+1
|
||||
|
||||
echo === Failed %%f ^(!duration! ms^)
|
||||
echo === Failed %%f ^(!durationSec!s^)
|
||||
|
||||
if defined APPVEYOR (
|
||||
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Failed -Duration !duration!
|
||||
@ -163,7 +177,7 @@ for %%f in (%tests%) do (
|
||||
) else (
|
||||
set /a testpass=testpass+1
|
||||
|
||||
echo === Passed %%f ^(!duration! ms^)
|
||||
echo === Passed %%f ^(!durationSec!s^)
|
||||
|
||||
if defined APPVEYOR (
|
||||
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Passed -Duration !duration!
|
||||
@ -232,6 +246,30 @@ winfsp-tests-x64 --mountpoint=mymnt * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgr-drive
|
||||
winfsp-tests-x64 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgr-dir
|
||||
winfsp-tests-x64 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgrfsd-drive
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x64 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgrfsd-dir
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x64 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-no-traverse
|
||||
winfsp-tests-x64 --no-traverse * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
@ -282,6 +320,30 @@ winfsp-tests-x86 --mountpoint=mymnt * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgr-drive
|
||||
winfsp-tests-x86 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgr-dir
|
||||
winfsp-tests-x86 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgrfsd-drive
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x86 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgrfsd-dir
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x86 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-no-traverse
|
||||
winfsp-tests-x86 --no-traverse * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
|
@ -62,7 +62,8 @@ static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo
|
||||
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
||||
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
||||
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
||||
FileInfo->IndexNumber = 0;
|
||||
FileInfo->IndexNumber =
|
||||
((UINT64)ByHandleFileInfo.nFileIndexHigh << 32) | (UINT64)ByHandleFileInfo.nFileIndexLow;
|
||||
FileInfo->HardLinks = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -67,6 +67,9 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
||||
Result = MemfsStart(Memfs);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspFsctlTransact(MemfsFileSystem(Memfs)->VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
memfs_running = 1;
|
||||
memfs_handle = MemfsFileSystem(Memfs)->VolumeHandle;
|
||||
|
||||
|
@ -215,6 +215,9 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||
|
||||
Result = FspFsctlTransact(VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
|
||||
Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_transact_dotest_thread, FilePath, 0, 0);
|
||||
@ -246,6 +249,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 != Request->Hint);
|
||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
||||
/* since we made RejectIrpPriorToTransact0 mandatory the assertions below do not hold */
|
||||
#if 0
|
||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
{
|
||||
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
||||
@ -265,6 +270,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size);
|
||||
ASSERT(0 == mywcscmp((PVOID)Request->Buffer, -1, L"\\file0", -1));
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd));
|
||||
|
||||
@ -294,7 +300,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
GetExitCodeThread(Thread, &ExitCode);
|
||||
CloseHandle(Thread);
|
||||
|
||||
ASSERT(ERROR_ACCESS_DENIED == ExitCode || ERROR_OPERATION_ABORTED == ExitCode);
|
||||
ASSERT(0 != ExitCode);
|
||||
//ASSERT(ERROR_ACCESS_DENIED == ExitCode || ERROR_OPERATION_ABORTED == ExitCode);
|
||||
}
|
||||
|
||||
void mount_volume_transact_test(void)
|
||||
|
@ -158,7 +158,10 @@ static void posix_map_sid_test(void)
|
||||
|
||||
CloseHandle(Token);
|
||||
|
||||
for (size_t i = 0; sizeof map / sizeof map[0] > i; i++)
|
||||
size_t n = sizeof map / sizeof map[0];
|
||||
if (RunningInContainer)
|
||||
n -= 2; /* container: disable tests for "user manager\containeradministrator" */
|
||||
for (size_t i = 0; n > i; i++)
|
||||
{
|
||||
Success = ConvertStringSidToSidW(map[i].SidStr, &Sid0);
|
||||
ASSERT(Success);
|
||||
|
@ -187,6 +187,8 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||
|
||||
Result = FspFsctlTransact(VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 RequestBuf[FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN];
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 ResponseBuf[FSP_FSCTL_TRANSACT_RSP_SIZEMAX];
|
||||
@ -223,6 +225,8 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 != Request->Hint);
|
||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
||||
/* since we made RejectIrpPriorToTransact0 mandatory the assertions below do not hold */
|
||||
#if 0
|
||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
{
|
||||
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
||||
@ -239,6 +243,7 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(!Request->Req.Create.OpenTargetDirectory);
|
||||
ASSERT(!Request->Req.Create.CaseSensitive);
|
||||
}
|
||||
#endif
|
||||
|
||||
ResponseBufSize = 0;
|
||||
RequestBufSize = sizeof RequestBuf;
|
||||
|
@ -89,7 +89,7 @@ static void volpath_test(void)
|
||||
* when *not* using the MountManager and therefore disable
|
||||
* this test when using a non-MountManager mount point.
|
||||
*/
|
||||
if (!NtfsTests && !OptMountPoint)
|
||||
if (NtfsTests || OptMountPoint)
|
||||
return;
|
||||
|
||||
if (WinFspDiskTests)
|
||||
@ -107,8 +107,15 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
BOOLEAN Success, VolumePathNameSuccess[8];
|
||||
WCHAR FilePath[MAX_PATH];
|
||||
WCHAR VolumePathName[MAX_PATH], VolumeName[MAX_PATH];
|
||||
WCHAR FinalPath[MAX_PATH];
|
||||
DWORD FinalResult;
|
||||
|
||||
Result = FspFileSystemSetMountPoint(MemfsFileSystem(memfs), MountPoint);
|
||||
if (STATUS_ACCESS_DENIED == Result)
|
||||
{
|
||||
FspDebugLog(__FUNCTION__ ": need Administrator\n");
|
||||
goto exit;
|
||||
}
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Prefix = FspFileSystemMountPoint(MemfsFileSystem(memfs));
|
||||
@ -125,6 +132,9 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
FinalResult = GetFinalPathNameByHandleW(
|
||||
Handle, FinalPath, MAX_PATH - 1, VOLUME_NAME_DOS | FILE_NAME_OPENED);
|
||||
ASSERT(0 != FinalResult && FinalResult < MAX_PATH);
|
||||
CloseHandle(Handle);
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||
@ -187,6 +197,9 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
FinalResult = GetFinalPathNameByHandleW(
|
||||
Handle, FinalPath, MAX_PATH - 1, VOLUME_NAME_DOS | FILE_NAME_OPENED);
|
||||
ASSERT(0 != FinalResult && FinalResult < MAX_PATH);
|
||||
CloseHandle(Handle);
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||
@ -232,6 +245,7 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
ASSERT(VolumePathNameSuccess[6]);
|
||||
}
|
||||
|
||||
exit:
|
||||
memfs_stop(memfs);
|
||||
}
|
||||
|
||||
@ -240,8 +254,13 @@ static void volpath_mount_test(void)
|
||||
/*
|
||||
* This test does FspFileSystemSetMountPoint and therefore
|
||||
* cannot be used with --external or --mountpoint.
|
||||
*
|
||||
* Also the MountMgr appears to be buggy and fail with spurious
|
||||
* STATUS_NOT_SUPPORTED and STATUS_INVALID_PARAMETER error codes
|
||||
* under Windows Containers (at least with ServerCore 1909). So
|
||||
* disable if RunningInContainer.
|
||||
*/
|
||||
if (NtfsTests || OptMountPoint)
|
||||
if (NtfsTests || OptMountPoint || RunningInContainer)
|
||||
return;
|
||||
|
||||
if (WinFspDiskTests)
|
||||
@ -270,6 +289,24 @@ static void volpath_mount_test(void)
|
||||
|
||||
//volpath_mount_dotest(MemfsDisk, 0, 0);
|
||||
volpath_mount_dotest(MemfsDisk, 0, MountPoint);
|
||||
|
||||
WCHAR DirBuf[MAX_PATH];
|
||||
int DirBufLen;
|
||||
GetTestDirectory(DirBuf);
|
||||
ASSERT(
|
||||
L'\\' == DirBuf[0] &&
|
||||
L'\\' == DirBuf[1] &&
|
||||
L'?' == DirBuf[2] &&
|
||||
L'\\' == DirBuf[3]);
|
||||
DirBuf[2] = '.';
|
||||
DirBufLen = lstrlenW(DirBuf);
|
||||
ASSERT(MAX_PATH >= DirBufLen + 5);
|
||||
DirBuf[DirBufLen++] = L'\\';
|
||||
DirBuf[DirBufLen++] = L'm';
|
||||
DirBuf[DirBufLen++] = L'n';
|
||||
DirBuf[DirBufLen++] = L't';
|
||||
DirBuf[DirBufLen++] = L'\0';
|
||||
volpath_mount_dotest(MemfsDisk, 0, DirBuf);
|
||||
}
|
||||
if (WinFspNetTests)
|
||||
{
|
||||
@ -290,7 +327,12 @@ void volpath_tests(void)
|
||||
/*
|
||||
* This test does FspFileSystemSetMountPoint and therefore
|
||||
* cannot be used with --external or --mountpoint.
|
||||
*
|
||||
* Also the MountMgr appears to be buggy and fail with spurious
|
||||
* STATUS_NOT_SUPPORTED and STATUS_INVALID_PARAMETER error codes
|
||||
* under Windows Containers (at least with ServerCore 1909). So
|
||||
* disable if RunningInContainer.
|
||||
*/
|
||||
if (!NtfsTests && !OptMountPoint)
|
||||
if (!NtfsTests && !OptMountPoint && !RunningInContainer)
|
||||
TEST(volpath_mount_test);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
int NtfsTests = 0;
|
||||
int WinFspDiskTests = 1;
|
||||
int WinFspNetTests = 1;
|
||||
int RunningInContainer = 0;
|
||||
|
||||
BOOLEAN OptExternal = FALSE;
|
||||
BOOLEAN OptFuseExternal = FALSE;
|
||||
@ -258,6 +259,12 @@ int main(int argc, char *argv[])
|
||||
if (0 == getenv("WINFSP_TESTS_EXCEPTION_FILTER_DISABLE"))
|
||||
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
||||
|
||||
RunningInContainer = ERROR_SUCCESS == RegGetValueW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
||||
L"ContainerType",
|
||||
RRF_RT_REG_DWORD, 0,
|
||||
0, 0);
|
||||
|
||||
for (int argi = 1; argc > argi; argi++)
|
||||
{
|
||||
const char *a = argv[argi];
|
||||
@ -266,6 +273,7 @@ int main(int argc, char *argv[])
|
||||
if (0 == strcmp("--ntfs", a) || 0 == strcmp("--external", a))
|
||||
{
|
||||
OptExternal = TRUE;
|
||||
OptFuseExternal = FALSE;
|
||||
NtfsTests = 1;
|
||||
WinFspDiskTests = 0;
|
||||
WinFspNetTests = 0;
|
||||
@ -404,6 +412,10 @@ int main(int argc, char *argv[])
|
||||
if (!NtfsTests && OptShareName)
|
||||
ABORT("option --share requires --ntfs/--external");
|
||||
|
||||
if (RunningInContainer)
|
||||
/* container: disable network file system tests */
|
||||
WinFspNetTests = 0;
|
||||
|
||||
DisableBackupRestorePrivileges();
|
||||
|
||||
AddNetShareIfNeeded();
|
||||
|
@ -213,6 +213,7 @@ VOID GetTestDirectoryEx(PWSTR DirBuf, ULONG DirBufSize, PWSTR DriveBuf);
|
||||
extern int NtfsTests;
|
||||
extern int WinFspDiskTests;
|
||||
extern int WinFspNetTests;
|
||||
extern int RunningInContainer;
|
||||
|
||||
extern BOOLEAN OptExternal;
|
||||
extern BOOLEAN OptFuseExternal;
|
||||
|
Reference in New Issue
Block a user