mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: FspFsextProvider
This commit is contained in:
parent
2cd1bddafb
commit
b637a72ec8
@ -65,6 +65,10 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
#define FSP_FSCTL_STOP \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
/* fsctl internal device codes (usable only in-kernel) */
|
||||
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'I', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
|
||||
|
||||
#define FSP_FSCTL_VOLUME_NAME_SIZE (64 * sizeof(WCHAR))
|
||||
@ -83,7 +87,7 @@ FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
|
||||
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN (64 * 1024)
|
||||
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
|
||||
|
||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((T) & 0xffffffff))
|
||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((UINT_PTR)((T) & 0xffffffff)))
|
||||
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff))
|
||||
|
||||
#define FSP_FSCTL_DEVICECONTROL_SIZEMAX (4 * 1024) /* must be < FSP_FSCTL_TRANSACT_{REQ,RSP}_SIZEMAX */
|
||||
@ -185,7 +189,8 @@ enum
|
||||
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 EaTimeout; /* EA timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 Reserved32[2];\
|
||||
UINT32 FsextControlCode;\
|
||||
UINT32 Reserved32[1];\
|
||||
UINT64 Reserved64[2];
|
||||
typedef struct
|
||||
{
|
||||
|
@ -43,10 +43,10 @@ typedef struct
|
||||
/* in */
|
||||
UINT32 DeviceTransactCode;
|
||||
UINT32 DeviceExtensionSize;
|
||||
NTSTATUS (*DeviceInit)(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS (*DeviceInit)(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_PARAMS *VolumeParams);
|
||||
VOID (*DeviceFini)(PDEVICE_OBJECT DeviceObject);
|
||||
VOID (*DeviceExpirationRoutine)(PDEVICE_OBJECT DeviceObject, UINT64 ExpirationTime);
|
||||
NTSTATUS (*DeviceTransact)(PIRP Irp, PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS (*DeviceTransact)(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
/* out */
|
||||
UINT32 DeviceExtensionOffset;
|
||||
} FSP_FSEXT_PROVIDER;
|
||||
|
@ -325,6 +325,20 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
* to track what has been initialized!
|
||||
*/
|
||||
|
||||
/* initialize any fsext provider */
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.FsextControlCode)
|
||||
{
|
||||
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||
FsvolDeviceExtension->VolumeParams.FsextControlCode);
|
||||
if (0 != Provider)
|
||||
{
|
||||
Result = Provider->DeviceInit(DeviceObject, &FsvolDeviceExtension->VolumeParams);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
FsvolDeviceExtension->InitDoneFsext = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* is there a virtual disk? */
|
||||
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
||||
{
|
||||
@ -500,6 +514,15 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||
if (0 != FsvolDeviceExtension->SwapVpb)
|
||||
FspFreeExternal(FsvolDeviceExtension->SwapVpb);
|
||||
}
|
||||
|
||||
/* finalize any fsext provider */
|
||||
if (FsvolDeviceExtension->InitDoneFsext)
|
||||
{
|
||||
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||
FsvolDeviceExtension->VolumeParams.FsextControlCode);
|
||||
if (0 != Provider)
|
||||
Provider->DeviceFini(DeviceObject);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID FspFsvolDeviceTimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
|
||||
@ -546,6 +569,14 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
|
||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->SecurityCache, InterruptTime);
|
||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->DirInfoCache, InterruptTime);
|
||||
FspMetaCacheInvalidateExpired(FsvolDeviceExtension->StreamInfoCache, InterruptTime);
|
||||
/* run any fsext provider expiration routine */
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.FsextControlCode)
|
||||
{
|
||||
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||
FsvolDeviceExtension->VolumeParams.FsextControlCode);
|
||||
if (0 != Provider)
|
||||
Provider->DeviceExpirationRoutine(DeviceObject, InterruptTime);
|
||||
}
|
||||
FspIoqRemoveExpired(FsvolDeviceExtension->Ioq, InterruptTime);
|
||||
|
||||
KeAcquireSpinLock(&FsvolDeviceExtension->ExpirationLock, &Irql);
|
||||
|
@ -1056,7 +1056,8 @@ typedef struct
|
||||
{
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1, InitDoneEa:1,
|
||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
|
||||
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1,
|
||||
InitDoneFsext;
|
||||
PDEVICE_OBJECT FsctlDeviceObject;
|
||||
PDEVICE_OBJECT FsvrtDeviceObject;
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
@ -1179,7 +1180,7 @@ VOID FspDeviceGlobalUnlock(VOID)
|
||||
// STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED)
|
||||
|
||||
/* fsext */
|
||||
FSP_FSEXT_PROVIDER *FspFsextProvider(VOID);
|
||||
FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode);
|
||||
|
||||
/* process buffers conditional usage */
|
||||
static inline
|
||||
|
@ -86,6 +86,7 @@ static NTSTATUS FspFsctlFileSystemControl(
|
||||
break;
|
||||
case FSP_FSCTL_TRANSACT:
|
||||
case FSP_FSCTL_TRANSACT_BATCH:
|
||||
case FSP_FSCTL_TRANSACT_INTERNAL:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeTransact(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
@ -93,6 +94,33 @@ static NTSTATUS FspFsctlFileSystemControl(
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeStop(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case 0:
|
||||
/* ensure that 0 != IrpSp->Parameters.FileSystemControl.FsControlCode in default: case */
|
||||
break;
|
||||
default:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
{
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
if (!FspDeviceReference(FsvolDeviceObject))
|
||||
{
|
||||
Result = STATUS_CANCELLED;
|
||||
break;
|
||||
}
|
||||
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(
|
||||
FsvolDeviceObject);
|
||||
if (IrpSp->Parameters.FileSystemControl.FsControlCode ==
|
||||
FsvolDeviceExtension->VolumeParams.FsextControlCode)
|
||||
{
|
||||
FSP_FSEXT_PROVIDER *Provider = FspFsextProvider(
|
||||
FsvolDeviceExtension->VolumeParams.FsextControlCode);
|
||||
if (0 != Provider)
|
||||
Result = Provider->DeviceTransact(FsvolDeviceObject, Irp);
|
||||
}
|
||||
|
||||
FspDeviceDereference(FsvolDeviceObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IRP_MN_MOUNT_VOLUME:
|
||||
|
@ -25,7 +25,7 @@
|
||||
static KSPIN_LOCK FsextSpinLock = 0;
|
||||
FSP_FSEXT_PROVIDER *FsextProvider;
|
||||
|
||||
FSP_FSEXT_PROVIDER *FspFsextProvider(VOID)
|
||||
FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode)
|
||||
{
|
||||
FSP_FSEXT_PROVIDER *Provider;
|
||||
KIRQL Irql;
|
||||
|
@ -652,7 +652,8 @@ NTSTATUS FspVolumeTransact(
|
||||
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||
ASSERT(
|
||||
FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||
FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_FSCTL_TRANSACT_INTERNAL == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||
ASSERT(
|
||||
METHOD_BUFFERED == (IrpSp->Parameters.FileSystemControl.FsControlCode & 3) ||
|
||||
METHOD_OUT_DIRECT == (IrpSp->Parameters.FileSystemControl.FsControlCode & 3));
|
||||
@ -663,8 +664,21 @@ NTSTATUS FspVolumeTransact(
|
||||
ULONG ControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
PVOID InputBuffer = 0;
|
||||
PVOID OutputBuffer = 0;
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
{
|
||||
InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
ASSERT(0 == InputBufferLength ||
|
||||
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) <= InputBufferLength);
|
||||
ASSERT(0 == OutputBufferLength ||
|
||||
sizeof(PVOID) <= OutputBufferLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (0 != InputBufferLength &&
|
||||
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
@ -674,6 +688,7 @@ NTSTATUS FspVolumeTransact(
|
||||
(FSP_FSCTL_TRANSACT_BATCH == ControlCode &&
|
||||
FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN > OutputBufferLength)))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (!FspDeviceReference(FsvolDeviceObject))
|
||||
return STATUS_CANCELLED;
|
||||
@ -683,6 +698,7 @@ NTSTATUS FspVolumeTransact(
|
||||
PUINT8 BufferEnd;
|
||||
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
||||
PVOID InternalBuffer = 0;
|
||||
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
|
||||
ULONG LoopCount;
|
||||
LARGE_INTEGER Timeout;
|
||||
@ -751,6 +767,9 @@ NTSTATUS FspVolumeTransact(
|
||||
/* were we sent an output buffer? */
|
||||
switch (ControlCode & 3)
|
||||
{
|
||||
case METHOD_NEITHER:
|
||||
OutputBuffer = Irp->UserBuffer;
|
||||
break;
|
||||
case METHOD_OUT_DIRECT:
|
||||
if (0 != Irp->MdlAddress)
|
||||
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||
@ -795,7 +814,9 @@ NTSTATUS FspVolumeTransact(
|
||||
RepostedIrp = 0;
|
||||
Request = OutputBuffer;
|
||||
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
||||
ASSERT(FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
||||
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode ?
|
||||
TRUE :
|
||||
FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
||||
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
|
||||
for (;;)
|
||||
{
|
||||
@ -815,9 +836,19 @@ NTSTATUS FspVolumeTransact(
|
||||
else if (!NT_SUCCESS(Result))
|
||||
FspIopCompleteIrp(PendingIrp, Result);
|
||||
else
|
||||
{
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
{
|
||||
InternalBuffer = FspAllocatePoolMustSucceed(
|
||||
PagedPool, PendingIrpRequest->Size, FSP_ALLOC_EXTERNAL_TAG);
|
||||
RtlCopyMemory(InternalBuffer, PendingIrpRequest, PendingIrpRequest->Size);
|
||||
*(PVOID *)OutputBuffer = InternalBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size);
|
||||
Request = FspFsctlTransactProduceRequest(Request, PendingIrpRequest->Size);
|
||||
}
|
||||
|
||||
if (!FspIoqStartProcessingIrp(FsvolDeviceExtension->Ioq, PendingIrp))
|
||||
{
|
||||
@ -828,12 +859,24 @@ NTSTATUS FspVolumeTransact(
|
||||
* also cancel the PendingIrp we have in our hands.
|
||||
*/
|
||||
ASSERT(FspIoqStopped(FsvolDeviceExtension->Ioq));
|
||||
if (0 != InternalBuffer)
|
||||
{
|
||||
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode);
|
||||
FspFree(InternalBuffer);
|
||||
}
|
||||
FspIopCompleteCanceledIrp(PendingIrp);
|
||||
Result = STATUS_CANCELLED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* are we doing single request or batch mode? */
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(PVOID);
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
if (FSP_FSCTL_TRANSACT == ControlCode)
|
||||
break;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user