sys,dll: ReadDirectory: add Marker, remove Offset

This commit is contained in:
Bill Zissimopoulos
2017-01-24 18:10:13 -08:00
parent ebad86387c
commit 7843c73d34
9 changed files with 178 additions and 217 deletions

View File

@ -580,58 +580,6 @@ VOID MemfsFileNodeMapEnumerateFree(MEMFS_FILE_NODE_MAP_ENUM_CONTEXT *Context)
free(Context->FileNodes);
}
typedef std::unordered_map<UINT64, std::wstring> MEMFS_DIR_DESC;
static inline
NTSTATUS MemfsDirDescCreate(MEMFS_DIR_DESC **PDirDesc)
{
*PDirDesc = 0;
try
{
*PDirDesc = new MEMFS_DIR_DESC;
return STATUS_SUCCESS;
}
catch (...)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
static inline
VOID MemfsDirDescDelete(MEMFS_DIR_DESC *DirDesc)
{
delete DirDesc;
}
static inline
VOID MemfsDirDescReset(MEMFS_DIR_DESC *DirDesc)
{
DirDesc->clear();
}
static inline
PWSTR MemfsDirDescGetFileName(MEMFS_DIR_DESC *DirDesc, UINT64 Offset)
{
MEMFS_DIR_DESC::iterator iter = DirDesc->find(Offset);
if (iter == DirDesc->end())
return 0;
return const_cast<PWSTR>(iter->second.c_str());
}
static inline
NTSTATUS MemfsDirDescInsertFileName(MEMFS_DIR_DESC *DirDesc, UINT64 Offset, PWSTR FileName)
{
try
{
DirDesc->insert(MEMFS_DIR_DESC::value_type(Offset, FileName));
return STATUS_SUCCESS;
}
catch (...)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
/*
* FSP_FILE_SYSTEM_INTERFACE
*/
@ -745,7 +693,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
#endif
MEMFS_FILE_NODE *FileNode;
MEMFS_FILE_NODE *ParentNode;
MEMFS_DIR_DESC *DirDesc = 0;
NTSTATUS Result;
BOOLEAN Inserted;
@ -794,20 +741,9 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
}
#endif
if (CreateOptions & FILE_DIRECTORY_FILE)
{
Result = MemfsDirDescCreate(&DirDesc);
if (!NT_SUCCESS(Result))
return Result;
}
Result = MemfsFileNodeCreate(FileName, &FileNode);
if (!NT_SUCCESS(Result))
{
if (0 != DirDesc)
MemfsDirDescDelete(DirDesc);
return Result;
}
#if defined(MEMFS_NAMED_STREAMS)
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
@ -823,8 +759,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
if (0 == FileNode->FileSecurity)
{
MemfsFileNodeDelete(FileNode);
if (0 != DirDesc)
MemfsDirDescDelete(DirDesc);
return STATUS_INSUFFICIENT_RESOURCES;
}
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
@ -837,8 +771,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
if (0 == FileNode->FileData)
{
MemfsFileNodeDelete(FileNode);
if (0 != DirDesc)
MemfsDirDescDelete(DirDesc);
return STATUS_INSUFFICIENT_RESOURCES;
}
}
@ -847,8 +779,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result) || !Inserted)
{
MemfsFileNodeDelete(FileNode);
if (0 != DirDesc)
MemfsDirDescDelete(DirDesc);
if (NT_SUCCESS(Result))
Result = STATUS_OBJECT_NAME_COLLISION; /* should not happen! */
return Result;
@ -869,9 +799,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
}
#endif
/* since we now use dir descriptors to quickly retrieve dir contents, place it in UserContext2 */
FspFileSystemGetOperationContext()->Response->Rsp.Create.Opened.UserContext2 = (UINT_PTR)DirDesc;
return STATUS_SUCCESS;
}
@ -881,7 +808,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
{
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode;
MEMFS_DIR_DESC *DirDesc = 0;
NTSTATUS Result;
if (MEMFS_MAX_PATH <= wcslen(FileName))
@ -895,13 +821,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
return Result;
}
if (0 != (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
Result = MemfsDirDescCreate(&DirDesc);
if (!NT_SUCCESS(Result))
return Result;
}
MemfsFileNodeReference(FileNode);
*PFileNode = FileNode;
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
@ -917,9 +836,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
}
#endif
/* since we now use dir descriptors to quickly retrieve dir contents, place it in UserContext2 */
FspFileSystemGetOperationContext()->Response->Rsp.Create.Opened.UserContext2 = (UINT_PTR)DirDesc;
return STATUS_SUCCESS;
}
@ -1025,13 +941,8 @@ static VOID Close(FSP_FILE_SYSTEM *FileSystem,
{
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
FspFileSystemGetOperationContext()->Request->Req.Close.UserContext2;
MemfsFileNodeDereference(FileNode);
if (0 != DirDesc)
MemfsDirDescDelete(DirDesc);
}
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
@ -1394,14 +1305,11 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
typedef struct _MEMFS_READ_DIRECTORY_CONTEXT
{
PVOID Buffer;
UINT64 Offset;
ULONG Length;
PULONG PBytesTransferred;
BOOLEAN OffsetFound;
MEMFS_DIR_DESC *DirDesc;
} MEMFS_READ_DIRECTORY_CONTEXT;
static BOOLEAN AddDirInfo(MEMFS_DIR_DESC *DirDesc, MEMFS_FILE_NODE *FileNode, PWSTR FileName,
static BOOLEAN AddDirInfo(MEMFS_FILE_NODE *FileNode, PWSTR FileName,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
UINT8 DirInfoBuf[sizeof(FSP_FSCTL_DIR_INFO) + sizeof FileNode->FileName];
@ -1414,14 +1322,11 @@ static BOOLEAN AddDirInfo(MEMFS_DIR_DESC *DirDesc, MEMFS_FILE_NODE *FileNode, PW
FspPathSuffix(FileNode->FileName, &Remain, &Suffix, Root);
FileName = Suffix;
FspPathCombine(FileNode->FileName, Suffix);
MemfsDirDescInsertFileName(DirDesc, FileNode->FileInfo.IndexNumber, FileName);
}
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(FileName) * sizeof(WCHAR));
DirInfo->FileInfo = FileNode->FileInfo;
DirInfo->NextOffset = FileNode->FileInfo.IndexNumber;
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred);
@ -1431,39 +1336,24 @@ static BOOLEAN ReadDirectoryEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
{
MEMFS_READ_DIRECTORY_CONTEXT *Context = (MEMFS_READ_DIRECTORY_CONTEXT *)Context0;
if (0 != Context->Offset && !Context->OffsetFound)
{
Context->OffsetFound = FileNode->FileInfo.IndexNumber == Context->Offset;
return TRUE;
}
return AddDirInfo(Context->DirDesc, FileNode, 0,
return AddDirInfo(FileNode, 0,
Context->Buffer, Context->Length, Context->PBytesTransferred);
}
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length,
PWSTR Pattern,
PVOID FileNode0, PVOID Buffer, ULONG Length,
PWSTR Pattern, PWSTR Marker,
PULONG PBytesTransferred)
{
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
FspFileSystemGetOperationContext()->Request->Req.QueryDirectory.UserContext2;
MEMFS_FILE_NODE *ParentNode;
MEMFS_READ_DIRECTORY_CONTEXT Context;
PWSTR PrevFileName = 0;
NTSTATUS Result;
Context.Buffer = Buffer;
Context.Offset = Offset;
Context.Length = Length;
Context.PBytesTransferred = PBytesTransferred;
Context.OffsetFound = FALSE;
Context.DirDesc = DirDesc;
if (0 == Offset)
MemfsDirDescReset(DirDesc);
if (L'\0' != FileNode->FileName[1])
{
@ -1473,25 +1363,20 @@ static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
if (0 == ParentNode)
return Result;
if (0 == Offset)
if (!AddDirInfo(DirDesc, FileNode, L".", Buffer, Length, PBytesTransferred))
return STATUS_SUCCESS;
if (0 == Offset || FileNode->FileInfo.IndexNumber == Offset)
if (0 == Marker)
{
Context.OffsetFound = FileNode->FileInfo.IndexNumber == Context.Offset;
if (!AddDirInfo(DirDesc, ParentNode, L"..", Buffer, Length, PBytesTransferred))
if (!AddDirInfo(FileNode, L".", Buffer, Length, PBytesTransferred))
return STATUS_SUCCESS;
}
if (0 == Marker || (L'.' == Marker[0] && L'\0' == Marker[1]))
{
if (!AddDirInfo(ParentNode, L"..", Buffer, Length, PBytesTransferred))
return STATUS_SUCCESS;
Marker = 0;
}
}
if (0 != Context.Offset && !Context.OffsetFound)
{
PrevFileName = MemfsDirDescGetFileName(DirDesc, Offset);
Context.OffsetFound = 0 != PrevFileName;
}
if (MemfsFileNodeMapEnumerateChildren(Memfs->FileNodeMap, FileNode, PrevFileName,
if (MemfsFileNodeMapEnumerateChildren(Memfs->FileNodeMap, FileNode, Marker,
ReadDirectoryEnumFn, &Context))
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);