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

📄 file.c

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

    /* Check if the caller was user mode */
    if (AccessMode != KernelMode)
    {
        /* Protect probe in SEH */
        _SEH_TRY
        {
            /* Probe the buffer */
            ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG));
        }
        _SEH_HANDLE
        {
            /* Get the exception code */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        /* Fail on exception */
        if (!NT_SUCCESS(Status))return Status;
    }

    /* Check if this is a basic or full request */
    IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION));

    /* Setup the Open Packet */
    RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
    OpenPacket.Type = IO_TYPE_OPEN_PACKET;
    OpenPacket.Size = sizeof(OPEN_PACKET);
    OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT;
    OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
    OpenPacket.Disposition = FILE_OPEN;
    OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL;
    OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo :
                                    (AccessMode != KernelMode) ?
                                    &NetworkOpenInfo : FileInformation;
    OpenPacket.QueryOnly = TRUE;
    OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE;
    OpenPacket.DummyFileObject = &DummyFileObject;

    /* Update the operation count */
    IopUpdateOperationCount(IopOtherTransfer);

    /*
     * Attempt opening the file. This will call the I/O Parse Routine for
     * the File Object (IopParseDevice) which will use the dummy file obejct
     * send the IRP to its device object. Note that we have two statuses
     * to worry about: the Object Manager's status (in Status) and the I/O
     * status, which is in the Open Packet's Final Status, and determined
     * by the Parse Check member.
     */
    Status = ObOpenObjectByName(ObjectAttributes,
                                NULL,
                                AccessMode,
                                NULL,
                                FILE_READ_ATTRIBUTES,
                                &OpenPacket,
                                &Handle);
    if (OpenPacket.ParseCheck != TRUE)
    {
        /* Parse failed */
        return Status;
    }
    else
    {
        /* Use the Io status */
        Status = OpenPacket.FinalStatus;
    }

    /* Check if we were succesful and this was user mode and a full query */
    if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic))
    {
        /* Enter SEH for copy */
        _SEH_TRY
        {
            /* Copy the buffer back */
            RtlCopyMemory(FileInformation,
                          &NetworkOpenInfo,
                          FileInformationSize);
        }
        _SEH_HANDLE
        {
            /* Get exception code */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;
    }

    /* Return status */
    return Status;
}

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

/*
 * @unimplemented
 */
NTSTATUS
NTAPI
IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
                               IN ULONG Length,
                               IN BOOLEAN SetOperation)
{
    UNIMPLEMENTED;
    return STATUS_NOT_IMPLEMENTED;
}

/*
 * @unimplemented
 */
NTSTATUS
NTAPI
IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
                           IN ULONG QuotaLength,
                           OUT PULONG ErrorOffset)
{
    UNIMPLEMENTED;
    return STATUS_NOT_IMPLEMENTED;
}

/*
 * @implemented
 */
NTSTATUS
NTAPI
IoCreateFile(OUT PHANDLE FileHandle,
             IN ACCESS_MASK DesiredAccess,
             IN POBJECT_ATTRIBUTES ObjectAttributes,
             OUT PIO_STATUS_BLOCK IoStatusBlock,
             IN PLARGE_INTEGER AllocationSize OPTIONAL,
             IN ULONG FileAttributes,
             IN ULONG ShareAccess,
             IN ULONG Disposition,
             IN ULONG CreateOptions,
             IN PVOID EaBuffer OPTIONAL,
             IN ULONG EaLength,
             IN CREATE_FILE_TYPE CreateFileType,
             IN PVOID ExtraCreateParameters OPTIONAL,
             IN ULONG Options)
{
    KPROCESSOR_MODE AccessMode;
    HANDLE LocalHandle = 0;
    LARGE_INTEGER SafeAllocationSize;
    PVOID SystemEaBuffer = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    OPEN_PACKET OpenPacket;
    PAGED_CODE();
    IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);

    /* Check if we have no parameter checking to do */
    if (Options & IO_NO_PARAMETER_CHECKING)
    {
        /* Then force kernel-mode access to avoid checks */
        AccessMode = KernelMode;
    }
    else
    {
        /* Otherwise, use the actual mode */
        AccessMode = ExGetPreviousMode();
    }

    /* Check if the call came from user mode */
    if (AccessMode != KernelMode)
    {
        _SEH_TRY
        {
            ProbeForWriteHandle(FileHandle);
            ProbeForWriteIoStatusBlock(IoStatusBlock);
            if (AllocationSize)
            {
                SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
            }
            else
            {
                SafeAllocationSize.QuadPart = 0;
            }

            if ((EaBuffer) && (EaLength))
            {
                ProbeForRead(EaBuffer,
                             EaLength,
                             sizeof(ULONG));

                /* marshal EaBuffer */
                SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                                       EaLength,
                                                       TAG_EA);
                if(!SystemEaBuffer)
                {
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                    _SEH_LEAVE;
                }

                RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength);
            }
        }
        _SEH_HANDLE
        {
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        if(!NT_SUCCESS(Status)) return Status;
    }
    else
    {
        /* Check if this is a device attach */
        if (CreateOptions & IO_ATTACH_DEVICE_API)
        {
            /* Set the flag properly */
            Options |= IO_ATTACH_DEVICE;
            CreateOptions &= ~IO_ATTACH_DEVICE_API;
        }

        /* Check if we have allocation size */
        if (AllocationSize)
        {
            /* Capture it */
            SafeAllocationSize = *AllocationSize;
        }
        else
        {
            /* Otherwise, no size */
            SafeAllocationSize.QuadPart = 0;
        }

        /* Check if we have an EA packet */
        if ((EaBuffer) && (EaLength))
        {
            /* Allocate the kernel copy */
            SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                                   EaLength,
                                                   TAG_EA);
            if (!SystemEaBuffer) return STATUS_INSUFFICIENT_RESOURCES;

            /* Copy the data */
            RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength);

            /* Validate the buffer */
            Status = IoCheckEaBufferValidity(SystemEaBuffer,
                                             EaLength,
                                             NULL);
            if (!NT_SUCCESS(Status))
            {
                /* FIXME: Fail once function is implemented */
            }
        }
    }

    /* Setup the Open Packet */
    RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
    OpenPacket.Type = IO_TYPE_OPEN_PACKET;
    OpenPacket.Size = sizeof(OPEN_PACKET);
    OpenPacket.OriginalAttributes = *ObjectAttributes;
    OpenPacket.AllocationSize = SafeAllocationSize;
    OpenPacket.CreateOptions = CreateOptions;
    OpenPacket.FileAttributes = (USHORT)FileAttributes;
    OpenPacket.ShareAccess = (USHORT)ShareAccess;
    OpenPacket.EaBuffer = SystemEaBuffer;
    OpenPacket.EaLength = EaLength;
    OpenPacket.Options = Options;
    OpenPacket.Disposition = Disposition;
    OpenPacket.CreateFileType = CreateFileType;
    OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters;

    /* Update the operation count */
    IopUpdateOperationCount(IopOtherTransfer);

    /*
     * Attempt opening the file. This will call the I/O Parse Routine for
     * the File Object (IopParseDevice) which will create the object and
     * send the IRP to its device object. Note that we have two statuses
     * to worry about: the Object Manager's status (in Status) and the I/O
     * status, which is in the Open Packet's Final Status, and determined
     * by the Parse Check member.
     */
    Status = ObOpenObjectByName(ObjectAttributes,
                                NULL,
                                AccessMode,
                                NULL,
                                DesiredAccess,
                                &OpenPacket,
                                &LocalHandle);

    /* Free the EA Buffer */
    if (OpenPacket.EaBuffer) ExFreePool(OpenPacket.EaBuffer);

    /* Now check for Ob or Io failure */
    if (!(NT_SUCCESS(Status)) || (OpenPacket.ParseCheck != TRUE))
    {
        /* Check if Ob thinks well went well */
        if (NT_SUCCESS(Status))
        {
            /*
             * Tell it otherwise. Because we didn't use an ObjectType,
             * it incorrectly returned us a handle to God knows what.
             */
            ZwClose(LocalHandle);
            Status = STATUS_OBJECT_TYPE_MISMATCH;
        }

        /* Now check the Io status */
        if (!NT_SUCCESS(OpenPacket.FinalStatus))
        {
            /* Use this status instead of Ob's */
            Status = OpenPacket.FinalStatus;

            /* Check if it was only a warning */
            if (NT_WARNING(Status))
            {
                /* Protect write with SEH */
                _SEH_TRY
                {
                    /* In this case, we copy the I/O Status back */
                    IoStatusBlock->Information = OpenPacket.Information;
                    IoStatusBlock->Status = OpenPacket.FinalStatus;
                }
                _SEH_HANDLE
                {
                    /* Get exception code */
                    Status = _SEH_GetExceptionCode();
                }
                _SEH_END;
            }
        }
        else if ((OpenPacket.FileObject) && (OpenPacket.ParseCheck != 1))
        {
            /*
             * This can happen in the very bizarre case where the parse routine
             * actually executed more then once (due to a reparse) and ended
             * up failing after already having created the File Object.
             */
            if (OpenPacket.FileObject->FileName.Length)
            {
                /* It had a name, free it */
                ExFreePool(OpenPacket.FileObject->FileName.Buffer);
            }

            /* Clear the device object to invalidate the FO, and dereference */
            OpenPacket.FileObject->DeviceObject = NULL;
            ObDereferenceObject(OpenPacket.FileObject);
        }
    }
    else
    {
        /* We reached success and have a valid file handle */
        OpenPacket.FileObject->Flags |= FO_HANDLE_CREATED;

        /* Enter SEH for write back */
        _SEH_TRY
        {
            /* Write back the handle and I/O Status */
            *FileHandle = LocalHandle;
            IoStatusBlock->Information = OpenPacket.Information;
            IoStatusBlock->Status = OpenPacket.FinalStatus;

            /* Get the Io status */
            Status = OpenPacket.FinalStatus;
        }
        _SEH_HANDLE
        {
            /* Get the exception status */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;
    }

    /* Check if we were 100% successful */
    

⌨️ 快捷键说明

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