Jacek Caban : ntoskrnl.exe: Add partial ObReferenceObjectByHandle implementation.

Alexandre Julliard julliard at winehq.org
Tue Feb 26 15:13:56 CST 2019


Module: wine
Branch: master
Commit: ad7c1392cece0046cf3a0d97c96357d2dbf44b8f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ad7c1392cece0046cf3a0d97c96357d2dbf44b8f

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Feb 26 13:39:43 2019 +0100

ntoskrnl.exe: Add partial ObReferenceObjectByHandle implementation.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/ntoskrnl.c         | 80 ++++++++++++++++++++++++++++--------
 dlls/ntoskrnl.exe/ntoskrnl_private.h |  5 ++-
 dlls/ntoskrnl.exe/tests/driver.c     |  9 ++--
 3 files changed, 70 insertions(+), 24 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 8591cd4..66ad3e3 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -275,6 +275,13 @@ void *alloc_kernel_object( POBJECT_TYPE type, SIZE_T size, LONG ref )
     return header + 1;
 }
 
+/* FIXME: Use ObReferenceObject instead. */
+static void reference_kernel_object( void *obj )
+{
+    struct object_header *header = (struct object_header*)obj - 1;
+    InterlockedIncrement( &header->ref );
+}
+
 /* FIXME: Use ObDereferenceObject instead. */
 static void dereference_kernel_object( void *obj )
 {
@@ -288,11 +295,66 @@ static void ObReferenceObject( void *obj )
     TRACE( "(%p): stub\n", obj );
 }
 
+static NTSTATUS kernel_object_from_handle( HANDLE handle, POBJECT_TYPE type, void **ret )
+{
+    char buf[256];
+    OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buf;
+    ULONG size;
+    void *obj;
+    NTSTATUS status;
+
+    status = NtQueryObject(handle, ObjectTypeInformation, buf, sizeof(buf), &size);
+    if (status) return status;
+
+    if (!!RtlCompareUnicodeStrings(type->name, strlenW(type->name), type_info->TypeName.Buffer,
+                                   type_info->TypeName.Length / sizeof(WCHAR), FALSE))
+        return STATUS_OBJECT_TYPE_MISMATCH;
+
+    FIXME( "semi-stub: returning new %s object instance\n", debugstr_w(type->name) );
+
+    if (type->constructor)
+        obj = type->constructor( handle );
+    else
+    {
+        obj = alloc_kernel_object( type, 0, 0 );
+        FIXME( "No constructor for type %s returning empty %p object\n", debugstr_w(type->name), obj );
+    }
+    if (!obj) return STATUS_NO_MEMORY;
+
+    TRACE( "%p -> %p\n", handle, obj );
+    *ret = obj;
+    return STATUS_SUCCESS;
+}
+
+/***********************************************************************
+ *           ObReferenceObjectByHandle    (NTOSKRNL.EXE.@)
+ */
+NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE handle, ACCESS_MASK access,
+                                           POBJECT_TYPE type,
+                                           KPROCESSOR_MODE mode, void **ptr,
+                                           POBJECT_HANDLE_INFORMATION info )
+{
+    NTSTATUS status;
+
+    TRACE( "%p %x %p %d %p %p\n", handle, access, type, mode, ptr, info );
+
+    if (mode != KernelMode)
+    {
+        FIXME("UserMode access not implemented\n");
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    status = kernel_object_from_handle( handle, type, ptr );
+    if (!status) reference_kernel_object( *ptr );
+    return status;
+}
+
 
 static const WCHAR file_type_name[] = {'F','i','l','e',0};
 
 static struct _OBJECT_TYPE file_type = {
     file_type_name,
+    NULL,
     free_kernel_object
 };
 
@@ -1151,6 +1213,7 @@ static const WCHAR driver_type_name[] = {'D','r','i','v','e','r',0};
 static struct _OBJECT_TYPE driver_type =
 {
     driver_type_name,
+    NULL,
     free_driver_object
 };
 
@@ -1226,6 +1289,7 @@ static const WCHAR device_type_name[] = {'D','e','v','i','c','e',0};
 static struct _OBJECT_TYPE device_type =
 {
     device_type_name,
+    NULL,
     free_kernel_object
 };
 
@@ -2583,22 +2647,6 @@ VOID WINAPI MmUnmapIoSpace( PVOID BaseAddress, SIZE_T NumberOfBytes )
 
 
  /***********************************************************************
- *           ObReferenceObjectByHandle    (NTOSKRNL.EXE.@)
- */
-NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE obj, ACCESS_MASK access,
-                                           POBJECT_TYPE type,
-                                           KPROCESSOR_MODE mode, PVOID* ptr,
-                                           POBJECT_HANDLE_INFORMATION info)
-{
-    FIXME( "stub: %p %x %p %d %p %p\n", obj, access, type, mode, ptr, info);
-
-    if(ptr)
-        *ptr = UlongToHandle(0xdeadbeaf);
-
-    return STATUS_SUCCESS;
-}
-
- /***********************************************************************
  *           ObReferenceObjectByName    (NTOSKRNL.EXE.@)
  */
 NTSTATUS WINAPI ObReferenceObjectByName( UNICODE_STRING *ObjectName,
diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h
index 027036e..87aa4f7 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl_private.h
+++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h
@@ -22,8 +22,9 @@
 #define __WINE_NTOSKRNL_PRIVATE_H
 
 struct _OBJECT_TYPE {
-    const WCHAR *name;      /* object type name used for type validation */
-    void (*release)(void*); /* called when the last reference is released */
+    const WCHAR *name;            /* object type name used for type validation */
+    void *(*constructor)(HANDLE); /* used for creating an object from server handle */
+    void (*release)(void*);       /* called when the last reference is released */
 };
 
 #ifdef __i386__
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index b16c428..aae5839 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -699,14 +699,10 @@ static void test_ob_reference(const WCHAR *test_path)
     ok(!status, "PsCreateSystemThread returned: %#x\n", status);
 
     status = ObReferenceObjectByHandle(NULL, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj1, NULL);
-    todo_wine
     ok(status == STATUS_INVALID_HANDLE, "ObReferenceObjectByHandle failed: %#x\n", status);
-    if (!status) ObDereferenceObject(obj1);
 
     status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj1, NULL);
-    todo_wine
     ok(status == STATUS_OBJECT_TYPE_MISMATCH, "ObReferenceObjectByHandle returned: %#x\n", status);
-    if (!status) ObDereferenceObject(obj1);
 
     status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj1, NULL);
     ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
@@ -718,12 +714,11 @@ static void test_ob_reference(const WCHAR *test_path)
     }
 
     status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj2, NULL);
-    todo_wine
     ok(status == STATUS_OBJECT_TYPE_MISMATCH, "ObReferenceObjectByHandle returned: %#x\n", status);
-    if (!status) ObDereferenceObject(obj2);
 
     status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj2, NULL);
     ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
+    todo_wine
     ok(obj1 == obj2, "obj1 != obj2\n");
 
     ObDereferenceObject(obj1);
@@ -734,6 +729,7 @@ static void test_ob_reference(const WCHAR *test_path)
 
     status = ObReferenceObjectByHandle(file_handle2, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj2, NULL);
     ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
+    todo_wine
     ok(obj1 == obj2, "obj1 != obj2\n");
 
     ObDereferenceObject(obj1);
@@ -744,6 +740,7 @@ static void test_ob_reference(const WCHAR *test_path)
 
     status = ObReferenceObjectByHandle(thread_handle, SYNCHRONIZE, *pPsThreadType, KernelMode, &obj2, NULL);
     ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
+    todo_wine
     ok(obj1 == obj2, "obj1 != obj2\n");
 
     ObDereferenceObject(obj1);




More information about the wine-cvs mailing list