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

📄 file.c

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

        /* Check if access failed */
        if (!AccessGranted)
        {
            /* Dereference the device and fail */
            DPRINT1("Traverse access failed!\n");
            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
            return STATUS_ACCESS_DENIED;
        }
    }

    /* Check if we can simply use a dummy file */
    UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));

    /* Check if this is a direct open */
    if (!(RemainingName->Length) &&
        !(OpenPacket->RelatedFileObject) &&
#if 0 // USETUP IS BROKEN!
        ((DesiredAccess & ~(SYNCHRONIZE |
                             FILE_READ_ATTRIBUTES |
                             READ_CONTROL |
                             ACCESS_SYSTEM_SECURITY |
                             WRITE_OWNER |
                             WRITE_DAC)) &&
#endif
        !(UseDummyFile))
    {
        if (DesiredAccess & ~(SYNCHRONIZE |
                              FILE_READ_ATTRIBUTES |
                              READ_CONTROL |
                              ACCESS_SYSTEM_SECURITY |
                              WRITE_OWNER |
                              WRITE_DAC))
        {
            DPRINT1("FIXME: Broken Parse due to invalid DesiredAccess: %lx\n",
                    DesiredAccess);
        }

        /* Remember this for later */
        DirectOpen = TRUE;
    }

    /* Check if we have a related FO that wasn't a direct open */
    if ((OpenPacket->RelatedFileObject) &&
        !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))
    {
        /* The device object is the one we were given */
        DeviceObject = ParseObject;

        /* Check if the related FO had a VPB */
        if (OpenPacket->RelatedFileObject->Vpb)
        {
            /* Yes, remember it */
            Vpb = OpenPacket->RelatedFileObject->Vpb;

            /* Reference it */
            InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
        }
    }
    else
    {
        /* The device object is the one we were given */
        DeviceObject = OriginalDeviceObject;

        /* Check if it has a VPB */
        if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
        {
            /* Check if the VPB is mounted, and mount it */
            Vpb = IopCheckVpbMounted(OpenPacket,
                                     OriginalDeviceObject,
                                     RemainingName,
                                     &Status);
            if (!Vpb) return Status;

            /* Get the VPB's device object */
            DeviceObject = Vpb->DeviceObject;
        }

        /* Check if there's an attached device */
        if (DeviceObject->AttachedDevice)
        {
            /* Get the attached device */
            DeviceObject = IoGetAttachedDevice(DeviceObject);
        }
    }

    /* Check if this is a secure FSD */
    if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
        ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
        (!VolumeOpen))
    {
        DPRINT1("Fix Secure FSD support!!!\n");
    }

    /* Allocate the IRP */
    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
    if (!Irp)
    {
        /* Dereference the device and VPB, then fail */
        IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
        if (Vpb) IopDereferenceVpb(Vpb);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Now set the IRP data */
    Irp->RequestorMode = AccessMode;
    Irp->Flags = IRP_CREATE_OPERATION |
                 IRP_SYNCHRONOUS_API |
                 IRP_DEFER_IO_COMPLETION;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->UserIosb = &IoStatusBlock;
    Irp->MdlAddress = NULL;
    Irp->PendingReturned = FALSE;
    Irp->UserEvent = NULL;
    Irp->Cancel = FALSE;
    Irp->CancelRoutine = NULL;
    Irp->Tail.Overlay.AuxiliaryBuffer = NULL;

    /* Setup the security context */
    SecurityContext.SecurityQos = SecurityQos;
    SecurityContext.AccessState = AccessState;
    SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess;
    SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;

    /* Get the I/O Stack location */
    StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
    StackLoc->Control = 0;

    /* Check what kind of file this is */
    switch (OpenPacket->CreateFileType)
    {
        /* Normal file */
        case CreateFileTypeNone:

            /* Set the major function and EA Length */
            StackLoc->MajorFunction = IRP_MJ_CREATE;
            StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength;

            /* Set the flags */
            StackLoc->Flags = (UCHAR)OpenPacket->Options;
            StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ?
                                SL_CASE_SENSITIVE: 0;
            break;

        /* Named pipe */
        case CreateFileTypeNamedPipe:

            /* Set the named pipe MJ and set the parameters */
            StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
            StackLoc->Parameters.CreatePipe.Parameters = 
                OpenPacket->MailslotOrPipeParameters;
            break;

        /* Mailslot */
        case CreateFileTypeMailslot:

            /* Set the mailslot MJ and set the parameters */
            StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
            StackLoc->Parameters.CreateMailslot.Parameters =
                OpenPacket->MailslotOrPipeParameters;
            break;
    }

    /* Set the common data */
    Irp->Overlay.AllocationSize = OpenPacket->AllocationSize;
    Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer;
    StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) |
                                          (OpenPacket->CreateOptions &
                                           0xFFFFFF);
    StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes;
    StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess;
    StackLoc->Parameters.Create.SecurityContext = &SecurityContext;

    /* Check if we really need to create an object */
    if (!UseDummyFile)
    {
        /* Create the actual file object */
        InitializeObjectAttributes(&ObjectAttributes,
                                   NULL,
                                   Attributes,
                                   NULL,
                                   NULL);
        Status = ObCreateObject(KernelMode,
                                IoFileObjectType,
                                &ObjectAttributes,
                                AccessMode,
                                NULL,
                                sizeof(FILE_OBJECT),
                                0,
                                0,
                                (PVOID*)&FileObject);
        if (!NT_SUCCESS(Status))
        {
            /* Create failed, free the IRP */
            IoFreeIrp(Irp);

            /* Dereference the device and VPB */
            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
            if (Vpb) IopDereferenceVpb(Vpb);

            /* We failed, return status */
            OpenPacket->FinalStatus = Status;
            return Status;
        }

        /* Clear the file object */
        RtlZeroMemory(FileObject, sizeof(FILE_OBJECT));

        /* Check if this is Synch I/O */
        if (OpenPacket->CreateOptions &
            (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
        {
            /* Set the synch flag */
            FileObject->Flags |= FO_SYNCHRONOUS_IO;

            /* Check if it's also alertable */
            if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
            {
                /* It is, set the alertable flag */
                FileObject->Flags |= FO_ALERTABLE_IO;
            }
        }

        /* Check if this is synch I/O */
        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
        {
            /* Initialize the event */
            KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE);
        }

        /* Check if the caller requested no intermediate buffering */
        if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
        {
            /* Set the correct flag for the FSD to read */
            FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
        }

        /* Check if the caller requested write through support */
        if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH)
        {
            /* Set the correct flag for the FSD to read */
            FileObject->Flags |= FO_WRITE_THROUGH;
        }

        /* Check if the caller says the file will be only read sequentially */
        if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY)
        {
            /* Set the correct flag for the FSD to read */
            FileObject->Flags |= FO_SEQUENTIAL_ONLY;
        }

        /* Check if the caller believes the file will be only read randomly */
        if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS)
        {
            /* Set the correct flag for the FSD to read */
            FileObject->Flags |= FO_RANDOM_ACCESS;
        }
    }
    else
    {
        /* Use the dummy object instead */
        DummyFileObject = OpenPacket->DummyFileObject;
        RtlZeroMemory(DummyFileObject, sizeof(DUMMY_FILE_OBJECT));

        /* Set it up */
        FileObject = (PFILE_OBJECT)&DummyFileObject->ObjectHeader.Body;
        DummyFileObject->ObjectHeader.Type = IoFileObjectType;
        DummyFileObject->ObjectHeader.PointerCount = 1;
    }

    /* Setup the file header */
    FileObject->Type = IO_TYPE_FILE;
    FileObject->Size = sizeof(FILE_OBJECT);
    FileObject->RelatedFileObject = OpenPacket->RelatedFileObject;
    FileObject->DeviceObject = OriginalDeviceObject;

    /* Check if this is a direct device open */
    if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;

    /* Check if the caller wants case sensitivity */
    if (!(Attributes & OBJ_CASE_INSENSITIVE))
    {
        /* Tell the driver about it */
        FileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
    }

    /* Now set the file object */
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    StackLoc->FileObject = FileObject;

    /* Check if the file object has a name */
    if (RemainingName->Length)
    {
        /* Setup the unicode string */
        FileObject->FileName.MaximumLength = RemainingName->Length +
                                             sizeof(WCHAR);
        FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool,
                                                            FileObject->
                                                            FileName.
                                                            MaximumLength,
                                                            TAG_IO_NAME);
        if (!FileObject->FileName.Buffer)
        {
            /* Failed to allocate the name, free the IRP */
            IoFreeIrp(Irp);

            /* Dereference the device object and VPB */
            IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
            if (Vpb) IopDereferenceVpb(Vpb);

            /* Clear the FO and dereference it */
            FileObject->DeviceObject = NULL;
            if (!UseDummyFile) ObDereferenceObject(FileObject);

            /* Fail */
            return STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    /* Copy the name */
    RtlCopyUnicodeString(&FileObject->FileName, RemainingName);

    /* Initialize the File Object event and set the FO */
    KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
    OpenPacket->FileObject = FileObject;

    /* Queue the IRP and call the driver */
    IopQueueIrpToThread(Irp);
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        /* Wait for the driver to complete the create */
        KeWaitForSingleObject(&FileObject->Event,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);

        /* Get the new status */
        Status = IoStatusBlock.Status;
    }
    else
    {
        /* We'll have to complete it ourselves */
        ASSERT(!Irp->PendingReturned);
        ASSERT(!Irp->MdlAddress);

        /* Completion happens at APC_LEVEL */
        KeRaiseIrql(APC_LEVEL, &OldIrql);

        /* Get the new I/O Status block ourselves */
        IoStatusBlock = Irp->IoStatus;
        Status = IoStatusBlock.Status;

        /* Manually signal the even, we can't have any waiters */
        FileObject->Event.Header.SignalState = 1;

        /* Now that we've signaled the events, de-associate the IRP */
        IopUnQueueIrpFromThread(Irp);

        /* Check if the IRP had an input buffer */
        if ((Irp->Flags & IRP_BUFFERED_IO) &&
            (Irp->Flags & IRP_DEALLOCATE_BUFFER))
        {
            /* Free it. A driver might've tacked one on */
            ExFreePool(Irp->AssociatedIrp.SystemBuffer);
        }

        /* Free the IRP and bring the IRQL back down */
        IoFreeIrp(Irp);
        KeLowerIrql(OldIrql);

⌨️ 快捷键说明

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