mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
144 Commits
Author | SHA1 | Date | |
---|---|---|---|
04cf0e04ba | |||
f51af55fb3 | |||
f9a2780311 | |||
43101dfe06 | |||
ac5ed1c238 | |||
03f0d2bd1a | |||
77c18fc59e | |||
77cf7f7398 | |||
c61da81475 | |||
a1b92d9095 | |||
ae8e4e61f7 | |||
e5c424dba1 | |||
554f07a50e | |||
bd53b452b2 | |||
82cea37036 | |||
2fcc065421 | |||
bf53c00f38 | |||
ec4197d8b7 | |||
897a08700b | |||
1ace7ffb41 | |||
d7c0657c3d | |||
5d73687de8 | |||
a5bfdcf416 | |||
b609435dad | |||
523ccbea02 | |||
cf699ba441 | |||
0d819eb800 | |||
4a653a8bc0 | |||
6932d42039 | |||
77fb2cc1c1 | |||
500dfe1958 | |||
1b40d8db80 | |||
307e18fb0d | |||
461266382a | |||
a809b0787e | |||
ea5e031af2 | |||
558487cd22 | |||
2ff21529d5 | |||
d43c0c2c85 | |||
eb0f03b17b | |||
575fe55eb8 | |||
b537c61f3b | |||
5cd40ff7ff | |||
753440e837 | |||
9b79bb24ca | |||
931d201527 | |||
ab3f3d2827 | |||
3dc09b2496 | |||
27d03d4323 | |||
ad1b53e5a4 | |||
e4077c92e9 | |||
e3290a30bc | |||
09309f858c | |||
12baaa6d50 | |||
c584782bc7 | |||
9c4a361c48 | |||
c1f4606683 | |||
f79db6a3db | |||
9a9a73d4d8 | |||
a56caf3f94 | |||
9b8b3e9cb8 | |||
5a8aad60b3 | |||
1906772aa2 | |||
ce924d737c | |||
aa50d5a8b9 | |||
6ffddf36b5 | |||
ee4145e947 | |||
fd817e37c9 | |||
2056766b4f | |||
c73f7099b7 | |||
3513f0da5f | |||
c9c62b1831 | |||
8422e8121c | |||
88516f371a | |||
916b4f5c3d | |||
a7424c911b | |||
fb8cb8aca9 | |||
d0f5ea69a2 | |||
fbb81b0463 | |||
14a2004437 | |||
d491031fda | |||
75a3d97c62 | |||
5f325304d3 | |||
8727497662 | |||
a2ed9f2b1a | |||
fdaf1da778 | |||
1123e7b0ef | |||
06ee833740 | |||
fbcefe6339 | |||
637a1dac7e | |||
05f622f2de | |||
ef5c947168 | |||
894ae7b8f3 | |||
7aadf259d9 | |||
d54e9a3049 | |||
7d56b9c23d | |||
deb237f7b0 | |||
5ae0804bd2 | |||
382599e38f | |||
498ab91123 | |||
c2f87029d7 | |||
157c4bc09a | |||
4fcaa99d63 | |||
d6c3849120 | |||
ec39d4b888 | |||
ebc8c268e5 | |||
9501b5771d | |||
5d34a3bd8c | |||
5b72b4ad4a | |||
740411d604 | |||
5c3549c6eb | |||
9f56a21c7f | |||
2e7e95df76 | |||
b2e6c16ba0 | |||
bd32f54904 | |||
7908ba09ac | |||
5713605030 | |||
994e232fb3 | |||
9553bd52c4 | |||
1cab0f3975 | |||
499a3d1138 | |||
d29218ba69 | |||
5564a9efae | |||
750e72e601 | |||
9f13c6e915 | |||
5005dd6f5b | |||
f9b6fb8817 | |||
6b0b4c8b8e | |||
abb504053b | |||
fb507fc0bc | |||
d38afe8d16 | |||
a4629b8f8b | |||
670a38d549 | |||
b939f6bd2b | |||
3df27f5b28 | |||
7581cece81 | |||
b4f5707e4e | |||
309827860f | |||
2b6b049f86 | |||
77f3e064a2 | |||
f691a7a3c7 | |||
cc58668ce5 | |||
064d0b94f2 | |||
a48668149b |
12
.github/ISSUE_TEMPLATE.md
vendored
12
.github/ISSUE_TEMPLATE.md
vendored
@ -1,12 +0,0 @@
|
||||
(Enter your issue here.)
|
||||
|
||||
----
|
||||
|
||||
Before submitting this issue please review this checklist. Ideally all checkmarks should be checked upon submitting. (Use an x inside square brackets like so: [x])
|
||||
|
||||
- [ ] **Issue type**: Please consider posting only bug reports or enhancement requests. Questions are better in the [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp).
|
||||
- [ ] **No Duplicate**: Ensure that your issue has not been filed before. (Check open and closed issues.)
|
||||
- [ ] **Description**: Provide a descriptive title and a detailed explanation of the problem you are experiencing (for a bug report) or you are trying to solve (for an enhancement request).
|
||||
- [ ] **Reproduce**: For bug reports provide detailed information on how to reproduce the problem. For enhancement requests you do not need to provide this information, unless you find it relevant.
|
||||
- [ ] **Behaviors**: Provide information on the expected and actual behaviors.
|
||||
- [ ] **Environment**: For bug reports provide information about your OS version and build (e.g. 10.0.14393) and WinFsp version and build (e.g. 2017.2 or 1.2.17341). For enhancement requests you do not need to provide this information, unless you find it relevant.
|
21
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: File a bug report.
|
||||
---
|
||||
|
||||
## Bug Report
|
||||
|
||||
_Provide a descriptive title and a detailed explanation of the problem you are experiencing. Ensure that your issue has not been filed before._
|
||||
|
||||
### How to Reproduce
|
||||
|
||||
_Provide detailed information on how to reproduce the problem._
|
||||
|
||||
### Behaviors
|
||||
|
||||
_Provide information on the expected and actual behaviors._
|
||||
|
||||
### Environment
|
||||
|
||||
- OS version and build: _e.g. 10.0.14393_
|
||||
- WinFsp version and build: _e.g. 2017.2 or 1.2.17341_
|
8
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
8
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: Enhancement Request
|
||||
about: File an enhancement request.
|
||||
---
|
||||
|
||||
## Enhancement Request
|
||||
|
||||
_Provide a descriptive title and a detailed explanation of the problem the requested enhancement would solve. Ensure that your issue has not been filed before._
|
8
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
8
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: Question
|
||||
about: Questions are better asked in the WinFsp Google Group. However you may ask a question here.
|
||||
---
|
||||
|
||||
## Question
|
||||
|
||||
_Please consider asking questions in the [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp) instead. Before asking a question please also consult the [WinFsp Frequently Asked Questions](https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions)._
|
@ -1,6 +1,75 @@
|
||||
= Changelog
|
||||
|
||||
|
||||
v1.4B2 (2018.2 B2)::
|
||||
|
||||
Changes since v1.3:
|
||||
|
||||
* FUSE3 API (version 3.2) is now available. The FUSE2 API (version 2.8) also remains supported.
|
||||
* New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API. FUSE `ioctl` is also supported.
|
||||
* `FlushAndPurgeOnCleanup` has now been added to the .NET API. (GitHub PR #176; thanks @FrKaram.)
|
||||
* New sample file system "airfs" contributed by @JohnOberschelp. Airfs is an in-memory file system like Memfs on which it is based on; it has received substantial improvements in how the file name space is maintained and has been modified to use modern C++ techniques by John.
|
||||
* New sample file system "passthrough-fuse3" passes all operations to an underlying file system. This file system is built using the FUSE3 API. It builds and runs on both Windows and Cygwin.
|
||||
* The FUSE layer now supports multiple file systems within a single process. This is a long standing problem that has been fixed. (GitHub issue #135.)
|
||||
|
||||
|
||||
v1.4B1 (2018.2 B1)::
|
||||
|
||||
Changes since v1.3:
|
||||
|
||||
* New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API.
|
||||
|
||||
|
||||
v1.3 (2018.1)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
||||
* Multiple Launcher changes:
|
||||
** New `FspLaunch` API. File systems can be started, stopped, queried and listed using `FspLaunchStart`, `FspLaunchStop`, `FspLaunchGetInfo` and `FspLaunchGetNameList`. The API is available in <winfsp/launch.h>
|
||||
** New Launcher registry settings `RunAs` and `WorkDirectory`. `RunAs` allows the laucher to launch a file system process under the service accounts LocalService and NetworkService. `WorkDirectory` can be used to specify the work directory for a newly launched file system process.
|
||||
* `FSP_FSCTL_VOLUME_PARAMS::FlushAndPurgeOnCleanup` limits the time that Windows keeps files open after an application has closed them. This purges the cache on the last `CloseHandle`, which is a performance drawback.
|
||||
** This is now the default behavior on FUSE. To revert to the previous behavior of keeping files open indefinitely use `-o KeepFileCache`.
|
||||
* `FSP_FSCTL_VOLUME_PARAMS` has been extended with fine-grained timeouts: `VolumeInfoTimeout`, `DirInfoTimeout`, `SecurityTimeout`, `StreamInfoTimeout`. Set `FSP_FSCTL_VOLUME_PARAMS::Version == sizeof(FSP_FSCTL_VOLUME_PARAMS)` to access the new fields.
|
||||
** New FUSE optons `VolumeInfoTimeout`, `DirInfoTimeout` complement the existing `FileInfoTimeout`.
|
||||
* The FSD (File System Driver) and its interaction with the Windows MUP (Multiple UNC Provider) has been changed. In practice this eliminates the delays experienced when right-clicking on a WinFsp-backed network drive in the Windows Explorer. (GitHub issue #87.)
|
||||
* The WinFsp network provider is now added first in the provider order list. Previously it was added last. (GitHub PR #131; thanks @felfert.)
|
||||
* The WinFsp installer now uses the Wix `Provides` dependency extension to provide a `WinFsp` dependency key. (GitHub PR #129; thanks @felfert.)
|
||||
* New FUSE `create_umask` option. (GitHub issue #138.)
|
||||
* Fix C++ compilation error for WinFsp-FUSE. (GitHub PR #154; thanks @benrubson.)
|
||||
|
||||
|
||||
v1.3B3 (2018.1 B3)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
||||
* Multiple Launcher changes:
|
||||
** New `FspLaunch` API. File systems can be started, stopped, queried and listed using `FspLaunchStart`, `FspLaunchStop`, `FspLaunchGetInfo` and `FspLaunchGetNameList`. The API is available in <winfsp/launch.h>
|
||||
** New Launcher registry settings `RunAs` and `WorkDirectory`. `RunAs` allows the laucher to launch a file system process under the service accounts LocalService and NetworkService. `WorkDirectory` can be used to specify the work directory for a newly launched file system process.
|
||||
* `FSP_FSCTL_VOLUME_PARAMS::FlushAndPurgeOnCleanup` limits the time that Windows keeps files open after an application has closed them. This purges the cache on the last `CloseHandle`, which is a performance drawback.
|
||||
** This is now the default behavior on FUSE. To revert to the previous behavior of keeping files open indefinitely use `-o KeepFileCache`.
|
||||
* `FSP_FSCTL_VOLUME_PARAMS` has been extended with fine-grained timeouts: `VolumeInfoTimeout`, `DirInfoTimeout`, `SecurityTimeout`, `StreamInfoTimeout`. Set `FSP_FSCTL_VOLUME_PARAMS::Version == sizeof(FSP_FSCTL_VOLUME_PARAMS)` to access the new fields.
|
||||
** New FUSE optons `VolumeInfoTimeout`, `DirInfoTimeout` complement the existing `FileInfoTimeout`.
|
||||
* The FSD (File System Driver) and its interaction with the Windows MUP (Multiple UNC Provider) has been changed. In practice this eliminates the delays experienced when right-clicking on a WinFsp-backed network drive in the Windows Explorer. (GitHub issue #87.)
|
||||
* The WinFsp network provider is now added first in the provider order list. Previously it was added last. (GitHub PR #131; thanks @felfert.)
|
||||
* The WinFsp installer now uses the Wix `Provides` dependency extension to provide a `WinFsp` dependency key. (GitHub PR #129; thanks @felfert.)
|
||||
* New FUSE `create_umask` option. (GitHub issue #138.)
|
||||
* Fix C++ compilation error for WinFsp-FUSE. (GitHub PR #154; thanks @benrubson.)
|
||||
* *NOTE*: Prior v1.3 betas run the MEMFS sample file systems under the LocalService account. This is no longer the case: going forward the MEMFS file systems will be running under the LocalSystem account (as in v1.2POST1).
|
||||
|
||||
|
||||
v1.3B2 (2018.1 B2)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
||||
* Multiple Launcher changes:
|
||||
** New `FspLaunch` API. File systems can be started, stopped, queried and listed using `FspLaunchStart`, `FspLaunchStop`, `FspLaunchGetInfo` and `FspLaunchGetNameList`.
|
||||
** New Launcher registry settings `RunAs` and `WorkDirectory`. `RunAs` allows the laucher to launch a file system process under the service accounts LocalService and NetworkService. `WorkDirectory` can be used to specify the work directory for a newly launched file system process.
|
||||
* The MEMFS sample file systems are now launched under the LocalService account.
|
||||
* The FSD (File System Driver) and its interaction with the Windows MUP (Multiple UNC Provider) has been changed. In practice this eliminates the delays experienced when right-clicking on a WinFsp-backed network drive in the Windows Explorer. (GitHub issue #87.)
|
||||
* The WinFsp network provider is now added first in the provider order list. Previously it was added last. (GitHub PR #131; thanks @felfert.)
|
||||
* The WinFsp installer now uses the Wix `Provides` dependency extension to provide a `WinFsp` dependency key. (GitHub PR #129; thanks @felfert.)
|
||||
|
||||
|
||||
v1.3B1 (2018.1 B1)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
@ -54,7 +54,9 @@ This CONTRIBUTOR AGREEMENT applies to any contribution that you make to the WinF
|
||||
CONTRIBUTOR LIST
|
||||
----------------
|
||||
|===
|
||||
|Ben Rubson |ben.rubson at gmail.com
|
||||
|Bill Zissimopoulos |billziss at navimatics.com
|
||||
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr
|
||||
|Fritz Elfert |fritz-github at fritz-elfert.de
|
||||
|John Oberschelp |john at oberschelp.net
|
||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||
|
116
README.md
116
README.md
@ -1,24 +1,74 @@
|
||||
# WinFsp - Windows File System Proxy
|
||||
<h1 align="center">
|
||||
WinFsp · Windows File System Proxy
|
||||
<a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fgithub.com%2Fbillziss-gh%2Fwinfsp&text=Do%20you%20want%20to%20write%20a%20file%20system%20on%20Windows%3F%20WinFsp%20is%20well%20tested%2C%20very%20fast%20and%20easy%20to%20use%21&hashtags=windows%2Cfilesystem">
|
||||
<img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share"/>
|
||||
</a>
|
||||
</h1>
|
||||
|
||||

|
||||
<p align="center">
|
||||
<b>Download</b><br>
|
||||
<a href="https://github.com/billziss-gh/winfsp/releases/latest">
|
||||
<img src="https://img.shields.io/github/release/billziss-gh/winfsp.svg?label=stable&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://github.com/billziss-gh/winfsp/releases">
|
||||
<img src="https://img.shields.io/github/release/billziss-gh/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge"/>
|
||||
</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/>
|
||||
<b>Quick Links</b><br/>
|
||||
<a href="#benefits">Benefits</a> |
|
||||
<a href="https://github.com/billziss-gh/winfsp/wiki">Wiki</a> |
|
||||
<a href="https://groups.google.com/forum/#!forum/winfsp">Questions</a> |
|
||||
<a href="https://twitter.com/BZissimopoulos">Author's Twitter</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="https://ci.appveyor.com/project/billziss-gh/winfsp">
|
||||
<img src="https://img.shields.io/appveyor/ci/billziss-gh/winfsp.svg"/>
|
||||
</a>
|
||||
<br/>
|
||||
<br/>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
|
||||
<br/>
|
||||
<br/>
|
||||
<img src="http://www.secfs.net/winfsp/files/cap.gif" height="450"/>
|
||||
</p>
|
||||
|
||||
<a href="https://github.com/billziss-gh/winfsp/releases/latest"><img src="http://www.secfs.net/winfsp/resources/Download-WinFsp.png" alt="Download WinFsp Installer" width="244" height="34"></a>
|
||||
 
|
||||
<a href="https://chocolatey.org/packages/winfsp"><img src="http://www.secfs.net/winfsp/resources/Choco-WinFsp.png" alt="choco install winfsp" width="244" height="34"></a>
|
||||
## Benefits
|
||||
|
||||
### Stability
|
||||
|
||||
WinFsp is very stable. There are no known kernel mode crashes and it does not suffer from resource leaks or similar problems. WinFsp owes this stability to its [Design](doc/WinFsp-Design.asciidoc) and its rigorous [Testing Regime](doc/WinFsp-Testing.asciidoc).
|
||||
|
||||
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
|
||||
### Performance
|
||||
|
||||
Some of the benefits of using WinFsp are listed below:
|
||||
WinFsp outperforms its competition and in many scenarios performs as well as NTFS. Read more about its [Performance](doc/WinFsp-Performance-Testing.asciidoc).
|
||||
|
||||
<p align="center">
|
||||
<img src="doc/WinFsp-Performance-Testing/file_tests.png" height="300"/>
|
||||
<img src="doc/WinFsp-Performance-Testing/rdwr_tests.png" height="300"/>
|
||||
</p>
|
||||
|
||||
### Compatibility
|
||||
|
||||
WinFsp strives for compatibility with NTFS and file system correctness. For the full details see the [Compatibility](doc/NTFS-Compatibility.asciidoc) document.
|
||||
|
||||
### Easy to Use
|
||||
|
||||
WinFsp has an easy to use but comprehensive API.
|
||||
|
||||
* This simple [Tutorial](doc/WinFsp-Tutorial.asciidoc) explains how to build a file system.
|
||||
* Consult the [API Reference](http://www.secfs.net/winfsp/apiref/) for native development.
|
||||
* Includes .NET layer for managed development. See [src/dotnet](src/dotnet).
|
||||
* Includes FUSE 2.8 compatibility layer: [fuse/fuse.h](inc/fuse/fuse.h)
|
||||
* Includes FUSE 3.2 compatibility layer: [fuse3/fuse.h](inc/fuse3/fuse.h)
|
||||
|
||||
### Other Benefits
|
||||
|
||||
* Very well-tested and stable. Read about its [Testing Strategy](doc/WinFsp-Testing.asciidoc).
|
||||
* Very fast. Read about its [Performance](doc/WinFsp-Performance-Testing.asciidoc).
|
||||
* Strives for compatibility with NTFS. Read about its [Compatibility](doc/NTFS-Compatibility.asciidoc ).
|
||||
* Easy to understand but comprehensive API. Consult the [API Reference](http://www.secfs.net/winfsp/apiref/). There is also a simple [Tutorial](doc/WinFsp-Tutorial.asciidoc).
|
||||
* FUSE compatibility layer for native Windows and Cygwin. See [fuse.h](inc/fuse/fuse.h).
|
||||
* .NET layer for managed development. See [src/dotnet](src/dotnet).
|
||||
* Signed drivers provided on every release.
|
||||
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
|
||||
|
||||
@ -26,27 +76,29 @@ To learn more about WinFsp, please visit its website: http://www.secfs.net/winfs
|
||||
|
||||
## Project Organization
|
||||
|
||||
WinFsp consists of a kernel mode FSD (File System Driver) and a user mode DLL (Dynamic Link Library). The FSD interfaces with NTOS (the Windows kernel) and handles all interactions necessary to present itself as a file system driver to NTOS. The DLL interfaces with the FSD and presents an easy to use API for creating user mode file systems.
|
||||
|
||||
The project source code is organized as follows:
|
||||
|
||||
* `build/VStudio`: WinFsp solution and project files.
|
||||
* `doc`: The WinFsp design documents and additional documentation can be found here.
|
||||
* `ext/tlib`: A small test library originally from the secfs (Secure Cloud File System) project.
|
||||
* `ext/test`: Submodule pointing to the secfs.test project, which contains a number of tools for testing Windows and POSIX file systems.
|
||||
* `inc/fuse`: Public headers for the FUSE compatibility layer.
|
||||
* `inc/winfsp`: Public headers for the WinFsp API.
|
||||
* `src/dll`: Source code to the WinFsp DLL.
|
||||
* `src/dll/fuse`: Source code to the FUSE compatibility layer.
|
||||
* `src/dotnet`: Source code to the .NET layer.
|
||||
* `src/fsptool`: Source code to fsptool command line utility.
|
||||
* `src/launcher`: Source code to the launcher service and the launchctl utility.
|
||||
* `src/sys`: Source code to the WinFsp FSD.
|
||||
* `opt/cygfuse`: Source code for the Cygwin FUSE package.
|
||||
* `tst/memfs*`: Source code to an example file system written in C/C++ (memfs) or C# (memfs-dotnet).
|
||||
* `tst/passthrough*`: Source code to additional example file systems.
|
||||
* `tst/winfsp-tests`: WinFsp test suite.
|
||||
* `tools`: Various tools for building and testing WinFsp.
|
||||
* :file_folder: [build/VStudio](build/VStudio): WinFsp solution and project files.
|
||||
* :file_folder: [doc](doc): The WinFsp design documents and additional documentation can be found here.
|
||||
* :file_folder: [ext](ext): External dependencies.
|
||||
* :file_folder: [ext/tlib](ext/tlib): A small test library originally from the secfs (Secure Cloud File System) project.
|
||||
* :file_folder: ext/test: Submodule pointing to the secfs.test project, which contains a number of tools for testing Windows and POSIX file systems.
|
||||
* :file_folder: [inc](inc): Public headers.
|
||||
* :file_folder: [inc/fuse](inc/fuse): Public headers for the FUSE compatibility layer.
|
||||
* :file_folder: [inc/fuse3](inc/fuse3): Public headers for the FUSE3 compatibility layer.
|
||||
* :file_folder: [inc/winfsp](inc/winfsp): Public headers for the WinFsp API.
|
||||
* :file_folder: [src](src): WinFsp source code.
|
||||
* :file_folder: [src/dll](src/dll): Source code to the WinFsp DLL.
|
||||
* :file_folder: [src/dll/fuse](src/dll/fuse): Source code to the FUSE compatibility layer.
|
||||
* :file_folder: [src/dll/fuse3](src/dll/fuse3): Source code to the FUSE3 compatibility layer.
|
||||
* :file_folder: [src/dotnet](src/dotnet): Source code to the .NET layer.
|
||||
* :file_folder: [src/fsptool](src/fsptool): Source code to fsptool command line utility.
|
||||
* :file_folder: [src/launcher](src/launcher): Source code to the launcher service and the launchctl utility.
|
||||
* :file_folder: [src/sys](src/sys): Source code to the WinFsp FSD.
|
||||
* :file_folder: [opt/cygfuse](opt/cygfuse): Source code to the FUSE for Cygwin package.
|
||||
* :file_folder: [tst](tst): Source code to example file systems and test suites.
|
||||
* :file_folder: [tst/winfsp-tests](tst/winfsp-tests): WinFsp test suite.
|
||||
* :file_folder: [tools](tools): Various tools for building and testing WinFsp.
|
||||
|
||||
## Building and Running
|
||||
|
||||
|
@ -188,10 +188,6 @@
|
||||
Type="string"
|
||||
Name="CommandLine"
|
||||
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="RunAs"
|
||||
Value="LocalService" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="Security"
|
||||
@ -218,10 +214,6 @@
|
||||
Type="string"
|
||||
Name="CommandLine"
|
||||
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="RunAs"
|
||||
Value="LocalService" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="Security"
|
||||
@ -248,10 +240,6 @@
|
||||
Type="string"
|
||||
Name="CommandLine"
|
||||
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="RunAs"
|
||||
Value="LocalService" />
|
||||
<RegistryValue
|
||||
Type="string"
|
||||
Name="Security"
|
||||
@ -272,6 +260,9 @@
|
||||
<Component Id="C.winfsp.h">
|
||||
<File Name="winfsp.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launch.h">
|
||||
<File Name="launch.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<!--Component Id="C.winfsp.hpp">
|
||||
<File Name="winfsp.hpp" KeyPath="yes" />
|
||||
</Component-->
|
||||
@ -290,6 +281,20 @@
|
||||
<File Name="winfsp_fuse.h" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="INCDIR.fuse3" Name="fuse3">
|
||||
<Component Id="C.fuse3.h">
|
||||
<File Id="fuse3.h" Name="fuse.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse3_common.h">
|
||||
<File Id="fuse3_common.h" Name="fuse_common.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse3_opt.h">
|
||||
<File Id="fuse3_opt.h" Name="fuse_opt.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.winfsp_fuse3.h">
|
||||
<File Id="winfsp_fuse3.h" Name="winfsp_fuse.h" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="LIBDIR" FileSource="..\build\$(var.Configuration)">
|
||||
<Component Id="C.winfsp_x64.lib">
|
||||
@ -318,17 +323,43 @@
|
||||
KeyPath="yes" />
|
||||
<Condition>NOT VersionNT64</Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win64 copy fuse3-x64.pc -->
|
||||
<Component Id="C.fuse3_x64.pc" Guid="FE59E3BA-E5EA-4822-80B1-19A1DE6B62C7">
|
||||
<File
|
||||
Id="FILE.fuse3_x64.pc"
|
||||
Name="fuse3.pc"
|
||||
Source="..\build\$(var.Configuration)\fuse3-x64.pc"
|
||||
KeyPath="yes" />
|
||||
<Condition>VersionNT64</Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win32 copy fuse3-x86.pc -->
|
||||
<Component Id="C.fuse3_x86.pc" Guid="176205D0-07EA-4DFC-947F-18E89ABDAFAB">
|
||||
<File
|
||||
Id="FILE.fuse3_x86.pc"
|
||||
Name="fuse3.pc"
|
||||
Source="..\build\$(var.Configuration)\fuse3-x86.pc"
|
||||
KeyPath="yes" />
|
||||
<Condition>NOT VersionNT64</Condition>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="OPTDIR">
|
||||
<Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist">
|
||||
<Directory Id="OPTDIR.cygfuse.x64" Name="x64">
|
||||
<Component Id="C.fuse.tar.xz.x64">
|
||||
<File Id="FILE.fuse.tar.xz.x64" Name="fuse-2.8-7.tar.xz" KeyPath="yes" />
|
||||
<File Id="FILE.fuse.tar.xz.x64" Name="fuse-2.8-9.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse3.tar.xz.x64">
|
||||
<File Id="FILE.fuse3.tar.xz.x64" Name="fuse3-3.2-1.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="OPTDIR.cygfuse.x86" Name="x86">
|
||||
<Component Id="C.fuse.tar.xz.x86">
|
||||
<File Id="FILE.fuse.tar.xz.x86" Name="fuse-2.8-7.tar.xz" KeyPath="yes" />
|
||||
<File Id="FILE.fuse.tar.xz.x86" Name="fuse-2.8-9.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fuse3.tar.xz.x86">
|
||||
<File Id="FILE.fuse3.tar.xz.x86" Name="fuse3-3.2-1.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Component Id="C.fuse.install.sh">
|
||||
@ -356,6 +387,20 @@
|
||||
<File Id="FILE.memfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.airfs" Name="airfs">
|
||||
<Component Id="C.airfs.cpp">
|
||||
<File Name="airfs.cpp" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.airfs.sln">
|
||||
<File Name="airfs.sln" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.airfs.vcxproj">
|
||||
<File Name="airfs.vcxproj" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.airfs.vcxproj.filters">
|
||||
<File Name="airfs.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough" Name="passthrough">
|
||||
<Component Id="C.passthrough.c">
|
||||
<File Name="passthrough.c" KeyPath="yes" />
|
||||
@ -410,6 +455,32 @@
|
||||
<File Name="README.md" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_fuse3" Name="passthrough-fuse3">
|
||||
<Component Id="C.passthrough_fuse3.c">
|
||||
<File Name="passthrough-fuse3.c" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.winposix.c">
|
||||
<File Id="F.passthrough_fuse3.winposix.c" Name="winposix.c" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.winposix.h">
|
||||
<File Id="F.passthrough_fuse3.winposix.h" Name="winposix.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.sln">
|
||||
<File Name="passthrough-fuse3.sln" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.vcxproj">
|
||||
<File Name="passthrough-fuse3.vcxproj" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.vcxproj.filters">
|
||||
<File Name="passthrough-fuse3.vcxproj.filters" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.Makefile">
|
||||
<File Id="F.passthrough_fuse3.Makefile" Name="Makefile" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.passthrough_fuse3.README.md">
|
||||
<File Id="F.passthrough_fuse3.README.md" Name="README.md" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="SMPDIR.passthrough_dotnet" Name="passthrough-dotnet">
|
||||
<Component Id="C.passthrough_dotnet.Program.cs">
|
||||
<File Id="FILE.passthrough_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||
@ -482,21 +553,30 @@
|
||||
<ComponentGroup Id="C.WinFsp.inc">
|
||||
<ComponentRef Id="C.fsctl.h" />
|
||||
<ComponentRef Id="C.winfsp.h" />
|
||||
<ComponentRef Id="C.launch.h" />
|
||||
<!--ComponentRef Id="C.winfsp.hpp" /-->
|
||||
<ComponentRef Id="C.fuse.h" />
|
||||
<ComponentRef Id="C.fuse_common.h" />
|
||||
<ComponentRef Id="C.fuse_opt.h" />
|
||||
<ComponentRef Id="C.winfsp_fuse.h" />
|
||||
<ComponentRef Id="C.fuse3.h" />
|
||||
<ComponentRef Id="C.fuse3_common.h" />
|
||||
<ComponentRef Id="C.fuse3_opt.h" />
|
||||
<ComponentRef Id="C.winfsp_fuse3.h" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.lib">
|
||||
<ComponentRef Id="C.winfsp_x64.lib" />
|
||||
<ComponentRef Id="C.winfsp_x86.lib" />
|
||||
<ComponentRef Id="C.fuse_x64.pc" />
|
||||
<ComponentRef Id="C.fuse_x86.pc" />
|
||||
<ComponentRef Id="C.fuse3_x64.pc" />
|
||||
<ComponentRef Id="C.fuse3_x86.pc" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.opt.fuse">
|
||||
<ComponentRef Id="C.fuse.tar.xz.x64" />
|
||||
<ComponentRef Id="C.fuse.tar.xz.x86" />
|
||||
<ComponentRef Id="C.fuse3.tar.xz.x64" />
|
||||
<ComponentRef Id="C.fuse3.tar.xz.x86" />
|
||||
<ComponentRef Id="C.fuse.install.sh" />
|
||||
<ComponentRef Id="C.fuse.uninstall.sh" />
|
||||
</ComponentGroup>
|
||||
@ -506,6 +586,10 @@
|
||||
<ComponentRef Id="C.memfs.h" />
|
||||
<ComponentRef Id="C.memfs.cpp" />
|
||||
<ComponentRef Id="C.memfs_main.c" />
|
||||
<ComponentRef Id="C.airfs.cpp" />
|
||||
<ComponentRef Id="C.airfs.sln" />
|
||||
<ComponentRef Id="C.airfs.vcxproj" />
|
||||
<ComponentRef Id="C.airfs.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough.c" />
|
||||
<ComponentRef Id="C.passthrough.sln" />
|
||||
<ComponentRef Id="C.passthrough.vcxproj" />
|
||||
@ -522,6 +606,14 @@
|
||||
<ComponentRef Id="C.passthrough_fuse.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough_fuse.Makefile" />
|
||||
<ComponentRef Id="C.passthrough_fuse.README.md" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.c" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.winposix.c" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.winposix.h" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.sln" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.vcxproj" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.vcxproj.filters" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.Makefile" />
|
||||
<ComponentRef Id="C.passthrough_fuse3.README.md" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.WinFsp.sym">
|
||||
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
|
||||
|
@ -182,14 +182,17 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\devctl-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\exec-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\flush-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-opt-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\info-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\lock-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\memfs-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\mount-test.c" />
|
||||
|
@ -85,6 +85,15 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\devctl-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||
|
@ -185,7 +185,6 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h" />
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -16,9 +16,6 @@
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||
<Filter>Include\shared</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h">
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\src\launcher\launchctl.c">
|
||||
|
@ -197,7 +197,6 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h" />
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -21,9 +21,6 @@
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||
<Filter>Include\shared</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h">
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\src\launcher\launcher-version.rc">
|
||||
|
@ -16,9 +16,9 @@
|
||||
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||
|
||||
<MyCanonicalVersion>1.3</MyCanonicalVersion>
|
||||
<MyCanonicalVersion>1.4</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2018.1 B1</MyProductVersion>
|
||||
<MyProductVersion>2018.2 B2</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
|
@ -20,13 +20,19 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse.h" />
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_common.h" />
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_opt.h" />
|
||||
<ClInclude Include="..\..\inc\fuse3\winfsp_fuse.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\fuse.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\fuse_common.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\fuse_opt.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\winfsp_fuse.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\launch.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp" />
|
||||
<ClInclude Include="..\..\src\dll\fuse3\library.h" />
|
||||
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
||||
<ClInclude Include="..\..\src\dll\library.h" />
|
||||
<ClInclude Include="..\..\src\shared\minimal.h" />
|
||||
@ -34,9 +40,13 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\dirbuf.c" />
|
||||
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3_compat.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_loop.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||
<ClCompile Include="..\..\src\dll\launch.c" />
|
||||
@ -78,6 +88,29 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse-$(PlatformTarget).pc</Outputs>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc
|
||||
copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Writing fuse3-$(PlatformTarget).pc</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects>
|
||||
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
|
||||
</CustomBuild>
|
||||
<None Include="..\..\src\dll\library.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -21,6 +21,12 @@
|
||||
<Filter Include="Source\fuse">
|
||||
<UniqueIdentifier>{518cce17-85cd-489c-b4be-920a84c1d73c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Include\fuse3">
|
||||
<UniqueIdentifier>{12afd2f1-f5ec-4008-b6ef-89cc626019ea}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source\fuse3">
|
||||
<UniqueIdentifier>{96091a7b-3923-4a74-9491-3ee230c688f9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
||||
@ -53,6 +59,24 @@
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp">
|
||||
<Filter>Include\winfsp</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\winfsp\launch.h">
|
||||
<Filter>Include\winfsp</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_common.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\fuse_opt.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\fuse3\winfsp_fuse.h">
|
||||
<Filter>Include\fuse3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\dll\fuse3\library.h">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\library.c">
|
||||
@ -118,6 +142,18 @@
|
||||
<ClCompile Include="..\..\src\dll\launch.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3.c">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_loop.c">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse3_compat.c">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
@ -136,5 +172,8 @@
|
||||
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in">
|
||||
<Filter>Source\fuse3</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -173,6 +173,7 @@
|
||||
<ClCompile Include="..\..\src\sys\ioq.c" />
|
||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||
<ClCompile Include="..\..\src\sys\mup.c" />
|
||||
<ClCompile Include="..\..\src\sys\name.c" />
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||
<ClCompile Include="..\..\src\sys\read.c" />
|
||||
|
@ -101,6 +101,9 @@
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\mup.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -4,30 +4,37 @@
|
||||
|
||||
[qanda]
|
||||
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed. [@efeat]::
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed.::
|
||||
|
||||
Your Windows 7 OS is missing SHA-2 Code Signing Support. You need to install the following security advisory that will rectify the problem:
|
||||
https://technet.microsoft.com/en-us/library/security/3033929.aspx
|
||||
|
||||
|
||||
Disconnecting (unmapping) a network drive does not work. [@carlreinke]::
|
||||
Disconnecting (unmapping) a network drive does not work.::
|
||||
|
||||
You may have Dokany installed. Dokany installs its own Network Provider DLL that unfortunately interferes with the WinFsp handling of network drives. The solution is to change your system's Network Provider order and ensure that the WinFsp Network Provider runs before the Dokany one. Instructions on how to change the Network Provider order can be found in this http://blogs.interfacett.com/changing-the-network-provider-order-in-windows-10[article].
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories? [@netheril96]::
|
||||
Case-sensitive file systems do not work properly when mounted as a directory.::
|
||||
|
||||
Windows and WinFsp support case-sensitive file systems. These file systems work properly when mounted as a drive. Unfortunately when a file system is mounted as a directory over NTFS, Windows expects it to be case-insensitive and will UPPERCASE many of the file names sent to the file system.
|
||||
+
|
||||
This is an unfortunate but well understood Windows limitation. Case-sensitive file systems should only be mounted as drives.
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories?::
|
||||
|
||||
It is true that this would make it convenient to load the DLL, because the Windows loader looks into the Windows system directories when it loads DLL's. However, in the opinion of the WinFsp author, software that does not ship with the OS should not be installing components in the system directories.
|
||||
+
|
||||
There are a few alternative methods to overcome this problem. WinFsp recommends marking the WinFsp DLL as "delay load" and then using `FspLoad` to dynamically load the DLL during process initialization. For more information see the WinFsp Tutorial.
|
||||
|
||||
|
||||
Does WinFsp provide debugging symbols? [@netheril96]::
|
||||
Does WinFsp provide debugging symbols?::
|
||||
|
||||
Public debugging symbols are already included in the installer. You need to install the "Developer" feature; the symbols can be found in the `sym` directory under the WinFsp installation directory.
|
||||
|
||||
|
||||
Is there a maximum number of concurrent file systems? [@efeat]::
|
||||
Is there a maximum number of concurrent file systems?::
|
||||
|
||||
WinFsp does not have a hard limit of how many file systems can be created or how many processes can create file systems.
|
||||
+
|
||||
@ -40,10 +47,10 @@ As of the commits required to fix issue #55, there is however a hash table insid
|
||||
|
||||
Which version of FUSE does WinFsp-FUSE support?::
|
||||
|
||||
Currently it supports FUSE 2.8.
|
||||
It supports both the FUSE 2.8 and FUSE 3.2 API's. For the FUSE 2.8 API include `<fuse/fuse.h>`. For the FUSE 3.2 API include `<fuse3/fuse.h>`.
|
||||
|
||||
|
||||
FUSE on UNIX systems mounts file systems over an existing directory. When mounting a WinFsp-FUSE file system on a directory, the directory is created and later deleted when the file system goes away. What is the reason for this incompatibility? [@efeat]::
|
||||
FUSE on UNIX systems mounts file systems over an existing directory. When mounting a WinFsp-FUSE file system on a directory, the directory is created and later deleted when the file system goes away. What is the reason for this incompatibility?::
|
||||
|
||||
It would be preferrable if WinFsp-FUSE behaved like FUSE on UNIX in this instance. However there are a number of reasons that this is not the case.
|
||||
+
|
||||
@ -54,3 +61,10 @@ With this in mind here are the reasons for the current WinFsp-FUSE behavior:
|
||||
- Symmetry with mounting on a drive. On Windows drives are created when the file system comes into existence and deleted when it is gone.
|
||||
- Inability to mount over a non-empty directory on Windows. On FUSE/UNIX this is possible, but not on Windows because NTFS disallows the creation of (mountpoint) reparse points on non-empty directories.
|
||||
- Most importantly: inability to guarantee that the mount point will cease to exist if the file system crashes. WinFsp attempts to guarantee that all resources used by a file system will get cleaned up. This is certainly true for the kernel-mode FSD, but an attempt is made to do so also in user mode. For this reason, drive symbolic links are marked as temporary and (importantly for our discussion) mount directories are opened with `FILE_FLAG_DELETE_ON_CLOSE`. There is no way to guarantee the removal of a reparse point in the same way.
|
||||
|
||||
|
||||
WinFsp-FUSE does not have the ability to support multiple file systems from within the same process. Why?::
|
||||
|
||||
This is supported as of WinFsp 2018.2 B2.
|
||||
+
|
||||
The core WinFsp layer always supported multiple file systems in the same process either simultaneously or one after another. However this was not the case with WinFsp-FUSE (i.e. the FUSE layer of WinFsp) prior to version 2018.2 B2. This limitation has been rectified as of WinFsp 2018 B2.
|
@ -9,7 +9,7 @@ The documentation available here discusses various aspects of WinFsp.
|
||||
## Programming
|
||||
|
||||
- The [[Tutorial|WinFsp-Tutorial]] describes how to create a simple, but complete file system in C/C++.
|
||||
- The [[API Reference|winfsp.h]] describes the native WinFsp API. This external [[link|http://www.secfs.net/winfsp/apiref/]] may be easier to browse for some people.
|
||||
- The [[API Reference|WinFsp-API-winfsp.h]] describes the native WinFsp API. This external [[link|http://www.secfs.net/winfsp/apiref/]] may be easier to browse for some people.
|
||||
- There is also a FUSE compatibility layer for native Windows and Cygwin. See fuse.h in the source repository.
|
||||
- This [[document|Native-API-vs-FUSE]] discusses the need for both a native API and FUSE and gives some pointers on which one to choose.
|
||||
|
||||
|
@ -4,6 +4,7 @@ This document contains a list of known file systems and file system libraries th
|
||||
|
||||
== File Systems
|
||||
|
||||
- https://github.com/vgough/encfs[EncFS] - an Encrypted Filesystem for FUSE
|
||||
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
||||
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
||||
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
||||
|
263
doc/WinFsp-API-launch.h.asciidoc
Normal file
263
doc/WinFsp-API-launch.h.asciidoc
Normal file
@ -0,0 +1,263 @@
|
||||
= winfsp/launch.h
|
||||
:author: (C) 2015-2018 Bill Zissimopoulos
|
||||
:toc: preamble
|
||||
:toc-title:
|
||||
|
||||
WinFsp Launch API.
|
||||
|
||||
In order to use the WinFsp Launch API a program must include <winfsp/launch.h>
|
||||
and link with the winfsp$$_$$x64.dll (or winfsp$$_$$x86.dll) library.
|
||||
|
||||
== Launch Control
|
||||
|
||||
=== Functions
|
||||
|
||||
*FspLaunchCallLauncherPipe* - Call launcher pipe.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command,
|
||||
ULONG Argc,
|
||||
PWSTR *Argv,
|
||||
ULONG *Argl,
|
||||
PWSTR Buffer,
|
||||
PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Command_ - Launcher command to send. For example, the 'L' launcher command instructs
|
||||
the launcher to list all running service instances.
|
||||
- _Argc_ - Command argument count. May be 0.
|
||||
- _Argv_ - Command argument array. May be NULL.
|
||||
- _Argl_ - Command argument length array. May be NULL. If this is NULL all command arguments
|
||||
are assumed to be NULL-terminated strings. It is also possible for specific arguments
|
||||
to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
|
||||
- _Buffer_ - Buffer that receives the command response. May be NULL.
|
||||
- _PSize_ - Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
contains the number of bytes transferred. May be NULL.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
*Discussion*
|
||||
|
||||
This function is used to send a command to the launcher and receive a response.
|
||||
|
||||
|
||||
*FspLaunchGetInfo* - Get information about a service instance.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName,
|
||||
PWSTR InstanceName,
|
||||
PWSTR Buffer,
|
||||
PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - Class name of the service instance to stop.
|
||||
- _InstanceName_ - Instance name of the service instance to stop.
|
||||
- _Buffer_ - Buffer that receives the command response. May be NULL.
|
||||
- _PSize_ - Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
contains the number of bytes transferred. May be NULL.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
*Discussion*
|
||||
|
||||
The information is a list of NULL-terminated strings: the class name of the service instance,
|
||||
the instance name of the service instance and the full command line used to start the service
|
||||
instance.
|
||||
|
||||
|
||||
*FspLaunchGetNameList* - List service instances.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer,
|
||||
PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Buffer_ - Buffer that receives the command response. May be NULL.
|
||||
- _PSize_ - Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
contains the number of bytes transferred. May be NULL.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
*Discussion*
|
||||
|
||||
The information is a list of pairs of NULL-terminated strings. Each pair contains the class
|
||||
name and instance name of a service instance. All currently running service instances are
|
||||
listed.
|
||||
|
||||
|
||||
*FspLaunchStart* - Start a service instance.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName,
|
||||
PWSTR InstanceName,
|
||||
ULONG Argc,
|
||||
PWSTR *Argv,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - Class name of the service instance to start.
|
||||
- _InstanceName_ - Instance name of the service instance to start.
|
||||
- _Argc_ - Service instance argument count. May be 0.
|
||||
- _Argv_ - Service instance argument array. May be NULL.
|
||||
- _HasSecret_ - Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
|
||||
Secrets are passed to service instances through standard input rather than the command
|
||||
line.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
|
||||
*FspLaunchStop* - Stop a service instance.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName,
|
||||
PWSTR InstanceName,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - Class name of the service instance to stop.
|
||||
- _InstanceName_ - Instance name of the service instance to stop.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
|
||||
== Service Registry
|
||||
|
||||
=== Functions
|
||||
|
||||
*FspLaunchRegFreeRecord* - Free a service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Record_ - The service record to free.
|
||||
|
||||
*See Also*
|
||||
|
||||
- FspLaunchRegGetRecord
|
||||
|
||||
|
||||
*FspLaunchRegGetRecord* - Get a service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName,
|
||||
PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - The service class name.
|
||||
- _Agent_ - The name of the agent that is retrieving the service record. This API matches
|
||||
the supplied Agent against the Agent in the service record and it only returns
|
||||
the record if they match. Pass NULL to match any Agent.
|
||||
- _PRecord_ - Pointer to a record pointer. Memory for the service record will be allocated
|
||||
and a pointer to it will be stored at this address. This memory must be later
|
||||
freed using FspLaunchRegFreeRecord.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
*See Also*
|
||||
|
||||
- FspLaunchRegFreeRecord
|
||||
|
||||
|
||||
*FspLaunchRegSetRecord* - Add/change/delete a service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - The service class name.
|
||||
- _Record_ - The record to set in the registry. If NULL, the registry record is deleted.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
|
||||
=== Typedefs
|
||||
|
||||
*FSP$$_$$LAUNCH$$_$$REG$$_$$RECORD* - Service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
typedef struct _FSP_LAUNCH_REG_RECORD {
|
||||
PWSTR Agent;
|
||||
PWSTR Executable;
|
||||
PWSTR CommandLine;
|
||||
PWSTR WorkDirectory;
|
||||
PWSTR RunAs;
|
||||
PWSTR Security;
|
||||
PVOID Reserved0[6];
|
||||
ULONG JobControl;
|
||||
ULONG Credentials;
|
||||
ULONG Reserved1[6];
|
||||
UINT8 Buffer[];
|
||||
} FSP_LAUNCH_REG_RECORD;
|
||||
----
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
= winfsp/winfsp.h
|
||||
:author: (C) 2015-2017 Bill Zissimopoulos
|
||||
:author: (C) 2015-2018 Bill Zissimopoulos
|
||||
:toc: preamble
|
||||
:toc-title:
|
||||
|
||||
@ -178,6 +178,43 @@ VOID ( *Close)(
|
||||
- _FileContext_ - The file context of the file or directory to be closed.
|
||||
|
||||
|
||||
*Control* - Process control code.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
NTSTATUS ( *Control)(
|
||||
FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext,
|
||||
UINT32 ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PULONG PBytesTransferred);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _FileSystem_ - The file system on which this request is posted.
|
||||
- _FileContext_ - The file context of the file or directory to be controled.
|
||||
- _ControlCode_ - The control code for the operation. This code must have a DeviceType with bit
|
||||
0x8000 set and must have a TransferType of METHOD$$_$$BUFFERED.
|
||||
- _InputBuffer_ - Pointer to a buffer that contains the input data.
|
||||
- _InputBufferLength_ - Input data length.
|
||||
- _OutputBuffer_ - Pointer to a buffer that will receive the output data.
|
||||
- _OutputBufferLength_ - Output data length.
|
||||
- _PBytesTransferred_ - [out]
|
||||
Pointer to a memory location that will receive the actual number of bytes transferred.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
*Discussion*
|
||||
|
||||
This function is called when a program uses the DeviceIoControl API.
|
||||
|
||||
|
||||
*Create* - Create new file or directory.
|
||||
|
||||
[source,c]
|
||||
@ -278,6 +315,33 @@ STATUS$$_$$SUCCESS or error code.
|
||||
Note that the FSD will also flush all file/volume caches prior to invoking this operation.
|
||||
|
||||
|
||||
*GetDirInfoByName* - Get directory information for a single file or directory within a parent directory.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
NTSTATUS ( *GetDirInfoByName)(
|
||||
FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext,
|
||||
PWSTR FileName,
|
||||
FSP_FSCTL_DIR_INFO *DirInfo);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _FileSystem_ - The file system on which this request is posted.
|
||||
- _FileContext_ - The file context of the parent directory.
|
||||
- _FileName_ - The name of the file or directory to get information for. This name is relative
|
||||
to the parent directory and is a single path component.
|
||||
- _DirInfo_ - [out]
|
||||
Pointer to a structure that will receive the directory information on successful
|
||||
return from this call. This information includes the file name, but also file
|
||||
attributes, file times, etc.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
|
||||
*GetFileInfo* - Get file or directory information.
|
||||
|
||||
[source,c]
|
||||
@ -1185,6 +1249,19 @@ The current operation context is stored in thread local storage. It allows acces
|
||||
Request and Response associated with this operation.
|
||||
|
||||
|
||||
*FspFileSystemOperationProcessId* - Gets the originating process ID.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
static inline UINT32 FspFileSystemOperationProcessId(
|
||||
VOID)
|
||||
----
|
||||
|
||||
*Discussion*
|
||||
|
||||
Valid only during Create, Open and Rename requests when the target exists.
|
||||
|
||||
|
||||
*FspFileSystemPreflight* - Check whether creating a file system object is possible.
|
||||
|
||||
[source,c]
|
||||
@ -1535,6 +1612,27 @@ call. The WinFsp Launcher is a Windows service that can be configured to launch
|
||||
multiple instances of a user mode file system.
|
||||
|
||||
|
||||
*FspServiceContextCheck* - Check if the supplied token is from the service context.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspServiceContextCheck(
|
||||
HANDLE Token,
|
||||
PBOOLEAN PIsLocalSystem);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Token_ - Token to check. Pass NULL to check the current process token.
|
||||
- _PIsLocalSystem_ - Pointer to a boolean that will receive a TRUE value if the token belongs to LocalSystem
|
||||
and FALSE otherwise. May be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the token is from the service context. STATUS$$_$$ACCESS$$_$$DENIED if it is not.
|
||||
Other error codes are possible.
|
||||
|
||||
|
||||
*FspServiceCreate* - Create a service object.
|
||||
|
||||
[source,c]
|
@ -87,7 +87,7 @@ struct fuse_operations
|
||||
/* _ */ unsigned int flag_nopath:1;
|
||||
/* _ */ unsigned int flag_utime_omit_ok:1;
|
||||
/* _ */ unsigned int flag_reserved:29;
|
||||
/* _ */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse_file_info *fi,
|
||||
/* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse_file_info *fi,
|
||||
unsigned int flags, void *data);
|
||||
/* _ */ int (*poll)(const char *path, struct fuse_file_info *fi,
|
||||
struct fuse_pollhandle *ph, unsigned *reventsp);
|
||||
|
@ -53,6 +53,17 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FSP_FUSE_DEVICE_TYPE (0x8000 | 'W' | 'F' * 0x100) /* DeviceIoControl -> ioctl */
|
||||
#define FSP_FUSE_CTLCODE_FROM_IOCTL(cmd)\
|
||||
(FSP_FUSE_DEVICE_TYPE << 16) | (((c) & 0x0fff) << 2)
|
||||
#define FSP_FUSE_IOCTL(cmd, isiz, osiz) \
|
||||
( \
|
||||
(((osiz) != 0) << 31) | \
|
||||
(((isiz) != 0) << 30) | \
|
||||
(((isiz) | (osiz)) << 16) | \
|
||||
(cmd) \
|
||||
)
|
||||
|
||||
/*
|
||||
* FUSE uses a number of types (notably: struct stat) that are OS specific.
|
||||
* Furthermore there are sometimes multiple definitions of the same type even
|
||||
@ -389,7 +400,7 @@ static inline int fsp_fuse_set_signal_handlers(void *se)
|
||||
static inline char *fsp_fuse_conv_to_win_path(const char *path)
|
||||
{
|
||||
void *cygwin_create_path(unsigned, const void *);
|
||||
return cygwin_create_path(
|
||||
return (char *)cygwin_create_path(
|
||||
0/*CCP_POSIX_TO_WIN_A*/ | 0x100/*CCP_RELATIVE*/,
|
||||
path);
|
||||
}
|
||||
|
334
inc/fuse3/fuse.h
Normal file
334
inc/fuse3/fuse.h
Normal file
@ -0,0 +1,334 @@
|
||||
/**
|
||||
* @file fuse3/fuse.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* This file is derived from libfuse/include/fuse.h:
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef FUSE_H_
|
||||
#define FUSE_H_
|
||||
|
||||
#include "fuse_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct fuse3;
|
||||
|
||||
enum fuse3_readdir_flags
|
||||
{
|
||||
FUSE_READDIR_PLUS = (1 << 0),
|
||||
};
|
||||
|
||||
enum fuse3_fill_dir_flags
|
||||
{
|
||||
FUSE_FILL_DIR_PLUS = (1 << 1),
|
||||
};
|
||||
|
||||
typedef int (*fuse3_fill_dir_t)(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off,
|
||||
enum fuse3_fill_dir_flags flags);
|
||||
|
||||
struct fuse3_config
|
||||
{
|
||||
int set_gid;
|
||||
unsigned int gid;
|
||||
int set_uid;
|
||||
unsigned int uid;
|
||||
int set_mode;
|
||||
unsigned int umask;
|
||||
double entry_timeout;
|
||||
double negative_timeout;
|
||||
double attr_timeout;
|
||||
int intr;
|
||||
int intr_signal;
|
||||
int remember;
|
||||
int hard_remove;
|
||||
int use_ino;
|
||||
int readdir_ino;
|
||||
int direct_io;
|
||||
int kernel_cache;
|
||||
int auto_cache;
|
||||
int ac_attr_timeout_set;
|
||||
double ac_attr_timeout;
|
||||
int nullpath_ok;
|
||||
/* private */
|
||||
int show_help;
|
||||
char *modules;
|
||||
int debug;
|
||||
};
|
||||
|
||||
struct fuse3_operations
|
||||
{
|
||||
/* S - supported by WinFsp */
|
||||
/* S */ int (*getattr)(const char *path, struct fuse_stat *stbuf,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*readlink)(const char *path, char *buf, size_t size);
|
||||
/* S */ int (*mknod)(const char *path, fuse_mode_t mode, fuse_dev_t dev);
|
||||
/* S */ int (*mkdir)(const char *path, fuse_mode_t mode);
|
||||
/* S */ int (*unlink)(const char *path);
|
||||
/* S */ int (*rmdir)(const char *path);
|
||||
/* S */ int (*symlink)(const char *dstpath, const char *srcpath);
|
||||
/* S */ int (*rename)(const char *oldpath, const char *newpath, unsigned int flags);
|
||||
/* _ */ int (*link)(const char *srcpath, const char *dstpath);
|
||||
/* S */ int (*chmod)(const char *path, fuse_mode_t mode,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*chown)(const char *path, fuse_uid_t uid, fuse_gid_t gid,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*truncate)(const char *path, fuse_off_t size,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*open)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*read)(const char *path, char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*write)(const char *path, const char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse3_file_info *fi);
|
||||
/* S */ int (*statfs)(const char *path, struct fuse_statvfs *stbuf);
|
||||
/* S */ int (*flush)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*release)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*fsync)(const char *path, int datasync, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*setxattr)(const char *path, const char *name, const char *value, size_t size,
|
||||
int flags);
|
||||
/* _ */ int (*getxattr)(const char *path, const char *name, char *value, size_t size);
|
||||
/* _ */ int (*listxattr)(const char *path, char *namebuf, size_t size);
|
||||
/* _ */ int (*removexattr)(const char *path, const char *name);
|
||||
/* S */ int (*opendir)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*readdir)(const char *path, void *buf, fuse3_fill_dir_t filler, fuse_off_t off,
|
||||
struct fuse3_file_info *fi, enum fuse3_readdir_flags);
|
||||
/* S */ int (*releasedir)(const char *path, struct fuse3_file_info *fi);
|
||||
/* S */ int (*fsyncdir)(const char *path, int datasync, struct fuse3_file_info *fi);
|
||||
/* S */ void *(*init)(struct fuse3_conn_info *conn,
|
||||
struct fuse3_config *conf);
|
||||
/* S */ void (*destroy)(void *data);
|
||||
/* _ */ int (*access)(const char *path, int mask);
|
||||
/* S */ int (*create)(const char *path, fuse_mode_t mode, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*lock)(const char *path,
|
||||
struct fuse3_file_info *fi, int cmd, struct fuse_flock *lock);
|
||||
/* S */ int (*utimens)(const char *path, const struct fuse_timespec tv[2],
|
||||
struct fuse3_file_info *fi);
|
||||
/* _ */ int (*bmap)(const char *path, size_t blocksize, uint64_t *idx);
|
||||
/* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse3_file_info *fi,
|
||||
unsigned int flags, void *data);
|
||||
/* _ */ int (*poll)(const char *path, struct fuse3_file_info *fi,
|
||||
struct fuse3_pollhandle *ph, unsigned *reventsp);
|
||||
/* _ */ int (*write_buf)(const char *path,
|
||||
struct fuse3_bufvec *buf, fuse_off_t off, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*read_buf)(const char *path,
|
||||
struct fuse3_bufvec **bufp, size_t size, fuse_off_t off, struct fuse3_file_info *fi);
|
||||
/* _ */ int (*flock)(const char *path, struct fuse3_file_info *, int op);
|
||||
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
||||
struct fuse3_file_info *fi);
|
||||
};
|
||||
|
||||
struct fuse3_context
|
||||
{
|
||||
struct fuse3 *fuse;
|
||||
fuse_uid_t uid;
|
||||
fuse_gid_t gid;
|
||||
fuse_pid_t pid;
|
||||
void *private_data;
|
||||
fuse_mode_t umask;
|
||||
};
|
||||
|
||||
#define fuse_main(argc, argv, ops, data)\
|
||||
fuse3_main_real(argc, argv, ops, sizeof *(ops), data)
|
||||
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_main_real)(struct fsp_fuse_env *env,
|
||||
int argc, char *argv[],
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_lib_help)(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args);
|
||||
FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new_30)(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data);
|
||||
FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new)(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_destroy)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_mount)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f, const char *mountpoint);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_unmount)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt_31)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f, int clone_fd);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f, struct fuse3_loop_config *config);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_exit)(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f);
|
||||
FSP_FUSE_API struct fuse3_context *FSP_FUSE_API_NAME(fsp_fuse3_get_context)(struct fsp_fuse_env *env);
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_main_real(int argc, char *argv[],
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_main_real)
|
||||
(fsp_fuse_env(), argc, argv, ops, opsize, data);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_lib_help(struct fuse_args *args),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_lib_help)
|
||||
(fsp_fuse_env(), args);
|
||||
})
|
||||
|
||||
#if FUSE_USE_VERSION == 30
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3 *fuse3_new_30(struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_new_30)
|
||||
(fsp_fuse_env(), args, ops, opsize, data);
|
||||
})
|
||||
#define fuse_new(args, op, size, data)\
|
||||
fuse3_new_30(args, op, size, data)
|
||||
|
||||
#else
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3 *fuse3_new(struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_new)
|
||||
(fsp_fuse_env(), args, ops, opsize, data);
|
||||
})
|
||||
#endif
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_destroy(struct fuse3 *f),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_destroy)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_mount(struct fuse3 *f, const char *mountpoint),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_mount)
|
||||
(fsp_fuse_env(), f, mountpoint);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_unmount(struct fuse3 *f),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_unmount)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_loop(struct fuse3 *f),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_loop)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
#if FUSE_USE_VERSION < 32
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_loop_mt_31(struct fuse3 *f, int clone_fd),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt_31)
|
||||
(fsp_fuse_env(), f, clone_fd);
|
||||
})
|
||||
#define fuse_loop_mt(f, clone_fd)\
|
||||
fuse3_loop_mt_31(f, clone_fd)
|
||||
|
||||
#else
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_loop_mt(struct fuse3 *f, struct fuse3_loop_config *config),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt)
|
||||
(fsp_fuse_env(), f, config);
|
||||
})
|
||||
#endif
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_exit(struct fuse3 *f),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_exit)
|
||||
(fsp_fuse_env(), f);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3_context *fuse3_get_context(void),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_get_context)
|
||||
(fsp_fuse_env());
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_getgroups(int size, fuse_gid_t list[]),
|
||||
{
|
||||
(void)size;
|
||||
(void)list;
|
||||
return -ENOSYS;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_interrupted(void),
|
||||
{
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_invalidate_path(struct fuse3 *f, const char *path),
|
||||
{
|
||||
(void)f;
|
||||
(void)path;
|
||||
return -ENOENT;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_notify_poll(struct fuse3_pollhandle *ph),
|
||||
{
|
||||
(void)ph;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_start_cleanup_thread(struct fuse3 *f),
|
||||
{
|
||||
(void)f;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_stop_cleanup_thread(struct fuse3 *f),
|
||||
{
|
||||
(void)f;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_clean_cache(struct fuse3 *f),
|
||||
{
|
||||
(void)f;
|
||||
return 600;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3_session *fuse3_get_session(struct fuse3 *f),
|
||||
{
|
||||
return (struct fuse3_session *)f;
|
||||
})
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
234
inc/fuse3/fuse_common.h
Normal file
234
inc/fuse3/fuse_common.h
Normal file
@ -0,0 +1,234 @@
|
||||
/**
|
||||
* @file fuse3/fuse_common.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* This file is derived from libfuse/include/fuse_common.h:
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef FUSE_COMMON_H_
|
||||
#define FUSE_COMMON_H_
|
||||
|
||||
#include "winfsp_fuse.h"
|
||||
#if !defined(WINFSP_DLL_INTERNAL)
|
||||
#include "fuse_opt.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FUSE_MAJOR_VERSION 3
|
||||
#define FUSE_MINOR_VERSION 2
|
||||
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
||||
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
|
||||
|
||||
#define FUSE_CAP_ASYNC_READ (1 << 0)
|
||||
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
|
||||
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
|
||||
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
||||
#define FUSE_CAP_DONT_MASK (1 << 6)
|
||||
#define FUSE_CAP_SPLICE_WRITE (1 << 7)
|
||||
#define FUSE_CAP_SPLICE_MOVE (1 << 8)
|
||||
#define FUSE_CAP_SPLICE_READ (1 << 9)
|
||||
#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
|
||||
#define FUSE_CAP_IOCTL_DIR (1 << 11)
|
||||
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
|
||||
#define FUSE_CAP_READDIRPLUS (1 << 13)
|
||||
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
|
||||
#define FUSE_CAP_ASYNC_DIO (1 << 15)
|
||||
#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
|
||||
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
|
||||
#define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
|
||||
#define FUSE_CAP_POSIX_ACL (1 << 19)
|
||||
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
|
||||
#define FUSE_CAP_ALLOCATE (1 << 27) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_EXCHANGE_DATA (1 << 28) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_CASE_INSENSITIVE (1 << 29) /* file system is case insensitive */
|
||||
#define FUSE_CAP_VOL_RENAME (1 << 30) /* reserved (OSXFUSE) */
|
||||
#define FUSE_CAP_XTIMES (1 << 31) /* reserved (OSXFUSE) */
|
||||
|
||||
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
|
||||
|
||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||
#define FUSE_IOCTL_RETRY (1 << 2)
|
||||
#define FUSE_IOCTL_DIR (1 << 4)
|
||||
#define FUSE_IOCTL_MAX_IOV 256
|
||||
|
||||
#define FUSE_BUFVEC_INIT(s) \
|
||||
((struct fuse3_bufvec){ 1, 0, 0, { {s, (enum fuse3_buf_flags)0, 0, -1, 0} } })
|
||||
|
||||
struct fuse3_file_info
|
||||
{
|
||||
int flags;
|
||||
unsigned int writepage:1;
|
||||
unsigned int direct_io:1;
|
||||
unsigned int keep_cache:1;
|
||||
unsigned int flush:1;
|
||||
unsigned int nonseekable:1;
|
||||
unsigned int flock_release:1;
|
||||
unsigned int padding:27;
|
||||
uint64_t fh;
|
||||
uint64_t lock_owner;
|
||||
uint32_t poll_events;
|
||||
};
|
||||
|
||||
struct fuse3_loop_config
|
||||
{
|
||||
int clone_fd;
|
||||
unsigned int max_idle_threads;
|
||||
};
|
||||
|
||||
struct fuse3_conn_info
|
||||
{
|
||||
unsigned proto_major;
|
||||
unsigned proto_minor;
|
||||
unsigned max_write;
|
||||
unsigned max_read;
|
||||
unsigned max_readahead;
|
||||
unsigned capable;
|
||||
unsigned want;
|
||||
unsigned max_background;
|
||||
unsigned congestion_threshold;
|
||||
unsigned time_gran;
|
||||
unsigned reserved[22];
|
||||
};
|
||||
|
||||
enum fuse3_buf_flags
|
||||
{
|
||||
FUSE_BUF_IS_FD = (1 << 1),
|
||||
FUSE_BUF_FD_SEEK = (1 << 2),
|
||||
FUSE_BUF_FD_RETRY = (1 << 3),
|
||||
};
|
||||
|
||||
enum fuse3_buf_copy_flags
|
||||
{
|
||||
FUSE_BUF_NO_SPLICE = (1 << 1),
|
||||
FUSE_BUF_FORCE_SPLICE = (1 << 2),
|
||||
FUSE_BUF_SPLICE_MOVE = (1 << 3),
|
||||
FUSE_BUF_SPLICE_NONBLOCK = (1 << 4),
|
||||
};
|
||||
|
||||
struct fuse3_buf
|
||||
{
|
||||
size_t size;
|
||||
enum fuse3_buf_flags flags;
|
||||
void *mem;
|
||||
int fd;
|
||||
fuse_off_t pos;
|
||||
};
|
||||
|
||||
struct fuse3_bufvec
|
||||
{
|
||||
size_t count;
|
||||
size_t idx;
|
||||
size_t off;
|
||||
struct fuse3_buf buf[1];
|
||||
};
|
||||
|
||||
struct fuse3_session;
|
||||
struct fuse3_pollhandle;
|
||||
struct fuse3_conn_info_opts;
|
||||
|
||||
FSP_FUSE_API struct fuse3_conn_info_opts *FSP_FUSE_API_NAME(fsp_fuse3_parse_conn_info_opts)(
|
||||
struct fsp_fuse_env *env,
|
||||
struct fuse_args *args);
|
||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_apply_conn_info_opts)(struct fsp_fuse_env *env,
|
||||
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn);
|
||||
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_version)(struct fsp_fuse_env *env);
|
||||
FSP_FUSE_API const char *FSP_FUSE_API_NAME(fsp_fuse3_pkgversion)(struct fsp_fuse_env *env);
|
||||
FSP_FUSE_API int32_t FSP_FUSE_API_NAME(fsp_fuse_ntstatus_from_errno)(struct fsp_fuse_env *env,
|
||||
int err);
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
struct fuse3_conn_info_opts* fuse3_parse_conn_info_opts(
|
||||
struct fuse_args *args),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_parse_conn_info_opts)
|
||||
(fsp_fuse_env(), args);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_apply_conn_info_opts(
|
||||
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn),
|
||||
{
|
||||
FSP_FUSE_API_CALL(fsp_fuse3_apply_conn_info_opts)
|
||||
(fsp_fuse_env(), opts, conn);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_version(void),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_version)
|
||||
(fsp_fuse_env());
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
const char *fuse3_pkgversion(void),
|
||||
{
|
||||
return FSP_FUSE_API_CALL(fsp_fuse3_pkgversion)
|
||||
(fsp_fuse_env());
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_pollhandle_destroy(struct fuse3_pollhandle *ph),
|
||||
{
|
||||
(void)ph;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
size_t fuse3_buf_size(const struct fuse3_bufvec *bufv),
|
||||
{
|
||||
(void)bufv;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
ssize_t fuse3_buf_copy(struct fuse3_bufvec *dst, struct fuse3_bufvec *src,
|
||||
enum fuse3_buf_copy_flags flags),
|
||||
{
|
||||
(void)dst;
|
||||
(void)src;
|
||||
(void)flags;
|
||||
return 0;
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_daemonize(int foreground),
|
||||
{
|
||||
return fsp_fuse_daemonize(foreground);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
int fuse3_set_signal_handlers(struct fuse3_session *se),
|
||||
{
|
||||
return fsp_fuse_set_signal_handlers(se);
|
||||
})
|
||||
|
||||
FSP_FUSE_SYM(
|
||||
void fuse3_remove_signal_handlers(struct fuse3_session *se),
|
||||
{
|
||||
(void)se;
|
||||
fsp_fuse_set_signal_handlers(0);
|
||||
})
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
19
inc/fuse3/fuse_opt.h
Normal file
19
inc/fuse3/fuse_opt.h
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @file fuse3/fuse_opt.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include "../fuse/fuse_opt.h"
|
78
inc/fuse3/winfsp_fuse.h
Normal file
78
inc/fuse3/winfsp_fuse.h
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file fuse3/winfsp_fuse.h
|
||||
* WinFsp FUSE3 compatible API.
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef FUSE3_WINFSP_FUSE_H_INCLUDED
|
||||
#define FUSE3_WINFSP_FUSE_H_INCLUDED
|
||||
|
||||
#include "../fuse/winfsp_fuse.h"
|
||||
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
typedef intptr_t ssize_t;
|
||||
#endif
|
||||
|
||||
#if !defined(WINFSP_DLL_INTERNAL)
|
||||
#define fuse3 fuse
|
||||
#define fuse3_apply_conn_info_opts fuse_apply_conn_info_opts
|
||||
#define fuse3_buf fuse_buf
|
||||
#define fuse3_buf_copy fuse_buf_copy
|
||||
#define fuse3_buf_copy_flags fuse_buf_copy_flags
|
||||
#define fuse3_buf_flags fuse_buf_flags
|
||||
#define fuse3_buf_size fuse_buf_size
|
||||
#define fuse3_bufvec fuse_bufvec
|
||||
#define fuse3_clean_cache fuse_clean_cache
|
||||
#define fuse3_config fuse_config
|
||||
#define fuse3_conn_info fuse_conn_info
|
||||
#define fuse3_conn_info_opts fuse_conn_info_opts
|
||||
#define fuse3_context fuse_context
|
||||
#define fuse3_daemonize fuse_daemonize
|
||||
#define fuse3_destroy fuse_destroy
|
||||
#define fuse3_exit fuse_exit
|
||||
#define fuse3_file_info fuse_file_info
|
||||
#define fuse3_fill_dir_flags fuse_fill_dir_flags
|
||||
#define fuse3_fill_dir_t fuse_fill_dir_t
|
||||
#define fuse3_get_context fuse_get_context
|
||||
#define fuse3_get_session fuse_get_session
|
||||
#define fuse3_getgroups fuse_getgroups
|
||||
#define fuse3_interrupted fuse_interrupted
|
||||
#define fuse3_invalidate_path fuse_invalidate_path
|
||||
#define fuse3_lib_help fuse_lib_help
|
||||
#define fuse3_loop fuse_loop
|
||||
#define fuse3_loop_config fuse_loop_config
|
||||
#define fuse3_loop_mt fuse_loop_mt
|
||||
#define fuse3_loop_mt_31 fuse_loop_mt_31
|
||||
#define fuse3_main_real fuse_main_real
|
||||
#define fuse3_mount fuse_mount
|
||||
#define fuse3_new fuse_new
|
||||
#define fuse3_new_30 fuse_new_30
|
||||
#define fuse3_notify_poll fuse_notify_poll
|
||||
#define fuse3_operations fuse_operations
|
||||
#define fuse3_parse_conn_info_opts fuse_parse_conn_info_opts
|
||||
#define fuse3_pkgversion fuse_pkgversion
|
||||
#define fuse3_pollhandle fuse_pollhandle
|
||||
#define fuse3_pollhandle_destroy fuse_pollhandle_destroy
|
||||
#define fuse3_readdir_flags fuse_readdir_flags
|
||||
#define fuse3_remove_signal_handlers fuse_remove_signal_handlers
|
||||
#define fuse3_session fuse_session
|
||||
#define fuse3_set_signal_handlers fuse_set_signal_handlers
|
||||
#define fuse3_start_cleanup_thread fuse_start_cleanup_thread
|
||||
#define fuse3_stop_cleanup_thread fuse_stop_cleanup_thread
|
||||
#define fuse3_unmount fuse_unmount
|
||||
#define fuse3_version fuse_version
|
||||
#endif
|
||||
|
||||
#endif
|
@ -34,6 +34,7 @@ extern "C" {
|
||||
#define FSP_FSCTL_DRIVER_NAME "WinFsp"
|
||||
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
|
||||
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
|
||||
#define FSP_FSCTL_MUP_DEVICE_NAME "WinFsp.Mup"
|
||||
|
||||
// {6F9D25FA-6DEE-4A9D-80F5-E98E14F35E54}
|
||||
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid =
|
||||
@ -81,6 +82,8 @@ FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
|
||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((T) & 0xffffffff))
|
||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff))
|
||||
|
||||
#define FSP_FSCTL_DEVICECONTROL_SIZEMAX (4 * 1024) /* must be < FSP_FSCTL_TRANSACT_{REQ,RSP}_SIZEMAX */
|
||||
|
||||
/* marshalling */
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||
@ -123,43 +126,66 @@ enum
|
||||
FspFsctlIrpCapacityMaximum = 1000,
|
||||
FspFsctlIrpCapacityDefault = 1000,
|
||||
};
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN\
|
||||
UINT16 Version; /* set to 0 or sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
|
||||
/* volume information */\
|
||||
UINT16 SectorSize;\
|
||||
UINT16 SectorsPerAllocationUnit;\
|
||||
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */\
|
||||
UINT64 VolumeCreationTime;\
|
||||
UINT32 VolumeSerialNumber;\
|
||||
/* I/O timeouts, capacity, etc. */\
|
||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */\
|
||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */\
|
||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/\
|
||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */\
|
||||
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */\
|
||||
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */\
|
||||
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */\
|
||||
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */\
|
||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */\
|
||||
UINT32 ReparsePoints:1; /* file system supports reparse points */\
|
||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */\
|
||||
UINT32 NamedStreams:1; /* file system supports named streams */\
|
||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */\
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */\
|
||||
UINT32 ReadOnlyVolume:1;\
|
||||
/* kernel-mode flags */\
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */\
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */\
|
||||
UINT32 AlwaysUseDoubleBuffering:1;\
|
||||
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */\
|
||||
UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */\
|
||||
UINT32 DeviceControl:1; /* support user-mode ioctl handling */\
|
||||
/* user-mode flags */\
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */\
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */\
|
||||
UINT32 UmReservedFlags:6;\
|
||||
/* additional kernel-mode flags */\
|
||||
UINT32 KmReservedFlags:8;\
|
||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
||||
/* additional fields; specify .Version == sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
|
||||
UINT32 VolumeInfoTimeoutValid:1; /* VolumeInfoTimeout field is valid */\
|
||||
UINT32 DirInfoTimeoutValid:1; /* DirInfoTimeout field is valid */\
|
||||
UINT32 SecurityTimeoutValid:1; /* SecurityTimeout field is valid*/\
|
||||
UINT32 StreamInfoTimeoutValid:1; /* StreamInfoTimeout field is valid */\
|
||||
UINT32 KmAdditionalReservedFlags:28;\
|
||||
UINT32 VolumeInfoTimeout; /* volume info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 DirInfoTimeout; /* dir info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 Reserved32[3];\
|
||||
UINT64 Reserved64[2];
|
||||
typedef struct
|
||||
{
|
||||
UINT16 Version; /* set to 0 */
|
||||
/* volume information */
|
||||
UINT16 SectorSize;
|
||||
UINT16 SectorsPerAllocationUnit;
|
||||
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */
|
||||
UINT64 VolumeCreationTime;
|
||||
UINT32 VolumeSerialNumber;
|
||||
/* I/O timeouts, capacity, etc. */
|
||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */
|
||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */
|
||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/
|
||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */
|
||||
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */
|
||||
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */
|
||||
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */
|
||||
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */
|
||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
|
||||
UINT32 ReparsePoints:1; /* file system supports reparse points */
|
||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */
|
||||
UINT32 NamedStreams:1; /* file system supports named streams */
|
||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
|
||||
UINT32 ReadOnlyVolume:1;
|
||||
/* kernel-mode flags */
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */
|
||||
UINT32 AlwaysUseDoubleBuffering:1;
|
||||
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */
|
||||
UINT32 KmReservedFlags:2;
|
||||
/* user-mode flags */
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
|
||||
UINT32 UmReservedFlags:14;
|
||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */
|
||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
|
||||
} FSP_FSCTL_VOLUME_PARAMS_V0;
|
||||
typedef struct
|
||||
{
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
|
||||
FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN
|
||||
} FSP_FSCTL_VOLUME_PARAMS;
|
||||
typedef struct
|
||||
{
|
||||
@ -359,6 +385,14 @@ typedef struct
|
||||
UINT16 TargetOnFileSystem; /* the target of the symbolic link is on this file system */
|
||||
} FileSystemControl;
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext;
|
||||
UINT64 UserContext2;
|
||||
UINT32 IoControlCode;
|
||||
FSP_FSCTL_TRANSACT_BUF Buffer;
|
||||
UINT32 OutputLength;
|
||||
} DeviceControl;
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext;
|
||||
UINT64 UserContext2;
|
||||
@ -444,6 +478,10 @@ typedef struct
|
||||
FSP_FSCTL_TRANSACT_BUF Buffer;
|
||||
} FileSystemControl;
|
||||
struct
|
||||
{
|
||||
FSP_FSCTL_TRANSACT_BUF Buffer;
|
||||
} DeviceControl;
|
||||
struct
|
||||
{
|
||||
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
|
||||
} QuerySecurity;
|
||||
|
276
inc/winfsp/launch.h
Normal file
276
inc/winfsp/launch.h
Normal file
@ -0,0 +1,276 @@
|
||||
/**
|
||||
* @file winfsp/launch.h
|
||||
* WinFsp Launch API.
|
||||
*
|
||||
* In order to use the WinFsp Launch API a program must include <winfsp/launch.h>
|
||||
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_LAUNCH_H_INCLUDED
|
||||
#define WINFSP_LAUNCH_H_INCLUDED
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FSP_LAUNCH_REGKEY "Software\\WinFsp\\Services"
|
||||
#define FSP_LAUNCH_REGKEY_WOW64 KEY_WOW64_32KEY
|
||||
|
||||
#define FSP_LAUNCH_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||
#define FSP_LAUNCH_PIPE_BUFFER_SIZE 4096
|
||||
#define FSP_LAUNCH_PIPE_OWNER ((PSID)WinLocalSystemSid)
|
||||
|
||||
/*
|
||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||
* pipe instances.
|
||||
*/
|
||||
#define FSP_LAUNCH_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
|
||||
|
||||
/*
|
||||
* The default service instance SDDL gives full access to LocalSystem and Administrators.
|
||||
* The only possible service instance rights are as follows:
|
||||
* RP SERVICE_START
|
||||
* WP SERVICE_STOP
|
||||
* LC SERVICE_QUERY_STATUS
|
||||
*
|
||||
* To create a service that can be started, stopped or queried by Everyone, you can set
|
||||
* the following SDDL:
|
||||
* D:P(A;;RPWPLC;;;WD)
|
||||
*/
|
||||
#define FSP_LAUNCH_SERVICE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
|
||||
#define FSP_LAUNCH_SERVICE_WORLD_SDDL "D:P(A;;RPWPLC;;;WD)"
|
||||
|
||||
enum
|
||||
{
|
||||
FspLaunchCmdStart = 'S', /* requires: SERVICE_START */
|
||||
FspLaunchCmdStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||
FspLaunchCmdStop = 'T', /* requires: SERVICE_STOP */
|
||||
FspLaunchCmdGetInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||
FspLaunchCmdGetNameList = 'L', /* requires: none*/
|
||||
FspLaunchCmdDefineDosDevice = 'D', /* internal: do not use! */
|
||||
FspLaunchCmdQuit = 'Q', /* DEBUG version only */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FspLaunchCmdSuccess = '$',
|
||||
FspLaunchCmdFailure = '!',
|
||||
};
|
||||
|
||||
/**
|
||||
* @group Launch Control
|
||||
*/
|
||||
/**
|
||||
* Call launcher pipe.
|
||||
*
|
||||
* This function is used to send a command to the launcher and receive a response.
|
||||
*
|
||||
* @param Command
|
||||
* Launcher command to send. For example, the 'L' launcher command instructs
|
||||
* the launcher to list all running service instances.
|
||||
* @param Argc
|
||||
* Command argument count. May be 0.
|
||||
* @param Argv
|
||||
* Command argument array. May be NULL.
|
||||
* @param Argl
|
||||
* Command argument length array. May be NULL. If this is NULL all command arguments
|
||||
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
|
||||
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError);
|
||||
/**
|
||||
* Start a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to start.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to start.
|
||||
* @param Argc
|
||||
* Service instance argument count. May be 0.
|
||||
* @param Argv
|
||||
* Service instance argument array. May be NULL.
|
||||
* @param HasSecret
|
||||
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
|
||||
* Secrets are passed to service instances through standard input rather than the command
|
||||
* line.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Stop a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Get information about a service instance.
|
||||
*
|
||||
* The information is a list of NULL-terminated strings: the class name of the service instance,
|
||||
* the instance name of the service instance and the full command line used to start the service
|
||||
* instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* List service instances.
|
||||
*
|
||||
* The information is a list of pairs of NULL-terminated strings. Each pair contains the class
|
||||
* name and instance name of a service instance. All currently running service instances are
|
||||
* listed.
|
||||
*
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
|
||||
/**
|
||||
* @group Service Registry
|
||||
*/
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||
/**
|
||||
* Service registry record.
|
||||
*/
|
||||
typedef struct _FSP_LAUNCH_REG_RECORD
|
||||
{
|
||||
PWSTR Agent;
|
||||
PWSTR Executable;
|
||||
PWSTR CommandLine;
|
||||
PWSTR WorkDirectory;
|
||||
PWSTR RunAs;
|
||||
PWSTR Security;
|
||||
PVOID Reserved0[6];
|
||||
ULONG JobControl;
|
||||
ULONG Credentials;
|
||||
ULONG Reserved1[6];
|
||||
UINT8 Buffer[];
|
||||
} FSP_LAUNCH_REG_RECORD;
|
||||
#pragma warning(pop)
|
||||
/**
|
||||
* Add/change/delete a service registry record.
|
||||
*
|
||||
* @param ClassName
|
||||
* The service class name.
|
||||
* @param Record
|
||||
* The record to set in the registry. If NULL, the registry record is deleted.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record);
|
||||
/**
|
||||
* Get a service registry record.
|
||||
*
|
||||
* @param ClassName
|
||||
* The service class name.
|
||||
* @param Agent
|
||||
* The name of the agent that is retrieving the service record. This API matches
|
||||
* the supplied Agent against the Agent in the service record and it only returns
|
||||
* the record if they match. Pass NULL to match any Agent.
|
||||
* @param PRecord
|
||||
* Pointer to a record pointer. Memory for the service record will be allocated
|
||||
* and a pointer to it will be stored at this address. This memory must be later
|
||||
* freed using FspLaunchRegFreeRecord.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code.
|
||||
* @see
|
||||
* FspLaunchRegFreeRecord
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName, PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord);
|
||||
/**
|
||||
* Free a service registry record.
|
||||
*
|
||||
* @param Record
|
||||
* The service record to free.
|
||||
* @see
|
||||
* FspLaunchRegGetRecord
|
||||
*/
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -822,12 +822,41 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
NTSTATUS (*GetDirInfoByName)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, PWSTR FileName,
|
||||
FSP_FSCTL_DIR_INFO *DirInfo);
|
||||
/**
|
||||
* Process control code.
|
||||
*
|
||||
* This function is called when a program uses the DeviceIoControl API.
|
||||
*
|
||||
* @param FileSystem
|
||||
* The file system on which this request is posted.
|
||||
* @param FileContext
|
||||
* The file context of the file or directory to be controled.
|
||||
* @param ControlCode
|
||||
* The control code for the operation. This code must have a DeviceType with bit
|
||||
* 0x8000 set and must have a TransferType of METHOD_BUFFERED.
|
||||
* @param InputBuffer
|
||||
* Pointer to a buffer that contains the input data.
|
||||
* @param InputBufferLength
|
||||
* Input data length.
|
||||
* @param OutputBuffer
|
||||
* Pointer to a buffer that will receive the output data.
|
||||
* @param OutputBufferLength
|
||||
* Output data length.
|
||||
* @param PBytesTransferred [out]
|
||||
* Pointer to a memory location that will receive the actual number of bytes transferred.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code.
|
||||
*/
|
||||
NTSTATUS (*Control)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, UINT32 ControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength,
|
||||
PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred);
|
||||
|
||||
/*
|
||||
* This ensures that this interface will always contain 64 function pointers.
|
||||
* Please update when changing the interface as it is important for future compatibility.
|
||||
*/
|
||||
NTSTATUS (*Reserved[39])();
|
||||
NTSTATUS (*Reserved[38])();
|
||||
} FSP_FILE_SYSTEM_INTERFACE;
|
||||
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||
@ -1141,6 +1170,8 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpDeviceControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
@ -1703,133 +1734,6 @@ FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem);
|
||||
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...);
|
||||
FSP_API VOID FspServiceLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||
|
||||
/**
|
||||
* @group Launch Control
|
||||
*/
|
||||
/**
|
||||
* Call launcher pipe.
|
||||
*
|
||||
* This function is used to send a command to the launcher and receive a response.
|
||||
*
|
||||
* @param Command
|
||||
* Launcher command to send. For example, the 'L' launcher command instructs
|
||||
* the launcher to list all running service instances.
|
||||
* @param Argc
|
||||
* Command argument count. May be 0.
|
||||
* @param Argv
|
||||
* Command argument array. May be NULL.
|
||||
* @param Argl
|
||||
* Command argument length array. May be NULL. If this is NULL all command arguments
|
||||
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
|
||||
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError);
|
||||
/**
|
||||
* Start a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to start.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to start.
|
||||
* @param Argc
|
||||
* Service instance argument count. May be 0.
|
||||
* @param Argv
|
||||
* Service instance argument array. May be NULL.
|
||||
* @param HasSecret
|
||||
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
|
||||
* Secrets are passed to service instances through standard input rather than the command
|
||||
* line.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Stop a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Get information about a service instance.
|
||||
*
|
||||
* The information is a list of NULL-terminated strings: the class name of the service instance,
|
||||
* the instance name of the service instance and the full command line used to start the service
|
||||
* instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* List service instances.
|
||||
*
|
||||
* The information is a list of pairs of NULL-terminated strings. Each pair contains the class
|
||||
* name and instance name of a service instance. All currently running service instances are
|
||||
* listed.
|
||||
*
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
|
1
opt/cygfuse/.gitignore
vendored
Normal file
1
opt/cygfuse/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
build
|
75
opt/cygfuse/Makefile
Normal file → Executable file
75
opt/cygfuse/Makefile
Normal file → Executable file
@ -1,30 +1,59 @@
|
||||
Version = $(shell sed -n '/^VERSION=/s/VERSION=\(.*\)/\1/p' fuse.cygport)
|
||||
#Debug = -g
|
||||
Arch = $(shell uname -m)
|
||||
Build = build
|
||||
|
||||
cygfuse-$(Version).dll libfuse-$(Version).dll.a fuse.pc: cygfuse.c fuse.pc.in
|
||||
gcc $(Debug) -shared -o cygfuse-$(Version).dll -Wl,--out-implib=libfuse-$(Version).dll.a -I../../inc/fuse cygfuse.c
|
||||
[ -n "$(Debug)" ] || strip cygfuse-$(Version).dll
|
||||
sed "s/@Version@/$(Version)/g" fuse.pc.in > fuse.pc
|
||||
.PHONY: usage
|
||||
usage:
|
||||
@echo "make cygport|dist" 1>&2
|
||||
@exit 2
|
||||
|
||||
cygfuse-test.exe: cygfuse-test.c cygfuse-$(Version).dll libfuse-$(Version).dll.a
|
||||
gcc $(Debug) -o cygfuse-test.exe -I../../inc/fuse -DCYGFUSE cygfuse-test.c -L$(PWD) -lfuse-$(Version)
|
||||
.PHONY: cygport dist clean
|
||||
cygport: clean cygport2 cygport3
|
||||
dist: cygport dist2 dist3
|
||||
clean:
|
||||
rm -rf $(Build)
|
||||
|
||||
cygport:
|
||||
git clean -dfx
|
||||
(\
|
||||
cd `git rev-parse --show-toplevel` &&\
|
||||
Stash=`git stash create` &&\
|
||||
git archive --prefix=winfsp-work/ --format=tar.gz $${Stash:-HEAD}\
|
||||
> opt/cygfuse/winfsp-work.tar.gz\
|
||||
)
|
||||
CYGPORT_SRC_URI=winfsp-work.tar.gz CYGPORT_SRC_DIR=winfsp-work cygport fuse.cygport download prep compile install package
|
||||
.PHONY: cygport2
|
||||
cygport2: $(Build)/winfsp-work-$(Arch).tar.gz
|
||||
cp fuse/fuse.cygport $(Build)/fuse.cygport
|
||||
CYGPORT_SRC_URI=winfsp-work-$(Arch).tar.gz CYGPORT_SRC_DIR=winfsp-work-$(Arch) \
|
||||
cygport $(Build)/fuse.cygport download prep compile install package
|
||||
|
||||
dist: cygport
|
||||
case $(shell uname -m) in \
|
||||
x86_64)\
|
||||
.PHONY: cygport3
|
||||
cygport3: $(Build)/winfsp-work-$(Arch).tar.gz
|
||||
cp fuse3/fuse3.cygport $(Build)/fuse3.cygport
|
||||
CYGPORT_SRC_URI=winfsp-work-$(Arch).tar.gz CYGPORT_SRC_DIR=winfsp-work-$(Arch) \
|
||||
cygport $(Build)/fuse3.cygport download prep compile install package
|
||||
|
||||
$(Build)/winfsp-work-$(Arch).tar.gz:
|
||||
mkdir -p $(Build)
|
||||
( \
|
||||
cd `git rev-parse --show-toplevel` && \
|
||||
Stash=`git stash create` && \
|
||||
git archive --prefix=winfsp-work-$(Arch)/ --format=tar.gz $${Stash:-HEAD} \
|
||||
) > $(Build)/winfsp-work-$(Arch).tar.gz
|
||||
|
||||
.PHONY: dist2
|
||||
dist2: cygport2
|
||||
case $(Arch) in \
|
||||
x86_64) \
|
||||
mkdir -p dist/x64 && \
|
||||
cp fuse-*/dist/fuse/fuse-*[0-9].tar.xz dist/x64 ;;\
|
||||
*)\
|
||||
rm -f dist/x64/fuse-*[0-9].tar.xz && \
|
||||
cp build/fuse-*[0-9].$(Arch)/dist/fuse/fuse-*[0-9].tar.xz dist/x64 ;; \
|
||||
i686) \
|
||||
mkdir -p dist/x86 && \
|
||||
cp fuse-*/dist/fuse/fuse-*[0-9].tar.xz dist/x86 ;;\
|
||||
rm -f dist/x86/fuse-*[0-9].tar.xz && \
|
||||
cp build/fuse-*[0-9].$(Arch)/dist/fuse/fuse-*[0-9].tar.xz dist/x86 ;; \
|
||||
esac
|
||||
|
||||
.PHONY: dist3
|
||||
dist3: cygport3
|
||||
case $(Arch) in \
|
||||
x86_64) \
|
||||
mkdir -p dist/x64 && \
|
||||
rm -f dist/x64/fuse3-*[0-9].tar.xz && \
|
||||
cp build/fuse3-*[0-9].$(Arch)/dist/fuse3/fuse3-*[0-9].tar.xz dist/x64 ;; \
|
||||
i686) \
|
||||
mkdir -p dist/x86 && \
|
||||
rm -f dist/x86/fuse3-*[0-9].tar.xz && \
|
||||
cp build/fuse3-*[0-9].$(Arch)/dist/fuse3/fuse3-*[0-9].tar.xz dist/x86 ;; \
|
||||
esac
|
||||
|
12
opt/cygfuse/dist/install.sh
vendored
12
opt/cygfuse/dist/install.sh
vendored
@ -1,8 +1,16 @@
|
||||
cd "$(dirname "$0")"
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
tar -C/ -xaf x64/fuse-2.8-*.tar.xz ;;
|
||||
tar -C/ -xaf x64/fuse-*.tar.xz
|
||||
tar -C/ -xaf x64/fuse3-*.tar.xz
|
||||
;;
|
||||
i686)
|
||||
tar -C/ -xaf x86/fuse-*.tar.xz
|
||||
tar -C/ -xaf x86/fuse3-*.tar.xz
|
||||
;;
|
||||
*)
|
||||
tar -C/ -xaf x86/fuse-2.8-*.tar.xz ;;
|
||||
echo unsupported architecture 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo FUSE for Cygwin installed.
|
||||
|
12
opt/cygfuse/dist/uninstall.sh
vendored
12
opt/cygfuse/dist/uninstall.sh
vendored
@ -1,8 +1,16 @@
|
||||
cd "$(dirname "$0")"
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
tar -taf x64/fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;;
|
||||
tar -taf x64/fuse-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
||||
tar -taf x64/fuse3-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
||||
;;
|
||||
i686)
|
||||
tar -taf x86/fuse-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
||||
tar -taf x86/fuse3-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
||||
;;
|
||||
*)
|
||||
tar -taf x86/fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;;
|
||||
echo unsupported architecture 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo FUSE for Cygwin uninstalled.
|
||||
|
BIN
opt/cygfuse/dist/x64/fuse-2.8-7.tar.xz
vendored
BIN
opt/cygfuse/dist/x64/fuse-2.8-7.tar.xz
vendored
Binary file not shown.
BIN
opt/cygfuse/dist/x64/fuse-2.8-9.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x64/fuse-2.8-9.tar.xz
vendored
Normal file
Binary file not shown.
BIN
opt/cygfuse/dist/x64/fuse3-3.2-1.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x64/fuse3-3.2-1.tar.xz
vendored
Normal file
Binary file not shown.
BIN
opt/cygfuse/dist/x86/fuse-2.8-7.tar.xz
vendored
BIN
opt/cygfuse/dist/x86/fuse-2.8-7.tar.xz
vendored
Binary file not shown.
BIN
opt/cygfuse/dist/x86/fuse-2.8-9.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x86/fuse-2.8-9.tar.xz
vendored
Normal file
Binary file not shown.
BIN
opt/cygfuse/dist/x86/fuse3-3.2-1.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x86/fuse3-3.2-1.tar.xz
vendored
Normal file
Binary file not shown.
29
opt/cygfuse/fuse/Makefile
Normal file
29
opt/cygfuse/fuse/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
Version = $(shell sed -n '/^VERSION=/s/VERSION=\(.*\)/\1/p' fuse.cygport)
|
||||
Arch = $(shell uname -m)
|
||||
Build = build/$(Arch)
|
||||
#Debug = -g
|
||||
|
||||
.PHONY: build test
|
||||
build: $(Build)/cygfuse-$(Version).dll $(Build)/fuse.pc
|
||||
test: $(Build)/cygfuse-test.exe
|
||||
|
||||
$(Build)/cygfuse-$(Version).dll: cygfuse.c fuse.cygport
|
||||
@mkdir -p $(Build)
|
||||
gcc $(Debug) \
|
||||
-shared -o $(Build)/cygfuse-$(Version).dll \
|
||||
-Wl,--out-implib=$(Build)/libfuse-$(Version).dll.a \
|
||||
-I../../../inc/fuse \
|
||||
cygfuse.c
|
||||
[ -n "$(Debug)" ] || strip $(Build)/cygfuse-$(Version).dll
|
||||
|
||||
$(Build)/fuse.pc: fuse.pc.in fuse.cygport
|
||||
@mkdir -p $(Build)
|
||||
sed "s/@Version@/$(Version)/g" fuse.pc.in > $(Build)/fuse.pc
|
||||
|
||||
$(Build)/cygfuse-test.exe: cygfuse-test.c $(Build)/cygfuse-$(Version).dll
|
||||
@mkdir -p $(Build)
|
||||
gcc $(Debug) \
|
||||
-o $(Build)/cygfuse-test.exe \
|
||||
-I../../../inc/fuse -DCYGFUSE \
|
||||
cygfuse-test.c \
|
||||
-L$(PWD)/$(Build) -lfuse-$(Version)
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file cygfuse/cygfuse.c
|
||||
* @file fuse/cygfuse.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
@ -1,9 +1,9 @@
|
||||
NAME="fuse"
|
||||
VERSION=2.8
|
||||
RELEASE=7
|
||||
RELEASE=9
|
||||
CATEGORY="Utils"
|
||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||
SUMMARY="WinFsp FUSE compatibility layer"
|
||||
DESCRIPTION="Enables FUSE file systems to be run on Cygwin."
|
||||
HOMEPAGE="http://www.secfs.net/winfsp/"
|
||||
|
||||
SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/billziss-gh/winfsp/archive/master.tar.gz"}
|
||||
@ -12,7 +12,7 @@ SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master}
|
||||
src_compile()
|
||||
{
|
||||
lndirs
|
||||
cd ${B}/opt/cygfuse
|
||||
cd ${B}/opt/cygfuse/fuse
|
||||
make
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ src_install()
|
||||
doinclude fuse_opt.h
|
||||
doinclude winfsp_fuse.h
|
||||
|
||||
cd ${B}/opt/cygfuse
|
||||
cd ${B}/opt/cygfuse/fuse/build/$(ARCH)
|
||||
dobin cygfuse-${VERSION}.dll
|
||||
dolib libfuse-${VERSION}.dll.a
|
||||
dosym libfuse-${VERSION}.dll.a /usr/lib/libfuse.dll.a
|
29
opt/cygfuse/fuse3/Makefile
Normal file
29
opt/cygfuse/fuse3/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
Version = $(shell sed -n '/^VERSION=/s/VERSION=\(.*\)/\1/p' fuse3.cygport)
|
||||
Arch = $(shell uname -m)
|
||||
Build = build/$(Arch)
|
||||
#Debug = -g
|
||||
|
||||
.PHONY: build test
|
||||
build: $(Build)/cygfuse-$(Version).dll $(Build)/fuse3.pc
|
||||
test: $(Build)/cygfuse-test.exe
|
||||
|
||||
$(Build)/cygfuse-$(Version).dll: cygfuse.c fuse3.cygport
|
||||
@mkdir -p $(Build)
|
||||
gcc $(Debug) \
|
||||
-shared -o $(Build)/cygfuse-$(Version).dll \
|
||||
-Wl,--out-implib=$(Build)/libfuse-$(Version).dll.a \
|
||||
-I../../../inc/fuse3 \
|
||||
cygfuse.c
|
||||
[ -n "$(Debug)" ] || strip $(Build)/cygfuse-$(Version).dll
|
||||
|
||||
$(Build)/fuse3.pc: fuse3.pc.in fuse3.cygport
|
||||
@mkdir -p $(Build)
|
||||
sed "s/@Version@/$(Version)/g" fuse3.pc.in > $(Build)/fuse3.pc
|
||||
|
||||
$(Build)/cygfuse-test.exe: cygfuse-test.c $(Build)/cygfuse-$(Version).dll
|
||||
@mkdir -p $(Build)
|
||||
gcc $(Debug) \
|
||||
-o $(Build)/cygfuse-test.exe \
|
||||
-I../../../inc/fuse3 -DCYGFUSE \
|
||||
cygfuse-test.c \
|
||||
-L$(PWD)/$(Build) -lfuse-$(Version)
|
6
opt/cygfuse/fuse3/cygfuse-test.c
Normal file
6
opt/cygfuse/fuse3/cygfuse-test.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <fuse.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
return !(FUSE_VERSION == fuse_version());
|
||||
}
|
169
opt/cygfuse/fuse3/cygfuse.c
Normal file
169
opt/cygfuse/fuse3/cygfuse.c
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* @file fuse3/cygfuse.c
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/cygwin.h>
|
||||
|
||||
static void *cygfuse_init_slow(int force);
|
||||
static void *cygfuse_init_winfsp();
|
||||
|
||||
static pthread_mutex_t cygfuse_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void *cygfuse_handle = 0;
|
||||
|
||||
static inline void *cygfuse_init_fast(void)
|
||||
{
|
||||
void *handle = cygfuse_handle;
|
||||
__sync_synchronize(); /* memory barrier */
|
||||
if (0 == handle)
|
||||
handle = cygfuse_init_slow(0);
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void *cygfuse_init_slow(int force)
|
||||
{
|
||||
void *handle;
|
||||
pthread_mutex_lock(&cygfuse_mutex);
|
||||
handle = cygfuse_handle;
|
||||
if (force || 0 == handle)
|
||||
{
|
||||
handle = cygfuse_init_winfsp();
|
||||
__sync_synchronize(); /* memory barrier */
|
||||
cygfuse_handle = handle;
|
||||
}
|
||||
pthread_mutex_unlock(&cygfuse_mutex);
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unfortunately Cygwin fork is very fragile and cannot even correctly
|
||||
* handle dlopen'ed DLL's if they are native (rather than Cygwin ones).
|
||||
*
|
||||
* So we have this very nasty hack where we reset the dlopen'ed handle
|
||||
* immediately after daemonization. This will force cygfuse_init() to
|
||||
* reload the WinFsp DLL and reset all API pointers in the daemonized
|
||||
* process.
|
||||
*/
|
||||
static inline int cygfuse_daemon(int nochdir, int noclose)
|
||||
{
|
||||
if (-1 == daemon(nochdir, noclose))
|
||||
return -1;
|
||||
|
||||
/* force reload of WinFsp DLL to workaround fork() problems */
|
||||
cygfuse_init_slow(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define daemon cygfuse_daemon
|
||||
|
||||
#define FSP_FUSE_API static
|
||||
#define FSP_FUSE_API_NAME(api) (* pfn_ ## api)
|
||||
#define FSP_FUSE_API_CALL(api) (cygfuse_init_fast(), pfn_ ## api)
|
||||
#define FSP_FUSE_SYM(proto, ...) __attribute__ ((visibility("default"))) proto { __VA_ARGS__ }
|
||||
#include <fuse_common.h>
|
||||
#include <fuse.h>
|
||||
#include <fuse_opt.h>
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define CYGFUSE_WINFSP_NAME "winfsp-x64.dll"
|
||||
#else
|
||||
#define CYGFUSE_WINFSP_NAME "winfsp-x86.dll"
|
||||
#endif
|
||||
#define CYGFUSE_WINFSP_PATH "bin\\" CYGFUSE_WINFSP_NAME
|
||||
#define CYGFUSE_GET_API(h, n) \
|
||||
if (0 == (*(void **)&(pfn_ ## n) = dlsym(h, #n)))\
|
||||
return cygfuse_init_fail();
|
||||
|
||||
static void *cygfuse_init_fail();
|
||||
static void *cygfuse_init_winfsp()
|
||||
{
|
||||
void *h;
|
||||
|
||||
h = dlopen(CYGFUSE_WINFSP_NAME, RTLD_NOW);
|
||||
if (0 == h)
|
||||
{
|
||||
char winpath[260], *psxpath;
|
||||
int regfd, bytes;
|
||||
|
||||
regfd = open("/proc/registry32/HKEY_LOCAL_MACHINE/Software/WinFsp/InstallDir", O_RDONLY);
|
||||
if (-1 == regfd)
|
||||
return cygfuse_init_fail();
|
||||
|
||||
bytes = read(regfd, winpath, sizeof winpath - sizeof CYGFUSE_WINFSP_PATH);
|
||||
close(regfd);
|
||||
if (-1 == bytes || 0 == bytes)
|
||||
return cygfuse_init_fail();
|
||||
|
||||
if ('\0' == winpath[bytes - 1])
|
||||
bytes--;
|
||||
memcpy(winpath + bytes, CYGFUSE_WINFSP_PATH, sizeof CYGFUSE_WINFSP_PATH);
|
||||
|
||||
psxpath = (char *)cygwin_create_path(CCP_WIN_A_TO_POSIX | CCP_PROC_CYGDRIVE, winpath);
|
||||
if (0 == psxpath)
|
||||
return cygfuse_init_fail();
|
||||
|
||||
h = dlopen(psxpath, RTLD_NOW);
|
||||
free(psxpath);
|
||||
if (0 == h)
|
||||
return cygfuse_init_fail();
|
||||
}
|
||||
|
||||
/* winfsp_fuse.h */
|
||||
CYGFUSE_GET_API(h, fsp_fuse_signal_handler);
|
||||
|
||||
/* fuse_common.h */
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_parse_conn_info_opts);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_apply_conn_info_opts);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_version);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_pkgversion);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_ntstatus_from_errno);
|
||||
|
||||
/* fuse.h */
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_main_real);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_lib_help);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_new_30);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_new);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_destroy);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_mount);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_unmount);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_loop);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_loop_mt_31);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_loop_mt);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_exit);
|
||||
CYGFUSE_GET_API(h, fsp_fuse3_get_context);
|
||||
|
||||
/* fuse_opt.h */
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_parse);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_add_arg);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_insert_arg);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_free_args);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_add_opt);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_add_opt_escaped);
|
||||
CYGFUSE_GET_API(h, fsp_fuse_opt_match);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void *cygfuse_init_fail()
|
||||
{
|
||||
fprintf(stderr, "cygfuse: initialization failed: " CYGFUSE_WINFSP_NAME " not found\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
37
opt/cygfuse/fuse3/fuse3.cygport
Normal file
37
opt/cygfuse/fuse3/fuse3.cygport
Normal file
@ -0,0 +1,37 @@
|
||||
NAME="fuse3"
|
||||
VERSION=3.2
|
||||
RELEASE=1
|
||||
CATEGORY="Utils"
|
||||
SUMMARY="WinFsp FUSE3 compatibility layer"
|
||||
DESCRIPTION="Enables FUSE3 file systems to be run on Cygwin."
|
||||
HOMEPAGE="http://www.secfs.net/winfsp/"
|
||||
|
||||
SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/billziss-gh/winfsp/archive/master.tar.gz"}
|
||||
SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master}
|
||||
|
||||
REQUIRES="fuse"
|
||||
|
||||
src_compile()
|
||||
{
|
||||
lndirs
|
||||
cd ${B}/opt/cygfuse/fuse3
|
||||
make
|
||||
}
|
||||
|
||||
src_install()
|
||||
{
|
||||
cd ${B}/inc/fuse3
|
||||
includeinto fuse3
|
||||
doinclude fuse.h
|
||||
doinclude fuse_common.h
|
||||
doinclude fuse_opt.h
|
||||
doinclude winfsp_fuse.h
|
||||
|
||||
cd ${B}/opt/cygfuse/fuse3/build/$(ARCH)
|
||||
dobin cygfuse-${VERSION}.dll
|
||||
dolib libfuse-${VERSION}.dll.a
|
||||
dosym libfuse-${VERSION}.dll.a /usr/lib/libfuse3.dll.a
|
||||
dopkgconfig fuse3.pc
|
||||
}
|
||||
|
||||
RESTRICT="strip postinst-doc"
|
9
opt/cygfuse/fuse3/fuse3.pc.in
Normal file
9
opt/cygfuse/fuse3/fuse3.pc.in
Normal file
@ -0,0 +1,9 @@
|
||||
prefix=/usr
|
||||
incdir=${prefix}/include/fuse3
|
||||
|
||||
Name: fuse
|
||||
Description: WinFsp FUSE3 compatible API
|
||||
Version: @Version@
|
||||
URL: http://www.secfs.net/winfsp/
|
||||
Libs: -lfuse-@Version@
|
||||
Cflags: -I"${incdir}" -DCYGFUSE
|
@ -162,6 +162,7 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
||||
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
|
||||
FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory;
|
||||
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
|
||||
FileSystem->Operations[FspFsctlTransactDeviceControlKind] = FspFileSystemOpDeviceControl;
|
||||
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
|
||||
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
|
||||
FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation;
|
||||
@ -207,7 +208,7 @@ static NTSTATUS FspFileSystemLauncherDefineDosDevice(
|
||||
Argv[0] = Argv0;
|
||||
Argv[1] = VolumeName;
|
||||
|
||||
Result = FspLaunchCallLauncherPipe('D', 2, Argv, 0, 0, 0, &ErrorCode);
|
||||
Result = FspLaunchCallLauncherPipe(FspLaunchCmdDefineDosDevice, 2, Argv, 0, 0, 0, &ErrorCode);
|
||||
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PWSTR DeviceRoot;
|
||||
SIZE_T DeviceRootSize, DevicePathSize;
|
||||
SIZE_T DeviceRootSize, DevicePathSize, VolumeParamsSize;
|
||||
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes;
|
||||
@ -55,8 +55,11 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
memcpy(DevicePathPtr, DevicePath, DevicePathSize);
|
||||
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DevicePathSize);
|
||||
memcpy(DevicePathPtr, PREFIXW, PREFIXW_SIZE);
|
||||
VolumeParamsSize = 0 == VolumeParams->Version ?
|
||||
sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) :
|
||||
VolumeParams->Version;
|
||||
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + PREFIXW_SIZE);
|
||||
DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + sizeof *VolumeParams * sizeof(WCHAR));
|
||||
DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + VolumeParamsSize * sizeof(WCHAR));
|
||||
for (PUINT8 VolumeParamsPtr = (PVOID)VolumeParams;
|
||||
DevicePathEnd > DevicePathPtr; DevicePathPtr++, VolumeParamsPtr++)
|
||||
{
|
||||
|
@ -1247,6 +1247,30 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemOpDeviceControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
ULONG BytesTransferred;
|
||||
|
||||
if (0 == FileSystem->Interface->Control)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
Result = FileSystem->Interface->Control(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.DeviceControl),
|
||||
Request->Req.DeviceControl.IoControlCode,
|
||||
Request->Buffer, Request->Req.DeviceControl.Buffer.Size,
|
||||
Response->Buffer, Request->Req.DeviceControl.OutputLength/* FSD guarantees correct size! */,
|
||||
&BytesTransferred);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
Response->Size = (UINT16)(sizeof *Response + BytesTransferred);
|
||||
Response->Rsp.DeviceControl.Buffer.Offset = 0;
|
||||
Response->Rsp.DeviceControl.Buffer.Size = (UINT16)BytesTransferred;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
#include <dll/fuse/library.h>
|
||||
|
||||
#define FSP_FUSE_SECTORSIZE_MIN 512
|
||||
#define FSP_FUSE_SECTORSIZE_MAX 4096
|
||||
|
||||
struct fuse_chan
|
||||
{
|
||||
PWSTR MountPoint;
|
||||
@ -27,25 +24,7 @@ struct fuse_chan
|
||||
};
|
||||
|
||||
#define FSP_FUSE_CORE_OPT(n, f, v) { n, offsetof(struct fsp_fuse_core_opt_data, f), v }
|
||||
|
||||
struct fsp_fuse_core_opt_data
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks;
|
||||
int set_FileInfoTimeout;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
};
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
||||
"fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same.");
|
||||
#define FSP_FUSE_CORE_OPT_NOHELP_IDX 4
|
||||
|
||||
static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
{
|
||||
@ -69,6 +48,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FUSE_OPT_KEY("noauto_cache", FUSE_OPT_KEY_DISCARD),
|
||||
FSP_FUSE_CORE_OPT("umask=", set_umask, 1),
|
||||
FSP_FUSE_CORE_OPT("umask=%o", umask, 0),
|
||||
FSP_FUSE_CORE_OPT("create_umask=", set_create_umask, 1),
|
||||
FSP_FUSE_CORE_OPT("create_umask=%o", create_umask, 0),
|
||||
FSP_FUSE_CORE_OPT("uid=", set_uid, 1),
|
||||
FSP_FUSE_CORE_OPT("uid=%d", uid, 0),
|
||||
FSP_FUSE_CORE_OPT("gid=", set_gid, 1),
|
||||
@ -96,6 +77,12 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("DirInfoTimeout=", set_DirInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("DirInfoTimeout=%d", VolumeParams.DirInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=", set_VolumeInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=%d", VolumeParams.VolumeInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("KeepFileCache=", set_KeepFileCache, 1),
|
||||
FSP_FUSE_CORE_OPT("ThreadCount=%u", ThreadCount, 0),
|
||||
FUSE_OPT_KEY("UNC=", 'U'),
|
||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||
FUSE_OPT_KEY("VolumePrefix=", 'U'),
|
||||
@ -107,36 +94,7 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
};
|
||||
|
||||
static INIT_ONCE fsp_fuse_initonce = INIT_ONCE_STATIC_INIT;
|
||||
static DWORD fsp_fuse_tlskey = TLS_OUT_OF_INDEXES;
|
||||
|
||||
struct fsp_fuse_obj_hdr
|
||||
{
|
||||
void (*dtor)(void *);
|
||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[];
|
||||
};
|
||||
|
||||
static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size)
|
||||
{
|
||||
struct fsp_fuse_obj_hdr *hdr;
|
||||
|
||||
hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size);
|
||||
if (0 == hdr)
|
||||
return 0;
|
||||
|
||||
hdr->dtor = env->memfree;
|
||||
memset(hdr->ObjectBuf, 0, size);
|
||||
return hdr->ObjectBuf;
|
||||
}
|
||||
|
||||
static inline void fsp_fuse_obj_free(void *obj)
|
||||
{
|
||||
if (0 == obj)
|
||||
return;
|
||||
|
||||
struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr));
|
||||
|
||||
hdr->dtor(hdr);
|
||||
}
|
||||
DWORD fsp_fuse_tlskey = TLS_OUT_OF_INDEXES;
|
||||
|
||||
static BOOL WINAPI fsp_fuse_initialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
@ -262,202 +220,6 @@ FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env,
|
||||
return fsp_fuse_opt_match(env, fsp_fuse_core_opts, opt);
|
||||
}
|
||||
|
||||
static void fsp_fuse_cleanup(struct fuse *f);
|
||||
|
||||
static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
{
|
||||
struct fuse *f = Service->UserContext;
|
||||
struct fuse_context *context;
|
||||
struct fuse_conn_info conn;
|
||||
NTSTATUS Result;
|
||||
|
||||
f->Service = Service;
|
||||
|
||||
context = fsp_fuse_get_context(f->env);
|
||||
if (0 == context)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
}
|
||||
context->fuse = f;
|
||||
context->private_data = f->data;
|
||||
context->uid = -1;
|
||||
context->gid = -1;
|
||||
context->pid = -1;
|
||||
|
||||
memset(&conn, 0, sizeof conn);
|
||||
conn.proto_major = 7; /* pretend that we are FUSE kernel protocol 7.12 */
|
||||
conn.proto_minor = 12; /* which was current at the time of FUSE 2.8 */
|
||||
conn.async_read = 1;
|
||||
conn.max_write = UINT_MAX;
|
||||
conn.capable =
|
||||
FUSE_CAP_ASYNC_READ |
|
||||
//FUSE_CAP_POSIX_LOCKS | /* WinFsp handles locking in the FSD currently */
|
||||
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
||||
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
||||
FUSE_CAP_BIG_WRITES |
|
||||
FUSE_CAP_DONT_MASK |
|
||||
FSP_FUSE_CAP_READDIR_PLUS |
|
||||
FSP_FUSE_CAP_READ_ONLY |
|
||||
FSP_FUSE_CAP_STAT_EX |
|
||||
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
||||
if (0 != f->ops.init)
|
||||
{
|
||||
context->private_data = f->data = f->ops.init(&conn);
|
||||
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
||||
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||
if (!f->VolumeParams.CaseSensitiveSearch)
|
||||
/*
|
||||
* Disable GetDirInfoByName when file system is case-insensitive.
|
||||
* The reason is that Windows always sends us queries with uppercase
|
||||
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
||||
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
||||
*/
|
||||
f->VolumeParams.PassQueryDirectoryFileName = FALSE;
|
||||
f->conn_want = conn.want;
|
||||
}
|
||||
f->fsinit = TRUE;
|
||||
if (0 != f->ops.statfs)
|
||||
{
|
||||
struct fuse_statvfs stbuf;
|
||||
int err;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
err = f->ops.statfs("/", &stbuf);
|
||||
if (0 != err)
|
||||
{
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 == f->VolumeParams.SectorSize && 0 != stbuf.f_frsize)
|
||||
f->VolumeParams.SectorSize = (UINT16)stbuf.f_frsize;
|
||||
#if 0
|
||||
if (0 == f->VolumeParams.SectorsPerAllocationUnit && 0 != stbuf.f_frsize)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = (UINT16)(stbuf.f_bsize / stbuf.f_frsize);
|
||||
#endif
|
||||
if (0 == f->VolumeParams.MaxComponentLength)
|
||||
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
||||
}
|
||||
if (0 != f->ops.getattr)
|
||||
{
|
||||
struct fuse_stat_ex stbuf;
|
||||
int err;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
err = f->ops.getattr("/", (void *)&stbuf);
|
||||
if (0 != err)
|
||||
{
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||
{
|
||||
if (0 != stbuf.st_birthtim.tv_sec)
|
||||
FspPosixUnixTimeToFileTime((void *)&stbuf.st_birthtim,
|
||||
&f->VolumeParams.VolumeCreationTime);
|
||||
else
|
||||
if (0 != stbuf.st_ctim.tv_sec)
|
||||
FspPosixUnixTimeToFileTime((void *)&stbuf.st_ctim,
|
||||
&f->VolumeParams.VolumeCreationTime);
|
||||
}
|
||||
}
|
||||
|
||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
||||
f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
||||
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
||||
if (f->VolumeParams.MaxComponentLength > 255)
|
||||
f->VolumeParams.MaxComponentLength = 255;
|
||||
|
||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||
{
|
||||
FILETIME FileTime;
|
||||
GetSystemTimeAsFileTime(&FileTime);
|
||||
f->VolumeParams.VolumeCreationTime = *(PUINT64)&FileTime;
|
||||
}
|
||||
if (0 == f->VolumeParams.VolumeSerialNumber)
|
||||
f->VolumeParams.VolumeSerialNumber =
|
||||
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->HighPart ^
|
||||
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->LowPart;
|
||||
|
||||
Result = FspFileSystemCreate(
|
||||
f->VolumeParams.Prefix[0] ?
|
||||
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
|
||||
&f->VolumeParams, &fsp_fuse_intf,
|
||||
&f->FileSystem);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"Cannot create " FSP_FUSE_LIBRARY_NAME " file system.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f->FileSystem->UserContext = f;
|
||||
FspFileSystemSetOperationGuard(f->FileSystem, fsp_fuse_op_enter, fsp_fuse_op_leave);
|
||||
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
|
||||
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
|
||||
|
||||
if (0 != f->MountPoint)
|
||||
{
|
||||
Result = FspFileSystemSetMountPoint(f->FileSystem,
|
||||
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"Cannot set " FSP_FUSE_LIBRARY_NAME " file system mount point.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
Result = FspFileSystemStartDispatcher(f->FileSystem, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"Cannot start " FSP_FUSE_LIBRARY_NAME " file system dispatcher.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
fsp_fuse_cleanup(f);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_svcstop(FSP_SERVICE *Service)
|
||||
{
|
||||
struct fuse *f = Service->UserContext;
|
||||
|
||||
FspFileSystemStopDispatcher(f->FileSystem);
|
||||
|
||||
fsp_fuse_cleanup(f);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void fsp_fuse_cleanup(struct fuse *f)
|
||||
{
|
||||
if (0 != f->FileSystem)
|
||||
{
|
||||
FspFileSystemDelete(f->FileSystem);
|
||||
f->FileSystem = 0;
|
||||
}
|
||||
|
||||
if (f->fsinit)
|
||||
{
|
||||
if (f->ops.destroy)
|
||||
f->ops.destroy(f->data);
|
||||
f->fsinit = FALSE;
|
||||
}
|
||||
|
||||
f->Service = 0;
|
||||
}
|
||||
|
||||
static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
@ -468,10 +230,11 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
default:
|
||||
return 1;
|
||||
case 'h':
|
||||
/* Note: The limit on FspServiceLog messages is 1024 bytes. This is getting close. */
|
||||
/* Note: The limit on FspServiceLog messages is 1024 bytes. */
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||
FSP_FUSE_LIBRARY_NAME " options:\n"
|
||||
" -o umask=MASK set file permissions (octal)\n"
|
||||
" -o create_umask=MASK set newly created file permissions (octal)\n"
|
||||
" -o uid=N set file owner (-1 for mounting user id)\n"
|
||||
" -o gid=N set file group (-1 for mounting user group)\n"
|
||||
" -o rellinks interpret absolute symlinks as volume relative\n"
|
||||
@ -480,14 +243,14 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
" --VolumePrefix=UNC set UNC prefix (\\Server\\Share)\n"
|
||||
" -o FileSystemName=NAME set file system name\n"
|
||||
" -o DebugLog=FILE debug log file (requires -d)\n"
|
||||
"\n"
|
||||
);
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||
FSP_FUSE_LIBRARY_NAME " advanced options:\n"
|
||||
" -o FileInfoTimeout=N metadata timeout (millis, -1 for data caching)\n"
|
||||
" -o SectorSize=N (512-4096, deflt: 4096)\n"
|
||||
" -o SectorsPerAllocationUnit=N (deflt: 1)\n"
|
||||
" -o MaxComponentLength=N (deflt: 255)\n"
|
||||
" -o VolumeCreationTime=T (FILETIME hex format)\n"
|
||||
" -o VolumeSerialNumber=N (32-bit wide)\n"
|
||||
" -o DirInfoTimeout=N directory info timeout (millis)\n"
|
||||
" -o VolumeInfoTimeout=N volume info timeout (millis)\n"
|
||||
" -o KeepFileCache do not discard cache when files are closed\n"
|
||||
" -o ThreadCount number of file system dispatcher threads\n"
|
||||
);
|
||||
opt_data->help = 1;
|
||||
return 1;
|
||||
@ -552,6 +315,18 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
}
|
||||
}
|
||||
|
||||
int fsp_fuse_core_opt_parse(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args, struct fsp_fuse_core_opt_data *opt_data,
|
||||
int help)
|
||||
{
|
||||
if (help)
|
||||
return fsp_fuse_opt_parse(env, args, opt_data,
|
||||
fsp_fuse_core_opts, fsp_fuse_core_opt_proc);
|
||||
else
|
||||
return fsp_fuse_opt_parse(env, args, opt_data,
|
||||
fsp_fuse_core_opts + FSP_FUSE_CORE_OPT_NOHELP_IDX, fsp_fuse_core_opt_proc);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
struct fuse_chan *ch, struct fuse_args *args,
|
||||
const struct fuse_operations *ops, size_t opsize, void *data)
|
||||
@ -568,9 +343,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
opt_data.env = env;
|
||||
opt_data.DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000; /* default FileInfoTimeout for FUSE file systems */
|
||||
opt_data.VolumeParams.Version = sizeof(FSP_FSCTL_VOLUME_PARAMS);
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000;
|
||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
||||
|
||||
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
||||
if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1))
|
||||
return 0;
|
||||
if (opt_data.help)
|
||||
return 0;
|
||||
@ -608,7 +385,13 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
}
|
||||
|
||||
if (!opt_data.set_FileInfoTimeout && opt_data.set_attr_timeout)
|
||||
opt_data.VolumeParams.FileInfoTimeout = opt_data.set_attr_timeout * 1000;
|
||||
opt_data.VolumeParams.FileInfoTimeout = opt_data.attr_timeout * 1000;
|
||||
if (opt_data.set_DirInfoTimeout)
|
||||
opt_data.VolumeParams.DirInfoTimeoutValid = 1;
|
||||
if (opt_data.set_VolumeInfoTimeout)
|
||||
opt_data.VolumeParams.VolumeInfoTimeoutValid = 1;
|
||||
if (opt_data.set_KeepFileCache)
|
||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = FALSE;
|
||||
opt_data.VolumeParams.CaseSensitiveSearch = TRUE;
|
||||
opt_data.VolumeParams.CasePreservedNames = TRUE;
|
||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||
@ -618,6 +401,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
opt_data.VolumeParams.ReadOnlyVolume = FALSE;
|
||||
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
||||
opt_data.VolumeParams.PassQueryDirectoryFileName = TRUE;
|
||||
opt_data.VolumeParams.DeviceControl = TRUE;
|
||||
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
||||
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||
memcpy(opt_data.VolumeParams.FileSystemName, L"FUSE", 5 * sizeof(WCHAR));
|
||||
@ -628,9 +412,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
|
||||
f->env = env;
|
||||
f->set_umask = opt_data.set_umask; f->umask = opt_data.umask;
|
||||
f->set_create_umask = opt_data.set_create_umask; f->create_umask = opt_data.create_umask;
|
||||
f->set_uid = opt_data.set_uid; f->uid = opt_data.uid;
|
||||
f->set_gid = opt_data.set_gid; f->gid = opt_data.gid;
|
||||
f->rellinks = opt_data.rellinks;
|
||||
f->ThreadCount = opt_data.ThreadCount;
|
||||
memcpy(&f->ops, ops, opsize);
|
||||
f->data = data;
|
||||
f->DebugLog = opt_data.debug ? -1 : 0;
|
||||
@ -644,6 +430,10 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
goto fail;
|
||||
memcpy(f->MountPoint, ch->MountPoint, Size);
|
||||
|
||||
f->LoopEvent = CreateEventW(0, TRUE, FALSE, 0);
|
||||
if (0 == f->LoopEvent)
|
||||
goto fail;
|
||||
|
||||
Result = FspFileSystemPreflight(
|
||||
f->VolumeParams.Prefix[0] ? L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
|
||||
'*' != f->MountPoint[0] || '\0' != f->MountPoint[1] ? f->MountPoint : 0);
|
||||
@ -691,34 +481,18 @@ fail:
|
||||
FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
fsp_fuse_cleanup(f);
|
||||
if (0 != f->LoopEvent)
|
||||
CloseHandle(f->LoopEvent);
|
||||
|
||||
fsp_fuse_obj_free(f->MountPoint);
|
||||
|
||||
fsp_fuse_obj_free(f);
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE;
|
||||
return 0 == FspServiceRunEx(FspDiagIdent(), fsp_fuse_svcstart, fsp_fuse_svcstop, 0, f) ?
|
||||
0 : -1;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse_loop_mt(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE;
|
||||
return 0 == FspServiceRunEx(FspDiagIdent(), fsp_fuse_svcstart, fsp_fuse_svcstop, 0, f) ?
|
||||
0 : -1;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
if (0 != f->Service)
|
||||
FspServiceStop(f->Service);
|
||||
SetEvent(f->LoopEvent);
|
||||
f->exited = 1;
|
||||
}
|
||||
|
||||
@ -779,10 +553,3 @@ FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env,
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cygwin signal support */
|
||||
|
||||
FSP_FUSE_API void fsp_fuse_signal_handler(int sig)
|
||||
{
|
||||
FspServiceConsoleCtrlHandler(CTRL_BREAK_EVENT);
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ loopend:;
|
||||
if (0 != f->ops.getattr)
|
||||
err = f->ops.getattr(PosixHiddenPath, (void *)&stbuf);
|
||||
else
|
||||
err = -ENOSYS;
|
||||
err = -ENOSYS_(f->env);
|
||||
} while (0 == err && 0 < --maxtries);
|
||||
|
||||
if (0 == err)
|
||||
@ -308,7 +308,7 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
if (0 != f->ops.getattr)
|
||||
err = f->ops.getattr(PosixDotPath, (void *)&stbuf);
|
||||
else
|
||||
err = -ENOSYS;
|
||||
err = -ENOSYS_(f->env);
|
||||
|
||||
MemFree(PosixDotPath);
|
||||
|
||||
@ -711,14 +711,16 @@ static NTSTATUS fsp_fuse_intf_GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
Result = fsp_fuse_intf_GetSecurityEx(FileSystem, PosixPath, 0,
|
||||
PFileAttributes, SecurityDescriptorBuf, PSecurityDescriptorSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
if (!NT_SUCCESS(Result) &&
|
||||
STATUS_OBJECT_NAME_NOT_FOUND != Result &&
|
||||
STATUS_OBJECT_PATH_NOT_FOUND != Result)
|
||||
goto exit;
|
||||
|
||||
if (FSP_FUSE_HAS_SYMLINKS(f) &&
|
||||
FspFileSystemFindReparsePoint(FileSystem, fsp_fuse_intf_GetReparsePointByName, 0,
|
||||
FileName, PFileAttributes))
|
||||
Result = STATUS_REPARSE;
|
||||
else
|
||||
else if (NT_SUCCESS(Result))
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
@ -731,7 +733,7 @@ exit:
|
||||
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||
PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
PVOID *PFileDesc, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fuse_context *context = fsp_fuse_get_context(f->env);
|
||||
@ -762,6 +764,8 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
goto exit;
|
||||
}
|
||||
Mode &= ~context->umask;
|
||||
if (f->set_create_umask)
|
||||
Mode = 0777 & ~f->create_umask;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
if ('C' == f->env->environment) /* Cygwin */
|
||||
@ -854,7 +858,7 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
*PFileNode = filedesc;
|
||||
*PFileDesc = filedesc;
|
||||
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
||||
|
||||
filedesc->PosixPath = contexthdr->PosixPath;
|
||||
@ -892,7 +896,7 @@ exit:
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||
PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
PVOID *PFileDesc, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fuse_context *context = fsp_fuse_get_context(f->env);
|
||||
@ -971,7 +975,7 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
||||
* Ignore fuse_file_info::nonseekable.
|
||||
*/
|
||||
|
||||
*PFileNode = filedesc;
|
||||
*PFileDesc = filedesc;
|
||||
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
||||
|
||||
filedesc->PosixPath = contexthdr->PosixPath;
|
||||
@ -992,11 +996,11 @@ exit:
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize,
|
||||
PVOID FileDesc, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
int err;
|
||||
@ -1045,10 +1049,10 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR FileName, ULONG Flags)
|
||||
PVOID FileDesc, PWSTR FileName, ULONG Flags)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
|
||||
/*
|
||||
* In Windows a DeleteFile/RemoveDirectory is the sequence of the following:
|
||||
@ -1081,10 +1085,10 @@ static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode)
|
||||
PVOID FileDesc)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
@ -1114,11 +1118,11 @@ static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Read(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length,
|
||||
PVOID FileDesc, PVOID Buffer, UINT64 Offset, ULONG Length,
|
||||
PULONG PBytesTransferred)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
int bytes;
|
||||
NTSTATUS Result;
|
||||
@ -1148,12 +1152,12 @@ static NTSTATUS fsp_fuse_intf_Read(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Write(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length,
|
||||
PVOID FileDesc, PVOID Buffer, UINT64 Offset, ULONG Length,
|
||||
BOOLEAN WriteToEndOfFile, BOOLEAN ConstrainedIo,
|
||||
PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||
@ -1211,11 +1215,11 @@ success:
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Flush(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||
@ -1262,11 +1266,11 @@ static NTSTATUS fsp_fuse_intf_Flush(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
|
||||
@ -1279,12 +1283,12 @@ static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, UINT32 FileAttributes,
|
||||
PVOID FileDesc, UINT32 FileAttributes,
|
||||
UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||
@ -1364,11 +1368,11 @@ static NTSTATUS fsp_fuse_intf_SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, UINT64 NewSize, BOOLEAN SetAllocationSize,
|
||||
PVOID FileDesc, UINT64 NewSize, BOOLEAN SetAllocationSize,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||
@ -1423,7 +1427,8 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
|
||||
/* !static: used by fuse2to3 */
|
||||
int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||
{
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
@ -1447,10 +1452,10 @@ static int fsp_fuse_intf_CanDeleteAddDirInfoOld(fuse_dirh_t dh, const char *name
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR FileName)
|
||||
PVOID FileDesc, PWSTR FileName)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
struct fuse_dirhandle dh;
|
||||
int err;
|
||||
@ -1486,7 +1491,7 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
@ -1494,7 +1499,7 @@ static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||
struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context);
|
||||
UINT32 Uid, Gid, Mode;
|
||||
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
int err;
|
||||
NTSTATUS Result;
|
||||
|
||||
@ -1520,11 +1525,11 @@ static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptorBuf, SIZE_T *PSecurityDescriptorSize)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
UINT32 FileAttributes;
|
||||
|
||||
@ -1537,11 +1542,11 @@ static NTSTATUS fsp_fuse_intf_GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
UINT32 Uid, Gid, Mode, NewUid, NewGid, NewMode;
|
||||
FSP_FSCTL_FILE_INFO FileInfo;
|
||||
@ -1613,7 +1618,8 @@ exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
/* !static: used by fuse2to3 */
|
||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||
{
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
@ -1648,7 +1654,8 @@ static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
memset(DirInfo, 0, sizeof *DirInfo);
|
||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + SizeW * sizeof(WCHAR));
|
||||
|
||||
if (dh->ReaddirPlus && 0 != stbuf)
|
||||
if (dh->ReaddirPlus && 0 != stbuf &&
|
||||
0120000/* S_IFLNK */ != (stbuf->st_mode & 0170000))
|
||||
{
|
||||
UINT32 Uid, Gid, Mode;
|
||||
NTSTATUS Result0;
|
||||
@ -1761,11 +1768,11 @@ exit:
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR Pattern, PWSTR Marker,
|
||||
PVOID FileDesc, PWSTR Pattern, PWSTR Marker,
|
||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_dirhandle dh;
|
||||
struct fuse_file_info fi;
|
||||
int err;
|
||||
@ -1816,11 +1823,11 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR FileName,
|
||||
PVOID FileDesc, PWSTR FileName,
|
||||
FSP_FSCTL_DIR_INFO *DirInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
char *PosixName = 0;
|
||||
char PosixPath[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||
int ParentLength, FSlashLength, PosixNameLength;
|
||||
@ -1903,10 +1910,10 @@ exit:
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_GetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
PWSTR FileName, PVOID Buffer, PSIZE_T PSize)
|
||||
{
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
@ -1917,12 +1924,12 @@ static NTSTATUS fsp_fuse_intf_GetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
PWSTR FileName, PVOID Buffer, SIZE_T Size)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fuse_context *context = fsp_fuse_get_context(f->env);
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
UINT32 Uid, Gid, Mode, Dev;
|
||||
FSP_FSCTL_FILE_INFO FileInfo;
|
||||
@ -2113,13 +2120,54 @@ exit:
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PVOID FileDesc,
|
||||
PWSTR FileName, PVOID Buffer, SIZE_T Size)
|
||||
{
|
||||
/* we were asked to delete the reparse point? no can do! */
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_Control(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileDesc, UINT32 ControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength,
|
||||
PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileDesc;
|
||||
struct fuse_file_info fi;
|
||||
int cmd;
|
||||
int err;
|
||||
|
||||
if (0 == f->ops.ioctl)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
if (FSP_FUSE_DEVICE_TYPE != DEVICE_TYPE_FROM_CTL_CODE(ControlCode))
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
if (0 != InputBufferLength && 0 != OutputBufferLength &&
|
||||
InputBufferLength != OutputBufferLength)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
fi.flags = filedesc->OpenFlags;
|
||||
fi.fh = filedesc->FileHandle;
|
||||
|
||||
/* construct a Linux compatible ioctl code */
|
||||
cmd = FSP_FUSE_IOCTL((ControlCode >> 2) & 0xfff, InputBufferLength, OutputBufferLength);
|
||||
|
||||
if (0 == OutputBufferLength)
|
||||
err = f->ops.ioctl(filedesc->PosixPath, cmd, 0, &fi, 0, InputBuffer);
|
||||
else
|
||||
{
|
||||
if (0 != InputBufferLength)
|
||||
// OutputBuffer points to Response->Buffer which is FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX long
|
||||
memcpy(OutputBuffer, InputBuffer, InputBufferLength);
|
||||
err = f->ops.ioctl(filedesc->PosixPath, cmd, 0, &fi, 0, OutputBuffer);
|
||||
}
|
||||
|
||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
|
||||
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
||||
{
|
||||
fsp_fuse_intf_GetVolumeInfo,
|
||||
@ -2147,6 +2195,7 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
||||
fsp_fuse_intf_DeleteReparsePoint,
|
||||
0,
|
||||
fsp_fuse_intf_GetDirInfoByName,
|
||||
fsp_fuse_intf_Control,
|
||||
};
|
||||
|
||||
/*
|
||||
|
297
src/dll/fuse/fuse_loop.c
Normal file
297
src/dll/fuse/fuse_loop.c
Normal file
@ -0,0 +1,297 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_loop.c
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/fuse/library.h>
|
||||
|
||||
#define FSP_FUSE_SECTORSIZE_MIN 512
|
||||
#define FSP_FUSE_SECTORSIZE_MAX 4096
|
||||
|
||||
static INIT_ONCE fsp_fuse_svconce = INIT_ONCE_STATIC_INIT;
|
||||
static HANDLE fsp_fuse_svcthread;
|
||||
|
||||
static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_svcstop(FSP_SERVICE *Service)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD WINAPI fsp_fuse_svcmain(PVOID Context)
|
||||
{
|
||||
return FspServiceRun(FspDiagIdent(), fsp_fuse_svcstart, fsp_fuse_svcstop, 0);
|
||||
}
|
||||
|
||||
static BOOL WINAPI fsp_fuse_svcinit(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
fsp_fuse_svcthread = CreateThread(0, 0, fsp_fuse_svcmain, 0, 0, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void fsp_fuse_loop_cleanup(struct fuse *f);
|
||||
|
||||
static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
||||
{
|
||||
struct fuse_context *context;
|
||||
struct fuse_conn_info conn;
|
||||
NTSTATUS Result;
|
||||
|
||||
context = fsp_fuse_get_context(f->env);
|
||||
if (0 == context)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
}
|
||||
context->fuse = f;
|
||||
context->private_data = f->data;
|
||||
context->uid = -1;
|
||||
context->gid = -1;
|
||||
context->pid = -1;
|
||||
|
||||
memset(&conn, 0, sizeof conn);
|
||||
conn.proto_major = 7; /* pretend that we are FUSE kernel protocol 7.12 */
|
||||
conn.proto_minor = 12; /* which was current at the time of FUSE 2.8 */
|
||||
conn.async_read = 1;
|
||||
conn.max_write = UINT_MAX;
|
||||
conn.capable =
|
||||
FUSE_CAP_ASYNC_READ |
|
||||
//FUSE_CAP_POSIX_LOCKS | /* WinFsp handles locking in the FSD currently */
|
||||
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
||||
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
||||
FUSE_CAP_BIG_WRITES |
|
||||
FUSE_CAP_DONT_MASK |
|
||||
FSP_FUSE_CAP_READDIR_PLUS |
|
||||
FSP_FUSE_CAP_READ_ONLY |
|
||||
FSP_FUSE_CAP_STAT_EX |
|
||||
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
||||
if (0 != f->ops.init)
|
||||
{
|
||||
context->private_data = f->data = f->ops.init(&conn);
|
||||
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
||||
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||
if (!f->VolumeParams.CaseSensitiveSearch)
|
||||
/*
|
||||
* Disable GetDirInfoByName when file system is case-insensitive.
|
||||
* The reason is that Windows always sends us queries with uppercase
|
||||
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
||||
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
||||
*/
|
||||
f->VolumeParams.PassQueryDirectoryFileName = FALSE;
|
||||
f->conn_want = conn.want;
|
||||
}
|
||||
f->fsinit = TRUE;
|
||||
if (0 != f->ops.statfs)
|
||||
{
|
||||
struct fuse_statvfs stbuf;
|
||||
int err;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
err = f->ops.statfs("/", &stbuf);
|
||||
if (0 != err)
|
||||
{
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 == f->VolumeParams.SectorSize && 0 != stbuf.f_frsize)
|
||||
f->VolumeParams.SectorSize = (UINT16)stbuf.f_frsize;
|
||||
#if 0
|
||||
if (0 == f->VolumeParams.SectorsPerAllocationUnit && 0 != stbuf.f_frsize)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = (UINT16)(stbuf.f_bsize / stbuf.f_frsize);
|
||||
#endif
|
||||
if (0 == f->VolumeParams.MaxComponentLength)
|
||||
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
||||
}
|
||||
if (0 != f->ops.getattr)
|
||||
{
|
||||
struct fuse_stat_ex stbuf;
|
||||
int err;
|
||||
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
err = f->ops.getattr("/", (void *)&stbuf);
|
||||
if (0 != err)
|
||||
{
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||
{
|
||||
if (0 != stbuf.st_birthtim.tv_sec)
|
||||
FspPosixUnixTimeToFileTime((void *)&stbuf.st_birthtim,
|
||||
&f->VolumeParams.VolumeCreationTime);
|
||||
else
|
||||
if (0 != stbuf.st_ctim.tv_sec)
|
||||
FspPosixUnixTimeToFileTime((void *)&stbuf.st_ctim,
|
||||
&f->VolumeParams.VolumeCreationTime);
|
||||
}
|
||||
}
|
||||
if (0 != f->ops.readlink)
|
||||
{
|
||||
char buf[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||
int err;
|
||||
|
||||
/* this should always fail with ENOSYS or EINVAL */
|
||||
err = f->ops.readlink("/", buf, sizeof buf);
|
||||
f->has_symlinks = -ENOSYS_(f->env) != err;
|
||||
}
|
||||
|
||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
||||
f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
||||
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
||||
if (f->VolumeParams.MaxComponentLength > 255)
|
||||
f->VolumeParams.MaxComponentLength = 255;
|
||||
|
||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||
{
|
||||
FILETIME FileTime;
|
||||
GetSystemTimeAsFileTime(&FileTime);
|
||||
f->VolumeParams.VolumeCreationTime = *(PUINT64)&FileTime;
|
||||
}
|
||||
if (0 == f->VolumeParams.VolumeSerialNumber)
|
||||
f->VolumeParams.VolumeSerialNumber =
|
||||
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->HighPart ^
|
||||
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->LowPart;
|
||||
|
||||
Result = FspFileSystemCreate(
|
||||
f->VolumeParams.Prefix[0] ?
|
||||
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
|
||||
&f->VolumeParams, &fsp_fuse_intf,
|
||||
&f->FileSystem);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"Cannot create " FSP_FUSE_LIBRARY_NAME " file system.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f->FileSystem->UserContext = f;
|
||||
FspFileSystemSetOperationGuard(f->FileSystem, fsp_fuse_op_enter, fsp_fuse_op_leave);
|
||||
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
|
||||
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
|
||||
|
||||
if (0 != f->MountPoint)
|
||||
{
|
||||
Result = FspFileSystemSetMountPoint(f->FileSystem,
|
||||
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"Cannot set " FSP_FUSE_LIBRARY_NAME " file system mount point.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
Result = FspFileSystemStartDispatcher(f->FileSystem, f->ThreadCount);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"Cannot start " FSP_FUSE_LIBRARY_NAME " file system dispatcher.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
fsp_fuse_loop_cleanup(f);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void fsp_fuse_loop_stop(struct fuse *f)
|
||||
{
|
||||
FspFileSystemStopDispatcher(f->FileSystem);
|
||||
|
||||
fsp_fuse_loop_cleanup(f);
|
||||
}
|
||||
|
||||
static void fsp_fuse_loop_cleanup(struct fuse *f)
|
||||
{
|
||||
if (0 != f->FileSystem)
|
||||
{
|
||||
FspFileSystemDelete(f->FileSystem);
|
||||
f->FileSystem = 0;
|
||||
}
|
||||
|
||||
if (f->fsinit)
|
||||
{
|
||||
if (f->ops.destroy)
|
||||
f->ops.destroy(f->data);
|
||||
f->fsinit = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_loop_internal(struct fuse *f)
|
||||
{
|
||||
HANDLE WaitObjects[2];
|
||||
DWORD WaitResult;
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = fsp_fuse_loop_start(f);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
/* emulate WinFsp-FUSE v1.3 behavior! */
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
L"The service %s has failed to start (Status=%lx).", FspDiagIdent(), Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
InitOnceExecuteOnce(&fsp_fuse_svconce, fsp_fuse_svcinit, 0, 0);
|
||||
if (0 == fsp_fuse_svcthread)
|
||||
{
|
||||
fsp_fuse_loop_stop(f);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* if either the service thread dies or our event gets signaled, stop the loop */
|
||||
WaitObjects[0] = fsp_fuse_svcthread;
|
||||
WaitObjects[1] = f->LoopEvent;
|
||||
WaitResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
|
||||
if (WAIT_OBJECT_0 != WaitResult && WAIT_OBJECT_0 + 1 != WaitResult)
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
fsp_fuse_loop_stop(f);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE;
|
||||
return NT_SUCCESS(fsp_fuse_loop_internal(f)) ? 0 : -1;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse_loop_mt(struct fsp_fuse_env *env,
|
||||
struct fuse *f)
|
||||
{
|
||||
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE;
|
||||
return NT_SUCCESS(fsp_fuse_loop_internal(f)) ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Cygwin signal support */
|
||||
|
||||
FSP_FUSE_API void fsp_fuse_signal_handler(int sig)
|
||||
{
|
||||
FspServiceConsoleCtrlHandler(CTRL_BREAK_EVENT);
|
||||
}
|
@ -25,40 +25,52 @@
|
||||
#define FSP_FUSE_LIBRARY_NAME LIBRARY_NAME "-FUSE"
|
||||
|
||||
#define FSP_FUSE_HDR_FROM_CONTEXT(c) \
|
||||
(struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header))
|
||||
((struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header)))
|
||||
#define FSP_FUSE_CONTEXT_FROM_HDR(h) \
|
||||
(struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header))
|
||||
((struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header)))
|
||||
|
||||
#define FSP_FUSE_HAS_SYMLINKS(f) (0 != (f)->ops.readlink)
|
||||
#define FSP_FUSE_HAS_SYMLINKS(f) ((f)->has_symlinks)
|
||||
|
||||
#define ENOSYS_(env) ('C' == (env)->environment ? 88 : 40)
|
||||
|
||||
/* NFS reparse points */
|
||||
#define NFS_SPECFILE_FIFO 0x000000004F464946
|
||||
#define NFS_SPECFILE_CHR 0x0000000000524843
|
||||
#define NFS_SPECFILE_BLK 0x00000000004b4c42
|
||||
#define NFS_SPECFILE_LNK 0x00000000014b4e4c
|
||||
#define NFS_SPECFILE_SOCK 0x000000004B434F53
|
||||
|
||||
/* FUSE internal struct's */
|
||||
struct fuse
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int set_umask, umask;
|
||||
int set_create_umask, create_umask;
|
||||
int set_uid, uid;
|
||||
int set_gid, gid;
|
||||
int rellinks;
|
||||
unsigned ThreadCount;
|
||||
struct fuse_operations ops;
|
||||
void *data;
|
||||
unsigned conn_want;
|
||||
BOOLEAN fsinit;
|
||||
BOOLEAN has_symlinks;
|
||||
UINT32 DebugLog;
|
||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
PWSTR MountPoint;
|
||||
HANDLE LoopEvent;
|
||||
FSP_FILE_SYSTEM *FileSystem;
|
||||
FSP_SERVICE *Service; /* weak */
|
||||
volatile int exited;
|
||||
struct fuse3 *fuse3;
|
||||
};
|
||||
|
||||
struct fsp_fuse_context_header
|
||||
{
|
||||
char *PosixPath;
|
||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ContextBuf[];
|
||||
};
|
||||
|
||||
struct fsp_fuse_file_desc
|
||||
{
|
||||
char *PosixPath;
|
||||
@ -67,7 +79,6 @@ struct fsp_fuse_file_desc
|
||||
UINT64 FileHandle;
|
||||
PVOID DirBuffer;
|
||||
};
|
||||
|
||||
struct fuse_dirhandle
|
||||
{
|
||||
/* ReadDirectory */
|
||||
@ -79,24 +90,82 @@ struct fuse_dirhandle
|
||||
BOOLEAN DotFiles, HasChild;
|
||||
};
|
||||
|
||||
/* FUSE obj alloc/free */
|
||||
struct fsp_fuse_obj_hdr
|
||||
{
|
||||
void (*dtor)(void *);
|
||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[];
|
||||
};
|
||||
static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size)
|
||||
{
|
||||
struct fsp_fuse_obj_hdr *hdr;
|
||||
|
||||
hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size);
|
||||
if (0 == hdr)
|
||||
return 0;
|
||||
|
||||
hdr->dtor = env->memfree;
|
||||
memset(hdr->ObjectBuf, 0, size);
|
||||
return hdr->ObjectBuf;
|
||||
}
|
||||
static inline void fsp_fuse_obj_free(void *obj)
|
||||
{
|
||||
if (0 == obj)
|
||||
return;
|
||||
|
||||
struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr));
|
||||
|
||||
hdr->dtor(hdr);
|
||||
}
|
||||
|
||||
/* fsp_fuse_get_context_internal */
|
||||
extern DWORD fsp_fuse_tlskey;
|
||||
static inline struct fuse_context *fsp_fuse_get_context_internal(void)
|
||||
{
|
||||
return TlsGetValue(fsp_fuse_tlskey);
|
||||
}
|
||||
|
||||
/* fsp_fuse_core_opt_parse */
|
||||
struct fsp_fuse_core_opt_data
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
set_create_umask, create_umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks;
|
||||
int set_FileInfoTimeout,
|
||||
set_DirInfoTimeout,
|
||||
set_VolumeInfoTimeout,
|
||||
set_KeepFileCache;
|
||||
unsigned ThreadCount;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
};
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel,
|
||||
"fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same.");
|
||||
int fsp_fuse_core_opt_parse(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args, struct fsp_fuse_core_opt_data *opt_data,
|
||||
int help);
|
||||
|
||||
/* misc public symbols */
|
||||
NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
|
||||
extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf;
|
||||
|
||||
int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off);
|
||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off);
|
||||
NTSTATUS fsp_fuse_get_token_uidgid(
|
||||
HANDLE Token,
|
||||
TOKEN_INFORMATION_CLASS UserOrOwnerClass, /* TokenUser|TokenOwner */
|
||||
PUINT32 PUid, PUINT32 PGid);
|
||||
|
||||
/* NFS reparse points */
|
||||
|
||||
#define NFS_SPECFILE_FIFO 0x000000004F464946
|
||||
#define NFS_SPECFILE_CHR 0x0000000000524843
|
||||
#define NFS_SPECFILE_BLK 0x00000000004b4c42
|
||||
#define NFS_SPECFILE_LNK 0x00000000014b4e4c
|
||||
#define NFS_SPECFILE_SOCK 0x000000004B434F53
|
||||
extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf;
|
||||
|
||||
#endif
|
||||
|
656
src/dll/fuse3/fuse2to3.c
Normal file
656
src/dll/fuse3/fuse2to3.c
Normal file
@ -0,0 +1,656 @@
|
||||
/**
|
||||
* @file dll/fuse3/fuse2to3.c
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/fuse3/library.h>
|
||||
|
||||
static inline struct fuse3 *fuse2to3_getfuse3(void)
|
||||
{
|
||||
return fsp_fuse_get_context_internal()->fuse->fuse3;
|
||||
}
|
||||
|
||||
static inline void fuse2to3_fi2from3(struct fuse_file_info *fi, struct fuse3_file_info *fi3)
|
||||
{
|
||||
memset(fi, 0, sizeof *fi);
|
||||
fi->flags = fi3->flags;
|
||||
fi->writepage = fi3->writepage;
|
||||
fi->direct_io = fi3->direct_io;
|
||||
fi->keep_cache = fi3->keep_cache;
|
||||
fi->flush = fi3->flush;
|
||||
fi->nonseekable = fi3->nonseekable;
|
||||
fi->fh = fi3->fh;
|
||||
fi->lock_owner = fi3->lock_owner;
|
||||
}
|
||||
|
||||
static inline void fuse2to3_fi3from2(struct fuse3_file_info *fi3, struct fuse_file_info *fi)
|
||||
{
|
||||
memset(fi3, 0, sizeof *fi3);
|
||||
fi3->flags = fi->flags;
|
||||
fi3->writepage = fi->writepage;
|
||||
fi3->direct_io = fi->direct_io;
|
||||
fi3->keep_cache = fi->keep_cache;
|
||||
fi3->flush = fi->flush;
|
||||
fi3->nonseekable = fi->nonseekable;
|
||||
fi3->fh = fi->fh;
|
||||
fi3->lock_owner = fi->lock_owner;
|
||||
}
|
||||
|
||||
static inline void fuse2to3_conn3from2(struct fuse3_conn_info *conn3, struct fuse_conn_info *conn)
|
||||
{
|
||||
memset(conn3, 0, sizeof *conn3);
|
||||
conn3->proto_major = 7; /* pretend that we are FUSE kernel protocol 7.26 */
|
||||
conn3->proto_minor = 26; /* which was current at the time of FUSE 3.2 */
|
||||
conn3->max_write = conn->max_write;
|
||||
conn3->max_read = conn->max_write;
|
||||
conn3->max_readahead = conn->max_readahead;
|
||||
conn3->capable = (conn->capable & ~FSP_FUSE_CAP_READDIR_PLUS) | FUSE_CAP_READDIRPLUS;
|
||||
conn3->want = conn->want;
|
||||
}
|
||||
|
||||
static int fuse2to3_getattr(const char *path, struct fuse_stat *stbuf)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.getattr(path, stbuf, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_readlink(const char *path, char *buf, size_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.readlink(path, buf, size);
|
||||
}
|
||||
|
||||
static int fuse2to3_mknod(const char *path, fuse_mode_t mode, fuse_dev_t dev)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.mknod(path, mode, dev);
|
||||
}
|
||||
|
||||
static int fuse2to3_mkdir(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.mkdir(path, mode);
|
||||
}
|
||||
|
||||
static int fuse2to3_unlink(const char *path)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.unlink(path);
|
||||
}
|
||||
|
||||
static int fuse2to3_rmdir(const char *path)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.rmdir(path);
|
||||
}
|
||||
|
||||
static int fuse2to3_symlink(const char *dstpath, const char *srcpath)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.symlink(dstpath, srcpath);
|
||||
}
|
||||
|
||||
static int fuse2to3_rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.rename(oldpath, newpath, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_link(const char *srcpath, const char *dstpath)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.link(srcpath, dstpath);
|
||||
}
|
||||
|
||||
static int fuse2to3_chmod(const char *path, fuse_mode_t mode)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.chmod(path, mode, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_chown(const char *path, fuse_uid_t uid, fuse_gid_t gid)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.chown(path, uid, gid, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_truncate(const char *path, fuse_off_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.truncate(path, size, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.open(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_read(const char *path, char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.read(path, buf, size, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_write(const char *path, const char *buf, size_t size, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.write(path, buf, size, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_statfs(const char *path, struct fuse_statvfs *stbuf)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.statfs(path, stbuf);
|
||||
}
|
||||
|
||||
static int fuse2to3_flush(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.flush(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_release(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.release(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fsync(const char *path, int datasync, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.fsync(path, datasync, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_setxattr(const char *path, const char *name, const char *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.setxattr(path, name, value, size, flags);
|
||||
}
|
||||
|
||||
static int fuse2to3_getxattr(const char *path, const char *name, char *value, size_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.getxattr(path, name, value, size);
|
||||
}
|
||||
|
||||
static int fuse2to3_listxattr(const char *path, char *namebuf, size_t size)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.listxattr(path, namebuf, size);
|
||||
}
|
||||
|
||||
static int fuse2to3_removexattr(const char *path, const char *name)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.removexattr(path, name);
|
||||
}
|
||||
|
||||
static int fuse2to3_opendir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.opendir(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_candel_filldir(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off,
|
||||
enum fuse3_fill_dir_flags flags)
|
||||
{
|
||||
return fsp_fuse_intf_CanDeleteAddDirInfo(buf, name, 0, off);
|
||||
}
|
||||
|
||||
static int fuse2to3_filldir(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off,
|
||||
enum fuse3_fill_dir_flags flags)
|
||||
{
|
||||
return 0 != (flags & FUSE_FILL_DIR_PLUS) ?
|
||||
fsp_fuse_intf_AddDirInfo(buf, name, stbuf, off) :
|
||||
fsp_fuse_intf_AddDirInfo(buf, name, 0, off);
|
||||
}
|
||||
|
||||
static int fuse2to3_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res;
|
||||
if (fsp_fuse_intf_CanDeleteAddDirInfo == filler)
|
||||
res = f3->ops.readdir(path, buf, &fuse2to3_candel_filldir, off, &fi3, 0);
|
||||
else if (fsp_fuse_intf_AddDirInfo == filler)
|
||||
res = f3->ops.readdir(path, buf, &fuse2to3_filldir, off, &fi3,
|
||||
dh->ReaddirPlus ? FUSE_READDIR_PLUS : 0);
|
||||
else
|
||||
{
|
||||
FspDebugLog("fuse2to3_readdir = -ENOSYS (internal error: unknown filler)\n");
|
||||
res = -ENOSYS_(f3->fuse->env);
|
||||
}
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.releasedir(path, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fsyncdir(const char *path, int datasync, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.fsyncdir(path, datasync, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void *fuse2to3_init(struct fuse_conn_info *conn)
|
||||
{
|
||||
struct fuse_context *context = fsp_fuse_get_context_internal();
|
||||
struct fuse *f = context->fuse;
|
||||
struct fuse3 *f3 = f->fuse3;
|
||||
|
||||
struct fuse3_conn_info conn3;
|
||||
fuse2to3_conn3from2(&conn3, conn);
|
||||
|
||||
struct fuse3_config conf3;
|
||||
memset(&conf3, 0, sizeof conf3);
|
||||
conf3.set_gid = f->set_gid;
|
||||
conf3.gid = f->gid;
|
||||
conf3.set_uid = f->set_uid;
|
||||
conf3.uid = f->uid;
|
||||
conf3.set_mode = f->set_umask;
|
||||
conf3.umask = f->umask;
|
||||
#if 0
|
||||
/*
|
||||
* Cannot set timeouts because of lack of floating point support.
|
||||
*
|
||||
* FUSE uses the `double` type for timeouts. This DLL does not use the standard library
|
||||
* for a variety of reasons. This means that we cannot easily perform the computations
|
||||
* below.
|
||||
*
|
||||
* If this becomes important (double) floating point values could perhaps be calculated
|
||||
* using bit tricks. See below:
|
||||
* - http://locklessinc.com/articles/i2f/
|
||||
* - https://stackoverflow.com/a/20308114
|
||||
*/
|
||||
conf3.entry_timeout = f->VolumeParams.DirInfoTimeoutValid ?
|
||||
f->VolumeParams.DirInfoTimeout / 1000 : f->VolumeParams.FileInfoTimeout / 1000;
|
||||
conf3.negative_timeout = 0;
|
||||
conf3.attr_timeout = f->VolumeParams.FileInfoTimeout / 1000;
|
||||
conf3.ac_attr_timeout = conf3.attr_timeout;
|
||||
#endif
|
||||
|
||||
void *res = f3->ops.init(&conn3, &conf3);
|
||||
|
||||
conn->max_write = conn3.max_write;
|
||||
conn->max_readahead = conn3.max_readahead;
|
||||
conn->want = 0 != (conn3.want & FUSE_CAP_READDIRPLUS) ? FSP_FUSE_CAP_READDIR_PLUS : 0;
|
||||
conn->want |= conn3.want & ~FUSE_CAP_READDIRPLUS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void fuse2to3_destroy(void *data)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
f3->ops.destroy(data);
|
||||
}
|
||||
|
||||
static int fuse2to3_access(const char *path, int mask)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.access(path, mask);
|
||||
}
|
||||
|
||||
static int fuse2to3_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.create(path, mode, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_ftruncate(const char *path, fuse_off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.truncate(path, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fgetattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.getattr(path, stbuf, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_lock(const char *path,
|
||||
struct fuse_file_info *fi, int cmd, struct fuse_flock *lock)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.lock(path, &fi3, cmd, lock);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_utimens(const char *path, const struct fuse_timespec tv[2])
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.utimens(path, tv, 0);
|
||||
}
|
||||
|
||||
static int fuse2to3_bmap(const char *path, size_t blocksize, uint64_t *idx)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
return f3->ops.bmap(path, blocksize, idx);
|
||||
}
|
||||
|
||||
static int fuse2to3_ioctl(const char *path, int cmd, void *arg, struct fuse_file_info *fi,
|
||||
unsigned int flags, void *data)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.ioctl(path, cmd, arg, &fi3, flags, data);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_poll(const char *path, struct fuse_file_info *fi,
|
||||
struct fuse_pollhandle *ph, unsigned *reventsp)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.poll(path, &fi3, (struct fuse3_pollhandle *)ph, reventsp);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_write_buf(const char *path,
|
||||
struct fuse_bufvec *buf, fuse_off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.write_buf(path,
|
||||
(struct fuse3_bufvec *)buf, /* revisit if we implement bufvec's */
|
||||
off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_read_buf(const char *path,
|
||||
struct fuse_bufvec **bufp, size_t size, fuse_off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.read_buf(path,
|
||||
(struct fuse3_bufvec **)bufp, /* revisit if we implement bufvec's */
|
||||
size, off, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_flock(const char *path, struct fuse_file_info *fi, int op)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.flock(path, &fi3, op);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse2to3_fallocate(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse3 *f3 = fuse2to3_getfuse3();
|
||||
struct fuse3_file_info fi3;
|
||||
fuse2to3_fi3from2(&fi3, fi);
|
||||
int res = f3->ops.fallocate(path, mode, off, len, &fi3);
|
||||
fuse2to3_fi2from3(fi, &fi3);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fsp_fuse3_copy_args(struct fsp_fuse_env *env,
|
||||
const struct fuse_args *args,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
outargs->argc = 0;
|
||||
outargs->argv = 0;
|
||||
outargs->allocated = 0;
|
||||
|
||||
for (int argi = 0; args->argc > argi; argi++)
|
||||
if (-1 == fsp_fuse_opt_add_arg(env, outargs, args->argv[argi]))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fsp_fuse_opt_free_args(env, outargs);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct fuse3 *fsp_fuse3_new_common(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data,
|
||||
int help)
|
||||
{
|
||||
/* preflight args */
|
||||
struct fsp_fuse_core_opt_data opt_data;
|
||||
struct fuse_args pfargs;
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
if (-1 == fsp_fuse3_copy_args(env, args, &pfargs))
|
||||
return 0;
|
||||
int optres = fsp_fuse_core_opt_parse(env, &pfargs, &opt_data, /*help=*/1);
|
||||
fsp_fuse_opt_free_args(env, &pfargs);
|
||||
if (-1 == optres)
|
||||
return 0;
|
||||
if (opt_data.help)
|
||||
return 0;
|
||||
|
||||
struct fuse3 *f3 = 0;
|
||||
|
||||
if (opsize > sizeof(struct fuse3_operations))
|
||||
opsize = sizeof(struct fuse3_operations);
|
||||
|
||||
f3 = fsp_fuse_obj_alloc(env, sizeof *f3);
|
||||
if (0 == f3)
|
||||
goto fail;
|
||||
|
||||
if (-1 == fsp_fuse3_copy_args(env, args, &f3->args))
|
||||
goto fail;
|
||||
memcpy(&f3->ops, ops, opsize);
|
||||
f3->data = data;
|
||||
|
||||
return f3;
|
||||
|
||||
fail:
|
||||
if (0 != f3)
|
||||
fsp_fuse3_destroy(env, f3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3 *fsp_fuse3_new_30(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data)
|
||||
{
|
||||
return fsp_fuse3_new_common(env, args, ops, opsize, data, /*help=*/1);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3 *fsp_fuse3_new(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args,
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data)
|
||||
{
|
||||
return fsp_fuse3_new_common(env, args, ops, opsize, data, /*help=*/0);
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_destroy(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
if (0 != f3->fuse)
|
||||
fsp_fuse_destroy(env, f3->fuse);
|
||||
|
||||
fsp_fuse_opt_free_args(env, &f3->args);
|
||||
|
||||
fsp_fuse_obj_free(f3);
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_mount(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3, const char *mountpoint)
|
||||
{
|
||||
struct fuse_chan *ch = 0;
|
||||
struct fuse *f = 0;
|
||||
struct fuse_operations fuse2to3_ops =
|
||||
{
|
||||
.getattr = 0 != f3->ops.getattr ? fuse2to3_getattr : 0,
|
||||
.readlink = 0 != f3->ops.readlink ? fuse2to3_readlink : 0,
|
||||
.mknod = 0 != f3->ops.mknod ? fuse2to3_mknod : 0,
|
||||
.mkdir = 0 != f3->ops.mkdir ? fuse2to3_mkdir : 0,
|
||||
.unlink = 0 != f3->ops.unlink ? fuse2to3_unlink : 0,
|
||||
.rmdir = 0 != f3->ops.rmdir ? fuse2to3_rmdir : 0,
|
||||
.symlink = 0 != f3->ops.symlink ? fuse2to3_symlink : 0,
|
||||
.rename = 0 != f3->ops.rename ? fuse2to3_rename : 0,
|
||||
.link = 0 != f3->ops.link ? fuse2to3_link : 0,
|
||||
.chmod = 0 != f3->ops.chmod ? fuse2to3_chmod : 0,
|
||||
.chown = 0 != f3->ops.chown ? fuse2to3_chown : 0,
|
||||
.truncate = 0 != f3->ops.truncate ? fuse2to3_truncate : 0,
|
||||
.open = 0 != f3->ops.open ? fuse2to3_open : 0,
|
||||
.read = 0 != f3->ops.read ? fuse2to3_read : 0,
|
||||
.write = 0 != f3->ops.write ? fuse2to3_write : 0,
|
||||
.statfs = 0 != f3->ops.statfs ? fuse2to3_statfs : 0,
|
||||
.flush = 0 != f3->ops.flush ? fuse2to3_flush : 0,
|
||||
.release = 0 != f3->ops.release ? fuse2to3_release : 0,
|
||||
.fsync = 0 != f3->ops.fsync ? fuse2to3_fsync : 0,
|
||||
.setxattr = 0 != f3->ops.setxattr ? fuse2to3_setxattr : 0,
|
||||
.getxattr = 0 != f3->ops.getxattr ? fuse2to3_getxattr : 0,
|
||||
.listxattr = 0 != f3->ops.listxattr ? fuse2to3_listxattr : 0,
|
||||
.removexattr = 0 != f3->ops.removexattr ? fuse2to3_removexattr : 0,
|
||||
.opendir = 0 != f3->ops.opendir ? fuse2to3_opendir : 0,
|
||||
.readdir = 0 != f3->ops.readdir ? fuse2to3_readdir : 0,
|
||||
.releasedir = 0 != f3->ops.releasedir ? fuse2to3_releasedir : 0,
|
||||
.fsyncdir = 0 != f3->ops.fsyncdir ? fuse2to3_fsyncdir : 0,
|
||||
.init = 0 != f3->ops.init ? fuse2to3_init : 0,
|
||||
.destroy = 0 != f3->ops.destroy ? fuse2to3_destroy : 0,
|
||||
.access = 0 != f3->ops.access ? fuse2to3_access : 0,
|
||||
.create = 0 != f3->ops.create ? fuse2to3_create : 0,
|
||||
.ftruncate = 0 != f3->ops.truncate ? fuse2to3_ftruncate : 0,
|
||||
.fgetattr = 0 != f3->ops.getattr ? fuse2to3_fgetattr : 0,
|
||||
.lock = 0 != f3->ops.lock ? fuse2to3_lock : 0,
|
||||
.utimens = 0 != f3->ops.utimens ? fuse2to3_utimens : 0,
|
||||
.bmap = 0 != f3->ops.bmap ? fuse2to3_bmap : 0,
|
||||
.ioctl = 0 != f3->ops.ioctl ? fuse2to3_ioctl : 0,
|
||||
.poll = 0 != f3->ops.poll ? fuse2to3_poll : 0,
|
||||
.write_buf = 0 != f3->ops.write_buf ? fuse2to3_write_buf : 0,
|
||||
.read_buf = 0 != f3->ops.read_buf ? fuse2to3_read_buf : 0,
|
||||
.flock = 0 != f3->ops.flock ? fuse2to3_flock : 0,
|
||||
.fallocate = 0 != f3->ops.fallocate ? fuse2to3_fallocate : 0,
|
||||
};
|
||||
|
||||
ch = fsp_fuse_mount(env, mountpoint, &f3->args);
|
||||
if (0 == ch)
|
||||
goto fail;
|
||||
|
||||
f = fsp_fuse_new(env, ch, &f3->args, &fuse2to3_ops, sizeof fuse2to3_ops, f3->data);
|
||||
if (0 == f)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Free the fuse_chan which is no longer needed. Note that this behavior is WinFsp-FUSE
|
||||
* specific, because WinFsp-FUSE only allocates/frees fuse_chan memory during fuse_mount/
|
||||
* fuse_unmount and does not perform any actual mounting/unmounting. This would not work
|
||||
* on a different FUSE implementation.
|
||||
*
|
||||
* (Store mountpoint and ch inside struct fuse3 so that they can be freed during fuse_destroy
|
||||
* in that case.)
|
||||
*/
|
||||
fsp_fuse_unmount(env, mountpoint, ch);
|
||||
|
||||
/* Free the args which are no longer needed. */
|
||||
fsp_fuse_opt_free_args(env, &f3->args);
|
||||
|
||||
f->fuse3 = f3;
|
||||
f3->fuse = f;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (0 != f)
|
||||
fsp_fuse_destroy(env, f);
|
||||
|
||||
if (0 != ch)
|
||||
fsp_fuse_unmount(env, mountpoint, ch);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_unmount(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
fsp_fuse_destroy(env, f3->fuse);
|
||||
f3->fuse = 0;
|
||||
}
|
154
src/dll/fuse3/fuse3.c
Normal file
154
src/dll/fuse3/fuse3.c
Normal file
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @file dll/fuse3/fuse3.c
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/fuse3/library.h>
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_main_real(struct fsp_fuse_env *env,
|
||||
int argc, char *argv[],
|
||||
const struct fuse3_operations *ops, size_t opsize, void *data)
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
char *mountpoint = 0;
|
||||
int multithreaded = 0;
|
||||
int foreground = 0;
|
||||
struct fuse3 *f3 = 0;
|
||||
int mounted = 0;
|
||||
int signal_handlers = 0;
|
||||
int result;
|
||||
|
||||
result = fsp_fuse_parse_cmdline(env, &args, &mountpoint, &multithreaded, &foreground);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
|
||||
f3 = fsp_fuse3_new_30(env, &args, ops, opsize, data);
|
||||
if (0 == f3)
|
||||
{
|
||||
result = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
result = fsp_fuse3_mount(env, f3, mountpoint);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
mounted = 1;
|
||||
|
||||
result = env->daemonize(foreground);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
|
||||
result = env->set_signal_handlers(f3);
|
||||
if (-1 == result)
|
||||
goto exit;
|
||||
signal_handlers = 1;
|
||||
|
||||
result = multithreaded ? fsp_fuse3_loop_mt(env, f3, 0) : fsp_fuse3_loop(env, f3);
|
||||
|
||||
exit:
|
||||
if (signal_handlers)
|
||||
env->set_signal_handlers(0);
|
||||
|
||||
if (mounted)
|
||||
fsp_fuse3_unmount(env, f3);
|
||||
|
||||
if (0 != f3)
|
||||
fsp_fuse3_destroy(env, f3);
|
||||
|
||||
env->memfree(mountpoint);
|
||||
|
||||
fsp_fuse_opt_free_args(env, &args);
|
||||
|
||||
/* main() style return: 0 success, 1 error */
|
||||
return !!result;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_lib_help(struct fsp_fuse_env *env,
|
||||
struct fuse_args *args)
|
||||
{
|
||||
char *helpargv[] =
|
||||
{
|
||||
"UNKNOWN",
|
||||
"-h",
|
||||
0
|
||||
};
|
||||
struct fuse_args helpargs = FUSE_ARGS_INIT(2, helpargv);
|
||||
struct fsp_fuse_core_opt_data opt_data;
|
||||
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
fsp_fuse_core_opt_parse(env, &helpargs, &opt_data, /*help=*/1);
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_loop(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
return 0 == fsp_fuse_loop(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_loop_mt_31(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3, int clone_fd)
|
||||
{
|
||||
return 0 == fsp_fuse_loop_mt(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */;
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_loop_mt(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3, struct fuse3_loop_config *config)
|
||||
{
|
||||
return 0 == fsp_fuse_loop_mt(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_exit(struct fsp_fuse_env *env,
|
||||
struct fuse3 *f3)
|
||||
{
|
||||
fsp_fuse_exit(env, f3->fuse);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3_context *fsp_fuse3_get_context(struct fsp_fuse_env *env)
|
||||
{
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
sizeof(struct fuse_context) == sizeof(struct fuse3_context),
|
||||
"incompatible structs fuse_context and fuse3_context");
|
||||
FSP_FSCTL_STATIC_ASSERT(FIELD_OFFSET(
|
||||
struct fuse_context, private_data) == FIELD_OFFSET(struct fuse3_context, private_data),
|
||||
"incompatible structs fuse_context and fuse3_context");
|
||||
return (struct fuse3_context *)fsp_fuse_get_context(env);
|
||||
}
|
||||
|
||||
FSP_FUSE_API struct fuse3_conn_info_opts *fsp_fuse3_parse_conn_info_opts(
|
||||
struct fsp_fuse_env *env,
|
||||
struct fuse_args *args)
|
||||
{
|
||||
static int dummy;
|
||||
return (struct fuse3_conn_info_opts *)&dummy;
|
||||
}
|
||||
|
||||
FSP_FUSE_API void fsp_fuse3_apply_conn_info_opts(struct fsp_fuse_env *env,
|
||||
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn)
|
||||
{
|
||||
}
|
||||
|
||||
FSP_FUSE_API int fsp_fuse3_version(struct fsp_fuse_env *env)
|
||||
{
|
||||
return FUSE_VERSION;
|
||||
}
|
||||
|
||||
FSP_FUSE_API const char *fsp_fuse3_pkgversion(struct fsp_fuse_env *env)
|
||||
{
|
||||
#define STR(x) STR_(x)
|
||||
#define STR_(x) #x
|
||||
return STR(FUSE_MAJOR_VERSION) "." STR(FUSE_MINOR_VERSION);
|
||||
#undef STR_
|
||||
#undef STR
|
||||
}
|
10
src/dll/fuse3/fuse3.pc.in
Normal file
10
src/dll/fuse3/fuse3.pc.in
Normal file
@ -0,0 +1,10 @@
|
||||
prefix=${pcfiledir}/..
|
||||
incdir=${prefix}/inc/fuse3
|
||||
implib=${prefix}/bin/winfsp-${arch}.dll
|
||||
|
||||
Name: fuse3
|
||||
Description: WinFsp FUSE3 compatible API
|
||||
Version: 3.2
|
||||
URL: http://www.secfs.net/winfsp/
|
||||
Libs: "${implib}"
|
||||
Cflags: -I"${incdir}"
|
34
src/dll/fuse3/fuse3_compat.c
Normal file
34
src/dll/fuse3/fuse3_compat.c
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse3_compat.c
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
/*
|
||||
* This file provides an implementation of the `fuse3_*` symbols. This
|
||||
* implementation is a simple shim that forwards `fuse3_*` calls to the
|
||||
* equivalent `fsp_fuse3_*` ones using a default `fsp_fuse_env`.
|
||||
*
|
||||
* These symbols should *not* be used by C/C++ programs. For this reason
|
||||
* the `fuse.h` headers only expose the `fsp_fuse3_*` symbols, wrapped
|
||||
* with macros. These symbols are for use only from programs using FFI
|
||||
* technology to access FUSE symbols (e.g. fusepy, jnr-fuse).
|
||||
*/
|
||||
|
||||
#define FSP_FUSE_API
|
||||
#define FSP_FUSE_SYM(proto, ...) __declspec(dllexport) proto { __VA_ARGS__ }
|
||||
#include <fuse3/fuse_common.h>
|
||||
#include <fuse3/fuse.h>
|
37
src/dll/fuse3/library.h
Normal file
37
src/dll/fuse3/library.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file dll/fuse3/library.h
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_DLL_FUSE3_LIBRARY_H_INCLUDED
|
||||
#define WINFSP_DLL_FUSE3_LIBRARY_H_INCLUDED
|
||||
|
||||
#include <dll/fuse/library.h>
|
||||
#undef FUSE_H_
|
||||
#undef FUSE_COMMON_H_
|
||||
#undef FUSE_MAJOR_VERSION
|
||||
#undef FUSE_MINOR_VERSION
|
||||
#undef fuse_main
|
||||
#include <fuse3/fuse.h>
|
||||
|
||||
struct fuse3
|
||||
{
|
||||
struct fuse_args args;
|
||||
struct fuse3_operations ops;
|
||||
void *data;
|
||||
struct fuse *fuse;
|
||||
};
|
||||
|
||||
#endif
|
329
src/dll/launch.c
329
src/dll/launch.c
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <launcher/launcher.h>
|
||||
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
@ -27,11 +26,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
NTSTATUS Result;
|
||||
ULONG ErrorCode;
|
||||
|
||||
if (0 != PSize)
|
||||
*PSize = 0;
|
||||
*PLauncherError = 0;
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
@ -44,7 +41,7 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
if (0 != Argv[I])
|
||||
{
|
||||
Length = 0 == Argl || -1 == Argl[I] ? lstrlenW(Argv[I]) : Argl[I];
|
||||
if (LAUNCHER_PIPE_BUFFER_SIZE < ((ULONG)(P - PipeBuf) + Length + 1) * sizeof(WCHAR))
|
||||
if (FSP_LAUNCH_PIPE_BUFFER_SIZE < ((ULONG)(P - PipeBuf) + Length + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
@ -52,9 +49,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
memcpy(P, Argv[I], Length * sizeof(WCHAR)); P += Length; *P++ = L'\0';
|
||||
}
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME,
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME,
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
@ -62,18 +59,18 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
ErrorCode = ERROR_BROKEN_PIPE; /* protocol error! */
|
||||
if (sizeof(WCHAR) <= BytesTransferred)
|
||||
{
|
||||
if (LauncherSuccess == PipeBuf[0])
|
||||
if (FspLaunchCmdSuccess == PipeBuf[0])
|
||||
{
|
||||
ErrorCode = 0;
|
||||
|
||||
if (0 != PSize)
|
||||
{
|
||||
BytesTransferred -= sizeof(WCHAR);
|
||||
memcpy(Buffer, PipeBuf, *PSize < BytesTransferred ? *PSize : BytesTransferred);
|
||||
memcpy(Buffer, PipeBuf + 1, *PSize < BytesTransferred ? *PSize : BytesTransferred);
|
||||
*PSize = BytesTransferred;
|
||||
}
|
||||
}
|
||||
else if (LauncherFailure == PipeBuf[0])
|
||||
else if (FspLaunchCmdFailure == PipeBuf[0])
|
||||
{
|
||||
ErrorCode = 0;
|
||||
|
||||
@ -92,6 +89,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
*PLauncherError = ErrorCode;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result) && 0 != PSize)
|
||||
*PSize = 0;
|
||||
|
||||
MemFree(PipeBuf);
|
||||
|
||||
return Result;
|
||||
@ -109,10 +109,10 @@ FSP_API NTSTATUS FspLaunchStart(
|
||||
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
memcpy(Argv + 2, Argv, Argc * sizeof(PWSTR));
|
||||
memcpy(Argv + 2, Argv0, Argc * sizeof(PWSTR));
|
||||
|
||||
return FspLaunchCallLauncherPipe(
|
||||
HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart,
|
||||
HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||
Argc + 2, Argv, 0, 0, 0, PLauncherError);
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ FSP_API NTSTATUS FspLaunchStop(
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
|
||||
return FspLaunchCallLauncherPipe(LauncherSvcInstanceStop,
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdStop,
|
||||
2, Argv, 0, 0, 0, PLauncherError);
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
|
||||
return FspLaunchCallLauncherPipe(LauncherSvcInstanceInfo,
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdGetInfo,
|
||||
2, Argv, 0, Buffer, PSize, PLauncherError);
|
||||
}
|
||||
|
||||
@ -147,6 +147,303 @@ FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError)
|
||||
{
|
||||
return FspLaunchCallLauncherPipe(LauncherSvcInstanceList,
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdGetNameList,
|
||||
0, 0, 0, Buffer, PSize, PLauncherError);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record)
|
||||
{
|
||||
#define SETFIELD(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
if (0 != Record->FieldName) \
|
||||
{ \
|
||||
RegResult = RegSetValueExW(RegKey,\
|
||||
L"" #FieldName, 0, REG_SZ,\
|
||||
(PVOID)Record->FieldName, (lstrlenW(Record->FieldName) + 1) * sizeof(WCHAR));\
|
||||
if (ERROR_SUCCESS != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegResult = RegDeleteValueW(RegKey,\
|
||||
L"" #FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
} while (0,0)
|
||||
#define SETFIELDI(FieldName, Deflt) \
|
||||
do \
|
||||
{ \
|
||||
if (Deflt != Record->FieldName) \
|
||||
{ \
|
||||
RegResult = RegSetValueExW(RegKey,\
|
||||
L"" #FieldName, 0, REG_DWORD,\
|
||||
(PVOID)&Record->FieldName, sizeof Record->FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegResult = RegDeleteValueW(RegKey,\
|
||||
L"" #FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
} while (0,0)
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG ClassNameLen;
|
||||
WCHAR RegPath[MAX_PATH];
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult;
|
||||
|
||||
if (0 != Record && 0 == Record->Executable)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ClassNameLen = lstrlenW(ClassName);
|
||||
if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR));
|
||||
RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\';
|
||||
memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR),
|
||||
ClassName, (ClassNameLen + 1) * sizeof(WCHAR));
|
||||
|
||||
if (0 != Record)
|
||||
{
|
||||
RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, RegPath,
|
||||
0, 0, 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_SET_VALUE, 0, &RegKey, 0);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
SETFIELD(Agent);
|
||||
SETFIELD(Executable);
|
||||
SETFIELD(CommandLine);
|
||||
SETFIELD(WorkDirectory);
|
||||
SETFIELD(RunAs);
|
||||
SETFIELD(Security);
|
||||
SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */
|
||||
SETFIELDI(Credentials, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RegResult = RegDeleteKeyEx(HKEY_LOCAL_MACHINE, RegPath,
|
||||
FSP_LAUNCH_REGKEY_WOW64, 0);
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return Result;
|
||||
|
||||
#undef SETFIELD
|
||||
#undef SETFIELDI
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName, PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord)
|
||||
{
|
||||
#define GETFIELD(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
RegSize = sizeof RegBuf - RegMark;\
|
||||
RegResult = RegQueryValueEx(RegKey,\
|
||||
L"" #FieldName, 0, &RegType,\
|
||||
(PVOID)(RegBuf + RegMark), &RegSize);\
|
||||
if (ERROR_SUCCESS != RegResult) \
|
||||
{ \
|
||||
if (ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else if (REG_SZ != RegType || \
|
||||
sizeof(WCHAR) > RegSize || \
|
||||
L'\0' != *(PWSTR)(RegBuf + RegMark + RegSize - sizeof(WCHAR)))\
|
||||
{ \
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;\
|
||||
goto exit; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Record->FieldName = (PWSTR)(RegBuf + RegMark);\
|
||||
RegMark += RegSize; \
|
||||
} \
|
||||
} while (0,0)
|
||||
#define GETFIELDI(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
RegSize = sizeof RegDword; \
|
||||
RegResult = RegQueryValueEx(RegKey,\
|
||||
L"" #FieldName, 0, &RegType,\
|
||||
(PVOID)&RegDword, &RegSize);\
|
||||
if (ERROR_SUCCESS != RegResult) \
|
||||
{ \
|
||||
if (ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else if (REG_DWORD != RegType) \
|
||||
{ \
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;\
|
||||
goto exit; \
|
||||
} \
|
||||
else \
|
||||
Record->FieldName = RegDword;\
|
||||
} while (0,0)
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG ClassNameLen;
|
||||
WCHAR RegPath[MAX_PATH];
|
||||
FSP_LAUNCH_REG_RECORD RecordBuf, *Record = &RecordBuf;
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult, RegDword, RegType, RegSize, RegMark;
|
||||
UINT8 RegBuf[2 * 1024];
|
||||
PWSTR P, Part;
|
||||
BOOLEAN FoundAgent;
|
||||
|
||||
*PRecord = 0;
|
||||
|
||||
ClassNameLen = lstrlenW(ClassName);
|
||||
if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR));
|
||||
RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\';
|
||||
memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR),
|
||||
ClassName, (ClassNameLen + 1) * sizeof(WCHAR));
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegPath,
|
||||
0, FSP_LAUNCH_REGKEY_WOW64 | KEY_QUERY_VALUE, &RegKey);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Record, 0, sizeof *Record);
|
||||
Record->JobControl = 1; /* default is YES! */
|
||||
RegMark = 0;
|
||||
|
||||
GETFIELD(Agent);
|
||||
if (0 != Agent && L'\0' != Agent[0] &&
|
||||
0 != Record->Agent && L'\0' != Record->Agent[0])
|
||||
{
|
||||
FoundAgent = FALSE;
|
||||
P = Record->Agent, Part = P;
|
||||
do
|
||||
{
|
||||
if (L',' == *P || '\0' == *P)
|
||||
{
|
||||
if (0 == invariant_wcsnicmp(Part, Agent, P - Part))
|
||||
{
|
||||
FoundAgent = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
Part = P + 1;
|
||||
}
|
||||
} while (L'\0' != *P++);
|
||||
|
||||
if (!FoundAgent)
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
GETFIELD(Executable);
|
||||
GETFIELD(CommandLine);
|
||||
GETFIELD(WorkDirectory);
|
||||
GETFIELD(RunAs);
|
||||
GETFIELD(Security);
|
||||
GETFIELDI(JobControl);
|
||||
GETFIELDI(Credentials);
|
||||
|
||||
if (0 == Record->Executable)
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Record = MemAlloc(FIELD_OFFSET(FSP_LAUNCH_REG_RECORD, Buffer) + RegMark);
|
||||
if (0 == Record)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Record, 0, sizeof *Record);
|
||||
memcpy(Record->Buffer, RegBuf, RegMark);
|
||||
Record->Agent = 0 != RecordBuf.Agent ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Agent - RegBuf)) : 0;
|
||||
Record->Executable = 0 != RecordBuf.Executable ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Executable - RegBuf)) : 0;
|
||||
Record->CommandLine = 0 != RecordBuf.CommandLine ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.CommandLine - RegBuf)) : 0;
|
||||
Record->WorkDirectory = 0 != RecordBuf.WorkDirectory ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.WorkDirectory - RegBuf)) : 0;
|
||||
Record->RunAs = 0 != RecordBuf.RunAs ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0;
|
||||
Record->Security = 0 != RecordBuf.Security ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0;
|
||||
Record->JobControl = RecordBuf.JobControl;
|
||||
Record->Credentials = RecordBuf.Credentials;
|
||||
|
||||
*PRecord = Record;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return Result;
|
||||
|
||||
#undef GETFIELDI
|
||||
#undef GETFIELD
|
||||
}
|
||||
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record)
|
||||
{
|
||||
MemFree(Record);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#define WINFSP_DLL_INTERNAL
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
|
58
src/dll/np.c
58
src/dll/np.c
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <launcher/launcher.h>
|
||||
#include <npapi.h>
|
||||
#include <wincred.h>
|
||||
|
||||
@ -248,14 +247,13 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
{
|
||||
HKEY RegKey = 0;
|
||||
DWORD NpResult, RegSize;
|
||||
DWORD Credentials;
|
||||
PWSTR ClassName, InstanceName;
|
||||
ULONG ClassNameLen, InstanceNameLen;
|
||||
WCHAR ClassNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||
FSP_LAUNCH_REG_RECORD *Record;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
||||
|
||||
@ -268,34 +266,22 @@ static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
||||
ClassNameBuf[ClassNameLen] = '\0';
|
||||
|
||||
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
if (ERROR_SUCCESS != NpResult)
|
||||
goto exit;
|
||||
Result = FspLaunchRegGetRecord(ClassNameBuf, L"" FSP_NP_NAME, &Record);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return WN_NO_NETWORK;
|
||||
|
||||
RegSize = sizeof Credentials;
|
||||
Credentials = 0; /* default is NO credentials */
|
||||
NpResult = RegGetValueW(RegKey, ClassNameBuf, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||
&Credentials, &RegSize);
|
||||
if (ERROR_SUCCESS != NpResult && ERROR_FILE_NOT_FOUND != NpResult)
|
||||
goto exit;
|
||||
|
||||
switch (Credentials)
|
||||
switch (Record->Credentials)
|
||||
{
|
||||
case FSP_NP_CREDENTIALS_NONE:
|
||||
case FSP_NP_CREDENTIALS_PASSWORD:
|
||||
case FSP_NP_CREDENTIALS_USERPASS:
|
||||
*PCredentialsKind = Credentials;
|
||||
*PCredentialsKind = Record->Credentials;
|
||||
break;
|
||||
}
|
||||
|
||||
NpResult = ERROR_SUCCESS;
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return NpResult;
|
||||
return WN_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD FspNpGetCredentials(
|
||||
@ -410,7 +396,7 @@ DWORD APIENTRY NPGetConnection(
|
||||
|
||||
Result = FspNpGetVolumeList(&VolumeListBuf, &VolumeListSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return WN_OUT_OF_MEMORY;
|
||||
return WN_NOT_CONNECTED;
|
||||
|
||||
NpResult = WN_NOT_CONNECTED;
|
||||
for (P = VolumeListBuf, VolumeListBufEnd = (PVOID)((PUINT8)P + VolumeListSize), VolumeName = P;
|
||||
@ -503,7 +489,9 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
return WN_ALREADY_CONNECTED;
|
||||
}
|
||||
|
||||
FspNpGetCredentialsKind(lpRemoteName, &CredentialsKind);
|
||||
NpResult = FspNpGetRemoteInfo(lpRemoteName, &CredentialsKind);
|
||||
if (WN_SUCCESS != NpResult)
|
||||
return NpResult;
|
||||
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
/* if we need credentials and none were passed check with the credential manager */
|
||||
@ -557,8 +545,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
}
|
||||
|
||||
NpResult = FspNpCallLauncherPipe(
|
||||
FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
|
||||
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart,
|
||||
FSP_NP_CREDENTIALS_NONE != CredentialsKind ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||
Argc, Argv, Argl, 0, 0);
|
||||
switch (NpResult)
|
||||
{
|
||||
@ -610,7 +597,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
|
||||
if (WN_SUCCESS != FspNpCallLauncherPipe(
|
||||
LauncherSvcInstanceInfo,
|
||||
FspLaunchCmdGetInfo,
|
||||
Argc, Argv, Argl, 0, 0))
|
||||
{
|
||||
/* looks like the file system is gone! */
|
||||
@ -688,7 +675,9 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
||||
return NpResult;
|
||||
}
|
||||
|
||||
FspNpGetCredentialsKind(RemoteName, &CredentialsKind);
|
||||
NpResult = FspNpGetRemoteInfo(RemoteName, &CredentialsKind);
|
||||
if (WN_SUCCESS != NpResult)
|
||||
return NpResult;
|
||||
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
||||
return WN_CANCEL;
|
||||
|
||||
@ -772,7 +761,7 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
|
||||
NpResult = FspNpCallLauncherPipe(
|
||||
LauncherSvcInstanceStop,
|
||||
FspLaunchCmdStop,
|
||||
Argc, Argv, Argl, 0, 0);
|
||||
switch (NpResult)
|
||||
{
|
||||
@ -1045,6 +1034,13 @@ NTSTATUS FspNpRegister(VOID)
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
RegResult = RegSetValueExW(RegKey,
|
||||
L"DeviceName", 0, REG_SZ,
|
||||
(PVOID)L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME,
|
||||
sizeof L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
RegResult = RegOpenKeyExW(
|
||||
|
@ -251,7 +251,7 @@ FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
||||
|
||||
/* ENTER CONSOLE MODE! */
|
||||
|
||||
/* create/reset the console mode event and console control handler */
|
||||
/* create the console mode event and console control handler */
|
||||
if (0 == FspServiceConsoleModeEvent)
|
||||
{
|
||||
FspServiceConsoleModeEvent = CreateEventW(0, TRUE, FALSE, 0);
|
||||
@ -267,12 +267,14 @@ FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
||||
goto console_mode_exit;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
ResetEvent(FspServiceConsoleModeEvent);
|
||||
FspServiceConsoleCtrlHandlerDisabled = 0;
|
||||
MemoryBarrier();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* prepare the command line arguments */
|
||||
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||
|
@ -966,6 +966,49 @@ namespace Fsp
|
||||
FileInfo = default(FileInfo);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Processes a control code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function is called when a program uses the DeviceIoControl API.
|
||||
/// </remarks>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory to be controled.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory to be controled.
|
||||
/// </param>
|
||||
/// <param name="ControlCode">
|
||||
/// The control code for the operation. This code must have a DeviceType with bit
|
||||
/// 0x8000 set and must have a TransferType of METHOD_BUFFERED.
|
||||
/// </param>
|
||||
/// <param name="InputBuffer">
|
||||
/// Pointer to a buffer that contains the input data.
|
||||
/// </param>
|
||||
/// <param name="InputBufferLength">
|
||||
/// Input data length.
|
||||
/// </param>
|
||||
/// <param name="OutputBuffer">
|
||||
/// Pointer to a buffer that will receive the output data.
|
||||
/// </param>
|
||||
/// <param name="OutputBufferLength">
|
||||
/// Output data length.
|
||||
/// </param>
|
||||
/// <param name="BytesTransferred">
|
||||
/// Receives the actual number of bytes transferred.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
public virtual Int32 Control(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
UInt32 ControlCode,
|
||||
IntPtr InputBuffer, UInt32 InputBufferLength,
|
||||
IntPtr OutputBuffer, UInt32 OutputBufferLength,
|
||||
out UInt32 BytesTransferred)
|
||||
{
|
||||
BytesTransferred = default(UInt32);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
/* helpers */
|
||||
/// <summary>
|
||||
|
@ -194,6 +194,11 @@ namespace Fsp
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PassQueryDirectoryFileName); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PassQueryDirectoryFileName : 0); }
|
||||
}
|
||||
public Boolean FlushAndPurgeOnCleanup
|
||||
{
|
||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.FlushAndPurgeOnCleanup); }
|
||||
set { _VolumeParams.Flags |= (value ? VolumeParams.FlushAndPurgeOnCleanup : 0); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the prefix for a network file system.
|
||||
/// </summary>
|
||||
@ -347,6 +352,13 @@ namespace Fsp
|
||||
{
|
||||
return Api.SetDebugLogFile(FileName);
|
||||
}
|
||||
/// <summary>
|
||||
/// Return the installed version of WinFsp.
|
||||
/// </summary>
|
||||
public static Version Version()
|
||||
{
|
||||
return Api.GetVersion();
|
||||
}
|
||||
|
||||
/* FSP_FILE_SYSTEM_INTERFACE */
|
||||
private static Byte[] ByteBufferNotNull = new Byte[0];
|
||||
@ -1020,6 +1032,35 @@ namespace Fsp
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Control(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
UInt32 ControlCode,
|
||||
IntPtr InputBuffer, UInt32 InputBufferLength,
|
||||
IntPtr OutputBuffer, UInt32 OutputBufferLength,
|
||||
out UInt32 PBytesTransferred)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Control(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
ControlCode,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
out PBytesTransferred);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PBytesTransferred = default(UInt32);
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
|
||||
static FileSystemHost()
|
||||
{
|
||||
@ -1048,6 +1089,7 @@ namespace Fsp
|
||||
_FileSystemInterface.DeleteReparsePoint = DeleteReparsePoint;
|
||||
_FileSystemInterface.GetStreamInfo = GetStreamInfo;
|
||||
_FileSystemInterface.GetDirInfoByName = GetDirInfoByName;
|
||||
_FileSystemInterface.Control = Control;
|
||||
|
||||
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
||||
Marshal.StructureToPtr(_FileSystemInterface, _FileSystemInterfacePtr, false);
|
||||
|
@ -43,6 +43,7 @@ namespace Fsp.Interop
|
||||
internal const UInt32 PassQueryDirectoryPattern = 0x00000800;
|
||||
internal const UInt32 AlwaysUseDoubleBuffering = 0x00001000;
|
||||
internal const UInt32 PassQueryDirectoryFileName = 0x00002000;
|
||||
internal const UInt32 FlushAndPurgeOnCleanup = 0x00004000;
|
||||
internal const UInt32 UmFileContextIsUserContext2 = 0x00010000;
|
||||
internal const UInt32 UmFileContextIsFullContext = 0x00020000;
|
||||
internal const int PrefixSize = 192;
|
||||
@ -457,6 +458,14 @@ namespace Fsp.Interop
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
out DirInfo DirInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Control(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
UInt32 ControlCode,
|
||||
IntPtr InputBuffer, UInt32 InputBufferLength,
|
||||
IntPtr OutputBuffer, UInt32 OutputBufferLength,
|
||||
out UInt32 PBytesTransferred);
|
||||
}
|
||||
|
||||
internal static int Size = IntPtr.Size * 64;
|
||||
@ -486,7 +495,8 @@ namespace Fsp.Interop
|
||||
internal Proto.DeleteReparsePoint DeleteReparsePoint;
|
||||
internal Proto.GetStreamInfo GetStreamInfo;
|
||||
internal Proto.GetDirInfoByName GetDirInfoByName;
|
||||
/* NTSTATUS (*Reserved[39])(); */
|
||||
internal Proto.Control Control;
|
||||
/* NTSTATUS (*Reserved[38])(); */
|
||||
}
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
@ -970,6 +980,13 @@ namespace Fsp.Interop
|
||||
return 0/*STATUS_SUCCESS*/;
|
||||
}
|
||||
|
||||
internal static Version GetVersion()
|
||||
{
|
||||
UInt32 Version = 0;
|
||||
FspVersion(out Version);
|
||||
return new System.Version((Int32)Version >> 16, (Int32)Version & 0xFFFF);
|
||||
}
|
||||
|
||||
/* initialization */
|
||||
private static IntPtr LoadDll()
|
||||
{
|
||||
|
@ -15,7 +15,8 @@
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <launcher/launcher.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
|
||||
#define PROGNAME "launchctl"
|
||||
|
||||
@ -67,15 +68,15 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
NTSTATUS Result;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
||||
LastError = FspWin32FromNtStatus(Result);
|
||||
|
||||
if (0 != LastError)
|
||||
warn("KO CallNamedPipe = %ld", LastError);
|
||||
else if (sizeof(WCHAR) > BytesTransferred)
|
||||
warn("KO launcher: empty buffer");
|
||||
else if (LauncherSuccess == PipeBuf[0])
|
||||
else if (FspLaunchCmdSuccess == PipeBuf[0])
|
||||
{
|
||||
if (sizeof(WCHAR) == BytesTransferred)
|
||||
info("OK");
|
||||
@ -100,7 +101,7 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
info("OK\n%S", PipeBuf + 1);
|
||||
}
|
||||
}
|
||||
else if (LauncherFailure == PipeBuf[0])
|
||||
else if (FspLaunchCmdFailure == PipeBuf[0])
|
||||
{
|
||||
if (BytesTransferred < RecvSize)
|
||||
PipeBuf[BytesTransferred / sizeof(WCHAR)] = L'\0';
|
||||
@ -132,7 +133,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||
*P++ = HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||
@ -157,7 +158,7 @@ int stop(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceStop;
|
||||
*P++ = FspLaunchCmdStop;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
|
||||
@ -177,7 +178,7 @@ int getinfo(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceInfo;
|
||||
*P++ = FspLaunchCmdGetInfo;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
|
||||
@ -192,7 +193,7 @@ int list(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceList;
|
||||
*P++ = FspLaunchCmdGetNameList;
|
||||
|
||||
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||
}
|
||||
@ -207,7 +208,7 @@ int quit(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherQuit;
|
||||
*P++ = FspLaunchCmdQuit;
|
||||
|
||||
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||
}
|
||||
@ -217,7 +218,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
PWSTR PipeBuf = 0;
|
||||
|
||||
/* allocate our PipeBuf early on; freed on process exit by the system */
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
return ERROR_NO_SYSTEM_RESOURCES;
|
||||
|
||||
@ -232,7 +233,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 > argc || argc > 12)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
return start(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
@ -241,7 +242,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (4 > argc || argc > 13)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
return start(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
@ -250,7 +251,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 != argc)
|
||||
usage();
|
||||
|
||||
return stop(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
return stop(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"info", argv[0]))
|
||||
@ -258,7 +259,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 != argc)
|
||||
usage();
|
||||
|
||||
return getinfo(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
return getinfo(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"list", argv[0]))
|
||||
@ -266,7 +267,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
return list(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
return list(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"quit", argv[0]))
|
||||
@ -275,7 +276,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
usage();
|
||||
|
||||
/* works only against DEBUG version of launcher */
|
||||
return quit(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
return quit(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
|
@ -15,7 +15,8 @@
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <launcher/launcher.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
#include <aclapi.h>
|
||||
#include <sddl.h>
|
||||
#include <userenv.h>
|
||||
@ -410,6 +411,11 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
||||
MemFree(KillProcessData);
|
||||
}
|
||||
|
||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT (2 * 15000 + 1000)
|
||||
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LONG RefCount;
|
||||
@ -858,8 +864,8 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" FSP_LAUNCH_REGKEY,
|
||||
0, FSP_LAUNCH_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
@ -950,7 +956,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
RegKey = 0;
|
||||
|
||||
if (L'\0' == Security[0])
|
||||
lstrcpyW(Security, L"" SVC_INSTANCE_DEFAULT_SDDL);
|
||||
lstrcpyW(Security, L"" FSP_LAUNCH_SERVICE_DEFAULT_SDDL);
|
||||
if (L'D' == Security[0] && L':' == Security[1])
|
||||
Security = SecurityBuf;
|
||||
|
||||
@ -1412,7 +1418,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
|
||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||
SecurityAttributes.bInheritHandle = FALSE;
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" LAUNCHER_PIPE_SDDL, SDDL_REVISION_1,
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" FSP_LAUNCH_PIPE_SDDL, SDDL_REVISION_1,
|
||||
&SecurityAttributes.lpSecurityDescriptor, 0))
|
||||
goto fail;
|
||||
|
||||
@ -1449,11 +1455,11 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 == SvcOverlapped.hEvent)
|
||||
goto fail;
|
||||
|
||||
SvcPipe = CreateNamedPipeW(L"" LAUNCHER_PIPE_NAME,
|
||||
SvcPipe = CreateNamedPipeW(L"" FSP_LAUNCH_PIPE_NAME,
|
||||
PIPE_ACCESS_DUPLEX |
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||
1, FSP_LAUNCH_PIPE_BUFFER_SIZE, FSP_LAUNCH_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||
&SecurityAttributes);
|
||||
if (INVALID_HANDLE_VALUE == SvcPipe)
|
||||
goto fail;
|
||||
@ -1581,7 +1587,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||
HANDLE ClientToken;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
FspServiceSetExitCode(Service, ERROR_NO_SYSTEM_RESOURCES);
|
||||
@ -1604,7 +1610,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||
}
|
||||
|
||||
LastError = SvcPipeWaitResult(
|
||||
ReadFile(SvcPipe, PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||
ReadFile(SvcPipe, PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||
SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
|
||||
if (-1 == LastError)
|
||||
break;
|
||||
@ -1694,11 +1700,11 @@ static inline VOID SvcPipeTransactResult(NTSTATUS Result, PWSTR PipeBuf, PULONG
|
||||
{
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
*PipeBuf = LauncherSuccess;
|
||||
*PipeBuf = FspLaunchCmdSuccess;
|
||||
*PSize += sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
*PSize = (wsprintfW(PipeBuf, L"%c%ld", LauncherFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||
*PSize = (wsprintfW(PipeBuf, L"%c%ld", FspLaunchCmdFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||
sizeof(WCHAR);
|
||||
}
|
||||
|
||||
@ -1721,10 +1727,10 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
|
||||
switch (*P++)
|
||||
{
|
||||
case LauncherSvcInstanceStartWithSecret:
|
||||
case FspLaunchCmdStartWithSecret:
|
||||
HasSecret = TRUE;
|
||||
/* fall through! */
|
||||
case LauncherSvcInstanceStart:
|
||||
case FspLaunchCmdStart:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
for (Argc = 0; sizeof Argv / sizeof Argv[0] > Argc; Argc++)
|
||||
@ -1739,7 +1745,7 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceStop:
|
||||
case FspLaunchCmdStop:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
@ -1750,28 +1756,28 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceInfo:
|
||||
case FspLaunchCmdGetInfo:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
if (0 != ClassName && 0 != InstanceName)
|
||||
{
|
||||
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||
*PSize = FSP_LAUNCH_PIPE_BUFFER_SIZE - 1;
|
||||
Result = SvcInstanceGetInfo(ClientToken, ClassName, InstanceName, PipeBuf + 1, PSize);
|
||||
}
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceList:
|
||||
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||
case FspLaunchCmdGetNameList:
|
||||
*PSize = FSP_LAUNCH_PIPE_BUFFER_SIZE - 1;
|
||||
Result = SvcInstanceGetNameList(ClientToken, PipeBuf + 1, PSize);
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherDefineDosDevice:
|
||||
case FspLaunchCmdDefineDosDevice:
|
||||
DeviceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
TargetPath = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
@ -1783,7 +1789,7 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
break;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
case LauncherQuit:
|
||||
case FspLaunchCmdQuit:
|
||||
SetEvent(SvcEvent);
|
||||
|
||||
SvcPipeTransactResult(STATUS_SUCCESS, PipeBuf, PSize);
|
||||
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* @file launcher/launcher.h
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||
#define WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <shared/minimal.h>
|
||||
|
||||
#define LAUNCHER_REGKEY "Software\\WinFsp\\Services"
|
||||
#define LAUNCHER_REGKEY_WOW64 KEY_WOW64_32KEY
|
||||
|
||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||
|
||||
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||
#define LAUNCHER_PIPE_BUFFER_SIZE 4096
|
||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT (2 * 15000 + 1000)
|
||||
|
||||
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||
|
||||
/*
|
||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||
* pipe instances.
|
||||
*/
|
||||
#define LAUNCHER_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
|
||||
#define LAUNCHER_PIPE_OWNER ((PSID)WinLocalSystemSid)
|
||||
|
||||
/*
|
||||
* The default service instance SDDL gives full access to LocalSystem and Administrators.
|
||||
* The only possible service instance rights are as follows:
|
||||
* RP SERVICE_START
|
||||
* WP SERVICE_STOP
|
||||
* LC SERVICE_QUERY_STATUS
|
||||
*
|
||||
* To create a service that can be started, stopped or queried by Everyone, you can set
|
||||
* the following SDDL:
|
||||
* D:P(A;;RPWPLC;;;WD)
|
||||
*/
|
||||
#define SVC_INSTANCE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
|
||||
|
||||
enum
|
||||
{
|
||||
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||
LauncherDefineDosDevice = 'D',
|
||||
LauncherQuit = 'Q', /* DEBUG version only */
|
||||
|
||||
LauncherSuccess = '$',
|
||||
LauncherFailure = '!',
|
||||
};
|
||||
|
||||
#endif
|
@ -123,6 +123,8 @@ static NTSTATUS FspFsvolCleanup(
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||
|
||||
FspFileNodeCleanupFlush(FileNode, FileObject);
|
||||
|
||||
if (Request->Req.Cleanup.Delete ||
|
||||
Request->Req.Cleanup.SetAllocationSize ||
|
||||
Request->Req.Cleanup.SetArchiveBit ||
|
||||
|
@ -164,6 +164,8 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
|
||||
FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb;
|
||||
|
||||
FileObject->FsContext2 = FsvolDeviceObject;
|
||||
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -281,6 +281,8 @@ const char *DeviceExtensionKindSym(UINT32 Kind)
|
||||
{
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
return "Ctl";
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
return "Mup";
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
return "Vrt";
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
|
105
src/sys/devctl.c
105
src/sys/devctl.c
@ -20,28 +20,81 @@
|
||||
static NTSTATUS FspFsvolDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolDeviceControlRequestFini;
|
||||
FSP_DRIVER_DISPATCH FspDeviceControl;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
|
||||
#pragma alloc_text(PAGE, FspDeviceControl)
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
RequestFileNode = 0,
|
||||
};
|
||||
|
||||
static NTSTATUS FspFsvolDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_REDIR_QUERY_PATH_EX :
|
||||
Result = FspVolumeRedirQueryPathEx(DeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
}
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
return Result;
|
||||
/* do we support DeviceControl? */
|
||||
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* do not forward IRP's originating in the kernel! */
|
||||
if (KernelMode == Irp->RequestorMode)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* only allow custom devices and METHOD_BUFFERED */
|
||||
if (0 == (DEVICE_TYPE_FROM_CTL_CODE(IoControlCode) & 0x8000) ||
|
||||
METHOD_BUFFERED != METHOD_FROM_CTL_CODE(IoControlCode))
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* is this a valid FileObject? */
|
||||
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
if (FSP_FSCTL_DEVICECONTROL_SIZEMAX < InputBufferLength ||
|
||||
FSP_FSCTL_DEVICECONTROL_SIZEMAX < OutputBufferLength)
|
||||
return STATUS_INVALID_BUFFER_SIZE;
|
||||
|
||||
Result = FspIopCreateRequestEx(Irp, 0, InputBufferLength,
|
||||
FspFsvolDeviceControlRequestFini, &Request);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
FspFileNodeAcquireShared(FileNode, Full);
|
||||
|
||||
Request->Kind = FspFsctlTransactDeviceControlKind;
|
||||
Request->Req.DeviceControl.UserContext = FileNode->UserContext;
|
||||
Request->Req.DeviceControl.UserContext2 = FileDesc->UserContext2;
|
||||
Request->Req.DeviceControl.IoControlCode = IoControlCode;
|
||||
Request->Req.DeviceControl.Buffer.Offset = 0;
|
||||
Request->Req.DeviceControl.Buffer.Size = (UINT16)InputBufferLength;
|
||||
Request->Req.DeviceControl.OutputLength = OutputBufferLength;
|
||||
RtlCopyMemory(Request->Buffer, InputBuffer, InputBufferLength);
|
||||
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
||||
|
||||
return FSP_STATUS_IOQ_POST;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolDeviceControlComplete(
|
||||
@ -49,12 +102,46 @@ NTSTATUS FspFsvolDeviceControlComplete(
|
||||
{
|
||||
FSP_ENTER_IOC(PAGED_CODE());
|
||||
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = Response->IoStatus.Status;
|
||||
FSP_RETURN();
|
||||
}
|
||||
|
||||
PVOID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
|
||||
if (Response->Buffer + Response->Rsp.DeviceControl.Buffer.Offset +
|
||||
Response->Rsp.DeviceControl.Buffer.Size > (PUINT8)Response + Response->Size)
|
||||
FSP_RETURN(Result = STATUS_INTERNAL_ERROR);
|
||||
|
||||
if (OutputBufferLength >= Response->Rsp.DeviceControl.Buffer.Size)
|
||||
OutputBufferLength = Response->Rsp.DeviceControl.Buffer.Size;
|
||||
else
|
||||
Result = STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
RtlCopyMemory(OutputBuffer, Response->Buffer + Response->Rsp.DeviceControl.Buffer.Offset,
|
||||
OutputBufferLength);
|
||||
|
||||
Irp->IoStatus.Information = OutputBufferLength;
|
||||
|
||||
FSP_LEAVE_IOC(
|
||||
"%s, FileObject=%p",
|
||||
IoctlCodeSym(IrpSp->Parameters.DeviceIoControl.IoControlCode),
|
||||
IrpSp->FileObject);
|
||||
}
|
||||
|
||||
static VOID FspFsvolDeviceControlRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
|
||||
|
||||
if (0 != FileNode)
|
||||
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||
}
|
||||
|
||||
NTSTATUS FspDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
|
@ -63,6 +63,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 FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
||||
VOID FspDeviceDeleteList(
|
||||
@ -94,6 +96,8 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
||||
#pragma alloc_text(PAGE, FspDeviceDeleteList)
|
||||
#pragma alloc_text(PAGE, FspDeviceDeleteAll)
|
||||
@ -118,6 +122,9 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION);
|
||||
@ -173,6 +180,9 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
Result = FspFsvolDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
Result = FspFsmupDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
Result = STATUS_SUCCESS;
|
||||
@ -199,6 +209,9 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
FspFsvolDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
FspFsmupDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
break;
|
||||
@ -333,7 +346,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneIoq = 1;
|
||||
|
||||
/* create our security meta cache */
|
||||
SecurityTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
SecurityTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.SecurityTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceSecurityCacheCapacity, FspFsvolDeviceSecurityCacheItemSizeMax, &SecurityTimeout,
|
||||
@ -343,7 +356,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneSec = 1;
|
||||
|
||||
/* create our directory meta cache */
|
||||
DirInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
DirInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.DirInfoTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceDirInfoCacheCapacity, FspFsvolDeviceDirInfoCacheItemSizeMax, &DirInfoTimeout,
|
||||
@ -353,7 +366,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneDir = 1;
|
||||
|
||||
/* create our stream info meta cache */
|
||||
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.StreamInfoTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceStreamInfoCacheCapacity, FspFsvolDeviceStreamInfoCacheItemSizeMax, &StreamInfoTimeout,
|
||||
@ -860,7 +873,7 @@ VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VO
|
||||
KeAcquireSpinLock(&FsvolDeviceExtension->InfoSpinLock, &Irql);
|
||||
FsvolDeviceExtension->VolumeInfo = VolumeInfoNp;
|
||||
FsvolDeviceExtension->InfoExpirationTime = FspExpirationTimeFromMillis(
|
||||
FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
FsvolDeviceExtension->VolumeParams.VolumeInfoTimeout);
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
@ -876,6 +889,39 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||
|
||||
/* initialize our prefix table */
|
||||
ExInitializeResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
RtlInitializeUnicodePrefix(&FsmupDeviceExtension->PrefixTable);
|
||||
RtlInitializeUnicodePrefix(&FsmupDeviceExtension->ClassTable);
|
||||
FsmupDeviceExtension->InitDonePfxTab = 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||
|
||||
if (FsmupDeviceExtension->InitDonePfxTab)
|
||||
{
|
||||
/*
|
||||
* Normally we would have to finalize our prefix table. This is not necessary as all
|
||||
* prefixes will be gone if this code ever gets reached.
|
||||
*/
|
||||
ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->PrefixTable, TRUE));
|
||||
ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->ClassTable, TRUE));
|
||||
ExDeleteResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount)
|
||||
{
|
||||
|
@ -551,7 +551,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR);
|
||||
QueryDirectoryLengthMin = FSP_FSCTL_ALIGN_UP(QueryDirectoryLengthMin, 8);
|
||||
ASSERT(QueryDirectoryLengthMin < FspFsvolQueryDirectoryLengthMax);
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout &&
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.DirInfoTimeout &&
|
||||
0 == FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
if (PatternIsFileName)
|
||||
|
113
src/sys/driver.c
113
src/sys/driver.c
@ -44,45 +44,6 @@ NTSTATUS DriverEntry(
|
||||
{
|
||||
FSP_ENTER_DRV();
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
FSP_RETURN();
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
|
||||
/* create the file system control device objects */
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
/* setup the driver object */
|
||||
#if defined(FSP_UNLOAD)
|
||||
DriverObject->DriverUnload = FspUnload;
|
||||
@ -127,7 +88,6 @@ NTSTATUS DriverEntry(
|
||||
FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspFsvolShutdownComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
||||
@ -169,9 +129,58 @@ NTSTATUS DriverEntry(
|
||||
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
|
||||
DriverObject->FastIoDispatch = &FspFastIoDispatch;
|
||||
|
||||
BOOLEAN InitDoneGRes = FALSE, InitDonePsBuf = FALSE;
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
InitDoneGRes = TRUE;
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
InitDonePsBuf = TRUE;
|
||||
|
||||
/* create the file system control device objects */
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
||||
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
||||
&FspFsmupDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsmupDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
Result = FsRtlRegisterUncProviderEx(&FspMupHandle,
|
||||
&DeviceName, FspFsmupDeviceObject, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Register our "disk" device as a file system. We do not register our "net" device
|
||||
* as a file system, but we register with the MUP instead at a later time.
|
||||
* as a file system; we register with the MUP instead.
|
||||
*
|
||||
* Please note that the call below makes our driver unloadable. In fact the driver
|
||||
* remains unloadable even if we issue an IoUnregisterFileSystem() call immediately
|
||||
@ -180,6 +189,23 @@ NTSTATUS DriverEntry(
|
||||
*/
|
||||
IoRegisterFileSystem(FspFsctlDiskDeviceObject);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != FspFsmupDeviceObject)
|
||||
FspDeviceDelete(FspFsmupDeviceObject);
|
||||
if (0 != FspFsctlNetDeviceObject)
|
||||
FspDeviceDelete(FspFsctlNetDeviceObject);
|
||||
if (0 != FspFsctlDiskDeviceObject)
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
if (InitDonePsBuf)
|
||||
FspProcessBufferFinalize();
|
||||
if (InitDoneGRes)
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
}
|
||||
|
||||
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
|
||||
FSP_LEAVE_DRV("DriverName=\"%wZ\", RegistryPath=\"%wZ\"",
|
||||
&DriverObject->DriverName, RegistryPath);
|
||||
@ -211,8 +237,11 @@ VOID FspUnload(
|
||||
{
|
||||
FSP_ENTER_VOID(PAGED_CODE());
|
||||
|
||||
FsRtlDeregisterUncProvider(FspMupHandle);
|
||||
|
||||
FspFsctlDiskDeviceObject = 0;
|
||||
FspFsctlNetDeviceObject = 0;
|
||||
FspFsmupDeviceObject = 0;
|
||||
//FspDeviceDeleteAll();
|
||||
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
@ -229,6 +258,8 @@ VOID FspUnload(
|
||||
PDRIVER_OBJECT FspDriverObject;
|
||||
PDEVICE_OBJECT FspFsctlDiskDeviceObject;
|
||||
PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
PDEVICE_OBJECT FspFsmupDeviceObject;
|
||||
HANDLE FspMupHandle;
|
||||
FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
|
||||
|
@ -180,6 +180,8 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result);
|
||||
#define FSP_LEAVE_DRV(fmt, ...) \
|
||||
FSP_LEAVE_(FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, NtStatusSym(Result))); return Result
|
||||
#define FSP_ENTER_MJ(...) \
|
||||
if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\
|
||||
return FspMupHandleIrp(DeviceObject, Irp);\
|
||||
NTSTATUS Result = STATUS_SUCCESS; \
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\
|
||||
BOOLEAN fsp_device_deref = FALSE; \
|
||||
@ -328,7 +330,6 @@ FSP_IOPREP_DISPATCH FspFsvolSetInformationPrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||
FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||
|
||||
@ -1007,6 +1008,7 @@ typedef struct
|
||||
enum
|
||||
{
|
||||
FspFsctlDeviceExtensionKind = '\0ltC', /* file system control device (e.g. \Device\WinFsp.Disk) */
|
||||
FspFsmupDeviceExtensionKind = '\0puM', /* our own MUP device (linked to \Device\WinFsp.Mup) */
|
||||
FspFsvrtDeviceExtensionKind = '\0trV', /* virtual volume device (e.g. \Device\Volume{GUID}) */
|
||||
FspFsvolDeviceExtensionKind = '\0loV', /* file system volume device (unnamed) */
|
||||
};
|
||||
@ -1023,11 +1025,12 @@ typedef struct
|
||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
||||
PDEVICE_OBJECT FsctlDeviceObject;
|
||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||
HANDLE MupHandle;
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
PVPB SwapVpb;
|
||||
FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UNICODE_STRING VolumePrefix;
|
||||
UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry;
|
||||
FSP_IOQ *Ioq;
|
||||
FSP_META_CACHE *SecurityCache;
|
||||
FSP_META_CACHE *DirInfoCache;
|
||||
@ -1049,6 +1052,14 @@ typedef struct
|
||||
LIST_ENTRY NotifyList;
|
||||
FSP_STATISTICS *Statistics;
|
||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT32 InitDonePfxTab:1;
|
||||
ERESOURCE PrefixTableResource;
|
||||
UNICODE_PREFIX_TABLE PrefixTable;
|
||||
UNICODE_PREFIX_TABLE ClassTable;
|
||||
} FSP_FSMUP_DEVICE_EXTENSION;
|
||||
static inline
|
||||
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
@ -1060,6 +1071,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
static inline
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FspFsmupDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics,
|
||||
PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid,
|
||||
@ -1156,6 +1173,14 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fsmup */
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||
|
||||
/* volume management */
|
||||
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
||||
NTSTATUS FspVolumeCreate(
|
||||
@ -1164,8 +1189,6 @@ VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -1335,6 +1358,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
@ -1559,6 +1583,8 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
|
||||
extern PDRIVER_OBJECT FspDriverObject;
|
||||
extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
|
||||
extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
extern PDEVICE_OBJECT FspFsmupDeviceObject;
|
||||
extern HANDLE FspMupHandle;
|
||||
extern FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
||||
|
@ -37,6 +37,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
@ -121,6 +122,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
||||
#pragma alloc_text(PAGE, FspFileNodeReleaseOwnerF)
|
||||
#pragma alloc_text(PAGE, FspFileNodeOpen)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCleanup)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCleanupFlush)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
|
||||
#pragma alloc_text(PAGE, FspFileNodeClose)
|
||||
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
|
||||
@ -772,6 +774,59 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG
|
||||
*PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0;
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||
{
|
||||
/*
|
||||
* Optionally flush the FileNode during Cleanup.
|
||||
*
|
||||
* The FileNode must be acquired exclusive (Full) when calling this function.
|
||||
*/
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
|
||||
if (!FsvolDeviceExtension->VolumeParams.FlushAndPurgeOnCleanup)
|
||||
return; /* nothing to do! */
|
||||
|
||||
BOOLEAN DeletePending, SingleHandle;
|
||||
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
DeletePending = 0 != FileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
|
||||
SingleHandle = 1 == FileNode->HandleCount;
|
||||
|
||||
if (SingleHandle && FileNode->TruncateOnClose)
|
||||
{
|
||||
/*
|
||||
* Even when the FileInfo is expired, this is the best guess for a file size
|
||||
* without asking the user-mode file system.
|
||||
*/
|
||||
TruncateSize = FileNode->Header.FileSize;
|
||||
PTruncateSize = &TruncateSize;
|
||||
}
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
||||
/* Flush and purge on last Cleanup. Keeps files off the "standby" list. (GitHub issue #104) */
|
||||
if (SingleHandle && !DeletePending)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
LARGE_INTEGER ZeroOffset = { 0 };
|
||||
|
||||
if (0 != PTruncateSize && 0 == PTruncateSize->HighPart)
|
||||
FspCcFlushCache(FileObject->SectionObjectPointer, &ZeroOffset, PTruncateSize->LowPart,
|
||||
&IoStatus);
|
||||
else
|
||||
FspCcFlushCache(FileObject->SectionObjectPointer, 0, 0,
|
||||
&IoStatus);
|
||||
}
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||
{
|
||||
/*
|
||||
@ -789,9 +844,9 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN DeletedFromContextTable = FALSE;
|
||||
BOOLEAN DeletePending, DeletedFromContextTable = FALSE, SingleHandle = FALSE;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
@ -816,6 +871,8 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
ASSERT(0 < FileNode->HandleCount);
|
||||
if (0 == --FileNode->HandleCount)
|
||||
{
|
||||
SingleHandle = TRUE;
|
||||
|
||||
DeletePending = 0 != FileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
|
||||
@ -832,7 +889,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
* We now have to deal with the scenario where there are cleaned up,
|
||||
* but unclosed streams for this file still in the context table.
|
||||
*/
|
||||
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.NamedStreams &&
|
||||
if (FsvolDeviceExtension->VolumeParams.NamedStreams &&
|
||||
0 == FileNode->MainFileNode)
|
||||
{
|
||||
BOOLEAN StreamDeletedFromContextTable;
|
||||
@ -869,8 +926,6 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
if (DeletePending || FileNode->TruncateOnClose)
|
||||
{
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
UINT64 AllocationUnit =
|
||||
FsvolDeviceExtension->VolumeParams.SectorSize *
|
||||
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
|
||||
@ -891,6 +946,34 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
||||
/* Flush and purge on last Cleanup. Keeps files off the "standby" list. (GitHub issue #104) */
|
||||
if (SingleHandle && FsvolDeviceExtension->VolumeParams.FlushAndPurgeOnCleanup)
|
||||
{
|
||||
/*
|
||||
* There is an important difference in behavior with respect to DeletePending when
|
||||
* FlushAndPurgeOnCleanup is FALSE vs when it is TRUE.
|
||||
*
|
||||
* With FlushAndPurgeOnCleanup==FALSE (the default), the WinFsp FSD preserves data
|
||||
* and allows a deleted file to have memory-mapped I/O done on it after the CLEANUP
|
||||
* completes. It is up to the user mode file system to decide whether to handle
|
||||
* this scenario or not. The MEMFS reference file system does.
|
||||
*
|
||||
* With FlushAndPurgeOnCleanup==TRUE, the FSD simply purges the cache section (if any),
|
||||
* which means that CACHED DATA WILL BE LOST. This is desirable, because we do not want
|
||||
* to unnecessarily flush data that are soon going to be deleted.
|
||||
*
|
||||
* This could affect a program that does memory-mapped I/O on a deleted file that has
|
||||
* been CloseHandle'd. Tests have shown that even NTFS cannot properly handle this
|
||||
* scenario in all cases (for example, when the file is not cached), so it is unlikely
|
||||
* that there are any useful programs out there that do this.
|
||||
*
|
||||
* So we deem this difference in behavior ok and desirable.
|
||||
*/
|
||||
|
||||
TruncateSize.QuadPart = 0;
|
||||
PTruncateSize = &TruncateSize;
|
||||
}
|
||||
|
||||
CcUninitializeCacheMap(FileObject, PTruncateSize, 0);
|
||||
|
||||
if (DeletedFromContextTable)
|
||||
|
428
src/sys/mup.c
Normal file
428
src/sys/mup.c
Normal file
@ -0,0 +1,428 @@
|
||||
/**
|
||||
* @file sys/mup.c
|
||||
*
|
||||
* @copyright 2015-2018 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 file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
/*
|
||||
* FSP_MUP_PREFIX_CLASS
|
||||
*
|
||||
* Define the following macro to claim "class" prefixes during prefix
|
||||
* resolution. A "class" prefix is of the form \ClassName. The alternative
|
||||
* is a "full" prefix, which is of the form \ClassName\InstanceName.
|
||||
*
|
||||
* Claiming a class prefix has advantages and disadvantages. The main
|
||||
* advantage is that by claiming a \ClassName prefix, paths such as
|
||||
* \ClassName\IPC$ will be handled by WinFsp, thus speeding up prefix
|
||||
* resolution for all \ClassName prefixed names. The disadvantage is
|
||||
* it is no longer possible for WinFsp and another redirector to handle
|
||||
* instances ("shares") under the same \ClassName prefix.
|
||||
*/
|
||||
#define FSP_MUP_PREFIX_CLASS
|
||||
|
||||
static NTSTATUS FspMupGetClassName(
|
||||
PUNICODE_STRING Prefix, PUNICODE_STRING ClassName);
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||
static NTSTATUS FspMupRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspMupGetClassName)
|
||||
#pragma alloc_text(PAGE, FspMupRegister)
|
||||
#pragma alloc_text(PAGE, FspMupUnregister)
|
||||
#pragma alloc_text(PAGE, FspMupHandleIrp)
|
||||
#pragma alloc_text(PAGE, FspMupRedirQueryPathEx)
|
||||
#endif
|
||||
|
||||
typedef struct _FSP_MUP_CLASS
|
||||
{
|
||||
LONG RefCount;
|
||||
UNICODE_STRING Name;
|
||||
UNICODE_PREFIX_TABLE_ENTRY Entry;
|
||||
WCHAR Buffer[];
|
||||
} FSP_MUP_CLASS;
|
||||
|
||||
static NTSTATUS FspMupGetClassName(
|
||||
PUNICODE_STRING VolumePrefix, PUNICODE_STRING ClassName)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
RtlZeroMemory(ClassName, sizeof *ClassName);
|
||||
|
||||
if (L'\\' == VolumePrefix->Buffer[0])
|
||||
for (PWSTR P = VolumePrefix->Buffer + 1,
|
||||
EndP = VolumePrefix->Buffer + VolumePrefix->Length / sizeof(WCHAR);
|
||||
EndP > P; P++)
|
||||
{
|
||||
if (L'\\' == *P)
|
||||
{
|
||||
ClassName->Buffer = VolumePrefix->Buffer;
|
||||
ClassName->Length = (USHORT)((P - ClassName->Buffer) * sizeof(WCHAR));
|
||||
ClassName->MaximumLength = ClassName->Length;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
BOOLEAN Success;
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PUNICODE_PREFIX_TABLE_ENTRY ClassEntry;
|
||||
UNICODE_STRING ClassName;
|
||||
FSP_MUP_CLASS *Class = 0;
|
||||
|
||||
Result = FspMupGetClassName(&FsvolDeviceExtension->VolumePrefix, &ClassName);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Class = FspAlloc(sizeof *Class + ClassName.Length);
|
||||
if (0 == Class)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RtlZeroMemory(Class, sizeof *Class);
|
||||
Class->RefCount = 1;
|
||||
Class->Name.Length = ClassName.Length;
|
||||
Class->Name.MaximumLength = ClassName.MaximumLength;
|
||||
Class->Name.Buffer = Class->Buffer;
|
||||
RtlCopyMemory(Class->Buffer, ClassName.Buffer, ClassName.Length);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
Success = RtlInsertUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FsvolDeviceExtension->VolumePrefix, &FsvolDeviceExtension->VolumePrefixEntry);
|
||||
if (Success)
|
||||
{
|
||||
FspDeviceReference(FsvolDeviceObject);
|
||||
|
||||
ClassEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
&Class->Name, 0);
|
||||
if (0 == ClassEntry)
|
||||
{
|
||||
Success = RtlInsertUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
&Class->Name, &Class->Entry);
|
||||
ASSERT(Success);
|
||||
Class = 0;
|
||||
}
|
||||
else
|
||||
CONTAINING_RECORD(ClassEntry, FSP_MUP_CLASS, Entry)->RefCount++;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
Result = STATUS_OBJECT_NAME_COLLISION;
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
|
||||
exit:
|
||||
if (0 != Class)
|
||||
FspFree(Class);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PUNICODE_PREFIX_TABLE_ENTRY PrefixEntry;
|
||||
PUNICODE_PREFIX_TABLE_ENTRY ClassEntry;
|
||||
UNICODE_STRING ClassName;
|
||||
FSP_MUP_CLASS *Class;
|
||||
|
||||
Result = FspMupGetClassName(&FsvolDeviceExtension->VolumePrefix, &ClassName);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
PrefixEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FsvolDeviceExtension->VolumePrefix, 0);
|
||||
if (0 != PrefixEntry)
|
||||
{
|
||||
RtlRemoveUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FsvolDeviceExtension->VolumePrefixEntry);
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
|
||||
ClassEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
&ClassName, 0);
|
||||
if (0 != ClassEntry)
|
||||
{
|
||||
Class = CONTAINING_RECORD(ClassEntry, FSP_MUP_CLASS, Entry);
|
||||
if (0 == --Class->RefCount)
|
||||
{
|
||||
RtlRemoveUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
ClassEntry);
|
||||
FspFree(Class);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
}
|
||||
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
PDEVICE_OBJECT FsvolDeviceObject = 0;
|
||||
PUNICODE_PREFIX_TABLE_ENTRY PrefixEntry;
|
||||
BOOLEAN DeviceDeref = FALSE;
|
||||
NTSTATUS Result;
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
switch (IrpSp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
/*
|
||||
* A CREATE request with an empty file name indicates that the fsmup device
|
||||
* is being opened. Check for this case and handle it.
|
||||
*/
|
||||
if (0 == FileObject->FileName.Length)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||
Result = Irp->IoStatus.Status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Every other CREATE request must be forwarded to the appropriate fsvol device.
|
||||
*/
|
||||
|
||||
if (0 != FileObject->RelatedFileObject)
|
||||
FileObject = FileObject->RelatedFileObject;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
PrefixEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FileObject->FileName, 0);
|
||||
if (0 != PrefixEntry)
|
||||
{
|
||||
FsvolDeviceObject = CONTAINING_RECORD(PrefixEntry,
|
||||
FSP_FSVOL_DEVICE_EXTENSION, VolumePrefixEntry)->FsvolDeviceObject;
|
||||
FspDeviceReference(FsvolDeviceObject);
|
||||
DeviceDeref = TRUE;
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
break;
|
||||
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
/*
|
||||
* A DEVICE_CONTROL request with IOCTL_REDIR_QUERY_PATH_EX must be handled
|
||||
* by the fsmup device. Check for this case and handle it.
|
||||
*/
|
||||
if (IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
Irp->IoStatus.Status = FspMupRedirQueryPathEx(FsmupDeviceObject, Irp, IrpSp);
|
||||
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||
Result = Irp->IoStatus.Status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Every other DEVICE_CONTROL request must be forwarded to the appropriate fsvol device.
|
||||
*/
|
||||
|
||||
/* fall through! */
|
||||
|
||||
default:
|
||||
/*
|
||||
* Every other request must be forwarded to the appropriate fsvol device. If there is no
|
||||
* fsvol device, then we must return the appropriate status code (see below).
|
||||
*
|
||||
* Please note that since we allow the fsmup device to be opened, we must also handle
|
||||
* CLEANUP and CLOSE requests for it.
|
||||
*/
|
||||
|
||||
if (0 != FileObject)
|
||||
{
|
||||
if (FspFileNodeIsValid(FileObject->FsContext))
|
||||
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
||||
else if (0 != FileObject->FsContext2 &&
|
||||
3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 == FsvolDeviceObject)
|
||||
{
|
||||
/*
|
||||
* We were not able to find an fsvol device to forward this IRP to. We will complete
|
||||
* the IRP with an appropriate status code.
|
||||
*/
|
||||
|
||||
switch (IrpSp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
/*
|
||||
* For CREATE requests we return STATUS_BAD_NETWORK_PATH. Here is why.
|
||||
*
|
||||
* When a file \ClassName\InstanceName\Path is opened by an application, this request
|
||||
* first goes to MUP. The MUP gives DFS a first chance to handle the request and if
|
||||
* that fails the MUP proceeds with prefix resolution. The DFS attempts to open the
|
||||
* file \ClassName\IPC$, this results in a prefix resolution for \ClassName\IPC$
|
||||
* through a recursive MUP call! If this resolution fails the DFS returns to the MUP,
|
||||
* which now attempts prefix resolution for \ClassName\InstanceName\Path.
|
||||
*
|
||||
* Under the new fsmup design we respond to IOCTL_REDIR_QUERY_PATH_EX by handling all
|
||||
* paths with a \ClassName prefix (that we know). This way we ensure that we will get
|
||||
* all opens for paths with a \ClassName prefix and avoid delays for requests of
|
||||
* \ClassName\IPC$, which if left unhandled will be forwarded to all network
|
||||
* redirectors.
|
||||
*
|
||||
* In order to successfully short-circuit requests for \ClassName\IPC$ we must also
|
||||
* return STATUS_BAD_NETWORK_PATH in CREATE. This makes DFS think that prefix
|
||||
* resolution failed and does not complain if it cannot open \ClassName\IPC$. Other
|
||||
* error codes cause DFS to completely fail the open issued by the application.
|
||||
*/
|
||||
Irp->IoStatus.Status = STATUS_BAD_NETWORK_PATH;
|
||||
break;
|
||||
case IRP_MJ_CLEANUP:
|
||||
case IRP_MJ_CLOSE:
|
||||
/*
|
||||
* CLEANUP and CLOSE requests ignore their status code (except for STATUS_PENDING).
|
||||
* So return STATUS_SUCCESS. This works regardless of whether this is a legitimate
|
||||
* fsmup request or an erroneous CLOSE request that we should not have seen.
|
||||
*/
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IRP_MJ_QUERY_INFORMATION:
|
||||
case IRP_MJ_SET_INFORMATION:
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
default:
|
||||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||
Result = Irp->IoStatus.Status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ASSERT(FspFsvolDeviceExtensionKind == FspDeviceExtension(FsvolDeviceObject)->Kind);
|
||||
|
||||
/*
|
||||
* Forward the IRP to the appropriate fsvol device. The fsvol device will take care
|
||||
* to complete the IRP, etc.
|
||||
*/
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Result = IoCallDriver(FsvolDeviceObject, Irp);
|
||||
|
||||
if (DeviceDeref)
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
|
||||
exit:
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMupRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction);
|
||||
ASSERT(IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* check parameters */
|
||||
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
QUERY_PATH_REQUEST_EX *QueryPathRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
QUERY_PATH_RESPONSE *QueryPathResponse = Irp->UserBuffer;
|
||||
if (sizeof(QUERY_PATH_REQUEST_EX) > InputBufferLength ||
|
||||
0 == QueryPathRequest || 0 == QueryPathResponse)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (sizeof(QUERY_PATH_RESPONSE) > OutputBufferLength)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
PUNICODE_PREFIX_TABLE_ENTRY Entry;
|
||||
|
||||
#if defined(FSP_MUP_PREFIX_CLASS)
|
||||
UNICODE_STRING ClassName;
|
||||
|
||||
Result = FspMupGetClassName(&QueryPathRequest->PathName, &ClassName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return STATUS_BAD_NETWORK_PATH;
|
||||
|
||||
Result = STATUS_BAD_NETWORK_PATH;
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable, &ClassName, 0);
|
||||
if (0 != Entry)
|
||||
{
|
||||
QueryPathResponse->LengthAccepted = ClassName.Length;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
#else
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
||||
|
||||
Result = STATUS_BAD_NETWORK_PATH;
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&QueryPathRequest->PathName, 0);
|
||||
if (0 != Entry)
|
||||
{
|
||||
FsvolDeviceExtension = CONTAINING_RECORD(Entry, FSP_FSVOL_DEVICE_EXTENSION, VolumePrefixEntry);
|
||||
if (!FspIoqStopped(FsvolDeviceExtension->Ioq))
|
||||
{
|
||||
if (0 < FsvolDeviceExtension->VolumePrefix.Length &&
|
||||
FspFsvolDeviceVolumePrefixInString(
|
||||
FsvolDeviceExtension->FsvolDeviceObject, &QueryPathRequest->PathName) &&
|
||||
(QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length ||
|
||||
'\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)]))
|
||||
{
|
||||
QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
#endif
|
||||
|
||||
return Result;
|
||||
}
|
@ -17,45 +17,19 @@
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
static NTSTATUS FspFsvolShutdown(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
FSP_DRIVER_DISPATCH FspShutdown;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFsvolShutdown)
|
||||
#pragma alloc_text(PAGE, FspFsvolShutdownComplete)
|
||||
#pragma alloc_text(PAGE, FspShutdown)
|
||||
#endif
|
||||
|
||||
static NTSTATUS FspFsvolShutdown(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolShutdownComplete(
|
||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
FSP_ENTER_IOC(PAGED_CODE());
|
||||
|
||||
FSP_LEAVE_IOC("%s", "");
|
||||
}
|
||||
|
||||
NTSTATUS FspShutdown(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
FSP_ENTER_MJ(PAGED_CODE());
|
||||
|
||||
switch (FspDeviceExtension(DeviceObject)->Kind)
|
||||
{
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
FSP_RETURN(Result = FspFsvolShutdown(DeviceObject, Irp, IrpSp));
|
||||
default:
|
||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
(PVOID)IrpSp;
|
||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||
|
||||
FSP_LEAVE_MJ("%s", "");
|
||||
}
|
||||
|
135
src/sys/volume.c
135
src/sys/volume.c
@ -21,7 +21,6 @@ NTSTATUS FspVolumeCreate(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static NTSTATUS FspVolumeCreateNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static WORKER_THREAD_ROUTINE FspVolumeCreateRegisterMup;
|
||||
VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static VOID FspVolumeDeleteNoLock(
|
||||
@ -31,8 +30,6 @@ NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static NTSTATUS FspVolumeMountNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -49,13 +46,11 @@ NTSTATUS FspVolumeWork(
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspVolumeCreate)
|
||||
#pragma alloc_text(PAGE, FspVolumeCreateNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeCreateRegisterMup)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeDelete)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeDeleteNoLock)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeDeleteDelayed)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeRedirQueryPathEx)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetName)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||
@ -67,13 +62,6 @@ NTSTATUS FspVolumeWork(
|
||||
#define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX
|
||||
#define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
NTSTATUS Result;
|
||||
FSP_SYNCHRONOUS_WORK_ITEM SynchronousWorkItem;
|
||||
} FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM;
|
||||
|
||||
NTSTATUS FspVolumeCreate(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
@ -106,25 +94,33 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
GUID Guid;
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING VolumeName;
|
||||
UNICODE_STRING FsmupDeviceName;
|
||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
||||
FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM RegisterMupWorkItem;
|
||||
|
||||
/* check parameters */
|
||||
if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS) * sizeof(WCHAR) > FileObject->FileName.Length)
|
||||
if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) * sizeof(WCHAR) > FileObject->FileName.Length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* copy the VolumeParams */
|
||||
for (USHORT Index = 0, Length = sizeof(FSP_FSCTL_VOLUME_PARAMS); Length > Index; Index++)
|
||||
{
|
||||
if (PREFIXW_SIZE / sizeof(WCHAR) + Index >= FileObject->FileName.Length / sizeof(WCHAR))
|
||||
break;
|
||||
|
||||
WCHAR Value = FileObject->FileName.Buffer[PREFIXW_SIZE / sizeof(WCHAR) + Index];
|
||||
if (0xF000 != (Value & 0xFF00))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
((PUINT8)&VolumeParams)[Index] = Value & 0xFF;
|
||||
}
|
||||
|
||||
/* check VolumeParams size */
|
||||
if (0 != VolumeParams.Version &&
|
||||
PREFIXW_SIZE + VolumeParams.Version * sizeof(WCHAR) != FileObject->FileName.Length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* check the VolumeParams */
|
||||
if (0 == VolumeParams.SectorSize)
|
||||
VolumeParams.SectorSize = 512;
|
||||
@ -145,6 +141,28 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
if (FspFsctlIrpCapacityMinimum > VolumeParams.IrpCapacity ||
|
||||
VolumeParams.IrpCapacity > FspFsctlIrpCapacityMaximum)
|
||||
VolumeParams.IrpCapacity = FspFsctlIrpCapacityDefault;
|
||||
if (sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) >= VolumeParams.Version)
|
||||
{
|
||||
VolumeParams.VolumeInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
VolumeParams.DirInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
||||
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!VolumeParams.VolumeInfoTimeoutValid)
|
||||
VolumeParams.VolumeInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
if (!VolumeParams.DirInfoTimeoutValid)
|
||||
VolumeParams.DirInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
if (!VolumeParams.SecurityTimeoutValid)
|
||||
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
||||
if (!VolumeParams.StreamInfoTimeoutValid)
|
||||
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
}
|
||||
VolumeParams.VolumeInfoTimeoutValid = 1;
|
||||
VolumeParams.DirInfoTimeoutValid = 1;
|
||||
VolumeParams.SecurityTimeoutValid = 1;
|
||||
VolumeParams.StreamInfoTimeoutValid = 1;
|
||||
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
|
||||
{
|
||||
VolumeParams.Prefix[sizeof VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
|
||||
@ -225,6 +243,7 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
FsvolDeviceExtension->FsctlDeviceObject = FsctlDeviceObject;
|
||||
FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
|
||||
FsvolDeviceExtension->FsvolDeviceObject = FsvolDeviceObject;
|
||||
FsvolDeviceExtension->VolumeParams = VolumeParams;
|
||||
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
|
||||
RtlInitUnicodeString(&FsvolDeviceExtension->VolumePrefix,
|
||||
@ -245,27 +264,24 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
}
|
||||
|
||||
/* do we need to register with MUP? */
|
||||
/* do we need to register with fsmup? */
|
||||
if (0 == FsvrtDeviceObject)
|
||||
{
|
||||
/*
|
||||
* Turns out we cannot call FsRtlRegisterUncProviderEx when the PreviousMode
|
||||
* is UserMode! So we need to somehow switch to KernelMode prior to issuing
|
||||
* the FsRtlRegisterUncProviderEx call. There seems to be no straightforward
|
||||
* way to switch the PreviousMode (no ExSetPreviousMode). So we do it indirectly
|
||||
* by executing a synchronous work item (FspExecuteSynchronousWorkItem).
|
||||
*/
|
||||
RtlZeroMemory(&RegisterMupWorkItem, sizeof RegisterMupWorkItem);
|
||||
RegisterMupWorkItem.FsvolDeviceObject = FsvolDeviceObject;
|
||||
FspInitializeSynchronousWorkItem(&RegisterMupWorkItem.SynchronousWorkItem,
|
||||
FspVolumeCreateRegisterMup, &RegisterMupWorkItem);
|
||||
FspExecuteSynchronousWorkItem(&RegisterMupWorkItem.SynchronousWorkItem);
|
||||
Result = RegisterMupWorkItem.Result;
|
||||
Result = FspMupRegister(FspFsmupDeviceObject, FsvolDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
return Result;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&FsmupDeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
Result = IoCreateSymbolicLink(&FsvolDeviceExtension->VolumeName, &FsmupDeviceName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject);
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/* associate the new volume device with our file object */
|
||||
@ -275,18 +291,6 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspVolumeCreateRegisterMup(PVOID Context)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM *RegisterMupWorkItem = Context;
|
||||
PDEVICE_OBJECT FsvolDeviceObject = RegisterMupWorkItem->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
|
||||
RegisterMupWorkItem->Result = FsRtlRegisterUncProviderEx(&FsvolDeviceExtension->MupHandle,
|
||||
&FsvolDeviceExtension->VolumeName, FsvolDeviceObject, 0);
|
||||
}
|
||||
|
||||
VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
@ -333,7 +337,7 @@ static VOID FspVolumeDeleteNoLock(
|
||||
/* stop the I/O queue */
|
||||
FspIoqStop(FsvolDeviceExtension->Ioq);
|
||||
|
||||
/* do we have a virtual disk device or a MUP handle? */
|
||||
/* do we have a virtual disk device or are we registered with fsmup? */
|
||||
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
||||
{
|
||||
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||
@ -391,10 +395,10 @@ static VOID FspVolumeDeleteNoLock(
|
||||
FspQueueDelayedWorkItem(&FsvolDeviceExtension->DeleteVolumeDelayedWorkItem, Delay);
|
||||
}
|
||||
}
|
||||
else if (0 != FsvolDeviceExtension->MupHandle)
|
||||
else
|
||||
{
|
||||
FsRtlDeregisterUncProvider(FsvolDeviceExtension->MupHandle);
|
||||
FsvolDeviceExtension->MupHandle = 0;
|
||||
IoDeleteSymbolicLink(&FsvolDeviceExtension->VolumeName);
|
||||
FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject);
|
||||
}
|
||||
|
||||
/* release the volume device object */
|
||||
@ -515,49 +519,6 @@ static NTSTATUS FspVolumeMountNoLock(
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction);
|
||||
ASSERT(IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* check parameters */
|
||||
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
QUERY_PATH_REQUEST_EX *QueryPathRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
QUERY_PATH_RESPONSE *QueryPathResponse = Irp->UserBuffer;
|
||||
if (sizeof(QUERY_PATH_REQUEST_EX) > InputBufferLength ||
|
||||
0 == QueryPathRequest || 0 == QueryPathResponse)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (sizeof(QUERY_PATH_RESPONSE) > OutputBufferLength)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
|
||||
Result = STATUS_BAD_NETWORK_PATH;
|
||||
if (!FspIoqStopped(FsvolDeviceExtension->Ioq))
|
||||
{
|
||||
if (0 < FsvolDeviceExtension->VolumePrefix.Length &&
|
||||
FspFsvolDeviceVolumePrefixInString(FsvolDeviceObject, &QueryPathRequest->PathName) &&
|
||||
(QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length ||
|
||||
'\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)]))
|
||||
{
|
||||
QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
|
@ -18,6 +18,7 @@ if not X%1==X-u (
|
||||
|
||||
reg add !RegKey!\!fsname! /v Executable /t REG_SZ /d !fsexec! /f /reg:32
|
||||
reg add !RegKey!\!fsname! /v CommandLine /t REG_SZ /d !fscmdl! /f /reg:32
|
||||
reg add !RegKey!\!fsname! /v JobControl /t REG_DWORD /d 1 /f /reg:32
|
||||
if not X!fssecu!==X reg add !RegKey!\!fsname! /v Security /t REG_SZ /d !fssecu! /f /reg:32
|
||||
) else (
|
||||
set unreg=1
|
||||
|
17
tools/gendoc/apidoc.sh
Normal file
17
tools/gendoc/apidoc.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname "$0")/../..
|
||||
|
||||
PRETTYDOC="$PWD/../prettydoc/prettydoc"
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "usage: $(basename $0) {asciidoc|html}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$PRETTYDOC" -f $1 -t -H=--outer-names-only -o doc inc/winfsp/winfsp.h inc/winfsp/launch.h
|
||||
|
||||
if [[ "$1" == "asciidoc" ]]; then
|
||||
mv doc/winfsp.h.asciidoc doc/WinFsp-API-winfsp.h.asciidoc
|
||||
mv doc/launch.h.asciidoc doc/WinFsp-API-launch.h.asciidoc
|
||||
fi
|
@ -20,7 +20,7 @@ launchctl-x64 start memfs32 testnet \memfs32\test P: >nul
|
||||
launchctl-x64 start memfs-dotnet testdsk "" Q: >nul
|
||||
launchctl-x64 start memfs-dotnet testnet \memfs-dotnet\test R: >nul
|
||||
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 5 2>nul
|
||||
cd M: >nul 2>nul || (echo === Unable to find drive M: >&2 & goto fail)
|
||||
cd N: >nul 2>nul || (echo === Unable to find drive N: >&2 & goto fail)
|
||||
cd O: >nul 2>nul || (echo === Unable to find drive O: >&2 & goto fail)
|
||||
@ -31,6 +31,7 @@ cd R: >nul 2>nul || (echo === Unable to find drive R: >&2 & goto fail)
|
||||
set dfl_tests=^
|
||||
winfsp-tests-x64 ^
|
||||
winfsp-tests-x64-case-randomize ^
|
||||
winfsp-tests-x64-flushpurge ^
|
||||
winfsp-tests-x64-mountpoint-drive ^
|
||||
winfsp-tests-x64-mountpoint-dir ^
|
||||
winfsp-tests-x64-no-traverse ^
|
||||
@ -48,6 +49,7 @@ set dfl_tests=^
|
||||
fscrash-x64 ^
|
||||
winfsp-tests-x86 ^
|
||||
winfsp-tests-x86-case-randomize ^
|
||||
winfsp-tests-x86-flushpurge ^
|
||||
winfsp-tests-x86-mountpoint-drive ^
|
||||
winfsp-tests-x86-mountpoint-dir ^
|
||||
winfsp-tests-x86-no-traverse ^
|
||||
@ -73,13 +75,21 @@ set opt_tests=^
|
||||
ifstest-memfs-x64-disk ^
|
||||
ifstest-memfs-x86-disk ^
|
||||
ifstest-memfs-dotnet-disk ^
|
||||
sample-airfs-x64 ^
|
||||
sample-airfs-x86 ^
|
||||
sample-passthrough-x64 ^
|
||||
sample-passthrough-x86 ^
|
||||
sample-passthrough-fuse-x64 ^
|
||||
sample-fsx-passthrough-fuse-x64 ^
|
||||
sample-passthrough-fuse-x86 ^
|
||||
sample-fsx-passthrough-fuse-x86 ^
|
||||
sample-passthrough-fuse3-x64 ^
|
||||
sample-fsx-passthrough-fuse3-x64 ^
|
||||
sample-passthrough-fuse3-x86 ^
|
||||
sample-fsx-passthrough-fuse3-x86 ^
|
||||
sample-passthrough-dotnet ^
|
||||
compat-v1.2-memfs-x64 ^
|
||||
compat-v1.2-memfs-x86 ^
|
||||
compat-v1.1-passthrough-fuse-x64 ^
|
||||
compat-v1.1-passthrough-fuse-x86 ^
|
||||
avast-tests-x64 ^
|
||||
@ -144,7 +154,7 @@ launchctl-x64 stop memfs32 testnet >nul
|
||||
launchctl-x64 stop memfs-dotnet testdsk >nul
|
||||
launchctl-x64 stop memfs-dotnet testnet >nul
|
||||
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 5 2>nul
|
||||
|
||||
set /a total=testpass+testfail
|
||||
echo === Total: %testpass%/%total%
|
||||
@ -167,6 +177,11 @@ winfsp-tests-x64 --case-randomize
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-flushpurge
|
||||
winfsp-tests-x64 --flush-and-purge-on-cleanup
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountpoint-drive
|
||||
winfsp-tests-x64 --mountpoint=X: --resilient
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
@ -197,6 +212,11 @@ winfsp-tests-x86 --case-randomize
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-flushpurge
|
||||
winfsp-tests-x86 --flush-and-purge-on-cleanup
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountpoint-drive
|
||||
winfsp-tests-x86 --mountpoint=X: --resilient
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
@ -635,6 +655,16 @@ for /F "delims=" %%l in ('call "%ProjRoot%\tools\ifstest.bat" %* /z /v ^| findst
|
||||
if not X!IfsTestFound!==XYES set IfsTestExit=1
|
||||
exit /b !IfsTestExit!
|
||||
|
||||
:sample-airfs-x64
|
||||
call :__run_sample_disk_test airfs x64 airfs-x64 winfsp-tests-x64 NOEXCL
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-airfs-x86
|
||||
call :__run_sample_disk_test airfs x86 airfs-x86 winfsp-tests-x86 NOEXCL
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-x64
|
||||
call :__run_sample_test passthrough x64 passthrough-x64 winfsp-tests-x64
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
@ -681,6 +711,58 @@ call :__run_sample_fsx_fuse_test passthrough-fuse x86 passthrough-fuse-x86 fsx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-fuse3-x64
|
||||
call :__run_sample_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 winfsp-tests-x64 ^
|
||||
"-create_fileattr_test -setfileinfo_test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-passthrough-fuse3-x86
|
||||
call :__run_sample_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 winfsp-tests-x86 ^
|
||||
"-create_fileattr_test -setfileinfo_test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-fsx-passthrough-fuse3-x64
|
||||
call :__run_sample_fsx_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 fsx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:sample-fsx-passthrough-fuse3-x86
|
||||
call :__run_sample_fsx_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 fsx
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:__run_sample_disk_test
|
||||
set RunSampleTestExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
mkdir "%TMP%\%1\test"
|
||||
call "%ProjRoot%\tools\fsreg" %1 "%TMP%\%1\build\%Configuration%\%3.exe" "-i -u %%%%1 -m %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||
echo launchctl-x64 start %1 testdsk "" L:
|
||||
launchctl-x64 start %1 testdsk "" L: >nul
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
if X%5==XNOEXCL (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient
|
||||
) else (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -getfileinfo_name_test -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test ^
|
||||
-reparse* -stream* %~5
|
||||
)
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo launchctl-x64 stop %1 testdsk
|
||||
launchctl-x64 stop %1 testdsk >nul
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
call "%ProjRoot%\tools\fsreg" -u %1
|
||||
rmdir /s/q "%TMP%\%1"
|
||||
exit /b !RunSampleTestExit!
|
||||
|
||||
:__run_sample_test
|
||||
set RunSampleTestExit=0
|
||||
call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1"
|
||||
@ -695,10 +777,15 @@ net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -getfileinfo_name_test -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test ^
|
||||
-reparse* -stream* %~5
|
||||
if X%5==XNOEXCL (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient
|
||||
) else (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -getfileinfo_name_test -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test ^
|
||||
-reparse* -stream* %~5
|
||||
)
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo net use L: /delete
|
||||
@ -722,11 +809,16 @@ net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if X%5==XNOEXCL (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient
|
||||
) else (
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||
-reparse* -stream* %~5
|
||||
)
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo net use L: /delete
|
||||
@ -759,6 +851,41 @@ call "%ProjRoot%\tools\fsreg" -u %1
|
||||
rmdir /s/q "%TMP%\%1"
|
||||
exit /b !RunSampleTestExit!
|
||||
|
||||
:compat-v1.2-memfs-x64
|
||||
copy "%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-*.dll" "%ProjRoot%\tst\compat\v1.2\memfs"
|
||||
call :__run_compat_memfs_test compat-memfs v1.2\memfs\memfs-x64 winfsp-tests-x64
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
del "%ProjRoot%\tst\compat\v1.2\memfs\winfsp-*.dll"
|
||||
exit /b 0
|
||||
|
||||
:compat-v1.2-memfs-x86
|
||||
copy "%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-*.dll" "%ProjRoot%\tst\compat\v1.2\memfs"
|
||||
call :__run_compat_memfs_test compat-memfs v1.2\memfs\memfs-x86 winfsp-tests-x86
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
del "%ProjRoot%\tst\compat\v1.2\memfs\winfsp-*.dll"
|
||||
exit /b 0
|
||||
|
||||
:__run_compat_memfs_test
|
||||
set RunSampleTestExit=0
|
||||
call "%ProjRoot%\tools\fsreg" %1 "%ProjRoot%\tst\compat\%2.exe" ^
|
||||
"-i -F NTFS -n 65536 -s 67108864 -u %%%%1 -m %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||
echo net use L: "\\%1\share"
|
||||
net use L: "\\%1\share"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
echo net use ^| findstr L:
|
||||
net use | findstr L:
|
||||
pushd >nul
|
||||
cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%3.exe" ^
|
||||
--external --resilient --share-prefix="\%1\share"
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
echo net use L: /delete
|
||||
net use L: /delete
|
||||
call "%ProjRoot%\tools\fsreg" -u %1
|
||||
exit /b !RunSampleTestExit!
|
||||
|
||||
:compat-v1.1-passthrough-fuse-x64
|
||||
call :__run_compat_fuse_test passthrough-fuse v1.1\passthrough-fuse\passthrough-fuse-x64 winfsp-tests-x64
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
|
5
tst/airfs/.gitignore
vendored
Normal file
5
tst/airfs/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
build
|
||||
*.ncb
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.vcxproj.user
|
2031
tst/airfs/airfs.cpp
Normal file
2031
tst/airfs/airfs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
tst/airfs/airfs.sln
Normal file
28
tst/airfs/airfs.sln
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "airfs", "airfs.vcxproj", "{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Debug|x64.Build.0 = Debug|x64
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Release|x64.ActiveCfg = Release|x64
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Release|x64.Build.0 = Release|x64
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
178
tst/airfs/airfs.vcxproj
Normal file
178
tst/airfs/airfs.vcxproj
Normal file
@ -0,0 +1,178 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{CA441CE7-C4DE-4B5E-AA72-D4D483413EF0}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>airfs</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="airfs.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
14
tst/airfs/airfs.vcxproj.filters
Normal file
14
tst/airfs/airfs.vcxproj.filters
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="airfs.cpp">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
tst/compat/README.md
Normal file
4
tst/compat/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
This directory contains binaries for backwards compatibility testing.
|
||||
|
||||
- `v1.1/passthrough-fuse`: testing of changes related to `struct fuse_stat_ex` (`v1.2B3`)
|
||||
- `v1.2/memfs`: testing of `FSP_FSCTL_VOLUME_PARAMS` size change (`v1.3B3`)
|
@ -1,3 +0,0 @@
|
||||
This directory contains binaries of `passthrough-fuse` from release `v1.2B2`. Both `x64` and `x86` binaries are provided.
|
||||
|
||||
The WinFsp-FUSE layer added support for `struct fuse_stat_ex` in `v1.2B3` which was a potentially breaking change for backwards compatibility. These binaries are used to verify that WinFsp-FUSE remains backwards compatible.
|
BIN
tst/compat/v1.2/memfs/memfs-x64.exe
Normal file
BIN
tst/compat/v1.2/memfs/memfs-x64.exe
Normal file
Binary file not shown.
BIN
tst/compat/v1.2/memfs/memfs-x86.exe
Normal file
BIN
tst/compat/v1.2/memfs/memfs-x86.exe
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user