[RFC PATCH 0/5] XAudio PE conversion.

Zebediah Figura (she/her) zfigura at codeweavers.com
Fri Sep 3 14:11:02 CDT 2021



On 9/3/21 12:02 PM, Alexandre Julliard wrote:
> "Zebediah Figura (she/her)" <zfigura at codeweavers.com> writes:
> 
>> On 9/3/21 3:26 AM, Alexandre Julliard wrote:
>>> "Zebediah Figura (she/her)" <zfigura at codeweavers.com> writes:
>>>
>>>> Actually, an alternate solution occurred to me:
>>>>
>>>> If we are loading any library that is a dependency of a builtin
>>>> library, always load it from a fixed path like /usr/lib/wine/ext/, and
>>>> essentially treat it as if we had loaded using an absolute path
>>>> instead of a relative path, so as to skip existing DLLs loaded under
>>>> that name.
>>>>
>>>> Mark that DLL with an internal flag, and don't consider it when
>>>> searching for existing DLLs with that name, to avoid the other side.
>>>>
>>>> I know there are a lot of other things standing in the way of shared
>>>> libraries, and that this would require some nontrivial loader work,
>>>> but does it at least seem plausible? Are there snags I'm not noticing?
>>> Sure, you can try to create a separate namespace for these without
>>> actually changing their names. It's not clear to me how you are going to
>>> determine which DLLs should go into that namespace, and how that's going
>>> to work with apps that do import resolving by hand.
>>> You'll also have to invent some mechanism to have Wine treat them as
>>> builtins even though they don't have the builtin flag.
>>
>> The distinguishing factor I was thinking of is that if it's a system
>> lib or linked to by a system lib, it's marked as a system lib. That
>> doesn't work for libraries loaded dynamically, and there we have the
>> extra caveat that we don't want to mark every dynamically loaded
>> library as a system lib, so I think we'd need an internal flag to
>> LoadLibraryExW().
> 
> I don't see how this would work. All such libraries will import msvcrt
> or kernel32, but you can't have these end up in a separate namespace.
> 
> And how do you define a "system lib"? Do you somehow tell the PE loader
> the actual Unix path that the dll was loaded from?  What if the distro
> installs the Wine DLLs in the same dir?
> 
>>> And somehow you
>>> need to differentiate them from the exact same DLLs being shipped by an
>>> app...
>>
>> Sorry, I'm not sure what you mean by this, that's different from what
>> I described above?
> 
> Well, you'll need to copy, say, zlib1.dll into the prefix. How do you
> know this is the zlib1.dll from the system package, and not one
> installed by an app?  Do you add the builtin flag, altering the binary
> when copying it?
> 

I did fail to consider that case, thanks.

After thinking about it for a while I've come up with the following 
algorithm:

Suppose that module A imports module B.

1. If module A is marked "builtin" or "system":

     a. Try to find a module marked "builtin" or "system" in memory, and 
return it if found. (Skip "builtin" if the load order requires.)

     b. Try to load a module from WINESYSTEMDLLDIR#. If found, mark the 
module as "system".

     c. Try to find a module marked "native" in memory, and return it if 
found. (Skip this step if the load order requires.)

     d. Try to load a builtin or native module using the normal logic.

2. Otherwise, i.e. module A is native:

     a. Try to find a module marked "builtin" or "native" (modulo load 
order) in memory, and return it if found. Skip "system".

     b. Try to load a builtin or native module using the normal logic.


This should avoid ever loading a system module for a native module; it 
should avoid loading a native module when we want a system module 
(provided that system modules are present; if they aren't things are 
already broken). It should also handle e.g. ucrtbase imports, regardless 
if ucrtbase is builtin or native.

The downside I can see is that if ucrtbase is native, we'll always 
search WINESYSTEMDLLDIRs for it. If that's a performance problem, we 
could always bypass step 1b for a predefined list of modules.

This does rely on the fact that WINESYSTEMDLLDIRs are unique and only 
contain system libraries. It's not obvious to me that would be a problem 
to guarantee. The list might contain one or more paths like:

* C:/windows/system32/wine-ext/ [1]
* Z:/usr/x86_64-w64-mingw32/bin/ [2]
* Z:/usr/lib/wine/ext/

I'm sure this all looks like a pile of hacks. Granted, it doesn't look 
unreasonable to me, but I suppose I'm also biased. I'm just trying my 
best to make dynamic libraries a possibility, because static libraries 
suck for development. And, more importantly, I'm trying to give 
distributions an accurate representation of our requirements.


[1] As far as I'm aware, the only reason we need to copy libraries to 
the C: drive is that anticheats *might* complain if libraries are loaded 
from another drive? Was there a concrete example of this? Or was there 
another problem I was missing?

[2] Or distribution equivalent. That's assuming that distributions are 
in favor of having us dynamically link to pre-built libraries, though, 
and that's an open question. It's also not clear how we would get this path.



More information about the wine-devel mailing list