Exemple #1
0
INT
Ext2CheckJournal(
    PEXT2_VCB          Vcb,
    PULONG             jNo
)
{
    struct ext3_super_block* esb = NULL;

    /* check ext3 super block */
    esb = (struct ext3_super_block *)Vcb->SuperBlock;
    if (IsFlagOn(esb->s_feature_incompat,
                 EXT3_FEATURE_INCOMPAT_RECOVER)) {
        SetLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER);
    }

    /* must stop here if volume is read-only */
    if (IsVcbReadOnly(Vcb)) {
        goto errorout;
    }

    /* journal is external ? */
    if (esb->s_journal_inum == 0) {
        goto errorout;
    }

    /* oops: volume is corrupted */
    if (esb->s_journal_dev) {
        goto errorout;
    }

    /* return the journal inode number */
    *jNo = esb->s_journal_inum;

    return TRUE;

errorout:

    return FALSE;
}
Exemple #2
0
BOOLEAN
Ext2QueryRegistrySettings(IN PUNICODE_STRING  RegistryPath)
{
    UNICODE_STRING              ParameterPath;
    UNICODE_STRING              UniName;
    ANSI_STRING                 AnsiName;

    ULONG                       WritingSupport = 0;
    ULONG                       CheckingBitmap = 0;
    ULONG                       Ext3ForceWriting = 0;
    ULONG                       AutoMount = 0;

    WCHAR                       UniBuffer[CODEPAGE_MAXLEN];
    USHORT                      Buffer[HIDINGPAT_LEN];

    NTSTATUS                    Status;

    ParameterPath.Length = 0;
    ParameterPath.MaximumLength =
        RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR);
    ParameterPath.Buffer =
        (PWSTR) Ext2AllocatePool(
            PagedPool,
            ParameterPath.MaximumLength,
            'LG2E'
        );
    if (!ParameterPath.Buffer) {
        DbgBreak();
        DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n"));
        return FALSE;
    }

    RtlCopyUnicodeString(&ParameterPath, RegistryPath);
    RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY);

    /* enable automount of ext2/3/4 volumes */
    SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);

    /* query parameter settings from registry */
    Ext2QueryGlobalParameters(&ParameterPath);

    /* set global codepage settings */
    if (wcslen(&Ext2Global->Codepage.PageName[0])) {
        UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->Codepage.PageName[0]);
        UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR);
        UniName.Buffer = &Ext2Global->Codepage.PageName[0];
        AnsiName.MaximumLength = CODEPAGE_MAXLEN;
        AnsiName.Length = 0;
        AnsiName.Buffer = &Ext2Global->Codepage.AnsiName[0];
        Status = RtlUnicodeStringToAnsiString(
                     &AnsiName,
                     &UniName,
                     FALSE);
        if (!NT_SUCCESS(Status)) {
            DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName));
            RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
        }
    } else {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: CodePage not specified.\n"));
        RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
    }
    Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0;


    /* set global hidden prefix pattern */
    if (wcslen(&Ext2Global->wHidingPrefix[0])) {
        UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingPrefix[0]);
        UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
        UniName.Buffer = &Ext2Global->wHidingPrefix[0];
        AnsiName.MaximumLength = HIDINGPAT_LEN;
        AnsiName.Length = 0;
        AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]);

        Status = RtlUnicodeStringToAnsiString(
                     &AnsiName,
                     &UniName,
                     FALSE);
        if (NT_SUCCESS(Status)) {
            Ext2Global->bHidingPrefix = TRUE;
        } else {
            DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingPrefix ...\n"));
        }
    } else {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix not specified.\n"));
    }
    Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;


    /* set global hidden suffix pattern */
    if (wcslen(&Ext2Global->wHidingSuffix[0])) {
        UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingSuffix[0]);
        UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
        UniName.Buffer = &Ext2Global->wHidingSuffix[0];
        AnsiName.MaximumLength = HIDINGPAT_LEN;
        AnsiName.Length = 0;
        AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]);

        Status = RtlUnicodeStringToAnsiString(
                     &AnsiName,
                     &UniName,
                     FALSE);
        if (NT_SUCCESS(Status)) {
            Ext2Global->bHidingSuffix = TRUE;
        } else {
            DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingSuffix ...\n"));
        }
    } else {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix not specified.\n"));
    }
    Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;

    Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer;
    Ext2Global->RegistryPath.Length = 0;
    Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength;
    RtlCopyUnicodeString(&Ext2Global->RegistryPath, RegistryPath);
    RtlAppendUnicodeToString(&Ext2Global->RegistryPath, VOLUMES_KEY);

    return TRUE;
}
Exemple #3
0
NTSTATUS
Ext2RegistryQueryCallback(
    IN PWSTR ValueName,
    IN ULONG ValueType,
    IN PVOID ValueData,
    IN ULONG ValueLength,
    IN PVOID Context,
    IN PVOID EntryContext
    )
{
    ULONG  i = 0;
    BYTE   *s, *t;

    if (NULL == ValueName || NULL == ValueData)
        return STATUS_SUCCESS;

    if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(WRITING_SUPPORT) &&
        _wcsnicmp(ValueName, WRITING_SUPPORT, wcslen(WRITING_SUPPORT)) == 0) {

        if (ValueData && ValueLength == sizeof(DWORD)) {
            if (*((PULONG)ValueData)) {
                SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
            } else {
                ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
            }
        }
    } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(CHECKING_BITMAP) &&
        _wcsnicmp(ValueName, CHECKING_BITMAP, wcslen(CHECKING_BITMAP)) == 0) {

        if (ValueData && ValueLength == sizeof(DWORD)) {
            if (*((PULONG)ValueData)) {
                SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
            } else {
                ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
            }
        }
    } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(EXT3_FORCEWRITING) &&
        _wcsnicmp(ValueName, EXT3_FORCEWRITING, wcslen(EXT3_FORCEWRITING)) == 0) {

        if (ValueData && ValueLength == sizeof(DWORD)) {
            if (*((PULONG)ValueData)) {
                SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
                SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
            } else {
                ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
            }
        }
    } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(AUTO_MOUNT) &&
        _wcsnicmp(ValueName, AUTO_MOUNT, wcslen(AUTO_MOUNT)) == 0) {

        if (ValueData && ValueLength == sizeof(DWORD)) {
            if (*((PULONG)ValueData)) {
                SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
            } else {
                ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
            }
        }
    } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(CODEPAGE_NAME) &&
        _wcsnicmp(ValueName, CODEPAGE_NAME, wcslen(CODEPAGE_NAME)) == 0) {

        if (ValueData && ValueLength <= sizeof(WCHAR) * CODEPAGE_MAXLEN) {
            RtlCopyMemory(&Ext2Global->Codepage.PageName[0],
                          ValueData, ValueLength);
        }
    } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_PREFIX) &&
        _wcsnicmp(ValueName, HIDING_PREFIX, wcslen(HIDING_PREFIX)) == 0) {

        if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) {
            RtlCopyMemory(&Ext2Global->wHidingPrefix[0],
                          ValueData, ValueLength);
        }
    } else  if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_SUFFIX) &&
        _wcsnicmp(ValueName, HIDING_SUFFIX, wcslen(HIDING_SUFFIX)) == 0) {

        if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) {
            RtlCopyMemory(&Ext2Global->wHidingSuffix[0],
                          ValueData, ValueLength);
        }
    }


    return STATUS_SUCCESS;
}
Exemple #4
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;
}
Exemple #5
0
BOOLEAN
Ext2QueryGlobalParameters( IN PUNICODE_STRING  RegistryPath)
{
    NTSTATUS                    Status;
    UNICODE_STRING              ParameterPath;
    RTL_QUERY_REGISTRY_TABLE    QueryTable[2];

    ULONG                       WritingSupport = 0;
    ULONG                       CheckingBitmap = 0;
    ULONG                       Ext3ForceWriting = 0;
    ULONG                       AutoMount = 0;

    UNICODE_STRING              UniName;
    ANSI_STRING                 AnsiName;

    WCHAR                       UniBuffer[CODEPAGE_MAXLEN];
    USHORT                      Buffer[HIDINGPAT_LEN];

    ParameterPath.Length = 0;

    ParameterPath.MaximumLength =
        RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR);

    ParameterPath.Buffer =
        (PWSTR) Ext2AllocatePool(
            PagedPool,
            ParameterPath.MaximumLength,
            'LG2E'
        );

    if (!ParameterPath.Buffer) {
        DbgBreak();
        DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n"));
        return FALSE;
    }

    RtlCopyUnicodeString(&ParameterPath, RegistryPath);
    RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY);

    /* querying value of WritingSupport */
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);

    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = WRITING_SUPPORT;
    QueryTable[0].EntryContext = &WritingSupport;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL        );

    DEBUG(DL_ERR, ( "Ext2QueryParameters: WritingSupport=%xh\n", WritingSupport));

    /* querying value of CheckingBitmap */
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = CHECKING_BITMAP;
    QueryTable[0].EntryContext = &CheckingBitmap;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL        );

    DEBUG(DL_ERR, ( "Ext2QueryParameters: CheckingBitmap=%xh\n", CheckingBitmap));

    /* querying value of Ext3ForceWriting */
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = EXT3_FORCEWRITING;
    QueryTable[0].EntryContext = &Ext3ForceWriting;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL        );

    DEBUG(DL_ERR, ( "Ext2QueryParameters: Ext3ForceWriting=%xh\n", Ext3ForceWriting));


    /* querying value of AutoMount */
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);

    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = AUTO_MOUNT;
    QueryTable[0].EntryContext = &AutoMount;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL        );

    SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
    if (NT_SUCCESS(Status) && AutoMount == 0) {
        ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
    }

    DEBUG(DL_ERR, ( "Ext2QueryParameters: AutoMount=%xh\n", AutoMount));

    /* querying codepage */
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = CODEPAGE_NAME;
    QueryTable[0].EntryContext = &(UniName);
    UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR);
    UniName.Length = 0;
    UniName.Buffer = (PWSTR)UniBuffer;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL        );

    if (NT_SUCCESS(Status)) {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: Ext2CodePage=%wZ\n", &UniName));
        AnsiName.MaximumLength = CODEPAGE_MAXLEN;
        AnsiName.Length = 0;
        AnsiName.Buffer = &(Ext2Global->Codepage.AnsiName[0]);

        Status = RtlUnicodeStringToAnsiString(
                     &AnsiName,
                     &UniName,
                     FALSE);

        if (!NT_SUCCESS(Status)) {
            DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName));
            RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
        }
    } else {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: CodePage not specified.\n"));
        RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
    }
    Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0;

    /* querying name hiding patterns: prefix*/
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = HIDING_PREFIX;
    QueryTable[0].EntryContext = &(UniName);
    UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
    UniName.Length = 0;
    UniName.Buffer = Buffer;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL        );

    if (NT_SUCCESS(Status)) {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix=%wZ\n", &UniName));
        AnsiName.MaximumLength =HIDINGPAT_LEN;
        AnsiName.Length = 0;
        AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]);

        Status = RtlUnicodeStringToAnsiString(
                     &AnsiName,
                     &UniName,
                     FALSE);
        if (NT_SUCCESS(Status)) {
            Ext2Global->bHidingPrefix = TRUE;
        } else {
            DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingPrefix ...\n"));
        }
    } else {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix not specified.\n"));
    }
    Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;

    /* querying name hiding patterns: suffix */
    RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = HIDING_SUFFIX;
    QueryTable[0].EntryContext = &(UniName);
    UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
    UniName.Length = 0;
    UniName.Buffer = Buffer;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 ParameterPath.Buffer,
                 &QueryTable[0],
                 NULL,
                 NULL
             );

    if (NT_SUCCESS(Status)) {

        DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix=%wZ\n", &UniName));
        AnsiName.MaximumLength = HIDINGPAT_LEN;
        AnsiName.Length = 0;
        AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]);

        Status = RtlUnicodeStringToAnsiString(
                     &AnsiName,
                     &UniName,
                     FALSE);
        if (NT_SUCCESS(Status)) {
            Ext2Global->bHidingSuffix = TRUE;
        } else {
            DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingSuffix ...\n"));
        }
    } else {
        DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix not specified.\n"));
    }
    Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;

    {
        if (WritingSupport) {
            SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
        } else {
            ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
        }

        if (CheckingBitmap) {
            SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
        } else {
            ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
        }

        if (Ext3ForceWriting) {
            DbgPrint("Ext2Fsd -- Warning: Ext3ForceWriting enabled !!!\n");

            SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
            SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
        } else {
            ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
        }
    }

    Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer;
    Ext2Global->RegistryPath.Length = 0;
    Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength;
    RtlCopyUnicodeString(&Ext2Global->RegistryPath, RegistryPath);
    RtlAppendUnicodeToString(&Ext2Global->RegistryPath, VOLUMES_KEY);

    return TRUE;
}
Exemple #6
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;
}
Exemple #7
0
NTSTATUS
Ext2ProcessVolumeProperty(
    IN  PEXT2_VCB              Vcb,
    IN  PEXT2_VOLUME_PROPERTY3 Property3,
    IN  ULONG Length
)
{
    struct nls_table * PageTable = NULL;
    PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3;
    PEXT2_VOLUME_PROPERTY  Property = (PVOID)Property3;
    NTSTATUS Status = STATUS_SUCCESS;
    BOOLEAN VcbResourceAcquired = FALSE;

    __try {

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

        if (Property->Command == APP_CMD_SET_PROPERTY ||
            Property->Command == APP_CMD_QUERY_PROPERTY) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }
        } else if (Property->Command == APP_CMD_SET_PROPERTY2 ||
                   Property->Command == APP_CMD_QUERY_PROPERTY2) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }
        } else if (Property->Command == APP_CMD_SET_PROPERTY3 ||
                   Property->Command == APP_CMD_QUERY_PROPERTY3) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }
        }

        switch (Property->Command) {

        case APP_CMD_SET_PROPERTY3:

            if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
                if (Property3->AutoMount)
                    SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
                else
                    ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
            }
            if (Property3->Flags2 & EXT2_VPROP3_USERIDS) {
                SetFlag(Vcb->Flags, VCB_USER_IDS);
                Vcb->uid = Property3->uid;
                Vcb->gid = Property3->gid;
                if (Property3->EIDS) {
                    Vcb->euid = Property3->euid;
                    Vcb->egid = Property3->egid;
                    SetFlag(Vcb->Flags, VCB_USER_EIDS);
                } else {
                    Vcb->euid = Vcb->egid = 0;
                    ClearFlag(Vcb->Flags, VCB_USER_EIDS);
                }
            } else {
                ClearFlag(Vcb->Flags, VCB_USER_IDS);
                ClearFlag(Vcb->Flags, VCB_USER_EIDS);
                Vcb->uid = Vcb->gid = 0;
                Vcb->euid = Vcb->egid = 0;
            }

        case APP_CMD_SET_PROPERTY2:

            RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN);
            if (Vcb->bHidingPrefix = Property2->bHidingPrefix) {
                RtlCopyMemory( Vcb->sHidingPrefix,
                               Property2->sHidingPrefix,
                               HIDINGPAT_LEN - 1);
            }

            RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN);
            if (Vcb->bHidingSuffix = Property2->bHidingSuffix) {
                RtlCopyMemory( Vcb->sHidingSuffix,
                               Property2->sHidingSuffix,
                               HIDINGPAT_LEN - 1);
            }
            Vcb->DrvLetter = Property2->DrvLetter;

        case APP_CMD_SET_PROPERTY:

            if (Property->bReadonly) {
                if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
                    Ext2FlushFiles(NULL, Vcb, FALSE);
                    Ext2FlushVolume(NULL, Vcb, FALSE);
                }
                SetLongFlag(Vcb->Flags, VCB_READ_ONLY);

            } else {

                if (Property->bExt3Writable) {
                    SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING);
                }

                if (!Vcb->IsExt3fs) {
                    ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                } else if (!Property->bExt3Writable) {
                    SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
                } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
                    ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                    Ext2RecoverJournal(NULL, Vcb);
                    if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
                        SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
                    } else {
                        ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                    }
                } else {
                    ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                }
            }

            PageTable = load_nls(Property->Codepage);
            memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
            Vcb->Codepage.PageTable = PageTable;
            if (Vcb->Codepage.PageTable) {
                Ext2InitializeLabel(Vcb, Vcb->SuperBlock);
            }

            break;

        case APP_CMD_QUERY_PROPERTY3:

            if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) {
                SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
                Property3->AutoMount = TRUE;
            } else {
                ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
                Property3->AutoMount = FALSE;
            }

            if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) {
                SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
                Property3->uid = Vcb->uid;
                Property3->gid = Vcb->gid;
                if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
                    Property3->EIDS = TRUE;
                    Property3->euid = Vcb->euid;
                    Property3->egid = Vcb->egid;
                } else {
                    Property3->EIDS = FALSE;
                }
            } else {
                ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
            }

        case APP_CMD_QUERY_PROPERTY2:

            RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16);
            Property2->DrvLetter = Vcb->DrvLetter;

            if (Property2->bHidingPrefix = Vcb->bHidingPrefix) {
                RtlCopyMemory( Property2->sHidingPrefix,
                               Vcb->sHidingPrefix,
                               HIDINGPAT_LEN);
            } else {
                RtlZeroMemory( Property2->sHidingPrefix,
                               HIDINGPAT_LEN);
            }

            if (Property2->bHidingSuffix = Vcb->bHidingSuffix) {
                RtlCopyMemory( Property2->sHidingSuffix,
                               Vcb->sHidingSuffix,
                               HIDINGPAT_LEN);
            } else {
                RtlZeroMemory( Property2->sHidingSuffix,
                               HIDINGPAT_LEN);
            }

        case APP_CMD_QUERY_PROPERTY:

            Property->bExt2 = TRUE;
            Property->bExt3 = Vcb->IsExt3fs;
            Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY);
            if (!Property->bReadonly && Vcb->IsExt3fs) {
                Property->bExt3Writable = TRUE;
            } else {
                Property->bExt3Writable = FALSE;
            }

            RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN);
            if (Vcb->Codepage.PageTable) {
                strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN);
            } else {
                strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN);
            }
            break;

        default:
            Status = STATUS_INVALID_PARAMETER;
            break;
        }

    } __finally {

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

    return Status;
}
Exemple #8
0
NTSTATUS
Ext2ProcessGlobalProperty(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PEXT2_VOLUME_PROPERTY3 Property3,
    IN  ULONG Length
)
{
    PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3;
    PEXT2_VOLUME_PROPERTY  Property = (PVOID)Property3;
    struct nls_table * PageTable = NULL;

    NTSTATUS        Status = STATUS_SUCCESS;
    BOOLEAN         GlobalDataResourceAcquired = FALSE;

    __try {

        if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        /* query Ext2Fsd's version and built date/time*/
        if (Property->Command == APP_CMD_QUERY_VERSION) {
            PEXT2_VOLUME_PROPERTY_VERSION PVPV =
                (PEXT2_VOLUME_PROPERTY_VERSION) Property;

            if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }

            RtlZeroMemory(&PVPV->Date[0],   0x20);
            RtlZeroMemory(&PVPV->Time[0],   0x20);
            RtlZeroMemory(&PVPV->Version[0],0x1C);
            strncpy(&PVPV->Version[0], gVersion, 0x1B);
            strncpy(&PVPV->Date[0], gDate, 0x1F);
            strncpy(&PVPV->Time[0], gTime, 0x1F);
            __leave;
        }

        /* must be property query/set commands */
        if (Property->Command == APP_CMD_SET_PROPERTY) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }
        } else if (Property->Command == APP_CMD_SET_PROPERTY2) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }
        } else if (Property->Command == APP_CMD_SET_PROPERTY3) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
                Status = STATUS_INVALID_PARAMETER;
                __leave;
            }
        } else {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE);
        GlobalDataResourceAcquired = TRUE;


        switch (Property->Command) {

            case APP_CMD_SET_PROPERTY3:

            if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
                if (Property3->AutoMount)
                    SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
                else
                    ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
            }

            case APP_CMD_SET_PROPERTY2:

            RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN);
            if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) {
                RtlCopyMemory( Ext2Global->sHidingPrefix,
                               Property2->sHidingPrefix,
                               HIDINGPAT_LEN - 1);
            }
            RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN);
            if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) {
                RtlCopyMemory( Ext2Global->sHidingSuffix,
                               Property2->sHidingSuffix,
                               HIDINGPAT_LEN - 1);
            }

            case APP_CMD_SET_PROPERTY:

            if (Property->bReadonly) {
                ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
                ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
            } else {
                SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
                if (Property->bExt3Writable) {
                    SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
                } else {
                    ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
                }
            }

            PageTable = load_nls(Property->Codepage);
            if (PageTable) {
                memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
                Ext2Global->Codepage.PageTable = PageTable;
            }

            break;

            default:
            break;
        }

    } __finally {

        if (GlobalDataResourceAcquired) {
            ExReleaseResourceLite(&Ext2Global->Resource);
        }
    }

    return Status;
}
Exemple #9
0
NTSTATUS
Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;
    BOOLEAN         GlobalDataResourceAcquired = 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_INVALID_DEVICE_REQUEST;
            __leave;
        }

        ExAcquireResourceExclusiveLite(
            &Ext2Global->Resource,
            TRUE );

        GlobalDataResourceAcquired = TRUE;

        if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) {
            DEBUG(DL_ERR, ( "Ext2PrepareUnload:  Already ready to unload.\n"));

            Status = STATUS_ACCESS_DENIED;

            __leave;
        }

        {
            PEXT2_VCB               Vcb;
            PLIST_ENTRY             ListEntry;

            ListEntry = Ext2Global->VcbList.Flink;

            while (ListEntry != &(Ext2Global->VcbList)) {

                Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
                ListEntry = ListEntry->Flink;

                if (Vcb && (!Vcb->ReferenceCount) &&
                        IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
                    Ext2RemoveVcb(Vcb);
                    Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);

                    Ext2DestroyVcb(Vcb);
                }
            }
        }

        if (!IsListEmpty(&(Ext2Global->VcbList))) {

            DEBUG(DL_ERR, ( "Ext2PrepareUnload:  Mounted volumes exists.\n"));

            Status = STATUS_ACCESS_DENIED;

            __leave;
        }

        IoUnregisterFileSystem(Ext2Global->DiskdevObject);
        IoUnregisterFileSystem(Ext2Global->CdromdevObject);
        Ext2Global->DriverObject->DriverUnload = DriverUnload;
        SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING);
        Status = STATUS_SUCCESS;

        DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n"));

    } __finally {

        if (GlobalDataResourceAcquired) {
            ExReleaseResourceLite(&Ext2Global->Resource);
        }

        if (!IrpContext->ExceptionInProgress) {
            Ext2CompleteIrpContext(IrpContext, Status);
        }
    }

    return Status;
}
Exemple #10
0
NTSTATUS
Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_SUCCESS;
    PEXT2_VCB       Vcb = NULL;
    PFILE_OBJECT    FileObject;
    PEXT2_FCB       Fcb = NULL;
    PEXT2_CCB       Ccb = NULL;
    BOOLEAN         VcbResourceAcquired = FALSE;
    BOOLEAN         FcbResourceAcquired = FALSE;
    BOOLEAN         bDeleteVcb = FALSE;
    BOOLEAN         bBeingClosed = FALSE;
    BOOLEAN         bSkipLeave = 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;
            Vcb = NULL;
            __leave;
        }

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

        if (!ExAcquireResourceExclusiveLite(
                    &Vcb->MainResource,
                    TRUE )) {
            DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
                           Vcb->OpenHandleCount, Vcb->ReferenceCount));

            Status = STATUS_PENDING;
            __leave;
        }
        VcbResourceAcquired = TRUE;

        bSkipLeave = TRUE;
        if (IsFlagOn(Vcb->Flags, VCB_BEING_CLOSED)) {
            bBeingClosed = TRUE;
        } else {
            SetLongFlag(Vcb->Flags, VCB_BEING_CLOSED);
            bBeingClosed = FALSE;
        }

        if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {

            FileObject = NULL;
            Fcb = IrpContext->Fcb;
            Ccb = IrpContext->Ccb;

        } else {

            FileObject = IrpContext->FileObject;
            Fcb = (PEXT2_FCB) FileObject->FsContext;
            if (!Fcb) {
                Status = STATUS_SUCCESS;
                __leave;
            }
            ASSERT(Fcb != NULL);
            Ccb = (PEXT2_CCB) FileObject->FsContext2;
        }

        DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n",
                        bBeingClosed, Vcb, Vcb->ReferenceCount));

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

            if (Ccb) {

                Ext2DerefXcb(&Vcb->ReferenceCount);
                Ext2FreeCcb(Vcb, Ccb);

                if (FileObject) {
                    FileObject->FsContext2 = Ccb = NULL;
                }
            }

            Status = STATUS_SUCCESS;
            __leave;
        }

        if ( Fcb->Identifier.Type != EXT2FCB ||
                Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
            __leave;
        }

        if (!ExAcquireResourceExclusiveLite(
                    &Fcb->MainResource,
                    TRUE )) {
            Status = STATUS_PENDING;
            __leave;
        }
        FcbResourceAcquired = TRUE;

        Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;

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

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

        if (IsFlagOn(Fcb->Flags, FCB_STATE_BUSY)) {
            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY);
            DEBUG(DL_WRN, ( "Ext2Close: busy bit set: %wZ\n", &Fcb->Mcb->FullName ));
            Status = STATUS_PENDING;
            __leave;
        }

        DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
                        Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));

        if (Ccb) {

            Ext2FreeCcb(Vcb, Ccb);

            if (FileObject) {
                FileObject->FsContext2 = Ccb = NULL;
            }
        }

        if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) {

            //
            // Remove Fcb from Vcb->FcbList ...
            //

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

            Ext2FreeFcb(Fcb);

            if (FileObject) {
                FileObject->FsContext = Fcb = NULL;
            }
        }

        Ext2DerefXcb(&Vcb->ReferenceCount);
        Status = STATUS_SUCCESS;

    } __finally {

        if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) {
            /* for Ext2Fsd driver open/close, Vcb is NULL */
            if ((!bBeingClosed) && (Vcb->ReferenceCount == 0) &&
                (!IsMounted(Vcb) || IsDispending(Vcb))) {
                bDeleteVcb = TRUE;
            }
        }

        if (bSkipLeave && !bBeingClosed) {
            ClearFlag(Vcb->Flags, VCB_BEING_CLOSED);
        }

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

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

        if (!IrpContext->ExceptionInProgress) {

            if (Status == STATUS_PENDING) {

                Ext2QueueCloseRequest(IrpContext);

            } else {

                Ext2CompleteIrpContext(IrpContext, Status);

                if (bDeleteVcb) {

                    PVPB Vpb = Vcb->Vpb;
                    DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n",
                                    Vcb, Vpb));

                    Ext2CheckDismount(IrpContext, Vcb, FALSE);
                }
            }
        }
    }

    return Status;
}