mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
tst: memfs: extended attributes support
This commit is contained in:
parent
58c6708123
commit
d8686a7726
@ -88,6 +88,9 @@ typedef struct _REPARSE_DATA_BUFFER
|
||||
/*
|
||||
* The FILE_FULL_EA_INFORMATION definitions are missing from the user mode headers.
|
||||
*/
|
||||
#if !defined(FILE_NEED_EA)
|
||||
#define FILE_NEED_EA 0x00000080
|
||||
#endif
|
||||
typedef struct _FILE_FULL_EA_INFORMATION
|
||||
{
|
||||
ULONG NextEntryOffset;
|
||||
@ -953,7 +956,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, SIZE_T EaLength,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
||||
PVOID *PFileContext, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
/**
|
||||
* Overwrite a file.
|
||||
@ -985,7 +988,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
*/
|
||||
NTSTATUS (*OverwriteEx)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize,
|
||||
PFILE_FULL_EA_INFORMATION Ea, SIZE_T EaLength,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
/**
|
||||
* Get extended attributes.
|
||||
@ -996,16 +999,19 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
* The file context of the file to get extended attributes for.
|
||||
* @param Ea
|
||||
* Extended attributes buffer.
|
||||
* @param EaLength [in,out]
|
||||
* @param EaLength
|
||||
* Extended attributes buffer length.
|
||||
* @param PBytesTransferred [out]
|
||||
* Pointer to a memory location that will receive the actual number of bytes transferred.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code.
|
||||
* @see
|
||||
* SetEa
|
||||
* FspFileSystemAddEa
|
||||
*/
|
||||
NTSTATUS (*GetEa)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext,
|
||||
PFILE_FULL_EA_INFORMATION Ea, PSIZE_T PEaLength);
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength, PULONG PBytesTransferred);
|
||||
/**
|
||||
* Set extended attributes.
|
||||
*
|
||||
@ -1024,7 +1030,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
*/
|
||||
NTSTATUS (*SetEa)(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext,
|
||||
PFILE_FULL_EA_INFORMATION Ea, SIZE_T EaLength);
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength);
|
||||
|
||||
/*
|
||||
* This ensures that this interface will always contain 64 function pointers.
|
||||
@ -1568,6 +1574,56 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
|
||||
*/
|
||||
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||
/**
|
||||
* Enumerate extended attributes in a buffer.
|
||||
*
|
||||
* This is a helper for implementing the CreateEx and SetEa operations in file systems
|
||||
* that support extended attributes.
|
||||
*
|
||||
* @param FileSystem
|
||||
* The file system object.
|
||||
* @param EnumerateEa
|
||||
* Pointer to function that receives a single extended attribute. The function
|
||||
* should return STATUS_SUCCESS or an error code if unsuccessful.
|
||||
* @param Context
|
||||
* User context to supply to EnumEa.
|
||||
* @param Ea
|
||||
* Extended attributes buffer.
|
||||
* @param EaLength
|
||||
* Extended attributes buffer length.
|
||||
* @return
|
||||
* STATUS_SUCCESS or error code from EnumerateEa.
|
||||
*/
|
||||
FSP_API NTSTATUS FspFileSystemEnumerateEa(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS (*EnumerateEa)(
|
||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||
PFILE_FULL_EA_INFORMATION SingleEa),
|
||||
PVOID Context,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength);
|
||||
/**
|
||||
* Add extended attribute to a buffer.
|
||||
*
|
||||
* This is a helper for implementing the GetEa operation.
|
||||
*
|
||||
* @param SingleEa
|
||||
* The extended attribute to add. A value of NULL acts as an EOF marker for a GetEa
|
||||
* operation.
|
||||
* @param Ea
|
||||
* Pointer to a buffer that will receive the extended attribute. This should contain
|
||||
* the same value passed to the GetEa Ea parameter.
|
||||
* @param EaLength
|
||||
* Length of buffer. This should contain the same value passed to the GetEa
|
||||
* EaLength parameter.
|
||||
* @param PBytesTransferred [out]
|
||||
* Pointer to a memory location that will receive the actual number of bytes stored. This should
|
||||
* contain the same value passed to the GetEa PBytesTransferred parameter.
|
||||
* @return
|
||||
* TRUE if the extended attribute was added, FALSE if there was not enough space to add it.
|
||||
* @see
|
||||
* GetEa
|
||||
*/
|
||||
FSP_API BOOLEAN FspFileSystemAddEa(PFILE_FULL_EA_INFORMATION SingleEa,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength, PULONG PBytesTransferred);
|
||||
|
||||
/*
|
||||
* Directory buffering
|
||||
|
@ -1187,21 +1187,21 @@ FSP_API NTSTATUS FspFileSystemOpQueryEa(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
SIZE_T EaSize;
|
||||
ULONG BytesTransferred;
|
||||
|
||||
if (0 == FileSystem->Interface->GetEa)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
EaSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
|
||||
BytesTransferred = 0;
|
||||
Result = FileSystem->Interface->GetEa(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.QueryEa),
|
||||
(PVOID)Response->Buffer, &EaSize);
|
||||
(PVOID)Response->Buffer, FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX, &BytesTransferred);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_EA_LIST_INCONSISTENT;
|
||||
|
||||
Response->Size = (UINT16)(sizeof *Response + EaSize);
|
||||
Response->Size = (UINT16)(sizeof *Response + BytesTransferred);
|
||||
Response->Rsp.QueryEa.Ea.Offset = 0;
|
||||
Response->Rsp.QueryEa.Ea.Size = (UINT16)EaSize;
|
||||
Response->Rsp.QueryEa.Ea.Size = (UINT16)BytesTransferred;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1797,3 +1797,55 @@ FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
||||
{
|
||||
return FspFileSystemAddXxxInfo(StreamInfo, Buffer, Length, PBytesTransferred);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemEnumerateEa(FSP_FILE_SYSTEM *FileSystem,
|
||||
NTSTATUS (*EnumerateEa)(
|
||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||
PFILE_FULL_EA_INFORMATION SingleEa),
|
||||
PVOID Context,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
||||
{
|
||||
PFILE_FULL_EA_INFORMATION EaEnd = (PVOID)((PUINT8)Ea + EaLength);
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
for (;
|
||||
EaEnd > Ea && 0 != Ea->NextEntryOffset;
|
||||
Ea = (PVOID)((PUINT8)Ea + Ea->NextEntryOffset))
|
||||
{
|
||||
Result = EnumerateEa(FileSystem, Context, Ea);
|
||||
if (!NT_SUCCESS(Result))
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API BOOLEAN FspFileSystemAddEa(PFILE_FULL_EA_INFORMATION SingleEa,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG Length, PULONG PBytesTransferred)
|
||||
{
|
||||
if (0 != SingleEa)
|
||||
{
|
||||
PUINT8 EaEnd = (PUINT8)Ea + Length;
|
||||
ULONG EaLength = sizeof *SingleEa + SingleEa->EaNameLength + SingleEa->EaValueLength;
|
||||
|
||||
Ea = (PVOID)((PUINT8)Ea + *PBytesTransferred);
|
||||
if ((PUINT8)Ea + EaLength > EaEnd)
|
||||
return FALSE;
|
||||
|
||||
memcpy(Ea, SingleEa, EaLength);
|
||||
Ea->NextEntryOffset = FSP_FSCTL_ALIGN_UP(EaLength, sizeof(ULONG));
|
||||
*PBytesTransferred += EaLength;
|
||||
}
|
||||
else if (sizeof *SingleEa <= *PBytesTransferred)
|
||||
{
|
||||
PUINT8 EaEnd = (PUINT8)Ea + *PBytesTransferred;
|
||||
|
||||
while (EaEnd > (PUINT8)Ea + Ea->NextEntryOffset)
|
||||
Ea = (PVOID)((PUINT8)Ea + Ea->NextEntryOffset);
|
||||
|
||||
Ea->NextEntryOffset = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -64,6 +64,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
||||
*/
|
||||
#define MEMFS_CONTROL
|
||||
|
||||
/*
|
||||
* Define the MEMFS_EA macro to include extended attributes support.
|
||||
*/
|
||||
#define MEMFS_EA
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -237,6 +242,36 @@ BOOLEAN MemfsFileNameHasPrefix(PWSTR a, PWSTR b, BOOLEAN CaseInsensitive)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MEMFS_EA)
|
||||
static inline
|
||||
int MemfsEaNameCompare(PSTR a, PSTR b)
|
||||
{
|
||||
/* EA names are always case-insensitive in MEMFS (to be inline with NTFS) */
|
||||
|
||||
int res;
|
||||
|
||||
res = CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE, a, -1, b, -1);
|
||||
if (0 != res)
|
||||
res -= 2;
|
||||
else
|
||||
res = _stricmp(a, b);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct MEMFS_FILE_NODE_EA_LESS
|
||||
{
|
||||
MEMFS_FILE_NODE_EA_LESS()
|
||||
{
|
||||
}
|
||||
bool operator()(PSTR a, PSTR b) const
|
||||
{
|
||||
return 0 > MemfsEaNameCompare(a, b);
|
||||
}
|
||||
};
|
||||
typedef std::map<PSTR, FILE_FULL_EA_INFORMATION *, MEMFS_FILE_NODE_EA_LESS> MEMFS_FILE_NODE_EA_MAP;
|
||||
#endif
|
||||
|
||||
typedef struct _MEMFS_FILE_NODE
|
||||
{
|
||||
WCHAR FileName[MEMFS_MAX_PATH];
|
||||
@ -252,6 +287,9 @@ typedef struct _MEMFS_FILE_NODE
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
struct _MEMFS_FILE_NODE *MainFileNode;
|
||||
#endif
|
||||
#if defined(MEMFS_EA)
|
||||
MEMFS_FILE_NODE_EA_MAP *EaMap;
|
||||
#endif
|
||||
} MEMFS_FILE_NODE;
|
||||
|
||||
struct MEMFS_FILE_NODE_LESS
|
||||
@ -311,6 +349,15 @@ NTSTATUS MemfsFileNodeCreate(PWSTR FileName, MEMFS_FILE_NODE **PFileNode)
|
||||
static inline
|
||||
VOID MemfsFileNodeDelete(MEMFS_FILE_NODE *FileNode)
|
||||
{
|
||||
#if defined(MEMFS_EA)
|
||||
if (0 != FileNode->EaMap)
|
||||
{
|
||||
for (MEMFS_FILE_NODE_EA_MAP::iterator p = FileNode->EaMap->begin(), q = FileNode->EaMap->end();
|
||||
p != q; ++p)
|
||||
free(p->second);
|
||||
delete FileNode->EaMap;
|
||||
}
|
||||
#endif
|
||||
#if defined(MEMFS_REPARSE_POINTS)
|
||||
free(FileNode->ReparseData);
|
||||
#endif
|
||||
@ -351,6 +398,120 @@ VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *Fi
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MEMFS_EA)
|
||||
static inline
|
||||
NTSTATUS MemfsFileNodeGetEaMap(MEMFS_FILE_NODE *FileNode, MEMFS_FILE_NODE_EA_MAP **PEaMap)
|
||||
{
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
if (0 != FileNode->MainFileNode)
|
||||
FileNode = FileNode->MainFileNode;
|
||||
#endif
|
||||
|
||||
*PEaMap = FileNode->EaMap;
|
||||
if (0 != *PEaMap)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
try
|
||||
{
|
||||
*PEaMap = FileNode->EaMap = new MEMFS_FILE_NODE_EA_MAP(MEMFS_FILE_NODE_EA_LESS());
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
*PEaMap = 0;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
NTSTATUS MemfsFileNodeSetEa(
|
||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||
PFILE_FULL_EA_INFORMATION Ea)
|
||||
{
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)Context;
|
||||
MEMFS_FILE_NODE_EA_MAP *EaMap;
|
||||
FILE_FULL_EA_INFORMATION *FileNodeEa = 0;
|
||||
MEMFS_FILE_NODE_EA_MAP::iterator p;
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = MemfsFileNodeGetEaMap(FileNode, &EaMap);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
if (0 != Ea->EaValueLength)
|
||||
{
|
||||
FileNodeEa = (FILE_FULL_EA_INFORMATION *)malloc(
|
||||
sizeof *FileNodeEa + Ea->EaNameLength + Ea->EaValueLength);
|
||||
if (0 == FileNodeEa)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
memcpy(FileNodeEa, Ea, sizeof *FileNodeEa + Ea->EaNameLength + Ea->EaValueLength);
|
||||
FileNodeEa->NextEntryOffset = 0;
|
||||
}
|
||||
|
||||
p = EaMap->find(Ea->EaName);
|
||||
if (p != EaMap->end())
|
||||
{
|
||||
free(p->second);
|
||||
EaMap->erase(p);
|
||||
}
|
||||
|
||||
if (0 != Ea->EaValueLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
EaMap->insert(MEMFS_FILE_NODE_EA_MAP::value_type(FileNodeEa->EaName, FileNodeEa));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
free(FileNodeEa);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline
|
||||
BOOLEAN MemfsFileNodeNeedEa(MEMFS_FILE_NODE *FileNode)
|
||||
{
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
if (0 != FileNode->MainFileNode)
|
||||
FileNode = FileNode->MainFileNode;
|
||||
#endif
|
||||
|
||||
if (0 != FileNode->EaMap)
|
||||
{
|
||||
for (MEMFS_FILE_NODE_EA_MAP::iterator p = FileNode->EaMap->begin(), q = FileNode->EaMap->end();
|
||||
p != q; ++p)
|
||||
if (0 != (p->second->Flags & FILE_NEED_EA))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline
|
||||
BOOLEAN MemfsFileNodeEnumerateEa(MEMFS_FILE_NODE *FileNode,
|
||||
BOOLEAN (*EnumFn)(PFILE_FULL_EA_INFORMATION Ea, PVOID), PVOID Context)
|
||||
{
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
if (0 != FileNode->MainFileNode)
|
||||
FileNode = FileNode->MainFileNode;
|
||||
#endif
|
||||
|
||||
if (0 != FileNode->EaMap)
|
||||
{
|
||||
for (MEMFS_FILE_NODE_EA_MAP::iterator p = FileNode->EaMap->begin(), q = FileNode->EaMap->end();
|
||||
p != q; ++p)
|
||||
if (!EnumFn(p->second, Context))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline
|
||||
VOID MemfsFileNodeMapDump(MEMFS_FILE_NODE_MAP *FileNodeMap)
|
||||
{
|
||||
@ -869,6 +1030,9 @@ 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,
|
||||
#endif
|
||||
PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||
@ -948,6 +1112,18 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
||||
}
|
||||
|
||||
#if defined(MEMFS_EA)
|
||||
if (0 != Ea)
|
||||
{
|
||||
Result = FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode, Ea, EaLength);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
MemfsFileNodeDelete(FileNode);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FileNode->FileInfo.AllocationSize = AllocationSize;
|
||||
if (0 != FileNode->FileInfo.AllocationSize)
|
||||
{
|
||||
@ -1005,6 +1181,22 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
||||
return Result;
|
||||
}
|
||||
|
||||
#if defined(MEMFS_EA)
|
||||
/* if the OP specified no EA's check the need EA count, but only if accessing main stream */
|
||||
if (0 != (CreateOptions & FILE_NO_EA_KNOWLEDGE)
|
||||
#if defined(MEMFS_NAMED_STREAMS)
|
||||
&& (0 == FileNode->MainFileNode)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (MemfsFileNodeNeedEa(FileNode))
|
||||
{
|
||||
Result = STATUS_ACCESS_DENIED;
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MemfsFileNodeReference(FileNode);
|
||||
*PFileNode = FileNode;
|
||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||
@ -1025,6 +1217,9 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize,
|
||||
#if defined(MEMFS_EA)
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
||||
#endif
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||
@ -1047,6 +1242,15 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
MemfsFileNodeMapEnumerateFree(&Context);
|
||||
#endif
|
||||
|
||||
#if defined(MEMFS_EA)
|
||||
if (0 != Ea)
|
||||
{
|
||||
Result = FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode, Ea, EaLength);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
}
|
||||
#endif
|
||||
|
||||
Result = SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
@ -1881,7 +2085,7 @@ static NTSTATUS GetStreamInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
#if defined(MEMFS_CONTROL)
|
||||
static NTSTATUS Control(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileContext, UINT32 ControlCode,
|
||||
PVOID FileNode, UINT32 ControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength,
|
||||
PVOID OutputBuffer, ULONG OutputBufferLength, PULONG PBytesTransferred)
|
||||
{
|
||||
@ -1911,14 +2115,63 @@ static NTSTATUS Control(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MEMFS_EA)
|
||||
typedef struct _MEMFS_GET_EA_CONTEXT
|
||||
{
|
||||
PFILE_FULL_EA_INFORMATION Ea;
|
||||
ULONG EaLength;
|
||||
PULONG PBytesTransferred;
|
||||
} MEMFS_GET_EA_CONTEXT;
|
||||
|
||||
static BOOLEAN GetEaEnumFn(PFILE_FULL_EA_INFORMATION Ea, PVOID Context0)
|
||||
{
|
||||
MEMFS_GET_EA_CONTEXT *Context = (MEMFS_GET_EA_CONTEXT *)Context0;
|
||||
|
||||
return FspFileSystemAddEa(Ea,
|
||||
Context->Ea, Context->EaLength, Context->PBytesTransferred);
|
||||
}
|
||||
|
||||
static NTSTATUS GetEa(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode0,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength, PULONG PBytesTransferred)
|
||||
{
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||
MEMFS_GET_EA_CONTEXT Context;
|
||||
|
||||
Context.Ea = Ea;
|
||||
Context.EaLength = EaLength;
|
||||
Context.PBytesTransferred = PBytesTransferred;
|
||||
|
||||
if (MemfsFileNodeEnumerateEa(FileNode, GetEaEnumFn, &Context))
|
||||
FspFileSystemAddEa(0, Ea, EaLength, PBytesTransferred);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS SetEa(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode,
|
||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength)
|
||||
{
|
||||
return FspFileSystemEnumerateEa(FileSystem, MemfsFileNodeSetEa, FileNode, Ea, EaLength);
|
||||
}
|
||||
#endif
|
||||
|
||||
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||
{
|
||||
GetVolumeInfo,
|
||||
SetVolumeLabel,
|
||||
GetSecurityByName,
|
||||
#if defined(MEMFS_EA)
|
||||
0,
|
||||
#else
|
||||
Create,
|
||||
#endif
|
||||
Open,
|
||||
#if defined(MEMFS_EA)
|
||||
0,
|
||||
#else
|
||||
Overwrite,
|
||||
#endif
|
||||
Cleanup,
|
||||
Close,
|
||||
Read,
|
||||
@ -1957,6 +2210,18 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||
Control,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
#if defined(MEMFS_EA)
|
||||
Create,
|
||||
Overwrite,
|
||||
GetEa,
|
||||
SetEa
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user