Exemplo n.º 1
0
VOID FlushFcb(__in PDokanFCB fcb, __in_opt PFILE_OBJECT fileObject) {

  if (fcb == NULL) {
    return;
  }

  if (fcb->SectionObjectPointers.ImageSectionObject != NULL) {
    DDbgPrint("  MmFlushImageSection FileName: %wZ FileCount: %lu.\n",
              &fcb->FileName, fcb->FileCount);
    MmFlushImageSection(&fcb->SectionObjectPointers, MmFlushForWrite);
    DDbgPrint("  MmFlushImageSection done FileName: %wZ FileCount: %lu.\n",
              &fcb->FileName, fcb->FileCount);
  }

  if (fcb->SectionObjectPointers.DataSectionObject != NULL) {
    DDbgPrint("  CcFlushCache FileName: %wZ FileCount: %lu.\n", &fcb->FileName,
              fcb->FileCount);
    ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
    CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
    CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
    if (fileObject != NULL) {
      CcUninitializeCacheMap(fileObject, NULL, NULL);
    }
    ExReleaseResourceLite(&fcb->PagingIoResource);
    DDbgPrint("  CcFlushCache done FileName: %wZ FileCount: %lu.\n",
              &fcb->FileName, fcb->FileCount);
  }
}
Exemplo n.º 2
0
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
    UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge)
{
    /*
     * The FileNode must be acquired exclusive (Full) when calling this function.
     */

    PAGED_CODE();

    LARGE_INTEGER FlushOffset;
    PLARGE_INTEGER PFlushOffset = &FlushOffset;
    FSP_FSCTL_FILE_INFO FileInfo;
    IO_STATUS_BLOCK IoStatus = { STATUS_SUCCESS };

    FlushOffset.QuadPart = FlushOffset64;
    if (FILE_WRITE_TO_END_OF_FILE == FlushOffset.LowPart && -1L == FlushOffset.HighPart)
    {
        if (FspFileNodeTryGetFileInfo(FileNode, &FileInfo))
            FlushOffset.QuadPart = FileInfo.FileSize;
        else
            PFlushOffset = 0; /* we don't know how big the file is, so flush it all! */
    }

    /* it is unclear if the Cc* calls below can raise or not; wrap them just in case */
    try
    {
        if (0 != FspMvCcCoherencyFlushAndPurgeCache)
        {
            /* if we are on Win7+ use CcCoherencyFlushAndPurgeCache */
            FspMvCcCoherencyFlushAndPurgeCache(
                &FileNode->NonPaged->SectionObjectPointers, PFlushOffset, FlushLength, &IoStatus,
                FlushAndPurge ? 0 : CC_FLUSH_AND_PURGE_NO_PURGE);

            if (STATUS_CACHE_PAGE_LOCKED == IoStatus.Status)
                IoStatus.Status = STATUS_SUCCESS;
        }
        else
        {
            /* do it the old-fashioned way; non-cached and mmap'ed I/O are non-coherent */
            CcFlushCache(&FileNode->NonPaged->SectionObjectPointers, PFlushOffset, FlushLength, &IoStatus);
            if (NT_SUCCESS(IoStatus.Status))
            {
                if (FlushAndPurge)
                    CcPurgeCacheSection(&FileNode->NonPaged->SectionObjectPointers, PFlushOffset, FlushLength, FALSE);

                IoStatus.Status = STATUS_SUCCESS;
            }
        }
    }
    except (EXCEPTION_EXECUTE_HANDLER)
    {
        IoStatus.Status = GetExceptionCode();
    }

    return IoStatus.Status;
}
Exemplo n.º 3
0
VOID PurgeFile(PLKLFCB fcb, BOOLEAN flush_before_purge)
{
	IO_STATUS_BLOCK iosb;

	ASSERT(fcb);

	if (flush_before_purge)
		CcFlushCache(&fcb->section_object, NULL, 0, &iosb);
	if (fcb->section_object.ImageSectionObject)
		MmFlushImageSection(&fcb->section_object, MmFlushForWrite);
	if (fcb->section_object.DataSectionObject)
		CcPurgeCacheSection(&fcb->section_object, NULL, 0, FALSE);
}
Exemplo n.º 4
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPurgeFile(
	IN PFFS_FCB Fcb,
	IN BOOLEAN  FlushBeforePurge)
{
	IO_STATUS_BLOCK    IoStatus;

    PAGED_CODE();

	ASSERT(Fcb != NULL);

	ASSERT((Fcb->Identifier.Type == FFSFCB) &&
			(Fcb->Identifier.Size == sizeof(FFS_FCB)));


	if(!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) && FlushBeforePurge &&
			!IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: CcFlushCache on %s.\n", 
					Fcb->AnsiFileName.Buffer));

		ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
		ExReleaseResourceLite(&Fcb->PagingIoResource);

		CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);

		ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
	}

	if (Fcb->SectionObject.ImageSectionObject)
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: MmFlushImageSection on %s.\n", 
					Fcb->AnsiFileName.Buffer));

		MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
	}

	if (Fcb->SectionObject.DataSectionObject)
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: CcPurgeCacheSection on %s.\n",
					Fcb->AnsiFileName.Buffer));

		CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
	}

	return STATUS_SUCCESS;
}
Exemplo n.º 5
0
BOOLEAN
NTAPI
CcFlushImageSection(PSECTION_OBJECT_POINTERS SectionObjectPointer,
                    MMFLUSH_TYPE FlushType)
{
    PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
    PNOCC_BCB Bcb;
    PLIST_ENTRY Entry;
    IO_STATUS_BLOCK IOSB;
    BOOLEAN Result = TRUE;

    if (!Map) return TRUE;

    for (Entry = Map->AssociatedBcb.Flink;
         Entry != &Map->AssociatedBcb;
         Entry = Entry->Flink)
    {
        Bcb = CONTAINING_RECORD(Entry, NOCC_BCB, ThisFileList);

        if (!Bcb->Dirty) continue;

        switch (FlushType)
        {
            case MmFlushForDelete:
                CcPurgeCacheSection(SectionObjectPointer,
                                    &Bcb->FileOffset,
                                    Bcb->Length,
                                    FALSE);
                break;
            case MmFlushForWrite:
                CcFlushCache(SectionObjectPointer,
                             &Bcb->FileOffset,
                             Bcb->Length,
                             &IOSB);
                break;
        }
    }

    return Result;
}
Exemplo n.º 6
0
/*
 * rename an existing FAT entry
 */
NTSTATUS
vfatRenameEntry(
    IN PDEVICE_EXTENSION DeviceExt,
    IN PVFATFCB pFcb,
    IN PUNICODE_STRING FileName,
    IN BOOLEAN CaseChangeOnly)
{
    OEM_STRING NameA;
    ULONG StartIndex;
    PVOID Context = NULL;
    LARGE_INTEGER Offset;
    PFATX_DIR_ENTRY pDirEntry;
    NTSTATUS Status;

    DPRINT("vfatRenameEntry(%p, %p, %wZ, %d)\n", DeviceExt, pFcb, FileName, CaseChangeOnly);

    if (pFcb->Flags & FCB_IS_FATX_ENTRY)
    {
        VFAT_DIRENTRY_CONTEXT DirContext;

        /* Open associated dir entry */
        StartIndex = pFcb->startIndex;
        Offset.u.HighPart = 0;
        Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
        _SEH2_TRY
        {
            CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;

        pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];

        /* Set file name */
        NameA.Buffer = (PCHAR)pDirEntry->Filename;
        NameA.Length = 0;
        NameA.MaximumLength = 42;
        RtlUnicodeStringToOemString(&NameA, FileName, FALSE);
        pDirEntry->FilenameLength = (unsigned char)NameA.Length;

        /* Update FCB */
        DirContext.ShortNameU.Length = 0;
        DirContext.ShortNameU.MaximumLength = 0;
        DirContext.ShortNameU.Buffer = NULL;
        DirContext.LongNameU = *FileName;
        DirContext.DirEntry.FatX = *pDirEntry;

        CcSetDirtyPinnedData(Context, NULL);
        CcUnpinData(Context);

        Status = vfatUpdateFCB(DeviceExt, pFcb, &DirContext, pFcb->parentFcb);
        if (NT_SUCCESS(Status))
        {
            CcPurgeCacheSection(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, FALSE);
        }

        return Status;
    }
Exemplo n.º 7
0
NTSTATUS
DokanDispatchSetInformation(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {

  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  PIO_STACK_LOCATION irpSp;
  PVOID buffer;
  PFILE_OBJECT fileObject;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  ULONG eventLength;
  PFILE_OBJECT targetFileObject;
  PEVENT_CONTEXT eventContext;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN fcbLocked = FALSE;
  PFILE_END_OF_FILE_INFORMATION pInfoEoF = NULL;

  vcb = DeviceObject->DeviceExtension;

  __try {
    DDbgPrint("==> DokanSetInformationn\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    ccb = (PDokanCCB)fileObject->FsContext2;
    ASSERT(ccb != NULL);

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    buffer = Irp->AssociatedIrp.SystemBuffer;

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    switch (irpSp->Parameters.SetFile.FileInformationClass) {
    case FileAllocationInformation:
      DDbgPrint(
          "  FileAllocationInformation %lld\n",
          ((PFILE_ALLOCATION_INFORMATION)buffer)->AllocationSize.QuadPart);
      break;
    case FileBasicInformation:
      DDbgPrint("  FileBasicInformation\n");
      break;
    case FileDispositionInformation:
      DDbgPrint("  FileDispositionInformation\n");
      break;
    case FileEndOfFileInformation:
      if ((fileObject->SectionObjectPointer != NULL) &&
          (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {

        pInfoEoF = (PFILE_END_OF_FILE_INFORMATION)buffer;

        if (!MmCanFileBeTruncated(fileObject->SectionObjectPointer,
                                  &pInfoEoF->EndOfFile)) {
          status = STATUS_USER_MAPPED_FILE;
          __leave;
        }

        if (!isPagingIo) {
          ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
          CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
          CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
          ExReleaseResourceLite(&fcb->PagingIoResource);
        }
      }
      DDbgPrint("  FileEndOfFileInformation %lld\n",
                ((PFILE_END_OF_FILE_INFORMATION)buffer)->EndOfFile.QuadPart);
      break;
    case FileLinkInformation:
      DDbgPrint("  FileLinkInformation\n");
      break;
    case FilePositionInformation: {
      PFILE_POSITION_INFORMATION posInfo;

      posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
      ASSERT(posInfo != NULL);

      DDbgPrint("  FilePositionInformation %lld\n",
                posInfo->CurrentByteOffset.QuadPart);
      fileObject->CurrentByteOffset = posInfo->CurrentByteOffset;

      status = STATUS_SUCCESS;

      __leave;
    } break;
    case FileRenameInformation:
      DDbgPrint("  FileRenameInformation\n");
      break;
    case FileValidDataLengthInformation:
      DDbgPrint("  FileValidDataLengthInformation\n");
      break;
    default:
      DDbgPrint("  unknown type:%d\n",
                irpSp->Parameters.SetFile.FileInformationClass);
      break;
    }

    //
    // when this IRP is not handled in swich case
    //

    // calcurate the size of EVENT_CONTEXT
    // it is sum of file name length and size of FileInformation
    DokanFCBLockRW(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length +
                  irpSp->Parameters.SetFile.Length;

    targetFileObject = irpSp->Parameters.SetFile.FileObject;

    if (targetFileObject) {
      DDbgPrint("  FileObject Specified %wZ\n", &(targetFileObject->FileName));
      eventLength += targetFileObject->FileName.Length;
    }

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;

    eventContext->Operation.SetFile.FileInformationClass =
        irpSp->Parameters.SetFile.FileInformationClass;

    // the size of FileInformation
    eventContext->Operation.SetFile.BufferLength =
        irpSp->Parameters.SetFile.Length;

    // the offset from begining of structure to fill FileInfo
    eventContext->Operation.SetFile.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.SetFile.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // the last null char

    BOOLEAN isRenameOrLink = irpSp->Parameters.SetFile.FileInformationClass ==
        FileRenameInformation ||
        irpSp->Parameters.SetFile.FileInformationClass == FileLinkInformation;

    if (!isRenameOrLink) {
        // copy FileInformation
        RtlCopyMemory(
            (PCHAR)eventContext + eventContext->Operation.SetFile.BufferOffset,
            Irp->AssociatedIrp.SystemBuffer, irpSp->Parameters.SetFile.Length);
    }

    if (isRenameOrLink) {
      // We need to hanle FileRenameInformation separetly because the structure
      // of FILE_RENAME_INFORMATION
      // has HANDLE type field, which size is different in 32 bit and 64 bit
      // environment.
      // This cases problems when driver is 64 bit and user mode library is 32
      // bit.
      PFILE_RENAME_INFORMATION renameInfo =
          (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
      PDOKAN_RENAME_INFORMATION renameContext = (PDOKAN_RENAME_INFORMATION)(
          (PCHAR)eventContext + eventContext->Operation.SetFile.BufferOffset);

      // This code assumes FILE_RENAME_INFORMATION and FILE_LINK_INFORMATION
      // have
      // the same typse and fields.
      ASSERT(sizeof(FILE_RENAME_INFORMATION) == sizeof(FILE_LINK_INFORMATION));

      renameContext->ReplaceIfExists = renameInfo->ReplaceIfExists;
      renameContext->FileNameLength = renameInfo->FileNameLength;
      RtlCopyMemory(renameContext->FileName, renameInfo->FileName,
                    renameInfo->FileNameLength);

      if (targetFileObject != NULL) {
        // if Parameters.SetFile.FileObject is specified, replase
        // FILE_RENAME_INFO's file name by
        // FileObject's file name. The buffer size is already adjusted.

        DDbgPrint("  renameContext->FileNameLength %d\n",
            renameContext->FileNameLength);
        DDbgPrint("  renameContext->FileName %ws\n", renameContext->FileName);
        RtlZeroMemory(renameContext->FileName, renameContext->FileNameLength);

        PFILE_OBJECT parentFileObject = targetFileObject->RelatedFileObject;
        if (parentFileObject != NULL) {
            RtlCopyMemory(renameContext->FileName,
                parentFileObject->FileName.Buffer,
                parentFileObject->FileName.Length);

            RtlStringCchCatW(renameContext->FileName, NTSTRSAFE_MAX_CCH, L"\\");
            RtlStringCchCatW(renameContext->FileName, NTSTRSAFE_MAX_CCH, targetFileObject->FileName.Buffer);
            renameContext->FileNameLength = targetFileObject->FileName.Length + 
                parentFileObject->FileName.Length + sizeof(WCHAR);
        } else {
            RtlCopyMemory(renameContext->FileName,
                targetFileObject->FileName.Buffer,
                targetFileObject->FileName.Length);
            renameContext->FileNameLength = targetFileObject->FileName.Length;
        }
      }

      if (irpSp->Parameters.SetFile.FileInformationClass ==
          FileRenameInformation) {
        DDbgPrint("   rename: %wZ => %ls, FileCount = %u\n", fcb->FileName,
                  renameContext->FileName, (ULONG)fcb->FileCount);
      }
    }

    // copy the file name
    eventContext->Operation.SetFile.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.SetFile.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);

    //
    //  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 waiting IRP list and make it pending status
    status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanSetInformation\n");
  }

  return status;
}
Exemplo n.º 8
0
__drv_mustHoldCriticalRegion    
NTSTATUS
FatCommonShutdown (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for shutdown called by both the fsd and
    fsp threads.

Arguments:

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    KEVENT Event;
    PLIST_ENTRY Links;
    PVCB Vcb;
    PIRP NewIrp;
    IO_STATUS_BLOCK Iosb;
    BOOLEAN VcbDeleted;

    PAGED_CODE();

    //
    //  Make sure we don't get any pop-ups, and write everything through.
    //

    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS |
                               IRP_CONTEXT_FLAG_WRITE_THROUGH);

    //
    //  Initialize an event for doing calls down to
    //  our target device objects.
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );

    //
    //  Indicate that shutdown has started.  This is used in FatFspClose.
    //

    FatData.ShutdownStarted = TRUE;    

    //
    //  Get everyone else out of the way
    //
    
    ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

#pragma prefast( push )
#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
#pragma prefast( disable: 28193, "this will always wait" )

    (VOID) FatAcquireExclusiveGlobal( IrpContext );

#pragma prefast( pop )

    try {

        //
        //  For every volume that is mounted we will flush the
        //  volume and then shutdown the target device objects.
        //

        Links = FatData.VcbQueue.Flink;
        while (Links != &FatData.VcbQueue) {

            Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks);

            Links = Links->Flink;

            //
            //  If we have already been called before for this volume
            //  (and yes this does happen), skip this volume as no writes
            //  have been allowed since the first shutdown.
            //

            if ( FlagOn( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) ||
                 (Vcb->VcbCondition != VcbGood) ) {

                continue;
            }

            FatAcquireExclusiveVolume( IrpContext, Vcb );

            try {

                (VOID)FatFlushVolume( IrpContext, Vcb, Flush );

                //
                //  The volume is now clean, note it.  We purge the
                //  volume file cache map before marking the volume
                //  clean incase there is a stale Bpb in the cache.
                //

                if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {

                    CcPurgeCacheSection( &Vcb->SectionObjectPointers,
                                         NULL,
                                         0,
                                         FALSE );

                    FatMarkVolume( IrpContext, Vcb, VolumeClean );
                }

            } except( EXCEPTION_EXECUTE_HANDLER ) {

                  FatResetExceptionState( IrpContext );
            }

            //
            //  Sometimes we take an excepion while flushing the volume, such
            //  as when autoconv has converted the volume and is rebooting.
            //  Even in that case we want to send the shutdown irp to the
            //  target device so it can know to flush its cache, if it has one.
            //

            try {

                NewIrp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN,
                                                       Vcb->TargetDeviceObject,
                                                       NULL,
                                                       0,
                                                       NULL,
                                                       &Event,
                                                       &Iosb );

                if (NewIrp != NULL) {

                    if (NT_SUCCESS(IoCallDriver( Vcb->TargetDeviceObject, NewIrp ))) {

                        (VOID) KeWaitForSingleObject( &Event,
                                                      Executive,
                                                      KernelMode,
                                                      FALSE,
                                                      NULL );

                        KeClearEvent( &Event );
                    }
                }

            } except( EXCEPTION_EXECUTE_HANDLER ) {

                  FatResetExceptionState( IrpContext );
            }

            SetFlag( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN );

            //
            //  Attempt to punch the volume down.
            //

            VcbDeleted = FatCheckForDismount( IrpContext,
                                              Vcb,
                                              FALSE );

            if (!VcbDeleted) {
                
#pragma prefast( suppress:28107, "prefast is having trouble figuring out that Vcb is acquired" )
                FatReleaseVolume( IrpContext, Vcb );
            }
        }

    } finally {

        FatReleaseGlobal( IrpContext );

        //
        //  Unregister the file system.
        //
        
        IoUnregisterFileSystem( FatDiskFileSystemDeviceObject);
        IoUnregisterFileSystem( FatCdromFileSystemDeviceObject);
        IoDeleteDevice( FatDiskFileSystemDeviceObject);
        IoDeleteDevice( FatCdromFileSystemDeviceObject);

        FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    }

    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFsdShutdown -> STATUS_SUCCESS\n", 0);

    return STATUS_SUCCESS;
}
Exemplo n.º 9
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdCleanup (IN PRFSD_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_SUCCESS;
    PRFSD_VCB       Vcb = 0;
    BOOLEAN         VcbResourceAcquired = FALSE;
    PFILE_OBJECT    FileObject;
    PRFSD_FCB       Fcb = 0;
    BOOLEAN         FcbResourceAcquired = FALSE;
    BOOLEAN         FcbPagingIoAcquired = FALSE;
    PRFSD_CCB       Ccb;
    PIRP            Irp;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(IrpContext != NULL);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
        
        if (DeviceObject == RfsdGlobal->DeviceObject) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);
        
        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
            (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
        if (!ExAcquireResourceExclusiveLite(
                 &Vcb->MainResource,
                 IrpContext->IsSynchronous
                 ))  {
            Status = STATUS_PENDING;
            _SEH2_LEAVE;
        }

        VcbResourceAcquired = TRUE;
        
        FileObject = IrpContext->FileObject;
        
        Fcb = (PRFSD_FCB) FileObject->FsContext;
        
        if (!Fcb) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        if (Fcb->Identifier.Type == RFSDVCB) {
            if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
                (Vcb->LockFile == FileObject) ) {
                ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
                Vcb->LockFile = NULL;

                RfsdClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
            }

            Vcb->OpenHandleCount--;

            if (!Vcb->OpenHandleCount) {
                IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
            }

            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
            (Fcb->Identifier.Size == sizeof(RFSD_FCB)));

/*
        if ( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
             !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
*/
        {
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
            if (!ExAcquireResourceExclusiveLite(
                     &Fcb->MainResource,
                     IrpContext->IsSynchronous
                     ))
            {
                Status = STATUS_PENDING;
                _SEH2_LEAVE;
            }

            FcbResourceAcquired = TRUE;
        }
        
        Ccb = (PRFSD_CCB) FileObject->FsContext2;

        if (!Ccb) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

        if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
            if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
                 IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
                 !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) {
                Status = RfsdFlushFile(Fcb);
            }
            _SEH2_LEAVE;
        }
        
        ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
            (Ccb->Identifier.Size == sizeof(RFSD_CCB)));        
        Irp = IrpContext->Irp;

        Fcb->OpenHandleCount--;

        if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED )) {
            Fcb->NonCachedOpenCount--;
        }

        Vcb->OpenFileHandleCount--;

        if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))  {
            SetFlag(Fcb->Flags, FCB_DELETE_PENDING);

            if (IsDirectory(Fcb)) {
                FsRtlNotifyFullChangeDirectory(
                                            Vcb->NotifySync,
                                            &Vcb->NotifyList,
                                            Fcb,
                                            NULL,
                                            FALSE,
                                            FALSE,
                                            0,
                                            NULL,
                                            NULL,
                                            NULL );
            }
        }

        if (IsDirectory(Fcb)) {

            FsRtlNotifyCleanup(
                Vcb->NotifySync,
                &Vcb->NotifyList,
                Ccb   );

        } else {

            //
            // Drop any byte range locks this process may have on the file.
            //

            FsRtlFastUnlockAll(
                &Fcb->FileLockAnchor,
                FileObject,
                IoGetRequestorProcess(Irp),
                NULL  );

            //
            // If there are no byte range locks owned by other processes on the
            // file the fast I/O read/write functions doesn't have to check for
            // locks so we set IsFastIoPossible to FastIoIsPossible again.
            //
            if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
                if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
                    RfsdPrint((
                        DBG_INFO, ": %-16.16s %-31s %s\n",
                        RfsdGetCurrentProcessName(),
                        "FastIoIsPossible",
                        Fcb->AnsiFileName.Buffer
                        ));

                    Fcb->Header.IsFastIoPossible = FastIoIsPossible;
                }
            }
        }

        if ( IsFlagOn( FileObject->Flags, FO_CACHE_SUPPORTED) &&
             (Fcb->NonCachedOpenCount != 0) &&
             (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) &&
             (Fcb->SectionObject.DataSectionObject != NULL)) {

            if( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
                !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
                CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
            }

            ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
            ExReleaseResourceLite(&(Fcb->PagingIoResource));

            CcPurgeCacheSection( &Fcb->SectionObject,
                                 NULL,
                                 0,
                                 FALSE );
        }

        if (Fcb->OpenHandleCount == 0) {

            if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
                //
                //  Have to delete this file...
                //

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
                if (!ExAcquireResourceExclusiveLite(
                         &Fcb->PagingIoResource,
                         IrpContext->IsSynchronous
                         )) {
                    Status = STATUS_PENDING;
                    _SEH2_LEAVE;
                }

                FcbPagingIoAcquired = TRUE;
DbgBreak();
#if DISABLED
                Status = RfsdDeleteFile(IrpContext, Vcb, Fcb);

                if (NT_SUCCESS(Status)) {
                    if (IsDirectory(Fcb)) {
                        RfsdNotifyReportChange( IrpContext, Vcb, Fcb,
                                                FILE_NOTIFY_CHANGE_DIR_NAME,
                                                FILE_ACTION_REMOVED );
                    } else {
                        RfsdNotifyReportChange( IrpContext, Vcb, Fcb,
                                                FILE_NOTIFY_CHANGE_FILE_NAME,
                                                FILE_ACTION_REMOVED );
                    }
                }
#endif
                if (CcIsFileCached(FileObject)) {

                    CcSetFileSizes(FileObject, 
                            (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }

                if (FcbPagingIoAcquired) {
                    ExReleaseResourceForThreadLite(
                        &Fcb->PagingIoResource,
                        ExGetCurrentResourceThread() );

                    FcbPagingIoAcquired = FALSE;
                }
            }
        }

        if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap) {
            RfsdPrint((DBG_INFO, "RfsdCleanup: CcUninitializeCacheMap is called for %s.\n",
                                  Fcb->AnsiFileName.Buffer ));

            CcUninitializeCacheMap(
                    FileObject,
                    (PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
                    NULL );
        }

        if (!Fcb->OpenHandleCount) {
            IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
        }

        RfsdPrint((DBG_INFO, "RfsdCleanup: OpenCount: %u ReferCount: %u %s\n",
            Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer ));

        Status = STATUS_SUCCESS;

        if (FileObject) {
            SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
        }

    } _SEH2_FINALLY {
       
        if (FcbPagingIoAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->PagingIoResource,
                ExGetCurrentResourceThread() );
        }

        if (FcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread() );
        }
        
        if (VcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread());
        }
        
        if (!IrpContext->ExceptionInProgress) {
            if (Status == STATUS_PENDING) {
                RfsdQueueRequest(IrpContext);
            } else {
                IrpContext->Irp->IoStatus.Status = Status;
                RfsdCompleteIrpContext(IrpContext, Status);
            }
        }
    } _SEH2_END;
    
    return Status;
}
Exemplo n.º 10
0
NTSTATUS
UDFCloseAllXXXDelayedInDir(
    IN PVCB             Vcb,
    IN PUDF_FILE_INFO   FileInfo,
    IN BOOLEAN          System
    )
{
    PUDF_FILE_INFO*    PassedList = NULL;
    ULONG              PassedListSize = 0;
    PUDF_FILE_INFO*    FoundList = NULL;
    ULONG              FoundListSize = 0;
    NTSTATUS           RC;
    ULONG              i;
    BOOLEAN            ResAcq = FALSE;
    BOOLEAN            AcquiredVcb = FALSE;
    UDFNTRequiredFCB*  NtReqFcb;
    PUDF_FILE_INFO     CurFileInfo;
    PFE_LIST_ENTRY     CurListPtr;
    PFE_LIST_ENTRY*    ListPtrArray = NULL;

    _SEH2_TRY {

        KdPrint(("    UDFCloseAllXXXDelayedInDir(): Acquire DelayedCloseResource\n"));
        // Acquire DelayedCloseResource
        UDFAcquireResourceExclusive(&(UDFGlobalData.DelayedCloseResource), TRUE);
        ResAcq = TRUE;

        UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
        AcquiredVcb = TRUE;

        RC = UDFBuildTreeItemsList(Vcb, FileInfo,
                System ? UDFIsLastClose : UDFIsInDelayedCloseQueue,
                &PassedList, &PassedListSize, &FoundList, &FoundListSize);

        if(!NT_SUCCESS(RC)) {
            KdPrint(("    UDFBuildTreeItemsList(): error %x\n", RC));
            try_return(RC);
        }

        if(!FoundList || !FoundListSize) {
            try_return(RC = STATUS_SUCCESS);
        }

        // build array of referenced pointers
        ListPtrArray = (PFE_LIST_ENTRY*)(MyAllocatePool__(NonPagedPool, FoundListSize*sizeof(PFE_LIST_ENTRY)));
        if(!ListPtrArray) {
            KdPrint(("    Can't alloc ListPtrArray for %x items\n", FoundListSize));
            try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
        }

        for(i=0;i<FoundListSize;i++) {

            _SEH2_TRY {
                
                CurFileInfo = FoundList[i];
                if(!CurFileInfo->ListPtr) {
                    CurFileInfo->ListPtr = (PFE_LIST_ENTRY)(MyAllocatePool__(NonPagedPool, sizeof(FE_LIST_ENTRY)));
                    if(!CurFileInfo->ListPtr) {
                        KdPrint(("    Can't alloc ListPtrEntry for items %x\n", i));
                        try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
                    }
                    CurFileInfo->ListPtr->FileInfo = CurFileInfo;
                    CurFileInfo->ListPtr->EntryRefCount = 0;
                }
                CurFileInfo->ListPtr->EntryRefCount++;
                ListPtrArray[i] = CurFileInfo->ListPtr;

            } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
                BrutePoint();
            } _SEH2_END;
        }

        UDFReleaseResource(&(Vcb->VCBResource));
        AcquiredVcb = FALSE;

        if(System) {
            // Remove from system queue
            PtrUDFFCB Fcb;
            IO_STATUS_BLOCK IoStatus;
            BOOLEAN NoDelayed = (Vcb->VCBFlags & UDF_VCB_FLAGS_NO_DELAYED_CLOSE) ?
                                     TRUE : FALSE;

            Vcb->VCBFlags |= UDF_VCB_FLAGS_NO_DELAYED_CLOSE;
            for(i=FoundListSize;i>0;i--) {
                UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
                AcquiredVcb = TRUE;
                _SEH2_TRY {

                    CurListPtr = ListPtrArray[i-1];
                    CurFileInfo = CurListPtr->FileInfo;
                    if(CurFileInfo &&
                       (Fcb = CurFileInfo->Fcb)) {
                        NtReqFcb = Fcb->NTRequiredFCB;
                        ASSERT((ULONG)NtReqFcb > 0x1000);
//                            ASSERT((ULONG)(NtReqFcb->SectionObject) > 0x1000);
                        if(!(NtReqFcb->NtReqFCBFlags & UDF_NTREQ_FCB_DELETED) &&
                            (NtReqFcb->NtReqFCBFlags & UDF_NTREQ_FCB_MODIFIED)) {
                            MmPrint(("    CcFlushCache()\n"));
                            CcFlushCache(&(NtReqFcb->SectionObject), NULL, 0, &IoStatus);
                        }
                        if(NtReqFcb->SectionObject.ImageSectionObject) {
                            MmPrint(("    MmFlushImageSection()\n"));
                            MmFlushImageSection(&(NtReqFcb->SectionObject), MmFlushForWrite);
                        }
                        if(NtReqFcb->SectionObject.DataSectionObject) {
                            MmPrint(("    CcPurgeCacheSection()\n"));
                            CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );
                        }
                    } else {
                        MmPrint(("    Skip item: deleted\n"));
                    }
                    CurListPtr->EntryRefCount--;
                    if(!CurListPtr->EntryRefCount) {
                        if(CurListPtr->FileInfo)
                            CurListPtr->FileInfo->ListPtr = NULL;
                        MyFreePool__(CurListPtr);
                    }
                } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
                    BrutePoint();
                } _SEH2_END;
                UDFReleaseResource(&(Vcb->VCBResource));
                AcquiredVcb = FALSE;
            }
            if(!NoDelayed)
                Vcb->VCBFlags &= ~UDF_VCB_FLAGS_NO_DELAYED_CLOSE;
        } else {
            // Remove from internal queue
            PtrUDFIrpContextLite NextIrpContextLite;

            for(i=FoundListSize;i>0;i--) {

                UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
                AcquiredVcb = TRUE;

                CurListPtr = ListPtrArray[i-1];
                CurFileInfo = CurListPtr->FileInfo;

                if(CurFileInfo &&
                   CurFileInfo->Fcb &&
                    (NextIrpContextLite = CurFileInfo->Fcb->IrpContextLite)) {
                    RemoveEntryList( &(NextIrpContextLite->DelayedCloseLinks) );
                    if (NextIrpContextLite->Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
//                            BrutePoint();
                        UDFGlobalData.DirDelayedCloseCount--;
                    } else {
                        UDFGlobalData.DelayedCloseCount--;
                    }
                    UDFDoDelayedClose(NextIrpContextLite);
                }
                CurListPtr->EntryRefCount--;
                if(!CurListPtr->EntryRefCount) {
                    if(CurListPtr->FileInfo)
                        CurListPtr->FileInfo->ListPtr = NULL;
                    MyFreePool__(CurListPtr);
                }
                UDFReleaseResource(&(Vcb->VCBResource));
                AcquiredVcb = FALSE;
            }
        }
        RC = STATUS_SUCCESS;

try_exit: NOTHING;

    } _SEH2_FINALLY {
Exemplo n.º 11
0
IO_STATUS_BLOCK
NTAPI
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
                    IN PFILE_OBJECT FileObject,
                    IN PVCB Vcb,
                    IN PFCB Fcb,
                    IN PACCESS_MASK DesiredAccess,
                    IN USHORT ShareAccess,
                    IN ULONG AllocationSize,
                    IN PFILE_FULL_EA_INFORMATION EaBuffer,
                    IN ULONG EaLength,
                    IN UCHAR FileAttributes,
                    IN ULONG CreateDisposition,
                    IN BOOLEAN NoEaKnowledge,
                    IN BOOLEAN DeleteOnClose,
                    IN BOOLEAN OpenedAsDos,
                    OUT PBOOLEAN OplockPostIrp)
{
    IO_STATUS_BLOCK Iosb = {{0}};
    ACCESS_MASK AddedAccess = 0;
    BOOLEAN Hidden;
    BOOLEAN System;
    PCCB Ccb = NULL;
    NTSTATUS Status, StatusPrev;

    /* Acquire exclusive FCB lock */
    (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);

    *OplockPostIrp = FALSE;

    /* Check if there is a batch oplock */
    if (FsRtlCurrentBatchOplock(&Fcb->Fcb.Oplock))
    {
        /* Return with a special information field */
        Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY;

        /* Check the oplock */
        Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
                                       IrpContext->Irp,
                                       IrpContext,
                                       FatOplockComplete,
                                       FatPrePostIrp);

        if (Iosb.Status != STATUS_SUCCESS &&
            Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
        {
            /* The Irp needs to be queued */
            *OplockPostIrp = TRUE;

            /* Release the FCB and return */
            FatReleaseFcb(IrpContext, Fcb);
            return Iosb;
        }
    }

    /* Validate parameters and modify access */
    if (CreateDisposition == FILE_CREATE)
    {
        Iosb.Status = STATUS_OBJECT_NAME_COLLISION;

        /* Release the FCB and return */
        FatReleaseFcb(IrpContext, Fcb);
        return Iosb;
    }
    else if (CreateDisposition == FILE_SUPERSEDE)
    {
        SetFlag(AddedAccess, DELETE & ~(*DesiredAccess));
        *DesiredAccess |= DELETE;
    }
    else if ((CreateDisposition == FILE_OVERWRITE) ||
             (CreateDisposition == FILE_OVERWRITE_IF))
    {
        SetFlag(AddedAccess,
                (FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
                & ~(*DesiredAccess) );

        *DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
    }

    // TODO: Check desired access

    // TODO: Check if this file is readonly and DeleteOnClose is set

    /* Validate disposition information */
    if ((CreateDisposition == FILE_SUPERSEDE) ||
        (CreateDisposition == FILE_OVERWRITE) ||
        (CreateDisposition == FILE_OVERWRITE_IF))
    {
        // TODO: Get this attributes from the dirent
        Hidden = FALSE;
        System = FALSE;

        if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
            (System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM)))
        {
            DPRINT1("Hidden/system attributes don't match\n");

            Iosb.Status = STATUS_ACCESS_DENIED;

            /* Release the FCB and return */
            FatReleaseFcb(IrpContext, Fcb);
            return Iosb;
        }

        // TODO: Check for write protected volume
    }

    /* Check share access */
    Iosb.Status = IoCheckShareAccess(*DesiredAccess,
                                     ShareAccess,
                                     FileObject,
                                     &Fcb->ShareAccess,
                                     FALSE);
    if (!NT_SUCCESS(Iosb.Status))
    {
        /* Release the FCB and return */
        FatReleaseFcb(IrpContext, Fcb);
        return Iosb;
    }

    /* Check the oplock status after checking for share access */
    Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
                                   IrpContext->Irp,
                                   IrpContext,
                                   FatOplockComplete,
                                   FatPrePostIrp );

    if (Iosb.Status != STATUS_SUCCESS &&
        Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
    {
        /* The Irp needs to be queued */
        *OplockPostIrp = TRUE;

        /* Release the FCB and return */
        FatReleaseFcb(IrpContext, Fcb);
        return Iosb;
    }

    /* Set Fast I/O flag */
    Fcb->Header.IsFastIoPossible = FALSE; //FatiIsFastIoPossible(Fcb);

    /* Make sure image is not mapped */
    if (DeleteOnClose || FlagOn(*DesiredAccess, FILE_WRITE_DATA))
    {
        /* Try to flush the image section */
        if (!MmFlushImageSection(&Fcb->SectionObjectPointers, MmFlushForWrite))
        {
            /* Yes, image section exists, set correct status code */
            if (DeleteOnClose)
                Iosb.Status = STATUS_CANNOT_DELETE;
            else
                Iosb.Status = STATUS_SHARING_VIOLATION;

            /* Release the FCB and return */
            FatReleaseFcb(IrpContext, Fcb);
            return Iosb;
        }
    }

    /* Flush the cache if it's non-cached non-pagefile access */
    if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING) &&
        Fcb->SectionObjectPointers.DataSectionObject &&
        !FlagOn(Fcb->State, FCB_STATE_PAGEFILE))
    {
        /* Set the flag that create is in progress */
        SetFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);

        /* Flush the cache */
        CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);

        /* Acquire and release Paging I/O resource before purging the cache section
           to let lazy writer finish */
        ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
        ExReleaseResourceLite( Fcb->Header.PagingIoResource );

        /* Delete the cache section */
        CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);

        /* Clear the flag */
        ClearFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
    }

    /* Check create disposition flags and branch accordingly */
    if (CreateDisposition == FILE_OPEN ||
        CreateDisposition == FILE_OPEN_IF)
    {
        DPRINT("Opening a file\n");

        /* Check if we need to bother with EA */
        if (NoEaKnowledge && FALSE /* FatIsFat32(Vcb)*/)
        {
            UNIMPLEMENTED;
        }

        /* Set up file object */
        Ccb = FatCreateCcb();
        FatSetFileObject(FileObject,
                         UserFileOpen,
                         Fcb,
                         Ccb);

        FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;

        /* The file is opened */
        Iosb.Information = FILE_OPENED;
        goto SuccComplete;
    }
    else if ((CreateDisposition == FILE_SUPERSEDE) ||
             (CreateDisposition == FILE_OVERWRITE) ||
             (CreateDisposition == FILE_OVERWRITE_IF))
    {
        /* Remember previous status */
        StatusPrev = Iosb.Status;

        // TODO: Check system security access

        /* Perform overwrite operation */
        Iosb = FatiOverwriteFile(IrpContext,
                                 FileObject,
                                 Fcb,
                                 AllocationSize,
                                 EaBuffer,
                                 EaLength,
                                 FileAttributes,
                                 CreateDisposition,
                                 NoEaKnowledge);

        /* Restore previous status in case of success */
        if (Iosb.Status == STATUS_SUCCESS)
            Iosb.Status = StatusPrev;

        /* Fall down to completion */
    }
    else
    {
        /* We can't get here */
        KeBugCheckEx(FAT_FILE_SYSTEM, CreateDisposition, 0, 0, 0);
    }


SuccComplete:
    /* If all is fine */
    if (Iosb.Status != STATUS_PENDING &&
        NT_SUCCESS(Iosb.Status))
    {
        /* Update access if needed */
        if (AddedAccess)
        {
            /* Remove added access flags from desired access */
            ClearFlag(*DesiredAccess, AddedAccess);

            /* Check share access */
            Status = IoCheckShareAccess(*DesiredAccess,
                                        ShareAccess,
                                        FileObject,
                                        &Fcb->ShareAccess,
                                        TRUE);

            /* Make sure it's success */
            ASSERT(Status == STATUS_SUCCESS);
        }
        else
        {
            /* Update the share access */
            IoUpdateShareAccess(FileObject, &Fcb->ShareAccess);
        }

        /* Clear the delay close */
        ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);

        /* Increase counters */
        Fcb->UncleanCount++;
        Fcb->OpenCount++;
        Vcb->OpenFileCount++;
        if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
        if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++;

        // TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB
    }

    return Iosb;
}
Exemplo n.º 12
0
NTSTATUS
XixFsdCommonCleanUp(
	IN PXIFS_IRPCONTEXT pIrpContext
	)
{
	NTSTATUS		RC = STATUS_SUCCESS;
	PXIFS_FCB		pFCB = NULL;
	PXIFS_CCB		pCCB = NULL;
	PXIFS_VCB		pVCB = NULL;
	PFILE_OBJECT	pFileObject = NULL;	
	TYPE_OF_OPEN	TypeOfOpen = UnopenedFileObject;

	PIRP					pIrp = NULL;
	PIO_STACK_LOCATION		pIrpSp = NULL;
	KIRQL					SavedIrql;

	PXIFS_LCB	pLCB = NULL;
	PXIFS_FCB	pParentFCB = NULL;

	BOOLEAN					Wait = FALSE;
	BOOLEAN					VCBAcquired = FALSE;
	BOOLEAN					ParentFCBAcquired = FALSE;
	BOOLEAN					CanWait = FALSE;
	BOOLEAN					AttemptTeardown = FALSE;
	BOOLEAN					SendUnlockNotification = FALSE;

	PAGED_CODE();

	DebugTrace((DEBUG_LEVEL_TRACE), (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT), 
		("Enter XifsdCommonCleanUp pIrpContext(%p)\n", pIrpContext));


	ASSERT_IRPCONTEXT(pIrpContext);

	pIrp = pIrpContext->Irp;
	ASSERT(pIrp);

	// check if open request is releated to file system CDO
	{
		PDEVICE_OBJECT	DeviceObject = pIrpContext->TargetDeviceObject;
		ASSERT(DeviceObject);
		
		if (DeviceObject == XiGlobalData.XifsControlDeviceObject) {
			RC = STATUS_SUCCESS;

			DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLEANUP), 
					("CDO Device TargetDevide(%p).\n", DeviceObject));
			XixFsdCompleteRequest(pIrpContext,RC,0);
			return(RC);
		}

	}	



	if(pIrpContext->VCB == NULL){

		DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_CLEANUP, 
					("pIrpContext->VCB == NULL.\n"));
		RC = STATUS_SUCCESS;
		XixFsdCompleteRequest(pIrpContext, RC, 0);
		return RC;
	}


	

	pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
	ASSERT(pIrpSp);

	pFileObject = pIrpSp->FileObject;
	ASSERT(pFileObject);

	TypeOfOpen = XixFsdDecodeFileObject(pFileObject, &pFCB, &pCCB);

	if(TypeOfOpen <= StreamFileOpen){
		DebugTrace((DEBUG_LEVEL_TRACE|DEBUG_LEVEL_INFO), DEBUG_TARGET_CLEANUP, 
					("TypeOfOpen <= StreamFileOpen.\n"));
		XixFsdCompleteRequest(pIrpContext, STATUS_SUCCESS, 0);
		return STATUS_SUCCESS;
	}


	CanWait = XifsdCheckFlagBoolean(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT);

	
	if(CanWait == FALSE){
		DebugTrace((DEBUG_LEVEL_TRACE|DEBUG_LEVEL_INFO), (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_IRPCONTEXT), 
					("PostRequest IrpCxt(%p) Irp(%p)\n", pIrpContext, pIrp));
		RC = XixFsdPostRequest(pIrpContext, pIrp);
		return RC;
	}

	ASSERT_FCB(pFCB);
	pVCB = pFCB->PtrVCB;
	ASSERT_VCB(pVCB);




	DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE|DEBUG_TARGET_VCB), 
				("Acquire exclusive pVCB(%p) VCBResource(%p).\n", pVCB, &pVCB->VCBResource));	

	if((TypeOfOpen == UserVolumeOpen)
		&& XifsdCheckFlagBoolean(pFileObject->Flags, FO_FILE_MODIFIED))
	{
		XifsdAcquireVcbExclusive(CanWait, pVCB, FALSE);
		VCBAcquired = TRUE;		
	}


	XifsdAcquireFcbExclusive(CanWait, pFCB, FALSE);		


	DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), 
					("Acquire exclusive FCB(%p) FCBResource(%p).\n", pFCB, pFCB->FCBResource));

	
	XifsdSetFlag(pFileObject->Flags, FO_CLEANUP_COMPLETE);
	DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), 
					("Set File Object Flags(0x%x)\n", pFileObject->Flags));	



	//IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess );

	try{
		switch(TypeOfOpen){
		case UserDirectoryOpen:
			
			if(XifsdCheckFlagBoolean(pCCB->CCBFlags, XIFSD_CCB_FLAG_NOFITY_SET))
			{
				DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, 
					("CompletionFilter Notify CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB));

				FsRtlNotifyCleanup(pVCB->NotifyIRPSync, &pVCB->NextNotifyIRP, pCCB);

				//DbgPrint("Notify CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB);

			}


			//DbgPrint("CleanUp (%wZ) pCCB(%p) pCCB->CCBFlags(%x)\n", &pFCB->FCBName, pCCB, pCCB->CCBFlags);


			DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, 
					("!!!!CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB));


			IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess );
			break;
			
		case UserFileOpen:
			//
			//  Coordinate the cleanup operation with the oplock state.
			//  Oplock cleanup operations can always cleanup immediately so no
			//  need to check for STATUS_PENDING.
			//

			FsRtlCheckOplock( &pFCB->FCBOplock,
							  pIrp,
							  pIrpContext,
							  NULL,
							  NULL );

			//
			//  Unlock all outstanding file locks.
			//

			if (pFCB->FCBFileLock != NULL) {

				FsRtlFastUnlockAll( pFCB->FCBFileLock,
									pFileObject,
									IoGetRequestorProcess( pIrp ),
									NULL );
			}



			//
			//  Check the fast io state.
			//

			XifsdLockFcb( pIrpContext, pFCB );
			pFCB->IsFastIoPossible = XixFsdCheckFastIoPossible( pFCB );
			XifsdUnlockFcb( pIrpContext, pFCB );


			/*
			if((pFCB->HasLock != FCB_FILE_LOCK_HAS)
				&& (!XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_OPEN_WRITE))
				&& XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED) 
				&& (pFCB->FCBCleanup == 1)
			){
					if(pFCB->SectionObject.DataSectionObject != NULL) 
					{
						
						CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL);

						ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE);
						ExReleaseResourceLite( pFCB->PagingIoResource );
						
						
						CcPurgeCacheSection( &(pFCB->SectionObject),
														NULL,
														0,
														FALSE 
														);	
														
					}			
			
			}
			*/


			
			if(
				XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED) &&
				(pFCB->FcbNonCachedOpenCount > 1)	&&
				((pFCB->FcbNonCachedOpenCount + 1) ==  pFCB->FCBCleanup)
			)
			{
				if(pFCB->SectionObject.DataSectionObject != NULL) 
				{

					// changed by ILGU HONG for readonly 09052006
					if(!pFCB->PtrVCB->IsVolumeWriteProctected)
						CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL);
					// changed by ILGU HONG for readonly end
					
					//DbgPrint("CcFlush  1 File(%wZ)\n", &pFCB->FCBFullPath);
					ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE);
					ExReleaseResourceLite( pFCB->PagingIoResource );


					CcPurgeCacheSection( &(pFCB->SectionObject),
														NULL,
														0,
														FALSE 
														);					
					

				}	
			}
			
			/*
			else if(pFCB->FCBCleanup == 1 ){
		
				if(XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED)){
					if(pFCB->SectionObject.DataSectionObject != NULL) 
					{
						CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL);

						ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE);
						ExReleaseResourceLite( pFCB->PagingIoResource );

						CcPurgeCacheSection( &(pFCB->SectionObject),
															NULL,
															0,
															FALSE 
															);					
						

					}
				}

				if(XifsdCheckFlagBoolean(pFCB->FCBFlags,XIFSD_FCB_MODIFIED_FILE)){
					XixFsdUpdateFCB(pFCB);
				}

			}
			*/

			IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess );
			//
			//  Cleanup the cache map.
			//
			
			CcUninitializeCacheMap( pFileObject, NULL, NULL );
					
			

			break;
		case UserVolumeOpen:
			break;
		default:
			break;
		}

		


		if((TypeOfOpen == UserDirectoryOpen) || (TypeOfOpen == UserFileOpen)){

			if(pFCB->FCBCleanup == 1 ){
				if(XifsdCheckFlagBoolean(pFCB->FCBFlags,XIFSD_FCB_MODIFIED_FILE)){
					
					// changed by ILGU HONG for readonly 09052006
					if(!pFCB->PtrVCB->IsVolumeWriteProctected){

						XixFsdUpdateFCB(pFCB);

						if(pFCB->WriteStartOffset != -1){

							//DbgPrint("Set Update Information!!!\n");
							XixFsdSendFileChangeRC(
									TRUE,
									pVCB->HostMac, 
									pFCB->LotNumber, 
									pVCB->DiskId, 
									pVCB->PartitionId, 
									pFCB->FileSize.QuadPart, 
									pFCB->RealAllocationSize,
									pFCB->WriteStartOffset
							);
							
							pFCB->WriteStartOffset = -1;
						}
					}
					// changed by ILGU HONG for readonly end

				}


	


			}




			if(XifsdCheckFlagBoolean(pCCB->CCBFlags, XIFSD_CCB_FLAGS_DELETE_ON_CLOSE)){
				
				if(pFCB == pFCB->PtrVCB->RootDirFCB){
					XifsdClearFlag(pCCB->CCBFlags, XIFSD_CCB_FLAGS_DELETE_ON_CLOSE);
					XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
				}else{
					XifsdSetFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
				}
			}

	


			// changed by ILGU HONG for readonly 09082006
			if(XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE) && (!pFCB->PtrVCB->IsVolumeWriteProctected) ){
			// changed by ILGU HONG for readonly end
				if(pFCB->FCBCleanup == 1){
					
					//DbgPrint(" !!!Delete Entry From table (%wZ)  .\n", &pFCB->FCBFullPath);

					ASSERT_CCB(pCCB);
					pLCB = pCCB->PtrLCB;

					ASSERT_LCB(pLCB);

					pParentFCB = pLCB->ParentFcb;
					ASSERT_FCB(pParentFCB);					



  					pFCB->FileSize.QuadPart = 0;
					pFCB->ValidDataLength.QuadPart = 0;

					if(pFCB->FCBType == FCB_TYPE_FILE){
						
						XifsdReleaseFcb(TRUE, pFCB);
						XifsdAcquireFcbExclusive(TRUE, pParentFCB, FALSE);
						ParentFCBAcquired = TRUE;
						XifsdAcquireFcbExclusive(TRUE, pFCB, FALSE);
						RC = DeleteParentChild(pIrpContext, pParentFCB, &pLCB->FileName);
						
						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							//XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						
						XifsdClearFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_DELETE_ON_CLOSE);
						XifsdSetFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_LINK_IS_GONE);
						
						XixFsdRemovePrefix(TRUE, pLCB);

						//
						//  Now Decrement the reference counts for the parent and drop the Vcb.
						//
						XifsdLockVcb(pIrpContext,pVCB);
						DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdDecRefCount( pParentFCB, 1, 1 );

						DebugTrace( DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdUnlockVcb( pIrpContext, pVCB );
						


						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						
						

					}else {
						
						RC = XixFsReLoadFileFromFcb(pFCB);
						
						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail XixFsReLoadFileFromFcb (%wZ)\n", &pFCB->FCBName));
							
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						
						if(pFCB->ChildCount != 0){
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}

						XifsdReleaseFcb(TRUE, pFCB);
						XifsdAcquireFcbExclusive(TRUE, pParentFCB, FALSE);
						ParentFCBAcquired = TRUE;
						
						XifsdAcquireFcbExclusive(TRUE, pFCB, FALSE);

						RC = DeleteParentChild(pIrpContext, pParentFCB, &pLCB->FileName);

						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							//ifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						

						XifsdClearFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_DELETE_ON_CLOSE);
						XifsdSetFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_LINK_IS_GONE);
						
						
						XixFsdRemovePrefix(TRUE, pLCB);

						//
						//  Now Decrement the reference counts for the parent and drop the Vcb.
						//
						XifsdLockVcb(pIrpContext,pVCB);
						DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdDecRefCount( pParentFCB, 1, 1 );

						DebugTrace( DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdUnlockVcb( pIrpContext, pVCB );

						
						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						

						
					}


			
					//XixFsdDeleteUpdateFCB(pFCB);

					XixFsdSendRenameLinkBC(
						TRUE,
						XIFS_SUBTYPE_FILE_DEL,
						pVCB->HostMac,
						pFCB->LotNumber,
						pVCB->DiskId,
						pVCB->PartitionId,
						pFCB->ParentLotNumber,
						0
					);

				}
			}
			

		}


pass_through:

		XifsdLockVcb(pIrpContext, pVCB);
		
		if(XifsdCheckFlagBoolean(pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
		{
			ASSERT(pFCB->FcbNonCachedOpenCount > 0);
			pFCB->FcbNonCachedOpenCount --;
		}

		XifsdDecrementClenupCount(pFCB);


		DebugTrace(DEBUG_LEVEL_ALL, DEBUG_TARGET_ALL,
			("Cleanup  Name(%wZ) FCBLotNumber(%I64d) FCBCleanUp(%ld) VCBCleanup(%ld) pCCB(%p) FileObject(%p)\n", 
			&pFCB->FCBName,
			pFCB->LotNumber, 
			pFCB->FCBCleanup, 
			pVCB->VCBCleanup,
			pCCB,
			pFileObject
			));
			
		XifsdUnlockVcb( pIrpContext, pVCB );

		AttemptTeardown = (pVCB->VCBCleanup == 0 && pVCB->VCBState == XIFSD_VCB_STATE_VOLUME_DISMOUNTED );
		
		if(pFileObject == pVCB->LockVolumeFileObject){
			ASSERT(XifsdCheckFlagBoolean(pVCB->VCBFlags, XIFSD_VCB_FLAGS_VOLUME_LOCKED));
			
			IoAcquireVpbSpinLock(&SavedIrql);
			XifsdClearFlag(pVCB->PtrVPB->Flags, VPB_LOCKED);
			IoReleaseVpbSpinLock( SavedIrql );
			
			XifsdClearFlag(pVCB->VCBFlags, XIFSD_VCB_FLAGS_VOLUME_LOCKED);
			pVCB->LockVolumeFileObject = NULL;
			SendUnlockNotification = TRUE;
			
		}

		

		/*
		if( (pFCB->FCBCleanup == 0) 
				&& (!XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE)) ){

			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT| DEBUG_TARGET_ALL), 
				("CleanUp Release Lot Lock LotNumber(%ld)\n", pFCB->LotNumber));

			XifsdLotUnLock(pVCB, pVCB->TargetDeviceObject, pFCB->LotNumber);
			pFCB->HasLock = FCB_FILE_LOCK_INVALID;
		}
		*/

		//
		//  We must clean up the share access at this time, since we may not
		//  get a Close call for awhile if the file was mapped through this
		//  File Object.
		//

		


	}finally{

		XifsdReleaseFcb(pIrpContext, pFCB);

		if(ParentFCBAcquired) {
			XifsdReleaseFcb(TRUE,pParentFCB);
		}
		

        if (SendUnlockNotification) {

            FsRtlNotifyVolumeEvent( pFileObject, FSRTL_VOLUME_UNLOCK );
        }

  		if (VCBAcquired)  {

			XifsdReleaseVcb( pIrpContext, pVCB);
		}


	}



    if (AttemptTeardown) {
        XifsdAcquireVcbExclusive( CanWait, pVCB, FALSE );

        try {
            
            XixFsdPurgeVolume( pIrpContext, pVCB, FALSE );

        } finally {

            XifsdReleaseVcb( pIrpContext, pVCB );
        }
    }


    //
    //  If this is a normal termination then complete the request
    //

	DebugTrace((DEBUG_LEVEL_TRACE), (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT), 
		("Exit XifsdCommonCleanUp pIrpContext(%p)\n", pIrpContext));

    XixFsdCompleteRequest( pIrpContext, STATUS_SUCCESS, 0 );

    return STATUS_SUCCESS;
}
Exemplo n.º 13
0
VOID
Secondary_TryCloseFilExts(
	PSECONDARY Secondary
	)
{
	PLIST_ENTRY		listEntry;


	Secondary_Reference( Secondary );

	if (ExTryToAcquireFastMutex(&Secondary->RecoveryCcbQMutex) == FALSE) {

		Secondary_Dereference(Secondary);
		return;
	}
	
	if (BooleanFlagOn(Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {

		ExReleaseFastMutex(&Secondary->RecoveryCcbQMutex);
		Secondary_Dereference(Secondary);
		return;
	}

	listEntry = Secondary->RecoveryCcbQueue.Flink;

	while (listEntry != &Secondary->RecoveryCcbQueue) {

		PCCB						ccb;
		PFCB						fcb;

		PSECTION_OBJECT_POINTERS	section;
		BOOLEAN						dataSectionExists;
		BOOLEAN						imageSectionExists;
		IRP_CONTEXT					IrpContext;

		ccb = CONTAINING_RECORD( listEntry, CCB, ListEntry );
		listEntry = listEntry->Flink;

		if (ccb->Fcb == NULL) {

			ASSERT(NDFAT_BUG);
			continue;
		}	

		if (NodeType(ccb->Fcb) != FAT_NTC_FCB) 
			continue;

		fcb = ccb->Fcb;

		if (fcb->UncleanCount != 0 || fcb->NonCachedUncleanCount != 0) {

			DebugTrace2( 0, Dbg, ("Secondary_TryCloseFilExts: fcb->FullFileName = %wZ\n", &ccb->Fcb->FullFileName) );
			break;
		}

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFilExts: fcb->FullFileName = %wZ\n", &ccb->Fcb->FullFileName) );

		RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
		SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
		
		section = &fcb->NonPaged->SectionObjectPointers;			
		if (section == NULL)
			break;

		dataSectionExists = (BOOLEAN)(section->DataSectionObject != NULL);
		imageSectionExists = (BOOLEAN)(section->ImageSectionObject != NULL);

		if (imageSectionExists) {

			(VOID)MmFlushImageSection( section, MmFlushForWrite );
		}

		if (dataSectionExists) {

            CcPurgeCacheSection( section, NULL, 0, FALSE );
	    }
	}

	ExReleaseFastMutex( &Secondary->RecoveryCcbQMutex );
	Secondary_Dereference( Secondary );

	return;
}
Exemplo n.º 14
0
/*************************************************************************
*
* Function: UDFCommonCleanup()
*
* Description:
*   The actual work is performed here. This routine may be invoked in one'
*   of the two possible contexts:
*   (a) in the context of a system worker thread
*   (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS
UDFCommonCleanup(
    PtrUDFIrpContext PtrIrpContext,
    PIRP             Irp)
{
    IO_STATUS_BLOCK         IoStatus;
    NTSTATUS                RC = STATUS_SUCCESS;
    NTSTATUS                RC2;
    PIO_STACK_LOCATION      IrpSp = NULL;
    PFILE_OBJECT            FileObject = NULL;
    PtrUDFFCB               Fcb = NULL;
    PtrUDFCCB               Ccb = NULL;
    PVCB                    Vcb = NULL;
    PtrUDFNTRequiredFCB     NtReqFcb = NULL;
    ULONG                   lc = 0;
    BOOLEAN                 AcquiredVcb = FALSE;
    BOOLEAN                 AcquiredFCB = FALSE;
    BOOLEAN                 AcquiredParentFCB = FALSE;

//    BOOLEAN                 CompleteIrp = TRUE;
//    BOOLEAN                 PostRequest = FALSE;
    BOOLEAN                 ChangeTime = FALSE;
#ifdef UDF_DBG
    BOOLEAN                 CanWait = FALSE;
#endif // UDF_DBG
    BOOLEAN                 ForcedCleanUp = FALSE;

    PUDF_FILE_INFO          NextFileInfo = NULL;
#ifdef UDF_DBG
    UNICODE_STRING          CurName;
    PDIR_INDEX_HDR          DirNdx;
#endif // UDF_DBG
//    PUDF_DATALOC_INFO       Dloc;

    TmPrint(("UDFCommonCleanup\n"));

//    BrutePoint();

    _SEH2_TRY {
        // First, get a pointer to the current I/O stack location
        IrpSp = IoGetCurrentIrpStackLocation(Irp);
        if(!IrpSp) try_return(RC = STATUS_INVALID_PARAMETER);

        FileObject = IrpSp->FileObject;

        // Get the FCB and CCB pointers
        Ccb = (PtrUDFCCB)(FileObject->FsContext2);
        ASSERT(Ccb);
        Fcb = Ccb->Fcb;
        ASSERT(Fcb);

        Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
        ASSERT(Vcb);
        ASSERT(Vcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB);
//        Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
#ifdef UDF_DBG
        CanWait = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE;
        AdPrint(("   %s\n", CanWait ? "Wt" : "nw"));
        ASSERT(CanWait);
#endif // UDF_DBG
        UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
        AcquiredVcb = TRUE;
        // Steps we shall take at this point are:
        // (a) Acquire the file (FCB) exclusively
        // (b) Flush file data to disk
        // (c) Talk to the FSRTL package (if we use it) about pending oplocks.
        // (d) Notify the FSRTL package for use with pending notification IRPs
        // (e) Unlock byte-range locks (if any were acquired by process)
        // (f) Update time stamp values (e.g. fast-IO had been performed)
        // (g) Inform the Cache Manager to uninitialize Cache Maps ...
        // and other similar stuff.
        //  BrutePoint();
        NtReqFcb = Fcb->NTRequiredFCB;

        if (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) {
            AdPrint(("Cleaning up Volume\n"));
            AdPrint(("UDF: OpenHandleCount: %x\n",Fcb->OpenHandleCount));

            UDFInterlockedDecrement((PLONG)&(Fcb->OpenHandleCount));
            UDFInterlockedDecrement((PLONG)&(Vcb->VCBHandleCount));
            if(FileObject->Flags & FO_CACHE_SUPPORTED) {
                // we've cached close
                UDFInterlockedDecrement((PLONG)&(Fcb->CachedOpenHandleCount));
            }
            ASSERT(Fcb->OpenHandleCount <= (Fcb->ReferenceCount-1));

            //  If this handle had write access, and actually wrote something,
            //  flush the device buffers, and then set the verify bit now
            //  just to be safe (in case there is no dismount).
            if( FileObject->WriteAccess &&
               (FileObject->Flags & FO_FILE_MODIFIED)) {

                Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
            }
            // User may decide to close locked volume without call to unlock proc
            // So, handle this situation properly & unlock it now...
            if (FileObject == Vcb->VolumeLockFileObject) {
                Vcb->VolumeLockFileObject = NULL;
                Vcb->VolumeLockPID = -1;
                Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
                Vcb->Vpb->Flags &= ~VPB_LOCKED;
                UDFNotifyVolumeEvent(FileObject, FSRTL_VOLUME_UNLOCK);
            }

            MmPrint(("    CcUninitializeCacheMap()\n"));
            CcUninitializeCacheMap(FileObject, NULL, NULL);
            // reset device
            if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) &&
                (Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER)) {
                // this call doesn't modify data buffer
                // it just requires its presence
                UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, TRUE);
            }
            //  We must clean up the share access at this time, since we may not
            //  get a Close call for awhile if the file was mapped through this
            //  File Object.
            IoRemoveShareAccess( FileObject, &(NtReqFcb->FCBShareAccess) );

            try_return(RC = STATUS_SUCCESS);
        }
//        BrutePoint();
#ifdef UDF_DBG
        DirNdx = UDFGetDirIndexByFileInfo(Fcb->FileInfo);
        if(DirNdx) {
            CurName.Buffer = UDFDirIndex(DirNdx, Fcb->FileInfo->Index)->FName.Buffer;
            if(CurName.Buffer) {
                AdPrint(("Cleaning up file: %ws %8.8x\n", CurName.Buffer, FileObject));
            } else {
                AdPrint(("Cleaning up file: ??? \n"));
            }
        }
#endif //UDF_DBG
        AdPrint(("UDF: OpenHandleCount: %x\n",Fcb->OpenHandleCount));
        // Acquire parent object
        if(Fcb->FileInfo->ParentFile) {
            UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB);
            UDFAcquireResourceExclusive(&(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB->MainResource),TRUE);
        } else {
            UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
        }
        AcquiredParentFCB = TRUE;
        // Acquire current object
        UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
        UDFAcquireResourceExclusive(&(NtReqFcb->MainResource),TRUE);
        AcquiredFCB = TRUE;
        // dereference object
        UDFInterlockedDecrement((PLONG)&(Fcb->OpenHandleCount));
        UDFInterlockedDecrement((PLONG)&(Vcb->VCBHandleCount));
        if(FileObject->Flags & FO_CACHE_SUPPORTED) {
            // we've cached close
            UDFInterlockedDecrement((PLONG)&(Fcb->CachedOpenHandleCount));
        }
        ASSERT(Fcb->OpenHandleCount <= (Fcb->ReferenceCount-1));
        // check if Ccb being cleaned up has DeleteOnClose flag set
#ifndef UDF_READ_ONLY_BUILD
        if(Ccb->CCBFlags & UDF_CCB_DELETE_ON_CLOSE) {
            AdPrint(("    DeleteOnClose\n"));
            // Ok, now we'll become 'delete on close'...
            ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
            Fcb->FCBFlags |= UDF_FCB_DELETE_ON_CLOSE;
            FileObject->DeletePending = TRUE;
            //  Report this to the dir notify package for a directory.
            if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
                FsRtlNotifyFullChangeDirectory( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP),
                                                (PVOID)Ccb, NULL, FALSE, FALSE,
                                                0, NULL, NULL, NULL );
            }
        }
#endif //UDF_READ_ONLY_BUILD

        if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
            //  Unlock all outstanding file locks.
            FsRtlFastUnlockAll(&(NtReqFcb->FileLock),
                               FileObject,
                               IoGetRequestorProcess(Irp),
                               NULL);
        }
        // get Link count
        lc = UDFGetFileLinkCount(Fcb->FileInfo);

#ifndef UDF_READ_ONLY_BUILD
        if( (Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) &&
           !(Fcb->OpenHandleCount)) {
            // This can be useful for Streams, those were brutally deleted
            // (together with parent object)
            ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
            FileObject->DeletePending = TRUE;

            // we should mark all streams of the file being deleted
            // for deletion too, if there are no more Links to
            // main data stream
            if((lc <= 1) &&
               !UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo)) {
                RC = UDFMarkStreamsForDeletion(Vcb, Fcb, TRUE); // Delete
            }
            // we can release these resources 'cause UDF_FCB_DELETE_ON_CLOSE
            // flag is already set & the file can't be opened
            UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
            UDFReleaseResource(&(NtReqFcb->MainResource));
            AcquiredFCB = FALSE;
            if(Fcb->FileInfo->ParentFile) {
                UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb->NTRequiredFCB);
                UDFReleaseResource(&(Fcb->ParentFcb->NTRequiredFCB->MainResource));
            } else {
                UDFReleaseResource(&(Vcb->VCBResource));
            }
            AcquiredParentFCB = FALSE;
            UDFReleaseResource(&(Vcb->VCBResource));
            AcquiredVcb = FALSE;

            // Make system to issue last Close request
            // for our Target ...
            UDFRemoveFromSystemDelayedQueue(Fcb);

#ifdef UDF_DELAYED_CLOSE
            // remove file from our DelayedClose queue
            UDFRemoveFromDelayedQueue(Fcb);
            ASSERT(!Fcb->IrpContextLite);
#endif //UDF_DELAYED_CLOSE

            UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
            AcquiredVcb = TRUE;
            if(Fcb->FileInfo->ParentFile) {
                UDF_CHECK_PAGING_IO_RESOURCE(Fcb->ParentFcb->NTRequiredFCB);
                UDFAcquireResourceExclusive(&(Fcb->ParentFcb->NTRequiredFCB->MainResource),TRUE);
            } else {
                UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
            }
            AcquiredParentFCB = TRUE;
            UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
            UDFAcquireResourceExclusive(&(NtReqFcb->MainResource),TRUE);
            AcquiredFCB = TRUE;

            // we should set file sizes to zero if there are no more
            // links to this file
            if(lc <= 1) {
                // Synchronize here with paging IO
                UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource),TRUE);
                // set file size to zero (for system cache manager)
//                NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart =
                NtReqFcb->CommonFCBHeader.FileSize.QuadPart =
                NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = 0;
                CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&(NtReqFcb->CommonFCBHeader.AllocationSize));

                UDFReleaseResource(&(NtReqFcb->PagingIoResource));
            }
        }
#endif //UDF_READ_ONLY_BUILD

#ifdef UDF_DELAYED_CLOSE
        if ((Fcb->ReferenceCount == 1) &&
         /*(Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB) &&*/ // see above
            (!(Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE)) ) {
            Fcb->FCBFlags |= UDF_FCB_DELAY_CLOSE;
        }
#endif //UDF_DELAYED_CLOSE

        NextFileInfo = Fcb->FileInfo;

#ifndef UDF_READ_ONLY_BUILD
        // do we need to delete it now ?
        if( (Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) &&
           !(Fcb->OpenHandleCount)) {

            // can we do it ?
            if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
                ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
                if(!UDFIsDirEmpty__(NextFileInfo)) {
                    // forget about it
                    Fcb->FCBFlags &= ~UDF_FCB_DELETE_ON_CLOSE;
                    goto DiscardDelete;
                }
            } else
            if (lc <= 1) {
                // Synchronize here with paging IO
                BOOLEAN AcquiredPagingIo;
                AcquiredPagingIo = UDFAcquireResourceExclusiveWithCheck(&(NtReqFcb->PagingIoResource));
                // set file size to zero (for UdfInfo package)
                // we should not do this for directories and linked files
                UDFResizeFile__(Vcb, NextFileInfo, 0);
                if(AcquiredPagingIo) {
                    UDFReleaseResource(&(NtReqFcb->PagingIoResource));
                }
            }
            // mark parent object for deletion if requested
            if((Fcb->FCBFlags & UDF_FCB_DELETE_PARENT) &&
                Fcb->ParentFcb) {
                ASSERT(!(Fcb->ParentFcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
                Fcb->ParentFcb->FCBFlags |= UDF_FCB_DELETE_ON_CLOSE;
            }
            // flush file. It is required by UDFUnlinkFile__()
            RC = UDFFlushFile__(Vcb, NextFileInfo);
            if(!NT_SUCCESS(RC)) {
                AdPrint(("Error flushing file !!!\n"));
            }
            // try to unlink
            if((RC = UDFUnlinkFile__(Vcb, NextFileInfo, TRUE)) == STATUS_CANNOT_DELETE) {
                // If we can't delete file with Streams due to references,
                // mark SDir & Streams
                // for Deletion. We shall also set DELETE_PARENT flag to
                // force Deletion of the current file later... when curently
                // opened Streams would be cleaned up.

                // WARNING! We should keep SDir & Streams if there is a
                // link to this file
                if(NextFileInfo->Dloc &&
                   NextFileInfo->Dloc->SDirInfo &&
                   NextFileInfo->Dloc->SDirInfo->Fcb) {

                    BrutePoint();
                    if(!UDFIsSDirDeleted(NextFileInfo->Dloc->SDirInfo)) {
//                        RC = UDFMarkStreamsForDeletion(Vcb, Fcb, TRUE); // Delete
//#ifdef UDF_ALLOW_PRETEND_DELETED
                        UDFPretendFileDeleted__(Vcb, Fcb->FileInfo);
//#endif //UDF_ALLOW_PRETEND_DELETED
                    }
                    goto NotifyDelete;

                } else {
                    // Getting here means that we can't delete file because of
                    // References/PemissionsDenied/Smth.Else,
                    // but not Linked+OpenedStream
                    BrutePoint();
//                    RC = STATUS_SUCCESS;
                    goto DiscardDelete_1;
                }
            } else {
DiscardDelete_1:
                // We have got an ugly ERROR, or
                // file is deleted, so forget about it
                ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
                ForcedCleanUp = TRUE;
                if(NT_SUCCESS(RC))
                    Fcb->FCBFlags &= ~UDF_FCB_DELETE_ON_CLOSE;
                Fcb->FCBFlags |= UDF_FCB_DELETED;
                RC = STATUS_SUCCESS;
            }
NotifyDelete:
            // We should prevent SetEOF operations on completly
            // deleted data streams
            if(lc < 1) {
                NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED;
            }
            // Report that we have removed an entry.
            if(UDFIsAStream(NextFileInfo)) {
                UDFNotifyFullReportChange( Vcb, NextFileInfo,
                                       FILE_NOTIFY_CHANGE_STREAM_NAME,
                                       FILE_ACTION_REMOVED_STREAM);
            } else {
                UDFNotifyFullReportChange( Vcb, NextFileInfo,
                                       UDFIsADirectory(NextFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
                                       FILE_ACTION_REMOVED);
            }
        } else
        if(Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) {
DiscardDelete:
            UDFNotifyFullReportChange( Vcb, NextFileInfo,
                                     ((Ccb->CCBFlags & UDF_CCB_ACCESS_TIME_SET) ? FILE_NOTIFY_CHANGE_LAST_ACCESS : 0) |
                                     ((Ccb->CCBFlags & UDF_CCB_WRITE_TIME_SET) ? (FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE) : 0) |
                                     0,
                                     UDFIsAStream(NextFileInfo) ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED);
        }
#endif //UDF_READ_ONLY_BUILD

        if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
            //  Report to the dir notify package for a directory.
            FsRtlNotifyCleanup( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), (PVOID)Ccb );
        }

        // we can't purge Cache when more than one link exists
        if(lc > 1) {
            ForcedCleanUp = FALSE;
        }

        if ( (FileObject->Flags & FO_CACHE_SUPPORTED) &&
             (NtReqFcb->SectionObject.DataSectionObject) ) {
            BOOLEAN LastNonCached = (!Fcb->CachedOpenHandleCount &&
                                      Fcb->OpenHandleCount);
            // If this was the last cached open, and there are open
            // non-cached handles, attempt a flush and purge operation
            // to avoid cache coherency overhead from these non-cached
            // handles later.  We ignore any I/O errors from the flush.
            // We shall not flush deleted files
            RC = STATUS_SUCCESS;
            if(  LastNonCached
                      ||
                (!Fcb->OpenHandleCount &&
                 !ForcedCleanUp) ) {

#ifndef UDF_READ_ONLY_BUILD
                LONGLONG OldFileSize, NewFileSize;

                if( (OldFileSize = NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart) < 
                    (NewFileSize = NtReqFcb->CommonFCBHeader.FileSize.QuadPart)) {
/*                    UDFZeroDataEx(NtReqFcb,
                                  OldFileSize,
                                  NewFileSize - OldFileSize,
                                  TRUE, Vcb, FileObject);*/
                    
                    NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = NewFileSize;
                }
#endif //UDF_READ_ONLY_BUILD
                MmPrint(("    CcFlushCache()\n"));
                CcFlushCache( &(NtReqFcb->SectionObject), NULL, 0, &IoStatus );
                if(!NT_SUCCESS(IoStatus.Status)) {
                    MmPrint(("    CcFlushCache() error: %x\n", IoStatus.Status));
                    RC = IoStatus.Status;
                }
            }
            // If file is deleted or it is last cached open, but there are
            // some non-cached handles we should purge cache section
            if(ForcedCleanUp || LastNonCached) {
                if(NtReqFcb->SectionObject.DataSectionObject) {
                    MmPrint(("    CcPurgeCacheSection()\n"));
                    CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );
                }
/*                MmPrint(("    CcPurgeCacheSection()\n"));
                CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );*/
            }
            // we needn't Flush here. It will be done in UDFCloseFileInfoChain()
        }

#ifndef UDF_READ_ONLY_BUILD
        // Update FileTimes & Attrs
        if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) &&
           !(Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE |
                              UDF_FCB_DELETED /*|
                              UDF_FCB_DIRECTORY |
                              UDF_FCB_READ_ONLY*/)) &&
           !UDFIsAStreamDir(NextFileInfo)) {
            LONGLONG NtTime;
            LONGLONG ASize;
            KeQuerySystemTime((PLARGE_INTEGER)&NtTime);
            // Check if we should set ARCHIVE bit & LastWriteTime
            if(FileObject->Flags & FO_FILE_MODIFIED) {
                ULONG Attr;
                PDIR_INDEX_ITEM DirNdx;
                DirNdx = UDFDirIndex(UDFGetDirIndexByFileInfo(NextFileInfo), NextFileInfo->Index);
                ASSERT(DirNdx);
                // Archive bit
                if(!(Ccb->CCBFlags & UDF_CCB_ATTRIBUTES_SET) &&
                    (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ARCH_BIT)) {
                    Attr = UDFAttributesToNT(DirNdx, NextFileInfo->Dloc->FileEntry);
                    if(!(Attr & FILE_ATTRIBUTE_ARCHIVE))
                        UDFAttributesToUDF(DirNdx, NextFileInfo->Dloc->FileEntry, Attr | FILE_ATTRIBUTE_ARCHIVE);
                }
                // WriteTime
                if(!(Ccb->CCBFlags & UDF_CCB_WRITE_TIME_SET) && 
                    (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_MODIFY_TIME)) {
                    UDFSetFileXTime(NextFileInfo, NULL, &NtTime, NULL, &NtTime);
                    NtReqFcb->LastWriteTime.QuadPart =
                    NtReqFcb->LastAccessTime.QuadPart = NtTime;
                    ChangeTime = TRUE;
                }
            }
            if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
                // Update sizes in DirIndex
                if(!Fcb->OpenHandleCount) {
                    ASize = UDFGetFileAllocationSize(Vcb, NextFileInfo);
//                        NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart;
                    UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize);
                } else
                if(FileObject->Flags & FO_FILE_SIZE_CHANGED) {
                    ASize = //UDFGetFileAllocationSize(Vcb, NextFileInfo);
                        NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart;
                    UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize);
                }
            }
            // AccessTime
            if((FileObject->Flags & FO_FILE_FAST_IO_READ) &&
               !(Ccb->CCBFlags & UDF_CCB_ACCESS_TIME_SET) &&
                (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ACCESS_TIME)) {
                UDFSetFileXTime(NextFileInfo, NULL, &NtTime, NULL, NULL);
                NtReqFcb->LastAccessTime.QuadPart = NtTime;
//                ChangeTime = TRUE;
            }
            // ChangeTime (AttrTime)
            if(!(Ccb->CCBFlags & UDF_CCB_MODIFY_TIME_SET) &&
                (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ATTR_TIME) &&
                (ChangeTime || (Ccb->CCBFlags & (UDF_CCB_ATTRIBUTES_SET |
                                                 UDF_CCB_CREATE_TIME_SET |
                                                 UDF_CCB_ACCESS_TIME_SET |
                                                 UDF_CCB_WRITE_TIME_SET))) ) {
                UDFSetFileXTime(NextFileInfo, NULL, NULL, &NtTime, NULL);
                NtReqFcb->ChangeTime.QuadPart = NtTime;
            }
        }
#endif //UDF_READ_ONLY_BUILD

        if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY) &&
            ForcedCleanUp) {
            // flush system cache
            MmPrint(("    CcUninitializeCacheMap()\n"));
            CcUninitializeCacheMap(FileObject, &(UDFGlobalData.UDFLargeZero), NULL);
        } else {
            MmPrint(("    CcUninitializeCacheMap()\n"));
            CcUninitializeCacheMap(FileObject, NULL, NULL);
        }

        // release resources now.
        // they'll be acquired in UDFCloseFileInfoChain()
        UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
        UDFReleaseResource(&(NtReqFcb->MainResource));
        AcquiredFCB = FALSE;

        if(Fcb->FileInfo->ParentFile) {
            UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB);
            UDFReleaseResource(&(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB->MainResource));
        } else {
            UDFReleaseResource(&(Vcb->VCBResource));
        }
        AcquiredParentFCB = FALSE;
        // close the chain
        ASSERT(AcquiredVcb);
        RC2 = UDFCloseFileInfoChain(Vcb, NextFileInfo, Ccb->TreeLength, TRUE);
        if(NT_SUCCESS(RC))
            RC = RC2;

        Ccb->CCBFlags |= UDF_CCB_CLEANED;

        //  We must clean up the share access at this time, since we may not
        //  get a Close call for awhile if the file was mapped through this
        //  File Object.
        IoRemoveShareAccess( FileObject, &(NtReqFcb->FCBShareAccess) );

        NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb);

        FileObject->Flags |= FO_CLEANUP_COMPLETE;

try_exit: NOTHING;

    } _SEH2_FINALLY {

        if(AcquiredFCB) {
            UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
            UDFReleaseResource(&(NtReqFcb->MainResource));
        }

        if(AcquiredParentFCB) {
            if(Fcb->FileInfo->ParentFile) {
                UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB);
                UDFReleaseResource(&(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB->MainResource));
            } else {
                UDFReleaseResource(&(Vcb->VCBResource));
            }
        }

        if(AcquiredVcb) {
            UDFReleaseResource(&(Vcb->VCBResource));
            AcquiredVcb = FALSE;
        }

        if (!_SEH2_AbnormalTermination()) {
            // complete the IRP
            Irp->IoStatus.Status = RC;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_DISK_INCREMENT);
            // Free up the Irp Context
            UDFReleaseIrpContext(PtrIrpContext);
        }

    } _SEH2_END; // end of "__finally" processing
    return(RC);
} // end UDFCommonCleanup()
Exemplo n.º 15
0
NTSTATUS
xixfs_PurgeVolume(
	IN PXIXFS_IRPCONTEXT IrpContext,
	IN PXIXFS_VCB		pVCB,
	IN BOOLEAN			DismountForce
)
{
	NTSTATUS Status = STATUS_SUCCESS;

	PVOID RestartKey = NULL;
	PXIXFS_FCB ThisFcb = NULL;
	PXIXFS_FCB NextFcb = NULL;
	
	BOOLEAN RemovedFcb = FALSE;
	BOOLEAN	CanWait = FALSE;
	uint32	lockedVcbValue = 0;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter  xixfs_PurgeVolume\n"));

	ASSERT_EXCLUSIVE_VCB(pVCB);

	CanWait = XIXCORE_TEST_FLAGS(IrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT);



	
	
	//
	//  Force any remaining Fcb's in the delayed close queue to be closed.
	//
	
	xixfs_RealCloseFCB(pVCB);

	//
	//  Acquire the global file resource.
	//

	//XifsdAcquireAllFiles( CanWait, pVCB );

	//
	//  Loop through each Fcb in the Fcb Table and perform the flush.
	//

	while (TRUE) {

		//
		//  Lock the Vcb to lookup the next Fcb.
		//

		XifsdLockVcb( IrpContext, pVCB );
		NextFcb = xixfs_FCBTLBGetNextEntry(pVCB, &RestartKey );

		//
		//  Reference the NextFcb if present.
		//

		if (NextFcb != NULL) {

			NextFcb->FCBReference += 1;
		}

		//
		//  If the last Fcb is present then decrement reference count and call teardown
		//  to see if it should be removed.
		//

		if (ThisFcb != NULL) {

			ThisFcb->FCBReference -= 1;

			XifsdUnlockVcb( IrpContext, pVCB );


			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_PNP|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO|DEBUG_TARGET_REFCOUNT),
					 ("XifsdPurgeVolume FCB(%I64d) VCB %d/%d FCB %d/%d\n",
					 ThisFcb->XixcoreFcb.LotNumber,
					 pVCB->VCBReference,
					 pVCB->VCBUserReference,
					 ThisFcb->FCBReference,
					 ThisFcb->FCBUserReference ));


			DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_PNP|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB|DEBUG_TARGET_REFCOUNT,
				("XifsdPurgeVolume FCBLotNumber(%I64d) FCBCleanUp(%ld) VCBCleanup(%ld)\n", 
				ThisFcb->XixcoreFcb.LotNumber, 
				ThisFcb->FCBCleanup, 
				pVCB->VCBCleanup));
			

			xixfs_TeardownStructures( CanWait, ThisFcb, FALSE, &RemovedFcb );

		} else {

			XifsdUnlockVcb( IrpContext, pVCB );
		}

		//
		//  Break out of the loop if no more Fcb's.
		//

		if (NextFcb == NULL) {

			break;
		}

		//
		//  Move to the next Fcb.
		//

		ThisFcb = NextFcb;

		//
		//  If there is a image section then see if that can be closed.
		//

		if(ThisFcb->XixcoreFcb.FCBType == FCB_TYPE_FILE){
			
			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("XifsdPurgeVolume FCB(%I64d) \n", 
						 ThisFcb->XixcoreFcb.LotNumber));
			
			XifsdAcquireFcbExclusive(TRUE, ThisFcb, FALSE);

			
			//	Added by ILGU HONG for readonly 09052006
			if(!ThisFcb->PtrVCB->XixcoreVcb.IsVolumeWriteProtected){
				if (ThisFcb->SectionObject.ImageSectionObject != NULL) {

					MmFlushImageSection( &ThisFcb->SectionObject, MmFlushForWrite );
				}

				//
				//  If there is a data section then purge this.  If there is an image
				//  section then we won't be able to.  Remember this if it is our first
				//  error.
				//

				
				CcFlushCache(&ThisFcb->SectionObject, NULL, 0, NULL);
				//DbgPrint("CcFlush  3 File(%wZ)\n", &ThisFcb->FCBFullPath);
			}
			//	Added by ILGU HONG for readonly end


			
			ExAcquireResourceSharedLite(ThisFcb->PagingIoResource, TRUE);
			ExReleaseResourceLite( ThisFcb->PagingIoResource );

			
			if ((ThisFcb->SectionObject.DataSectionObject != NULL) &&
				!CcPurgeCacheSection( &ThisFcb->SectionObject,
									   NULL,
									   0,
									   FALSE ) &&
				(Status == STATUS_SUCCESS)) {

				Status = STATUS_UNABLE_TO_DELETE_SECTION;
			}
			
			

			XifsdReleaseFcb(TRUE, ThisFcb);
		}
		//
		//  Dereference the internal stream if dismounting.
		//

		if (DismountForce &&
			(ThisFcb->XixcoreFcb.FCBType  != FCB_TYPE_FILE) &&
			(ThisFcb->XixcoreFcb.FCBType != FCB_TYPE_DIR)	&&
			(ThisFcb->FileObject != NULL)) {

			xixfs_DeleteInternalStream( CanWait, ThisFcb );
		}
	}

	//
	//  Now look at the Root Index, Metadata, Volume Dasd and VAT Fcbs.
	//  Note that we usually hit the Root Index in the loop above, but
	//  it is possible miss it if it didn't get into the Fcb table in the
	//  first place!
	//


	DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("xixfs_PurgeVolume DismountFore (%s)\n", ((DismountForce)?"TRUE":"FALSE")));


	if (DismountForce) {




		if (pVCB->RootDirFCB != NULL) {
			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
				("Deal with RootFCB \n"));


			ThisFcb = pVCB->RootDirFCB;
			InterlockedIncrement( &ThisFcb->FCBReference );

			if ((ThisFcb->SectionObject.DataSectionObject != NULL) &&
				!CcPurgeCacheSection( &ThisFcb->SectionObject,
									   NULL,
									   0,
									   FALSE ) &&
				(Status == STATUS_SUCCESS)) {

				Status = STATUS_UNABLE_TO_DELETE_SECTION;
			}


			InterlockedDecrement( &ThisFcb->FCBReference );
/*
			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
						 ("pVCB->RootDirFCB FCB(%I64d) VCB %d/%d FCB %d/%d\n",
						 ThisFcb->LotNumber,
						 pVCB->VCBReference,
						 pVCB->VCBUserReference,
						 ThisFcb->FCBReference,
						 ThisFcb->FCBUserReference ));
			
			XifsdLockVcb(IrpContext, pVCB);
			XifsdDecRefCount(ThisFcb, 1, 1);
			XifsdUnlockVcb(IrpContext, pVCB);
*/	
			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("pVCB->RootDirFCB FCB(%I64d)  VCB %d/%d FCB %d/%d\n",
						 ThisFcb->XixcoreFcb.LotNumber,
						 pVCB->VCBReference,
						 pVCB->VCBUserReference,
						 ThisFcb->FCBReference,
						 ThisFcb->FCBUserReference ));

			xixfs_TeardownStructures( CanWait, ThisFcb, FALSE, &RemovedFcb );
			
		}
    
		if (pVCB->MetaFCB != NULL) {

			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
				("Deal with pVCB->MetaFCB \n"));

			ThisFcb = pVCB->MetaFCB;
			InterlockedIncrement( &ThisFcb->FCBReference );

			if ((ThisFcb->SectionObject.DataSectionObject != NULL) &&
				!CcPurgeCacheSection( &ThisFcb->SectionObject,
									   NULL,
									   0,
									   FALSE ) &&
				(Status == STATUS_SUCCESS)) {

				Status = STATUS_UNABLE_TO_DELETE_SECTION;
			}

			
			xixfs_DeleteInternalStream( CanWait, ThisFcb );

			InterlockedDecrement( &ThisFcb->FCBReference );

/*			
			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("pVCB->MetaFCB FCB(%I64d)  VCB %d/%d FCB %d/%d\n",
						 ThisFcb->LotNumber,
						 pVCB->VCBReference,
						 pVCB->VCBUserReference,
						 ThisFcb->FCBReference,
						 ThisFcb->FCBUserReference ));

			XifsdLockVcb(IrpContext, pVCB);
			XifsdDecRefCount(ThisFcb, 1, 1);
			XifsdUnlockVcb(IrpContext, pVCB);
*/
			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("pVCB->MetaFCB FCB(%I64d)  VCB %d/%d FCB %d/%d\n",
						 ThisFcb->XixcoreFcb.LotNumber,
						 pVCB->VCBReference,
						 pVCB->VCBUserReference,
						 ThisFcb->FCBReference,
						 ThisFcb->FCBUserReference ));



			xixfs_TeardownStructures( CanWait, ThisFcb, FALSE, &RemovedFcb );
			
			
			
		}

		if (pVCB->VolumeDasdFCB != NULL) {
			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
				("Deal with pVCB->VolumeDasdFCB \n"));

			ThisFcb = pVCB->VolumeDasdFCB;
			InterlockedIncrement( &ThisFcb->FCBReference );

			if ((ThisFcb->SectionObject.DataSectionObject != NULL) &&
				!CcPurgeCacheSection( &ThisFcb->SectionObject,
									   NULL,
									   0,
									   FALSE ) &&
				(Status == STATUS_SUCCESS)) {

				Status = STATUS_UNABLE_TO_DELETE_SECTION;
			}
			
			xixfs_DeleteInternalStream( CanWait, ThisFcb );

			InterlockedDecrement( &ThisFcb->FCBReference );
/*
			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("pVCB->VolumeDasdFCB FCB(%I64d)  VCB %d/%d FCB %d/%d\n",
						 ThisFcb->LotNumber,
						 pVCB->VCBReference,
						 pVCB->VCBUserReference,
						 ThisFcb->FCBReference,
						 ThisFcb->FCBUserReference ));

			
			XifsdLockVcb(IrpContext, pVCB);
			XifsdDecRefCount(ThisFcb, 1, 1);
			XifsdUnlockVcb(IrpContext, pVCB);
*/			
			DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("pVCB->VolumeDasdFCB FCB(%I64d)  VCB %d/%d FCB %d/%d\n",
						 ThisFcb->XixcoreFcb.LotNumber,
						 pVCB->VCBReference,
						 pVCB->VCBUserReference,
						 ThisFcb->FCBReference,
						 ThisFcb->FCBUserReference ));	
			

			
			xixfs_TeardownStructures( CanWait, ThisFcb, FALSE, &RemovedFcb );
			
		}
	}

	//
	//  Release all of the files.
	//

	//XifsdReleaseAllFiles( CanWait, pVCB );
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit  xixfs_PurgeVolume\n"));
	return Status;
}
Exemplo n.º 16
0
VOID
FFSUnpinRepinnedBcbs(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	IO_STATUS_BLOCK    RaiseIosb;
	PFFS_REPINNED_BCBS Repinned;
	BOOLEAN            WriteThroughToDisk;
	PFILE_OBJECT       FileObject = NULL;
	BOOLEAN            ForceVerify = FALSE;
	ULONG              i;

	Repinned = &IrpContext->Repinned;
	RaiseIosb.Status = STATUS_SUCCESS;

	WriteThroughToDisk = (BOOLEAN)(IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
			IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY));

	while (Repinned != NULL)
	{
		for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
		{
			if (Repinned->Bcb[i] != NULL)
			{
				IO_STATUS_BLOCK Iosb;

				ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

				if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY))
				{
					FileObject = CcGetFileObjectFromBcb(Repinned->Bcb[i]);
				}

				ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

				CcUnpinRepinnedBcb(Repinned->Bcb[i],
						WriteThroughToDisk,
						&Iosb);

				ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

				if (!NT_SUCCESS(Iosb.Status))
				{
					if (RaiseIosb.Status == STATUS_SUCCESS)
					{
						RaiseIosb = Iosb;
					}

					if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) &&
							(IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
							(IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
							(IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION))
					{

						CcPurgeCacheSection(FileObject->SectionObjectPointer,
								NULL,
								0,
								FALSE);

						ForceVerify = TRUE;
					}
				}

				Repinned->Bcb[i] = NULL;

			}
			else
			{
				break;
			}
		}

		if (Repinned != &IrpContext->Repinned)
		{
			PFFS_REPINNED_BCBS Saved;

			Saved = Repinned->Next;
			ExFreePool(Repinned);
			Repinned = Saved;

		}
		else
		{
			Repinned = Repinned->Next;
			IrpContext->Repinned.Next = NULL;
		}
	}

	if (!NT_SUCCESS(RaiseIosb.Status))
	{
		FFSBreakPoint();

		if (ForceVerify && FileObject)
		{
			SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
			IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
					FileObject->DeviceObject);
		}

		IrpContext->Irp->IoStatus = RaiseIosb;
		FFSNormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status);
	}

	return;
}
Exemplo n.º 17
0
VOID
ReadonlyTryCloseCcb (
	IN PREADONLY Readonly
	)
{
	PLIST_ENTRY		listEntry;


	Readonly_Reference( Readonly );	
	
	if (ExTryToAcquireFastMutex(&Readonly->CcbQMutex) == FALSE) {

		Readonly_Dereference( Readonly );
		return;
	}
	
	listEntry = Readonly->CcbQueue.Flink;

	while (listEntry != &Readonly->CcbQueue) {

		PNDAS_CCB					ccb = NULL;
		PNDAS_FCB					fcb;
		PSECTION_OBJECT_POINTERS	section;
		BOOLEAN						dataSectionExists;
		BOOLEAN						imageSectionExists;

		ccb = CONTAINING_RECORD( listEntry, NDAS_CCB, ListEntry );
		listEntry = listEntry->Flink;

		if (ccb->TypeOfOpen != UserFileOpen)
			break;

		fcb = ccb->Fcb;

		if (fcb == NULL) {

			ASSERT( LFS_BUG );
			break;
		}	

		SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, 
					   ("ReadonlyTryCloseCcb: fcb->FullFileName = %wZ\n", &fcb->FullFileName) );

		if (fcb->UncleanCount != 0) {

			SPY_LOG_PRINT( LFS_DEBUG_SECONDARY_TRACE, 
						   ("ReadonlyTryCloseCcb: fcb->FullFileName = %wZ\n", &fcb->FullFileName) );
			break;
		}

	    if (fcb->Header.PagingIoResource != NULL) {

			ASSERT( LFS_REQUIRED );
			break;
		}

		section = &fcb->NonPaged->SectionObjectPointers;			
		if (section == NULL)
			break;

        //CcFlushCache(section, NULL, 0, &ioStatusBlock);

		dataSectionExists = (BOOLEAN)(section->DataSectionObject != NULL);
		imageSectionExists = (BOOLEAN)(section->ImageSectionObject != NULL);

		if (imageSectionExists) {

			(VOID)MmFlushImageSection( section, MmFlushForWrite );
		}

		if (dataSectionExists) {

            CcPurgeCacheSection( section, NULL, 0, FALSE );
	    }
	}

	ExReleaseFastMutex( &Readonly->CcbQMutex );
	Readonly_Dereference( Readonly );

	return;
}
Exemplo n.º 18
0
NTSTATUS
SecondaryRecoverySession (
	IN  PSECONDARY		Secondary
	)
{
	NTSTATUS			status;
	LONG				slotIndex;

	LARGE_INTEGER		timeOut;
	OBJECT_ATTRIBUTES	objectAttributes;

	ULONG				reconnectionTry;
    PLIST_ENTRY			ccblistEntry;
	BOOLEAN				isLocalAddress;


	DebugTrace2( 0, Dbg2, ("SecondaryRecoverySession: Called Secondary = %p\n", Secondary) );

	SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

	ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); 
	ASSERT( Secondary->ThreadHandle );

	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	for (slotIndex=0; slotIndex < Secondary->Thread.SessionContext.SessionSlotCount; slotIndex++) {

		ASSERT( Secondary->Thread.SessionSlot[slotIndex] == NULL );
	}

	if (Secondary->ThreadHandle) {

		ASSERT( Secondary->ThreadObject );
		
		timeOut.QuadPart = -NDASFAT_TIME_OUT;
		status = KeWaitForSingleObject( Secondary->ThreadObject,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if (status != STATUS_SUCCESS) {

			NDASFAT_ASSERT( FALSE );

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return status;
		}

		DebugTrace2( 0, Dbg2, ("Secondary_Stop: thread stoped\n") );

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = 0;
		Secondary->ThreadObject = 0;

		RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );
	}

	for (status = STATUS_UNSUCCESSFUL, reconnectionTry = 0; reconnectionTry < MAX_RECONNECTION_TRY; reconnectionTry++) {

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_LOCKED)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->NdasFatFlags, ND_FAT_DEVICE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY) {
			
			status = STATUS_SUCCESS;
		
		} else {

			status = ((PVOLUME_DEVICE_OBJECT) FatData.DiskFileSystemDeviceObject)->
						NdfsCallback.SecondaryToPrimary( Secondary->VolDo->Vcb.Vpb->RealDevice, TRUE );

			if (status == STATUS_NO_SUCH_DEVICE) {

				NDASFAT_ASSERT( FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_LOCKED) );
				ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

				return STATUS_UNSUCCESSFUL;
			}
		}

		//FatDebugTraceLevel = 0;

		DebugTrace2( 0, Dbg2, ("SecondaryToPrimary status = %x\n", status) ); 

#if 0
		if (queryResult == TRUE) {
			
			BOOLEAN	result0, result1;
		    IRP_CONTEXT IrpContext;
		
			ASSERT( Secondary->VolDo->Vcb.VirtualVolumeFile );
			result0 = CcPurgeCacheSection( &Secondary->VolDo->Vcb.SectionObjectPointers,
										   NULL,
										   0,
										   FALSE );
			ASSERT( Secondary->VolDo->Vcb.RootDcb->Specific.Dcb.DirectoryFile );
			result1 = CcPurgeCacheSection( &Secondary->VolDo->Vcb.RootDcb->NonPaged->SectionObjectPointers,
										   NULL,
										   0,
										   FALSE );
		
			ASSERT( result0 == TRUE );
			ASSERT( result1 == TRUE );

			ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
		    RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
            SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
			FatTearDownAllocationSupport ( &IrpContext, &Secondary->VolDo->Vcb );
   			FatSetupAllocationSupport( &IrpContext, &Secondary->VolDo->Vcb );
			FatCheckDirtyBit( &IrpContext, &Secondary->VolDo->Vcb );

	        ASSERT( IrpContext.Repinned.Bcb[0] == NULL );
	        FatUnpinRepinnedBcbs( &IrpContext );
    
			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 
			Secondary->VolDo->SecondaryState = CONNECT_TO_LOCAL_STATE;
		}
#endif

		if (status == STATUS_SUCCESS) {

			PVCB				vcb = &Secondary->VolDo->Vcb;
#if 0
			TOP_LEVEL_CONTEXT	topLevelContext;
			PTOP_LEVEL_CONTEXT	threadTopLevelContext;
#endif
			IRP_CONTEXT			tempIrpContext2;
			PIRP_CONTEXT		tempIrpContext = NULL;

			SetFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&FatData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&FatData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->SecondaryResource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->SecondaryResource) );	


			//FatReleaseAllResources( IrpContext );

			//ObReferenceObject( vcb->TargetDeviceObject );

			DebugTrace2( 0, Dbg2, ("Vcb->State = %X\n", vcb->VcbState) );
			DebugTrace2( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );

			tempIrpContext = NULL;

#if 0
			threadTopLevelContext = FatInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			FatInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            FatUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );
			
			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
#endif
			tempIrpContext = &tempIrpContext2;

			RtlZeroMemory( tempIrpContext, sizeof(IRP_CONTEXT) );
			SetFlag( tempIrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
			SetFlag( tempIrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

			try {
			
				status = STATUS_UNSUCCESSFUL;
				status = CleanUpVcb( tempIrpContext, vcb );
			
			} finally {
                
				//FatCompleteRequest( tempIrpContext, NULL, 0 );
				//ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

			ASSERT( status == STATUS_SUCCESS );
			//ASSERT( FlagOn(vcb->VcbState, VCB_STATE_MOUNT_COMPLETED) );
			ASSERT( FlagOn(Secondary->VolDo->NdasFatFlags, ND_FAT_DEVICE_FLAG_MOUNTED) );
			ASSERT( !ExIsResourceAcquiredExclusiveLite(&FatData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&FatData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->SecondaryResource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->SecondaryResource) );	

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );


			DebugTrace2( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->OpenFileCount) );

#if 0
			tempIrpContext = NULL;

			threadTopLevelContext = FatInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			FatInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            FatUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
#endif

			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 

			tempIrpContext = &tempIrpContext2;

			RtlZeroMemory( tempIrpContext, sizeof(IRP_CONTEXT) );
			SetFlag( tempIrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
			SetFlag( tempIrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
			
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;
			
			SetFlag( Secondary->Flags, SECONDARY_FLAG_REMOUNT_VOLUME );

			try {
			
				status = STATUS_UNSUCCESSFUL;

				status = NdasFatMountVolume( tempIrpContext, vcb->TargetDeviceObject, vcb->Vpb, NULL );
			
			} finally {
                
				//FatCompleteRequest( tempIrpContext, NULL, 0 );
				//ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			//ObDereferenceObject( vcb->TargetDeviceObject );

			//FatDebugTraceLevel = 0xFFFFFFFFFFFFFFFF;
			//FatDebugTraceLevel |= DEBUG_TRACE_CREATE;

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_REMOUNT_VOLUME );

			ASSERT( status == STATUS_SUCCESS );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&FatData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&FatData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			DebugTrace2( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->OpenFileCount) );

#if 0

			if (vcb->MftScb) {
			
				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftScb->Header.Resource) );	
			}

			if (vcb->Mft2Scb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->Mft2Scb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->Mft2Scb->Header.Resource) );	
			}

			if (vcb->LogFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->LogFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->LogFileScb->Header.Resource) );			
			}

			if (vcb->VolumeDasdScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->VolumeDasdScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->VolumeDasdScb->Header.Resource) );			
			}

			if (vcb->AttributeDefTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->AttributeDefTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->AttributeDefTableScb->Header.Resource) );			
			}

			if (vcb->UpcaseTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UpcaseTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UpcaseTableScb->Header.Resource) );			
			}

			if (vcb->RootIndexScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->RootIndexScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->RootIndexScb->Header.Resource) );			
			}

			if (vcb->BitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BitmapScb->Header.Resource) );			
			}

			if (vcb->BadClusterFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BadClusterFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BadClusterFileScb->Header.Resource) );		
			}

			if (vcb->MftBitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftBitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftBitmapScb->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorStream) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorStream->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorStream->Header.Resource) );			
			}

			if (vcb->UsnJournal) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UsnJournal->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UsnJournal->Header.Resource) );			
			}

			if (vcb->ExtendDirectory) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->ExtendDirectory->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->ExtendDirectory->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorHashIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
			}

			if (vcb->SecurityIdIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityIdIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityIdIndex->Header.Resource) );			
			}
#endif
		}


		status = ((PVOLUME_DEVICE_OBJECT) FatData.DiskFileSystemDeviceObject)->
						NdfsCallback.QueryPrimaryAddress( &Secondary->VolDo->NetdiskPartitionInformation, &Secondary->PrimaryAddress, &isLocalAddress );

		DebugTrace2( 0, Dbg2, ("RecoverSession: LfsTable_QueryPrimaryAddress status = %X\n", status) );
	
		if (status == STATUS_SUCCESS && !(Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY && isLocalAddress)) {

			DebugTrace2( 0, Dbg, ("SecondaryRecoverySessionStart: Found PrimaryAddress :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
								  Secondary->PrimaryAddress.Node[0],
								  Secondary->PrimaryAddress.Node[1],
								  Secondary->PrimaryAddress.Node[2],
								  Secondary->PrimaryAddress.Node[3],
								  Secondary->PrimaryAddress.Node[4],
								  Secondary->PrimaryAddress.Node[5],
								  NTOHS(Secondary->PrimaryAddress.Port)) );
		
		} else {

			//ASSERT( FALSE );
			continue;
		}	

		KeInitializeEvent( &Secondary->ReadyEvent, NotificationEvent, FALSE );
		KeInitializeEvent( &Secondary->RequestEvent, NotificationEvent, FALSE );

		InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

		status = PsCreateSystemThread( &Secondary->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   SecondaryThreadProc,
									   Secondary );

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASFAT_UNEXPECTED );
			break;
		}

		status = ObReferenceObjectByHandle( Secondary->ThreadHandle,
											FILE_READ_DATA,
											NULL,
											KernelMode,
											&Secondary->ThreadObject,
											NULL );

		if (!NT_SUCCESS(status)) {

			ASSERT (NDASFAT_INSUFFICIENT_RESOURCES );
			break;
		}

		timeOut.QuadPart = -NDASFAT_TIME_OUT;
		status = KeWaitForSingleObject( &Secondary->ReadyEvent,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if (status != STATUS_SUCCESS) {

			ASSERT( NDASFAT_BUG );
			break;
		}

		KeClearEvent( &Secondary->ReadyEvent );

		InterlockedIncrement( &Secondary->SessionId );	

		ExAcquireFastMutex( &Secondary->FastMutex );

		if (!FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) || FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) {

			ExReleaseFastMutex( &Secondary->FastMutex );

			if (Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) {

				status = STATUS_SUCCESS;
				break;
			}

			timeOut.QuadPart = -NDASFAT_TIME_OUT;
			status = KeWaitForSingleObject( Secondary->ThreadObject,
											Executive,
											KernelMode,
											FALSE,
											&timeOut );

			if (status != STATUS_SUCCESS) {

				ASSERT( NDASFAT_BUG );
				return status;
			}

			DebugTrace2( 0, Dbg, ("Secondary_Stop: thread stoped\n") );

			ObDereferenceObject( Secondary->ThreadObject );

			Secondary->ThreadHandle = 0;
			Secondary->ThreadObject = 0;

			RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );

			continue;
		} 

		ExReleaseFastMutex( &Secondary->FastMutex );

		status = STATUS_SUCCESS;

		DebugTrace2( 0, Dbg2, ("SecondaryRecoverySession Success Secondary = %p\n", Secondary) );

		break;
	}
Exemplo n.º 19
0
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;

	//PAGED_CODE();

	__try {

		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanCleanup");
	
		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");
			status = STATUS_SUCCESS;
			__leave;
		}

		vcb = DeviceObject->DeviceExtension;
		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);

		eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
		eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

		if (eventContext == NULL) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		if (fileObject->SectionObjectPointer != NULL &&
			fileObject->SectionObjectPointer->DataSectionObject != NULL) {
			CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
			CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
			CcUninitializeCacheMap(fileObject, NULL, NULL);
		}
		fileObject->Flags |= FO_CLEANUP_COMPLETE;

		eventContext->Context = ccb->UserContext;
		//DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

		// copy the filename to EventContext from ccb
		eventContext->Cleanup.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->Cleanup.FileName, fcb->FileName.Buffer, fcb->FileName.Length);

		// register this IRP to pending IRP list
		status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanCleanup");
	
		FsRtlExitFileSystem();
	}

	return status;
}
Exemplo n.º 20
0
VOID
W2kNtfsFlushOnDirectoryControl (
    IN PDEVICE_OBJECT		FSpyDeviceObject,
    IN PDEVICE_OBJECT		baseDeviceObject,
	IN PIO_STACK_LOCATION	IrpSp,
	IN ULONG				BufferLen,
	IN PCHAR				Buffer
	)
{
	PVCB					vcb;
//	PDEVICE_OBJECT			baseDeviceObject;
    PVOLUME_DEVICE_OBJECT	volDo;
	PFILE_OBJECT			fileObject;
				

//	baseDeviceObject 
//		= ((PFILESPY_DEVICE_EXTENSION) (FSpyDeviceObject->DeviceExtension))->BaseVolumeDeviceObject;
	volDo = (PVOLUME_DEVICE_OBJECT)baseDeviceObject;
	vcb = &volDo->Vcb;
		
	fileObject = IrpSp->FileObject;

	SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
		("fileObject->FileName = %Z\n",
			&fileObject->FileName)); 
			
//	if (FlagOn( vcb->VcbState, VCB_STATE_MOUNT_READ_ONLY ))
	{
		PSCB			scb;
		TYPE_OF_OPEN	typeOfOpen = UnopenedFileObject;	
		PCCB			ccb;
				
				
		ccb = (PCCB)fileObject->FsContext2;
		ASSERT(ccb);

		typeOfOpen = ccb->TypeOfOpen;

		scb = (PSCB)fileObject->FsContext;
		ASSERT(scb != NULL);

		if ((UserDirectoryOpen == typeOfOpen) &&
			!FlagOn( scb->ScbState, SCB_STATE_VIEW_INDEX )) 
		{
			BOOLEAN flushResult;
			BOOLEAN	scbResult0 = 0;
				

			flushResult = W2kNtfsFlushMetaFile (
								FSpyDeviceObject,
								baseDeviceObject,
								BufferLen,
								Buffer
								);

			if(flushResult != TRUE) {
				DbgPrint("flushResult = %d\n", flushResult);
				return;
			}

										
			if(scb->NonpagedScb && scb->FileObject)
				scbResult0 = CcPurgeCacheSection (
//								scb->FileObject->SectionObjectPointer,
								&scb->NonpagedScb->SegmentObject,
								NULL,
								0,
								FALSE
								);
			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
							("scbResult0 = %d\n", scbResult0));
		}
	}
	
	return;
}
Exemplo n.º 21
0
NTSTATUS
DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID buffer;
  BOOLEAN writeToEoF = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isNonCached = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN fcbLocked = FALSE;

  __try {

    DDbgPrint("==> DokanWrite\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length write then return SUCCESS immediately.
    //

    if (irpSp->Parameters.Write.Length == 0) {
      DDbgPrint("  Parameters.Write.Length == 0\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->MdlAddress) {
      DDbgPrint("  use MdlAddress\n");
      buffer = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
    } else {
      DDbgPrint("  use UserBuffer\n");
      buffer = Irp->UserBuffer;
    }

    if (buffer == NULL) {
      DDbgPrint("  buffer == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (irpSp->Parameters.Write.ByteOffset.LowPart ==
            FILE_WRITE_TO_END_OF_FILE &&
        irpSp->Parameters.Write.ByteOffset.HighPart == -1) {
      writeToEoF = TRUE;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      isNonCached = TRUE;
    }

    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   writeToEoF ? NULL : &irpSp->Parameters.Write.ByteOffset,
                   irpSp->Parameters.Write.Length, NULL);
      CcPurgeCacheSection(&fcb->SectionObjectPointers,
                          writeToEoF ? NULL
                                     : &irpSp->Parameters.Write.ByteOffset,
                          irpSp->Parameters.Write.Length, FALSE);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    // Cannot write at end of the file when using paging IO
    if (writeToEoF && isPagingIo) {
      DDbgPrint("  writeToEoF & isPagingIo\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    // the length of EventContext is sum of length to write and length of file
    // name
    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + irpSp->Parameters.Write.Length +
                  fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    // no more memory!
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    // When the length is bigger than usual event notitfication buffer,
    // saves pointer in DiverContext to copy EventContext after allocating
    // more bigger memory.
    Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = eventContext;

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }
    if (isNonCached) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to write
    eventContext->Operation.Write.ByteOffset =
        irpSp->Parameters.Write.ByteOffset;

    if (writeToEoF) {
      eventContext->FileFlags |= DOKAN_WRITE_TO_END_OF_FILE;
      DDbgPrint("  WriteOffset = end of file\n");
    }

    if (isSynchronousIo &&
        ((irpSp->Parameters.Write.ByteOffset.LowPart ==
          FILE_USE_FILE_POINTER_POSITION) &&
         (irpSp->Parameters.Write.ByteOffset.HighPart == -1))) {
      // NOTE:
      // http://msdn.microsoft.com/en-us/library/ms795960.aspx
      // Do not check IrpSp->Parameters.Write.ByteOffset.QuadPart == 0
      // Probably the document is wrong.
      eventContext->Operation.Write.ByteOffset.QuadPart =
          fileObject->CurrentByteOffset.QuadPart;
    }

    // the size of buffer to write
    eventContext->Operation.Write.BufferLength = irpSp->Parameters.Write.Length;

    // the offset from the begining of structure
    // the contents to write will be copyed to this offset
    eventContext->Operation.Write.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.Write.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // adds last null char

    // copies the content to write to EventContext
    RtlCopyMemory((PCHAR)eventContext +
                      eventContext->Operation.Write.BufferOffset,
                  buffer, irpSp->Parameters.Write.Length);

    // copies file name
    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.
    if (eventLength <= EVENT_CONTEXT_MAX_SIZE) {

      DDbgPrint("   Offset %d:%d, Length %d\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // 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.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      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_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // register this IRP to IRP waiting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

      // Resuests bigger memory
      // eventContext will be freed later using
      // Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]
    } else {
      // the length at lest file name can be stored
      ULONG requestContextLength = max(
          sizeof(EVENT_CONTEXT), eventContext->Operation.Write.BufferOffset);
      PEVENT_CONTEXT requestContext =
          AllocateEventContext(vcb->Dcb, Irp, requestContextLength, ccb);

      // no more memory!
      if (requestContext == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
        DokanFreeEventContext(eventContext);
        __leave;
      }

      DDbgPrint("   Offset %d:%d, Length %d (request)\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // copies from begining of EventContext to the end of file name
      RtlCopyMemory(requestContext, eventContext,
                    eventContext->Operation.Write.BufferOffset);
      // puts actual size of RequestContext
      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.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      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_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;
        }
      }

      // regiters this IRP to IRP wainting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, requestContext, 0);
    }

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanWrite\n");
  }

  return status;
}
Exemplo n.º 22
0
NTSTATUS
FFSv1WriteInode(
	IN PFFS_IRP_CONTEXT     IrpContext,
	IN PFFS_VCB             Vcb,
	IN PFFSv1_INODE         dinode1,
	IN ULONGLONG            offset,
	IN PVOID                Buffer,
	IN ULONG                size,
	IN BOOLEAN              bWriteToDisk,
	OUT PULONG              dwRet)
{
	PFFS_BDL    ffs_bdl = NULL;
	ULONG       blocks, i;
	NTSTATUS    Status = STATUS_UNSUCCESSFUL;
	ULONG       Totalblocks;
	LONGLONG    AllocSize;

	if (dwRet)
	{
		*dwRet = 0;
	}

	Totalblocks = (dinode1->di_blocks);
	AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);

	if ((LONGLONG)offset >= AllocSize)
	{
		FFSPrint((DBG_ERROR, "FFSv1WriteInode: beyond the file range.\n"));
		return STATUS_SUCCESS;
	}

	if ((LONGLONG)offset + size > AllocSize)
	{
		size = (ULONG)(AllocSize - offset);
	}

	blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);

	if (blocks <= 0)
	{
		return STATUS_SUCCESS;
	}

#if DBG
	{
		ULONG   dwTotal = 0;
		FFSPrint((DBG_INFO, "FFSv1WriteInode: BDLCount = %xh Size=%xh Off=%xh\n",
					blocks, size, offset));
		for(i = 0; i < blocks; i++)
		{
			FFSPrint((DBG_INFO, "FFSv1WriteInode: Lba=%I64xh Len=%xh Off=%xh\n",
						ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
			dwTotal += ffs_bdl[i].Length;
		}

		if (dwTotal != size)
		{
			FFSBreakPoint();
		}

		FFSPrint((DBG_INFO, "FFSv1WriteInode: Total = %xh (WriteToDisk=%x)\n",
					dwTotal, bWriteToDisk));
	}
#endif

	if (bWriteToDisk)
	{

#if 0
		for(i = 0; i < blocks; i++)
		{
			{
				CcFlushCache(&(Vcb->SectionObject),
						(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
						ffs_bdl[i].Length,
						NULL);

				if (Vcb->SectionObject.DataSectionObject != NULL)
				{
					ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
					ExReleaseResource(&Vcb->PagingIoResource);

					CcPurgeCacheSection(&(Vcb->SectionObject),
							(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
							ffs_bdl[i].Length,
							FALSE);
				}
			}
		}
#endif

		// assume offset is aligned.
		Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
	}
	else
	{
		for(i = 0; i < blocks; i++)
		{
			if(!FFSSaveBuffer(IrpContext, Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset)))
				goto errorout;
		}

		if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
		{
			FFSPrint((DBG_USER, "FFSv1WriteInode is starting FlushingDpc...\n"));
			FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
		}

		Status = STATUS_SUCCESS;
	}

errorout:

	if (ffs_bdl)
		ExFreePool(ffs_bdl);

	if (NT_SUCCESS(Status))
	{
		if (dwRet) *dwRet = size;
	}

	return Status;
}
Exemplo n.º 23
0
NTSTATUS
Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_SUCCESS;
    PEXT2_VCB       Vcb;
    PFILE_OBJECT    FileObject;
    PEXT2_FCB       Fcb;
    PEXT2_CCB       Ccb;
    PIRP            Irp;
    PEXT2_MCB       Mcb;


    BOOLEAN         VcbResourceAcquired = FALSE;
    BOOLEAN         FcbResourceAcquired = FALSE;
    BOOLEAN         FcbPagingIoResourceAcquired = FALSE;

    __try {

        ASSERT(IrpContext != NULL);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        if (IsExt2FsDevice(DeviceObject))  {
            Status = STATUS_SUCCESS;
            __leave;
        }

        Irp = IrpContext->Irp;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        if (!IsVcbInited(Vcb)) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        FileObject = IrpContext->FileObject;
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
                     Fcb->Identifier.Type != EXT2FCB)) {
            Status = STATUS_SUCCESS;
            __leave;
        }
        Mcb = Fcb->Mcb;
        Ccb = (PEXT2_CCB) FileObject->FsContext2;

        if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        VcbResourceAcquired =
            ExAcquireResourceExclusiveLite(
                &Vcb->MainResource,
                IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
            );

        if (Fcb->Identifier.Type == EXT2VCB) {

            if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
                    (Vcb->LockFile == FileObject) ) {

                ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
                Vcb->LockFile = NULL;
                Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
            }

            if (Ccb) {
                Ext2DerefXcb(&Vcb->OpenHandleCount);
                Ext2DerefXcb(&Vcb->OpenVolumeCount);
            }

            IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);

            Status = STATUS_SUCCESS;
            __leave;
        }

        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
            if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
                    IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
                    !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) {
                Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
            }
            __leave;
        }

        if (Ccb == NULL) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (IsDirectory(Fcb)) {
            if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))  {
                SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);

                FsRtlNotifyFullChangeDirectory(
                    Vcb->NotifySync,
                    &Vcb->NotifyList,
                    Ccb,
                    NULL,
                    FALSE,
                    FALSE,
                    0,
                    NULL,
                    NULL,
                    NULL );
            }

            FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);

        }

        ExReleaseResourceLite(&Vcb->MainResource);
        VcbResourceAcquired = FALSE;

        FcbResourceAcquired =
            ExAcquireResourceExclusiveLite(
                &Fcb->MainResource,
                IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
            );

        ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
               (Ccb->Identifier.Size == sizeof(EXT2_CCB)));

        Ext2DerefXcb(&Vcb->OpenHandleCount);
        Ext2DerefXcb(&Fcb->OpenHandleCount);

        if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
            Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
        }

        if (IsDirectory(Fcb)) {

            ext3_release_dir(Fcb->Inode, &Ccb->filp);

        } else {

            if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
                    !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {

                LARGE_INTEGER   SysTime;
                KeQuerySystemTime(&SysTime);

                Fcb->Inode->i_atime =
                    Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
                Fcb->Mcb->LastAccessTime =
                    Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);

                Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);

                Ext2NotifyReportChange(
                    IrpContext,
                    Vcb,
                    Fcb->Mcb,
                    FILE_NOTIFY_CHANGE_ATTRIBUTES |
                    FILE_NOTIFY_CHANGE_LAST_WRITE |
                    FILE_NOTIFY_CHANGE_LAST_ACCESS,
                    FILE_ACTION_MODIFIED );
            }

            FsRtlCheckOplock( &Fcb->Oplock,
                              Irp,
                              IrpContext,
                              NULL,
                              NULL );

            Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);

            if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
                Fcb->NonCachedOpenCount--;
            }

            if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))  {
                SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
            }

            //
            // Drop any byte range locks this process may have on the file.
            //

            FsRtlFastUnlockAll(
                &Fcb->FileLockAnchor,
                FileObject,
                IoGetRequestorProcess(Irp),
                NULL  );

            //
            // If there are no byte range locks owned by other processes on the
            // file the fast I/O read/write functions doesn't have to check for
            // locks so we set IsFastIoPossible to FastIoIsPossible again.
            //
            if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
                if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
#if EXT2_DEBUG
                    DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
                                   Ext2GetCurrentProcessName(),
                                   "FastIoIsPossible",
                                   &Fcb->Mcb->FullName
                                  ));
#endif

                    Fcb->Header.IsFastIoPossible = FastIoIsPossible;
                }
            }

            if (Fcb->OpenHandleCount == 0 &&
                    (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE) ||
                     IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_WRITE)) ) {

                LARGE_INTEGER Size;

                ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
                FcbPagingIoResourceAcquired = TRUE;

                Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
                                                (ULONGLONG)Fcb->Mcb->Inode.i_size,
                                                (ULONGLONG)BLOCK_SIZE);
                if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {

                    Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
                    Fcb->Header.ValidDataLength.QuadPart =
                        Fcb->Header.FileSize.QuadPart = Fcb->Mcb->Inode.i_size;
                    Fcb->Header.AllocationSize = Size;
                    if (CcIsFileCached(FileObject)) {
                        CcSetFileSizes(FileObject,
                                       (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    }
                }
                ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE);
                ExReleaseResourceLite(&Fcb->PagingIoResource);
                FcbPagingIoResourceAcquired = FALSE;
            }
        }

        if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {

            if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {

                //
                // Ext2DeleteFile will acquire these lock inside
                //

                if (FcbResourceAcquired) {
                    ExReleaseResourceLite(&Fcb->MainResource);
                    FcbResourceAcquired = FALSE;
                }

                //
                //  this file is to be deleted ...
                //
                if (Ccb->SymLink) {
                    Mcb = Ccb->SymLink;
                    FileObject->DeletePending = FALSE;
                }

                Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);

                if (NT_SUCCESS(Status)) {
                    if (IsMcbDirectory(Mcb)) {
                        Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
                                                FILE_NOTIFY_CHANGE_DIR_NAME,
                                                FILE_ACTION_REMOVED );
                    } else {
                        Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
                                                FILE_NOTIFY_CHANGE_FILE_NAME,
                                                FILE_ACTION_REMOVED );
                    }
                }

                //
                // re-acquire the main resource lock
                //

                FcbResourceAcquired =
                    ExAcquireResourceExclusiveLite(
                        &Fcb->MainResource,
                        IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
                    );

                if (CcIsFileCached(FileObject)) {
                    CcSetFileSizes(FileObject,
                                   (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }
            }
        }

        if (!IsDirectory(Fcb)) {

            if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
                    (Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) &&
                    (Fcb->SectionObject.DataSectionObject != NULL)) {

                if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
                        !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) {
                    CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
                }

                if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
                    ExReleaseResourceLite(&(Fcb->PagingIoResource));
                }

                CcPurgeCacheSection( &Fcb->SectionObject,
                                     NULL,
                                     0,
                                     FALSE );
            }

            CcUninitializeCacheMap(FileObject, NULL, NULL);
        }

        IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);

        DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
                        Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));

        Status = STATUS_SUCCESS;

        if (FileObject) {
            SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
        }

    } __finally {

        if (FcbPagingIoResourceAcquired) {
            ExReleaseResourceLite(&Fcb->PagingIoResource);
        }

        if (FcbResourceAcquired) {
            ExReleaseResourceLite(&Fcb->MainResource);
        }

        if (VcbResourceAcquired) {
            ExReleaseResourceLite(&Vcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {
            if (Status == STATUS_PENDING) {
                Ext2QueueRequest(IrpContext);
            } else {
                IrpContext->Irp->IoStatus.Status = Status;
                Ext2CompleteIrpContext(IrpContext, Status);
            }
        }
    }

    return Status;
}
Exemplo n.º 24
0
NTSTATUS
CmpDoFileSetSize(
    PHHIVE      Hive,
    ULONG       FileType,
    ULONG       FileSize,
    ULONG       OldFileSize
    )
/*++

Routine Description:

    This routine sets the size of a file.  It must not return until
    the size is guaranteed.

    It is environment specific.

    Must be running in the context of the cmp worker thread.

Arguments:

    Hive - Hive we are doing I/O for

    FileType - which supporting file to use

    FileSize - 32 bit value to set the file's size to

    OldFileSize - old file size, in order to determine if this is a shrink;
                - ignored if file type is not primary, or hive doesn't use 
                the mapped views technique

Return Value:

    FALSE if failure
    TRUE if success

--*/
{
    PCMHIVE                         CmHive;
    HANDLE                          FileHandle;
    NTSTATUS                        Status;
    FILE_END_OF_FILE_INFORMATION    FileInfo;
    IO_STATUS_BLOCK                 IoStatus;
    BOOLEAN                         oldFlag;
    LARGE_INTEGER                   FileOffset;         // where the mapping starts

    ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);

    CmHive = (PCMHIVE)Hive;
    FileHandle = CmHive->FileHandles[FileType];
    if (FileHandle == NULL) {
        return TRUE;
    }

    //
    // disable hard error popups, to avoid self deadlock on bogus devices
    //
    oldFlag = IoSetThreadHardErrorMode(FALSE);

    FileInfo.EndOfFile.HighPart = 0L;
    if( FileType == HFILE_TYPE_PRIMARY ) {
        FileInfo.EndOfFile.LowPart  = ROUND_UP(FileSize, CM_FILE_GROW_INCREMENT);
    } else {
        FileInfo.EndOfFile.LowPart  = FileSize;
    }

    ASSERT_PASSIVE_LEVEL();

    Status = ZwSetInformationFile(
                FileHandle,
                &IoStatus,
                (PVOID)&FileInfo,
                sizeof(FILE_END_OF_FILE_INFORMATION),
                FileEndOfFileInformation
                );

    if (NT_SUCCESS(Status)) {
        ASSERT(IoStatus.Status == Status);
    } else {
        
        //
        // set debugging info
        //
        CmRegistryIODebug.Action = CmpIoFileSetSize;
        CmRegistryIODebug.Handle = FileHandle;
        CmRegistryIODebug.Status = Status;
#if DBG
        DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpFileSetSize:\tHandle=%08lx  OldLength = %08lx NewLength=%08lx  \n", 
                                                        FileHandle, OldFileSize, FileSize);
#endif
        if( (Status == STATUS_DISK_FULL) && ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) ) {
            DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Disk is full while attempting to grow file %lx; will flush upon lock release\n",FileHandle);
            CmpFlushOnLockRelease = TRUE;;
        }
    }

    //
    // restore hard error popups mode
    //
    IoSetThreadHardErrorMode(oldFlag);
    

    //
    // purge
    //
    if( HiveWritesThroughCache(Hive,FileType) && (OldFileSize > FileSize)) {
        //
        // first we have to unmap any possible mapped views in the last 256K window
        // to avoid deadlock on CcWaitOnActiveCount inside CcPurgeCacheSection call below
        //
        ULONG   Offset = FileSize & (~(_256K - 1));
        //
        // we are not allowed to shrink in shared mode.
        //
	    ASSERT_HIVE_WRITER_LOCK_OWNED((PCMHIVE)Hive);

        while( Offset < OldFileSize ) {
            CmpUnmapCmViewSurroundingOffset((PCMHIVE)Hive,Offset);
            Offset += CM_VIEW_SIZE;
        }

        //
        // we need to take extra precaution here and unmap the very last view too
        //
        
        FileOffset.HighPart = 0;
        FileOffset.LowPart = FileSize;
        //
        // This is a shrink; Inform cache manager of the change of the size
        //
        CcPurgeCacheSection( ((PCMHIVE)Hive)->FileObject->SectionObjectPointer, (PLARGE_INTEGER)(((ULONG_PTR)(&FileOffset)) + 1), 
                            OldFileSize - FileSize, FALSE );

        //
        // Flush out this view to clear out the Cc dirty hints
        //
        CcFlushCache( ((PCMHIVE)Hive)->FileObject->SectionObjectPointer, (PLARGE_INTEGER)(((ULONG_PTR)(&FileOffset)) + 1),/*we are private writers*/
                            OldFileSize - FileSize,NULL);

    }
    
    return Status;
}
Exemplo n.º 25
0
BOOLEAN
W2kNtfsFlushMetaFile (
    IN PDEVICE_OBJECT		FSpyDeviceObject,
    IN PDEVICE_OBJECT		baseDeviceObject,
	IN ULONG				BufferLen,
	IN PCHAR				Buffer
	)
{
	PVCB						vcb;
	PVOLUME_DEVICE_OBJECT		volDo;
	PFILESPY_DEVICE_EXTENSION	devExt;
	NTSTATUS					status;	
	BOOLEAN						found;
	PFILE_RECORD_SEGMENT_HEADER fileRecord;
	PATTRIBUTE_RECORD_HEADER	attribute;
	LARGE_INTEGER				validDataLength;
	LARGE_INTEGER				mftOffset;
	BOOLEAN						result1 = 0, result2 = 0, result3 = 0;
	FILE_REFERENCE				fileReference;
	PATTRIBUTE_RECORD_HEADER	mftBitmapAttribute;
				


//	baseDeviceObject 
//		= ((PFILESPY_DEVICE_EXTENSION) (FSpyDeviceObject->DeviceExtension))->BaseVolumeDeviceObject;
	volDo = (PVOLUME_DEVICE_OBJECT)baseDeviceObject;
	vcb = &volDo->Vcb;

	devExt = FSpyDeviceObject->DeviceExtension;
	SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
					("FSpyDeviceObject = %p, devExt = %p\n", FSpyDeviceObject, devExt));
	ASSERT(Buffer);

	if(Buffer == NULL)
		return FALSE;

	status = W2KNtfsPerformVerifyDiskRead (
				devExt->DiskDeviceObject,
				(PVOID)Buffer,
				(LONGLONG)LlBytesFromClusters(vcb, vcb->MftStartLcn),
				(LONG)BufferLen
				);

	if(!NT_SUCCESS(status)) {
		DbgPrint("read fail\n");
		return FALSE;
	}
					
	if(vcb->BitmapScb && vcb->BitmapScb->FileObject)
		result1 = CcPurgeCacheSection (
					&vcb->BitmapScb->NonpagedScb->SegmentObject,
					NULL,
					0,
					FALSE
					);
					
	if(vcb->MftBitmapScb && vcb->MftBitmapScb->FileObject)
		result2 = CcPurgeCacheSection (
					&vcb->MftBitmapScb->NonpagedScb->SegmentObject,
					NULL,
					0,
					FALSE
					);

	/* 0 - 3 can' be purged */
	NtfsSetSegmentNumber(&fileReference, 0, 4);
	mftOffset.QuadPart = NtfsFullSegmentNumber( &fileReference );
	mftOffset.QuadPart = LlBytesFromFileRecords( vcb, mftOffset.QuadPart );
				
	if(vcb->MftScb && vcb->MftScb->FileObject)
		result3 = CcPurgeCacheSection (
					&vcb->MftScb->NonpagedScb->SegmentObject,
					&mftOffset,
					(ULONG)vcb->MftScb->Header.FileSize.QuadPart,
					FALSE
					);

	fileRecord = (PFILE_RECORD_SEGMENT_HEADER)Buffer;

//	if(devExt->MftLsn.QuadPart == fileRecord->Lsn.QuadPart)
//		goto DO_NOTHING;

//	devExt->MftLsn.QuadPart = fileRecord->Lsn.QuadPart;

	found = W2KNtfsFindAttribute(Buffer, $DATA, &attribute);
	if(!found) {
		DbgPrint("attribute fail\n");
		//ASSERT(FALSE);
		return FALSE;
	}

	if (NtfsIsAttributeResident( attribute )) {
		// DbgPrint("attrHeader1->Form.Resident.ValueLength = %x\n",
		//	attrHeader1->Form.Resident.ValueLength);
		ASSERT(FALSE);		// do more
		return FALSE;
	} else
	{
		validDataLength.QuadPart = attribute->Form.Nonresident.ValidDataLength;
	}

	if(vcb->MftScb && validDataLength.QuadPart != vcb->MftScb->Header.ValidDataLength.QuadPart)
	{
		VCN		vcn;
		BOOLEAN	result0 = 0, result1 = 0, result2 = 0, 
				result3 = 0, result4 = 0, result5 = 0;
						

		SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
			("attribute->Form.Nonresident.AllocatedLength = %x\n",
			attribute->Form.Nonresident.AllocatedLength / 512));
		SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
			("attribute->Form.Nonresident.ValidDataLength = %x\n",
			attribute->Form.Nonresident.ValidDataLength / 512));
		SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
			("attribute->Form.Nonresident.TotalAllocated = %x\n",
			attribute->Form.Nonresident.TotalAllocated / 512));					
//		SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
//			("devExt->MftLsn.QuadPart = %I64x, fileRecord->Lsn.QuadPart = %I64x\n",
//			devExt->MftLsn.QuadPart, fileRecord->Lsn.QuadPart));
	
		vcb->MftScb->Header.AllocationSize.QuadPart 
			= attribute->Form.Nonresident.AllocatedLength;
		vcb->MftScb->Header.ValidDataLength.QuadPart 
			= attribute->Form.Nonresident.ValidDataLength;
		vcb->MftScb->Header.FileSize.QuadPart
			= attribute->Form.Nonresident.FileSize;
			
		vcb->MftScb->TotalAllocated
			= vcb->MftScb->Header.AllocationSize.QuadPart;
						
		CcSetFileSizes( vcb->MftScb->FileObject,
			(PCC_FILE_SIZES)&vcb->MftScb->Header.AllocationSize
			);
											
		vcn = attribute->Form.Nonresident.LowestVcn;
		
		do {
			LCN			lcn;
			LONGLONG	clusterCount;
	
		
			W2KNtfsLookupAllocation (
				attribute,
				vcb->MftScb,
				vcn,
				&lcn,
				&clusterCount,
				NULL,
				NULL
				);
						
			vcn += clusterCount;
		} while(vcn < attribute->Form.Nonresident.HighestVcn);
	}

	found = W2KNtfsFindAttribute(Buffer, $BITMAP, &mftBitmapAttribute);
	if(!found) {
		DbgPrint("mftBitmapAttribute fail\n");
		ASSERT(FALSE);
		return FALSE;
	}

	if (NtfsIsAttributeResident( mftBitmapAttribute )) {
		// DbgPrint("attrHeader1->Form.Resident.ValueLength = %x\n",
		//	attrHeader1->Form.Resident.ValueLength);
		ASSERT(FALSE);		// do more
	} else
	{
		validDataLength.QuadPart = attribute->Form.Nonresident.ValidDataLength;
	}

	if(vcb->MftBitmapScb && validDataLength.QuadPart != vcb->MftBitmapScb->Header.ValidDataLength.QuadPart)
	{
		VCN		mftBitmapVcn;
		BOOLEAN	result0 = 0, result1 = 0, result2 = 0, 
				result3 = 0, result4 = 0, result5 = 0;
							

		vcb->MftBitmapScb->Header.AllocationSize.QuadPart 
			= mftBitmapAttribute->Form.Nonresident.AllocatedLength;
		vcb->MftBitmapScb->Header.ValidDataLength.QuadPart 
			= mftBitmapAttribute->Form.Nonresident.ValidDataLength;
		vcb->MftBitmapScb->Header.FileSize.QuadPart
			= mftBitmapAttribute->Form.Nonresident.FileSize;
		
		vcb->MftBitmapScb->TotalAllocated
			= vcb->MftBitmapScb->Header.AllocationSize.QuadPart;
						
		CcSetFileSizes( vcb->MftBitmapScb->FileObject,
			(PCC_FILE_SIZES)&vcb->MftBitmapScb->Header.AllocationSize
		);
					
		mftBitmapVcn = mftBitmapAttribute->Form.Nonresident.LowestVcn;
		do {
			LCN			mftBitmapLcn;
			LONGLONG	mftBitmapVcnClusterCount;
		
			
			W2KNtfsLookupAllocation (
				mftBitmapAttribute,
				vcb->MftBitmapScb,
				mftBitmapVcn,
				&mftBitmapLcn,
				&mftBitmapVcnClusterCount,
				NULL,
				NULL
				);
			
			mftBitmapVcn += mftBitmapVcnClusterCount;	
		} while(mftBitmapVcn < mftBitmapAttribute->Form.Nonresident.HighestVcn);
	}

	return TRUE;
}
Exemplo n.º 26
0
NTSTATUS
Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PEXT2_VCB           Vcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PEXT2_FCBVCB        FcbOrVcb = NULL;
    PFILE_OBJECT        FileObject = NULL;

    PDEVICE_OBJECT      DeviceObject = NULL;

    PIRP                Irp = NULL;
    PIO_STACK_LOCATION  IoStackLocation = NULL;

    ULONG               Length;
    LARGE_INTEGER       ByteOffset;

    BOOLEAN             PagingIo = FALSE;
    BOOLEAN             Nocache = FALSE;
    BOOLEAN             SynchronousIo = FALSE;
    BOOLEAN             MainResourceAcquired = FALSE;

    BOOLEAN             bDeferred = FALSE;

    PUCHAR              Buffer = NULL;
    PEXT2_EXTENT        Chain = NULL;
    EXT2_EXTENT         BlockArray;

    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
        ASSERT(FcbOrVcb);

        if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        Irp = IrpContext->Irp;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Write.Length;
        ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        DEBUG(DL_INF, ("Ext2WriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
                       ByteOffset.QuadPart, Length, PagingIo, Nocache));

        if (Length == 0) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (Nocache &&
                (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
                 Length & (SECTOR_SIZE - 1))) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            __leave;
        }

        if (ByteOffset.QuadPart >=
                Vcb->PartitionInformation.PartitionLength.QuadPart  ) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_END_OF_FILE;
            __leave;
        }

        if (!Nocache) {

            BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
            BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
            BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

            if ( !CcCanIWrite(
                        FileObject,
                        Length,
                        (bWait && bQueue),
                        bAgain ) ) {

                Status = Ext2LockUserBuffer(
                             IrpContext->Irp,
                             Length,
                             IoReadAccess);
                if (NT_SUCCESS(Status)) {
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
                    CcDeferWrite( FileObject,
                                  (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
                                  IrpContext,
                                  Irp,
                                  Length,
                                  bAgain );

                    bDeferred = TRUE;
                    Status = STATUS_PENDING;

                    __leave;
                }
            }
        }

        /*
         * User direct volume access
         */

        if (Ccb != NULL && !PagingIo) {

            if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {

                if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
                    Status = Ext2PurgeVolume( Vcb, TRUE);
                }

                SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
            }

            if (!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) {
                if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
                    Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
                }
            }

        } else if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL))  {

            ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
            MainResourceAcquired = TRUE;

            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResourceLite(&Vcb->PagingIoResource);

            CcFlushCache( &(Vcb->SectionObject),
                          &ByteOffset,
                          Length,
                          &(Irp->IoStatus));

            if (!NT_SUCCESS(Irp->IoStatus.Status))  {
                Status = Irp->IoStatus.Status;
                __leave;
            }

            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResourceLite(&Vcb->PagingIoResource);

            CcPurgeCacheSection( &(Vcb->SectionObject),
                                 (PLARGE_INTEGER)&(ByteOffset),
                                 Length,
                                 FALSE );

            ExReleaseResourceLite(&Vcb->MainResource);
            MainResourceAcquired = FALSE;
        }

        if ( (ByteOffset.QuadPart + Length) > Vcb->Header.FileSize.QuadPart) {
            Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
        }

        if (!Nocache) {

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {

                CcPrepareMdlWrite (
                    Vcb->Volume,
                    &ByteOffset,
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    DbgBreak();

                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

                if (!CcCopyWrite( Vcb->Volume,
                                  (PLARGE_INTEGER)(&ByteOffset),
                                  Length,
                                  TRUE,
                                  Buffer )) {
                    Status = STATUS_PENDING;
                    __leave;
                }

                Status = Irp->IoStatus.Status;
                Ext2AddVcbExtent(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
            }

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
            }

        } else if (PagingIo) {

            LONGLONG            DirtyStart;
            LONGLONG            DirtyLba;
            LONGLONG            DirtyLength;
            LONGLONG            RemainLength;

            PEXT2_EXTENT        Extent = NULL;
            PEXT2_EXTENT        List = NULL;

            Length &= ~((ULONG)SECTOR_SIZE - 1);

            Status = Ext2LockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            DirtyLba = ByteOffset.QuadPart;
            RemainLength = (LONGLONG) Length;

            ASSERT(Length >= SECTOR_SIZE);

            while (RemainLength > 0) {

                DirtyStart = DirtyLba;
                ASSERT(DirtyStart >= ByteOffset.QuadPart);
                ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);

                if (Ext2LookupVcbExtent(Vcb, DirtyStart, &DirtyLba, &DirtyLength)) {

                    if (DirtyLba == -1) {

                        DirtyLba = DirtyStart + DirtyLength;
                        if (ByteOffset.QuadPart + Length > DirtyLba) {
                            RemainLength = ByteOffset.QuadPart + Length - DirtyLba;
                            ASSERT(DirtyStart >= ByteOffset.QuadPart);
                            ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
                        } else {
                            RemainLength = 0;
                        }
                        continue;
                    }

                    ASSERT(DirtyLba <= DirtyStart);
                    Extent = Ext2AllocateExtent();

                    if (!Extent) {
                        DEBUG(DL_ERR, ( "Ex2WriteVolume: failed to allocate Extent\n"));
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        __leave;
                    }

                    Extent->Irp = NULL;
                    Extent->Lba = DirtyLba;
                    Extent->Offset = (ULONG)( DirtyStart + Length -
                                              RemainLength - DirtyLba );
                    ASSERT(Extent->Offset <= Length);

                    if (DirtyLba + DirtyLength >= DirtyStart + RemainLength) {
                        Extent->Length = (ULONG)( DirtyLba +
                                                  RemainLength -
                                                  DirtyStart );
                        ASSERT(Extent->Length <= Length);
                        RemainLength = 0;
                    } else {
                        Extent->Length = (ULONG)(DirtyLength + DirtyLba - DirtyStart);
                        RemainLength =  (DirtyStart + RemainLength) -
                                        (DirtyLba + DirtyLength);
                        ASSERT(RemainLength <= (LONGLONG)Length);
                        ASSERT(Extent->Length <= Length);
                    }

                    ASSERT(Extent->Length >= SECTOR_SIZE);
                    DirtyLba = DirtyStart + DirtyLength;

                    if (List) {
                        List->Next = Extent;
                        List = Extent;
                    } else {
                        Chain = List = Extent;
                    }

                } else {

                    if (RemainLength > SECTOR_SIZE) {
                        DirtyLba = DirtyStart + SECTOR_SIZE;
                        RemainLength -= SECTOR_SIZE;
                    } else {
                        RemainLength = 0;
                    }
                }
            }

            if (Chain) {
                Status = Ext2ReadWriteBlocks(IrpContext,
                                             Vcb,
                                             Chain,
                                             Length );
                Irp = IrpContext->Irp;

                if (NT_SUCCESS(Status)) {
                    for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
                        Ext2RemoveVcbExtent(Vcb, Extent->Lba, Extent->Length);
                    }
                }

                if (!Irp) {
                    __leave;
                }

            } else {

                Irp->IoStatus.Information = Length;
                Status = STATUS_SUCCESS;
                __leave;
            }

        } else {

            Length &= ~((ULONG)SECTOR_SIZE - 1);

            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         Length,
                         IoWriteAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            BlockArray.Irp = NULL;
            BlockArray.Lba = ByteOffset.QuadPart;
            BlockArray.Offset = 0;
            BlockArray.Length = Length;
            BlockArray.Next = NULL;

            Status = Ext2ReadWriteBlocks(IrpContext,
                                         Vcb,
                                         &BlockArray,
                                         Length );

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
            }

            Irp = IrpContext->Irp;
            if (!Irp) {
                __leave;
            }
        }

    } __finally {

        if (MainResourceAcquired) {
            ExReleaseResourceLite(&Vcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {

            if (Irp) {

                if (Status == STATUS_PENDING) {

                    if (!bDeferred) {
                        Status = Ext2LockUserBuffer(
                                     IrpContext->Irp,
                                     Length,
                                     IoReadAccess );

                        if (NT_SUCCESS(Status)) {
                            Status = Ext2QueueRequest(IrpContext);
                        } else {
                            Ext2CompleteIrpContext(IrpContext, Status);
                        }
                    }

                } else {

                    if (NT_SUCCESS(Status)) {

                        if (SynchronousIo && !PagingIo) {
                            FileObject->CurrentByteOffset.QuadPart =
                                ByteOffset.QuadPart + Irp->IoStatus.Information;
                        }

                        if (!PagingIo) {
                            SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                        }
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);
                }

            } else {

                Ext2FreeIrpContext(IrpContext);
            }
        }

        if (Chain) {
            Ext2DestroyExtentChain(Chain);
        }
    }

    return Status;
}
Exemplo n.º 27
0
NTSTATUS
FFSWriteVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb  = NULL;
	PFFS_CCB            Ccb = NULL;
	PFFS_FCBVCB         FcbOrVcb  = NULL;
	PFILE_OBJECT        FileObject  = NULL;

	PDEVICE_OBJECT      DeviceObject  = NULL;

	PIRP                Irp  = NULL;
	PIO_STACK_LOCATION  IoStackLocation  = NULL;

	ULONG               Length;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer = NULL;

	__try
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		FileObject = IrpContext->FileObject;

		FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;

		ASSERT(FcbOrVcb);

		if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		// For the case of "Direct Access Storage Device", we
		// need flush/purge the cache

		if (Ccb != NULL)
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			Status = FFSPurgeVolume(Vcb, TRUE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;

			if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO))
			{
				if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart)
				{
					Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
				}
			}

			{
				FFS_BDL BlockArray;

				if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
						(Length & (SECTOR_SIZE - 1)))
				{
					Status = STATUS_INVALID_PARAMETER;
					__leave;
				}

				Status = FFSLockUserBuffer(
							IrpContext->Irp,
							Length,
							IoReadAccess);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}

				BlockArray.Irp = NULL;
				BlockArray.Lba = ByteOffset.QuadPart;;
				BlockArray.Offset = 0;
				BlockArray.Length = Length;

				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							&BlockArray,
							Length,
							1,
							FALSE);
				Irp = IrpContext->Irp;

				__leave;
			}
		}                    

		if (Nocache &&
				(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
				 Length & (SECTOR_SIZE - 1)))
		{
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
		{
			ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
			Status = STATUS_PENDING;
			__leave;
		}

		if (ByteOffset.QuadPart >=
				Vcb->PartitionInformation.PartitionLength.QuadPart)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_END_OF_FILE;
			__leave;
		}

#if FALSE

		if (!Nocache)
		{
			BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
			BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
			BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

			if (!CcCanIWrite(
						FileObject,
						Length,
						(bWait && bQueue),
						bAgain))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;

				__leave;
			}
		}

#endif

		if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcFlushCache(&(Vcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
				Status = Irp->IoStatus.Status;
				__leave;
			}

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcPurgeCacheSection(&(Vcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Vcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource);

			FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/

			if (Ccb)
			{
				if (!ExAcquireResourceSharedLite(
							&Vcb->PagingIoResource,
							IrpContext->IsSynchronous))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				PagingIoResourceAcquired = TRUE;
			}
		}

		if (!Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart
			)
			{
				Length = (ULONG) (
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{

				CcPrepareMdlWrite(
						Vcb->StreamObj,
						&ByteOffset,
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();

					Status = STATUS_INVALID_USER_BUFFER;
					__leave;
				}

				if (!CcCopyWrite(Vcb->StreamObj,
							(PLARGE_INTEGER)(&ByteOffset),
							Length,
							TRUE,
							Buffer))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				Status = Irp->IoStatus.Status;
				FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
			}

			if (NT_SUCCESS(Status))
			{
				Irp->IoStatus.Information = Length;
			}
		}
		else
		{
			PFFS_BDL            ffs_bdl = NULL;
			ULONG               Blocks = 0;

			LONGLONG            DirtyStart;
			LONGLONG            DirtyLba;
			LONGLONG            DirtyLength;
			LONGLONG            RemainLength;

			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart)
			{
				Length = (ULONG)(
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			Status = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoReadAccess);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

			ffs_bdl = ExAllocatePool(PagedPool, 
					(Length / Vcb->BlockSize) *
					sizeof(FFS_BDL));

			if (!ffs_bdl)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}

			DirtyLba = ByteOffset.QuadPart;
			RemainLength = (LONGLONG)Length;

			while (RemainLength > 0)
			{
				DirtyStart = DirtyLba;

				if (FFSLookupMcbEntry(Vcb, 
							DirtyStart,
							&DirtyLba,
							&DirtyLength,
							(PLONGLONG)NULL,
							(PLONGLONG)NULL,
							(PULONG)NULL))
				{

					if (DirtyLba == -1)
					{
						DirtyLba = DirtyStart + DirtyLength;

						RemainLength = ByteOffset.QuadPart + 
							(LONGLONG)Length -
							DirtyLba;
						continue;
					}

					ffs_bdl[Blocks].Irp = NULL;
					ffs_bdl[Blocks].Lba = DirtyLba;
					ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length +
							DirtyStart -
							RemainLength - 
							DirtyLba);

					if (DirtyLba + DirtyLength > DirtyStart + RemainLength)
					{
						ffs_bdl[Blocks].Length = (ULONG)(DirtyStart +
								RemainLength -
								DirtyLba);
						RemainLength = 0;
					}
					else
					{
						ffs_bdl[Blocks].Length = (ULONG)DirtyLength;
						RemainLength =  (DirtyStart + RemainLength) -
							(DirtyLba + DirtyLength);
					}

					DirtyLba = DirtyStart + DirtyLength;
					Blocks++;
				}
				else
				{
					if (Blocks == 0)
					{
						if (ffs_bdl)
							ExFreePool(ffs_bdl);

						//
						// Lookup fails at the first time, ie. 
						// no dirty blocks in the run
						//

						FFSBreakPoint();

						if (RemainLength == (LONGLONG)Length)
							Status = STATUS_SUCCESS;
						else
							Status = STATUS_UNSUCCESSFUL;

						__leave;
					}
					else
					{
						break;
					}
				}
			}

			if (Blocks > 0)
			{
				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							ffs_bdl,
							Length,
							Blocks,
							FALSE);
				Irp = IrpContext->Irp;

				if (NT_SUCCESS(Status))
				{
					ULONG   i;

					for (i = 0; i < Blocks; i++)
					{
						FFSRemoveMcbEntry(Vcb,
								ffs_bdl[i].Lba,
								ffs_bdl[i].Length);
					}
				}

				if (ffs_bdl)
					ExFreePool(ffs_bdl);

				if (!Irp)
					__leave;

			}
			else
			{
				if (ffs_bdl)
					ExFreePool(ffs_bdl);

				Irp->IoStatus.Information = Length;

				Status = STATUS_SUCCESS;
				__leave;
			}
		}
	}

	__finally
	{
		if (PagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

		if (MainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING)
				{
					if(!bDeferred)
					{
						Status = FFSLockUserBuffer(
								IrpContext->Irp,
								Length,
								IoReadAccess);

						if (NT_SUCCESS(Status))
						{
							Status = FFSQueueRequest(IrpContext);
						}
						else
						{
							FFSCompleteIrpContext(IrpContext, Status);
						}
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;
}
Exemplo n.º 28
0
NTSTATUS
Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
{
    PEXT2_VCB           Vcb = NULL;
    PEXT2_FCB           Fcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PFILE_OBJECT        FileObject = NULL;

    PDEVICE_OBJECT      DeviceObject = NULL;

    PIRP                Irp = NULL;
    PIO_STACK_LOCATION  IoStackLocation = NULL;
    PUCHAR              Buffer = NULL;

    LARGE_INTEGER       ByteOffset;
    ULONG               ReturnedLength = 0;
    ULONG               Length;

    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    BOOLEAN             OpPostIrp = FALSE;
    BOOLEAN             PagingIo = FALSE;
    BOOLEAN             Nocache = FALSE;
    BOOLEAN             SynchronousIo = FALSE;

    BOOLEAN             RecursiveWriteThrough = FALSE;
    BOOLEAN             MainResourceAcquired = FALSE;
    BOOLEAN             PagingIoResourceAcquired = FALSE;

    BOOLEAN             bDeferred = FALSE;
    BOOLEAN             UpdateFileValidSize = FALSE;
    BOOLEAN             FileSizesChanged = FALSE;
    BOOLEAN             rc;


    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        ASSERT(Fcb);
        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        Irp = IrpContext->Irp;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Write.Length;
        ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n",
                       &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));

        if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        if (IsFileDeleted(Fcb->Mcb) ||
            (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) {
            Status = STATUS_FILE_DELETED;
            __leave;
        }

        if (Length == 0) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
            ByteOffset.HighPart == -1) {
            ByteOffset = FileObject->CurrentByteOffset;
        } else if (IsWritingToEof(ByteOffset)) {
            ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
        }

        if (Nocache && !PagingIo &&
            ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
               (Length & (SECTOR_SIZE - 1))) ) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            __leave;
        }

        if (!Nocache) {

            BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
            BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
            BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

            if ( !CcCanIWrite(
                        FileObject,
                        Length,
                        (bWait && bQueue),
                        bAgain ) ) {

                Status = Ext2LockUserBuffer(
                             IrpContext->Irp,
                             Length,
                             IoReadAccess);

                if (NT_SUCCESS(Status)) {
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
                    CcDeferWrite( FileObject,
                                  (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
                                  IrpContext,
                                  Irp,
                                  Length,
                                  bAgain );
                    bDeferred = TRUE;
                    Status = STATUS_PENDING;
                    __leave;
                }
            }
        }

        if (IsDirectory(Fcb) && !PagingIo) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) {

            PIRP TopIrp;

            TopIrp = IoGetTopLevelIrp();

            if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG &&
                    NodeType(TopIrp) == IO_TYPE_IRP) {

                PIO_STACK_LOCATION IrpStack;

                IrpStack = IoGetCurrentIrpStackLocation(TopIrp);

                if ((IrpStack->MajorFunction == IRP_MJ_WRITE) &&
                    (IrpStack->FileObject->FsContext == FileObject->FsContext) &&
                    !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) {

                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
                    RecursiveWriteThrough = TRUE;
                }
            }
        }

        if (PagingIo) {

            if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) {
                Status = STATUS_PENDING;
                __leave;
            }
            PagingIoResourceAcquired = TRUE;

            if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {

                if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {

                    Status = STATUS_SUCCESS;
                    Irp->IoStatus.Information = 0;
                    __leave;

                } else {

                    ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
                    if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart)
                        Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
                }

            } else {

                ReturnedLength = Length;
            }

        } else {

            if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) {
                Status = STATUS_ACCESS_DENIED;
                __leave;
            }

            if (IsDirectory(Fcb)) {
                __leave;
            }

            if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) {
                Status = STATUS_PENDING;
                __leave;
            }
            MainResourceAcquired = TRUE;

            //
            //  Do flushing for such cases
            //
            if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL)  {

                ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
                ExReleaseResourceLite(&Fcb->PagingIoResource);

                CcFlushCache( &(Fcb->SectionObject),
                              &ByteOffset,
                              CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
                              &(Irp->IoStatus));
                ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);

                if (!NT_SUCCESS(Irp->IoStatus.Status)) {
                    Status = Irp->IoStatus.Status;
                    __leave;
                }

                ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
                ExReleaseResourceLite(&Fcb->PagingIoResource);

                CcPurgeCacheSection( &(Fcb->SectionObject),
                                     &(ByteOffset),
                                     CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
                                     FALSE );
            }

            if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }

            if (Ccb != NULL) {

                Status = FsRtlCheckOplock( &Fcb->Oplock,
                                           Irp,
                                           IrpContext,
                                           Ext2OplockComplete,
                                           Ext2LockIrp );

                if (Status != STATUS_SUCCESS) {
                    OpPostIrp = TRUE;
                    __leave;
                }

                //
                //  Set the flag indicating if Fast I/O is possible
                //

                Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
            }

            //
            //  Extend the inode size when the i/o is beyond the file end ?
            //

            if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {

                LARGE_INTEGER AllocationSize, Last;

                if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                PagingIoResourceAcquired = TRUE;

                /* let this irp wait, since it has to be synchronous */
                SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

                Last.QuadPart = Fcb->Header.AllocationSize.QuadPart;
                AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
                AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
                                          (ULONGLONG)AllocationSize.QuadPart,
                                          (ULONGLONG)BLOCK_SIZE);

                /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks
                   for indirect files, otherwise we might get gabage data in holes */
                IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION;
                Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize);
                IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
                if (AllocationSize.QuadPart > Last.QuadPart) {
                    Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
                    SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE);
                }
                ExReleaseResourceLite(&Fcb->PagingIoResource);
                PagingIoResourceAcquired = FALSE;

                if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
                    if (NT_SUCCESS(Status)) {
                        DbgBreak();
                        Status = STATUS_UNSUCCESSFUL;
                    }
                    __leave;
                }

                if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) {
                    Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
                }

                Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length;
                Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);

                if (CcIsFileCached(FileObject)) {
                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                }

                FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
                FileSizesChanged = TRUE;

                if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
                        !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
                    SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
                    Ext2SaveSuper(IrpContext, Vcb);
                }

                DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n",
                              &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
                              Fcb->Header.AllocationSize.QuadPart));
            }

            ReturnedLength = Length;
        }

        if (!Nocache) {

            if (FileObject->PrivateCacheMap == NULL) {
                CcInitializeCacheMap(
                    FileObject,
                    (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
                    FALSE,
                    &Ext2Global->CacheManagerCallbacks,
                    Fcb );

                CcSetReadAheadGranularity(
                    FileObject,
                    READ_AHEAD_GRANULARITY );
            }

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {

                CcPrepareMdlWrite(
                    FileObject,
                    &ByteOffset,
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    DbgBreak();
                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

                if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {

                    /* let this irp wait, since it has to be synchronous */
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

                    rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
                                      &Fcb->Header.ValidDataLength, &ByteOffset);
                    if (!rc) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }

                if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) {
                    if (Ext2CanIWait() || 
                        !CcCopyWrite(FileObject,  &ByteOffset, Length, TRUE, Buffer)) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }

                if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {

                    if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
                        Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
                    } else {
                        if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
                            Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
                    }

                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    FileSizesChanged = TRUE;
                }

                Status = STATUS_SUCCESS;
            }

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
                if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
                    DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n"));
                    Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject);
                }
            }

        } else {

            if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
                if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {

                    /* let this irp wait, since it has to be synchronous */
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
                    rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
                                      &Fcb->Header.ValidDataLength,
                                      &ByteOffset);
                    if (!rc) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }
            }

            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         Length,
                         IoReadAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = ReturnedLength;

            Status = Ext2WriteInode(
                         IrpContext,
                         Vcb,
                         Fcb->Mcb,
                         (ULONGLONG)(ByteOffset.QuadPart),
                         NULL,
                         ReturnedLength,
                         TRUE,
                         &Length
                     );

            Irp = IrpContext->Irp;

            if (NT_SUCCESS(Status) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {

                if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {

                    FileSizesChanged = TRUE;

                    if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
                        if (!PagingIo)
                            Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + Length;
                        Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
                    } else {
                        if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
                            Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
                    }

                    if (!PagingIo && CcIsFileCached(FileObject)) {
                        CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    }

                    DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n",
                                  &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
                                   Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length));
                }
            }
        }

        if (FileSizesChanged) {
            FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
            Ext2NotifyReportChange( IrpContext,  Vcb, Fcb->Mcb,
                                    FILE_NOTIFY_CHANGE_SIZE,
                                    FILE_ACTION_MODIFIED );
        }

    } __finally {

        /*
         *  in case we got excpetions, we need revert MajorFunction
         *  back to IRP_MJ_WRITE. The reason we do this, is to tell
         *  Ext2ExpandFile to allocate unwritten extent or don't add
         *  new blocks for indirect files.
         */
        if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION)
            IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;

        if (Irp) {
            if (PagingIoResourceAcquired) {
                ExReleaseResourceLite(&Fcb->PagingIoResource);
            }

            if (MainResourceAcquired) {
                ExReleaseResourceLite(&Fcb->MainResource);
            }
        }

        if (!OpPostIrp && !IrpContext->ExceptionInProgress) {

            if (Irp) {

                if (Status == STATUS_PENDING ||
                        Status == STATUS_CANT_WAIT ) {

                    if (!bDeferred) {
                        Status = Ext2QueueRequest(IrpContext);
                    }

                } else {

                    if (NT_SUCCESS(Status) && !PagingIo) {

                        if (SynchronousIo) {
                            FileObject->CurrentByteOffset.QuadPart =
                                ByteOffset.QuadPart + Irp->IoStatus.Information;
                        }

                        SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                        SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);
                }
            } else {
                Ext2FreeIrpContext(IrpContext);
            }
        }
    }

    DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d "
                  "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n",
                  &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength,
                  Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart,
                  Fcb->Inode->i_size, Status));

    return Status;
}
Exemplo n.º 29
0
NTSTATUS
FFSWriteFile(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb  = NULL;
	PFFS_FCB            Fcb  = NULL;
	PFFS_CCB            Ccb =  NULL;
	PFILE_OBJECT        FileObject  = NULL;
	PFILE_OBJECT        CacheObject;

	PDEVICE_OBJECT      DeviceObject  = NULL;

	PIRP                Irp  = NULL;
	PIO_STACK_LOCATION  IoStackLocation  = NULL;

	ULONG               Length;
	ULONG               ReturnedLength = 0;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bNeedExtending = FALSE;
	BOOLEAN             bAppendFile = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer = NULL;

	__try
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb);

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		/*
		if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
		{
			Status = STATUS_FILE_DELETED;
			__leave;
		}

		if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
		{
			Status = STATUS_DELETE_PENDING;
			__leave;
		}
		*/

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		if (Nocache &&
				(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
				 Length & (SECTOR_SIZE - 1)))
		{
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
		{
			ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
			Status = STATUS_PENDING;
			__leave;
		}

#if FALSE
		if (!Nocache)
		{
			BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
			BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
			BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

			if (!CcCanIWrite(
						FileObject,
						Length,
						(bWait && bQueue),
						bAgain))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;
				__leave;
			}
		}

#endif

		if (IsEndOfFile(ByteOffset))
		{
			bAppendFile = TRUE;
			ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
		}

		if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		//
		//  Do flushing for such cases
		//
		if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Fcb->MainResource, 
					IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));

			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
			ExReleaseResource(&Fcb->PagingIoResource);

			CcFlushCache(&(Fcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));
			ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
				Status = Irp->IoStatus.Status;
				__leave;
			}

			ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
			ExReleaseResource(&Fcb->PagingIoResource);

			CcPurgeCacheSection(&(Fcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Fcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);

			FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
			Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/
			if (!ExAcquireResourceSharedLite(
						&Fcb->PagingIoResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			PagingIoResourceAcquired = TRUE;
		}

		if (!PagingIo)
		{
			if (!FsRtlCheckLockForWriteAccess(
						&Fcb->FileLockAnchor,
						Irp))
			{
				Status = STATUS_FILE_LOCK_CONFLICT;
				__leave;
			}
		}

		if (Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Fcb->Header.AllocationSize.QuadPart)
			{
				if (ByteOffset.QuadPart >= 
						Fcb->Header.AllocationSize.QuadPart)
				{
					Status = STATUS_SUCCESS;
					Irp->IoStatus.Information = 0;
					__leave;
				}
				else
				{
					if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart
								- ByteOffset.QuadPart))
					{
						Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart
								- ByteOffset.QuadPart);
					}
				}
			}
		}

		if (!Nocache)
		{
			if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
			{
				__leave;
			}

			if (FileObject->PrivateCacheMap == NULL)
			{
				CcInitializeCacheMap(
						FileObject,
						(PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
						FALSE,
						&FFSGlobal->CacheManagerCallbacks,
						Fcb);

				CcSetReadAheadGranularity(
						FileObject,
						READ_AHEAD_GRANULARITY);

				CcSetFileSizes(
						FileObject, 
						(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
			}

			CacheObject = FileObject;

			//
			//  Need extending the size of inode ?
			//
			if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) >
						(ULONG)(Fcb->Header.FileSize.QuadPart)))
			{

				LARGE_INTEGER   ExtendSize;
				LARGE_INTEGER   FileSize;

				bNeedExtending = TRUE;
				FileSize = Fcb->Header.FileSize;
				ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);

				if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
				{
					if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize))
					{
						Status = STATUS_INSUFFICIENT_RESOURCES;
						__leave;
					}
				}

				{
					Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
					Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart;
				}

				if (FileObject->PrivateCacheMap)
				{
					CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));

					if (ByteOffset.QuadPart > FileSize.QuadPart)
					{
						FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, 
								ByteOffset.QuadPart - FileSize.QuadPart);
					}

					if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart)
					{
						FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, 
								Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
					}
				}

				if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1))
				{
					Status = STATUS_SUCCESS;
				}

				FFSNotifyReportChange(
						IrpContext,
						Vcb,
						Fcb,
						FILE_NOTIFY_CHANGE_SIZE,
						FILE_ACTION_MODIFIED);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{
				CcPrepareMdlWrite(
						CacheObject,
						(&ByteOffset),
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();
					Status = STATUS_INVALID_USER_BUFFER;
					__leave;
				}

				if (!CcCopyWrite(
							CacheObject,
							(PLARGE_INTEGER)&ByteOffset,
							Length,
							IrpContext->IsSynchronous,
							Buffer))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				Status = Irp->IoStatus.Status;
			}

			if (NT_SUCCESS(Status))
			{
				Irp->IoStatus.Information = Length;

				if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
				{
					FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n"));
					FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject);
				}
			}
		}
		else
		{
			ReturnedLength = Length;

			Status = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoReadAccess);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

			Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = Length;

			Status = 
				FFSv1WriteInode(
						IrpContext,
						Vcb,
						Fcb->dinode1,
						(ULONGLONG)(ByteOffset.QuadPart),
						NULL,
						Length,
						TRUE,
						&ReturnedLength);

			Irp = IrpContext->Irp;

		}
	}

	__finally
	{
		if (PagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

		if (MainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING)
				{
					if (!bDeferred)
					{
						Status = FFSLockUserBuffer(
									IrpContext->Irp,
									Length,
									IoReadAccess);

						if (NT_SUCCESS(Status))
						{
							Status = FFSQueueRequest(IrpContext);
						}
						else
						{
							FFSCompleteIrpContext(IrpContext, Status);
						}
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
							SetFlag(Fcb->Flags, FCB_FILE_MODIFIED);
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;

}
Exemplo n.º 30
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdPurgeVolume (IN PRFSD_VCB Vcb,
                 IN BOOLEAN  FlushBeforePurge )
{
    PRFSD_FCB       Fcb;
    LIST_ENTRY      FcbList;
    PLIST_ENTRY     ListEntry;
    PFCB_LIST_ENTRY FcbListEntry;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
        (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
        IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
            FlushBeforePurge = FALSE;
        }

        FcbListEntry= NULL;
        InitializeListHead(&FcbList);

        for (ListEntry = Vcb->FcbList.Flink;
        ListEntry != &Vcb->FcbList;
        ListEntry = ListEntry->Flink  ) {

            Fcb = CONTAINING_RECORD(ListEntry, RFSD_FCB, Next);

            Fcb->ReferenceCount++;

            RfsdPrint((DBG_INFO, "RfsdPurgeVolume: %s refercount=%xh\n", Fcb->AnsiFileName.Buffer, Fcb->ReferenceCount));

            FcbListEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FCB_LIST_ENTRY), RFSD_POOL_TAG);

            if (FcbListEntry) {

                FcbListEntry->Fcb = Fcb;

                InsertTailList(&FcbList, &FcbListEntry->Next);
            } else {
                RfsdPrint((DBG_ERROR, "RfsdPurgeVolume: Error allocating FcbListEntry ...\n"));
            }
        }

        while (!IsListEmpty(&FcbList)) {

            ListEntry = RemoveHeadList(&FcbList);

            FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);

            Fcb = FcbListEntry->Fcb;

            if (ExAcquireResourceExclusiveLite(
                        &Fcb->MainResource,
                        TRUE )) {

                RfsdPurgeFile(Fcb, FlushBeforePurge);

                if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) {
                    RemoveEntryList(&Fcb->Next);
                    RfsdFreeFcb(Fcb);
                } else {
                    ExReleaseResourceForThreadLite(
                        &Fcb->MainResource,
                        ExGetCurrentResourceThread());
                }
            }

            ExFreePool(FcbListEntry);
        }

        if (FlushBeforePurge) {
            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResourceLite(&Vcb->PagingIoResource);

            CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL);
        }

        if (Vcb->SectionObject.ImageSectionObject) {
            MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
        }

        if (Vcb->SectionObject.DataSectionObject) {
            CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
        }

        RfsdPrint((DBG_INFO, "RfsdPurgeVolume: Volume flushed and purged.\n"));

    } _SEH2_FINALLY {
        // Nothing
    } _SEH2_END;

    return STATUS_SUCCESS;
}