From f57a383d090469895954a861083401b2ab81eb02 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 25 Mar 2019 14:38:57 +0100 Subject: [PATCH] ntoskrnl.exe: Support waiting on kernel objects. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/ntoskrnl.exe/ntoskrnl.c | 14 ++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl_private.h | 1 + dlls/ntoskrnl.exe/sync.c | 11 ++++++----- dlls/ntoskrnl.exe/tests/driver.c | 3 +-- include/wine/server_protocol.h | 22 +++++++++++++++++++++- server/device.c | 19 +++++++++++++++++++ server/protocol.def | 10 ++++++++++ server/request.h | 8 ++++++++ server/trace.c | 15 +++++++++++++++ 9 files changed, 95 insertions(+), 8 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 1a4cc749083..77a610d7dba 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -367,6 +367,20 @@ static void ObReferenceObject( void *obj ) LeaveCriticalSection( &obref_cs ); } +HANDLE kernel_object_handle( void *obj, unsigned int access ) +{ + HANDLE handle = NULL; + SERVER_START_REQ( get_kernel_object_handle ) + { + req->manager = wine_server_obj_handle( get_device_manager() ); + req->user_ptr = wine_server_client_ptr( obj ); + req->access = access; + if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + return handle; +} + static const POBJECT_TYPE *known_types[] = { &ExEventObjectType, diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h index 9bef13dfced..82ee18e56a4 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl_private.h +++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h @@ -28,6 +28,7 @@ struct _OBJECT_TYPE { }; void *alloc_kernel_object( POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG ref ) DECLSPEC_HIDDEN; +HANDLE kernel_object_handle( void *obj, unsigned int access ) DECLSPEC_HIDDEN; extern POBJECT_TYPE ExEventObjectType; extern POBJECT_TYPE ExSemaphoreObjectType; diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 7cb31852dae..5a72bc516bb 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -78,8 +78,7 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[], { if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE) { - FIXME("unsupported on kernel objects\n"); - handles[i] = INVALID_HANDLE_VALUE; + handles[i] = kernel_object_handle( objs[i], SYNCHRONIZE ); continue; } @@ -134,9 +133,11 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[], } } - if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE) continue; - - if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink)) + if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE) + { + NtClose( handles[i] ); + } + else if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink)) { switch (objs[i]->Type) { diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 55455d7a40d..0fc0058a284 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -458,10 +458,10 @@ static void test_sync(void) ok(!ret, "ObReferenceObjectByHandle failed: %#x\n", ret); ret = wait_single(event, 0); - todo_wine ok(ret == 0, "got %#x\n", ret); KeResetEvent(event); ret = wait_single(event, 0); + todo_wine ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); ret = wait_single_handle(handle, 0); todo_wine @@ -469,7 +469,6 @@ static void test_sync(void) KeSetEvent(event, 0, FALSE); ret = wait_single(event, 0); - todo_wine ok(ret == 0, "got %#x\n", ret); ret = wait_single_handle(handle, 0); ok(!ret, "got %#x\n", ret); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index cd508941ab1..32d2d6a60b8 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -5309,6 +5309,23 @@ struct release_kernel_object_reply +struct get_kernel_object_handle_request +{ + struct request_header __header; + obj_handle_t manager; + client_ptr_t user_ptr; + unsigned int access; + char __pad_28[4]; +}; +struct get_kernel_object_handle_reply +{ + struct reply_header __header; + obj_handle_t handle; + char __pad_12[4]; +}; + + + struct make_process_system_request { struct request_header __header; @@ -5999,6 +6016,7 @@ enum request REQ_set_kernel_object_ptr, REQ_grab_kernel_object, REQ_release_kernel_object, + REQ_get_kernel_object_handle, REQ_make_process_system, REQ_get_token_statistics, REQ_create_completion, @@ -6301,6 +6319,7 @@ union generic_request struct set_kernel_object_ptr_request set_kernel_object_ptr_request; struct grab_kernel_object_request grab_kernel_object_request; struct release_kernel_object_request release_kernel_object_request; + struct get_kernel_object_handle_request get_kernel_object_handle_request; struct make_process_system_request make_process_system_request; struct get_token_statistics_request get_token_statistics_request; struct create_completion_request create_completion_request; @@ -6601,6 +6620,7 @@ union generic_reply struct set_kernel_object_ptr_reply set_kernel_object_ptr_reply; struct grab_kernel_object_reply grab_kernel_object_reply; struct release_kernel_object_reply release_kernel_object_reply; + struct get_kernel_object_handle_reply get_kernel_object_handle_reply; struct make_process_system_reply make_process_system_reply; struct get_token_statistics_reply get_token_statistics_reply; struct create_completion_reply create_completion_reply; @@ -6630,6 +6650,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 575 +#define SERVER_PROTOCOL_VERSION 576 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/device.c b/server/device.c index e9cf43f4016..5880ea620b9 100644 --- a/server/device.c +++ b/server/device.c @@ -969,3 +969,22 @@ DECL_HANDLER(release_kernel_object) release_object( manager ); } + + +/* get handle from kernel object pointer */ +DECL_HANDLER(get_kernel_object_handle) +{ + struct device_manager *manager; + struct kernel_object *ref; + + if (!(manager = (struct device_manager *)get_handle_obj( current->process, req->manager, + 0, &device_manager_ops ))) + return; + + if ((ref = kernel_object_from_ptr( manager, req->user_ptr ))) + reply->handle = alloc_handle( current->process, ref->object, req->access, 0 ); + else + set_error( STATUS_INVALID_HANDLE ); + + release_object( manager ); +} diff --git a/server/protocol.def b/server/protocol.def index f889e3b2d4f..6cdd59fa84a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3660,6 +3660,16 @@ struct handle_info @END +/* Get handle from kernel object pointer */ +@REQ(get_kernel_object_handle) + obj_handle_t manager; /* handle to the device manager */ + client_ptr_t user_ptr; /* kernel object pointer */ + unsigned int access; /* wanted access rights */ +@REPLY + obj_handle_t handle; /* kernel object handle */ +@END + + /* Make the current process a system process */ @REQ(make_process_system) @REPLY diff --git a/server/request.h b/server/request.h index da4d942bb73..4d143a51b06 100644 --- a/server/request.h +++ b/server/request.h @@ -380,6 +380,7 @@ DECL_HANDLER(get_kernel_object_ptr); DECL_HANDLER(set_kernel_object_ptr); DECL_HANDLER(grab_kernel_object); DECL_HANDLER(release_kernel_object); +DECL_HANDLER(get_kernel_object_handle); DECL_HANDLER(make_process_system); DECL_HANDLER(get_token_statistics); DECL_HANDLER(create_completion); @@ -681,6 +682,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_set_kernel_object_ptr, (req_handler)req_grab_kernel_object, (req_handler)req_release_kernel_object, + (req_handler)req_get_kernel_object_handle, (req_handler)req_make_process_system, (req_handler)req_get_token_statistics, (req_handler)req_create_completion, @@ -2308,6 +2310,12 @@ C_ASSERT( sizeof(struct grab_kernel_object_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct release_kernel_object_request, manager) == 12 ); C_ASSERT( FIELD_OFFSET(struct release_kernel_object_request, user_ptr) == 16 ); C_ASSERT( sizeof(struct release_kernel_object_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct get_kernel_object_handle_request, manager) == 12 ); +C_ASSERT( FIELD_OFFSET(struct get_kernel_object_handle_request, user_ptr) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_kernel_object_handle_request, access) == 24 ); +C_ASSERT( sizeof(struct get_kernel_object_handle_request) == 32 ); +C_ASSERT( FIELD_OFFSET(struct get_kernel_object_handle_reply, handle) == 8 ); +C_ASSERT( sizeof(struct get_kernel_object_handle_reply) == 16 ); C_ASSERT( sizeof(struct make_process_system_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct make_process_system_reply, event) == 8 ); C_ASSERT( sizeof(struct make_process_system_reply) == 16 ); diff --git a/server/trace.c b/server/trace.c index d79549345cf..1e590ef532e 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4328,6 +4328,18 @@ static void dump_release_kernel_object_request( const struct release_kernel_obje dump_uint64( ", user_ptr=", &req->user_ptr ); } +static void dump_get_kernel_object_handle_request( const struct get_kernel_object_handle_request *req ) +{ + fprintf( stderr, " manager=%04x", req->manager ); + dump_uint64( ", user_ptr=", &req->user_ptr ); + fprintf( stderr, ", access=%08x", req->access ); +} + +static void dump_get_kernel_object_handle_reply( const struct get_kernel_object_handle_reply *req ) +{ + fprintf( stderr, " handle=%04x", req->handle ); +} + static void dump_make_process_system_request( const struct make_process_system_request *req ) { } @@ -4845,6 +4857,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_set_kernel_object_ptr_request, (dump_func)dump_grab_kernel_object_request, (dump_func)dump_release_kernel_object_request, + (dump_func)dump_get_kernel_object_handle_request, (dump_func)dump_make_process_system_request, (dump_func)dump_get_token_statistics_request, (dump_func)dump_create_completion_request, @@ -5143,6 +5156,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { NULL, NULL, NULL, + (dump_func)dump_get_kernel_object_handle_reply, (dump_func)dump_make_process_system_reply, (dump_func)dump_get_token_statistics_reply, (dump_func)dump_create_completion_reply, @@ -5441,6 +5455,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "set_kernel_object_ptr", "grab_kernel_object", "release_kernel_object", + "get_kernel_object_handle", "make_process_system", "get_token_statistics", "create_completion",