2.1.ReactOS系统NtReadFile函数的实现。

ReactOS系统NtReadFile函数的实现。

ReactOS系统NtReadFile函数的实现。

文章目录


NtReadFile()是windows的一个系统调用,内核中有一个叫NtReadFile的函数

NtReadFile函数的定义

cpp 复制代码
NTSTATUS  WINAPI NtReadFile(
						HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,
						PIO_STATUS_BLOCK,PVOID,ULONG,PLARGE_INTEGER,PULONG);

上面的函数看起来很费解。

我们用另外一个函数来看

这里涉及到内核的快速调用的知识。

eax,0B7h:系统调用号:指向NtReadFile(xxxxxxxxx)函数

edx,7ffe0300h:系统调用函数的地址

这样之后就实现了。R3与R0的隔离

NtReadFile函数的实现

cpp 复制代码
NTSTATUS
NTAPI
NtReadFile(IN HANDLE FileHandle,
           IN HANDLE Event OPTIONAL,
           IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
           IN PVOID ApcContext OPTIONAL,
           OUT PIO_STATUS_BLOCK IoStatusBlock,
           OUT PVOID Buffer,
           IN ULONG Length,
           IN PLARGE_INTEGER ByteOffset OPTIONAL,
           IN PULONG Key OPTIONAL)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PFILE_OBJECT FileObject;
    PIRP Irp;
    PDEVICE_OBJECT DeviceObject;
    PIO_STACK_LOCATION StackPtr;
    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
    PKEVENT EventObject = NULL;
    LARGE_INTEGER CapturedByteOffset;
    ULONG CapturedKey = 0;
    BOOLEAN Synchronous = FALSE;
    PMDL Mdl;
    PAGED_CODE();
    CapturedByteOffset.QuadPart = 0;
    IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);

    /* Validate User-Mode Buffers */
    if(PreviousMode != KernelMode)
    {
        _SEH_TRY
        {
            /* Probe the status block */
            ProbeForWriteIoStatusBlock(IoStatusBlock);

            /* Probe the read buffer */
            ProbeForWrite(Buffer, Length, 1);

            /* Check if we got a byte offset */
            if (ByteOffset)
            {
                /* Capture and probe it */
                CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
            }

            /* Capture and probe the key */
            if (Key) CapturedKey = ProbeForReadUlong(Key);
        }
        _SEH_HANDLE
        {
            /* Get the exception code */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        /* Check for probe failure */
        if (!NT_SUCCESS(Status)) return Status;
    }
    else
    {
        /* Kernel mode: capture directly */
        if (ByteOffset) CapturedByteOffset = *ByteOffset;
        if (Key) CapturedKey = *Key;
    }

    /* Get File Object */
    Status = ObReferenceObjectByHandle(FileHandle,
                                       FILE_READ_DATA,
                                       IoFileObjectType,
                                       PreviousMode,
                                       (PVOID*)&FileObject,
                                       NULL);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check for event */
    if (Event)
    {
        /* Reference it */
        Status = ObReferenceObjectByHandle(Event,
                                           EVENT_MODIFY_STATE,
                                           ExEventObjectType,
                                           PreviousMode,
                                           (PVOID*)&EventObject,
                                           NULL);
        if (!NT_SUCCESS(Status))
        {
            /* Fail */
            ObDereferenceObject(FileObject);
            return Status;
        }

        /* Otherwise reset the event */
        KeClearEvent(EventObject);
    }

    /* Check if we should use Sync IO or not */
    if (FileObject->Flags & FO_SYNCHRONOUS_IO)
    {
        /* Lock the file object */
        IopLockFileObject(FileObject);

        /* Check if we don't have a byte offset avilable */
        if (!(ByteOffset) ||
            ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) &&
             (CapturedByteOffset.u.HighPart == -1)))
        {
            /* Use the Current Byte Offset instead */
            CapturedByteOffset = FileObject->CurrentByteOffset;
        }

        /* Rememer we are sync */
        Synchronous = TRUE;
    }
    else if (!(ByteOffset) &&
             !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT)))
    {
        /* Otherwise, this was async I/O without a byte offset, so fail */
        if (EventObject) ObDereferenceObject(EventObject);
        ObDereferenceObject(FileObject);
        return STATUS_INVALID_PARAMETER;
    }

    /* Get the device object */
    DeviceObject = IoGetRelatedDeviceObject(FileObject);

    /* Clear the File Object's event */
    KeClearEvent(&FileObject->Event);

    /* Allocate the IRP */
    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
    if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL);

    /* Set the IRP */
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->RequestorMode = KernelMode;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
    Irp->UserIosb = IoStatusBlock;
    Irp->UserEvent = EventObject;
    Irp->PendingReturned = FALSE;
    Irp->Cancel = FALSE;
    Irp->CancelRoutine = NULL;
    Irp->AssociatedIrp.SystemBuffer = NULL;
    Irp->MdlAddress = NULL;

    /* Set the Stack Data */
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->MajorFunction = IRP_MJ_READ;
    StackPtr->FileObject = FileObject;
    StackPtr->Parameters.Read.Key = CapturedKey;
    StackPtr->Parameters.Read.Length = Length;
    StackPtr->Parameters.Read.ByteOffset = CapturedByteOffset;

    /* Check if this is buffered I/O */
    if (DeviceObject->Flags & DO_BUFFERED_IO)
    {
        /* Check if we have a buffer length */
        if (Length)
        {
            /* Enter SEH */
            _SEH_TRY
            {
                /* Allocate a buffer */
                Irp->AssociatedIrp.SystemBuffer =
                    ExAllocatePoolWithTag(NonPagedPool,
                                          Length,
                                          TAG_SYSB);
            }
            _SEH_HANDLE
            {
                /* Allocating failed, clean up */
                IopCleanupAfterException(FileObject, Irp, NULL, Event);
                Status = _SEH_GetExceptionCode();
            }
            _SEH_END;
            if (!NT_SUCCESS(Status)) return Status;

            /* Set the buffer and flags */
            Irp->UserBuffer = Buffer;
            Irp->Flags = (IRP_BUFFERED_IO |
                          IRP_DEALLOCATE_BUFFER |
                          IRP_INPUT_OPERATION);
        }
        else
        {
            /* Not reading anything */
            Irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
        }
    }
    else if (DeviceObject->Flags & DO_DIRECT_IO)
    {
        /* Check if we have a buffer length */
        if (Length)
        {
            /* Allocate an MDL */
            Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp);
            MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess);
        }

        /* No allocation flags */
        Irp->Flags = 0;
    }
    else
    {
        /* No allocation flags, and use the buffer directly */
        Irp->Flags = 0;
        Irp->UserBuffer = Buffer;
    }

    /* Now set the deferred read flags */
    Irp->Flags |= (IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION);
#if 0
    /* FIXME: VFAT SUCKS */
    if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
#endif

    /* Perform the call */
    return IopPerformSynchronousRequest(DeviceObject,
                                        Irp,
                                        FileObject,
                                        TRUE,
                                        PreviousMode,
                                        Synchronous,
                                        IopReadTransfer);
}

//从上面可以看出ReadFile函数是很大的,可以对文件,IO,事件等的处理

相关推荐
诚丞成38 分钟前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++
yylの博客1 小时前
Windows通过git-bash安装zsh
windows·git·bash·zsh
东风吹柳2 小时前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
A懿轩A2 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
进击的code2 小时前
windows 下使用WLS2 编译aosp Android14并刷机到pixle 5a
windows
大胆飞猪3 小时前
C++9--前置++和后置++重载,const,日期类的实现(对前几篇知识点的应用)
c++
1 9 J3 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
夕泠爱吃糖3 小时前
C++中如何实现序列化和反序列化?
服务器·数据库·c++
长潇若雪3 小时前
《类和对象:基础原理全解析(上篇)》
开发语言·c++·经验分享·类和对象
染指11105 小时前
50.第二阶段x86游戏实战2-lua获取本地寻路,跨地图寻路和获取当前地图id
c++·windows·lua·游戏安全·反游戏外挂·游戏逆向·luastudio