From: Rose Hellsing <rose@pinkro.se> --- dlls/wow64/struct32.h | 12 +++ dlls/wow64/sync.c | 167 ++++++++++++++++++++++++++++++++----- dlls/wow64/wow64_private.h | 31 +++++++ 3 files changed, 191 insertions(+), 19 deletions(-) diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h index de378c13cc2..6d1acf6736e 100644 --- a/dlls/wow64/struct32.h +++ b/dlls/wow64/struct32.h @@ -749,4 +749,16 @@ typedef struct LARGE_INTEGER TimeLimit; } QUOTA_LIMITS32; +typedef struct +{ + USHORT DataSize; + USHORT MessageSize; + USHORT MessageType; + USHORT VirtualRangesOffset; + CLIENT_ID32 ClientId; + ULONG MessageId; + ULONG SectionSize; + UCHAR Data[ANYSIZE_ARRAY]; +} LPC_MESSAGE32; + #endif /* __WOW64_STRUCT32_H */ diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index c4ba357979b..ecd3994cd15 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -135,13 +135,22 @@ NTSTATUS WINAPI wow64_NtAcceptConnectPort( UINT *args ) { ULONG *handle_ptr = get_ptr( &args ); ULONG id = get_ulong( &args ); - LPC_MESSAGE *msg = get_ptr( &args ); + LPC_MESSAGE32 *msg32 = get_ptr( &args ); BOOLEAN accept = get_ulong( &args ); LPC_SECTION_WRITE *write = get_ptr( &args ); LPC_SECTION_READ *read = get_ptr( &args ); + LPC_MESSAGE *msg = NULL; HANDLE handle = 0; NTSTATUS status; + ULONG size; + + if (msg32) + { + size = sizeof(LPC_MESSAGE) + msg32->DataSize; + msg = Wow64AllocateTemp( size ); + lpc_message_32to64( msg, msg32 ); + } status = NtAcceptConnectPort( &handle, id, msg, accept, write, read ); put_handle( handle_ptr, handle ); @@ -558,10 +567,19 @@ NTSTATUS WINAPI wow64_NtDuplicateObject( UINT *args ) NTSTATUS WINAPI wow64_NtImpersonateClientOfPort( UINT *args ) { HANDLE handle = get_handle( &args ); - LPC_MESSAGE *msg = get_ptr( &args ); + LPC_MESSAGE32 *msg32 = get_ptr( &args ); - FIXME( "%p %p: stub\n", handle, msg ); - return STATUS_NOT_IMPLEMENTED; + LPC_MESSAGE *msg = NULL; + ULONG size; + + if (msg32) + { + size = sizeof(LPC_MESSAGE) + msg32->DataSize; + msg = Wow64AllocateTemp( size ); + lpc_message_32to64( msg, msg32 ); + } + + return NtImpersonateClientOfPort( handle, msg ); } @@ -571,9 +589,26 @@ NTSTATUS WINAPI wow64_NtImpersonateClientOfPort( UINT *args ) NTSTATUS WINAPI wow64_NtListenPort( UINT *args ) { HANDLE handle = get_handle( &args ); - LPC_MESSAGE *msg = get_ptr( &args ); + LPC_MESSAGE32 *msg32 = get_ptr( &args ); + + LPC_MESSAGE *msg = NULL; + NTSTATUS status; + ULONG size; + + if (msg32) + { + /* Allocate enough space for max LPC message data */ + size = sizeof(LPC_MESSAGE) + 0x1000; + msg = Wow64AllocateTemp( size ); + memset( msg, 0, size ); + } + + status = NtListenPort( handle, msg ); - return NtListenPort( handle, msg ); + if (!status && msg32) + put_lpc_message( msg32, msg ); + + return status; } @@ -1325,9 +1360,20 @@ NTSTATUS WINAPI wow64_NtReadRequestData( UINT *args ) NTSTATUS WINAPI wow64_NtReplyPort( UINT *args ) { HANDLE handle = get_handle( &args ); - LPC_MESSAGE *reply = get_ptr( &args ); + LPC_MESSAGE32 *reply32 = get_ptr( &args ); + + LPC_MESSAGE *reply; + NTSTATUS status; + ULONG size; - return NtReplyPort( handle, reply ); + if (!reply32) return NtReplyPort( handle, NULL ); + + size = sizeof(LPC_MESSAGE) + reply32->DataSize; + reply = Wow64AllocateTemp( size ); + lpc_message_32to64( reply, reply32 ); + + status = NtReplyPort( handle, reply ); + return status; } @@ -1338,10 +1384,34 @@ NTSTATUS WINAPI wow64_NtReplyWaitReceivePort( UINT *args ) { HANDLE handle = get_handle( &args ); ULONG *id = get_ptr( &args ); - LPC_MESSAGE *reply = get_ptr( &args ); - LPC_MESSAGE *msg = get_ptr( &args ); + LPC_MESSAGE32 *reply32 = get_ptr( &args ); + LPC_MESSAGE32 *msg32 = get_ptr( &args ); + + LPC_MESSAGE *reply = NULL; + LPC_MESSAGE *msg = NULL; + NTSTATUS status; + ULONG size; + + if (reply32) + { + size = sizeof(LPC_MESSAGE) + reply32->DataSize; + reply = Wow64AllocateTemp( size ); + lpc_message_32to64( reply, reply32 ); + } + if (msg32) + { + /* Allocate enough space for max LPC message data */ + size = sizeof(LPC_MESSAGE) + 0x1000; + msg = Wow64AllocateTemp( size ); + memset( msg, 0, size ); + } - return NtReplyWaitReceivePort( handle, id, reply, msg ); + status = NtReplyWaitReceivePort( handle, id, reply, msg ); + + if (!status && msg32) + put_lpc_message( msg32, msg ); + + return status; } @@ -1352,11 +1422,35 @@ NTSTATUS WINAPI wow64_NtReplyWaitReceivePortEx( UINT *args ) { HANDLE handle = get_handle( &args ); ULONG *id = get_ptr( &args ); - LPC_MESSAGE *reply = get_ptr( &args ); - LPC_MESSAGE *msg = get_ptr( &args ); + LPC_MESSAGE32 *reply32 = get_ptr( &args ); + LPC_MESSAGE32 *msg32 = get_ptr( &args ); LARGE_INTEGER *timeout = get_ptr( &args ); - return NtReplyWaitReceivePortEx( handle, id, reply, msg, timeout ); + LPC_MESSAGE *reply = NULL; + LPC_MESSAGE *msg = NULL; + NTSTATUS status; + ULONG size; + + if (reply32) + { + size = sizeof(LPC_MESSAGE) + reply32->DataSize; + reply = Wow64AllocateTemp( size ); + lpc_message_32to64( reply, reply32 ); + } + if (msg32) + { + /* Allocate enough space for max LPC message data */ + size = sizeof(LPC_MESSAGE) + 0x1000; + msg = Wow64AllocateTemp( size ); + memset( msg, 0, size ); + } + + status = NtReplyWaitReceivePortEx( handle, id, reply, msg, timeout ); + + if (!status && msg32) + put_lpc_message( msg32, msg ); + + return status; } @@ -1366,9 +1460,20 @@ NTSTATUS WINAPI wow64_NtReplyWaitReceivePortEx( UINT *args ) NTSTATUS WINAPI wow64_NtRequestPort( UINT *args ) { HANDLE handle = get_handle( &args ); - LPC_MESSAGE *msg = get_ptr( &args ); + LPC_MESSAGE32 *msg32 = get_ptr( &args ); + + LPC_MESSAGE *msg; + NTSTATUS status; + ULONG size; + + if (!msg32) return NtRequestPort( handle, NULL ); - return NtRequestPort( handle, msg ); + size = sizeof(LPC_MESSAGE) + msg32->DataSize; + msg = Wow64AllocateTemp( size ); + lpc_message_32to64( msg, msg32 ); + + status = NtRequestPort( handle, msg ); + return status; } @@ -1378,10 +1483,34 @@ NTSTATUS WINAPI wow64_NtRequestPort( UINT *args ) NTSTATUS WINAPI wow64_NtRequestWaitReplyPort( UINT *args ) { HANDLE handle = get_handle( &args ); - LPC_MESSAGE *msg_in = get_ptr( &args ); - LPC_MESSAGE *msg_out = get_ptr( &args ); + LPC_MESSAGE32 *msg_in32 = get_ptr( &args ); + LPC_MESSAGE32 *msg_out32 = get_ptr( &args ); + + LPC_MESSAGE *msg_in = NULL; + LPC_MESSAGE *msg_out = NULL; + NTSTATUS status; + ULONG size; + + if (msg_in32) + { + size = sizeof(LPC_MESSAGE) + msg_in32->DataSize; + msg_in = Wow64AllocateTemp( size ); + lpc_message_32to64( msg_in, msg_in32 ); + } + if (msg_out32) + { + /* Allocate enough space for max LPC message data */ + size = sizeof(LPC_MESSAGE) + 0x1000; + msg_out = Wow64AllocateTemp( size ); + memset( msg_out, 0, size ); + } - return NtRequestWaitReplyPort( handle, msg_in, msg_out ); + status = NtRequestWaitReplyPort( handle, msg_in, msg_out ); + + if (!status && msg_out32) + put_lpc_message( msg_out32, msg_out ); + + return status; } diff --git a/dlls/wow64/wow64_private.h b/dlls/wow64/wow64_private.h index deca72d445c..f1c4ff9e469 100644 --- a/dlls/wow64/wow64_private.h +++ b/dlls/wow64/wow64_private.h @@ -241,6 +241,37 @@ static inline void put_client_id( CLIENT_ID32 *id32, const CLIENT_ID *id ) id32->UniqueThread = HandleToLong( id->UniqueThread ); } +static inline LPC_MESSAGE *lpc_message_32to64( LPC_MESSAGE *msg, const LPC_MESSAGE32 *msg32 ) +{ + if (!msg32) return NULL; + msg->DataSize = msg32->DataSize; + msg->MessageSize = msg32->MessageSize; + msg->MessageType = msg32->MessageType; + msg->VirtualRangesOffset = msg32->VirtualRangesOffset; + msg->ClientId.UniqueProcess = LongToHandle( msg32->ClientId.UniqueProcess ); + msg->ClientId.UniqueThread = LongToHandle( msg32->ClientId.UniqueThread ); + msg->MessageId = msg32->MessageId; + msg->SectionSize = msg32->SectionSize; + if (msg32->DataSize) + memcpy( msg->Data, msg32->Data, msg32->DataSize ); + return msg; +} + +static inline void put_lpc_message( LPC_MESSAGE32 *msg32, const LPC_MESSAGE *msg ) +{ + if (!msg32) return; + msg32->DataSize = msg->DataSize; + msg32->MessageSize = sizeof(LPC_MESSAGE32) + msg->DataSize; + msg32->MessageType = msg->MessageType; + msg32->VirtualRangesOffset = msg->VirtualRangesOffset; + msg32->ClientId.UniqueProcess = HandleToLong( msg->ClientId.UniqueProcess ); + msg32->ClientId.UniqueThread = HandleToLong( msg->ClientId.UniqueThread ); + msg32->MessageId = msg->MessageId; + msg32->SectionSize = msg->SectionSize; + if (msg->DataSize) + memcpy( msg32->Data, msg->Data, msg->DataSize ); +} + static inline void put_iosb( IO_STATUS_BLOCK32 *io32, const IO_STATUS_BLOCK *io ) { /* sync I/O modifies the 64-bit iosb right away, so in that case we update the 32-bit one */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10611