Mike Hearn wrote:
There is no need to export __wine_is_current_process from ntdll and use it here when standard win32 apis will suffice.
Oh yes, I was wondering why this was bothering me. I think you can achieve the same effect like this:
if ((handle == (HANDLE)0xffffffff) || (handle == (HANDLE) NtCurrentTeb()->ClientId.UniqueProcess))
Well, not quite. You can open another handle to the process using DuplicateHandle or something else, so you need to go via the server. The simplest way to do this using Win32 is: if (GetProcessId(handle) == GetCurrentProcessId())
On the multiplexing - I spent a few minutes kicking around ideas for others way to do it, but they all basically boiled down to variations on what you've done here ... the only way to make it race free is via the server, and that means marshalling the call into a structure and uploading it to the server so the other process can download it when it's been forced onto the right codepath.
That leaves the question of how to do the forcing.
The simplest is to have a worker thread which simply sits blocked on a semaphore or something, and then when signalled downloads a request from the server, dispatches it, and returns. That means spinning up a thread at startup though, and I seem to recall that due to the dubious history of the 'service thread' people are no longer keen on that.
So ... another way would be to send a signal and use a signal handler to invoke the RPC. I don't really know enough to comment on this approach: I think the way signals work differs in kthread/pthread systems, ie on NPTL boxes signals are sent to threads not processes which could cause wierd races and bugs inside apps. Maybe you can still send signals to processes in NPTL ... I don't know.
The final way I can think of is to suspend the entire app using ptrace, grab a thread (which?) and rewrite its register context and stack to point at some remote_op_dispatcher function the address of which is registered at startup with the wineserver. This downloads the struct using the host threads wineserver connection, deals with the request and returns. Then the stack is cleaned up, the register context restored, and the app resumed.
This seems like the best idea if it is possible. The stack doesn't need to be anything special, just a rewritable piece of memory whose location is always known. The only trouble is that creating a thread is quite complicated and involves a lot of code, so there is a chance that it may not work using this method.
Ick. That sounds really really complicated. I'd be tempted to go for bringing back the service thread but I wasn't around when it was busy causing pain so maybe I sound a bit blase about that :)
Perhaps the old-timers can tell us a story around the camp fire about this...
Rob