⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rawfs.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:

    /* Check what kind of request this is */
    switch (IoStackLocation->Parameters.FileSystemControl.FsControlCode)
    {
        /* Oplock requests */
        case FSCTL_REQUEST_OPLOCK_LEVEL_1:
        case FSCTL_REQUEST_OPLOCK_LEVEL_2:
        case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
        case FSCTL_OPLOCK_BREAK_NOTIFY:

            /* We don't handle them */
            Status = STATUS_NOT_IMPLEMENTED;
            break;

        /* Lock request */
        case FSCTL_LOCK_VOLUME:

            /* Make sure we're not locked, and that we're alone */
            if (!(Vcb->VcbState & 1) && (Vcb->OpenCount == 1))
            {
                /* Lock the VCB */
                Vcb->VcbState |= 1;
                Status = STATUS_SUCCESS;
            }
            else
            {
                /* Otherwise, we can't do this */
                Status = STATUS_ACCESS_DENIED;
            }
            break;

        /* Unlock request */
        case FSCTL_UNLOCK_VOLUME:

            /* Make sure we're locked */
            if (!(Vcb->VcbState & 1))
            {
                /* Let caller know we're not */
                Status = STATUS_NOT_LOCKED;
            }
            else
            {
                /* Unlock the VCB */
                Vcb->VcbState &= ~1;
                Status = STATUS_SUCCESS;
            }
            break;

        /* Dismount request */
        case FSCTL_DISMOUNT_VOLUME:

            /* Make sure we're locked */
            if (Vcb->VcbState & 1)
            {
                /* Do nothing, just return success */
                Status = STATUS_SUCCESS;
            }
            else
            {
                /* We can't dismount, device not locked */
                Status = STATUS_ACCESS_DENIED;
            }
            break;

        /* Unknown request */
        default:

            /* Fail */
            Status = STATUS_INVALID_PARAMETER;
            break;
    }

    /* Unlock device and return */
    KeReleaseMutex(&Vcb->Mutex, FALSE);
    return Status;
}

NTSTATUS
NTAPI
RawFileSystemControl(IN PVCB Vcb,
                     IN PIRP Irp,
                     IN PIO_STACK_LOCATION IoStackLocation)
{
    NTSTATUS Status;
    PAGED_CODE();

    /* Check the kinds of FSCTLs that we support */
    switch (IoStackLocation->MinorFunction)
    {
        /* User-mode request */
        case IRP_MN_USER_FS_REQUEST:

            /* Handle it */
            Status = RawUserFsCtrl(IoStackLocation, Vcb);
            break;

        /* Mount request */
        case IRP_MN_MOUNT_VOLUME:

            /* Mount the volume */
            Status = RawMountVolume(IoStackLocation);
            break;

        case IRP_MN_VERIFY_VOLUME:

            /* We don't do verifies */
            Status = STATUS_WRONG_VOLUME;
            Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;

            /* Check if we should delete the device */
            if (RawCheckForDismount(Vcb, FALSE))
            {
                /* Do it */
                IoDeleteDevice((PDEVICE_OBJECT)
                               CONTAINING_RECORD(Vcb,
                                                 VOLUME_DEVICE_OBJECT,
                                                 Vcb));
            }

            /* We're done */
            break;

        /* Invalid request */
        default:

            /* Fail it */
            Status = STATUS_INVALID_DEVICE_REQUEST;
            break;
    }

    /* Complete the request */
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
    return Status;
}

NTSTATUS
NTAPI
RawQueryInformation(IN PVCB Vcb,
                    IN PIRP Irp,
                    IN PIO_STACK_LOCATION IoStackLocation)
{
    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
    PULONG Length;
    PFILE_POSITION_INFORMATION Buffer;
    PAGED_CODE();

    /* Get information from the IRP */
    Length = &IoStackLocation->Parameters.QueryFile.Length;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    /* We only handle this request */
    if (IoStackLocation->Parameters.QueryFile.FileInformationClass ==
        FilePositionInformation)
    {
        /* Validate buffer size */
        if (*Length < sizeof(FILE_POSITION_INFORMATION))
        {
            /* Invalid, fail */
            Irp->IoStatus.Information = 0;
            Status = STATUS_BUFFER_OVERFLOW;
        }
        else
        {
            /* Get offset and update length */
            Buffer->CurrentByteOffset = IoStackLocation->FileObject->
                                        CurrentByteOffset;
            *Length -= sizeof(FILE_POSITION_INFORMATION);

            /* Set IRP Status information */
            Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
            Status = STATUS_SUCCESS;
        }
    }

    /* Complete it */
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
    return Status;
}

NTSTATUS
NTAPI
RawSetInformation(IN PVCB Vcb,
                  IN PIRP Irp,
                  IN PIO_STACK_LOCATION IoStackLocation)
{
    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
    PULONG Length;
    PFILE_POSITION_INFORMATION Buffer;
    PDEVICE_OBJECT DeviceObject;
    PAGED_CODE();

    /* Get information from the IRP */
    Length = &IoStackLocation->Parameters.QueryFile.Length;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    /* We only handle this request */
    if (IoStackLocation->Parameters.QueryFile.FileInformationClass ==
        FilePositionInformation)
    {
        /* Get the DO */
        DeviceObject = IoGetRelatedDeviceObject(IoStackLocation->FileObject);

        /* Make sure the offset is aligned */
        if ((Buffer->CurrentByteOffset.LowPart &
            DeviceObject->AlignmentRequirement))
        {
            /* It's not, fail */
            Status = STATUS_INVALID_PARAMETER;
        }
        else
        {
            /* Otherwise, set offset */
            IoStackLocation->FileObject->CurrentByteOffset = Buffer->
                                                             CurrentByteOffset;

            /* Set IRP Status information */
            Status = STATUS_SUCCESS;
        }
    }

    /* Complete it */
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
    return Status;
}

NTSTATUS
NTAPI
RawQueryFsVolumeInfo(IN PVCB Vcb,
                     IN PFILE_FS_VOLUME_INFORMATION Buffer,
                     IN OUT PULONG Length)
{
    PAGED_CODE();

    /* Clear the buffer and stub it out */
    RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
    Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
    Buffer->SupportsObjects = FALSE;
    Buffer->VolumeLabelLength = 0;

    /* Return length and success */
    *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
    return STATUS_SUCCESS;
}

NTSTATUS
NTAPI
RawQueryFsSizeInfo(IN PVCB Vcb,
                   IN PFILE_FS_SIZE_INFORMATION Buffer,
                   IN OUT PULONG Length)
{
    PIRP Irp;
    KEVENT Event;
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatusBlock;
    PDEVICE_OBJECT RealDevice;
    DISK_GEOMETRY DiskGeometry;
    PARTITION_INFORMATION PartitionInformation;
    BOOLEAN DiskHasPartitions;
    PAGED_CODE();

    /* Validate the buffer */
    if (*Length < sizeof(FILE_FS_SIZE_INFORMATION))
    {
        /* Fail */
        return STATUS_BUFFER_OVERFLOW;
    }

    /* Clear the buffer, initialize the event and set the DO */
    RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION));
    KeInitializeEvent(&Event, NotificationEvent, FALSE);
    RealDevice = Vcb->Vpb->RealDevice;

    /* Build query IRP */
    Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                        RealDevice,
                                        NULL,
                                        0,
                                        &DiskGeometry,
                                        sizeof(DISK_GEOMETRY),
                                        FALSE,
                                        &Event,
                                        &IoStatusBlock);

    /* Call driver and check if we're pending */
    Status = IoCallDriver(RealDevice, Irp);
    if (Status == STATUS_PENDING)
    {
        /* Wait on driver to finish */
        KeWaitForSingleObject(&Event,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
        Status = IoStatusBlock.Status;
    }

    /* Fail if we couldn't get CHS data */
    if (!NT_SUCCESS(Status))
    {
        *Length = 0;
        return Status;
    }

    /* Check if this is a floppy */
    if (FlagOn(RealDevice->Characteristics, FILE_FLOPPY_DISKETTE))
    {
        /* Floppies don't have partitions */
        DiskHasPartitions = FALSE;
    }
    else
    {
        /* Setup query IRP */
        KeResetEvent(&Event);
        Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
                                            RealDevice,
                                            NULL,
                                            0,
                                            &PartitionInformation,
                                            sizeof(PARTITION_INFORMATION),
                                            FALSE,
                                            &Event,
                                            &IoStatusBlock);

        /* Call driver and check if we're pending */
        Status = IoCallDriver(RealDevice, Irp);
        if (Status == STATUS_PENDING)
        {
            /* Wait on driver to finish */
            KeWaitForSingleObject(&Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = IoStatusBlock.Status;
        }

        /* If this was an invalid request, then the disk is not partitioned */
        if (Status == STATUS_INVALID_DEVICE_REQUEST)
        {
            DiskHasPartitions = FALSE;
        }
        else
        {
            /* Otherwise, it must be */
            ASSERT(NT_SUCCESS(Status));
            DiskHasPartitions = TRUE;
        }
    }

    /* Set sector data */
    Buffer->BytesPerSector = DiskGeometry.BytesPerSector;
    Buffer->SectorsPerAllocationUnit = 1;

    /* Calculate allocation units */
    if (DiskHasPartitions)
    {
        /* Use partition data */
        Buffer->TotalAllocationUnits =
            RtlExtendedLargeIntegerDivide(PartitionInformation.PartitionLength,
                                          DiskGeometry.BytesPerSector,
                                          NULL);
    }
    else
    {
        /* Use CHS */
        Buffer->TotalAllocationUnits =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -