mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
5005dd6f5b | |||
f9b6fb8817 | |||
6b0b4c8b8e | |||
abb504053b | |||
fb507fc0bc | |||
d38afe8d16 | |||
a4629b8f8b | |||
670a38d549 | |||
b939f6bd2b | |||
3df27f5b28 | |||
7581cece81 | |||
b4f5707e4e | |||
309827860f | |||
2b6b049f86 | |||
77f3e064a2 | |||
f691a7a3c7 | |||
cc58668ce5 | |||
064d0b94f2 | |||
a48668149b |
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
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).
|
||||
- [ ] **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.
|
||||
|
@ -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">
|
||||
|
@ -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">
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<MyCanonicalVersion>1.3</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2018.1 B1</MyProductVersion>
|
||||
<MyProductVersion>2018.1 B2</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" />
|
||||
|
@ -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">
|
||||
|
@ -173,6 +173,7 @@
|
||||
<ClCompile Include="..\..\src\sys\ioq.c" />
|
||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||
<ClCompile Include="..\..\src\sys\mup.c" />
|
||||
<ClCompile Include="..\..\src\sys\name.c" />
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||
<ClCompile Include="..\..\src\sys\read.c" />
|
||||
|
@ -101,6 +101,9 @@
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\mup.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -4,30 +4,37 @@
|
||||
|
||||
[qanda]
|
||||
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed. [@efeat]::
|
||||
I am running Windows 7 and I am finding that the installed driver is not signed.::
|
||||
|
||||
Your Windows 7 OS is missing SHA-2 Code Signing Support. You need to install the following security advisory that will rectify the problem:
|
||||
https://technet.microsoft.com/en-us/library/security/3033929.aspx
|
||||
|
||||
|
||||
Disconnecting (unmapping) a network drive does not work. [@carlreinke]::
|
||||
Disconnecting (unmapping) a network drive does not work.::
|
||||
|
||||
You may have Dokany installed. Dokany installs its own Network Provider DLL that unfortunately interferes with the WinFsp handling of network drives. The solution is to change your system's Network Provider order and ensure that the WinFsp Network Provider runs before the Dokany one. Instructions on how to change the Network Provider order can be found in this http://blogs.interfacett.com/changing-the-network-provider-order-in-windows-10[article].
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories? [@netheril96]::
|
||||
Case-sensitive file systems do not work properly when mounted as a directory.::
|
||||
|
||||
Windows and WinFsp support case-sensitive file systems. These file systems work properly when mounted as a drive. Unfortunately when a file system is mounted as a directory over NTFS, Windows expects it to be case-insensitive and will UPPERCASE many of the file names sent to the file system.
|
||||
+
|
||||
This is an unfortunate but well understood Windows limitation. Case-sensitive file systems should only be mounted as drives.
|
||||
|
||||
|
||||
Why is the DLL not installed in the Windows system directories?::
|
||||
|
||||
It is true that this would make it convenient to load the DLL, because the Windows loader looks into the Windows system directories when it loads DLL's. However, in the opinion of the WinFsp author, software that does not ship with the OS should not be installing components in the system directories.
|
||||
+
|
||||
There are a few alternative methods to overcome this problem. WinFsp recommends marking the WinFsp DLL as "delay load" and then using `FspLoad` to dynamically load the DLL during process initialization. For more information see the WinFsp Tutorial.
|
||||
|
||||
|
||||
Does WinFsp provide debugging symbols? [@netheril96]::
|
||||
Does WinFsp provide debugging symbols?::
|
||||
|
||||
Public debugging symbols are already included in the installer. You need to install the "Developer" feature; the symbols can be found in the `sym` directory under the WinFsp installation directory.
|
||||
|
||||
|
||||
Is there a maximum number of concurrent file systems? [@efeat]::
|
||||
Is there a maximum number of concurrent file systems?::
|
||||
|
||||
WinFsp does not have a hard limit of how many file systems can be created or how many processes can create file systems.
|
||||
+
|
||||
@ -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.
|
||||
|
||||
|
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]
|
@ -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 =
|
||||
|
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
|
@ -1703,133 +1703,6 @@ FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem);
|
||||
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...);
|
||||
FSP_API VOID FspServiceLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||
|
||||
/**
|
||||
* @group Launch Control
|
||||
*/
|
||||
/**
|
||||
* Call launcher pipe.
|
||||
*
|
||||
* This function is used to send a command to the launcher and receive a response.
|
||||
*
|
||||
* @param Command
|
||||
* Launcher command to send. For example, the 'L' launcher command instructs
|
||||
* the launcher to list all running service instances.
|
||||
* @param Argc
|
||||
* Command argument count. May be 0.
|
||||
* @param Argv
|
||||
* Command argument array. May be NULL.
|
||||
* @param Argl
|
||||
* Command argument length array. May be NULL. If this is NULL all command arguments
|
||||
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
|
||||
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError);
|
||||
/**
|
||||
* Start a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to start.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to start.
|
||||
* @param Argc
|
||||
* Service instance argument count. May be 0.
|
||||
* @param Argv
|
||||
* Service instance argument array. May be NULL.
|
||||
* @param HasSecret
|
||||
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
|
||||
* Secrets are passed to service instances through standard input rather than the command
|
||||
* line.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStart(
|
||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
|
||||
BOOLEAN HasSecret,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Stop a service instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchStop(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* Get information about a service instance.
|
||||
*
|
||||
* The information is a list of NULL-terminated strings: the class name of the service instance,
|
||||
* the instance name of the service instance and the full command line used to start the service
|
||||
* instance.
|
||||
*
|
||||
* @param ClassName
|
||||
* Class name of the service instance to stop.
|
||||
* @param InstanceName
|
||||
* Instance name of the service instance to stop.
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
PWSTR ClassName, PWSTR InstanceName,
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
/**
|
||||
* List service instances.
|
||||
*
|
||||
* The information is a list of pairs of NULL-terminated strings. Each pair contains the class
|
||||
* name and instance name of a service instance. All currently running service instances are
|
||||
* listed.
|
||||
*
|
||||
* @param Buffer
|
||||
* Buffer that receives the command response. May be NULL.
|
||||
* @param PSize
|
||||
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
|
||||
* contains the number of bytes transferred. May be NULL.
|
||||
* @param PLauncherError
|
||||
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
|
||||
* @return
|
||||
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
|
||||
* returns an error. Other status codes indicate a communication error. Launcher errors are
|
||||
* reported through PLauncherError.
|
||||
*/
|
||||
FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError);
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
|
@ -207,7 +207,7 @@ static NTSTATUS FspFileSystemLauncherDefineDosDevice(
|
||||
Argv[0] = Argv0;
|
||||
Argv[1] = VolumeName;
|
||||
|
||||
Result = FspLaunchCallLauncherPipe('D', 2, Argv, 0, 0, 0, &ErrorCode);
|
||||
Result = FspLaunchCallLauncherPipe(FspLaunchCmdDefineDosDevice, 2, Argv, 0, 0, 0, &ErrorCode);
|
||||
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
||||
}
|
||||
|
||||
|
329
src/dll/launch.c
329
src/dll/launch.c
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <launcher/launcher.h>
|
||||
|
||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||
@ -27,11 +26,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
NTSTATUS Result;
|
||||
ULONG ErrorCode;
|
||||
|
||||
if (0 != PSize)
|
||||
*PSize = 0;
|
||||
*PLauncherError = 0;
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
@ -44,7 +41,7 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
if (0 != Argv[I])
|
||||
{
|
||||
Length = 0 == Argl || -1 == Argl[I] ? lstrlenW(Argv[I]) : Argl[I];
|
||||
if (LAUNCHER_PIPE_BUFFER_SIZE < ((ULONG)(P - PipeBuf) + Length + 1) * sizeof(WCHAR))
|
||||
if (FSP_LAUNCH_PIPE_BUFFER_SIZE < ((ULONG)(P - PipeBuf) + Length + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
@ -52,9 +49,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
memcpy(P, Argv[I], Length * sizeof(WCHAR)); P += Length; *P++ = L'\0';
|
||||
}
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME,
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME,
|
||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
@ -62,18 +59,18 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
ErrorCode = ERROR_BROKEN_PIPE; /* protocol error! */
|
||||
if (sizeof(WCHAR) <= BytesTransferred)
|
||||
{
|
||||
if (LauncherSuccess == PipeBuf[0])
|
||||
if (FspLaunchCmdSuccess == PipeBuf[0])
|
||||
{
|
||||
ErrorCode = 0;
|
||||
|
||||
if (0 != PSize)
|
||||
{
|
||||
BytesTransferred -= sizeof(WCHAR);
|
||||
memcpy(Buffer, PipeBuf, *PSize < BytesTransferred ? *PSize : BytesTransferred);
|
||||
memcpy(Buffer, PipeBuf + 1, *PSize < BytesTransferred ? *PSize : BytesTransferred);
|
||||
*PSize = BytesTransferred;
|
||||
}
|
||||
}
|
||||
else if (LauncherFailure == PipeBuf[0])
|
||||
else if (FspLaunchCmdFailure == PipeBuf[0])
|
||||
{
|
||||
ErrorCode = 0;
|
||||
|
||||
@ -92,6 +89,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||
*PLauncherError = ErrorCode;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result) && 0 != PSize)
|
||||
*PSize = 0;
|
||||
|
||||
MemFree(PipeBuf);
|
||||
|
||||
return Result;
|
||||
@ -109,10 +109,10 @@ FSP_API NTSTATUS FspLaunchStart(
|
||||
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
memcpy(Argv + 2, Argv, Argc * sizeof(PWSTR));
|
||||
memcpy(Argv + 2, Argv0, Argc * sizeof(PWSTR));
|
||||
|
||||
return FspLaunchCallLauncherPipe(
|
||||
HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart,
|
||||
HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||
Argc + 2, Argv, 0, 0, 0, PLauncherError);
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ FSP_API NTSTATUS FspLaunchStop(
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
|
||||
return FspLaunchCallLauncherPipe(LauncherSvcInstanceStop,
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdStop,
|
||||
2, Argv, 0, 0, 0, PLauncherError);
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ FSP_API NTSTATUS FspLaunchGetInfo(
|
||||
Argv[0] = ClassName;
|
||||
Argv[1] = InstanceName;
|
||||
|
||||
return FspLaunchCallLauncherPipe(LauncherSvcInstanceInfo,
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdGetInfo,
|
||||
2, Argv, 0, Buffer, PSize, PLauncherError);
|
||||
}
|
||||
|
||||
@ -147,6 +147,303 @@ FSP_API NTSTATUS FspLaunchGetNameList(
|
||||
PWSTR Buffer, PULONG PSize,
|
||||
PULONG PLauncherError)
|
||||
{
|
||||
return FspLaunchCallLauncherPipe(LauncherSvcInstanceList,
|
||||
return FspLaunchCallLauncherPipe(FspLaunchCmdGetNameList,
|
||||
0, 0, 0, Buffer, PSize, PLauncherError);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchRegSetRecord(
|
||||
PWSTR ClassName,
|
||||
const FSP_LAUNCH_REG_RECORD *Record)
|
||||
{
|
||||
#define SETFIELD(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
if (0 != Record->FieldName) \
|
||||
{ \
|
||||
RegResult = RegSetValueExW(RegKey,\
|
||||
L"" #FieldName, 0, REG_SZ,\
|
||||
(PVOID)Record->FieldName, (lstrlenW(Record->FieldName) + 1) * sizeof(WCHAR));\
|
||||
if (ERROR_SUCCESS != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegResult = RegDeleteValueW(RegKey,\
|
||||
L"" #FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
} while (0,0)
|
||||
#define SETFIELDI(FieldName, Deflt) \
|
||||
do \
|
||||
{ \
|
||||
if (Deflt != Record->FieldName) \
|
||||
{ \
|
||||
RegResult = RegSetValueExW(RegKey,\
|
||||
L"" #FieldName, 0, REG_DWORD,\
|
||||
(PVOID)&Record->FieldName, sizeof Record->FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RegResult = RegDeleteValueW(RegKey,\
|
||||
L"" #FieldName);\
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
} while (0,0)
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG ClassNameLen;
|
||||
WCHAR RegPath[MAX_PATH];
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult;
|
||||
|
||||
if (0 != Record && 0 == Record->Executable)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ClassNameLen = lstrlenW(ClassName);
|
||||
if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR));
|
||||
RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\';
|
||||
memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR),
|
||||
ClassName, (ClassNameLen + 1) * sizeof(WCHAR));
|
||||
|
||||
if (0 != Record)
|
||||
{
|
||||
RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, RegPath,
|
||||
0, 0, 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_SET_VALUE, 0, &RegKey, 0);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
SETFIELD(Agent);
|
||||
SETFIELD(Executable);
|
||||
SETFIELD(CommandLine);
|
||||
SETFIELD(WorkDirectory);
|
||||
SETFIELD(RunAs);
|
||||
SETFIELD(Security);
|
||||
SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */
|
||||
SETFIELDI(Credentials, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RegResult = RegDeleteKeyEx(HKEY_LOCAL_MACHINE, RegPath,
|
||||
FSP_LAUNCH_REGKEY_WOW64, 0);
|
||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return Result;
|
||||
|
||||
#undef SETFIELD
|
||||
#undef SETFIELDI
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspLaunchRegGetRecord(
|
||||
PWSTR ClassName, PWSTR Agent,
|
||||
FSP_LAUNCH_REG_RECORD **PRecord)
|
||||
{
|
||||
#define GETFIELD(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
RegSize = sizeof RegBuf - RegMark;\
|
||||
RegResult = RegQueryValueEx(RegKey,\
|
||||
L"" #FieldName, 0, &RegType,\
|
||||
(PVOID)(RegBuf + RegMark), &RegSize);\
|
||||
if (ERROR_SUCCESS != RegResult) \
|
||||
{ \
|
||||
if (ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else if (REG_SZ != RegType || \
|
||||
sizeof(WCHAR) > RegSize || \
|
||||
L'\0' != *(PWSTR)(RegBuf + RegMark + RegSize - sizeof(WCHAR)))\
|
||||
{ \
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;\
|
||||
goto exit; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Record->FieldName = (PWSTR)(RegBuf + RegMark);\
|
||||
RegMark += RegSize; \
|
||||
} \
|
||||
} while (0,0)
|
||||
#define GETFIELDI(FieldName) \
|
||||
do \
|
||||
{ \
|
||||
RegSize = sizeof RegDword; \
|
||||
RegResult = RegQueryValueEx(RegKey,\
|
||||
L"" #FieldName, 0, &RegType,\
|
||||
(PVOID)&RegDword, &RegSize);\
|
||||
if (ERROR_SUCCESS != RegResult) \
|
||||
{ \
|
||||
if (ERROR_FILE_NOT_FOUND != RegResult)\
|
||||
{ \
|
||||
Result = FspNtStatusFromWin32(RegResult);\
|
||||
goto exit; \
|
||||
} \
|
||||
} \
|
||||
else if (REG_DWORD != RegType) \
|
||||
{ \
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;\
|
||||
goto exit; \
|
||||
} \
|
||||
else \
|
||||
Record->FieldName = RegDword;\
|
||||
} while (0,0)
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG ClassNameLen;
|
||||
WCHAR RegPath[MAX_PATH];
|
||||
FSP_LAUNCH_REG_RECORD RecordBuf, *Record = &RecordBuf;
|
||||
HKEY RegKey = 0;
|
||||
DWORD RegResult, RegDword, RegType, RegSize, RegMark;
|
||||
UINT8 RegBuf[2 * 1024];
|
||||
PWSTR P, Part;
|
||||
BOOLEAN FoundAgent;
|
||||
|
||||
*PRecord = 0;
|
||||
|
||||
ClassNameLen = lstrlenW(ClassName);
|
||||
if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR));
|
||||
RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\';
|
||||
memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR),
|
||||
ClassName, (ClassNameLen + 1) * sizeof(WCHAR));
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegPath,
|
||||
0, FSP_LAUNCH_REGKEY_WOW64 | KEY_QUERY_VALUE, &RegKey);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Record, 0, sizeof *Record);
|
||||
Record->JobControl = 1; /* default is YES! */
|
||||
RegMark = 0;
|
||||
|
||||
GETFIELD(Agent);
|
||||
if (0 != Agent && L'\0' != Agent[0] &&
|
||||
0 != Record->Agent && L'\0' != Record->Agent[0])
|
||||
{
|
||||
FoundAgent = FALSE;
|
||||
P = Record->Agent, Part = P;
|
||||
do
|
||||
{
|
||||
if (L',' == *P || '\0' == *P)
|
||||
{
|
||||
if (0 == invariant_wcsnicmp(Part, Agent, P - Part))
|
||||
{
|
||||
FoundAgent = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
Part = P + 1;
|
||||
}
|
||||
} while (L'\0' != *P++);
|
||||
|
||||
if (!FoundAgent)
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
GETFIELD(Executable);
|
||||
GETFIELD(CommandLine);
|
||||
GETFIELD(WorkDirectory);
|
||||
GETFIELD(RunAs);
|
||||
GETFIELD(Security);
|
||||
GETFIELDI(JobControl);
|
||||
GETFIELDI(Credentials);
|
||||
|
||||
if (0 == Record->Executable)
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Record = MemAlloc(FIELD_OFFSET(FSP_LAUNCH_REG_RECORD, Buffer) + RegMark);
|
||||
if (0 == Record)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Record, 0, sizeof *Record);
|
||||
memcpy(Record->Buffer, RegBuf, RegMark);
|
||||
Record->Agent = 0 != RecordBuf.Agent ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Agent - RegBuf)) : 0;
|
||||
Record->Executable = 0 != RecordBuf.Executable ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Executable - RegBuf)) : 0;
|
||||
Record->CommandLine = 0 != RecordBuf.CommandLine ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.CommandLine - RegBuf)) : 0;
|
||||
Record->WorkDirectory = 0 != RecordBuf.WorkDirectory ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.WorkDirectory - RegBuf)) : 0;
|
||||
Record->RunAs = 0 != RecordBuf.RunAs ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0;
|
||||
Record->Security = 0 != RecordBuf.Security ?
|
||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0;
|
||||
Record->JobControl = RecordBuf.JobControl;
|
||||
Record->Credentials = RecordBuf.Credentials;
|
||||
|
||||
*PRecord = Record;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return Result;
|
||||
|
||||
#undef GETFIELDI
|
||||
#undef GETFIELD
|
||||
}
|
||||
|
||||
FSP_API VOID FspLaunchRegFreeRecord(
|
||||
FSP_LAUNCH_REG_RECORD *Record)
|
||||
{
|
||||
MemFree(Record);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#define WINFSP_DLL_INTERNAL
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
|
58
src/dll/np.c
58
src/dll/np.c
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <launcher/launcher.h>
|
||||
#include <npapi.h>
|
||||
#include <wincred.h>
|
||||
|
||||
@ -248,14 +247,13 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
{
|
||||
HKEY RegKey = 0;
|
||||
DWORD NpResult, RegSize;
|
||||
DWORD Credentials;
|
||||
PWSTR ClassName, InstanceName;
|
||||
ULONG ClassNameLen, InstanceNameLen;
|
||||
WCHAR ClassNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||
FSP_LAUNCH_REG_RECORD *Record;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
||||
|
||||
@ -268,34 +266,22 @@ static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
||||
ClassNameBuf[ClassNameLen] = '\0';
|
||||
|
||||
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
if (ERROR_SUCCESS != NpResult)
|
||||
goto exit;
|
||||
Result = FspLaunchRegGetRecord(ClassNameBuf, L"" FSP_NP_NAME, &Record);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return WN_NO_NETWORK;
|
||||
|
||||
RegSize = sizeof Credentials;
|
||||
Credentials = 0; /* default is NO credentials */
|
||||
NpResult = RegGetValueW(RegKey, ClassNameBuf, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||
&Credentials, &RegSize);
|
||||
if (ERROR_SUCCESS != NpResult && ERROR_FILE_NOT_FOUND != NpResult)
|
||||
goto exit;
|
||||
|
||||
switch (Credentials)
|
||||
switch (Record->Credentials)
|
||||
{
|
||||
case FSP_NP_CREDENTIALS_NONE:
|
||||
case FSP_NP_CREDENTIALS_PASSWORD:
|
||||
case FSP_NP_CREDENTIALS_USERPASS:
|
||||
*PCredentialsKind = Credentials;
|
||||
*PCredentialsKind = Record->Credentials;
|
||||
break;
|
||||
}
|
||||
|
||||
NpResult = ERROR_SUCCESS;
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
exit:
|
||||
if (0 != RegKey)
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
return NpResult;
|
||||
return WN_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD FspNpGetCredentials(
|
||||
@ -410,7 +396,7 @@ DWORD APIENTRY NPGetConnection(
|
||||
|
||||
Result = FspNpGetVolumeList(&VolumeListBuf, &VolumeListSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return WN_OUT_OF_MEMORY;
|
||||
return WN_NOT_CONNECTED;
|
||||
|
||||
NpResult = WN_NOT_CONNECTED;
|
||||
for (P = VolumeListBuf, VolumeListBufEnd = (PVOID)((PUINT8)P + VolumeListSize), VolumeName = P;
|
||||
@ -503,7 +489,9 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
return WN_ALREADY_CONNECTED;
|
||||
}
|
||||
|
||||
FspNpGetCredentialsKind(lpRemoteName, &CredentialsKind);
|
||||
NpResult = FspNpGetRemoteInfo(lpRemoteName, &CredentialsKind);
|
||||
if (WN_SUCCESS != NpResult)
|
||||
return NpResult;
|
||||
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
/* if we need credentials and none were passed check with the credential manager */
|
||||
@ -557,8 +545,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
}
|
||||
|
||||
NpResult = FspNpCallLauncherPipe(
|
||||
FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
|
||||
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart,
|
||||
FSP_NP_CREDENTIALS_NONE != CredentialsKind ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||
Argc, Argv, Argl, 0, 0);
|
||||
switch (NpResult)
|
||||
{
|
||||
@ -610,7 +597,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
|
||||
if (WN_SUCCESS != FspNpCallLauncherPipe(
|
||||
LauncherSvcInstanceInfo,
|
||||
FspLaunchCmdGetInfo,
|
||||
Argc, Argv, Argl, 0, 0))
|
||||
{
|
||||
/* looks like the file system is gone! */
|
||||
@ -688,7 +675,9 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
||||
return NpResult;
|
||||
}
|
||||
|
||||
FspNpGetCredentialsKind(RemoteName, &CredentialsKind);
|
||||
NpResult = FspNpGetRemoteInfo(RemoteName, &CredentialsKind);
|
||||
if (WN_SUCCESS != NpResult)
|
||||
return NpResult;
|
||||
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
||||
return WN_CANCEL;
|
||||
|
||||
@ -772,7 +761,7 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
||||
Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
|
||||
|
||||
NpResult = FspNpCallLauncherPipe(
|
||||
LauncherSvcInstanceStop,
|
||||
FspLaunchCmdStop,
|
||||
Argc, Argv, Argl, 0, 0);
|
||||
switch (NpResult)
|
||||
{
|
||||
@ -1045,6 +1034,13 @@ NTSTATUS FspNpRegister(VOID)
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
RegResult = RegSetValueExW(RegKey,
|
||||
L"DeviceName", 0, REG_SZ,
|
||||
(PVOID)L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME,
|
||||
sizeof L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
RegCloseKey(RegKey);
|
||||
|
||||
RegResult = RegOpenKeyExW(
|
||||
|
@ -15,7 +15,8 @@
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <launcher/launcher.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
|
||||
#define PROGNAME "launchctl"
|
||||
|
||||
@ -67,15 +68,15 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
NTSTATUS Result;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
||||
LastError = FspWin32FromNtStatus(Result);
|
||||
|
||||
if (0 != LastError)
|
||||
warn("KO CallNamedPipe = %ld", LastError);
|
||||
else if (sizeof(WCHAR) > BytesTransferred)
|
||||
warn("KO launcher: empty buffer");
|
||||
else if (LauncherSuccess == PipeBuf[0])
|
||||
else if (FspLaunchCmdSuccess == PipeBuf[0])
|
||||
{
|
||||
if (sizeof(WCHAR) == BytesTransferred)
|
||||
info("OK");
|
||||
@ -100,7 +101,7 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
info("OK\n%S", PipeBuf + 1);
|
||||
}
|
||||
}
|
||||
else if (LauncherFailure == PipeBuf[0])
|
||||
else if (FspLaunchCmdFailure == PipeBuf[0])
|
||||
{
|
||||
if (BytesTransferred < RecvSize)
|
||||
PipeBuf[BytesTransferred / sizeof(WCHAR)] = L'\0';
|
||||
@ -132,7 +133,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||
*P++ = HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||
@ -157,7 +158,7 @@ int stop(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceStop;
|
||||
*P++ = FspLaunchCmdStop;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
|
||||
@ -177,7 +178,7 @@ int getinfo(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceInfo;
|
||||
*P++ = FspLaunchCmdGetInfo;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
|
||||
@ -192,7 +193,7 @@ int list(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceList;
|
||||
*P++ = FspLaunchCmdGetNameList;
|
||||
|
||||
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||
}
|
||||
@ -207,7 +208,7 @@ int quit(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherQuit;
|
||||
*P++ = FspLaunchCmdQuit;
|
||||
|
||||
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||
}
|
||||
@ -217,7 +218,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
PWSTR PipeBuf = 0;
|
||||
|
||||
/* allocate our PipeBuf early on; freed on process exit by the system */
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
return ERROR_NO_SYSTEM_RESOURCES;
|
||||
|
||||
@ -232,7 +233,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 > argc || argc > 12)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
return start(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
@ -241,7 +242,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (4 > argc || argc > 13)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
return start(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
@ -250,7 +251,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 != argc)
|
||||
usage();
|
||||
|
||||
return stop(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
return stop(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"info", argv[0]))
|
||||
@ -258,7 +259,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (3 != argc)
|
||||
usage();
|
||||
|
||||
return getinfo(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
return getinfo(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"list", argv[0]))
|
||||
@ -266,7 +267,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
return list(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
return list(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"quit", argv[0]))
|
||||
@ -275,7 +276,7 @@ int wmain(int argc, wchar_t **argv)
|
||||
usage();
|
||||
|
||||
/* works only against DEBUG version of launcher */
|
||||
return quit(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
return quit(PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
|
@ -15,7 +15,8 @@
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <launcher/launcher.h>
|
||||
#include <winfsp/launch.h>
|
||||
#include <shared/minimal.h>
|
||||
#include <aclapi.h>
|
||||
#include <sddl.h>
|
||||
#include <userenv.h>
|
||||
@ -410,6 +411,11 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
||||
MemFree(KillProcessData);
|
||||
}
|
||||
|
||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT (2 * 15000 + 1000)
|
||||
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LONG RefCount;
|
||||
@ -858,8 +864,8 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY,
|
||||
0, LAUNCHER_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" FSP_LAUNCH_REGKEY,
|
||||
0, FSP_LAUNCH_REGKEY_WOW64 | KEY_READ, &RegKey);
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(RegResult);
|
||||
@ -950,7 +956,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||
RegKey = 0;
|
||||
|
||||
if (L'\0' == Security[0])
|
||||
lstrcpyW(Security, L"" SVC_INSTANCE_DEFAULT_SDDL);
|
||||
lstrcpyW(Security, L"" FSP_LAUNCH_SERVICE_DEFAULT_SDDL);
|
||||
if (L'D' == Security[0] && L':' == Security[1])
|
||||
Security = SecurityBuf;
|
||||
|
||||
@ -1412,7 +1418,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
|
||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||
SecurityAttributes.bInheritHandle = FALSE;
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" LAUNCHER_PIPE_SDDL, SDDL_REVISION_1,
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" FSP_LAUNCH_PIPE_SDDL, SDDL_REVISION_1,
|
||||
&SecurityAttributes.lpSecurityDescriptor, 0))
|
||||
goto fail;
|
||||
|
||||
@ -1449,11 +1455,11 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 == SvcOverlapped.hEvent)
|
||||
goto fail;
|
||||
|
||||
SvcPipe = CreateNamedPipeW(L"" LAUNCHER_PIPE_NAME,
|
||||
SvcPipe = CreateNamedPipeW(L"" FSP_LAUNCH_PIPE_NAME,
|
||||
PIPE_ACCESS_DUPLEX |
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||
1, FSP_LAUNCH_PIPE_BUFFER_SIZE, FSP_LAUNCH_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||
&SecurityAttributes);
|
||||
if (INVALID_HANDLE_VALUE == SvcPipe)
|
||||
goto fail;
|
||||
@ -1581,7 +1587,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||
HANDLE ClientToken;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||
PipeBuf = MemAlloc(FSP_LAUNCH_PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
{
|
||||
FspServiceSetExitCode(Service, ERROR_NO_SYSTEM_RESOURCES);
|
||||
@ -1604,7 +1610,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||
}
|
||||
|
||||
LastError = SvcPipeWaitResult(
|
||||
ReadFile(SvcPipe, PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||
ReadFile(SvcPipe, PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||
SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
|
||||
if (-1 == LastError)
|
||||
break;
|
||||
@ -1694,11 +1700,11 @@ static inline VOID SvcPipeTransactResult(NTSTATUS Result, PWSTR PipeBuf, PULONG
|
||||
{
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
*PipeBuf = LauncherSuccess;
|
||||
*PipeBuf = FspLaunchCmdSuccess;
|
||||
*PSize += sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
*PSize = (wsprintfW(PipeBuf, L"%c%ld", LauncherFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||
*PSize = (wsprintfW(PipeBuf, L"%c%ld", FspLaunchCmdFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||
sizeof(WCHAR);
|
||||
}
|
||||
|
||||
@ -1721,10 +1727,10 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
|
||||
switch (*P++)
|
||||
{
|
||||
case LauncherSvcInstanceStartWithSecret:
|
||||
case FspLaunchCmdStartWithSecret:
|
||||
HasSecret = TRUE;
|
||||
/* fall through! */
|
||||
case LauncherSvcInstanceStart:
|
||||
case FspLaunchCmdStart:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
for (Argc = 0; sizeof Argv / sizeof Argv[0] > Argc; Argc++)
|
||||
@ -1739,7 +1745,7 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceStop:
|
||||
case FspLaunchCmdStop:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
@ -1750,28 +1756,28 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceInfo:
|
||||
case FspLaunchCmdGetInfo:
|
||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
if (0 != ClassName && 0 != InstanceName)
|
||||
{
|
||||
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||
*PSize = FSP_LAUNCH_PIPE_BUFFER_SIZE - 1;
|
||||
Result = SvcInstanceGetInfo(ClientToken, ClassName, InstanceName, PipeBuf + 1, PSize);
|
||||
}
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherSvcInstanceList:
|
||||
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||
case FspLaunchCmdGetNameList:
|
||||
*PSize = FSP_LAUNCH_PIPE_BUFFER_SIZE - 1;
|
||||
Result = SvcInstanceGetNameList(ClientToken, PipeBuf + 1, PSize);
|
||||
|
||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||
break;
|
||||
|
||||
case LauncherDefineDosDevice:
|
||||
case FspLaunchCmdDefineDosDevice:
|
||||
DeviceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
TargetPath = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||
|
||||
@ -1783,7 +1789,7 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
break;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
case LauncherQuit:
|
||||
case FspLaunchCmdQuit:
|
||||
SetEvent(SvcEvent);
|
||||
|
||||
SvcPipeTransactResult(STATUS_SUCCESS, PipeBuf, PSize);
|
||||
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* @file launcher/launcher.h
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#ifndef WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||
#define WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <shared/minimal.h>
|
||||
|
||||
#define LAUNCHER_REGKEY "Software\\WinFsp\\Services"
|
||||
#define LAUNCHER_REGKEY_WOW64 KEY_WOW64_32KEY
|
||||
|
||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||
|
||||
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||
#define LAUNCHER_PIPE_BUFFER_SIZE 4096
|
||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT (2 * 15000 + 1000)
|
||||
|
||||
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||
|
||||
/*
|
||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||
* pipe instances.
|
||||
*/
|
||||
#define LAUNCHER_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
|
||||
#define LAUNCHER_PIPE_OWNER ((PSID)WinLocalSystemSid)
|
||||
|
||||
/*
|
||||
* The default service instance SDDL gives full access to LocalSystem and Administrators.
|
||||
* The only possible service instance rights are as follows:
|
||||
* RP SERVICE_START
|
||||
* WP SERVICE_STOP
|
||||
* LC SERVICE_QUERY_STATUS
|
||||
*
|
||||
* To create a service that can be started, stopped or queried by Everyone, you can set
|
||||
* the following SDDL:
|
||||
* D:P(A;;RPWPLC;;;WD)
|
||||
*/
|
||||
#define SVC_INSTANCE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
|
||||
|
||||
enum
|
||||
{
|
||||
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||
LauncherDefineDosDevice = 'D',
|
||||
LauncherQuit = 'Q', /* DEBUG version only */
|
||||
|
||||
LauncherSuccess = '$',
|
||||
LauncherFailure = '!',
|
||||
};
|
||||
|
||||
#endif
|
@ -164,6 +164,8 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
|
||||
FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb;
|
||||
|
||||
FileObject->FsContext2 = FsvolDeviceObject;
|
||||
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -281,6 +281,8 @@ const char *DeviceExtensionKindSym(UINT32 Kind)
|
||||
{
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
return "Ctl";
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
return "Mup";
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
return "Vrt";
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
@ -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)
|
||||
{
|
||||
|
113
src/sys/driver.c
113
src/sys/driver.c
@ -44,45 +44,6 @@ NTSTATUS DriverEntry(
|
||||
{
|
||||
FSP_ENTER_DRV();
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
FSP_RETURN();
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
|
||||
/* create the file system control device objects */
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
FspProcessBufferFinalize();
|
||||
FSP_RETURN();
|
||||
}
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
/* setup the driver object */
|
||||
#if defined(FSP_UNLOAD)
|
||||
DriverObject->DriverUnload = FspUnload;
|
||||
@ -127,7 +88,6 @@ NTSTATUS DriverEntry(
|
||||
FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspFsvolShutdownComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
||||
@ -169,9 +129,58 @@ NTSTATUS DriverEntry(
|
||||
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
|
||||
DriverObject->FastIoDispatch = &FspFastIoDispatch;
|
||||
|
||||
BOOLEAN InitDoneGRes = FALSE, InitDonePsBuf = FALSE;
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
|
||||
FspDriverObject = DriverObject;
|
||||
ExInitializeResourceLite(&FspDeviceGlobalResource);
|
||||
InitDoneGRes = TRUE;
|
||||
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
Result = FspProcessBufferInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
InitDonePsBuf = TRUE;
|
||||
|
||||
/* create the file system control device objects */
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&FspFsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
||||
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
||||
&FspFsmupDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
Result = FspDeviceInitialize(FspFsmupDeviceObject);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
Result = FsRtlRegisterUncProviderEx(&FspMupHandle,
|
||||
&DeviceName, FspFsmupDeviceObject, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Register our "disk" device as a file system. We do not register our "net" device
|
||||
* as a file system, but we register with the MUP instead at a later time.
|
||||
* as a file system; we register with the MUP instead.
|
||||
*
|
||||
* Please note that the call below makes our driver unloadable. In fact the driver
|
||||
* remains unloadable even if we issue an IoUnregisterFileSystem() call immediately
|
||||
@ -180,6 +189,23 @@ NTSTATUS DriverEntry(
|
||||
*/
|
||||
IoRegisterFileSystem(FspFsctlDiskDeviceObject);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != FspFsmupDeviceObject)
|
||||
FspDeviceDelete(FspFsmupDeviceObject);
|
||||
if (0 != FspFsctlNetDeviceObject)
|
||||
FspDeviceDelete(FspFsctlNetDeviceObject);
|
||||
if (0 != FspFsctlDiskDeviceObject)
|
||||
FspDeviceDelete(FspFsctlDiskDeviceObject);
|
||||
if (InitDonePsBuf)
|
||||
FspProcessBufferFinalize();
|
||||
if (InitDoneGRes)
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
}
|
||||
|
||||
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
|
||||
FSP_LEAVE_DRV("DriverName=\"%wZ\", RegistryPath=\"%wZ\"",
|
||||
&DriverObject->DriverName, RegistryPath);
|
||||
@ -211,8 +237,11 @@ VOID FspUnload(
|
||||
{
|
||||
FSP_ENTER_VOID(PAGED_CODE());
|
||||
|
||||
FsRtlDeregisterUncProvider(FspMupHandle);
|
||||
|
||||
FspFsctlDiskDeviceObject = 0;
|
||||
FspFsctlNetDeviceObject = 0;
|
||||
FspFsmupDeviceObject = 0;
|
||||
//FspDeviceDeleteAll();
|
||||
|
||||
ExDeleteResourceLite(&FspDeviceGlobalResource);
|
||||
@ -229,6 +258,8 @@ VOID FspUnload(
|
||||
PDRIVER_OBJECT FspDriverObject;
|
||||
PDEVICE_OBJECT FspFsctlDiskDeviceObject;
|
||||
PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
PDEVICE_OBJECT FspFsmupDeviceObject;
|
||||
HANDLE FspMupHandle;
|
||||
FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
|
||||
|
@ -180,6 +180,8 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result);
|
||||
#define FSP_LEAVE_DRV(fmt, ...) \
|
||||
FSP_LEAVE_(FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, NtStatusSym(Result))); return Result
|
||||
#define FSP_ENTER_MJ(...) \
|
||||
if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\
|
||||
return FspMupHandleIrp(DeviceObject, Irp);\
|
||||
NTSTATUS Result = STATUS_SUCCESS; \
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\
|
||||
BOOLEAN fsp_device_deref = FALSE; \
|
||||
@ -328,7 +330,6 @@ FSP_IOPREP_DISPATCH FspFsvolSetInformationPrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||
FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||
|
||||
@ -1007,6 +1008,7 @@ typedef struct
|
||||
enum
|
||||
{
|
||||
FspFsctlDeviceExtensionKind = '\0ltC', /* file system control device (e.g. \Device\WinFsp.Disk) */
|
||||
FspFsmupDeviceExtensionKind = '\0puM', /* our own MUP device (linked to \Device\WinFsp.Mup) */
|
||||
FspFsvrtDeviceExtensionKind = '\0trV', /* virtual volume device (e.g. \Device\Volume{GUID}) */
|
||||
FspFsvolDeviceExtensionKind = '\0loV', /* file system volume device (unnamed) */
|
||||
};
|
||||
@ -1023,11 +1025,12 @@ typedef struct
|
||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
||||
PDEVICE_OBJECT FsctlDeviceObject;
|
||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||
HANDLE MupHandle;
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
PVPB SwapVpb;
|
||||
FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||
UNICODE_STRING VolumePrefix;
|
||||
UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry;
|
||||
FSP_IOQ *Ioq;
|
||||
FSP_META_CACHE *SecurityCache;
|
||||
FSP_META_CACHE *DirInfoCache;
|
||||
@ -1049,6 +1052,14 @@ typedef struct
|
||||
LIST_ENTRY NotifyList;
|
||||
FSP_STATISTICS *Statistics;
|
||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT32 InitDonePfxTab:1;
|
||||
ERESOURCE PrefixTableResource;
|
||||
UNICODE_PREFIX_TABLE PrefixTable;
|
||||
UNICODE_PREFIX_TABLE ClassTable;
|
||||
} FSP_FSMUP_DEVICE_EXTENSION;
|
||||
static inline
|
||||
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
@ -1060,6 +1071,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
static inline
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FspFsmupDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind);
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics,
|
||||
PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid,
|
||||
@ -1156,6 +1173,14 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fsmup */
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||
|
||||
/* volume management */
|
||||
#define FspVolumeTransactEarlyTimeout (1 * 10000ULL)
|
||||
NTSTATUS FspVolumeCreate(
|
||||
@ -1164,8 +1189,6 @@ VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -1559,6 +1582,8 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
|
||||
extern PDRIVER_OBJECT FspDriverObject;
|
||||
extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
|
||||
extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
|
||||
extern PDEVICE_OBJECT FspFsmupDeviceObject;
|
||||
extern HANDLE FspMupHandle;
|
||||
extern FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
||||
|
428
src/sys/mup.c
Normal file
428
src/sys/mup.c
Normal file
@ -0,0 +1,428 @@
|
||||
/**
|
||||
* @file sys/mup.c
|
||||
*
|
||||
* @copyright 2015-2018 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this file in
|
||||
* accordance with the commercial license agreement provided with the
|
||||
* software.
|
||||
*/
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
/*
|
||||
* FSP_MUP_PREFIX_CLASS
|
||||
*
|
||||
* Define the following macro to claim "class" prefixes during prefix
|
||||
* resolution. A "class" prefix is of the form \ClassName. The alternative
|
||||
* is a "full" prefix, which is of the form \ClassName\InstanceName.
|
||||
*
|
||||
* Claiming a class prefix has advantages and disadvantages. The main
|
||||
* advantage is that by claiming a \ClassName prefix, paths such as
|
||||
* \ClassName\IPC$ will be handled by WinFsp, thus speeding up prefix
|
||||
* resolution for all \ClassName prefixed names. The disadvantage is
|
||||
* it is no longer possible for WinFsp and another redirector to handle
|
||||
* instances ("shares") under the same \ClassName prefix.
|
||||
*/
|
||||
#define FSP_MUP_PREFIX_CLASS
|
||||
|
||||
static NTSTATUS FspMupGetClassName(
|
||||
PUNICODE_STRING Prefix, PUNICODE_STRING ClassName);
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||
static NTSTATUS FspMupRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspMupGetClassName)
|
||||
#pragma alloc_text(PAGE, FspMupRegister)
|
||||
#pragma alloc_text(PAGE, FspMupUnregister)
|
||||
#pragma alloc_text(PAGE, FspMupHandleIrp)
|
||||
#pragma alloc_text(PAGE, FspMupRedirQueryPathEx)
|
||||
#endif
|
||||
|
||||
typedef struct _FSP_MUP_CLASS
|
||||
{
|
||||
LONG RefCount;
|
||||
UNICODE_STRING Name;
|
||||
UNICODE_PREFIX_TABLE_ENTRY Entry;
|
||||
WCHAR Buffer[];
|
||||
} FSP_MUP_CLASS;
|
||||
|
||||
static NTSTATUS FspMupGetClassName(
|
||||
PUNICODE_STRING VolumePrefix, PUNICODE_STRING ClassName)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
RtlZeroMemory(ClassName, sizeof *ClassName);
|
||||
|
||||
if (L'\\' == VolumePrefix->Buffer[0])
|
||||
for (PWSTR P = VolumePrefix->Buffer + 1,
|
||||
EndP = VolumePrefix->Buffer + VolumePrefix->Length / sizeof(WCHAR);
|
||||
EndP > P; P++)
|
||||
{
|
||||
if (L'\\' == *P)
|
||||
{
|
||||
ClassName->Buffer = VolumePrefix->Buffer;
|
||||
ClassName->Length = (USHORT)((P - ClassName->Buffer) * sizeof(WCHAR));
|
||||
ClassName->MaximumLength = ClassName->Length;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
BOOLEAN Success;
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PUNICODE_PREFIX_TABLE_ENTRY ClassEntry;
|
||||
UNICODE_STRING ClassName;
|
||||
FSP_MUP_CLASS *Class = 0;
|
||||
|
||||
Result = FspMupGetClassName(&FsvolDeviceExtension->VolumePrefix, &ClassName);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Class = FspAlloc(sizeof *Class + ClassName.Length);
|
||||
if (0 == Class)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RtlZeroMemory(Class, sizeof *Class);
|
||||
Class->RefCount = 1;
|
||||
Class->Name.Length = ClassName.Length;
|
||||
Class->Name.MaximumLength = ClassName.MaximumLength;
|
||||
Class->Name.Buffer = Class->Buffer;
|
||||
RtlCopyMemory(Class->Buffer, ClassName.Buffer, ClassName.Length);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
Success = RtlInsertUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FsvolDeviceExtension->VolumePrefix, &FsvolDeviceExtension->VolumePrefixEntry);
|
||||
if (Success)
|
||||
{
|
||||
FspDeviceReference(FsvolDeviceObject);
|
||||
|
||||
ClassEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
&Class->Name, 0);
|
||||
if (0 == ClassEntry)
|
||||
{
|
||||
Success = RtlInsertUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
&Class->Name, &Class->Entry);
|
||||
ASSERT(Success);
|
||||
Class = 0;
|
||||
}
|
||||
else
|
||||
CONTAINING_RECORD(ClassEntry, FSP_MUP_CLASS, Entry)->RefCount++;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
Result = STATUS_OBJECT_NAME_COLLISION;
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
|
||||
exit:
|
||||
if (0 != Class)
|
||||
FspFree(Class);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID FspMupUnregister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PUNICODE_PREFIX_TABLE_ENTRY PrefixEntry;
|
||||
PUNICODE_PREFIX_TABLE_ENTRY ClassEntry;
|
||||
UNICODE_STRING ClassName;
|
||||
FSP_MUP_CLASS *Class;
|
||||
|
||||
Result = FspMupGetClassName(&FsvolDeviceExtension->VolumePrefix, &ClassName);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
PrefixEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FsvolDeviceExtension->VolumePrefix, 0);
|
||||
if (0 != PrefixEntry)
|
||||
{
|
||||
RtlRemoveUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FsvolDeviceExtension->VolumePrefixEntry);
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
|
||||
ClassEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
&ClassName, 0);
|
||||
if (0 != ClassEntry)
|
||||
{
|
||||
Class = CONTAINING_RECORD(ClassEntry, FSP_MUP_CLASS, Entry);
|
||||
if (0 == --Class->RefCount)
|
||||
{
|
||||
RtlRemoveUnicodePrefix(&FsmupDeviceExtension->ClassTable,
|
||||
ClassEntry);
|
||||
FspFree(Class);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
}
|
||||
|
||||
NTSTATUS FspMupHandleIrp(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
PDEVICE_OBJECT FsvolDeviceObject = 0;
|
||||
PUNICODE_PREFIX_TABLE_ENTRY PrefixEntry;
|
||||
BOOLEAN DeviceDeref = FALSE;
|
||||
NTSTATUS Result;
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
switch (IrpSp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
/*
|
||||
* A CREATE request with an empty file name indicates that the fsmup device
|
||||
* is being opened. Check for this case and handle it.
|
||||
*/
|
||||
if (0 == FileObject->FileName.Length)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||
Result = Irp->IoStatus.Status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Every other CREATE request must be forwarded to the appropriate fsvol device.
|
||||
*/
|
||||
|
||||
if (0 != FileObject->RelatedFileObject)
|
||||
FileObject = FileObject->RelatedFileObject;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
PrefixEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&FileObject->FileName, 0);
|
||||
if (0 != PrefixEntry)
|
||||
{
|
||||
FsvolDeviceObject = CONTAINING_RECORD(PrefixEntry,
|
||||
FSP_FSVOL_DEVICE_EXTENSION, VolumePrefixEntry)->FsvolDeviceObject;
|
||||
FspDeviceReference(FsvolDeviceObject);
|
||||
DeviceDeref = TRUE;
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
break;
|
||||
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
/*
|
||||
* A DEVICE_CONTROL request with IOCTL_REDIR_QUERY_PATH_EX must be handled
|
||||
* by the fsmup device. Check for this case and handle it.
|
||||
*/
|
||||
if (IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
Irp->IoStatus.Status = FspMupRedirQueryPathEx(FsmupDeviceObject, Irp, IrpSp);
|
||||
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||
Result = Irp->IoStatus.Status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Every other DEVICE_CONTROL request must be forwarded to the appropriate fsvol device.
|
||||
*/
|
||||
|
||||
/* fall through! */
|
||||
|
||||
default:
|
||||
/*
|
||||
* Every other request must be forwarded to the appropriate fsvol device. If there is no
|
||||
* fsvol device, then we must return the appropriate status code (see below).
|
||||
*
|
||||
* Please note that since we allow the fsmup device to be opened, we must also handle
|
||||
* CLEANUP and CLOSE requests for it.
|
||||
*/
|
||||
|
||||
if (0 != FileObject)
|
||||
{
|
||||
if (FspFileNodeIsValid(FileObject->FsContext))
|
||||
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
||||
else if (0 != FileObject->FsContext2 &&
|
||||
3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 == FsvolDeviceObject)
|
||||
{
|
||||
/*
|
||||
* We were not able to find an fsvol device to forward this IRP to. We will complete
|
||||
* the IRP with an appropriate status code.
|
||||
*/
|
||||
|
||||
switch (IrpSp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
/*
|
||||
* For CREATE requests we return STATUS_BAD_NETWORK_PATH. Here is why.
|
||||
*
|
||||
* When a file \ClassName\InstanceName\Path is opened by an application, this request
|
||||
* first goes to MUP. The MUP gives DFS a first chance to handle the request and if
|
||||
* that fails the MUP proceeds with prefix resolution. The DFS attempts to open the
|
||||
* file \ClassName\IPC$, this results in a prefix resolution for \ClassName\IPC$
|
||||
* through a recursive MUP call! If this resolution fails the DFS returns to the MUP,
|
||||
* which now attempts prefix resolution for \ClassName\InstanceName\Path.
|
||||
*
|
||||
* Under the new fsmup design we respond to IOCTL_REDIR_QUERY_PATH_EX by handling all
|
||||
* paths with a \ClassName prefix (that we know). This way we ensure that we will get
|
||||
* all opens for paths with a \ClassName prefix and avoid delays for requests of
|
||||
* \ClassName\IPC$, which if left unhandled will be forwarded to all network
|
||||
* redirectors.
|
||||
*
|
||||
* In order to successfully short-circuit requests for \ClassName\IPC$ we must also
|
||||
* return STATUS_BAD_NETWORK_PATH in CREATE. This makes DFS think that prefix
|
||||
* resolution failed and does not complain if it cannot open \ClassName\IPC$. Other
|
||||
* error codes cause DFS to completely fail the open issued by the application.
|
||||
*/
|
||||
Irp->IoStatus.Status = STATUS_BAD_NETWORK_PATH;
|
||||
break;
|
||||
case IRP_MJ_CLEANUP:
|
||||
case IRP_MJ_CLOSE:
|
||||
/*
|
||||
* CLEANUP and CLOSE requests ignore their status code (except for STATUS_PENDING).
|
||||
* So return STATUS_SUCCESS. This works regardless of whether this is a legitimate
|
||||
* fsmup request or an erroneous CLOSE request that we should not have seen.
|
||||
*/
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IRP_MJ_QUERY_INFORMATION:
|
||||
case IRP_MJ_SET_INFORMATION:
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
default:
|
||||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||
Result = Irp->IoStatus.Status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ASSERT(FspFsvolDeviceExtensionKind == FspDeviceExtension(FsvolDeviceObject)->Kind);
|
||||
|
||||
/*
|
||||
* Forward the IRP to the appropriate fsvol device. The fsvol device will take care
|
||||
* to complete the IRP, etc.
|
||||
*/
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Result = IoCallDriver(FsvolDeviceObject, Irp);
|
||||
|
||||
if (DeviceDeref)
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
|
||||
exit:
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMupRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction);
|
||||
ASSERT(IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* check parameters */
|
||||
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
QUERY_PATH_REQUEST_EX *QueryPathRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
QUERY_PATH_RESPONSE *QueryPathResponse = Irp->UserBuffer;
|
||||
if (sizeof(QUERY_PATH_REQUEST_EX) > InputBufferLength ||
|
||||
0 == QueryPathRequest || 0 == QueryPathResponse)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (sizeof(QUERY_PATH_RESPONSE) > OutputBufferLength)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject);
|
||||
PUNICODE_PREFIX_TABLE_ENTRY Entry;
|
||||
|
||||
#if defined(FSP_MUP_PREFIX_CLASS)
|
||||
UNICODE_STRING ClassName;
|
||||
|
||||
Result = FspMupGetClassName(&QueryPathRequest->PathName, &ClassName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return STATUS_BAD_NETWORK_PATH;
|
||||
|
||||
Result = STATUS_BAD_NETWORK_PATH;
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable, &ClassName, 0);
|
||||
if (0 != Entry)
|
||||
{
|
||||
QueryPathResponse->LengthAccepted = ClassName.Length;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
#else
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
||||
|
||||
Result = STATUS_BAD_NETWORK_PATH;
|
||||
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
|
||||
Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
|
||||
&QueryPathRequest->PathName, 0);
|
||||
if (0 != Entry)
|
||||
{
|
||||
FsvolDeviceExtension = CONTAINING_RECORD(Entry, FSP_FSVOL_DEVICE_EXTENSION, VolumePrefixEntry);
|
||||
if (!FspIoqStopped(FsvolDeviceExtension->Ioq))
|
||||
{
|
||||
if (0 < FsvolDeviceExtension->VolumePrefix.Length &&
|
||||
FspFsvolDeviceVolumePrefixInString(
|
||||
FsvolDeviceExtension->FsvolDeviceObject, &QueryPathRequest->PathName) &&
|
||||
(QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length ||
|
||||
'\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)]))
|
||||
{
|
||||
QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||
#endif
|
||||
|
||||
return Result;
|
||||
}
|
@ -17,45 +17,19 @@
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
static NTSTATUS FspFsvolShutdown(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
FSP_DRIVER_DISPATCH FspShutdown;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFsvolShutdown)
|
||||
#pragma alloc_text(PAGE, FspFsvolShutdownComplete)
|
||||
#pragma alloc_text(PAGE, FspShutdown)
|
||||
#endif
|
||||
|
||||
static NTSTATUS FspFsvolShutdown(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolShutdownComplete(
|
||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
FSP_ENTER_IOC(PAGED_CODE());
|
||||
|
||||
FSP_LEAVE_IOC("%s", "");
|
||||
}
|
||||
|
||||
NTSTATUS FspShutdown(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
FSP_ENTER_MJ(PAGED_CODE());
|
||||
|
||||
switch (FspDeviceExtension(DeviceObject)->Kind)
|
||||
{
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
FSP_RETURN(Result = FspFsvolShutdown(DeviceObject, Irp, IrpSp));
|
||||
default:
|
||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
(PVOID)IrpSp;
|
||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||
|
||||
FSP_LEAVE_MJ("%s", "");
|
||||
}
|
||||
|
103
src/sys/volume.c
103
src/sys/volume.c
@ -21,7 +21,6 @@ NTSTATUS FspVolumeCreate(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static NTSTATUS FspVolumeCreateNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static WORKER_THREAD_ROUTINE FspVolumeCreateRegisterMup;
|
||||
VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static VOID FspVolumeDeleteNoLock(
|
||||
@ -31,8 +30,6 @@ NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static NTSTATUS FspVolumeMountNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -49,13 +46,11 @@ NTSTATUS FspVolumeWork(
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspVolumeCreate)
|
||||
#pragma alloc_text(PAGE, FspVolumeCreateNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeCreateRegisterMup)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeDelete)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeDeleteNoLock)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeDeleteDelayed)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeRedirQueryPathEx)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetName)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||
@ -67,13 +62,6 @@ NTSTATUS FspVolumeWork(
|
||||
#define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX
|
||||
#define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
NTSTATUS Result;
|
||||
FSP_SYNCHRONOUS_WORK_ITEM SynchronousWorkItem;
|
||||
} FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM;
|
||||
|
||||
NTSTATUS FspVolumeCreate(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
@ -106,11 +94,11 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
GUID Guid;
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING VolumeName;
|
||||
UNICODE_STRING FsmupDeviceName;
|
||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
||||
FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM RegisterMupWorkItem;
|
||||
|
||||
/* check parameters */
|
||||
if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS) * sizeof(WCHAR) > FileObject->FileName.Length)
|
||||
@ -225,6 +213,7 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
FsvolDeviceExtension->FsctlDeviceObject = FsctlDeviceObject;
|
||||
FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
|
||||
FsvolDeviceExtension->FsvolDeviceObject = FsvolDeviceObject;
|
||||
FsvolDeviceExtension->VolumeParams = VolumeParams;
|
||||
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
|
||||
RtlInitUnicodeString(&FsvolDeviceExtension->VolumePrefix,
|
||||
@ -245,27 +234,24 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
}
|
||||
|
||||
/* do we need to register with MUP? */
|
||||
/* do we need to register with fsmup? */
|
||||
if (0 == FsvrtDeviceObject)
|
||||
{
|
||||
/*
|
||||
* Turns out we cannot call FsRtlRegisterUncProviderEx when the PreviousMode
|
||||
* is UserMode! So we need to somehow switch to KernelMode prior to issuing
|
||||
* the FsRtlRegisterUncProviderEx call. There seems to be no straightforward
|
||||
* way to switch the PreviousMode (no ExSetPreviousMode). So we do it indirectly
|
||||
* by executing a synchronous work item (FspExecuteSynchronousWorkItem).
|
||||
*/
|
||||
RtlZeroMemory(&RegisterMupWorkItem, sizeof RegisterMupWorkItem);
|
||||
RegisterMupWorkItem.FsvolDeviceObject = FsvolDeviceObject;
|
||||
FspInitializeSynchronousWorkItem(&RegisterMupWorkItem.SynchronousWorkItem,
|
||||
FspVolumeCreateRegisterMup, &RegisterMupWorkItem);
|
||||
FspExecuteSynchronousWorkItem(&RegisterMupWorkItem.SynchronousWorkItem);
|
||||
Result = RegisterMupWorkItem.Result;
|
||||
Result = FspMupRegister(FspFsmupDeviceObject, FsvolDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
return Result;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&FsmupDeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
|
||||
Result = IoCreateSymbolicLink(&FsvolDeviceExtension->VolumeName, &FsmupDeviceName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject);
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/* associate the new volume device with our file object */
|
||||
@ -275,18 +261,6 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspVolumeCreateRegisterMup(PVOID Context)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM *RegisterMupWorkItem = Context;
|
||||
PDEVICE_OBJECT FsvolDeviceObject = RegisterMupWorkItem->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
|
||||
RegisterMupWorkItem->Result = FsRtlRegisterUncProviderEx(&FsvolDeviceExtension->MupHandle,
|
||||
&FsvolDeviceExtension->VolumeName, FsvolDeviceObject, 0);
|
||||
}
|
||||
|
||||
VOID FspVolumeDelete(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
@ -333,7 +307,7 @@ static VOID FspVolumeDeleteNoLock(
|
||||
/* stop the I/O queue */
|
||||
FspIoqStop(FsvolDeviceExtension->Ioq);
|
||||
|
||||
/* do we have a virtual disk device or a MUP handle? */
|
||||
/* do we have a virtual disk device or are we registered with fsmup? */
|
||||
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
||||
{
|
||||
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||
@ -391,10 +365,10 @@ static VOID FspVolumeDeleteNoLock(
|
||||
FspQueueDelayedWorkItem(&FsvolDeviceExtension->DeleteVolumeDelayedWorkItem, Delay);
|
||||
}
|
||||
}
|
||||
else if (0 != FsvolDeviceExtension->MupHandle)
|
||||
else
|
||||
{
|
||||
FsRtlDeregisterUncProvider(FsvolDeviceExtension->MupHandle);
|
||||
FsvolDeviceExtension->MupHandle = 0;
|
||||
IoDeleteSymbolicLink(&FsvolDeviceExtension->VolumeName);
|
||||
FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject);
|
||||
}
|
||||
|
||||
/* release the volume device object */
|
||||
@ -515,49 +489,6 @@ static NTSTATUS FspVolumeMountNoLock(
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeRedirQueryPathEx(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction);
|
||||
ASSERT(IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* check parameters */
|
||||
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
QUERY_PATH_REQUEST_EX *QueryPathRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
QUERY_PATH_RESPONSE *QueryPathResponse = Irp->UserBuffer;
|
||||
if (sizeof(QUERY_PATH_REQUEST_EX) > InputBufferLength ||
|
||||
0 == QueryPathRequest || 0 == QueryPathResponse)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (sizeof(QUERY_PATH_RESPONSE) > OutputBufferLength)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
|
||||
Result = STATUS_BAD_NETWORK_PATH;
|
||||
if (!FspIoqStopped(FsvolDeviceExtension->Ioq))
|
||||
{
|
||||
if (0 < FsvolDeviceExtension->VolumePrefix.Length &&
|
||||
FspFsvolDeviceVolumePrefixInString(FsvolDeviceObject, &QueryPathRequest->PathName) &&
|
||||
(QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length ||
|
||||
'\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)]))
|
||||
{
|
||||
QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
|
17
tools/gendoc/apidoc.sh
Normal file
17
tools/gendoc/apidoc.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname "$0")/../..
|
||||
|
||||
PRETTYDOC="$PWD/../prettydoc/prettydoc"
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "usage: $(basename $0) {asciidoc|html}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$PRETTYDOC" -f $1 -t -H=--outer-names-only -o doc inc/winfsp/winfsp.h inc/winfsp/launch.h
|
||||
|
||||
if [[ "$1" == "asciidoc" ]]; then
|
||||
mv doc/winfsp.h.asciidoc doc/WinFsp-API-winfsp.h.asciidoc
|
||||
mv doc/launch.h.asciidoc doc/WinFsp-API-launch.h.asciidoc
|
||||
fi
|
@ -20,7 +20,7 @@ launchctl-x64 start memfs32 testnet \memfs32\test P: >nul
|
||||
launchctl-x64 start memfs-dotnet testdsk "" Q: >nul
|
||||
launchctl-x64 start memfs-dotnet testnet \memfs-dotnet\test R: >nul
|
||||
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 5 2>nul
|
||||
cd M: >nul 2>nul || (echo === Unable to find drive M: >&2 & goto fail)
|
||||
cd N: >nul 2>nul || (echo === Unable to find drive N: >&2 & goto fail)
|
||||
cd O: >nul 2>nul || (echo === Unable to find drive O: >&2 & goto fail)
|
||||
@ -144,7 +144,7 @@ launchctl-x64 stop memfs32 testnet >nul
|
||||
launchctl-x64 stop memfs-dotnet testdsk >nul
|
||||
launchctl-x64 stop memfs-dotnet testnet >nul
|
||||
rem Cannot use timeout under cygwin/mintty: "Input redirection is not supported"
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 5 2>nul
|
||||
|
||||
set /a total=testpass+testfail
|
||||
echo === Total: %testpass%/%total%
|
||||
|
294
tst/winfsp-tests/launch-test.c
Normal file
294
tst/winfsp-tests/launch-test.c
Normal file
@ -0,0 +1,294 @@
|
||||
/**
|
||||
* @file launch-test.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 <winfsp/launch.h>
|
||||
#include <tlib/testsuite.h>
|
||||
|
||||
#include "winfsp-tests.h"
|
||||
|
||||
static void launch_reg_test(void)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PWSTR ClassName = L"winfsp-tests-launch-reg-test";
|
||||
FSP_LAUNCH_REG_RECORD RecordBuf = { 0 }, *Record;
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result);
|
||||
ASSERT(0 == Record);
|
||||
|
||||
RecordBuf.Executable = 0;
|
||||
Result = FspLaunchRegSetRecord(ClassName, &RecordBuf);
|
||||
ASSERT(STATUS_INVALID_PARAMETER == Result);
|
||||
|
||||
RecordBuf.Executable = L"Executable";
|
||||
RecordBuf.CommandLine = L"CommandLine";
|
||||
RecordBuf.WorkDirectory = L"WorkDirectory";
|
||||
RecordBuf.RunAs = L"RunAs";
|
||||
RecordBuf.Security = L"Security";
|
||||
RecordBuf.JobControl = 1;
|
||||
RecordBuf.Credentials = 42;
|
||||
Result = FspLaunchRegSetRecord(ClassName, &RecordBuf);
|
||||
if (STATUS_ACCESS_DENIED == Result)
|
||||
{
|
||||
FspDebugLog(__FUNCTION__ ": need Administrator\n");
|
||||
return;
|
||||
}
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 != Record);
|
||||
ASSERT(0 == Record->Agent);
|
||||
ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable));
|
||||
ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine));
|
||||
ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory));
|
||||
ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs));
|
||||
ASSERT(0 == wcscmp(RecordBuf.Security, Record->Security));
|
||||
ASSERT(RecordBuf.JobControl == Record->JobControl);
|
||||
ASSERT(RecordBuf.Credentials == Record->Credentials);
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
Result = FspLaunchRegSetRecord(ClassName, &RecordBuf);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 != Record);
|
||||
ASSERT(0 == Record->Agent);
|
||||
ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable));
|
||||
ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine));
|
||||
ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory));
|
||||
ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs));
|
||||
ASSERT(0 == wcscmp(RecordBuf.Security, Record->Security));
|
||||
ASSERT(RecordBuf.JobControl == Record->JobControl);
|
||||
ASSERT(RecordBuf.Credentials == Record->Credentials);
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
RecordBuf.Security = 0;
|
||||
RecordBuf.Credentials = 0;
|
||||
Result = FspLaunchRegSetRecord(ClassName, &RecordBuf);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 != Record);
|
||||
ASSERT(0 == Record->Agent);
|
||||
ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable));
|
||||
ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine));
|
||||
ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory));
|
||||
ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs));
|
||||
ASSERT(0 == Record->Security);
|
||||
ASSERT(RecordBuf.JobControl == Record->JobControl);
|
||||
ASSERT(RecordBuf.Credentials == Record->Credentials);
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
Result = FspLaunchRegSetRecord(ClassName, 0);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result);
|
||||
ASSERT(0 == Record);
|
||||
|
||||
Result = FspLaunchRegSetRecord(ClassName, 0);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result);
|
||||
ASSERT(0 == Record);
|
||||
|
||||
RecordBuf.Agent = L"Agent1,Agent2";
|
||||
Result = FspLaunchRegSetRecord(ClassName, &RecordBuf);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, L"Agent", &Record);
|
||||
ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result);
|
||||
ASSERT(0 == Record);
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, L"Agent1", &Record);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 != Record);
|
||||
ASSERT(0 == wcscmp(RecordBuf.Agent, Record->Agent));
|
||||
ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable));
|
||||
ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine));
|
||||
ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory));
|
||||
ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs));
|
||||
ASSERT(0 == Record->Security);
|
||||
ASSERT(RecordBuf.JobControl == Record->JobControl);
|
||||
ASSERT(RecordBuf.Credentials == Record->Credentials);
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 != Record);
|
||||
ASSERT(0 == wcscmp(RecordBuf.Agent, Record->Agent));
|
||||
ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable));
|
||||
ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine));
|
||||
ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory));
|
||||
ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs));
|
||||
ASSERT(0 == Record->Security);
|
||||
ASSERT(RecordBuf.JobControl == Record->JobControl);
|
||||
ASSERT(RecordBuf.Credentials == Record->Credentials);
|
||||
FspLaunchRegFreeRecord(Record);
|
||||
|
||||
Result = FspLaunchRegSetRecord(ClassName, 0);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspLaunchRegGetRecord(ClassName, 0, &Record);
|
||||
ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result);
|
||||
ASSERT(0 == Record);
|
||||
}
|
||||
|
||||
static void launch_test(void)
|
||||
{
|
||||
/* this test assumes that memfs32 is registered */
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG LauncherError;
|
||||
PWSTR Argv[2];
|
||||
FSP_LAUNCH_REG_RECORD *Record;
|
||||
WCHAR Buffer[1024];
|
||||
ULONG Size;
|
||||
ULONG FoundClass, FoundInst1, FoundInst2;
|
||||
|
||||
Result = FspLaunchRegGetRecord(L"memfs32", 0, &Record);
|
||||
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
||||
{
|
||||
FspDebugLog(__FUNCTION__ ": need memfs32 registration\n");
|
||||
return;
|
||||
}
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Argv[0] = L"";
|
||||
Argv[1] = L"*";
|
||||
|
||||
Result = FspLaunchStart(L"memfs32", L"winfsp-tests-share1", 2, Argv, FALSE, &LauncherError);
|
||||
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
||||
{
|
||||
FspDebugLog(__FUNCTION__ ": need WinFsp.Launcher\n");
|
||||
return;
|
||||
}
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
|
||||
Result = FspLaunchStart(L"memfs32", L"winfsp-tests-share2", 2, Argv, FALSE, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
|
||||
Result = FspLaunchStart(L"memfs32", L"winfsp-tests-share1", 2, Argv, FALSE, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(ERROR_ALREADY_EXISTS == LauncherError);
|
||||
|
||||
Result = FspLaunchStart(L"memfs32", L"winfsp-tests-share2", 2, Argv, FALSE, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(ERROR_ALREADY_EXISTS == LauncherError);
|
||||
|
||||
Size = sizeof Buffer;
|
||||
Result = FspLaunchGetInfo(L"memfs32", L"winfsp-tests-share1", Buffer, &Size, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
ASSERT((wcslen(L"memfs32") + 1) * sizeof(WCHAR) < Size);
|
||||
ASSERT((wcslen(L"winfsp-tests-share1") + 1) * sizeof(WCHAR) < Size);
|
||||
ASSERT(0 == wcscmp(L"memfs32", Buffer));
|
||||
ASSERT(0 == wcscmp(L"winfsp-tests-share1", Buffer + 8));
|
||||
|
||||
Size = sizeof Buffer;
|
||||
Result = FspLaunchGetInfo(L"memfs32", L"winfsp-tests-share2", Buffer, &Size, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
ASSERT((wcslen(L"memfs32") + 1) * sizeof(WCHAR) < Size);
|
||||
ASSERT((wcslen(L"winfsp-tests-share2") + 1) * sizeof(WCHAR) < Size);
|
||||
ASSERT(0 == wcscmp(L"memfs32", Buffer));
|
||||
ASSERT(0 == wcscmp(L"winfsp-tests-share2", Buffer + 8));
|
||||
|
||||
Size = sizeof Buffer;
|
||||
Result = FspLaunchGetNameList(Buffer, &Size, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
FoundClass = FoundInst1 = FoundInst2 = 0;
|
||||
for (PWSTR P = Buffer, EndP = (PVOID)((PUINT8)P + Size), Part = P; EndP > P; P++)
|
||||
if (L'\0' == *P)
|
||||
{
|
||||
if (0 == wcscmp(L"memfs32", Part))
|
||||
FoundClass++;
|
||||
else if (0 == wcscmp(L"winfsp-tests-share1", Part))
|
||||
FoundInst1++;
|
||||
else if (0 == wcscmp(L"winfsp-tests-share2", Part))
|
||||
FoundInst2++;
|
||||
Part = P + 1;
|
||||
}
|
||||
ASSERT(2 == FoundClass);
|
||||
ASSERT(1 == FoundInst1);
|
||||
ASSERT(1 == FoundInst2);
|
||||
|
||||
Result = FspLaunchStop(L"memfs32", L"winfsp-tests-share1", &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
|
||||
Result = FspLaunchStop(L"memfs32", L"winfsp-tests-share2", &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
|
||||
/* give the launcher a chance to stop the file systems! */
|
||||
Sleep(3000);
|
||||
|
||||
Size = sizeof Buffer;
|
||||
Result = FspLaunchGetInfo(L"memfs32", L"winfsp-tests-share1", Buffer, &Size, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(ERROR_FILE_NOT_FOUND == LauncherError);
|
||||
|
||||
Size = sizeof Buffer;
|
||||
Result = FspLaunchGetInfo(L"memfs32", L"winfsp-tests-share2", Buffer, &Size, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(ERROR_FILE_NOT_FOUND == LauncherError);
|
||||
|
||||
Result = FspLaunchStop(L"memfs32", L"winfsp-tests-share1", &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(ERROR_FILE_NOT_FOUND == LauncherError);
|
||||
|
||||
Result = FspLaunchStop(L"memfs32", L"winfsp-tests-share2", &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(ERROR_FILE_NOT_FOUND == LauncherError);
|
||||
|
||||
Size = sizeof Buffer;
|
||||
Result = FspLaunchGetNameList(Buffer, &Size, &LauncherError);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
ASSERT(0 == LauncherError);
|
||||
FoundClass = FoundInst1 = FoundInst2 = 0;
|
||||
for (PWSTR P = Buffer, EndP = (PVOID)((PUINT8)P + Size), Part = P; EndP > P; P++)
|
||||
if (L'\0' == *P)
|
||||
{
|
||||
if (0 == wcscmp(L"memfs32", Part))
|
||||
FoundClass++;
|
||||
else if (0 == wcscmp(L"winfsp-tests-share1", Part))
|
||||
FoundInst1++;
|
||||
else if (0 == wcscmp(L"winfsp-tests-share2", Part))
|
||||
FoundInst2++;
|
||||
Part = P + 1;
|
||||
}
|
||||
ASSERT(0 == FoundClass);
|
||||
ASSERT(0 == FoundInst1);
|
||||
ASSERT(0 == FoundInst2);
|
||||
}
|
||||
|
||||
void launch_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
TEST(launch_reg_test);
|
||||
//TEST(launch_test);
|
||||
}
|
@ -186,6 +186,7 @@ int main(int argc, char *argv[])
|
||||
TESTSUITE(path_tests);
|
||||
TESTSUITE(dirbuf_tests);
|
||||
TESTSUITE(version_tests);
|
||||
TESTSUITE(launch_tests);
|
||||
TESTSUITE(mount_tests);
|
||||
TESTSUITE(timeout_tests);
|
||||
TESTSUITE(memfs_tests);
|
||||
|
Reference in New Issue
Block a user