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

📄 rawfs.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
* PROJECT:         ReactOS Kernel
* LICENSE:         GPL - See COPYING in the top level directory
* FILE:            ntoskrnl/io/iomgr/rawfs.c
* PURPOSE:         Raw File System Driver
* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
*/

/* INCLUDES *****************************************************************/

#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>

/* TYPES *******************************************************************/

typedef struct _VCB
{
    USHORT NodeTypeCode;
    USHORT NodeByteSize;
    PDEVICE_OBJECT TargetDeviceObject;
    PVPB Vpb;
    ULONG VcbState;
    KMUTEX Mutex;
    CLONG OpenCount;
    SHARE_ACCESS ShareAccess;
    ULONG BytesPerSector;
    LARGE_INTEGER SectorsOnDisk;
} VCB, *PVCB;

typedef struct _VOLUME_DEVICE_OBJECT
{
    DEVICE_OBJECT DeviceObject;
    VCB Vcb;
} VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT;

/* GLOBALS *******************************************************************/

PDEVICE_OBJECT RawDiskDeviceObject, RawCdromDeviceObject, RawTapeDeviceObject;

/* FUNCTIONS *****************************************************************/

VOID
NTAPI
RawInitializeVcb(IN OUT PVCB Vcb,
                 IN PDEVICE_OBJECT TargetDeviceObject,
                 IN PVPB Vpb)
{
    PAGED_CODE();

    /* Clear it */
    RtlZeroMemory(Vcb, sizeof(VCB));

    /* Associate to system objects */
    Vcb->TargetDeviceObject = TargetDeviceObject;
    Vcb->Vpb = Vpb;

    /* Initialize the lock */
    KeInitializeMutex(&Vcb->Mutex, 0);
}

BOOLEAN
NTAPI
RawCheckForDismount(IN PVCB Vcb,
                    IN BOOLEAN CreateOperation)
{
    KIRQL OldIrql;
    PVPB Vpb;
    BOOLEAN Delete;

    /* Lock VPB */
    IoAcquireVpbSpinLock(&OldIrql);

    /* Reference it and check if a create is being done */
    Vpb = Vcb->Vpb;
    if (Vcb->Vpb->ReferenceCount != CreateOperation)
    {
        /* Don't do anything */
        Delete = FALSE;
    }
    else
    {
        /* Otherwise, delete the volume */
        Delete = TRUE;

        /* Check if it has a VPB and unmount it */
        if (Vpb->RealDevice->Vpb == Vpb)
        {
            Vpb->DeviceObject = NULL;
            Vpb->Flags &= ~VPB_MOUNTED;
        }
    }

    /* Release lock and return status */
    IoReleaseVpbSpinLock(OldIrql);
    return Delete;
}

NTSTATUS
NTAPI
RawCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp,
                     IN PVOID Context)
{
    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

    /* Check if this was a valid sync R/W request */
    if (((IoStackLocation->MajorFunction == IRP_MJ_READ) ||
         (IoStackLocation->MajorFunction == IRP_MJ_WRITE)) &&
        ((IoStackLocation->FileObject)) &&
         (FlagOn(IoStackLocation->FileObject->Flags, FO_SYNCHRONOUS_IO)) &&
         (NT_SUCCESS(Irp->IoStatus.Status)))
    {
        /* Update byte offset */
        IoStackLocation->FileObject->CurrentByteOffset.QuadPart +=
            Irp->IoStatus.Information;
    }

    /* Mark the IRP Pending if it was */
    if (Irp->PendingReturned) IoMarkIrpPending(Irp);
    return STATUS_SUCCESS;
}

NTSTATUS
NTAPI
RawClose(IN PVCB Vcb,
         IN PIRP Irp,
         IN PIO_STACK_LOCATION IoStackLocation)
{
    NTSTATUS Status;
    BOOLEAN Deleted = FALSE;
    PAGED_CODE();

    /* Make sure we can clean up */
    Status = KeWaitForSingleObject(&Vcb->Mutex,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   NULL);
    ASSERT(NT_SUCCESS(Status));

    /* Decrease the open count and check if this is a dismount */
    Vcb->OpenCount--;
    if (!Vcb->OpenCount) Deleted = RawCheckForDismount(Vcb, FALSE);

    /* Check if we should delete the device */
    KeReleaseMutex(&Vcb->Mutex, FALSE);
    if (Deleted)
    {
        /* Delete it */
        IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
                                                         VOLUME_DEVICE_OBJECT,
                                                         Vcb));
    }

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

NTSTATUS
NTAPI
RawCreate(IN PVCB Vcb,
          IN PIRP Irp,
          IN PIO_STACK_LOCATION IoStackLocation)
{
    NTSTATUS Status;
    BOOLEAN Deleted = FALSE;
    USHORT ShareAccess;
    ACCESS_MASK DesiredAccess;
    PAGED_CODE();

    /* Make sure we can clean up */
    Status = KeWaitForSingleObject(&Vcb->Mutex,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   NULL);
    ASSERT(NT_SUCCESS(Status));

    /* Check if this is a valid non-directory file open */
    if ((!(IoStackLocation->FileObject) ||
         !(IoStackLocation->FileObject->FileName.Length)) &&
        ((IoStackLocation->Parameters.Create.Options >> 24) == FILE_OPEN) &&
         (!(IoStackLocation->Parameters.Create.Options & FILE_DIRECTORY_FILE)))
    {
        /* Make sure the VCB isn't locked */
        if (Vcb->VcbState & 1)
        {
            /* Refuse the operation */
            Status = STATUS_ACCESS_DENIED;
            Irp->IoStatus.Information = 0;
        }
        else
        {
            /* Setup share access */
            ShareAccess = IoStackLocation->Parameters.Create.ShareAccess;
            DesiredAccess = IoStackLocation->Parameters.Create.
                            SecurityContext->DesiredAccess;

            /* Check if this VCB was already opened */
            if (Vcb->OpenCount > 0)
            {
                /* Try to see if we have access to it */
                Status = IoCheckShareAccess(DesiredAccess,
                                            ShareAccess,
                                            IoStackLocation->FileObject,
                                            &Vcb->ShareAccess,
                                            TRUE);
                if (!NT_SUCCESS(Status)) Irp->IoStatus.Information = 0;
            }

            /* Make sure we have access */
            if (NT_SUCCESS(Status))
            {
                /* Check if this is the first open */
                if (!Vcb->OpenCount)
                {
                    /* Set the share access */
                    IoSetShareAccess(DesiredAccess,
                                     ShareAccess,
                                     IoStackLocation->FileObject,
                                     &Vcb->ShareAccess);
                }

                /* Increase the open count and set the VPB */
                Vcb->OpenCount += 1;
                IoStackLocation->FileObject->Vpb = Vcb->Vpb;

                /* Set IRP status and disable intermediate buffering */
                Status = STATUS_SUCCESS;
                Irp->IoStatus.Information = FILE_OPENED;
                IoStackLocation->FileObject->Flags |=
                    FO_NO_INTERMEDIATE_BUFFERING;
            }
        }
    }
    else
    {
        /* Invalid create request */
        Status = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;
    }

    /* Check if the request failed */
    if (!(NT_SUCCESS(Status)) && !(Vcb->OpenCount))
    {
        /* Check if we can dismount the device */
        Deleted = RawCheckForDismount(Vcb, FALSE);
    }

    /* Check if we should delete the device */
    KeReleaseMutex(&Vcb->Mutex, FALSE);
    if (Deleted)
    {
        /* Delete it */
        IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
                                                         VOLUME_DEVICE_OBJECT,
                                                         Vcb));
    }

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

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

    /* Don't do anything if the request was 0 bytes */
    if (((IoStackLocation->MajorFunction == IRP_MJ_READ) ||
         (IoStackLocation->MajorFunction == IRP_MJ_WRITE)) &&
        !(IoStackLocation->Parameters.Read.Length))
    {
        /* Complete it */
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
        return STATUS_SUCCESS;
    }

    /* Copy the IRP stack location */
    IoCopyCurrentIrpStackLocationToNext(Irp);

    /* Disable verifies */
    IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;

    /* Setup a completion routine */
    IoSetCompletionRoutine(Irp,
                           RawCompletionRoutine,
                           NULL,
                           TRUE,
                           TRUE,
                           TRUE);

    /* Call the next driver and exit */
    Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
    return Status;
}

NTSTATUS
NTAPI
RawMountVolume(IN PIO_STACK_LOCATION IoStackLocation)
{
    NTSTATUS Status;
    PDEVICE_OBJECT DeviceObject;
    PVOLUME_DEVICE_OBJECT Volume;
    PAGED_CODE();

    /* Remember our owner */
    DeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject;

    /* Create the volume */
    Status = IoCreateDevice(RawDiskDeviceObject->DriverObject,
                            sizeof(VOLUME_DEVICE_OBJECT) -
                            sizeof(DEVICE_OBJECT),
                            NULL,
                            FILE_DEVICE_DISK_FILE_SYSTEM,
                            0,
                            FALSE,
                            (PDEVICE_OBJECT*)&Volume);
    if (!NT_SUCCESS(Status)) return Status;

    /* Use highest alignment requirement */
    Volume->DeviceObject.AlignmentRequirement = max(DeviceObject->
                                                    AlignmentRequirement,
                                                    Volume->DeviceObject.
                                                    AlignmentRequirement);

    /* Setup the VCB */
    RawInitializeVcb(&Volume->Vcb,
                     IoStackLocation->Parameters.MountVolume.DeviceObject,
                     IoStackLocation->Parameters.MountVolume.Vpb);

    /* Set dummy label and serial number */
    Volume->Vcb.Vpb->SerialNumber = 0xFFFFFFFF;
    Volume->Vcb.Vpb->VolumeLabelLength = 0;

    /* Setup the DO */
    Volume->Vcb.Vpb->DeviceObject = &Volume->DeviceObject;
    Volume->DeviceObject.StackSize = DeviceObject->StackSize + 1;
    Volume->DeviceObject.SectorSize = DeviceObject->SectorSize;
    Volume->DeviceObject.Flags |= DO_DIRECT_IO;
    Volume->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
    return Status;
}

NTSTATUS
NTAPI
RawUserFsCtrl(IN PIO_STACK_LOCATION IoStackLocation,
              IN PVCB Vcb)
{
    NTSTATUS Status;
    PAGED_CODE();

    /* Lock the device */
    Status = KeWaitForSingleObject(&Vcb->Mutex,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   NULL);
    ASSERT(NT_SUCCESS(Status));

⌨️ 快捷键说明

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