From 62b0e889b24eda3e664386c524325fd86b80d6cf Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 21 Mar 2019 14:05:17 -0700 Subject: [PATCH] sys: FileEaInformation and EaSize support --- inc/winfsp/fsctl.h | 11 +++++++++++ src/sys/dirctl.c | 13 +++++++++---- src/sys/fileinfo.c | 39 ++++++++++++++++++++++++++------------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 6d7d99be..2e039c96 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -206,6 +206,8 @@ typedef struct UINT16 VolumeLabelLength; WCHAR VolumeLabel[32]; } FSP_FSCTL_VOLUME_INFO; +FSP_FSCTL_STATIC_ASSERT(88 == sizeof(FSP_FSCTL_VOLUME_INFO), + "sizeof(FSP_FSCTL_VOLUME_INFO) must be exactly 88."); typedef struct { UINT32 FileAttributes; @@ -218,13 +220,18 @@ typedef struct UINT64 ChangeTime; UINT64 IndexNumber; UINT32 HardLinks; /* unimplemented: set to 0 */ + UINT32 EaSize; } FSP_FSCTL_FILE_INFO; +FSP_FSCTL_STATIC_ASSERT(72 == sizeof(FSP_FSCTL_FILE_INFO), + "sizeof(FSP_FSCTL_FILE_INFO) must be exactly 72."); typedef struct { FSP_FSCTL_FILE_INFO FileInfo; PWSTR NormalizedName; UINT16 NormalizedNameSize; } FSP_FSCTL_OPEN_FILE_INFO; +FSP_FSCTL_STATIC_ASSERT(88 == sizeof(FSP_FSCTL_OPEN_FILE_INFO), + "sizeof(FSP_FSCTL_OPEN_FILE_INFO) must be exactly 88."); typedef struct { UINT16 Size; @@ -233,6 +240,8 @@ typedef struct /* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */ WCHAR FileNameBuf[]; } FSP_FSCTL_DIR_INFO; +FSP_FSCTL_STATIC_ASSERT(104 == sizeof(FSP_FSCTL_DIR_INFO), + "sizeof(FSP_FSCTL_DIR_INFO) must be exactly 104."); typedef struct { UINT16 Size; @@ -240,6 +249,8 @@ typedef struct UINT64 StreamAllocationSize; WCHAR StreamNameBuf[]; } FSP_FSCTL_STREAM_INFO; +FSP_FSCTL_STATIC_ASSERT(24 == sizeof(FSP_FSCTL_STREAM_INFO), + "sizeof(FSP_FSCTL_STREAM_INFO) must be exactly 24."); typedef struct { UINT64 UserContext; diff --git a/src/sys/dirctl.c b/src/sys/dirctl.c index fa999838..8621511d 100644 --- a/src/sys/dirctl.c +++ b/src/sys/dirctl.c @@ -25,6 +25,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy( PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive, PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut, FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry, + BOOLEAN ReturnEaSize, FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize, PVOID DestBuf, PULONG PDestLen); static NTSTATUS FspFsvolQueryDirectoryCopyCache( @@ -88,6 +89,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy( PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive, PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut, FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry, + BOOLEAN ReturnEaSize, FSP_FSCTL_DIR_INFO **PDirInfo, ULONG DirInfoSize, PVOID DestBuf, PULONG PDestLen) { @@ -226,12 +228,12 @@ static NTSTATUS FspFsvolQueryDirectoryCopy( break; case FileFullDirectoryInformation: FILL_INFO(FILE_FULL_DIR_INFORMATION, - Info->EaSize = 0; + Info->EaSize = ReturnEaSize ? DirInfo->FileInfo.EaSize : 0; ); break; case FileIdFullDirectoryInformation: FILL_INFO(FILE_ID_FULL_DIR_INFORMATION, - Info->EaSize = 0; + Info->EaSize = ReturnEaSize ? DirInfo->FileInfo.EaSize : 0; Info->FileId.QuadPart = DirInfo->FileInfo.IndexNumber; ); break; @@ -240,14 +242,14 @@ static NTSTATUS FspFsvolQueryDirectoryCopy( break; case FileBothDirectoryInformation: FILL_INFO(FILE_BOTH_DIR_INFORMATION, - Info->EaSize = 0; + Info->EaSize = ReturnEaSize ? DirInfo->FileInfo.EaSize : 0; Info->ShortNameLength = 0; RtlZeroMemory(Info->ShortName, sizeof Info->ShortName); ); break; case FileIdBothDirectoryInformation: FILL_INFO(FILE_ID_BOTH_DIR_INFORMATION, - Info->EaSize = 0; + Info->EaSize = ReturnEaSize ? DirInfo->FileInfo.EaSize : 0; Info->ShortNameLength = 0; RtlZeroMemory(Info->ShortName, sizeof Info->ShortName); Info->FileId.QuadPart = DirInfo->FileInfo.IndexNumber; @@ -321,6 +323,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyCache( Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive, 0 != FileDesc->DirInfoCacheHint ? 0 : &FileDesc->DirectoryMarker, &DirectoryMarker, FileInformationClass, ReturnSingleEntry, + !!FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes, &DirInfo, DirInfoSize, DestBuf, PDestLen); @@ -354,6 +357,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace( BOOLEAN CaseInsensitive = !FileDesc->CaseSensitive; PUNICODE_STRING DirectoryPattern = &FileDesc->DirectoryPattern; UNICODE_STRING DirectoryMarker = FileDesc->DirectoryMarker; + FSP_FILE_NODE *FileNode = FileDesc->FileNode; FSP_FSCTL_STATIC_ASSERT( FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) >= @@ -363,6 +367,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopyInPlace( Result = FspFsvolQueryDirectoryCopy(DirectoryPattern, CaseInsensitive, 0, &DirectoryMarker, FileInformationClass, ReturnSingleEntry, + !!FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes, &DirInfo, DirInfoSize, DestBuf, PDestLen); diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index 431e6f03..c3188f96 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -31,7 +31,8 @@ static NTSTATUS FspFsvolQueryBasicInformation(PFILE_OBJECT FileObject, PVOID *PBuffer, PVOID BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo); static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject, - PVOID *PBuffer, PVOID BufferEnd); + PVOID *PBuffer, PVOID BufferEnd, + const FSP_FSCTL_FILE_INFO *FileInfo); static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject, PVOID *PBuffer, PVOID BufferEnd); static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject, @@ -175,7 +176,9 @@ static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject, Info->InternalInformation.IndexNumber.QuadPart = FileNode->IndexNumber; - Info->EaInformation.EaSize = 0; + Info->EaInformation.EaSize = + FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes ? + FileInfo->EaSize : 0; Info->PositionInformation.CurrentByteOffset = FileObject->CurrentByteOffset; @@ -236,20 +239,25 @@ static NTSTATUS FspFsvolQueryBasicInformation(PFILE_OBJECT FileObject, } static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject, - PVOID *PBuffer, PVOID BufferEnd) + PVOID *PBuffer, PVOID BufferEnd, + const FSP_FSCTL_FILE_INFO *FileInfo) { PAGED_CODE(); PFILE_EA_INFORMATION Info = (PFILE_EA_INFORMATION)*PBuffer; - if ((PVOID)(Info + 1) > BufferEnd) - return STATUS_BUFFER_TOO_SMALL; + if (0 == FileInfo) + { + if ((PVOID)(Info + 1) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; - /* - * No EA support currently. We must nevertheless respond to this query - * or SRV2 gets unhappy. Just tell them that we have 0 EA's. - */ - Info->EaSize = 0; + return STATUS_SUCCESS; + } + + FSP_FILE_NODE *FileNode = FileObject->FsContext; + Info->EaSize = + FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)->VolumeParams.ExtendedAttributes ? + FileInfo->EaSize : 0; *PBuffer = (PVOID)(Info + 1); @@ -679,9 +687,8 @@ static NTSTATUS FspFsvolQueryInformation( Result = STATUS_INVALID_PARAMETER; /* no compression support */ return Result; case FileEaInformation: - Result = FspFsvolQueryEaInformation(FileObject, &Buffer, BufferEnd); - Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer); - return Result; + Result = FspFsvolQueryEaInformation(FileObject, &Buffer, BufferEnd, 0); + break; case FileHardLinkInformation: Result = STATUS_NOT_SUPPORTED; /* no hard link support */ return Result; @@ -733,6 +740,9 @@ static NTSTATUS FspFsvolQueryInformation( case FileBasicInformation: Result = FspFsvolQueryBasicInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf); break; + case FileEaInformation: + Result = FspFsvolQueryEaInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf); + break; case FileNetworkOpenInformation: Result = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf); break; @@ -840,6 +850,9 @@ NTSTATUS FspFsvolQueryInformationComplete( case FileBasicInformation: Result = FspFsvolQueryBasicInformation(FileObject, &Buffer, BufferEnd, FileInfo); break; + case FileEaInformation: + Result = FspFsvolQueryEaInformation(FileObject, &Buffer, BufferEnd, FileInfo); + break; case FileNetworkOpenInformation: Result = FspFsvolQueryNetworkOpenInformation(FileObject, &Buffer, BufferEnd, FileInfo); break;