From: Rose Hellsing <rose@pinkro.se> Implement client-side LPC message sending: - NtRequestPort: Send a datagram message - NtRequestWaitReplyPort: Send a request message and wait for a reply NtRequestWaitReplyPort loops until a reply is received, waiting on the port for message availability. --- dlls/ntdll/ntdll.spec | 4 +- dlls/ntdll/signal_arm64ec.c | 1 + dlls/ntdll/unix/sync.c | 91 ++++++++++++++++++++++++++++++++++--- dlls/wow64/sync.c | 18 ++++++-- 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5aa620bd60b..0ee1b0303a0 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -370,7 +370,7 @@ @ stdcall -syscall=0x000b NtReplyWaitReceivePort(ptr ptr ptr ptr) @ stdcall -syscall=0x002b NtReplyWaitReceivePortEx(long ptr ptr ptr ptr) # @ stub NtReplyWaitReplyPort -# @ stub NtRequestPort +@ stdcall -syscall NtRequestPort(ptr ptr) @ stdcall -syscall=0x0022 NtRequestWaitReplyPort(ptr ptr ptr) @ stdcall -syscall NtResetEvent(long ptr) @ stdcall -syscall NtResetWriteWatch(long ptr long) @@ -1442,7 +1442,7 @@ @ stdcall -private ZwReplyWaitReceivePort(ptr ptr ptr ptr) NtReplyWaitReceivePort @ stdcall -private ZwReplyWaitReceivePortEx(long ptr ptr ptr ptr) NtReplyWaitReceivePortEx # @ stub ZwReplyWaitReplyPort -# @ stub ZwRequestPort +@ stdcall -private ZwRequestPort(ptr ptr) NtRequestPort @ stdcall -private ZwRequestWaitReplyPort(ptr ptr ptr) NtRequestWaitReplyPort @ stdcall -private ZwResetEvent(long ptr) NtResetEvent @ stdcall -private ZwResetWriteWatch(long ptr long) NtResetWriteWatch diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 73a67029bb9..4a39b3edfaa 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -532,6 +532,7 @@ DEFINE_SYSCALL(NtReplaceKey, (OBJECT_ATTRIBUTES *attr, HANDLE key, OBJECT_ATTRIB DEFINE_SYSCALL(NtReplyPort, (HANDLE handle, LPC_MESSAGE *reply)) DEFINE_SYSCALL(NtReplyWaitReceivePort, (HANDLE handle, ULONG *id, LPC_MESSAGE *reply, LPC_MESSAGE *msg)) DEFINE_SYSCALL(NtReplyWaitReceivePortEx, (HANDLE handle, ULONG *id, LPC_MESSAGE *reply, LPC_MESSAGE *msg, LARGE_INTEGER *timeout)) +DEFINE_SYSCALL(NtRequestPort, (HANDLE handle, LPC_MESSAGE *msg)) DEFINE_SYSCALL(NtRequestWaitReplyPort, (HANDLE handle, LPC_MESSAGE *msg_in, LPC_MESSAGE *msg_out)) DEFINE_SYSCALL(NtResetEvent, (HANDLE handle, LONG *prev_state)) DEFINE_SYSCALL(NtResetWriteWatch, (HANDLE process, PVOID base, SIZE_T size)) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 9265b438ff9..d3f82e2cc49 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -3364,13 +3364,90 @@ NTSTATUS WINAPI NtRegisterThreadTerminatePort( HANDLE handle ) */ NTSTATUS WINAPI NtRequestWaitReplyPort( HANDLE handle, LPC_MESSAGE *msg_in, LPC_MESSAGE *msg_out ) { - FIXME( "(%p,%p,%p),stub!\n", handle, msg_in, msg_out ); - if (msg_in) - TRACE("datasize %u msgsize %u type %u ranges %u client %p/%p msgid %lu size %lu data %s\n", - msg_in->DataSize, msg_in->MessageSize, msg_in->MessageType, msg_in->VirtualRangesOffset, - msg_in->ClientId.UniqueProcess, msg_in->ClientId.UniqueThread, msg_in->MessageId, - msg_in->SectionSize, debugstr_an( (const char *)msg_in->Data, msg_in->DataSize )); - return STATUS_NOT_IMPLEMENTED; + unsigned int ret; + USHORT data_size; + + TRACE( "(%p,%p,%p)\n", handle, msg_in, msg_out ); + + if (!msg_in || !msg_out) return STATUS_INVALID_PARAMETER; + + data_size = msg_in->DataSize; + + /* Send the request message */ + SERVER_START_REQ( request_lpc_reply ) + { + req->handle = wine_server_obj_handle( handle ); + req->data_size = data_size; + req->msg_type = 1; /* request */ + wine_server_add_data( req, msg_in->Data, data_size ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + if (ret) return ret; + + /* Wait for and receive the reply */ + for (;;) + { + SERVER_START_REQ( reply_wait_receive_lpc ) + { + req->handle = wine_server_obj_handle( handle ); + req->reply_msg_id = 0; + req->reply_size = 0; + req->timeout = TIMEOUT_INFINITE; + /* Use a reasonable max size for LPC message data. + * sizeof(msg_out->Data) is just 1 due to ANYSIZE_ARRAY. */ + wine_server_set_reply( req, msg_out->Data, 0x1000 ); + ret = wine_server_call( req ); + if (!ret) + { + msg_out->DataSize = reply->data_size; + msg_out->MessageSize = sizeof(*msg_out) + reply->data_size; + msg_out->MessageType = reply->msg_type; + msg_out->VirtualRangesOffset = 0; + msg_out->ClientId.UniqueProcess = ULongToHandle( reply->client_pid ); + msg_out->ClientId.UniqueThread = ULongToHandle( reply->client_tid ); + msg_out->MessageId = reply->msg_id; + msg_out->SectionSize = 0; + } + } + SERVER_END_REQ; + + if (ret != STATUS_PENDING) break; + + /* Wait on port for message availability */ + ret = NtWaitForSingleObject( handle, FALSE, NULL ); + if (ret) break; + } + return ret; +} + + +/*********************************************************************** + * NtRequestPort (NTDLL.@) + */ +NTSTATUS WINAPI NtRequestPort( HANDLE handle, LPC_MESSAGE *msg ) +{ + unsigned int ret; + USHORT data_size; + + TRACE( "(%p,%p)\n", handle, msg ); + + if (!msg) + return STATUS_INVALID_PARAMETER; + + data_size = msg->DataSize; + + SERVER_START_REQ( request_lpc_reply ) + { + req->handle = wine_server_obj_handle( handle ); + req->data_size = data_size; + req->msg_type = 3; /* datagram */ + wine_server_add_data( req, msg->Data, data_size ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; } diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index fad6e1ca304..3b89e633ab1 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1358,8 +1358,19 @@ NTSTATUS WINAPI wow64_NtReplyWaitReceivePortEx( UINT *args ) LPC_MESSAGE *msg = get_ptr( &args ); LARGE_INTEGER *timeout = get_ptr( &args ); - FIXME( "%p %p %p %p %p: stub\n", handle, id, reply, msg, timeout ); - return STATUS_NOT_IMPLEMENTED; + return NtReplyWaitReceivePortEx( handle, id, reply, msg, timeout ); +} + + +/********************************************************************** + * wow64_NtRequestPort + */ +NTSTATUS WINAPI wow64_NtRequestPort( UINT *args ) +{ + HANDLE handle = get_handle( &args ); + LPC_MESSAGE *msg = get_ptr( &args ); + + return NtRequestPort( handle, msg ); } @@ -1372,8 +1383,7 @@ NTSTATUS WINAPI wow64_NtRequestWaitReplyPort( UINT *args ) LPC_MESSAGE *msg_in = get_ptr( &args ); LPC_MESSAGE *msg_out = get_ptr( &args ); - FIXME( "%p %p %p: stub\n", handle, msg_in, msg_out ); - return STATUS_NOT_IMPLEMENTED; + return NtRequestWaitReplyPort( handle, msg_in, msg_out ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10611