mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: FspFsextProvider
This commit is contained in:
		| @@ -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,17 +664,31 @@ 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 (0 != InputBufferLength && | ||||
|         FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     if (0 != OutputBufferLength && | ||||
|         ((FSP_FSCTL_TRANSACT == ControlCode && | ||||
|             FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN > OutputBufferLength) || | ||||
|         (FSP_FSCTL_TRANSACT_BATCH == ControlCode && | ||||
|             FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN > OutputBufferLength))) | ||||
|         return STATUS_BUFFER_TOO_SMALL; | ||||
|     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; | ||||
|         if (0 != OutputBufferLength && | ||||
|             ((FSP_FSCTL_TRANSACT == ControlCode && | ||||
|                 FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN > OutputBufferLength) || | ||||
|             (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 (;;) | ||||
|     { | ||||
| @@ -816,8 +837,18 @@ NTSTATUS FspVolumeTransact( | ||||
|             FspIopCompleteIrp(PendingIrp, Result); | ||||
|         else | ||||
|         { | ||||
|             RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size); | ||||
|             Request = FspFsctlTransactProduceRequest(Request, PendingIrpRequest->Size); | ||||
|             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; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user