tst: memfs: MEMFS_NAMED_STREAMS macro

This commit is contained in:
Bill Zissimopoulos 2016-10-03 11:55:39 -07:00
parent dfd6cbbde1
commit 87b2d4ca4c

View File

@ -22,6 +22,11 @@
#include <cassert> #include <cassert>
#include <VersionHelpers.h> #include <VersionHelpers.h>
/*
* Define the MEMFS_NAMED_STREAMS macro to include named streams support.
*/
//#define MEMFS_NAMED_STREAMS
/* /*
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes * 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. * a check for the Write buffer to ensure that it is read-only.
@ -48,14 +53,18 @@ int MemfsFileNameCompare(PWSTR a, PWSTR b)
} }
static inline static inline
BOOLEAN MemfsFileNameHasPrefix(PWSTR a, PWSTR b, BOOLEAN AllowStreams) BOOLEAN MemfsFileNameHasPrefix(PWSTR a, PWSTR b)
{ {
size_t alen = wcslen(a); size_t alen = wcslen(a);
size_t blen = wcslen(b); size_t blen = wcslen(b);
return alen >= blen && 0 == memcmp(a, b, blen * sizeof(WCHAR)) && return alen >= blen && 0 == memcmp(a, b, blen * sizeof(WCHAR)) &&
(alen == blen || (1 == blen && L'\\' == b[0]) || (alen == blen || (1 == blen && L'\\' == b[0]) ||
(L'\\' == a[blen] || (AllowStreams && L':' == a[blen]))); #if defined(MEMFS_NAMED_STREAMS)
(L'\\' == a[blen] || L':' == a[blen]));
#else
(L'\\' == a[blen]));
#endif
} }
typedef struct _MEMFS_FILE_NODE typedef struct _MEMFS_FILE_NODE
@ -68,8 +77,9 @@ typedef struct _MEMFS_FILE_NODE
SIZE_T ReparseDataSize; SIZE_T ReparseDataSize;
PVOID ReparseData; PVOID ReparseData;
ULONG RefCount; ULONG RefCount;
/* stream support */ #if defined(MEMFS_NAMED_STREAMS)
struct _MEMFS_FILE_NODE *MainFileNode; struct _MEMFS_FILE_NODE *MainFileNode;
#endif
} MEMFS_FILE_NODE; } MEMFS_FILE_NODE;
struct MEMFS_FILE_NODE_LESS struct MEMFS_FILE_NODE_LESS
@ -131,6 +141,7 @@ VOID MemfsFileNodeDelete(MEMFS_FILE_NODE *FileNode)
static inline static inline
VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo) VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo)
{ {
#if defined(MEMFS_NAMED_STREAMS)
if (0 == FileNode->MainFileNode) if (0 == FileNode->MainFileNode)
*FileInfo = FileNode->FileInfo; *FileInfo = FileNode->FileInfo;
else else
@ -141,6 +152,9 @@ VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *Fi
FileInfo->AllocationSize = FileNode->FileInfo.AllocationSize; FileInfo->AllocationSize = FileNode->FileInfo.AllocationSize;
FileInfo->FileSize = FileNode->FileInfo.FileSize; FileInfo->FileSize = FileNode->FileInfo.FileSize;
} }
#else
*FileInfo = FileNode->FileInfo;
#endif
} }
static inline static inline
@ -193,6 +207,7 @@ MEMFS_FILE_NODE *MemfsFileNodeMapGet(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR Fil
return iter->second; return iter->second;
} }
#if defined(MEMFS_NAMED_STREAMS)
static inline static inline
MEMFS_FILE_NODE *MemfsFileNodeMapGetMain(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0) MEMFS_FILE_NODE *MemfsFileNodeMapGetMain(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0)
{ {
@ -207,6 +222,7 @@ MEMFS_FILE_NODE *MemfsFileNodeMapGetMain(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR
return 0; return 0;
return iter->second; return iter->second;
} }
#endif
static inline static inline
MEMFS_FILE_NODE *MemfsFileNodeMapGetParent(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0, MEMFS_FILE_NODE *MemfsFileNodeMapGetParent(MEMFS_FILE_NODE_MAP *FileNodeMap, PWSTR FileName0,
@ -282,12 +298,13 @@ BOOLEAN MemfsFileNodeMapEnumerateChildren(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMF
BOOLEAN IsDirectoryChild; BOOLEAN IsDirectoryChild;
for (; FileNodeMap->end() != iter; ++iter) for (; FileNodeMap->end() != iter; ++iter)
{ {
if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName, FALSE)) if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName))
break; break;
FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root); FspPathSuffix(iter->second->FileName, &Remain, &Suffix, Root);
IsDirectoryChild = IsDirectoryChild = 0 == MemfsFileNameCompare(Remain, FileNode->FileName);
0 == MemfsFileNameCompare(Remain, FileNode->FileName) && #if defined(MEMFS_NAMED_STREAMS)
0 == wcschr(Suffix, L':'); IsDirectoryChild = IsDirectoryChild && 0 == wcschr(Suffix, L':');
#endif
FspPathCombine(iter->second->FileName, Suffix); FspPathCombine(iter->second->FileName, Suffix);
if (IsDirectoryChild) if (IsDirectoryChild)
{ {
@ -298,6 +315,7 @@ BOOLEAN MemfsFileNodeMapEnumerateChildren(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMF
return TRUE; return TRUE;
} }
#if defined(MEMFS_NAMED_STREAMS)
static inline static inline
BOOLEAN MemfsFileNodeMapEnumerateNamedStreams(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode, BOOLEAN MemfsFileNodeMapEnumerateNamedStreams(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode,
BOOLEAN (*EnumFn)(MEMFS_FILE_NODE *, PVOID), PVOID Context) BOOLEAN (*EnumFn)(MEMFS_FILE_NODE *, PVOID), PVOID Context)
@ -305,7 +323,7 @@ BOOLEAN MemfsFileNodeMapEnumerateNamedStreams(MEMFS_FILE_NODE_MAP *FileNodeMap,
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName); MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->upper_bound(FileNode->FileName);
for (; FileNodeMap->end() != iter; ++iter) for (; FileNodeMap->end() != iter; ++iter)
{ {
if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName, FALSE)) if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName))
break; break;
if (L':' != iter->second->FileName[wcslen(FileNode->FileName)]) if (L':' != iter->second->FileName[wcslen(FileNode->FileName)])
break; break;
@ -314,6 +332,7 @@ BOOLEAN MemfsFileNodeMapEnumerateNamedStreams(MEMFS_FILE_NODE_MAP *FileNodeMap,
} }
return TRUE; return TRUE;
} }
#endif
static inline static inline
BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode, BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode,
@ -323,7 +342,7 @@ BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, M
MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->lower_bound(FileNode->FileName); MEMFS_FILE_NODE_MAP::iterator iter = FileNodeMap->lower_bound(FileNode->FileName);
for (; FileNodeMap->end() != iter; ++iter) for (; FileNodeMap->end() != iter; ++iter)
{ {
if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName, TRUE)) if (!MemfsFileNameHasPrefix(iter->second->FileName, FileNode->FileName))
break; break;
if (!EnumFn(iter->second, Context)) if (!EnumFn(iter->second, Context))
return FALSE; return FALSE;
@ -398,8 +417,10 @@ static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
return Result; return Result;
} }
#if defined(MEMFS_NAMED_STREAMS)
if (0 != FileNode->MainFileNode) if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode; FileNode = FileNode->MainFileNode;
#endif
if (0 != PFileAttributes) if (0 != PFileAttributes)
*PFileAttributes = FileNode->FileInfo.FileAttributes; *PFileAttributes = FileNode->FileInfo.FileAttributes;
@ -451,7 +472,9 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return Result; return Result;
#if defined(MEMFS_NAMED_STREAMS)
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName); FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
#endif
FileNode->FileInfo.FileAttributes = (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FileNode->FileInfo.FileAttributes = (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
FileAttributes : FileAttributes | FILE_ATTRIBUTE_ARCHIVE; FileAttributes : FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
@ -555,6 +578,7 @@ NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
#if defined(MEMFS_NAMED_STREAMS)
typedef struct _MEMFS_CLEANUP_CONTEXT typedef struct _MEMFS_CLEANUP_CONTEXT
{ {
MEMFS_FILE_NODE **FileNodes; MEMFS_FILE_NODE **FileNodes;
@ -569,6 +593,7 @@ static BOOLEAN CleanupEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
return TRUE; return TRUE;
} }
#endif
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem, static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_REQ *Request,
@ -582,6 +607,7 @@ static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode)) if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
{ {
#if defined(MEMFS_NAMED_STREAMS)
MEMFS_CLEANUP_CONTEXT Context = { 0 }; MEMFS_CLEANUP_CONTEXT Context = { 0 };
ULONG Index; ULONG Index;
@ -593,6 +619,7 @@ static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]); MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
free(Context.FileNodes); free(Context.FileNodes);
} }
#endif
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode); MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
} }
@ -709,8 +736,10 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
{ {
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
#if defined(MEMFS_NAMED_STREAMS)
if (0 != FileNode->MainFileNode) if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode; FileNode = FileNode->MainFileNode;
#endif
if (INVALID_FILE_ATTRIBUTES != FileAttributes) if (INVALID_FILE_ATTRIBUTES != FileAttributes)
FileNode->FileInfo.FileAttributes = FileAttributes; FileNode->FileInfo.FileAttributes = FileAttributes;
@ -855,7 +884,7 @@ static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
for (Index = 0; Context.Count > Index; Index++) for (Index = 0; Context.Count > Index; Index++)
{ {
DescendantFileNode = Context.FileNodes[Index]; DescendantFileNode = Context.FileNodes[Index];
assert(MemfsFileNameHasPrefix(DescendantFileNode->FileName, FileNode->FileName, TRUE)); assert(MemfsFileNameHasPrefix(DescendantFileNode->FileName, FileNode->FileName));
if (MAX_PATH <= wcslen(DescendantFileNode->FileName) - FileNameLen + NewFileNameLen) if (MAX_PATH <= wcslen(DescendantFileNode->FileName) - FileNameLen + NewFileNameLen)
{ {
Result = STATUS_OBJECT_NAME_INVALID; Result = STATUS_OBJECT_NAME_INVALID;
@ -908,8 +937,10 @@ static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem,
{ {
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
#if defined(MEMFS_NAMED_STREAMS)
if (0 != FileNode->MainFileNode) if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode; FileNode = FileNode->MainFileNode;
#endif
if (FileNode->FileSecuritySize > *PSecurityDescriptorSize) if (FileNode->FileSecuritySize > *PSecurityDescriptorSize)
{ {
@ -934,8 +965,10 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
SIZE_T FileSecuritySize; SIZE_T FileSecuritySize;
NTSTATUS Result; NTSTATUS Result;
#if defined(MEMFS_NAMED_STREAMS)
if (0 != FileNode->MainFileNode) if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode; FileNode = FileNode->MainFileNode;
#endif
Result = FspSetSecurityDescriptor(FileSystem, Request, FileNode->FileSecurity, Result = FspSetSecurityDescriptor(FileSystem, Request, FileNode->FileSecurity,
&NewSecurityDescriptor); &NewSecurityDescriptor);
@ -1164,6 +1197,7 @@ static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
#if defined(MEMFS_NAMED_STREAMS)
typedef struct _MEMFS_GET_STREAM_INFO_CONTEXT typedef struct _MEMFS_GET_STREAM_INFO_CONTEXT
{ {
PVOID Buffer; PVOID Buffer;
@ -1224,6 +1258,7 @@ static NTSTATUS GetStreamInfo(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
#endif
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
{ {
@ -1250,7 +1285,11 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
GetReparsePoint, GetReparsePoint,
SetReparsePoint, SetReparsePoint,
DeleteReparsePoint, DeleteReparsePoint,
#if defined(MEMFS_NAMED_STREAMS)
GetStreamInfo, GetStreamInfo,
#else
0,
#endif
}; };
NTSTATUS MemfsCreate( NTSTATUS MemfsCreate(
@ -1313,7 +1352,9 @@ NTSTATUS MemfsCreate(
VolumeParams.PersistentAcls = 1; VolumeParams.PersistentAcls = 1;
VolumeParams.ReparsePoints = 1; VolumeParams.ReparsePoints = 1;
VolumeParams.ReparsePointsAccessCheck = 0; VolumeParams.ReparsePointsAccessCheck = 0;
#if defined(MEMFS_NAMED_STREAMS)
VolumeParams.NamedStreams = 1; VolumeParams.NamedStreams = 1;
#endif
VolumeParams.PostCleanupOnDeleteOnly = 1; VolumeParams.PostCleanupOnDeleteOnly = 1;
if (0 != VolumePrefix) if (0 != VolumePrefix)
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix); wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);