wslinux support: ATOMIC_CREATE_ECP_CONTEXT

This commit is contained in:
Bill Zissimopoulos 2019-04-27 15:30:57 -07:00
parent 195f3bf92d
commit c01402443d
12 changed files with 250 additions and 59 deletions

View File

@ -168,7 +168,8 @@ enum
/* additional kernel-mode flags */\
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
UINT32 KmReservedFlags:6;\
UINT32 WslFeatures:1; /* support features required for WSLinux */\
UINT32 KmReservedFlags:5;\
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
@ -277,7 +278,7 @@ typedef struct
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes buffer */
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes or reparse point buffer */
UINT32 UserMode:1; /* request originated in user mode */
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
UINT32 HasBackupPrivilege:1; /* requestor has TOKEN_HAS_BACKUP_PRIVILEGE */
@ -286,6 +287,7 @@ typedef struct
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
UINT32 HasTrailingBackslash:1; /* FileName had trailing backslash */
UINT32 AcceptsSecurityDescriptor:1;
UINT32 EaIsReparsePoint:1; /* Ea buffer is reparse point */
UINT32 ReservedFlags:24;
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
} Create;

View File

@ -912,7 +912,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
/**
* Create new file or directory.
*
* This function works like Create, except that it also accepts EA (extended attributes).
* This function works like Create, except that it also accepts an extra buffer that
* may contain extended attributes or a reparse point.
*
* NOTE: If both Create and CreateEx are defined, CreateEx takes precedence.
*
@ -941,10 +942,12 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* Windows GetSecurityDescriptorLength API. Will be NULL for named streams.
* @param AllocationSize
* Allocation size for the newly created file.
* @param Ea
* Extended attributes buffer.
* @param EaLength
* Extended attributes buffer length.
* @param ExtraBuffer
* Extended attributes or reparse point buffer.
* @param ExtraLength
* Extended attributes or reparse point buffer length.
* @param ExtraBufferIsReparsePoint
* FALSE: extra buffer is extended attributes; TRUE: extra buffer is reparse point.
* @param PFileContext [out]
* Pointer that will receive the file context on successful return from this call.
* @param FileInfo [out]
@ -956,7 +959,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
NTSTATUS (*CreateEx)(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
PVOID ExtraBuffer, ULONG ExtraLength, BOOLEAN ExtraBufferIsReparsePoint,
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo);
/**
* Overwrite a file.

View File

@ -443,6 +443,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
0 != Request->Req.Create.Ea.Size ?
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
Request->Req.Create.Ea.Size,
Request->Req.Create.EaIsReparsePoint,
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
else
Result = FileSystem->Interface->Create(FileSystem,
@ -590,6 +591,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
0 != Request->Req.Create.Ea.Size ?
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
Request->Req.Create.Ea.Size,
Request->Req.Create.EaIsReparsePoint,
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
else
Result = FileSystem->Interface->Create(FileSystem,
@ -724,6 +726,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
0 != Request->Req.Create.Ea.Size ?
(PVOID)(Request->Buffer + Request->Req.Create.Ea.Offset) : 0,
Request->Req.Create.Ea.Size,
Request->Req.Create.EaIsReparsePoint,
AddrOfFileContext(FullContext), &OpenFileInfo.FileInfo);
else
Result = FileSystem->Interface->Create(FileSystem,

View File

@ -752,7 +752,7 @@ exit:
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
PVOID ExtraBuffer, ULONG ExtraLength, BOOLEAN ExtraBufferIsReparsePoint,
PVOID *PFileDesc, FSP_FSCTL_FILE_INFO *FileInfo)
{
struct fuse *f = FileSystem->UserContext;
@ -766,12 +766,21 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
int err;
NTSTATUS Result;
if (0 != Ea)
if (0 != ExtraBuffer)
{
if (0 == f->ops.listxattr || 0 == f->ops.getxattr ||
0 == f->ops.setxattr || 0 == f->ops.removexattr)
if (!ExtraBufferIsReparsePoint)
{
Result = STATUS_EAS_NOT_SUPPORTED;
if (0 == f->ops.listxattr || 0 == f->ops.getxattr ||
0 == f->ops.setxattr || 0 == f->ops.removexattr)
{
Result = STATUS_EAS_NOT_SUPPORTED;
goto exit;
}
}
else
{
/* !!!: revisit */
Result = STATUS_INVALID_PARAMETER;
goto exit;
}
}
@ -889,12 +898,21 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
goto exit;
}
if (0 != Ea)
if (0 != ExtraBuffer)
{
Result = FspFileSystemEnumerateEa(FileSystem,
fsp_fuse_intf_SetEaEntry, contexthdr->PosixPath, Ea, EaLength);
if (!NT_SUCCESS(Result))
if (!ExtraBufferIsReparsePoint)
{
Result = FspFileSystemEnumerateEa(FileSystem,
fsp_fuse_intf_SetEaEntry, contexthdr->PosixPath, ExtraBuffer, ExtraLength);
if (!NT_SUCCESS(Result))
goto exit;
}
else
{
/* !!!: revisit: WslFeatures, GetFileInfoFunnel, GetReparsePointEx, SetReparsePoint */
Result = STATUS_INVALID_PARAMETER;
goto exit;
}
}
/*
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.

View File

@ -1085,8 +1085,9 @@ namespace Fsp
UInt32 FileAttributes,
Byte[] SecurityDescriptor,
UInt64 AllocationSize,
IntPtr Ea,
UInt32 EaLength,
IntPtr ExtraBuffer,
UInt32 ExtraLength,
Boolean ExtraBufferIsReparsePoint,
out Object FileNode,
out Object FileDesc,
out FileInfo FileInfo,
@ -1391,6 +1392,16 @@ namespace Fsp
}
}
/// <summary>
/// Makes a byte array that contains a reparse point.
/// </summary>
/// <returns>The reparse point byte array.</returns>
public static Byte[] MakeReparsePoint(
IntPtr Buffer,
UInt32 Size)
{
return Api.MakeReparsePoint(Buffer, (UIntPtr)Size);
}
/// <summary>
/// Gets the reparse tag from reparse data.
/// </summary>
/// <param name="ReparseData">

View File

@ -221,6 +221,11 @@ namespace Fsp
get { return 0 != (_VolumeParams.Flags & VolumeParams.AllowOpenInKernelMode); }
set { _VolumeParams.Flags |= (value ? VolumeParams.AllowOpenInKernelMode : 0); }
}
public Boolean WslFeatures
{
get { return 0 != (_VolumeParams.Flags & VolumeParams.WslFeatures); }
set { _VolumeParams.Flags |= (value ? VolumeParams.WslFeatures : 0); }
}
/// <summary>
/// Gets or sets the prefix for a network file system.
/// </summary>
@ -472,8 +477,9 @@ namespace Fsp
UInt32 FileAttributes,
IntPtr SecurityDescriptor,
UInt64 AllocationSize,
IntPtr Ea,
UInt32 EaLength,
IntPtr ExtraBuffer,
UInt32 ExtraLength,
Boolean ExtraBufferIsReparsePoint,
ref FullContext FullContext,
ref OpenFileInfo OpenFileInfo)
{
@ -490,8 +496,9 @@ namespace Fsp
FileAttributes,
Api.MakeSecurityDescriptor(SecurityDescriptor),
AllocationSize,
Ea,
EaLength,
ExtraBuffer,
ExtraLength,
ExtraBufferIsReparsePoint,
out FileNode,
out FileDesc,
out OpenFileInfo.FileInfo,

View File

@ -53,6 +53,7 @@ namespace Fsp.Interop
internal const UInt32 UmFileContextIsFullContext = 0x00020000;
internal const UInt32 AllowOpenInKernelMode = 0x01000000;
internal const UInt32 CasePreservedExtendedAttributes = 0x02000000;
internal const UInt32 WslFeatures = 0x04000000;
internal const int PrefixSize = 192;
internal const int FileSystemNameSize = 16;
@ -557,8 +558,9 @@ namespace Fsp.Interop
UInt32 FileAttributes,
IntPtr SecurityDescriptor,
UInt64 AllocationSize,
IntPtr Ea,
UInt32 EaLength,
IntPtr ExtraBuffer,
UInt32 ExtraLength,
[MarshalAs(UnmanagedType.U1)] Boolean ExtraBufferIsReparsePoint,
ref FullContext FullContext,
ref OpenFileInfo OpenFileInfo);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]

View File

@ -29,7 +29,7 @@ static NTSTATUS FspFsvolCreate(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolCreateNoLock(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN MainFileOpen);
BOOLEAN MainFileOpen, PFSP_ATOMIC_CREATE_ECP_CONTEXT AtomicCreateEcp);
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
@ -144,6 +144,7 @@ static NTSTATUS FspFsvolCreate(
PECP_LIST ExtraCreateParameters;
PVOID ExtraCreateParameter;
BOOLEAN MainFileOpen = FALSE;
PFSP_ATOMIC_CREATE_ECP_CONTEXT AtomicCreateEcp = 0;
/*
* Check if the IRP has ECP's.
@ -219,6 +220,21 @@ static NTSTATUS FspFsvolCreate(
}
}
#endif
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.WslFeatures)
{
// {4720bd83-52ac-4104-a130-d1ec6a8cc8e5}
static const GUID FspAtomicCreateEcpGuid =
{ 0x4720bd83, 0x52ac, 0x4104, { 0xa1, 0x30, 0xd1, 0xec, 0x6a, 0x8c, 0xc8, 0xe5 } };
ExtraCreateParameter = 0;
AtomicCreateEcp =
NT_SUCCESS(FsRtlFindExtraCreateParameter(ExtraCreateParameters,
&FspAtomicCreateEcpGuid, &ExtraCreateParameter, 0)) &&
0 != ExtraCreateParameter &&
!FsRtlIsEcpFromUserMode(ExtraCreateParameter) ?
ExtraCreateParameter : 0;
}
}
if (!MainFileOpen)
@ -226,7 +242,8 @@ static NTSTATUS FspFsvolCreate(
FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject);
try
{
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp, FALSE);
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp,
MainFileOpen, AtomicCreateEcp);
}
finally
{
@ -235,14 +252,15 @@ static NTSTATUS FspFsvolCreate(
}
}
else
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp, TRUE);
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp,
MainFileOpen, AtomicCreateEcp);
return Result;
}
static NTSTATUS FspFsvolCreateNoLock(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN MainFileOpen)
BOOLEAN MainFileOpen, PFSP_ATOMIC_CREATE_ECP_CONTEXT AtomicCreateEcp)
{
PAGED_CODE();
@ -279,6 +297,8 @@ static NTSTATUS FspFsvolCreateNoLock(
USHORT ShareAccess = IrpSp->Parameters.Create.ShareAccess;
PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG EaLength = IrpSp->Parameters.Create.EaLength;
PVOID ExtraBuffer = 0;
ULONG ExtraLength = 0;
ULONG Flags = IrpSp->Flags;
KPROCESSOR_MODE RequestorMode =
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
@ -292,6 +312,7 @@ static NTSTATUS FspFsvolCreateNoLock(
BOOLEAN HasRestorePrivilege =
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_RESTORE_PRIVILEGE);
BOOLEAN HasTrailingBackslash = FALSE;
BOOLEAN EaIsReparsePoint = FALSE;
FSP_FILE_NODE *FileNode, *RelatedFileNode;
FSP_FILE_DESC *FileDesc;
UNICODE_STRING MainFileName = { 0 }, StreamPart = { 0 };
@ -302,6 +323,36 @@ static NTSTATUS FspFsvolCreateNoLock(
if (FlagOn(CreateOptions, FILE_OPEN_BY_FILE_ID))
return STATUS_NOT_IMPLEMENTED;
/* is there an AtomicCreateEcp attached? */
if (0 != AtomicCreateEcp)
{
if ((FILE_CREATE != CreateDisposition && FILE_OPEN_IF != CreateDisposition) ||
0 != EaBuffer ||
RTL_SIZEOF_THROUGH_FIELD(FSP_ATOMIC_CREATE_ECP_CONTEXT, ReparseBuffer) >
AtomicCreateEcp->Size ||
/* !!!: revisit: FlagOn*/
!FlagOn(AtomicCreateEcp->InFlags,
ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT |
ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED))
return STATUS_INVALID_PARAMETER; /* docs do not say what to return on failure! */
if (FlagOn(AtomicCreateEcp->InFlags,
ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED))
{
Result = FsRtlValidateReparsePointBuffer(AtomicCreateEcp->ReparseBufferLength,
AtomicCreateEcp->ReparseBuffer);
if (!NT_SUCCESS(Result))
return Result;
/* mark that we satisfied the reparse point request, although we may fail it later! */
AtomicCreateEcp->OutFlags = ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET;
ExtraBuffer = AtomicCreateEcp->ReparseBuffer;
ExtraLength = AtomicCreateEcp->ReparseBufferLength;
EaIsReparsePoint = TRUE;
}
}
/* was an EA buffer specified? */
if (0 != EaBuffer)
{
@ -318,6 +369,9 @@ static NTSTATUS FspFsvolCreateNoLock(
EaBuffer, EaLength, (PULONG)&Irp->IoStatus.Information);
if (!NT_SUCCESS(Result))
return Result;
ExtraBuffer = EaBuffer;
ExtraLength = EaLength;
}
/* cannot open a paging file */
@ -555,9 +609,9 @@ static NTSTATUS FspFsvolCreateNoLock(
SecurityDescriptorSize = 0;
FileAttributes = 0;
/* cannot set EA on named stream */
EaBuffer = 0;
EaLength = 0;
/* cannot set extra buffer on named stream */
ExtraBuffer = 0;
ExtraLength = 0;
/* remember the main file node */
ASSERT(0 == FileNode->MainFileNode);
@ -577,8 +631,8 @@ static NTSTATUS FspFsvolCreateNoLock(
/* create the user-mode file system request */
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
0 != EaBuffer ?
FSP_FSCTL_DEFAULT_ALIGN_UP(SecurityDescriptorSize) + EaLength : SecurityDescriptorSize,
0 != ExtraBuffer ?
FSP_FSCTL_DEFAULT_ALIGN_UP(SecurityDescriptorSize) + ExtraLength : SecurityDescriptorSize,
FspFsvolCreateRequestFini, &Request);
if (!NT_SUCCESS(Result))
{
@ -616,10 +670,10 @@ static NTSTATUS FspFsvolCreateNoLock(
Request->Req.Create.DesiredAccess = DesiredAccess;
Request->Req.Create.GrantedAccess = GrantedAccess;
Request->Req.Create.ShareAccess = ShareAccess;
Request->Req.Create.Ea.Offset = 0 != EaBuffer ?
Request->Req.Create.Ea.Offset = 0 != ExtraBuffer ?
(0 != Request->Req.Create.SecurityDescriptor.Offset ?
NEXTOFS(Request->Req.Create.SecurityDescriptor) : NEXTOFS(Request->FileName)) : 0;
Request->Req.Create.Ea.Size = 0 != EaBuffer ? (UINT16)EaLength : 0;
Request->Req.Create.Ea.Size = 0 != ExtraBuffer ? (UINT16)ExtraLength : 0;
Request->Req.Create.UserMode = UserMode == RequestorMode;
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
Request->Req.Create.HasBackupPrivilege = HasBackupPrivilege;
@ -628,10 +682,10 @@ static NTSTATUS FspFsvolCreateNoLock(
Request->Req.Create.CaseSensitive = CaseSensitive;
Request->Req.Create.HasTrailingBackslash = HasTrailingBackslash;
Request->Req.Create.NamedStream = MainFileName.Length;
#undef NEXTOFS
Request->Req.Create.AcceptsSecurityDescriptor = 0 == Request->Req.Create.NamedStream &&
!!FsvolDeviceExtension->VolumeParams.AllowOpenInKernelMode;
Request->Req.Create.EaIsReparsePoint = EaIsReparsePoint;
#undef NEXTOFS
ASSERT(
0 == StreamPart.Length && 0 == MainFileName.Length ||
@ -642,10 +696,10 @@ static NTSTATUS FspFsvolCreateNoLock(
RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
SecurityDescriptor, SecurityDescriptorSize);
/* copy the EA buffer (if any) into the request */
if (0 != EaBuffer)
/* copy the extra buffer (if any) into the request */
if (0 != ExtraBuffer)
RtlCopyMemory(Request->Buffer + Request->Req.Create.Ea.Offset,
EaBuffer, EaLength);
ExtraBuffer, ExtraLength);
/* fix FileNode->FileName if we are doing SL_OPEN_TARGET_DIRECTORY */
if (Request->Req.Create.OpenTargetDirectory)

View File

@ -1678,4 +1678,39 @@ typedef struct
ULONG LxDeviceIdMajor;
ULONG LxDeviceIdMinor;
} FSP_FILE_STAT_LX_INFORMATION, *PFSP_FILE_STAT_LX_INFORMATION;
/* ATOMIC_CREATE_ECP_CONTEXT is missing on some WDK's */
#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED 0x0002
#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET 0x0002
#define ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT 0x0100
typedef struct
{
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
} FSP_FILE_TIMESTAMPS, *PFSP_FILE_TIMESTAMPS;
typedef struct
{
USHORT Size;
USHORT InFlags;
USHORT OutFlags;
USHORT ReparseBufferLength;
PREPARSE_DATA_BUFFER ReparseBuffer;
LONGLONG FileSize;
LONGLONG ValidDataLength;
PFSP_FILE_TIMESTAMPS FileTimestamps;
ULONG FileAttributes;
ULONG UsnSourceInfo;
USN Usn;
ULONG SuppressFileAttributeInheritanceMask;
ULONG InOpFlags;
ULONG OutOpFlags;
ULONG InGenFlags;
ULONG OutGenFlags;
ULONG CaseSensitiveFlagsMask;
ULONG InCaseSensitiveFlags;
ULONG OutCaseSensitiveFlags;
} FSP_ATOMIC_CREATE_ECP_CONTEXT, *PFSP_ATOMIC_CREATE_ECP_CONTEXT;
#endif

View File

@ -981,10 +981,16 @@ static NTSTATUS FspFsvolQueryInformation(
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, 0);
break;
case 68/*FileStatInformation*/:
Result = FspFsvolQueryStatBaseInformation(FileObject, &Buffer, BufferEnd, 0);
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.WslFeatures)
Result = FspFsvolQueryStatBaseInformation(FileObject, &Buffer, BufferEnd, 0);
else
Result = STATUS_INVALID_PARAMETER;
break;
case 70/*FileStatLxInformation*/:
Result = FspFsvolQueryStatLxBaseInformation(FileObject, &Buffer, BufferEnd, 0);
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.WslFeatures)
Result = FspFsvolQueryStatLxBaseInformation(FileObject, &Buffer, BufferEnd, 0);
else
Result = STATUS_INVALID_PARAMETER;
break;
default:
Result = STATUS_INVALID_PARAMETER;

View File

@ -274,6 +274,7 @@ namespace memfs
Host.PostCleanupWhenModifiedOnly = true;
Host.PassQueryDirectoryFileName = true;
Host.ExtendedAttributes = true;
Host.WslFeatures = true;
return STATUS_SUCCESS;
}
@ -331,8 +332,9 @@ namespace memfs
UInt32 FileAttributes,
Byte[] SecurityDescriptor,
UInt64 AllocationSize,
IntPtr Ea,
UInt32 EaLength,
IntPtr ExtraBuffer,
UInt32 ExtraLength,
Boolean ExtraBufferIsReparsePoint,
out Object FileNode0,
out Object FileDesc,
out FileInfo FileInfo,
@ -369,11 +371,21 @@ namespace memfs
FileNode.FileInfo.FileAttributes = 0 != (FileAttributes & (UInt32)System.IO.FileAttributes.Directory) ?
FileAttributes : FileAttributes | (UInt32)System.IO.FileAttributes.Archive;
FileNode.FileSecurity = SecurityDescriptor;
if (IntPtr.Zero != Ea)
if (IntPtr.Zero != ExtraBuffer)
{
Result = SetEaEntries(FileNode, null, Ea, EaLength);
if (0 > Result)
return Result;
if (!ExtraBufferIsReparsePoint)
{
Result = SetEaEntries(FileNode, null, ExtraBuffer, ExtraLength);
if (0 > Result)
return Result;
}
else
{
Byte[] ReparseData = MakeReparsePoint(ExtraBuffer, ExtraLength);
FileNode.FileInfo.FileAttributes |= (UInt32)System.IO.FileAttributes.ReparsePoint;
FileNode.FileInfo.ReparseTag = GetReparseTag(ReparseData);
FileNode.ReparseData = ReparseData;
}
}
if (0 != AllocationSize)
{

View File

@ -70,6 +70,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
#define MEMFS_EA
/*
* Define the MEMFS_WSL macro to include WSLinux support.
*/
#define MEMFS_WSL
/*
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
* a check for the Write buffer to ensure that it is read-only.
*
@ -1047,8 +1052,8 @@ static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
#if defined(MEMFS_EA)
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
PVOID ExtraBuffer, ULONG ExtraLength, BOOLEAN ExtraBufferIsReparsePoint,
#endif
PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo)
{
@ -1129,15 +1134,43 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
}
#if defined(MEMFS_EA)
if (0 != Ea)
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
if (0 != ExtraBuffer)
{
Result = FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode, Ea, EaLength);
if (!NT_SUCCESS(Result))
#if defined(MEMFS_EA)
if (!ExtraBufferIsReparsePoint)
{
MemfsFileNodeDelete(FileNode);
return Result;
Result = FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode,
(PFILE_FULL_EA_INFORMATION)ExtraBuffer, ExtraLength);
if (!NT_SUCCESS(Result))
{
MemfsFileNodeDelete(FileNode);
return Result;
}
}
#endif
#if defined(MEMFS_WSL)
if (ExtraBufferIsReparsePoint)
{
#if defined(MEMFS_REPARSE_POINTS)
FileNode->ReparseDataSize = ExtraLength;
FileNode->ReparseData = malloc(ExtraLength);
if (0 == FileNode->ReparseData && 0 != ExtraLength)
{
MemfsFileNodeDelete(FileNode);
return STATUS_INSUFFICIENT_RESOURCES;
}
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
FileNode->FileInfo.ReparseTag = *(PULONG)ExtraBuffer;
/* the first field in a reparse buffer is the reparse tag */
memcpy(FileNode->ReparseData, ExtraBuffer, ExtraLength);
#else
MemfsFileNodeDelete(FileNode);
return STATUS_INVALID_PARAMETER;
#endif
}
#endif
}
#endif
@ -2189,7 +2222,7 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
GetVolumeInfo,
SetVolumeLabel,
GetSecurityByName,
#if defined(MEMFS_EA)
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
0,
#else
Create,
@ -2240,8 +2273,10 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
0,
#endif
0,
#if defined(MEMFS_EA)
#if defined(MEMFS_EA) || defined(MEMFS_WSL)
Create,
#endif
#if defined(MEMFS_EA)
Overwrite,
GetEa,
SetEa
@ -2347,6 +2382,9 @@ NTSTATUS MemfsCreateFunnel(
#endif
#if defined(MEMFS_EA)
VolumeParams.ExtendedAttributes = 1;
#endif
#if defined(MEMFS_WSL)
VolumeParams.WslFeatures = 1;
#endif
VolumeParams.AllowOpenInKernelMode = 1;
if (0 != VolumePrefix)