mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
96 Commits
pvt-lockin
...
v1.3B3
Author | SHA1 | Date | |
---|---|---|---|
d54e9a3049 | |||
7d56b9c23d | |||
deb237f7b0 | |||
5ae0804bd2 | |||
382599e38f | |||
498ab91123 | |||
c2f87029d7 | |||
157c4bc09a | |||
4fcaa99d63 | |||
d6c3849120 | |||
ec39d4b888 | |||
ebc8c268e5 | |||
9501b5771d | |||
5d34a3bd8c | |||
5b72b4ad4a | |||
740411d604 | |||
5c3549c6eb | |||
9f56a21c7f | |||
2e7e95df76 | |||
b2e6c16ba0 | |||
bd32f54904 | |||
7908ba09ac | |||
5713605030 | |||
994e232fb3 | |||
9553bd52c4 | |||
1cab0f3975 | |||
499a3d1138 | |||
d29218ba69 | |||
5564a9efae | |||
750e72e601 | |||
9f13c6e915 | |||
5005dd6f5b | |||
f9b6fb8817 | |||
6b0b4c8b8e | |||
abb504053b | |||
fb507fc0bc | |||
d38afe8d16 | |||
a4629b8f8b | |||
670a38d549 | |||
b939f6bd2b | |||
3df27f5b28 | |||
7581cece81 | |||
b4f5707e4e | |||
309827860f | |||
2b6b049f86 | |||
77f3e064a2 | |||
f691a7a3c7 | |||
cc58668ce5 | |||
064d0b94f2 | |||
a48668149b | |||
b9915dcaa7 | |||
a7febb8265 | |||
d6aaf0088a | |||
f05af124e7 | |||
886b7cf9f7 | |||
e111451475 | |||
0c38f92082 | |||
9bd9cf4fbd | |||
2f026cbc6f | |||
68d8ade667 | |||
d9c450ecf4 | |||
e6d2ef9274 | |||
299f371dee | |||
bb8aee8673 | |||
08bf8e14ce | |||
ef1912bd8a | |||
ff155694ce | |||
e6ed6dbf4f | |||
f13b98c880 | |||
5d3b37122c | |||
9d1c892d68 | |||
7008871ed7 | |||
2a3eabfab2 | |||
35255526d3 | |||
b2e474658d | |||
4fe85222b1 | |||
fd3e5bad43 | |||
ea873ece22 | |||
42e01a9b27 | |||
c1c9dca94b | |||
dcabdff422 | |||
a2ec40008f | |||
f3819ba839 | |||
ead599e337 | |||
eb88f25f40 | |||
c2b066a054 | |||
266e0f4bab | |||
d02030897d | |||
c87ff75b8f | |||
2ca33665ef | |||
391dcf8a21 | |||
69d68eb22f | |||
d58f4b84a5 | |||
61935e4671 | |||
41838627c0 | |||
0b67329fc2 |
12
.github/ISSUE_TEMPLATE.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
(Enter your issue here.)
|
||||
|
||||
----
|
||||
|
||||
Before submitting this issue please review this checklist. Ideally all checkmarks should be checked upon submitting. (Use an x inside square brackets like so: [x])
|
||||
|
||||
- [ ] **Issue type**: Please consider posting only bug reports or enhancement requests. Questions are better in the [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp). Please also consult the [WinFsp Frequently Asked Questions](https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions).
|
||||
- [ ] **No Duplicate**: Ensure that your issue has not been filed before. (Check open and closed issues.)
|
||||
- [ ] **Description**: Provide a descriptive title and a detailed explanation of the problem you are experiencing (for a bug report) or you are trying to solve (for an enhancement request).
|
||||
- [ ] **Reproduce**: For bug reports provide detailed information on how to reproduce the problem. For enhancement requests you do not need to provide this information, unless you find it relevant.
|
||||
- [ ] **Behaviors**: Provide information on the expected and actual behaviors.
|
||||
- [ ] **Environment**: For bug reports provide information about your OS version and build (e.g. 10.0.14393) and WinFsp version and build (e.g. 2017.2 or 1.2.17341). For enhancement requests you do not need to provide this information, unless you find it relevant.
|
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
(Enter your PR description here.)
|
||||
|
||||
----
|
||||
|
||||
Before submitting this PR please review this checklist. Ideally all checkmarks should be checked upon submitting. (Use an x inside square brackets like so: [x])
|
||||
|
||||
- [ ] **Contributing**: You MUST read and be willing to accept the [CONTRIBUTOR AGREEMENT](https://github.com/billziss-gh/winfsp/blob/master/Contributors.asciidoc). The agreement gives joint copyright interests in your contributions to you and the original WinFsp author. If you have already accepted the [CONTRIBUTOR AGREEMENT](https://github.com/billziss-gh/winfsp/blob/master/Contributors.asciidoc) you do not need to do so again.
|
||||
- [ ] **Topic branch**: Avoid creating the PR off the master branch of your fork. Consider creating a topic branch and request a pull from that. This allows you to add commits to the master branch of your fork without affecting this PR.
|
||||
- [ ] **No tabs**: Consistently use SPACES everywhere. NO TABS, unless the file format requires it (e.g. Makefile).
|
||||
- [ ] **Style**: Follow the same code style as the rest of the project.
|
||||
- [ ] **Tests**: Include tests to the extent that it is possible, especially if you add a new feature.
|
||||
- [ ] **Quality**: Your design and code should be of high quality and something that you are proud of.
|
@ -1,6 +1,75 @@
|
||||
= Changelog
|
||||
|
||||
|
||||
v1.3B3 (2018.1 B3)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
||||
* Multiple Launcher changes:
|
||||
** New `FspLaunch` API. File systems can be started, stopped, queried and listed using `FspLaunchStart`, `FspLaunchStop`, `FspLaunchGetInfo` and `FspLaunchGetNameList`. The API is available in <winfsp/launch.h>
|
||||
** New Launcher registry settings `RunAs` and `WorkDirectory`. `RunAs` allows the laucher to launch a file system process under the service accounts LocalService and NetworkService. `WorkDirectory` can be used to specify the work directory for a newly launched file system process.
|
||||
* `FSP_FSCTL_VOLUME_PARAMS::FlushAndPurgeOnCleanup` limits the time that Windows keeps files open after an application has closed them. This purges the cache on the last `CloseHandle`, which is a performance drawback.
|
||||
** This is now the default behavior on FUSE. To revert to the previous behavior of keeping files open indefinitely use `-o KeepFileCache`.
|
||||
* `FSP_FSCTL_VOLUME_PARAMS` has been extended with fine-grained timeouts: `VolumeInfoTimeout`, `DirInfoTimeout`, `SecurityTimeout`, `StreamInfoTimeout`. Set `FSP_FSCTL_VOLUME_PARAMS::Version == sizeof(FSP_FSCTL_VOLUME_PARAMS)` to access the new fields.
|
||||
** New FUSE optons `VolumeInfoTimeout`, `DirInfoTimeout` complement the existing `FileInfoTimeout`.
|
||||
* The FSD (File System Driver) and its interaction with the Windows MUP (Multiple UNC Provider) has been changed. In practice this eliminates the delays experienced when right-clicking on a WinFsp-backed network drive in the Windows Explorer. (GitHub issue #87.)
|
||||
* The WinFsp network provider is now added first in the provider order list. Previously it was added last. (GitHub PR #131; thanks @felfert.)
|
||||
* The WinFsp installer now uses the Wix `Provides` dependency extension to provide a `WinFsp` dependency key. (GitHub PR #129; thanks @felfert.)
|
||||
* New FUSE `create_umask` option. (GitHub issue #138.)
|
||||
* Fix C++ compilation error for WinFsp-FUSE. (GitHub PR #154; thanks @benrubson.)
|
||||
* *NOTE*: Prior v1.3 betas run the MEMFS sample file systems under the LocalService account. This is no longer the case: going forward the MEMFS file systems will be running under the LocalSystem account (as in v1.2POST1).
|
||||
|
||||
|
||||
v1.3B2 (2018.1 B2)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
||||
* Multiple Launcher changes:
|
||||
** New `FspLaunch` API. File systems can be started, stopped, queried and listed using `FspLaunchStart`, `FspLaunchStop`, `FspLaunchGetInfo` and `FspLaunchGetNameList`.
|
||||
** New Launcher registry settings `RunAs` and `WorkDirectory`. `RunAs` allows the laucher to launch a file system process under the service accounts LocalService and NetworkService. `WorkDirectory` can be used to specify the work directory for a newly launched file system process.
|
||||
* The MEMFS sample file systems are now launched under the LocalService account.
|
||||
* The FSD (File System Driver) and its interaction with the Windows MUP (Multiple UNC Provider) has been changed. In practice this eliminates the delays experienced when right-clicking on a WinFsp-backed network drive in the Windows Explorer. (GitHub issue #87.)
|
||||
* The WinFsp network provider is now added first in the provider order list. Previously it was added last. (GitHub PR #131; thanks @felfert.)
|
||||
* The WinFsp installer now uses the Wix `Provides` dependency extension to provide a `WinFsp` dependency key. (GitHub PR #129; thanks @felfert.)
|
||||
|
||||
|
||||
v1.3B1 (2018.1 B1)::
|
||||
|
||||
Changes since v1.2POST1:
|
||||
|
||||
- The WinFsp Launcher can now be controlled by the new `FspLaunch` API. File systems can be started, stopped, queried and listed using `FspLaunchStart`, `FspLaunchStop`, `FspLaunchGetInfo` and `FspLaunchGetNameList`.
|
||||
- The WinFsp launcher now supports new registry settings `RunAs` and `WorkDirectory`. `RunAs` allows the laucher to launch a file system process under the service accounts LocalService and NetworkService. `WorkDirectory` can be used to specify the work directory for a newly launched file system process.
|
||||
- The MEMFS sample file systems are now launched under the LocalService account.
|
||||
- The WinFsp network provider is now added first in the provider order list. Previously it was added last. (GitHub PR #131; thanks @felfert.)
|
||||
- The WinFsp installer now uses the Wix `Provides` dependency extension to provide a `WinFsp` dependency key. (GitHub PR #129; thanks @felfert.)
|
||||
|
||||
|
||||
v1.2POST1 (2017.2; issue #127)::
|
||||
|
||||
Changes since v1.1:
|
||||
|
||||
- WinFsp-FUSE now supports BSD flags (Windows file attributes) during `getattr` and `fgetattr`. It also adds the `chflags` operation. BSD flags support requires use of the `FSP_FUSE_CAP_STAT_EX` capability and the new `struct fuse_stat_ex` which includes an `st_flags` field. If the preprocessor macro `FSP_FUSE_USE_STAT_EX` is defined before inclusion of `<fuse.h>` then `struct fuse_stat` will also be defined to include the `st_flags` field.
|
||||
- WinFsp-FUSE also adds the following OSXFUSE operations: `setcrtime`, `setchgtime`. These can be used to set the creation (birth) time and change (ctime) time of a file.
|
||||
- New `GetDirInfoByName` file system operation adds fast queries of directory info by file name rather than pattern [e.g. `FindFirstFileW(L"foobar", FindData)`]. Tests with fsbench showed that such queries are sped up by an order of magnitude when using `GetDirInfoByName` in MEMFS. Case-sensitive FUSE file systems get this optimization for free. The .NET layer also adds `GetDirInfoByName`.
|
||||
- New `FspFileSystemOperationProcessId` API adds support for getting the originating process ID (PID) during `Create`, `Open` and `Rename` calls. FUSE file systems can now access `fuse_context::pid`. The .NET layer also adds `GetOperationProcessId`.
|
||||
- New command line tool `fsptool` allows command line access to some WinFsp features.
|
||||
- The WinFsp launcher now passes the name of the user who launched the file system as a special parameter %U. This is useful to file systems that use the launcher infrastructure, such as SSHFS-Win. [Please note that in earlier betas the user name was passed as parameter %3; the previous method was insecure and is no longer supported.]
|
||||
- Important GitHub issues fixed: #96, #97, #103, #107, #127
|
||||
|
||||
|
||||
v1.2 (2017.2)::
|
||||
|
||||
Changes since v1.1:
|
||||
|
||||
- WinFsp-FUSE now supports BSD flags (Windows file attributes) during `getattr` and `fgetattr`. It also adds the `chflags` operation. BSD flags support requires use of the `FSP_FUSE_CAP_STAT_EX` capability and the new `struct fuse_stat_ex` which includes an `st_flags` field. If the preprocessor macro `FSP_FUSE_USE_STAT_EX` is defined before inclusion of `<fuse.h>` then `struct fuse_stat` will also be defined to include the `st_flags` field.
|
||||
- WinFsp-FUSE also adds the following OSXFUSE operations: `setcrtime`, `setchgtime`. These can be used to set the creation (birth) time and change (ctime) time of a file.
|
||||
- New `GetDirInfoByName` file system operation adds fast queries of directory info by file name rather than pattern [e.g. `FindFirstFileW(L"foobar", FindData)`]. Tests with fsbench showed that such queries are sped up by an order of magnitude when using `GetDirInfoByName` in MEMFS. Case-sensitive FUSE file systems get this optimization for free. The .NET layer also adds `GetDirInfoByName`.
|
||||
- New `FspFileSystemOperationProcessId` API adds support for getting the originating process ID (PID) during `Create`, `Open` and `Rename` calls. FUSE file systems can now access `fuse_context::pid`. The .NET layer also adds `GetOperationProcessId`.
|
||||
- New command line tool `fsptool` allows command line access to some WinFsp features.
|
||||
- The WinFsp launcher now passes the name of the user who launched the file system as a special parameter %U. This is useful to file systems that use the launcher infrastructure, such as SSHFS-Win. [Please note that in earlier betas the user name was passed as parameter %3; the previous method was insecure and is no longer supported.]
|
||||
- Important GitHub issues fixed: #96, #97, #103, #107
|
||||
|
||||
|
||||
v1.2B3 (2017.2 B3)::
|
||||
|
||||
Changes since v1.1:
|
||||
|
@ -54,7 +54,9 @@ This CONTRIBUTOR AGREEMENT applies to any contribution that you make to the WinF
|
||||
CONTRIBUTOR LIST
|
||||
----------------
|
||||
|===
|
||||
|Ben Rubson |ben.rubson at gmail.com
|
||||
|Bill Zissimopoulos |billziss at navimatics.com
|
||||
|Fritz Elfert |fritz-github at fritz-elfert.de
|
||||
|John Oberschelp |john at oberschelp.net
|
||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||
|Tobias Urlaub |saibotu at outlook.de
|
||||
|
32
README.md
32
README.md
@ -30,21 +30,23 @@ WinFsp consists of a kernel mode FSD (File System Driver) and a user mode DLL (D
|
||||
|
||||
The project source code is organized as follows:
|
||||
|
||||
* build/VStudio: WinFsp solution and project files.
|
||||
* doc: The WinFsp design documents and additional documentation can be found here.
|
||||
* ext/tlib: A small test library originally from the secfs (Secure Cloud File System) project.
|
||||
* ext/test: Submodule pointing to the secfs.test project, which contains a number of tools for testing Windows and POSIX file systems.
|
||||
* inc/winfsp: Public headers for the WinFsp API.
|
||||
* inc/fuse: Public headers for the FUSE compatibility layer.
|
||||
* src/dll: Source code to the WinFsp DLL.
|
||||
* src/dll/fuse: Source code to the FUSE compatibility layer.
|
||||
* src/dotnet: Source code to the .NET layer.
|
||||
* src/launcher: Source code to the launcher service and the launchctl utility.
|
||||
* src/sys: Source code to the WinFsp FSD.
|
||||
* opt/cygfuse: Source code for the Cygwin FUSE package.
|
||||
* tst/memfs*: Source code to an example file system written in C/C++ (memfs) or C# (memfs-dotnet).
|
||||
* tst/passthrough*: Source code to additional example file systems.
|
||||
* tst/winfsp-tests: WinFsp test suite.
|
||||
* `build/VStudio`: WinFsp solution and project files.
|
||||
* `doc`: The WinFsp design documents and additional documentation can be found here.
|
||||
* `ext/tlib`: A small test library originally from the secfs (Secure Cloud File System) project.
|
||||
* `ext/test`: Submodule pointing to the secfs.test project, which contains a number of tools for testing Windows and POSIX file systems.
|
||||
* `inc/fuse`: Public headers for the FUSE compatibility layer.
|
||||
* `inc/winfsp`: Public headers for the WinFsp API.
|
||||
* `src/dll`: Source code to the WinFsp DLL.
|
||||
* `src/dll/fuse`: Source code to the FUSE compatibility layer.
|
||||
* `src/dotnet`: Source code to the .NET layer.
|
||||
* `src/fsptool`: Source code to fsptool command line utility.
|
||||
* `src/launcher`: Source code to the launcher service and the launchctl utility.
|
||||
* `src/sys`: Source code to the WinFsp FSD.
|
||||
* `opt/cygfuse`: Source code for the Cygwin FUSE package.
|
||||
* `tst/memfs*`: Source code to an example file system written in C/C++ (memfs) or C# (memfs-dotnet).
|
||||
* `tst/passthrough*`: Source code to additional example file systems.
|
||||
* `tst/winfsp-tests`: WinFsp test suite.
|
||||
* `tools`: Various tools for building and testing WinFsp.
|
||||
|
||||
## Building and Running
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file CustomActions.cpp
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
|
||||
<Product
|
||||
Id="*"
|
||||
Name="$(var.MyProductName) $(var.MyProductVersion)"
|
||||
@ -53,8 +54,8 @@
|
||||
Key="[P.RegistryKey]"
|
||||
Name="InstallDir"
|
||||
Type="string"
|
||||
Value="[INSTALLDIR]"
|
||||
KeyPath="yes" />
|
||||
Value="[INSTALLDIR]" />
|
||||
<dep:Provides Key="WinFsp" />
|
||||
</Component>
|
||||
<Component Id="C.License.txt">
|
||||
<File Name="License.txt" Source="..\..\..\License.txt" KeyPath="yes" />
|
||||
@ -259,6 +260,9 @@
|
||||
<Component Id="C.winfsp.h">
|
||||
<File Name="winfsp.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launch.h">
|
||||
<File Name="launch.h" KeyPath="yes" />
|
||||
</Component>
|
||||
<!--Component Id="C.winfsp.hpp">
|
||||
<File Name="winfsp.hpp" KeyPath="yes" />
|
||||
</Component-->
|
||||
@ -310,12 +314,12 @@
|
||||
<Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist">
|
||||
<Directory Id="OPTDIR.cygfuse.x64" Name="x64">
|
||||
<Component Id="C.fuse.tar.xz.x64">
|
||||
<File Id="FILE.fuse.tar.xz.x64" Name="fuse-2.8-6.tar.xz" KeyPath="yes" />
|
||||
<File Id="FILE.fuse.tar.xz.x64" Name="fuse-2.8-8.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="OPTDIR.cygfuse.x86" Name="x86">
|
||||
<Component Id="C.fuse.tar.xz.x86">
|
||||
<File Id="FILE.fuse.tar.xz.x86" Name="fuse-2.8-6.tar.xz" KeyPath="yes" />
|
||||
<File Id="FILE.fuse.tar.xz.x86" Name="fuse-2.8-8.tar.xz" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Component Id="C.fuse.install.sh">
|
||||
@ -469,6 +473,7 @@
|
||||
<ComponentGroup Id="C.WinFsp.inc">
|
||||
<ComponentRef Id="C.fsctl.h" />
|
||||
<ComponentRef Id="C.winfsp.h" />
|
||||
<ComponentRef Id="C.launch.h" />
|
||||
<!--ComponentRef Id="C.winfsp.hpp" /-->
|
||||
<ComponentRef Id="C.fuse.h" />
|
||||
<ComponentRef Id="C.fuse_common.h" />
|
||||
|
@ -39,6 +39,10 @@
|
||||
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||
<Name>WixUIExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixDependencyExtension">
|
||||
<HintPath>$(WixExtDir)\WixDependencyExtension.dll</HintPath>
|
||||
<Name>WixDependencyExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" />
|
||||
<!--
|
||||
|
@ -190,6 +190,7 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\fuse-opt-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\hooks.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\info-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\lock-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\memfs-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\mount-test.c" />
|
||||
|
@ -85,6 +85,9 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\launch-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||
|
@ -185,7 +185,6 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h" />
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -16,9 +16,6 @@
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||
<Filter>Include\shared</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h">
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\src\launcher\launchctl.c">
|
||||
|
@ -112,7 +112,7 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -134,7 +134,7 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -159,7 +159,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -184,7 +184,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;userenv.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -197,7 +197,6 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h" />
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -21,9 +21,6 @@
|
||||
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||
<Filter>Include\shared</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\launcher\launcher.h">
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\src\launcher\launcher-version.rc">
|
||||
|
@ -16,9 +16,9 @@
|
||||
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||
|
||||
<MyCanonicalVersion>1.2</MyCanonicalVersion>
|
||||
<MyCanonicalVersion>1.3</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2017.2 B3</MyProductVersion>
|
||||
<MyProductVersion>2018.1 B3</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
|
@ -25,6 +25,7 @@
|
||||
<ClInclude Include="..\..\inc\fuse\fuse_opt.h" />
|
||||
<ClInclude Include="..\..\inc\fuse\winfsp_fuse.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\launch.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp" />
|
||||
<ClInclude Include="..\..\src\dll\fuse\library.h" />
|
||||
@ -39,6 +40,7 @@
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||
<ClCompile Include="..\..\src\dll\launch.c" />
|
||||
<ClCompile Include="..\..\src\dll\np.c" />
|
||||
<ClCompile Include="..\..\src\dll\posix.c" />
|
||||
<ClCompile Include="..\..\src\dll\security.c" />
|
||||
@ -51,6 +53,7 @@
|
||||
<ClCompile Include="..\..\src\dll\path.c" />
|
||||
<ClCompile Include="..\..\src\dll\service.c" />
|
||||
<ClCompile Include="..\..\src\dll\util.c" />
|
||||
<ClCompile Include="..\..\src\dll\wksid.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in">
|
||||
|
@ -53,6 +53,9 @@
|
||||
<ClInclude Include="..\..\inc\winfsp\winfsp.hpp">
|
||||
<Filter>Include\winfsp</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\winfsp\launch.h">
|
||||
<Filter>Include\winfsp</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\library.c">
|
||||
@ -112,6 +115,12 @@
|
||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c">
|
||||
<Filter>Source\fuse</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\wksid.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\launch.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
|
@ -173,6 +173,7 @@
|
||||
<ClCompile Include="..\..\src\sys\ioq.c" />
|
||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||
<ClCompile Include="..\..\src\sys\mup.c" />
|
||||
<ClCompile Include="..\..\src\sys\name.c" />
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||
<ClCompile Include="..\..\src\sys\read.c" />
|
||||
|
@ -101,6 +101,9 @@
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\mup.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -28,7 +28,7 @@ if ($key.Count -eq 1) {
|
||||
-File "$file"
|
||||
}
|
||||
} elseif ($key.Count -eq 0) {
|
||||
Write-Warning "$packageName has already been uninstalled by other means."
|
||||
# Write-Warning "$packageName is not installed"
|
||||
} 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:"
|
@ -1,16 +1,14 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
$fileLocation = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||
. "$toolsdir\chocolateyHelper.ps1"
|
||||
|
||||
$packageArgs = @{
|
||||
packageName = 'winfsp'
|
||||
fileType = 'msi'
|
||||
file = $fileLocation
|
||||
file = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||
silentArgs = "/qn /norestart INSTALLLEVEL=1000"
|
||||
validExitCodes = @(0, 3010, 1641)
|
||||
}
|
||||
|
||||
Install-ChocolateyInstallPackage @packageArgs
|
||||
|
||||
Remove-Item -Force $packageArgs.file
|
||||
|
4
build/choco/chocolateyUninstall.ps1
Normal file
4
build/choco/chocolateyUninstall.ps1
Normal file
@ -0,0 +1,4 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
. "$toolsdir\chocolateyHelper.ps1"
|
@ -50,7 +50,8 @@ To verify installation:
|
||||
<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="chocolateyUninstall.ps1" target="tools" />
|
||||
<file src="chocolateyHelper.ps1" target="tools" />
|
||||
<file src="winfsp-$version$.msi" target="tools" />
|
||||
</files>
|
||||
</package>
|
||||
|
@ -4,30 +4,37 @@
|
||||
|
||||
[qanda]
|
||||
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed. [@efeat]::
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed.::
|
||||
|
||||
Your Windows 7 OS is missing SHA-2 Code Signing Support. You need to install the following security advisory that will rectify the problem:
|
||||
https://technet.microsoft.com/en-us/library/security/3033929.aspx
|
||||
|
||||
|
||||
Disconnecting (unmapping) a network drive does not work. [@carlreinke]::
|
||||
Disconnecting (unmapping) a network drive does not work.::
|
||||
|
||||
You may have Dokany installed. Dokany installs its own Network Provider DLL that unfortunately interferes with the WinFsp handling of network drives. The solution is to change your system's Network Provider order and ensure that the WinFsp Network Provider runs before the Dokany one. Instructions on how to change the Network Provider order can be found in this http://blogs.interfacett.com/changing-the-network-provider-order-in-windows-10[article].
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories? [@netheril96]::
|
||||
Case-sensitive file systems do not work properly when mounted as a directory.::
|
||||
|
||||
Windows and WinFsp support case-sensitive file systems. These file systems work properly when mounted as a drive. Unfortunately when a file system is mounted as a directory over NTFS, Windows expects it to be case-insensitive and will UPPERCASE many of the file names sent to the file system.
|
||||
+
|
||||
This is an unfortunate but well understood Windows limitation. Case-sensitive file systems should only be mounted as drives.
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories?::
|
||||
|
||||
It is true that this would make it convenient to load the DLL, because the Windows loader looks into the Windows system directories when it loads DLL's. However, in the opinion of the WinFsp author, software that does not ship with the OS should not be installing components in the system directories.
|
||||
+
|
||||
There are a few alternative methods to overcome this problem. WinFsp recommends marking the WinFsp DLL as "delay load" and then using `FspLoad` to dynamically load the DLL during process initialization. For more information see the WinFsp Tutorial.
|
||||
|
||||
|
||||
Does WinFsp provide debugging symbols? [@netheril96]::
|
||||
Does WinFsp provide debugging symbols?::
|
||||
|
||||
Public debugging symbols are already included in the installer. You need to install the "Developer" feature; the symbols can be found in the `sym` directory under the WinFsp installation directory.
|
||||
|
||||
|
||||
Is there a maximum number of concurrent file systems? [@efeat]::
|
||||
Is there a maximum number of concurrent file systems?::
|
||||
|
||||
WinFsp does not have a hard limit of how many file systems can be created or how many processes can create file systems.
|
||||
+
|
||||
@ -43,7 +50,7 @@ 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]::
|
||||
FUSE on UNIX systems mounts file systems over an existing directory. When mounting a WinFsp-FUSE file system on a directory, the directory is created and later deleted when the file system goes away. What is the reason for this incompatibility?::
|
||||
|
||||
It would be preferrable if WinFsp-FUSE behaved like FUSE on UNIX in this instance. However there are a number of reasons that this is not the case.
|
||||
+
|
||||
@ -54,3 +61,12 @@ With this in mind here are the reasons for the current WinFsp-FUSE behavior:
|
||||
- Symmetry with mounting on a drive. On Windows drives are created when the file system comes into existence and deleted when it is gone.
|
||||
- Inability to mount over a non-empty directory on Windows. On FUSE/UNIX this is possible, but not on Windows because NTFS disallows the creation of (mountpoint) reparse points on non-empty directories.
|
||||
- Most importantly: inability to guarantee that the mount point will cease to exist if the file system crashes. WinFsp attempts to guarantee that all resources used by a file system will get cleaned up. This is certainly true for the kernel-mode FSD, but an attempt is made to do so also in user mode. For this reason, drive symbolic links are marked as temporary and (importantly for our discussion) mount directories are opened with `FILE_FLAG_DELETE_ON_CLOSE`. There is no way to guarantee the removal of a reparse point in the same way.
|
||||
|
||||
|
||||
WinFsp-FUSE does not have the ability to support multiple file systems from within the same process. Why?::
|
||||
|
||||
The core WinFsp layer supports multiple file systems in the same process either simultaneously or one after another. However this is not the case with WinFsp-FUSE (i.e. the FUSE layer of WinFsp).
|
||||
+
|
||||
File systems in Windows often need to be run as services. For this reason the WinFsp-FUSE layer provides both file system and Windows service API functionality. This way a WinFsp-FUSE file system can easily become a Windows service. There is a problem: once a Windows process starts acting as a service and then stops being a service, it cannot become a service again.
|
||||
+
|
||||
Having FUSE file systems being able to act as Windows services is valuable. Therefore this is not a limitation that can easily be fixed as FUSE file systems would lose the "free" ability to act as Windows services.
|
||||
|
@ -9,7 +9,7 @@ The documentation available here discusses various aspects of WinFsp.
|
||||
## Programming
|
||||
|
||||
- The [[Tutorial|WinFsp-Tutorial]] describes how to create a simple, but complete file system in C/C++.
|
||||
- The [[API Reference|winfsp.h]] describes the native WinFsp API. This external [[link|http://www.secfs.net/winfsp/apiref/]] may be easier to browse for some people.
|
||||
- The [[API Reference|WinFsp-API-winfsp.h]] describes the native WinFsp API. This external [[link|http://www.secfs.net/winfsp/apiref/]] may be easier to browse for some people.
|
||||
- There is also a FUSE compatibility layer for native Windows and Cygwin. See fuse.h in the source repository.
|
||||
- This [[document|Native-API-vs-FUSE]] discusses the need for both a native API and FUSE and gives some pointers on which one to choose.
|
||||
|
||||
|
@ -4,6 +4,9 @@ This document contains a list of known file systems and file system libraries th
|
||||
|
||||
== File Systems
|
||||
|
||||
- https://github.com/vgough/encfs[EncFS] - an Encrypted Filesystem for FUSE
|
||||
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
||||
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
||||
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
||||
- https://github.com/ncw/rclone[rclone] - rsync for cloud storage
|
||||
- https://github.com/hasse69/rar2fs[rar2fs] - FUSE file system for reading RAR archives
|
||||
|
263
doc/WinFsp-API-launch.h.asciidoc
Normal file
263
doc/WinFsp-API-launch.h.asciidoc
Normal file
@ -0,0 +1,263 @@
|
||||
= winfsp/launch.h
|
||||
:author: (C) 2015-2018 Bill Zissimopoulos
|
||||
:toc: preamble
|
||||
:toc-title:
|
||||
|
||||
WinFsp Launch API.
|
||||
|
||||
In order to use the WinFsp Launch API a program must include <winfsp/launch.h>
|
||||
and link with the winfsp$$_$$x64.dll (or winfsp$$_$$x86.dll) library.
|
||||
|
||||
== Launch Control
|
||||
|
||||
=== Functions
|
||||
|
||||
*FspLaunchCallLauncherPipe* - Call launcher pipe.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command,
|
||||
ULONG Argc,
|
||||
PWSTR *Argv,
|
||||
ULONG *Argl,
|
||||
PWSTR Buffer,
|
||||
PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Command_ - Launcher command to send. For example, the 'L' launcher command instructs
|
||||
the launcher to list all running service instances.
|
||||
- _Argc_ - Command argument count. May be 0.
|
||||
- _Argv_ - Command argument array. May be NULL.
|
||||
- _Argl_ - Command argument length array. May be NULL. If this is NULL all command arguments
|
||||
are assumed to be NULL-terminated strings. It is also possible for specific arguments
|
||||
to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
|
||||
- _Buffer_ - Buffer that receives the command response. May be NULL.
|
||||
- _PSize_ - Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
contains the number of bytes transferred. May be NULL.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
*Discussion*
|
||||
|
||||
This function is used to send a command to the launcher and receive a response.
|
||||
|
||||
|
||||
*FspLaunchGetInfo* - Get information about a service instance.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName,
|
||||
PWSTR InstanceName,
|
||||
PWSTR Buffer,
|
||||
PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - Class name of the service instance to stop.
|
||||
- _InstanceName_ - Instance name of the service instance to stop.
|
||||
- _Buffer_ - Buffer that receives the command response. May be NULL.
|
||||
- _PSize_ - Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
contains the number of bytes transferred. May be NULL.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
*Discussion*
|
||||
|
||||
The information is a list of NULL-terminated strings: the class name of the service instance,
|
||||
the instance name of the service instance and the full command line used to start the service
|
||||
instance.
|
||||
|
||||
|
||||
*FspLaunchGetNameList* - List service instances.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer,
|
||||
PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Buffer_ - Buffer that receives the command response. May be NULL.
|
||||
- _PSize_ - Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
contains the number of bytes transferred. May be NULL.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
*Discussion*
|
||||
|
||||
The information is a list of pairs of NULL-terminated strings. Each pair contains the class
|
||||
name and instance name of a service instance. All currently running service instances are
|
||||
listed.
|
||||
|
||||
|
||||
*FspLaunchStart* - Start a service instance.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName,
|
||||
PWSTR InstanceName,
|
||||
ULONG Argc,
|
||||
PWSTR *Argv,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - Class name of the service instance to start.
|
||||
- _InstanceName_ - Instance name of the service instance to start.
|
||||
- _Argc_ - Service instance argument count. May be 0.
|
||||
- _Argv_ - Service instance argument array. May be NULL.
|
||||
- _HasSecret_ - Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
|
||||
Secrets are passed to service instances through standard input rather than the command
|
||||
line.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
|
||||
*FspLaunchStop* - Stop a service instance.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName,
|
||||
PWSTR InstanceName,
|
||||
PULONG PLauncherError);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - Class name of the service instance to stop.
|
||||
- _InstanceName_ - Instance name of the service instance to stop.
|
||||
- _PLauncherError_ - Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
reported through PLauncherError.
|
||||
|
||||
|
||||
== Service Registry
|
||||
|
||||
=== Functions
|
||||
|
||||
*FspLaunchRegFreeRecord* - Free a service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Record_ - The service record to free.
|
||||
|
||||
*See Also*
|
||||
|
||||
- FspLaunchRegGetRecord
|
||||
|
||||
|
||||
*FspLaunchRegGetRecord* - Get a service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName,
|
||||
PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - The service class name.
|
||||
- _Agent_ - The name of the agent that is retrieving the service record. This API matches
|
||||
the supplied Agent against the Agent in the service record and it only returns
|
||||
the record if they match. Pass NULL to match any Agent.
|
||||
- _PRecord_ - Pointer to a record pointer. Memory for the service record will be allocated
|
||||
and a pointer to it will be stored at this address. This memory must be later
|
||||
freed using FspLaunchRegFreeRecord.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
*See Also*
|
||||
|
||||
- FspLaunchRegFreeRecord
|
||||
|
||||
|
||||
*FspLaunchRegSetRecord* - Add/change/delete a service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _ClassName_ - The service class name.
|
||||
- _Record_ - The record to set in the registry. If NULL, the registry record is deleted.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
|
||||
=== Typedefs
|
||||
|
||||
*FSP$$_$$LAUNCH$$_$$REG$$_$$RECORD* - Service registry record.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
typedef struct _FSP_LAUNCH_REG_RECORD {
|
||||
PWSTR Agent;
|
||||
PWSTR Executable;
|
||||
PWSTR CommandLine;
|
||||
PWSTR WorkDirectory;
|
||||
PWSTR RunAs;
|
||||
PWSTR Security;
|
||||
PVOID Reserved0[6];
|
||||
ULONG JobControl;
|
||||
ULONG Credentials;
|
||||
ULONG Reserved1[6];
|
||||
UINT8 Buffer[];
|
||||
} FSP_LAUNCH_REG_RECORD;
|
||||
----
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
= winfsp/winfsp.h
|
||||
:author: (C) 2015-2017 Bill Zissimopoulos
|
||||
:author: (C) 2015-2018 Bill Zissimopoulos
|
||||
:toc: preamble
|
||||
:toc-title:
|
||||
|
||||
@ -278,6 +278,33 @@ STATUS$$_$$SUCCESS or error code.
|
||||
Note that the FSD will also flush all file/volume caches prior to invoking this operation.
|
||||
|
||||
|
||||
*GetDirInfoByName* - Get directory information for a single file or directory within a parent directory.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
NTSTATUS ( *GetDirInfoByName)(
|
||||
FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext,
|
||||
PWSTR FileName,
|
||||
FSP_FSCTL_DIR_INFO *DirInfo);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _FileSystem_ - The file system on which this request is posted.
|
||||
- _FileContext_ - The file context of the parent directory.
|
||||
- _FileName_ - The name of the file or directory to get information for. This name is relative
|
||||
to the parent directory and is a single path component.
|
||||
- _DirInfo_ - [out]
|
||||
Pointer to a structure that will receive the directory information on successful
|
||||
return from this call. This information includes the file name, but also file
|
||||
attributes, file times, etc.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS or error code.
|
||||
|
||||
|
||||
*GetFileInfo* - Get file or directory information.
|
||||
|
||||
[source,c]
|
||||
@ -1185,6 +1212,19 @@ The current operation context is stored in thread local storage. It allows acces
|
||||
Request and Response associated with this operation.
|
||||
|
||||
|
||||
*FspFileSystemOperationProcessId* - Gets the originating process ID.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
static inline UINT32 FspFileSystemOperationProcessId(
|
||||
VOID)
|
||||
----
|
||||
|
||||
*Discussion*
|
||||
|
||||
Valid only during Create, Open and Rename requests when the target exists.
|
||||
|
||||
|
||||
*FspFileSystemPreflight* - Check whether creating a file system object is possible.
|
||||
|
||||
[source,c]
|
||||
@ -1535,6 +1575,27 @@ call. The WinFsp Launcher is a Windows service that can be configured to launch
|
||||
multiple instances of a user mode file system.
|
||||
|
||||
|
||||
*FspServiceContextCheck* - Check if the supplied token is from the service context.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
FSP_API NTSTATUS FspServiceContextCheck(
|
||||
HANDLE Token,
|
||||
PBOOLEAN PIsLocalSystem);
|
||||
----
|
||||
|
||||
*Parameters*
|
||||
|
||||
- _Token_ - Token to check. Pass NULL to check the current process token.
|
||||
- _PIsLocalSystem_ - Pointer to a boolean that will receive a TRUE value if the token belongs to LocalSystem
|
||||
and FALSE otherwise. May be NULL.
|
||||
|
||||
*Return Value*
|
||||
|
||||
STATUS$$_$$SUCCESS if the token is from the service context. STATUS$$_$$ACCESS$$_$$DENIED if it is not.
|
||||
Other error codes are possible.
|
||||
|
||||
|
||||
*FspServiceCreate* - Create a service object.
|
||||
|
||||
[source,c]
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/callstack.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/callstack.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/callstack.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_CALLSTACK_H_INCLUDED
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/allfunc.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_INJECTED_ALLFUNC_H_INCLUDED
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/curlfunc.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/injected/curlfunc.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/curlfunc.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_INJECTED_CURLFUNC_H_INCLUDED
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/stdfunc.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/injected/stdfunc.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injected/stdfunc.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_INJECTED_STDFUNC_H_INCLUDED
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injection.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/injection.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/injection.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
/* NOTE: This header may usefully be included multiple times.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/testsuite.c
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#include <tlib/testsuite.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file tlib/testsuite.h
|
||||
*
|
||||
* @copyright 2014-2017 Bill Zissimopoulos
|
||||
* @copyright 2014-2018 Bill Zissimopoulos
|
||||
*/
|
||||
|
||||
#ifndef TLIB_TESTSUITE_H_INCLUDED
|
||||
|
@ -6,7 +6,7 @@
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -6,7 +6,7 @@
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -6,7 +6,7 @@
|
||||
* FUSE: Filesystem in Userspace
|
||||
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @file fuse/winfsp_fuse.h
|
||||
* WinFsp FUSE compatible API.
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -389,7 +389,7 @@ static inline int fsp_fuse_set_signal_handlers(void *se)
|
||||
static inline char *fsp_fuse_conv_to_win_path(const char *path)
|
||||
{
|
||||
void *cygwin_create_path(unsigned, const void *);
|
||||
return cygwin_create_path(
|
||||
return (char *)cygwin_create_path(
|
||||
0/*CCP_POSIX_TO_WIN_A*/ | 0x100/*CCP_RELATIVE*/,
|
||||
path);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file winfsp/fsctl.h
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -34,6 +34,7 @@ extern "C" {
|
||||
#define FSP_FSCTL_DRIVER_NAME "WinFsp"
|
||||
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
|
||||
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
|
||||
#define FSP_FSCTL_MUP_DEVICE_NAME "WinFsp.Mup"
|
||||
|
||||
// {6F9D25FA-6DEE-4A9D-80F5-E98E14F35E54}
|
||||
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid =
|
||||
@ -123,44 +124,64 @@ enum
|
||||
FspFsctlIrpCapacityMaximum = 1000,
|
||||
FspFsctlIrpCapacityDefault = 1000,
|
||||
};
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN\
|
||||
UINT16 Version; /* set to 0 or sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
|
||||
/* volume information */\
|
||||
UINT16 SectorSize;\
|
||||
UINT16 SectorsPerAllocationUnit;\
|
||||
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */\
|
||||
UINT64 VolumeCreationTime;\
|
||||
UINT32 VolumeSerialNumber;\
|
||||
/* I/O timeouts, capacity, etc. */\
|
||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */\
|
||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */\
|
||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/\
|
||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */\
|
||||
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */\
|
||||
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */\
|
||||
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */\
|
||||
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */\
|
||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */\
|
||||
UINT32 ReparsePoints:1; /* file system supports reparse points */\
|
||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */\
|
||||
UINT32 NamedStreams:1; /* file system supports named streams */\
|
||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */\
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */\
|
||||
UINT32 ReadOnlyVolume:1;\
|
||||
/* kernel-mode flags */\
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */\
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */\
|
||||
UINT32 AlwaysUseDoubleBuffering:1;\
|
||||
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */\
|
||||
UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */\
|
||||
UINT32 KmReservedFlags:1;\
|
||||
/* user-mode flags */\
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */\
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */\
|
||||
UINT32 UmReservedFlags:14;\
|
||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
||||
/* additional fields; specify .Version == sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
|
||||
UINT32 VolumeInfoTimeoutValid:1; /* VolumeInfoTimeout field is valid */\
|
||||
UINT32 DirInfoTimeoutValid:1; /* DirInfoTimeout field is valid */\
|
||||
UINT32 SecurityTimeoutValid:1; /* SecurityTimeout field is valid*/\
|
||||
UINT32 StreamInfoTimeoutValid:1; /* StreamInfoTimeout field is valid */\
|
||||
UINT32 KmAdditionalReservedFlags:28;\
|
||||
UINT32 VolumeInfoTimeout; /* volume info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 DirInfoTimeout; /* dir info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 Reserved32[3];\
|
||||
UINT64 Reserved64[2];
|
||||
typedef struct
|
||||
{
|
||||
UINT16 Version; /* set to 0 */
|
||||
/* volume information */
|
||||
UINT16 SectorSize;
|
||||
UINT16 SectorsPerAllocationUnit;
|
||||
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */
|
||||
UINT64 VolumeCreationTime;
|
||||
UINT32 VolumeSerialNumber;
|
||||
/* I/O timeouts, capacity, etc. */
|
||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */
|
||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */
|
||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/
|
||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */
|
||||
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */
|
||||
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */
|
||||
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */
|
||||
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */
|
||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
|
||||
UINT32 ReparsePoints:1; /* file system supports reparse points */
|
||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */
|
||||
UINT32 NamedStreams:1; /* file system supports named streams */
|
||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
|
||||
UINT32 ReadOnlyVolume:1;
|
||||
/* kernel-mode flags */
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */
|
||||
UINT32 AlwaysUseDoubleBuffering:1;
|
||||
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */
|
||||
UINT32 UserModeFileLocking:1; /* pass file locking requests to user mode */
|
||||
UINT32 KmReservedFlags:1;
|
||||
/* user-mode flags */
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
|
||||
UINT32 UmReservedFlags:14;
|
||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */
|
||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
|
||||
} FSP_FSCTL_VOLUME_PARAMS_V0;
|
||||
typedef struct
|
||||
{
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
|
||||
FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN
|
||||
} FSP_FSCTL_VOLUME_PARAMS;
|
||||
typedef struct
|
||||
{
|
||||
@ -260,7 +281,6 @@ typedef struct
|
||||
UINT32 SetLastAccessTime:1;
|
||||
UINT32 SetLastWriteTime:1;
|
||||
UINT32 SetChangeTime:1;
|
||||
UINT32 UnlockAll:1;
|
||||
} Cleanup;
|
||||
struct
|
||||
{
|
||||
@ -275,7 +295,6 @@ typedef struct
|
||||
UINT64 Offset;
|
||||
UINT32 Length;
|
||||
UINT32 Key;
|
||||
UINT32 ProcessId;
|
||||
} Read;
|
||||
struct
|
||||
{
|
||||
@ -286,8 +305,6 @@ typedef struct
|
||||
UINT32 Length;
|
||||
UINT32 Key;
|
||||
UINT32 ConstrainedIo:1;
|
||||
UINT32 ReservedFlags:31;
|
||||
UINT32 ProcessId;
|
||||
} Write;
|
||||
struct
|
||||
{
|
||||
@ -364,18 +381,6 @@ typedef struct
|
||||
UINT16 TargetOnFileSystem; /* the target of the symbolic link is on this file system */
|
||||
} FileSystemControl;
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext;
|
||||
UINT64 UserContext2;
|
||||
UINT32 LockFunction;
|
||||
UINT64 Offset;
|
||||
UINT64 Length;
|
||||
UINT32 Key;
|
||||
UINT32 ProcessId;
|
||||
UINT32 Exclusive:1;
|
||||
UINT32 FailImmediately:1;
|
||||
} LockControl;
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext;
|
||||
UINT64 UserContext2;
|
||||
|
276
inc/winfsp/launch.h
Normal file
276
inc/winfsp/launch.h
Normal file
@ -0,0 +1,276 @@
|
||||
/**
|
||||
* @file winfsp/launch.h
|
||||
* WinFsp Launch API.
|
||||
*
|
||||
* In order to use the WinFsp Launch API a program must include <winfsp/launch.h>
|
||||
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_LAUNCH_H_INCLUDED
|
||||
#define WINFSP_LAUNCH_H_INCLUDED
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FSP_LAUNCH_REGKEY "Software\\WinFsp\\Services"
|
||||
#define FSP_LAUNCH_REGKEY_WOW64 KEY_WOW64_32KEY
|
||||
|
||||
#define FSP_LAUNCH_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||
#define FSP_LAUNCH_PIPE_BUFFER_SIZE 4096
|
||||
#define FSP_LAUNCH_PIPE_OWNER ((PSID)WinLocalSystemSid)
|
||||
|
||||
/*
|
||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||
* pipe instances.
|
||||
*/
|
||||
#define FSP_LAUNCH_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
|
||||
|
||||
/*
|
||||
* The default service instance SDDL gives full access to LocalSystem and Administrators.
|
||||
* The only possible service instance rights are as follows:
|
||||
* RP SERVICE_START
|
||||
* WP SERVICE_STOP
|
||||
* LC SERVICE_QUERY_STATUS
|
||||
*
|
||||
* To create a service that can be started, stopped or queried by Everyone, you can set
|
||||
* the following SDDL:
|
||||
* D:P(A;;RPWPLC;;;WD)
|
||||
*/
|
||||
#define FSP_LAUNCH_SERVICE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
|
||||
#define FSP_LAUNCH_SERVICE_WORLD_SDDL "D:P(A;;RPWPLC;;;WD)"
|
||||
|
||||
enum
|
||||
{
|
||||
FspLaunchCmdStart = 'S', /* requires: SERVICE_START */
|
||||
FspLaunchCmdStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||
FspLaunchCmdStop = 'T', /* requires: SERVICE_STOP */
|
||||
FspLaunchCmdGetInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||
FspLaunchCmdGetNameList = 'L', /* requires: none*/
|
||||
FspLaunchCmdDefineDosDevice = 'D', /* internal: do not use! */
|
||||
FspLaunchCmdQuit = 'Q', /* DEBUG version only */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FspLaunchCmdSuccess = '$',
|
||||
FspLaunchCmdFailure = '!',
|
||||
};
|
||||
|
||||
/**
|
||||
* @group Launch Control
|
||||
*/
|
||||
/**
|
||||
* Call launcher pipe.
|
||||
*
|
||||
* This function is used to send a command to the launcher and receive a response.
|
||||
*
|
||||
* @param Command
|
||||
* Launcher command to send. For example, the 'L' launcher command instructs
|
||||
* the launcher to list all running service instances.
|
||||
* @param Argc
|
||||
* Command argument count. May be 0.
|
||||
* @param Argv
|
||||
* Command argument array. May be NULL.
|
||||
* @param Argl
|
||||
* Command argument length array. May be NULL. If this is NULL all command arguments
|
||||
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
|
||||
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError);
|
||||
/**
|
||||
* Start a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to start.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to start.
|
||||
* @param Argc
|
||||
* Service instance argument count. May be 0.
|
||||
* @param Argv
|
||||
* Service instance argument array. May be NULL.
|
||||
* @param HasSecret
|
||||
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
|
||||
* Secrets are passed to service instances through standard input rather than the command
|
||||
* line.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Stop a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Get information about a service instance.
|
||||
*
|
||||
* The information is a list of NULL-terminated strings: the class name of the service instance,
|
||||
* the instance name of the service instance and the full command line used to start the service
|
||||
* instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* List service instances.
|
||||
*
|
||||
* The information is a list of pairs of NULL-terminated strings. Each pair contains the class
|
||||
* name and instance name of a service instance. All currently running service instances are
|
||||
* listed.
|
||||
*
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
|
||||
/**
|
||||
* @group Service Registry
|
||||
*/
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||
/**
|
||||
* Service registry record.
|
||||
*/
|
||||
typedef struct _FSP_LAUNCH_REG_RECORD
|
||||
{
|
||||
PWSTR Agent;
|
||||
PWSTR Executable;
|
||||
PWSTR CommandLine;
|
||||
PWSTR WorkDirectory;
|
||||
PWSTR RunAs;
|
||||
PWSTR Security;
|
||||
PVOID Reserved0[6];
|
||||
ULONG JobControl;
|
||||
ULONG Credentials;
|
||||
ULONG Reserved1[6];
|
||||
UINT8 Buffer[];
|
||||
} FSP_LAUNCH_REG_RECORD;
|
||||
#pragma warning(pop)
|
||||
/**
|
||||
* Add/change/delete a service registry record.
|
||||
*
|
||||
* @param ClassName
|
||||
* The service class name.
|
||||
* @param Record
|
||||
* The record to set in the registry. If NULL, the registry record is deleted.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record);
|
||||
/**
|
||||
* Get a service registry record.
|
||||
*
|
||||
* @param ClassName
|
||||
* The service class name.
|
||||
* @param Agent
|
||||
* The name of the agent that is retrieving the service record. This API matches
|
||||
* the supplied Agent against the Agent in the service record and it only returns
|
||||
* the record if they match. Pass NULL to match any Agent.
|
||||
* @param PRecord
|
||||
* Pointer to a record pointer. Memory for the service record will be allocated
|
||||
* and a pointer to it will be stored at this address. This memory must be later
|
||||
* freed using FspLaunchRegFreeRecord.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code.
|
||||
* @see
|
||||
* FspLaunchRegFreeRecord
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName, PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord);
|
||||
/**
|
||||
* Free a service registry record.
|
||||
*
|
||||
* @param Record
|
||||
* The service record to free.
|
||||
* @see
|
||||
* FspLaunchRegGetRecord
|
||||
*/
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -5,7 +5,7 @@
|
||||
* In order to use the WinFsp API the user mode file system must include <winfsp/winfsp.h>
|
||||
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -133,7 +133,6 @@ enum
|
||||
FspCleanupSetLastAccessTime = 0x20,
|
||||
FspCleanupSetLastWriteTime = 0x40,
|
||||
FspCleanupSetChangeTime = 0x80,
|
||||
FspCleanupUnlockAll = 0x0100,
|
||||
};
|
||||
/**
|
||||
* @class FSP_FILE_SYSTEM
|
||||
@ -823,80 +822,12 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
NTSTATUS (*GetDirInfoByName)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, PWSTR FileName,
|
||||
FSP_FSCTL_DIR_INFO *DirInfo);
|
||||
/**
|
||||
* Lock a file range.
|
||||
*
|
||||
* At the time of this call the FSD has already done its own locking processing.
|
||||
* Thus the kernel may fail a lock control request or a Read or Write without
|
||||
* informing the user mode file system.
|
||||
*
|
||||
* @param FileSystem
|
||||
* The file system on which this request is posted.
|
||||
* @param FileContext
|
||||
* The file context of the file to be locked.
|
||||
* @param Offset
|
||||
* Offset within the file to lock.
|
||||
* @param Length
|
||||
* Length of data to lock.
|
||||
* @param Owner
|
||||
* Lock owner. This 64-bit value consists of a PID in the high 32-bits and a "Key"
|
||||
* in the low 32-bits. The PID is that of the process requesting the lock. The Key
|
||||
* is an arbitrary value.
|
||||
*
|
||||
* The triplet (FileDesc,PID,Key) uniquely identifies the lock owner.
|
||||
* @param Exclusive
|
||||
* When TRUE an exclusive lock is requested. Otherwise a shared lock is requested.
|
||||
* @param FailImmediately
|
||||
* When TRUE the function should return immediately if it is unable to acquire the
|
||||
* requested lock. Otherwise the function should wait until the lock can be granted.
|
||||
* In this case the function may also return STATUS_PENDING.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code. STATUS_PENDING is supported allowing for asynchronous
|
||||
* operation.
|
||||
*/
|
||||
NTSTATUS (*Lock)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, UINT64 Offset, UINT64 Length, UINT64 Owner,
|
||||
BOOLEAN Exclusive, BOOLEAN FailImmediately);
|
||||
/**
|
||||
* Unlock file ranges.
|
||||
*
|
||||
* At the time of this call the FSD has already done its own locking processing.
|
||||
* Thus the kernel may fail a lock control request or a Read or Write without
|
||||
* informing the user mode file system.
|
||||
*
|
||||
* An Unlock operation with Offset == Length == -1 is a request to remove multiple locks.
|
||||
* The set of possible locks to remove includes all locks made by the process described
|
||||
* by the Owner parameter through the file descriptor described by the FileContext parameter.
|
||||
* If the Key portion of the Owner parameter is 0, all the locks in the set are removed.
|
||||
* If the Key portion of the Owner paramter is non-0, only locks that match the Key are
|
||||
* removed.
|
||||
*
|
||||
* @param FileSystem
|
||||
* The file system on which this request is posted.
|
||||
* @param FileContext
|
||||
* The file context of the file to be unlocked.
|
||||
* @param Offset
|
||||
* Offset within the file to unlock.
|
||||
* @param Length
|
||||
* Length of data to unlock.
|
||||
* @param Owner
|
||||
* Lock owner. This 64-bit value consists of a PID in the high 32-bits and a "Key"
|
||||
* in the low 32-bits. The PID is that of the process requesting the lock. The Key
|
||||
* is an arbitrary value.
|
||||
*
|
||||
* The triplet (FileDesc,PID,Key) uniquely identifies the lock owner.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code. STATUS_PENDING is supported allowing for asynchronous
|
||||
* operation.
|
||||
*/
|
||||
NTSTATUS (*Unlock)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, UINT64 Offset, UINT64 Length, UINT64 Owner);
|
||||
|
||||
/*
|
||||
* This ensures that this interface will always contain 64 function pointers.
|
||||
* Please update when changing the interface as it is important for future compatibility.
|
||||
*/
|
||||
NTSTATUS (*Reserved[37])();
|
||||
NTSTATUS (*Reserved[39])();
|
||||
} FSP_FILE_SYSTEM_INTERFACE;
|
||||
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||
@ -1155,7 +1086,7 @@ BOOLEAN FspFileSystemIsOperationCaseSensitive(VOID)
|
||||
}
|
||||
FSP_API BOOLEAN FspFileSystemIsOperationCaseSensitiveF(VOID);
|
||||
/**
|
||||
* Get the originating process ID.
|
||||
* Gets the originating process ID.
|
||||
*
|
||||
* Valid only during Create, Open and Rename requests when the target exists.
|
||||
*/
|
||||
@ -1176,28 +1107,6 @@ UINT32 FspFileSystemOperationProcessId(VOID)
|
||||
}
|
||||
}
|
||||
FSP_API UINT32 FspFileSystemOperationProcessIdF(VOID);
|
||||
/**
|
||||
* Get the lock owner.
|
||||
*
|
||||
* Valid only during Read, Write, Lock and Unlock requests.
|
||||
*/
|
||||
static inline
|
||||
UINT64 FspFileSystemOperationLockOwner(VOID)
|
||||
{
|
||||
FSP_FSCTL_TRANSACT_REQ *Request = FspFileSystemGetOperationContext()->Request;
|
||||
switch (Request->Kind)
|
||||
{
|
||||
case FspFsctlTransactReadKind:
|
||||
return ((UINT64)Request->Req.Read.ProcessId << 32) | (UINT64)Request->Req.Read.Key;
|
||||
case FspFsctlTransactWriteKind:
|
||||
return ((UINT64)Request->Req.Write.ProcessId << 32) | (UINT64)Request->Req.Write.Key;
|
||||
case FspFsctlTransactLockControlKind:
|
||||
return ((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
FSP_API UINT64 FspFileSystemOperationLockOwnerF(VOID);
|
||||
|
||||
/*
|
||||
* Operations
|
||||
@ -1232,8 +1141,6 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpLockControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
@ -1768,6 +1675,19 @@ FSP_API VOID FspServiceStop(FSP_SERVICE *Service);
|
||||
* TRUE if the process is running in running user interactive mode.
|
||||
*/
|
||||
FSP_API BOOLEAN FspServiceIsInteractive(VOID);
|
||||
/**
|
||||
* Check if the supplied token is from the service context.
|
||||
*
|
||||
* @param Token
|
||||
* Token to check. Pass NULL to check the current process token.
|
||||
* @param PIsLocalSystem
|
||||
* Pointer to a boolean that will receive a TRUE value if the token belongs to LocalSystem
|
||||
* and FALSE otherwise. May be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the token is from the service context. STATUS_ACCESS_DENIED if it is not.
|
||||
* Other error codes are possible.
|
||||
*/
|
||||
FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem);
|
||||
/**
|
||||
* Log a service message.
|
||||
*
|
||||
@ -1793,6 +1713,7 @@ FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||
FSP_API VOID FspDebugLogSetHandle(HANDLE Handle);
|
||||
FSP_API VOID FspDebugLog(const char *Format, ...);
|
||||
FSP_API VOID FspDebugLogSD(const char *Format, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||
FSP_API VOID FspDebugLogSid(const char *format, PSID Sid);
|
||||
FSP_API VOID FspDebugLogFT(const char *Format, PFILETIME FileTime);
|
||||
FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request);
|
||||
FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @file winfsp/winfsp.hpp
|
||||
* WinFsp C++ Layer.
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -22,7 +22,9 @@ cygport:
|
||||
dist: cygport
|
||||
case $(shell uname -m) in \
|
||||
x86_64)\
|
||||
mkdir -p dist/x64 && \
|
||||
cp fuse-*/dist/fuse/fuse-*[0-9].tar.xz dist/x64 ;;\
|
||||
*)\
|
||||
mkdir -p dist/x86 && \
|
||||
cp fuse-*/dist/fuse/fuse-*[0-9].tar.xz dist/x86 ;;\
|
||||
esac
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file cygfuse/cygfuse.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
BIN
opt/cygfuse/dist/x64/fuse-2.8-6.tar.xz
vendored
BIN
opt/cygfuse/dist/x64/fuse-2.8-6.tar.xz
vendored
Binary file not shown.
BIN
opt/cygfuse/dist/x64/fuse-2.8-8.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x64/fuse-2.8-8.tar.xz
vendored
Normal file
Binary file not shown.
BIN
opt/cygfuse/dist/x86/fuse-2.8-6.tar.xz
vendored
BIN
opt/cygfuse/dist/x86/fuse-2.8-6.tar.xz
vendored
Binary file not shown.
BIN
opt/cygfuse/dist/x86/fuse-2.8-8.tar.xz
vendored
Normal file
BIN
opt/cygfuse/dist/x86/fuse-2.8-8.tar.xz
vendored
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
NAME="fuse"
|
||||
VERSION=2.8
|
||||
RELEASE=6
|
||||
RELEASE=8
|
||||
CATEGORY="Utils"
|
||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/debug.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -63,6 +63,21 @@ FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDesc
|
||||
FspDebugLog(format, "invalid security descriptor");
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogSid(const char *format, PSID Sid)
|
||||
{
|
||||
char *S;
|
||||
|
||||
if (0 == Sid)
|
||||
FspDebugLog(format, "null SID");
|
||||
else if (ConvertSidToStringSidA(Sid, &S))
|
||||
{
|
||||
FspDebugLog(format, S);
|
||||
LocalFree(S);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid SID");
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime)
|
||||
{
|
||||
SYSTEMTIME SystemTime;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/dirbuf.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/eventlog.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
72
src/dll/fs.c
72
src/dll/fs.c
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fs.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -162,7 +162,6 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
||||
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
|
||||
FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory;
|
||||
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
|
||||
FileSystem->Operations[FspFsctlTransactLockControlKind] = FspFileSystemOpLockControl;
|
||||
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
|
||||
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
|
||||
FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation;
|
||||
@ -188,17 +187,62 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
|
||||
MemFree(FileSystem);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileSystemLauncherDefineDosDevice(
|
||||
WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName)
|
||||
{
|
||||
if (2 != lstrlenW(MountPoint) ||
|
||||
FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= lstrlenW(VolumeName))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
WCHAR Argv0[4];
|
||||
PWSTR Argv[2];
|
||||
NTSTATUS Result;
|
||||
ULONG ErrorCode;
|
||||
|
||||
Argv0[0] = Sign;
|
||||
Argv0[1] = MountPoint[0];
|
||||
Argv0[2] = MountPoint[1];
|
||||
Argv0[3] = L'\0';
|
||||
|
||||
Argv[0] = Argv0;
|
||||
Argv[1] = VolumeName;
|
||||
|
||||
Result = FspLaunchCallLauncherPipe(FspLaunchCmdDefineDosDevice, 2, Argv, 0, 0, 0, &ErrorCode);
|
||||
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
|
||||
PHANDLE PMountHandle)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
BOOLEAN IsLocalSystem, IsServiceContext;
|
||||
|
||||
*PMountHandle = 0;
|
||||
|
||||
Result = FspServiceContextCheck(0, &IsLocalSystem);
|
||||
IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem;
|
||||
if (IsServiceContext)
|
||||
{
|
||||
/*
|
||||
* If the current process is in the service context but not LocalSystem,
|
||||
* ask the launcher to DefineDosDevice for us. This is because the launcher
|
||||
* runs in the LocalSystem context and can create global drives.
|
||||
*
|
||||
* In this case the launcher will also add DELETE access to the drive symlink
|
||||
* for us, so that we can make it temporary below.
|
||||
*/
|
||||
Result = FspFileSystemLauncherDefineDosDevice(L'+', MountPoint, VolumeName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
if (0 != FspNtOpenSymbolicLinkObject)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
WCHAR SymlinkBuf[6];
|
||||
UNICODE_STRING Symlink;
|
||||
OBJECT_ATTRIBUTES Obja;
|
||||
@ -225,6 +269,13 @@ static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeN
|
||||
}
|
||||
}
|
||||
|
||||
/* HACK:
|
||||
*
|
||||
* Handles do not use the low 2 bits (unless they are console handles).
|
||||
* Abuse this fact to remember that we are running in the service context.
|
||||
*/
|
||||
*PMountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)*PMountHandle | IsServiceContext);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -412,6 +463,16 @@ exit:
|
||||
|
||||
static VOID FspFileSystemRemoveMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, HANDLE MountHandle)
|
||||
{
|
||||
BOOLEAN IsServiceContext = 0 != ((DWORD)(UINT_PTR)MountHandle & 1);
|
||||
MountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)MountHandle & ~1);
|
||||
if (IsServiceContext)
|
||||
/*
|
||||
* If the current process is in the service context but not LocalSystem,
|
||||
* ask the launcher to DefineDosDevice for us. This is because the launcher
|
||||
* runs in the LocalSystem context and can remove global drives.
|
||||
*/
|
||||
FspFileSystemLauncherDefineDosDevice(L'-', MountPoint, VolumeName);
|
||||
else
|
||||
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||
MountPoint, VolumeName);
|
||||
|
||||
@ -689,8 +750,3 @@ FSP_API UINT32 FspFileSystemOperationProcessIdF(VOID)
|
||||
{
|
||||
return FspFileSystemOperationProcessId();
|
||||
}
|
||||
|
||||
FSP_API UINT64 FspFileSystemOperationLockOwnerF(VOID)
|
||||
{
|
||||
return FspFileSystemOperationLockOwner();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fsctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -31,7 +31,7 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PWSTR DeviceRoot;
|
||||
SIZE_T DeviceRootSize, DevicePathSize;
|
||||
SIZE_T DeviceRootSize, DevicePathSize, VolumeParamsSize;
|
||||
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes;
|
||||
@ -55,8 +55,11 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
memcpy(DevicePathPtr, DevicePath, DevicePathSize);
|
||||
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DevicePathSize);
|
||||
memcpy(DevicePathPtr, PREFIXW, PREFIXW_SIZE);
|
||||
VolumeParamsSize = 0 == VolumeParams->Version ?
|
||||
sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) :
|
||||
VolumeParams->Version;
|
||||
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + PREFIXW_SIZE);
|
||||
DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + sizeof *VolumeParams * sizeof(WCHAR));
|
||||
DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + VolumeParamsSize * sizeof(WCHAR));
|
||||
for (PUINT8 VolumeParamsPtr = (PVOID)VolumeParams;
|
||||
DevicePathEnd > DevicePathPtr; DevicePathPtr++, VolumeParamsPtr++)
|
||||
{
|
||||
@ -284,7 +287,7 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
* This function adds an ACE that allows Everyone to start a service.
|
||||
*/
|
||||
|
||||
PSID WorldSid = 0;
|
||||
PSID WorldSid;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||
PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
|
||||
EXPLICIT_ACCESSW AccessEntry;
|
||||
@ -296,18 +299,12 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
NTSTATUS Result;
|
||||
|
||||
/* get the Everyone (World) SID */
|
||||
Size = SECURITY_MAX_SID_SIZE;
|
||||
WorldSid = MemAlloc(Size);
|
||||
WorldSid = FspWksidGet(WinWorldSid);
|
||||
if (0 == WorldSid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
if (!CreateWellKnownSid(WinWorldSid, 0, WorldSid, &Size))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* get the service security descriptor DACL */
|
||||
Size = 0;
|
||||
@ -394,7 +391,6 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
exit:
|
||||
LocalFree(NewSecurityDescriptor);
|
||||
MemFree(SecurityDescriptor);
|
||||
MemFree(WorldSid);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fsop.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -886,7 +886,6 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
|
||||
(0 != Request->Req.Cleanup.UnlockAll ? FspCleanupUnlockAll : 0) |
|
||||
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@ -1248,43 +1247,6 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemOpLockControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
switch (Request->Req.LockControl.LockFunction)
|
||||
{
|
||||
case 0x01/*IRP_MN_LOCK*/:
|
||||
if (0 != FileSystem->Interface->Lock)
|
||||
Result = FileSystem->Interface->Lock(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.LockControl),
|
||||
Request->Req.LockControl.Offset, Request->Req.LockControl.Length,
|
||||
((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key,
|
||||
0 != Request->Req.LockControl.Exclusive,
|
||||
0 != Request->Req.LockControl.FailImmediately);
|
||||
break;
|
||||
case 0x02/*IRP_MN_UNLOCK_SINGLE*/:
|
||||
if (0 != FileSystem->Interface->Unlock)
|
||||
Result = FileSystem->Interface->Unlock(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.LockControl),
|
||||
Request->Req.LockControl.Offset, Request->Req.LockControl.Length,
|
||||
((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key);
|
||||
break;
|
||||
case 0x03/*IRP_MN_UNLOCK_ALL*/:
|
||||
case 0x04/*IRP_MN_UNLOCK_ALL_BY_KEY*/:
|
||||
if (0 != FileSystem->Interface->Unlock)
|
||||
Result = FileSystem->Interface->Unlock(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.LockControl),
|
||||
(UINT64)-1LL, (UINT64)-1LL,
|
||||
((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key);
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -34,11 +34,16 @@ struct fsp_fuse_core_opt_data
|
||||
int help, debug;
|
||||
HANDLE DebugLogHandle;
|
||||
int set_umask, umask,
|
||||
set_create_umask, create_umask,
|
||||
set_uid, uid,
|
||||
set_gid, gid,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks;
|
||||
int set_FileInfoTimeout;
|
||||
int set_FileInfoTimeout,
|
||||
set_DirInfoTimeout,
|
||||
set_VolumeInfoTimeout,
|
||||
set_KeepFileCache;
|
||||
unsigned ThreadCount;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UINT16 VolumeLabelLength;
|
||||
WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)];
|
||||
@ -69,6 +74,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FUSE_OPT_KEY("noauto_cache", FUSE_OPT_KEY_DISCARD),
|
||||
FSP_FUSE_CORE_OPT("umask=", set_umask, 1),
|
||||
FSP_FUSE_CORE_OPT("umask=%o", umask, 0),
|
||||
FSP_FUSE_CORE_OPT("create_umask=", set_create_umask, 1),
|
||||
FSP_FUSE_CORE_OPT("create_umask=%o", create_umask, 0),
|
||||
FSP_FUSE_CORE_OPT("uid=", set_uid, 1),
|
||||
FSP_FUSE_CORE_OPT("uid=%d", uid, 0),
|
||||
FSP_FUSE_CORE_OPT("gid=", set_gid, 1),
|
||||
@ -96,6 +103,12 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("DirInfoTimeout=", set_DirInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("DirInfoTimeout=%d", VolumeParams.DirInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=", set_VolumeInfoTimeout, 1),
|
||||
FSP_FUSE_CORE_OPT("VolumeInfoTimeout=%d", VolumeParams.VolumeInfoTimeout, 0),
|
||||
FSP_FUSE_CORE_OPT("KeepFileCache=", set_KeepFileCache, 1),
|
||||
FSP_FUSE_CORE_OPT("ThreadCount=%u", ThreadCount, 0),
|
||||
FUSE_OPT_KEY("UNC=", 'U'),
|
||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||
FUSE_OPT_KEY("VolumePrefix=", 'U'),
|
||||
@ -413,7 +426,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
}
|
||||
}
|
||||
|
||||
Result = FspFileSystemStartDispatcher(f->FileSystem, 0);
|
||||
Result = FspFileSystemStartDispatcher(f->FileSystem, f->ThreadCount);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||
@ -468,10 +481,11 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
default:
|
||||
return 1;
|
||||
case 'h':
|
||||
/* Note: The limit on FspServiceLog messages is 1024 bytes. This is getting close. */
|
||||
/* Note: The limit on FspServiceLog messages is 1024 bytes. */
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||
FSP_FUSE_LIBRARY_NAME " options:\n"
|
||||
" -o umask=MASK set file permissions (octal)\n"
|
||||
" -o create_umask=MASK set newly created file permissions (octal)\n"
|
||||
" -o uid=N set file owner (-1 for mounting user id)\n"
|
||||
" -o gid=N set file group (-1 for mounting user group)\n"
|
||||
" -o rellinks interpret absolute symlinks as volume relative\n"
|
||||
@ -480,14 +494,14 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
" --VolumePrefix=UNC set UNC prefix (\\Server\\Share)\n"
|
||||
" -o FileSystemName=NAME set file system name\n"
|
||||
" -o DebugLog=FILE debug log file (requires -d)\n"
|
||||
"\n"
|
||||
);
|
||||
FspServiceLog(EVENTLOG_ERROR_TYPE, L""
|
||||
FSP_FUSE_LIBRARY_NAME " advanced options:\n"
|
||||
" -o FileInfoTimeout=N metadata timeout (millis, -1 for data caching)\n"
|
||||
" -o SectorSize=N (512-4096, deflt: 4096)\n"
|
||||
" -o SectorsPerAllocationUnit=N (deflt: 1)\n"
|
||||
" -o MaxComponentLength=N (deflt: 255)\n"
|
||||
" -o VolumeCreationTime=T (FILETIME hex format)\n"
|
||||
" -o VolumeSerialNumber=N (32-bit wide)\n"
|
||||
" -o DirInfoTimeout=N directory info timeout (millis)\n"
|
||||
" -o VolumeInfoTimeout=N volume info timeout (millis)\n"
|
||||
" -o KeepFileCache do not discard cache when files are closed\n"
|
||||
" -o ThreadCount number of file system dispatcher threads\n"
|
||||
);
|
||||
opt_data->help = 1;
|
||||
return 1;
|
||||
@ -568,7 +582,9 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
memset(&opt_data, 0, sizeof opt_data);
|
||||
opt_data.env = env;
|
||||
opt_data.DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000; /* default FileInfoTimeout for FUSE file systems */
|
||||
opt_data.VolumeParams.Version = sizeof(FSP_FSCTL_VOLUME_PARAMS);
|
||||
opt_data.VolumeParams.FileInfoTimeout = 1000;
|
||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE;
|
||||
|
||||
if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc))
|
||||
return 0;
|
||||
@ -608,7 +624,13 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
}
|
||||
|
||||
if (!opt_data.set_FileInfoTimeout && opt_data.set_attr_timeout)
|
||||
opt_data.VolumeParams.FileInfoTimeout = opt_data.set_attr_timeout * 1000;
|
||||
opt_data.VolumeParams.FileInfoTimeout = opt_data.attr_timeout * 1000;
|
||||
if (opt_data.set_DirInfoTimeout)
|
||||
opt_data.VolumeParams.DirInfoTimeoutValid = 1;
|
||||
if (opt_data.set_VolumeInfoTimeout)
|
||||
opt_data.VolumeParams.VolumeInfoTimeoutValid = 1;
|
||||
if (opt_data.set_KeepFileCache)
|
||||
opt_data.VolumeParams.FlushAndPurgeOnCleanup = FALSE;
|
||||
opt_data.VolumeParams.CaseSensitiveSearch = TRUE;
|
||||
opt_data.VolumeParams.CasePreservedNames = TRUE;
|
||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||
@ -628,9 +650,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
|
||||
f->env = env;
|
||||
f->set_umask = opt_data.set_umask; f->umask = opt_data.umask;
|
||||
f->set_create_umask = opt_data.set_create_umask; f->create_umask = opt_data.create_umask;
|
||||
f->set_uid = opt_data.set_uid; f->uid = opt_data.uid;
|
||||
f->set_gid = opt_data.set_gid; f->gid = opt_data.gid;
|
||||
f->rellinks = opt_data.rellinks;
|
||||
f->ThreadCount = opt_data.ThreadCount;
|
||||
memcpy(&f->ops, ops, opsize);
|
||||
f->data = data;
|
||||
f->DebugLog = opt_data.debug ? -1 : 0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_compat.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_intf.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -711,14 +711,16 @@ static NTSTATUS fsp_fuse_intf_GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
Result = fsp_fuse_intf_GetSecurityEx(FileSystem, PosixPath, 0,
|
||||
PFileAttributes, SecurityDescriptorBuf, PSecurityDescriptorSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
if (!NT_SUCCESS(Result) &&
|
||||
STATUS_OBJECT_NAME_NOT_FOUND != Result &&
|
||||
STATUS_OBJECT_PATH_NOT_FOUND != Result)
|
||||
goto exit;
|
||||
|
||||
if (FSP_FUSE_HAS_SYMLINKS(f) &&
|
||||
FspFileSystemFindReparsePoint(FileSystem, fsp_fuse_intf_GetReparsePointByName, 0,
|
||||
FileName, PFileAttributes))
|
||||
Result = STATUS_REPARSE;
|
||||
else
|
||||
else if (NT_SUCCESS(Result))
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
@ -762,12 +764,14 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
goto exit;
|
||||
}
|
||||
Mode &= ~context->umask;
|
||||
if (f->set_create_umask)
|
||||
Mode = 0777 & ~f->create_umask;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
if ('C' == f->env->environment) /* Cygwin */
|
||||
fi.flags = 0x0200 | 2 /*O_CREAT|O_RDWR*/;
|
||||
fi.flags = 0x0200 | 0x0800 | 2 /*O_CREAT|O_EXCL|O_RDWR*/;
|
||||
else
|
||||
fi.flags = 0x0100 | 2 /*O_CREAT|O_RDWR*/;
|
||||
fi.flags = 0x0100 | 0x0400 | 2 /*O_CREAT|O_EXCL|O_RDWR*/;
|
||||
|
||||
if (CreateOptions & FILE_DIRECTORY_FILE)
|
||||
{
|
||||
@ -821,15 +825,24 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
Opened = TRUE;
|
||||
|
||||
if (Uid != context->uid || Gid != context->gid)
|
||||
if (0 != f->ops.chown)
|
||||
{
|
||||
err = f->ops.chown(contexthdr->PosixPath, Uid, Gid);
|
||||
if (0 != err)
|
||||
if (0 != FileAttributes &&
|
||||
0 != (f->conn_want & FSP_FUSE_CAP_STAT_EX) && 0 != f->ops.chflags)
|
||||
{
|
||||
err = f->ops.chflags(contexthdr->PosixPath,
|
||||
fsp_fuse_intf_MapFileAttributesToFlags(CreateOptions & FILE_DIRECTORY_FILE ?
|
||||
FileAttributes : FileAttributes | FILE_ATTRIBUTE_ARCHIVE));
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((Uid != context->uid || Gid != context->gid) &&
|
||||
0 != f->ops.chown)
|
||||
{
|
||||
err = f->ops.chown(contexthdr->PosixPath, Uid, Gid);
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1015,6 +1028,22 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
if (0 != FileAttributes &&
|
||||
0 != (f->conn_want & FSP_FUSE_CAP_STAT_EX) && 0 != f->ops.chflags)
|
||||
{
|
||||
/*
|
||||
* The code below is not strictly correct. File attributes should be
|
||||
* replaced when ReplaceFileAttributes is TRUE and merged (or'ed) when
|
||||
* ReplaceFileAttributes is FALSE. I am punting on this detail for now.
|
||||
*/
|
||||
|
||||
err = f->ops.chflags(filedesc->PosixPath,
|
||||
fsp_fuse_intf_MapFileAttributesToFlags(FileAttributes | FILE_ATTRIBUTE_ARCHIVE));
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
return Result;
|
||||
}
|
||||
|
||||
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
||||
&Uid, &Gid, &Mode, FileInfo);
|
||||
}
|
||||
@ -1623,7 +1652,8 @@ static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
memset(DirInfo, 0, sizeof *DirInfo);
|
||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + SizeW * sizeof(WCHAR));
|
||||
|
||||
if (dh->ReaddirPlus && 0 != stbuf)
|
||||
if (dh->ReaddirPlus && 0 != stbuf &&
|
||||
0120000/* S_IFLNK */ != (stbuf->st_mode & 0170000))
|
||||
{
|
||||
UINT32 Uid, Gid, Mode;
|
||||
NTSTATUS Result0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_main.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fuse/fuse_opt.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/fuse/library.h
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -35,9 +35,11 @@ struct fuse
|
||||
{
|
||||
struct fsp_fuse_env *env;
|
||||
int set_umask, umask;
|
||||
int set_create_umask, create_umask;
|
||||
int set_uid, uid;
|
||||
int set_gid, gid;
|
||||
int rellinks;
|
||||
unsigned ThreadCount;
|
||||
struct fuse_operations ops;
|
||||
void *data;
|
||||
unsigned conn_want;
|
||||
|
449
src/dll/launch.c
Normal file
449
src/dll/launch.c
Normal file
@ -0,0 +1,449 @@
|
||||
/**
|
||||
* @file dll/launch.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError)
|
||||
{
|
||||
PWSTR PipeBuf = 0, P;
|
||||
ULONG Length, BytesTransferred;
|
||||
NTSTATUS Result;
|
||||
ULONG ErrorCode;
|
||||
|
||||
*PLauncherError = 0;
|
||||
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = Command;
|
||||
for (ULONG I = 0; Argc > I; I++)
|
||||
if (0 != Argv[I])
|
||||
{
|
||||
Length = 0 == Argl || -1 == Argl[I] ? lstrlenW(Argv[I]) : Argl[I];
|
||||
if (FSP_LAUNCH_PIPE_BUFFER_SIZE < ((ULONG)(P - PipeBuf) + Length + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
memcpy(P, Argv[I], Length * sizeof(WCHAR)); P += Length; *P++ = L'\0';
|
||||
}
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME,
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
ErrorCode = ERROR_BROKEN_PIPE; /* protocol error! */
|
||||
if (sizeof(WCHAR) <= BytesTransferred)
|
||||
{
|
||||
if (FspLaunchCmdSuccess == PipeBuf[0])
|
||||
{
|
||||
ErrorCode = 0;
|
||||
|
||||
if (0 != PSize)
|
||||
{
|
||||
BytesTransferred -= sizeof(WCHAR);
|
||||
memcpy(Buffer, PipeBuf + 1, *PSize < BytesTransferred ? *PSize : BytesTransferred);
|
||||
*PSize = BytesTransferred;
|
||||
}
|
||||
}
|
||||
else if (FspLaunchCmdFailure == PipeBuf[0])
|
||||
{
|
||||
ErrorCode = 0;
|
||||
|
||||
for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++)
|
||||
{
|
||||
if (L'0' > *P || *P > L'9')
|
||||
break;
|
||||
ErrorCode = 10 * ErrorCode + (*P - L'0');
|
||||
}
|
||||
|
||||
if (0 == ErrorCode)
|
||||
ErrorCode = ERROR_BROKEN_PIPE; /* protocol error! */
|
||||
}
|
||||
}
|
||||
|
||||
*PLauncherError = ErrorCode;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result) && 0 != PSize)
|
||||
*PSize = 0;
|
||||
|
||||
MemFree(PipeBuf);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError)
|
||||
{
|
||||
PWSTR Argv[9 + 2];
|
||||
|
||||
if (9 < Argc)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
memcpy(Argv + 2, Argv0, Argc * sizeof(PWSTR));
|
||||
|
||||
return FspLaunchCallLauncherPipe(
|
||||
HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||
Argc + 2, Argv, 0, 0, 0, PLauncherError);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PULONG PLauncherError)
|
||||
{
|
||||
PWSTR Argv[2];
|
||||
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdStop,
|
||||
2, Argv, 0, 0, 0, PLauncherError);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError)
|
||||
{
|
||||
PWSTR Argv[2];
|
||||
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdGetInfo,
|
||||
2, Argv, 0, Buffer, PSize, PLauncherError);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError)
|
||||
{
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdGetNameList,
|
||||
0, 0, 0, Buffer, PSize, PLauncherError);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record)
|
||||
{
|
||||
#define SETFIELD(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
if (0 != Record->FieldName) \
|
||||
{ \
|
||||
RegResult = RegSetValueExW(RegKey,\
|
||||
L"" #FieldName, 0, REG_SZ,\
|
||||
(PVOID)Record->FieldName, (lstrlenW(Record->FieldName) + 1) * sizeof(WCHAR));\
|
||||
if (ERROR_SUCCESS != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegResult = RegDeleteValueW(RegKey,\
|
||||
L"" #FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
} while (0,0)
|
||||
#define SETFIELDI(FieldName, Deflt) \
|
||||
do \
|
||||
{ \
|
||||
if (Deflt != Record->FieldName) \
|
||||
{ \
|
||||
RegResult = RegSetValueExW(RegKey,\
|
||||
L"" #FieldName, 0, REG_DWORD,\
|
||||
(PVOID)&Record->FieldName, sizeof Record->FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegResult = RegDeleteValueW(RegKey,\
|
||||
L"" #FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
} while (0,0)
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG ClassNameLen;
|
||||
WCHAR RegPath[MAX_PATH];
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult;
|
||||
|
||||
if (0 != Record && 0 == Record->Executable)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ClassNameLen = lstrlenW(ClassName);
|
||||
if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR));
|
||||
RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\';
|
||||
memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR),
|
||||
ClassName, (ClassNameLen + 1) * sizeof(WCHAR));
|
||||
|
||||
if (0 != Record)
|
||||
{
|
||||
RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, RegPath,
|
||||
0, 0, 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_SET_VALUE, 0, &RegKey, 0);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
SETFIELD(Agent);
|
||||
SETFIELD(Executable);
|
||||
SETFIELD(CommandLine);
|
||||
SETFIELD(WorkDirectory);
|
||||
SETFIELD(RunAs);
|
||||
SETFIELD(Security);
|
||||
SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */
|
||||
SETFIELDI(Credentials, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RegResult = RegDeleteKeyEx(HKEY_LOCAL_MACHINE, RegPath,
|
||||
FSP_LAUNCH_REGKEY_WOW64, 0);
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return Result;
|
||||
|
||||
#undef SETFIELD
|
||||
#undef SETFIELDI
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName, PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord)
|
||||
{
|
||||
#define GETFIELD(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
RegSize = sizeof RegBuf - RegMark;\
|
||||
RegResult = RegQueryValueEx(RegKey,\
|
||||
L"" #FieldName, 0, &RegType,\
|
||||
(PVOID)(RegBuf + RegMark), &RegSize);\
|
||||
if (ERROR_SUCCESS != RegResult) \
|
||||
{ \
|
||||
if (ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else if (REG_SZ != RegType || \
|
||||
sizeof(WCHAR) > RegSize || \
|
||||
L'\0' != *(PWSTR)(RegBuf + RegMark + RegSize - sizeof(WCHAR)))\
|
||||
{ \
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;\
|
||||
goto exit; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Record->FieldName = (PWSTR)(RegBuf + RegMark);\
|
||||
RegMark += RegSize; \
|
||||
} \
|
||||
} while (0,0)
|
||||
#define GETFIELDI(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
RegSize = sizeof RegDword; \
|
||||
RegResult = RegQueryValueEx(RegKey,\
|
||||
L"" #FieldName, 0, &RegType,\
|
||||
(PVOID)&RegDword, &RegSize);\
|
||||
if (ERROR_SUCCESS != RegResult) \
|
||||
{ \
|
||||
if (ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else if (REG_DWORD != RegType) \
|
||||
{ \
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;\
|
||||
goto exit; \
|
||||
} \
|
||||
else \
|
||||
Record->FieldName = RegDword;\
|
||||
} while (0,0)
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG ClassNameLen;
|
||||
WCHAR RegPath[MAX_PATH];
|
||||
FSP_LAUNCH_REG_RECORD RecordBuf, *Record = &RecordBuf;
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult, RegDword, RegType, RegSize, RegMark;
|
||||
UINT8 RegBuf[2 * 1024];
|
||||
PWSTR P, Part;
|
||||
BOOLEAN FoundAgent;
|
||||
|
||||
*PRecord = 0;
|
||||
|
||||
ClassNameLen = lstrlenW(ClassName);
|
||||
if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR));
|
||||
RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\';
|
||||
memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR),
|
||||
ClassName, (ClassNameLen + 1) * sizeof(WCHAR));
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegPath,
|
||||
0, FSP_LAUNCH_REGKEY_WOW64 | KEY_QUERY_VALUE, &RegKey);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Record, 0, sizeof *Record);
|
||||
Record->JobControl = 1; /* default is YES! */
|
||||
RegMark = 0;
|
||||
|
||||
GETFIELD(Agent);
|
||||
if (0 != Agent && L'\0' != Agent[0] &&
|
||||
0 != Record->Agent && L'\0' != Record->Agent[0])
|
||||
{
|
||||
FoundAgent = FALSE;
|
||||
P = Record->Agent, Part = P;
|
||||
do
|
||||
{
|
||||
if (L',' == *P || '\0' == *P)
|
||||
{
|
||||
if (0 == invariant_wcsnicmp(Part, Agent, P - Part))
|
||||
{
|
||||
FoundAgent = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
Part = P + 1;
|
||||
}
|
||||
} while (L'\0' != *P++);
|
||||
|
||||
if (!FoundAgent)
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
GETFIELD(Executable);
|
||||
GETFIELD(CommandLine);
|
||||
GETFIELD(WorkDirectory);
|
||||
GETFIELD(RunAs);
|
||||
GETFIELD(Security);
|
||||
GETFIELDI(JobControl);
|
||||
GETFIELDI(Credentials);
|
||||
|
||||
if (0 == Record->Executable)
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Record = MemAlloc(FIELD_OFFSET(FSP_LAUNCH_REG_RECORD, Buffer) + RegMark);
|
||||
if (0 == Record)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Record, 0, sizeof *Record);
|
||||
memcpy(Record->Buffer, RegBuf, RegMark);
|
||||
Record->Agent = 0 != RecordBuf.Agent ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Agent - RegBuf)) : 0;
|
||||
Record->Executable = 0 != RecordBuf.Executable ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Executable - RegBuf)) : 0;
|
||||
Record->CommandLine = 0 != RecordBuf.CommandLine ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.CommandLine - RegBuf)) : 0;
|
||||
Record->WorkDirectory = 0 != RecordBuf.WorkDirectory ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.WorkDirectory - RegBuf)) : 0;
|
||||
Record->RunAs = 0 != RecordBuf.RunAs ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0;
|
||||
Record->Security = 0 != RecordBuf.Security ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0;
|
||||
Record->JobControl = RecordBuf.JobControl;
|
||||
Record->Credentials = RecordBuf.Credentials;
|
||||
|
||||
*PRecord = Record;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return Result;
|
||||
|
||||
#undef GETFIELDI
|
||||
#undef GETFIELD
|
||||
}
|
||||
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record)
|
||||
{
|
||||
MemFree(Record);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/library.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -44,6 +44,7 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||
FspServiceFinalize(Dynamic);
|
||||
FspEventLogFinalize(Dynamic);
|
||||
FspPosixFinalize(Dynamic);
|
||||
FspWksidFinalize(Dynamic);
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/library.h
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#define WINFSP_DLL_INTERNAL
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
@ -31,11 +32,15 @@
|
||||
FspDebugLog("[U] " LIBRARY_NAME "!" __FUNCTION__ ": " fmt "\n", __VA_ARGS__)
|
||||
#define DEBUGLOGSD(fmt, SD) \
|
||||
FspDebugLogSD("[U] " LIBRARY_NAME "!" __FUNCTION__ ": " fmt "\n", SD)
|
||||
#define DEBUGLOGSID(fmt, Sid) \
|
||||
FspDebugLogSid("[U] " LIBRARY_NAME "!" __FUNCTION__ ": " fmt "\n", Sid)
|
||||
#else
|
||||
#define DEBUGLOG(fmt, ...) ((void)0)
|
||||
#define DEBUGLOGSD(fmt, SD) ((void)0)
|
||||
#define DEBUGLOGSID(fmt, Sid) ((void)0)
|
||||
#endif
|
||||
|
||||
VOID FspWksidFinalize(BOOLEAN Dynamic);
|
||||
VOID FspPosixFinalize(BOOLEAN Dynamic);
|
||||
VOID FspEventLogFinalize(BOOLEAN Dynamic);
|
||||
VOID FspServiceFinalize(BOOLEAN Dynamic);
|
||||
@ -49,6 +54,9 @@ NTSTATUS FspNpUnregister(VOID);
|
||||
NTSTATUS FspEventLogRegister(VOID);
|
||||
NTSTATUS FspEventLogUnregister(VOID);
|
||||
|
||||
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
||||
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
||||
|
||||
PWSTR FspDiagIdent(VOID);
|
||||
|
||||
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||
|
194
src/dll/np.c
194
src/dll/np.c
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/np.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -16,8 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <launcher/launcher.h>
|
||||
#include <lmcons.h>
|
||||
#include <npapi.h>
|
||||
#include <wincred.h>
|
||||
|
||||
@ -36,6 +34,12 @@
|
||||
*/
|
||||
#define FSP_NP_CREDENTIAL_MANAGER
|
||||
|
||||
/*
|
||||
* Define the following macro to register ourselves as the first network provider.
|
||||
* Otherwise we will be registered as the last network provider.
|
||||
*/
|
||||
#define FSP_NP_ORDER_FIRST
|
||||
|
||||
enum
|
||||
{
|
||||
FSP_NP_CREDENTIALS_NONE = 0,
|
||||
@ -169,45 +173,17 @@ static inline BOOLEAN FspNpParseRemoteUserName(PWSTR RemoteName,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline BOOLEAN FspNpGetLocalUserName(
|
||||
PWSTR UserName, ULONG UserNameSize/* in chars */)
|
||||
static inline DWORD FspNpCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
PWSTR Buffer, PULONG PSize)
|
||||
{
|
||||
return GetUserName(UserName, &UserNameSize);
|
||||
}
|
||||
|
||||
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
{
|
||||
DWORD NpResult;
|
||||
NTSTATUS Result;
|
||||
DWORD BytesTransferred;
|
||||
ULONG ErrorCode;
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||
|
||||
if (!NT_SUCCESS(Result))
|
||||
NpResult = WN_NO_NETWORK;
|
||||
else if (sizeof(WCHAR) > BytesTransferred)
|
||||
NpResult = WN_NO_NETWORK;
|
||||
else if (LauncherSuccess == PipeBuf[0])
|
||||
NpResult = WN_SUCCESS;
|
||||
else if (LauncherFailure == PipeBuf[0])
|
||||
{
|
||||
NpResult = 0;
|
||||
for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++)
|
||||
{
|
||||
if (L'0' > *P || *P > L'9')
|
||||
break;
|
||||
|
||||
NpResult = 10 * NpResult + (*P - L'0');
|
||||
}
|
||||
|
||||
if (0 == NpResult)
|
||||
NpResult = WN_NO_NETWORK;
|
||||
}
|
||||
else
|
||||
NpResult = WN_NO_NETWORK;
|
||||
|
||||
return NpResult;
|
||||
Result = FspLaunchCallLauncherPipe(Command, Argc, Argv, Argl, Buffer, PSize, &ErrorCode);
|
||||
return !NT_SUCCESS(Result) ?
|
||||
WN_NO_NETWORK :
|
||||
(ERROR_BROKEN_PIPE == ErrorCode ? WN_NO_NETWORK : ErrorCode);
|
||||
}
|
||||
|
||||
static NTSTATUS FspNpGetVolumeList(
|
||||
@ -271,14 +247,13 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
{
|
||||
HKEY RegKey = 0;
|
||||
DWORD NpResult, RegSize;
|
||||
DWORD Credentials;
|
||||
PWSTR ClassName, InstanceName;
|
||||
ULONG ClassNameLen, InstanceNameLen;
|
||||
WCHAR ClassNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||
FSP_LAUNCH_REG_RECORD *Record;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
||||
|
||||
@ -291,34 +266,22 @@ static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
||||
ClassNameBuf[ClassNameLen] = '\0';
|
||||
|
||||
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
if (ERROR_SUCCESS != NpResult)
|
||||
goto exit;
|
||||
Result = FspLaunchRegGetRecord(ClassNameBuf, L"" FSP_NP_NAME, &Record);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return WN_NO_NETWORK;
|
||||
|
||||
RegSize = sizeof Credentials;
|
||||
Credentials = 0; /* default is NO credentials */
|
||||
NpResult = RegGetValueW(RegKey, ClassNameBuf, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||
&Credentials, &RegSize);
|
||||
if (ERROR_SUCCESS != NpResult && ERROR_FILE_NOT_FOUND != NpResult)
|
||||
goto exit;
|
||||
|
||||
switch (Credentials)
|
||||
switch (Record->Credentials)
|
||||
{
|
||||
case FSP_NP_CREDENTIALS_NONE:
|
||||
case FSP_NP_CREDENTIALS_PASSWORD:
|
||||
case FSP_NP_CREDENTIALS_USERPASS:
|
||||
*PCredentialsKind = Credentials;
|
||||
*PCredentialsKind = Record->Credentials;
|
||||
break;
|
||||
}
|
||||
|
||||
NpResult = ERROR_SUCCESS;
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return NpResult;
|
||||
return WN_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD FspNpGetCredentials(
|
||||
@ -433,7 +396,7 @@ DWORD APIENTRY NPGetConnection(
|
||||
|
||||
Result = FspNpGetVolumeList(&VolumeListBuf, &VolumeListSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return WN_OUT_OF_MEMORY;
|
||||
return WN_NOT_CONNECTED;
|
||||
|
||||
NpResult = WN_NOT_CONNECTED;
|
||||
for (P = VolumeListBuf, VolumeListBufEnd = (PVOID)((PUINT8)P + VolumeListSize), VolumeName = P;
|
||||
@ -496,9 +459,10 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
WCHAR LocalNameBuf[3];
|
||||
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||
ULONG ClassNameLen, InstanceNameLen;
|
||||
WCHAR LocalUserName[UNLEN + 1];
|
||||
DWORD CredentialsKind;
|
||||
PWSTR PipeBuf = 0;
|
||||
ULONG Argc;
|
||||
PWSTR Argv[6];
|
||||
ULONG Argl[6];
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
PCREDENTIALW Credential = 0;
|
||||
#endif
|
||||
@ -525,10 +489,9 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
return WN_ALREADY_CONNECTED;
|
||||
}
|
||||
|
||||
if (!FspNpGetLocalUserName(LocalUserName, sizeof LocalUserName / sizeof LocalUserName[0]))
|
||||
LocalUserName[0] = L'\0';
|
||||
|
||||
FspNpGetCredentialsKind(lpRemoteName, &CredentialsKind);
|
||||
NpResult = FspNpGetRemoteInfo(lpRemoteName, &CredentialsKind);
|
||||
if (WN_SUCCESS != NpResult)
|
||||
return NpResult;
|
||||
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
/* if we need credentials and none were passed check with the credential manager */
|
||||
@ -567,33 +530,23 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
}
|
||||
}
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
NpResult = WN_OUT_OF_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* we do not explicitly check, but assumption is it all fits in LAUNCHER_PIPE_BUFFER_SIZE */
|
||||
P = PipeBuf;
|
||||
*P++ = FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
|
||||
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
||||
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
||||
lstrcpyW(P, LocalUserName); P += lstrlenW(LocalUserName) + 1;
|
||||
Argc = 0;
|
||||
Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
Argv[Argc] = RemoteName; Argl[Argc] = -1; Argc++;
|
||||
Argv[Argc] = LocalNameBuf; Argl[Argc] = -1; Argc++;
|
||||
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
|
||||
{
|
||||
lstrcpyW(P, lpUserName); P += lstrlenW(lpUserName) + 1;
|
||||
Argv[Argc] = lpUserName; Argl[Argc] = -1; Argc++;
|
||||
}
|
||||
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind)
|
||||
{
|
||||
lstrcpyW(P, lpPassword); P += lstrlenW(lpPassword) + 1;
|
||||
Argv[Argc] = lpPassword; Argl[Argc] = -1; Argc++;
|
||||
}
|
||||
|
||||
NpResult = FspNpCallLauncherPipe(
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
FSP_NP_CREDENTIALS_NONE != CredentialsKind ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||
Argc, Argv, Argl, 0, 0);
|
||||
switch (NpResult)
|
||||
{
|
||||
case WN_SUCCESS:
|
||||
@ -639,13 +592,13 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
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';
|
||||
Argc = 0;
|
||||
Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
|
||||
if (WN_SUCCESS != FspNpCallLauncherPipe(
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE))
|
||||
FspLaunchCmdGetInfo,
|
||||
Argc, Argv, Argl, 0, 0))
|
||||
{
|
||||
/* looks like the file system is gone! */
|
||||
NpResult = WN_NO_NETWORK;
|
||||
@ -689,8 +642,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
}
|
||||
|
||||
exit:
|
||||
MemFree(PipeBuf);
|
||||
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
if (0 != Credential)
|
||||
CredFree(Credential);
|
||||
@ -724,7 +675,9 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
||||
return NpResult;
|
||||
}
|
||||
|
||||
FspNpGetCredentialsKind(RemoteName, &CredentialsKind);
|
||||
NpResult = FspNpGetRemoteInfo(RemoteName, &CredentialsKind);
|
||||
if (WN_SUCCESS != NpResult)
|
||||
return NpResult;
|
||||
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
||||
return WN_CANCEL;
|
||||
|
||||
@ -779,9 +732,11 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
||||
DWORD NpResult;
|
||||
WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||
DWORD RemoteNameSize;
|
||||
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||
PWSTR ClassName, InstanceName, RemoteName;
|
||||
ULONG ClassNameLen, InstanceNameLen;
|
||||
PWSTR PipeBuf = 0;
|
||||
ULONG Argc;
|
||||
PWSTR Argv[2];
|
||||
ULONG Argl[2];
|
||||
|
||||
if (FspNpCheckLocalName(lpName))
|
||||
{
|
||||
@ -801,17 +756,13 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
||||
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||
return WN_BAD_NETNAME;
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
return WN_OUT_OF_MEMORY;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceStop;
|
||||
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||
Argc = 0;
|
||||
Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
|
||||
NpResult = FspNpCallLauncherPipe(
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
FspLaunchCmdStop,
|
||||
Argc, Argv, Argl, 0, 0);
|
||||
switch (NpResult)
|
||||
{
|
||||
case WN_SUCCESS:
|
||||
@ -824,8 +775,6 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
||||
break;
|
||||
}
|
||||
|
||||
MemFree(PipeBuf);
|
||||
|
||||
return NpResult;
|
||||
}
|
||||
|
||||
@ -1028,7 +977,7 @@ NTSTATUS FspNpRegister(VOID)
|
||||
WCHAR ProviderPath[MAX_PATH];
|
||||
WCHAR RegBuffer[1024];
|
||||
PWSTR P, Part;
|
||||
DWORD RegResult, RegType, RegBufferSize;
|
||||
DWORD RegResult, RegType, RegBufferSize, RegBufferOffset;
|
||||
HKEY RegKey;
|
||||
BOOLEAN FoundProvider;
|
||||
|
||||
@ -1085,6 +1034,13 @@ NTSTATUS FspNpRegister(VOID)
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
RegResult = RegSetValueExW(RegKey,
|
||||
L"DeviceName", 0, REG_SZ,
|
||||
(PVOID)L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME,
|
||||
sizeof L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
RegResult = RegOpenKeyExW(
|
||||
@ -1094,15 +1050,20 @@ NTSTATUS FspNpRegister(VOID)
|
||||
return FspNtStatusFromWin32(RegResult);
|
||||
|
||||
RegBufferSize = sizeof RegBuffer - sizeof L"," FSP_NP_NAME;
|
||||
#ifdef FSP_NP_ORDER_FIRST
|
||||
RegBufferOffset = sizeof "" FSP_NP_NAME;
|
||||
#else
|
||||
RegBufferOffset = 0;
|
||||
#endif
|
||||
RegResult = RegQueryValueExW(RegKey,
|
||||
L"ProviderOrder", 0, &RegType, (PVOID)RegBuffer, &RegBufferSize);
|
||||
L"ProviderOrder", 0, &RegType, (PVOID)&RegBuffer[RegBufferOffset], &RegBufferSize);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
RegBufferSize /= sizeof(WCHAR);
|
||||
|
||||
FoundProvider = FALSE;
|
||||
RegBuffer[RegBufferSize] = L'\0';
|
||||
P = RegBuffer, Part = P;
|
||||
RegBuffer[RegBufferSize + RegBufferOffset] = L'\0';
|
||||
P = &RegBuffer[RegBufferOffset], Part = P;
|
||||
do
|
||||
{
|
||||
if (L',' == *P || '\0' == *P)
|
||||
@ -1119,8 +1080,11 @@ NTSTATUS FspNpRegister(VOID)
|
||||
|
||||
if (!FoundProvider)
|
||||
{
|
||||
P--;
|
||||
memcpy(P, L"," FSP_NP_NAME, sizeof L"," FSP_NP_NAME);
|
||||
#ifdef FSP_NP_ORDER_FIRST
|
||||
memcpy((PWSTR)RegBuffer, L"" FSP_NP_NAME ",", sizeof L"" FSP_NP_NAME);
|
||||
#else
|
||||
memcpy(--P, L"," FSP_NP_NAME, sizeof L"," FSP_NP_NAME);
|
||||
#endif
|
||||
|
||||
RegBufferSize = lstrlenW(RegBuffer);
|
||||
RegBufferSize++;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/ntstatus.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/path.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -14,7 +14,7 @@
|
||||
* [SNAME]
|
||||
* https://www.cygwin.com/cygwin-ug-net/using-specialnames.html
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -453,9 +453,12 @@ FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor(
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = FspPosixMapUidToSid(0x10100, &WorldSid);
|
||||
if (!NT_SUCCESS(Result))
|
||||
WorldSid = FspWksidGet(WinWorldSid);
|
||||
if (0 == WorldSid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
OwnerPerm = (Mode & 0700) >> 6;
|
||||
GroupPerm = (Mode & 0070) >> 3;
|
||||
@ -579,9 +582,6 @@ exit:
|
||||
|
||||
MemFree(Acl);
|
||||
|
||||
if (0 != WorldSid)
|
||||
FspDeleteSid(WorldSid, FspPosixMapUidToSid);
|
||||
|
||||
if (0 != GroupSid)
|
||||
FspDeleteSid(GroupSid, FspPosixMapUidToSid);
|
||||
|
||||
@ -649,13 +649,19 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
||||
|
||||
if (0 != Acl)
|
||||
{
|
||||
Result = FspPosixMapUidToSid(0x10100, &WorldSid);
|
||||
if (!NT_SUCCESS(Result))
|
||||
WorldSid = FspWksidGet(WinWorldSid);
|
||||
if (0 == WorldSid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = FspPosixMapUidToSid(11, &AuthUsersSid);
|
||||
if (!NT_SUCCESS(Result))
|
||||
AuthUsersSid = FspWksidGet(WinAuthenticatedUserSid);
|
||||
if (0 == AuthUsersSid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
OwnerAllow = OwnerDeny = GroupAllow = GroupDeny = WorldAllow = WorldDeny = 0;
|
||||
|
||||
@ -771,12 +777,6 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions(
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != AuthUsersSid)
|
||||
FspDeleteSid(AuthUsersSid, FspPosixMapUidToSid);
|
||||
|
||||
if (0 != WorldSid)
|
||||
FspDeleteSid(WorldSid, FspPosixMapUidToSid);
|
||||
|
||||
return Result;
|
||||
|
||||
lasterror:
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/security.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/service.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -566,6 +566,106 @@ FSP_API BOOLEAN FspServiceIsInteractive(VOID)
|
||||
return IsInteractive;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PSID LocalSystemSid, ServiceSid;
|
||||
BOOLEAN IsLocalSystem = FALSE;
|
||||
BOOL HasServiceSid = FALSE;
|
||||
HANDLE ProcessToken = 0, ImpersonationToken = 0;
|
||||
DWORD SessionId, Size;
|
||||
union
|
||||
{
|
||||
TOKEN_USER V;
|
||||
UINT8 B[128];
|
||||
} UserInfoBuf;
|
||||
PTOKEN_USER UserInfo = &UserInfoBuf.V;
|
||||
|
||||
LocalSystemSid = FspWksidGet(WinLocalSystemSid);
|
||||
ServiceSid = FspWksidGet(WinServiceSid);
|
||||
if (0 == LocalSystemSid || 0 == ServiceSid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 == Token)
|
||||
{
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &ProcessToken) ||
|
||||
!DuplicateToken(ProcessToken, SecurityImpersonation, &ImpersonationToken))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Token = ImpersonationToken;
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(Token, TokenSessionId, &SessionId, sizeof SessionId, &Size))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 != SessionId)
|
||||
{
|
||||
Result = STATUS_ACCESS_DENIED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
IsLocalSystem = EqualSid(LocalSystemSid, UserInfo->User.Sid);
|
||||
if (IsLocalSystem)
|
||||
{
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!CheckTokenMembership(Token, ServiceSid, &HasServiceSid))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = HasServiceSid ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
|
||||
|
||||
exit:
|
||||
if (0 != PIsLocalSystem)
|
||||
*PIsLocalSystem = NT_SUCCESS(Result) ? IsLocalSystem : FALSE;
|
||||
|
||||
if (UserInfo != &UserInfoBuf.V)
|
||||
MemFree(UserInfo);
|
||||
|
||||
if (0 != ImpersonationToken)
|
||||
CloseHandle(ImpersonationToken);
|
||||
|
||||
if (0 != ProcessToken)
|
||||
CloseHandle(ProcessToken);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file dll/util.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -97,26 +97,16 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||
{
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||
PSID OwnerSid, WellKnownSid = 0;
|
||||
DWORD SidSize, LastError;
|
||||
DWORD LastError;
|
||||
|
||||
/* if it is a small number treat it like a well known SID */
|
||||
if (1024 > (INT_PTR)Sid)
|
||||
{
|
||||
SidSize = SECURITY_MAX_SID_SIZE;
|
||||
WellKnownSid = MemAlloc(SidSize);
|
||||
WellKnownSid = FspWksidNew((INT_PTR)Sid, &Result);
|
||||
if (0 == WellKnownSid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto sid_exit;
|
||||
}
|
||||
|
||||
if (!CreateWellKnownSid((INT_PTR)Sid, 0, WellKnownSid, &SidSize))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto sid_exit;
|
||||
}
|
||||
}
|
||||
|
||||
LastError = GetSecurityInfo(Pipe, SE_FILE_OBJECT,
|
||||
OWNER_SECURITY_INFORMATION, &OwnerSid, 0, 0, 0, &SecurityDescriptor);
|
||||
if (0 != LastError)
|
||||
|
108
src/dll/wksid.c
Normal file
108
src/dll/wksid.c
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @file dll/wksid.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
static INIT_ONCE FspWksidInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static PSID FspWksidWorld;
|
||||
static PSID FspWksidAuthenticatedUser;
|
||||
static PSID FspWksidLocalSystem;
|
||||
static PSID FspWksidService;
|
||||
|
||||
static BOOL WINAPI FspWksidInitialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
FspWksidWorld = FspWksidNew(WinWorldSid, 0);
|
||||
FspWksidAuthenticatedUser = FspWksidNew(WinAuthenticatedUserSid, 0);
|
||||
FspWksidLocalSystem = FspWksidNew(WinLocalSystemSid, 0);
|
||||
FspWksidService = FspWksidNew(WinServiceSid, 0);
|
||||
|
||||
//DEBUGLOGSID("FspWksidWorld=%s", FspWksidWorld);
|
||||
//DEBUGLOGSID("FspWksidAuthenticatedUser=%s", FspWksidAuthenticatedUser);
|
||||
//DEBUGLOGSID("FspWksidLocalSystem=%s", FspWksidLocalSystem);
|
||||
//DEBUGLOGSID("FspWksidService=%s", FspWksidService);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID FspWksidFinalize(BOOLEAN Dynamic)
|
||||
{
|
||||
/*
|
||||
* This function is called during DLL_PROCESS_DETACH. We must therefore keep
|
||||
* finalization tasks to a minimum.
|
||||
*
|
||||
* We must deregister our event source (if any). We only do so if the library
|
||||
* is being explicitly unloaded (rather than the process exiting).
|
||||
*/
|
||||
|
||||
if (Dynamic)
|
||||
{
|
||||
MemFree(FspWksidWorld); FspWksidWorld = 0;
|
||||
MemFree(FspWksidAuthenticatedUser); FspWksidAuthenticatedUser = 0;
|
||||
MemFree(FspWksidLocalSystem); FspWksidLocalSystem = 0;
|
||||
MemFree(FspWksidService); FspWksidService = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PSID Sid;
|
||||
DWORD Size;
|
||||
|
||||
Size = SECURITY_MAX_SID_SIZE;
|
||||
Sid = MemAlloc(Size);
|
||||
if (0 == Sid)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!CreateWellKnownSid(WellKnownSidType, 0, Sid, &Size))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
MemFree(Sid); Sid = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != PResult)
|
||||
*PResult = Result;
|
||||
|
||||
return Sid;
|
||||
}
|
||||
|
||||
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspWksidInitOnce, FspWksidInitialize, 0, 0);
|
||||
|
||||
switch (WellKnownSidType)
|
||||
{
|
||||
case WinWorldSid:
|
||||
return FspWksidWorld;
|
||||
case WinAuthenticatedUserSid:
|
||||
return FspWksidAuthenticatedUser;
|
||||
case WinLocalSystemSid:
|
||||
return FspWksidLocalSystem;
|
||||
case WinServiceSid:
|
||||
return FspWksidService;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* dotnet/FileSystemBase+Const.cs
|
||||
*
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* dotnet/FileSystemBase.cs
|
||||
*
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* dotnet/FileSystemHost.cs
|
||||
*
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* dotnet/Interop.cs
|
||||
*
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* dotnet/Service.cs
|
||||
*
|
||||
* Copyright 2015-2017 Bill Zissimopoulos
|
||||
* Copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file fsptool/fsptool.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file launcher/launchctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -15,7 +15,8 @@
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <launcher/launcher.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
|
||||
#define PROGNAME "launchctl"
|
||||
|
||||
@ -67,15 +68,15 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
NTSTATUS Result;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
||||
LastError = FspWin32FromNtStatus(Result);
|
||||
|
||||
if (0 != LastError)
|
||||
warn("KO CallNamedPipe = %ld", LastError);
|
||||
else if (sizeof(WCHAR) > BytesTransferred)
|
||||
warn("KO launcher: empty buffer");
|
||||
else if (LauncherSuccess == PipeBuf[0])
|
||||
else if (FspLaunchCmdSuccess == PipeBuf[0])
|
||||
{
|
||||
if (sizeof(WCHAR) == BytesTransferred)
|
||||
info("OK");
|
||||
@ -100,7 +101,7 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
info("OK\n%S", PipeBuf + 1);
|
||||
}
|
||||
}
|
||||
else if (LauncherFailure == PipeBuf[0])
|
||||
else if (FspLaunchCmdFailure == PipeBuf[0])
|
||||
{
|
||||
if (BytesTransferred < RecvSize)
|
||||
PipeBuf[BytesTransferred / sizeof(WCHAR)] = L'\0';
|
||||
@ -132,7 +133,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||
*P++ = HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||
@ -157,7 +158,7 @@ int stop(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceStop;
|
||||
*P++ = FspLaunchCmdStop;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
|
||||
@ -177,7 +178,7 @@ int getinfo(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceInfo;
|
||||
*P++ = FspLaunchCmdGetInfo;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
|
||||
@ -192,7 +193,7 @@ int list(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceList;
|
||||
*P++ = FspLaunchCmdGetNameList;
|
||||
|
||||
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||
}
|
||||
@ -207,7 +208,7 @@ int quit(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherQuit;
|
||||
*P++ = FspLaunchCmdQuit;
|
||||
|
||||
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||
}
|
||||
@ -217,7 +218,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
PWSTR PipeBuf = 0;
|
||||
|
||||
/* allocate our PipeBuf early on; freed on process exit by the system */
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
return ERROR_NO_SYSTEM_RESOURCES;
|
||||
|
||||
@ -232,7 +233,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 > argc || argc > 12)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
return start(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
@ -241,7 +242,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (4 > argc || argc > 13)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
return start(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
@ -250,7 +251,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 != argc)
|
||||
usage();
|
||||
|
||||
return stop(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
return stop(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"info", argv[0]))
|
||||
@ -258,7 +259,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 != argc)
|
||||
usage();
|
||||
|
||||
return getinfo(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
return getinfo(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"list", argv[0]))
|
||||
@ -266,7 +267,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
return list(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
return list(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"quit", argv[0]))
|
||||
@ -275,7 +276,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
usage();
|
||||
|
||||
/* works only against DEBUG version of launcher */
|
||||
return quit(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
return quit(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file launcher/launcher.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -15,18 +15,32 @@
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <launcher/launcher.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
#include <aclapi.h>
|
||||
#include <sddl.h>
|
||||
#include <userenv.h>
|
||||
|
||||
#define PROGNAME "WinFsp.Launcher"
|
||||
|
||||
BOOL CreateOverlappedPipe(
|
||||
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
||||
static NTSTATUS (NTAPI *SvcNtOpenSymbolicLinkObject)(
|
||||
PHANDLE LinkHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes);
|
||||
static NTSTATUS (NTAPI *SvcNtClose)(
|
||||
HANDLE Handle);
|
||||
|
||||
static BOOL CreateOverlappedPipe(
|
||||
PHANDLE PReadPipe, PHANDLE PWritePipe,
|
||||
DWORD Size,
|
||||
BOOL ReadInherit, BOOL WriteInherit,
|
||||
DWORD ReadMode, DWORD WriteMode)
|
||||
{
|
||||
RPC_STATUS RpcStatus;
|
||||
UUID Uuid;
|
||||
WCHAR PipeNameBuf[MAX_PATH];
|
||||
SECURITY_ATTRIBUTES ReadSecurityAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, ReadInherit };
|
||||
SECURITY_ATTRIBUTES WriteSecurityAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, WriteInherit };
|
||||
HANDLE ReadPipe, WritePipe;
|
||||
DWORD LastError;
|
||||
|
||||
@ -46,13 +60,13 @@ BOOL CreateOverlappedPipe(
|
||||
ReadPipe = CreateNamedPipeW(PipeNameBuf,
|
||||
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | ReadMode,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1, Size, Size, 120 * 1000, SecurityAttributes);
|
||||
1, Size, Size, 120 * 1000, &ReadSecurityAttributes);
|
||||
if (INVALID_HANDLE_VALUE == ReadPipe)
|
||||
return FALSE;
|
||||
|
||||
WritePipe = CreateFileW(PipeNameBuf,
|
||||
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
SecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||
&WriteSecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||
if (INVALID_HANDLE_VALUE == WritePipe)
|
||||
{
|
||||
LastError = GetLastError();
|
||||
@ -67,6 +81,279 @@ BOOL CreateOverlappedPipe(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS GetTokenUserName(HANDLE Token, PWSTR *PUserName)
|
||||
{
|
||||
union
|
||||
{
|
||||
TOKEN_USER V;
|
||||
UINT8 B[128];
|
||||
} UserInfoBuf;
|
||||
PTOKEN_USER UserInfo = &UserInfoBuf.V;
|
||||
WCHAR Name[256], Domn[256];
|
||||
DWORD UserSize, NameSize, DomnSize;
|
||||
SID_NAME_USE Use;
|
||||
PWSTR P;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PUserName = 0;
|
||||
|
||||
if (!GetTokenInformation(Token, TokenUser, UserInfo, sizeof UserInfoBuf, &UserSize))
|
||||
{
|
||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
UserInfo = MemAlloc(UserSize);
|
||||
if (0 == UserInfo)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(Token, TokenUser, UserInfo, UserSize, &UserSize))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
NameSize = sizeof Name / sizeof Name[0];
|
||||
DomnSize = sizeof Domn / sizeof Domn[0];
|
||||
if (!LookupAccountSidW(0, UserInfo->User.Sid, Name, &NameSize, Domn, &DomnSize, &Use))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
NameSize = lstrlenW(Name);
|
||||
DomnSize = lstrlenW(Domn);
|
||||
|
||||
P = *PUserName = MemAlloc((DomnSize + 1 + NameSize + 1) * sizeof(WCHAR));
|
||||
if (0 == P)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 < DomnSize)
|
||||
{
|
||||
memcpy(P, Domn, DomnSize * sizeof(WCHAR));
|
||||
P[DomnSize] = L'\\';
|
||||
P += DomnSize + 1;
|
||||
}
|
||||
memcpy(P, Name, NameSize * sizeof(WCHAR));
|
||||
P[NameSize] = L'\0';
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (UserInfo != &UserInfoBuf.V)
|
||||
MemFree(UserInfo);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS AddAccessForTokenUser(HANDLE Handle, DWORD Access, HANDLE Token)
|
||||
{
|
||||
union
|
||||
{
|
||||
TOKEN_USER V;
|
||||
UINT8 B[128];
|
||||
} UserInfoBuf;
|
||||
PTOKEN_USER UserInfo = &UserInfoBuf.V;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||
PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
|
||||
EXPLICIT_ACCESSW AccessEntry;
|
||||
DWORD Size, LastError;
|
||||
NTSTATUS Result;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, 0, 0, &Size))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
SecurityDescriptor = MemAlloc(Size);
|
||||
if (0 == SecurityDescriptor)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!GetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
AccessEntry.grfAccessPermissions = Access;
|
||||
AccessEntry.grfAccessMode = GRANT_ACCESS;
|
||||
AccessEntry.grfInheritance = NO_INHERITANCE;
|
||||
AccessEntry.Trustee.pMultipleTrustee = 0;
|
||||
AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||
AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||
AccessEntry.Trustee.ptstrName = UserInfo->User.Sid;
|
||||
|
||||
LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor,
|
||||
&Size, &NewSecurityDescriptor);
|
||||
if (0 != LastError)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(LastError);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!SetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, NewSecurityDescriptor))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
LocalFree(NewSecurityDescriptor);
|
||||
MemFree(SecurityDescriptor);
|
||||
if (UserInfo != &UserInfoBuf.V)
|
||||
MemFree(UserInfo);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static BOOL LogonCreateProcess(
|
||||
PWSTR UserName,
|
||||
LPCWSTR ApplicationName,
|
||||
LPWSTR CommandLine,
|
||||
LPSECURITY_ATTRIBUTES ProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES ThreadAttributes,
|
||||
BOOL InheritHandles,
|
||||
DWORD CreationFlags,
|
||||
LPVOID Environment,
|
||||
LPCWSTR CurrentDirectory,
|
||||
LPSTARTUPINFOW StartupInfo,
|
||||
LPPROCESS_INFORMATION ProcessInformation)
|
||||
{
|
||||
PWSTR DomainName = 0;
|
||||
|
||||
if (0 != UserName)
|
||||
{
|
||||
if (0 == invariant_wcsicmp(UserName, L"LocalSystem"))
|
||||
UserName = 0;
|
||||
else
|
||||
if (0 == invariant_wcsicmp(UserName, L"LocalService") ||
|
||||
0 == invariant_wcsicmp(UserName, L"NetworkService"))
|
||||
DomainName = L"NT AUTHORITY";
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == UserName)
|
||||
/* without a user name go ahead and call CreateProcessW */
|
||||
return CreateProcessW(
|
||||
ApplicationName,
|
||||
CommandLine,
|
||||
ProcessAttributes,
|
||||
ThreadAttributes,
|
||||
InheritHandles,
|
||||
CreationFlags,
|
||||
Environment,
|
||||
CurrentDirectory,
|
||||
StartupInfo,
|
||||
ProcessInformation);
|
||||
|
||||
HANDLE LogonToken = 0;
|
||||
PVOID EnvironmentBlock = 0;
|
||||
DWORD LastError;
|
||||
BOOL Success;
|
||||
|
||||
Success = LogonUserW(
|
||||
UserName,
|
||||
DomainName,
|
||||
0,
|
||||
LOGON32_LOGON_SERVICE,
|
||||
LOGON32_PROVIDER_DEFAULT,
|
||||
&LogonToken);
|
||||
if (!Success)
|
||||
goto exit;
|
||||
|
||||
if (0 == Environment)
|
||||
{
|
||||
Success = CreateEnvironmentBlock(&EnvironmentBlock, LogonToken, FALSE);
|
||||
if (!Success)
|
||||
goto exit;
|
||||
|
||||
CreationFlags |= CREATE_UNICODE_ENVIRONMENT;
|
||||
Environment = EnvironmentBlock;
|
||||
}
|
||||
|
||||
Success = ImpersonateLoggedOnUser(LogonToken);
|
||||
if (!Success)
|
||||
goto exit;
|
||||
|
||||
Success = CreateProcessAsUserW(
|
||||
LogonToken,
|
||||
ApplicationName,
|
||||
CommandLine,
|
||||
ProcessAttributes,
|
||||
ThreadAttributes,
|
||||
InheritHandles,
|
||||
CreationFlags,
|
||||
Environment,
|
||||
CurrentDirectory,
|
||||
StartupInfo,
|
||||
ProcessInformation);
|
||||
|
||||
if (!RevertToSelf())
|
||||
/* should not happen! */
|
||||
ExitProcess(GetLastError());
|
||||
|
||||
exit:
|
||||
if (!Success)
|
||||
LastError = GetLastError();
|
||||
|
||||
if (0 != EnvironmentBlock)
|
||||
DestroyEnvironmentBlock(EnvironmentBlock);
|
||||
if (0 != LogonToken)
|
||||
CloseHandle(LogonToken);
|
||||
|
||||
if (!Success)
|
||||
SetLastError(LastError);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE Process;
|
||||
@ -75,7 +362,7 @@ typedef struct
|
||||
|
||||
static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout);
|
||||
|
||||
VOID KillProcess(ULONG ProcessId, HANDLE Process, ULONG Timeout)
|
||||
static VOID KillProcess(ULONG ProcessId, HANDLE Process, ULONG Timeout)
|
||||
{
|
||||
if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, ProcessId))
|
||||
{
|
||||
@ -124,6 +411,11 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
||||
MemFree(KillProcessData);
|
||||
}
|
||||
|
||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT (2 * 15000 + 1000)
|
||||
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LONG RefCount;
|
||||
@ -142,6 +434,17 @@ typedef struct
|
||||
static CRITICAL_SECTION SvcInstanceLock;
|
||||
static HANDLE SvcInstanceEvent;
|
||||
static LIST_ENTRY SvcInstanceList = { &SvcInstanceList, &SvcInstanceList };
|
||||
static DWORD SvcInstanceTlsKey = TLS_OUT_OF_INDEXES;
|
||||
|
||||
static inline PWSTR SvcInstanceUserName(VOID)
|
||||
{
|
||||
return TlsGetValue(SvcInstanceTlsKey);
|
||||
}
|
||||
|
||||
static inline VOID SvcInstanceSetUserName(PWSTR UserName)
|
||||
{
|
||||
TlsSetValue(SvcInstanceTlsKey, UserName);
|
||||
}
|
||||
|
||||
static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout);
|
||||
|
||||
@ -210,6 +513,14 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
||||
else
|
||||
Length += SvcInstanceArgumentLength(EmptyArg);
|
||||
}
|
||||
else
|
||||
if (L'U' == *P)
|
||||
{
|
||||
if (0 != SvcInstanceUserName())
|
||||
Length += SvcInstanceArgumentLength(SvcInstanceUserName());
|
||||
else
|
||||
Length += SvcInstanceArgumentLength(EmptyArg);
|
||||
}
|
||||
else
|
||||
Length++;
|
||||
break;
|
||||
@ -236,6 +547,14 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
||||
else
|
||||
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
||||
}
|
||||
else
|
||||
if (L'U' == *P)
|
||||
{
|
||||
if (0 != SvcInstanceUserName())
|
||||
Q = SvcInstanceArgumentCopy(Q, SvcInstanceUserName());
|
||||
else
|
||||
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
||||
}
|
||||
else
|
||||
*Q++ = *P;
|
||||
break;
|
||||
@ -251,6 +570,67 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS SvcInstanceAddUserRights(HANDLE Token,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR *PNewSecurityDescriptor)
|
||||
{
|
||||
PSECURITY_DESCRIPTOR NewSecurityDescriptor;
|
||||
TOKEN_USER *User = 0;
|
||||
EXPLICIT_ACCESSW AccessEntry;
|
||||
DWORD Size, LastError;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PNewSecurityDescriptor = 0;
|
||||
|
||||
if (GetTokenInformation(Token, TokenUser, 0, 0, &Size))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
User = MemAlloc(Size);
|
||||
if (0 == User)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(Token, TokenUser, User, Size, &Size))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
AccessEntry.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_STOP;
|
||||
AccessEntry.grfAccessMode = GRANT_ACCESS;
|
||||
AccessEntry.grfInheritance = NO_INHERITANCE;
|
||||
AccessEntry.Trustee.pMultipleTrustee = 0;
|
||||
AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||
AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||
AccessEntry.Trustee.ptstrName = User->User.Sid;
|
||||
|
||||
LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor,
|
||||
&Size, &NewSecurityDescriptor);
|
||||
if (0 != LastError)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(LastError);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*PNewSecurityDescriptor = NewSecurityDescriptor;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(User);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
@ -279,18 +659,35 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||
static NTSTATUS SvcInstanceCreateProcess(PWSTR UserName,
|
||||
PWSTR Executable, PWSTR CommandLine, PWSTR WorkDirectory,
|
||||
HANDLE StdioHandles[2],
|
||||
PPROCESS_INFORMATION ProcessInfo)
|
||||
{
|
||||
WCHAR WorkDirectoryBuf[MAX_PATH];
|
||||
STARTUPINFOEXW StartupInfoEx;
|
||||
HANDLE ChildHandles[3] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0/* DO NOT CLOSE!*/ };
|
||||
HANDLE ParentHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
||||
SECURITY_ATTRIBUTES PipeAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
|
||||
PPROC_THREAD_ATTRIBUTE_LIST AttrList = 0;
|
||||
SIZE_T Size;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 != WorkDirectory && L'.' == WorkDirectory[0] && L'\0' == WorkDirectory[1])
|
||||
{
|
||||
PWSTR Backslash = 0, P;
|
||||
|
||||
if (0 == GetModuleFileNameW(0, WorkDirectoryBuf, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
for (P = WorkDirectoryBuf; *P; P++)
|
||||
if (L'\\' == *P)
|
||||
Backslash = P;
|
||||
if (0 != Backslash && WorkDirectoryBuf < Backslash && L':' != Backslash[-1])
|
||||
*Backslash = L'\0';
|
||||
|
||||
WorkDirectory = WorkDirectoryBuf;
|
||||
}
|
||||
|
||||
memset(&StartupInfoEx, 0, sizeof StartupInfoEx);
|
||||
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||
|
||||
@ -304,16 +701,16 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||
*/
|
||||
|
||||
/* create stdin read/write ends; make them inheritable */
|
||||
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0], &PipeAttributes, 0,
|
||||
0, 0))
|
||||
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0],
|
||||
0, TRUE, FALSE, 0, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* create stdout read/write ends; make them inheritable */
|
||||
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1], &PipeAttributes, 0,
|
||||
FILE_FLAG_OVERLAPPED, 0))
|
||||
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1],
|
||||
0, FALSE, TRUE, FILE_FLAG_OVERLAPPED, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
@ -357,18 +754,44 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
|
||||
StartupInfoEx.StartupInfo.hStdError = ChildHandles[2];
|
||||
|
||||
if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0,
|
||||
if (!LogonCreateProcess(UserName,
|
||||
Executable, CommandLine, 0, 0, TRUE,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT,
|
||||
0, WorkDirectory,
|
||||
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||
{
|
||||
if (ERROR_NO_SYSTEM_RESOURCES != GetLastError())
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* On Win7 CreateProcessW with EXTENDED_STARTUPINFO_PRESENT
|
||||
* may fail with ERROR_NO_SYSTEM_RESOURCES.
|
||||
*
|
||||
* In that case go ahead and retry with a CreateProcessW with
|
||||
* bInheritHandles==TRUE, but without EXTENDED_STARTUPINFO_PRESENT.
|
||||
* Not ideal, but...
|
||||
*/
|
||||
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||
if (!LogonCreateProcess(UserName,
|
||||
Executable, CommandLine, 0, 0, TRUE,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP,
|
||||
0, WorkDirectory,
|
||||
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CreateProcessW(Executable, CommandLine, 0, 0, FALSE,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0,
|
||||
if (!LogonCreateProcess(UserName,
|
||||
Executable, CommandLine, 0, 0, FALSE,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP,
|
||||
0, WorkDirectory,
|
||||
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
@ -411,10 +834,11 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult, RegSize;
|
||||
DWORD ClassNameSize, InstanceNameSize;
|
||||
WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512];
|
||||
WCHAR Executable[MAX_PATH], CommandLineBuf[512], WorkDirectory[MAX_PATH],
|
||||
SecurityBuf[512], RunAsBuf[64];
|
||||
PWSTR CommandLine, Security;
|
||||
DWORD JobControl, Credentials;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0, NewSecurityDescriptor;
|
||||
PWSTR Argv[10];
|
||||
PROCESS_INFORMATION ProcessInfo;
|
||||
NTSTATUS Result;
|
||||
@ -440,8 +864,8 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" FSP_LAUNCH_REGKEY,
|
||||
0, FSP_LAUNCH_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
@ -488,6 +912,16 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
CommandLine[-1] = L'\0';
|
||||
CommandLine = CommandLineBuf;
|
||||
|
||||
RegSize = sizeof WorkDirectory;
|
||||
WorkDirectory[0] = L'\0';
|
||||
RegResult = RegGetValueW(RegKey, ClassName, L"WorkDirectory", RRF_RT_REG_SZ, 0,
|
||||
WorkDirectory, &RegSize);
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Security = SecurityBuf + lstrlenW(SecurityBuf);
|
||||
RegSize = (DWORD)(sizeof SecurityBuf - (Security - SecurityBuf) * sizeof(WCHAR));
|
||||
RegResult = RegGetValueW(RegKey, ClassName, L"Security", RRF_RT_REG_SZ, 0,
|
||||
@ -498,6 +932,16 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RegSize = sizeof RunAsBuf;
|
||||
RunAsBuf[0] = L'\0';
|
||||
RegResult = RegGetValueW(RegKey, ClassName, L"RunAs", RRF_RT_REG_SZ, 0,
|
||||
RunAsBuf, &RegSize);
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RegSize = sizeof JobControl;
|
||||
JobControl = 1; /* default is YES! */
|
||||
RegResult = RegGetValueW(RegKey, ClassName, L"JobControl", RRF_RT_REG_DWORD, 0,
|
||||
@ -512,7 +956,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
RegKey = 0;
|
||||
|
||||
if (L'\0' == Security[0])
|
||||
lstrcpyW(Security, L"" SVC_INSTANCE_DEFAULT_SDDL);
|
||||
lstrcpyW(Security, L"" FSP_LAUNCH_SERVICE_DEFAULT_SDDL);
|
||||
if (L'D' == Security[0] && L':' == Security[1])
|
||||
Security = SecurityBuf;
|
||||
|
||||
@ -529,6 +973,14 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = SvcInstanceAddUserRights(ClientToken, SecurityDescriptor, &NewSecurityDescriptor);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
LocalFree(SecurityDescriptor);
|
||||
SecurityDescriptor = NewSecurityDescriptor;
|
||||
|
||||
//FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor);
|
||||
|
||||
ClassNameSize = (lstrlenW(ClassName) + 1) * sizeof(WCHAR);
|
||||
InstanceNameSize = (lstrlenW(InstanceName) + 1) * sizeof(WCHAR);
|
||||
|
||||
@ -553,7 +1005,8 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = SvcInstanceCreateProcess(Executable, SvcInstance->CommandLine,
|
||||
Result = SvcInstanceCreateProcess(L'\0' != RunAsBuf[0] ? RunAsBuf : 0,
|
||||
Executable, SvcInstance->CommandLine, L'\0' != WorkDirectory[0] ? WorkDirectory : 0,
|
||||
RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
@ -624,6 +1077,9 @@ exit:
|
||||
|
||||
LeaveCriticalSection(&SvcInstanceLock);
|
||||
|
||||
FspServiceLog(EVENTLOG_INFORMATION_TYPE,
|
||||
L"create %s\\%s = %lx", ClassName, InstanceName, Result);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -657,6 +1113,9 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout)
|
||||
{
|
||||
SVC_INSTANCE *SvcInstance = Context;
|
||||
|
||||
FspServiceLog(EVENTLOG_INFORMATION_TYPE,
|
||||
L"terminated %s\\%s", SvcInstance->ClassName, SvcInstance->InstanceName);
|
||||
|
||||
SvcInstanceRelease(SvcInstance);
|
||||
}
|
||||
|
||||
@ -752,6 +1211,10 @@ exit:
|
||||
|
||||
SvcInstanceRelease(SvcInstance);
|
||||
|
||||
if (STATUS_TIMEOUT == Result)
|
||||
/* convert to an error! */
|
||||
Result = 0x80070000 | ERROR_TIMEOUT;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -885,6 +1348,53 @@ NTSTATUS SvcInstanceStopAndWaitAll(VOID)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS SvcDefineDosDevice(HANDLE ClientToken,
|
||||
PWSTR DeviceName, PWSTR TargetPath)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
|
||||
if (L'+' != DeviceName[0] && L'-' != DeviceName[0])
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Result = FspServiceContextCheck(ClientToken, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
if (!DefineDosDeviceW(
|
||||
DDD_RAW_TARGET_PATH |
|
||||
(L'+' == DeviceName[0] ? 0 : DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE),
|
||||
DeviceName + 1, TargetPath))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
if (L'+' == DeviceName[0] && 0 != SvcNtOpenSymbolicLinkObject)
|
||||
{
|
||||
/* The drive symlink now exists; add DELETE access to it for the ClientToken. */
|
||||
WCHAR SymlinkBuf[6];
|
||||
UNICODE_STRING Symlink;
|
||||
OBJECT_ATTRIBUTES Obja;
|
||||
HANDLE MountHandle;
|
||||
|
||||
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
||||
SymlinkBuf[4] = DeviceName[1];
|
||||
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 = SvcNtOpenSymbolicLinkObject(&MountHandle, READ_CONTROL | WRITE_DAC, &Obja);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
AddAccessForTokenUser(MountHandle, DELETE, ClientToken);
|
||||
SvcNtClose(MountHandle);
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static HANDLE SvcJob, SvcThread, SvcEvent;
|
||||
static DWORD SvcThreadId;
|
||||
static HANDLE SvcPipe = INVALID_HANDLE_VALUE;
|
||||
@ -908,7 +1418,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
|
||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||
SecurityAttributes.bInheritHandle = FALSE;
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" LAUNCHER_PIPE_SDDL, SDDL_REVISION_1,
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" FSP_LAUNCH_PIPE_SDDL, SDDL_REVISION_1,
|
||||
&SecurityAttributes.lpSecurityDescriptor, 0))
|
||||
goto fail;
|
||||
|
||||
@ -918,6 +1428,10 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 == SvcInstanceEvent)
|
||||
goto fail;
|
||||
|
||||
SvcInstanceTlsKey = TlsAlloc();
|
||||
if (TLS_OUT_OF_INDEXES == SvcInstanceTlsKey)
|
||||
goto fail;
|
||||
|
||||
SvcJob = CreateJobObjectW(0, 0);
|
||||
if (0 != SvcJob)
|
||||
{
|
||||
@ -941,11 +1455,11 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 == SvcOverlapped.hEvent)
|
||||
goto fail;
|
||||
|
||||
SvcPipe = CreateNamedPipeW(L"" LAUNCHER_PIPE_NAME,
|
||||
SvcPipe = CreateNamedPipeW(L"" FSP_LAUNCH_PIPE_NAME,
|
||||
PIPE_ACCESS_DUPLEX |
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||
1, FSP_LAUNCH_PIPE_BUFFER_SIZE, FSP_LAUNCH_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||
&SecurityAttributes);
|
||||
if (INVALID_HANDLE_VALUE == SvcPipe)
|
||||
goto fail;
|
||||
@ -980,6 +1494,9 @@ fail:
|
||||
if (0 != SvcJob)
|
||||
CloseHandle(SvcJob);
|
||||
|
||||
if (TLS_OUT_OF_INDEXES != SvcInstanceTlsKey)
|
||||
TlsFree(SvcInstanceTlsKey);
|
||||
|
||||
if (0 != SvcInstanceEvent)
|
||||
CloseHandle(SvcInstanceEvent);
|
||||
|
||||
@ -1023,6 +1540,9 @@ static NTSTATUS SvcStop(FSP_SERVICE *Service)
|
||||
if (0 != SvcJob)
|
||||
CloseHandle(SvcJob);
|
||||
|
||||
if (TLS_OUT_OF_INDEXES != SvcInstanceTlsKey)
|
||||
TlsFree(SvcInstanceTlsKey);
|
||||
|
||||
if (0 != SvcInstanceEvent)
|
||||
CloseHandle(SvcInstanceEvent);
|
||||
|
||||
@ -1067,7 +1587,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||
HANDLE ClientToken;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
FspServiceSetExitCode(Service, ERROR_NO_SYSTEM_RESOURCES);
|
||||
@ -1090,7 +1610,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||
}
|
||||
|
||||
LastError = SvcPipeWaitResult(
|
||||
ReadFile(SvcPipe, PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||
ReadFile(SvcPipe, PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||
SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
|
||||
if (-1 == LastError)
|
||||
break;
|
||||
@ -1180,11 +1700,11 @@ static inline VOID SvcPipeTransactResult(NTSTATUS Result, PWSTR PipeBuf, PULONG
|
||||
{
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
*PipeBuf = LauncherSuccess;
|
||||
*PipeBuf = FspLaunchCmdSuccess;
|
||||
*PSize += sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
*PSize = (wsprintfW(PipeBuf, L"%c%ld", LauncherFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||
*PSize = (wsprintfW(PipeBuf, L"%c%ld", FspLaunchCmdFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||
sizeof(WCHAR);
|
||||
}
|
||||
|
||||
@ -1194,19 +1714,23 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
return;
|
||||
|
||||
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
||||
PWSTR ClassName, InstanceName;
|
||||
PWSTR ClassName, InstanceName, UserName;
|
||||
PWSTR DeviceName, TargetPath;
|
||||
ULONG Argc; PWSTR Argv[9];
|
||||
BOOLEAN HasSecret = FALSE;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PSize = 0;
|
||||
|
||||
GetTokenUserName(ClientToken, &UserName);
|
||||
SvcInstanceSetUserName(UserName);
|
||||
|
||||
switch (*P++)
|
||||
{
|
||||
case LauncherSvcInstanceStartWithSecret:
|
||||
case FspLaunchCmdStartWithSecret:
|
||||
HasSecret = TRUE;
|
||||
/* fall through! */
|
||||
case LauncherSvcInstanceStart:
|
||||
case FspLaunchCmdStart:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
for (Argc = 0; sizeof Argv / sizeof Argv[0] > Argc; Argc++)
|
||||
@ -1221,7 +1745,7 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceStop:
|
||||
case FspLaunchCmdStop:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
@ -1232,29 +1756,40 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceInfo:
|
||||
case FspLaunchCmdGetInfo:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
if (0 != ClassName && 0 != InstanceName)
|
||||
{
|
||||
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||
*PSize = FSP_LAUNCH_PIPE_BUFFER_SIZE - 1;
|
||||
Result = SvcInstanceGetInfo(ClientToken, ClassName, InstanceName, PipeBuf + 1, PSize);
|
||||
}
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceList:
|
||||
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||
case FspLaunchCmdGetNameList:
|
||||
*PSize = FSP_LAUNCH_PIPE_BUFFER_SIZE - 1;
|
||||
Result = SvcInstanceGetNameList(ClientToken, PipeBuf + 1, PSize);
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case FspLaunchCmdDefineDosDevice:
|
||||
DeviceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
TargetPath = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
if (0 != DeviceName && 0 != TargetPath)
|
||||
Result = SvcDefineDosDevice(ClientToken, DeviceName, TargetPath);
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
case LauncherQuit:
|
||||
case FspLaunchCmdQuit:
|
||||
SetEvent(SvcEvent);
|
||||
|
||||
SvcPipeTransactResult(STATUS_SUCCESS, PipeBuf, PSize);
|
||||
@ -1264,10 +1799,26 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(STATUS_INVALID_PARAMETER, PipeBuf, PSize);
|
||||
break;
|
||||
}
|
||||
|
||||
SvcInstanceSetUserName(0);
|
||||
MemFree(UserName);
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t **argv)
|
||||
{
|
||||
HANDLE Handle = GetModuleHandleW(L"ntdll.dll");
|
||||
if (0 != Handle)
|
||||
{
|
||||
SvcNtOpenSymbolicLinkObject = (PVOID)GetProcAddress(Handle, "NtOpenSymbolicLinkObject");
|
||||
SvcNtClose = (PVOID)GetProcAddress(Handle, "NtClose");
|
||||
|
||||
if (0 == SvcNtOpenSymbolicLinkObject || 0 == SvcNtClose)
|
||||
{
|
||||
SvcNtOpenSymbolicLinkObject = 0;
|
||||
SvcNtClose = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
||||
}
|
||||
|
||||
|
@ -1,71 +0,0 @@
|
||||
/**
|
||||
* @file launcher/launcher.h
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||
#define WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <shared/minimal.h>
|
||||
|
||||
#define LAUNCHER_REGKEY "Software\\WinFsp\\Services"
|
||||
#define LAUNCHER_REGKEY_WOW64 KEY_WOW64_32KEY
|
||||
|
||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||
|
||||
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||
#define LAUNCHER_PIPE_BUFFER_SIZE 4096
|
||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
||||
|
||||
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||
|
||||
/*
|
||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||
* pipe instances.
|
||||
*/
|
||||
#define LAUNCHER_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
|
||||
#define LAUNCHER_PIPE_OWNER ((PSID)WinLocalSystemSid)
|
||||
|
||||
/*
|
||||
* The default service instance SDDL gives full access to LocalSystem and Administrators.
|
||||
* The only possible service instance rights are as follows:
|
||||
* RP SERVICE_START
|
||||
* WP SERVICE_STOP
|
||||
* LC SERVICE_QUERY_STATUS
|
||||
*
|
||||
* To create a service that can be started, stopped or queried by Everyone, you can set
|
||||
* the following SDDL:
|
||||
* D:P(A;;RPWPLC;;;WD)
|
||||
*/
|
||||
#define SVC_INSTANCE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
|
||||
|
||||
enum
|
||||
{
|
||||
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||
LauncherQuit = 'Q', /* DEBUG version only */
|
||||
|
||||
LauncherSuccess = '$',
|
||||
LauncherFailure = '!',
|
||||
};
|
||||
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file shared/minimal.h
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @file sys/callbacks.c
|
||||
* Fast I/O and resource acquisition callbacks.
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/cleanup.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -117,20 +117,19 @@ static NTSTATUS FspFsvolCleanup(
|
||||
Request->Req.Cleanup.SetLastWriteTime = FileModified && !FileDesc->DidSetLastWriteTime;
|
||||
Request->Req.Cleanup.SetChangeTime = (FileModified || FileDesc->DidSetMetadata) &&
|
||||
!FileDesc->DidSetChangeTime;
|
||||
Request->Req.Cleanup.UnlockAll = FsvolDeviceExtension->VolumeParams.UserModeFileLocking &&
|
||||
FsRtlAreThereCurrentOrInProgressFileLocks(&FileNode->FileLock);
|
||||
|
||||
FspFileNodeAcquireExclusive(FileNode, Pgio);
|
||||
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||
|
||||
FspFileNodeCleanupFlush(FileNode, FileObject);
|
||||
|
||||
if (Request->Req.Cleanup.Delete ||
|
||||
Request->Req.Cleanup.SetAllocationSize ||
|
||||
Request->Req.Cleanup.SetArchiveBit ||
|
||||
Request->Req.Cleanup.SetLastWriteTime ||
|
||||
Request->Req.Cleanup.SetChangeTime ||
|
||||
Request->Req.Cleanup.UnlockAll ||
|
||||
!FsvolDeviceExtension->VolumeParams.PostCleanupWhenModifiedOnly)
|
||||
/*
|
||||
* Note that it is still possible for this request to not be delivered,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/close.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/create.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -164,6 +164,8 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
|
||||
FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb;
|
||||
|
||||
FileObject->FsContext2 = FsvolDeviceObject;
|
||||
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/debug.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -281,6 +281,8 @@ const char *DeviceExtensionKindSym(UINT32 Kind)
|
||||
{
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
return "Ctl";
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
return "Mup";
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
return "Vrt";
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/devctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -33,15 +33,7 @@ static NTSTATUS FspFsvolDeviceControl(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_REDIR_QUERY_PATH_EX :
|
||||
Result = FspVolumeRedirQueryPathEx(DeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolDeviceControlComplete(
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/device.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -63,6 +63,8 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I
|
||||
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
||||
VOID FspDeviceDeleteList(
|
||||
@ -94,6 +96,8 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
||||
#pragma alloc_text(PAGE, FspDeviceDeleteList)
|
||||
#pragma alloc_text(PAGE, FspDeviceDeleteAll)
|
||||
@ -118,6 +122,9 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION);
|
||||
@ -173,6 +180,9 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
Result = FspFsvolDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
Result = FspFsmupDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
Result = STATUS_SUCCESS;
|
||||
@ -199,6 +209,9 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
FspFsvolDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
FspFsmupDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
break;
|
||||
@ -333,7 +346,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneIoq = 1;
|
||||
|
||||
/* create our security meta cache */
|
||||
SecurityTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
SecurityTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.SecurityTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceSecurityCacheCapacity, FspFsvolDeviceSecurityCacheItemSizeMax, &SecurityTimeout,
|
||||
@ -343,7 +356,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneSec = 1;
|
||||
|
||||
/* create our directory meta cache */
|
||||
DirInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
DirInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.DirInfoTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceDirInfoCacheCapacity, FspFsvolDeviceDirInfoCacheItemSizeMax, &DirInfoTimeout,
|
||||
@ -353,7 +366,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneDir = 1;
|
||||
|
||||
/* create our stream info meta cache */
|
||||
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.StreamInfoTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceStreamInfoCacheCapacity, FspFsvolDeviceStreamInfoCacheItemSizeMax, &StreamInfoTimeout,
|
||||
@ -860,7 +873,7 @@ VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VO
|
||||
KeAcquireSpinLock(&FsvolDeviceExtension->InfoSpinLock, &Irql);
|
||||
FsvolDeviceExtension->VolumeInfo = VolumeInfoNp;
|
||||
FsvolDeviceExtension->InfoExpirationTime = FspExpirationTimeFromMillis(
|
||||
FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
FsvolDeviceExtension->VolumeParams.VolumeInfoTimeout);
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
@ -876,6 +889,39 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||
|
||||
/* initialize our prefix table */
|
||||
ExInitializeResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
RtlInitializeUnicodePrefix(&FsmupDeviceExtension->PrefixTable);
|
||||
RtlInitializeUnicodePrefix(&FsmupDeviceExtension->ClassTable);
|
||||
FsmupDeviceExtension->InitDonePfxTab = 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||
|
||||
if (FsmupDeviceExtension->InitDonePfxTab)
|
||||
{
|
||||
/*
|
||||
* Normally we would have to finalize our prefix table. This is not necessary as all
|
||||
* prefixes will be gone if this code ever gets reached.
|
||||
*/
|
||||
ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->PrefixTable, TRUE));
|
||||
ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->ClassTable, TRUE));
|
||||
ExDeleteResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/dirctl.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -551,7 +551,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR);
|
||||
QueryDirectoryLengthMin = FSP_FSCTL_ALIGN_UP(QueryDirectoryLengthMin, 8);
|
||||
ASSERT(QueryDirectoryLengthMin < FspFsvolQueryDirectoryLengthMax);
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout &&
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.DirInfoTimeout &&
|
||||
0 == FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
if (PatternIsFileName)
|
||||
@ -611,7 +611,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
||||
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
ASSERT(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR) >=
|
||||
FileDesc->DirectoryMarker.Length);
|
||||
|
||||
Request->Req.QueryDirectory.Marker.Offset =
|
||||
@ -921,7 +921,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
ASSERT(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR) >=
|
||||
FileDesc->DirectoryMarker.Length);
|
||||
|
||||
Request->Req.QueryDirectory.Marker.Offset =
|
||||
|
116
src/sys/driver.c
116
src/sys/driver.c
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/driver.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -44,45 +44,6 @@ NTSTATUS DriverEntry(
|
||||
{
|
||||
FSP_ENTER_DRV();
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
FSP_RETURN();
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
|
||||
/* create the file system control device objects */
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
/* setup the driver object */
|
||||
#if defined(FSP_UNLOAD)
|
||||
DriverObject->DriverUnload = FspUnload;
|
||||
@ -127,8 +88,6 @@ NTSTATUS DriverEntry(
|
||||
FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspFsvolShutdownComplete;
|
||||
FspFileNodeCompleteLockIrp = FspFsvolLockControlForward;
|
||||
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
||||
@ -170,9 +129,58 @@ NTSTATUS DriverEntry(
|
||||
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
|
||||
DriverObject->FastIoDispatch = &FspFastIoDispatch;
|
||||
|
||||
BOOLEAN InitDoneGRes = FALSE, InitDonePsBuf = FALSE;
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
InitDoneGRes = TRUE;
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
InitDonePsBuf = TRUE;
|
||||
|
||||
/* create the file system control device objects */
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
||||
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
||||
&FspFsmupDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsmupDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
Result = FsRtlRegisterUncProviderEx(&FspMupHandle,
|
||||
&DeviceName, FspFsmupDeviceObject, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Register our "disk" device as a file system. We do not register our "net" device
|
||||
* as a file system, but we register with the MUP instead at a later time.
|
||||
* as a file system; we register with the MUP instead.
|
||||
*
|
||||
* Please note that the call below makes our driver unloadable. In fact the driver
|
||||
* remains unloadable even if we issue an IoUnregisterFileSystem() call immediately
|
||||
@ -181,6 +189,23 @@ NTSTATUS DriverEntry(
|
||||
*/
|
||||
IoRegisterFileSystem(FspFsctlDiskDeviceObject);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != FspFsmupDeviceObject)
|
||||
FspDeviceDelete(FspFsmupDeviceObject);
|
||||
if (0 != FspFsctlNetDeviceObject)
|
||||
FspDeviceDelete(FspFsctlNetDeviceObject);
|
||||
if (0 != FspFsctlDiskDeviceObject)
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
if (InitDonePsBuf)
|
||||
FspProcessBufferFinalize();
|
||||
if (InitDoneGRes)
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
}
|
||||
|
||||
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
|
||||
FSP_LEAVE_DRV("DriverName=\"%wZ\", RegistryPath=\"%wZ\"",
|
||||
&DriverObject->DriverName, RegistryPath);
|
||||
@ -212,8 +237,11 @@ VOID FspUnload(
|
||||
{
|
||||
FSP_ENTER_VOID(PAGED_CODE());
|
||||
|
||||
FsRtlDeregisterUncProvider(FspMupHandle);
|
||||
|
||||
FspFsctlDiskDeviceObject = 0;
|
||||
FspFsctlNetDeviceObject = 0;
|
||||
FspFsmupDeviceObject = 0;
|
||||
//FspDeviceDeleteAll();
|
||||
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
@ -230,6 +258,8 @@ VOID FspUnload(
|
||||
PDRIVER_OBJECT FspDriverObject;
|
||||
PDEVICE_OBJECT FspFsctlDiskDeviceObject;
|
||||
PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
PDEVICE_OBJECT FspFsmupDeviceObject;
|
||||
HANDLE FspMupHandle;
|
||||
FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/driver.h
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -180,6 +180,8 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result);
|
||||
#define FSP_LEAVE_DRV(fmt, ...) \
|
||||
FSP_LEAVE_(FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, NtStatusSym(Result))); return Result
|
||||
#define FSP_ENTER_MJ(...) \
|
||||
if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\
|
||||
return FspMupHandleIrp(DeviceObject, Irp);\
|
||||
NTSTATUS Result = STATUS_SUCCESS; \
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\
|
||||
BOOLEAN fsp_device_deref = FALSE; \
|
||||
@ -316,7 +318,6 @@ FSP_IOPREP_DISPATCH FspFsvolDirectoryControlPrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolDirectoryControlComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolFlushBuffersComplete;
|
||||
NTSTATUS FspFsvolLockControlForward(PVOID Context, PIRP Irp);
|
||||
FSP_IOCMPL_DISPATCH FspFsvolLockControlComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
|
||||
@ -329,7 +330,6 @@ FSP_IOPREP_DISPATCH FspFsvolSetInformationPrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||
FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||
|
||||
@ -1008,6 +1008,7 @@ typedef struct
|
||||
enum
|
||||
{
|
||||
FspFsctlDeviceExtensionKind = '\0ltC', /* file system control device (e.g. \Device\WinFsp.Disk) */
|
||||
FspFsmupDeviceExtensionKind = '\0puM', /* our own MUP device (linked to \Device\WinFsp.Mup) */
|
||||
FspFsvrtDeviceExtensionKind = '\0trV', /* virtual volume device (e.g. \Device\Volume{GUID}) */
|
||||
FspFsvolDeviceExtensionKind = '\0loV', /* file system volume device (unnamed) */
|
||||
};
|
||||
@ -1024,11 +1025,12 @@ typedef struct
|
||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
||||
PDEVICE_OBJECT FsctlDeviceObject;
|
||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||
HANDLE MupHandle;
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
PVPB SwapVpb;
|
||||
FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UNICODE_STRING VolumePrefix;
|
||||
UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry;
|
||||
FSP_IOQ *Ioq;
|
||||
FSP_META_CACHE *SecurityCache;
|
||||
FSP_META_CACHE *DirInfoCache;
|
||||
@ -1050,6 +1052,14 @@ typedef struct
|
||||
LIST_ENTRY NotifyList;
|
||||
FSP_STATISTICS *Statistics;
|
||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT32 InitDonePfxTab:1;
|
||||
ERESOURCE PrefixTableResource;
|
||||
UNICODE_PREFIX_TABLE PrefixTable;
|
||||
UNICODE_PREFIX_TABLE ClassTable;
|
||||
} FSP_FSMUP_DEVICE_EXTENSION;
|
||||
static inline
|
||||
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
@ -1061,6 +1071,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
static inline
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FspFsmupDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics,
|
||||
PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid,
|
||||
@ -1157,6 +1173,14 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fsmup */
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||
|
||||
/* volume management */
|
||||
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
||||
NTSTATUS FspVolumeCreate(
|
||||
@ -1165,8 +1189,6 @@ VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -1336,6 +1358,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
@ -1560,12 +1583,13 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
|
||||
extern PDRIVER_OBJECT FspDriverObject;
|
||||
extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
|
||||
extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
extern PDEVICE_OBJECT FspFsmupDeviceObject;
|
||||
extern HANDLE FspMupHandle;
|
||||
extern FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
||||
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
||||
extern ERESOURCE FspDeviceGlobalResource;
|
||||
extern PCOMPLETE_LOCK_IRP_ROUTINE FspFileNodeCompleteLockIrp;
|
||||
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
|
||||
extern const GUID FspMainFileOpenEcpGuid;
|
||||
extern ULONG FspProcessorCount;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/ea.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
113
src/sys/file.c
113
src/sys/file.c
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/file.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
@ -37,6 +37,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
@ -83,6 +84,7 @@ VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||
BOOLEAN InvalidateCaches);
|
||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||
@ -120,6 +122,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
||||
#pragma alloc_text(PAGE, FspFileNodeReleaseOwnerF)
|
||||
#pragma alloc_text(PAGE, FspFileNodeOpen)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCleanup)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCleanupFlush)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
|
||||
#pragma alloc_text(PAGE, FspFileNodeClose)
|
||||
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
|
||||
@ -148,6 +151,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
||||
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
||||
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
||||
#pragma alloc_text(PAGE, FspFileNodeProcessLockIrp)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
||||
#pragma alloc_text(PAGE, FspFileDescCreate)
|
||||
#pragma alloc_text(PAGE, FspFileDescDelete)
|
||||
#pragma alloc_text(PAGE, FspFileDescResetDirectory)
|
||||
@ -770,6 +774,59 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG
|
||||
*PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0;
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||
{
|
||||
/*
|
||||
* Optionally flush the FileNode during Cleanup.
|
||||
*
|
||||
* The FileNode must be acquired exclusive (Full) when calling this function.
|
||||
*/
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
|
||||
if (!FsvolDeviceExtension->VolumeParams.FlushAndPurgeOnCleanup)
|
||||
return; /* nothing to do! */
|
||||
|
||||
BOOLEAN DeletePending, SingleHandle;
|
||||
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
DeletePending = 0 != FileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
|
||||
SingleHandle = 1 == FileNode->HandleCount;
|
||||
|
||||
if (SingleHandle && FileNode->TruncateOnClose)
|
||||
{
|
||||
/*
|
||||
* Even when the FileInfo is expired, this is the best guess for a file size
|
||||
* without asking the user-mode file system.
|
||||
*/
|
||||
TruncateSize = FileNode->Header.FileSize;
|
||||
PTruncateSize = &TruncateSize;
|
||||
}
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
||||
/* Flush and purge on last Cleanup. Keeps files off the "standby" list. (GitHub issue #104) */
|
||||
if (SingleHandle && !DeletePending)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
LARGE_INTEGER ZeroOffset = { 0 };
|
||||
|
||||
if (0 != PTruncateSize && 0 == PTruncateSize->HighPart)
|
||||
FspCcFlushCache(FileObject->SectionObjectPointer, &ZeroOffset, PTruncateSize->LowPart,
|
||||
&IoStatus);
|
||||
else
|
||||
FspCcFlushCache(FileObject->SectionObjectPointer, 0, 0,
|
||||
&IoStatus);
|
||||
}
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||
{
|
||||
/*
|
||||
@ -787,9 +844,9 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN DeletedFromContextTable = FALSE;
|
||||
BOOLEAN DeletePending, DeletedFromContextTable = FALSE, SingleHandle = FALSE;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
@ -814,6 +871,8 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
ASSERT(0 < FileNode->HandleCount);
|
||||
if (0 == --FileNode->HandleCount)
|
||||
{
|
||||
SingleHandle = TRUE;
|
||||
|
||||
DeletePending = 0 != FileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
|
||||
@ -830,7 +889,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
* We now have to deal with the scenario where there are cleaned up,
|
||||
* but unclosed streams for this file still in the context table.
|
||||
*/
|
||||
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.NamedStreams &&
|
||||
if (FsvolDeviceExtension->VolumeParams.NamedStreams &&
|
||||
0 == FileNode->MainFileNode)
|
||||
{
|
||||
BOOLEAN StreamDeletedFromContextTable;
|
||||
@ -867,8 +926,6 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
if (DeletePending || FileNode->TruncateOnClose)
|
||||
{
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
UINT64 AllocationUnit =
|
||||
FsvolDeviceExtension->VolumeParams.SectorSize *
|
||||
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
|
||||
@ -889,6 +946,34 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
||||
/* Flush and purge on last Cleanup. Keeps files off the "standby" list. (GitHub issue #104) */
|
||||
if (SingleHandle && FsvolDeviceExtension->VolumeParams.FlushAndPurgeOnCleanup)
|
||||
{
|
||||
/*
|
||||
* There is an important difference in behavior with respect to DeletePending when
|
||||
* FlushAndPurgeOnCleanup is FALSE vs when it is TRUE.
|
||||
*
|
||||
* With FlushAndPurgeOnCleanup==FALSE (the default), the WinFsp FSD preserves data
|
||||
* and allows a deleted file to have memory-mapped I/O done on it after the CLEANUP
|
||||
* completes. It is up to the user mode file system to decide whether to handle
|
||||
* this scenario or not. The MEMFS reference file system does.
|
||||
*
|
||||
* With FlushAndPurgeOnCleanup==TRUE, the FSD simply purges the cache section (if any),
|
||||
* which means that CACHED DATA WILL BE LOST. This is desirable, because we do not want
|
||||
* to unnecessarily flush data that are soon going to be deleted.
|
||||
*
|
||||
* This could affect a program that does memory-mapped I/O on a deleted file that has
|
||||
* been CloseHandle'd. Tests have shown that even NTFS cannot properly handle this
|
||||
* scenario in all cases (for example, when the file is not cached), so it is unlikely
|
||||
* that there are any useful programs out there that do this.
|
||||
*
|
||||
* So we deem this difference in behavior ok and desirable.
|
||||
*/
|
||||
|
||||
TruncateSize.QuadPart = 0;
|
||||
PTruncateSize = &TruncateSize;
|
||||
}
|
||||
|
||||
CcUninitializeCacheMap(FileObject, PTruncateSize, 0);
|
||||
|
||||
if (DeletedFromContextTable)
|
||||
@ -2028,6 +2113,19 @@ NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp)
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result = Irp->IoStatus.Status;
|
||||
|
||||
DEBUGLOGIRP(Irp, Result);
|
||||
|
||||
FspIopCompleteIrp(Irp, Result);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc)
|
||||
{
|
||||
PAGED_CODE();
|
||||
@ -2151,7 +2249,7 @@ NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||
FspFsvolDeviceExtension(FileDesc->FileNode->FsvolDeviceObject);
|
||||
UNICODE_STRING DirectoryMarker;
|
||||
|
||||
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength < FileName->Length)
|
||||
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR) < FileName->Length)
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
DirectoryMarker.Length = DirectoryMarker.MaximumLength = FileName->Length;
|
||||
@ -2364,7 +2462,6 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp)
|
||||
FspIopCompleteIrp(Irp, Irp->IoStatus.Status);
|
||||
}
|
||||
|
||||
PCOMPLETE_LOCK_IRP_ROUTINE FspFileNodeCompleteLockIrp;
|
||||
WCHAR FspFileDescDirectoryPatternMatchAll[] = L"*";
|
||||
|
||||
// {904862B4-EB3F-461E-ACB2-4DF2B3FC898B}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file sys/fileinfo.c
|
||||
*
|
||||
* @copyright 2015-2017 Bill Zissimopoulos
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user