Compare commits
330 Commits
Author | SHA1 | Date | |
---|---|---|---|
38ad8fd27d | |||
de85070e73 | |||
5b8ebd6e1d | |||
db530cb5e5 | |||
7cd4d4faab | |||
2560a513dc | |||
1ee95be5d7 | |||
bd7546559c | |||
d18a2c8b75 | |||
0ebae0adc1 | |||
d70c49ccd0 | |||
5846939116 | |||
f124e74f01 | |||
05abb93e4b | |||
5839d46b7a | |||
bce0d63f7d | |||
14b9f5affc | |||
035a430470 | |||
0af9e46e76 | |||
c4530f1252 | |||
9f78a17583 | |||
eea0b1bc79 | |||
8338a6e066 | |||
ddba49dbea | |||
a6ff8a87de | |||
bf64bcf9ba | |||
8c5d9bda20 | |||
f1ac28b0aa | |||
ff725f931d | |||
31519ba416 | |||
0bca8f851c | |||
acf175da60 | |||
23eac24c84 | |||
0f9ef3bd51 | |||
2bdd54536e | |||
060ebcca0d | |||
b38a89e485 | |||
b5bfeee027 | |||
f36cacaf84 | |||
4278cec465 | |||
151627091b | |||
2ee3f02928 | |||
d77d3ccccf | |||
1e0c91658e | |||
568096b560 | |||
b2e175a991 | |||
757c4f151d | |||
8b71e18972 | |||
4e7f988371 | |||
eb04d7ab90 | |||
d6c3b7304d | |||
1ee563cd13 | |||
8787f2c528 | |||
4c102ab57c | |||
bf87c539fd | |||
d5802f3a5f | |||
c144d4d303 | |||
9770efde14 | |||
197ce7c30a | |||
5d8384a508 | |||
8bb46a5f86 | |||
a3087cb696 | |||
92b1a8c00d | |||
bbf641e721 | |||
539ab9ce63 | |||
a29390412b | |||
739eb80cfb | |||
f9a470a0f0 | |||
44358e118c | |||
2a7ee146f1 | |||
0ddeb02235 | |||
26d8ea1c1c | |||
fa4aaf2fb7 | |||
7645a0185b | |||
dcf38cdf08 | |||
c7ca500dd5 | |||
d9fcc8ca1c | |||
259f2bf1c1 | |||
67711082b0 | |||
f2d98bbf25 | |||
e40505adb5 | |||
ac7b7f4a1b | |||
aa53b1e5ef | |||
c4b73c8eda | |||
332bce6322 | |||
5ef1de2647 | |||
de60e76b1d | |||
8f8e8fe086 | |||
0ac9a83026 | |||
b8c97caec0 | |||
f9b8bfc020 | |||
f938bf5e3f | |||
a0df9babf9 | |||
0d9d8ef5a2 | |||
668948ebc1 | |||
83c9351d38 | |||
aa1e32494c | |||
6365a553dc | |||
1245a29be6 | |||
c79785c2db | |||
f117a89697 | |||
33f5b8c05b | |||
9a02a46cf4 | |||
4d6fc3c848 | |||
964f2eed69 | |||
b45cff2881 | |||
f219885939 | |||
0cfc730745 | |||
a3643f8b02 | |||
de61eaf6b8 | |||
075a2b6e4c | |||
37affbf572 | |||
20b3ecd0cd | |||
c782c4d668 | |||
d545b8df26 | |||
08e520e0ec | |||
a5db7a2cca | |||
74c2494bbd | |||
858f77cdf7 | |||
30dae34700 | |||
36d50facd7 | |||
55dd8797d8 | |||
27114184d2 | |||
1980f511ce | |||
4cbee05849 | |||
f2391d99d5 | |||
fa9ff37de9 | |||
39b60c1348 | |||
5bc15a7e54 | |||
81bc200fe7 | |||
89324d2327 | |||
47b81a8025 | |||
02cec420e7 | |||
8e7e959d8a | |||
fc51b7cc22 | |||
ff5850847f | |||
ab462fb546 | |||
a5eadc50a7 | |||
afe7f8d728 | |||
c137d49dcd | |||
b70337bac3 | |||
c9b5f25ffc | |||
96f6c28885 | |||
deb8aed91f | |||
fac270e596 | |||
0189adac8f | |||
af772d7a86 | |||
96554cc0ca | |||
ddb3698c89 | |||
9657ae31c3 | |||
0795774e9e | |||
763f256e1f | |||
367f450e30 | |||
7afdee7c01 | |||
87c5f19ce1 | |||
00d1a3176e | |||
6318e7b0ef | |||
5d23b1fef8 | |||
44fe02d2fd | |||
1f0de20b7f | |||
bfd2e106ac | |||
b1848e963f | |||
a29611fa2a | |||
8a369bd48a | |||
9ca7424d27 | |||
4f640755bc | |||
c085a91991 | |||
83cd3cab99 | |||
67dff84a13 | |||
c702a86fbf | |||
f335a990af | |||
ba68ab845b | |||
db0566701e | |||
433e62f813 | |||
6777de6569 | |||
63ee24235b | |||
c3eb46813e | |||
bee0fa79b2 | |||
d907bf2769 | |||
38bcece5ce | |||
193de36301 | |||
c080e86f11 | |||
79811a2faa | |||
b1e287727d | |||
2def18e271 | |||
3ddc2249f6 | |||
709ead9e06 | |||
7c574da261 | |||
0980365082 | |||
ba46d9fef8 | |||
4c0386bf8d | |||
6774c34422 | |||
3215d8e26a | |||
7911f1354f | |||
28f97c2619 | |||
4b43cc590f | |||
441c45c77f | |||
c246acb2d3 | |||
50ed020e16 | |||
12704a3a4a | |||
186f7cd9ee | |||
50830f0bf2 | |||
86025aa30b | |||
31e6f15eaf | |||
5ce6d74e90 | |||
02ffa6afb2 | |||
712870ddd9 | |||
35d1adb360 | |||
3b9f9ce93b | |||
a7c5e4f80c | |||
0b826f04c2 | |||
69d53b7a28 | |||
877bd97ba8 | |||
559b7e80a3 | |||
495c78eb25 | |||
cf69d6a08d | |||
0d95bb9b14 | |||
cf48d19759 | |||
14c602ccd8 | |||
2d45082d80 | |||
25cf527af4 | |||
76d081937e | |||
ccd4bb869c | |||
46d5c98926 | |||
1726ca8ccb | |||
b8c257f996 | |||
53e6894298 | |||
10d1ba707e | |||
c234e2af2a | |||
fa652cdb56 | |||
aeaeba0dd6 | |||
b299027f6e | |||
5edd9eb548 | |||
fbc24bcca9 | |||
4ef6dcb71d | |||
b8f0d08672 | |||
5c82044295 | |||
e3b5426e45 | |||
d34f262c02 | |||
ede72e4c5f | |||
9c4b73dac1 | |||
9ecfc64178 | |||
fbe46d8c81 | |||
2a12ed490d | |||
c6d9e68c3f | |||
bfc41127d0 | |||
6e70500afc | |||
dca3cb93f3 | |||
2f0061b4ba | |||
3fcef3b0fa | |||
6a0574e309 | |||
0c945b67f3 | |||
25b3e111fa | |||
09101129a3 | |||
3700b375a7 | |||
22fccdb575 | |||
c4932f7c7e | |||
303cadb55d | |||
5617d09edc | |||
eefaad241d | |||
11dce32baa | |||
3b8396dc27 | |||
da7082030a | |||
7425eba8af | |||
acf6ce1008 | |||
06f6c192ed | |||
b7a06c7046 | |||
edb675d2d4 | |||
9533815931 | |||
fe74fc4013 | |||
5bd6c1a122 | |||
7b15d32c33 | |||
c186289672 | |||
ff649e05c5 | |||
9a9d3cd4e8 | |||
d1bb65a998 | |||
178200fd63 | |||
396d9d97d2 | |||
1d35069aab | |||
4421c82ce0 | |||
36f0978971 | |||
dae4bad732 | |||
75744571ff | |||
0494726f52 | |||
a964ab1b73 | |||
796010c9fe | |||
dc343ecbe5 | |||
706fa2cc07 | |||
c0aaebd0a5 | |||
9c2b4e5631 | |||
206b85c278 | |||
075d1821a2 | |||
c252382204 | |||
a91e5b01ab | |||
473914d45f | |||
e12e3630bb | |||
960c627924 | |||
f97ef5704f | |||
41605a3d5a | |||
e4f0406c4f | |||
b5bf84b618 | |||
3c340345c0 | |||
63c23f382b | |||
de5ef0c81d | |||
7288605f65 | |||
55a7864173 | |||
4fe72ab332 | |||
76a2926116 | |||
7843c73d34 | |||
ebad86387c | |||
5475c414b3 | |||
e3e111ab27 | |||
9cd6710438 | |||
a5f8736b1e | |||
2ced698256 | |||
53a4bdc478 | |||
eea92e89ef | |||
d519145f61 | |||
2809f56217 | |||
8cb76783ad | |||
117ab9c3e4 | |||
61a001baf1 | |||
d0c700eb0f | |||
b774aea4f4 | |||
f8e4c1bbc4 | |||
3bbff30f14 | |||
2fe4e18d9c | |||
b65322c2ac | |||
7764663386 | |||
c6ae62f301 |
@ -1,6 +1,51 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v1.1 (2017.1)::
|
||||||
|
|
||||||
|
This release brings some major new components and improvements.
|
||||||
|
|
||||||
|
- A .NET layer that allows the creation of file systems in managed mode. This is contained in the new `winfsp-msil.dll`. The new .NET layer is being tested with the WinFsp test suites and Microsoft's ifstest.
|
||||||
|
- A simple C++ layer can be found in `inc/winfsp/winfsp.hpp`.
|
||||||
|
- FUSE for Cygwin is now included with the installer.
|
||||||
|
- FUSE now has a `-ovolname=VOLNAME` parameter that allows setting the volume label. Thanks @samkelly.
|
||||||
|
|
||||||
|
|
||||||
|
v1.0::
|
||||||
|
|
||||||
|
This is the WinFsp 2017 release! :tada:
|
||||||
|
|
||||||
|
- The API is now *FROZEN*. Breaking API changes will receive a major version update (`2.0`). Incremental API changes will receive a minor version update (`1.x`).
|
||||||
|
- Adds chocolatey package. Try `choco install winfsp` (note: pending approval from chocolatey.org).
|
||||||
|
- FUSE `-d` output now always goes to stderr. There is also a new `-oDebugLog=FILE` switch to specify a debug output file.
|
||||||
|
- FUSE now provides a default `statfs` implementation if a file system does not provide one.
|
||||||
|
- The WinFsp DLL now exports `fuse_*` symbols in addition to the `fsp_fuse_*` symbols. These symbols are for use with programs that use FFI technology such as jnr-fuse and fusepy *ONLY*. They are not supposed to be used by native C/C++ programs. Such programs are supposed to include the `<fuse.h>` headers.
|
||||||
|
|
||||||
|
|
||||||
|
v1.0RC3::
|
||||||
|
|
||||||
|
This is the WinFsp 2017 Release Candidate 3, which should be the last Release Candidate according to the current plan. This release fixes a major issue with some file systems and includes a few smaller changes:
|
||||||
|
|
||||||
|
- Fixes GitHub issue #55. Prior to this fix it was possible for a rogue process (or faulty file system) to crash Windows using WinFsp. For full details read http://www.osronline.com/showthread.cfm?link=282037[this thread].
|
||||||
|
- Introduces the `FspFileSystemSetMountPointEx` API, which allows the specification of a security descriptor when mounting over a directory.
|
||||||
|
- Introduces the `FspVersion` API, which allows the retrieval of the WinFsp DLL version. Currently this reports `0x00010000` (version `1.0`).
|
||||||
|
- Introduces the `FSP_FUSE_CAP_CASE_INSENSITIVE` and `FSP_FUSE_CAP_READDIR_PLUS` WinFsp-FUSE flags. The `FSP_FUSE_CAP_CASE_INSENSITIVE` flag allows a file system to mark itself as case-insensitive. The `FSP_FUSE_CAP_READDIR_PLUS` flag allows a file system to include full `stat` details when responding to the `readdir` operation (thus avoiding extraneous `getattr` calls).
|
||||||
|
- When using WinFsp-FUSE over Cygwin, POSIX paths can be used as mountpoints.
|
||||||
|
- Fixes GitHub issue #45. Prior to this fix, file systems that do not properly implement `Cleanup` (including FUSE file systems) would at times disallow renaming of directories.
|
||||||
|
|
||||||
|
|
||||||
|
v1.0RC2::
|
||||||
|
|
||||||
|
This is the WinFsp 2017 Release Candidate 2. Some important changes included below:
|
||||||
|
|
||||||
|
- WinFsp is now available under the GPLv3 with a special exception for Free/Libre and Open Source Software.
|
||||||
|
- The location of the WinFsp launcher registry entries is now `HKEY_LOCAL_MACHINE\Software\WinFsp\Services`. [On Win64 the actual location is `HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services`.] This change was necessary to avoid loss of third party file system registry entries during WinFsp uninstallation. [See GitHub issue #31.]
|
||||||
|
- Despite stating in the previous release that the API has been finalized the `ReadDirectory` `FSP_FILE_SYSTEM_INTERFACE` operation has been changed. Extensive testing with multiple file systems has shown that `ReadDirectory` was hard to implement correctly. The new definition should make implementation easier for most file systems. [See GitHub issue #34.]
|
||||||
|
- Some API's to facilitate `ReadDirectory` implementation have been added. Look for `FspFileSystem*DirectoryBuffer` symbols.
|
||||||
|
- The installer now (optionally) installs a sample file system called "passthrough". This is a simple file system that passes all operations to an underlying file system. There is also a tutorial for this file system (in the doc directory).
|
||||||
|
- The installer now (optionally) installs a sample file system called "passthrough-fuse". This file system performs the same function as the "passthrough" file system, but uses the FUSE compatibility layer. It builds and runs on both Windows and Cygwin.
|
||||||
|
|
||||||
|
|
||||||
v1.0RC1::
|
v1.0RC1::
|
||||||
|
|
||||||
This is the WinFsp 2017 Release Candidate 1. It has been tested extensively in a variety of scenarios for stability and correct file system semantics. Some of the more important changes:
|
This is the WinFsp 2017 Release Candidate 1. It has been tested extensively in a variety of scenarios for stability and correct file system semantics. Some of the more important changes:
|
||||||
|
@ -54,5 +54,6 @@ This CONTRIBUTOR AGREEMENT applies to any contribution that you make to the WinF
|
|||||||
CONTRIBUTOR LIST
|
CONTRIBUTOR LIST
|
||||||
----------------
|
----------------
|
||||||
|===
|
|===
|
||||||
|Bill Zissimopoulos |billziss at navimatics.com
|
|Bill Zissimopoulos |billziss at navimatics.com
|
||||||
|
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||||
|===
|
|===
|
||||||
|
31
License.txt
@ -1,8 +1,35 @@
|
|||||||
The WinFsp project is Copyright (C) Bill Zissimopoulos. It is licensed
|
The WinFsp project is Copyright (C) Bill Zissimopoulos. It is licensed
|
||||||
under the terms of the GPLv3. The full text of this license follows
|
under the terms of the GPLv3.
|
||||||
below. Commercial licensing options are also available: Please contact
|
|
||||||
|
As a special exception to GPLv3, Bill Zissimopoulos grants additional
|
||||||
|
permissions to Free/Libre and Open Source Software ("FLOSS") without requiring
|
||||||
|
that such software is covered by the GPLv3.
|
||||||
|
|
||||||
|
1. Permission to link with a platform specific version of the WinFsp DLL
|
||||||
|
(one of: winfsp-x64.dll, winfsp-x86.dll, winfsp-msil.dll).
|
||||||
|
|
||||||
|
2. Permission to distribute unmodified binary releases of the WinFsp
|
||||||
|
installer (as released by the WinFsp project).
|
||||||
|
|
||||||
|
These permissions (and no other) are granted provided that the software:
|
||||||
|
|
||||||
|
1. Is distributed under a license that satisfies the Free Software
|
||||||
|
Definition Version 1.141 (https://www.gnu.org/philosophy/free-sw.en.html)
|
||||||
|
or the Open Source Definition Version 1.9 (https://opensource.org/osd).
|
||||||
|
|
||||||
|
2. Includes the copyright notice "WinFsp - Windows File System Proxy,
|
||||||
|
Copyright (C) Bill Zissimopoulos" and a link to the WinFsp repository in
|
||||||
|
its user-interface and any user-facing documentation.
|
||||||
|
|
||||||
|
3. Is not linked or distributed with proprietary (non-FLOSS) software.
|
||||||
|
[You cannot mix FLOSS and proprietary software while using WinFsp under
|
||||||
|
this special exception.]
|
||||||
|
|
||||||
|
Commercial licensing options are also available: Please contact
|
||||||
Bill Zissimopoulos <billziss at navimatics.com>.
|
Bill Zissimopoulos <billziss at navimatics.com>.
|
||||||
|
|
||||||
|
The full text of the GPLv3 license follows below.
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
31
README.md
@ -2,6 +2,13 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
Some of the benefits of using WinFsp are listed below:
|
Some of the benefits of using WinFsp are listed below:
|
||||||
@ -9,10 +16,11 @@ Some of the benefits of using WinFsp are listed below:
|
|||||||
* Very well-tested and stable. Read about its [Testing Strategy](doc/WinFsp-Testing.asciidoc).
|
* 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).
|
* Very fast. Read about its [Performance](doc/WinFsp-Performance-Testing.asciidoc).
|
||||||
* Strives for compatibility with NTFS. Read about its [Compatibility](doc/NTFS-Compatibility.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/).
|
* 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).
|
* 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.
|
* Signed drivers provided on every release.
|
||||||
* Available under the GPLv3.
|
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
|
||||||
|
|
||||||
To learn more about WinFsp, please visit its website: http://www.secfs.net/winfsp/
|
To learn more about WinFsp, please visit its website: http://www.secfs.net/winfsp/
|
||||||
|
|
||||||
@ -30,29 +38,34 @@ The project source code is organized as follows:
|
|||||||
* inc/fuse: Public headers for the FUSE compatibility layer.
|
* inc/fuse: Public headers for the FUSE compatibility layer.
|
||||||
* src/dll: Source code to the WinFsp DLL.
|
* src/dll: Source code to the WinFsp DLL.
|
||||||
* src/dll/fuse: Source code to the FUSE compatibility layer.
|
* src/dll/fuse: Source code to the FUSE compatibility layer.
|
||||||
|
* src/dotnet: Source code to the .NET layer.
|
||||||
* src/launcher: Source code to the launcher service and the launchctl utility.
|
* src/launcher: Source code to the launcher service and the launchctl utility.
|
||||||
* src/sys: Source code to the WinFsp FSD.
|
* src/sys: Source code to the WinFsp FSD.
|
||||||
* opt/cygfuse: Source code for the Cygwin FUSE package.
|
* opt/cygfuse: Source code for the Cygwin FUSE package.
|
||||||
* tst/memfs: Source code to an example file system written in C++ (memfs).
|
* 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.
|
* tst/winfsp-tests: WinFsp test suite.
|
||||||
|
|
||||||
## Building and Running
|
## Building and Running
|
||||||
|
|
||||||
In order to build WinFsp you will need the following:
|
In order to build WinFsp you will need the following:
|
||||||
|
|
||||||
* Windows 10
|
|
||||||
* Visual Studio 2015
|
* Visual Studio 2015
|
||||||
* Windows Driver Kit (WDK) 10
|
* Windows Driver Kit (WDK) 10
|
||||||
* [Wix toolset](http://wixtoolset.org)
|
* [Wix toolset](http://wixtoolset.org)
|
||||||
|
|
||||||
If you build the driver yourself it will not be signed and Windows will refuse to load it unless you enable "testsigning". You can enable "testsigning" using the command `bcdedit.exe -set testsigning`. For more information see this [document](http://www.secfs.net/winfsp/develop/debug/).
|
To fully build WinFsp (including the installer) you must use `tools\build.bat`. By default it builds a Release build, but you can choose either the Debug or Release configuration by using the syntax:
|
||||||
|
|
||||||
WinFsp is designed to run on Vista and above. It has been tested on the following platforms so far:
|
tools\build.bat CONFIGURATION
|
||||||
|
|
||||||
|
If you build the driver yourself it will not be signed and Windows will refuse to load it unless you enable "testsigning". You can enable "testsigning" using the command `bcdedit.exe -set testsigning on`. For more information see this [document](http://www.secfs.net/winfsp/develop/debug/).
|
||||||
|
|
||||||
|
WinFsp is designed to run on Windows 7 and above. It has been tested on the following platforms:
|
||||||
|
|
||||||
* Windows 7 Enterprise
|
* Windows 7 Enterprise
|
||||||
* Windows 8 Pro
|
* Windows 8 Pro
|
||||||
* Windows 10 Pro
|
|
||||||
* Windows Server 2012
|
* Windows Server 2012
|
||||||
|
* Windows 10 Pro
|
||||||
* Windows Server 2016
|
* Windows Server 2016
|
||||||
|
|
||||||
## How to Help
|
## How to Help
|
||||||
@ -60,7 +73,7 @@ WinFsp is designed to run on Vista and above. It has been tested on the followin
|
|||||||
I am looking for help in the following areas:
|
I am looking for help in the following areas:
|
||||||
|
|
||||||
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
|
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
|
||||||
* If you are working with a language other than C/C++ (e.g. Delphi, C#, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
* If you are working with a language other than C/C++ (e.g. Delphi, Java, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
||||||
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/billziss-gh/winfsp/issues). Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart.
|
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/billziss-gh/winfsp/issues). Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart.
|
||||||
|
|
||||||
In all cases I can provide ideas and/or support.
|
In all cases I can provide ideas and/or support.
|
||||||
@ -74,4 +87,4 @@ If you wish to discuss WinFsp there are now two options:
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
WinFsp is available under the [GPLv3](http://www.gnu.org/licenses/gpl-3.0.html) license. If you find the constraints of the GPLv3 too onerous, a commercial license is also available. Please contact Bill Zissimopoulos <billziss at navimatics.com> for more details.
|
WinFsp is available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software. A commercial license is also available. Please contact Bill Zissimopoulos \<billziss at navimatics.com> for more details.
|
||||||
|
@ -23,13 +23,15 @@ build_script:
|
|||||||
- tools\build.bat %CONFIGURATION%
|
- tools\build.bat %CONFIGURATION%
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- for %%f in ("build\VStudio\build\%CONFIGURATION%\winfsp-*.msi") do start /wait msiexec /i %%f /qn INSTALLLEVEL=1000
|
- choco install winfsp -s build\VStudio\build\%CONFIGURATION% -y
|
||||||
- if %TESTING%==Func appveyor DownloadFile http://www.secfs.net/winfsp/resources/Test.Filter.Driver.zip && 7z x Test.Filter.Driver.zip
|
- if %TESTING%==Func appveyor DownloadFile http://www.secfs.net/winfsp/resources/Test.Filter.Driver.zip && 7z x Test.Filter.Driver.zip
|
||||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
||||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
||||||
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
|
||||||
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
||||||
|
- choco uninstall winfsp -y
|
||||||
- if exist %SystemRoot%\memory.dmp exit 1
|
- if exist %SystemRoot%\memory.dmp exit 1
|
||||||
|
|
||||||
on_finish:
|
on_finish:
|
||||||
|
1
build/VStudio/.gitignore
vendored
@ -3,3 +3,4 @@ build
|
|||||||
*.suo
|
*.suo
|
||||||
*.vcproj.*
|
*.vcproj.*
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
|
*.csproj.user
|
||||||
|
113
build/VStudio/dotnet/winfsp.net.csproj
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{94580219-CC8D-4FE5-A3BE-437B0B3481E1}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<ProjectName>winfsp.net</ProjectName>
|
||||||
|
<RootNamespace>Fsp</RootNamespace>
|
||||||
|
<AssemblyName>winfsp-msil</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<DocumentationFile>$(BaseIntermediateOutputPath)$(Configuration)\winfsp-msil.xml</DocumentationFile>
|
||||||
|
<NoWarn>1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<DocumentationFile>$(BaseIntermediateOutputPath)$(Configuration)\winfsp-msil.xml</DocumentationFile>
|
||||||
|
<NoWarn>1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<AssemblyOriginatorKeyFile>winfsp.net.snk</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\..\..\src\dotnet\FileSystemBase+Const.cs">
|
||||||
|
<Link>FileSystemBase+Const.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\..\..\src\dotnet\FileSystemBase.cs">
|
||||||
|
<Link>FileSystemBase.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\..\..\src\dotnet\FileSystemHost.cs">
|
||||||
|
<Link>FileSystemHost.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\..\..\src\dotnet\Interop.cs">
|
||||||
|
<Link>Interop.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\..\..\src\dotnet\Service.cs">
|
||||||
|
<Link>Service.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="winfsp.net.snk" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
<ItemGroup>
|
||||||
|
<AssemblyInfo Include="using System.Reflection%3b" />
|
||||||
|
<AssemblyInfo Include="[assembly: AssemblyProduct("$(MyProductName)")]" />
|
||||||
|
<AssemblyInfo Include="[assembly: AssemblyTitle("$(MyDescription)")]" />
|
||||||
|
<AssemblyInfo Include="[assembly: AssemblyCompany("$(MyCompanyName)")]" />
|
||||||
|
<AssemblyInfo Include="[assembly: AssemblyCopyright("$(MyCopyright)")]" />
|
||||||
|
<AssemblyInfo Include="[assembly: AssemblyVersion("$(MyAssemblyVersion)")]" />
|
||||||
|
<AssemblyInfo Include="[assembly: AssemblyFileVersion("$(MyVersion)")]" />
|
||||||
|
</ItemGroup>
|
||||||
|
<MakeDir Directories="$(IntermediateOutputPath)" />
|
||||||
|
<WriteLinesToFile File="$(IntermediateOutputPath)AssemblyInfo.cs" Lines="@(AssemblyInfo)" Overwrite="true" />
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
|
||||||
|
<FileWrites Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
<PropertyGroup>
|
||||||
|
<PostBuildEvent>exit /b 0
|
||||||
|
|
||||||
|
set TargetName=$(TargetName)
|
||||||
|
set MyAssemblyPolicyVersion=$(MyAssemblyPolicyVersion)
|
||||||
|
set MyAssemblyVersion=$(MyAssemblyVersion)
|
||||||
|
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
if exist $(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config del $(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config
|
||||||
|
for /f "delims=" %25%25l in ($(ProjectDir)winfsp.net.policy.config) do (
|
||||||
|
set line=%25%25l
|
||||||
|
echo !line! >>$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config
|
||||||
|
)
|
||||||
|
|
||||||
|
"$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.0A\Bin\al.exe" /product:"$(MyProductName)" /title:"$(MyDescription)" /company:"$(MyCompanyName)" /copyright:"$(MyCopyright)" /version:"$(MyAssemblyPolicyVersion)" /fileversion:"$(MyVersion)" /link:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).config /out:$(OutDir)policy.$(MyAssemblyPolicyVersion).$(TargetName).dll /keyfile:$(ProjectDir)$(ProjectName).snk
|
||||||
|
</PostBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
10
build/VStudio/dotnet/winfsp.net.policy.config
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="!TargetName!" publicKeyToken="b099876d8fa9b1f3" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="!MyAssemblyPolicyVersion!.0.0-!MyAssemblyVersion!" newVersion="!MyAssemblyVersion!" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
BIN
build/VStudio/dotnet/winfsp.net.snk
Normal file
@ -22,7 +22,7 @@
|
|||||||
<Media Id="1" Cabinet="WinFsp.cab" EmbedCab="yes" />
|
<Media Id="1" Cabinet="WinFsp.cab" EmbedCab="yes" />
|
||||||
|
|
||||||
<Property Id="P.LauncherName">$(var.MyProductName).Launcher</Property>
|
<Property Id="P.LauncherName">$(var.MyProductName).Launcher</Property>
|
||||||
<Property Id="P.LauncherRegistryKey">SYSTEM\\CurrentControlSet\\Services\\$(var.MyProductName).Launcher\\Services</Property>
|
<Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property>
|
||||||
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
|
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
|
||||||
<Property Id="INSTALLDIR">
|
<Property Id="INSTALLDIR">
|
||||||
<RegistrySearch
|
<RegistrySearch
|
||||||
@ -39,6 +39,7 @@
|
|||||||
<Directory Id="BINDIR" Name="bin" />
|
<Directory Id="BINDIR" Name="bin" />
|
||||||
<Directory Id="INCDIR" Name="inc" />
|
<Directory Id="INCDIR" Name="inc" />
|
||||||
<Directory Id="LIBDIR" Name="lib" />
|
<Directory Id="LIBDIR" Name="lib" />
|
||||||
|
<Directory Id="OPTDIR" Name="opt" />
|
||||||
<Directory Id="SMPDIR" Name="samples" />
|
<Directory Id="SMPDIR" Name="samples" />
|
||||||
<Directory Id="SYMDIR" Name="sym" />
|
<Directory Id="SYMDIR" Name="sym" />
|
||||||
</Directory>
|
</Directory>
|
||||||
@ -55,6 +56,9 @@
|
|||||||
Value="[INSTALLDIR]"
|
Value="[INSTALLDIR]"
|
||||||
KeyPath="yes" />
|
KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="C.License.txt">
|
||||||
|
<File Name="License.txt" Source="..\..\..\License.txt" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
||||||
<Component Id="C.winfsp_x64.sys">
|
<Component Id="C.winfsp_x64.sys">
|
||||||
@ -84,6 +88,23 @@
|
|||||||
<Condition>NOT VersionNT64</Condition>
|
<Condition>NOT VersionNT64</Condition>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
|
<!-- install assembly -->
|
||||||
|
<Component Id="C.winfsp_msil.dll" Guid="0D8BA6AE-9F87-402B-AE1A-95B0AE3BE179">
|
||||||
|
<File Id="FILE.winfsp_msil.dll" Name="winfsp-msil.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.winfsp_msil.xml" Guid="1657F707-C112-454C-91AE-0FDEBBF454AB">
|
||||||
|
<File Id="FILE.winfsp_msil.xml" Name="winfsp-msil.xml" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<!--
|
||||||
|
<Component Id="C.winfsp_msil.dll.GAC" Guid="6469467D-8C90-4889-8138-4028F9DA6E85">
|
||||||
|
<File Id="FILE.winfsp_msil.dll.GAC" Name="winfsp-msil.dll" KeyPath="yes" Assembly=".net" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.policy.winfsp_msil.dll.GAC">
|
||||||
|
<File Name="policy.1.0.winfsp-msil.dll" KeyPath="yes" Assembly=".net" />
|
||||||
|
<File Name="policy.1.0.winfsp-msil.config" KeyPath="no" />
|
||||||
|
</Component>
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
||||||
<Component Id="C.launcher_x64.exe.svcinst">
|
<Component Id="C.launcher_x64.exe.svcinst">
|
||||||
<File Id="launcher_x64.exe.svcinst" Name="launcher-x64.exe" KeyPath="yes" />
|
<File Id="launcher_x64.exe.svcinst" Name="launcher-x64.exe" KeyPath="yes" />
|
||||||
@ -140,6 +161,9 @@
|
|||||||
<Component Id="C.diag.bat">
|
<Component Id="C.diag.bat">
|
||||||
<File Name="diag.bat" Source="..\..\..\tools\diag.bat" KeyPath="yes" />
|
<File Name="diag.bat" Source="..\..\..\tools\diag.bat" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="C.fsreg.bat">
|
||||||
|
<File Name="fsreg.bat" Source="..\..\..\tools\fsreg.bat" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
<Component Id="C.memfs_x64.exe">
|
<Component Id="C.memfs_x64.exe">
|
||||||
<File Name="memfs-x64.exe" KeyPath="yes" />
|
<File Name="memfs-x64.exe" KeyPath="yes" />
|
||||||
@ -193,6 +217,32 @@
|
|||||||
</RegistryKey>
|
</RegistryKey>
|
||||||
</RegistryKey>
|
</RegistryKey>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="C.memfs_dotnet_msil.exe">
|
||||||
|
<File Name="memfs-dotnet-msil.exe" KeyPath="yes" />
|
||||||
|
<RegistryKey
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.LauncherRegistryKey]">
|
||||||
|
<RegistryKey
|
||||||
|
Key="memfs-dotnet">
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="Executable"
|
||||||
|
Value="[BINDIR]memfs-dotnet-msil.exe" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="CommandLine"
|
||||||
|
Value="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="Security"
|
||||||
|
Value="D:P(A;;RPWPLC;;;WD)" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="integer"
|
||||||
|
Name="JobControl"
|
||||||
|
Value="1" />
|
||||||
|
</RegistryKey>
|
||||||
|
</RegistryKey>
|
||||||
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="INCDIR" FileSource="..\..\..\inc">
|
<DirectoryRef Id="INCDIR" FileSource="..\..\..\inc">
|
||||||
<Directory Id="INCDIR.winfsp" Name="winfsp">
|
<Directory Id="INCDIR.winfsp" Name="winfsp">
|
||||||
@ -202,6 +252,9 @@
|
|||||||
<Component Id="C.winfsp.h">
|
<Component Id="C.winfsp.h">
|
||||||
<File Name="winfsp.h" KeyPath="yes" />
|
<File Name="winfsp.h" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="C.winfsp.hpp">
|
||||||
|
<File Name="winfsp.hpp" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
<Directory Id="INCDIR.fuse" Name="fuse">
|
<Directory Id="INCDIR.fuse" Name="fuse">
|
||||||
<Component Id="C.fuse.h">
|
<Component Id="C.fuse.h">
|
||||||
@ -246,6 +299,19 @@
|
|||||||
<Condition>NOT VersionNT64</Condition>
|
<Condition>NOT VersionNT64</Condition>
|
||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="OPTDIR">
|
||||||
|
<Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist">
|
||||||
|
<Component Id="C.fuse.tar.xz">
|
||||||
|
<File Name="fuse-2.8-4.tar.xz" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.fuse.install.sh">
|
||||||
|
<File Name="install.sh" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.fuse.uninstall.sh">
|
||||||
|
<File Name="uninstall.sh" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="SMPDIR" FileSource="..\..\..\tst">
|
<DirectoryRef Id="SMPDIR" FileSource="..\..\..\tst">
|
||||||
<Directory Id="SMPDIR.memfs" Name="memfs">
|
<Directory Id="SMPDIR.memfs" Name="memfs">
|
||||||
<Component Id="C.memfs.h">
|
<Component Id="C.memfs.h">
|
||||||
@ -258,6 +324,76 @@
|
|||||||
<File Name="memfs-main.c" KeyPath="yes" />
|
<File Name="memfs-main.c" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.memfs_dotnet" Name="memfs-dotnet">
|
||||||
|
<Component Id="C.memfs_dotnet.Program.cs">
|
||||||
|
<File Id="FILE.memfs_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.passthrough" Name="passthrough">
|
||||||
|
<Component Id="C.passthrough.c">
|
||||||
|
<File Name="passthrough.c" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough.sln">
|
||||||
|
<File Name="passthrough.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough.vcxproj">
|
||||||
|
<File Name="passthrough.vcxproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough.vcxproj.filters">
|
||||||
|
<File Name="passthrough.vcxproj.filters" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.passthrough_cpp" Name="passthrough-cpp">
|
||||||
|
<Component Id="C.passthrough_cpp.cpp">
|
||||||
|
<File Name="passthrough-cpp.cpp" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_cpp.sln">
|
||||||
|
<File Name="passthrough-cpp.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_cpp.vcxproj">
|
||||||
|
<File Name="passthrough-cpp.vcxproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_cpp.vcxproj.filters">
|
||||||
|
<File Name="passthrough-cpp.vcxproj.filters" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="SMPDIR.passthrough_fuse" Name="passthrough-fuse">
|
||||||
|
<Component Id="C.passthrough_fuse.c">
|
||||||
|
<File Name="passthrough-fuse.c" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.winposix.c">
|
||||||
|
<File Name="winposix.c" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.winposix.h">
|
||||||
|
<File Name="winposix.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.sln">
|
||||||
|
<File Name="passthrough-fuse.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.vcxproj">
|
||||||
|
<File Name="passthrough-fuse.vcxproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.vcxproj.filters">
|
||||||
|
<File Name="passthrough-fuse.vcxproj.filters" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.Makefile">
|
||||||
|
<File Name="Makefile" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_fuse.README.md">
|
||||||
|
<File 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" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_dotnet.sln">
|
||||||
|
<File Name="passthrough-dotnet.sln" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.passthrough_dotnet.csproj">
|
||||||
|
<File Name="passthrough-dotnet.csproj" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="SYMDIR">
|
<DirectoryRef Id="SYMDIR">
|
||||||
<Component Id="C.winfsp_x64.sys.pdb">
|
<Component Id="C.winfsp_x64.sys.pdb">
|
||||||
@ -306,10 +442,12 @@
|
|||||||
<ComponentRef Id="C.launchctl_x64.exe" />
|
<ComponentRef Id="C.launchctl_x64.exe" />
|
||||||
<ComponentRef Id="C.launchctl_x86.exe" />
|
<ComponentRef Id="C.launchctl_x86.exe" />
|
||||||
<ComponentRef Id="C.diag.bat" />
|
<ComponentRef Id="C.diag.bat" />
|
||||||
|
<ComponentRef Id="C.fsreg.bat" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="C.WinFsp.inc">
|
<ComponentGroup Id="C.WinFsp.inc">
|
||||||
<ComponentRef Id="C.fsctl.h" />
|
<ComponentRef Id="C.fsctl.h" />
|
||||||
<ComponentRef Id="C.winfsp.h" />
|
<ComponentRef Id="C.winfsp.h" />
|
||||||
|
<ComponentRef Id="C.winfsp.hpp" />
|
||||||
<ComponentRef Id="C.fuse.h" />
|
<ComponentRef Id="C.fuse.h" />
|
||||||
<ComponentRef Id="C.fuse_common.h" />
|
<ComponentRef Id="C.fuse_common.h" />
|
||||||
<ComponentRef Id="C.fuse_opt.h" />
|
<ComponentRef Id="C.fuse_opt.h" />
|
||||||
@ -321,12 +459,33 @@
|
|||||||
<ComponentRef Id="C.fuse_x64.pc" />
|
<ComponentRef Id="C.fuse_x64.pc" />
|
||||||
<ComponentRef Id="C.fuse_x86.pc" />
|
<ComponentRef Id="C.fuse_x86.pc" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.opt.fuse">
|
||||||
|
<ComponentRef Id="C.fuse.tar.xz" />
|
||||||
|
<ComponentRef Id="C.fuse.install.sh" />
|
||||||
|
<ComponentRef Id="C.fuse.uninstall.sh" />
|
||||||
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="C.WinFsp.smp">
|
<ComponentGroup Id="C.WinFsp.smp">
|
||||||
<ComponentRef Id="C.memfs_x64.exe" />
|
<ComponentRef Id="C.memfs_x64.exe" />
|
||||||
<ComponentRef Id="C.memfs_x86.exe" />
|
<ComponentRef Id="C.memfs_x86.exe" />
|
||||||
<ComponentRef Id="C.memfs.h" />
|
<ComponentRef Id="C.memfs.h" />
|
||||||
<ComponentRef Id="C.memfs.cpp" />
|
<ComponentRef Id="C.memfs.cpp" />
|
||||||
<ComponentRef Id="C.memfs_main.c" />
|
<ComponentRef Id="C.memfs_main.c" />
|
||||||
|
<ComponentRef Id="C.passthrough.c" />
|
||||||
|
<ComponentRef Id="C.passthrough.sln" />
|
||||||
|
<ComponentRef Id="C.passthrough.vcxproj" />
|
||||||
|
<ComponentRef Id="C.passthrough.vcxproj.filters" />
|
||||||
|
<ComponentRef Id="C.passthrough_cpp.cpp" />
|
||||||
|
<ComponentRef Id="C.passthrough_cpp.sln" />
|
||||||
|
<ComponentRef Id="C.passthrough_cpp.vcxproj" />
|
||||||
|
<ComponentRef Id="C.passthrough_cpp.vcxproj.filters" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.c" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.winposix.c" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.winposix.h" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.sln" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.vcxproj" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.vcxproj.filters" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.Makefile" />
|
||||||
|
<ComponentRef Id="C.passthrough_fuse.README.md" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="C.WinFsp.sym">
|
<ComponentGroup Id="C.WinFsp.sym">
|
||||||
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
|
<ComponentRef Id="C.winfsp_x64.sys.pdb" />
|
||||||
@ -340,6 +499,21 @@
|
|||||||
<ComponentRef Id="C.memfs_x64.pdb" />
|
<ComponentRef Id="C.memfs_x64.pdb" />
|
||||||
<ComponentRef Id="C.memfs_x86.pdb" />
|
<ComponentRef Id="C.memfs_x86.pdb" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.net">
|
||||||
|
<ComponentRef Id="C.winfsp_msil.dll" />
|
||||||
|
<ComponentRef Id="C.winfsp_msil.xml" />
|
||||||
|
<!--
|
||||||
|
<ComponentRef Id="C.winfsp_msil.dll.GAC" />
|
||||||
|
<ComponentRef Id="C.policy.winfsp_msil.dll.GAC" />
|
||||||
|
-->
|
||||||
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.smp.net">
|
||||||
|
<ComponentRef Id="C.memfs_dotnet_msil.exe" />
|
||||||
|
<ComponentRef Id="C.memfs_dotnet.Program.cs" />
|
||||||
|
<ComponentRef Id="C.passthrough_dotnet.Program.cs" />
|
||||||
|
<ComponentRef Id="C.passthrough_dotnet.sln" />
|
||||||
|
<ComponentRef Id="C.passthrough_dotnet.csproj" />
|
||||||
|
</ComponentGroup>
|
||||||
|
|
||||||
<Feature
|
<Feature
|
||||||
Id="F.Main"
|
Id="F.Main"
|
||||||
@ -352,6 +526,7 @@
|
|||||||
InstallDefault="local"
|
InstallDefault="local"
|
||||||
Absent="disallow">
|
Absent="disallow">
|
||||||
<ComponentRef Id="C.INSTALLDIR" />
|
<ComponentRef Id="C.INSTALLDIR" />
|
||||||
|
<ComponentRef Id="C.License.txt" />
|
||||||
<Feature
|
<Feature
|
||||||
Id="F.User"
|
Id="F.User"
|
||||||
Level="1"
|
Level="1"
|
||||||
@ -361,7 +536,20 @@
|
|||||||
InstallDefault="local"
|
InstallDefault="local"
|
||||||
Absent="disallow">
|
Absent="disallow">
|
||||||
<ComponentGroupRef Id="C.WinFsp.bin" />
|
<ComponentGroupRef Id="C.WinFsp.bin" />
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.net" />
|
||||||
</Feature>
|
</Feature>
|
||||||
|
<!--
|
||||||
|
<Feature
|
||||||
|
Id="F.Net"
|
||||||
|
Level="10"
|
||||||
|
Title=".NET"
|
||||||
|
Description="The managed $(var.MyProductName) files."
|
||||||
|
AllowAdvertise="no"
|
||||||
|
InstallDefault="local"
|
||||||
|
Absent="allow">
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.net" />
|
||||||
|
</Feature>
|
||||||
|
-->
|
||||||
<Feature
|
<Feature
|
||||||
Id="F.Developer"
|
Id="F.Developer"
|
||||||
Level="1000"
|
Level="1000"
|
||||||
@ -373,8 +561,19 @@
|
|||||||
<ComponentGroupRef Id="C.WinFsp.inc" />
|
<ComponentGroupRef Id="C.WinFsp.inc" />
|
||||||
<ComponentGroupRef Id="C.WinFsp.lib" />
|
<ComponentGroupRef Id="C.WinFsp.lib" />
|
||||||
<ComponentGroupRef Id="C.WinFsp.smp" />
|
<ComponentGroupRef Id="C.WinFsp.smp" />
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.smp.net" />
|
||||||
<ComponentGroupRef Id="C.WinFsp.sym" />
|
<ComponentGroupRef Id="C.WinFsp.sym" />
|
||||||
</Feature>
|
</Feature>
|
||||||
|
<Feature
|
||||||
|
Id="F.Cygfuse"
|
||||||
|
Level="1000"
|
||||||
|
Title="FUSE for Cygwin"
|
||||||
|
Description="From a Cygwin prompt change to $InstallDir/opt/cygfuse and run install.sh."
|
||||||
|
AllowAdvertise="no"
|
||||||
|
InstallDefault="local"
|
||||||
|
Absent="allow">
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.opt.fuse" />
|
||||||
|
</Feature>
|
||||||
</Feature>
|
</Feature>
|
||||||
|
|
||||||
<WixVariable Id="WixUIBannerBmp" Value="wixbanner.bmp" />
|
<WixVariable Id="WixUIBannerBmp" Value="wixbanner.bmp" />
|
||||||
|
63
build/VStudio/testing/memfs-dotnet.csproj
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{4920E350-D496-4652-AE98-6C4208AEC1D8}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<ProjectName>memfs-dotnet</ProjectName>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>memfs</RootNamespace>
|
||||||
|
<AssemblyName>memfs-dotnet-msil</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\..\..\tst\memfs-dotnet\Program.cs">
|
||||||
|
<Link>Program.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\dotnet\winfsp.net.csproj">
|
||||||
|
<Project>{94580219-cc8d-4fe5-a3be-437b0b3481e1}</Project>
|
||||||
|
<Name>winfsp.net</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
@ -182,8 +182,10 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
|
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-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\flush-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-opt-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-opt-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
||||||
@ -200,6 +202,7 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -212,6 +215,9 @@
|
|||||||
<Project>{4a7c0b21-9e10-4c81-92de-1493efcf24eb}</Project>
|
<Project>{4a7c0b21-9e10-4c81-92de-1493efcf24eb}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\..\tst\winfsp-tests\helper\winfsp-tests-helper.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
@ -76,6 +76,15 @@
|
|||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\oplock-test.c">
|
<ClCompile Include="..\..\..\tst\winfsp-tests\oplock-test.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\exec-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||||
@ -88,4 +97,9 @@
|
|||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\..\tst\winfsp-tests\helper\winfsp-tests-helper.rc">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -15,14 +15,17 @@
|
|||||||
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
||||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||||
|
|
||||||
<MyCanonicalVersion>1.0</MyCanonicalVersion>
|
<MyCanonicalVersion>1.1</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2017 RC1</MyProductVersion>
|
<MyProductVersion>2017.1 B2</MyProductVersion>
|
||||||
<MyProductStage>RC</MyProductStage>
|
<MyProductStage>Beta</MyProductStage>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
<MyFullVersion>$(MyCanonicalVersion).$(MyBuildNumber).$(MyGitRevision)</MyFullVersion>
|
<MyFullVersion>$(MyCanonicalVersion).$(MyBuildNumber).$(MyGitRevision)</MyFullVersion>
|
||||||
|
|
||||||
|
<MyAssemblyPolicyVersion>$(MyCanonicalVersion.Substring(0,$(MyVersion.IndexOf('.')))).0</MyAssemblyPolicyVersion>
|
||||||
|
<MyAssemblyVersion>$(MyAssemblyPolicyVersion).0.0</MyAssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
|
@ -53,146 +53,238 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fscrash", "testing\fscrash.
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsbench", "testing\fsbench.vcxproj", "{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsbench", "testing\fsbench.vcxproj", "{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winfsp.net", "dotnet\winfsp.net.csproj", "{94580219-CC8D-4FE5-A3BE-437B0B3481E1}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB} = {4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332} = {C85C26BA-8C22-4D30-83DA-46C3548E6332}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{A998CEC4-4B34-43DC-8457-F7761228BA67}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "memfs-dotnet", "testing\memfs-dotnet.csproj", "{4920E350-D496-4652-AE98-6C4208AEC1D8}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
Installer.Debug|Any CPU = Installer.Debug|Any CPU
|
||||||
Installer.Debug|x64 = Installer.Debug|x64
|
Installer.Debug|x64 = Installer.Debug|x64
|
||||||
Installer.Debug|x86 = Installer.Debug|x86
|
Installer.Debug|x86 = Installer.Debug|x86
|
||||||
|
Installer.Release|Any CPU = Installer.Release|Any CPU
|
||||||
Installer.Release|x64 = Installer.Release|x64
|
Installer.Release|x64 = Installer.Release|x64
|
||||||
Installer.Release|x86 = Installer.Release|x86
|
Installer.Release|x86 = Installer.Release|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.ActiveCfg = Debug|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.Build.0 = Debug|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.Build.0 = Debug|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.ActiveCfg = Debug|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.Build.0 = Debug|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x64.ActiveCfg = Release|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.ActiveCfg = Release|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.Build.0 = Release|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.Build.0 = Release|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.ActiveCfg = Release|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.Build.0 = Release|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.ActiveCfg = Debug|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.Build.0 = Debug|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.Build.0 = Debug|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.ActiveCfg = Debug|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.Build.0 = Debug|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x64.ActiveCfg = Release|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.ActiveCfg = Release|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.Build.0 = Release|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.Build.0 = Release|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.ActiveCfg = Release|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.Build.0 = Release|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.ActiveCfg = Debug|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.Build.0 = Debug|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.Build.0 = Debug|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.ActiveCfg = Debug|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.Build.0 = Debug|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x64.ActiveCfg = Release|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.ActiveCfg = Release|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.ActiveCfg = Release|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.Build.0 = Release|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.Build.0 = Release|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.ActiveCfg = Release|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.Build.0 = Release|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.ActiveCfg = Debug|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.Build.0 = Debug|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.Build.0 = Debug|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.ActiveCfg = Debug|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.Build.0 = Debug|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x64.ActiveCfg = Release|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.ActiveCfg = Release|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.Build.0 = Release|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.Build.0 = Release|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.ActiveCfg = Release|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.Build.0 = Release|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x64.ActiveCfg = Debug|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x64.ActiveCfg = Debug|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x86.ActiveCfg = Debug|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|Any CPU.ActiveCfg = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|Any CPU.Build.0 = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.ActiveCfg = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.ActiveCfg = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.Build.0 = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.Build.0 = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.ActiveCfg = Debug|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.Build.0 = Debug|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|Any CPU.Build.0 = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.ActiveCfg = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.ActiveCfg = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.Build.0 = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.Build.0 = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.ActiveCfg = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.ActiveCfg = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.Build.0 = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.Build.0 = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x64.ActiveCfg = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x64.ActiveCfg = Release|x86
|
||||||
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x86.ActiveCfg = Release|x86
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x64.ActiveCfg = Debug|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x64.ActiveCfg = Debug|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x86.ActiveCfg = Debug|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|Any CPU.Build.0 = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.ActiveCfg = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.ActiveCfg = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.Build.0 = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.Build.0 = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.Build.0 = Debug|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|Any CPU.Build.0 = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.ActiveCfg = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.ActiveCfg = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.Build.0 = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.Build.0 = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.Build.0 = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.Build.0 = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x64.ActiveCfg = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x64.ActiveCfg = Release|Win32
|
||||||
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x86.ActiveCfg = Release|Win32
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.ActiveCfg = Debug|x64
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.Build.0 = Debug|x64
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.Build.0 = Debug|x64
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.ActiveCfg = Debug|Win32
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.Build.0 = Debug|Win32
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x64.ActiveCfg = Release|x64
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.ActiveCfg = Release|x64
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.ActiveCfg = Release|x64
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.Build.0 = Release|x64
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.Build.0 = Release|x64
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.ActiveCfg = Release|Win32
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.Build.0 = Release|Win32
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.ActiveCfg = Debug|x64
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.Build.0 = Debug|x64
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.Build.0 = Debug|x64
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.ActiveCfg = Debug|Win32
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.Build.0 = Debug|Win32
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x64.ActiveCfg = Release|x64
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.ActiveCfg = Release|x64
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.ActiveCfg = Release|x64
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.Build.0 = Release|x64
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.Build.0 = Release|x64
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.ActiveCfg = Release|Win32
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.Build.0 = Release|Win32
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{10757011-749D-4954-873B-AE38D8145472}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x64.ActiveCfg = Debug|x64
|
{10757011-749D-4954-873B-AE38D8145472}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x64.Build.0 = Debug|x64
|
{10757011-749D-4954-873B-AE38D8145472}.Debug|x64.Build.0 = Debug|x64
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x86.ActiveCfg = Debug|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Debug|x86.Build.0 = Debug|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Debug|x86.Build.0 = Debug|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x64.ActiveCfg = Release|x64
|
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x64.Build.0 = Release|x64
|
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Installer.Release|x86.Build.0 = Release|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x64.ActiveCfg = Release|x64
|
{10757011-749D-4954-873B-AE38D8145472}.Release|x64.ActiveCfg = Release|x64
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x64.Build.0 = Release|x64
|
{10757011-749D-4954-873B-AE38D8145472}.Release|x64.Build.0 = Release|x64
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x86.ActiveCfg = Release|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{10757011-749D-4954-873B-AE38D8145472}.Release|x86.Build.0 = Release|Win32
|
{10757011-749D-4954-873B-AE38D8145472}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x64.ActiveCfg = Debug|x64
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x64.Build.0 = Debug|x64
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x64.Build.0 = Debug|x64
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x86.ActiveCfg = Debug|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x86.Build.0 = Debug|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|Any CPU.ActiveCfg = Release|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Debug|x86.Build.0 = Debug|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x64.ActiveCfg = Release|x64
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x64.Build.0 = Release|x64
|
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Installer.Release|x86.Build.0 = Release|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x64.ActiveCfg = Release|x64
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x64.Build.0 = Release|x64
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x64.Build.0 = Release|x64
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x86.ActiveCfg = Release|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x86.Build.0 = Release|Win32
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Installer.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Installer.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -206,5 +298,7 @@ Global
|
|||||||
{73EAAEDA-557B-48D5-A137-328934720FB4} = {FD28A504-431E-49B9-BB8C-DCA0E7019F66}
|
{73EAAEDA-557B-48D5-A137-328934720FB4} = {FD28A504-431E-49B9-BB8C-DCA0E7019F66}
|
||||||
{10757011-749D-4954-873B-AE38D8145472} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
{10757011-749D-4954-873B-AE38D8145472} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||||
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
{C4E1E9E5-0959-488E-8C6A-C327CC81BEFB} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||||
|
{94580219-CC8D-4FE5-A3BE-437B0B3481E1} = {A998CEC4-4B34-43DC-8457-F7761228BA67}
|
||||||
|
{4920E350-D496-4652-AE98-6C4208AEC1D8} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -26,13 +26,16 @@
|
|||||||
<ClInclude Include="..\..\inc\fuse\winfsp_fuse.h" />
|
<ClInclude Include="..\..\inc\fuse\winfsp_fuse.h" />
|
||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||||
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
||||||
|
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp" />
|
||||||
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
||||||
<ClInclude Include="..\..\src\dll\library.h" />
|
<ClInclude Include="..\..\src\dll\library.h" />
|
||||||
<ClInclude Include="..\..\src\shared\minimal.h" />
|
<ClInclude Include="..\..\src\shared\minimal.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\src\dll\dirbuf.c" />
|
||||||
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse.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_intf.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||||
@ -50,7 +53,7 @@
|
|||||||
<ClCompile Include="..\..\src\dll\util.c" />
|
<ClCompile Include="..\..\src\dll\util.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc">
|
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
||||||
<FileType>Document</FileType>
|
<FileType>Document</FileType>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse-$(PlatformTarget).pc
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse-$(PlatformTarget).pc
|
||||||
copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(PlatformTarget).pc >nul</Command>
|
copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(PlatformTarget).pc >nul</Command>
|
||||||
|
@ -50,6 +50,9 @@
|
|||||||
<ClInclude Include="..\..\src\dll\fuse\library.h">
|
<ClInclude Include="..\..\src\dll\fuse\library.h">
|
||||||
<Filter>Source\fuse</Filter>
|
<Filter>Source\fuse</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp">
|
||||||
|
<Filter>Include\winfsp</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\dll\library.c">
|
<ClCompile Include="..\..\src\dll\library.c">
|
||||||
@ -103,6 +106,12 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c">
|
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c">
|
||||||
<Filter>Source\fuse</Filter>
|
<Filter>Source\fuse</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\dirbuf.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c">
|
||||||
|
<Filter>Source\fuse</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\library.def">
|
<None Include="..\..\src\dll\library.def">
|
||||||
@ -118,7 +127,7 @@
|
|||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc">
|
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
||||||
<Filter>Source\fuse</Filter>
|
<Filter>Source\fuse</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -174,6 +174,7 @@
|
|||||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||||
<ClCompile Include="..\..\src\sys\name.c" />
|
<ClCompile Include="..\..\src\sys\name.c" />
|
||||||
|
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||||
<ClCompile Include="..\..\src\sys\read.c" />
|
<ClCompile Include="..\..\src\sys\read.c" />
|
||||||
<ClCompile Include="..\..\src\sys\security.c" />
|
<ClCompile Include="..\..\src\sys\security.c" />
|
||||||
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
||||||
|
@ -98,6 +98,9 @@
|
|||||||
<ClCompile Include="..\..\src\sys\statistics.c">
|
<ClCompile Include="..\..\src\sys\statistics.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\sys\psbuffer.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\sys\driver.h">
|
<ClInclude Include="..\..\src\sys\driver.h">
|
||||||
@ -113,8 +116,8 @@
|
|||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\sys\driver.inf.in">
|
<CustomBuild Include="..\..\src\sys\driver.inf.in">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</None>
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
4
build/choco/LICENSE.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
From: https://github.com/billziss-gh/winfsp/blob/master/License.txt
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
|
15
build/choco/VERIFICATION.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
VERIFICATION
|
||||||
|
Verification is intended to assist the Chocolatey moderators and community
|
||||||
|
in verifying that this package's contents are trustworthy.
|
||||||
|
|
||||||
|
WinFsp GitHub repository: https://github.com/billziss-gh/winfsp
|
||||||
|
WinFsp MSI releases : https://github.com/billziss-gh/winfsp/releases
|
||||||
|
|
||||||
|
You may use the Windows certutil utility to confirm the hash of the MSI
|
||||||
|
included in this package against the WinFsp MSI release of the same version.
|
||||||
|
For example, for WinFsp version 1.0.17072 the command line to use is:
|
||||||
|
|
||||||
|
certutil -hashfile winfsp-1.0.17072.msi SHA256
|
||||||
|
|
||||||
|
The certutil output of the MSI in this package is included below.
|
||||||
|
|
36
build/choco/chocolateyBeforeModify.ps1
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
$ErrorActionPreference = 'Stop';
|
||||||
|
|
||||||
|
$packageName = 'winfsp'
|
||||||
|
$softwareName = 'WinFsp*'
|
||||||
|
$installerType = 'msi'
|
||||||
|
$silentArgs = '/qn /norestart'
|
||||||
|
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
|
||||||
|
|
||||||
|
[array]$key = Get-UninstallRegistryKey -SoftwareName $softwareName
|
||||||
|
|
||||||
|
if ($key.Count -eq 1) {
|
||||||
|
$key | % {
|
||||||
|
# The Product Code GUID is all that should be passed for MSI, and very
|
||||||
|
# FIRST, because it comes directly after /x, which is already set in the
|
||||||
|
# Uninstall-ChocolateyPackage msiargs (facepalm).
|
||||||
|
$silentArgs = "$($_.PSChildName) $silentArgs"
|
||||||
|
|
||||||
|
# Don't pass anything for file, it is ignored for msi (facepalm number 2)
|
||||||
|
# Alternatively if you need to pass a path to an msi, determine that and
|
||||||
|
# use it instead of the above in silentArgs, still very first
|
||||||
|
$file = ''
|
||||||
|
|
||||||
|
Uninstall-ChocolateyPackage `
|
||||||
|
-PackageName $packageName `
|
||||||
|
-FileType $installerType `
|
||||||
|
-SilentArgs "$silentArgs" `
|
||||||
|
-ValidExitCodes $validExitCodes `
|
||||||
|
-File "$file"
|
||||||
|
}
|
||||||
|
} elseif ($key.Count -eq 0) {
|
||||||
|
Write-Warning "$packageName has already been uninstalled by other means."
|
||||||
|
} elseif ($key.Count -gt 1) {
|
||||||
|
Write-Warning "Too many matching packages found! Package may not be uninstalled."
|
||||||
|
Write-Warning "Please alert package maintainer the following packages were matched:"
|
||||||
|
$key | % {Write-Warning "- $_"}
|
||||||
|
}
|
16
build/choco/chocolateyInstall.ps1
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
$ErrorActionPreference = 'Stop';
|
||||||
|
|
||||||
|
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||||
|
$fileLocation = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||||
|
|
||||||
|
$packageArgs = @{
|
||||||
|
packageName = 'winfsp'
|
||||||
|
fileType = 'msi'
|
||||||
|
file = $fileLocation
|
||||||
|
silentArgs = "/qn /norestart INSTALLLEVEL=1000"
|
||||||
|
validExitCodes = @(0, 3010, 1641)
|
||||||
|
}
|
||||||
|
|
||||||
|
Install-ChocolateyInstallPackage @packageArgs
|
||||||
|
|
||||||
|
Remove-Item -Force $packageArgs.file
|
56
build/choco/winfsp.nuspec
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>winfsp</id>
|
||||||
|
<version>$version$</version>
|
||||||
|
<packageSourceUrl>https://github.com/billziss-gh/winfsp/tree/master/build/choco</packageSourceUrl>
|
||||||
|
<owners>Bill Zissimopoulos</owners>
|
||||||
|
|
||||||
|
<title>WinFsp</title>
|
||||||
|
<authors>Bill Zissimopoulos</authors>
|
||||||
|
<projectUrl>https://github.com/billziss-gh/winfsp</projectUrl>
|
||||||
|
<iconUrl>https://github.com/billziss-gh/winfsp/raw/master/art/winfsp-solid.png</iconUrl>
|
||||||
|
<copyright>Bill Zissimopoulos</copyright>
|
||||||
|
<licenseUrl>https://github.com/billziss-gh/winfsp/blob/master/License.txt</licenseUrl>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<projectSourceUrl>https://github.com/billziss-gh/winfsp</projectSourceUrl>
|
||||||
|
<docsUrl>https://github.com/billziss-gh/winfsp/tree/master/doc</docsUrl>
|
||||||
|
<mailingListUrl>https://groups.google.com/forum/#!forum/winfsp</mailingListUrl>
|
||||||
|
<bugTrackerUrl>https://github.com/billziss-gh/winfsp/issues</bugTrackerUrl>
|
||||||
|
<tags>driver filesystem fuse gplv3 windows-kernel admin</tags>
|
||||||
|
<summary>Windows File System Proxy - FUSE for Windows</summary>
|
||||||
|
<description>
|
||||||
|
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.
|
||||||
|
|
||||||
|
Some of the benefits of using WinFsp are listed below:
|
||||||
|
|
||||||
|
* Very well-tested and stable.
|
||||||
|
* Very fast.
|
||||||
|
* Strives for compatibility with NTFS.
|
||||||
|
* Easy to understand but comprehensive API.
|
||||||
|
* FUSE compatibility layer for native Windows and Cygwin.
|
||||||
|
* Signed drivers provided on every release.
|
||||||
|
* Available under the GPLv3 license with a special exception for Free/Libre and Open Source Software.
|
||||||
|
|
||||||
|
To verify installation:
|
||||||
|
|
||||||
|
* For 64-bit Windows: `net use m: \\memfs64\share` from the command prompt.
|
||||||
|
* For 32-bit Windows: `net use m: \\memfs32\share`
|
||||||
|
* For Cygwin: `net use m: '\\memfs64\share'`
|
||||||
|
* To delete the drive: `net use m: /delete`
|
||||||
|
</description>
|
||||||
|
<releaseNotes>https://github.com/billziss-gh/winfsp/blob/master/Changelog.asciidoc</releaseNotes>
|
||||||
|
|
||||||
|
<!--<dependencies>
|
||||||
|
<dependency id="chocolatey-uninstall.extension" />
|
||||||
|
</dependencies>-->
|
||||||
|
</metadata>
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file src="LICENSE.txt" target="tools" />
|
||||||
|
<file src="VERIFICATION.txt" target="tools" />
|
||||||
|
<file src="chocolateyInstall.ps1" target="tools" />
|
||||||
|
<file src="chocolateyBeforeModify.ps1" target="tools" />
|
||||||
|
<file src="winfsp-$version$.msi" target="tools" />
|
||||||
|
</files>
|
||||||
|
</package>
|
51
doc/Frequently-Asked-Questions.asciidoc
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
= Frequently Asked Questions
|
||||||
|
|
||||||
|
== General
|
||||||
|
|
||||||
|
[qanda]
|
||||||
|
|
||||||
|
I am running Windows 7 and I am finding that the installed driver is not signed. [@efeat]::
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
Why is the DLL not installed in the Windows system directories? [@netheril96]::
|
||||||
|
|
||||||
|
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]::
|
||||||
|
|
||||||
|
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]::
|
||||||
|
|
||||||
|
WinFsp does not have a hard limit of how many file systems can be created or how many processes can create file systems.
|
||||||
|
+
|
||||||
|
As of the commits required to fix issue #55, there is however a hash table inside the FSD that uses PID's (Process ID's) as keys. This hash table currently expects that in general there will not be more than 50 processes creating file systems. However this is not a hard limit.
|
||||||
|
|
||||||
|
|
||||||
|
== FUSE
|
||||||
|
|
||||||
|
[qanda]
|
||||||
|
|
||||||
|
Which version of FUSE does WinFsp-FUSE support?::
|
||||||
|
|
||||||
|
Currently it supports FUSE 2.8.
|
||||||
|
|
||||||
|
|
||||||
|
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]::
|
||||||
|
|
||||||
|
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.
|
||||||
|
+
|
||||||
|
When mounting over directories in Windows, WinFsp-FUSE uses a special construct called a reparse point. Reparse points are a general mechanism for adding special behavior to files and directories. One of the possible reparse points is the "mountpoint" reparse point (often called "junction"), which converts a directory into a mount point.
|
||||||
|
+
|
||||||
|
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.
|
32
doc/Home.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# WinFsp - Windows File System Proxy
|
||||||
|
|
||||||
|
[[WinFsp-Icon.png]]
|
||||||
|
|
||||||
|
Developing file systems is a challenging proposition. Developing file systems for Windows is an order of magnitude more difficult. WinFsp eases the task of writing a new file system for Windows. WinFsp file systems are user mode programs and they can be written in a variety of languages and frameworks.
|
||||||
|
|
||||||
|
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.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
## Design
|
||||||
|
|
||||||
|
- The [[Design|WinFsp-Design]] document describes the high-level design of WinFsp.
|
||||||
|
- The [[IPC|WinFsp-as-an-IPC-Mechanism]] document offers insights into the WinFsp Inter-Process Communication mechanism.
|
||||||
|
- The [[Service Architecture|WinFsp-Service-Architecture]] document discusses how to intergrate a file system into Windows as a service and the reasons to do so.
|
||||||
|
- The [[SSHFS Port Case Study|SSHFS-Port-Case-Study]] document chronicles the creation of the WinFsp-FUSE compatibility layer and the decisions that led to its design.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- The [[Testing|WinFsp-Testing]] document discusses the WinFsp testing strategy and how WinFsp achieves correctness and stability.
|
||||||
|
- The [[Performance|WinFsp-Performance-Testing]] document compares WinFsp performance against other file systems.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
- The [[Compatibility|NTFS-Compatibility]] document discusses current WinFsp compatibility with NTFS.
|
||||||
|
|
||||||
|
WinFsp is available under the GPLv3 license with a special exception for Free/Libre and Open Source Software.
|
18
doc/Known-File-Systems.asciidoc
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
= Known File Systems and File System Libraries
|
||||||
|
|
||||||
|
This document contains a list of known file systems and file system libraries that run on WinFsp. Please contact the WinFsp project to have your file system solution added to this list.
|
||||||
|
|
||||||
|
== File Systems
|
||||||
|
|
||||||
|
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
||||||
|
- https://github.com/billziss-gh/redditfs[redditfs] - ls -l /r/programming
|
||||||
|
- https://github.com/netheril96/securefs[securefs] - Filesystem in userspace (FUSE) with transparent authenticated encryption
|
||||||
|
- https://github.com/billziss-gh/sshfs-win[sshfs-win] - SSHFS for Windows
|
||||||
|
|
||||||
|
== File System Libraries
|
||||||
|
|
||||||
|
- https://github.com/billziss-gh/cgofuse[cgofuse] - Cross-platform FUSE library for Go
|
||||||
|
- https://github.com/DuroSoft/fuse-bindings[fuse-bindings] - Fully maintained FUSE bindings for Node that aims to cover the entire FUSE api
|
||||||
|
- https://github.com/ui4j/fuse-jna[fuse-jna] - No-nonsense, actually-working Java bindings to FUSE using JNA
|
||||||
|
- https://github.com/billziss-gh/fusepy[fusepy] - Simple ctypes bindings for FUSE
|
||||||
|
- https://github.com/yogendersolanki91/winfsp[WinFsp fork with .NET Layer] - by @yogendersolanki91
|
BIN
doc/WinFsp-Icon.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
@ -20,19 +20,21 @@ In order to overcome the issue with launching multiple instances of a particular
|
|||||||
|
|
||||||
Services that wish to be controlled by the WinFsp.Launcher must add themselves under the following registry key:
|
Services that wish to be controlled by the WinFsp.Launcher must add themselves under the following registry key:
|
||||||
|
|
||||||
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services
|
HKEY_LOCAL_MACHINE\Software\WinFsp\Services
|
||||||
|
|
||||||
For example, the MEMFS sample adds the following registry entries under this key:
|
NOTE: Please note that in a 64-bit system the actual location is `HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services`.
|
||||||
|
|
||||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services\memfs32]
|
For example, the MEMFS sample adds the following registry entries in a 64-bit system:
|
||||||
|
|
||||||
|
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services\memfs32]
|
||||||
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x86.exe"
|
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x86.exe"
|
||||||
"CommandLine"="-u %1 -m %2"
|
"CommandLine"="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2"
|
||||||
"Security"="D:P(A;;RPWPLC;;;WD)"
|
"Security"="D:P(A;;RPWPLC;;;WD)"
|
||||||
"JobControl"=dword:00000001
|
"JobControl"=dword:00000001
|
||||||
|
|
||||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services\memfs64]
|
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\WinFsp\Services\memfs64]
|
||||||
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x64.exe"
|
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x64.exe"
|
||||||
"CommandLine"="-u %1 -m %2"
|
"CommandLine"="-i -F NTFS -n 65536 -s 67108864 -u %1 -m %2"
|
||||||
"Security"="D:P(A;;RPWPLC;;;WD)"
|
"Security"="D:P(A;;RPWPLC;;;WD)"
|
||||||
"JobControl"=dword:00000001
|
"JobControl"=dword:00000001
|
||||||
|
|
||||||
@ -44,4 +46,4 @@ One final note regarding security. Notice the `Security` registry value in the e
|
|||||||
|
|
||||||
WinFsp includes a Network Provider that integrates with Windows and can be used to start and stop user mode file systems from the Windows shell. To achieve this the Network Provider (implemented as part of the WinFsp DLL) works closely with the WinFsp.Launcher service.
|
WinFsp includes a Network Provider that integrates with Windows and can be used to start and stop user mode file systems from the Windows shell. To achieve this the Network Provider (implemented as part of the WinFsp DLL) works closely with the WinFsp.Launcher service.
|
||||||
|
|
||||||
For example, if a user uses the Windows Explorer to map `\\memfs64\share` to the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to start an instance of the memfs64 service with command line `-u \\memfs64\share -m Z:`. When the user disconnects the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to stop the previously started instance of the memfs64 service.
|
For example, if a user uses the Windows Explorer to map `\\memfs64\share` to the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to start an instance of the memfs64 service with command line `-i -F NTFS -n 65536 -s 67108864 -u \\memfs64\share -m Z:`. When the user disconnects the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to stop the previously started instance of the memfs64 service.
|
||||||
|
1326
doc/WinFsp-Tutorial.asciidoc
Normal file
BIN
doc/WinFsp-Tutorial/EntryExit.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
doc/WinFsp-Tutorial/Explorer.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
doc/WinFsp-Tutorial/FirstRun.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
doc/WinFsp-Tutorial/Installer.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
doc/WinFsp-Tutorial/MissingDll.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
doc/WinFsp-Tutorial/NetUse.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
doc/WinFsp-Tutorial/NewProject.png
Normal file
After Width: | Height: | Size: 20 KiB |
1741
doc/winfsp.h.asciidoc
Normal file
@ -41,6 +41,15 @@ extern "C" {
|
|||||||
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
||||||
#define FUSE_CAP_BIG_WRITES (1 << 5)
|
#define FUSE_CAP_BIG_WRITES (1 << 5)
|
||||||
#define FUSE_CAP_DONT_MASK (1 << 6)
|
#define FUSE_CAP_DONT_MASK (1 << 6)
|
||||||
|
#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_READDIR_PLUS (1 << 21) /* file system supports enhanced readdir */
|
||||||
|
#define FSP_FUSE_CAP_READ_ONLY (1 << 22) /* file system is marked read-only */
|
||||||
|
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
|
||||||
|
|
||||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||||
|
@ -177,6 +177,7 @@ struct fuse_flock
|
|||||||
MemAlloc, MemFree, \
|
MemAlloc, MemFree, \
|
||||||
fsp_fuse_daemonize, \
|
fsp_fuse_daemonize, \
|
||||||
fsp_fuse_set_signal_handlers, \
|
fsp_fuse_set_signal_handlers, \
|
||||||
|
0/*conv_to_win_path*/, \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define FSP_FUSE_ENV_INIT \
|
#define FSP_FUSE_ENV_INIT \
|
||||||
@ -185,6 +186,7 @@ struct fuse_flock
|
|||||||
malloc, free, \
|
malloc, free, \
|
||||||
fsp_fuse_daemonize, \
|
fsp_fuse_daemonize, \
|
||||||
fsp_fuse_set_signal_handlers, \
|
fsp_fuse_set_signal_handlers, \
|
||||||
|
0/*conv_to_win_path*/, \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -226,6 +228,7 @@ struct fuse_flock
|
|||||||
malloc, free, \
|
malloc, free, \
|
||||||
fsp_fuse_daemonize, \
|
fsp_fuse_daemonize, \
|
||||||
fsp_fuse_set_signal_handlers, \
|
fsp_fuse_set_signal_handlers, \
|
||||||
|
fsp_fuse_conv_to_win_path, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -244,7 +247,8 @@ struct fsp_fuse_env
|
|||||||
void (*memfree)(void *);
|
void (*memfree)(void *);
|
||||||
int (*daemonize)(int);
|
int (*daemonize)(int);
|
||||||
int (*set_signal_handlers)(void *);
|
int (*set_signal_handlers)(void *);
|
||||||
void (*reserved[4])();
|
char *(*conv_to_win_path)(const char *);
|
||||||
|
void (*reserved[3])();
|
||||||
};
|
};
|
||||||
|
|
||||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
||||||
@ -348,6 +352,13 @@ static inline int fsp_fuse_set_signal_handlers(void *se)
|
|||||||
#undef FSP_FUSE_SET_SIGNAL_HANDLER
|
#undef FSP_FUSE_SET_SIGNAL_HANDLER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char *fsp_fuse_conv_to_win_path(const char *path)
|
||||||
|
{
|
||||||
|
void *cygwin_create_path(unsigned, const void *);
|
||||||
|
return cygwin_create_path(
|
||||||
|
0/*CCP_POSIX_TO_WIN_A*/ | 0x100/*CCP_RELATIVE*/,
|
||||||
|
path);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,7 +147,9 @@ typedef struct
|
|||||||
UINT32 ReadOnlyVolume:1;
|
UINT32 ReadOnlyVolume:1;
|
||||||
/* kernel-mode flags */
|
/* kernel-mode flags */
|
||||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
||||||
UINT32 KmReservedFlags:5;
|
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */
|
||||||
|
UINT32 AlwaysUseDoubleBuffering:1;
|
||||||
|
UINT32 KmReservedFlags:3;
|
||||||
/* user-mode flags */
|
/* user-mode flags */
|
||||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
||||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
|
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
|
||||||
@ -185,8 +187,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
UINT16 Size;
|
UINT16 Size;
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
UINT64 NextOffset;
|
UINT8 Padding[24];
|
||||||
UINT8 Padding[16];
|
|
||||||
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
|
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
|
||||||
WCHAR FileNameBuf[];
|
WCHAR FileNameBuf[];
|
||||||
} FSP_FSCTL_DIR_INFO;
|
} FSP_FSCTL_DIR_INFO;
|
||||||
@ -339,9 +340,9 @@ typedef struct
|
|||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
UINT64 Address;
|
UINT64 Address;
|
||||||
UINT64 Offset;
|
|
||||||
UINT32 Length;
|
UINT32 Length;
|
||||||
FSP_FSCTL_TRANSACT_BUF Pattern;
|
FSP_FSCTL_TRANSACT_BUF Pattern;
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Marker;
|
||||||
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
||||||
} QueryDirectory;
|
} QueryDirectory;
|
||||||
struct
|
struct
|
||||||
|
@ -26,7 +26,10 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef WIN32_NO_STATUS
|
#undef WIN32_NO_STATUS
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4005) /* macro redefinition */
|
||||||
#include <ntstatus.h>
|
#include <ntstatus.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
#if defined(WINFSP_DLL_INTERNAL)
|
#if defined(WINFSP_DLL_INTERNAL)
|
||||||
#define FSP_API __declspec(dllexport)
|
#define FSP_API __declspec(dllexport)
|
||||||
@ -647,30 +650,18 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* The file system on which this request is posted.
|
* The file system on which this request is posted.
|
||||||
* @param FileContext
|
* @param FileContext
|
||||||
* The file context of the directory to be read.
|
* The file context of the directory to be read.
|
||||||
* @param Buffer
|
|
||||||
* Pointer to a buffer that will receive the results of the read operation.
|
|
||||||
* @param Offset
|
|
||||||
* Offset within the directory to read from. The kernel does not interpret this value
|
|
||||||
* which is used solely by the file system to locate directory entries. However the
|
|
||||||
* special value 0 indicates that the read should start from the first entries. The first
|
|
||||||
* two entries returned by ReadDirectory should always be the "." and ".." entries,
|
|
||||||
* except for the root directory which does not have these entries.
|
|
||||||
*
|
|
||||||
* This parameter is used by the WinFsp FSD to break directory listings into chunks.
|
|
||||||
* In this case all 64-bits of the Offset are valid. In some cases the Windows kernel
|
|
||||||
* (NTOS) may also use this parameter. In this case only the lower 32-bits of this
|
|
||||||
* parameter will be valid. This is an unfortunate limitation of Windows (for more
|
|
||||||
* information see the documentation for IRP_MJ_DIRECTORY_CONTROL and the flag
|
|
||||||
* SL_INDEX_SPECIFIED).
|
|
||||||
*
|
|
||||||
* In practice this means that you should only rely on the lower 32-bits of this value
|
|
||||||
* to be valid.
|
|
||||||
* @param Length
|
|
||||||
* Length of data to read.
|
|
||||||
* @param Pattern
|
* @param Pattern
|
||||||
* The pattern to match against files in this directory. Can be NULL. The file system
|
* The pattern to match against files in this directory. Can be NULL. The file system
|
||||||
* can choose to ignore this parameter as the FSD will always perform its own pattern
|
* can choose to ignore this parameter as the FSD will always perform its own pattern
|
||||||
* matching on the returned results.
|
* matching on the returned results.
|
||||||
|
* @param Marker
|
||||||
|
* A file name that marks where in the directory to start reading. Files with names
|
||||||
|
* that are greater than (not equal to) this marker (in the directory order determined
|
||||||
|
* by the file system) should be returned. Can be NULL.
|
||||||
|
* @param Buffer
|
||||||
|
* Pointer to a buffer that will receive the results of the read operation.
|
||||||
|
* @param Length
|
||||||
|
* Length of data to read.
|
||||||
* @param PBytesTransferred [out]
|
* @param PBytesTransferred [out]
|
||||||
* Pointer to a memory location that will receive the actual number of bytes read.
|
* Pointer to a memory location that will receive the actual number of bytes read.
|
||||||
* @return
|
* @return
|
||||||
@ -680,9 +671,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* FspFileSystemAddDirInfo
|
* FspFileSystemAddDirInfo
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*ReadDirectory)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*ReadDirectory)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length,
|
PVOID FileContext, PWSTR Pattern, PWSTR Marker,
|
||||||
PWSTR Pattern,
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
PULONG PBytesTransferred);
|
|
||||||
/**
|
/**
|
||||||
* Resolve reparse points.
|
* Resolve reparse points.
|
||||||
*
|
*
|
||||||
@ -845,6 +835,20 @@ typedef struct _FSP_FILE_SYSTEM_OPERATION_CONTEXT
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response;
|
FSP_FSCTL_TRANSACT_RSP *Response;
|
||||||
} FSP_FILE_SYSTEM_OPERATION_CONTEXT;
|
} FSP_FILE_SYSTEM_OPERATION_CONTEXT;
|
||||||
|
/**
|
||||||
|
* Check whether creating a file system object is possible.
|
||||||
|
*
|
||||||
|
* @param DevicePath
|
||||||
|
* The name of the control device for this file system. This must be either
|
||||||
|
* FSP_FSCTL_DISK_DEVICE_NAME or FSP_FSCTL_NET_DEVICE_NAME.
|
||||||
|
* @param MountPoint
|
||||||
|
* The mount point for the new file system. A value of NULL means that the file system should
|
||||||
|
* use the next available drive letter counting downwards from Z: as its mount point.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
|
||||||
|
PWSTR MountPoint);
|
||||||
/**
|
/**
|
||||||
* Create a file system object.
|
* Create a file system object.
|
||||||
*
|
*
|
||||||
@ -892,6 +896,8 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem);
|
|||||||
* STATUS_SUCCESS or error code.
|
* STATUS_SUCCESS or error code.
|
||||||
*/
|
*/
|
||||||
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint);
|
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint);
|
||||||
|
FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||||
/**
|
/**
|
||||||
* Remove the mount point for a file system.
|
* Remove the mount point for a file system.
|
||||||
*
|
*
|
||||||
@ -955,11 +961,14 @@ FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
* The current operation context.
|
* The current operation context.
|
||||||
*/
|
*/
|
||||||
FSP_API FSP_FILE_SYSTEM_OPERATION_CONTEXT *FspFileSystemGetOperationContext(VOID);
|
FSP_API FSP_FILE_SYSTEM_OPERATION_CONTEXT *FspFileSystemGetOperationContext(VOID);
|
||||||
|
FSP_API PWSTR FspFileSystemMountPointF(FSP_FILE_SYSTEM *FileSystem);
|
||||||
static inline
|
static inline
|
||||||
PWSTR FspFileSystemMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
PWSTR FspFileSystemMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
||||||
{
|
{
|
||||||
return FileSystem->MountPoint;
|
return FileSystem->MountPoint;
|
||||||
}
|
}
|
||||||
|
FSP_API NTSTATUS FspFileSystemEnterOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
static inline
|
static inline
|
||||||
NTSTATUS FspFileSystemEnterOperation(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS FspFileSystemEnterOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
@ -969,6 +978,8 @@ NTSTATUS FspFileSystemEnterOperation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
return FileSystem->EnterOperation(FileSystem, Request, Response);
|
return FileSystem->EnterOperation(FileSystem, Request, Response);
|
||||||
}
|
}
|
||||||
|
FSP_API NTSTATUS FspFileSystemLeaveOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
static inline
|
static inline
|
||||||
NTSTATUS FspFileSystemLeaveOperation(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS FspFileSystemLeaveOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
@ -978,6 +989,9 @@ NTSTATUS FspFileSystemLeaveOperation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
return FileSystem->LeaveOperation(FileSystem, Request, Response);
|
return FileSystem->LeaveOperation(FileSystem, Request, Response);
|
||||||
}
|
}
|
||||||
|
FSP_API VOID FspFileSystemSetOperationGuardF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION_GUARD *LeaveOperation);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileSystemSetOperationGuard(FSP_FILE_SYSTEM *FileSystem,
|
VOID FspFileSystemSetOperationGuard(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
||||||
@ -996,12 +1010,17 @@ VOID FspFileSystemSetOperationGuard(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
* @see
|
* @see
|
||||||
* FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY
|
* FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY
|
||||||
*/
|
*/
|
||||||
|
FSP_API VOID FspFileSystemSetOperationGuardStrategyF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileSystemSetOperationGuardStrategy(FSP_FILE_SYSTEM *FileSystem,
|
VOID FspFileSystemSetOperationGuardStrategy(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy)
|
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy)
|
||||||
{
|
{
|
||||||
FileSystem->OpGuardStrategy = GuardStrategy;
|
FileSystem->OpGuardStrategy = GuardStrategy;
|
||||||
}
|
}
|
||||||
|
FSP_API VOID FspFileSystemSetOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
ULONG Index,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION *Operation);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileSystemSetOperation(FSP_FILE_SYSTEM *FileSystem,
|
VOID FspFileSystemSetOperation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
ULONG Index,
|
ULONG Index,
|
||||||
@ -1009,6 +1028,8 @@ VOID FspFileSystemSetOperation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
FileSystem->Operations[Index] = Operation;
|
FileSystem->Operations[Index] = Operation;
|
||||||
}
|
}
|
||||||
|
FSP_API VOID FspFileSystemGetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS *PDispatcherResult);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileSystemGetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
VOID FspFileSystemGetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
||||||
NTSTATUS *PDispatcherResult)
|
NTSTATUS *PDispatcherResult)
|
||||||
@ -1017,6 +1038,8 @@ VOID FspFileSystemGetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
*PDispatcherResult = FileSystem->DispatcherResult;
|
*PDispatcherResult = FileSystem->DispatcherResult;
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
}
|
}
|
||||||
|
FSP_API VOID FspFileSystemSetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS DispatcherResult);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileSystemSetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
VOID FspFileSystemSetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
||||||
NTSTATUS DispatcherResult)
|
NTSTATUS DispatcherResult)
|
||||||
@ -1025,12 +1048,15 @@ VOID FspFileSystemSetDispatcherResult(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return;
|
return;
|
||||||
InterlockedCompareExchange(&FileSystem->DispatcherResult, DispatcherResult, 0);
|
InterlockedCompareExchange(&FileSystem->DispatcherResult, DispatcherResult, 0);
|
||||||
}
|
}
|
||||||
|
FSP_API VOID FspFileSystemSetDebugLogF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
UINT32 DebugLog);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileSystemSetDebugLog(FSP_FILE_SYSTEM *FileSystem,
|
VOID FspFileSystemSetDebugLog(FSP_FILE_SYSTEM *FileSystem,
|
||||||
UINT32 DebugLog)
|
UINT32 DebugLog)
|
||||||
{
|
{
|
||||||
FileSystem->DebugLog = DebugLog;
|
FileSystem->DebugLog = DebugLog;
|
||||||
}
|
}
|
||||||
|
FSP_API BOOLEAN FspFileSystemIsOperationCaseSensitiveF(VOID);
|
||||||
static inline
|
static inline
|
||||||
BOOLEAN FspFileSystemIsOperationCaseSensitive(VOID)
|
BOOLEAN FspFileSystemIsOperationCaseSensitive(VOID)
|
||||||
{
|
{
|
||||||
@ -1292,6 +1318,19 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
|||||||
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
||||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Directory buffering
|
||||||
|
*/
|
||||||
|
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
BOOLEAN Reset, PNTSTATUS PResult);
|
||||||
|
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult);
|
||||||
|
FSP_API VOID FspFileSystemReleaseDirectoryBuffer(PVOID *PDirBuffer);
|
||||||
|
FSP_API VOID FspFileSystemReadDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
PWSTR Marker,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
FSP_API VOID FspFileSystemDeleteDirectoryBuffer(PVOID *PDirBuffer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Security
|
* Security
|
||||||
*/
|
*/
|
||||||
@ -1389,6 +1428,8 @@ NTSTATUS FspPosixMapPosixToWindowsPath(const char *PosixPath, PWSTR *PWindowsPat
|
|||||||
return FspPosixMapPosixToWindowsPathEx(PosixPath, PWindowsPath, TRUE);
|
return FspPosixMapPosixToWindowsPathEx(PosixPath, PWindowsPath, TRUE);
|
||||||
}
|
}
|
||||||
FSP_API VOID FspPosixDeletePath(void *Path);
|
FSP_API VOID FspPosixDeletePath(void *Path);
|
||||||
|
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size);
|
||||||
|
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Path Handling
|
* Path Handling
|
||||||
@ -1609,6 +1650,71 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
|||||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
PULONG PBytesTransferred, ULONG Timeout,
|
PULONG PBytesTransferred, ULONG Timeout,
|
||||||
PSID Sid);
|
PSID Sid);
|
||||||
|
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delay load
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
NTSTATUS FspLoad(PVOID *PModule)
|
||||||
|
{
|
||||||
|
#if defined(_WIN64)
|
||||||
|
#define FSP_DLLNAME "winfsp-x64.dll"
|
||||||
|
#else
|
||||||
|
#define FSP_DLLNAME "winfsp-x86.dll"
|
||||||
|
#endif
|
||||||
|
#define FSP_DLLPATH "bin\\" FSP_DLLNAME
|
||||||
|
|
||||||
|
WINADVAPI
|
||||||
|
LSTATUS
|
||||||
|
APIENTRY
|
||||||
|
RegGetValueW(
|
||||||
|
HKEY hkey,
|
||||||
|
LPCWSTR lpSubKey,
|
||||||
|
LPCWSTR lpValue,
|
||||||
|
DWORD dwFlags,
|
||||||
|
LPDWORD pdwType,
|
||||||
|
PVOID pvData,
|
||||||
|
LPDWORD pcbData);
|
||||||
|
|
||||||
|
WCHAR PathBuf[MAX_PATH];
|
||||||
|
DWORD Size;
|
||||||
|
HKEY RegKey;
|
||||||
|
LONG Result;
|
||||||
|
HMODULE Module;
|
||||||
|
|
||||||
|
if (0 != PModule)
|
||||||
|
*PModule = 0;
|
||||||
|
|
||||||
|
Module = LoadLibraryW(L"" FSP_DLLNAME);
|
||||||
|
if (0 == Module)
|
||||||
|
{
|
||||||
|
Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\WinFsp",
|
||||||
|
0, KEY_READ | KEY_WOW64_32KEY, &RegKey);
|
||||||
|
if (ERROR_SUCCESS == Result)
|
||||||
|
{
|
||||||
|
Size = sizeof PathBuf - sizeof L"" FSP_DLLPATH + sizeof(WCHAR);
|
||||||
|
Result = RegGetValueW(RegKey, 0, L"InstallDir",
|
||||||
|
RRF_RT_REG_SZ, 0, PathBuf, &Size);
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
}
|
||||||
|
if (ERROR_SUCCESS != Result)
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
RtlCopyMemory(PathBuf + (Size / sizeof(WCHAR) - 1), L"" FSP_DLLPATH, sizeof L"" FSP_DLLPATH);
|
||||||
|
Module = LoadLibraryW(PathBuf);
|
||||||
|
if (0 == Module)
|
||||||
|
return STATUS_DLL_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != PModule)
|
||||||
|
*PModule = Module;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
#undef FSP_DLLNAME
|
||||||
|
#undef FSP_DLLPATH
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
1308
inc/winfsp/winfsp.hpp
Normal file
BIN
opt/cygfuse/dist/fuse-2.8-4.tar.xz
vendored
Normal file
1
opt/cygfuse/dist/install.sh
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
tar -C/ -xaf fuse-2.8-*.tar.xz
|
1
opt/cygfuse/dist/uninstall.sh
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
tar -taf fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f
|
@ -1,6 +1,6 @@
|
|||||||
NAME="fuse"
|
NAME="fuse"
|
||||||
VERSION=2.8
|
VERSION=2.8
|
||||||
RELEASE=3
|
RELEASE=4
|
||||||
CATEGORY="Utils"
|
CATEGORY="Utils"
|
||||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||||
|
@ -106,7 +106,7 @@ static const char *FspDebugLogDispositionString(UINT32 CreateOptions)
|
|||||||
|
|
||||||
static const char *FspDebugLogUserContextString(UINT64 UserContext, UINT64 UserContext2, char *Buf)
|
static const char *FspDebugLogUserContextString(UINT64 UserContext, UINT64 UserContext2, char *Buf)
|
||||||
{
|
{
|
||||||
wsprintfA(Buf, 0 == UserContext2 ? "%p" : "%p:%p", UserContext, UserContext2);
|
wsprintfA(Buf, 0 == UserContext2 ? "%p" : "%p:%p", (PVOID)UserContext, (PVOID)UserContext2);
|
||||||
|
|
||||||
return Buf;
|
return Buf;
|
||||||
}
|
}
|
||||||
@ -269,13 +269,13 @@ static const char *FspDebugLogReparseDataString(PVOID ReparseData0, char *Buf)
|
|||||||
static VOID FspDebugLogRequestVoid(FSP_FSCTL_TRANSACT_REQ *Request, const char *Name)
|
static VOID FspDebugLogRequestVoid(FSP_FSCTL_TRANSACT_REQ *Request, const char *Name)
|
||||||
{
|
{
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint, Name);
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspDebugLogResponseStatus(FSP_FSCTL_TRANSACT_RSP *Response, const char *Name)
|
static VOID FspDebugLogResponseStatus(FSP_FSCTL_TRANSACT_RSP *Response, const char *Name)
|
||||||
{
|
{
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<%s IoStatus=%lx[%ld]\n",
|
FspDebugLog("%S[TID=%04lx]: %p: <<%s IoStatus=%lx[%ld]\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint, Name,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint, Name,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information);
|
Response->IoStatus.Status, Response->IoStatus.Information);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
"AllocationSize=%lx:%lx, "
|
"AllocationSize=%lx:%lx, "
|
||||||
"AccessToken=%p, DesiredAccess=%lx, GrantedAccess=%lx, "
|
"AccessToken=%p, DesiredAccess=%lx, GrantedAccess=%lx, "
|
||||||
"ShareAccess=%lx\n",
|
"ShareAccess=%lx\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->Req.Create.UserMode ? 'U' : 'K',
|
Request->Req.Create.UserMode ? 'U' : 'K',
|
||||||
Request->Req.Create.HasTraversePrivilege ? 'T' : '-',
|
Request->Req.Create.HasTraversePrivilege ? 'T' : '-',
|
||||||
Request->Req.Create.HasBackupPrivilege ? 'B' : '-',
|
Request->Req.Create.HasBackupPrivilege ? 'B' : '-',
|
||||||
@ -328,7 +328,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case FspFsctlTransactOverwriteKind:
|
case FspFsctlTransactOverwriteKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>Overwrite%s %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>Overwrite%s %s%S%s%s, "
|
||||||
"FileAttributes=%lx\n",
|
"FileAttributes=%lx\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->Req.Overwrite.Supersede ? " [Supersede]" : "",
|
Request->Req.Overwrite.Supersede ? " [Supersede]" : "",
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
@ -340,7 +340,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
case FspFsctlTransactCleanupKind:
|
case FspFsctlTransactCleanupKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>Cleanup%s %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>Cleanup%s %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->Req.Cleanup.Delete ? " [Delete]" : "",
|
Request->Req.Cleanup.Delete ? " [Delete]" : "",
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
@ -351,7 +351,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
case FspFsctlTransactCloseKind:
|
case FspFsctlTransactCloseKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>Close %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>Close %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -362,14 +362,14 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case FspFsctlTransactReadKind:
|
case FspFsctlTransactReadKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>Read %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>Read %s%S%s%s, "
|
||||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
FspDebugLogUserContextString(
|
FspDebugLogUserContextString(
|
||||||
Request->Req.Read.UserContext, Request->Req.Read.UserContext2,
|
Request->Req.Read.UserContext, Request->Req.Read.UserContext2,
|
||||||
UserContextBuf),
|
UserContextBuf),
|
||||||
Request->Req.Read.Address,
|
(PVOID)Request->Req.Read.Address,
|
||||||
MAKE_UINT32_PAIR(Request->Req.Read.Offset),
|
MAKE_UINT32_PAIR(Request->Req.Read.Offset),
|
||||||
Request->Req.Read.Length,
|
Request->Req.Read.Length,
|
||||||
Request->Req.Read.Key);
|
Request->Req.Read.Key);
|
||||||
@ -377,7 +377,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case FspFsctlTransactWriteKind:
|
case FspFsctlTransactWriteKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>Write%s %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>Write%s %s%S%s%s, "
|
||||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->Req.Write.ConstrainedIo ? " [C]" : "",
|
Request->Req.Write.ConstrainedIo ? " [C]" : "",
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
@ -385,14 +385,14 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
FspDebugLogUserContextString(
|
FspDebugLogUserContextString(
|
||||||
Request->Req.Write.UserContext, Request->Req.Write.UserContext2,
|
Request->Req.Write.UserContext, Request->Req.Write.UserContext2,
|
||||||
UserContextBuf),
|
UserContextBuf),
|
||||||
Request->Req.Write.Address,
|
(PVOID)Request->Req.Write.Address,
|
||||||
MAKE_UINT32_PAIR(Request->Req.Write.Offset),
|
MAKE_UINT32_PAIR(Request->Req.Write.Offset),
|
||||||
Request->Req.Write.Length,
|
Request->Req.Write.Length,
|
||||||
Request->Req.Write.Key);
|
Request->Req.Write.Key);
|
||||||
break;
|
break;
|
||||||
case FspFsctlTransactQueryInformationKind:
|
case FspFsctlTransactQueryInformationKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryInformation %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>QueryInformation %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -406,7 +406,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case 4/*FileBasicInformation*/:
|
case 4/*FileBasicInformation*/:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Basic] %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Basic] %s%S%s%s, "
|
||||||
"FileAttributes=%lx, CreationTime=%s, LastAccessTime=%s, LastWriteTime=%s\n",
|
"FileAttributes=%lx, CreationTime=%s, LastAccessTime=%s, LastWriteTime=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -424,7 +424,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case 19/*FileAllocationInformation*/:
|
case 19/*FileAllocationInformation*/:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Allocation] %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Allocation] %s%S%s%s, "
|
||||||
"AllocationSize=%lx:%lx\n",
|
"AllocationSize=%lx:%lx\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -436,7 +436,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case 20/*FileEndOfFileInformation*/:
|
case 20/*FileEndOfFileInformation*/:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [EndOfFile] %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [EndOfFile] %s%S%s%s, "
|
||||||
"FileSize = %lx:%lx\n",
|
"FileSize = %lx:%lx\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -448,7 +448,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case 13/*FileDispositionInformation*/:
|
case 13/*FileDispositionInformation*/:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Disposition] %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Disposition] %s%S%s%s, "
|
||||||
"%s\n",
|
"%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -460,7 +460,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case 10/*FileRenameInformation*/:
|
case 10/*FileRenameInformation*/:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Rename] %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Rename] %s%S%s%s, "
|
||||||
"NewFileName=\"%S\", AccessToken=%p\n",
|
"NewFileName=\"%S\", AccessToken=%p\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -472,7 +472,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [INVALID] %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [INVALID] %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -490,7 +490,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
case FspFsctlTransactFlushBuffersKind:
|
case FspFsctlTransactFlushBuffersKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>FlushBuffers %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>FlushBuffers %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -507,39 +507,42 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case 2/*FileFsLabelInformation*/:
|
case 2/*FileFsLabelInformation*/:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [FsLabel] "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [FsLabel] "
|
||||||
"Label=\"%S\"\n",
|
"Label=\"%S\"\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
(PWSTR)Request->Buffer);
|
(PWSTR)Request->Buffer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [INVALID]\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [INVALID]\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint);
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FspFsctlTransactQueryDirectoryKind:
|
case FspFsctlTransactQueryDirectoryKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
|
||||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Pattern=%s%S%s\n",
|
"Address=%p, Length=%ld, Pattern=%s%S%s, Marker=%s%S%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
FspDebugLogUserContextString(
|
FspDebugLogUserContextString(
|
||||||
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
|
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
|
||||||
UserContextBuf),
|
UserContextBuf),
|
||||||
Request->Req.QueryDirectory.Address,
|
(PVOID)Request->Req.QueryDirectory.Address,
|
||||||
MAKE_UINT32_PAIR(Request->Req.QueryDirectory.Offset),
|
|
||||||
Request->Req.QueryDirectory.Length,
|
Request->Req.QueryDirectory.Length,
|
||||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||||
Request->Req.QueryDirectory.Pattern.Size ?
|
Request->Req.QueryDirectory.Pattern.Size ?
|
||||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
|
||||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "");
|
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||||
|
Request->Req.QueryDirectory.Marker.Size ? "\"" : "",
|
||||||
|
Request->Req.QueryDirectory.Marker.Size ?
|
||||||
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : L"NULL",
|
||||||
|
Request->Req.QueryDirectory.Marker.Size ? "\"" : "");
|
||||||
break;
|
break;
|
||||||
case FspFsctlTransactFileSystemControlKind:
|
case FspFsctlTransactFileSystemControlKind:
|
||||||
switch (Request->Req.FileSystemControl.FsControlCode)
|
switch (Request->Req.FileSystemControl.FsControlCode)
|
||||||
{
|
{
|
||||||
case FSCTL_GET_REPARSE_POINT:
|
case FSCTL_GET_REPARSE_POINT:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [FSCTL_GET_REPARSE_POINT] %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [FSCTL_GET_REPARSE_POINT] %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -551,7 +554,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
case FSCTL_DELETE_REPARSE_POINT:
|
case FSCTL_DELETE_REPARSE_POINT:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [%s] %s%S%s%s "
|
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [%s] %s%S%s%s "
|
||||||
"ReparseData=%s\n",
|
"ReparseData=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode ?
|
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode ?
|
||||||
"FSCTL_SET_REPARSE_POINT" : "FSCTL_DELETE_REPARSE_POINT",
|
"FSCTL_SET_REPARSE_POINT" : "FSCTL_DELETE_REPARSE_POINT",
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
@ -565,7 +568,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [INVALID] %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [INVALID] %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -586,7 +589,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
case FspFsctlTransactQuerySecurityKind:
|
case FspFsctlTransactQuerySecurityKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>QuerySecurity %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>QuerySecurity %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -604,7 +607,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
&Sddl, 0);
|
&Sddl, 0);
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
|
||||||
"SecurityInformation=%lx, Security=%s%s%s\n",
|
"SecurityInformation=%lx, Security=%s%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -619,7 +622,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
case FspFsctlTransactQueryStreamInformationKind:
|
case FspFsctlTransactQueryStreamInformationKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryStreamInformation %s%S%s%s\n",
|
FspDebugLog("%S[TID=%04lx]: %p: >>QueryStreamInformation %s%S%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
Request->FileName.Size ? "\", " : "",
|
Request->FileName.Size ? "\", " : "",
|
||||||
@ -655,7 +658,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
if (0/*IO_REPARSE*/ == Response->IoStatus.Information)
|
if (0/*IO_REPARSE*/ == Response->IoStatus.Information)
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||||
"Reparse.FileName=\"%s\"\n",
|
"Reparse.FileName=\"%s\"\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogWideCharBufferString(
|
FspDebugLogWideCharBufferString(
|
||||||
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
||||||
@ -666,7 +669,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||||
"Reparse.Data=\"%s\"\n",
|
"Reparse.Data=\"%s\"\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogReparseDataString(
|
FspDebugLogReparseDataString(
|
||||||
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
||||||
@ -675,7 +678,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||||
"UserContext=%s, GrantedAccess=%lx, FileInfo=%s\n",
|
"UserContext=%s, GrantedAccess=%lx, FileInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogUserContextString(
|
FspDebugLogUserContextString(
|
||||||
Response->Rsp.Create.Opened.UserContext, Response->Rsp.Create.Opened.UserContext2,
|
Response->Rsp.Create.Opened.UserContext, Response->Rsp.Create.Opened.UserContext2,
|
||||||
@ -689,7 +692,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<Overwrite IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<Overwrite IoStatus=%lx[%ld] "
|
||||||
"FileInfo=%s\n",
|
"FileInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogFileInfoString(&Response->Rsp.Overwrite.FileInfo, InfoBuf));
|
FspDebugLogFileInfoString(&Response->Rsp.Overwrite.FileInfo, InfoBuf));
|
||||||
break;
|
break;
|
||||||
@ -708,7 +711,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<Write IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<Write IoStatus=%lx[%ld] "
|
||||||
"FileInfo=%s\n",
|
"FileInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogFileInfoString(&Response->Rsp.Write.FileInfo, InfoBuf));
|
FspDebugLogFileInfoString(&Response->Rsp.Write.FileInfo, InfoBuf));
|
||||||
break;
|
break;
|
||||||
@ -718,7 +721,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<QueryInformation IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<QueryInformation IoStatus=%lx[%ld] "
|
||||||
"FileInfo=%s\n",
|
"FileInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogFileInfoString(&Response->Rsp.QueryInformation.FileInfo, InfoBuf));
|
FspDebugLogFileInfoString(&Response->Rsp.QueryInformation.FileInfo, InfoBuf));
|
||||||
break;
|
break;
|
||||||
@ -728,7 +731,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetInformation IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<SetInformation IoStatus=%lx[%ld] "
|
||||||
"FileInfo=%s\n",
|
"FileInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogFileInfoString(&Response->Rsp.SetInformation.FileInfo, InfoBuf));
|
FspDebugLogFileInfoString(&Response->Rsp.SetInformation.FileInfo, InfoBuf));
|
||||||
break;
|
break;
|
||||||
@ -747,7 +750,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<QueryVolumeInformation IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<QueryVolumeInformation IoStatus=%lx[%ld] "
|
||||||
"VolumeInfo=%s\n",
|
"VolumeInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogVolumeInfoString(&Response->Rsp.QueryVolumeInformation.VolumeInfo, InfoBuf));
|
FspDebugLogVolumeInfoString(&Response->Rsp.QueryVolumeInformation.VolumeInfo, InfoBuf));
|
||||||
break;
|
break;
|
||||||
@ -757,7 +760,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetVolumeInformation IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<SetVolumeInformation IoStatus=%lx[%ld] "
|
||||||
"VolumeInfo=%s\n",
|
"VolumeInfo=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogVolumeInfoString(&Response->Rsp.SetVolumeInformation.VolumeInfo, InfoBuf));
|
FspDebugLogVolumeInfoString(&Response->Rsp.SetVolumeInformation.VolumeInfo, InfoBuf));
|
||||||
break;
|
break;
|
||||||
@ -771,7 +774,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
else
|
else
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<FileSystemControl IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<FileSystemControl IoStatus=%lx[%ld] "
|
||||||
"ReparseData=%s\n",
|
"ReparseData=%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
FspDebugLogReparseDataString(Response->Buffer + Response->Rsp.FileSystemControl.Buffer.Offset,
|
FspDebugLogReparseDataString(Response->Buffer + Response->Rsp.FileSystemControl.Buffer.Offset,
|
||||||
InfoBuf));
|
InfoBuf));
|
||||||
@ -799,7 +802,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
&Sddl, 0);
|
&Sddl, 0);
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<QuerySecurity IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<QuerySecurity IoStatus=%lx[%ld] "
|
||||||
"Security=%s%s%s\n",
|
"Security=%s%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
Sddl ? "\"" : "",
|
Sddl ? "\"" : "",
|
||||||
Sddl ? Sddl : "NULL",
|
Sddl ? Sddl : "NULL",
|
||||||
@ -821,7 +824,7 @@ FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
|||||||
&Sddl, 0);
|
&Sddl, 0);
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetSecurity IoStatus=%lx[%ld] "
|
FspDebugLog("%S[TID=%04lx]: %p: <<SetSecurity IoStatus=%lx[%ld] "
|
||||||
"Security=%s%s%s\n",
|
"Security=%s%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Response->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||||
Sddl ? "\"" : "",
|
Sddl ? "\"" : "",
|
||||||
Sddl ? Sddl : "NULL",
|
Sddl ? Sddl : "NULL",
|
||||||
|
404
src/dll/dirbuf.c
Normal file
@ -0,0 +1,404 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/dirbuf.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2017 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>
|
||||||
|
|
||||||
|
#define RETURN(R, B) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (0 != PResult) \
|
||||||
|
*PResult = R; \
|
||||||
|
return B; \
|
||||||
|
} while (0,0)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRWLOCK Lock;
|
||||||
|
ULONG Capacity, LoMark, HiMark;
|
||||||
|
PUINT8 Buffer;
|
||||||
|
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
|
||||||
|
|
||||||
|
static int FspFileSystemDirectoryBufferFileNameCmp(PWSTR a, int alen, PWSTR b, int blen)
|
||||||
|
{
|
||||||
|
int len, res;
|
||||||
|
|
||||||
|
if (-1 == alen)
|
||||||
|
alen = (int)lstrlenW(a);
|
||||||
|
if (-1 == blen)
|
||||||
|
blen = (int)lstrlenW(b);
|
||||||
|
|
||||||
|
len = alen < blen ? alen : blen;
|
||||||
|
|
||||||
|
/* order "." and ".." first */
|
||||||
|
switch (alen)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (L'.' == a[0])
|
||||||
|
a = L"\1";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (L'.' == a[0] && L'.' == a[1])
|
||||||
|
a = L"\1\1";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* order "." and ".." first */
|
||||||
|
switch (blen)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (L'.' == b[0])
|
||||||
|
b = L"\1";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (L'.' == b[0] && L'.' == b[1])
|
||||||
|
b = L"\1\1";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = invariant_wcsncmp(a, b, len);
|
||||||
|
|
||||||
|
if (0 == res)
|
||||||
|
res = alen - blen;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Binary search
|
||||||
|
* "I wish I had the standard library!"
|
||||||
|
*/
|
||||||
|
static BOOLEAN FspFileSystemSearchDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer,
|
||||||
|
PWSTR Marker, int MarkerLen, PULONG PIndexNum)
|
||||||
|
{
|
||||||
|
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
|
||||||
|
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo;
|
||||||
|
int Lo = 0, Hi = Count - 1, Mi;
|
||||||
|
int CmpResult;
|
||||||
|
|
||||||
|
while (Lo <= Hi)
|
||||||
|
{
|
||||||
|
Mi = (unsigned)(Lo + Hi) >> 1;
|
||||||
|
|
||||||
|
DirInfo = (PVOID)(DirBuffer->Buffer + Index[Mi]);
|
||||||
|
CmpResult = FspFileSystemDirectoryBufferFileNameCmp(
|
||||||
|
DirInfo->FileNameBuf, (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR),
|
||||||
|
Marker, MarkerLen);
|
||||||
|
|
||||||
|
if (0 > CmpResult)
|
||||||
|
Lo = Mi + 1;
|
||||||
|
else if (0 < CmpResult)
|
||||||
|
Hi = Mi - 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*PIndexNum = Mi;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*PIndexNum = Lo;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quick sort
|
||||||
|
* "I wish I had the standard library!"
|
||||||
|
*
|
||||||
|
* Based on Sedgewick's Algorithms in C++; multiple editions.
|
||||||
|
*
|
||||||
|
* Implements a non-recursive quicksort with tail-end recursion eliminated
|
||||||
|
* and median-of-three partitioning.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define less(a, b) FspFileSystemDirectoryBufferLess(Buffer, a, b)
|
||||||
|
#define exch(a, b) { ULONG t = a; a = b; b = t; }
|
||||||
|
#define compexch(a, b) if (less(b, a)) exch(a, b)
|
||||||
|
#define push(i) (stack[stackpos++] = (i))
|
||||||
|
#define pop() (stack[--stackpos])
|
||||||
|
|
||||||
|
static __forceinline
|
||||||
|
int FspFileSystemDirectoryBufferLess(PUINT8 Buffer, int a, int b)
|
||||||
|
{
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfoA = (FSP_FSCTL_DIR_INFO *)(Buffer + a);
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfoB = (FSP_FSCTL_DIR_INFO *)(Buffer + b);
|
||||||
|
return 0 > FspFileSystemDirectoryBufferFileNameCmp(
|
||||||
|
DirInfoA->FileNameBuf, (DirInfoA->Size - sizeof *DirInfoA) / sizeof(WCHAR),
|
||||||
|
DirInfoB->FileNameBuf, (DirInfoB->Size - sizeof *DirInfoB) / sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline
|
||||||
|
int FspFileSystemPartitionDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l, int r)
|
||||||
|
{
|
||||||
|
int i = l - 1, j = r;
|
||||||
|
ULONG v = Index[r];
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (less(Index[++i], v))
|
||||||
|
;
|
||||||
|
|
||||||
|
while (less(v, Index[--j]))
|
||||||
|
if (j == l)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i >= j)
|
||||||
|
break;
|
||||||
|
|
||||||
|
exch(Index[i], Index[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
exch(Index[i], Index[r]);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFileSystemQSortDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l, int r)
|
||||||
|
{
|
||||||
|
int stack[64], stackpos = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (r > l)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
exch(Index[(l + r) / 2], Index[r - 1]);
|
||||||
|
compexch(Index[l], Index[r - 1]);
|
||||||
|
compexch(Index[l], Index[r]);
|
||||||
|
compexch(Index[r - 1], Index[r]);
|
||||||
|
|
||||||
|
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l + 1, r - 1);
|
||||||
|
#else
|
||||||
|
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l, r);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (i - l > r - i)
|
||||||
|
{
|
||||||
|
push(l); push(i - 1);
|
||||||
|
l = i + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
push(i + 1); push(r);
|
||||||
|
r = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == stackpos)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = pop(); l = pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef push
|
||||||
|
#undef pop
|
||||||
|
#undef less
|
||||||
|
#undef compexch
|
||||||
|
#undef exch
|
||||||
|
|
||||||
|
static inline VOID FspFileSystemSortDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer)
|
||||||
|
{
|
||||||
|
PUINT8 Buffer = DirBuffer->Buffer;
|
||||||
|
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
|
||||||
|
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
|
||||||
|
|
||||||
|
FspFileSystemQSortDirectoryBuffer(Buffer, Index, 0, Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
BOOLEAN Reset, PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
|
||||||
|
MemoryBarrier();
|
||||||
|
|
||||||
|
if (0 == DirBuffer)
|
||||||
|
{
|
||||||
|
static SRWLOCK CreateLock = SRWLOCK_INIT;
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *NewDirBuffer;
|
||||||
|
|
||||||
|
NewDirBuffer = MemAlloc(sizeof *NewDirBuffer);
|
||||||
|
if (0 == NewDirBuffer)
|
||||||
|
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
||||||
|
memset(NewDirBuffer, 0, sizeof *NewDirBuffer);
|
||||||
|
InitializeSRWLock(&NewDirBuffer->Lock);
|
||||||
|
AcquireSRWLockExclusive(&NewDirBuffer->Lock);
|
||||||
|
|
||||||
|
AcquireSRWLockExclusive(&CreateLock);
|
||||||
|
DirBuffer = *PDirBuffer;
|
||||||
|
MemoryBarrier();
|
||||||
|
if (0 == DirBuffer)
|
||||||
|
*PDirBuffer = DirBuffer = NewDirBuffer;
|
||||||
|
ReleaseSRWLockExclusive(&CreateLock);
|
||||||
|
|
||||||
|
if (DirBuffer == NewDirBuffer)
|
||||||
|
RETURN(STATUS_SUCCESS, TRUE);
|
||||||
|
|
||||||
|
ReleaseSRWLockExclusive(&NewDirBuffer->Lock);
|
||||||
|
MemFree(NewDirBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reset)
|
||||||
|
{
|
||||||
|
AcquireSRWLockExclusive(&DirBuffer->Lock);
|
||||||
|
|
||||||
|
DirBuffer->LoMark = 0;
|
||||||
|
DirBuffer->HiMark = DirBuffer->Capacity;
|
||||||
|
|
||||||
|
RETURN(STATUS_SUCCESS, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN(STATUS_SUCCESS, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
|
||||||
|
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
|
||||||
|
ULONG Capacity, LoMark, HiMark;
|
||||||
|
PUINT8 Buffer;
|
||||||
|
|
||||||
|
if (0 == DirInfo)
|
||||||
|
RETURN(STATUS_INVALID_PARAMETER, FALSE);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
LoMark = DirBuffer->LoMark;
|
||||||
|
HiMark = DirBuffer->HiMark;
|
||||||
|
Buffer = DirBuffer->Buffer;
|
||||||
|
|
||||||
|
if (FspFileSystemAddDirInfo(DirInfo,
|
||||||
|
Buffer,
|
||||||
|
HiMark > sizeof(ULONG) ? HiMark - sizeof(ULONG)/*space for new index entry*/ : HiMark,
|
||||||
|
&LoMark))
|
||||||
|
{
|
||||||
|
HiMark -= sizeof(ULONG);
|
||||||
|
*(PULONG)(Buffer + HiMark) = DirBuffer->LoMark;
|
||||||
|
|
||||||
|
DirBuffer->LoMark = LoMark;
|
||||||
|
DirBuffer->HiMark = HiMark;
|
||||||
|
|
||||||
|
RETURN (STATUS_SUCCESS, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == Buffer)
|
||||||
|
{
|
||||||
|
Buffer = MemAlloc(Capacity = 512);
|
||||||
|
if (0 == Buffer)
|
||||||
|
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
||||||
|
|
||||||
|
HiMark = Capacity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Buffer = MemRealloc(Buffer, Capacity = DirBuffer->Capacity * 2);
|
||||||
|
if (0 == Buffer)
|
||||||
|
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
||||||
|
|
||||||
|
ULONG IndexSize = DirBuffer->Capacity - HiMark;
|
||||||
|
ULONG NewHiMark = Capacity - IndexSize;
|
||||||
|
|
||||||
|
memmove(Buffer + NewHiMark, Buffer + HiMark, IndexSize);
|
||||||
|
HiMark = NewHiMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirBuffer->Capacity = Capacity;
|
||||||
|
DirBuffer->LoMark = LoMark;
|
||||||
|
DirBuffer->HiMark = HiMark;
|
||||||
|
DirBuffer->Buffer = Buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemReleaseDirectoryBuffer(PVOID *PDirBuffer)
|
||||||
|
{
|
||||||
|
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
|
||||||
|
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
|
||||||
|
|
||||||
|
FspFileSystemSortDirectoryBuffer(DirBuffer);
|
||||||
|
|
||||||
|
ReleaseSRWLockExclusive(&DirBuffer->Lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemReadDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
PWSTR Marker,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
|
||||||
|
MemoryBarrier();
|
||||||
|
|
||||||
|
if (0 != DirBuffer)
|
||||||
|
{
|
||||||
|
AcquireSRWLockShared(&DirBuffer->Lock);
|
||||||
|
|
||||||
|
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
|
||||||
|
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
|
||||||
|
ULONG IndexNum;
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo;
|
||||||
|
|
||||||
|
if (0 == Marker)
|
||||||
|
IndexNum = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FspFileSystemSearchDirectoryBuffer(DirBuffer,
|
||||||
|
Marker, lstrlenW(Marker),
|
||||||
|
&IndexNum);
|
||||||
|
IndexNum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; IndexNum < Count; IndexNum++)
|
||||||
|
{
|
||||||
|
DirInfo = (PVOID)(DirBuffer->Buffer + Index[IndexNum]);
|
||||||
|
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
|
||||||
|
{
|
||||||
|
ReleaseSRWLockShared(&DirBuffer->Lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseSRWLockShared(&DirBuffer->Lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemDeleteDirectoryBuffer(PVOID *PDirBuffer)
|
||||||
|
{
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
|
||||||
|
MemoryBarrier();
|
||||||
|
|
||||||
|
if (0 != DirBuffer)
|
||||||
|
{
|
||||||
|
MemFree(DirBuffer->Buffer);
|
||||||
|
MemFree(DirBuffer);
|
||||||
|
*PDirBuffer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount)
|
||||||
|
{
|
||||||
|
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
|
||||||
|
|
||||||
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
|
||||||
|
|
||||||
|
*PBuffer = DirBuffer->Buffer;
|
||||||
|
*PIndex = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
|
||||||
|
*PCount = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
|
||||||
|
}
|
324
src/dll/fs.c
@ -72,6 +72,48 @@ VOID FspFileSystemFinalize(BOOLEAN Dynamic)
|
|||||||
TlsFree(FspFileSystemTlsKey);
|
TlsFree(FspFileSystemTlsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
|
||||||
|
PWSTR MountPoint)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
WCHAR TargetPath[MAX_PATH];
|
||||||
|
HANDLE DirHandle;
|
||||||
|
|
||||||
|
Result = FspFsctlPreflight(DevicePath);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
if (0 == MountPoint)
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FspPathIsDrive(MountPoint))
|
||||||
|
Result = QueryDosDeviceW(MountPoint, TargetPath, MAX_PATH) ?
|
||||||
|
STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DirHandle = CreateFileW(MountPoint,
|
||||||
|
FILE_READ_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE != DirHandle)
|
||||||
|
{
|
||||||
|
CloseHandle(DirHandle);
|
||||||
|
Result = STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
}
|
||||||
|
else if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||||||
|
Result = STATUS_OBJECT_NAME_INVALID;
|
||||||
|
else
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
||||||
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
||||||
const FSP_FILE_SYSTEM_INTERFACE *Interface,
|
const FSP_FILE_SYSTEM_INTERFACE *Interface,
|
||||||
@ -145,20 +187,63 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
|
|||||||
MemFree(FileSystem);
|
MemFree(FileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWSTR VolumeName)
|
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
|
||||||
|
PHANDLE PMountHandle)
|
||||||
|
{
|
||||||
|
*PMountHandle = 0;
|
||||||
|
|
||||||
|
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
if (0 != FspNtOpenSymbolicLinkObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
WCHAR SymlinkBuf[6];
|
||||||
|
UNICODE_STRING Symlink;
|
||||||
|
OBJECT_ATTRIBUTES Obja;
|
||||||
|
|
||||||
|
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
||||||
|
SymlinkBuf[4] = MountPoint[0];
|
||||||
|
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
||||||
|
Symlink.Buffer = SymlinkBuf;
|
||||||
|
|
||||||
|
memset(&Obja, 0, sizeof Obja);
|
||||||
|
Obja.Length = sizeof Obja;
|
||||||
|
Obja.ObjectName = &Symlink;
|
||||||
|
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
|
||||||
|
Result = FspNtOpenSymbolicLinkObject(PMountHandle, DELETE, &Obja);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = FspNtMakeTemporaryObject(*PMountHandle);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspNtClose(*PMountHandle);
|
||||||
|
*PMountHandle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR VolumeName,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
HANDLE DirHandle;
|
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||||
BOOL Success;
|
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
||||||
DWORD Backslashes, Bytes;
|
DWORD Backslashes, Bytes;
|
||||||
USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
|
USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
|
||||||
PREPARSE_DATA_BUFFER ReparseData = 0;
|
PREPARSE_DATA_BUFFER ReparseData = 0;
|
||||||
PWSTR P, PathBuffer;
|
PWSTR P, PathBuffer;
|
||||||
|
|
||||||
|
*PMountHandle = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windows does not allow mount points (junctions) to point to network file systems.
|
* Windows does not allow mount points (junctions) to point to network file systems.
|
||||||
*
|
*
|
||||||
* Count how many backslashes our VolumeName. If it is 3 or more this is a network
|
* Count how many backslashes our VolumeName has. If it is 3 or more this is a network
|
||||||
* file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED.
|
* file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED.
|
||||||
*/
|
*/
|
||||||
for (P = VolumeName, Backslashes = 0; *P; P++)
|
for (P = VolumeName, Backslashes = 0; *P; P++)
|
||||||
@ -169,25 +254,24 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateDirectoryW(MountPoint, 0))
|
memset(&SecurityAttributes, 0, sizeof SecurityAttributes);
|
||||||
|
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||||
|
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||||
|
|
||||||
|
MountHandle = CreateFileW(MountPoint,
|
||||||
|
FILE_WRITE_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
&SecurityAttributes,
|
||||||
|
CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY |
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DirHandle = CreateFileW(MountPoint,
|
|
||||||
FILE_WRITE_ATTRIBUTES,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
0,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
|
||||||
0);
|
|
||||||
if (INVALID_HANDLE_VALUE == DirHandle)
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto rmdir_and_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
VolumeNameLength = (USHORT)lstrlenW(VolumeName);
|
VolumeNameLength = (USHORT)lstrlenW(VolumeName);
|
||||||
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
|
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
|
||||||
VolumeNameLength *= sizeof(WCHAR);
|
VolumeNameLength *= sizeof(WCHAR);
|
||||||
@ -201,7 +285,7 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS
|
|||||||
if (0 == ReparseData)
|
if (0 == ReparseData)
|
||||||
{
|
{
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto rmdir_and_exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||||
@ -228,86 +312,35 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS
|
|||||||
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
||||||
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
Success = DeviceIoControl(DirHandle, FSCTL_SET_REPARSE_POINT,
|
if (!DeviceIoControl(MountHandle, FSCTL_SET_REPARSE_POINT,
|
||||||
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
||||||
0, 0,
|
0, 0,
|
||||||
&Bytes, 0);
|
&Bytes, 0))
|
||||||
CloseHandle(DirHandle);
|
|
||||||
if (!Success)
|
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
goto rmdir_and_exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*PMountHandle = MountHandle;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
||||||
|
CloseHandle(MountHandle);
|
||||||
|
|
||||||
MemFree(ReparseData);
|
MemFree(ReparseData);
|
||||||
return Result;
|
|
||||||
|
|
||||||
rmdir_and_exit:
|
|
||||||
RemoveDirectoryW(MountPoint);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS FspFileSystemSetMountPoint_MakeTemporary(PWSTR MountPoint, PHANDLE PMountHandle)
|
|
||||||
{
|
|
||||||
NTSTATUS Result = STATUS_SUCCESS;
|
|
||||||
HANDLE MountHandle = 0;
|
|
||||||
|
|
||||||
if (FspPathIsDrive(MountPoint))
|
|
||||||
{
|
|
||||||
if (0 != FspNtOpenSymbolicLinkObject)
|
|
||||||
{
|
|
||||||
WCHAR SymlinkBuf[6];
|
|
||||||
UNICODE_STRING Symlink;
|
|
||||||
OBJECT_ATTRIBUTES Obja;
|
|
||||||
|
|
||||||
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
|
||||||
SymlinkBuf[4] = MountPoint[0];
|
|
||||||
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
|
||||||
Symlink.Buffer = SymlinkBuf;
|
|
||||||
|
|
||||||
memset(&Obja, 0, sizeof Obja);
|
|
||||||
Obja.Length = sizeof Obja;
|
|
||||||
Obja.ObjectName = &Symlink;
|
|
||||||
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
|
||||||
|
|
||||||
Result = FspNtOpenSymbolicLinkObject(&MountHandle, DELETE, &Obja);
|
|
||||||
if (NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
Result = FspNtMakeTemporaryObject(MountHandle);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
FspNtClose(MountHandle);
|
|
||||||
MountHandle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* open the directory for DELETE_ON_CLOSE; closing it will remove the directory */
|
|
||||||
MountHandle = CreateFileW(MountPoint,
|
|
||||||
FILE_READ_ATTRIBUTES,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
0,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_DELETE_ON_CLOSE,
|
|
||||||
0);
|
|
||||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
|
||||||
{
|
|
||||||
MountHandle = 0;
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*PMountHandle = MountHandle;
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
||||||
|
{
|
||||||
|
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||||
{
|
{
|
||||||
if (0 != FileSystem->MountPoint)
|
if (0 != FileSystem->MountPoint)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
@ -333,11 +366,10 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
|
|||||||
if (0 == (Drives & (1 << (Drive - 'A'))))
|
if (0 == (Drives & (1 << (Drive - 'A'))))
|
||||||
{
|
{
|
||||||
MountPoint[0] = Drive;
|
MountPoint[0] = Drive;
|
||||||
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName))
|
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
|
||||||
{
|
&MountHandle);
|
||||||
Result = STATUS_SUCCESS;
|
if (NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Result = STATUS_NO_SUCH_DEVICE;
|
Result = STATUS_NO_SUCH_DEVICE;
|
||||||
}
|
}
|
||||||
@ -358,22 +390,16 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
|
|||||||
MountPoint = P;
|
MountPoint = P;
|
||||||
|
|
||||||
if (FspPathIsDrive(MountPoint))
|
if (FspPathIsDrive(MountPoint))
|
||||||
{
|
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
|
||||||
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName))
|
&MountHandle);
|
||||||
Result = STATUS_SUCCESS;
|
|
||||||
else
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
Result = FspFileSystemSetMountPoint_CreateDirectory(MountPoint, FileSystem->VolumeName);
|
Result = FspFileSystemSetMountPoint_Directory(MountPoint, FileSystem->VolumeName,
|
||||||
|
SecurityDescriptor, &MountHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspFileSystemSetMountPoint_MakeTemporary(MountPoint, &MountHandle);
|
|
||||||
/* ignore result; this path always considered successful */
|
|
||||||
|
|
||||||
FileSystem->MountPoint = MountPoint;
|
FileSystem->MountPoint = MountPoint;
|
||||||
FileSystem->MountHandle = MountHandle;
|
FileSystem->MountHandle = MountHandle;
|
||||||
}
|
}
|
||||||
@ -383,33 +409,35 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspFileSystemRemoveMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, HANDLE MountHandle)
|
||||||
|
{
|
||||||
|
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||||
|
MountPoint, VolumeName);
|
||||||
|
|
||||||
|
if (0 != MountHandle)
|
||||||
|
FspNtClose(MountHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFileSystemRemoveMountPoint_Directory(HANDLE MountHandle)
|
||||||
|
{
|
||||||
|
/* directory is marked DELETE_ON_CLOSE */
|
||||||
|
CloseHandle(MountHandle);
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
||||||
{
|
{
|
||||||
BOOLEAN IsDrive;
|
|
||||||
|
|
||||||
if (0 == FileSystem->MountPoint)
|
if (0 == FileSystem->MountPoint)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IsDrive = FspPathIsDrive(FileSystem->MountPoint);
|
if (FspPathIsDrive(FileSystem->MountPoint))
|
||||||
if (IsDrive)
|
FspFileSystemRemoveMountPoint_Drive(FileSystem->MountPoint, FileSystem->VolumeName,
|
||||||
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
FileSystem->MountHandle);
|
||||||
FileSystem->MountPoint, FileSystem->VolumeName);
|
|
||||||
else
|
else
|
||||||
/* nothing to do! directory will be deleted when the MountHandle is closed */;
|
FspFileSystemRemoveMountPoint_Directory(FileSystem->MountHandle);
|
||||||
|
|
||||||
MemFree(FileSystem->MountPoint);
|
MemFree(FileSystem->MountPoint);
|
||||||
FileSystem->MountPoint = 0;
|
FileSystem->MountPoint = 0;
|
||||||
|
FileSystem->MountHandle = 0;
|
||||||
if (0 != FileSystem->MountHandle)
|
|
||||||
{
|
|
||||||
if (IsDrive)
|
|
||||||
FspNtClose(FileSystem->MountHandle);
|
|
||||||
else
|
|
||||||
/* CloseHandle really calls NtClose, but I like being defensive when programming */
|
|
||||||
CloseHandle(FileSystem->MountHandle);
|
|
||||||
|
|
||||||
FileSystem->MountHandle = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0)
|
static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0)
|
||||||
@ -591,3 +619,67 @@ FSP_API FSP_FILE_SYSTEM_OPERATION_CONTEXT *FspFileSystemGetOperationContext(VOID
|
|||||||
{
|
{
|
||||||
return (FSP_FILE_SYSTEM_OPERATION_CONTEXT *)TlsGetValue(FspFileSystemTlsKey);
|
return (FSP_FILE_SYSTEM_OPERATION_CONTEXT *)TlsGetValue(FspFileSystemTlsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Out-of-Line
|
||||||
|
*/
|
||||||
|
|
||||||
|
FSP_API PWSTR FspFileSystemMountPointF(FSP_FILE_SYSTEM *FileSystem)
|
||||||
|
{
|
||||||
|
return FspFileSystemMountPoint(FileSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemEnterOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
return FspFileSystemEnterOperation(FileSystem, Request, Response);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemLeaveOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
return FspFileSystemLeaveOperation(FileSystem, Request, Response);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemSetOperationGuardF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION_GUARD *EnterOperation,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION_GUARD *LeaveOperation)
|
||||||
|
{
|
||||||
|
FspFileSystemSetOperationGuard(FileSystem, EnterOperation, LeaveOperation);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemSetOperationGuardStrategyF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy)
|
||||||
|
{
|
||||||
|
FspFileSystemSetOperationGuardStrategy(FileSystem, GuardStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemSetOperationF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
ULONG Index,
|
||||||
|
FSP_FILE_SYSTEM_OPERATION *Operation)
|
||||||
|
{
|
||||||
|
FspFileSystemSetOperation(FileSystem, Index, Operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemGetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS *PDispatcherResult)
|
||||||
|
{
|
||||||
|
FspFileSystemGetDispatcherResult(FileSystem, PDispatcherResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemSetDispatcherResultF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS DispatcherResult)
|
||||||
|
{
|
||||||
|
FspFileSystemSetDispatcherResult(FileSystem, DispatcherResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspFileSystemSetDebugLogF(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
UINT32 DebugLog)
|
||||||
|
{
|
||||||
|
FspFileSystemSetDebugLog(FileSystem, DebugLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemIsOperationCaseSensitiveF(VOID)
|
||||||
|
{
|
||||||
|
return FspFileSystemIsOperationCaseSensitive();
|
||||||
|
}
|
||||||
|
@ -355,10 +355,18 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
|||||||
{
|
{
|
||||||
LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
|
LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
|
||||||
if (0 != LastError)
|
if (0 != LastError)
|
||||||
{
|
/*
|
||||||
Result = FspNtStatusFromWin32(LastError);
|
* Apparently GetEffectiveRightsFromAclW can fail with ERROR_CIRCULAR_DEPENDENCY
|
||||||
goto exit;
|
* in some rare circumstances. Calling GetEffectiveRightsFromAclW is not essential
|
||||||
}
|
* in this instance. It is only done to check whether the "Everyone/World" SID
|
||||||
|
* already has the access required to start the FSD; if it does not have those
|
||||||
|
* rights already they are added. It is probably safe to just assume that the
|
||||||
|
* required rights are not there if GetEffectiveRightsFromAclW fails; the worst
|
||||||
|
* that can happen is that the rights get added twice (which is benign).
|
||||||
|
*
|
||||||
|
* See https://github.com/billziss-gh/winfsp/issues/62
|
||||||
|
*/
|
||||||
|
AccessRights = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do we have the required access rights? */
|
/* do we have the required access rights? */
|
||||||
|
@ -1133,11 +1133,12 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
BytesTransferred = 0;
|
BytesTransferred = 0;
|
||||||
Result = FileSystem->Interface->ReadDirectory(FileSystem,
|
Result = FileSystem->Interface->ReadDirectory(FileSystem,
|
||||||
(PVOID)ValOfFileContext(Request->Req.QueryDirectory),
|
(PVOID)ValOfFileContext(Request->Req.QueryDirectory),
|
||||||
(PVOID)Request->Req.QueryDirectory.Address,
|
|
||||||
Request->Req.QueryDirectory.Offset,
|
|
||||||
Request->Req.QueryDirectory.Length,
|
|
||||||
0 != Request->Req.QueryDirectory.Pattern.Size ?
|
0 != Request->Req.QueryDirectory.Pattern.Size ?
|
||||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0,
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0,
|
||||||
|
0 != Request->Req.QueryDirectory.Marker.Size ?
|
||||||
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : 0,
|
||||||
|
(PVOID)Request->Req.QueryDirectory.Address,
|
||||||
|
Request->Req.QueryDirectory.Length,
|
||||||
&BytesTransferred);
|
&BytesTransferred);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -1353,7 +1354,7 @@ FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS FspFileSystemResolveReparsePointsInternal(FSP_FILE_SYSTEM *FileSystem,
|
||||||
NTSTATUS (*GetReparsePointByName)(
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||||
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
||||||
|
@ -32,18 +32,20 @@ struct fsp_fuse_core_opt_data
|
|||||||
{
|
{
|
||||||
struct fsp_fuse_env *env;
|
struct fsp_fuse_env *env;
|
||||||
int help, debug;
|
int help, debug;
|
||||||
int hard_remove,
|
HANDLE DebugLogHandle;
|
||||||
use_ino, readdir_ino,
|
int set_umask, umask,
|
||||||
set_umask, umask,
|
|
||||||
set_uid, uid,
|
set_uid, uid,
|
||||||
set_gid, gid,
|
set_gid, gid,
|
||||||
set_attr_timeout, attr_timeout,
|
set_attr_timeout, attr_timeout,
|
||||||
rellinks;
|
rellinks;
|
||||||
int set_FileInfoTimeout;
|
int set_FileInfoTimeout;
|
||||||
int CaseInsensitiveSearch,
|
|
||||||
ReadOnlyVolume;
|
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
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.");
|
||||||
|
|
||||||
static struct fuse_opt fsp_fuse_core_opts[] =
|
static struct fuse_opt fsp_fuse_core_opts[] =
|
||||||
{
|
{
|
||||||
@ -56,9 +58,11 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("-d", debug, 1),
|
FSP_FUSE_CORE_OPT("-d", debug, 1),
|
||||||
FSP_FUSE_CORE_OPT("debug", debug, 1),
|
FSP_FUSE_CORE_OPT("debug", debug, 1),
|
||||||
|
|
||||||
FSP_FUSE_CORE_OPT("hard_remove", hard_remove, 1),
|
FUSE_OPT_KEY("DebugLog=", 'D'),
|
||||||
FSP_FUSE_CORE_OPT("use_ino", use_ino, 1),
|
|
||||||
FSP_FUSE_CORE_OPT("readdir_ino", readdir_ino, 1),
|
FUSE_OPT_KEY("hard_remove", FUSE_OPT_KEY_DISCARD),
|
||||||
|
FUSE_OPT_KEY("use_ino", FUSE_OPT_KEY_DISCARD),
|
||||||
|
FUSE_OPT_KEY("readdir_ino", FUSE_OPT_KEY_DISCARD),
|
||||||
FUSE_OPT_KEY("direct_io", FUSE_OPT_KEY_DISCARD),
|
FUSE_OPT_KEY("direct_io", FUSE_OPT_KEY_DISCARD),
|
||||||
FUSE_OPT_KEY("kernel_cache", FUSE_OPT_KEY_DISCARD),
|
FUSE_OPT_KEY("kernel_cache", FUSE_OPT_KEY_DISCARD),
|
||||||
FUSE_OPT_KEY("auto_cache", FUSE_OPT_KEY_DISCARD),
|
FUSE_OPT_KEY("auto_cache", FUSE_OPT_KEY_DISCARD),
|
||||||
@ -83,23 +87,15 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
FSP_FUSE_CORE_OPT("norellinks", rellinks, 0),
|
||||||
|
|
||||||
FUSE_OPT_KEY("fstypename=", 'F'),
|
FUSE_OPT_KEY("fstypename=", 'F'),
|
||||||
|
FUSE_OPT_KEY("volname=", 'v'),
|
||||||
|
|
||||||
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
||||||
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
||||||
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
||||||
FSP_FUSE_CORE_OPT("VolumeCreationTime=%lli", VolumeParams.VolumeCreationTime, 0),
|
FSP_FUSE_CORE_OPT("VolumeCreationTime=%lli", VolumeParams.VolumeCreationTime, 0),
|
||||||
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
||||||
FSP_FUSE_CORE_OPT("TransactTimeout=%u", VolumeParams.TransactTimeout, 0),
|
|
||||||
FSP_FUSE_CORE_OPT("IrpTimeout=%u", VolumeParams.IrpTimeout, 0),
|
|
||||||
FSP_FUSE_CORE_OPT("IrpCapacity=%u", VolumeParams.IrpCapacity, 0),
|
|
||||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||||
FSP_FUSE_CORE_OPT("CaseInsensitiveSearch", CaseInsensitiveSearch, 1),
|
|
||||||
FSP_FUSE_CORE_OPT("ReadOnlyVolume", ReadOnlyVolume, 1),
|
|
||||||
FUSE_OPT_KEY("ReparsePoints", FUSE_OPT_KEY_DISCARD),
|
|
||||||
FUSE_OPT_KEY("NamedStreams", FUSE_OPT_KEY_DISCARD),
|
|
||||||
FUSE_OPT_KEY("HardLinks", FUSE_OPT_KEY_DISCARD),
|
|
||||||
FUSE_OPT_KEY("ExtendedAttributes", FUSE_OPT_KEY_DISCARD),
|
|
||||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||||
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
||||||
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
||||||
@ -131,6 +127,9 @@ static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size)
|
|||||||
|
|
||||||
static inline void fsp_fuse_obj_free(void *obj)
|
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));
|
struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr));
|
||||||
|
|
||||||
hdr->dtor(hdr);
|
hdr->dtor(hdr);
|
||||||
@ -190,23 +189,55 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
|||||||
const char *mountpoint, struct fuse_args *args)
|
const char *mountpoint, struct fuse_args *args)
|
||||||
{
|
{
|
||||||
struct fuse_chan *ch = 0;
|
struct fuse_chan *ch = 0;
|
||||||
|
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH];
|
||||||
int Size;
|
int Size;
|
||||||
|
|
||||||
if (0 == mountpoint)
|
if (0 == mountpoint || '\0' == mountpoint[0] ||
|
||||||
mountpoint = "";
|
('*' == mountpoint[0] && '\0' == mountpoint[1]))
|
||||||
|
{
|
||||||
|
MountPointBuf[0] = L'*';
|
||||||
|
MountPointBuf[1] = L'\0';
|
||||||
|
Size = 2 * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
(
|
||||||
|
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
||||||
|
('a' <= mountpoint[0] && mountpoint[0] <= 'z')
|
||||||
|
) &&
|
||||||
|
':' == mountpoint[1] && '\0' == mountpoint[2])
|
||||||
|
{
|
||||||
|
MountPointBuf[0] = mountpoint[0];
|
||||||
|
MountPointBuf[1] = ':';
|
||||||
|
MountPointBuf[2] = '\0';
|
||||||
|
Size = 3 * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *win_mountpoint = 0;
|
||||||
|
|
||||||
Size = MultiByteToWideChar(CP_UTF8, 0, mountpoint, -1, 0, 0);
|
if (0 != env->conv_to_win_path)
|
||||||
if (0 == Size)
|
mountpoint = win_mountpoint = env->conv_to_win_path(mountpoint);
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ch = fsp_fuse_obj_alloc(env, sizeof *ch + Size * sizeof(WCHAR));
|
Size = 0;
|
||||||
|
if (0 != mountpoint &&
|
||||||
|
0 != MultiByteToWideChar(CP_UTF8, 0, mountpoint, -1, TempMountPointBuf, MAX_PATH))
|
||||||
|
Size = GetFullPathNameW(TempMountPointBuf, MAX_PATH, MountPointBuf, 0);
|
||||||
|
|
||||||
|
env->memfree(win_mountpoint);
|
||||||
|
|
||||||
|
if (0 == Size || MAX_PATH <= Size)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
mountpoint = 0;
|
||||||
|
Size = (Size + 1) * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = fsp_fuse_obj_alloc(env, sizeof *ch + Size);
|
||||||
if (0 == ch)
|
if (0 == ch)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ch->MountPoint = (PVOID)ch->Buffer;
|
ch->MountPoint = (PVOID)ch->Buffer;
|
||||||
Size = MultiByteToWideChar(CP_UTF8, 0, mountpoint, -1, ch->MountPoint, Size);
|
memcpy(ch->MountPoint, MountPointBuf, Size);
|
||||||
if (0 == Size)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
|
|
||||||
@ -230,36 +261,6 @@ FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env,
|
|||||||
|
|
||||||
static void fsp_fuse_cleanup(struct fuse *f);
|
static void fsp_fuse_cleanup(struct fuse *f);
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_preflight(struct fuse *f)
|
|
||||||
{
|
|
||||||
NTSTATUS Result;
|
|
||||||
|
|
||||||
Result = FspFsctlPreflight(f->VolumeParams.Prefix[0] ?
|
|
||||||
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
|
|
||||||
if (L'\0' != f->MountPoint)
|
|
||||||
{
|
|
||||||
if ((
|
|
||||||
(L'A' <= f->MountPoint[0] && f->MountPoint[0] <= L'Z') ||
|
|
||||||
(L'a' <= f->MountPoint[0] && f->MountPoint[0] <= L'z')
|
|
||||||
) &&
|
|
||||||
L':' == f->MountPoint[1] || L'\0' == f->MountPoint[2])
|
|
||||||
{
|
|
||||||
if (GetLogicalDrives() & (1 << ((f->MountPoint[0] & ~0x20) - 'a')))
|
|
||||||
return STATUS_OBJECT_NAME_COLLISION;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1])
|
|
||||||
;
|
|
||||||
else
|
|
||||||
return STATUS_OBJECT_NAME_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||||
{
|
{
|
||||||
struct fuse *f = Service->UserContext;
|
struct fuse *f = Service->UserContext;
|
||||||
@ -291,9 +292,17 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
||||||
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
||||||
FUSE_CAP_BIG_WRITES |
|
FUSE_CAP_BIG_WRITES |
|
||||||
FUSE_CAP_DONT_MASK;
|
FUSE_CAP_DONT_MASK |
|
||||||
|
FSP_FUSE_CAP_READDIR_PLUS |
|
||||||
|
FSP_FUSE_CAP_READ_ONLY |
|
||||||
|
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
||||||
if (0 != f->ops.init)
|
if (0 != f->ops.init)
|
||||||
|
{
|
||||||
context->private_data = f->data = f->ops.init(&conn);
|
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);
|
||||||
|
f->conn_want = conn.want;
|
||||||
|
}
|
||||||
f->fsinit = TRUE;
|
f->fsinit = TRUE;
|
||||||
if (0 != f->ops.statfs)
|
if (0 != f->ops.statfs)
|
||||||
{
|
{
|
||||||
@ -308,10 +317,12 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stbuf.f_frsize > FSP_FUSE_SECTORSIZE_MAX)
|
if (0 == f->VolumeParams.SectorSize && 0 != stbuf.f_frsize)
|
||||||
stbuf.f_frsize = FSP_FUSE_SECTORSIZE_MAX;
|
|
||||||
if (0 == f->VolumeParams.SectorSize)
|
|
||||||
f->VolumeParams.SectorSize = (UINT16)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)
|
if (0 == f->VolumeParams.MaxComponentLength)
|
||||||
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
||||||
}
|
}
|
||||||
@ -343,9 +354,8 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN)
|
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
||||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MIN;
|
f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
||||||
if (f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
|
||||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
||||||
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
||||||
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
||||||
@ -380,7 +390,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
|
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
|
||||||
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
|
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
|
||||||
|
|
||||||
if (L'\0' != f->MountPoint)
|
if (0 != f->MountPoint)
|
||||||
{
|
{
|
||||||
Result = FspFileSystemSetMountPoint(f->FileSystem,
|
Result = FspFileSystemSetMountPoint(f->FileSystem,
|
||||||
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
|
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
|
||||||
@ -449,14 +459,13 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
case 'h':
|
case 'h':
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||||
FSP_FUSE_LIBRARY_NAME " options:\n"
|
FSP_FUSE_LIBRARY_NAME " options:\n"
|
||||||
" -o SectorSize=N sector size for Windows (512-4096, deflt: 512)\n"
|
" -o DebugLog=FILE debug log file (deflt: stderr)\n"
|
||||||
" -o SectorsPerAllocationUnit=N allocation unit size (deflt: 1*SectorSize)\n"
|
" -o SectorSize=N sector size for Windows (512-4096, deflt: 4096)\n"
|
||||||
|
" -o SectorsPerAllocationUnit=N sectors per allocation unit (deflt: 1)\n"
|
||||||
" -o MaxComponentLength=N max file name component length (deflt: 255)\n"
|
" -o MaxComponentLength=N max file name component length (deflt: 255)\n"
|
||||||
" -o VolumeCreationTime=T volume creation time (FILETIME hex format)\n"
|
" -o VolumeCreationTime=T volume creation time (FILETIME hex format)\n"
|
||||||
" -o VolumeSerialNumber=N 32-bit wide\n"
|
" -o VolumeSerialNumber=N 32-bit wide\n"
|
||||||
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
||||||
" -o CaseInsensitiveSearch file system supports case-insensitive file names\n"
|
|
||||||
//" -o ReadOnlyVolume file system is read only\n"
|
|
||||||
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
||||||
" --FileSystemName=FSN Name of user mode file system\n");
|
" --FileSystemName=FSN Name of user mode file system\n");
|
||||||
opt_data->help = 1;
|
opt_data->help = 1;
|
||||||
@ -467,6 +476,17 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION);
|
FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION);
|
||||||
opt_data->help = 1;
|
opt_data->help = 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
case 'D':
|
||||||
|
arg += sizeof "DebugLog=" - 1;
|
||||||
|
opt_data->DebugLogHandle = CreateFileA(
|
||||||
|
arg,
|
||||||
|
FILE_APPEND_DATA,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
0,
|
||||||
|
OPEN_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0);
|
||||||
|
return 0;
|
||||||
case 'U':
|
case 'U':
|
||||||
if ('U' == arg[2])
|
if ('U' == arg[2])
|
||||||
arg += sizeof "--UNC=" - 1;
|
arg += sizeof "--UNC=" - 1;
|
||||||
@ -485,12 +505,20 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
arg += sizeof "--FileSystemName=" - 1;
|
arg += sizeof "--FileSystemName=" - 1;
|
||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||||
opt_data->VolumeParams.FileSystemName + 5,
|
opt_data->VolumeParams.FileSystemName + 5,
|
||||||
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR)) - 5)
|
sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 5))
|
||||||
return -1;
|
return -1;
|
||||||
opt_data->VolumeParams.FileSystemName
|
opt_data->VolumeParams.FileSystemName
|
||||||
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
[sizeof opt_data->VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
|
memcpy(opt_data->VolumeParams.FileSystemName, L"FUSE-", 5 * sizeof(WCHAR));
|
||||||
return 0;
|
return 0;
|
||||||
|
case 'v':
|
||||||
|
arg += sizeof "volname=" - 1;
|
||||||
|
opt_data->VolumeLabelLength = (UINT16)(sizeof(WCHAR) *
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, arg, lstrlenA(arg),
|
||||||
|
opt_data->VolumeLabel, sizeof opt_data->VolumeLabel / sizeof(WCHAR)));
|
||||||
|
if (0 == opt_data->VolumeLabelLength)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,20 +537,54 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
|
|
||||||
memset(&opt_data, 0, sizeof opt_data);
|
memset(&opt_data, 0, sizeof opt_data);
|
||||||
opt_data.env = env;
|
opt_data.env = env;
|
||||||
|
opt_data.DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
opt_data.VolumeParams.FileInfoTimeout = 1000; /* default FileInfoTimeout for FUSE file systems */
|
||||||
|
|
||||||
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
||||||
return 0;
|
return 0;
|
||||||
if (opt_data.help)
|
if (opt_data.help)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (opt_data.debug)
|
||||||
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE == opt_data.DebugLogHandle)
|
||||||
|
{
|
||||||
|
ErrorMessage = L": cannot open debug log file.";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
FspDebugLogSetHandle(opt_data.DebugLogHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((opt_data.set_uid && -1 == opt_data.uid) ||
|
||||||
|
(opt_data.set_gid && -1 == opt_data.gid))
|
||||||
|
{
|
||||||
|
HANDLE Token;
|
||||||
|
|
||||||
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
|
||||||
|
{
|
||||||
|
fsp_fuse_get_token_uidgid(Token, TokenUser,
|
||||||
|
opt_data.set_uid && -1 == opt_data.uid ? &opt_data.uid : 0,
|
||||||
|
opt_data.set_gid && -1 == opt_data.gid ? &opt_data.gid : 0);
|
||||||
|
|
||||||
|
CloseHandle(Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((opt_data.set_uid && -1 == opt_data.uid) ||
|
||||||
|
(opt_data.set_gid && -1 == opt_data.gid))
|
||||||
|
{
|
||||||
|
ErrorMessage = L": unknown user/group.";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!opt_data.set_FileInfoTimeout && opt_data.set_attr_timeout)
|
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.set_attr_timeout * 1000;
|
||||||
opt_data.VolumeParams.CaseSensitiveSearch = !opt_data.CaseInsensitiveSearch;
|
opt_data.VolumeParams.CaseSensitiveSearch = TRUE;
|
||||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||||
opt_data.VolumeParams.ReparsePoints = TRUE;
|
opt_data.VolumeParams.ReparsePoints = TRUE;
|
||||||
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
||||||
opt_data.VolumeParams.NamedStreams = FALSE;
|
opt_data.VolumeParams.NamedStreams = FALSE;
|
||||||
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
opt_data.VolumeParams.ReadOnlyVolume = FALSE;
|
||||||
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
||||||
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
||||||
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||||
@ -541,6 +603,8 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
f->data = data;
|
f->data = data;
|
||||||
f->DebugLog = opt_data.debug ? -1 : 0;
|
f->DebugLog = opt_data.debug ? -1 : 0;
|
||||||
memcpy(&f->VolumeParams, &opt_data.VolumeParams, sizeof opt_data.VolumeParams);
|
memcpy(&f->VolumeParams, &opt_data.VolumeParams, sizeof opt_data.VolumeParams);
|
||||||
|
f->VolumeLabelLength = opt_data.VolumeLabelLength;
|
||||||
|
memcpy(&f->VolumeLabel, &opt_data.VolumeLabel, opt_data.VolumeLabelLength);
|
||||||
|
|
||||||
Size = (lstrlenW(ch->MountPoint) + 1) * sizeof(WCHAR);
|
Size = (lstrlenW(ch->MountPoint) + 1) * sizeof(WCHAR);
|
||||||
f->MountPoint = fsp_fuse_obj_alloc(env, Size);
|
f->MountPoint = fsp_fuse_obj_alloc(env, Size);
|
||||||
@ -548,7 +612,9 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
goto fail;
|
goto fail;
|
||||||
memcpy(f->MountPoint, ch->MountPoint, Size);
|
memcpy(f->MountPoint, ch->MountPoint, Size);
|
||||||
|
|
||||||
Result = fsp_fuse_preflight(f);
|
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);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
switch (Result)
|
switch (Result)
|
||||||
|
35
src/dll/fuse/fuse_compat.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/fuse/fuse_compat.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2017 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 `fuse_*` symbols. This
|
||||||
|
* implementation is a simple shim that forwards `fuse_*` calls to the
|
||||||
|
* equivalent `fsp_fuse_*` 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_fuse_*` 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 <fuse/fuse_common.h>
|
||||||
|
#include <fuse/fuse.h>
|
||||||
|
#include <fuse/fuse_opt.h>
|
@ -116,19 +116,6 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PWSTR FileName = 0, Suffix;
|
PWSTR FileName = 0, Suffix;
|
||||||
WCHAR Root[2] = L"\\";
|
WCHAR Root[2] = L"\\";
|
||||||
HANDLE Token = 0;
|
HANDLE Token = 0;
|
||||||
union
|
|
||||||
{
|
|
||||||
TOKEN_USER V;
|
|
||||||
UINT8 B[128];
|
|
||||||
} UserInfoBuf;
|
|
||||||
PTOKEN_USER UserInfo = &UserInfoBuf.V;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
TOKEN_PRIMARY_GROUP V;
|
|
||||||
UINT8 B[128];
|
|
||||||
} GroupInfoBuf;
|
|
||||||
PTOKEN_PRIMARY_GROUP GroupInfo = &GroupInfoBuf.V;
|
|
||||||
DWORD Size;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
@ -157,55 +144,7 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (0 != Token)
|
if (0 != Token)
|
||||||
{
|
{
|
||||||
if (!GetTokenInformation(Token, TokenUser, UserInfo, sizeof UserInfoBuf, &Size))
|
Result = fsp_fuse_get_token_uidgid(Token, TokenUser, &Uid, &Gid);
|
||||||
{
|
|
||||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserInfo = MemAlloc(Size);
|
|
||||||
if (0 == UserInfo)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetTokenInformation(Token, TokenUser, UserInfo, Size, &Size))
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, sizeof GroupInfoBuf, &Size))
|
|
||||||
{
|
|
||||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupInfo = MemAlloc(Size);
|
|
||||||
if (0 == UserInfo)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, Size, &Size))
|
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = FspPosixMapSidToUid(UserInfo->User.Sid, &Uid);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
Result = FspPosixMapSidToUid(GroupInfo->PrimaryGroup, &Gid);
|
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -230,12 +169,6 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (UserInfo != &UserInfoBuf.V)
|
|
||||||
MemFree(UserInfo);
|
|
||||||
|
|
||||||
if (GroupInfo != &GroupInfoBuf.V)
|
|
||||||
MemFree(GroupInfo);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Result) && 0 != PosixPath)
|
if (!NT_SUCCESS(Result) && 0 != PosixPath)
|
||||||
FspPosixDeletePath(PosixPath);
|
FspPosixDeletePath(PosixPath);
|
||||||
|
|
||||||
@ -378,28 +311,34 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
||||||
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, PUid, PGid, PMode, 0, FileInfo)
|
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0, PUid, PGid, PMode, 0, FileInfo)
|
||||||
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
||||||
const char *PosixPath, struct fuse_file_info *fi,
|
const char *PosixPath, struct fuse_file_info *fi, const struct fuse_stat *stbufp,
|
||||||
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode, PUINT32 PDev,
|
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode, PUINT32 PDev,
|
||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
UINT64 AllocationUnit;
|
UINT64 AllocationUnit;
|
||||||
struct fuse_stat stbuf;
|
struct fuse_stat stbuf;
|
||||||
int err;
|
|
||||||
|
|
||||||
memset(&stbuf, 0, sizeof stbuf);
|
if (0 != stbufp)
|
||||||
|
memcpy(&stbuf, stbufp, sizeof stbuf);
|
||||||
if (0 != f->ops.fgetattr && 0 != fi && -1 != fi->fh)
|
|
||||||
err = f->ops.fgetattr(PosixPath, (void *)&stbuf, fi);
|
|
||||||
else if (0 != f->ops.getattr)
|
|
||||||
err = f->ops.getattr(PosixPath, (void *)&stbuf);
|
|
||||||
else
|
else
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
if (0 != err)
|
memset(&stbuf, 0, sizeof stbuf);
|
||||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
|
||||||
|
if (0 != f->ops.fgetattr && 0 != fi && -1 != fi->fh)
|
||||||
|
err = f->ops.fgetattr(PosixPath, (void *)&stbuf, fi);
|
||||||
|
else if (0 != f->ops.getattr)
|
||||||
|
err = f->ops.getattr(PosixPath, (void *)&stbuf);
|
||||||
|
else
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
if (0 != err)
|
||||||
|
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
}
|
||||||
|
|
||||||
if (f->set_umask)
|
if (f->set_umask)
|
||||||
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
||||||
@ -580,7 +519,7 @@ static NTSTATUS fsp_fuse_intf_GetReparsePointEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SIZE_T Size;
|
SIZE_T Size;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi,
|
Result = fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0,
|
||||||
&Uid, &Gid, &Mode, &Dev, &FileInfo);
|
&Uid, &Gid, &Mode, &Dev, &FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -697,18 +636,18 @@ static NTSTATUS fsp_fuse_intf_GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
struct fuse_statvfs stbuf;
|
struct fuse_statvfs stbuf;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (0 == f->ops.statfs)
|
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
|
|
||||||
memset(&stbuf, 0, sizeof stbuf);
|
memset(&stbuf, 0, sizeof stbuf);
|
||||||
err = f->ops.statfs("/", &stbuf);
|
if (0 != f->ops.statfs)
|
||||||
if (0 != err)
|
{
|
||||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
err = f->ops.statfs("/", &stbuf);
|
||||||
|
if (0 != err)
|
||||||
|
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
}
|
||||||
|
|
||||||
VolumeInfo->TotalSize = (UINT64)stbuf.f_blocks * (UINT64)stbuf.f_frsize;
|
VolumeInfo->TotalSize = (UINT64)stbuf.f_blocks * (UINT64)stbuf.f_frsize;
|
||||||
VolumeInfo->FreeSize = (UINT64)stbuf.f_bfree * (UINT64)stbuf.f_frsize;
|
VolumeInfo->FreeSize = (UINT64)stbuf.f_bfree * (UINT64)stbuf.f_frsize;
|
||||||
VolumeInfo->VolumeLabelLength = 0;
|
VolumeInfo->VolumeLabelLength = f->VolumeLabelLength;
|
||||||
VolumeInfo->VolumeLabel[0] = L'\0';
|
memcpy(&VolumeInfo->VolumeLabel, &f->VolumeLabel, f->VolumeLabelLength);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -882,7 +821,6 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->OpenFlags = fi.flags;
|
filedesc->OpenFlags = fi.flags;
|
||||||
filedesc->FileHandle = fi.fh;
|
filedesc->FileHandle = fi.fh;
|
||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
filedesc->DirBufferSize = 0;
|
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -1000,7 +938,6 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->OpenFlags = fi.flags;
|
filedesc->OpenFlags = fi.flags;
|
||||||
filedesc->FileHandle = fi.fh;
|
filedesc->FileHandle = fi.fh;
|
||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
filedesc->DirBufferSize = 0;
|
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -1113,7 +1050,7 @@ static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
f->ops.release(filedesc->PosixPath, &fi);
|
f->ops.release(filedesc->PosixPath, &fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemFree(filedesc->DirBuffer);
|
FspFileSystemDeleteDirectoryBuffer(&filedesc->DirBuffer);
|
||||||
MemFree(filedesc->PosixPath);
|
MemFree(filedesc->PosixPath);
|
||||||
MemFree(filedesc);
|
MemFree(filedesc);
|
||||||
}
|
}
|
||||||
@ -1459,7 +1396,13 @@ static NTSTATUS fsp_fuse_intf_CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memset(&dh, 0, sizeof dh);
|
memset(&dh, 0, sizeof dh);
|
||||||
|
|
||||||
if (0 != f->ops.readdir)
|
if (0 != f->ops.readdir)
|
||||||
|
{
|
||||||
|
memset(&fi, 0, sizeof fi);
|
||||||
|
fi.flags = filedesc->OpenFlags;
|
||||||
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfo, 0, &fi);
|
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfo, 0, &fi);
|
||||||
|
}
|
||||||
else if (0 != f->ops.getdir)
|
else if (0 != f->ops.getdir)
|
||||||
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfoOld);
|
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_CanDeleteAddDirInfoOld);
|
||||||
else
|
else
|
||||||
@ -1496,7 +1439,8 @@ static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
STATUS_OBJECT_PATH_NOT_FOUND != Result)
|
STATUS_OBJECT_PATH_NOT_FOUND != Result)
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result) &&
|
||||||
|
(f->VolumeParams.CaseSensitiveSearch || 0 != invariant_wcsicmp(FileName, NewFileName)))
|
||||||
{
|
{
|
||||||
if (!ReplaceIfExists)
|
if (!ReplaceIfExists)
|
||||||
return STATUS_OBJECT_NAME_COLLISION;
|
return STATUS_OBJECT_NAME_COLLISION;
|
||||||
@ -1603,185 +1547,111 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||||
{
|
{
|
||||||
struct fuse_dirhandle *dh = buf;
|
struct fuse_dirhandle *dh = buf;
|
||||||
struct fsp_fuse_dirinfo *di;
|
struct fsp_fuse_file_desc *filedesc = dh->filedesc;
|
||||||
ULONG len, xfersize;
|
|
||||||
|
|
||||||
len = lstrlenA(name);
|
|
||||||
if (len > 255)
|
|
||||||
len = 255;
|
|
||||||
|
|
||||||
di = (PVOID)((PUINT8)dh->Buffer + dh->BytesTransferred);
|
|
||||||
xfersize = FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(struct fsp_fuse_dirinfo) + len + 1);
|
|
||||||
|
|
||||||
if ((PUINT8)di + xfersize > (PUINT8)dh->Buffer + dh->Length)
|
|
||||||
{
|
|
||||||
PVOID Buffer;
|
|
||||||
ULONG Length = dh->Length;
|
|
||||||
|
|
||||||
if (0 == Length)
|
|
||||||
Length = 16 * 1024;
|
|
||||||
else if (Length < 16 * 1024 * 1024)
|
|
||||||
Length *= 2;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
Buffer = MemAlloc(Length);
|
|
||||||
if (0 == Buffer)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
memcpy(Buffer, dh->Buffer, dh->BytesTransferred);
|
|
||||||
MemFree(dh->Buffer);
|
|
||||||
|
|
||||||
dh->Buffer = Buffer;
|
|
||||||
dh->Length = Length;
|
|
||||||
|
|
||||||
di = (PVOID)((PUINT8)dh->Buffer + dh->BytesTransferred);
|
|
||||||
}
|
|
||||||
|
|
||||||
dh->BytesTransferred += xfersize;
|
|
||||||
dh->NonZeroOffset = dh->NonZeroOffset || 0 != off;
|
|
||||||
|
|
||||||
di->Size = (UINT16)(sizeof(struct fsp_fuse_dirinfo) + len + 1);
|
|
||||||
di->FileInfoValid = FALSE;
|
|
||||||
di->NextOffset = 0 != off ? off : dh->BytesTransferred;
|
|
||||||
memcpy(di->PosixNameBuf, name, len);
|
|
||||||
di->PosixNameBuf[len] = '\0';
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
|
|
||||||
int type, fuse_ino_t ino)
|
|
||||||
{
|
|
||||||
return fsp_fuse_intf_AddDirInfo(dh, name, 0, 0) ? -ENOMEM : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|
||||||
PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length,
|
|
||||||
PWSTR Pattern,
|
|
||||||
PULONG PBytesTransferred)
|
|
||||||
{
|
|
||||||
struct fuse *f = FileSystem->UserContext;
|
|
||||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
|
||||||
struct fuse_file_info fi;
|
|
||||||
struct fuse_dirhandle dh;
|
|
||||||
struct fsp_fuse_dirinfo *di;
|
|
||||||
PUINT8 diend;
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
FSP_FSCTL_DIR_INFO V;
|
FSP_FSCTL_DIR_INFO V;
|
||||||
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + 255 * sizeof(WCHAR)];
|
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + 255 * sizeof(WCHAR)];
|
||||||
} DirInfoBuf;
|
} DirInfoBuf;
|
||||||
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.V;
|
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.V;
|
||||||
UINT32 Uid, Gid, Mode;
|
ULONG SizeA, SizeW;
|
||||||
|
|
||||||
|
if ('/' == filedesc->PosixPath[0] && '\0' == filedesc->PosixPath[1])
|
||||||
|
{
|
||||||
|
/* if this is the root directory do not add the dot entries */
|
||||||
|
|
||||||
|
if ('.' == name[0] && ('\0' == name[1] ||
|
||||||
|
('.' == name[1] && '\0' == name[2])))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeA = lstrlenA(name);
|
||||||
|
if (SizeA > 255)
|
||||||
|
/* ignore bad filenames; should we return error code? */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
SizeW = MultiByteToWideChar(CP_UTF8, 0, name, SizeA, DirInfo->FileNameBuf, 255);
|
||||||
|
if (0 == SizeW)
|
||||||
|
/* ignore bad filenames; should we return error code? */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset(DirInfo, 0, sizeof *DirInfo);
|
||||||
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + SizeW * sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (dh->ReaddirPlus && 0 != stbuf)
|
||||||
|
{
|
||||||
|
UINT32 Uid, Gid, Mode;
|
||||||
|
NTSTATUS Result0;
|
||||||
|
|
||||||
|
Result0 = fsp_fuse_intf_GetFileInfoFunnel(dh->FileSystem, 0, 0, stbuf,
|
||||||
|
&Uid, &Gid, &Mode, 0, &DirInfo->FileInfo);
|
||||||
|
if (NT_SUCCESS(Result0))
|
||||||
|
DirInfo->Padding[0] = 1; /* HACK: remember that the FileInfo is valid */
|
||||||
|
}
|
||||||
|
|
||||||
|
return !FspFileSystemFillDirectoryBuffer(&filedesc->DirBuffer, DirInfo, &dh->Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
|
||||||
|
int type, fuse_ino_t ino)
|
||||||
|
{
|
||||||
|
return fsp_fuse_intf_AddDirInfo(dh, name, 0, 0) ? -ENOMEM : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS fsp_fuse_intf_FixDirInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
struct fsp_fuse_file_desc *filedesc)
|
||||||
|
{
|
||||||
char *PosixPath = 0, *PosixName, *PosixPathEnd, SavedPathChar;
|
char *PosixPath = 0, *PosixName, *PosixPathEnd, SavedPathChar;
|
||||||
PWSTR FileName = 0;
|
ULONG SizeA, SizeW;
|
||||||
ULONG Size;
|
PUINT8 Buffer;
|
||||||
int err;
|
PULONG Index, IndexEnd;
|
||||||
|
ULONG Count;
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo;
|
||||||
|
UINT32 Uid, Gid, Mode;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (!filedesc->IsDirectory)
|
SizeA = lstrlenA(filedesc->PosixPath);
|
||||||
return STATUS_ACCESS_DENIED;
|
PosixPath = MemAlloc(SizeA + 1 + 255 + 1);
|
||||||
|
if (0 == PosixPath)
|
||||||
memset(&dh, 0, sizeof dh);
|
|
||||||
|
|
||||||
if (0 == filedesc->DirBuffer)
|
|
||||||
{
|
{
|
||||||
if (0 != f->ops.readdir)
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
{
|
goto exit;
|
||||||
memset(&fi, 0, sizeof fi);
|
}
|
||||||
fi.flags = filedesc->OpenFlags;
|
|
||||||
fi.fh = filedesc->FileHandle;
|
|
||||||
|
|
||||||
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, Offset, &fi);
|
memcpy(PosixPath, filedesc->PosixPath, SizeA);
|
||||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
if (1 < SizeA)
|
||||||
}
|
/* if not root */
|
||||||
else if (0 != f->ops.getdir)
|
PosixPath[SizeA++] = '/';
|
||||||
{
|
PosixPath[SizeA] = '\0';
|
||||||
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfoOld);
|
PosixName = PosixPath + SizeA;
|
||||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Result = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Result))
|
FspFileSystemPeekInDirectoryBuffer(&filedesc->DirBuffer, &Buffer, &Index, &Count);
|
||||||
goto exit;
|
|
||||||
|
|
||||||
if (0 == dh.BytesTransferred)
|
for (IndexEnd = Index + Count; IndexEnd > Index; Index++)
|
||||||
|
{
|
||||||
|
DirInfo = (FSP_FSCTL_DIR_INFO *)(Buffer + *Index);
|
||||||
|
SizeW = (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (DirInfo->Padding[0])
|
||||||
{
|
{
|
||||||
/* EOF */
|
/* DirInfo has been filled already! */
|
||||||
*PBytesTransferred = 0;
|
|
||||||
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
DirInfo->Padding[0] = 0;
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
else if (dh.NonZeroOffset)
|
|
||||||
{
|
|
||||||
di = (PVOID)((PUINT8)dh.Buffer + 0);
|
|
||||||
diend = (PUINT8)dh.Buffer + dh.BytesTransferred;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
di = (PVOID)((PUINT8)dh.Buffer + Offset);
|
if (1 == SizeW && L'.' == DirInfo->FileNameBuf[0])
|
||||||
diend = (PUINT8)dh.Buffer + dh.BytesTransferred;
|
|
||||||
filedesc->DirBuffer = dh.Buffer;
|
|
||||||
filedesc->DirBufferSize = dh.BytesTransferred;
|
|
||||||
dh.Buffer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
di = (PVOID)((PUINT8)filedesc->DirBuffer + Offset);
|
|
||||||
diend = (PUINT8)filedesc->DirBuffer + filedesc->DirBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;
|
|
||||||
(PUINT8)di + sizeof(di->Size) <= diend;
|
|
||||||
di = (PVOID)((PUINT8)di + FSP_FSCTL_DEFAULT_ALIGN_UP(di->Size)))
|
|
||||||
{
|
|
||||||
if (sizeof(struct fsp_fuse_dirinfo) > di->Size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ('/' == filedesc->PosixPath[0] && '\0' == filedesc->PosixPath[1])
|
|
||||||
{
|
|
||||||
/* if this is the root directory do not add the dot entries */
|
|
||||||
|
|
||||||
if ('.' == di->PosixNameBuf[0] && ('\0' == di->PosixNameBuf[1] ||
|
|
||||||
('.' == di->PosixNameBuf[1] && '\0' == di->PosixNameBuf[2])))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!di->FileInfoValid)
|
|
||||||
{
|
|
||||||
if (0 == PosixPath)
|
|
||||||
{
|
|
||||||
Size = lstrlenA(filedesc->PosixPath);
|
|
||||||
PosixPath = MemAlloc(Size + 1 + 255 + 1);
|
|
||||||
if (0 == PosixPath)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(PosixPath, filedesc->PosixPath, Size);
|
|
||||||
if (1 < Size)
|
|
||||||
/* if not root */
|
|
||||||
PosixPath[Size++] = '/';
|
|
||||||
PosixPath[Size] = '\0';
|
|
||||||
PosixName = PosixPath + Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('.' == di->PosixNameBuf[0] && '\0' == di->PosixNameBuf[1])
|
|
||||||
{
|
{
|
||||||
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 1 : PosixName;
|
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 1 : PosixName;
|
||||||
SavedPathChar = *PosixPathEnd;
|
SavedPathChar = *PosixPathEnd;
|
||||||
*PosixPathEnd = '\0';
|
*PosixPathEnd = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if ('.' == di->PosixNameBuf[0] && '.' == di->PosixNameBuf[1] && '\0' == di->PosixNameBuf[2])
|
if (2 == SizeW && L'.' == DirInfo->FileNameBuf[0] && L'.' == DirInfo->FileNameBuf[1])
|
||||||
{
|
{
|
||||||
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
|
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
|
||||||
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
|
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
|
||||||
@ -1794,58 +1664,91 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PosixPathEnd = 0;
|
PosixPathEnd = 0;
|
||||||
Size = lstrlenA(di->PosixNameBuf);
|
SizeA = WideCharToMultiByte(CP_UTF8, 0, DirInfo->FileNameBuf, SizeW, PosixName, 255, 0, 0);
|
||||||
if (Size > 255)
|
if (0 == SizeA)
|
||||||
Size = 255;
|
{
|
||||||
memcpy(PosixName, di->PosixNameBuf, Size);
|
/* this should never happen because we just converted using MultiByteToWideChar */
|
||||||
PosixName[Size] = '\0';
|
Result = STATUS_OBJECT_NAME_INVALID;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
PosixName[SizeA] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, 0,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, 0,
|
||||||
&Uid, &Gid, &Mode, &di->FileInfo);
|
&Uid, &Gid, &Mode, &DirInfo->FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (0 != PosixPathEnd)
|
if (0 != PosixPathEnd)
|
||||||
*PosixPathEnd = SavedPathChar;
|
*PosixPathEnd = SavedPathChar;
|
||||||
|
|
||||||
di->FileInfoValid = TRUE;
|
|
||||||
}
|
}
|
||||||
memcpy(&DirInfo->FileInfo, &di->FileInfo, sizeof di->FileInfo);
|
|
||||||
|
|
||||||
Result = FspPosixMapPosixToWindowsPath(di->PosixNameBuf, &FileName);
|
FspPosixDecodeWindowsPath(DirInfo->FileNameBuf, SizeW);
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
Size = lstrlenW(FileName);
|
|
||||||
if (Size > 255)
|
|
||||||
Size = 255;
|
|
||||||
Size *= sizeof(WCHAR);
|
|
||||||
memcpy(DirInfo->FileNameBuf, FileName, Size);
|
|
||||||
|
|
||||||
FspPosixDeletePath(FileName);
|
|
||||||
|
|
||||||
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + Size);
|
|
||||||
DirInfo->NextOffset = di->NextOffset;
|
|
||||||
|
|
||||||
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((PUINT8)di + sizeof(di->Size) > diend)
|
|
||||||
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
|
||||||
|
|
||||||
success:
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
MemFree(PosixPath);
|
MemFree(PosixPath);
|
||||||
MemFree(dh.Buffer);
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileNode, PWSTR Pattern, PWSTR Marker,
|
||||||
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
|
{
|
||||||
|
struct fuse *f = FileSystem->UserContext;
|
||||||
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
|
struct fuse_dirhandle dh;
|
||||||
|
struct fuse_file_info fi;
|
||||||
|
int err;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (FspFileSystemAcquireDirectoryBuffer(&filedesc->DirBuffer, 0 == Marker, &Result))
|
||||||
|
{
|
||||||
|
memset(&dh, 0, sizeof dh);
|
||||||
|
dh.filedesc = filedesc;
|
||||||
|
dh.FileSystem = FileSystem;
|
||||||
|
dh.ReaddirPlus = 0 != (f->conn_want & FSP_FUSE_CAP_READDIR_PLUS);
|
||||||
|
dh.Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (0 != f->ops.readdir)
|
||||||
|
{
|
||||||
|
memset(&fi, 0, sizeof fi);
|
||||||
|
fi.flags = filedesc->OpenFlags;
|
||||||
|
fi.fh = filedesc->FileHandle;
|
||||||
|
|
||||||
|
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, 0, &fi);
|
||||||
|
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
}
|
||||||
|
else if (0 != f->ops.getdir)
|
||||||
|
{
|
||||||
|
err = f->ops.getdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfoOld);
|
||||||
|
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = dh.Result;
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
Result = fsp_fuse_intf_FixDirInfo(FileSystem, filedesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileSystemReleaseDirectoryBuffer(&filedesc->DirBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
FspFileSystemReadDirectoryBuffer(&filedesc->DirBuffer,
|
||||||
|
Marker, Buffer, Length, PBytesTransferred);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent,
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent,
|
||||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
@ -2120,3 +2023,140 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
|||||||
fsp_fuse_intf_SetReparsePoint,
|
fsp_fuse_intf_SetReparsePoint,
|
||||||
fsp_fuse_intf_DeleteReparsePoint,
|
fsp_fuse_intf_DeleteReparsePoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility
|
||||||
|
*/
|
||||||
|
NTSTATUS fsp_fuse_get_token_uidgid(
|
||||||
|
HANDLE Token,
|
||||||
|
TOKEN_INFORMATION_CLASS UserOrOwnerClass, /* TokenUser|TokenOwner */
|
||||||
|
PUINT32 PUid, PUINT32 PGid)
|
||||||
|
{
|
||||||
|
UINT32 Uid, Gid;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
TOKEN_USER V;
|
||||||
|
UINT8 B[128];
|
||||||
|
} UserInfoBuf;
|
||||||
|
PTOKEN_USER UserInfo = &UserInfoBuf.V;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
TOKEN_OWNER V;
|
||||||
|
UINT8 B[128];
|
||||||
|
} OwnerInfoBuf;
|
||||||
|
PTOKEN_OWNER OwnerInfo = &OwnerInfoBuf.V;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
TOKEN_PRIMARY_GROUP V;
|
||||||
|
UINT8 B[128];
|
||||||
|
} GroupInfoBuf;
|
||||||
|
PTOKEN_PRIMARY_GROUP GroupInfo = &GroupInfoBuf.V;
|
||||||
|
DWORD Size;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 != PUid && TokenUser == UserOrOwnerClass)
|
||||||
|
{
|
||||||
|
if (!GetTokenInformation(Token, TokenUser, UserInfo, sizeof UserInfoBuf, &Size))
|
||||||
|
{
|
||||||
|
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInfo = MemAlloc(Size);
|
||||||
|
if (0 == UserInfo)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetTokenInformation(Token, TokenUser, UserInfo, Size, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspPosixMapSidToUid(UserInfo->User.Sid, &Uid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else if (0 != PUid && TokenOwner == UserOrOwnerClass)
|
||||||
|
{
|
||||||
|
if (!GetTokenInformation(Token, TokenOwner, OwnerInfo, sizeof OwnerInfoBuf, &Size))
|
||||||
|
{
|
||||||
|
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
OwnerInfo = MemAlloc(Size);
|
||||||
|
if (0 == OwnerInfo)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetTokenInformation(Token, TokenOwner, OwnerInfo, Size, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspPosixMapSidToUid(OwnerInfo->Owner, &Uid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != PGid)
|
||||||
|
{
|
||||||
|
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, sizeof GroupInfoBuf, &Size))
|
||||||
|
{
|
||||||
|
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupInfo = MemAlloc(Size);
|
||||||
|
if (0 == GroupInfo)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, Size, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspPosixMapSidToUid(GroupInfo->PrimaryGroup, &Gid);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != PUid)
|
||||||
|
*PUid = Uid;
|
||||||
|
|
||||||
|
if (0 != PGid)
|
||||||
|
*PGid = Gid;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (UserInfo != &UserInfoBuf.V)
|
||||||
|
MemFree(UserInfo);
|
||||||
|
|
||||||
|
if (OwnerInfo != &OwnerInfoBuf.V)
|
||||||
|
MemFree(OwnerInfo);
|
||||||
|
|
||||||
|
if (GroupInfo != &GroupInfoBuf.V)
|
||||||
|
MemFree(GroupInfo);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
@ -40,12 +40,15 @@ struct fuse
|
|||||||
int rellinks;
|
int rellinks;
|
||||||
struct fuse_operations ops;
|
struct fuse_operations ops;
|
||||||
void *data;
|
void *data;
|
||||||
|
unsigned conn_want;
|
||||||
|
BOOLEAN fsinit;
|
||||||
UINT32 DebugLog;
|
UINT32 DebugLog;
|
||||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
|
UINT16 VolumeLabelLength;
|
||||||
|
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||||
PWSTR MountPoint;
|
PWSTR MountPoint;
|
||||||
FSP_FILE_SYSTEM *FileSystem;
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
BOOLEAN fsinit;
|
|
||||||
FSP_SERVICE *Service; /* weak */
|
FSP_SERVICE *Service; /* weak */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,27 +65,19 @@ struct fsp_fuse_file_desc
|
|||||||
int OpenFlags;
|
int OpenFlags;
|
||||||
UINT64 FileHandle;
|
UINT64 FileHandle;
|
||||||
PVOID DirBuffer;
|
PVOID DirBuffer;
|
||||||
ULONG DirBufferSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_dirhandle
|
struct fuse_dirhandle
|
||||||
{
|
{
|
||||||
PVOID Buffer;
|
/* ReadDirectory */
|
||||||
ULONG Length;
|
struct fsp_fuse_file_desc *filedesc;
|
||||||
ULONG BytesTransferred;
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
BOOLEAN NonZeroOffset;
|
BOOLEAN ReaddirPlus;
|
||||||
|
NTSTATUS Result;
|
||||||
|
/* CanDelete */
|
||||||
BOOLEAN DotFiles, HasChild;
|
BOOLEAN DotFiles, HasChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fsp_fuse_dirinfo
|
|
||||||
{
|
|
||||||
UINT16 Size;
|
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
|
||||||
BOOLEAN FileInfoValid;
|
|
||||||
UINT64 NextOffset;
|
|
||||||
char PosixNameBuf[]; /* includes term-0 (unlike FSP_FSCTL_DIR_INFO) */
|
|
||||||
};
|
|
||||||
|
|
||||||
NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -90,6 +85,11 @@ NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf;
|
extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf;
|
||||||
|
|
||||||
|
NTSTATUS fsp_fuse_get_token_uidgid(
|
||||||
|
HANDLE Token,
|
||||||
|
TOKEN_INFORMATION_CLASS UserOrOwnerClass, /* TokenUser|TokenOwner */
|
||||||
|
PUINT32 PUid, PUINT32 PGid);
|
||||||
|
|
||||||
/* NFS reparse points */
|
/* NFS reparse points */
|
||||||
|
|
||||||
#define NFS_SPECFILE_FIFO 0x000000004F464946
|
#define NFS_SPECFILE_FIFO 0x000000004F464946
|
||||||
|
@ -51,6 +51,9 @@ NTSTATUS FspEventLogUnregister(VOID);
|
|||||||
|
|
||||||
PWSTR FspDiagIdent(VOID);
|
PWSTR FspDiagIdent(VOID);
|
||||||
|
|
||||||
|
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount);
|
||||||
|
|
||||||
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
|
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
|
||||||
|
|
||||||
static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
||||||
@ -73,7 +76,7 @@ static inline BOOLEAN FspPathIsDrive(PWSTR FileName)
|
|||||||
(L'A' <= FileName[0] && FileName[0] <= L'Z') ||
|
(L'A' <= FileName[0] && FileName[0] <= L'Z') ||
|
||||||
(L'a' <= FileName[0] && FileName[0] <= L'z')
|
(L'a' <= FileName[0] && FileName[0] <= L'z')
|
||||||
) &&
|
) &&
|
||||||
L':' == FileName[1] || L'\0' == FileName[2];
|
L':' == FileName[1] && L'\0' == FileName[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
61
src/dll/np.c
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
||||||
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
||||||
|
#define FSP_NP_ADDCONNECTION_TIMEOUT 15000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the following macro to use CredUIPromptForWindowsCredentials.
|
* Define the following macro to use CredUIPromptForWindowsCredentials.
|
||||||
@ -283,7 +284,8 @@ static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
|||||||
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
||||||
ClassNameBuf[ClassNameLen] = '\0';
|
ClassNameBuf[ClassNameLen] = '\0';
|
||||||
|
|
||||||
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY, 0, KEY_READ, &RegKey);
|
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||||
|
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||||
if (ERROR_SUCCESS != NpResult)
|
if (ERROR_SUCCESS != NpResult)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -583,6 +585,63 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
|||||||
switch (NpResult)
|
switch (NpResult)
|
||||||
{
|
{
|
||||||
case WN_SUCCESS:
|
case WN_SUCCESS:
|
||||||
|
/*
|
||||||
|
* The Launcher is reporting success. Wait until we can access the new volume
|
||||||
|
* root directory. If we see it report success, otherwise report error.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
WCHAR RemoteNameBuf[9 + sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
HANDLE Handle;
|
||||||
|
|
||||||
|
if (L'\0' != LocalNameBuf[0])
|
||||||
|
{
|
||||||
|
P = RemoteNameBuf;
|
||||||
|
*P++ = L'\\'; *P++ = L'\\'; *P++ = L'?'; *P++ = L'\\';
|
||||||
|
*P++ = LocalNameBuf[0]; *P++ = L':'; *P++ = L'\\';
|
||||||
|
*P++ = L'\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P = RemoteNameBuf;
|
||||||
|
*P++ = L'\\'; *P++ = L'\\'; *P++ = L'?'; *P++ = L'\\';
|
||||||
|
*P++ = L'U'; *P++ = L'N'; *P++ = L'C'; *P++ = L'\\';
|
||||||
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\\';
|
||||||
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\\';
|
||||||
|
*P++ = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = WN_NO_NETWORK; /* timeout error */
|
||||||
|
|
||||||
|
for (ULONG I = 0, N = 1 + FSP_NP_ADDCONNECTION_TIMEOUT / 500; N > I; I++)
|
||||||
|
{
|
||||||
|
if (0 != I)
|
||||||
|
Sleep(500);
|
||||||
|
|
||||||
|
Handle = CreateFileW(RemoteNameBuf,
|
||||||
|
FILE_READ_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE != Handle)
|
||||||
|
{
|
||||||
|
/* the file system is up and running */
|
||||||
|
CloseHandle(Handle);
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceInfo;
|
||||||
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||||
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||||
|
|
||||||
|
if (WN_SUCCESS != FspNpCallLauncherPipe(
|
||||||
|
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE))
|
||||||
|
{
|
||||||
|
/* looks like the file system is gone! */
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WN_ACCESS_DENIED:
|
case WN_ACCESS_DENIED:
|
||||||
break;
|
break;
|
||||||
case ERROR_ALREADY_EXISTS:
|
case ERROR_ALREADY_EXISTS:
|
||||||
|
@ -923,3 +923,30 @@ FSP_API VOID FspPosixDeletePath(void *Path)
|
|||||||
{
|
{
|
||||||
MemFree(Path);
|
MemFree(Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspPosixEncodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
||||||
|
{
|
||||||
|
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
|
||||||
|
{
|
||||||
|
WCHAR c = *p;
|
||||||
|
|
||||||
|
if (L'\\' == c)
|
||||||
|
*p = L'/';
|
||||||
|
/* encode characters in the Unicode private use area: U+F0XX -> XX */
|
||||||
|
else if (0xf000 <= c && c <= 0xf0ff)
|
||||||
|
*p &= ~0xf000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size)
|
||||||
|
{
|
||||||
|
for (PWSTR p = WindowsPath, endp = p + Size; endp > p; p++)
|
||||||
|
{
|
||||||
|
WCHAR c = *p;
|
||||||
|
|
||||||
|
if (L'/' == c)
|
||||||
|
*p = L'\\';
|
||||||
|
else if (128 > c && (FspPosixInvalidPathChars[c >> 5] & (0x80000000 >> (c & 0x1f))))
|
||||||
|
*p |= 0xf000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -79,7 +79,7 @@ FSP_API ULONG FspServiceRunEx(PWSTR ServiceName,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
L"The service %s cannot be created (Status=%lx).", Service->ServiceName, Result);
|
L"The service %s cannot be created (Status=%lx).", ServiceName, Result);
|
||||||
return FspWin32FromNtStatus(Result);
|
return FspWin32FromNtStatus(Result);
|
||||||
}
|
}
|
||||||
Service->UserContext = UserContext;
|
Service->UserContext = UserContext;
|
||||||
@ -92,7 +92,7 @@ FSP_API ULONG FspServiceRunEx(PWSTR ServiceName,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
L"The service %s has failed to run (Status=%lx).", Service->ServiceName, Result);
|
L"The service %s has failed to run (Status=%lx).", ServiceName, Result);
|
||||||
return FspWin32FromNtStatus(Result);
|
return FspWin32FromNtStatus(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,3 +163,49 @@ exit:
|
|||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspVersion(PUINT32 PVersion)
|
||||||
|
{
|
||||||
|
static UINT32 Version;
|
||||||
|
|
||||||
|
if (0 == Version)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This check is not thread-safe, but that should be ok.
|
||||||
|
* Two threads competing to read the version will read
|
||||||
|
* the same value from the Version resource.
|
||||||
|
*/
|
||||||
|
*PVersion = 0;
|
||||||
|
|
||||||
|
extern HINSTANCE DllInstance;
|
||||||
|
WCHAR ModuleFileName[MAX_PATH];
|
||||||
|
PVOID VersionInfo;
|
||||||
|
DWORD Size;
|
||||||
|
VS_FIXEDFILEINFO *FixedFileInfo = 0;
|
||||||
|
|
||||||
|
if (0 != GetModuleFileNameW(DllInstance, ModuleFileName, MAX_PATH))
|
||||||
|
{
|
||||||
|
Size = GetFileVersionInfoSizeW(ModuleFileName, &Size/*dummy*/);
|
||||||
|
if (0 < Size)
|
||||||
|
{
|
||||||
|
VersionInfo = MemAlloc(Size);
|
||||||
|
if (0 != VersionInfo &&
|
||||||
|
GetFileVersionInfoW(ModuleFileName, 0, Size, VersionInfo) &&
|
||||||
|
VerQueryValueW(VersionInfo, L"\\", &FixedFileInfo, &Size))
|
||||||
|
{
|
||||||
|
/* 32-bit store should be atomic! */
|
||||||
|
Version = FixedFileInfo->dwFileVersionMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemFree(VersionInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == FixedFileInfo)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PVersion = Version;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
2364
src/dotnet/FileSystemBase+Const.cs
Normal file
1153
src/dotnet/FileSystemBase.cs
Normal file
1029
src/dotnet/FileSystemHost.cs
Normal file
1081
src/dotnet/Interop.cs
Normal file
187
src/dotnet/Service.cs
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* dotnet/Service.cs
|
||||||
|
*
|
||||||
|
* Copyright 2015-2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Fsp.Interop;
|
||||||
|
|
||||||
|
namespace Fsp
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides the base class for a process that can be run as a service,
|
||||||
|
/// command line application or under the control of the WinFsp launcher.
|
||||||
|
/// </summary>
|
||||||
|
public class Service
|
||||||
|
{
|
||||||
|
/* const */
|
||||||
|
public const UInt32 EVENTLOG_ERROR_TYPE = 0x0001;
|
||||||
|
public const UInt32 EVENTLOG_WARNING_TYPE = 0x0002;
|
||||||
|
public const UInt32 EVENTLOG_INFORMATION_TYPE = 0x0004;
|
||||||
|
|
||||||
|
/* ctor/dtor */
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of the Service class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ServiceName">The name of the service.</param>
|
||||||
|
public Service(String ServiceName)
|
||||||
|
{
|
||||||
|
Api.FspServiceCreate(ServiceName, _OnStart, _OnStop, null, out _ServicePtr);
|
||||||
|
if (IntPtr.Zero != _ServicePtr)
|
||||||
|
Api.SetUserContext(_ServicePtr, this);
|
||||||
|
}
|
||||||
|
~Service()
|
||||||
|
{
|
||||||
|
if (IntPtr.Zero != _ServicePtr)
|
||||||
|
{
|
||||||
|
Api.DisposeUserContext(_ServicePtr);
|
||||||
|
Api.FspServiceDelete(_ServicePtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* control */
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a service.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Service process exit code.</returns>
|
||||||
|
public int Run()
|
||||||
|
{
|
||||||
|
if (IntPtr.Zero == _ServicePtr)
|
||||||
|
{
|
||||||
|
const Int32 STATUS_INSUFFICIENT_RESOURCES = unchecked((Int32)0xc000009a);
|
||||||
|
Log(EVENTLOG_ERROR_TYPE,
|
||||||
|
String.Format("The service {0} cannot be created (Status={1:X}).",
|
||||||
|
GetType().FullName, STATUS_INSUFFICIENT_RESOURCES));
|
||||||
|
return (int)Api.FspWin32FromNtStatus(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
Api.FspServiceAllowConsoleMode(_ServicePtr);
|
||||||
|
Int32 Result = Api.FspServiceLoop(_ServicePtr);
|
||||||
|
int ExitCode = (int)Api.FspServiceGetExitCode(_ServicePtr);
|
||||||
|
if (0 > Result)
|
||||||
|
{
|
||||||
|
Log(EVENTLOG_ERROR_TYPE,
|
||||||
|
String.Format("The service {0} has failed to run (Status={1:X}).",
|
||||||
|
GetType().FullName, Result));
|
||||||
|
return (int)Api.FspWin32FromNtStatus(Result);
|
||||||
|
}
|
||||||
|
return ExitCode;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Stops a running service.
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
if (IntPtr.Zero == _ServicePtr)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
Api.FspServiceStop(_ServicePtr);
|
||||||
|
}
|
||||||
|
public void RequestTime(UInt32 Time)
|
||||||
|
{
|
||||||
|
if (IntPtr.Zero == _ServicePtr)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
Api.FspServiceRequestTime(_ServicePtr, Time);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the service process exit code.
|
||||||
|
/// </summary>
|
||||||
|
public int ExitCode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IntPtr.Zero == _ServicePtr)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
return (int)Api.FspServiceGetExitCode(_ServicePtr);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (IntPtr.Zero == _ServicePtr)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
Api.FspServiceSetExitCode(_ServicePtr, (UInt32)value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public IntPtr ServiceHandle
|
||||||
|
{
|
||||||
|
get { return _ServicePtr; }
|
||||||
|
}
|
||||||
|
public static void Log(UInt32 Type, String Message)
|
||||||
|
{
|
||||||
|
Api.FspServiceLog(Type, "%s", Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start/stop */
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a means to customize the returned status code when an exception happens.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ex"></param>
|
||||||
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
|
protected virtual Int32 ExceptionHandler(Exception ex)
|
||||||
|
{
|
||||||
|
return unchecked((Int32)0xE0434f4D)/*STATUS_CLR_EXCEPTION*/;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the service starts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Args">Command line arguments passed to the service.</param>
|
||||||
|
protected virtual void OnStart(String[] Args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the service stops.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnStop()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* callbacks */
|
||||||
|
private static Int32 OnStart(
|
||||||
|
IntPtr Service,
|
||||||
|
UInt32 Argc,
|
||||||
|
String[] Argv)
|
||||||
|
{
|
||||||
|
Service self = (Service)Api.GetUserContext(Service);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self.OnStart(
|
||||||
|
Argv);
|
||||||
|
return 0/*STATUS_SUCCESS*/;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return self.ExceptionHandler(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static Int32 OnStop(
|
||||||
|
IntPtr Service)
|
||||||
|
{
|
||||||
|
Service self = (Service)Api.GetUserContext(Service);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self.OnStop();
|
||||||
|
return 0/*STATUS_SUCCESS*/;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return self.ExceptionHandler(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Api.Proto.ServiceStart _OnStart = OnStart;
|
||||||
|
private static Api.Proto.ServiceStop _OnStop = OnStop;
|
||||||
|
private IntPtr _ServicePtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,7 +19,6 @@
|
|||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
|
|
||||||
#define PROGNAME "WinFsp.Launcher"
|
#define PROGNAME "WinFsp.Launcher"
|
||||||
#define REGKEY LAUNCHER_REGKEY
|
|
||||||
|
|
||||||
BOOL CreateOverlappedPipe(
|
BOOL CreateOverlappedPipe(
|
||||||
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
||||||
@ -441,7 +440,8 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" REGKEY, 0, KEY_READ, &RegKey);
|
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||||
|
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||||
if (ERROR_SUCCESS != RegResult)
|
if (ERROR_SUCCESS != RegResult)
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(RegResult);
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
#include <winfsp/winfsp.h>
|
#include <winfsp/winfsp.h>
|
||||||
#include <shared/minimal.h>
|
#include <shared/minimal.h>
|
||||||
|
|
||||||
#define LAUNCHER_REGKEY "SYSTEM\\CurrentControlSet\\Services\\WinFsp.Launcher\\Services"
|
#define LAUNCHER_REGKEY "Software\\WinFsp\\Services"
|
||||||
|
#define LAUNCHER_REGKEY_WOW64 KEY_WOW64_32KEY
|
||||||
|
|
||||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||||
|
@ -126,6 +126,10 @@ static inline void *MemAlloc(size_t Size)
|
|||||||
{
|
{
|
||||||
return HeapAlloc(GetProcessHeap(), 0, Size);
|
return HeapAlloc(GetProcessHeap(), 0, Size);
|
||||||
}
|
}
|
||||||
|
static inline void *MemRealloc(void *Pointer, size_t Size)
|
||||||
|
{
|
||||||
|
return HeapReAlloc(GetProcessHeap(), 0, Pointer, Size);
|
||||||
|
}
|
||||||
static inline void MemFree(void *Pointer)
|
static inline void MemFree(void *Pointer)
|
||||||
{
|
{
|
||||||
if (0 != Pointer)
|
if (0 != Pointer)
|
||||||
|
@ -80,8 +80,18 @@ static NTSTATUS FspFsvolClose(
|
|||||||
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
||||||
FspFileNodeDereference(FileNode);
|
FspFileNodeDereference(FileNode);
|
||||||
|
|
||||||
|
/* if we are closing files in the context of a rename make it synchronous */
|
||||||
|
if (FspFsvolDeviceFileRenameIsAcquiredExclusive(FsvolDeviceObject))
|
||||||
|
{
|
||||||
|
/* acquire ownership of the Request */
|
||||||
|
Request->Hint = (UINT_PTR)Irp;
|
||||||
|
FspIrpSetRequest(Irp, Request);
|
||||||
|
|
||||||
|
return FSP_STATUS_IOQ_POST_BEST_EFFORT;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Post as a BestEffort work request. This allows us to complete our own IRP
|
* Post as a BestEffort WORK request. This allows us to complete our own IRP
|
||||||
* and return immediately.
|
* and return immediately.
|
||||||
*/
|
*/
|
||||||
FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request);
|
FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request);
|
||||||
|
@ -808,6 +808,16 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* populate the FileNode/FileDesc fields from the Response */
|
/* populate the FileNode/FileDesc fields from the Response */
|
||||||
|
FileNode->UserContext = Response->Rsp.Create.Opened.UserContext;
|
||||||
|
FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber;
|
||||||
|
FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
FileNode->IsRootDirectory = FileNode->IsDirectory &&
|
||||||
|
sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0];
|
||||||
|
FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2;
|
||||||
|
FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);
|
||||||
|
|
||||||
|
/* handle normalized names */
|
||||||
if (!FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch)
|
if (!FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch)
|
||||||
{
|
{
|
||||||
/* is there a normalized file name as part of the response? */
|
/* is there a normalized file name as part of the response? */
|
||||||
@ -843,14 +853,6 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
RtlCopyMemory(FileNode->FileName.Buffer, NormalizedName.Buffer, NormalizedName.Length);
|
RtlCopyMemory(FileNode->FileName.Buffer, NormalizedName.Buffer, NormalizedName.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileNode->UserContext = Response->Rsp.Create.Opened.UserContext;
|
|
||||||
FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber;
|
|
||||||
FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,
|
|
||||||
FILE_ATTRIBUTE_DIRECTORY);
|
|
||||||
FileNode->IsRootDirectory = FileNode->IsDirectory &&
|
|
||||||
sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0];
|
|
||||||
FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2;
|
|
||||||
FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);
|
|
||||||
|
|
||||||
/* open the FileNode */
|
/* open the FileNode */
|
||||||
Result = FspFileNodeOpen(FileNode, FileObject,
|
Result = FspFileNodeOpen(FileNode, FileObject,
|
||||||
@ -876,8 +878,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
|
|
||||||
Result = FspFsvolCreateSharingViolationOplock(
|
Result = FspFsvolCreateSharingViolationOplock(
|
||||||
FsvolDeviceObject, Irp, IrpSp, FALSE);
|
FsvolDeviceObject, Irp, IrpSp, FALSE);
|
||||||
if (STATUS_PENDING == Result)
|
FSP_RETURN();
|
||||||
FSP_RETURN();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1315,6 +1316,7 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
|
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response;
|
FSP_FSCTL_TRANSACT_RSP *Response;
|
||||||
|
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
||||||
FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
|
FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
|
||||||
ULONG SharingViolationReason = (ULONG)Irp->IoStatus.Information;
|
ULONG SharingViolationReason = (ULONG)Irp->IoStatus.Information;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -1351,6 +1353,12 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
return FspWqRepostIrpWorkItem(Irp,
|
return FspWqRepostIrpWorkItem(Irp,
|
||||||
FspFsvolCreateSharingViolationOplock, FspFsvolCreateRequestFini);
|
FspFsvolCreateSharingViolationOplock, FspFsvolCreateRequestFini);
|
||||||
|
|
||||||
|
FspFileNodeClose(ExtraFileNode, 0, TRUE);
|
||||||
|
FspFileNodeDereference(ExtraFileNode);
|
||||||
|
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
|
||||||
|
|
||||||
|
FspFsvolCreatePostClose(FileDesc);
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
return STATUS_SHARING_VIOLATION;
|
return STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
@ -1369,7 +1377,6 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
* stream.
|
* stream.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
|
||||||
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
||||||
|
|
||||||
/* break Batch oplocks on the main file and this stream */
|
/* break Batch oplocks on the main file and this stream */
|
||||||
@ -1425,14 +1432,14 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
|
|
||||||
Response = FspIopIrpResponse(Irp);
|
Response = FspIopIrpResponse(Irp);
|
||||||
|
|
||||||
if (STATUS_SUCCESS == Result)
|
FspFileNodeClose(ExtraFileNode, 0, TRUE);
|
||||||
{
|
FspFileNodeDereference(ExtraFileNode);
|
||||||
FspFileNodeClose(ExtraFileNode, 0, TRUE);
|
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
|
||||||
FspFileNodeDereference(ExtraFileNode);
|
|
||||||
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
|
if (STATUS_SUCCESS != Result)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
FspFsvolCreatePostClose(FileDesc);
|
||||||
|
|
||||||
Response->IoStatus.Status = (UINT32)Result;
|
Response->IoStatus.Status = (UINT32)Result;
|
||||||
Response->IoStatus.Information = (UINT32)Irp->IoStatus.Information;
|
Response->IoStatus.Information = (UINT32)Irp->IoStatus.Information;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
|||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
||||||
@ -80,6 +81,7 @@ VOID FspDeviceDeleteAll(VOID);
|
|||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameIsAcquiredExclusive)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
|
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
|
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
||||||
@ -574,6 +576,15 @@ VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Own
|
|||||||
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
|
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
return ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->FileRenameResource);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
|
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
298
src/sys/dirctl.c
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
||||||
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
||||||
UINT64 DirectoryOffset, PUINT64 PDirectoryOffset,
|
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
||||||
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
||||||
PVOID DestBuf, PULONG PDestLen);
|
PVOID DestBuf, PULONG PDestLen);
|
||||||
@ -74,13 +74,11 @@ FSP_DRIVER_DISPATCH FspDirectoryControl;
|
|||||||
#pragma alloc_text(PAGE, FspDirectoryControl)
|
#pragma alloc_text(PAGE, FspDirectoryControl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FILE_INDEX_FROM_OFFSET(v) ((ULONG)(v))
|
|
||||||
#define OFFSET_FROM_FILE_INDEX(v) ((UINT64)(v))
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/* QueryDirectory */
|
/* QueryDirectory */
|
||||||
RequestIrp = 0,
|
RequestIrp = 0,
|
||||||
|
RequestCookie = 1,
|
||||||
RequestMdl = 1,
|
RequestMdl = 1,
|
||||||
RequestAddress = 2,
|
RequestAddress = 2,
|
||||||
RequestProcess = 3,
|
RequestProcess = 3,
|
||||||
@ -91,10 +89,11 @@ enum
|
|||||||
/* DirectoryControlComplete retry */
|
/* DirectoryControlComplete retry */
|
||||||
RequestDirInfoChangeNumber = 0,
|
RequestDirInfoChangeNumber = 0,
|
||||||
};
|
};
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestMdl, "");
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
||||||
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
||||||
UINT64 DirectoryOffset, PUINT64 PDirectoryOffset,
|
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
||||||
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
||||||
PVOID DestBuf, PULONG PDestLen)
|
PVOID DestBuf, PULONG PDestLen)
|
||||||
@ -104,7 +103,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
{\
|
{\
|
||||||
TYPE InfoStruct = { 0 }, *Info = &InfoStruct;\
|
TYPE InfoStruct = { 0 }, *Info = &InfoStruct;\
|
||||||
Info->NextEntryOffset = 0;\
|
Info->NextEntryOffset = 0;\
|
||||||
Info->FileIndex = FILE_INDEX_FROM_OFFSET(DirInfo->NextOffset);\
|
Info->FileIndex = 0;\
|
||||||
Info->FileNameLength = FileName.Length;\
|
Info->FileNameLength = FileName.Length;\
|
||||||
__VA_ARGS__\
|
__VA_ARGS__\
|
||||||
Info = DestBuf;\
|
Info = DestBuf;\
|
||||||
@ -128,7 +127,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
|
|
||||||
NTSTATUS Result = STATUS_SUCCESS;
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer, Match;
|
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer, Match;
|
||||||
BOOLEAN Loop = TRUE, DirectoryOffsetFound = FALSE;
|
BOOLEAN Loop = TRUE, DirectoryMarkerFound = FALSE;
|
||||||
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
|
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
|
||||||
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
||||||
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
||||||
@ -178,16 +177,18 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != DirectoryOffset && !DirectoryOffsetFound)
|
|
||||||
{
|
|
||||||
DirectoryOffsetFound = DirInfo->NextOffset == DirectoryOffset;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileName.Length =
|
FileName.Length =
|
||||||
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
|
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
FileName.Buffer = DirInfo->FileNameBuf;
|
FileName.Buffer = DirInfo->FileNameBuf;
|
||||||
|
|
||||||
|
if (0 != DirectoryMarker && 0 != DirectoryMarker->Buffer &&
|
||||||
|
!DirectoryMarkerFound)
|
||||||
|
{
|
||||||
|
DirectoryMarkerFound = 0 == FspFileNameCompare(
|
||||||
|
&FileName, DirectoryMarker, CaseInsensitive, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
||||||
CopyLength = FileName.Length;
|
CopyLength = FileName.Length;
|
||||||
|
|
||||||
@ -223,7 +224,6 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
*(PULONG)PrevDestBuf = (ULONG)((PUINT8)DestBuf - (PUINT8)PrevDestBuf);
|
*(PULONG)PrevDestBuf = (ULONG)((PUINT8)DestBuf - (PUINT8)PrevDestBuf);
|
||||||
PrevDestBuf = DestBuf;
|
PrevDestBuf = DestBuf;
|
||||||
|
|
||||||
*PDirectoryOffset = DirInfo->NextOffset;
|
|
||||||
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
|
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
|
||||||
|
|
||||||
switch (FileInformationClass)
|
switch (FileInformationClass)
|
||||||
@ -265,6 +265,9 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
|
||||||
|
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
|
||||||
|
|
||||||
DestBuf = (PVOID)((PUINT8)DestBuf +
|
DestBuf = (PVOID)((PUINT8)DestBuf +
|
||||||
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
|
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
|
||||||
|
|
||||||
@ -273,7 +276,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
Loop = FALSE;
|
Loop = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*PDirectoryOffset = DirInfo->NextOffset;
|
*DirectoryMarkerOut = FileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
except (EXCEPTION_EXECUTE_HANDLER)
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
@ -315,7 +318,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
||||||
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
||||||
UINT64 DirectoryOffset = FileDesc->DirectoryOffset;
|
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
|
||||||
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
|
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
|
||||||
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
||||||
|
|
||||||
@ -323,17 +326,20 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
|
|||||||
DirInfoSize = (ULONG)(DirInfoEnd - (PUINT8)DirInfo);
|
DirInfoSize = (ULONG)(DirInfoEnd - (PUINT8)DirInfo);
|
||||||
|
|
||||||
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
||||||
0 != FileDesc->DirInfoCacheHint ? 0 : DirectoryOffset, &DirectoryOffset,
|
0 != FileDesc->DirInfoCacheHint ? 0 : &FileDesc->DirectoryMarker, &DirectoryMarker,
|
||||||
FileInformationClass, ReturnSingleEntry,
|
FileInformationClass, ReturnSingleEntry,
|
||||||
&DirInfo, DirInfoSize,
|
&DirInfo, DirInfoSize,
|
||||||
DestBuf, PDestLen);
|
DestBuf, PDestLen);
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != *PDestLen)
|
Result = FspFileDescSetDirectoryMarker(FileDesc, &DirectoryMarker);
|
||||||
FileDesc->DirectoryHasSuchFile = TRUE;
|
if (NT_SUCCESS(Result))
|
||||||
FileDesc->DirectoryOffset = DirectoryOffset;
|
{
|
||||||
FileDesc->DirInfoCacheHint = (ULONG)((PUINT8)DirInfo - DirInfoBgn);
|
if (0 != *PDestLen)
|
||||||
|
FileDesc->DirectoryHasSuchFile = TRUE;
|
||||||
|
FileDesc->DirInfoCacheHint = (ULONG)((PUINT8)DirInfo - DirInfoBgn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
||||||
Result = STATUS_NO_SUCH_FILE;
|
Result = STATUS_NO_SUCH_FILE;
|
||||||
@ -354,7 +360,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
||||||
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
||||||
UINT64 DirectoryOffset = FileDesc->DirectoryOffset;
|
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
|
||||||
|
|
||||||
ASSERT(DirInfo == DestBuf);
|
ASSERT(DirInfo == DestBuf);
|
||||||
FSP_FSCTL_STATIC_ASSERT(
|
FSP_FSCTL_STATIC_ASSERT(
|
||||||
@ -363,16 +369,19 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
|
|||||||
"FSP_FSCTL_DIR_INFO must be bigger than FILE_ID_BOTH_DIR_INFORMATION");
|
"FSP_FSCTL_DIR_INFO must be bigger than FILE_ID_BOTH_DIR_INFORMATION");
|
||||||
|
|
||||||
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
||||||
0, &DirectoryOffset,
|
0, &DirectoryMarker,
|
||||||
FileInformationClass, ReturnSingleEntry,
|
FileInformationClass, ReturnSingleEntry,
|
||||||
&DirInfo, DirInfoSize,
|
&DirInfo, DirInfoSize,
|
||||||
DestBuf, PDestLen);
|
DestBuf, PDestLen);
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != *PDestLen)
|
Result = FspFileDescSetDirectoryMarker(FileDesc, &DirectoryMarker);
|
||||||
FileDesc->DirectoryHasSuchFile = TRUE;
|
if (NT_SUCCESS(Result))
|
||||||
FileDesc->DirectoryOffset = DirectoryOffset;
|
{
|
||||||
|
if (0 != *PDestLen)
|
||||||
|
FileDesc->DirectoryHasSuchFile = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
||||||
Result = STATUS_NO_SUCH_FILE;
|
Result = STATUS_NO_SUCH_FILE;
|
||||||
@ -442,7 +451,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
* counter-productive to try to read more than we need.
|
* counter-productive to try to read more than we need.
|
||||||
*/
|
*/
|
||||||
#define GetSystemBufferLengthMaybeCached()\
|
#define GetSystemBufferLengthMaybeCached()\
|
||||||
(0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryOffset) ||\
|
(0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryMarker.Buffer) ||\
|
||||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?\
|
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?\
|
||||||
FspFsvolDeviceDirInfoCacheItemSizeMax : Length
|
FspFsvolDeviceDirInfoCacheItemSizeMax : Length
|
||||||
#define GetSystemBufferLengthNonCached()\
|
#define GetSystemBufferLengthNonCached()\
|
||||||
@ -463,7 +472,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
BOOLEAN ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
|
BOOLEAN ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
|
||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
|
||||||
PUNICODE_STRING FileName = IrpSp->Parameters.QueryDirectory.FileName;
|
PUNICODE_STRING FileName = IrpSp->Parameters.QueryDirectory.FileName;
|
||||||
ULONG FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
|
//ULONG FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
|
||||||
PVOID Buffer = 0 != Irp->AssociatedIrp.SystemBuffer ?
|
PVOID Buffer = 0 != Irp->AssociatedIrp.SystemBuffer ?
|
||||||
Irp->AssociatedIrp.SystemBuffer : Irp->UserBuffer;
|
Irp->AssociatedIrp.SystemBuffer : Irp->UserBuffer;
|
||||||
ULONG Length = IrpSp->Parameters.QueryDirectory.Length;
|
ULONG Length = IrpSp->Parameters.QueryDirectory.Length;
|
||||||
@ -511,27 +520,14 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
Request = 0;
|
Request = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the DirectoryPattern in the FileDesc */
|
/* reset the FileDesc */
|
||||||
Result = FspFileDescResetDirectoryPattern(FileDesc, FileName,
|
Result = FspFileDescResetDirectory(FileDesc, FileName, RestartScan, IndexSpecified);
|
||||||
RestartScan && 0 != FileName && 0 != FileName->Length);
|
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspFileNodeRelease(FileNode, Full);
|
FspFileNodeRelease(FileNode, Full);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine where to (re)start */
|
|
||||||
if (IndexSpecified)
|
|
||||||
{
|
|
||||||
FileDesc->DirectoryHasSuchFile = FALSE;
|
|
||||||
FileDesc->DirectoryOffset = OFFSET_FROM_FILE_INDEX(FileIndex);
|
|
||||||
}
|
|
||||||
else if (RestartScan)
|
|
||||||
{
|
|
||||||
FileDesc->DirectoryHasSuchFile = FALSE;
|
|
||||||
FileDesc->DirectoryOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* see if the required information is still in the cache and valid! */
|
/* see if the required information is still in the cache and valid! */
|
||||||
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
|
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
|
||||||
{
|
{
|
||||||
@ -571,8 +567,10 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
|
|
||||||
/* create request */
|
/* create request */
|
||||||
Result = FspIopCreateRequestEx(Irp, 0,
|
Result = FspIopCreateRequestEx(Irp, 0,
|
||||||
|
(FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern &&
|
||||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?
|
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?
|
||||||
FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0,
|
FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0) +
|
||||||
|
(FsvolDeviceExtension->VolumeParams.MaxComponentLength + 1) * sizeof(WCHAR),
|
||||||
FspFsvolQueryDirectoryRequestFini, &Request);
|
FspFsvolQueryDirectoryRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
@ -583,19 +581,38 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
Request->Kind = FspFsctlTransactQueryDirectoryKind;
|
Request->Kind = FspFsctlTransactQueryDirectoryKind;
|
||||||
Request->Req.QueryDirectory.UserContext = FileNode->UserContext;
|
Request->Req.QueryDirectory.UserContext = FileNode->UserContext;
|
||||||
Request->Req.QueryDirectory.UserContext2 = FileDesc->UserContext2;
|
Request->Req.QueryDirectory.UserContext2 = FileDesc->UserContext2;
|
||||||
Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset;
|
|
||||||
Request->Req.QueryDirectory.Length = SystemBufferLength;
|
Request->Req.QueryDirectory.Length = SystemBufferLength;
|
||||||
Request->Req.QueryDirectory.CaseSensitive = FileDesc->CaseSensitive;
|
Request->Req.QueryDirectory.CaseSensitive = FileDesc->CaseSensitive;
|
||||||
|
|
||||||
if (FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
if (FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern &&
|
||||||
|
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
||||||
{
|
{
|
||||||
Request->Req.QueryDirectory.Pattern.Offset = Request->FileName.Size;
|
Request->Req.QueryDirectory.Pattern.Offset =
|
||||||
|
Request->FileName.Size;
|
||||||
Request->Req.QueryDirectory.Pattern.Size =
|
Request->Req.QueryDirectory.Pattern.Size =
|
||||||
FileDesc->DirectoryPattern.Length + sizeof(WCHAR);
|
FileDesc->DirectoryPattern.Length + sizeof(WCHAR);
|
||||||
RtlCopyMemory(Request->Buffer + Request->FileName.Size,
|
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset,
|
||||||
FileDesc->DirectoryPattern.Buffer, FileDesc->DirectoryPattern.Length);
|
FileDesc->DirectoryPattern.Buffer, FileDesc->DirectoryPattern.Length);
|
||||||
*(PWSTR)(Request->Buffer + Request->FileName.Size + FileDesc->DirectoryPattern.Length) =
|
*(PWSTR)(Request->Buffer +
|
||||||
L'\0';
|
Request->Req.QueryDirectory.Pattern.Offset +
|
||||||
|
FileDesc->DirectoryPattern.Length) = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
ASSERT(
|
||||||
|
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||||
|
FileDesc->DirectoryMarker.Length);
|
||||||
|
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset =
|
||||||
|
Request->FileName.Size + Request->Req.QueryDirectory.Pattern.Size;
|
||||||
|
Request->Req.QueryDirectory.Marker.Size =
|
||||||
|
FileDesc->DirectoryMarker.Length + sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset,
|
||||||
|
FileDesc->DirectoryMarker.Buffer, FileDesc->DirectoryMarker.Length);
|
||||||
|
*(PWSTR)(Request->Buffer +
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset +
|
||||||
|
FileDesc->DirectoryMarker.Length) = L'\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
@ -818,41 +835,67 @@ NTSTATUS FspFsvolDirectoryControlPrepare(
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
if (FspQueryDirectoryIrpShouldUseProcessBuffer(Irp, Request->Req.QueryDirectory.Length))
|
||||||
PMDL Mdl = 0;
|
|
||||||
PVOID Address;
|
|
||||||
PEPROCESS Process;
|
|
||||||
|
|
||||||
Mdl = IoAllocateMdl(
|
|
||||||
Irp->AssociatedIrp.SystemBuffer,
|
|
||||||
Request->Req.QueryDirectory.Length,
|
|
||||||
FALSE, FALSE, 0);
|
|
||||||
if (0 == Mdl)
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
|
||||||
MmBuildMdlForNonPagedPool(Mdl);
|
|
||||||
|
|
||||||
/* map the MDL into user-mode */
|
|
||||||
Result = FspMapLockedPagesInUserMode(Mdl, &Address, 0);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
{
|
||||||
if (0 != Mdl)
|
NTSTATUS Result;
|
||||||
IoFreeMdl(Mdl);
|
PVOID Cookie;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
|
||||||
return Result;
|
Result = FspProcessBufferAcquire(Request->Req.QueryDirectory.Length, &Cookie, &Address);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
/* get a pointer to the current process so that we can release the buffer later */
|
||||||
|
Process = PsGetCurrentProcess();
|
||||||
|
ObReferenceObject(Process);
|
||||||
|
|
||||||
|
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestCookie) = (PVOID)((UINT_PTR)Cookie | 1);
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
PMDL Mdl = 0;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
|
||||||
/* get a pointer to the current process so that we can unmap the address later */
|
Mdl = IoAllocateMdl(
|
||||||
Process = PsGetCurrentProcess();
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
ObReferenceObject(Process);
|
Request->Req.QueryDirectory.Length,
|
||||||
|
FALSE, FALSE, 0);
|
||||||
|
if (0 == Mdl)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
MmBuildMdlForNonPagedPool(Mdl);
|
||||||
|
|
||||||
FspIopRequestContext(Request, RequestMdl) = Mdl;
|
/* map the MDL into user-mode */
|
||||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
Result = FspMapLockedPagesInUserMode(Mdl, &Address, 0);
|
||||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (0 != Mdl)
|
||||||
|
IoFreeMdl(Mdl);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a pointer to the current process so that we can unmap the address later */
|
||||||
|
Process = PsGetCurrentProcess();
|
||||||
|
ObReferenceObject(Process);
|
||||||
|
|
||||||
|
Request->Req.QueryDirectory.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestMdl) = Mdl;
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolDirectoryControlComplete(
|
NTSTATUS FspFsvolDirectoryControlComplete(
|
||||||
@ -885,7 +928,6 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
ASSERT(Request->Req.QueryDirectory.Offset == FileDesc->DirectoryOffset);
|
|
||||||
|
|
||||||
if (0 == Response->IoStatus.Information)
|
if (0 == Response->IoStatus.Information)
|
||||||
{
|
{
|
||||||
@ -896,6 +938,23 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
|
|
||||||
if (FspFsctlTransactQueryDirectoryKind == Request->Kind)
|
if (FspFsctlTransactQueryDirectoryKind == Request->Kind)
|
||||||
{
|
{
|
||||||
|
if ((UINT_PTR)FspIopRequestContext(Request, RequestCookie) & 1)
|
||||||
|
{
|
||||||
|
PVOID Address = FspIopRequestContext(Request, RequestAddress);
|
||||||
|
|
||||||
|
ASSERT(0 != Address);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Address, Response->IoStatus.Information);
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Result = GetExceptionCode();
|
||||||
|
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DirInfoChangeNumber = FspFileNodeDirInfoChangeNumber(FileNode);
|
DirInfoChangeNumber = FspFileNodeDirInfoChangeNumber(FileNode);
|
||||||
Request->Kind = FspFsctlTransactReservedKind;
|
Request->Kind = FspFsctlTransactReservedKind;
|
||||||
FspIopResetRequest(Request, 0);
|
FspIopResetRequest(Request, 0);
|
||||||
@ -913,7 +972,8 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
FSP_RETURN();
|
FSP_RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == FileDesc->DirectoryOffset &&
|
if (0 == Request->Req.QueryDirectory.Pattern.Size &&
|
||||||
|
0 == Request->Req.QueryDirectory.Marker.Size &&
|
||||||
FspFileNodeTrySetDirInfo(FileNode,
|
FspFileNodeTrySetDirInfo(FileNode,
|
||||||
Irp->AssociatedIrp.SystemBuffer,
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
(ULONG)Response->IoStatus.Information,
|
(ULONG)Response->IoStatus.Information,
|
||||||
@ -952,7 +1012,24 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
FspIopResetRequest(Request, FspFsvolQueryDirectoryRequestFini);
|
FspIopResetRequest(Request, FspFsvolQueryDirectoryRequestFini);
|
||||||
|
|
||||||
Request->Req.QueryDirectory.Address = 0;
|
Request->Req.QueryDirectory.Address = 0;
|
||||||
Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset;
|
Request->Req.QueryDirectory.Marker.Offset = 0;
|
||||||
|
Request->Req.QueryDirectory.Marker.Size = 0;
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
ASSERT(
|
||||||
|
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||||
|
FileDesc->DirectoryMarker.Length);
|
||||||
|
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset =
|
||||||
|
Request->FileName.Size + Request->Req.QueryDirectory.Pattern.Size;
|
||||||
|
Request->Req.QueryDirectory.Marker.Size =
|
||||||
|
FileDesc->DirectoryMarker.Length + sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset,
|
||||||
|
FileDesc->DirectoryMarker.Buffer, FileDesc->DirectoryMarker.Length);
|
||||||
|
*(PWSTR)(Request->Buffer +
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset +
|
||||||
|
FileDesc->DirectoryMarker.Length) = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||||
@ -978,29 +1055,56 @@ static VOID FspFsvolQueryDirectoryRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, P
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PIRP Irp = Context[RequestIrp];
|
PIRP Irp = Context[RequestIrp];
|
||||||
PMDL Mdl = Context[RequestMdl];
|
|
||||||
PVOID Address = Context[RequestAddress];
|
|
||||||
PEPROCESS Process = Context[RequestProcess];
|
|
||||||
|
|
||||||
if (0 != Address)
|
if ((UINT_PTR)Context[RequestCookie] & 1)
|
||||||
{
|
{
|
||||||
KAPC_STATE ApcState;
|
PVOID Cookie = (PVOID)((UINT_PTR)Context[RequestCookie] & ~1);
|
||||||
BOOLEAN Attach;
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
ASSERT(0 != Process);
|
if (0 != Address)
|
||||||
Attach = Process != PsGetCurrentProcess();
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
if (Attach)
|
ASSERT(0 != Process);
|
||||||
KeStackAttachProcess(Process, &ApcState);
|
Attach = Process != PsGetCurrentProcess();
|
||||||
MmUnmapLockedPages(Address, Mdl);
|
|
||||||
if (Attach)
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
|
|
||||||
ObDereferenceObject(Process);
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
FspProcessBufferRelease(Cookie, Address);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PMDL Mdl = Context[RequestMdl];
|
||||||
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
if (0 != Mdl)
|
if (0 != Address)
|
||||||
IoFreeMdl(Mdl);
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
|
ASSERT(0 != Process);
|
||||||
|
Attach = Process != PsGetCurrentProcess();
|
||||||
|
|
||||||
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
MmUnmapLockedPages(Address, Mdl);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != Mdl)
|
||||||
|
IoFreeMdl(Mdl);
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != Irp)
|
if (0 != Irp)
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,10 @@ NTSTATUS DriverEntry(
|
|||||||
|
|
||||||
FspDriverMultiVersionInitialize();
|
FspDriverMultiVersionInitialize();
|
||||||
|
|
||||||
|
Result = FspProcessBufferInitialize();
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
FSP_RETURN();
|
||||||
|
|
||||||
FspDriverObject = DriverObject;
|
FspDriverObject = DriverObject;
|
||||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||||
|
|
||||||
@ -59,14 +63,21 @@ NTSTATUS DriverEntry(
|
|||||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||||
&FspFsctlDiskDeviceObject);
|
&FspFsctlDiskDeviceObject);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspProcessBufferFinalize();
|
||||||
FSP_RETURN();
|
FSP_RETURN();
|
||||||
|
}
|
||||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||||
&FspFsctlNetDeviceObject);
|
&FspFsctlNetDeviceObject);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
FSP_RETURN(FspDeviceDelete(FspFsctlDiskDeviceObject));
|
{
|
||||||
|
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||||
|
FspProcessBufferFinalize();
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||||
ASSERT(STATUS_SUCCESS == Result);
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||||
@ -178,6 +189,7 @@ static VOID FspDriverMultiVersionInitialize(VOID)
|
|||||||
{
|
{
|
||||||
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
||||||
|
|
||||||
|
#pragma prefast(suppress:30035, "FspDriverMultiVersionInitialize is called from DriverEntry")
|
||||||
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
|
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
|
||||||
|
|
||||||
if (RtlIsNtDdiVersionAvailable(NTDDI_WIN7))
|
if (RtlIsNtDdiVersionAvailable(NTDDI_WIN7))
|
||||||
@ -206,6 +218,8 @@ VOID FspUnload(
|
|||||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||||
FspDriverObject = 0;
|
FspDriverObject = 0;
|
||||||
|
|
||||||
|
FspProcessBufferFinalize();
|
||||||
|
|
||||||
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
||||||
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
||||||
&DriverObject->DriverName);
|
&DriverObject->DriverName);
|
||||||
|
@ -601,6 +601,14 @@ VOID FspIrpHookReset(PIRP Irp);
|
|||||||
PVOID FspIrpHookContext(PVOID Context);
|
PVOID FspIrpHookContext(PVOID Context);
|
||||||
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||||
|
|
||||||
|
/* process buffers */
|
||||||
|
#define FspProcessBufferSizeMax (64 * 1024)
|
||||||
|
NTSTATUS FspProcessBufferInitialize(VOID);
|
||||||
|
VOID FspProcessBufferFinalize(VOID);
|
||||||
|
VOID FspProcessBufferCollect(HANDLE ProcessId);
|
||||||
|
NTSTATUS FspProcessBufferAcquire(SIZE_T BufferSize, PVOID *PBufferCookie, PVOID *PBuffer);
|
||||||
|
VOID FspProcessBufferRelease(PVOID BufferCookie, PVOID Buffer);
|
||||||
|
|
||||||
/* IRP context */
|
/* IRP context */
|
||||||
#define FspIrpTimestampInfinity ((ULONG)-1L)
|
#define FspIrpTimestampInfinity ((ULONG)-1L)
|
||||||
#define FspIrpTimestamp(Irp) \
|
#define FspIrpTimestamp(Irp) \
|
||||||
@ -1064,6 +1072,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
|||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
||||||
@ -1112,6 +1121,35 @@ VOID FspDeviceGlobalUnlock(VOID)
|
|||||||
//(FILE_DEVICE_DISK_FILE_SYSTEM == (DeviceObject)->DeviceType ?\
|
//(FILE_DEVICE_DISK_FILE_SYSTEM == (DeviceObject)->DeviceType ?\
|
||||||
// STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED)
|
// STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED)
|
||||||
|
|
||||||
|
/* process buffers conditional usage */
|
||||||
|
static inline
|
||||||
|
BOOLEAN FspReadIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||||
|
{
|
||||||
|
ASSERT(0 != Irp);
|
||||||
|
#if DBG
|
||||||
|
return DEBUGTEST(50) ||
|
||||||
|
#else
|
||||||
|
return FspProcessBufferSizeMax >= BufferSize ||
|
||||||
|
#endif
|
||||||
|
FspFsvolDeviceExtension(IoGetCurrentIrpStackLocation(Irp)->DeviceObject)->
|
||||||
|
VolumeParams.AlwaysUseDoubleBuffering;
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
BOOLEAN FspWriteIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||||
|
{
|
||||||
|
ASSERT(0 != Irp);
|
||||||
|
#if DBG
|
||||||
|
return DEBUGTEST(50);
|
||||||
|
#else
|
||||||
|
return FspProcessBufferSizeMax >= BufferSize;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||||
|
{
|
||||||
|
return FspReadIrpShouldUseProcessBuffer(Irp, BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
/* volume management */
|
/* volume management */
|
||||||
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
||||||
NTSTATUS FspVolumeCreate(
|
NTSTATUS FspVolumeCreate(
|
||||||
@ -1231,7 +1269,7 @@ typedef struct
|
|||||||
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
|
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
|
||||||
DirectoryHasSuchFile:1;
|
DirectoryHasSuchFile:1;
|
||||||
UNICODE_STRING DirectoryPattern;
|
UNICODE_STRING DirectoryPattern;
|
||||||
UINT64 DirectoryOffset;
|
UNICODE_STRING DirectoryMarker;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
ULONG DirInfoCacheHint;
|
ULONG DirInfoCacheHint;
|
||||||
/* stream support */
|
/* stream support */
|
||||||
@ -1362,8 +1400,10 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action
|
|||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified);
|
||||||
|
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||||
|
PUNICODE_STRING FileName);
|
||||||
NTSTATUS FspMainFileOpen(
|
NTSTATUS FspMainFileOpen(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PDEVICE_OBJECT DeviceObjectHint,
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
|
121
src/sys/file.c
@ -84,8 +84,10 @@ NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
|||||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
||||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified);
|
||||||
|
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||||
|
PUNICODE_STRING FileName);
|
||||||
NTSTATUS FspMainFileOpen(
|
NTSTATUS FspMainFileOpen(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PDEVICE_OBJECT DeviceObjectHint,
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
@ -147,7 +149,8 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
|||||||
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
||||||
#pragma alloc_text(PAGE, FspFileDescCreate)
|
#pragma alloc_text(PAGE, FspFileDescCreate)
|
||||||
#pragma alloc_text(PAGE, FspFileDescDelete)
|
#pragma alloc_text(PAGE, FspFileDescDelete)
|
||||||
#pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern)
|
#pragma alloc_text(PAGE, FspFileDescResetDirectory)
|
||||||
|
#pragma alloc_text(PAGE, FspFileDescSetDirectoryMarker)
|
||||||
#pragma alloc_text(PAGE, FspMainFileOpen)
|
#pragma alloc_text(PAGE, FspMainFileOpen)
|
||||||
#pragma alloc_text(PAGE, FspMainFileClose)
|
#pragma alloc_text(PAGE, FspMainFileClose)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeOplockPrepare)
|
#pragma alloc_text(PAGE, FspFileNodeOplockPrepare)
|
||||||
@ -1240,6 +1243,50 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* flush and purge cleaned up but still open files affected by rename (github issue #45) */
|
||||||
|
{
|
||||||
|
PIRP TopLevelIrp;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
|
||||||
|
/* reset the top-level IRP to avoid deadlock on the FileNodes' resources */
|
||||||
|
TopLevelIrp = IoGetTopLevelIrp();
|
||||||
|
IoSetTopLevelIrp(0);
|
||||||
|
|
||||||
|
/* enumerate in reverse order so that files are flushed before containing directories */
|
||||||
|
for (
|
||||||
|
DescendantFileNodeIndex = DescendantFileNodeCount - 1;
|
||||||
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
|
DescendantFileNodeIndex--)
|
||||||
|
{
|
||||||
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
HasHandles = (UINT_PTR)DescendantFileNode & 1;
|
||||||
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||||
|
|
||||||
|
if (HasHandles)
|
||||||
|
continue;
|
||||||
|
if (CheckingOldName &&
|
||||||
|
(DescendantFileNode->FileName.Length <= FileName->Length ||
|
||||||
|
L'\\' != DescendantFileNode->FileName.Buffer[FileName->Length / sizeof(WCHAR)]))
|
||||||
|
continue;
|
||||||
|
if (MmDoesFileHaveUserWritableReferences(&DescendantFileNode->NonPaged->SectionObjectPointers))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are no handles and no writable user mappings. [Ideally we would want to know
|
||||||
|
* that there are no handles and no user mappings, period. Is there an DDI/method to
|
||||||
|
* do that?] There may be a read-only user mapping, but in this case CcFlushCache
|
||||||
|
* should be a no-op and MmForceSectionClosed will fail (which is fine).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASSERT(DescendantFileNode != FileNode && DescendantFileNode->MainFileNode != FileNode);
|
||||||
|
|
||||||
|
FspCcFlushCache(&DescendantFileNode->NonPaged->SectionObjectPointers, 0, 0, &IoStatus);
|
||||||
|
MmForceSectionClosed(&DescendantFileNode->NonPaged->SectionObjectPointers, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
IoSetTopLevelIrp(TopLevelIrp);
|
||||||
|
}
|
||||||
|
|
||||||
/* break any Batch or Handle oplocks on descendants */
|
/* break any Batch or Handle oplocks on descendants */
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
for (
|
for (
|
||||||
@ -1984,15 +2031,19 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc)
|
|||||||
RtlFreeUnicodeString(&FileDesc->DirectoryPattern);
|
RtlFreeUnicodeString(&FileDesc->DirectoryPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
|
||||||
FspFree(FileDesc);
|
FspFree(FileDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset)
|
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
if (Reset || 0 == FileDesc->DirectoryPattern.Buffer)
|
if (0 == FileDesc->DirectoryPattern.Buffer ||
|
||||||
|
(RestartScan && 0 != FileName && 0 != FileName->Length))
|
||||||
{
|
{
|
||||||
UNICODE_STRING DirectoryPattern;
|
UNICODE_STRING DirectoryPattern;
|
||||||
|
|
||||||
@ -2029,7 +2080,65 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileDesc->DirectoryPattern = DirectoryPattern;
|
FileDesc->DirectoryPattern = DirectoryPattern;
|
||||||
|
FileDesc->DirectoryHasSuchFile = FALSE;
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
FileDesc->DirectoryMarker.Buffer = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (RestartScan)
|
||||||
|
{
|
||||||
|
ASSERT(0 == FileName || 0 == FileName->Length);
|
||||||
|
|
||||||
|
FileDesc->DirectoryHasSuchFile = FALSE;
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
FileDesc->DirectoryMarker.Buffer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IndexSpecified && 0 != FileName && 0 != FileName->Length)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFileDescSetDirectoryMarker(FileDesc, FileName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
FileDesc->DirectoryHasSuchFile = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||||
|
PUNICODE_STRING FileName)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (&FileDesc->DirectoryMarker == FileName)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FileDesc->FileNode->FsvolDeviceObject);
|
||||||
|
UNICODE_STRING DirectoryMarker;
|
||||||
|
|
||||||
|
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength < FileName->Length)
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
|
||||||
|
DirectoryMarker.Length = DirectoryMarker.MaximumLength = FileName->Length;
|
||||||
|
DirectoryMarker.Buffer = FspAlloc(FileName->Length);
|
||||||
|
if (0 == DirectoryMarker.Buffer)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
RtlCopyMemory(DirectoryMarker.Buffer, FileName->Buffer, FileName->Length);
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
|
||||||
|
FileDesc->DirectoryMarker = DirectoryMarker;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
277
src/sys/psbuffer.c
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/**
|
||||||
|
* @file sys/psbuffer.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2017 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>
|
||||||
|
|
||||||
|
#define SafeGetCurrentProcessId() (PsGetProcessId(PsGetCurrentProcess()))
|
||||||
|
|
||||||
|
#define FspProcessBufferCountMax (2 >= FspProcessorCount ? 2 : (8 <= FspProcessorCount ? 8 : FspProcessorCount))
|
||||||
|
#define ProcessBufferBucketCount 61 /* are you going to have that many file systems? */
|
||||||
|
|
||||||
|
typedef struct _FSP_PROCESS_BUFFER_ITEM
|
||||||
|
{
|
||||||
|
struct _FSP_PROCESS_BUFFER_ITEM *DictNext;
|
||||||
|
struct _FSP_PROCESS_BUFFER_LIST_ENTRY *BufferList;
|
||||||
|
ULONG BufferCount;
|
||||||
|
HANDLE ProcessId;
|
||||||
|
} FSP_PROCESS_BUFFER_ITEM;
|
||||||
|
|
||||||
|
typedef struct _FSP_PROCESS_BUFFER_LIST_ENTRY
|
||||||
|
{
|
||||||
|
struct _FSP_PROCESS_BUFFER_LIST_ENTRY *Next;
|
||||||
|
PVOID Buffer;
|
||||||
|
} FSP_PROCESS_BUFFER_LIST_ENTRY;
|
||||||
|
|
||||||
|
static KSPIN_LOCK ProcessBufferLock;
|
||||||
|
static FSP_PROCESS_BUFFER_ITEM *ProcessBufferBuckets[ProcessBufferBucketCount];
|
||||||
|
|
||||||
|
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create);
|
||||||
|
|
||||||
|
static inline FSP_PROCESS_BUFFER_ITEM *FspProcessBufferLookupItemAtDpcLevel(HANDLE ProcessId)
|
||||||
|
{
|
||||||
|
FSP_PROCESS_BUFFER_ITEM *Item = 0;
|
||||||
|
ULONG HashIndex = FspHashMixPointer(ProcessId) % ProcessBufferBucketCount;
|
||||||
|
for (FSP_PROCESS_BUFFER_ITEM *ItemX = ProcessBufferBuckets[HashIndex]; ItemX; ItemX = ItemX->DictNext)
|
||||||
|
if (ItemX->ProcessId == ProcessId)
|
||||||
|
{
|
||||||
|
Item = ItemX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline VOID FspProcessBufferAddItemAtDpcLevel(FSP_PROCESS_BUFFER_ITEM *Item)
|
||||||
|
{
|
||||||
|
ULONG HashIndex = FspHashMixPointer(Item->ProcessId) % ProcessBufferBucketCount;
|
||||||
|
#if DBG
|
||||||
|
for (FSP_PROCESS_BUFFER_ITEM *ItemX = ProcessBufferBuckets[HashIndex]; ItemX; ItemX = ItemX->DictNext)
|
||||||
|
ASSERT(ItemX->ProcessId != Item->ProcessId);
|
||||||
|
#endif
|
||||||
|
Item->DictNext = ProcessBufferBuckets[HashIndex];
|
||||||
|
ProcessBufferBuckets[HashIndex] = Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline FSP_PROCESS_BUFFER_ITEM *FspProcessBufferRemoveItemAtDpcLevel(HANDLE ProcessId)
|
||||||
|
{
|
||||||
|
FSP_PROCESS_BUFFER_ITEM *Item = 0;
|
||||||
|
ULONG HashIndex = FspHashMixPointer(ProcessId) % ProcessBufferBucketCount;
|
||||||
|
for (FSP_PROCESS_BUFFER_ITEM **P = &ProcessBufferBuckets[HashIndex]; *P; P = &(*P)->DictNext)
|
||||||
|
if ((*P)->ProcessId == ProcessId)
|
||||||
|
{
|
||||||
|
Item = *P;
|
||||||
|
*P = (*P)->DictNext;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline VOID FspProcessBufferReuseEntry(HANDLE ProcessId,
|
||||||
|
FSP_PROCESS_BUFFER_LIST_ENTRY *BufferEntry)
|
||||||
|
{
|
||||||
|
KIRQL Irql;
|
||||||
|
FSP_PROCESS_BUFFER_ITEM *Item;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||||
|
|
||||||
|
Item = FspProcessBufferLookupItemAtDpcLevel(ProcessId);
|
||||||
|
|
||||||
|
if (0 != Item)
|
||||||
|
{
|
||||||
|
BufferEntry->Next = Item->BufferList;
|
||||||
|
Item->BufferList = BufferEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||||
|
|
||||||
|
if (0 == Item)
|
||||||
|
{
|
||||||
|
if (0 != BufferEntry->Buffer)
|
||||||
|
{
|
||||||
|
SIZE_T BufferSize = 0;
|
||||||
|
ZwFreeVirtualMemory(ZwCurrentProcess(), &BufferEntry->Buffer, &BufferSize, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFree(BufferEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspProcessBufferInitialize(VOID)
|
||||||
|
{
|
||||||
|
KeInitializeSpinLock(&ProcessBufferLock);
|
||||||
|
|
||||||
|
return PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspProcessBufferFinalize(VOID)
|
||||||
|
{
|
||||||
|
PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
|
||||||
|
{
|
||||||
|
if (!Create)
|
||||||
|
FspProcessBufferCollect(ProcessId);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspProcessBufferCollect(HANDLE ProcessId)
|
||||||
|
{
|
||||||
|
KIRQL Irql;
|
||||||
|
FSP_PROCESS_BUFFER_ITEM *Item = 0;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||||
|
|
||||||
|
Item = FspProcessBufferRemoveItemAtDpcLevel(ProcessId);
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||||
|
|
||||||
|
if (0 != Item)
|
||||||
|
{
|
||||||
|
DEBUGLOG("pid=%ld", (ULONG)(UINT_PTR)ProcessId);
|
||||||
|
|
||||||
|
for (FSP_PROCESS_BUFFER_LIST_ENTRY *P = Item->BufferList, *Next; P; P = Next)
|
||||||
|
{
|
||||||
|
Next = P->Next;
|
||||||
|
FspFree(P);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFree(Item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspProcessBufferAcquire(SIZE_T BufferSize, PVOID *PBufferCookie, PVOID *PBuffer)
|
||||||
|
{
|
||||||
|
if (FspProcessBufferSizeMax >= BufferSize)
|
||||||
|
{
|
||||||
|
HANDLE ProcessId = SafeGetCurrentProcessId();
|
||||||
|
KIRQL Irql;
|
||||||
|
FSP_PROCESS_BUFFER_ITEM *Item, *NewItem;
|
||||||
|
FSP_PROCESS_BUFFER_LIST_ENTRY *BufferEntry = 0;
|
||||||
|
BOOLEAN AllocNoReuse;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||||
|
|
||||||
|
Item = FspProcessBufferLookupItemAtDpcLevel(ProcessId);
|
||||||
|
|
||||||
|
if (0 != Item)
|
||||||
|
{
|
||||||
|
BufferEntry = Item->BufferList;
|
||||||
|
if (0 != BufferEntry)
|
||||||
|
Item->BufferList = BufferEntry->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocNoReuse = 0 == BufferEntry &&
|
||||||
|
(0 != Item && FspProcessBufferCountMax <= Item->BufferCount);
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||||
|
|
||||||
|
if (AllocNoReuse)
|
||||||
|
goto alloc_no_reuse;
|
||||||
|
|
||||||
|
if (0 == BufferEntry)
|
||||||
|
{
|
||||||
|
*PBufferCookie = 0;
|
||||||
|
*PBuffer = 0;
|
||||||
|
|
||||||
|
BufferEntry = FspAllocNonPaged(sizeof *BufferEntry);
|
||||||
|
if (0 == BufferEntry)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
RtlZeroMemory(BufferEntry, sizeof *BufferEntry);
|
||||||
|
|
||||||
|
NewItem = FspAllocNonPaged(sizeof *NewItem);
|
||||||
|
if (0 == NewItem)
|
||||||
|
{
|
||||||
|
FspFree(BufferEntry);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
RtlZeroMemory(NewItem, sizeof *NewItem);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ProcessBufferLock, &Irql);
|
||||||
|
|
||||||
|
Item = FspProcessBufferLookupItemAtDpcLevel(ProcessId);
|
||||||
|
|
||||||
|
if (0 == Item)
|
||||||
|
{
|
||||||
|
Item = NewItem;
|
||||||
|
NewItem = 0;
|
||||||
|
Item->BufferCount = 1;
|
||||||
|
Item->ProcessId = ProcessId;
|
||||||
|
FspProcessBufferAddItemAtDpcLevel(Item);
|
||||||
|
}
|
||||||
|
else if (FspProcessBufferCountMax > Item->BufferCount)
|
||||||
|
Item->BufferCount++;
|
||||||
|
else
|
||||||
|
AllocNoReuse = TRUE;
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ProcessBufferLock, Irql);
|
||||||
|
|
||||||
|
if (0 != NewItem)
|
||||||
|
FspFree(NewItem);
|
||||||
|
|
||||||
|
if (AllocNoReuse)
|
||||||
|
{
|
||||||
|
FspFree(BufferEntry);
|
||||||
|
goto alloc_no_reuse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == BufferEntry->Buffer)
|
||||||
|
{
|
||||||
|
BufferSize = FspProcessBufferSizeMax;
|
||||||
|
Result = ZwAllocateVirtualMemory(ZwCurrentProcess(),
|
||||||
|
&BufferEntry->Buffer, 0, &BufferSize, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
/* failed to allocate actual buffer; reuse BufferEntry */
|
||||||
|
FspProcessBufferReuseEntry(ProcessId, BufferEntry);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*PBufferCookie = BufferEntry;
|
||||||
|
*PBuffer = BufferEntry->Buffer;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alloc_no_reuse:
|
||||||
|
*PBufferCookie = 0;
|
||||||
|
*PBuffer = 0;
|
||||||
|
return ZwAllocateVirtualMemory(ZwCurrentProcess(),
|
||||||
|
PBuffer, 0, &BufferSize, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspProcessBufferRelease(PVOID BufferCookie, PVOID Buffer)
|
||||||
|
{
|
||||||
|
if (0 != BufferCookie)
|
||||||
|
{
|
||||||
|
HANDLE ProcessId = SafeGetCurrentProcessId();
|
||||||
|
FSP_PROCESS_BUFFER_LIST_ENTRY *BufferEntry = BufferCookie;
|
||||||
|
|
||||||
|
ASSERT(Buffer == BufferEntry->Buffer);
|
||||||
|
|
||||||
|
FspProcessBufferReuseEntry(ProcessId, BufferEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SIZE_T BufferSize = 0;
|
||||||
|
ZwFreeVirtualMemory(ZwCurrentProcess(), &Buffer, &BufferSize, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
}
|
175
src/sys/read.c
@ -44,10 +44,12 @@ enum
|
|||||||
{
|
{
|
||||||
/* ReadNonCached */
|
/* ReadNonCached */
|
||||||
RequestIrp = 0,
|
RequestIrp = 0,
|
||||||
|
RequestCookie = 1,
|
||||||
RequestSafeMdl = 1,
|
RequestSafeMdl = 1,
|
||||||
RequestAddress = 2,
|
RequestAddress = 2,
|
||||||
RequestProcess = 3,
|
RequestProcess = 3,
|
||||||
};
|
};
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
||||||
|
|
||||||
static NTSTATUS FspFsvolRead(
|
static NTSTATUS FspFsvolRead(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
@ -346,41 +348,70 @@ NTSTATUS FspFsvolReadPrepare(
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
if (FspReadIrpShouldUseProcessBuffer(Irp, Request->Req.Read.Length))
|
||||||
FSP_SAFE_MDL *SafeMdl = 0;
|
|
||||||
PVOID Address;
|
|
||||||
PEPROCESS Process;
|
|
||||||
|
|
||||||
/* create a "safe" MDL if necessary */
|
|
||||||
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
|
||||||
{
|
{
|
||||||
Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl);
|
NTSTATUS Result;
|
||||||
|
PVOID Cookie;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
|
||||||
|
if (0 == MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority))
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES; /* something is seriously screwy! */
|
||||||
|
|
||||||
|
Result = FspProcessBufferAcquire(Request->Req.Read.Length, &Cookie, &Address);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
}
|
|
||||||
|
|
||||||
/* map the MDL into user-mode */
|
/* get a pointer to the current process so that we can release the buffer later */
|
||||||
Result = FspMapLockedPagesInUserMode(
|
Process = PsGetCurrentProcess();
|
||||||
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, 0);
|
ObReferenceObject(Process);
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
|
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestCookie) = (PVOID)((UINT_PTR)Cookie | 1);
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (0 != SafeMdl)
|
NTSTATUS Result;
|
||||||
FspSafeMdlDelete(SafeMdl);
|
FSP_SAFE_MDL *SafeMdl = 0;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
|
||||||
return Result;
|
/* create a "safe" MDL if necessary */
|
||||||
|
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||||
|
{
|
||||||
|
Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map the MDL into user-mode */
|
||||||
|
Result = FspMapLockedPagesInUserMode(
|
||||||
|
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlDelete(SafeMdl);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a pointer to the current process so that we can unmap the address later */
|
||||||
|
Process = PsGetCurrentProcess();
|
||||||
|
ObReferenceObject(Process);
|
||||||
|
|
||||||
|
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a pointer to the current process so that we can unmap the address later */
|
|
||||||
Process = PsGetCurrentProcess();
|
|
||||||
ObReferenceObject(Process);
|
|
||||||
|
|
||||||
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
|
|
||||||
|
|
||||||
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
|
||||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
|
||||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolReadComplete(
|
NTSTATUS FspFsvolReadComplete(
|
||||||
@ -400,15 +431,36 @@ NTSTATUS FspFsvolReadComplete(
|
|||||||
if (Response->IoStatus.Information > Request->Req.Read.Length)
|
if (Response->IoStatus.Information > Request->Req.Read.Length)
|
||||||
FSP_RETURN(Result = STATUS_INTERNAL_ERROR);
|
FSP_RETURN(Result = STATUS_INTERNAL_ERROR);
|
||||||
|
|
||||||
FSP_SAFE_MDL *SafeMdl = FspIopRequestContext(Request, RequestSafeMdl);
|
if ((UINT_PTR)FspIopRequestContext(Request, RequestCookie) & 1)
|
||||||
|
{
|
||||||
|
PVOID Address = FspIopRequestContext(Request, RequestAddress);
|
||||||
|
PVOID SystemAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
||||||
|
|
||||||
|
ASSERT(0 != Address);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RtlCopyMemory(SystemAddress, Address, Response->IoStatus.Information);
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Result = GetExceptionCode();
|
||||||
|
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSP_SAFE_MDL *SafeMdl = FspIopRequestContext(Request, RequestSafeMdl);
|
||||||
|
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlCopyBack(SafeMdl);
|
||||||
|
}
|
||||||
|
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
|
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
|
||||||
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||||
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
|
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
|
||||||
|
|
||||||
if (0 != SafeMdl)
|
|
||||||
FspSafeMdlCopyBack(SafeMdl);
|
|
||||||
|
|
||||||
/* if we are top-level */
|
/* if we are top-level */
|
||||||
if (0 == FspIrpTopFlags(Irp))
|
if (0 == FspIrpTopFlags(Irp))
|
||||||
{
|
{
|
||||||
@ -442,29 +494,56 @@ static VOID FspFsvolReadNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PIRP Irp = Context[RequestIrp];
|
PIRP Irp = Context[RequestIrp];
|
||||||
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
|
||||||
PVOID Address = Context[RequestAddress];
|
|
||||||
PEPROCESS Process = Context[RequestProcess];
|
|
||||||
|
|
||||||
if (0 != Address)
|
if ((UINT_PTR)Context[RequestCookie] & 1)
|
||||||
{
|
{
|
||||||
KAPC_STATE ApcState;
|
PVOID Cookie = (PVOID)((UINT_PTR)Context[RequestCookie] & ~1);
|
||||||
BOOLEAN Attach;
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
ASSERT(0 != Process);
|
if (0 != Address)
|
||||||
Attach = Process != PsGetCurrentProcess();
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
if (Attach)
|
ASSERT(0 != Process);
|
||||||
KeStackAttachProcess(Process, &ApcState);
|
Attach = Process != PsGetCurrentProcess();
|
||||||
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
|
||||||
if (Attach)
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
|
|
||||||
ObDereferenceObject(Process);
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
FspProcessBufferRelease(Cookie, Address);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||||
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
if (0 != SafeMdl)
|
if (0 != Address)
|
||||||
FspSafeMdlDelete(SafeMdl);
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
|
ASSERT(0 != Process);
|
||||||
|
Attach = Process != PsGetCurrentProcess();
|
||||||
|
|
||||||
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlDelete(SafeMdl);
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != Irp)
|
if (0 != Irp)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,8 @@ NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLen
|
|||||||
|
|
||||||
NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics)
|
NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
*PStatistics = FspAllocNonPaged(sizeof(FSP_STATISTICS) * FspProcessorCount);
|
*PStatistics = FspAllocNonPaged(sizeof(FSP_STATISTICS) * FspProcessorCount);
|
||||||
if (0 == *PStatistics)
|
if (0 == *PStatistics)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
@ -49,11 +51,15 @@ NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics)
|
|||||||
|
|
||||||
VOID FspStatisticsDelete(FSP_STATISTICS *Statistics)
|
VOID FspStatisticsDelete(FSP_STATISTICS *Statistics)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
FspFree(Statistics);
|
FspFree(Statistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLength)
|
NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLength)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
ULONG StatLength;
|
ULONG StatLength;
|
||||||
|
|
||||||
|
@ -171,6 +171,16 @@ static NTSTATUS FspVolumeCreateNoLock(
|
|||||||
}
|
}
|
||||||
VolumeParams.FileSystemName[sizeof VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
VolumeParams.FileSystemName[sizeof VolumeParams.FileSystemName / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
|
||||||
|
#if !DBG
|
||||||
|
/*
|
||||||
|
* In Release builds we hardcode AlwaysUseDoubleBuffering for Reads as we do not want someone
|
||||||
|
* to use WinFsp to crash Windows.
|
||||||
|
*
|
||||||
|
* See http://www.osronline.com/showthread.cfm?link=282037
|
||||||
|
*/
|
||||||
|
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* create volume guid */
|
/* create volume guid */
|
||||||
Result = FspCreateGuid(&Guid);
|
Result = FspCreateGuid(&Guid);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
|
162
src/sys/write.c
@ -45,10 +45,12 @@ enum
|
|||||||
{
|
{
|
||||||
/* WriteNonCached */
|
/* WriteNonCached */
|
||||||
RequestIrp = 0,
|
RequestIrp = 0,
|
||||||
|
RequestCookie = 1,
|
||||||
RequestSafeMdl = 1,
|
RequestSafeMdl = 1,
|
||||||
RequestAddress = 2,
|
RequestAddress = 2,
|
||||||
RequestProcess = 3,
|
RequestProcess = 3,
|
||||||
};
|
};
|
||||||
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
||||||
|
|
||||||
static NTSTATUS FspFsvolWrite(
|
static NTSTATUS FspFsvolWrite(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
@ -416,41 +418,86 @@ NTSTATUS FspFsvolWritePrepare(
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
if (FspWriteIrpShouldUseProcessBuffer(Irp, Request->Req.Write.Length))
|
||||||
FSP_SAFE_MDL *SafeMdl = 0;
|
|
||||||
PVOID Address;
|
|
||||||
PEPROCESS Process;
|
|
||||||
|
|
||||||
/* create a "safe" MDL if necessary */
|
|
||||||
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
|
||||||
{
|
{
|
||||||
Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl);
|
NTSTATUS Result;
|
||||||
|
PVOID Cookie;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
PVOID SystemAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
||||||
|
|
||||||
|
if (0 == SystemAddress)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES; /* something is seriously screwy! */
|
||||||
|
|
||||||
|
Result = FspProcessBufferAcquire(Request->Req.Write.Length, &Cookie, &Address);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
}
|
|
||||||
|
|
||||||
/* map the MDL into user-mode */
|
ASSERT(0 != Address);
|
||||||
Result = FspMapLockedPagesInUserMode(
|
try
|
||||||
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, FspMvMdlMappingNoWrite);
|
{
|
||||||
if (!NT_SUCCESS(Result))
|
RtlCopyMemory(Address, SystemAddress, Request->Req.Write.Length);
|
||||||
|
}
|
||||||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Result = GetExceptionCode();
|
||||||
|
Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
|
||||||
|
|
||||||
|
FspProcessBufferRelease(Cookie, Address);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a pointer to the current process so that we can release the buffer later */
|
||||||
|
Process = PsGetCurrentProcess();
|
||||||
|
ObReferenceObject(Process);
|
||||||
|
|
||||||
|
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestCookie) = (PVOID)((UINT_PTR)Cookie | 1);
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (0 != SafeMdl)
|
NTSTATUS Result;
|
||||||
FspSafeMdlDelete(SafeMdl);
|
FSP_SAFE_MDL *SafeMdl = 0;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
|
||||||
return Result;
|
/* create a "safe" MDL if necessary */
|
||||||
|
if (!FspSafeMdlCheck(Irp->MdlAddress))
|
||||||
|
{
|
||||||
|
Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map the MDL into user-mode */
|
||||||
|
Result = FspMapLockedPagesInUserMode(
|
||||||
|
0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address, FspMvMdlMappingNoWrite);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlDelete(SafeMdl);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a pointer to the current process so that we can unmap the address later */
|
||||||
|
Process = PsGetCurrentProcess();
|
||||||
|
ObReferenceObject(Process);
|
||||||
|
|
||||||
|
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
||||||
|
|
||||||
|
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
||||||
|
FspIopRequestContext(Request, RequestAddress) = Address;
|
||||||
|
FspIopRequestContext(Request, RequestProcess) = Process;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a pointer to the current process so that we can unmap the address later */
|
|
||||||
Process = PsGetCurrentProcess();
|
|
||||||
ObReferenceObject(Process);
|
|
||||||
|
|
||||||
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
|
|
||||||
|
|
||||||
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
|
|
||||||
FspIopRequestContext(Request, RequestAddress) = Address;
|
|
||||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolWriteComplete(
|
NTSTATUS FspFsvolWriteComplete(
|
||||||
@ -524,29 +571,56 @@ static VOID FspFsvolWriteNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, P
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PIRP Irp = Context[RequestIrp];
|
PIRP Irp = Context[RequestIrp];
|
||||||
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
|
||||||
PVOID Address = Context[RequestAddress];
|
|
||||||
PEPROCESS Process = Context[RequestProcess];
|
|
||||||
|
|
||||||
if (0 != Address)
|
if ((UINT_PTR)Context[RequestCookie] & 1)
|
||||||
{
|
{
|
||||||
KAPC_STATE ApcState;
|
PVOID Cookie = (PVOID)((UINT_PTR)Context[RequestCookie] & ~1);
|
||||||
BOOLEAN Attach;
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
ASSERT(0 != Process);
|
if (0 != Address)
|
||||||
Attach = Process != PsGetCurrentProcess();
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
if (Attach)
|
ASSERT(0 != Process);
|
||||||
KeStackAttachProcess(Process, &ApcState);
|
Attach = Process != PsGetCurrentProcess();
|
||||||
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
|
||||||
if (Attach)
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
|
|
||||||
ObDereferenceObject(Process);
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
FspProcessBufferRelease(Cookie, Address);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
|
||||||
|
PVOID Address = Context[RequestAddress];
|
||||||
|
PEPROCESS Process = Context[RequestProcess];
|
||||||
|
|
||||||
if (0 != SafeMdl)
|
if (0 != Address)
|
||||||
FspSafeMdlDelete(SafeMdl);
|
{
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
BOOLEAN Attach;
|
||||||
|
|
||||||
|
ASSERT(0 != Process);
|
||||||
|
Attach = Process != PsGetCurrentProcess();
|
||||||
|
|
||||||
|
if (Attach)
|
||||||
|
KeStackAttachProcess(Process, &ApcState);
|
||||||
|
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
|
||||||
|
if (Attach)
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != SafeMdl)
|
||||||
|
FspSafeMdlDelete(SafeMdl);
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != Irp)
|
if (0 != Irp)
|
||||||
{
|
{
|
||||||
|
42
tools/build-sample.bat
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
if not X%1==X set Config=%1
|
||||||
|
if not X%2==X set Arch=%2
|
||||||
|
if not X%3==X set Sample=%3
|
||||||
|
if not X%4==X set ProjDir=%~4
|
||||||
|
|
||||||
|
if X!ProjDir!==X (echo usage: build-sample Config Arch Sample ProjDir >&2 & goto fail)
|
||||||
|
|
||||||
|
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x64
|
||||||
|
|
||||||
|
if X!FSP_SAMPLE_DIR!==X (
|
||||||
|
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||||
|
set RegVal="InstallDir"
|
||||||
|
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||||
|
if !ERRORLEVEL! equ 0 (
|
||||||
|
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||||
|
set InstallDir=%%j
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not exist "!InstallDir!" (echo cannot find WinFsp installation >&2 & goto fail)
|
||||||
|
if not exist "!InstallDir!samples\!Sample!" (echo cannot find WinFsp sample !Sample! >&2 & goto fail)
|
||||||
|
|
||||||
|
set SampleDir=!InstallDir!samples
|
||||||
|
) else (
|
||||||
|
set SampleDir=!FSP_SAMPLE_DIR!
|
||||||
|
)
|
||||||
|
|
||||||
|
if exist "!ProjDir!" rmdir /s/q "!ProjDir!"
|
||||||
|
mkdir "!ProjDir!"
|
||||||
|
xcopy /s/e/q/y "!SampleDir!\!Sample!" "!ProjDir!"
|
||||||
|
|
||||||
|
devenv "!ProjDir!\!Sample!.sln" /build "!Config!|!Arch!"
|
||||||
|
if !ERRORLEVEL! neq 0 goto :fail
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
exit /b 1
|
@ -1,6 +1,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
setlocal
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
set MsiName="WinFsp - Windows File System Proxy"
|
set MsiName="WinFsp - Windows File System Proxy"
|
||||||
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
||||||
@ -19,6 +20,7 @@ if not X%SignedPackage%==X (
|
|||||||
if not exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp-*.msi" (echo previous build not found >&2 & exit /b 1)
|
if not exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp-*.msi" (echo previous build not found >&2 & exit /b 1)
|
||||||
if not exist "%SignedPackage%" (echo signed package not found >&2 & exit /b 1)
|
if not exist "%SignedPackage%" (echo signed package not found >&2 & exit /b 1)
|
||||||
del "%~dp0..\build\VStudio\build\%Configuration%\winfsp-*.msi"
|
del "%~dp0..\build\VStudio\build\%Configuration%\winfsp-*.msi"
|
||||||
|
if exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg" del "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg"
|
||||||
for /R "%SignedPackage%" %%f in (*.sys) do (
|
for /R "%SignedPackage%" %%f in (*.sys) do (
|
||||||
copy "%%f" "%~dp0..\build\VStudio\build\%Configuration%" >nul
|
copy "%%f" "%~dp0..\build\VStudio\build\%Configuration%" >nul
|
||||||
)
|
)
|
||||||
@ -81,6 +83,18 @@ for %%f in (build\%Configuration%\winfsp-*.msi) do (
|
|||||||
|
|
||||||
if not %signfail%==0 echo SIGNING FAILED! The product has been successfully built, but not signed.
|
if not %signfail%==0 echo SIGNING FAILED! The product has been successfully built, but not signed.
|
||||||
|
|
||||||
|
where /q choco.exe
|
||||||
|
if %ERRORLEVEL% equ 0 (
|
||||||
|
for %%f in (build\%Configuration%\winfsp-*.msi) do set Version=%%~nf
|
||||||
|
set Version=!Version:winfsp-=!
|
||||||
|
|
||||||
|
copy ..\choco\* build\%Configuration%
|
||||||
|
copy ..\choco\LICENSE.TXT /B + ..\..\License.txt /B build\%Configuration%\LICENSE.txt /B
|
||||||
|
certutil -hashfile build\%Configuration%\winfsp-!Version!.msi SHA256 >>build\%Configuration%\VERIFICATION.txt
|
||||||
|
choco pack build\%Configuration%\winfsp.nuspec --version=!Version! --outputdirectory=build\%Configuration%
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
)
|
||||||
|
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
setlocal
|
setlocal
|
||||||
|
|
||||||
echo WINFSP INSTALLATION DIRECTORY
|
echo WINFSP INSTALLATION DIRECTORY AND LAUNCHER REGISTRATIONS
|
||||||
reg query HKLM\SOFTWARE\WinFsp /reg:32
|
reg query HKLM\SOFTWARE\WinFsp /s /reg:32
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo WINFSP DLL REGISTRATIONS
|
echo WINFSP DLL REGISTRATIONS
|
||||||
@ -12,10 +12,6 @@ reg query HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Np\NetworkProvider
|
|||||||
reg query HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\WinFsp
|
reg query HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\WinFsp
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo WINFSP LAUNCHER REGISTRATIONS
|
|
||||||
reg query HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services /s
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo WINFSP FSD CONFIGURATION AND STATUS
|
echo WINFSP FSD CONFIGURATION AND STATUS
|
||||||
sc query WinFsp
|
sc query WinFsp
|
||||||
sc qc WinFsp
|
sc qc WinFsp
|
||||||
|
41
tools/fsreg.bat
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
set RegKey=HKLM\Software\WinFsp\Services
|
||||||
|
|
||||||
|
if not X%1==X-u (
|
||||||
|
set unreg=0
|
||||||
|
|
||||||
|
if not X%1==X set fsname=%1
|
||||||
|
if not X%2==X set fsexec="%~f2"
|
||||||
|
if not X%3==X set fscmdl=%3
|
||||||
|
if not X%4==X set fssecu=%4
|
||||||
|
|
||||||
|
if X!fscmdl!==X goto usage
|
||||||
|
if not exist !fsexec! goto notfound
|
||||||
|
|
||||||
|
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
|
||||||
|
if not X!fssecu!==X reg add !RegKey!\!fsname! /v Security /t REG_SZ /d !fssecu! /f /reg:32
|
||||||
|
) else (
|
||||||
|
set unreg=1
|
||||||
|
|
||||||
|
if not X%2==X set fsname=%2
|
||||||
|
|
||||||
|
if X!fsname!==X goto usage
|
||||||
|
|
||||||
|
reg delete !RegKey!\!fsname! /f /reg:32
|
||||||
|
)
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:notfound
|
||||||
|
echo executable !fsexec! not found >&2
|
||||||
|
exit /b 2
|
||||||
|
|
||||||
|
:usage
|
||||||
|
echo usage: fsreg NAME EXECUTABLE COMMANDLINE [SECURITY] >&2
|
||||||
|
echo usage: fsreg -u NAME >&2
|
||||||
|
exit /b 2
|
@ -17,12 +17,16 @@ launchctl-x64 start memfs64 testdsk "" M: >nul
|
|||||||
launchctl-x64 start memfs64 testnet \memfs64\test N: >nul
|
launchctl-x64 start memfs64 testnet \memfs64\test N: >nul
|
||||||
launchctl-x64 start memfs32 testdsk "" O: >nul
|
launchctl-x64 start memfs32 testdsk "" O: >nul
|
||||||
launchctl-x64 start memfs32 testnet \memfs32\test P: >nul
|
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"
|
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||||
cd M: >nul 2>nul || (echo === Unable to find drive M: >&2 & goto fail)
|
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 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)
|
cd O: >nul 2>nul || (echo === Unable to find drive O: >&2 & goto fail)
|
||||||
cd P: >nul 2>nul || (echo === Unable to find drive P: >&2 & goto fail)
|
cd P: >nul 2>nul || (echo === Unable to find drive P: >&2 & goto fail)
|
||||||
|
cd Q: >nul 2>nul || (echo === Unable to find drive Q: >&2 & goto fail)
|
||||||
|
cd R: >nul 2>nul || (echo === Unable to find drive R: >&2 & goto fail)
|
||||||
|
|
||||||
set dfl_tests=^
|
set dfl_tests=^
|
||||||
winfsp-tests-x64 ^
|
winfsp-tests-x64 ^
|
||||||
@ -31,6 +35,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x64-mountpoint-dir ^
|
winfsp-tests-x64-mountpoint-dir ^
|
||||||
winfsp-tests-x64-no-traverse ^
|
winfsp-tests-x64-no-traverse ^
|
||||||
winfsp-tests-x64-oplock ^
|
winfsp-tests-x64-oplock ^
|
||||||
|
winfsp-tests-x64-external ^
|
||||||
winfsp-tests-x64-external-share ^
|
winfsp-tests-x64-external-share ^
|
||||||
fsx-memfs-x64-disk ^
|
fsx-memfs-x64-disk ^
|
||||||
fsx-memfs-x64-net ^
|
fsx-memfs-x64-net ^
|
||||||
@ -46,6 +51,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x86-mountpoint-dir ^
|
winfsp-tests-x86-mountpoint-dir ^
|
||||||
winfsp-tests-x86-no-traverse ^
|
winfsp-tests-x86-no-traverse ^
|
||||||
winfsp-tests-x86-oplock ^
|
winfsp-tests-x86-oplock ^
|
||||||
|
winfsp-tests-x86-external ^
|
||||||
winfsp-tests-x86-external-share ^
|
winfsp-tests-x86-external-share ^
|
||||||
fsx-memfs-x86-disk ^
|
fsx-memfs-x86-disk ^
|
||||||
fsx-memfs-x86-net ^
|
fsx-memfs-x86-net ^
|
||||||
@ -54,10 +60,20 @@ set dfl_tests=^
|
|||||||
net-use-memfs-x86 ^
|
net-use-memfs-x86 ^
|
||||||
winfstest-memfs-x86-disk ^
|
winfstest-memfs-x86-disk ^
|
||||||
winfstest-memfs-x86-net ^
|
winfstest-memfs-x86-net ^
|
||||||
fscrash-x86
|
fscrash-x86 ^
|
||||||
|
winfsp-tests-dotnet-external ^
|
||||||
|
winfsp-tests-dotnet-external-share
|
||||||
set opt_tests=^
|
set opt_tests=^
|
||||||
ifstest-memfs-x64-disk ^
|
ifstest-memfs-x64-disk ^
|
||||||
ifstest-memfs-x86-disk
|
ifstest-memfs-x86-disk ^
|
||||||
|
ifstest-memfs-dotnet-disk ^
|
||||||
|
sample-passthrough-x64 ^
|
||||||
|
sample-passthrough-x86 ^
|
||||||
|
sample-passthrough-cpp-x64 ^
|
||||||
|
sample-passthrough-cpp-x86 ^
|
||||||
|
sample-passthrough-fuse-x64 ^
|
||||||
|
sample-passthrough-fuse-x86 ^
|
||||||
|
sample-passthrough-dotnet
|
||||||
|
|
||||||
set tests=
|
set tests=
|
||||||
for %%f in (%dfl_tests%) do (
|
for %%f in (%dfl_tests%) do (
|
||||||
@ -114,6 +130,8 @@ launchctl-x64 stop memfs64 testdsk >nul
|
|||||||
launchctl-x64 stop memfs64 testnet >nul
|
launchctl-x64 stop memfs64 testnet >nul
|
||||||
launchctl-x64 stop memfs32 testdsk >nul
|
launchctl-x64 stop memfs32 testdsk >nul
|
||||||
launchctl-x64 stop memfs32 testnet >nul
|
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"
|
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||||
|
|
||||||
@ -139,7 +157,7 @@ if !ERRORLEVEL! neq 0 goto fail
|
|||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x64-mountpoint-drive
|
:winfsp-tests-x64-mountpoint-drive
|
||||||
winfsp-tests-x64 --mountpoint=X:
|
winfsp-tests-x64 --mountpoint=X: --resilient
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
@ -169,7 +187,7 @@ if !ERRORLEVEL! neq 0 goto fail
|
|||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x86-mountpoint-drive
|
:winfsp-tests-x86-mountpoint-drive
|
||||||
winfsp-tests-x86 --mountpoint=X:
|
winfsp-tests-x86 --mountpoint=X: --resilient
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
@ -188,6 +206,12 @@ winfsp-tests-x86 --oplock=filter --resilient
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-external
|
||||||
|
M:
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --resilient
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x64-external-share
|
:winfsp-tests-x64-external-share
|
||||||
M:
|
M:
|
||||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --share=winfsp-tests-share=M:\ --resilient ^
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --share=winfsp-tests-share=M:\ --resilient ^
|
||||||
@ -235,6 +259,12 @@ net use L: /delete
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-external
|
||||||
|
O:
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" --external --resilient
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x86-external-share
|
:winfsp-tests-x86-external-share
|
||||||
O:
|
O:
|
||||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" --external --share=winfsp-tests-share=O:\ --resilient ^
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" --external --share=winfsp-tests-share=O:\ --resilient ^
|
||||||
@ -344,6 +374,19 @@ fscrash-x86 --huge-alloc-size --cached >nul 2>&1
|
|||||||
if !ERRORLEVEL! neq 1 goto fail
|
if !ERRORLEVEL! neq 1 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-dotnet-external
|
||||||
|
Q:
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --resilient
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-dotnet-external-share
|
||||||
|
Q:
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" --external --share=winfsp-tests-share=Q:\ --resilient ^
|
||||||
|
-reparse_symlink*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:ifstest-memfs-x64-disk
|
:ifstest-memfs-x64-disk
|
||||||
call :__ifstest-memfs M: \Device\WinFsp.Disk C:
|
call :__ifstest-memfs M: \Device\WinFsp.Disk C:
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
@ -354,23 +397,28 @@ call :__ifstest-memfs O: \Device\WinFsp.Disk C:
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:ifstest-memfs-dotnet-disk
|
||||||
|
call :__ifstest-memfs Q: \Device\WinFsp.Disk C:
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:__ifstest-memfs
|
:__ifstest-memfs
|
||||||
%1
|
%1
|
||||||
set IfsTestDirectories=^
|
set IfsTestDirectories=^
|
||||||
securit^
|
securit^
|
||||||
opcreatg^
|
opcreatg^
|
||||||
opcreatp^
|
opcreatp^
|
||||||
closedel^
|
closedel^
|
||||||
volinfo^
|
volinfo^
|
||||||
fileinfo^
|
fileinfo^
|
||||||
dirinfo^
|
dirinfo^
|
||||||
filelock^
|
filelock^
|
||||||
oplocks^
|
oplocks^
|
||||||
chgnotif^
|
chgnotif^
|
||||||
readwr^
|
readwr^
|
||||||
seccache^
|
seccache^
|
||||||
reparspt^
|
reparspt^
|
||||||
estream
|
estream
|
||||||
set IfsTestMemfsExit=0
|
set IfsTestMemfsExit=0
|
||||||
call :__ifstest %1 /g Security
|
call :__ifstest %1 /g Security
|
||||||
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
|
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
|
||||||
@ -414,7 +462,7 @@ rem StreamEnhancements.StreamNotifyNameTest: WinFsp does not notify when streams
|
|||||||
call :__ifstest %1 /g StreamEnhancements -t StreamRenameTest -t StreamNotifyNameTest
|
call :__ifstest %1 /g StreamEnhancements -t StreamRenameTest -t StreamNotifyNameTest
|
||||||
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
|
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
|
||||||
for %%d in (!IfsTestDirectories!) do (
|
for %%d in (!IfsTestDirectories!) do (
|
||||||
if exist %%d (echo :ifstest directory %%d still exists & set IfsTestMemfsExit=1)
|
if exist %%d (echo :ifstest directory %%d still exists & set IfsTestMemfsExit=1)
|
||||||
)
|
)
|
||||||
exit /b !IfsTestMemfsExit!
|
exit /b !IfsTestMemfsExit!
|
||||||
|
|
||||||
@ -477,6 +525,96 @@ for /F "delims=" %%l in ('call "%ProjRoot%\tools\ifstest.bat" %* /z /v ^| findst
|
|||||||
if not X!IfsTestFound!==XYES set IfsTestExit=1
|
if not X!IfsTestFound!==XYES set IfsTestExit=1
|
||||||
exit /b !IfsTestExit!
|
exit /b !IfsTestExit!
|
||||||
|
|
||||||
|
:sample-passthrough-x64
|
||||||
|
call :__run_sample_test passthrough x64 passthrough-x64 winfsp-tests-x64
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-passthrough-x86
|
||||||
|
call :__run_sample_test passthrough x86 passthrough-x86 winfsp-tests-x86
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-passthrough-cpp-x64
|
||||||
|
call :__run_sample_test passthrough-cpp x64 passthrough-cpp-x64 winfsp-tests-x64
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-passthrough-cpp-x86
|
||||||
|
call :__run_sample_test passthrough-cpp x86 passthrough-cpp-x86 winfsp-tests-x86
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-passthrough-dotnet
|
||||||
|
call :__run_sample_test passthrough-dotnet anycpu passthrough-dotnet winfsp-tests-x64 ^
|
||||||
|
"-create_backup_test -create_restore_test -create_namelen_test -delete_access_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-passthrough-fuse-x64
|
||||||
|
call :__run_sample_fuse_test passthrough-fuse x64 passthrough-fuse-x64 winfsp-tests-x64
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:sample-passthrough-fuse-x86
|
||||||
|
call :__run_sample_fuse_test passthrough-fuse x86 passthrough-fuse-x86 winfsp-tests-x86
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:__run_sample_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" "-u %%%%1 -m %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||||
|
echo net use L: "\\%1\%TMP::=$%\%1\test"
|
||||||
|
net use L: "\\%1\%TMP::=$%\%1\test"
|
||||||
|
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%\%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
|
||||||
|
net use L: /delete
|
||||||
|
call "%ProjRoot%\tools\fsreg" -u %1
|
||||||
|
rmdir /s/q "%TMP%\%1"
|
||||||
|
exit /b !RunSampleTestExit!
|
||||||
|
|
||||||
|
:__run_sample_fuse_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" ^
|
||||||
|
"-ouid=11,gid=65792 --VolumePrefix=%%%%1 %%%%2" "D:P(A;;RPWPLC;;;WD)"
|
||||||
|
echo net use L: "\\%1\%TMP::=$%\%1\test"
|
||||||
|
net use L: "\\%1\%TMP::=$%\%1\test"
|
||||||
|
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%\%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 -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -exec_rename_dir_test ^
|
||||||
|
-reparse* -stream*
|
||||||
|
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||||
|
popd
|
||||||
|
echo net use L: /delete
|
||||||
|
net use L: /delete
|
||||||
|
call "%ProjRoot%\tools\fsreg" -u %1
|
||||||
|
rmdir /s/q "%TMP%\%1"
|
||||||
|
exit /b !RunSampleTestExit!
|
||||||
|
|
||||||
:leak-test
|
:leak-test
|
||||||
for /F "tokens=1,2 delims=:" %%i in ('verifier /query ^| findstr ^
|
for /F "tokens=1,2 delims=:" %%i in ('verifier /query ^| findstr ^
|
||||||
/c:"Current Pool Allocations:" ^
|
/c:"Current Pool Allocations:" ^
|
||||||
|
15
tools/version-info.bat
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
for %%f in (%*) do (
|
||||||
|
set file="%%~f"
|
||||||
|
if exist !file! (
|
||||||
|
echo version-info: !file!
|
||||||
|
powershell -command "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(""!file!"") | fl -property ProductName, ProductVersion, ProductVersionRaw, LegalCopyright, CompanyName, FileDescription, FileVersionRaw, FileVersion"
|
||||||
|
powershell -command "try { [System.Reflection.AssemblyName]::GetAssemblyName(""!file!"") | fl -property FullName, Version } catch {}"
|
||||||
|
) else (
|
||||||
|
echo version-info: file !file! not found
|
||||||
|
)
|
||||||
|
)
|
1156
tst/memfs-dotnet/Program.cs
Normal file
@ -106,7 +106,7 @@ NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
if (0 != DebugLogFile)
|
if (0 != DebugLogFile)
|
||||||
{
|
{
|
||||||
if (0 == wcscmp(L"-", DebugLogFile))
|
if (0 == wcscmp(L"-", DebugLogFile))
|
||||||
DebugLogHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
else
|
else
|
||||||
DebugLogHandle = CreateFileW(
|
DebugLogHandle = CreateFileW(
|
||||||
DebugLogFile,
|
DebugLogFile,
|
||||||
@ -184,7 +184,7 @@ usage:
|
|||||||
"\n"
|
"\n"
|
||||||
"options:\n"
|
"options:\n"
|
||||||
" -d DebugFlags [-1: enable all debug logs]\n"
|
" -d DebugFlags [-1: enable all debug logs]\n"
|
||||||
" -D DebugLogFile [file path; use - for stdout]\n"
|
" -D DebugLogFile [file path; use - for stderr]\n"
|
||||||
" -i [case insensitive file system]\n"
|
" -i [case insensitive file system]\n"
|
||||||
" -t FileInfoTimeout [millis]\n"
|
" -t FileInfoTimeout [millis]\n"
|
||||||
" -n MaxFileNodes\n"
|
" -n MaxFileNodes\n"
|
||||||
|
@ -45,9 +45,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
|||||||
/*
|
/*
|
||||||
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
||||||
* a check for the Write buffer to ensure that it is read-only.
|
* a check for the Write buffer to ensure that it is read-only.
|
||||||
|
*
|
||||||
|
* Since ProcessBuffer support in the FSD, this is no longer a guarantee.
|
||||||
*/
|
*/
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
#define DEBUG_BUFFER_CHECK
|
//#define DEBUG_BUFFER_CHECK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MEMFS_SECTOR_SIZE 512
|
#define MEMFS_SECTOR_SIZE 512
|
||||||
@ -580,58 +582,6 @@ VOID MemfsFileNodeMapEnumerateFree(MEMFS_FILE_NODE_MAP_ENUM_CONTEXT *Context)
|
|||||||
free(Context->FileNodes);
|
free(Context->FileNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::unordered_map<UINT64, std::wstring> MEMFS_DIR_DESC;
|
|
||||||
|
|
||||||
static inline
|
|
||||||
NTSTATUS MemfsDirDescCreate(MEMFS_DIR_DESC **PDirDesc)
|
|
||||||
{
|
|
||||||
*PDirDesc = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
*PDirDesc = new MEMFS_DIR_DESC;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
VOID MemfsDirDescDelete(MEMFS_DIR_DESC *DirDesc)
|
|
||||||
{
|
|
||||||
delete DirDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
VOID MemfsDirDescReset(MEMFS_DIR_DESC *DirDesc)
|
|
||||||
{
|
|
||||||
DirDesc->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
PWSTR MemfsDirDescGetFileName(MEMFS_DIR_DESC *DirDesc, UINT64 Offset)
|
|
||||||
{
|
|
||||||
MEMFS_DIR_DESC::iterator iter = DirDesc->find(Offset);
|
|
||||||
if (iter == DirDesc->end())
|
|
||||||
return 0;
|
|
||||||
return const_cast<PWSTR>(iter->second.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
NTSTATUS MemfsDirDescInsertFileName(MEMFS_DIR_DESC *DirDesc, UINT64 Offset, PWSTR FileName)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DirDesc->insert(MEMFS_DIR_DESC::value_type(Offset, FileName));
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FSP_FILE_SYSTEM_INTERFACE
|
* FSP_FILE_SYSTEM_INTERFACE
|
||||||
*/
|
*/
|
||||||
@ -745,7 +695,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
#endif
|
#endif
|
||||||
MEMFS_FILE_NODE *FileNode;
|
MEMFS_FILE_NODE *FileNode;
|
||||||
MEMFS_FILE_NODE *ParentNode;
|
MEMFS_FILE_NODE *ParentNode;
|
||||||
MEMFS_DIR_DESC *DirDesc = 0;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN Inserted;
|
BOOLEAN Inserted;
|
||||||
|
|
||||||
@ -794,20 +743,9 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CreateOptions & FILE_DIRECTORY_FILE)
|
|
||||||
{
|
|
||||||
Result = MemfsDirDescCreate(&DirDesc);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = MemfsFileNodeCreate(FileName, &FileNode);
|
Result = MemfsFileNodeCreate(FileName, &FileNode);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MEMFS_NAMED_STREAMS)
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
|
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
|
||||||
@ -823,8 +761,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == FileNode->FileSecurity)
|
if (0 == FileNode->FileSecurity)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
||||||
@ -837,8 +773,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == FileNode->FileData)
|
if (0 == FileNode->FileData)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -847,8 +781,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result) || !Inserted)
|
if (!NT_SUCCESS(Result) || !Inserted)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
Result = STATUS_OBJECT_NAME_COLLISION; /* should not happen! */
|
Result = STATUS_OBJECT_NAME_COLLISION; /* should not happen! */
|
||||||
return Result;
|
return Result;
|
||||||
@ -869,9 +801,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* since we now use dir descriptors to quickly retrieve dir contents, place it in UserContext2 */
|
|
||||||
FspFileSystemGetOperationContext()->Response->Rsp.Create.Opened.UserContext2 = (UINT_PTR)DirDesc;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,7 +810,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode;
|
MEMFS_FILE_NODE *FileNode;
|
||||||
MEMFS_DIR_DESC *DirDesc = 0;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (MEMFS_MAX_PATH <= wcslen(FileName))
|
if (MEMFS_MAX_PATH <= wcslen(FileName))
|
||||||
@ -895,13 +823,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
||||||
{
|
|
||||||
Result = MemfsDirDescCreate(&DirDesc);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemfsFileNodeReference(FileNode);
|
MemfsFileNodeReference(FileNode);
|
||||||
*PFileNode = FileNode;
|
*PFileNode = FileNode;
|
||||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
@ -917,9 +838,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* since we now use dir descriptors to quickly retrieve dir contents, place it in UserContext2 */
|
|
||||||
FspFileSystemGetOperationContext()->Response->Rsp.Create.Opened.UserContext2 = (UINT_PTR)DirDesc;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,13 +943,8 @@ static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
|
|
||||||
FspFileSystemGetOperationContext()->Request->Req.Close.UserContext2;
|
|
||||||
|
|
||||||
MemfsFileNodeDereference(FileNode);
|
MemfsFileNodeDereference(FileNode);
|
||||||
|
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -1394,14 +1307,11 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
typedef struct _MEMFS_READ_DIRECTORY_CONTEXT
|
typedef struct _MEMFS_READ_DIRECTORY_CONTEXT
|
||||||
{
|
{
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
UINT64 Offset;
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PULONG PBytesTransferred;
|
PULONG PBytesTransferred;
|
||||||
BOOLEAN OffsetFound;
|
|
||||||
MEMFS_DIR_DESC *DirDesc;
|
|
||||||
} MEMFS_READ_DIRECTORY_CONTEXT;
|
} MEMFS_READ_DIRECTORY_CONTEXT;
|
||||||
|
|
||||||
static BOOLEAN AddDirInfo(MEMFS_DIR_DESC *DirDesc, MEMFS_FILE_NODE *FileNode, PWSTR FileName,
|
static BOOLEAN AddDirInfo(MEMFS_FILE_NODE *FileNode, PWSTR FileName,
|
||||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
UINT8 DirInfoBuf[sizeof(FSP_FSCTL_DIR_INFO) + sizeof FileNode->FileName];
|
UINT8 DirInfoBuf[sizeof(FSP_FSCTL_DIR_INFO) + sizeof FileNode->FileName];
|
||||||
@ -1414,14 +1324,11 @@ static BOOLEAN AddDirInfo(MEMFS_DIR_DESC *DirDesc, MEMFS_FILE_NODE *FileNode, PW
|
|||||||
FspPathSuffix(FileNode->FileName, &Remain, &Suffix, Root);
|
FspPathSuffix(FileNode->FileName, &Remain, &Suffix, Root);
|
||||||
FileName = Suffix;
|
FileName = Suffix;
|
||||||
FspPathCombine(FileNode->FileName, Suffix);
|
FspPathCombine(FileNode->FileName, Suffix);
|
||||||
|
|
||||||
MemfsDirDescInsertFileName(DirDesc, FileNode->FileInfo.IndexNumber, FileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
DirInfo->FileInfo = FileNode->FileInfo;
|
DirInfo->FileInfo = FileNode->FileInfo;
|
||||||
DirInfo->NextOffset = FileNode->FileInfo.IndexNumber;
|
|
||||||
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
|
|
||||||
return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred);
|
return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred);
|
||||||
@ -1431,39 +1338,23 @@ static BOOLEAN ReadDirectoryEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
|
|||||||
{
|
{
|
||||||
MEMFS_READ_DIRECTORY_CONTEXT *Context = (MEMFS_READ_DIRECTORY_CONTEXT *)Context0;
|
MEMFS_READ_DIRECTORY_CONTEXT *Context = (MEMFS_READ_DIRECTORY_CONTEXT *)Context0;
|
||||||
|
|
||||||
if (0 != Context->Offset && !Context->OffsetFound)
|
return AddDirInfo(FileNode, 0,
|
||||||
{
|
|
||||||
Context->OffsetFound = FileNode->FileInfo.IndexNumber == Context->Offset;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddDirInfo(Context->DirDesc, FileNode, 0,
|
|
||||||
Context->Buffer, Context->Length, Context->PBytesTransferred);
|
Context->Buffer, Context->Length, Context->PBytesTransferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length,
|
PVOID FileNode0, PWSTR Pattern, PWSTR Marker,
|
||||||
PWSTR Pattern,
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
PULONG PBytesTransferred)
|
|
||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
|
|
||||||
FspFileSystemGetOperationContext()->Request->Req.QueryDirectory.UserContext2;
|
|
||||||
MEMFS_FILE_NODE *ParentNode;
|
MEMFS_FILE_NODE *ParentNode;
|
||||||
MEMFS_READ_DIRECTORY_CONTEXT Context;
|
MEMFS_READ_DIRECTORY_CONTEXT Context;
|
||||||
PWSTR PrevFileName = 0;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Context.Buffer = Buffer;
|
Context.Buffer = Buffer;
|
||||||
Context.Offset = Offset;
|
|
||||||
Context.Length = Length;
|
Context.Length = Length;
|
||||||
Context.PBytesTransferred = PBytesTransferred;
|
Context.PBytesTransferred = PBytesTransferred;
|
||||||
Context.OffsetFound = FALSE;
|
|
||||||
Context.DirDesc = DirDesc;
|
|
||||||
|
|
||||||
if (0 == Offset)
|
|
||||||
MemfsDirDescReset(DirDesc);
|
|
||||||
|
|
||||||
if (L'\0' != FileNode->FileName[1])
|
if (L'\0' != FileNode->FileName[1])
|
||||||
{
|
{
|
||||||
@ -1473,25 +1364,20 @@ static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == ParentNode)
|
if (0 == ParentNode)
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
if (0 == Offset)
|
if (0 == Marker)
|
||||||
if (!AddDirInfo(DirDesc, FileNode, L".", Buffer, Length, PBytesTransferred))
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
if (0 == Offset || FileNode->FileInfo.IndexNumber == Offset)
|
|
||||||
{
|
{
|
||||||
Context.OffsetFound = FileNode->FileInfo.IndexNumber == Context.Offset;
|
if (!AddDirInfo(FileNode, L".", Buffer, Length, PBytesTransferred))
|
||||||
|
|
||||||
if (!AddDirInfo(DirDesc, ParentNode, L"..", Buffer, Length, PBytesTransferred))
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
if (0 == Marker || (L'.' == Marker[0] && L'\0' == Marker[1]))
|
||||||
|
{
|
||||||
|
if (!AddDirInfo(ParentNode, L"..", Buffer, Length, PBytesTransferred))
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
Marker = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != Context.Offset && !Context.OffsetFound)
|
if (MemfsFileNodeMapEnumerateChildren(Memfs->FileNodeMap, FileNode, Marker,
|
||||||
{
|
|
||||||
PrevFileName = MemfsDirDescGetFileName(DirDesc, Offset);
|
|
||||||
Context.OffsetFound = 0 != PrevFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MemfsFileNodeMapEnumerateChildren(Memfs->FileNodeMap, FileNode, PrevFileName,
|
|
||||||
ReadDirectoryEnumFn, &Context))
|
ReadDirectoryEnumFn, &Context))
|
||||||
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
||||||
|
|
||||||
|
5
tst/passthrough-cpp/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
build
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.vcproj.*
|
||||||
|
*.vcxproj.user
|
1016
tst/passthrough-cpp/passthrough-cpp.cpp
Normal file
28
tst/passthrough-cpp/passthrough-cpp.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}") = "passthrough-cpp", "passthrough-cpp.vcxproj", "{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}"
|
||||||
|
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
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x64.Build.0 = Release|x64
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
178
tst/passthrough-cpp/passthrough-cpp.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>{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>passthroughcpp</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="passthrough-cpp.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
14
tst/passthrough-cpp/passthrough-cpp.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="passthrough-cpp.cpp">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
6
tst/passthrough-dotnet/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
build
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.vcproj.*
|
||||||
|
*.vcxproj.user
|
||||||
|
*.csproj.user
|
845
tst/passthrough-dotnet/Program.cs
Normal file
@ -0,0 +1,845 @@
|
|||||||
|
/**
|
||||||
|
* @file Program.cs
|
||||||
|
*
|
||||||
|
* @copyright 2015-2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.AccessControl;
|
||||||
|
|
||||||
|
using Fsp;
|
||||||
|
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
||||||
|
using FileInfo = Fsp.Interop.FileInfo;
|
||||||
|
|
||||||
|
namespace passthrough
|
||||||
|
{
|
||||||
|
class Ptfs : FileSystemBase
|
||||||
|
{
|
||||||
|
protected const int ALLOCATION_UNIT = 4096;
|
||||||
|
|
||||||
|
protected static void ThrowIoExceptionWithHResult(Int32 HResult)
|
||||||
|
{
|
||||||
|
throw new IOException(null, HResult);
|
||||||
|
}
|
||||||
|
protected static void ThrowIoExceptionWithWin32(Int32 Error)
|
||||||
|
{
|
||||||
|
ThrowIoExceptionWithHResult(unchecked((Int32)(0x80070000 | Error)));
|
||||||
|
}
|
||||||
|
protected static void ThrowIoExceptionWithNtStatus(Int32 Status)
|
||||||
|
{
|
||||||
|
ThrowIoExceptionWithWin32((Int32)Win32FromNtStatus(Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class FileDesc
|
||||||
|
{
|
||||||
|
public FileStream Stream;
|
||||||
|
public DirectoryInfo DirInfo;
|
||||||
|
public DictionaryEntry[] FileSystemInfos;
|
||||||
|
|
||||||
|
public FileDesc(FileStream Stream)
|
||||||
|
{
|
||||||
|
this.Stream = Stream;
|
||||||
|
}
|
||||||
|
public FileDesc(DirectoryInfo DirInfo)
|
||||||
|
{
|
||||||
|
this.DirInfo = DirInfo;
|
||||||
|
}
|
||||||
|
public static void GetFileInfoFromFileSystemInfo(
|
||||||
|
FileSystemInfo Info,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileInfo.FileAttributes = (UInt32)Info.Attributes;
|
||||||
|
FileInfo.ReparseTag = 0;
|
||||||
|
FileInfo.FileSize = Info is System.IO.FileInfo ?
|
||||||
|
(UInt64)((System.IO.FileInfo)Info).Length : 0;
|
||||||
|
FileInfo.AllocationSize = (FileInfo.FileSize + ALLOCATION_UNIT - 1)
|
||||||
|
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
|
||||||
|
FileInfo.CreationTime = (UInt64)Info.CreationTimeUtc.ToFileTimeUtc();
|
||||||
|
FileInfo.LastAccessTime = (UInt64)Info.LastAccessTimeUtc.ToFileTimeUtc();
|
||||||
|
FileInfo.LastWriteTime = (UInt64)Info.LastWriteTimeUtc.ToFileTimeUtc();
|
||||||
|
FileInfo.ChangeTime = FileInfo.LastWriteTime;
|
||||||
|
FileInfo.IndexNumber = 0;
|
||||||
|
FileInfo.HardLinks = 0;
|
||||||
|
}
|
||||||
|
public Int32 GetFileInfo(out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
if (null != Stream)
|
||||||
|
{
|
||||||
|
BY_HANDLE_FILE_INFORMATION Info;
|
||||||
|
if (!GetFileInformationByHandle(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||||
|
out Info))
|
||||||
|
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||||
|
FileInfo.FileAttributes = Info.dwFileAttributes;
|
||||||
|
FileInfo.ReparseTag = 0;
|
||||||
|
FileInfo.FileSize = (UInt64)Stream.Length;
|
||||||
|
FileInfo.AllocationSize = (FileInfo.FileSize + ALLOCATION_UNIT - 1)
|
||||||
|
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
|
||||||
|
FileInfo.CreationTime = Info.ftCreationTime;
|
||||||
|
FileInfo.LastAccessTime = Info.ftLastAccessTime;
|
||||||
|
FileInfo.LastWriteTime = Info.ftLastWriteTime;
|
||||||
|
FileInfo.ChangeTime = FileInfo.LastWriteTime;
|
||||||
|
FileInfo.IndexNumber = 0;
|
||||||
|
FileInfo.HardLinks = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GetFileInfoFromFileSystemInfo(DirInfo, out FileInfo);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public void SetBasicInfo(
|
||||||
|
UInt32 FileAttributes,
|
||||||
|
UInt64 CreationTime,
|
||||||
|
UInt64 LastAccessTime,
|
||||||
|
UInt64 LastWriteTime)
|
||||||
|
{
|
||||||
|
if (0 == FileAttributes)
|
||||||
|
FileAttributes = (UInt32)System.IO.FileAttributes.Normal;
|
||||||
|
if (null != Stream)
|
||||||
|
{
|
||||||
|
FILE_BASIC_INFO Info = default(FILE_BASIC_INFO);
|
||||||
|
if (unchecked((UInt32)(-1)) != FileAttributes)
|
||||||
|
Info.FileAttributes = FileAttributes;
|
||||||
|
if (0 != CreationTime)
|
||||||
|
Info.CreationTime = CreationTime;
|
||||||
|
if (0 != LastAccessTime)
|
||||||
|
Info.LastAccessTime = LastAccessTime;
|
||||||
|
if (0 != LastWriteTime)
|
||||||
|
Info.LastWriteTime = LastWriteTime;
|
||||||
|
if (!SetFileInformationByHandle(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||||
|
0/*FileBasicInfo*/, ref Info, (UInt32)Marshal.SizeOf(Info)))
|
||||||
|
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (unchecked((UInt32)(-1)) != FileAttributes)
|
||||||
|
DirInfo.Attributes = (System.IO.FileAttributes)FileAttributes;
|
||||||
|
if (0 != CreationTime)
|
||||||
|
DirInfo.CreationTimeUtc = DateTime.FromFileTimeUtc((Int64)CreationTime);
|
||||||
|
if (0 != LastAccessTime)
|
||||||
|
DirInfo.LastAccessTimeUtc = DateTime.FromFileTimeUtc((Int64)LastAccessTime);
|
||||||
|
if (0 != LastWriteTime)
|
||||||
|
DirInfo.LastWriteTimeUtc = DateTime.FromFileTimeUtc((Int64)LastWriteTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public UInt32 GetFileAttributes()
|
||||||
|
{
|
||||||
|
FileInfo FileInfo;
|
||||||
|
GetFileInfo(out FileInfo);
|
||||||
|
return FileInfo.FileAttributes;
|
||||||
|
}
|
||||||
|
public void SetFileAttributes(UInt32 FileAttributes)
|
||||||
|
{
|
||||||
|
SetBasicInfo(FileAttributes, 0, 0, 0);
|
||||||
|
}
|
||||||
|
public Byte[] GetSecurityDescriptor()
|
||||||
|
{
|
||||||
|
if (null != Stream)
|
||||||
|
return Stream.GetAccessControl().GetSecurityDescriptorBinaryForm();
|
||||||
|
else
|
||||||
|
return DirInfo.GetAccessControl().GetSecurityDescriptorBinaryForm();
|
||||||
|
}
|
||||||
|
public void SetSecurityDescriptor(AccessControlSections Sections, Byte[] SecurityDescriptor)
|
||||||
|
{
|
||||||
|
Int32 SecurityInformation = 0;
|
||||||
|
if (0 != (Sections & AccessControlSections.Owner))
|
||||||
|
SecurityInformation |= 1/*OWNER_SECURITY_INFORMATION*/;
|
||||||
|
if (0 != (Sections & AccessControlSections.Group))
|
||||||
|
SecurityInformation |= 2/*GROUP_SECURITY_INFORMATION*/;
|
||||||
|
if (0 != (Sections & AccessControlSections.Access))
|
||||||
|
SecurityInformation |= 4/*DACL_SECURITY_INFORMATION*/;
|
||||||
|
if (0 != (Sections & AccessControlSections.Audit))
|
||||||
|
SecurityInformation |= 8/*SACL_SECURITY_INFORMATION*/;
|
||||||
|
if (null != Stream)
|
||||||
|
{
|
||||||
|
if (!SetKernelObjectSecurity(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||||
|
SecurityInformation, SecurityDescriptor))
|
||||||
|
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!SetFileSecurityW(DirInfo.FullName,
|
||||||
|
SecurityInformation, SecurityDescriptor))
|
||||||
|
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void SetDisposition(Boolean Safe)
|
||||||
|
{
|
||||||
|
if (null != Stream)
|
||||||
|
{
|
||||||
|
FILE_DISPOSITION_INFO Info;
|
||||||
|
Info.DeleteFile = true;
|
||||||
|
if (!SetFileInformationByHandle(Stream.SafeFileHandle.DangerousGetHandle(),
|
||||||
|
4/*FileDispositionInfo*/, ref Info, (UInt32)Marshal.SizeOf(Info)))
|
||||||
|
if (!Safe)
|
||||||
|
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DirInfo.Delete();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (!Safe)
|
||||||
|
ThrowIoExceptionWithHResult(ex.HResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void Rename(String FileName, String NewFileName, Boolean ReplaceIfExists)
|
||||||
|
{
|
||||||
|
if (!MoveFileExW(FileName, NewFileName, ReplaceIfExists ? 1U/*MOVEFILE_REPLACE_EXISTING*/ : 0))
|
||||||
|
ThrowIoExceptionWithWin32(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interop */
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
private struct BY_HANDLE_FILE_INFORMATION
|
||||||
|
{
|
||||||
|
public UInt32 dwFileAttributes;
|
||||||
|
public UInt64 ftCreationTime;
|
||||||
|
public UInt64 ftLastAccessTime;
|
||||||
|
public UInt64 ftLastWriteTime;
|
||||||
|
public UInt32 dwVolumeSerialNumber;
|
||||||
|
public UInt32 nFileSizeHigh;
|
||||||
|
public UInt32 nFileSizeLow;
|
||||||
|
public UInt32 nNumberOfLinks;
|
||||||
|
public UInt32 nFileIndexHigh;
|
||||||
|
public UInt32 nFileIndexLow;
|
||||||
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct FILE_BASIC_INFO
|
||||||
|
{
|
||||||
|
public UInt64 CreationTime;
|
||||||
|
public UInt64 LastAccessTime;
|
||||||
|
public UInt64 LastWriteTime;
|
||||||
|
public UInt64 ChangeTime;
|
||||||
|
public UInt32 FileAttributes;
|
||||||
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct FILE_DISPOSITION_INFO
|
||||||
|
{
|
||||||
|
public Boolean DeleteFile;
|
||||||
|
}
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern Boolean GetFileInformationByHandle(
|
||||||
|
IntPtr hFile,
|
||||||
|
out BY_HANDLE_FILE_INFORMATION lpFileInformation);
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern Boolean SetFileInformationByHandle(
|
||||||
|
IntPtr hFile,
|
||||||
|
Int32 FileInformationClass,
|
||||||
|
ref FILE_BASIC_INFO lpFileInformation,
|
||||||
|
UInt32 dwBufferSize);
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern Boolean SetFileInformationByHandle(
|
||||||
|
IntPtr hFile,
|
||||||
|
Int32 FileInformationClass,
|
||||||
|
ref FILE_DISPOSITION_INFO lpFileInformation,
|
||||||
|
UInt32 dwBufferSize);
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern Boolean MoveFileExW(
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)] String lpExistingFileName,
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)] String lpNewFileName,
|
||||||
|
UInt32 dwFlags);
|
||||||
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||||||
|
private static extern Boolean SetFileSecurityW(
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||||
|
Int32 SecurityInformation,
|
||||||
|
Byte[] SecurityDescriptor);
|
||||||
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||||||
|
private static extern Boolean SetKernelObjectSecurity(
|
||||||
|
IntPtr Handle,
|
||||||
|
Int32 SecurityInformation,
|
||||||
|
Byte[] SecurityDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DirectoryEntryComparer : IComparer
|
||||||
|
{
|
||||||
|
public int Compare(object x, object y)
|
||||||
|
{
|
||||||
|
return String.Compare(
|
||||||
|
(String)((DictionaryEntry)x).Key,
|
||||||
|
(String)((DictionaryEntry)y).Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static DirectoryEntryComparer _DirectoryEntryComparer =
|
||||||
|
new DirectoryEntryComparer();
|
||||||
|
|
||||||
|
public Ptfs(String Path0)
|
||||||
|
{
|
||||||
|
_Path = Path.GetFullPath(Path0);
|
||||||
|
if (_Path.EndsWith("\\"))
|
||||||
|
_Path = _Path.Substring(0, _Path.Length - 1);
|
||||||
|
}
|
||||||
|
public String ConcatPath(String FileName)
|
||||||
|
{
|
||||||
|
return _Path + FileName;
|
||||||
|
}
|
||||||
|
public override Int32 ExceptionHandler(Exception ex)
|
||||||
|
{
|
||||||
|
Int32 HResult = ex.HResult; /* needs Framework 4.5 */
|
||||||
|
if (0x80070000 == (HResult & 0xFFFF0000))
|
||||||
|
return NtStatusFromWin32((UInt32)HResult & 0xFFFF);
|
||||||
|
return STATUS_UNEXPECTED_IO_ERROR;
|
||||||
|
}
|
||||||
|
public override Int32 Init(Object Host0)
|
||||||
|
{
|
||||||
|
FileSystemHost Host = (FileSystemHost)Host0;
|
||||||
|
Host.SectorSize = ALLOCATION_UNIT;
|
||||||
|
Host.SectorsPerAllocationUnit = 1;
|
||||||
|
Host.MaxComponentLength = 255;
|
||||||
|
Host.FileInfoTimeout = 1000;
|
||||||
|
Host.CaseSensitiveSearch = false;
|
||||||
|
Host.CasePreservedNames = true;
|
||||||
|
Host.UnicodeOnDisk = true;
|
||||||
|
Host.PersistentAcls = true;
|
||||||
|
Host.PostCleanupWhenModifiedOnly = true;
|
||||||
|
Host.PassQueryDirectoryPattern = true;
|
||||||
|
Host.VolumeCreationTime = (UInt64)File.GetCreationTimeUtc(_Path).ToFileTimeUtc();
|
||||||
|
Host.VolumeSerialNumber = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 GetVolumeInfo(
|
||||||
|
out VolumeInfo VolumeInfo)
|
||||||
|
{
|
||||||
|
VolumeInfo = default(VolumeInfo);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DriveInfo Info = new DriveInfo(_Path);
|
||||||
|
VolumeInfo.TotalSize = (UInt64)Info.TotalSize;
|
||||||
|
VolumeInfo.FreeSize = (UInt64)Info.TotalFreeSpace;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* DriveInfo only supports drives and does not support UNC paths.
|
||||||
|
* It would be better to use GetDiskFreeSpaceEx here.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 GetSecurityByName(
|
||||||
|
String FileName,
|
||||||
|
out UInt32 FileAttributes/* or ReparsePointIndex */,
|
||||||
|
ref Byte[] SecurityDescriptor)
|
||||||
|
{
|
||||||
|
FileName = ConcatPath(FileName);
|
||||||
|
System.IO.FileInfo Info = new System.IO.FileInfo(FileName);
|
||||||
|
FileAttributes = (UInt32)Info.Attributes;
|
||||||
|
if (null != SecurityDescriptor)
|
||||||
|
SecurityDescriptor = Info.GetAccessControl().GetSecurityDescriptorBinaryForm();
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 Create(
|
||||||
|
String FileName,
|
||||||
|
UInt32 CreateOptions,
|
||||||
|
UInt32 GrantedAccess,
|
||||||
|
UInt32 FileAttributes,
|
||||||
|
Byte[] SecurityDescriptor,
|
||||||
|
UInt64 AllocationSize,
|
||||||
|
out Object FileNode,
|
||||||
|
out Object FileDesc0,
|
||||||
|
out FileInfo FileInfo,
|
||||||
|
out String NormalizedName)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileName = ConcatPath(FileName);
|
||||||
|
if (0 == (CreateOptions & FILE_DIRECTORY_FILE))
|
||||||
|
{
|
||||||
|
FileSecurity Security = null;
|
||||||
|
if (null != SecurityDescriptor)
|
||||||
|
{
|
||||||
|
Security = new FileSecurity();
|
||||||
|
Security.SetSecurityDescriptorBinaryForm(SecurityDescriptor);
|
||||||
|
}
|
||||||
|
FileDesc = new FileDesc(
|
||||||
|
new FileStream(
|
||||||
|
FileName,
|
||||||
|
FileMode.CreateNew,
|
||||||
|
(FileSystemRights)GrantedAccess | FileSystemRights.WriteAttributes,
|
||||||
|
FileShare.Read | FileShare.Write | FileShare.Delete,
|
||||||
|
4096,
|
||||||
|
0,
|
||||||
|
Security));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Directory.Exists(FileName))
|
||||||
|
ThrowIoExceptionWithNtStatus(STATUS_OBJECT_NAME_COLLISION);
|
||||||
|
DirectorySecurity Security = null;
|
||||||
|
if (null != SecurityDescriptor)
|
||||||
|
{
|
||||||
|
Security = new DirectorySecurity();
|
||||||
|
Security.SetSecurityDescriptorBinaryForm(SecurityDescriptor);
|
||||||
|
}
|
||||||
|
FileDesc = new FileDesc(
|
||||||
|
Directory.CreateDirectory(FileName, Security));
|
||||||
|
}
|
||||||
|
FileDesc.SetFileAttributes(FileAttributes);
|
||||||
|
FileNode = default(Object);
|
||||||
|
FileDesc0 = FileDesc;
|
||||||
|
NormalizedName = default(String);
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if (null != FileDesc && null != FileDesc.Stream)
|
||||||
|
FileDesc.Stream.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Int32 Open(
|
||||||
|
String FileName,
|
||||||
|
UInt32 CreateOptions,
|
||||||
|
UInt32 GrantedAccess,
|
||||||
|
out Object FileNode,
|
||||||
|
out Object FileDesc0,
|
||||||
|
out FileInfo FileInfo,
|
||||||
|
out String NormalizedName)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileName = ConcatPath(FileName);
|
||||||
|
if (!Directory.Exists(FileName))
|
||||||
|
{
|
||||||
|
FileDesc = new FileDesc(
|
||||||
|
new FileStream(
|
||||||
|
FileName,
|
||||||
|
FileMode.Open,
|
||||||
|
(FileSystemRights)GrantedAccess,
|
||||||
|
FileShare.Read | FileShare.Write | FileShare.Delete,
|
||||||
|
4096,
|
||||||
|
0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileDesc = new FileDesc(
|
||||||
|
new DirectoryInfo(FileName));
|
||||||
|
}
|
||||||
|
FileNode = default(Object);
|
||||||
|
FileDesc0 = FileDesc;
|
||||||
|
NormalizedName = default(String);
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if (null != FileDesc && null != FileDesc.Stream)
|
||||||
|
FileDesc.Stream.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Int32 Overwrite(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
UInt32 FileAttributes,
|
||||||
|
Boolean ReplaceFileAttributes,
|
||||||
|
UInt64 AllocationSize,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (ReplaceFileAttributes)
|
||||||
|
FileDesc.SetFileAttributes(FileAttributes);
|
||||||
|
else if (0 != FileAttributes)
|
||||||
|
FileDesc.SetFileAttributes(FileDesc.GetFileAttributes() | FileAttributes);
|
||||||
|
FileDesc.Stream.SetLength(0);
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
public override void Cleanup(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
String FileName,
|
||||||
|
UInt32 Flags)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (0 != (Flags & CleanupDelete))
|
||||||
|
{
|
||||||
|
FileDesc.SetDisposition(true);
|
||||||
|
if (null != FileDesc.Stream)
|
||||||
|
FileDesc.Stream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void Close(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (null != FileDesc.Stream)
|
||||||
|
FileDesc.Stream.Dispose();
|
||||||
|
}
|
||||||
|
public override Int32 Read(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt32 Length,
|
||||||
|
out UInt32 PBytesTransferred)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (Offset >= (UInt64)FileDesc.Stream.Length)
|
||||||
|
ThrowIoExceptionWithNtStatus(STATUS_END_OF_FILE);
|
||||||
|
Byte[] Bytes = new byte[Length];
|
||||||
|
FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin);
|
||||||
|
PBytesTransferred = (UInt32)FileDesc.Stream.Read(Bytes, 0, Bytes.Length);
|
||||||
|
Marshal.Copy(Bytes, 0, Buffer, Bytes.Length);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 Write(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt32 Length,
|
||||||
|
Boolean WriteToEndOfFile,
|
||||||
|
Boolean ConstrainedIo,
|
||||||
|
out UInt32 PBytesTransferred,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (ConstrainedIo)
|
||||||
|
{
|
||||||
|
if (Offset >= (UInt64)FileDesc.Stream.Length)
|
||||||
|
{
|
||||||
|
PBytesTransferred = default(UInt32);
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (Offset + Length > (UInt64)FileDesc.Stream.Length)
|
||||||
|
Length = (UInt32)((UInt64)FileDesc.Stream.Length - Offset);
|
||||||
|
}
|
||||||
|
Byte[] Bytes = new byte[Length];
|
||||||
|
Marshal.Copy(Buffer, Bytes, 0, Bytes.Length);
|
||||||
|
if (!WriteToEndOfFile)
|
||||||
|
FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin);
|
||||||
|
FileDesc.Stream.Write(Bytes, 0, Bytes.Length);
|
||||||
|
PBytesTransferred = (UInt32)Bytes.Length;
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
public override Int32 Flush(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (null == FileDesc)
|
||||||
|
{
|
||||||
|
/* we do not flush the whole volume, so just return SUCCESS */
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
FileDesc.Stream.Flush(true);
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
public override Int32 GetFileInfo(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
public override Int32 SetBasicInfo(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
UInt32 FileAttributes,
|
||||||
|
UInt64 CreationTime,
|
||||||
|
UInt64 LastAccessTime,
|
||||||
|
UInt64 LastWriteTime,
|
||||||
|
UInt64 ChangeTime,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
FileDesc.SetBasicInfo(FileAttributes, CreationTime, LastAccessTime, LastWriteTime);
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
public override Int32 SetFileSize(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
UInt64 NewSize,
|
||||||
|
Boolean SetAllocationSize,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (!SetAllocationSize || (UInt64)FileDesc.Stream.Length > NewSize)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* "FileInfo.FileSize > NewSize" explanation:
|
||||||
|
* Ptfs does not support allocation size. However if the new AllocationSize
|
||||||
|
* is less than the current FileSize we must truncate the file.
|
||||||
|
*/
|
||||||
|
FileDesc.Stream.SetLength((Int64)NewSize);
|
||||||
|
}
|
||||||
|
return FileDesc.GetFileInfo(out FileInfo);
|
||||||
|
}
|
||||||
|
public override Int32 CanDelete(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
String FileName)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
FileDesc.SetDisposition(false);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 Rename(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
String FileName,
|
||||||
|
String NewFileName,
|
||||||
|
Boolean ReplaceIfExists)
|
||||||
|
{
|
||||||
|
FileName = ConcatPath(FileName);
|
||||||
|
NewFileName = ConcatPath(NewFileName);
|
||||||
|
FileDesc.Rename(FileName, NewFileName, ReplaceIfExists);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 GetSecurity(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
ref Byte[] SecurityDescriptor)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
SecurityDescriptor = FileDesc.GetSecurityDescriptor();
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Int32 SetSecurity(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
AccessControlSections Sections,
|
||||||
|
Byte[] SecurityDescriptor)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
FileDesc.SetSecurityDescriptor(Sections, SecurityDescriptor);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
public override Boolean ReadDirectoryEntry(
|
||||||
|
Object FileNode,
|
||||||
|
Object FileDesc0,
|
||||||
|
String Pattern,
|
||||||
|
String Marker,
|
||||||
|
ref Object Context,
|
||||||
|
out String FileName,
|
||||||
|
out FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||||
|
if (null == FileDesc.FileSystemInfos)
|
||||||
|
{
|
||||||
|
IEnumerable Enum = FileDesc.DirInfo.EnumerateFileSystemInfos(
|
||||||
|
null != Pattern ? Pattern : "*");
|
||||||
|
SortedList List = new SortedList();
|
||||||
|
List.Add(".", FileDesc.DirInfo);
|
||||||
|
List.Add("..", FileDesc.DirInfo.Parent);
|
||||||
|
foreach (FileSystemInfo Info in Enum)
|
||||||
|
List.Add(Info.Name, Info);
|
||||||
|
FileDesc.FileSystemInfos = new DictionaryEntry[List.Count];
|
||||||
|
List.CopyTo(FileDesc.FileSystemInfos, 0);
|
||||||
|
}
|
||||||
|
int Index;
|
||||||
|
if (null == Context)
|
||||||
|
{
|
||||||
|
Index = 0;
|
||||||
|
if (null != Marker)
|
||||||
|
{
|
||||||
|
Index = Array.BinarySearch(FileDesc.FileSystemInfos,
|
||||||
|
new DictionaryEntry(Marker, null),
|
||||||
|
_DirectoryEntryComparer);
|
||||||
|
if (0 <= Index)
|
||||||
|
Index++;
|
||||||
|
else
|
||||||
|
Index = ~Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Index = (int)Context;
|
||||||
|
if (FileDesc.FileSystemInfos.Length > Index)
|
||||||
|
{
|
||||||
|
Context = Index + 1;
|
||||||
|
FileName = (String)FileDesc.FileSystemInfos[Index].Key;
|
||||||
|
FileDesc.GetFileInfoFromFileSystemInfo(
|
||||||
|
(FileSystemInfo)FileDesc.FileSystemInfos[Index].Value,
|
||||||
|
out FileInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileName = default(String);
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String _Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PtfsService : Service
|
||||||
|
{
|
||||||
|
private class CommandLineUsageException : Exception
|
||||||
|
{
|
||||||
|
public CommandLineUsageException(String Message = null) : base(Message)
|
||||||
|
{
|
||||||
|
HasMessage = null != Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private const String PROGNAME = "passthrough-dotnet";
|
||||||
|
|
||||||
|
public PtfsService() : base("PtfsService")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart(String[] Args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String DebugLogFile = null;
|
||||||
|
UInt32 DebugFlags = 0;
|
||||||
|
String VolumePrefix = null;
|
||||||
|
String PassThrough = null;
|
||||||
|
String MountPoint = null;
|
||||||
|
IntPtr DebugLogHandle = (IntPtr)(-1);
|
||||||
|
FileSystemHost Host = null;
|
||||||
|
Ptfs Ptfs = null;
|
||||||
|
int I;
|
||||||
|
|
||||||
|
for (I = 1; Args.Length > I; I++)
|
||||||
|
{
|
||||||
|
String Arg = Args[I];
|
||||||
|
if ('-' != Arg[0])
|
||||||
|
break;
|
||||||
|
switch (Arg[1])
|
||||||
|
{
|
||||||
|
case '?':
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
case 'd':
|
||||||
|
argtol(Args, ref I, ref DebugFlags);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
argtos(Args, ref I, ref DebugLogFile);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
argtos(Args, ref I, ref MountPoint);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
argtos(Args, ref I, ref PassThrough);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
argtos(Args, ref I, ref VolumePrefix);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Args.Length > I)
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
|
||||||
|
if (null == PassThrough && null != VolumePrefix)
|
||||||
|
{
|
||||||
|
I = VolumePrefix.IndexOf('\\');
|
||||||
|
if (-1 != I && VolumePrefix.Length > I && '\\' != VolumePrefix[I + 1])
|
||||||
|
{
|
||||||
|
I = VolumePrefix.IndexOf('\\', I + 1);
|
||||||
|
if (-1 != I &&
|
||||||
|
VolumePrefix.Length > I + 1 &&
|
||||||
|
(
|
||||||
|
('A' <= VolumePrefix[I + 1] && VolumePrefix[I + 1] <= 'Z') ||
|
||||||
|
('a' <= VolumePrefix[I + 1] && VolumePrefix[I + 1] <= 'z')
|
||||||
|
) &&
|
||||||
|
'$' == VolumePrefix[I + 2])
|
||||||
|
{
|
||||||
|
PassThrough = String.Format("{0}:{1}", VolumePrefix[I + 1], VolumePrefix.Substring(I + 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == PassThrough || null == MountPoint)
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
|
||||||
|
if (null != DebugLogFile)
|
||||||
|
if (0 > FileSystemHost.SetDebugLogFile(DebugLogFile))
|
||||||
|
throw new CommandLineUsageException("cannot open debug log file");
|
||||||
|
|
||||||
|
Host = new FileSystemHost(Ptfs = new Ptfs(PassThrough));
|
||||||
|
Host.Prefix = VolumePrefix;
|
||||||
|
if (0 > Host.Mount(MountPoint, null, true, DebugFlags))
|
||||||
|
throw new IOException("cannot mount file system");
|
||||||
|
MountPoint = Host.MountPoint();
|
||||||
|
_Host = Host;
|
||||||
|
|
||||||
|
Log(EVENTLOG_INFORMATION_TYPE, String.Format("{0}{1}{2} -p {3} -m {4}",
|
||||||
|
PROGNAME,
|
||||||
|
null != VolumePrefix && 0 < VolumePrefix.Length ? " -u " : "",
|
||||||
|
null != VolumePrefix && 0 < VolumePrefix.Length ? VolumePrefix : "",
|
||||||
|
PassThrough,
|
||||||
|
MountPoint));
|
||||||
|
}
|
||||||
|
catch (CommandLineUsageException ex)
|
||||||
|
{
|
||||||
|
Log(EVENTLOG_ERROR_TYPE, String.Format(
|
||||||
|
"{0}" +
|
||||||
|
"usage: {1} OPTIONS\n" +
|
||||||
|
"\n" +
|
||||||
|
"options:\n" +
|
||||||
|
" -d DebugFlags [-1: enable all debug logs]\n" +
|
||||||
|
" -D DebugLogFile [file path; use - for stderr]\n" +
|
||||||
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
||||||
|
" -p Directory [directory to expose as pass through file system]\n" +
|
||||||
|
" -m MountPoint [X:|*|directory]\n",
|
||||||
|
ex.HasMessage ? ex.Message + "\n" : "",
|
||||||
|
PROGNAME));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log(EVENTLOG_ERROR_TYPE, String.Format("{0}", ex.Message));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected override void OnStop()
|
||||||
|
{
|
||||||
|
_Host.Unmount();
|
||||||
|
_Host = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void argtos(String[] Args, ref int I, ref String V)
|
||||||
|
{
|
||||||
|
if (Args.Length > ++I)
|
||||||
|
V = Args[I];
|
||||||
|
else
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
}
|
||||||
|
private static void argtol(String[] Args, ref int I, ref UInt32 V)
|
||||||
|
{
|
||||||
|
Int32 R;
|
||||||
|
if (Args.Length > ++I)
|
||||||
|
V = Int32.TryParse(Args[I], out R) ? (UInt32)R : V;
|
||||||
|
else
|
||||||
|
throw new CommandLineUsageException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileSystemHost _Host;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Environment.ExitCode = new PtfsService().Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
tst/passthrough-dotnet/passthrough-dotnet.csproj
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{6EC13EBC-BD7E-4997-9B29-49D5F06103A6}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>passthrough</RootNamespace>
|
||||||
|
<AssemblyName>passthrough-dotnet</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<BaseIntermediateOutputPath>$(SolutionDir)build\$(ProjectName).build\</BaseIntermediateOutputPath>
|
||||||
|
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="winfsp-msil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b099876d8fa9b1f3, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>$(MSBuildProgramFiles32)\WinFsp\bin\winfsp-msil.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|