On 4/19/23 10:58, Jin-oh Kang wrote:
On Tue, Apr 18, 2023, 4:44 PM Richard W.M. Jones rjones@redhat.com wrote:
I'm trying to bring my old AF_UNIX patch up to date:
https://www.winehq.org/pipermail/wine-devel/2021-May/187049.html
It's not going too well as the code has changed quite a lot.
Yes. A quick overview:
- dlls/ws2_32/socket.c is the Windows Socket 2 implementation. It acts as a
frontend for the underlying socket implementation (AFD.SYS).
- dlls/ntdll/unix/socket.c emulates the AFD.SYS driver. It acts as the
backend and does the actual socket I/O.
- server/sock.c manages socket polling, asynchronous I/O, as well as
overall socket state management.
I'm going to nitpick, but this is kind of a false dichotomy. ntdll and server both handle different socket ioctls, or different parts of the same ioctls, and hence can both be said to stand in for afd.sys.
What goes in ntdll or the server depends on a few different factors. Some things need to be in the server because they're state shared across multiple processes (e.g. SNDBUF, RCVBUF) that can't be stored in the socket itself (SNDBUF exists on native but doesn't behave the same way). Shutdown handling and socket events need to be in the server for much of the same reason, and hence async I/O management and much of the polling logic does too—but the actual send and recv calls need to be in ntdll since they're using the address space of the process in question.
Otherwise, we try to keep things out of the server where possible, both to avoid round trips, and simply to avoid adding more complex code to a component which we try to make a point of keeping robust.
One particular problem I'm having is in wineserver. We need to convert the Windows socket path encoded as a UTF-8 string (eg. Z:\tmp\sock) into a Unix filename. In the old code I used:
num = MultiByteToWideChar(CP_UTF8, 0, wun->sun_path, -1, NULL, 0);
win_path = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WCHAR));
if (win_path == NULL)
return 0;
MultiByteToWideChar(CP_UTF8, 0, wun->sun_path, -1, win_path, num);
unix_path = wine_get_unix_file_name(win_path);
heap_free(win_path);
However none of this seems to work inside wineserver (I guess because it's not part of the "Windows world"). I cannot work out the equivalent of this for wineserver, or if there's something else I should be doing, such as converting the path before it is sent to wineserver.
You should be converting the path before sending it to wineserver. The simplest hack would be using wine_get_unix_file_name() from ws2_32.
To add some more context: yes, the server cannot convert between NT and Unix paths. This is not so much due to layering reasons—actually, it would be rather nice if the server could do this—but I believe the main problem is that conversion can involve slow lookups, and we don't want that to block the server.
I'm not sure that doing the conversion in ws2_32 is a hack, either. The NT interface is not well defined. Without seeing the code, it may be possible to do conversion either in ws2_32 or in ntdll.
Note that you can't call wine_get_unix_file_name() from ntdll. That would constitute violation of abstraction boundary between the Win32 subsystem (which deals with DOS/Win32 paths) and the NT kernel (which deals with NT paths in Object Manager).
True, but note that we also have wine_unix_to_nt_file_name() in ntdll, or on the Unix side (which is more likely), simply nt_to_unix_file_name().
Supplemental question: There appears to be duplicate socket handling code in wineserver server/sock.c and dlls/ntdll/unix/socket.c.
I don't believe this to be the case.
Well, there is some duplicated code, yes. For example, socket address conversion is done on both sides. That's not particularly avoidable.
--Zeb