VOID DokanUnmount(__in PDokanDCB Dcb) { ULONG eventLength; PEVENT_CONTEXT eventContext; PDRIVER_EVENT_CONTEXT driverEventContext; PKEVENT completedEvent; LARGE_INTEGER timeout; PDokanVCB vcb = Dcb->Vcb; ULONG deviceNamePos; DDbgPrint("==> DokanUnmount\n"); eventLength = sizeof(EVENT_CONTEXT); eventContext = AllocateEventContextRaw(eventLength); if (eventContext == NULL) { ; // STATUS_INSUFFICIENT_RESOURCES; DDbgPrint(" Not able to allocate eventContext.\n"); if (vcb) { DokanEventRelease(vcb->DeviceObject); } return; } driverEventContext = CONTAINING_RECORD(eventContext, DRIVER_EVENT_CONTEXT, EventContext); completedEvent = ExAllocatePool(sizeof(KEVENT)); if (completedEvent) { KeInitializeEvent(completedEvent, NotificationEvent, FALSE); driverEventContext->Completed = completedEvent; } deviceNamePos = Dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1; for (; Dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos) ; RtlStringCchCopyW(eventContext->Operation.Unmount.DeviceName, sizeof(eventContext->Operation.Unmount.DeviceName) / sizeof(WCHAR), &(Dcb->SymbolicLinkName->Buffer[deviceNamePos])); DDbgPrint(" Send Unmount to Service : %ws\n", eventContext->Operation.Unmount.DeviceName); DokanEventNotification(&Dcb->Global->NotifyService, eventContext); if (completedEvent) { timeout.QuadPart = -1 * 10 * 1000 * 10; // 10 sec KeWaitForSingleObject(completedEvent, Executive, KernelMode, FALSE, &timeout); } if (vcb) { DokanEventRelease(vcb->DeviceObject); } if (completedEvent) { ExFreePool(completedEvent); } DDbgPrint("<== DokanUnmount\n"); }
NTSTATUS DokanRegisterPendingIrp( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PEVENT_CONTEXT EventContext, __in ULONG Flags ) { PDokanVCB vcb = DeviceObject->DeviceExtension; NTSTATUS status; if (GetIdentifierType(vcb) != VCB) { DbgPrint(" Type != VCB\n"); return STATUS_INVALID_PARAMETER; } status = RegisterPendingIrpMain( DeviceObject, Irp, EventContext->SerialNumber, &vcb->Dcb->PendingIrp, Flags, TRUE); if (status == STATUS_PENDING) { DokanEventNotification(&vcb->Dcb->NotifyEvent, EventContext); } else { DokanFreeEventContext(EventContext); } return status; }
VOID DokanCheckKeepAlive( PDEVICE_EXTENSION DeviceExtension) { LARGE_INTEGER tickCount; ULONG eventLength; PEVENT_CONTEXT eventContext; ULONG mounted; //DDbgPrint("==> DokanCheckKeepAlive\n"); KeQueryTickCount(&tickCount); ExAcquireResourceSharedLite(&DeviceExtension->Resource, TRUE); if ( (tickCount.QuadPart - DeviceExtension->TickCount.QuadPart) * KeQueryTimeIncrement() > DOKAN_KEEPALIVE_TIMEOUT * 10000 * 1000) { mounted = DeviceExtension->Mounted; ExReleaseResourceLite(&DeviceExtension->Resource); DDbgPrint(" Force to umount\n"); if (!mounted) { // not mounted return; } eventLength = sizeof(EVENT_CONTEXT); eventContext = ExAllocatePool(eventLength); if (eventContext == NULL) { ;//STATUS_INSUFFICIENT_RESOURCES; DokanEventRelease(DeviceExtension->DeviceObject); return; } RtlZeroMemory(eventContext, eventLength); eventContext->Length = eventLength; // set drive letter eventContext->Flags = mounted; DokanEventNotification(&DeviceExtension->Global->NotifyService, eventContext); DokanEventRelease(DeviceExtension->DeviceObject); } else { ExReleaseResourceLite(&DeviceExtension->Resource); } //DDbgPrint("<== DokanCheckKeepAlive\n"); }
NTSTATUS DokanDispatchClose( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: This device control dispatcher handles create & close IRPs. 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; PEVENT_CONTEXT eventContext; ULONG eventLength; PDokanFCB fcb; //PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanClose"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject is NULL"); status = STATUS_SUCCESS; __leave; } DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { if (fileObject->FsContext2) { ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); DDbgPrint(" Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); } status = STATUS_SUCCESS; __leave; } ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { //status = STATUS_INSUFFICIENT_RESOURCES; DDbgPrint(" eventContext == NULL"); DDbgPrint(" Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); status = STATUS_SUCCESS; __leave; } eventContext->Context = ccb->UserContext; DDbgPrint(" UserContext:%X\n", (ULONG)ccb->UserContext); // copy the file name to be closed eventContext->Close.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Close.FileName, fcb->FileName.Buffer, fcb->FileName.Length); DDbgPrint(" Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); // Close can not be pending status // don't register this IRP //status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext->SerialNumber, 0); // inform it to user-mode DokanEventNotification(&vcb->Dcb->NotifyEvent, eventContext); status = STATUS_SUCCESS; } __finally { if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } DDbgPrint("<== DokanClose"); FsRtlExitFileSystem(); } return status; }