The message queue needs both an inproc sync, to wake inproc waits on a message and trigger a server request, and a server sync, for when the wait is only on the queue and should be optimized into a single server request.
It could be better to avoid a dedicated request to retrieve the queue inproc sync fd, for instance by sending an fd on thread init, but we can use this to duality to gradually introduce inproc syncs requests instead and avoid dead code (even though the code ultimately returns STATUS_NOT_IMPLEMENTED for now). We can change the way queue inproc sync fds are retrieved later on.
-- v3: ntdll: Check inproc sync handle access rights on wait. server: Add a request to retrieve the inproc sync fds. server: Create inproc sync events for message queues. ntdll: Retrieve and cache an ntsync device on process init. ntdll: Add stub functions for in-process synchronization. ntdll: Add some traces to synchronization methods.
From: Elizabeth Figura zfigura@codeweavers.com
Normally we can rely on +server for these, but with fast synchronization we'll be skipping the server. --- dlls/ntdll/unix/sync.c | 59 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 3ad06e1f720..c501a9f5cca 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -74,9 +74,11 @@ HANDLE keyed_event = 0; static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) { if (!timeout) return "(infinite)"; - return wine_dbgstr_longlong( timeout->QuadPart ); + return wine_dbg_sprintf( "%lld.%07ld", (long long)(timeout->QuadPart / TICKSPERSEC), + (long)(timeout->QuadPart % TICKSPERSEC) ); }
+ /* return a monotonic time counter, in Win32 ticks */ static inline ULONGLONG monotonic_counter(void) { @@ -311,6 +313,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ data_size_t len; struct object_attributes *objattr;
+ TRACE( "access %#x, name %s, initial %d, max %d\n", access, + attr ? debugstr_us(attr->ObjectName) : "(null)", initial, max ); + *handle = 0; if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; @@ -338,6 +343,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC { unsigned int ret;
+ TRACE( "access %#x, name %s\n", access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); + *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret;
@@ -397,6 +404,8 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous { unsigned int ret;
+ TRACE( "handle %p, count %u, prev_count %p\n", handle, count, previous ); + SERVER_START_REQ( release_semaphore ) { req->handle = wine_server_obj_handle( handle ); @@ -421,6 +430,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ data_size_t len; struct object_attributes *objattr;
+ TRACE( "access %#x, name %s, type %u, state %u\n", access, + attr ? debugstr_us(attr->ObjectName) : "(null)", type, state ); + *handle = 0; if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; @@ -448,6 +460,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT { unsigned int ret;
+ TRACE( "access %#x, name %s\n", access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); + *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret;
@@ -473,6 +487,8 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret;
+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); @@ -492,6 +508,8 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret;
+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); @@ -521,6 +539,8 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret;
+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); @@ -577,6 +597,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT data_size_t len; struct object_attributes *objattr;
+ TRACE( "access %#x, name %s, owned %u\n", access, + attr ? debugstr_us(attr->ObjectName) : "(null)", owned ); + *handle = 0; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
@@ -602,6 +625,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A { unsigned int ret;
+ TRACE( "access %#x, name %s\n", access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); + *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret;
@@ -627,6 +652,8 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) { unsigned int ret;
+ TRACE( "handle %p, prev_count %p\n", handle, prev_count ); + SERVER_START_REQ( release_mutex ) { req->handle = wine_server_obj_handle( handle ); @@ -1426,6 +1453,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ data_size_t len; struct object_attributes *objattr;
+ TRACE( "access %#x, name %s, type %u\n", access, + attr ? debugstr_us(attr->ObjectName) : "(null)", type ); + *handle = 0; if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; @@ -1453,6 +1483,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT { unsigned int ret;
+ TRACE( "access %#x, name %s\n", access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); + *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret;
@@ -1506,6 +1538,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) { unsigned int ret;
+ TRACE( "handle %p, state %p\n", handle, state ); + SERVER_START_REQ( cancel_timer ) { req->handle = wine_server_obj_handle( handle ); @@ -1574,13 +1608,23 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO { union select_op select_op; UINT i, flags = SELECT_INTERRUPTIBLE; + unsigned int ret;
if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
+ if (TRACE_ON(sync)) + { + TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] ); + for (i = 1; i < count; i++) TRACE( ", %p", handles[i] ); + TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); + } + if (alertable) flags |= SELECT_ALERTABLE; select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); - return server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); + ret = server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); + TRACE( "-> %#x\n", ret ); + return ret; }
@@ -1602,6 +1646,8 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE;
+ TRACE( "signal %p, wait %p, alertable %u, timeout %s\n", signal, wait, alertable, debugstr_timeout(timeout) ); + if (!signal) return STATUS_INVALID_HANDLE;
if (alertable) flags |= SELECT_ALERTABLE; @@ -1846,6 +1892,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, data_size_t len; struct object_attributes *objattr;
+ TRACE( "access %#x, name %s, flags %#x\n", access, + attr ? debugstr_us(attr->ObjectName) : "(null)", flags ); + *handle = 0; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
@@ -1870,6 +1919,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE { unsigned int ret;
+ TRACE( "access %#x, name %s\n", access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); + *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret;
@@ -1896,6 +1947,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE;
+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); + if (!handle) handle = keyed_event; if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; if (alertable) flags |= SELECT_ALERTABLE; @@ -1915,6 +1968,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE;
+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); + if (!handle) handle = keyed_event; if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; if (alertable) flags |= SELECT_ALERTABLE;
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/sync.c | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index c501a9f5cca..425543d0d6a 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -303,6 +303,59 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at }
+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + /****************************************************************************** * NtCreateSemaphore (NTDLL.@) */ @@ -382,6 +435,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla
if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
+ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); + return ret; + } + SERVER_START_REQ( query_semaphore ) { req->handle = wine_server_obj_handle( handle ); @@ -406,6 +465,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
TRACE( "handle %p, count %u, prev_count %p\n", handle, count, previous );
+ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( release_semaphore ) { req->handle = wine_server_obj_handle( handle ); @@ -489,6 +551,9 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
TRACE( "handle %p, prev_state %p\n", handle, prev_state );
+ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); @@ -510,6 +575,9 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
TRACE( "handle %p, prev_state %p\n", handle, prev_state );
+ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); @@ -541,6 +609,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
TRACE( "handle %p, prev_state %p\n", handle, prev_state );
+ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); @@ -572,6 +643,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class,
if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
+ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); + return ret; + } + SERVER_START_REQ( query_event ) { req->handle = wine_server_obj_handle( handle ); @@ -654,6 +731,9 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count )
TRACE( "handle %p, prev_count %p\n", handle, prev_count );
+ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( release_mutex ) { req->handle = wine_server_obj_handle( handle ); @@ -684,6 +764,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class,
if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
+ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); + return ret; + } + SERVER_START_REQ( query_mutex ) { req->handle = wine_server_obj_handle( handle ); @@ -1619,6 +1705,12 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); }
+ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + { + TRACE( "-> %#x\n", ret ); + return ret; + } + if (alertable) flags |= SELECT_ALERTABLE; select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); @@ -1645,11 +1737,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, { union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; + NTSTATUS ret;
TRACE( "signal %p, wait %p, alertable %u, timeout %s\n", signal, wait, alertable, debugstr_timeout(timeout) );
if (!signal) return STATUS_INVALID_HANDLE;
+ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + return ret; + if (alertable) flags |= SELECT_ALERTABLE; select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; select_op.signal_and_wait.wait = wine_server_obj_handle( wait );
From: Elizabeth Figura zfigura@codeweavers.com
--- configure.ac | 1 + dlls/ntdll/unix/server.c | 31 +++++++++++------ dlls/ntdll/unix/sync.c | 14 ++++++++ dlls/ntdll/unix/unix_private.h | 2 ++ server/Makefile.in | 1 + server/inproc_sync.c | 61 ++++++++++++++++++++++++++++++++++ server/object.h | 4 +++ server/protocol.def | 1 + server/thread.c | 7 ++++ 9 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 server/inproc_sync.c
diff --git a/configure.ac b/configure.ac index 6d093b52526..72d30e69fe9 100644 --- a/configure.ac +++ b/configure.ac @@ -677,6 +677,7 @@ AC_CHECK_HEADERS(\ linux/input.h \ linux/ioctl.h \ linux/major.h \ + linux/ntsync.h \ linux/param.h \ linux/serial.h \ linux/types.h \ diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 3969c2bb898..1613c163f33 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -961,7 +961,7 @@ void wine_server_send_fd( int fd ) * * Receive a file descriptor passed from the server. */ -static int receive_fd( obj_handle_t *handle ) +int wine_server_receive_fd( obj_handle_t *handle ) { struct iovec vec; struct msghdr msghdr; @@ -1156,7 +1156,7 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, if (type) *type = reply->type; if (options) *options = reply->options; access = reply->access; - if ((fd = receive_fd( &fd_handle )) != -1) + if ((fd = wine_server_receive_fd( &fd_handle )) != -1) { assert( wine_server_ptr_handle(fd_handle) == handle ); *needs_close = (!reply->cacheable || @@ -1570,6 +1570,7 @@ size_t server_init_process(void) { const char *arch = getenv( "WINEARCH" ); const char *env_socket = getenv( "WINESERVERSOCKET" ); + struct ntdll_thread_data *data = ntdll_get_thread_data(); obj_handle_t version; unsigned int i; int ret, reply_pipe; @@ -1609,7 +1610,7 @@ size_t server_init_process(void) pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
/* receive the first thread request fd on the main socket */ - ntdll_get_thread_data()->request_fd = receive_fd( &version ); + data->request_fd = wine_server_receive_fd( &version );
#ifdef SO_PASSCRED /* now that we hopefully received the server_pid, disable SO_PASSCRED */ @@ -1644,16 +1645,24 @@ size_t server_init_process(void) req->unix_pid = getpid(); req->unix_tid = get_unix_tid(); req->reply_fd = reply_pipe; - req->wait_fd = ntdll_get_thread_data()->wait_fd[1]; + req->wait_fd = data->wait_fd[1]; req->debug_level = (TRACE_ON(server) != 0); wine_server_set_reply( req, supported_machines, sizeof(supported_machines) ); - ret = wine_server_call( req ); - pid = reply->pid; - tid = reply->tid; - peb->SessionId = reply->session_id; - info_size = reply->info_size; - server_start_time = reply->server_start; - supported_machines_count = wine_server_reply_size( reply ) / sizeof(*supported_machines); + if (!(ret = wine_server_call( req ))) + { + obj_handle_t handle; + pid = reply->pid; + tid = reply->tid; + peb->SessionId = reply->session_id; + info_size = reply->info_size; + server_start_time = reply->server_start; + supported_machines_count = wine_server_reply_size( reply ) / sizeof(*supported_machines); + if (reply->inproc_device) + { + inproc_device_fd = wine_server_receive_fd( &handle ); + assert( handle == reply->inproc_device ); + } + } } SERVER_END_REQ; close( reply_pipe ); diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 425543d0d6a..e861bffc874 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -57,6 +57,9 @@ #ifdef HAVE_KQUEUE # include <sys/event.h> #endif +#ifdef HAVE_LINUX_NTSYNC_H +# include <linux/ntsync.h> +#endif
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -70,6 +73,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync);
HANDLE keyed_event = 0; +int inproc_device_fd = -1;
static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) { @@ -305,53 +309,63 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at
static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index a735e54d9ff..756f1e91a3e 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -197,6 +197,7 @@ extern unsigned int supported_machines_count; extern USHORT supported_machines[8]; extern BOOL process_exiting; extern HANDLE keyed_event; +extern int inproc_device_fd; extern timeout_t server_start_time; extern sigset_t server_block_set; extern struct _KUSER_SHARED_DATA *user_shared_data; @@ -233,6 +234,7 @@ extern unsigned int server_queue_process_apc( HANDLE process, const union apc_ca extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, int *needs_close, enum server_fd_type *type, unsigned int *options ); extern void wine_server_send_fd( int fd ); +extern int wine_server_receive_fd( obj_handle_t *handle ); extern void process_exit_wrapper( int status ) DECLSPEC_NORETURN; extern size_t server_init_process(void); extern void server_init_process_done(void); diff --git a/server/Makefile.in b/server/Makefile.in index 6e4e68d6ebf..57250fd0332 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -16,6 +16,7 @@ SOURCES = \ file.c \ handle.c \ hook.c \ + inproc_sync.c \ mach.c \ mailslot.c \ main.c \ diff --git a/server/inproc_sync.c b/server/inproc_sync.c new file mode 100644 index 00000000000..1bef2469e96 --- /dev/null +++ b/server/inproc_sync.c @@ -0,0 +1,61 @@ +/* + * In-process synchronization primitives + * + * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include <assert.h> +#include <stdint.h> +#include <stdio.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "winternl.h" + +#include "file.h" +#include "handle.h" +#include "request.h" +#include "thread.h" + +#ifdef HAVE_LINUX_NTSYNC_H +# include <linux/ntsync.h> +#endif + +#ifdef NTSYNC_IOC_EVENT_READ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <unistd.h> + +int get_inproc_device_fd(void) +{ + static int fd = -2; + if (fd == -2) fd = open( "/dev/ntsync", O_CLOEXEC | O_RDONLY ); + return fd; +} + +#else /* NTSYNC_IOC_EVENT_READ */ + +int get_inproc_device_fd(void) +{ + return -1; +} + +#endif /* NTSYNC_IOC_EVENT_READ */ diff --git a/server/object.h b/server/object.h index 848f6dc977e..fc0bb51f5f5 100644 --- a/server/object.h +++ b/server/object.h @@ -237,6 +237,10 @@ extern void reset_event( struct event *event );
extern void abandon_mutexes( struct thread *thread );
+/* in-process synchronization functions */ + +extern int get_inproc_device_fd(void); + /* serial functions */
int get_serial_async_timeout(struct object *obj, int type, int count); diff --git a/server/protocol.def b/server/protocol.def index 22470e33ae0..4429159a720 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1121,6 +1121,7 @@ struct obj_locator thread_id_t tid; /* thread id of the new thread */ timeout_t server_start; /* server start time */ unsigned int session_id; /* process session id */ + obj_handle_t inproc_device;/* inproc device fd in flight with this handle */ data_size_t info_size; /* total size of startup info */ VARARG(machines,ushorts); /* array of supported machines */ @END diff --git a/server/thread.c b/server/thread.c index 05ec6a4ec00..fb66fac8eef 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1694,6 +1694,7 @@ static int init_thread( struct thread *thread, int reply_fd, int wait_fd ) DECL_HANDLER(init_first_thread) { struct process *process = current->process; + int fd;
if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
@@ -1716,6 +1717,12 @@ DECL_HANDLER(init_first_thread) reply->server_start = server_start_time; set_reply_data( supported_machines, min( supported_machines_count * sizeof(unsigned short), get_reply_max_size() )); + + if ((fd = get_inproc_device_fd()) >= 0) + { + reply->inproc_device = get_process_id( process ) | 1; + send_client_fd( process, fd, reply->inproc_device ); + } }
/* initialize a new thread */
From: Elizabeth Figura zfigura@codeweavers.com
--- server/inproc_sync.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ server/object.h | 10 +++++ server/queue.c | 16 +++++--- 3 files changed, 109 insertions(+), 5 deletions(-)
diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 1bef2469e96..4016421ef36 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -51,6 +51,81 @@ int get_inproc_device_fd(void) return fd; }
+struct inproc_sync +{ + struct object obj; /* object header */ + enum inproc_sync_type type; + int fd; +}; + +static void inproc_sync_dump( struct object *obj, int verbose ); +static void inproc_sync_destroy( struct object *obj ); + +static const struct object_ops inproc_sync_ops = +{ + sizeof(struct inproc_sync), /* size */ + &no_type, /* type */ + inproc_sync_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 */ + inproc_sync_destroy, /* destroy */ +}; + +struct inproc_sync *create_inproc_event_sync( int manual, int signaled ) +{ + struct ntsync_event_args args = {.signaled = signaled, .manual = manual}; + struct inproc_sync *event; + + if (!(event = alloc_object( &inproc_sync_ops ))) return NULL; + event->type = INPROC_SYNC_EVENT; + event->fd = ioctl( get_inproc_device_fd(), NTSYNC_IOC_CREATE_EVENT, &args ); + + return event; +} + +static void inproc_sync_dump( struct object *obj, int verbose ) +{ + struct inproc_sync *sync = (struct inproc_sync *)obj; + assert( obj->ops == &inproc_sync_ops ); + fprintf( stderr, "Inproc sync type=%d, fd=%d\n", sync->type, sync->fd ); +} + +void signal_inproc_sync( struct inproc_sync *sync ) +{ + __u32 count; + if (debug_level) fprintf( stderr, "set_inproc_event %d\n", sync->fd ); + ioctl( sync->fd, NTSYNC_IOC_EVENT_SET, &count ); +} + +void reset_inproc_sync( struct inproc_sync *sync ) +{ + __u32 count; + if (debug_level) fprintf( stderr, "reset_inproc_event %d\n", sync->fd ); + ioctl( sync->fd, NTSYNC_IOC_EVENT_RESET, &count ); +} + +static void inproc_sync_destroy( struct object *obj ) +{ + struct inproc_sync *sync = (struct inproc_sync *)obj; + assert( obj->ops == &inproc_sync_ops ); + close( sync->fd ); +} + #else /* NTSYNC_IOC_EVENT_READ */
int get_inproc_device_fd(void) @@ -58,4 +133,17 @@ int get_inproc_device_fd(void) return -1; }
+struct inproc_sync *create_inproc_event_sync( int manual, int signaled ) +{ + return NULL; +} + +void signal_inproc_sync( struct inproc_sync *sync ) +{ +} + +void reset_inproc_sync( struct inproc_sync *sync ) +{ +} + #endif /* NTSYNC_IOC_EVENT_READ */ diff --git a/server/object.h b/server/object.h index fc0bb51f5f5..b609f5f7af9 100644 --- a/server/object.h +++ b/server/object.h @@ -239,7 +239,17 @@ extern void abandon_mutexes( struct thread *thread );
/* in-process synchronization functions */
+enum inproc_sync_type +{ + INPROC_SYNC_UNKNOWN, + INPROC_SYNC_EVENT, +}; + +struct inproc_sync; extern int get_inproc_device_fd(void); +extern struct inproc_sync *create_inproc_event_sync( int manual, int signaled ); +extern void signal_inproc_sync( struct inproc_sync *sync ); +extern void reset_inproc_sync( struct inproc_sync *sync );
/* serial functions */
diff --git a/server/queue.c b/server/queue.c index 3845a86c962..792947c6813 100644 --- a/server/queue.c +++ b/server/queue.c @@ -116,6 +116,7 @@ struct msg_queue { struct object obj; /* object header */ struct fd *fd; /* optional file descriptor to poll */ + struct inproc_sync *inproc_sync; /* inproc sync for client-side waits */ int signaled; /* queue is signaled from fd POLLIN or masks */ int paint_count; /* pending paint messages count */ int hotkey_count; /* pending hotkey messages count */ @@ -306,6 +307,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ if ((queue = alloc_object( &msg_queue_ops ))) { queue->fd = NULL; + queue->inproc_sync = NULL; queue->signaled = 0; queue->paint_count = 0; queue->hotkey_count = 0; @@ -325,11 +327,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ list_init( &queue->expired_timers ); for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] );
- if (!(queue->shared = alloc_shared_object())) - { - release_object( queue ); - return NULL; - } + if (get_inproc_device_fd() >= 0 && !(queue->inproc_sync = create_inproc_event_sync( 1, 0 ))) goto error; + if (!(queue->shared = alloc_shared_object())) goto error;
SHARED_WRITE_BEGIN( queue->shared, queue_shm_t ) { @@ -351,6 +350,10 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ } if (new_input) release_object( new_input ); return queue; + +error: + release_object( queue ); + return NULL; }
/* free the message queue of a thread at thread exit */ @@ -714,11 +717,13 @@ static void signal_queue_sync( struct msg_queue *queue ) if (queue->signaled) return; queue->signaled = 1; wake_up( &queue->obj, 0 ); + if (queue->inproc_sync) signal_inproc_sync( queue->inproc_sync ); }
static void reset_queue_sync( struct msg_queue *queue ) { queue->signaled = 0; + if (queue->inproc_sync) reset_inproc_sync( queue->inproc_sync ); }
/* check the queue status */ @@ -1395,6 +1400,7 @@ static void msg_queue_destroy( struct object *obj ) if (queue->hooks) release_object( queue->hooks ); if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); + if (queue->inproc_sync) release_object( queue->inproc_sync ); }
static void msg_queue_poll_event( struct fd *fd, int event )
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/sync.c | 55 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 1 + server/inproc_sync.c | 39 ++++++++++++++++++++++++ server/object.h | 6 ---- server/protocol.def | 14 +++++++++ server/queue.c | 6 ++++ server/user.h | 1 + 8 files changed, 117 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 1613c163f33..eca25743812 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -104,7 +104,7 @@ sigset_t server_block_set; /* signals to block during server calls */ static int fd_socket = -1; /* socket to exchange file descriptors with the server */ static int initial_cwd = -1; static pid_t server_pid; -static pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
/* atomically exchange a 64-bit value */ static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val ) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index e861bffc874..4211b796042 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -307,6 +307,45 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at }
+struct inproc_sync +{ + int fd; + unsigned int type : 2; +}; + +static void release_inproc_sync( struct inproc_sync *sync ) +{ + close( sync->fd ); +} + +static NTSTATUS get_inproc_sync( HANDLE handle, struct inproc_sync *sync ) +{ + sigset_t sigset; + NTSTATUS ret; + + /* We need to use fd_cache_mutex here to protect against races with + * other threads trying to receive fds for the fd cache, + * and we need to use an uninterrupted section to prevent reentrancy. */ + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + + SERVER_START_REQ( get_inproc_sync_fd ) + { + req->handle = wine_server_obj_handle( handle ); + if (!(ret = wine_server_call( req ))) + { + obj_handle_t fd_handle; + sync->fd = wine_server_receive_fd( &fd_handle ); + assert( wine_server_ptr_handle(fd_handle) == handle ); + sync->type = reply->type; + } + } + SERVER_END_REQ; + + server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + + return ret; +} + static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) { if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; @@ -358,7 +397,23 @@ static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *inf static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + struct inproc_sync *syncs[64], stack[ARRAY_SIZE(syncs)]; + NTSTATUS ret; + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; + + assert( count <= ARRAY_SIZE(syncs) ); + for (int i = 0; i < count; ++i) + { + if ((ret = get_inproc_sync( handles[i], stack + i ))) + { + while (i--) release_inproc_sync( syncs[i] ); + return ret; + } + syncs[i] = stack + i; + } + + while (count--) release_inproc_sync( syncs[count] ); return STATUS_NOT_IMPLEMENTED; }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 756f1e91a3e..188fa07ba5d 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -200,6 +200,7 @@ extern HANDLE keyed_event; extern int inproc_device_fd; extern timeout_t server_start_time; extern sigset_t server_block_set; +extern pthread_mutex_t fd_cache_mutex; extern struct _KUSER_SHARED_DATA *user_shared_data; #ifdef __i386__ extern struct ldt_copy __wine_ldt_copy; diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 4016421ef36..995e8b57c4e 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -32,6 +32,7 @@ #include "handle.h" #include "request.h" #include "thread.h" +#include "user.h"
#ifdef HAVE_LINUX_NTSYNC_H # include <linux/ntsync.h> @@ -126,6 +127,26 @@ static void inproc_sync_destroy( struct object *obj ) close( sync->fd ); }
+static int get_inproc_sync_fd( struct object *obj, unsigned char *type ) +{ + struct object *sync; + int fd = -1; + + if (obj != (struct object *)current->queue) sync = get_obj_sync( obj ); + else sync = thread_queue_inproc_sync( current ); + if (!sync) return -1; + + if (sync->ops == &inproc_sync_ops) + { + struct inproc_sync *inproc = (struct inproc_sync *)sync; + *type = inproc->type; + fd = inproc->fd; + } + + release_object( sync ); + return fd; +} + #else /* NTSYNC_IOC_EVENT_READ */
int get_inproc_device_fd(void) @@ -146,4 +167,22 @@ void reset_inproc_sync( struct inproc_sync *sync ) { }
+static int get_inproc_sync_fd( struct object *obj, unsigned char *type ) +{ + return -1; +} + #endif /* NTSYNC_IOC_EVENT_READ */ + +DECL_HANDLER(get_inproc_sync_fd) +{ + struct object *obj; + int fd; + + if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return; + + if ((fd = get_inproc_sync_fd( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); + else send_client_fd( current->process, fd, req->handle ); + + release_object( obj ); +} diff --git a/server/object.h b/server/object.h index b609f5f7af9..f770db550c3 100644 --- a/server/object.h +++ b/server/object.h @@ -239,12 +239,6 @@ extern void abandon_mutexes( struct thread *thread );
/* in-process synchronization functions */
-enum inproc_sync_type -{ - INPROC_SYNC_UNKNOWN, - INPROC_SYNC_EVENT, -}; - struct inproc_sync; extern int get_inproc_device_fd(void); extern struct inproc_sync *create_inproc_event_sync( int manual, int signaled ); diff --git a/server/protocol.def b/server/protocol.def index 4429159a720..bfc13d0bffe 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4117,3 +4117,17 @@ struct handle_info @REPLY int enable; /* previous state of auto-repeat enable */ @END + + +enum inproc_sync_type +{ + INPROC_SYNC_UNKNOWN = 0, + INPROC_SYNC_EVENT = 1, +}; + +/* Get the in-process synchronization fd associated with the waitable handle */ +@REQ(get_inproc_sync_fd) + obj_handle_t handle; /* handle to the object */ +@REPLY + unsigned char type; /* inproc sync type */ +@END diff --git a/server/queue.c b/server/queue.c index 792947c6813..74268420969 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1490,6 +1490,12 @@ int init_thread_queue( struct thread *thread ) return (create_msg_queue( thread, NULL ) != NULL); }
+struct object *thread_queue_inproc_sync( struct thread *thread ) +{ + if (!thread->queue) return NULL; + return grab_object( thread->queue->inproc_sync ); +} + /* attach two thread input data structures */ int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) { diff --git a/server/user.h b/server/user.h index ee0042b8755..ffd4b8b595c 100644 --- a/server/user.h +++ b/server/user.h @@ -120,6 +120,7 @@ extern void inc_queue_paint_count( struct thread *thread, int incr ); extern void queue_cleanup_window( struct thread *thread, user_handle_t win ); extern int init_thread_queue( struct thread *thread ); extern void check_thread_queue_idle( struct thread *thread ); +extern struct object *thread_queue_inproc_sync( struct thread *thread ); extern int attach_thread_input( struct thread *thread_from, struct thread *thread_to ); extern void detach_thread_input( struct thread *thread_from ); extern void set_clip_rectangle( struct desktop *desktop, const struct rectangle *rect,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/sync.c | 15 ++++++++++++--- server/inproc_sync.c | 2 ++ server/protocol.def | 1 + 3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 4211b796042..7f603882074 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -310,6 +310,7 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at struct inproc_sync { int fd; + unsigned int access; unsigned int type : 2; };
@@ -318,7 +319,7 @@ static void release_inproc_sync( struct inproc_sync *sync ) close( sync->fd ); }
-static NTSTATUS get_inproc_sync( HANDLE handle, struct inproc_sync *sync ) +static NTSTATUS get_inproc_sync( HANDLE handle, ACCESS_MASK desired_access, struct inproc_sync *sync ) { sigset_t sigset; NTSTATUS ret; @@ -336,6 +337,7 @@ static NTSTATUS get_inproc_sync( HANDLE handle, struct inproc_sync *sync ) obj_handle_t fd_handle; sync->fd = wine_server_receive_fd( &fd_handle ); assert( wine_server_ptr_handle(fd_handle) == handle ); + sync->access = reply->access; sync->type = reply->type; } } @@ -343,7 +345,14 @@ static NTSTATUS get_inproc_sync( HANDLE handle, struct inproc_sync *sync )
server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
- return ret; + if (ret) return ret; + if ((sync->access & desired_access) != desired_access) + { + release_inproc_sync( sync ); + return STATUS_ACCESS_DENIED; + } + + return STATUS_SUCCESS; }
static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) @@ -405,7 +414,7 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an assert( count <= ARRAY_SIZE(syncs) ); for (int i = 0; i < count; ++i) { - if ((ret = get_inproc_sync( handles[i], stack + i ))) + if ((ret = get_inproc_sync( handles[i], SYNCHRONIZE, stack + i ))) { while (i--) release_inproc_sync( syncs[i] ); return ret; diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 995e8b57c4e..90c5f17d5e6 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -181,6 +181,8 @@ DECL_HANDLER(get_inproc_sync_fd)
if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
+ reply->access = get_handle_access( current->process, req->handle ); + if ((fd = get_inproc_sync_fd( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); else send_client_fd( current->process, fd, req->handle );
diff --git a/server/protocol.def b/server/protocol.def index bfc13d0bffe..ec6cde3e606 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4130,4 +4130,5 @@ enum inproc_sync_type obj_handle_t handle; /* handle to the object */ @REPLY unsigned char type; /* inproc sync type */ + unsigned int access; /* handle access rights */ @END
v2: Rename cache to stack, remove output pointer.
This merge request was approved by Elizabeth Figura.
Can you please rebase or merge it if it's still planned? Since esync is disabled / unsupported in Wine staging for a while now, it would be nice to have ntsync in some upcoming Wine version if possible.
On Thu Aug 7 09:10:31 2025 +0000, Shmerl wrote:
Can you please rebase or merge it if it's still planned? Since esync is disabled / unsupported in Wine staging for a while now, it would be nice to have ntsync in some upcoming Wine version if possible.
This will likely take more time, please be patient. It's summer and many people are taking some time off.
I have updated the branch here https://gitlab.winehq.org/rbernon/wine/-/commits/wip/ntsync, although note that some people reported that it was possibly broken and I didn't investigate, also if this hasn't been merged it probably means that some things would need to be done differently, so possibly some larger changes that would break the patches again in the future.
On Thu Aug 7 14:05:38 2025 +0000, Rémi Bernon wrote:
This will likely take more time, please be patient. It's summer and many people are taking some time off. I have updated the branch here https://gitlab.winehq.org/rbernon/wine/-/commits/wip/ntsync, although note that some people reported that it was possibly broken and I didn't investigate, also if this hasn't been merged it probably means that some things would need to be done differently, so possibly some larger changes that would break the patches again in the future.
Thanks for the heads up. I can try testing the current branch to see if it works for some games.
On Fri Aug 8 01:48:29 2025 +0000, Shmerl wrote:
Thanks for the heads up. I can try testing the current branch to see if it works for some games.
FYI, trying to build your branch:
``` gcc -m64 -c -o dlls/ntdll/unix/virtual.o /home/user/build/wine/source/dlls/ntdll/unix/virtual.c -Idlls/ntdll \ -I/home/user/build/wine/source/dlls/ntdll -Iinclude -I/home/user/build/wine/source/include \ -D__WINESRC__ -DLTC_NO_PROTOTYPES -DLTC_SOURCE -D_NTSYSTEM_ -D_ACRTIMP= -DWINBASEAPI= \ -DWINE_UNIX_LIB -I/usr/include/x86_64-linux-gnu -Wall -pipe -fcf-protection=none \ -fvisibility=hidden -fno-stack-protector -fno-strict-aliasing -Wdeclaration-after-statement \ -Wempty-body -Wignored-qualifiers -Winit-self -Wlogical-op -Wno-packed-not-aligned -Wpointer-arith \ -Wshift-overflow=2 -Wstrict-prototypes -Wtype-limits -Wunused-but-set-parameter -Wvla \ -Wwrite-strings -Wno-misleading-indentation -fPIC -fasynchronous-unwind-tables -O3 -march=znver4 /home/user/build/wine/source/dlls/ntdll/unix/server.c: In function ‘server_init_process’: /home/user/build/wine/source/dlls/ntdll/unix/server.c:1675:22: error: ‘const struct init_first_thread_reply’ has no member named ‘inproc_device’ 1675 | if (reply->inproc_device) ```