Alexandre Julliard wrote:

> Jeremy White <[EMAIL PROTECTED]> writes:
>
> > Specifically, I have added a special constructor inside libwine.so
> > which initializes most of Wine (by calling PROCESS_InitWine;
> > see my prior patch).  Since this constructor fires prior to
> > the MFC constructors, the MFC constructors are able to work.
> >
> > The basic concept, is, IMHO sound.  I would like Wine more
> > or less fully functional as soon as libwine.so is done loading.
>
> The main problem is that this will only initialize libwine.so, not all
> the other dlls that MFC depends on. In order to do this correctly
> you'll need to have the init code of all dlls run from constructors.
>
> This is certainly doable with .so dlls, but it probably won't work
> right with static linking (though I'm not sure if we care about that).
> And of course you won't have access to the command-line when
> initializing the dlls, so options like -display, -dll, -desktop
> won't be supported.

    Good point.  I favor this option over the others, because I believe
it to be the more correct one.  (Empirically MFC works with
only GDI, Kernel, and User, but your point remains valid - my solution
is not complete).

    If we were to change to have each DLL initialize itself
from its constructor, is argc/argv processing the only flaw
with this approach?  (I ask because a brief review of the glibc
code indicates that argc/argv are processed prior to
traversing the ctors list, so they should be available to us).

  (To reprise the whole problem, I've got a more detailed
summary at the bottom).


>
>
> >     2.  GNU ld does not (AFAIK) allow me to specify
> >           constructor order.   Ideally, I want my new constructor
> >           to be the *last* constructor fired.  Right now, I've
> >           arranged this by jimmying the parameter order passed
> >           to the linker, but this could cause problems.
>
> There is no real reason (except modularity) to have multiple
> constructors inside libwine.so; if the order is important you can have
> your constructor call the other functions explicitly.

    The constructor in scheduler/thread.c must be called
prior to PROCESS_InitWine(); it establishes the %fs
register that many other things depend on.  However,
you are correct that PROCESS_InitWine() can call
THREAD_Init(), and resolve the problem.  However, I also
prefer isolating this constructor code to a separate
DLL so that I only introduce the argc/argv problems
for Winelib apps.


   A complete description of the problem and the three
proposed solutions are as follows:
   The problem:  MFC (and other C++ code) calls Windows APIs from
C++ constructors.  A Winelib port of MFC then breaks because Wine is
not able to provide Windows APIs until after main() has been called,
because Wine is not initialized until then, and the C++ constructors are
invoked (on Linux) during the processing of the ctors list, which occurs
on library load.
    The three solutions I'm aware of are as follows:
        1.  Make all Winelib apps into DLLs
             This approach works today, and (I think?) is preferred by
Alexandre.
              Instead of foo.cpp building into a Linux executable foo,
              it builds into foo.so.  Then, foo.spec is built into an
exectuable
              foo, which gains control when main() is invoked,
              does a LoadLibrary() on foo, a GetProcAddress of WinMain,
              and then invokes it.  I am not aware of any significant
flaws
              with this approach (but I'd love to hear anyone who can
think of
              any, because I find it strangely unsatisfying <g>).
         2.  Make Wine constructors initialize Wine during the ctors
processing
              This approach is what I'm proposing and am a proponent of.
              The key known flaw is that during ctors processing, we
don't have
               access to argc/argv, so Wine initialization cannot use
command
               line arguments (i.e.  no -display, no -window, for startup
purposes).
         3.   Intercept ctors processing
               In this  case, best demostrated by Berthos, I believe, you

               intercept the ctors process of your target library (say,
MFC).
               You stash a pointer to the ctors chain somewhere, and
               then force the glibc processing code to return
immediately.
               Later, during 'normal' library initialization (invoked
after main()),
               you walk the rest of the ctors chain.

               This option would be more appealing to me if there was a
formal
                way to accomplish this with linker scripts, rather than
with a hack.


Jeremy

Reply via email to