sys: dirctl: support directory marker as FUSE style next offset

This commit is contained in:
Bill Zissimopoulos 2019-10-30 16:40:48 -07:00
parent 847eab3da4
commit 5110b3c5a1
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
2 changed files with 56 additions and 13 deletions

View File

@ -96,7 +96,7 @@ FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
/* marshalling */
#pragma warning(push)
#pragma warning(disable:4200) /* zero-sized array in struct/union */
#pragma warning(disable:4200 4201) /* zero-sized array in struct/union; nameless struct/union */
enum
{
FspFsctlTransactReservedKind = 0,
@ -175,7 +175,8 @@ enum
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
UINT32 WslFeatures:1; /* support features required for WSLinux */\
UINT32 KmReservedFlags:5;\
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
UINT32 KmReservedFlags:4;\
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\
@ -242,8 +243,12 @@ typedef struct
{
UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
union
{
UINT64 NextOffset;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
} DUMMYUNIONNAME;
WCHAR FileNameBuf[];
} FSP_FSCTL_DIR_INFO;
FSP_FSCTL_STATIC_ASSERT(104 == sizeof(FSP_FSCTL_DIR_INFO),

View File

@ -24,6 +24,7 @@
static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
PUINT64 DirectoryMarkerAsNextOffset,
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
BOOLEAN ReturnEaSize,
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
@ -88,6 +89,7 @@ enum
static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
PUINT64 DirectoryMarkerAsNextOffset,
FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry,
BOOLEAN ReturnEaSize,
FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize,
@ -130,6 +132,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
PVOID PrevDestBuf = 0;
ULONG BaseInfoLen, CopyLength;
UNICODE_STRING FileName;
UINT64 DirectoryNextOffset;
*PDestLen = 0;
@ -176,12 +179,21 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
FileName.MaximumLength = (USHORT)(DirInfoSize - sizeof(FSP_FSCTL_DIR_INFO));
FileName.Buffer = DirInfo->FileNameBuf;
DirectoryNextOffset = DirInfo->NextOffset;
if (0 != DirectoryMarker && 0 != DirectoryMarker->Buffer &&
!DirectoryMarkerFound)
{
DirectoryMarkerFound = 0 == FspFileNameCompare(
&FileName, DirectoryMarker, CaseInsensitive, 0);
continue;
if (0 == DirectoryMarkerAsNextOffset)
{
DirectoryMarkerFound = 0 == FspFileNameCompare(
&FileName, DirectoryMarker, CaseInsensitive, 0);
}
else
{
ASSERT(sizeof(UINT64) == DirectoryMarker->Length);
DirectoryMarkerFound = DirectoryNextOffset == *(PUINT64)DirectoryMarker->Buffer;
}
}
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
@ -272,8 +284,16 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
break;
}
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
if (0 == DirectoryMarkerAsNextOffset)
{
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = FileName.Length;
DirectoryMarkerOut->Buffer = (PVOID)((PUINT8)DestBuf + BaseInfoLen);
}
else
{
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = sizeof(UINT64);
DirectoryMarkerOut->Buffer = (PVOID)DirectoryMarkerAsNextOffset;
}
DestBuf = (PVOID)((PUINT8)DestBuf +
FSP_FSCTL_ALIGN_UP(BaseInfoLen + CopyLength, sizeof(LONGLONG)));
@ -283,7 +303,15 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
Loop = FALSE;
}
else
*DirectoryMarkerOut = FileName;
{
if (0 == DirectoryMarkerAsNextOffset)
*DirectoryMarkerOut = FileName;
else
{
DirectoryMarkerOut->Length = DirectoryMarkerOut->MaximumLength = sizeof(UINT64);
DirectoryMarkerOut->Buffer = (PVOID)DirectoryMarkerAsNextOffset;
}
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
@ -323,9 +351,12 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
FileDesc->DirInfo = FileNode->NonPaged->DirInfo;
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
UINT64 DirectoryMarkerAsNextOffset = 0;
PUINT8 DirInfoBgn = (PUINT8)DirInfo;
PUINT8 DirInfoEnd = (PUINT8)DirInfo + DirInfoSize;
@ -334,8 +365,10 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache(
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
0 != FileDesc->DirInfoCacheHint ? 0 : &FileDesc->DirectoryMarker, &DirectoryMarker,
FsvolDeviceExtension->VolumeParams.DirectoryMarkerAsNextOffset ?
&DirectoryMarkerAsNextOffset : 0,
FileInformationClass, ReturnSingleEntry,
!!FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes,
!!FsvolDeviceExtension->VolumeParams.ExtendedAttributes,
&DirInfo, DirInfoSize,
DestBuf, PDestLen);
@ -366,10 +399,13 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
PAGED_CODE();
NTSTATUS Result;
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);
BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive;
PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern;
UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker;
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
UINT64 DirectoryMarkerAsNextOffset = 0;
FSP_FSCTL_STATIC_ASSERT(
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) >=
@ -378,8 +414,10 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace(
Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive,
0, &DirectoryMarker,
FsvolDeviceExtension->VolumeParams.DirectoryMarkerAsNextOffset ?
&DirectoryMarkerAsNextOffset : 0,
FileInformationClass, ReturnSingleEntry,
!!FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes,
!!FsvolDeviceExtension->VolumeParams.ExtendedAttributes,
&DirInfo, DirInfoSize,
DestBuf, PDestLen);