When starting a Wine process from command line (we'll get later on to
the differences between NE, PE and Winelib executables), there are a
couple of things Wine need to do first. A first executable is run to
check the threading model of the underlying OS (see
Section 8.4 for the details) and will start the real
Wine loader corresponding to the choosen threading model.

Then Wine graps a few elements from the Unix world: the environment,
the program arguments. Then the ntdll.dll.so is
loaded into memory using the standard shared library dynamic
loader. When loaded, NTDLL will mainly first
create a decent Windows environment:

set up the connection to the Wine server - and eventually
launching the Wine server if none runs

create the process heap

Then Kernel32 is loaded (but now using the
Windows dynamic loading capabilities) and a Wine specific entry point
is called __wine_kernel_init. This function will
actually handle all the logic of the process loading and execution,
and will never return from it's call.

__wine_kernel_init will undergo the following
tasks:

initialization of program arguments from Unix program arguments

lookup of executable in the file system

If the file is not found, then an error is printed and the Wine
loader stops.

We'll cover the non-PE file type later on, so assume for now
it's a PE file. The PE module is loaded in memory using the
same mechanisms as for a native DLLs (mainly mapping the file
data and code sections into memory, and handling relocation if
needed). Note that the dependencies on the module are not
resolved at this point.

A new stack is created, which size is given in the PE header,
and this stack is made the one of the running thread (which is
still the only one in the process). The stack used at startup
will no longer be used.

Which this new stack,
ntdll.LdrInitializeThunk is called which
performs the remaining initialization parts, including resolving
all the DLL imports on the PE module, and doing the init of the
TLS slots.

Control can now be passed to the EntryPoint
of the PE module, which will let the executable run.

There are however a few points to look at a bit more closely. The
inner implementation creates the child process using the
fork() and exec()
calls. This means that we don't need to check again for the threading
model, we can use what the parent (or the grand-parent process...)
started from command line has found.

The Win32 process creation allows to pass a lot of information between
the parent and the child. This includes object handles, windows title,
console parameters, environment strings... Wine makes use of both the
standard Unix inheritance mechanisms (for environment for example) and
the Wine server (to pass from parent to child a chunk of data
containing the relevant information).

The previously described loading mechanism will check in the Wine
server if such a chunk exists, and, if so, will perform the relevant
initialization.

Some further synchronization is also put in place: a parent will wait
until the child has started, or has failed. The Wine server is also
used to perform those tasks.

Before going into the gory details, let's first go back to what a
Winelib application is. It can be either a regular Unix executable, or
a more specific Wine beast. This later form in fact creates two files
for a given executable (say foo.exe). The first
one, named foo will be a symbolic link to the
Wine loader (wine). The second one, named
foo.exe.so, is the equivalent of the
.dll.so files we've already described for
DLLs. As in Windows, an executable is, among other things, a module
with its import and export information, as any DLL, it makes sense
Wine uses the same mechanisms for loading native executables and
DLLs.

When starting a Winelib application from the command line (say with
foo arg1 arg2), the Unix shell will execute
foo as a Unix executable. Since this is in fact the
Wine loader, Wine will fire up. However, it will notice that it hasn't
been started as wine but as foo,
and hence, will try to load (using Unix shared library mechanism) the
second file foo.exe.so. Wine will recognize a 32-bit
module (with its descriptor) embedded in the shared library, and
once the shared library loaded, it will proceed the same path as when
loading a standard native PE executable.

Wine needs to implement this second form of executable in order to
maintain the order of initialization of some elements in the
executable. One particular issue is when dealing with global C++
objects. In standard Unix executable, the call of the constructor to
such objects is stored in the specific section of the executable
(.init not to name it). All constructors in this
section are called before the main() or
WinMain function is called. Creating a Wine
executable using the first form mentionned above will let those
constructors being called before Wine gets a chance to initialize
itself. So, any constructor using a Windows API will fail, because
Wine infrastructure isn't in place. The use of the second form for
Winelib executables ensures that we do the initialization using the
following steps:

initialize the Wine infrastructure

load the executable into memory

handle the import sections for the executable

call the global object constructors (if any). They now can
properly call the Windows APIs

call the executable entry point

The attentive reader would have noted that the resolution of imports
for the executable is done, as for a DLL, when the executable/DLL
descriptor is registered. However, this is done also by adding a
specific constructor in the .init section. For
the above describe scheme to function properly, this constructor must
be the first constructor to be called, before all the other
constructors, generated by the executable itself. The Wine build chain
takes care of that, and also generating the executable/DLL descriptor
for the Winelib executable.