diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 8bdfd4bc..507aa487 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -48,6 +48,7 @@ typedef struct { UINT64 TotalAllocationUnits; UINT64 AvailableAllocationUnits; + UINT64 VolumeCreationTime; UINT16 VolumeLabelLength; WCHAR VolumeLabel[32]; } FSP_FSCTL_VOLUME_INFO; diff --git a/src/sys/volinfo.c b/src/sys/volinfo.c index dd80a85f..8a8a9596 100644 --- a/src/sys/volinfo.c +++ b/src/sys/volinfo.c @@ -6,17 +6,17 @@ #include -static NTSTATUS FspFsvolQueryVolumeAttributeInformation( +static NTSTATUS FspFsvolQueryFsAttributeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd); -static NTSTATUS FspFsvolQueryVolumeDeviceInformation( +static NTSTATUS FspFsvolQueryFsDeviceInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd); -static NTSTATUS FspFsvolQueryVolumeFullSizeInformation( +static NTSTATUS FspFsvolQueryFsFullSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); -static NTSTATUS FspFsvolQueryVolumeSizeInformation( +static NTSTATUS FspFsvolQueryFsSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); -static NTSTATUS FspFsvolQueryVolumeFsVolumeInformation( +static NTSTATUS FspFsvolQueryFsVolumeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); static NTSTATUS FspFsvolQueryVolumeInformation( @@ -29,11 +29,11 @@ FSP_DRIVER_DISPATCH FspQueryVolumeInformation; FSP_DRIVER_DISPATCH FspSetVolumeInformation; #ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, FspFsvolQueryVolumeAttributeInformation) -#pragma alloc_text(PAGE, FspFsvolQueryVolumeDeviceInformation) -#pragma alloc_text(PAGE, FspFsvolQueryVolumeFullSizeInformation) -#pragma alloc_text(PAGE, FspFsvolQueryVolumeSizeInformation) -#pragma alloc_text(PAGE, FspFsvolQueryVolumeFsVolumeInformation) +#pragma alloc_text(PAGE, FspFsvolQueryFsAttributeInformation) +#pragma alloc_text(PAGE, FspFsvolQueryFsDeviceInformation) +#pragma alloc_text(PAGE, FspFsvolQueryFsFullSizeInformation) +#pragma alloc_text(PAGE, FspFsvolQueryFsSizeInformation) +#pragma alloc_text(PAGE, FspFsvolQueryFsVolumeInformation) #pragma alloc_text(PAGE, FspFsvolQueryVolumeInformation) #pragma alloc_text(PAGE, FspFsvolQueryVolumeInformationComplete) #pragma alloc_text(PAGE, FspFsvolSetVolumeInformation) @@ -42,47 +42,157 @@ FSP_DRIVER_DISPATCH FspSetVolumeInformation; #pragma alloc_text(PAGE, FspSetVolumeInformation) #endif -static NTSTATUS FspFsvolQueryVolumeAttributeInformation( +#define GETVOLUMEINFO() \ + FSP_FSCTL_VOLUME_INFO VolumeInfoBuf;\ + if (0 == VolumeInfo) \ + { \ + if (!FspFsvolTryGetVolumeInfo(FsvolDeviceObject, &VolumeInfoBuf))\ + return FSP_STATUS_IOQ_POST; \ + VolumeInfo = &VolumeInfoBuf; \ + } + +static NTSTATUS FspFsvolQueryFsAttributeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + if (*PBuffer + sizeof(FILE_FS_ATTRIBUTE_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + NTSTATUS Result = STATUS_SUCCESS; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_FS_ATTRIBUTE_INFORMATION Info = (PFILE_FS_ATTRIBUTE_INFORMATION)*PBuffer; + PUINT8 Buffer = (PUINT8)Info->FileSystemName; + ULONG CopyLength; + + Info->FileSystemAttributes = + (FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch ? FILE_CASE_SENSITIVE_SEARCH : 0) | + (FsvolDeviceExtension->VolumeParams.CasePreservedNames ? FILE_CASE_PRESERVED_NAMES : 0) | + (FsvolDeviceExtension->VolumeParams.UnicodeOnDisk ? FILE_UNICODE_ON_DISK : 0) | + (FsvolDeviceExtension->VolumeParams.PersistentAcls ? FILE_PERSISTENT_ACLS : 0) | + (FsvolDeviceExtension->VolumeParams.ReparsePoints ? FILE_SUPPORTS_REPARSE_POINTS : 0) | + (FsvolDeviceExtension->VolumeParams.NamedStreams ? FILE_NAMED_STREAMS : 0) | + //(FsvolDeviceExtension->VolumeParams.HardLinks ? FILE_SUPPORTS_HARD_LINKS : 0) | + //(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) | + (FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0); + Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength; + Info->FileSystemNameLength = sizeof L"" DRIVER_NAME - sizeof(WCHAR); + + CopyLength = Info->FileSystemNameLength; + if (Buffer + CopyLength > BufferEnd) + { + CopyLength = (ULONG)(BufferEnd - Buffer); + Result = STATUS_BUFFER_OVERFLOW; + } + RtlCopyMemory(Buffer, L"" DRIVER_NAME, CopyLength); + Buffer += CopyLength; + + *PBuffer = Buffer; + + return Result; } -static NTSTATUS FspFsvolQueryVolumeDeviceInformation( +static NTSTATUS FspFsvolQueryFsDeviceInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + if (*PBuffer + sizeof(FILE_FS_DEVICE_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + PFILE_FS_DEVICE_INFORMATION Info = (PFILE_FS_DEVICE_INFORMATION)*PBuffer; + + Info->DeviceType = FsvolDeviceObject->DeviceType; + Info->Characteristics = FsvolDeviceObject->Characteristics; + + *PBuffer += sizeof(FILE_FS_DEVICE_INFORMATION); + + return STATUS_SUCCESS; } -static NTSTATUS FspFsvolQueryVolumeFullSizeInformation( +static NTSTATUS FspFsvolQueryFsFullSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + if (*PBuffer + sizeof(FILE_FS_FULL_SIZE_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + GETVOLUMEINFO(); + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_FS_FULL_SIZE_INFORMATION Info = (PFILE_FS_FULL_SIZE_INFORMATION)*PBuffer; + + Info->TotalAllocationUnits.QuadPart = VolumeInfo->TotalAllocationUnits; + Info->CallerAvailableAllocationUnits.QuadPart = VolumeInfo->AvailableAllocationUnits; + Info->ActualAvailableAllocationUnits.QuadPart = VolumeInfo->AvailableAllocationUnits; + Info->SectorsPerAllocationUnit = FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit; + Info->BytesPerSector = FsvolDeviceExtension->VolumeParams.SectorSize; + + *PBuffer += sizeof(FILE_FS_FULL_SIZE_INFORMATION); + + return STATUS_SUCCESS; } -static NTSTATUS FspFsvolQueryVolumeSizeInformation( +static NTSTATUS FspFsvolQueryFsSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + if (*PBuffer + sizeof(FILE_FS_SIZE_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + GETVOLUMEINFO(); + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_FS_SIZE_INFORMATION Info = (PFILE_FS_SIZE_INFORMATION)*PBuffer; + + Info->TotalAllocationUnits.QuadPart = VolumeInfo->TotalAllocationUnits; + Info->AvailableAllocationUnits.QuadPart = VolumeInfo->AvailableAllocationUnits; + Info->SectorsPerAllocationUnit = FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit; + Info->BytesPerSector = FsvolDeviceExtension->VolumeParams.SectorSize; + + *PBuffer += sizeof(FILE_FS_SIZE_INFORMATION); + + return STATUS_SUCCESS; } -static NTSTATUS FspFsvolQueryVolumeFsVolumeInformation( +static NTSTATUS FspFsvolQueryFsVolumeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + if (*PBuffer + sizeof(FILE_FS_VOLUME_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + GETVOLUMEINFO(); + + NTSTATUS Result = STATUS_SUCCESS; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_FS_VOLUME_INFORMATION Info = (PFILE_FS_VOLUME_INFORMATION)*PBuffer; + PUINT8 Buffer = (PUINT8)Info->VolumeLabel; + ULONG CopyLength; + + Info->VolumeCreationTime.QuadPart = VolumeInfo->VolumeCreationTime; + Info->VolumeSerialNumber = FsvolDeviceExtension->VolumeParams.SerialNumber; + Info->VolumeLabelLength = VolumeInfo->VolumeLabelLength; + Info->SupportsObjects = FALSE; + + CopyLength = VolumeInfo->VolumeLabelLength; + if (Buffer + CopyLength > BufferEnd) + { + CopyLength = (ULONG)(BufferEnd - Buffer); + Result = STATUS_BUFFER_OVERFLOW; + } + RtlCopyMemory(Buffer, VolumeInfo->VolumeLabel, CopyLength); + Buffer += CopyLength; + + *PBuffer = Buffer; + + return Result; } static NTSTATUS FspFsvolQueryVolumeInformation( @@ -97,19 +207,19 @@ static NTSTATUS FspFsvolQueryVolumeInformation( switch (IrpSp->Parameters.QueryVolume.FsInformationClass) { case FileFsAttributeInformation: - Result = FspFsvolQueryVolumeAttributeInformation(FsvolDeviceObject, &Buffer, BufferEnd); + Result = FspFsvolQueryFsAttributeInformation(FsvolDeviceObject, &Buffer, BufferEnd); break; case FileFsDeviceInformation: - Result = FspFsvolQueryVolumeDeviceInformation(FsvolDeviceObject, &Buffer, BufferEnd); + Result = FspFsvolQueryFsDeviceInformation(FsvolDeviceObject, &Buffer, BufferEnd); break; case FileFsFullSizeInformation: - Result = FspFsvolQueryVolumeFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); + Result = FspFsvolQueryFsFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); break; case FileFsSizeInformation: - Result = FspFsvolQueryVolumeSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); + Result = FspFsvolQueryFsSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); break; case FileFsVolumeInformation: - Result = FspFsvolQueryVolumeFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); + Result = FspFsvolQueryFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); break; default: Result = STATUS_INVALID_PARAMETER; @@ -153,21 +263,20 @@ VOID FspFsvolQueryVolumeInformationComplete( PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length; - //FspVolumeSetSizeInfo(FsvolDeviceObject, - // &Response->Rsp.QueryVolumeInformation.TotalAllocationUnits); + FspFsvolSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.QueryVolumeInformation.VolumeInfo); switch (IrpSp->Parameters.QueryVolume.FsInformationClass) { case FileFsFullSizeInformation: - Result = FspFsvolQueryVolumeFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, + Result = FspFsvolQueryFsFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, &Response->Rsp.QueryVolumeInformation.VolumeInfo); break; case FileFsSizeInformation: - Result = FspFsvolQueryVolumeSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, + Result = FspFsvolQueryFsSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, &Response->Rsp.QueryVolumeInformation.VolumeInfo); break; case FileFsVolumeInformation: - Result = FspFsvolQueryVolumeFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd, + Result = FspFsvolQueryFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd, &Response->Rsp.QueryVolumeInformation.VolumeInfo); break; default: