mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-08 04:52:10 -05:00
sys,dll: ReadDirectory: add Marker, remove Offset
This commit is contained in:
parent
ebad86387c
commit
7843c73d34
@ -185,8 +185,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
UINT16 Size;
|
UINT16 Size;
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
UINT64 NextOffset;
|
UINT8 Padding[24];
|
||||||
UINT8 Padding[16];
|
|
||||||
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
|
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
|
||||||
WCHAR FileNameBuf[];
|
WCHAR FileNameBuf[];
|
||||||
} FSP_FSCTL_DIR_INFO;
|
} FSP_FSCTL_DIR_INFO;
|
||||||
@ -339,9 +338,9 @@ typedef struct
|
|||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
UINT64 Address;
|
UINT64 Address;
|
||||||
UINT64 Offset;
|
|
||||||
UINT32 Length;
|
UINT32 Length;
|
||||||
FSP_FSCTL_TRANSACT_BUF Pattern;
|
FSP_FSCTL_TRANSACT_BUF Pattern;
|
||||||
|
FSP_FSCTL_TRANSACT_BUF Marker;
|
||||||
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
||||||
} QueryDirectory;
|
} QueryDirectory;
|
||||||
struct
|
struct
|
||||||
|
@ -649,28 +649,16 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* The file context of the directory to be read.
|
* The file context of the directory to be read.
|
||||||
* @param Buffer
|
* @param Buffer
|
||||||
* Pointer to a buffer that will receive the results of the read operation.
|
* Pointer to a buffer that will receive the results of the read operation.
|
||||||
* @param Offset
|
|
||||||
* Offset within the directory to read from. The kernel does not interpret this value
|
|
||||||
* which is used solely by the file system to locate directory entries. However the
|
|
||||||
* special value 0 indicates that the read should start from the first entries. The first
|
|
||||||
* two entries returned by ReadDirectory should always be the "." and ".." entries,
|
|
||||||
* except for the root directory which does not have these entries.
|
|
||||||
*
|
|
||||||
* This parameter is used by the WinFsp FSD to break directory listings into chunks.
|
|
||||||
* In this case all 64-bits of the Offset are valid. In some cases the Windows kernel
|
|
||||||
* (NTOS) may also use this parameter. In this case only the lower 32-bits of this
|
|
||||||
* parameter will be valid. This is an unfortunate limitation of Windows (for more
|
|
||||||
* information see the documentation for IRP_MJ_DIRECTORY_CONTROL and the flag
|
|
||||||
* SL_INDEX_SPECIFIED).
|
|
||||||
*
|
|
||||||
* In practice this means that you should only rely on the lower 32-bits of this value
|
|
||||||
* to be valid.
|
|
||||||
* @param Length
|
* @param Length
|
||||||
* Length of data to read.
|
* Length of data to read.
|
||||||
* @param Pattern
|
* @param Pattern
|
||||||
* The pattern to match against files in this directory. Can be NULL. The file system
|
* The pattern to match against files in this directory. Can be NULL. The file system
|
||||||
* can choose to ignore this parameter as the FSD will always perform its own pattern
|
* can choose to ignore this parameter as the FSD will always perform its own pattern
|
||||||
* matching on the returned results.
|
* matching on the returned results.
|
||||||
|
* @param Marker
|
||||||
|
* A file name that marks where in the directory to start reading. Files with names
|
||||||
|
* that are greater than (not equal to) this marker (in the directory order determined
|
||||||
|
* by the file system) should be returned. Can be NULL.
|
||||||
* @param PBytesTransferred [out]
|
* @param PBytesTransferred [out]
|
||||||
* Pointer to a memory location that will receive the actual number of bytes read.
|
* Pointer to a memory location that will receive the actual number of bytes read.
|
||||||
* @return
|
* @return
|
||||||
@ -680,8 +668,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* FspFileSystemAddDirInfo
|
* FspFileSystemAddDirInfo
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*ReadDirectory)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*ReadDirectory)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG Length,
|
PVOID FileContext, PVOID Buffer, ULONG Length,
|
||||||
PWSTR Pattern,
|
PWSTR Pattern, PWSTR Marker,
|
||||||
PULONG PBytesTransferred);
|
PULONG PBytesTransferred);
|
||||||
/**
|
/**
|
||||||
* Resolve reparse points.
|
* Resolve reparse points.
|
||||||
|
@ -518,7 +518,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
break;
|
break;
|
||||||
case FspFsctlTransactQueryDirectoryKind:
|
case FspFsctlTransactQueryDirectoryKind:
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
|
||||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Pattern=%s%S%s\n",
|
"Address=%p, Length=%ld, Pattern=%s%S%s, Marker=%s%S%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
@ -527,12 +527,15 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
|
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
|
||||||
UserContextBuf),
|
UserContextBuf),
|
||||||
Request->Req.QueryDirectory.Address,
|
Request->Req.QueryDirectory.Address,
|
||||||
MAKE_UINT32_PAIR(Request->Req.QueryDirectory.Offset),
|
|
||||||
Request->Req.QueryDirectory.Length,
|
Request->Req.QueryDirectory.Length,
|
||||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||||
Request->Req.QueryDirectory.Pattern.Size ?
|
Request->Req.QueryDirectory.Pattern.Size ?
|
||||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
|
||||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "");
|
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||||
|
Request->Req.QueryDirectory.Marker.Size ? "\"" : "",
|
||||||
|
Request->Req.QueryDirectory.Marker.Size ?
|
||||||
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : L"NULL",
|
||||||
|
Request->Req.QueryDirectory.Marker.Size ? "\"" : "");
|
||||||
break;
|
break;
|
||||||
case FspFsctlTransactFileSystemControlKind:
|
case FspFsctlTransactFileSystemControlKind:
|
||||||
switch (Request->Req.FileSystemControl.FsControlCode)
|
switch (Request->Req.FileSystemControl.FsControlCode)
|
||||||
|
@ -1134,10 +1134,11 @@ FSP_API NTSTATUS FspFileSystemOpQueryDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Result = FileSystem->Interface->ReadDirectory(FileSystem,
|
Result = FileSystem->Interface->ReadDirectory(FileSystem,
|
||||||
(PVOID)ValOfFileContext(Request->Req.QueryDirectory),
|
(PVOID)ValOfFileContext(Request->Req.QueryDirectory),
|
||||||
(PVOID)Request->Req.QueryDirectory.Address,
|
(PVOID)Request->Req.QueryDirectory.Address,
|
||||||
Request->Req.QueryDirectory.Offset,
|
|
||||||
Request->Req.QueryDirectory.Length,
|
Request->Req.QueryDirectory.Length,
|
||||||
0 != Request->Req.QueryDirectory.Pattern.Size ?
|
0 != Request->Req.QueryDirectory.Pattern.Size ?
|
||||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0,
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : 0,
|
||||||
|
0 != Request->Req.QueryDirectory.Marker.Size ?
|
||||||
|
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : 0,
|
||||||
&BytesTransferred);
|
&BytesTransferred);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -1661,10 +1661,12 @@ int fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length,
|
PVOID FileContext, PVOID Buffer, ULONG Length,
|
||||||
PWSTR Pattern,
|
PWSTR Pattern, PWSTR Marker,
|
||||||
PULONG PBytesTransferred)
|
PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
#if 0
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
@ -1844,6 +1846,7 @@ exit:
|
|||||||
MemFree(dh.Buffer);
|
MemFree(dh.Buffer);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
135
src/sys/dirctl.c
135
src/sys/dirctl.c
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
||||||
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
||||||
UINT64 DirectoryOffset, PUINT64 PDirectoryOffset,
|
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
||||||
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
||||||
PVOID DestBuf, PULONG PDestLen);
|
PVOID DestBuf, PULONG PDestLen);
|
||||||
@ -74,9 +74,6 @@ FSP_DRIVER_DISPATCH FspDirectoryControl;
|
|||||||
#pragma alloc_text(PAGE, FspDirectoryControl)
|
#pragma alloc_text(PAGE, FspDirectoryControl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FILE_INDEX_FROM_OFFSET(v) ((ULONG)(v))
|
|
||||||
#define OFFSET_FROM_FILE_INDEX(v) ((UINT64)(v))
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/* QueryDirectory */
|
/* QueryDirectory */
|
||||||
@ -94,7 +91,7 @@ enum
|
|||||||
|
|
||||||
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
static NTSTATUS FspFsvolQueryDirectoryCopy(
|
||||||
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
|
||||||
UINT64 DirectoryOffset, PUINT64 PDirectoryOffset,
|
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
|
||||||
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
|
||||||
PVOID DestBuf, PULONG PDestLen)
|
PVOID DestBuf, PULONG PDestLen)
|
||||||
@ -104,7 +101,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
{\
|
{\
|
||||||
TYPE InfoStruct = { 0 }, *Info = &InfoStruct;\
|
TYPE InfoStruct = { 0 }, *Info = &InfoStruct;\
|
||||||
Info->NextEntryOffset = 0;\
|
Info->NextEntryOffset = 0;\
|
||||||
Info->FileIndex = FILE_INDEX_FROM_OFFSET(DirInfo->NextOffset);\
|
Info->FileIndex = 0;\
|
||||||
Info->FileNameLength = FileName.Length;\
|
Info->FileNameLength = FileName.Length;\
|
||||||
__VA_ARGS__\
|
__VA_ARGS__\
|
||||||
Info = DestBuf;\
|
Info = DestBuf;\
|
||||||
@ -128,7 +125,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
|
|
||||||
NTSTATUS Result = STATUS_SUCCESS;
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer, Match;
|
BOOLEAN MatchAll = FspFileDescDirectoryPatternMatchAll == DirectoryPattern->Buffer, Match;
|
||||||
BOOLEAN Loop = TRUE, DirectoryOffsetFound = FALSE;
|
BOOLEAN Loop = TRUE, DirectoryMarkerFound = FALSE;
|
||||||
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
|
FSP_FSCTL_DIR_INFO *DirInfo = *PDirInfo;
|
||||||
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
||||||
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
PUINT8 DestBufBgn = (PUINT8)DestBuf;
|
||||||
@ -178,16 +175,18 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != DirectoryOffset && !DirectoryOffsetFound)
|
|
||||||
{
|
|
||||||
DirectoryOffsetFound = DirInfo->NextOffset == DirectoryOffset;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileName.Length =
|
FileName.Length =
|
||||||
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
|
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
FileName.Buffer = DirInfo->FileNameBuf;
|
FileName.Buffer = DirInfo->FileNameBuf;
|
||||||
|
|
||||||
|
if (0 != DirectoryMarker && 0 != DirectoryMarker->Buffer &&
|
||||||
|
!DirectoryMarkerFound)
|
||||||
|
{
|
||||||
|
DirectoryMarkerFound = 0 == FspFileNameCompare(
|
||||||
|
&FileName, DirectoryMarker, CaseInsensitive, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
||||||
CopyLength = FileName.Length;
|
CopyLength = FileName.Length;
|
||||||
|
|
||||||
@ -223,7 +222,6 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
*(PULONG)PrevDestBuf = (ULONG)((PUINT8)DestBuf - (PUINT8)PrevDestBuf);
|
*(PULONG)PrevDestBuf = (ULONG)((PUINT8)DestBuf - (PUINT8)PrevDestBuf);
|
||||||
PrevDestBuf = DestBuf;
|
PrevDestBuf = DestBuf;
|
||||||
|
|
||||||
*PDirectoryOffset = DirInfo->NextOffset;
|
|
||||||
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
|
*PDestLen = (ULONG)((PUINT8)DestBuf + BaseInfoLen + CopyLength - DestBufBgn);
|
||||||
|
|
||||||
switch (FileInformationClass)
|
switch (FileInformationClass)
|
||||||
@ -265,6 +263,9 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
|
||||||
|
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
|
||||||
|
|
||||||
DestBuf = (PVOID)((PUINT8)DestBuf +
|
DestBuf = (PVOID)((PUINT8)DestBuf +
|
||||||
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
|
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
|
||||||
|
|
||||||
@ -273,7 +274,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
Loop = FALSE;
|
Loop = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*PDirectoryOffset = DirInfo->NextOffset;
|
*DirectoryMarkerOut = FileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
except (EXCEPTION_EXECUTE_HANDLER)
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
@ -315,7 +316,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
||||||
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
||||||
UINT64 DirectoryOffset = FileDesc->DirectoryOffset;
|
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
|
||||||
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
|
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
|
||||||
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
|
||||||
|
|
||||||
@ -323,17 +324,20 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
|
|||||||
DirInfoSize = (ULONG)(DirInfoEnd - (PUINT8)DirInfo);
|
DirInfoSize = (ULONG)(DirInfoEnd - (PUINT8)DirInfo);
|
||||||
|
|
||||||
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
||||||
0 != FileDesc->DirInfoCacheHint ? 0 : DirectoryOffset, &DirectoryOffset,
|
0 != FileDesc->DirInfoCacheHint ? 0 : &FileDesc->DirectoryMarker, &DirectoryMarker,
|
||||||
FileInformationClass, ReturnSingleEntry,
|
FileInformationClass, ReturnSingleEntry,
|
||||||
&DirInfo, DirInfoSize,
|
&DirInfo, DirInfoSize,
|
||||||
DestBuf, PDestLen);
|
DestBuf, PDestLen);
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != *PDestLen)
|
Result = FspFileDescSetDirectoryMarker(FileDesc, &DirectoryMarker);
|
||||||
FileDesc->DirectoryHasSuchFile = TRUE;
|
if (NT_SUCCESS(Result))
|
||||||
FileDesc->DirectoryOffset = DirectoryOffset;
|
{
|
||||||
FileDesc->DirInfoCacheHint = (ULONG)((PUINT8)DirInfo - DirInfoBgn);
|
if (0 != *PDestLen)
|
||||||
|
FileDesc->DirectoryHasSuchFile = TRUE;
|
||||||
|
FileDesc->DirInfoCacheHint = (ULONG)((PUINT8)DirInfo - DirInfoBgn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
||||||
Result = STATUS_NO_SUCH_FILE;
|
Result = STATUS_NO_SUCH_FILE;
|
||||||
@ -354,7 +358,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
|
||||||
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
|
||||||
UINT64 DirectoryOffset = FileDesc->DirectoryOffset;
|
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
|
||||||
|
|
||||||
ASSERT(DirInfo == DestBuf);
|
ASSERT(DirInfo == DestBuf);
|
||||||
FSP_FSCTL_STATIC_ASSERT(
|
FSP_FSCTL_STATIC_ASSERT(
|
||||||
@ -363,16 +367,19 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
|
|||||||
"FSP_FSCTL_DIR_INFO must be bigger than FILE_ID_BOTH_DIR_INFORMATION");
|
"FSP_FSCTL_DIR_INFO must be bigger than FILE_ID_BOTH_DIR_INFORMATION");
|
||||||
|
|
||||||
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
|
||||||
0, &DirectoryOffset,
|
0, &DirectoryMarker,
|
||||||
FileInformationClass, ReturnSingleEntry,
|
FileInformationClass, ReturnSingleEntry,
|
||||||
&DirInfo, DirInfoSize,
|
&DirInfo, DirInfoSize,
|
||||||
DestBuf, PDestLen);
|
DestBuf, PDestLen);
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 != *PDestLen)
|
Result = FspFileDescSetDirectoryMarker(FileDesc, &DirectoryMarker);
|
||||||
FileDesc->DirectoryHasSuchFile = TRUE;
|
if (NT_SUCCESS(Result))
|
||||||
FileDesc->DirectoryOffset = DirectoryOffset;
|
{
|
||||||
|
if (0 != *PDestLen)
|
||||||
|
FileDesc->DirectoryHasSuchFile = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
else if (STATUS_NO_MORE_FILES == Result && !FileDesc->DirectoryHasSuchFile)
|
||||||
Result = STATUS_NO_SUCH_FILE;
|
Result = STATUS_NO_SUCH_FILE;
|
||||||
@ -442,7 +449,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
* counter-productive to try to read more than we need.
|
* counter-productive to try to read more than we need.
|
||||||
*/
|
*/
|
||||||
#define GetSystemBufferLengthMaybeCached()\
|
#define GetSystemBufferLengthMaybeCached()\
|
||||||
(0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryOffset) ||\
|
(0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && 0 == FileDesc->DirectoryMarker.Buffer) ||\
|
||||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?\
|
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?\
|
||||||
FspFsvolDeviceDirInfoCacheItemSizeMax : Length
|
FspFsvolDeviceDirInfoCacheItemSizeMax : Length
|
||||||
#define GetSystemBufferLengthNonCached()\
|
#define GetSystemBufferLengthNonCached()\
|
||||||
@ -463,7 +470,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
BOOLEAN ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
|
BOOLEAN ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
|
||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
|
||||||
PUNICODE_STRING FileName = IrpSp->Parameters.QueryDirectory.FileName;
|
PUNICODE_STRING FileName = IrpSp->Parameters.QueryDirectory.FileName;
|
||||||
ULONG FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
|
//ULONG FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
|
||||||
PVOID Buffer = 0 != Irp->AssociatedIrp.SystemBuffer ?
|
PVOID Buffer = 0 != Irp->AssociatedIrp.SystemBuffer ?
|
||||||
Irp->AssociatedIrp.SystemBuffer : Irp->UserBuffer;
|
Irp->AssociatedIrp.SystemBuffer : Irp->UserBuffer;
|
||||||
ULONG Length = IrpSp->Parameters.QueryDirectory.Length;
|
ULONG Length = IrpSp->Parameters.QueryDirectory.Length;
|
||||||
@ -511,27 +518,14 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
Request = 0;
|
Request = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the DirectoryPattern in the FileDesc */
|
/* reset the FileDesc */
|
||||||
Result = FspFileDescResetDirectoryPattern(FileDesc, FileName,
|
Result = FspFileDescResetDirectory(FileDesc, FileName, RestartScan, IndexSpecified);
|
||||||
RestartScan && 0 != FileName && 0 != FileName->Length);
|
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
FspFileNodeRelease(FileNode, Full);
|
FspFileNodeRelease(FileNode, Full);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine where to (re)start */
|
|
||||||
if (IndexSpecified)
|
|
||||||
{
|
|
||||||
FileDesc->DirectoryHasSuchFile = FALSE;
|
|
||||||
FileDesc->DirectoryOffset = OFFSET_FROM_FILE_INDEX(FileIndex);
|
|
||||||
}
|
|
||||||
else if (RestartScan)
|
|
||||||
{
|
|
||||||
FileDesc->DirectoryHasSuchFile = FALSE;
|
|
||||||
FileDesc->DirectoryOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* see if the required information is still in the cache and valid! */
|
/* see if the required information is still in the cache and valid! */
|
||||||
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
|
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
|
||||||
{
|
{
|
||||||
@ -571,8 +565,9 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
|
|
||||||
/* create request */
|
/* create request */
|
||||||
Result = FspIopCreateRequestEx(Irp, 0,
|
Result = FspIopCreateRequestEx(Irp, 0,
|
||||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?
|
(FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer ?
|
||||||
FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0,
|
FileDesc->DirectoryPattern.Length + sizeof(WCHAR) : 0) +
|
||||||
|
(FsvolDeviceExtension->VolumeParams.MaxComponentLength + 1) * sizeof(WCHAR),
|
||||||
FspFsvolQueryDirectoryRequestFini, &Request);
|
FspFsvolQueryDirectoryRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
@ -583,19 +578,37 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
Request->Kind = FspFsctlTransactQueryDirectoryKind;
|
Request->Kind = FspFsctlTransactQueryDirectoryKind;
|
||||||
Request->Req.QueryDirectory.UserContext = FileNode->UserContext;
|
Request->Req.QueryDirectory.UserContext = FileNode->UserContext;
|
||||||
Request->Req.QueryDirectory.UserContext2 = FileDesc->UserContext2;
|
Request->Req.QueryDirectory.UserContext2 = FileDesc->UserContext2;
|
||||||
Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset;
|
|
||||||
Request->Req.QueryDirectory.Length = SystemBufferLength;
|
Request->Req.QueryDirectory.Length = SystemBufferLength;
|
||||||
Request->Req.QueryDirectory.CaseSensitive = FileDesc->CaseSensitive;
|
Request->Req.QueryDirectory.CaseSensitive = FileDesc->CaseSensitive;
|
||||||
|
|
||||||
if (FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
if (FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
||||||
{
|
{
|
||||||
Request->Req.QueryDirectory.Pattern.Offset = Request->FileName.Size;
|
Request->Req.QueryDirectory.Pattern.Offset =
|
||||||
|
Request->FileName.Size;
|
||||||
Request->Req.QueryDirectory.Pattern.Size =
|
Request->Req.QueryDirectory.Pattern.Size =
|
||||||
FileDesc->DirectoryPattern.Length + sizeof(WCHAR);
|
FileDesc->DirectoryPattern.Length + sizeof(WCHAR);
|
||||||
RtlCopyMemory(Request->Buffer + Request->FileName.Size,
|
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset,
|
||||||
FileDesc->DirectoryPattern.Buffer, FileDesc->DirectoryPattern.Length);
|
FileDesc->DirectoryPattern.Buffer, FileDesc->DirectoryPattern.Length);
|
||||||
*(PWSTR)(Request->Buffer + Request->FileName.Size + FileDesc->DirectoryPattern.Length) =
|
*(PWSTR)(Request->Buffer +
|
||||||
L'\0';
|
Request->Req.QueryDirectory.Pattern.Offset +
|
||||||
|
FileDesc->DirectoryPattern.Length) = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
ASSERT(
|
||||||
|
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||||
|
FileDesc->DirectoryMarker.Length);
|
||||||
|
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset =
|
||||||
|
Request->FileName.Size + Request->Req.QueryDirectory.Pattern.Size;
|
||||||
|
Request->Req.QueryDirectory.Marker.Size =
|
||||||
|
FileDesc->DirectoryMarker.Length + sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset,
|
||||||
|
FileDesc->DirectoryMarker.Buffer, FileDesc->DirectoryMarker.Length);
|
||||||
|
*(PWSTR)(Request->Buffer +
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset +
|
||||||
|
FileDesc->DirectoryMarker.Length) = L'\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
@ -885,7 +898,6 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
ASSERT(Request->Req.QueryDirectory.Offset == FileDesc->DirectoryOffset);
|
|
||||||
|
|
||||||
if (0 == Response->IoStatus.Information)
|
if (0 == Response->IoStatus.Information)
|
||||||
{
|
{
|
||||||
@ -913,7 +925,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
FSP_RETURN();
|
FSP_RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == FileDesc->DirectoryOffset &&
|
if (0 == Request->Req.QueryDirectory.Marker.Size &&
|
||||||
FspFileNodeTrySetDirInfo(FileNode,
|
FspFileNodeTrySetDirInfo(FileNode,
|
||||||
Irp->AssociatedIrp.SystemBuffer,
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
(ULONG)Response->IoStatus.Information,
|
(ULONG)Response->IoStatus.Information,
|
||||||
@ -952,7 +964,24 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
|||||||
FspIopResetRequest(Request, FspFsvolQueryDirectoryRequestFini);
|
FspIopResetRequest(Request, FspFsvolQueryDirectoryRequestFini);
|
||||||
|
|
||||||
Request->Req.QueryDirectory.Address = 0;
|
Request->Req.QueryDirectory.Address = 0;
|
||||||
Request->Req.QueryDirectory.Offset = FileDesc->DirectoryOffset;
|
Request->Req.QueryDirectory.Marker.Offset = 0;
|
||||||
|
Request->Req.QueryDirectory.Marker.Size = 0;
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
ASSERT(
|
||||||
|
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||||
|
FileDesc->DirectoryMarker.Length);
|
||||||
|
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset =
|
||||||
|
Request->FileName.Size + Request->Req.QueryDirectory.Pattern.Size;
|
||||||
|
Request->Req.QueryDirectory.Marker.Size =
|
||||||
|
FileDesc->DirectoryMarker.Length + sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset,
|
||||||
|
FileDesc->DirectoryMarker.Buffer, FileDesc->DirectoryMarker.Length);
|
||||||
|
*(PWSTR)(Request->Buffer +
|
||||||
|
Request->Req.QueryDirectory.Marker.Offset +
|
||||||
|
FileDesc->DirectoryMarker.Length) = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||||
|
@ -1231,7 +1231,7 @@ typedef struct
|
|||||||
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
|
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
|
||||||
DirectoryHasSuchFile:1;
|
DirectoryHasSuchFile:1;
|
||||||
UNICODE_STRING DirectoryPattern;
|
UNICODE_STRING DirectoryPattern;
|
||||||
UINT64 DirectoryOffset;
|
UNICODE_STRING DirectoryMarker;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
ULONG DirInfoCacheHint;
|
ULONG DirInfoCacheHint;
|
||||||
/* stream support */
|
/* stream support */
|
||||||
@ -1362,8 +1362,10 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action
|
|||||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified);
|
||||||
|
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||||
|
PUNICODE_STRING FileName);
|
||||||
NTSTATUS FspMainFileOpen(
|
NTSTATUS FspMainFileOpen(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PDEVICE_OBJECT DeviceObjectHint,
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
|
@ -84,8 +84,10 @@ NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
|||||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
||||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified);
|
||||||
|
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||||
|
PUNICODE_STRING FileName);
|
||||||
NTSTATUS FspMainFileOpen(
|
NTSTATUS FspMainFileOpen(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PDEVICE_OBJECT DeviceObjectHint,
|
PDEVICE_OBJECT DeviceObjectHint,
|
||||||
@ -147,7 +149,8 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
|||||||
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
||||||
#pragma alloc_text(PAGE, FspFileDescCreate)
|
#pragma alloc_text(PAGE, FspFileDescCreate)
|
||||||
#pragma alloc_text(PAGE, FspFileDescDelete)
|
#pragma alloc_text(PAGE, FspFileDescDelete)
|
||||||
#pragma alloc_text(PAGE, FspFileDescResetDirectoryPattern)
|
#pragma alloc_text(PAGE, FspFileDescResetDirectory)
|
||||||
|
#pragma alloc_text(PAGE, FspFileDescSetDirectoryMarker)
|
||||||
#pragma alloc_text(PAGE, FspMainFileOpen)
|
#pragma alloc_text(PAGE, FspMainFileOpen)
|
||||||
#pragma alloc_text(PAGE, FspMainFileClose)
|
#pragma alloc_text(PAGE, FspMainFileClose)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeOplockPrepare)
|
#pragma alloc_text(PAGE, FspFileNodeOplockPrepare)
|
||||||
@ -1984,15 +1987,19 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc)
|
|||||||
RtlFreeUnicodeString(&FileDesc->DirectoryPattern);
|
RtlFreeUnicodeString(&FileDesc->DirectoryPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
|
||||||
FspFree(FileDesc);
|
FspFree(FileDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||||
PUNICODE_STRING FileName, BOOLEAN Reset)
|
PUNICODE_STRING FileName, BOOLEAN RestartScan, BOOLEAN IndexSpecified)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
if (Reset || 0 == FileDesc->DirectoryPattern.Buffer)
|
if (0 == FileDesc->DirectoryPattern.Buffer ||
|
||||||
|
(RestartScan && 0 != FileName && 0 != FileName->Length))
|
||||||
{
|
{
|
||||||
UNICODE_STRING DirectoryPattern;
|
UNICODE_STRING DirectoryPattern;
|
||||||
|
|
||||||
@ -2029,7 +2036,51 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileDesc->DirectoryPattern = DirectoryPattern;
|
FileDesc->DirectoryPattern = DirectoryPattern;
|
||||||
|
FileDesc->DirectoryHasSuchFile = FALSE;
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
{
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
FileDesc->DirectoryMarker.Buffer = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (IndexSpecified && 0 != FileName && 0 != FileName->Length)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = FspFileDescSetDirectoryMarker(FileDesc, FileName);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
FileDesc->DirectoryHasSuchFile = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||||
|
PUNICODE_STRING FileName)
|
||||||
|
{
|
||||||
|
if (&FileDesc->DirectoryMarker == FileName)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(FileDesc->FileNode->FsvolDeviceObject);
|
||||||
|
UNICODE_STRING DirectoryMarker;
|
||||||
|
|
||||||
|
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength < FileName->Length)
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
|
||||||
|
DirectoryMarker.Length = DirectoryMarker.MaximumLength = FileName->Length;
|
||||||
|
DirectoryMarker.Buffer = FspAlloc(FileName->Length);
|
||||||
|
if (0 == DirectoryMarker.Buffer)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
RtlCopyMemory(DirectoryMarker.Buffer, FileName->Buffer, FileName->Length);
|
||||||
|
|
||||||
|
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||||
|
FspFree(FileDesc->DirectoryMarker.Buffer);
|
||||||
|
|
||||||
|
FileDesc->DirectoryMarker = DirectoryMarker;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -580,58 +580,6 @@ VOID MemfsFileNodeMapEnumerateFree(MEMFS_FILE_NODE_MAP_ENUM_CONTEXT *Context)
|
|||||||
free(Context->FileNodes);
|
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
|
* FSP_FILE_SYSTEM_INTERFACE
|
||||||
*/
|
*/
|
||||||
@ -745,7 +693,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
#endif
|
#endif
|
||||||
MEMFS_FILE_NODE *FileNode;
|
MEMFS_FILE_NODE *FileNode;
|
||||||
MEMFS_FILE_NODE *ParentNode;
|
MEMFS_FILE_NODE *ParentNode;
|
||||||
MEMFS_DIR_DESC *DirDesc = 0;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN Inserted;
|
BOOLEAN Inserted;
|
||||||
|
|
||||||
@ -794,20 +741,9 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CreateOptions & FILE_DIRECTORY_FILE)
|
|
||||||
{
|
|
||||||
Result = MemfsDirDescCreate(&DirDesc);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = MemfsFileNodeCreate(FileName, &FileNode);
|
Result = MemfsFileNodeCreate(FileName, &FileNode);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MEMFS_NAMED_STREAMS)
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
|
FileNode->MainFileNode = MemfsFileNodeMapGetMain(Memfs->FileNodeMap, FileName);
|
||||||
@ -823,8 +759,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == FileNode->FileSecurity)
|
if (0 == FileNode->FileSecurity)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
memcpy(FileNode->FileSecurity, SecurityDescriptor, FileNode->FileSecuritySize);
|
||||||
@ -837,8 +771,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == FileNode->FileData)
|
if (0 == FileNode->FileData)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -847,8 +779,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result) || !Inserted)
|
if (!NT_SUCCESS(Result) || !Inserted)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
Result = STATUS_OBJECT_NAME_COLLISION; /* should not happen! */
|
Result = STATUS_OBJECT_NAME_COLLISION; /* should not happen! */
|
||||||
return Result;
|
return Result;
|
||||||
@ -869,9 +799,6 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,7 +808,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode;
|
MEMFS_FILE_NODE *FileNode;
|
||||||
MEMFS_DIR_DESC *DirDesc = 0;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (MEMFS_MAX_PATH <= wcslen(FileName))
|
if (MEMFS_MAX_PATH <= wcslen(FileName))
|
||||||
@ -895,13 +821,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
||||||
{
|
|
||||||
Result = MemfsDirDescCreate(&DirDesc);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemfsFileNodeReference(FileNode);
|
MemfsFileNodeReference(FileNode);
|
||||||
*PFileNode = FileNode;
|
*PFileNode = FileNode;
|
||||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
@ -917,9 +836,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,13 +941,8 @@ static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
|
|
||||||
FspFileSystemGetOperationContext()->Request->Req.Close.UserContext2;
|
|
||||||
|
|
||||||
MemfsFileNodeDereference(FileNode);
|
MemfsFileNodeDereference(FileNode);
|
||||||
|
|
||||||
if (0 != DirDesc)
|
|
||||||
MemfsDirDescDelete(DirDesc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -1394,14 +1305,11 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
typedef struct _MEMFS_READ_DIRECTORY_CONTEXT
|
typedef struct _MEMFS_READ_DIRECTORY_CONTEXT
|
||||||
{
|
{
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
UINT64 Offset;
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PULONG PBytesTransferred;
|
PULONG PBytesTransferred;
|
||||||
BOOLEAN OffsetFound;
|
|
||||||
MEMFS_DIR_DESC *DirDesc;
|
|
||||||
} MEMFS_READ_DIRECTORY_CONTEXT;
|
} 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)
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
UINT8 DirInfoBuf[sizeof(FSP_FSCTL_DIR_INFO) + sizeof FileNode->FileName];
|
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);
|
FspPathSuffix(FileNode->FileName, &Remain, &Suffix, Root);
|
||||||
FileName = Suffix;
|
FileName = Suffix;
|
||||||
FspPathCombine(FileNode->FileName, Suffix);
|
FspPathCombine(FileNode->FileName, Suffix);
|
||||||
|
|
||||||
MemfsDirDescInsertFileName(DirDesc, FileNode->FileInfo.IndexNumber, FileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(FileName) * sizeof(WCHAR));
|
||||||
DirInfo->FileInfo = FileNode->FileInfo;
|
DirInfo->FileInfo = FileNode->FileInfo;
|
||||||
DirInfo->NextOffset = FileNode->FileInfo.IndexNumber;
|
|
||||||
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
|
|
||||||
return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred);
|
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;
|
MEMFS_READ_DIRECTORY_CONTEXT *Context = (MEMFS_READ_DIRECTORY_CONTEXT *)Context0;
|
||||||
|
|
||||||
if (0 != Context->Offset && !Context->OffsetFound)
|
return AddDirInfo(FileNode, 0,
|
||||||
{
|
|
||||||
Context->OffsetFound = FileNode->FileInfo.IndexNumber == Context->Offset;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddDirInfo(Context->DirDesc, FileNode, 0,
|
|
||||||
Context->Buffer, Context->Length, Context->PBytesTransferred);
|
Context->Buffer, Context->Length, Context->PBytesTransferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length,
|
PVOID FileNode0, PVOID Buffer, ULONG Length,
|
||||||
PWSTR Pattern,
|
PWSTR Pattern, PWSTR Marker,
|
||||||
PULONG PBytesTransferred)
|
PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
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_FILE_NODE *ParentNode;
|
||||||
MEMFS_READ_DIRECTORY_CONTEXT Context;
|
MEMFS_READ_DIRECTORY_CONTEXT Context;
|
||||||
PWSTR PrevFileName = 0;
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Context.Buffer = Buffer;
|
Context.Buffer = Buffer;
|
||||||
Context.Offset = Offset;
|
|
||||||
Context.Length = Length;
|
Context.Length = Length;
|
||||||
Context.PBytesTransferred = PBytesTransferred;
|
Context.PBytesTransferred = PBytesTransferred;
|
||||||
Context.OffsetFound = FALSE;
|
|
||||||
Context.DirDesc = DirDesc;
|
|
||||||
|
|
||||||
if (0 == Offset)
|
|
||||||
MemfsDirDescReset(DirDesc);
|
|
||||||
|
|
||||||
if (L'\0' != FileNode->FileName[1])
|
if (L'\0' != FileNode->FileName[1])
|
||||||
{
|
{
|
||||||
@ -1473,25 +1363,20 @@ static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 == ParentNode)
|
if (0 == ParentNode)
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
if (0 == Offset)
|
if (0 == Marker)
|
||||||
if (!AddDirInfo(DirDesc, FileNode, L".", Buffer, Length, PBytesTransferred))
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
if (0 == Offset || FileNode->FileInfo.IndexNumber == Offset)
|
|
||||||
{
|
{
|
||||||
Context.OffsetFound = FileNode->FileInfo.IndexNumber == Context.Offset;
|
if (!AddDirInfo(FileNode, L".", Buffer, Length, PBytesTransferred))
|
||||||
|
|
||||||
if (!AddDirInfo(DirDesc, ParentNode, L"..", Buffer, Length, PBytesTransferred))
|
|
||||||
return STATUS_SUCCESS;
|
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)
|
if (MemfsFileNodeMapEnumerateChildren(Memfs->FileNodeMap, FileNode, Marker,
|
||||||
{
|
|
||||||
PrevFileName = MemfsDirDescGetFileName(DirDesc, Offset);
|
|
||||||
Context.OffsetFound = 0 != PrevFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MemfsFileNodeMapEnumerateChildren(Memfs->FileNodeMap, FileNode, PrevFileName,
|
|
||||||
ReadDirectoryEnumFn, &Context))
|
ReadDirectoryEnumFn, &Context))
|
||||||
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user