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

📄 iofunc.c

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

    /* Set up the IRP */
    Irp->RequestorMode = PreviousMode;
    Irp->UserIosb = IoStatusBlock;
    Irp->UserEvent = Event;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;

    /* Set up Stack Data */
    IoStack = IoGetNextIrpStackLocation(Irp);
    IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
    IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
    IoStack->FileObject = FileObject;

    /* Set parameters */
    IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
    IoStack->Parameters.NotifyDirectory.Length = BufferSize;
    if (WatchTree) IoStack->Flags = SL_WATCH_TREE;

    /* Perform the call */
    return IopPerformSynchronousRequest(DeviceObject,
                                        Irp,
                                        FileObject,
                                        FALSE,
                                        PreviousMode,
                                        LockedForSync,
                                        IopOtherTransfer);
}

/*
 * @implemented
 */
NTSTATUS
NTAPI
NtLockFile(IN HANDLE FileHandle,
           IN HANDLE EventHandle OPTIONAL,
           IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
           IN PVOID ApcContext OPTIONAL,
           OUT PIO_STATUS_BLOCK IoStatusBlock,
           IN PLARGE_INTEGER ByteOffset,
           IN PLARGE_INTEGER Length,
           IN ULONG  Key,
           IN BOOLEAN FailImmediately,
           IN BOOLEAN ExclusiveLock)
{
    PFILE_OBJECT FileObject;
    PLARGE_INTEGER LocalLength = NULL;
    PIRP Irp;
    PIO_STACK_LOCATION StackPtr;
    PDEVICE_OBJECT DeviceObject;
    PKEVENT Event = NULL;
    BOOLEAN LockedForSync = FALSE;
    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
    LARGE_INTEGER CapturedByteOffset, CapturedLength;
    NTSTATUS Status = STATUS_SUCCESS;
    OBJECT_HANDLE_INFORMATION HandleInformation;
    PAGED_CODE();
    CapturedByteOffset.QuadPart = 0;
    CapturedLength.QuadPart = 0;
    IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);

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

    /* Check if we're called from user mode */
    if (PreviousMode != KernelMode)
    {
        /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
        if (!(HandleInformation.GrantedAccess &
            (FILE_WRITE_DATA | FILE_READ_DATA)))
        {
            ObDereferenceObject(FileObject);
            return STATUS_ACCESS_DENIED;
        }

        /* Enter SEH for probing */
        _SEH_TRY
        {
            /* Probe the I/O STatus block */
            ProbeForWriteIoStatusBlock(IoStatusBlock);

            /* Probe and capture the large integers */
            CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
            CapturedLength = ProbeForReadLargeInteger(Length);
        }
        _SEH_HANDLE
        {
            /* Get the exception code */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        /* Check if probing failed */
        if (!NT_SUCCESS(Status))
        {
            /* Dereference the object and return exception code */
            ObDereferenceObject(FileObject);
            return Status;
        }
    }
    else
    {
        /* Otherwise, capture them directly */
        CapturedByteOffset = *ByteOffset;
        CapturedLength = *Length;
    }

    /* Check if we have an event handle */
    if (EventHandle)
    {
        /* Reference it */
        Status = ObReferenceObjectByHandle(EventHandle,
                                           EVENT_MODIFY_STATE,
                                           ExEventObjectType,
                                           PreviousMode,
                                           (PVOID *)&Event,
                                           NULL);
        if (Status != STATUS_SUCCESS) return Status;
        KeClearEvent(Event);
    }

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

    /* Check if we should use Sync IO or not */
    if (FileObject->Flags & FO_SYNCHRONOUS_IO)
    {
        /* Lock it */
        IopLockFileObject(FileObject);
        LockedForSync = TRUE;
    }

    /* Clear File Object event */
    KeClearEvent(&FileObject->Event);
    FileObject->LockOperation = TRUE;

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

    /* Set up the IRP */
    Irp->RequestorMode = PreviousMode;
    Irp->UserIosb = IoStatusBlock;
    Irp->UserEvent = Event;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;

    /* Set up Stack Data */
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
    StackPtr->MinorFunction = IRP_MN_LOCK;
    StackPtr->FileObject = FileObject;

    /* Enter SEH */
    _SEH_TRY
    {
        /* Allocate local buffer */
        LocalLength = ExAllocatePoolWithTag(NonPagedPool,
                                            sizeof(LARGE_INTEGER),
                                            TAG_LOCK);

        /* Set the length */
        *LocalLength = CapturedLength;
        Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength;
        StackPtr->Parameters.LockControl.Length = LocalLength;
    }
    _SEH_HANDLE
    {
        /* Allocating failed, clean up */
        IopCleanupAfterException(FileObject, Irp, Event, NULL);
        if (LocalLength) ExFreePool(LocalLength);

        /* Get status */
        Status = _SEH_GetExceptionCode();
    }
    _SEH_END;
    if (!NT_SUCCESS(Status)) return Status;

    /* Set Parameters */
    StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
    StackPtr->Parameters.LockControl.Key = Key;

    /* Set Flags */
    if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
    if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;

    /* Perform the call */
    return IopPerformSynchronousRequest(DeviceObject,
                                        Irp,
                                        FileObject,
                                        FALSE,
                                        PreviousMode,
                                        LockedForSync,
                                        IopOtherTransfer);
}

/*
 * @implemented
 */
NTSTATUS
NTAPI
NtQueryDirectoryFile(IN HANDLE FileHandle,
                     IN HANDLE EventHandle OPTIONAL,
                     IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
                     IN PVOID ApcContext OPTIONAL,
                     OUT PIO_STATUS_BLOCK IoStatusBlock,
                     OUT PVOID FileInformation,
                     IN ULONG Length,
                     IN FILE_INFORMATION_CLASS FileInformationClass,
                     IN BOOLEAN ReturnSingleEntry,
                     IN PUNICODE_STRING FileName OPTIONAL,
                     IN BOOLEAN RestartScan)
{
    PIRP Irp;
    PDEVICE_OBJECT DeviceObject;
    PFILE_OBJECT FileObject;
    PIO_STACK_LOCATION StackPtr;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status = STATUS_SUCCESS;
    BOOLEAN LockedForSynch = FALSE;
    PKEVENT Event = NULL;
    PVOID AuxBuffer = NULL;
    PMDL Mdl;
    UNICODE_STRING CapturedFileName;
    PUNICODE_STRING SearchPattern;
    PAGED_CODE();
    IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);

    /* Check if we came from user mode */
    if (PreviousMode != KernelMode)
    {
        /* Enter SEH for probing */
        _SEH_TRY
        {
            /* Probe the I/O Status Block */
            ProbeForWriteIoStatusBlock(IoStatusBlock);

            /* Probe the file information */
            ProbeForWrite(FileInformation, Length, sizeof(ULONG));

            /* Check if we have a file name */
            if (FileName)
            {
                /* Capture it */
                CapturedFileName = ProbeForReadUnicodeString(FileName);
                if (CapturedFileName.Length)
                {
                    /* Probe its buffer */
                    ProbeForRead(CapturedFileName.Buffer,
                                 CapturedFileName.Length,
                                 1);
                }

                /* Allocate the auxiliary buffer */
                AuxBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                                  CapturedFileName.Length +
                                                  sizeof(UNICODE_STRING),
                                                  TAG_SYSB);
                RtlCopyMemory((PVOID)((ULONG_PTR)AuxBuffer +
                                      sizeof(UNICODE_STRING)),
                              CapturedFileName.Buffer,
                              CapturedFileName.Length);

                /* Setup the search pattern */
                SearchPattern = (PUNICODE_STRING)AuxBuffer;
                SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)AuxBuffer +
                                                 sizeof(UNICODE_STRING));
                SearchPattern->Length = CapturedFileName.Length;
                SearchPattern->MaximumLength = CapturedFileName.Length;
            }
        }
        _SEH_HANDLE
        {
            /* Get exception code and free the buffer */
            if (AuxBuffer) ExFreePool(AuxBuffer);
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        /* Return status on failure */
        if (!NT_SUCCESS(Status)) return Status;
    }

    /* Get File Object */
    Status = ObReferenceObjectByHandle(FileHandle,
                                       FILE_LIST_DIRECTORY,
                                       IoFileObjectType,
                                       PreviousMode,
                                       (PVOID *)&FileObject,
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
        /* Fail */
        if (AuxBuffer) ExFreePool(AuxBuffer);
        return Status;
    }

    /* Check if we have an even handle */
    if (EventHandle)
    {
        /* Get its pointer */
        Status = ObReferenceObjectByHandle(EventHandle,
                                           EVENT_MODIFY_STATE,
                                           ExEventObjectType,
                                           PreviousMode,
                                           (PVOID *)&Event,
                                           NULL);
        if (!NT_SUCCESS(Status))
        {
            /* Fail */
            ObDereferenceObject(FileObject);
            return Status;
        }

        /* Clear it */
        KeClearEvent(Event);
    }

    /* Check if this is a file that was opened for Synch I/O */
    if (FileObject->Flags & FO_SYNCHRONOUS_IO)
    {
        /* Lock it */
        IopLockFileObject(FileObject);

        /* Remember to unlock later */
        LockedForSynch = TRUE;
    }

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

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

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

    /* Set up the IRP */
    Irp->RequestorMode = PreviousMode;
    Irp->UserIosb = IoStatusBlock;
    Irp->UserEvent = Event;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
    Irp->MdlAddress = NULL;
    Irp->Tail.Overlay.AuxiliaryBuffer = AuxBuffer;
    Irp->AssociatedIrp.SystemBuffer = NULL;

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

            /* Get status */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;
        if (!NT_SUCCESS(Status)) return Status;

        /* Set the buffer and flags */
        Irp->UserBuffer = FileInformation;
        Irp->Flags = (IRP_BUFFERED_IO |

⌨️ 快捷键说明

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