From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/signal_arm64ec.c | 1 + dlls/ntdll/tests/om.c | 1 - dlls/ntdll/unix/sync.c | 26 ++++++++++++ dlls/wow64/sync.c | 21 ++++++++++ include/winternl.h | 1 + server/completion.c | 84 ++++++++++++++++++++++++++++++++++++- server/directory.c | 1 + server/object.h | 1 + server/protocol.def | 9 ++++ 10 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 7c2e494e4ad..c089b4129a3 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -201,6 +201,7 @@ @ stdcall -syscall NtCreateToken(ptr long ptr long ptr ptr ptr ptr ptr ptr ptr ptr ptr) @ stdcall -syscall NtCreateTransaction(ptr long ptr ptr long long long long ptr ptr) @ stdcall -syscall NtCreateUserProcess(ptr ptr long long ptr ptr long long ptr ptr ptr) +@ stdcall -syscall NtCreateWaitCompletionPacket(ptr long ptr) # @ stub NtCreateWaitablePort @ stdcall -arch=i386 NtCurrentTeb() @ stdcall -syscall NtDebugActiveProcess(long long) diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 0f4b55b60c4..af6c11d3cea 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -399,6 +399,7 @@ DEFINE_SYSCALL(NtCreateThreadEx, (HANDLE *handle, ACCESS_MASK access, OBJECT_ATT DEFINE_SYSCALL(NtCreateTimer, (HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, TIMER_TYPE type)) DEFINE_SYSCALL(NtCreateToken, (HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, TOKEN_TYPE type, LUID *token_id, LARGE_INTEGER *expire, TOKEN_USER *user, TOKEN_GROUPS *groups, TOKEN_PRIVILEGES *privs, TOKEN_OWNER *owner, TOKEN_PRIMARY_GROUP *group, TOKEN_DEFAULT_DACL *dacl, TOKEN_SOURCE *source)) DEFINE_SYSCALL(NtCreateTransaction, (HANDLE *handle, ACCESS_MASK mask, OBJECT_ATTRIBUTES *obj_attr, GUID *guid, HANDLE tm, ULONG options, ULONG isol_level, ULONG isol_flags, PLARGE_INTEGER timeout, UNICODE_STRING *description)) +DEFINE_SYSCALL(NtCreateWaitCompletionPacket, (HANDLE *handle, ACCESS_MASK mask, OBJECT_ATTRIBUTES *obj_attr)) DEFINE_SYSCALL(NtCreateUserProcess, (HANDLE *process_handle_ptr, HANDLE *thread_handle_ptr, ACCESS_MASK process_access, ACCESS_MASK thread_access, OBJECT_ATTRIBUTES *process_attr, OBJECT_ATTRIBUTES *thread_attr, ULONG process_flags, ULONG thread_flags, RTL_USER_PROCESS_PARAMETERS *params, PS_CREATE_INFO *info, PS_ATTRIBUTE_LIST *ps_attr)) DEFINE_SYSCALL(NtDebugActiveProcess, (HANDLE process, HANDLE debug)) DEFINE_SYSCALL(NtDebugContinue, (HANDLE handle, CLIENT_ID *client, NTSTATUS status)) diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c index 8a62ba39893..ed3e48b421c 100644 --- a/dlls/ntdll/tests/om.c +++ b/dlls/ntdll/tests/om.c @@ -2412,7 +2412,6 @@ static void test_object_types(void) break; }
- todo_wine_if(!lstrcmpW(tests[i].name, L"WaitCompletionPacket")) ok( broken(!lstrcmpW(tests[i].name, L"WaitCompletionPacket") && j == ARRAY_SIZE(all_types)) /* Win7 doesn't have WaitCompletionPacket */ || j < ARRAY_SIZE(all_types), "type %s not found\n", debugstr_w(tests[i].name) ); } diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 117915beb19..a5d9f830c2e 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2872,6 +2872,32 @@ NTSTATUS WINAPI NtCreateTransaction( HANDLE *handle, ACCESS_MASK mask, OBJECT_AT return STATUS_SUCCESS; }
+/*********************************************************************** + * NtCreateWaitCompletionPacket (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateWaitCompletionPacket( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr ) +{ + struct object_attributes *objattr; + unsigned int ret; + data_size_t len; + + TRACE( "%p, %08x, %p\n", handle, (int)access, attr ); + + *handle = 0; + if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; + + SERVER_START_REQ( create_completion_packet ) + { + req->access = access; + wine_server_add_data( req, objattr, len ); + if (!(ret = wine_server_call( req ))) + *handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + free( objattr ); + return ret; +} + /*********************************************************************** * NtCommitTransaction (NTDLL.@) */ diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index 537e695cc87..4cf4d3b6f2a 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1858,6 +1858,27 @@ NTSTATUS WINAPI wow64_NtCreateTransaction( UINT *args ) }
+/********************************************************************** + * wow64_NtCreateWaitCompletionPacket + */ +NTSTATUS WINAPI wow64_NtCreateWaitCompletionPacket( UINT *args ) +{ + ULONG *handle_ptr = get_ptr( &args ); + ACCESS_MASK access = get_ulong( &args ); + OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args ); + + struct object_attr64 attr; + HANDLE handle = 0; + NTSTATUS status; + + *handle_ptr = 0; + status = NtCreateWaitCompletionPacket( &handle, access, objattr_32to64( &attr, attr32 )); + put_handle( handle_ptr, handle ); + + return status; +} + + /********************************************************************** * wow64_NtCommitTransaction */ diff --git a/include/winternl.h b/include/winternl.h index ae2689165f3..2137965ebef 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4502,6 +4502,7 @@ NTSYSAPI NTSTATUS WINAPI NtCreateThreadEx(HANDLE*,ACCESS_MASK,OBJECT_ATTRIBUTES NTSYSAPI NTSTATUS WINAPI NtCreateTimer(HANDLE*, ACCESS_MASK, const OBJECT_ATTRIBUTES*, TIMER_TYPE); NTSYSAPI NTSTATUS WINAPI NtCreateToken(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,TOKEN_TYPE,PLUID,PLARGE_INTEGER,PTOKEN_USER,PTOKEN_GROUPS,PTOKEN_PRIVILEGES,PTOKEN_OWNER,PTOKEN_PRIMARY_GROUP,PTOKEN_DEFAULT_DACL,PTOKEN_SOURCE); NTSYSAPI NTSTATUS WINAPI NtCreateTransaction(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,LPGUID,HANDLE,ULONG,ULONG,ULONG,PLARGE_INTEGER,PUNICODE_STRING); +NTSYSAPI NTSTATUS WINAPI NtCreateWaitCompletionPacket(HANDLE *,ACCESS_MASK,OBJECT_ATTRIBUTES *); NTSYSAPI NTSTATUS WINAPI NtCreateUserProcess(HANDLE*,HANDLE*,ACCESS_MASK,ACCESS_MASK,OBJECT_ATTRIBUTES*,OBJECT_ATTRIBUTES*,ULONG,ULONG,RTL_USER_PROCESS_PARAMETERS*,PS_CREATE_INFO*,PS_ATTRIBUTE_LIST*); NTSYSAPI NTSTATUS WINAPI NtDebugActiveProcess(HANDLE,HANDLE); NTSYSAPI NTSTATUS WINAPI NtDebugContinue(HANDLE,CLIENT_ID*,NTSTATUS); diff --git a/server/completion.c b/server/completion.c index a2028a89823..4bf264f379d 100644 --- a/server/completion.c +++ b/server/completion.c @@ -36,7 +36,6 @@ #include "handle.h" #include "request.h"
- static const WCHAR completion_name[] = {'I','o','C','o','m','p','l','e','t','i','o','n'};
struct type_descr completion_type = @@ -79,6 +78,11 @@ struct completion unsigned int depth; };
+struct completion_packet +{ + struct object obj; /* object header */ +}; + static void completion_wait_dump( struct object*, int ); static int completion_wait_signaled( struct object *obj, struct wait_queue_entry *entry ); static void completion_wait_satisfied( struct object *obj, struct wait_queue_entry *entry ); @@ -319,6 +323,61 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ if (!list_empty( &completion->queue )) signal_sync( completion->sync ); }
+static const WCHAR completion_packet_name[] = {'W','a','i','t','C','o','m','p','l','e','t','i','o','n','P','a','c','k','e','t'}; + +struct type_descr completion_packet_type = +{ + { completion_packet_name, sizeof(completion_packet_name) }, /* name */ + WAIT_COMPLETION_PACKET_ALL_ACCESS | SYNCHRONIZE, /* valid_access */ + { /* mapping */ + WAIT_COMPLETION_PACKET_GENERIC_READ, + WAIT_COMPLETION_PACKET_GENERIC_WRITE, + WAIT_COMPLETION_PACKET_GENERIC_EXECUTE, + WAIT_COMPLETION_PACKET_ALL_ACCESS + }, +}; + +static void completion_packet_dump( struct object *, int ); + +static const struct object_ops completion_packet_ops = +{ + sizeof(struct completion_packet), /* size */ + &completion_packet_type, /* type */ + completion_packet_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ + default_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + default_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + no_destroy /* destroy */ +}; + +static void completion_packet_dump( struct object *obj, int verbose ) +{ + assert( obj->ops == &completion_packet_ops ); + fprintf( stderr, "WaitCompletionPacket\n" ); +} + +static struct completion_packet *create_completion_packet( struct object *root, + const struct unicode_str *name, + unsigned int attr, + const struct security_descriptor *sd ) +{ + return create_named_object( root, &completion_packet_ops, name, attr, sd ); +} + /* create a completion */ DECL_HANDLER(create_completion) { @@ -454,3 +513,26 @@ DECL_HANDLER(query_completion)
release_object( completion ); } + +/* create a wait completion packet */ +DECL_HANDLER(create_completion_packet) +{ + struct completion_packet *packet; + struct unicode_str name; + struct object *root; + const struct security_descriptor *sd; + const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root ); + + if (!objattr) return; + if ((packet = create_completion_packet( root, &name, objattr->attributes, sd ))) + { + if (get_error() == STATUS_OBJECT_NAME_EXISTS) + reply->handle = alloc_handle( current->process, packet, req->access, objattr->attributes ); + else + reply->handle = alloc_handle_no_access_check( current->process, packet, + req->access, objattr->attributes ); + release_object( packet ); + } + + if (root) release_object( root ); +} diff --git a/server/directory.c b/server/directory.c index c56c216d6d5..bbb89304bed 100644 --- a/server/directory.c +++ b/server/directory.c @@ -165,6 +165,7 @@ static struct type_descr *types[] = &key_type, &apc_reserve_type, &completion_reserve_type, + &completion_packet_type, };
static void object_type_dump( struct object *obj, int verbose ) diff --git a/server/object.h b/server/object.h index 1bf439338d4..5df9b380f0c 100644 --- a/server/object.h +++ b/server/object.h @@ -353,6 +353,7 @@ extern struct type_descr mapping_type; extern struct type_descr key_type; extern struct type_descr apc_reserve_type; extern struct type_descr completion_reserve_type; +extern struct type_descr completion_packet_type;
#define KEYEDEVENT_WAIT 0x0001 #define KEYEDEVENT_WAKE 0x0002 diff --git a/server/protocol.def b/server/protocol.def index 22470e33ae0..3b7e8efbde4 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3884,6 +3884,15 @@ struct handle_info @END
+/* create a wait completion packet */ +@REQ(create_completion_packet) + unsigned int access; /* desired access */ + VARARG(objattr,object_attributes); /* object attributes */ +@REPLY + obj_handle_t handle; /* wait completion packet handle */ +@END + + /* check for associated completion and push msg */ @REQ(add_fd_completion) obj_handle_t handle; /* async' object */