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

📄 file.c

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

    /* Copy the I/O Status */
    OpenPacket->Information = IoStatusBlock.Information;

    /* The driver failed to create the file */
    if (!NT_SUCCESS(Status))
    {
        /* Check if we have a name */
        if (FileObject->FileName.Length)
        {
            /* Free it */
            ExFreePool(FileObject->FileName.Buffer);
            FileObject->FileName.Length = 0;
        }

        /* Clear its device object */
        FileObject->DeviceObject = NULL;

        /* Save this now because the FO might go away */
        OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ?
                        TRUE : FALSE;

        /* Clear the file object in the open packet */
        OpenPacket->FileObject = NULL;

        /* Dereference the file object */
        if (!UseDummyFile) ObDereferenceObject(FileObject);

        /* Dereference the device object */
        IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);

        /* Unless the driver cancelled the open, dereference the VPB */
        if (!(OpenCancelled) && (Vpb)) IopDereferenceVpb(Vpb);

        /* Set the status and return */
        OpenPacket->FinalStatus = Status;
        return Status;
    }
    else if (Status == STATUS_REPARSE)
    {
        /* FIXME: We don't handle this at all! */
        KEBUGCHECK(0);
    }

    /* Get the owner of the File Object */
    OwnerDevice = IoGetRelatedDeviceObject(FileObject);

    /*
     * It's possible that the device to whom we sent the IRP to
     * isn't actually the device that ended opening the file object
     * internally.
     */
    if (OwnerDevice != DeviceObject)
    {
        /* We have to de-reference the VPB we had associated */
        if (Vpb) IopDereferenceVpb(Vpb);

        /* And re-associate with the actual one */
        Vpb = FileObject->Vpb;
        if (Vpb) InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
    }

    /* Make sure we are not using a dummy */
    if (!UseDummyFile)
    {
        /* Check if this was a volume open */
        if ((!(FileObject->RelatedFileObject) ||
              (FileObject->RelatedFileObject->Flags & FO_VOLUME_OPEN)) &&
            !(FileObject->FileName.Length))
        {
            /* All signs point to it, but make sure it was actually an FSD */
            if ((OwnerDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||
                (OwnerDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) ||
                (OwnerDevice->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) ||
                (OwnerDevice->DeviceType == FILE_DEVICE_FILE_SYSTEM))
            {
                /* The owner device is an FSD, so this is a volume open for real */
                FileObject->Flags |= FO_VOLUME_OPEN;
            }
        }

        /* Reference the object and set the parse check */
        ObReferenceObject(FileObject);
        *Object = FileObject;
        OpenPacket->FinalStatus = IoStatusBlock.Status;
        OpenPacket->ParseCheck = TRUE;
        return OpenPacket->FinalStatus;
    }
    else
    {
        /* Check if this was a query */
        if (OpenPacket->QueryOnly)
        {
            /* Check if the caller wants basic info only */
            if (!OpenPacket->FullAttributes)
            {
                /* Allocate the buffer */
                FileBasicInfo = ExAllocatePoolWithTag(NonPagedPool,
                                                      sizeof(*FileBasicInfo),
                                                      TAG_IO);
                if (FileBasicInfo)
                {
                    /* Do the query */
                    Status = IoQueryFileInformation(FileObject,
                                                    FileBasicInformation,
                                                    sizeof(*FileBasicInfo),
                                                    FileBasicInfo,
                                                    &ReturnLength);
                    if (NT_SUCCESS(Status))
                    {
                        /* Copy the data */
                        RtlCopyMemory(OpenPacket->BasicInformation,
                                      FileBasicInfo,
                                      ReturnLength);
                    }

                    /* Free our buffer */
                    ExFreePool(FileBasicInfo);
                }
                else
                {
                    /* Fail */
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
            else
            {
                /* This is a full query */
                Status = IoQueryFileInformation(
                    FileObject,
                    FileNetworkOpenInformation,
                    sizeof(FILE_NETWORK_OPEN_INFORMATION),
                    OpenPacket->NetworkInformation,
                    &ReturnLength);
                if (!NT_SUCCESS(Status)) ASSERT(Status != STATUS_NOT_IMPLEMENTED);
            }
        }

        /* Delete the file object */
        IopDeleteFile(FileObject);

        /* Clear out the file */
        OpenPacket->FileObject = NULL;

        /* Set and return status */
        OpenPacket->FinalStatus = Status;
        OpenPacket->ParseCheck = TRUE;
        return Status;
    }
}

NTSTATUS
NTAPI
IopParseFile(IN PVOID ParseObject,
             IN PVOID ObjectType,
             IN OUT PACCESS_STATE AccessState,
             IN KPROCESSOR_MODE AccessMode,
             IN ULONG Attributes,
             IN OUT PUNICODE_STRING CompleteName,
             IN OUT PUNICODE_STRING RemainingName,
             IN OUT PVOID Context OPTIONAL,
             IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
             OUT PVOID *Object)
{
    PVOID DeviceObject;
    POPEN_PACKET OpenPacket = (POPEN_PACKET)Context;

    /* Validate the open packet */
    if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;

    /* Get the device object */
    DeviceObject = IoGetRelatedDeviceObject(ParseObject);
    OpenPacket->RelatedFileObject = ParseObject;

    /* Call the main routine */
    return IopParseDevice(DeviceObject,
                          ObjectType,
                          AccessState,
                          AccessMode,
                          Attributes,
                          CompleteName,
                          RemainingName,
                          OpenPacket,
                          SecurityQos,
                          Object);
}

VOID
NTAPI
IopDeleteFile(IN PVOID ObjectBody)
{
    PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
    PIRP Irp;
    PIO_STACK_LOCATION StackPtr;
    NTSTATUS Status;
    KEVENT Event;
    PDEVICE_OBJECT DeviceObject;
    BOOLEAN DereferenceDone = FALSE;
    PVPB Vpb;
    KIRQL OldIrql;
    IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);

    /* Check if the file has a device object */
    if (FileObject->DeviceObject)
    {
        /* Check if this is a direct open or not */
        if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
        {
            /* Get the attached device */
            DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
        }
        else
        {
            /* Use the file object's device object */
            DeviceObject = IoGetRelatedDeviceObject(FileObject);
        }

        /* Sanity check */
        ASSERT(!(FileObject->Flags & FO_SYNCHRONOUS_IO) ||
               (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE));

        /* Check if the handle wasn't created yet */
        if (!(FileObject->Flags & FO_HANDLE_CREATED))
        {
            /* Send the cleanup IRP */
            IopCloseFile(NULL, ObjectBody, 0, 1, 1);
        }

        /* Clear and set up Events */
        KeClearEvent(&FileObject->Event);
        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);

        /* Allocate an IRP */
        Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
        if (!Irp) return;

        /* Set it up */
        Irp->UserEvent = &Event;
        Irp->UserIosb = &Irp->IoStatus;
        Irp->Tail.Overlay.Thread = PsGetCurrentThread();
        Irp->Tail.Overlay.OriginalFileObject = FileObject;
        Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;

        /* Set up Stack Pointer Data */
        StackPtr = IoGetNextIrpStackLocation(Irp);
        StackPtr->MajorFunction = IRP_MJ_CLOSE;
        StackPtr->FileObject = FileObject;

        /* Queue the IRP */
        IopQueueIrpToThread(Irp);

        /* Get the VPB and check if this isn't a direct open */
        Vpb = FileObject->Vpb;
        if ((Vpb) && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
        {
            /* Dereference the VPB before the close */
            InterlockedDecrement((PLONG)&Vpb->ReferenceCount);
        }

        /* Check if the FS will never disappear by itself */
        if (FileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE)
        {
            /* Dereference it */
            InterlockedDecrement(&FileObject->DeviceObject->ReferenceCount);
            DereferenceDone = TRUE;
        }

        /* Call the FS Driver */
        Status = IoCallDriver(DeviceObject, Irp);
        if (Status == STATUS_PENDING)
        {
            /* Wait for completion */
            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        }

        /* De-queue the IRP */
        KeRaiseIrql(APC_LEVEL, &OldIrql);
        IopUnQueueIrpFromThread(Irp);
        KeLowerIrql(OldIrql);

        /* Free the IRP */
        IoFreeIrp(Irp);

        /* Clear the file name */
        if (FileObject->FileName.Buffer)
        {
           ExFreePool(FileObject->FileName.Buffer);
           FileObject->FileName.Buffer = NULL;
        }

        /* Check if the FO had a completion port */
        if (FileObject->CompletionContext)
        {
            /* Free it */
            ObDereferenceObject(FileObject->CompletionContext->Port);
            ExFreePool(FileObject->CompletionContext);
        }

        /* Check if dereference has been done yet */
        if (!DereferenceDone)
        {
            /* Dereference device object */
            IopDereferenceDeviceObject(FileObject->DeviceObject, FALSE);
        }
    }
}

NTSTATUS
NTAPI
IopSecurityFile(IN PVOID ObjectBody,
                IN SECURITY_OPERATION_CODE OperationCode,
                IN PSECURITY_INFORMATION SecurityInformation,
                IN PSECURITY_DESCRIPTOR SecurityDescriptor,
                IN OUT PULONG BufferLength,
                IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
                IN POOL_TYPE PoolType,
                IN OUT PGENERIC_MAPPING GenericMapping)
{
    IO_STATUS_BLOCK IoStatusBlock;
    PIO_STACK_LOCATION StackPtr;
    PFILE_OBJECT FileObject;
    PDEVICE_OBJECT DeviceObject;
    PIRP Irp;
    BOOLEAN LocalEvent = FALSE;
    KEVENT Event;
    NTSTATUS Status = STATUS_SUCCESS;
    PAGED_CODE();
    IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);

    /* Check if this is a device or file */
    if (((PFILE_OBJECT)ObjectBody)->Type == IO_TYPE_DEVICE)
    {
        /* It's a device */
        DeviceObject = (PDEVICE_OBJECT)ObjectBody;
        FileObject = NULL;
    }
    else
    {
        /* It's a file */
        FileObject = (PFILE_OBJECT)ObjectBody;

        /* Check if this is a direct open */
        if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
        {
            /* Get the Device Object */
            DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
        }
        else
        {
            /* Otherwise, use the direct device*/
            DeviceObject = FileObject->DeviceObject;
        }
    }

    /* Check if the request was for a device object */
    if (!(FileObject) ||
        (!(FileObject->FileName.Length) && !(FileObject->RelatedFileObject)) ||
        (FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
    {
        /* Check what kind of request this was */
        if (OperationCode == QuerySecurityDescriptor)
        {
            DPRINT1("FIXME: Device Query security descriptor UNHANDLED\n");
            return STATUS_SUCCESS;
        }
        else if (OperationCode == DeleteSecurityDescriptor)
        {
            /* Simply return success */
            return STATUS_SUCCESS;
        }
        else if (OperationCode == AssignSecurityDescriptor)
        {

⌨️ 快捷键说明

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