mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-07 20:42:09 -05:00
sys: FspFsvolCreateTryFlushImage
This commit is contained in:
parent
8264ace57a
commit
12cec5dc22
@ -48,7 +48,7 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||
enum
|
||||
{
|
||||
FspFsctlTransactUnknownKind = 0,
|
||||
FspFsctlTransactReservedKind = 0,
|
||||
FspFsctlTransactCreateKind,
|
||||
FspFsctlTransactOverwriteKind,
|
||||
FspFsctlTransactCleanupKind,
|
||||
|
133
src/sys/create.c
133
src/sys/create.c
@ -15,7 +15,10 @@ static NTSTATUS FspFsvolCreate(
|
||||
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
|
||||
static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc);
|
||||
static NTSTATUS FspFsvolCreateTryFlushImage(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request,
|
||||
FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject);
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini;
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolCreateReservedRequestFini;
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolCreateOverwriteRequestFini;
|
||||
FSP_DRIVER_DISPATCH FspCreate;
|
||||
|
||||
@ -26,7 +29,9 @@ FSP_DRIVER_DISPATCH FspCreate;
|
||||
#pragma alloc_text(PAGE, FspFsvolCreatePrepare)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateComplete)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreatePostClose)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateTryFlushImage)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateRequestFini)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateReservedRequestFini)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateOverwriteRequestFini)
|
||||
#pragma alloc_text(PAGE, FspCreate)
|
||||
#endif
|
||||
@ -41,7 +46,7 @@ enum
|
||||
RequestAccessToken = 1,
|
||||
RequestProcess = 2,
|
||||
|
||||
/* OverwriteRequest */
|
||||
/* Reserved/OverwriteRequest */
|
||||
//RequestFileDesc = 0,
|
||||
RequestFileObject = 1,
|
||||
RequestState = 2,
|
||||
@ -347,7 +352,37 @@ NTSTATUS FspFsvolCreatePrepare(
|
||||
FSP_FILE_DESC *FileDesc;
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
if (FspFsctlTransactReservedKind == Request->Kind)
|
||||
{
|
||||
/*
|
||||
* This branch is not taken during IRP preparation, but rather during IRP completion
|
||||
* when FlushImageSection needs to be retried.
|
||||
*/
|
||||
FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
||||
FileNode = FileDesc->FileNode;
|
||||
FileObject = FspIopRequestContext(Request, RequestFileObject);
|
||||
|
||||
Result = FspFsvolCreateTryFlushImage(Irp, Request, FileNode, FileDesc, FileObject);
|
||||
if (STATUS_PENDING == Result)
|
||||
return Result;
|
||||
else
|
||||
{
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
/* SUCCESS! */
|
||||
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DEBUGLOGIRP(Irp, Result);
|
||||
|
||||
FspIopCompleteIrp(Irp, Result);
|
||||
|
||||
return FSP_STATUS_COMPLETED;
|
||||
}
|
||||
}
|
||||
else if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
{
|
||||
SecuritySubjectContext = &IrpSp->Parameters.Create.SecurityContext->
|
||||
AccessState->SubjectSecurityContext;
|
||||
@ -558,15 +593,9 @@ VOID FspFsvolCreateComplete(
|
||||
if (FlagOn(Response->Rsp.Create.Opened.GrantedAccess, FILE_WRITE_DATA) ||
|
||||
DeleteOnClose)
|
||||
{
|
||||
if (!MmFlushImageSection(&FileNode->NonPaged->SectionObjectPointers,
|
||||
MmFlushForWrite))
|
||||
{
|
||||
FspFsvolCreatePostClose(FileDesc);
|
||||
FspFileNodeClose(FileNode, FileObject, 0);
|
||||
|
||||
Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
||||
Result = FspFsvolCreateTryFlushImage(Irp, 0, FileNode, FileDesc, FileObject);
|
||||
if (STATUS_PENDING == Result || !NT_SUCCESS(Result))
|
||||
FSP_RETURN();
|
||||
}
|
||||
}
|
||||
|
||||
/* SUCCESS! */
|
||||
@ -690,6 +719,70 @@ static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc)
|
||||
*/
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvolCreateTryFlushImage(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request,
|
||||
FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(0 == Request || FspFsctlTransactReservedKind == Request->Kind);
|
||||
|
||||
BOOLEAN Success;
|
||||
|
||||
Success = FspFileNodeTryAcquireExclusive(FileNode, Main);
|
||||
if (!Success)
|
||||
{
|
||||
/* repost the IRP to retry later */
|
||||
NTSTATUS Result;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
||||
|
||||
if (0 == Request)
|
||||
{
|
||||
/* delete the old request */
|
||||
Request = FspIrpRequest(Irp);
|
||||
FspIrpRequest(Irp) = 0;
|
||||
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
||||
/* disassociate the FileDesc from the old Request as we want to keep it around! */
|
||||
FspIopDeleteRequest(Request);
|
||||
|
||||
/* create the special Reserved request */
|
||||
FspIopCreateRequestFunnel(Irp, 0, 0,
|
||||
FspFsvolCreateReservedRequestFini, TRUE,
|
||||
&Request);
|
||||
|
||||
/* associate the FileDesc and FileObject with the Reserved request */
|
||||
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
|
||||
FspIopRequestContext(Request, RequestFileObject) = FileObject;
|
||||
|
||||
Request->Kind = FspFsctlTransactReservedKind;
|
||||
}
|
||||
|
||||
FspIoqPostIrpBestEffort(FsvolDeviceExtension->Ioq, Irp, &Result);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
Success = MmFlushImageSection(&FileNode->NonPaged->SectionObjectPointers,
|
||||
MmFlushForWrite);
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
if (!Success)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
BOOLEAN DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);
|
||||
|
||||
if (0 == Request)
|
||||
{
|
||||
FspFsvolCreatePostClose(FileDesc);
|
||||
FspFileNodeClose(FileNode, FileObject, 0);
|
||||
}
|
||||
|
||||
return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspFsvolCreateRequestFini(PVOID Context[3])
|
||||
{
|
||||
PAGED_CODE();
|
||||
@ -731,6 +824,26 @@ static VOID FspFsvolCreateRequestFini(PVOID Context[3])
|
||||
Context[RequestFileDesc] = Context[RequestAccessToken] = Context[RequestProcess] = 0;
|
||||
}
|
||||
|
||||
static VOID FspFsvolCreateReservedRequestFini(PVOID Context[3])
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FILE_DESC *FileDesc = Context[RequestFileDesc];
|
||||
PFILE_OBJECT FileObject = Context[RequestFileObject];
|
||||
|
||||
if (0 != FileDesc)
|
||||
{
|
||||
ASSERT(0 != FileObject);
|
||||
|
||||
FspFsvolCreatePostClose(FileDesc);
|
||||
FspFileNodeClose(FileDesc->FileNode, FileObject, 0);
|
||||
FspFileNodeDereference(FileDesc->FileNode);
|
||||
FspFileDescDelete(FileDesc);
|
||||
}
|
||||
|
||||
Context[RequestFileDesc] = Context[RequestFileObject] = 0;
|
||||
}
|
||||
|
||||
static VOID FspFsvolCreateOverwriteRequestFini(PVOID Context[3])
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define FSP_STATUS_PRIVATE_BIT (0x20000000)
|
||||
#define FSP_STATUS_IOQ_POST (FSP_STATUS_PRIVATE_BIT | 0x0000)
|
||||
#define FSP_STATUS_IOQ_POST_BEST_EFFORT (FSP_STATUS_PRIVATE_BIT | 0x0001)
|
||||
#define FSP_STATUS_COMPLETED (FSP_STATUS_PRIVATE_BIT | 0x0002)
|
||||
|
||||
/* misc macros */
|
||||
#define FSP_ALLOC_INTERNAL_TAG 'IpsF'
|
||||
@ -43,6 +44,13 @@
|
||||
#define DEBUGLOG(fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
/* DEBUGLOGIRP */
|
||||
#if DBG
|
||||
#define DEBUGLOGIRP(Irp, Result) FspDebugLogIrp(Irp, Result)
|
||||
#else
|
||||
#define DEBUGLOGIRP(Irp, Result) ((void)0)
|
||||
#endif
|
||||
|
||||
/* DEBUGBREAK */
|
||||
#if DBG
|
||||
extern __declspec(selectany) int fsp_bp = 1;
|
||||
@ -590,6 +598,19 @@ const char *NtStatusSym(NTSTATUS Status);
|
||||
const char *IrpMajorFunctionSym(UCHAR MajorFunction);
|
||||
const char *IrpMinorFunctionSym(UCHAR MajorFunction, UCHAR MinorFunction);
|
||||
const char *IoctlCodeSym(ULONG ControlCode);
|
||||
static inline
|
||||
VOID FspDebugLogIrp(PIRP Irp, NTSTATUS Result)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
DEBUGLOG("IRP=%p, %s%c, %s%s, IoStatus=%s[%lld]",
|
||||
Irp,
|
||||
(const char *)&FspDeviceExtension(IrpSp->DeviceObject)->Kind,
|
||||
Irp->RequestorMode == KernelMode ? 'K' : 'U',
|
||||
IrpMajorFunctionSym(IrpSp->MajorFunction),
|
||||
IrpMinorFunctionSym(IrpSp->MajorFunction, IrpSp->MinorFunction),
|
||||
NtStatusSym(Result),
|
||||
(LONGLONG)Irp->IoStatus.Information);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* extern */
|
||||
|
@ -238,15 +238,7 @@ VOID FspIopCompleteCanceledIrp(PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
#if DBG
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
DEBUGLOG("IRP=%p, %s%c, %s%s",
|
||||
Irp,
|
||||
(const char *)&FspDeviceExtension(IrpSp->DeviceObject)->Kind,
|
||||
Irp->RequestorMode == KernelMode ? 'K' : 'U',
|
||||
IrpMajorFunctionSym(IrpSp->MajorFunction),
|
||||
IrpMinorFunctionSym(IrpSp->MajorFunction, IrpSp->MinorFunction));
|
||||
#endif
|
||||
DEBUGLOGIRP(Irp, STATUS_CANCELLED);
|
||||
|
||||
FspIopCompleteIrpEx(Irp, STATUS_CANCELLED, TRUE);
|
||||
}
|
||||
|
@ -565,7 +565,9 @@ NTSTATUS FspVolumeTransact(
|
||||
PendingIrpRequest = FspIrpRequest(PendingIrp);
|
||||
|
||||
Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest);
|
||||
if (STATUS_PENDING == Result)
|
||||
if (FSP_STATUS_COMPLETED == Result)
|
||||
;
|
||||
else if (STATUS_PENDING == Result)
|
||||
{
|
||||
/*
|
||||
* The IRP has been reposted to our Ioq. Remember the first such IRP,
|
||||
|
Loading…
x
Reference in New Issue
Block a user