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