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 | 24 ++++++++++++ dlls/wow64/sync.c | 20 ++++++++++ include/winternl.h | 1 + server/completion.c | 75 +++++++++++++++++++++++++++++++++++++ server/directory.c | 1 + server/file.h | 5 +++ server/object.h | 1 + server/protocol.def | 9 +++++ 11 files changed, 138 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 3bb20691208..e529bd623c8 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -199,6 +199,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 a2811c91af5..00195b41e88 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -294,6 +294,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 8f38b3eecd7..55c838d066d 100644 --- a/dlls/ntdll/tests/om.c +++ b/dlls/ntdll/tests/om.c @@ -2391,7 +2391,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 d486b50001d..b9b883205d8 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2794,6 +2794,30 @@ 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; + + *handle = 0; + if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; + + SERVER_START_REQ( create_wait_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 54dca19dc1a..2f516b8f40c 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1781,6 +1781,26 @@ NTSTATUS WINAPI wow64_NtCreateTransaction( UINT *args ) return status; }
+/********************************************************************** + * 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 4926bd1bf82..aa2427b0f6a 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4528,6 +4528,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 f4fad9dbeca..9edc3d0e041 100644 --- a/server/completion.c +++ b/server/completion.c @@ -36,6 +36,61 @@ #include "handle.h" #include "request.h"
+static const WCHAR wait_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 wait_completion_packet_type = +{ + { wait_completion_packet_name, sizeof(wait_completion_packet_name) }, /* name */ + WAIT_COMPLETION_PACKET_ALL_ACCESS, /* 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 wait_completion_packet_dump( struct object *, int ); + +static const struct object_ops wait_completion_packet_ops = +{ + sizeof(struct wait_completion_packet), /* size */ + &wait_completion_packet_type, /* type */ + wait_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_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 wait_completion_packet_dump( struct object *obj, int verbose ) +{ + struct wait_completion_packet *packet = (struct wait_completion_packet *)obj; + + assert( obj->ops == &wait_completion_packet_ops ); + fprintf( stderr, "WaitCompletionPacket\n" ); +} + +static struct wait_completion_packet *create_wait_completion_packet( struct object *root, + const struct unicode_str *name, + unsigned int attr, + const struct security_descriptor *sd ) +{ + return create_named_object( root, &wait_completion_packet_ops, name, attr, sd ); +}
static const WCHAR completion_name[] = {'I','o','C','o','m','p','l','e','t','i','o','n'};
@@ -310,6 +365,26 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); }
+/* create a wait completion packet */ +DECL_HANDLER(create_wait_completion_packet) +{ + struct wait_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_wait_completion_packet( root, &name, objattr->attributes, sd )) + && get_error() != STATUS_OBJECT_NAME_EXISTS) + { + reply->handle = alloc_handle( current->process, packet, req->access, objattr->attributes ); + release_object( packet ); + } + + if (root) release_object( root ); +} + /* create a completion */ DECL_HANDLER(create_completion) { diff --git a/server/directory.c b/server/directory.c index b37ec969a9e..cbf53b12f3b 100644 --- a/server/directory.c +++ b/server/directory.c @@ -163,6 +163,7 @@ static struct type_descr *types[] = &key_type, &apc_reserve_type, &completion_reserve_type, + &wait_completion_packet_type, };
static void object_type_dump( struct object *obj, int verbose ) diff --git a/server/file.h b/server/file.h index 4f5fc7b26f1..5e988376e55 100644 --- a/server/file.h +++ b/server/file.h @@ -48,6 +48,11 @@ struct async_queue struct list queue; /* queue of async objects */ };
+struct wait_completion_packet +{ + struct object obj; /* object header */ +}; + /* operations valid on file descriptor objects */ struct fd_ops { diff --git a/server/object.h b/server/object.h index 7555f564a08..e02dbdc6b71 100644 --- a/server/object.h +++ b/server/object.h @@ -333,6 +333,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 wait_completion_packet_type;
#define KEYEDEVENT_WAIT 0x0001 #define KEYEDEVENT_WAKE 0x0002 diff --git a/server/protocol.def b/server/protocol.def index bd0307c5d79..5f9431d9517 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3849,6 +3849,15 @@ struct handle_info @END
+/* create a wait completion packet */ +@REQ(create_wait_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 */