Module: wine Branch: master Commit: ad7c1392cece0046cf3a0d97c96357d2dbf44b8f URL: https://source.winehq.org/git/wine.git/?a=commit;h=ad7c1392cece0046cf3a0d97c...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Feb 26 13:39:43 2019 +0100
ntoskrnl.exe: Add partial ObReferenceObjectByHandle implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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);