I wrote a program called winestreamproxy [1] that proxys data between a named pipe in Wine and a unix domain socket outside of Wine. This program should automatically exit when no other non-system program is running in the bottle/prefix if the parameter --system is supplied. For this purpose it marks itself as a system process using __wine_make_process_system() from ntdll, and waits on the returned event handle to exit.
This worked fine, until a change was introduced that seemingly made every non-system process spawn a conhost.exe instance. Since conhost.exe is not a system process, this breaks the auto-exit functionality of winestreamproxy. I understand that using Wine-internal functions is not supported, however the desired behavior seems hard if not impossible to implement otherwise.
Making conhost mark itself as a system process would allow the automatic exit to work again. I don't think this would break anything, because at the point in the bottle/prefix lifecycle where this becomes relevant there are no non-system processes anymore, and anything else has either explicitly opted into this behavior or not received a conhost instance in the first place.
As to why winestreamproxy is necessary at all: It allows Windows games running under Wine to communicate with Linux-native Discord [2] and show status messages and invite buttons on a user's profile.
[1] https://github.com/openglfreak/winestreamproxy [2] https://discord.com/
Signed-off-by: Torge Matthies openglfreak@googlemail.com --- programs/conhost/conhost.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 6985a9ca0b0..46b48d086d4 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -42,6 +42,8 @@ static CRITICAL_SECTION console_section = { &critsect_debug, -1, 0, 0, 0, 0 }; static void *ioctl_buffer; static size_t ioctl_buffer_size;
+extern HANDLE CDECL __wine_make_process_system(void); + static void *alloc_ioctl_buffer( size_t size ) { if (size > ioctl_buffer_size) @@ -2526,7 +2528,7 @@ static NTSTATUS process_console_ioctls( struct console *console ) static int main_loop( struct console *console, HANDLE signal ) { HANDLE signal_event = NULL; - HANDLE wait_handles[3]; + HANDLE wait_handles[4]; unsigned int wait_cnt = 0; unsigned short signal_id; IO_STATUS_BLOCK signal_io; @@ -2544,6 +2546,7 @@ static int main_loop( struct console *console, HANDLE signal )
if (!alloc_ioctl_buffer( 4096 )) return 1;
+ wait_handles[wait_cnt++] = __wine_make_process_system(); wait_handles[wait_cnt++] = console->server; if (signal) wait_handles[wait_cnt++] = signal_event; if (console->input_thread) wait_handles[wait_cnt++] = console->input_thread; @@ -2570,13 +2573,14 @@ static int main_loop( struct console *console, HANDLE signal ) switch (res) { case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: EnterCriticalSection( &console_section ); status = process_console_ioctls( console ); LeaveCriticalSection( &console_section ); - if (status) return 0; + if (status || res == WAIT_OBJECT_0) return 0; break;
- case WAIT_OBJECT_0 + 1: + case WAIT_OBJECT_0 + 2: if (signal_io.Status || signal_io.Information != sizeof(signal_id)) { TRACE( "signaled quit\n" );