https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3b64f7f8fbbc64ada4dfdb6bdd1feff4bac10c1d

commit 3b64f7f8fbbc64ada4dfdb6bdd1feff4bac10c1d
Author: Pierre Schweitzer <pie...@reactos.org>
AuthorDate: Sun Nov 12 22:28:54 2017 +0100

    [NTOSKRNL] Implement (with many FIXMEs) ObReferenceFileObjectForWrite() so 
that it can already do the job!
    CORE-14003
---
 ntoskrnl/include/internal/ob.h |   9 ++++
 ntoskrnl/ob/obref.c            | 108 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+)

diff --git a/ntoskrnl/include/internal/ob.h b/ntoskrnl/include/internal/ob.h
index a78b5ad457..374f4a2c3e 100644
--- a/ntoskrnl/include/internal/ob.h
+++ b/ntoskrnl/include/internal/ob.h
@@ -384,6 +384,15 @@ ObpDeleteObjectType(
     IN PVOID Object
 );
 
+NTSTATUS
+NTAPI
+ObReferenceFileObjectForWrite(
+    IN HANDLE Handle,
+    IN KPROCESSOR_MODE AccessMode,
+    OUT PFILE_OBJECT *FileObject,
+    OUT POBJECT_HANDLE_INFORMATION HandleInformation
+);
+
 //
 // DOS Devices Functions
 //
diff --git a/ntoskrnl/ob/obref.c b/ntoskrnl/ob/obref.c
index 00e2188069..2f4da20149 100644
--- a/ntoskrnl/ob/obref.c
+++ b/ntoskrnl/ob/obref.c
@@ -15,6 +15,8 @@
 #define NDEBUG
 #include <debug.h>
 
+extern ULONG ObpAccessProtectCloseBit;
+
 /* PRIVATE FUNCTIONS *********************************************************/
 
 BOOLEAN
@@ -195,6 +197,112 @@ ObFastReplaceObject(IN PEX_FAST_REF FastRef,
     return OldObject;
 }
 
+NTSTATUS
+NTAPI
+ObReferenceFileObjectForWrite(IN HANDLE Handle,
+                              IN KPROCESSOR_MODE AccessMode,
+                              OUT PFILE_OBJECT *FileObject,
+                              OUT POBJECT_HANDLE_INFORMATION HandleInformation)
+{
+    NTSTATUS Status;
+    PHANDLE_TABLE HandleTable;
+    POBJECT_HEADER ObjectHeader;
+    PHANDLE_TABLE_ENTRY HandleEntry;
+    ACCESS_MASK GrantedAccess, DesiredAccess;
+
+    /* Assume failure */
+    *FileObject = NULL;
+
+    /* Check if this is a special handle */
+    if (HandleToLong(Handle) < 0)
+    {
+        /* Make sure we have a valid kernel handle */
+        if (AccessMode != KernelMode || Handle == NtCurrentProcess() || Handle 
== NtCurrentThread())
+        {
+            return STATUS_INVALID_HANDLE;
+        }
+
+        /* Use the kernel handle table and get the actual handle value */
+        Handle = ObKernelHandleToHandle(Handle);
+        HandleTable = ObpKernelHandleTable;
+    }
+    else
+    {
+        /* Otherwise use this process's handle table */
+        HandleTable = PsGetCurrentProcess()->ObjectTable;
+    }
+
+    ASSERT(HandleTable != NULL);
+    KeEnterCriticalRegion();
+
+    /* Get the handle entry */
+    HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
+    if (HandleEntry)
+    {
+        /* Get the object header and validate the type*/
+        ObjectHeader = ObpGetHandleObject(HandleEntry);
+
+        /* Get the desired access from the file object */
+        if 
(!NT_SUCCESS(IoComputeDesiredAccessFileObject((PFILE_OBJECT)&ObjectHeader->Body,
+                        &DesiredAccess)))
+        {
+            Status = STATUS_OBJECT_TYPE_MISMATCH;
+        }
+        else
+        {
+            /* Extract the granted access from the handle entry */
+            if (BooleanFlagOn(NtGlobalFlag, FLG_KERNEL_STACK_TRACE_DB))
+            {
+                /* FIXME: Translate granted access */
+                GrantedAccess = HandleEntry->GrantedAccess;
+            }
+            else
+            {
+                GrantedAccess = HandleEntry->GrantedAccess & 
~ObpAccessProtectCloseBit;
+            }
+
+            /* FIXME: Get handle information for audit */
+
+            HandleInformation->GrantedAccess = GrantedAccess;
+
+            /* FIXME: Get handle attributes */
+            HandleInformation->HandleAttributes = 0;
+
+            /* Do granted and desired access match? */
+            if (GrantedAccess & DesiredAccess)
+            {
+                /* FIXME: Audit access if required */
+
+                /* Reference the object directly since we have its header */
+                InterlockedIncrement(&ObjectHeader->PointerCount);
+
+                /* Unlock the handle */
+                ExUnlockHandleTableEntry(HandleTable, HandleEntry);
+                KeLeaveCriticalRegion();
+
+                *FileObject = (PFILE_OBJECT)&ObjectHeader->Body;
+
+                /* Return success */
+                ASSERT(*FileObject != NULL);
+                return STATUS_SUCCESS;
+            }
+
+            /* No match, deny write access */
+            Status = STATUS_ACCESS_DENIED;
+
+            ExUnlockHandleTableEntry(HandleTable, HandleEntry);
+        }
+    }
+    else
+    {
+        Status = STATUS_INVALID_HANDLE;
+    }
+
+    /* Return failure status */
+    KeLeaveCriticalRegion();
+    return Status;
+}
+
 /* PUBLIC FUNCTIONS *********************************************************/
 
 LONG_PTR

Reply via email to