mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-04 01:42:58 -05:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
b323925d94 | |||
3206e3dd15 | |||
0f185587c9 | |||
3119922708 | |||
5d90c35e20 | |||
a910385cb1 | |||
17d687fe7e | |||
4deb7b96a9 | |||
36ba4ff402 | |||
55955b8514 | |||
1bebbcf634 | |||
a292cd4d73 | |||
0de00e872f | |||
084f0b5b36 | |||
901ef5e92f | |||
f09597a519 |
@ -1,6 +1,23 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v1.4B4 (2018.2 B4)::
|
||||||
|
|
||||||
|
Changes since v1.3:
|
||||||
|
|
||||||
|
* FUSE3 API (version 3.2) is now available. The FUSE2 API (version 2.8) also remains supported.
|
||||||
|
* New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API. FUSE `ioctl` is also supported.
|
||||||
|
* New `SetDelete` file system operation can optionally be used instead of `CanDelete`. `SetDelete` or `CanDelete` are used to handle the file "disposition" flag, which determines if a file is marked for deletion. See the relevant documentation for more details.
|
||||||
|
* `FlushAndPurgeOnCleanup` has now been added to the .NET API. (GitHub PR #176; thanks @FrKaram.)
|
||||||
|
* New sample file system "airfs" contributed by @JohnOberschelp. Airfs is an in-memory file system like Memfs on which it is based on; it has received substantial improvements in how the file name space is maintained and has been modified to use modern C++ techniques by John.
|
||||||
|
* New sample file system "passthrough-fuse3" passes all operations to an underlying file system. This file system is built using the FUSE3 API. It builds and runs on both Windows and Cygwin.
|
||||||
|
* The FUSE layer now supports multiple file systems within a single process. This is a long standing problem that has been fixed. (GitHub issue #135.)
|
||||||
|
* The FSD includes a fix for a Windows problem: that case-sensitive file systems do not work properly when mounted as directories. See FAQ entry #3.
|
||||||
|
* The FSD includes a fix for a rare but serious problem. (GitHub issue #177. Thanks @thinkport.)
|
||||||
|
* The FSD includes a fix for an incompatibility with DrWeb Antivirus. (GitHub issue #192)
|
||||||
|
* The DLL includes a fix for an errorenous `STATUS_ACCESS_DENIED` on read-only directories. (GitHub issue #190. Thanks @alfaunits.)
|
||||||
|
|
||||||
|
|
||||||
v1.4B3 (2018.2 B3)::
|
v1.4B3 (2018.2 B3)::
|
||||||
|
|
||||||
Changes since v1.3:
|
Changes since v1.3:
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<MyCanonicalVersion>1.4</MyCanonicalVersion>
|
<MyCanonicalVersion>1.4</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2018.2 B3</MyProductVersion>
|
<MyProductVersion>2018.2 B4</MyProductVersion>
|
||||||
<MyProductStage>Beta</MyProductStage>
|
<MyProductStage>Beta</MyProductStage>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
|
@ -222,7 +222,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -250,7 +250,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -281,7 +281,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -312,7 +312,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib</AdditionalDependencies>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
@ -111,7 +111,43 @@ enum
|
|||||||
*/
|
*/
|
||||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError);
|
PWSTR Buffer, PULONG PSize,
|
||||||
|
PULONG PLauncherError);
|
||||||
|
/**
|
||||||
|
* 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 AllowImpersonation
|
||||||
|
* Allow caller to be impersonated by launcher.
|
||||||
|
* @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 FspLaunchCallLauncherPipeEx(
|
||||||
|
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||||
|
PWSTR Buffer, PULONG PSize,
|
||||||
|
BOOLEAN AllowImpersonation,
|
||||||
|
PULONG PLauncherError);
|
||||||
/**
|
/**
|
||||||
* Start a service instance.
|
* Start a service instance.
|
||||||
*
|
*
|
||||||
@ -138,6 +174,35 @@ FSP_API NTSTATUS FspLaunchStart(
|
|||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
||||||
BOOLEAN HasSecret,
|
BOOLEAN HasSecret,
|
||||||
PULONG PLauncherError);
|
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 AllowImpersonation
|
||||||
|
* Allow caller to be impersonated by launcher.
|
||||||
|
* @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 FspLaunchStartEx(
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
||||||
|
BOOLEAN HasSecret,
|
||||||
|
BOOLEAN AllowImpersonation,
|
||||||
|
PULONG PLauncherError);
|
||||||
/**
|
/**
|
||||||
* Stop a service instance.
|
* Stop a service instance.
|
||||||
*
|
*
|
||||||
@ -221,10 +286,12 @@ typedef struct _FSP_LAUNCH_REG_RECORD
|
|||||||
PWSTR WorkDirectory;
|
PWSTR WorkDirectory;
|
||||||
PWSTR RunAs;
|
PWSTR RunAs;
|
||||||
PWSTR Security;
|
PWSTR Security;
|
||||||
PVOID Reserved0[6];
|
PWSTR AuthPackage;
|
||||||
|
PVOID Reserved0[5];
|
||||||
ULONG JobControl;
|
ULONG JobControl;
|
||||||
ULONG Credentials;
|
ULONG Credentials;
|
||||||
ULONG Reserved1[6];
|
ULONG AuthPackageId;
|
||||||
|
ULONG Reserved1[5];
|
||||||
UINT8 Buffer[];
|
UINT8 Buffer[];
|
||||||
} FSP_LAUNCH_REG_RECORD;
|
} FSP_LAUNCH_REG_RECORD;
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@ -1795,6 +1795,10 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
|||||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
PULONG PBytesTransferred, ULONG Timeout,
|
PULONG PBytesTransferred, ULONG Timeout,
|
||||||
PSID Sid);
|
PSID Sid);
|
||||||
|
FSP_API NTSTATUS FspCallNamedPipeSecurelyEx(PWSTR PipeName,
|
||||||
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
|
PULONG PBytesTransferred, ULONG Timeout, BOOLEAN AllowImpersonation,
|
||||||
|
PSID Sid);
|
||||||
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -23,7 +23,18 @@
|
|||||||
|
|
||||||
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
||||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||||
PWSTR Buffer, PULONG PSize, PULONG PLauncherError)
|
PWSTR Buffer, PULONG PSize,
|
||||||
|
PULONG PLauncherError)
|
||||||
|
{
|
||||||
|
return FspLaunchCallLauncherPipeEx(
|
||||||
|
Command, Argc, Argv, Argl, Buffer, PSize, FALSE, PLauncherError);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspLaunchCallLauncherPipeEx(
|
||||||
|
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||||
|
PWSTR Buffer, PULONG PSize,
|
||||||
|
BOOLEAN AllowImpersonation,
|
||||||
|
PULONG PLauncherError)
|
||||||
{
|
{
|
||||||
PWSTR PipeBuf = 0, P;
|
PWSTR PipeBuf = 0, P;
|
||||||
ULONG Length, BytesTransferred;
|
ULONG Length, BytesTransferred;
|
||||||
@ -53,9 +64,9 @@ FSP_API NTSTATUS FspLaunchCallLauncherPipe(
|
|||||||
memcpy(P, Argv[I], Length * sizeof(WCHAR)); P += Length; *P++ = L'\0';
|
memcpy(P, Argv[I], Length * sizeof(WCHAR)); P += Length; *P++ = L'\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME,
|
Result = FspCallNamedPipeSecurelyEx(L"" FSP_LAUNCH_PIPE_NAME,
|
||||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE,
|
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, FSP_LAUNCH_PIPE_BUFFER_SIZE,
|
||||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, AllowImpersonation, FSP_LAUNCH_PIPE_OWNER);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -102,8 +113,17 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspLaunchStart(
|
FSP_API NTSTATUS FspLaunchStart(
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
||||||
|
BOOLEAN HasSecret,
|
||||||
|
PULONG PLauncherError)
|
||||||
|
{
|
||||||
|
return FspLaunchStartEx(ClassName, InstanceName, Argc, Argv, HasSecret, FALSE, PLauncherError);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspLaunchStartEx(
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
|
||||||
BOOLEAN HasSecret,
|
BOOLEAN HasSecret,
|
||||||
|
BOOLEAN AllowImpersonation,
|
||||||
PULONG PLauncherError)
|
PULONG PLauncherError)
|
||||||
{
|
{
|
||||||
PWSTR Argv[9 + 2];
|
PWSTR Argv[9 + 2];
|
||||||
@ -115,9 +135,9 @@ FSP_API NTSTATUS FspLaunchStart(
|
|||||||
Argv[1] = InstanceName;
|
Argv[1] = InstanceName;
|
||||||
memcpy(Argv + 2, Argv0, Argc * sizeof(PWSTR));
|
memcpy(Argv + 2, Argv0, Argc * sizeof(PWSTR));
|
||||||
|
|
||||||
return FspLaunchCallLauncherPipe(
|
return FspLaunchCallLauncherPipeEx(
|
||||||
HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
HasSecret ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||||
Argc + 2, Argv, 0, 0, 0, PLauncherError);
|
Argc + 2, Argv, 0, 0, 0, AllowImpersonation, PLauncherError);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspLaunchStop(
|
FSP_API NTSTATUS FspLaunchStop(
|
||||||
@ -250,8 +270,10 @@ FSP_API NTSTATUS FspLaunchRegSetRecord(
|
|||||||
SETFIELD(WorkDirectory);
|
SETFIELD(WorkDirectory);
|
||||||
SETFIELD(RunAs);
|
SETFIELD(RunAs);
|
||||||
SETFIELD(Security);
|
SETFIELD(Security);
|
||||||
|
SETFIELD(AuthPackage);
|
||||||
SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */
|
SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */
|
||||||
SETFIELDI(Credentials, 0);
|
SETFIELDI(Credentials, 0);
|
||||||
|
SETFIELDI(AuthPackageId, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -400,8 +422,10 @@ FSP_API NTSTATUS FspLaunchRegGetRecord(
|
|||||||
GETFIELD(WorkDirectory);
|
GETFIELD(WorkDirectory);
|
||||||
GETFIELD(RunAs);
|
GETFIELD(RunAs);
|
||||||
GETFIELD(Security);
|
GETFIELD(Security);
|
||||||
|
GETFIELD(AuthPackage);
|
||||||
GETFIELDI(JobControl);
|
GETFIELDI(JobControl);
|
||||||
GETFIELDI(Credentials);
|
GETFIELDI(Credentials);
|
||||||
|
GETFIELDI(AuthPackageId);
|
||||||
|
|
||||||
if (0 == Record->Executable)
|
if (0 == Record->Executable)
|
||||||
{
|
{
|
||||||
@ -430,8 +454,11 @@ FSP_API NTSTATUS FspLaunchRegGetRecord(
|
|||||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0;
|
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0;
|
||||||
Record->Security = 0 != RecordBuf.Security ?
|
Record->Security = 0 != RecordBuf.Security ?
|
||||||
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0;
|
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0;
|
||||||
|
Record->AuthPackage = 0 != RecordBuf.AuthPackage ?
|
||||||
|
(PVOID)(Record->Buffer + ((PUINT8)RecordBuf.AuthPackage - RegBuf)) : 0;
|
||||||
Record->JobControl = RecordBuf.JobControl;
|
Record->JobControl = RecordBuf.JobControl;
|
||||||
Record->Credentials = RecordBuf.Credentials;
|
Record->Credentials = RecordBuf.Credentials;
|
||||||
|
Record->AuthPackageId = RecordBuf.AuthPackageId;
|
||||||
|
|
||||||
*PRecord = Record;
|
*PRecord = Record;
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
@ -46,6 +46,7 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
|||||||
Dynamic = 0 == Reserved;
|
Dynamic = 0 == Reserved;
|
||||||
fsp_fuse_finalize(Dynamic);
|
fsp_fuse_finalize(Dynamic);
|
||||||
FspServiceFinalize(Dynamic);
|
FspServiceFinalize(Dynamic);
|
||||||
|
FspFileSystemFinalize(Dynamic);
|
||||||
FspEventLogFinalize(Dynamic);
|
FspEventLogFinalize(Dynamic);
|
||||||
FspPosixFinalize(Dynamic);
|
FspPosixFinalize(Dynamic);
|
||||||
FspWksidFinalize(Dynamic);
|
FspWksidFinalize(Dynamic);
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
VOID FspWksidFinalize(BOOLEAN Dynamic);
|
VOID FspWksidFinalize(BOOLEAN Dynamic);
|
||||||
VOID FspPosixFinalize(BOOLEAN Dynamic);
|
VOID FspPosixFinalize(BOOLEAN Dynamic);
|
||||||
VOID FspEventLogFinalize(BOOLEAN Dynamic);
|
VOID FspEventLogFinalize(BOOLEAN Dynamic);
|
||||||
|
VOID FspFileSystemFinalize(BOOLEAN Dynamic);
|
||||||
VOID FspServiceFinalize(BOOLEAN Dynamic);
|
VOID FspServiceFinalize(BOOLEAN Dynamic);
|
||||||
VOID fsp_fuse_finalize(BOOLEAN Dynamic);
|
VOID fsp_fuse_finalize(BOOLEAN Dynamic);
|
||||||
VOID fsp_fuse_finalize_thread(VOID);
|
VOID fsp_fuse_finalize_thread(VOID);
|
||||||
|
121
src/dll/np.c
121
src/dll/np.c
@ -23,6 +23,9 @@
|
|||||||
#include <npapi.h>
|
#include <npapi.h>
|
||||||
#include <wincred.h>
|
#include <wincred.h>
|
||||||
|
|
||||||
|
#define _NTDEF_
|
||||||
|
#include <ntsecapi.h>
|
||||||
|
|
||||||
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
||||||
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
||||||
#define FSP_NP_ADDCONNECTION_TIMEOUT 15000
|
#define FSP_NP_ADDCONNECTION_TIMEOUT 15000
|
||||||
@ -179,12 +182,14 @@ static inline BOOLEAN FspNpParseRemoteUserName(PWSTR RemoteName,
|
|||||||
|
|
||||||
static inline DWORD FspNpCallLauncherPipe(
|
static inline DWORD FspNpCallLauncherPipe(
|
||||||
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
|
||||||
PWSTR Buffer, PULONG PSize)
|
PWSTR Buffer, PULONG PSize,
|
||||||
|
BOOLEAN AllowImpersonation)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
ULONG ErrorCode;
|
ULONG ErrorCode;
|
||||||
|
|
||||||
Result = FspLaunchCallLauncherPipe(Command, Argc, Argv, Argl, Buffer, PSize, &ErrorCode);
|
Result = FspLaunchCallLauncherPipeEx(Command, Argc, Argv, Argl, Buffer, PSize, AllowImpersonation,
|
||||||
|
&ErrorCode);
|
||||||
return !NT_SUCCESS(Result) ?
|
return !NT_SUCCESS(Result) ?
|
||||||
WN_NO_NETWORK :
|
WN_NO_NETWORK :
|
||||||
(ERROR_BROKEN_PIPE == ErrorCode ? WN_NO_NETWORK : ErrorCode);
|
(ERROR_BROKEN_PIPE == ErrorCode ? WN_NO_NETWORK : ErrorCode);
|
||||||
@ -251,7 +256,50 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
static NTSTATUS FspNpGetAuthPackage(PWSTR AuthPackageName, PULONG PAuthPackage)
|
||||||
|
{
|
||||||
|
HANDLE LsaHandle;
|
||||||
|
BOOLEAN LsaHandleValid = FALSE;
|
||||||
|
CHAR LsaAuthPackageNameBuf[127]; /* "The package name must not exceed 127 bytes in length." */
|
||||||
|
LSA_STRING LsaAuthPackageName;
|
||||||
|
ULONG AuthPackage;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PAuthPackage = 0;
|
||||||
|
|
||||||
|
Result = LsaConnectUntrusted(&LsaHandle);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
LsaHandleValid = TRUE;
|
||||||
|
|
||||||
|
LsaAuthPackageName.MaximumLength = sizeof LsaAuthPackageNameBuf;
|
||||||
|
LsaAuthPackageName.Buffer = LsaAuthPackageNameBuf;
|
||||||
|
LsaAuthPackageName.Length = WideCharToMultiByte(CP_UTF8, 0,
|
||||||
|
AuthPackageName, lstrlenW(AuthPackageName),
|
||||||
|
LsaAuthPackageNameBuf, sizeof LsaAuthPackageNameBuf,
|
||||||
|
0, 0);
|
||||||
|
if (0 == LsaAuthPackageName.Length)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = LsaLookupAuthenticationPackage(LsaHandle, &LsaAuthPackageName, &AuthPackage);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
*PAuthPackage = AuthPackage;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (LsaHandleValid)
|
||||||
|
LsaDeregisterLogonProcess(LsaHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD FspNpGetRemoteInfo(PWSTR RemoteName,
|
||||||
|
PDWORD PAuthPackage, PDWORD PCredentialsKind, PBOOLEAN PAllowImpersonation)
|
||||||
{
|
{
|
||||||
PWSTR ClassName, InstanceName;
|
PWSTR ClassName, InstanceName;
|
||||||
ULONG ClassNameLen, InstanceNameLen;
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
@ -259,7 +307,14 @@ static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
|||||||
FSP_LAUNCH_REG_RECORD *Record;
|
FSP_LAUNCH_REG_RECORD *Record;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
if (0 != PAuthPackage)
|
||||||
|
*PAuthPackage = 0;
|
||||||
|
|
||||||
|
if (0 != PCredentialsKind)
|
||||||
|
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
||||||
|
|
||||||
|
if (0 != PAllowImpersonation)
|
||||||
|
*PAllowImpersonation = FALSE;
|
||||||
|
|
||||||
if (!FspNpParseRemoteName(RemoteName,
|
if (!FspNpParseRemoteName(RemoteName,
|
||||||
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
@ -274,15 +329,36 @@ static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return WN_NO_NETWORK;
|
return WN_NO_NETWORK;
|
||||||
|
|
||||||
switch (Record->Credentials)
|
if (0 != PAuthPackage)
|
||||||
{
|
{
|
||||||
case FSP_NP_CREDENTIALS_NONE:
|
if (0 != Record->AuthPackage)
|
||||||
case FSP_NP_CREDENTIALS_PASSWORD:
|
{
|
||||||
case FSP_NP_CREDENTIALS_USERPASS:
|
ULONG AuthPackage = 0;
|
||||||
*PCredentialsKind = Record->Credentials;
|
|
||||||
break;
|
Result = FspNpGetAuthPackage(Record->AuthPackage, &AuthPackage);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return WN_NO_NETWORK;
|
||||||
|
|
||||||
|
*PAuthPackage = AuthPackage + 1; /* ensure non-0 (Negotiate AuthPackage == 0) */
|
||||||
|
}
|
||||||
|
else if (0 != Record->AuthPackageId)
|
||||||
|
*PAuthPackage = Record->AuthPackageId + 1; /* ensure non-0 (Negotiate AuthPackage == 0) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 != PCredentialsKind)
|
||||||
|
switch (Record->Credentials)
|
||||||
|
{
|
||||||
|
case FSP_NP_CREDENTIALS_NONE:
|
||||||
|
case FSP_NP_CREDENTIALS_PASSWORD:
|
||||||
|
case FSP_NP_CREDENTIALS_USERPASS:
|
||||||
|
*PCredentialsKind = Record->Credentials;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != PAllowImpersonation)
|
||||||
|
*PAllowImpersonation = 0 != Record->RunAs &&
|
||||||
|
L'.' == Record->RunAs[0] && L'\0' == Record->RunAs[1];
|
||||||
|
|
||||||
FspLaunchRegFreeRecord(Record);
|
FspLaunchRegFreeRecord(Record);
|
||||||
|
|
||||||
return WN_SUCCESS;
|
return WN_SUCCESS;
|
||||||
@ -290,7 +366,7 @@ static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, PDWORD PCredentialsKind)
|
|||||||
|
|
||||||
static DWORD FspNpGetCredentials(
|
static DWORD FspNpGetCredentials(
|
||||||
HWND hwndOwner, PWSTR Caption, DWORD PrevNpResult,
|
HWND hwndOwner, PWSTR Caption, DWORD PrevNpResult,
|
||||||
DWORD CredentialsKind,
|
DWORD AuthPackage0, DWORD CredentialsKind,
|
||||||
PBOOL PSave,
|
PBOOL PSave,
|
||||||
PWSTR UserName, ULONG UserNameSize/* in chars */,
|
PWSTR UserName, ULONG UserNameSize/* in chars */,
|
||||||
PWSTR Password, ULONG PasswordSize/* in chars */)
|
PWSTR Password, ULONG PasswordSize/* in chars */)
|
||||||
@ -317,7 +393,7 @@ static DWORD FspNpGetCredentials(
|
|||||||
(FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind ? 0/*CREDUI_FLAGS_KEEP_USERNAME*/ : 0));
|
(FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind ? 0/*CREDUI_FLAGS_KEEP_USERNAME*/ : 0));
|
||||||
#else
|
#else
|
||||||
WCHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
|
WCHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
|
||||||
ULONG AuthPackage = 0;
|
ULONG AuthPackage = 0 != AuthPackage0 ? AuthPackage0 - 1 : 0;
|
||||||
PVOID InAuthBuf = 0, OutAuthBuf = 0;
|
PVOID InAuthBuf = 0, OutAuthBuf = 0;
|
||||||
ULONG InAuthSize, OutAuthSize, DomainSize;
|
ULONG InAuthSize, OutAuthSize, DomainSize;
|
||||||
|
|
||||||
@ -346,7 +422,8 @@ static DWORD FspNpGetCredentials(
|
|||||||
|
|
||||||
NpResult = CredUIPromptForWindowsCredentialsW(&UiInfo, PrevNpResult,
|
NpResult = CredUIPromptForWindowsCredentialsW(&UiInfo, PrevNpResult,
|
||||||
&AuthPackage, InAuthBuf, InAuthSize, &OutAuthBuf, &OutAuthSize, PSave,
|
&AuthPackage, InAuthBuf, InAuthSize, &OutAuthBuf, &OutAuthSize, PSave,
|
||||||
CREDUIWIN_GENERIC | (0 != PSave ? CREDUIWIN_CHECKBOX : 0));
|
(0 != AuthPackage0 ? CREDUIWIN_AUTHPACKAGE_ONLY : CREDUIWIN_GENERIC) |
|
||||||
|
(0 != PSave ? CREDUIWIN_CHECKBOX : 0));
|
||||||
if (ERROR_SUCCESS != NpResult)
|
if (ERROR_SUCCESS != NpResult)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -464,6 +541,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
|||||||
PWSTR ClassName, InstanceName, RemoteName, P;
|
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||||
ULONG ClassNameLen, InstanceNameLen;
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
DWORD CredentialsKind;
|
DWORD CredentialsKind;
|
||||||
|
BOOLEAN AllowImpersonation;
|
||||||
ULONG Argc;
|
ULONG Argc;
|
||||||
PWSTR Argv[6];
|
PWSTR Argv[6];
|
||||||
ULONG Argl[6];
|
ULONG Argl[6];
|
||||||
@ -493,7 +571,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
|||||||
return WN_ALREADY_CONNECTED;
|
return WN_ALREADY_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NpResult = FspNpGetRemoteInfo(lpRemoteName, &CredentialsKind);
|
NpResult = FspNpGetRemoteInfo(lpRemoteName, 0, &CredentialsKind, &AllowImpersonation);
|
||||||
if (WN_SUCCESS != NpResult)
|
if (WN_SUCCESS != NpResult)
|
||||||
return NpResult;
|
return NpResult;
|
||||||
|
|
||||||
@ -550,7 +628,8 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
|||||||
|
|
||||||
NpResult = FspNpCallLauncherPipe(
|
NpResult = FspNpCallLauncherPipe(
|
||||||
FSP_NP_CREDENTIALS_NONE != CredentialsKind ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
FSP_NP_CREDENTIALS_NONE != CredentialsKind ? FspLaunchCmdStartWithSecret : FspLaunchCmdStart,
|
||||||
Argc, Argv, Argl, 0, 0);
|
Argc, Argv, Argl, 0, 0,
|
||||||
|
AllowImpersonation);
|
||||||
switch (NpResult)
|
switch (NpResult)
|
||||||
{
|
{
|
||||||
case WN_SUCCESS:
|
case WN_SUCCESS:
|
||||||
@ -602,7 +681,8 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
|||||||
|
|
||||||
if (WN_SUCCESS != FspNpCallLauncherPipe(
|
if (WN_SUCCESS != FspNpCallLauncherPipe(
|
||||||
FspLaunchCmdGetInfo,
|
FspLaunchCmdGetInfo,
|
||||||
Argc, Argv, Argl, 0, 0))
|
Argc, Argv, Argl, 0, 0,
|
||||||
|
FALSE))
|
||||||
{
|
{
|
||||||
/* looks like the file system is gone! */
|
/* looks like the file system is gone! */
|
||||||
NpResult = WN_NO_NETWORK;
|
NpResult = WN_NO_NETWORK;
|
||||||
@ -659,7 +739,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
PWSTR RemoteName = lpNetResource->lpRemoteName;
|
PWSTR RemoteName = lpNetResource->lpRemoteName;
|
||||||
DWORD CredentialsKind;
|
DWORD AuthPackage, CredentialsKind;
|
||||||
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
|
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
|
||||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
BOOL Save = TRUE;
|
BOOL Save = TRUE;
|
||||||
@ -679,7 +759,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
return NpResult;
|
return NpResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
NpResult = FspNpGetRemoteInfo(RemoteName, &CredentialsKind);
|
NpResult = FspNpGetRemoteInfo(RemoteName, &AuthPackage, &CredentialsKind, 0);
|
||||||
if (WN_SUCCESS != NpResult)
|
if (WN_SUCCESS != NpResult)
|
||||||
return NpResult;
|
return NpResult;
|
||||||
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
||||||
@ -695,7 +775,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
{
|
{
|
||||||
NpResult = FspNpGetCredentials(
|
NpResult = FspNpGetCredentials(
|
||||||
hwndOwner, RemoteName, NpResult,
|
hwndOwner, RemoteName, NpResult,
|
||||||
CredentialsKind,
|
AuthPackage, CredentialsKind,
|
||||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
&Save,
|
&Save,
|
||||||
#else
|
#else
|
||||||
@ -766,7 +846,8 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
|||||||
|
|
||||||
NpResult = FspNpCallLauncherPipe(
|
NpResult = FspNpCallLauncherPipe(
|
||||||
FspLaunchCmdStop,
|
FspLaunchCmdStop,
|
||||||
Argc, Argv, Argl, 0, 0);
|
Argc, Argv, Argl, 0, 0,
|
||||||
|
FALSE);
|
||||||
switch (NpResult)
|
switch (NpResult)
|
||||||
{
|
{
|
||||||
case WN_SUCCESS:
|
case WN_SUCCESS:
|
||||||
|
@ -341,26 +341,25 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (Request->Req.Create.UserMode)
|
if (Request->Req.Create.UserMode)
|
||||||
{
|
{
|
||||||
if (0 != (FileAttributes & FILE_ATTRIBUTE_READONLY))
|
if (FILE_ATTRIBUTE_READONLY == (FileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY)) &&
|
||||||
|
(DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)))
|
||||||
{
|
{
|
||||||
if (DesiredAccess &
|
Result = STATUS_ACCESS_DENIED;
|
||||||
(FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD))
|
goto exit;
|
||||||
{
|
}
|
||||||
Result = STATUS_ACCESS_DENIED;
|
|
||||||
goto exit;
|
if (FILE_ATTRIBUTE_READONLY == (FileAttributes & FILE_ATTRIBUTE_READONLY) &&
|
||||||
}
|
(Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE))
|
||||||
if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE)
|
{
|
||||||
{
|
Result = STATUS_CANNOT_DELETE;
|
||||||
Result = STATUS_CANNOT_DELETE;
|
goto exit;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == SecurityDescriptorSize)
|
if (0 == SecurityDescriptorSize)
|
||||||
*PGrantedAccess = (MAXIMUM_ALLOWED & DesiredAccess) ?
|
*PGrantedAccess = (MAXIMUM_ALLOWED & DesiredAccess) ?
|
||||||
FspFileGenericMapping.GenericAll : DesiredAccess;
|
FspFileGenericMapping.GenericAll : DesiredAccess;
|
||||||
|
|
||||||
if (0 != (FileAttributes & FILE_ATTRIBUTE_READONLY) &&
|
if (FILE_ATTRIBUTE_READONLY == (FileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY)) &&
|
||||||
0 != (MAXIMUM_ALLOWED & DesiredAccess))
|
0 != (MAXIMUM_ALLOWED & DesiredAccess))
|
||||||
*PGrantedAccess &= ~(FILE_WRITE_DATA | FILE_APPEND_DATA |
|
*PGrantedAccess &= ~(FILE_WRITE_DATA | FILE_APPEND_DATA |
|
||||||
FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD);
|
FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD);
|
||||||
|
@ -67,6 +67,16 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
|||||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
PULONG PBytesTransferred, ULONG Timeout,
|
PULONG PBytesTransferred, ULONG Timeout,
|
||||||
PSID Sid)
|
PSID Sid)
|
||||||
|
{
|
||||||
|
return FspCallNamedPipeSecurelyEx(PipeName,
|
||||||
|
InBuffer, InBufferSize, OutBuffer, OutBufferSize, PBytesTransferred, Timeout,
|
||||||
|
FALSE, Sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspCallNamedPipeSecurelyEx(PWSTR PipeName,
|
||||||
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
|
PULONG PBytesTransferred, ULONG Timeout, BOOLEAN AllowImpersonation,
|
||||||
|
PSID Sid)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
HANDLE Pipe = INVALID_HANDLE_VALUE;
|
HANDLE Pipe = INVALID_HANDLE_VALUE;
|
||||||
@ -75,7 +85,8 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
|||||||
Pipe = CreateFileW(PipeName,
|
Pipe = CreateFileW(PipeName,
|
||||||
GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES,
|
GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
||||||
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0);
|
SECURITY_SQOS_PRESENT | (AllowImpersonation ? SECURITY_IMPERSONATION : SECURITY_IDENTIFICATION),
|
||||||
|
0);
|
||||||
if (INVALID_HANDLE_VALUE == Pipe)
|
if (INVALID_HANDLE_VALUE == Pipe)
|
||||||
{
|
{
|
||||||
if (ERROR_PIPE_BUSY != GetLastError())
|
if (ERROR_PIPE_BUSY != GetLastError())
|
||||||
@ -89,7 +100,8 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
|||||||
Pipe = CreateFileW(PipeName,
|
Pipe = CreateFileW(PipeName,
|
||||||
GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES,
|
GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
||||||
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0);
|
SECURITY_SQOS_PRESENT | (AllowImpersonation ? SECURITY_IMPERSONATION : SECURITY_IDENTIFICATION),
|
||||||
|
0);
|
||||||
if (INVALID_HANDLE_VALUE == Pipe)
|
if (INVALID_HANDLE_VALUE == Pipe)
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
@ -707,7 +707,7 @@ namespace Fsp
|
|||||||
/// Describes the modifications to apply to the file or directory security descriptor.
|
/// Describes the modifications to apply to the file or directory security descriptor.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
/// <seealso cref="ModifySecurityDescriptor"/>
|
/// <seealso cref="ModifySecurityDescriptorEx"/>
|
||||||
public virtual Int32 SetSecurity(
|
public virtual Int32 SetSecurity(
|
||||||
Object FileNode,
|
Object FileNode,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -1105,7 +1105,7 @@ namespace Fsp
|
|||||||
return (int)Api.FspFileSystemOperationProcessId();
|
return (int)Api.FspFileSystemOperationProcessId();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modifies a security descriptor.
|
/// Modifies a security descriptor. [OBSOLETE]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This is a helper for implementing the SetSecurity operation.
|
/// This is a helper for implementing the SetSecurity operation.
|
||||||
@ -1121,6 +1121,7 @@ namespace Fsp
|
|||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The modified security descriptor.</returns>
|
/// <returns>The modified security descriptor.</returns>
|
||||||
/// <seealso cref="SetSecurity"/>
|
/// <seealso cref="SetSecurity"/>
|
||||||
|
[Obsolete("use ModifySecurityDescriptorEx")]
|
||||||
public static byte[] ModifySecurityDescriptor(
|
public static byte[] ModifySecurityDescriptor(
|
||||||
Byte[] SecurityDescriptor,
|
Byte[] SecurityDescriptor,
|
||||||
AccessControlSections Sections,
|
AccessControlSections Sections,
|
||||||
@ -1140,6 +1141,47 @@ namespace Fsp
|
|||||||
SecurityInformation,
|
SecurityInformation,
|
||||||
ModificationDescriptor);
|
ModificationDescriptor);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Modifies a security descriptor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is a helper for implementing the SetSecurity operation.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="SecurityDescriptor">
|
||||||
|
/// The original security descriptor.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Sections">
|
||||||
|
/// Describes what parts of the file or directory security descriptor should be modified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="ModificationDescriptor">
|
||||||
|
/// Describes the modifications to apply to the file or directory security descriptor.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="ModifiedDescriptor">
|
||||||
|
/// The modified security descriptor. This parameter is modified only on success.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
|
/// <seealso cref="SetSecurity"/>
|
||||||
|
public static Int32 ModifySecurityDescriptorEx(
|
||||||
|
Byte[] SecurityDescriptor,
|
||||||
|
AccessControlSections Sections,
|
||||||
|
Byte[] ModificationDescriptor,
|
||||||
|
ref Byte[] ModifiedDescriptor)
|
||||||
|
{
|
||||||
|
UInt32 SecurityInformation = 0;
|
||||||
|
if (0 != (Sections & AccessControlSections.Owner))
|
||||||
|
SecurityInformation |= 1/*OWNER_SECURITY_INFORMATION*/;
|
||||||
|
if (0 != (Sections & AccessControlSections.Group))
|
||||||
|
SecurityInformation |= 2/*GROUP_SECURITY_INFORMATION*/;
|
||||||
|
if (0 != (Sections & AccessControlSections.Access))
|
||||||
|
SecurityInformation |= 4/*DACL_SECURITY_INFORMATION*/;
|
||||||
|
if (0 != (Sections & AccessControlSections.Audit))
|
||||||
|
SecurityInformation |= 8/*SACL_SECURITY_INFORMATION*/;
|
||||||
|
return Api.ModifySecurityDescriptorEx(
|
||||||
|
SecurityDescriptor,
|
||||||
|
SecurityInformation,
|
||||||
|
ModificationDescriptor,
|
||||||
|
ref ModifiedDescriptor);
|
||||||
|
}
|
||||||
public Int32 SeekableReadDirectory(
|
public Int32 SeekableReadDirectory(
|
||||||
Object FileNode,
|
Object FileNode,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
|
@ -928,6 +928,26 @@ namespace Fsp.Interop
|
|||||||
return SecurityDescriptorBytes;
|
return SecurityDescriptorBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal unsafe static Int32 ModifySecurityDescriptorEx(
|
||||||
|
Byte[] SecurityDescriptorBytes,
|
||||||
|
UInt32 SecurityInformation,
|
||||||
|
Byte[] ModificationDescriptorBytes,
|
||||||
|
ref Byte[] ModifiedDescriptorBytes)
|
||||||
|
{
|
||||||
|
fixed (Byte *S = SecurityDescriptorBytes)
|
||||||
|
fixed (Byte *M = ModificationDescriptorBytes)
|
||||||
|
{
|
||||||
|
IntPtr SecurityDescriptor;
|
||||||
|
Int32 Result = FspSetSecurityDescriptor(
|
||||||
|
(IntPtr)S, SecurityInformation, (IntPtr)M, out SecurityDescriptor);
|
||||||
|
if (0 > Result)
|
||||||
|
return Result;
|
||||||
|
SecurityDescriptorBytes = MakeSecurityDescriptor(SecurityDescriptor);
|
||||||
|
FspDeleteSecurityDescriptor(SecurityDescriptor, _FspSetSecurityDescriptorPtr);
|
||||||
|
ModifiedDescriptorBytes = SecurityDescriptorBytes;
|
||||||
|
return 0/*STATUS_SUCCESS*/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal unsafe static Int32 CopyReparsePoint(
|
internal unsafe static Int32 CopyReparsePoint(
|
||||||
Byte[] ReparseData,
|
Byte[] ReparseData,
|
||||||
|
@ -72,8 +72,8 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
DWORD LastError, BytesTransferred;
|
DWORD LastError, BytesTransferred;
|
||||||
|
|
||||||
Result = FspCallNamedPipeSecurely(L"" FSP_LAUNCH_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
Result = FspCallNamedPipeSecurelyEx(L"" FSP_LAUNCH_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, FSP_LAUNCH_PIPE_OWNER);
|
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, TRUE, FSP_LAUNCH_PIPE_OWNER);
|
||||||
LastError = FspWin32FromNtStatus(Result);
|
LastError = FspWin32FromNtStatus(Result);
|
||||||
|
|
||||||
if (0 != LastError)
|
if (0 != LastError)
|
||||||
|
@ -255,6 +255,7 @@ exit:
|
|||||||
|
|
||||||
static BOOL LogonCreateProcess(
|
static BOOL LogonCreateProcess(
|
||||||
PWSTR UserName,
|
PWSTR UserName,
|
||||||
|
HANDLE Token,
|
||||||
LPCWSTR ApplicationName,
|
LPCWSTR ApplicationName,
|
||||||
LPWSTR CommandLine,
|
LPWSTR CommandLine,
|
||||||
LPSECURITY_ATTRIBUTES ProcessAttributes,
|
LPSECURITY_ATTRIBUTES ProcessAttributes,
|
||||||
@ -271,11 +272,20 @@ static BOOL LogonCreateProcess(
|
|||||||
if (0 != UserName)
|
if (0 != UserName)
|
||||||
{
|
{
|
||||||
if (0 == invariant_wcsicmp(UserName, L"LocalSystem"))
|
if (0 == invariant_wcsicmp(UserName, L"LocalSystem"))
|
||||||
|
{
|
||||||
UserName = 0;
|
UserName = 0;
|
||||||
|
Token = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (0 == invariant_wcsicmp(UserName, L"LocalService") ||
|
if (0 == invariant_wcsicmp(UserName, L"LocalService") ||
|
||||||
0 == invariant_wcsicmp(UserName, L"NetworkService"))
|
0 == invariant_wcsicmp(UserName, L"NetworkService"))
|
||||||
|
{
|
||||||
DomainName = L"NT AUTHORITY";
|
DomainName = L"NT AUTHORITY";
|
||||||
|
Token = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == invariant_wcsicmp(UserName, L"."))
|
||||||
|
;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_ACCESS_DENIED);
|
SetLastError(ERROR_ACCESS_DENIED);
|
||||||
@ -299,18 +309,40 @@ static BOOL LogonCreateProcess(
|
|||||||
|
|
||||||
HANDLE LogonToken = 0;
|
HANDLE LogonToken = 0;
|
||||||
PVOID EnvironmentBlock = 0;
|
PVOID EnvironmentBlock = 0;
|
||||||
|
DWORD SessionId;
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
BOOL Success;
|
BOOL Success;
|
||||||
|
|
||||||
Success = LogonUserW(
|
if (0 == Token)
|
||||||
UserName,
|
{
|
||||||
DomainName,
|
Success = LogonUserW(
|
||||||
0,
|
UserName,
|
||||||
LOGON32_LOGON_SERVICE,
|
DomainName,
|
||||||
LOGON32_PROVIDER_DEFAULT,
|
0,
|
||||||
&LogonToken);
|
LOGON32_LOGON_SERVICE,
|
||||||
if (!Success)
|
LOGON32_PROVIDER_DEFAULT,
|
||||||
goto exit;
|
&LogonToken);
|
||||||
|
if (!Success)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* convert the impersonation token to a primary token */
|
||||||
|
Success = DuplicateTokenEx(Token,
|
||||||
|
TOKEN_ALL_ACCESS,
|
||||||
|
0,
|
||||||
|
SecurityAnonymous,
|
||||||
|
TokenPrimary,
|
||||||
|
&LogonToken);
|
||||||
|
if (!Success)
|
||||||
|
goto exit;
|
||||||
|
if (!ProcessIdToSessionId(GetCurrentProcessId(), &SessionId))
|
||||||
|
SessionId = 0;
|
||||||
|
/* place the duplicated token in the service session (session 0) */
|
||||||
|
Success = SetTokenInformation(LogonToken, TokenSessionId, &SessionId, sizeof SessionId);
|
||||||
|
if (!Success)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == Environment)
|
if (0 == Environment)
|
||||||
{
|
{
|
||||||
@ -663,7 +695,7 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS SvcInstanceCreateProcess(PWSTR UserName,
|
static NTSTATUS SvcInstanceCreateProcess(PWSTR UserName, HANDLE ClientToken,
|
||||||
PWSTR Executable, PWSTR CommandLine, PWSTR WorkDirectory,
|
PWSTR Executable, PWSTR CommandLine, PWSTR WorkDirectory,
|
||||||
HANDLE StdioHandles[2],
|
HANDLE StdioHandles[2],
|
||||||
PPROCESS_INFORMATION ProcessInfo)
|
PPROCESS_INFORMATION ProcessInfo)
|
||||||
@ -758,7 +790,7 @@ static NTSTATUS SvcInstanceCreateProcess(PWSTR UserName,
|
|||||||
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
|
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
|
||||||
StartupInfoEx.StartupInfo.hStdError = ChildHandles[2];
|
StartupInfoEx.StartupInfo.hStdError = ChildHandles[2];
|
||||||
|
|
||||||
if (!LogonCreateProcess(UserName,
|
if (!LogonCreateProcess(UserName, ClientToken,
|
||||||
Executable, CommandLine, 0, 0, TRUE,
|
Executable, CommandLine, 0, 0, TRUE,
|
||||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT,
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT,
|
||||||
0, WorkDirectory,
|
0, WorkDirectory,
|
||||||
@ -779,7 +811,7 @@ static NTSTATUS SvcInstanceCreateProcess(PWSTR UserName,
|
|||||||
* Not ideal, but...
|
* Not ideal, but...
|
||||||
*/
|
*/
|
||||||
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||||
if (!LogonCreateProcess(UserName,
|
if (!LogonCreateProcess(UserName, ClientToken,
|
||||||
Executable, CommandLine, 0, 0, TRUE,
|
Executable, CommandLine, 0, 0, TRUE,
|
||||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP,
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP,
|
||||||
0, WorkDirectory,
|
0, WorkDirectory,
|
||||||
@ -792,7 +824,7 @@ static NTSTATUS SvcInstanceCreateProcess(PWSTR UserName,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!LogonCreateProcess(UserName,
|
if (!LogonCreateProcess(UserName, ClientToken,
|
||||||
Executable, CommandLine, 0, 0, FALSE,
|
Executable, CommandLine, 0, 0, FALSE,
|
||||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP,
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP,
|
||||||
0, WorkDirectory,
|
0, WorkDirectory,
|
||||||
@ -1009,7 +1041,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
Result = SvcInstanceCreateProcess(L'\0' != RunAsBuf[0] ? RunAsBuf : 0,
|
Result = SvcInstanceCreateProcess(L'\0' != RunAsBuf[0] ? RunAsBuf : 0, ClientToken,
|
||||||
Executable, SvcInstance->CommandLine, L'\0' != WorkDirectory[0] ? WorkDirectory : 0,
|
Executable, SvcInstance->CommandLine, L'\0' != WorkDirectory[0] ? WorkDirectory : 0,
|
||||||
RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
|
RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -1629,7 +1661,10 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
|||||||
|
|
||||||
ClientToken = 0;
|
ClientToken = 0;
|
||||||
if (!ImpersonateNamedPipeClient(SvcPipe) ||
|
if (!ImpersonateNamedPipeClient(SvcPipe) ||
|
||||||
!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &ClientToken) ||
|
(
|
||||||
|
!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_DUPLICATE, FALSE, &ClientToken) &&
|
||||||
|
!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &ClientToken)
|
||||||
|
) ||
|
||||||
!RevertToSelf())
|
!RevertToSelf())
|
||||||
{
|
{
|
||||||
LastError = GetLastError();
|
LastError = GetLastError();
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvrtDeviceControl(
|
||||||
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolDeviceControl(
|
static NTSTATUS FspFsvolDeviceControl(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
|
||||||
@ -28,6 +30,7 @@ static FSP_IOP_REQUEST_FINI FspFsvolDeviceControlRequestFini;
|
|||||||
FSP_DRIVER_DISPATCH FspDeviceControl;
|
FSP_DRIVER_DISPATCH FspDeviceControl;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspFsvrtDeviceControl)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
|
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
|
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
|
||||||
@ -39,6 +42,28 @@ enum
|
|||||||
RequestFileNode = 0,
|
RequestFileNode = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvrtDeviceControl(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix GitHub issue #177. All credit for the investigation of this issue
|
||||||
|
* and the suggested steps to reproduce and work around the problem goes
|
||||||
|
* to GitHub user @thinkport.
|
||||||
|
*
|
||||||
|
* When Windows attempts to mount a new volume it iterates over all disk file
|
||||||
|
* systems registered with IoRegisterFileSystem. Foreign (i.e. non-WinFsp) file
|
||||||
|
* systems would in some cases attempt to mount our Fsvrt volume device by
|
||||||
|
* sending it unknown IOCTL codes, which would then be failed with
|
||||||
|
* STATUS_INVALID_DEVICE_REQUEST. Unfortunately the file systems would then
|
||||||
|
* report this error code to the I/O Manager, which would cause it to abort the
|
||||||
|
* mounting process completely and thus WinFsp would never get a chance to
|
||||||
|
* mount its own volume device!
|
||||||
|
*/
|
||||||
|
return STATUS_UNRECOGNIZED_VOLUME;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolDeviceControl(
|
static NTSTATUS FspFsvolDeviceControl(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -155,6 +180,8 @@ NTSTATUS FspDeviceControl(
|
|||||||
{
|
{
|
||||||
case FspFsvolDeviceExtensionKind:
|
case FspFsvolDeviceExtensionKind:
|
||||||
FSP_RETURN(Result = FspFsvolDeviceControl(DeviceObject, Irp, IrpSp));
|
FSP_RETURN(Result = FspFsvolDeviceControl(DeviceObject, Irp, IrpSp));
|
||||||
|
case FspFsvrtDeviceExtensionKind:
|
||||||
|
FSP_RETURN(Result = FspFsvrtDeviceControl(DeviceObject, Irp, IrpSp));
|
||||||
default:
|
default:
|
||||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,21 @@ NTSTATUS DriverEntry(
|
|||||||
&FspFsmupDeviceObject);
|
&FspFsmupDeviceObject);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
/*
|
||||||
|
* Fix GitHub issue #177. All credit for the investigation of this issue
|
||||||
|
* and the suggested steps to reproduce and work around the problem goes
|
||||||
|
* to GitHub user @thinkport.
|
||||||
|
*
|
||||||
|
* On debug builds set DO_LOW_PRIORITY_FILESYSTEM to place the file system
|
||||||
|
* at the end of the file system list during IoRegisterFileSystem below.
|
||||||
|
* This allows us to test the behavior of our Fsvrt devices when foreign
|
||||||
|
* file systems attempt to use them for mounting.
|
||||||
|
*/
|
||||||
|
SetFlag(FspFsctlDiskDeviceObject->Flags, DO_LOW_PRIORITY_FILESYSTEM);
|
||||||
|
#endif
|
||||||
|
|
||||||
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
|
||||||
ASSERT(STATUS_SUCCESS == Result);
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
|
||||||
|
@ -725,13 +725,13 @@ exit /b 0
|
|||||||
|
|
||||||
:sample-passthrough-fuse3-x64
|
:sample-passthrough-fuse3-x64
|
||||||
call :__run_sample_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 winfsp-tests-x64 ^
|
call :__run_sample_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 winfsp-tests-x64 ^
|
||||||
"-create_fileattr_test -setfileinfo_test"
|
"-create_fileattr_test -create_readonlydir_test -setfileinfo_test"
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:sample-passthrough-fuse3-x86
|
:sample-passthrough-fuse3-x86
|
||||||
call :__run_sample_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 winfsp-tests-x86 ^
|
call :__run_sample_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 winfsp-tests-x86 ^
|
||||||
"-create_fileattr_test -setfileinfo_test"
|
"-create_fileattr_test -create_readonlydir_test -setfileinfo_test"
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
@ -923,7 +923,7 @@ cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
|||||||
L:
|
L:
|
||||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%3.exe" ^
|
"%ProjRoot%\build\VStudio\build\%Configuration%\%3.exe" ^
|
||||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||||
-create_fileattr_test -create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
-create_fileattr_test -create_readonlydir_test -create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||||
-getfileinfo_name_test -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
-getfileinfo_name_test -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||||
-reparse* -stream*
|
-reparse* -stream*
|
||||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||||
|
@ -783,10 +783,8 @@ namespace memfs
|
|||||||
if (null != FileNode.MainFileNode)
|
if (null != FileNode.MainFileNode)
|
||||||
FileNode = FileNode.MainFileNode;
|
FileNode = FileNode.MainFileNode;
|
||||||
|
|
||||||
FileNode.FileSecurity = ModifySecurityDescriptor(
|
return ModifySecurityDescriptorEx(FileNode.FileSecurity, Sections, SecurityDescriptor,
|
||||||
FileNode.FileSecurity, Sections, SecurityDescriptor);
|
ref FileNode.FileSecurity);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Boolean ReadDirectoryEntry(
|
public override Boolean ReadDirectoryEntry(
|
||||||
|
@ -352,6 +352,68 @@ static void create_fileattr_test(void)
|
|||||||
create_fileattr_dotest(MemfsNet, L"\\\\memfs\\share");
|
create_fileattr_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void create_readonlydir_dotest(ULONG Flags, PWSTR Prefix)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start(Flags);
|
||||||
|
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOLEAN Success;
|
||||||
|
DWORD FileAttributes;
|
||||||
|
WCHAR DirPath[MAX_PATH], FilePath[MAX_PATH];
|
||||||
|
|
||||||
|
StringCbPrintfW(DirPath, sizeof DirPath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0\\file0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Success = CreateDirectoryW(DirPath, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
Success = SetFileAttributesW(DirPath, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
FileAttributes = GetFileAttributesW(DirPath);
|
||||||
|
ASSERT((FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY) == FileAttributes);
|
||||||
|
|
||||||
|
Handle = CreateFileW(FilePath,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
Success = DeleteFileW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
Success = RemoveDirectoryW(DirPath);
|
||||||
|
ASSERT(!Success);
|
||||||
|
ASSERT(ERROR_ACCESS_DENIED == GetLastError());
|
||||||
|
|
||||||
|
Success = SetFileAttributesW(DirPath, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
FileAttributes = GetFileAttributesW(DirPath);
|
||||||
|
ASSERT(FILE_ATTRIBUTE_DIRECTORY == FileAttributes);
|
||||||
|
|
||||||
|
Success = RemoveDirectoryW(DirPath);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_readonlydir_test(void)
|
||||||
|
{
|
||||||
|
if (NtfsTests)
|
||||||
|
{
|
||||||
|
WCHAR DirBuf[MAX_PATH];
|
||||||
|
GetTestDirectory(DirBuf);
|
||||||
|
create_readonlydir_dotest(-1, DirBuf);
|
||||||
|
}
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
create_readonlydir_dotest(MemfsDisk, 0);
|
||||||
|
if (WinFspNetTests)
|
||||||
|
create_readonlydir_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||||
|
}
|
||||||
|
|
||||||
void create_related_dotest(ULONG Flags, PWSTR Prefix)
|
void create_related_dotest(ULONG Flags, PWSTR Prefix)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start(Flags);
|
void *memfs = memfs_start(Flags);
|
||||||
@ -1265,6 +1327,7 @@ void create_tests(void)
|
|||||||
{
|
{
|
||||||
TEST(create_test);
|
TEST(create_test);
|
||||||
TEST(create_fileattr_test);
|
TEST(create_fileattr_test);
|
||||||
|
TEST(create_readonlydir_test);
|
||||||
TEST(create_related_test);
|
TEST(create_related_test);
|
||||||
TEST(create_allocation_test);
|
TEST(create_allocation_test);
|
||||||
TEST(create_sd_test);
|
TEST(create_sd_test);
|
||||||
|
Reference in New Issue
Block a user