NTSTATUS DokanDispatchCleanup(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) /*++ Routine Description: This device control dispatcher handles Cleanup IRP. Arguments: DeviceObject - Context for the activity. Irp - The device control argument block. Return Value: NTSTATUS --*/ { PDokanVCB vcb; PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_INVALID_PARAMETER; PFILE_OBJECT fileObject; PDokanCCB ccb = NULL; PDokanFCB fcb = NULL; PEVENT_CONTEXT eventContext; ULONG eventLength; DOKAN_INIT_LOGGER(logger, DeviceObject->DriverObject, IRP_MJ_CLEANUP); __try { DDbgPrint("==> DokanCleanup\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); // Cleanup must be success in any case if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_SUCCESS; __leave; } vcb = DeviceObject->DeviceExtension; if (vcb == NULL) { DDbgPrint(" No device extension\n"); status = STATUS_SUCCESS; __leave; } if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_SUCCESS; __leave; } ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); if (fcb->IsKeepalive) { DokanFCBLockRW(fcb); BOOLEAN shouldUnmount = ccb->IsKeepaliveActive; if (shouldUnmount) { // Here we intentionally let the VCB-level flag stay set, because // there's no sense in having an opportunity for an "operation timeout // unmount" in this case. ccb->IsKeepaliveActive = FALSE; } DokanFCBUnlock(fcb); if (shouldUnmount) { if (IsUnmountPendingVcb(vcb)) { DokanLogInfo(&logger, L"Ignoring keepalive close because unmount is already in" L" progress."); } else { DokanLogInfo(&logger, L"Unmounting due to keepalive close."); DokanUnmount(vcb->Dcb); } } } if (fcb->BlockUserModeDispatch) { status = STATUS_SUCCESS; __leave; } FlushFcb(fcb, fileObject); DokanFCBLockRW(fcb); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DokanFCBUnlock(fcb); __leave; } fileObject->Flags |= FO_CLEANUP_COMPLETE; eventContext->Context = ccb->UserContext; eventContext->FileFlags |= DokanCCBFlagsGet(ccb); // DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); // copy the filename to EventContext from ccb eventContext->Operation.Cleanup.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.Cleanup.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking. status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, DokanOplockComplete, DokanPrePostIrp); DokanFCBUnlock(fcb); // // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // if (status != STATUS_SUCCESS) { if (status == STATUS_PENDING) { DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); } else { DokanFreeEventContext(eventContext); } __leave; } // register this IRP to pending IRP list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { DokanCompleteIrpRequest(Irp, status, 0); DDbgPrint("<== DokanCleanup\n"); } return status; }
NTSTATUS DokanDispatchCleanup(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) /*++ Routine Description: This device control dispatcher handles Cleanup IRP. Arguments: DeviceObject - Context for the activity. Irp - The device control argument block. Return Value: NTSTATUS --*/ { PDokanVCB vcb; PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_INVALID_PARAMETER; PFILE_OBJECT fileObject; PDokanCCB ccb = NULL; PDokanFCB fcb = NULL; PEVENT_CONTEXT eventContext; ULONG eventLength; __try { DDbgPrint("==> DokanCleanup\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); // Cleanup must be success in any case if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_SUCCESS; __leave; } vcb = DeviceObject->DeviceExtension; if (vcb == NULL) { DDbgPrint(" No device extension\n"); status = STATUS_SUCCESS; __leave; } if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_SUCCESS; __leave; } ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); FlushFcb(fcb, fileObject); DokanFCBLockRW(fcb); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DokanFCBUnlock(fcb); __leave; } fileObject->Flags |= FO_CLEANUP_COMPLETE; eventContext->Context = ccb->UserContext; eventContext->FileFlags |= DokanCCBFlagsGet(ccb); // DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); // copy the filename to EventContext from ccb eventContext->Operation.Cleanup.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.Cleanup.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking. status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, DokanOplockComplete, DokanPrePostIrp); DokanFCBUnlock(fcb); // // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted // to service an oplock break and we need to leave now. // if (status != STATUS_SUCCESS) { if (status == STATUS_PENDING) { DDbgPrint(" FsRtlCheckOplock returned STATUS_PENDING\n"); } else { DokanFreeEventContext(eventContext); } __leave; } // register this IRP to pending IRP list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { DokanCompleteIrpRequest(Irp, status, 0); DDbgPrint("<== DokanCleanup\n"); } return status; }