fsctl: FSP_FSCTL_VOLUME_PARAMS

This commit is contained in:
Bill Zissimopoulos 2016-01-25 12:02:52 -08:00
parent ed91c26c59
commit 1c464cad2b
5 changed files with 124 additions and 20 deletions

View File

@ -43,7 +43,14 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */ #define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */ #define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */
/* file metadata */ /* volume/file metadata */
typedef struct
{
UINT64 TotalAllocationUnits;
UINT64 AvailableAllocationUnits;
UINT16 VolumeLabelLength;
WCHAR VolumeLabel[32];
} FSP_FSCTL_VOLUME_INFO;
typedef struct typedef struct
{ {
UINT32 FileAttributes; UINT32 FileAttributes;
@ -100,14 +107,28 @@ enum
}; };
typedef struct typedef struct
{ {
UINT16 Version; UINT16 Version; /* set to 0 */
/* volume information */
UINT16 SectorSize; UINT16 SectorSize;
UINT32 SerialNumber; UINT16 SectorsPerAllocationUnit;
UINT32 TransactTimeout; /* milliseconds; values between 1 sec and 10 sec */ UINT16 MaxComponentLength; /* maximum file name component length (bytes) */
UINT32 IrpTimeout; /* milliseconds; values between 1 min and 10 min */ UINT32 SerialNumber; /* volume serial number */
UINT32 IrpCapacity; /* maximum number of pending IRP's */ /* I/O timeouts, capacity, etc. */
UINT32 FileInfoTimeout; /* milliseconds */ UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */
UINT32 EaSupported:1; /* supports extended attributes (unimplemented; set to 0) */ UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/
UINT32 FileInfoTimeout; /* FileInfo/VolumeInfo timeout (millis) */
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
UINT32 ReparsePoints:1; /* file system supports reparse points (!!!: unimplemented) */
UINT32 NamedStreams:1; /* file system supports named streams (!!!: unimplemented) */
UINT32 HardLinks:1; /* unimplemented; set to 0 */
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
UINT32 ReadOnlyVolume:1;
/* other flags */
UINT32 FileNameRequired:1; /* FileName required for all operations (not just Create) */ UINT32 FileNameRequired:1; /* FileName required for all operations (not just Create) */
WCHAR Prefix[64]; /* UNC prefix to recognize (\\server\path format, 0-term) */ WCHAR Prefix[64]; /* UNC prefix to recognize (\\server\path format, 0-term) */
} FSP_FSCTL_VOLUME_PARAMS; } FSP_FSCTL_VOLUME_PARAMS;
@ -205,8 +226,7 @@ typedef struct
} QueryInformation; } QueryInformation;
struct struct
{ {
UINT64 TotalAllocationUnits; FSP_FSCTL_VOLUME_INFO VolumeInfo;
UINT64 AvailableAllocationUnits;
} QueryVolumeInformation; } QueryVolumeInformation;
} Rsp; } Rsp;
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[]; FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];

View File

@ -35,6 +35,9 @@ VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareElement; static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareElement;
static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateElement; static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateElement;
static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeElement; static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeElement;
VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
NTSTATUS FspDeviceCopyList( NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
VOID FspDeviceDeleteList( VOID FspDeviceDeleteList(
@ -307,6 +310,10 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
IoStartTimer(DeviceObject); IoStartTimer(DeviceObject);
FsvolDeviceExtension->InitDoneTimer = 1; FsvolDeviceExtension->InitDoneTimer = 1;
/* initialize the volume information */
KeInitializeSpinLock(&FsvolDeviceExtension->InfoSpinLock);
FsvolDeviceExtension->InitDoneInfo = 1;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -509,6 +516,66 @@ static VOID NTAPI FspFsvolDeviceFreeElement(
PAGED_CODE(); PAGED_CODE();
} }
VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{
// !PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
FSP_FSCTL_VOLUME_INFO VolumeInfoNp;
KIRQL Irql;
KeAcquireSpinLock(&FsvolDeviceExtension->InfoSpinLock, &Irql);
VolumeInfoNp = FsvolDeviceExtension->VolumeInfo;
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
*VolumeInfo = VolumeInfoNp;
}
#pragma warning(push)
#pragma warning(disable:4701) /* disable idiotic warning! */
BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{
// !PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
FSP_FSCTL_VOLUME_INFO VolumeInfoNp;
KIRQL Irql;
BOOLEAN Result;
KeAcquireSpinLock(&FsvolDeviceExtension->InfoSpinLock, &Irql);
if (0 < FsvolDeviceExtension->InfoExpirationTime &&
KeQueryInterruptTime() < FsvolDeviceExtension->InfoExpirationTime)
{
VolumeInfoNp = FsvolDeviceExtension->VolumeInfo;
Result = TRUE;
}
else
Result = FALSE;
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
if (Result)
*VolumeInfo = VolumeInfoNp;
return Result;
}
#pragma warning(pop)
VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{
// !PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
FSP_FSCTL_VOLUME_INFO VolumeInfoNp = *VolumeInfo;
KIRQL Irql;
UINT64 FileInfoTimeout = FsvolDeviceExtension->VolumeParams.FileInfoTimeout * 10000ULL;
KeAcquireSpinLock(&FsvolDeviceExtension->InfoSpinLock, &Irql);
FsvolDeviceExtension->VolumeInfo = VolumeInfoNp;
FsvolDeviceExtension->InfoExpirationTime = 0 != FileInfoTimeout ?
KeQueryInterruptTime() + FileInfoTimeout : 0;
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
}
NTSTATUS FspDeviceCopyList( NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount) PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount)
{ {

View File

@ -443,7 +443,8 @@ typedef struct
typedef struct typedef struct
{ {
FSP_DEVICE_EXTENSION Base; FSP_DEVICE_EXTENSION Base;
UINT32 InitDoneFsvrt:1, InitDoneDelRsc:1, InitDoneIoq:1, InitDoneGenTab:1, InitDoneTimer:1; UINT32 InitDoneFsvrt:1, InitDoneDelRsc:1, InitDoneIoq:1, InitDoneGenTab:1, InitDoneTimer:1,
InitDoneInfo:1;
PDEVICE_OBJECT FsctlDeviceObject; PDEVICE_OBJECT FsctlDeviceObject;
PDEVICE_OBJECT FsvrtDeviceObject; PDEVICE_OBJECT FsvrtDeviceObject;
HANDLE MupHandle; HANDLE MupHandle;
@ -461,6 +462,9 @@ typedef struct
PVOID GenericTableElementStorage; PVOID GenericTableElementStorage;
UNICODE_STRING VolumeName; UNICODE_STRING VolumeName;
WCHAR VolumeNameBuf[FSP_DEVICE_VOLUME_NAME_LENMAX / sizeof(WCHAR)]; WCHAR VolumeNameBuf[FSP_DEVICE_VOLUME_NAME_LENMAX / sizeof(WCHAR)];
KSPIN_LOCK InfoSpinLock;
UINT64 InfoExpirationTime;
FSP_FSCTL_VOLUME_INFO VolumeInfo;
} FSP_FSVOL_DEVICE_EXTENSION; } FSP_FSVOL_DEVICE_EXTENSION;
static inline static inline
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject) FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
@ -491,6 +495,9 @@ PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier
FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
PBOOLEAN PDeleted); PBOOLEAN PDeleted);
VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
NTSTATUS FspDeviceCopyList( NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
VOID FspDeviceDeleteList( VOID FspDeviceDeleteList(

View File

@ -12,12 +12,13 @@ static NTSTATUS FspFsvolQueryVolumeDeviceInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd); PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd);
static NTSTATUS FspFsvolQueryVolumeFullSizeInformation( static NTSTATUS FspFsvolQueryVolumeFullSizeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
const UINT64 *Sizes); const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
static NTSTATUS FspFsvolQueryVolumeSizeInformation( static NTSTATUS FspFsvolQueryVolumeSizeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
const UINT64 *Sizes); const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
static NTSTATUS FspFsvolQueryVolumeFsVolumeInformation( static NTSTATUS FspFsvolQueryVolumeFsVolumeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd); PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
static NTSTATUS FspFsvolQueryVolumeInformation( static NTSTATUS FspFsvolQueryVolumeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete;
@ -59,7 +60,7 @@ static NTSTATUS FspFsvolQueryVolumeDeviceInformation(
static NTSTATUS FspFsvolQueryVolumeFullSizeInformation( static NTSTATUS FspFsvolQueryVolumeFullSizeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
const UINT64 *Sizes) const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{ {
PAGED_CODE(); PAGED_CODE();
@ -68,7 +69,7 @@ static NTSTATUS FspFsvolQueryVolumeFullSizeInformation(
static NTSTATUS FspFsvolQueryVolumeSizeInformation( static NTSTATUS FspFsvolQueryVolumeSizeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
const UINT64 *Sizes) const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{ {
PAGED_CODE(); PAGED_CODE();
@ -76,7 +77,8 @@ static NTSTATUS FspFsvolQueryVolumeSizeInformation(
} }
static NTSTATUS FspFsvolQueryVolumeFsVolumeInformation( static NTSTATUS FspFsvolQueryVolumeFsVolumeInformation(
PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd) PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd,
const FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{ {
PAGED_CODE(); PAGED_CODE();
@ -107,7 +109,7 @@ static NTSTATUS FspFsvolQueryVolumeInformation(
Result = FspFsvolQueryVolumeSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); Result = FspFsvolQueryVolumeSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
break; break;
case FileFsVolumeInformation: case FileFsVolumeInformation:
Result = FspFsvolQueryVolumeFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd); Result = FspFsvolQueryVolumeFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0);
break; break;
default: default:
Result = STATUS_INVALID_PARAMETER; Result = STATUS_INVALID_PARAMETER;
@ -158,11 +160,15 @@ VOID FspFsvolQueryVolumeInformationComplete(
{ {
case FileFsFullSizeInformation: case FileFsFullSizeInformation:
Result = FspFsvolQueryVolumeFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, Result = FspFsvolQueryVolumeFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd,
&Response->Rsp.QueryVolumeInformation.TotalAllocationUnits); &Response->Rsp.QueryVolumeInformation.VolumeInfo);
break; break;
case FileFsSizeInformation: case FileFsSizeInformation:
Result = FspFsvolQueryVolumeSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, Result = FspFsvolQueryVolumeSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd,
&Response->Rsp.QueryVolumeInformation.TotalAllocationUnits); &Response->Rsp.QueryVolumeInformation.VolumeInfo);
break;
case FileFsVolumeInformation:
Result = FspFsvolQueryVolumeFsVolumeInformation(FsvolDeviceObject, &Buffer, BufferEnd,
&Response->Rsp.QueryVolumeInformation.VolumeInfo);
break; break;
default: default:
ASSERT(0); ASSERT(0);

View File

@ -87,6 +87,10 @@ NTSTATUS FspVolumeCreate(
/* check the VolumeParams */ /* check the VolumeParams */
if (0 == VolumeParams.SectorSize) if (0 == VolumeParams.SectorSize)
VolumeParams.SectorSize = 512; VolumeParams.SectorSize = 512;
if (0 == VolumeParams.SectorsPerAllocationUnit)
VolumeParams.SectorsPerAllocationUnit = 1;
if (0 == VolumeParams.MaxComponentLength)
VolumeParams.MaxComponentLength = 255;
if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout || if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum) VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault; VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;