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 */ /* marshalling */
#pragma warning(push) #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 enum
{ {
FspFsctlTransactReservedKind = 0, FspFsctlTransactReservedKind = 0,
@ -175,7 +175,8 @@ enum
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\ UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\ UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
UINT32 WslFeatures:1; /* support features required for WSLinux */\ 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 Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)]; WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\ #define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
@ -242,8 +243,12 @@ typedef struct
{ {
UINT16 Size; UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo; FSP_FSCTL_FILE_INFO FileInfo;
UINT8 Padding[24]; union
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */ {
UINT64 NextOffset;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
} DUMMYUNIONNAME;
WCHAR FileNameBuf[]; WCHAR FileNameBuf[];
} FSP_FSCTL_DIR_INFO; } FSP_FSCTL_DIR_INFO;
FSP_FSCTL_STATIC_ASSERT(104 == sizeof(FSP_FSCTL_DIR_INFO), FSP_FSCTL_STATIC_ASSERT(104 == sizeof(FSP_FSCTL_DIR_INFO),

View File

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