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.
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.
Supplemental question: There appears to be duplicate socket handling code in wineserver server/sock.c and dlls/ntdll/unix/socket.c. In my tests only the wineserver code is called, and never the ntdll/unix code. Why is that?
(I'm not very familiar with the architecture of wine, which seems a bit confusing, so I'm just guessing how it all works.)
Rich.
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.
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.
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).
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.
In my
tests only the wineserver code is called, and never the ntdll/unix code. Why is that?
This would need further elaboration: which part of dlls/ntdll/unix/* did you expect to be called, but wasn't?
(I'm not very familiar with the architecture of wine, which seems a bit confusing, so I'm just guessing how it all works.)
Rich.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
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
On Thu, Apr 20, 2023 at 12:58:04AM +0900, Jin-oh Kang wrote:
On Tue, Apr 18, 2023, 4:44 PM Richard W.M. Jones rjones@redhat.com wrote: 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.
In my tests only the wineserver code is called, and never the ntdll/unix code. Why is that?
This would need further elaboration: which part of dlls/ntdll/unix/* did you expect to be called, but wasn't?
Thanks for the other tips.
In the case above I was referring to these pieces of code which both may be doing conversion to and from Unix sockaddr:
https://gitlab.winehq.org/wine/wine/-/blob/9e99c6f66d236101a084b6a3a24c98b5c...
https://gitlab.winehq.org/wine/wine/-/blob/9e99c6f66d236101a084b6a3a24c98b5c...
They appear identical. In my test only the one in server/sock.c was called (not that I'm saying the other is never called, just that I didn't see it).
Are they used in different circumstances?
Rich.
On Thu, Apr 20, 2023, 2:11 AM Richard W.M. Jones rjones@redhat.com wrote:
On Thu, Apr 20, 2023 at 12:58:04AM +0900, Jin-oh Kang wrote:
On Tue, Apr 18, 2023, 4:44 PM Richard W.M. Jones rjones@redhat.com
wrote:
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.
In my tests only the wineserver code is called, and never the ntdll/unix code. Why is that?
This would need further elaboration: which part of dlls/ntdll/unix/* did
you
expect to be called, but wasn't?
Thanks for the other tips.
In the case above I was referring to these pieces of code which both may be doing conversion to and from Unix sockaddr:
https://gitlab.winehq.org/wine/wine/-/blob/9e99c6f66d236101a084b6a3a24c98b5c...
https://gitlab.winehq.org/wine/wine/-/blob/9e99c6f66d236101a084b6a3a24c98b5c...
They appear identical. In my test only the one in server/sock.c was called (not that I'm saying the other is never called, just that I didn't see it).
Are they used in different circumstances?
The former sockadr_from_unix (in ntdll) seems to be for WS2 getpeername() and recvfrom().
In case you haven't tried, running wine tests should give an idea about which function is called in which scenario.
Rich.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW