Example #1
0
NTSTATUS
Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS                Status;

    PIRP                    Irp;
    PIO_STACK_LOCATION      IrpSp;

    PEXT2_VCB               Vcb;
    PLIST_ENTRY             ListEntry;

    BOOLEAN                 GlobalResourceAcquired = FALSE;

    __try {

        Status = STATUS_SUCCESS;

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

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

        if (!ExAcquireResourceExclusiveLite(
                    &Ext2Global->Resource,
                    IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
            Status = STATUS_PENDING;
            __leave;
        }

        GlobalResourceAcquired = TRUE;

        for (ListEntry = Ext2Global->VcbList.Flink;
                ListEntry != &(Ext2Global->VcbList);
                ListEntry = ListEntry->Flink ) {

            Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);

            if (ExAcquireResourceExclusiveLite(
                        &Vcb->MainResource,
                        TRUE )) {

                if (IsMounted(Vcb)) {

                    /* update mount count */
                    Vcb->SuperBlock->s_mnt_count++;
                    if (Vcb->SuperBlock->s_mnt_count >
                            Vcb->SuperBlock->s_max_mnt_count ) {
                        Vcb->SuperBlock->s_mnt_count =
                            Vcb->SuperBlock->s_max_mnt_count;
                    }
                    Ext2SaveSuper(IrpContext, Vcb);

                    /* flush dirty cache for all files */
                    Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
                    if (!NT_SUCCESS(Status)) {
                        DbgBreak();
                    }

                    /* flush volume stream's cache to disk */
                    Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);

                    if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
                        DbgBreak();
                    }

                    /* send shutdown request to underlying disk */
                    Ext2DiskShutDown(Vcb);
                }

                ExReleaseResourceLite(&Vcb->MainResource);
            }
        }

        /*
                IoUnregisterFileSystem(Ext2Global->DiskdevObject);
                IoUnregisterFileSystem(Ext2Global->CdromdevObject);
        */

    } __finally {

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

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

    return Status;
}
Example #2
0
NTSTATUS
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS                Status = STATUS_SUCCESS;

    PIRP                    Irp = NULL;
    PIO_STACK_LOCATION      IrpSp = NULL;

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

    PDEVICE_OBJECT          DeviceObject = NULL;

    BOOLEAN                 MainResourceAcquired = FALSE;

    __try {

        ASSERT(IrpContext);

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

        DeviceObject = IrpContext->DeviceObject;

        //
        // This request is not allowed on the main device object
        //
        if (IsExt2FsDevice(DeviceObject)) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

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

        ASSERT(IsMounted(Vcb));
        if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
                IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
            Status =  STATUS_SUCCESS;
            __leave;
        }

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

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

        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        if (Ccb == NULL) {
            Status =  STATUS_SUCCESS;
            __leave;
        }

        MainResourceAcquired =
            ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource,
                                           IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));

        ASSERT(MainResourceAcquired);
        DEBUG(DL_INF, ("Ext2Flush-pre:  total mcb records=%u\n",
                       FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));

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

            Ext2VerifyVcb(IrpContext, Vcb);
            Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
            if (NT_SUCCESS(Status)) {
                __leave;
            }

            Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);

            if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
                ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
            }

        } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {

            Fcb = (PEXT2_FCB)(FcbOrVcb);

            Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
            if (NT_SUCCESS(Status)) {
                if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
                    Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
                    ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }
            }
        }

        DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
                       FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));


    } __finally {

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

        if (!IrpContext->ExceptionInProgress) {

            if (Vcb && Irp && IrpSp && (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))) {

                // Call the disk driver to flush the physial media.
                NTSTATUS DriverStatus;
                PIO_STACK_LOCATION NextIrpSp;

                NextIrpSp = IoGetNextIrpStackLocation(Irp);

                *NextIrpSp = *IrpSp;

                IoSetCompletionRoutine( Irp,
                                        Ext2FlushCompletionRoutine,
                                        NULL,
                                        TRUE,
                                        TRUE,
                                        TRUE );

                DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);

                Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
                         Status : DriverStatus;

                IrpContext->Irp = Irp = NULL;
            }

            Ext2CompleteIrpContext(IrpContext, Status);
        }
    }

    return Status;
}
Example #3
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;
}