From 9527353b15d56473b8e99274a3bcf7aa86b35672 Mon Sep 17 00:00:00 2001 From: Bailey Date: Tue, 5 Jul 2016 12:28:31 +0200 Subject: [PATCH 1/2] add more use of FsRtlCheckOplock() where appropriate --- sys/cleanup.c | 13 +++++++++++++ sys/fileinfo.c | 12 ++++++++++++ sys/flush.c | 12 ++++++++++++ sys/fscontrol.c | 2 +- sys/write.c | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) diff --git a/sys/cleanup.c b/sys/cleanup.c index d72e990aa..5aebf8b49 100644 --- a/sys/cleanup.c +++ b/sys/cleanup.c @@ -110,6 +110,19 @@ Return Value: eventContext->Operation.Cleanup.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.Cleanup.FileName, fcb->FileName.Buffer, fcb->FileName.Length); + + + status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, + DokanOplockComplete, DokanPrePostIrp); + + // + // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted + // to service an oplock break and we need to leave now. + // + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + __leave; + } // register this IRP to pending IRP list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); diff --git a/sys/fileinfo.c b/sys/fileinfo.c index 697aa872d..c45003ce6 100644 --- a/sys/fileinfo.c +++ b/sys/fileinfo.c @@ -459,6 +459,18 @@ DokanDispatchSetInformation(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { eventContext->Operation.SetFile.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.SetFile.FileName, fcb->FileName.Buffer, fcb->FileName.Length); + + status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, + DokanOplockComplete, DokanPrePostIrp); + + // + // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted + // to service an oplock break and we need to leave now. + // + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + __leave; + } // register this IRP to waiting IRP list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); diff --git a/sys/flush.c b/sys/flush.c index 636006f88..078462558 100644 --- a/sys/flush.c +++ b/sys/flush.c @@ -77,6 +77,18 @@ DokanDispatchFlush(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { CcUninitializeCacheMap(fileObject, NULL, NULL); // fileObject->Flags &= FO_CLEANUP_COMPLETE; + + status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, + DokanOplockComplete, DokanPrePostIrp); + + // + // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted + // to service an oplock break and we need to leave now. + // + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + __leave; + } // register this IRP to waiting IRP list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); diff --git a/sys/fscontrol.c b/sys/fscontrol.c index 5e1126ed4..7fa5edfc4 100644 --- a/sys/fscontrol.c +++ b/sys/fscontrol.c @@ -131,7 +131,7 @@ NTSTATUS DokanOplockRequest(__in PIRP *pIrp) { ) { AcquiredVcb = ExAcquireResourceSharedLite(&(Fcb->Vcb->Resource), TRUE); - AcquiredFcb = ExAcquireResourceSharedLite(&(Fcb->Resource), TRUE); + AcquiredFcb = ExAcquireResourceExclusiveLite(&(Fcb->Resource), TRUE); #if (NTDDI_VERSION >= NTDDI_WIN7) if (!Dcb->FileLockInUserMode && FsRtlOplockIsSharedRequest(Irp)) { diff --git a/sys/write.c b/sys/write.c index 00369cbe5..d10025ca7 100644 --- a/sys/write.c +++ b/sys/write.c @@ -168,6 +168,8 @@ DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { eventContext->Operation.Write.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.Write.FileName, fcb->FileName.Buffer, fcb->FileName.Length); + + // When eventlength is less than event notification buffer, // returns it to user-mode using pending event. @@ -180,6 +182,25 @@ DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { // EventContext is no longer needed, clear it Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0; + + + // + // We now check whether we can proceed based on the state of + // the file oplocks. + // + if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) { + status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, + DokanOplockComplete, DokanPrePostIrp); + + // + // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted + // to service an oplock break and we need to leave now. + // + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + __leave; + } + } // register this IRP to IRP waiting list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); @@ -214,6 +235,24 @@ DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { requestContext->Length = requestContextLength; // requsts enough size to copy EventContext requestContext->Operation.Write.RequestLength = eventLength; + + // + // We now check whether we can proceed based on the state of + // the file oplocks. + // + if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) { + status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, requestContext, + DokanOplockComplete, DokanPrePostIrp); + + // + // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted + // to service an oplock break and we need to leave now. + // + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + __leave; + } + } // regiters this IRP to IRP wainting list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, requestContext, 0); From 0c64b849c8ce817037dcd5e67dac29bdd33971e1 Mon Sep 17 00:00:00 2001 From: Bailey Date: Tue, 5 Jul 2016 19:56:39 +0200 Subject: [PATCH 2/2] handle status other than STATUS_PENDING from FsRtlCheckOplock() --- sys/cleanup.c | 8 ++++++-- sys/fileinfo.c | 8 ++++++-- sys/flush.c | 8 ++++++-- sys/read.c | 8 ++++++-- sys/write.c | 18 ++++++++++++++---- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/sys/cleanup.c b/sys/cleanup.c index 5aebf8b49..04b2af2ba 100644 --- a/sys/cleanup.c +++ b/sys/cleanup.c @@ -119,8 +119,12 @@ Return Value: // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // - if (status == STATUS_PENDING) { - DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + if (status != STATUS_SUCCESS) { + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + } else { + DokanFreeEventContext(eventContext); + } __leave; } diff --git a/sys/fileinfo.c b/sys/fileinfo.c index c45003ce6..e946c65dc 100644 --- a/sys/fileinfo.c +++ b/sys/fileinfo.c @@ -467,8 +467,12 @@ DokanDispatchSetInformation(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // - if (status == STATUS_PENDING) { - DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + if (status != STATUS_SUCCESS) { + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + } else { + DokanFreeEventContext(eventContext); + } __leave; } diff --git a/sys/flush.c b/sys/flush.c index 078462558..025528fbf 100644 --- a/sys/flush.c +++ b/sys/flush.c @@ -85,8 +85,12 @@ DokanDispatchFlush(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // - if (status == STATUS_PENDING) { - DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + if (status != STATUS_SUCCESS) { + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + } else { + DokanFreeEventContext(eventContext); + } __leave; } diff --git a/sys/read.c b/sys/read.c index 99de1c6ae..2396ef9e1 100644 --- a/sys/read.c +++ b/sys/read.c @@ -203,8 +203,12 @@ Return Value: // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // - if (status == STATUS_PENDING) { - DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + if (status != STATUS_SUCCESS) { + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + } else { + DokanFreeEventContext(eventContext); + } __leave; } diff --git a/sys/write.c b/sys/write.c index d10025ca7..b47bffb19 100644 --- a/sys/write.c +++ b/sys/write.c @@ -196,8 +196,12 @@ DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // - if (status == STATUS_PENDING) { - DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + if (status != STATUS_SUCCESS) { + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + } else { + DokanFreeEventContext(eventContext); + } __leave; } } @@ -248,8 +252,14 @@ DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // - if (status == STATUS_PENDING) { - DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + if (status != STATUS_SUCCESS) { + if (status == STATUS_PENDING) { + DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); + } else { + DokanFreeEventContext(requestContext); + Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0; + DokanFreeEventContext(eventContext); + } __leave; } }