7.2. 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.