diff --git a/documentation/architecture.sgml b/documentation/architecture.sgml
index a42f93840ac..66afd02199c 100644
--- a/documentation/architecture.sgml
+++ b/documentation/architecture.sgml
@@ -1947,6 +1947,149 @@ WSOCK32.DLL: 32-bit sockets APIs
+
+ The Wine initialization process
+
+
+ Wine has a rather complex startup procedure, so unlike many programs the best place to begin
+ exploring the code-base is not in fact at the main() function but instead
+ at some of the more straightforward DLLs that exist on the periphery such as MSI, the widget
+ library (in USER and COMCTL32) etc. The purpose of this section is to document and explain how
+ Wine starts up from the moment the user runs "wine myprogram.exe" to the point at which
+ myprogram gets control.
+
+
+
+ First Steps
+
+
+ The actual wine binary that the user runs does not do very much, in fact it is only
+ responsible for checking the threading model in use (NPTL vs LinuxThreads) and then invoking
+ a new binary which performs the next stage in the startup sequence. See the threading chapter
+ for more information on this check and why it's necessary. You can find this code in
+ loader/glibc.c. The result of this check is an exec of either
+ wine-pthread or wine-kthread, potentially (on Linux) via
+ the preloader. We need to use separate binaries here because overriding
+ the native pthreads library requires us to exploit a property of ELF symbol fixup semantics:
+ it's not possible to do this without starting a new process.
+
+
+
+ The Wine preloader is found in loader/preloader.c, and is required in
+ order to impose a Win32 style address space layout upon the newly created Win32 process. The
+ details of what this does is covered in the address space layout chapter. The preloader is a
+ statically linked ELF binary which is passed the name of the actual Wine binary to run (either
+ wine-kthread or wine-pthread) along with the arguments the user passed in from the command
+ line. The preloader is an unusual program: it does not have a main() function. In standard ELF
+ applications, the entry point is actually at a symbol named _start: this is provided by the
+ standard gcc infrastructure and normally jumps to __libc_start_main which
+ initializes glibc before passing control to the main function as defined by the programmer.
+
+
+
+ The preloader takes control direct from the entry point for a few reasons. Firstly, it is
+ required that glibc is not initialized twice: the result of such behaviour is undefined and
+ subject to change without notice. Secondly, it's possible that as part of initializing glibc,
+ the address space layout could be changed - for instance, any call to malloc will initialize a
+ heap arena which modifies the VM mappings. Finally, glibc does not return to _start at any
+ point, so by reusing it we avoid the need to recreate the ELF bootstrap stack (env, argv,
+ auxiliary array etc).
+
+
+
+ The preloader is responsible for two things: protecting important regions of the address
+ space so the dynamic linker does not map shared libraries into them, and once that is done
+ loading the real Wine binary off disk, linking it and starting it up. Normally all this is
+ done automatically by glibc and the kernel but as we intercepted this process by using a
+ static binary it's up to us to restart the process. The bulk of the code in the preloader is
+ about loading wine-[pk]thread and ld-linux.so.2 off disk, linking them together, then
+ starting the dynamic linking process.
+
+
+
+ One of the last things the preloader does before jumping into the dynamic linker is scan the
+ symbol table of the loaded Wine binary and set the value of a global variable directly: this
+ is a more efficient way of passing information to the main Wine program than flattening the
+ data structures into an environment variable or command line parameter then unpacking it on
+ the other side, but it achieves pretty much the same thing. The global variable set points to
+ the preload descriptor table, which contains the VMA regions protected by the preloader. This
+ allows Wine to unmap them once the dynamic linker has been run, so leaving gaps we can
+ initialize properly later on.
+
+
+
+
+
+ Starting the emulator
+
+
+ The process of starting up the emulator itself is mostly one of chaining through various
+ initializer functions defined in the core libraries and DLLs: libwine, then NTDLL, then kernel32.
+
+
+
+ Both the wine-pthread and wine-kthread binaries share a common main
+ function, defined in loader/main.c, so no matter which binary is selected
+ after the preloader has run we start here. This passes the information provided by the
+ preloader into libwine and then calls wine_init, defined
+ in libs/wine/loader.c. This is where the emulation really starts:
+ wine_init can, with the correct preparation,
+ be called from programs other than the wine loader itself.
+
+
+
+ wine_init does some very basic setup tasks such as initializing the
+ debugging infrastructure, yet more address space manipulation (see the information on the
+ 4G/4G VM split in the address space chapter), before loading NTDLL - the core of both Wine and
+ the Windows NT series - and jumping to the __wine_process_init function defined
+ in dlls/ntdll/loader.c
+
+
+
+ This function is responsible for initializing the primary Win32 environment. In thread_init(),
+ it sets up the TEB, the wineserver connection for the main thread and the process heap. See
+ the threading chapter for more information on this.
+
+
+
+ Finally, it loads and jumps to __wine_kernel_init in kernel32.dll: this
+ is defined in dlls/kernel32/process.c. This is where the bulk of the work
+ is done. The kernel32 initialization code retrieves the startup info for the process from the
+ server, initializes the registry, sets up the drive mapping system and locale data, then
+ begins loading the requested application itself. Each process has a STARTUPINFO block that can
+ be passed into CreateProcess specifying various things like how the first
+ window should be displayed: this is sent to the new process via the wineserver.
+
+
+
+ After determining the type of file given to Wine by the user (a Win32 EXE file, a Win16 EXE, a
+ Winelib app etc), the program is loaded into memory (which may involve loading and
+ initializing other DLLs, the bulk of Wines startup code), before control reaches the end of
+ __wine_kernel_init. This function ends with the new process stack being
+ initialized, and start_process being called on the new stack. Nearly there!
+
+
+
+ The final element of initializing Wine is starting the newly loaded program
+ itself. start_process sets up the SEH backstop handler, calls
+ LdrInitializeThunk which performs the last part of the process
+ initialization (such as performing relocations and calling the DllMains with PROCESS_ATTACH),
+ grabs the entry point of the executable and then on this line:
+
+
+
+ ExitProcess( entry( peb ) );
+
+
+
+ ... jumps to the entry point of the program. At this point the users program is running and
+ the API provided by Wine is ready to be used. When entry returns,
+ the ExitProcess API will be used to initialize a graceful shutdown.
+
+
+
+
+
-
+