VOID DokanCompleteCleanup(__in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PDokanCCB ccb; PDokanFCB fcb; PDokanVCB vcb; PFILE_OBJECT fileObject; DDbgPrint("==> DokanCompleteCleanup\n"); irp = IrpEntry->Irp; irpSp = IrpEntry->IrpSp; fileObject = IrpEntry->FileObject; ASSERT(fileObject != NULL); ccb = fileObject->FsContext2; ASSERT(ccb != NULL); ccb->UserContext = EventInfo->Context; // DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); fcb = ccb->Fcb; ASSERT(fcb != NULL); vcb = fcb->Vcb; status = EventInfo->Status; DokanFCBLockRO(fcb); if (DokanFCBFlagsIsSet(fcb, DOKAN_DELETE_ON_CLOSE)) { if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED); } else { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED); } } DokanFCBUnlock(fcb); // // Unlock all outstanding file locks. // (VOID) FsRtlFastUnlockAll(&fcb->FileLock, fileObject, IoGetRequestorProcess(irp), NULL); if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) { FsRtlNotifyCleanup(vcb->NotifySync, &vcb->DirNotifyList, ccb); } IoRemoveShareAccess(irpSp->FileObject, &fcb->ShareAccess); DokanCompleteIrpRequest(irp, status, 0); DDbgPrint("<== DokanCompleteCleanup\n"); }
VOID DokanCompleteSetInformation( __in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo ) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status; ULONG info = 0; PDokanCCB ccb; PDokanFCB fcb; UNICODE_STRING oldFileName; FILE_INFORMATION_CLASS infoClass; __try { DDbgPrint("==> DokanCompleteSetInformation\n"); irp = IrpEntry->Irp; irpSp = IrpEntry->IrpSp; ccb = IrpEntry->FileObject->FsContext2; ASSERT(ccb != NULL); ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE); fcb = ccb->Fcb; ASSERT(fcb != NULL); ccb->UserContext = EventInfo->Context; status = EventInfo->Status; info = EventInfo->BufferLength; infoClass = irpSp->Parameters.SetFile.FileInformationClass; RtlZeroMemory(&oldFileName, sizeof(UNICODE_STRING)); if (NT_SUCCESS(status)) { if (infoClass == FileDispositionInformation) { if (EventInfo->Delete.DeleteOnClose) { if (!MmFlushImageSection( &fcb->SectionObjectPointers, MmFlushForDelete)) { DDbgPrint(" Cannot delete user mapped image\n"); status = STATUS_CANNOT_DELETE; } else { ccb->Flags |= DOKAN_DELETE_ON_CLOSE; fcb->Flags |= DOKAN_DELETE_ON_CLOSE; DDbgPrint(" FileObject->DeletePending = TRUE\n"); IrpEntry->FileObject->DeletePending = TRUE; } } else { ccb->Flags &= ~DOKAN_DELETE_ON_CLOSE; fcb->Flags &= ~DOKAN_DELETE_ON_CLOSE; DDbgPrint(" FileObject->DeletePending = FALSE\n"); IrpEntry->FileObject->DeletePending = FALSE; } } // if rename is executed, reassign the file name if(infoClass == FileRenameInformation) { PVOID buffer = NULL; ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE); // this is used to inform rename in the bellow switch case oldFileName.Buffer = fcb->FileName.Buffer; oldFileName.Length = (USHORT)fcb->FileName.Length; oldFileName.MaximumLength = (USHORT)fcb->FileName.Length; // copy new file name buffer = ExAllocatePool(EventInfo->BufferLength+sizeof(WCHAR)); if (buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; ExReleaseResourceLite(&fcb->Resource); ExReleaseResourceLite(&ccb->Resource); __leave; } fcb->FileName.Buffer = buffer; ASSERT(fcb->FileName.Buffer != NULL); RtlZeroMemory(fcb->FileName.Buffer, EventInfo->BufferLength+sizeof(WCHAR)); RtlCopyMemory(fcb->FileName.Buffer, EventInfo->Buffer, EventInfo->BufferLength); fcb->FileName.Length = (USHORT)EventInfo->BufferLength; fcb->FileName.MaximumLength = (USHORT)EventInfo->BufferLength; ExReleaseResourceLite(&fcb->Resource); } } ExReleaseResourceLite(&ccb->Resource); if (NT_SUCCESS(status)) { switch (irpSp->Parameters.SetFile.FileInformationClass) { case FileAllocationInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); break; case FileBasicInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION, FILE_ACTION_MODIFIED); break; case FileDispositionInformation: if (IrpEntry->FileObject->DeletePending) { if (fcb->Flags & DOKAN_FILE_DIRECTORY) { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED); } else { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED); } } break; case FileEndOfFileInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); break; case FileLinkInformation: // TODO: should check whether this is a directory // TODO: should notify new link name //DokanNotifyReportChange(vcb, ccb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED); break; case FilePositionInformation: // this is never used break; case FileRenameInformation: { DokanNotifyReportChange0(fcb, &oldFileName, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_OLD_NAME); // free old file name ExFreePool(oldFileName.Buffer); DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_NEW_NAME); } break; case FileValidDataLengthInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); break; default: DDbgPrint(" unknown type:%d\n", irpSp->Parameters.SetFile.FileInformationClass); break; } } } __finally { irp->IoStatus.Status = status; irp->IoStatus.Information = info; IoCompleteRequest(irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); DDbgPrint("<== DokanCompleteSetInformation\n"); } }
VOID DokanCompleteWrite(__in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PDokanCCB ccb; PDokanFCB fcb; PFILE_OBJECT fileObject; fileObject = IrpEntry->FileObject; ASSERT(fileObject != NULL); DDbgPrint("==> DokanCompleteWrite %wZ\n", &fileObject->FileName); irp = IrpEntry->Irp; irpSp = IrpEntry->IrpSp; ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); ccb->UserContext = EventInfo->Context; // DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); status = EventInfo->Status; irp->IoStatus.Status = status; irp->IoStatus.Information = EventInfo->BufferLength; if (NT_SUCCESS(status)) { //Check if file size changed if (fcb->AdvancedFCBHeader.FileSize.QuadPart < EventInfo->Operation.Write.CurrentByteOffset.QuadPart) { if (!(irp->Flags & IRP_PAGING_IO)) { DokanFCBLockRO(fcb); } DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); if (!(irp->Flags & IRP_PAGING_IO)) { DokanFCBUnlock(fcb); } //Update size with new offset InterlockedExchange64( &fcb->AdvancedFCBHeader.FileSize.QuadPart, EventInfo->Operation.Write.CurrentByteOffset.QuadPart); } DokanFCBFlagsSetBit(fcb, DOKAN_FILE_CHANGE_LAST_WRITE); if (EventInfo->BufferLength != 0 && fileObject->Flags & FO_SYNCHRONOUS_IO && !(irp->Flags & IRP_PAGING_IO)) { // update current byte offset only when synchronous IO and not paging IO fileObject->CurrentByteOffset.QuadPart = EventInfo->Operation.Write.CurrentByteOffset.QuadPart; DDbgPrint(" Updated CurrentByteOffset %I64d\n", fileObject->CurrentByteOffset.QuadPart); } } DokanCompleteIrpRequest(irp, irp->IoStatus.Status, irp->IoStatus.Information); DDbgPrint("<== DokanCompleteWrite\n"); }
VOID DokanCompleteCreate( __in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo ) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status; ULONG info; PDokanCCB ccb; PDokanFCB fcb; irp = IrpEntry->Irp; irpSp = IrpEntry->IrpSp; DDbgPrint("==> DokanCompleteCreate\n"); ccb = IrpEntry->FileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); DDbgPrint(" FileName:%wZ\n", &fcb->FileName); ccb->UserContext = EventInfo->Context; //DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); status = EventInfo->Status; info = EventInfo->Create.Information; switch (info) { case FILE_OPENED: DDbgPrint(" FILE_OPENED\n"); break; case FILE_CREATED: DDbgPrint(" FILE_CREATED\n"); break; case FILE_OVERWRITTEN: DDbgPrint(" FILE_OVERWRITTEN\n"); break; case FILE_DOES_NOT_EXIST: DDbgPrint(" FILE_DOES_NOT_EXIST\n"); break; case FILE_EXISTS: DDbgPrint(" FILE_EXISTS\n"); break; default: DDbgPrint(" info = %d\n", info); break; } ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE); if (NT_SUCCESS(status) && (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE || EventInfo->Create.Flags & DOKAN_FILE_DIRECTORY)) { if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) { DDbgPrint(" FILE_DIRECTORY_FILE %p\n", fcb); } else { DDbgPrint(" DOKAN_FILE_DIRECTORY %p\n", fcb); } fcb->Flags |= DOKAN_FILE_DIRECTORY; } ExReleaseResourceLite(&fcb->Resource); ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE); if (NT_SUCCESS(status)) { ccb->Flags |= DOKAN_FILE_OPENED; } ExReleaseResourceLite(&ccb->Resource); if (NT_SUCCESS(status)) { if (info == FILE_CREATED) { if (fcb->Flags & DOKAN_FILE_DIRECTORY) { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_ADDED); } else { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED); } } } else { DDbgPrint(" IRP_MJ_CREATE failed. Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); } irp->IoStatus.Status = status; irp->IoStatus.Information = info; IoCompleteRequest(irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); DDbgPrint("<== DokanCompleteCreate\n"); }