Reorganizing wine-devel:
- killing the advanced part (and moving its chapters in both
developing Wine and Wine archi parts)
- creating a new book on coding practices from i18n.sgml, patches.sgml
and porting.sgml
- creating a new book on some debugging strategies from the old
advanced book and cvs-regression.sgml
- creating a new book on the kernel modules (NTDLL & KERNEL32) from
architecture.sgml / related DLLs and address-space.sgml,
console.sgml, threading.sgml
- creating a new book on the windowing from architecture.sgml / USER32
and related
- creating a new book on the graphical parts from architecture.sgml /
GDI32 and related
Other changes:
- removed list of DLLs and their role (from the modules overview)
- removed in X11 keyboard mapping section the part related to submit a
patch
diff --git a/documentation/Makefile.in b/documentation/Makefile.in
index f80417e..bbabb82 100644
--- a/documentation/Makefile.in
+++ b/documentation/Makefile.in
@@ -26,20 +26,20 @@
WINE_DEVEL_SRCS = \
address-space.sgml \
architecture.sgml \
- consoles.sgml \
- cvs-regression.sgml \
ddraw.sgml \
debugger.sgml \
debugging.sgml \
documentation.sgml \
- i18n.sgml \
- implementation.sgml \
multimedia.sgml \
ole.sgml \
opengl.sgml \
patches.sgml \
- porting.sgml \
- testing.sgml
+ testing.sgml \
+ winedev-coding.sgml \
+ winedev-graphical.sgml \
+ winedev-kernel.sgml \
+ winedev-otherdebug.sgml \
+ winedev-windowing.sgml
WINELIB_USER_SRCS = \
winelib-bindlls.sgml \
diff --git a/documentation/architecture.sgml b/documentation/architecture.sgml
index 66afd02..62f9f89 100644
--- a/documentation/architecture.sgml
+++ b/documentation/architecture.sgml
@@ -659,6 +659,125 @@
shared library.
</para>
</sect2>
+ <sect2 id="arch-dlls">
+ <title>Wine/Windows DLLs</title>
+
+ <para>
+ This document mainly deals with the status of current DLL
+ support by Wine. The Wine ini file currently supports
+ settings to change the load order of DLLs. The load order
+ depends on several issues, which results in different settings
+ for various DLLs.
+ </para>
+
+ <sect3>
+ <title>Pros of Native DLLs</title>
+
+ <para>
+ Native DLLs of course guarantee 100% compatibility for
+ routines they implement. For example, using the native USER
+ DLL would maintain a virtually perfect and Windows 95-like
+ look for window borders, dialog controls, and so on. Using
+ the built-in Wine version of this library, on the other
+ hand, would produce a display that does not precisely mimic
+ that of Windows 95. Such subtle differences can be
+ engendered in other important DLLs, such as the common
+ controls library COMMCTRL or the common dialogs library
+ COMMDLG, when built-in Wine DLLs outrank other types in load
+ order.
+ </para>
+ <para>
+ More significant, less aesthetically-oriented problems can
+ result if the built-in Wine version of the SHELL DLL is
+ loaded before the native version of this library. SHELL
+ contains routines such as those used by installer utilities
+ to create desktop shortcuts. Some installers might fail when
+ using Wine's built-in SHELL.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Cons of Native DLLs</title>
+
+ <para>
+ Not every application performs better under native DLLs. If
+ a library tries to access features of the rest of the system
+ that are not fully implemented in Wine, the native DLL might
+ work much worse than the corresponding built-in one, if at
+ all. For example, the native Windows GDI library must be
+ paired with a Windows display driver, which of course is not
+ present under Intel Unix and Wine.
+ </para>
+ <para>
+ Finally, occasionally built-in Wine DLLs implement more
+ features than the corresponding native Windows DLLs.
+ Probably the most important example of such behavior is the
+ integration of Wine with X provided by Wine's built-in USER
+ DLL. Should the native Windows USER library take load-order
+ precedence, such features as the ability to use the
+ clipboard or drag-and-drop between Wine windows and X
+ windows will be lost.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Deciding Between Native and Built-In DLLs</title>
+
+ <para>
+ Clearly, there is no one rule-of-thumb regarding which
+ load-order to use. So, you must become familiar with
+ what specific DLLs do and which other DLLs or features
+ a given library interacts with, and use this information
+ to make a case-by-case decision.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Load Order for DLLs</title>
+
+ <para>
+ Using the DLL sections from the wine configuration file, the
+ load order can be tweaked to a high degree. In general it is
+ advised not to change the settings of the configuration
+ file. The default configuration specifies the right load
+ order for the most important DLLs.
+ </para>
+ <para>
+ The default load order follows this algorithm: for all DLLs
+ which have a fully-functional Wine implementation, or where
+ the native DLL is known not to work, the built-in library
+ will be loaded first. In all other cases, the native DLL
+ takes load-order precedence.
+ </para>
+ <para>
+ The <varname>DefaultLoadOrder</varname> from the
+ [DllDefaults] section specifies for all DLLs which version
+ to try first. See manpage for explanation of the arguments.
+ </para>
+ <para>
+ The [DllOverrides] section deals with DLLs, which need a
+ different-from-default treatment.
+ </para>
+ <para>
+ The [DllPairs] section is for DLLs, which must be loaded in
+ pairs. In general, these are DLLs for either 16-bit or
+ 32-bit applications. In most cases in Windows, the 32-bit
+ version cannot be used without its 16-bit counterpart. For
+ Wine, it is customary that the 16-bit implementations rely
+ on the 32-bit implementations and cast the results back to
+ 16-bit arguments. Changing anything in this section is bound
+ to result in errors.
+ </para>
+ <para>
+ For the future, the Wine implementation of Windows DLL seems
+ to head towards unifying the 16 and 32 bit DLLs wherever
+ possible, resulting in larger DLLs. They are stored in the
+ <filename>dlls/</filename> subdirectory using the 32-bit
+ name.
+ </para>
+ </sect3>
+ </sect2>
+
<sect2 id="arch-mem">
<title>Memory management</title>
<para>
@@ -828,7 +947,116 @@
Wine is using, the glibc malloc arena and so on.
</para>
</sect3>
+
+ <sect3 id="address-space">
+ <title>Laying out the address space</title>
+
+ <para>
+ Up until about the start of 2004, the Linux address space
+ very much resembled the Windows 9x layout: the kernel sat
+ in the top gigabyte, the bottom pages were unmapped to
+ catch null pointer dereferences, and the rest was
+ free. The kernels mmap algorithm was predictable: it would
+ start by mapping files at low addresses and work up from
+ there.
+ </para>
+
+ <para>
+ The development of a series of new low level patches
+ violated many of these assumptions, and resulted in Wine
+ needing to force the Win32 address space layout upon the
+ system. This section looks at why and how this is done.
+ </para>
+
+ <para>
+ The exec-shield patch increases security by randomizing
+ the kernels mmap algorithms. Rather than consistently
+ choosing the same addresses given the same sequence of
+ requests, the kernel will now choose randomized
+ addresses. Because the Linux dynamic linker
+ (ld-linux.so.2) loads DSOs into memory by using mmap, this
+ means that DSOs are no longer loaded at predictable
+ addresses, so making it harder to attack software by using
+ buffer overflows. It also attempts to relocate certain
+ binaries into a special low area of memory known as the
+ ASCII armor so making it harder to jump into them when
+ using string based attacks.
+ </para>
+
+ <para>
+ Prelink is a technology that enhances startup times by
+ precalculating ELF global offset tables then saving the
+ results inside the native binaries themselves. By grid
+ fitting each DSO into the address space, the dynamic
+ linker does not have to perform as many relocations so
+ allowing applications that heavily rely on dynamic linkage
+ to be loaded into memory much quicker. Complex C++
+ applications such as Mozilla, OpenOffice and KDE can
+ especially benefit from this technique.
+ </para>
+
+ <para>
+ The 4G VM split patch was developed by Ingo Molnar. It
+ gives the Linux kernel its own address space, thereby
+ allowing processes to access the maximum addressable
+ amount of memory on a 32-bit machine: 4 gigabytes. It
+ allows people with lots of RAM to fully utilise that in
+ any given process at the cost of performance: the reason
+ behind giving the kernel a part of each processes address
+ space was to avoid the overhead of switching on each
+ syscall.
+ </para>
+
+ <para>
+ Each of these changes alter the address space in a way
+ incompatible with Windows. Prelink and exec-shield mean
+ that the libraries Wine uses can be placed at any point in
+ the address space: typically this meant that a library was
+ sitting in the region that the EXE you wanted to run had
+ to be loaded (remember that unlike DLLs, EXE files cannot
+ be moved around in memory). The 4G VM split means that
+ programs could receive pointers to the top gigabyte of
+ address space which some are not prepared for (they may
+ store extra information in the high bits of a pointer, for
+ instance). In particular, in combination with exec-shield
+ this one is especially deadly as it's possible the process
+ heap could be allocated beyond ADDRESS_SPACE_LIMIT which
+ causes Wine initialization to fail.
+ </para>
+
+ <para>
+ The solution to these problems is for Wine to reserve
+ particular parts of the address space so that areas that
+ we don't want the system to use will be avoided. We later
+ on (re/de)allocate those areas as needed. One problem is
+ that some of these mappings are put in place automatically
+ by the dynamic linker: for instance any libraries that
+ Wine is linked to (like libc, libwine, libpthread etc)
+ will be mapped into memory before Wine even gets
+ control. In order to solve that, Wine overrides the
+ default ELF initialization sequence at a low level and
+ reserves the needed areas by using direct syscalls into
+ the kernel (ie without linking against any other code to
+ do it) before restarting the standard initialization and
+ letting the dynamic linker continue. This is referred to
+ as the preloader and is found in loader/preloader.c.
+ </para>
+
+ <para>
+ Once the usual ELF boot sequence has been completed, some
+ native libraries may well have been mapped above the 3gig
+ limit: however, this doesn't matter as 3G is a Windows
+ limit, not a Linux limit. We still have to prevent the
+ system from allocating anything else above there (like the
+ heap or other DLLs) though so Wine performs a binary
+ search over the upper gig of address space in order to
+ iteratively fill in the holes with MAP_NORESERVE mappings
+ so the address space is allocated but the memory to
+ actually back it is not. This code can be found in libs/wine/mmap.c:reserve_area.
+ </para>
+ </sect3>
</sect2>
+
<sect2>
<title>Processes</title>
<para>
@@ -1124,971 +1352,8 @@
</para>
</sect2>
</sect1>
-
- <sect1 id="module-overview">
-
- <title>Module Overview</title>
- <sect2>
- <title>NTDLL Module</title>
- <para>
- NTDLL provides most of the services you'd expect from a
- kernel.
- </para>
- <para>
- Process and thread management are part of them (even if
- process management is still mainly done in KERNEL32, unlike
- NT). A Windows process runs as a Unix process, and a Windows
- thread runs as a Unix thread.
- </para>
- <para>
- Wine also provide fibers (which is the Windows name of
- co-routines).
- </para>
- <para>
- Most of the Windows memory handling (Heap, Global and Local
- functions, virtual memory...) are easily mapped upon their
- Unix equivalents. Note the NTDLL doesn't know about 16 bit
- memory, which is only handled in KERNEL32/KRNL386.EXE (and
- also the DOS routines).
- </para>
-
- <sect3>
- <title>File management</title>
- <para>
- Wine uses some configuration in order to map Windows
- filenames (either defined with drive letters, or as UNC
- names) to the unix filenames. Wine also uses some
- incantation so that most of file related APIs can also
- take full unix names. This is handy when passing filenames
- on the command line.
- </para>
- <para>
- File handles can be waitable objects, as Windows define
- them.
- </para>
- <para>
- Asynchronous I/O is implemented on file handles by
- queueing pseudo APC. They are not real APC in the sense
- that they have the same priority as the threads in the
- considered process (while APCs on NT have normally a
- higher priority). These APCs get called when invoking
- Wine server (which should lead to correct behavior when the
- program ends up waiting on some object - waiting always
- implies calling Wine server).
- </para>
- <para>
- FIXME: this should be enhanced and updated to latest work
- on FS.
- </para>
- </sect3>
-
- <sect3>
- <title>Synchronization</title>
- <para>
- Most of the synchronization (between threads or processes)
- is done in Wine server, which handles both the waiting
- operation (on a single object or a set of objects) and the
- signaling of objects.
- </para>
- </sect3>
-
- <sect3>
- <title>Module (DLL) loading</title>
- <para>
- Wine is able to load any NE and PE module. In all cases,
- the module's binary code is directly executed by the
- processor.
- </para>
- </sect3>
-
- <sect3>
- <title>Device management</title>
- <para>
- Wine allows usage a wide variety of devices:
- <itemizedlist>
- <listitem>
- <para>
- Communication ports are mapped to Unix
- communication ports (if they have sufficient
- permissions).
- </para>
- </listitem>
- <listitem>
- <para>
- Parallel ports are mapped to Unix parallel ports (if
- they have sufficient permissions).
- </para>
- </listitem>
- <listitem>
- <para>
- CDROM: the Windows device I/O control calls are
- mapped onto Unix <function>ioctl()</function>.
- </para>
- </listitem>
- <listitem>
- <para>
- Some Win9x VxDs are supported, by rewriting some of
- their internal behavior. But this support is
- limited. Portable programs to Windows NT shouldn't
- need them.
- </para>
- <para>
- Wine will not support native VxD.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </sect3>
- </sect2>
-
- <sect2>
- <title>KERNEL Module</title>
-
- <para>
- FIXME: Needs some content...
- </para>
- </sect2>
-
- <sect2>
- <title>GDI Module</title>
-
- <sect3>
- <title>X Windows System interface</title>
-
- <para>
- The X libraries used to implement X clients (such as Wine)
- do not work properly if multiple threads access the same
- display concurrently. It is possible to compile the X
- libraries to perform their own synchronization (initiated
- by calling <function>XInitThreads()</function>). However,
- Wine does not use this approach. Instead Wine performs its
- own synchronization using the
- <function>wine_tsx11_lock()</function> / <function>wine_tsx11_unlock()</function>
- functions. This locking protects library access
- with a critical section, and also arranges things so that
- X libraries compiled without <option>-D_REENTRANT</option>
- (eg. with global <varname>errno</varname> variable) will
- work with Wine.
- </para>
- <para>
- In the past, all calls to X used to go through a wrapper called
- <function>TSX...()</function> (for "Thread Safe X ...").
- While it is still being used in the code, it's inefficient
- as the lock is potentially aquired and released unnecessarily.
- New code should explicitly aquire the lock.
- </para>
- </sect3>
- </sect2>
-
- <sect2>
- <title>USER Module</title>
-
- <para>
- USER implements windowing and messaging subsystems. It also
- contains code for common controls and for other
- miscellaneous stuff (rectangles, clipboard, WNet, etc).
- Wine USER code is located in <filename>windows/</filename>,
- <filename>controls/</filename>, and
- <filename>misc/</filename> directories.
- </para>
-
- <sect3>
- <title>Windowing subsystem</title>
-
- <para><filename>windows/win.c</filename></para>
- <para><filename>windows/winpos.c</filename></para>
- <para>
- Windows are arranged into parent/child hierarchy with one
- common ancestor for all windows (desktop window). Each
- window structure contains a pointer to the immediate
- ancestor (parent window if <constant>WS_CHILD</constant>
- style bit is set), a pointer to the sibling (returned by
- <function>GetWindow(..., GW_NEXT)</function>), a pointer
- to the owner window (set only for popup window if it was
- created with valid <varname>hwndParent</varname>
- parameter), and a pointer to the first child window
- (<function>GetWindow(.., GW_CHILD)</function>). All popup
- and non-child windows are therefore placed in the first
- level of this hierarchy and their ancestor link
- (<varname>wnd->parent</varname>) points to the desktop
- window.
- </para>
- <screen>
- Desktop window - root window
- | \ `-.
- | \ `-.
- popup -> wnd1 -> wnd2 - top level windows
- | \ `-. `-.
- | \ `-. `-.
- child1 child2 -> child3 child4 - child windows
- </screen>
- <para>
- Horizontal arrows denote sibling relationship, vertical
- lines - ancestor/child. To summarize, all windows with the
- same immediate ancestor are sibling windows, all windows
- which do not have desktop as their immediate ancestor are
- child windows. Popup windows behave as topmost top-level
- windows unless they are owned. In this case the only
- requirement is that they must precede their owners in the
- top-level sibling list (they are not topmost). Child
- windows are confined to the client area of their parent
- windows (client area is where window gets to do its own
- drawing, non-client area consists of caption, menu,
- borders, intrinsic scrollbars, and
- minimize/maximize/close/help buttons).
- </para>
- <para>
- Another fairly important concept is
- <firstterm>z-order</firstterm>. It is derived from the
- ancestor/child hierarchy and is used to determine
- "above/below" relationship. For instance, in the example
- above, z-order is
- </para>
- <screen>
-child1->popup->child2->child3->wnd1->child4->wnd2->desktop.
- </screen>
- <para>
- Current active window ("foreground window" in Win32) is
- moved to the front of z-order unless its top-level
- ancestor owns popup windows.
- </para>
- <para>
- All these issues are dealt with (or supposed to be) in
- <filename>windows/winpos.c</filename> with
- <function>SetWindowPos()</function> being the primary
- interface to the window manager.
- </para>
- <para>
- Wine specifics: in default and managed mode each top-level
- window gets its own X counterpart with desktop window
- being basically a fake stub. In desktop mode, however,
- only desktop window has an X window associated with it.
- Also, <function>SetWindowPos()</function> should
- eventually be implemented via
- <function>Begin/End/DeferWindowPos()</function> calls and
- not the other way around.
- </para>
-
- <sect4>
- <title>Visible region, clipping region and update region</title>
-
- <para><filename>windows/dce.c</filename></para>
- <para><filename>windows/winpos.c</filename></para>
- <para><filename>windows/painting.c</filename></para>
-
- <screen>
- ________________________
- |_________ | A and B are child windows of C
- | A |______ |
- | | | |
- |---------' | |
- | | B | |
- | | | |
- | `------------' |
- | C |
- `------------------------'
- </screen>
- <para>
- Visible region determines which part of the window is
- not obscured by other windows. If a window has the
- <constant>WS_CLIPCHILDREN</constant> style then all
- areas below its children are considered invisible.
- Similarly, if the <constant>WS_CLIPSIBLINGS</constant>
- bit is in effect then all areas obscured by its siblings
- are invisible. Child windows are always clipped by the
- boundaries of their parent windows.
- </para>
- <para>
- B has a <constant>WS_CLIPSIBLINGS</constant> style:
- </para>
- <screen>
- . ______
- : | |
- | ,-----' |
- | | B | - visible region of B
- | | |
- : `------------'
- </screen>
- <para>
- When the program requests a <firstterm>display
- context</firstterm> (DC) for a window it can specify
- an optional clipping region that further restricts the
- area where the graphics output can appear. This area is
- calculated as an intersection of the visible region and
- a clipping region.
- </para>
- <para>
- Program asked for a DC with a clipping region:
- </para>
- <screen>
- ______
- ,--|--. | . ,--.
- ,--+--' | | : _: |
- | | B | | => | | | - DC region where the painting will
- | | | | | | | be visible
- `--|-----|---' : `----'
- `-----'
- </screen>
- <para>
- When the window manager detects that some part of the window
- became visible it adds this area to the update region of this
- window and then generates <constant>WM_ERASEBKGND</constant> and
- <constant>WM_PAINT</constant> messages. In addition,
- <constant>WM_NCPAINT</constant> message is sent when the
- uncovered area intersects a nonclient part of the window.
- Application must reply to the <constant>WM_PAINT</constant>
- message by calling the
- <function>BeginPaint()</function>/<function>EndPaint()</function>
- pair of functions. <function>BeginPaint()</function> returns a DC
- that uses accumulated update region as a clipping region. This
- operation cleans up invalidated area and the window will not
- receive another <constant>WM_PAINT</constant> until the window
- manager creates a new update region.
- </para>
- <para>
- A was moved to the left:
- </para>
- <screen>
- ________________________ ... / C update region
- |______ | : .___ /
- | A |_________ | => | ...|___|..
- | | | | | : | |
- |------' | | | : '---'
- | | B | | | : \
- | | | | : \
- | `------------' | B update region
- | C |
- `------------------------'
- </screen>
- <para>
- Windows maintains a display context cache consisting of
- entries that include the DC itself, the window to which
- it belongs, and an optional clipping region (visible
- region is stored in the DC itself). When an API call
- changes the state of the window tree, window manager has
- to go through the DC cache to recalculate visible
- regions for entries whose windows were involved in the
- operation. DC entries (DCE) can be either private to the
- window, or private to the window class, or shared
- between all windows (Windows 3.1 limits the number of
- shared DCEs to 5).
- </para>
- </sect4>
- </sect3>
-
- <sect3>
- <title>Messaging subsystem</title>
-
- <para><filename>windows/queue.c</filename></para>
- <para><filename>windows/message.c</filename></para>
-
- <para>
- Each Windows task/thread has its own message queue - this
- is where it gets messages from. Messages can be:
- <orderedlist>
- <listitem>
- <para>
- generated on the fly (<constant>WM_PAINT</constant>,
- <constant>WM_NCPAINT</constant>,
- <constant>WM_TIMER</constant>)
- </para>
- </listitem>
- <listitem>
- <para>
- created by the system (hardware messages)
- </para>
- </listitem>
- <listitem>
- <para>
- posted by other tasks/threads (<function>PostMessage</function>)
- </para>
- </listitem>
- <listitem>
- <para>
- sent by other tasks/threads (<function>SendMessage</function>)
- </para>
- </listitem>
- </orderedlist>
- </para>
- <para>
- Message priority:
- </para>
- <para>
- First the system looks for sent messages, then for posted
- messages, then for hardware messages, then it checks if
- the queue has the "dirty window" bit set, and, finally, it
- checks for expired timers. See
- <filename>windows/message.c</filename>.
- </para>
- <para>
- From all these different types of messages, only posted
- messages go directly into the private message queue.
- System messages (even in Win95) are first collected in the
- system message queue and then they either sit there until
- <function>Get/PeekMessage</function> gets to process them
- or, as in Win95, if system queue is getting clobbered, a
- special thread ("raw input thread") assigns them to the
- private queues. Sent messages are queued separately and
- the sender sleeps until it gets a reply. Special messages
- are generated on the fly depending on the window/queue
- state. If the window update region is not empty, the
- system sets the <constant>QS_PAINT</constant> bit in the
- owning queue and eventually this window receives a
- <constant>WM_PAINT</constant> message
- (<constant>WM_NCPAINT</constant> too if the update region
- intersects with the non-client area). A timer event is
- raised when one of the queue timers expire. Depending on
- the timer parameters <function>DispatchMessage</function>
- either calls the callback function or the window
- procedure. If there are no messages pending the
- task/thread sleeps until messages appear.
- </para>
- <para>
- There are several tricky moments (open for discussion) -
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- System message order has to be honored and messages
- should be processed within correct task/thread
- context. Therefore when <function>Get/PeekMessage</function> encounters
- unassigned system message and this message appears not
- to be for the current task/thread it should either
- skip it (or get rid of it by moving it into the
- private message queue of the target task/thread -
- Win95, AFAIK) and look further or roll back and then
- yield until this message gets processed when system
- switches to the correct context (Win16). In the first
- case we lose correct message ordering, in the second
- case we have the infamous synchronous system message
- queue. Here is a post to one of the OS/2 newsgroup I
- found to be relevant:
- </para>
- <blockquote>
- <attribution>by David Charlap</attribution>
- <para>
- " Here's the problem in a nutshell, and there is no
- good solution. Every possible solution creates a
- different problem.
- </para>
- <para>
- With a windowing system, events can go to many
- different windows. Most are sent by applications or
- by the OS when things relating to that window happen
- (like repainting, timers, etc.)
- </para>
- <para>
- Mouse input events go to the window you click on
- (unless some window captures the mouse).
- </para>
- <para>
- So far, no problem. Whenever an event happens, you
- put a message on the target window's message queue.
- Every process has a message queue. If the process
- queue fills up, the messages back up onto the system
- queue.
- </para>
- <para>
- This is the first cause of apps hanging the GUI. If
- an app doesn't handle messages and they back up into
- the system queue, other apps can't get any more
- messages. The reason is that the next message in
- line can't go anywhere, and the system won't skip
- over it.
- </para>
- <para>
- This can be fixed by making apps have bigger private
- message queues. The SIQ fix does this. PMQSIZE does
- this for systems without the SIQ fix. Applications
- can also request large queues on their own.
- </para>
- <para>
- Another source of the problem, however, happens when
- you include keyboard events. When you press a key,
- there's no easy way to know what window the
- keystroke message should be delivered to.
- </para>
- <para>
- Most windowing systems use a concept known as
- "focus". The window with focus gets all incoming
- keyboard messages. Focus can be changed from window
- to window by apps or by users clicking on windows.
- </para>
- <para>
- This is the second source of the problem. Suppose
- window A has focus. You click on window B and start
- typing before the window gets focus. Where should
- the keystrokes go? On the one hand, they should go
- to A until the focus actually changes to B. On the
- other hand, you probably want the keystrokes to go
- to B, since you clicked there first.
- </para>
- <para>
- OS/2's solution is that when a focus-changing event
- happens (like clicking on a window), OS/2 holds all
- messages in the system queue until the focus change
- actually happens. This way, subsequent keystrokes
- go to the window you clicked on, even if it takes a
- while for that window to get focus.
- </para>
- <para>
- The downside is that if the window takes a real long
- time to get focus (maybe it's not handling events,
- or maybe the window losing focus isn't handling
- events), everything backs up in the system queue and
- the system appears hung.
- </para>
- <para>
- There are a few solutions to this problem.
- </para>
- <para>
- One is to make focus policy asynchronous. That is,
- focus changing has absolutely nothing to do with the
- keyboard. If you click on a window and start typing
- before the focus actually changes, the keystrokes go
- to the first window until focus changes, then they
- go to the second. This is what X-windows does.
- </para>
- <para>
- Another is what NT does. When focus changes,
- keyboard events are held in the system message
- queue, but other events are allowed through. This is
- "asynchronous" because the messages in the system
- queue are delivered to the application queues in a
- different order from that with which they were
- posted. If a bad app won't handle the "lose focus"
- message, it's of no consequence - the app receiving
- focus will get its "gain focus" message, and the
- keystrokes will go to it.
- </para>
- <para>
- The NT solution also takes care of the application
- queue filling up problem. Since the system delivers
- messages asynchronously, messages waiting in the
- system queue will just sit there and the rest of the
- messages will be delivered to their apps.
- </para>
- <para>
- The OS/2 SIQ solution is this: When a
- focus-changing event happens, in addition to
- blocking further messages from the application
- queues, a timer is started. When the timer goes
- off, if the focus change has not yet happened, the
- bad app has its focus taken away and all messages
- targeted at that window are skipped. When the bad
- app finally handles the focus change message, OS/2
- will detect this and stop skipping its messages.
- </para>
-
- <para>
- As for the pros and cons:
- </para>
- <para>
- The X-windows solution is probably the easiest. The
- problem is that users generally don't like having to
- wait for the focus to change before they start
- typing. On many occasions, you can type and the
- characters end up in the wrong window because
- something (usually heavy system load) is preventing
- the focus change from happening in a timely manner.
- </para>
- <para>
- The NT solution seems pretty nice, but making the
- system message queue asynchronous can cause similar
- problems to the X-windows problem. Since messages
- can be delivered out of order, programs must not
- assume that two messages posted in a particular
- order will be delivered in that same order. This
- can break legacy apps, but since Win32 always had an
- asynchronous queue, it is fair to simply tell app
- designers "don't do that". It's harder to tell app
- designers something like that on OS/2 - they'll
- complain "you changed the rules and our apps are
- breaking."
- </para>
- <para>
- The OS/2 solution's problem is that nothing happens
- until you try to change window focus, and then wait
- for the timeout. Until then, the bad app is not
- detected and nothing is done."
- </para>
- </blockquote>
- </listitem>
-
- <listitem>
- <para>
- Intertask/interthread
- <function>SendMessage</function>. The system has to
- inform the target queue about the forthcoming message,
- then it has to carry out the context switch and wait
- until the result is available. Win16 stores necessary
- parameters in the queue structure and then calls
- <function>DirectedYield()</function> function.
- However, in Win32 there could be several messages
- pending sent by preemptively executing threads, and in
- this case <function>SendMessage</function> has to
- build some sort of message queue for sent messages.
- Another issue is what to do with messages sent to the
- sender when it is blocked inside its own
- <function>SendMessage</function>.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- </sect2>
- </sect1>
-
- <sect1 id="arch-dlls">
- <title>Wine/Windows DLLs</title>
-
- <para>
- This document mainly deals with the status of current DLL
- support by Wine. The Wine ini file currently supports
- settings to change the load order of DLLs. The load order
- depends on several issues, which results in different settings
- for various DLLs.
- </para>
-
- <sect2>
- <title>Pros of Native DLLs</title>
-
- <para>
- Native DLLs of course guarantee 100% compatibility for
- routines they implement. For example, using the native USER
- DLL would maintain a virtually perfect and Windows 95-like
- look for window borders, dialog controls, and so on. Using
- the built-in Wine version of this library, on the other
- hand, would produce a display that does not precisely mimic
- that of Windows 95. Such subtle differences can be
- engendered in other important DLLs, such as the common
- controls library COMMCTRL or the common dialogs library
- COMMDLG, when built-in Wine DLLs outrank other types in load
- order.
- </para>
- <para>
- More significant, less aesthetically-oriented problems can
- result if the built-in Wine version of the SHELL DLL is
- loaded before the native version of this library. SHELL
- contains routines such as those used by installer utilities
- to create desktop shortcuts. Some installers might fail when
- using Wine's built-in SHELL.
- </para>
- </sect2>
-
- <sect2>
- <title>Cons of Native DLLs</title>
-
- <para>
- Not every application performs better under native DLLs. If
- a library tries to access features of the rest of the system
- that are not fully implemented in Wine, the native DLL might
- work much worse than the corresponding built-in one, if at
- all. For example, the native Windows GDI library must be
- paired with a Windows display driver, which of course is not
- present under Intel Unix and Wine.
- </para>
- <para>
- Finally, occasionally built-in Wine DLLs implement more
- features than the corresponding native Windows DLLs.
- Probably the most important example of such behavior is the
- integration of Wine with X provided by Wine's built-in USER
- DLL. Should the native Windows USER library take load-order
- precedence, such features as the ability to use the
- clipboard or drag-and-drop between Wine windows and X
- windows will be lost.
- </para>
- </sect2>
-
- <sect2>
- <title>Deciding Between Native and Built-In DLLs</title>
-
- <para>
- Clearly, there is no one rule-of-thumb regarding which
- load-order to use. So, you must become familiar with
- what specific DLLs do and which other DLLs or features
- a given library interacts with, and use this information
- to make a case-by-case decision.
- </para>
-
- </sect2>
-
- <sect2>
- <title>Load Order for DLLs</title>
-
- <para>
- Using the DLL sections from the wine configuration file, the
- load order can be tweaked to a high degree. In general it is
- advised not to change the settings of the configuration
- file. The default configuration specifies the right load
- order for the most important DLLs.
- </para>
- <para>
- The default load order follows this algorithm: for all DLLs
- which have a fully-functional Wine implementation, or where
- the native DLL is known not to work, the built-in library
- will be loaded first. In all other cases, the native DLL
- takes load-order precedence.
- </para>
- <para>
- The <varname>DefaultLoadOrder</varname> from the
- [DllDefaults] section specifies for all DLLs which version
- to try first. See manpage for explanation of the arguments.
- </para>
- <para>
- The [DllOverrides] section deals with DLLs, which need a
- different-from-default treatment.
- </para>
- <para>
- The [DllPairs] section is for DLLs, which must be loaded in
- pairs. In general, these are DLLs for either 16-bit or
- 32-bit applications. In most cases in Windows, the 32-bit
- version cannot be used without its 16-bit counterpart. For
- Wine, it is customary that the 16-bit implementations rely
- on the 32-bit implementations and cast the results back to
- 16-bit arguments. Changing anything in this section is bound
- to result in errors.
- </para>
- <para>
- For the future, the Wine implementation of Windows DLL seems
- to head towards unifying the 16 and 32 bit DLLs wherever
- possible, resulting in larger DLLs. They are stored in the
- <filename>dlls/</filename> subdirectory using the 32-bit
- name.
- </para>
- </sect2>
-
- <sect2>
- <title>Understanding What DLLs Do</title>
-
- <para>
- The following list briefly describes each of the DLLs
- commonly found in Windows whose load order may be modified
- during the configuration and compilation of Wine.
- </para>
- <para>
- (See also <filename>./DEVELOPER-HINTS</filename> or the
- <filename>dlls/</filename> subdirectory to see which DLLs
- are currently being rewritten for Wine)
- </para>
-
-<!-- FIXME: Should convert this table into a VariableList element -->
- <screen>
-ADVAPI32.DLL: 32-bit application advanced programming interfaces
- like crypto, systeminfo, security and event logging
-AVIFILE.DLL: 32-bit application programming interfaces for the
- Audio Video Interleave (AVI) Windows-specific
- Microsoft audio-video standard
-COMMCTRL.DLL: 16-bit common controls
-COMCTL32.DLL: 32-bit common controls
-COMDLG32.DLL: 32-bit common dialogs
-COMMDLG.DLL: 16-bit common dialogs
-COMPOBJ.DLL: OLE 16- and 32-bit compatibility libraries
-CRTDLL.DLL: Microsoft C runtime
-DCIMAN.DLL: 16-bit
-DCIMAN32.DLL: 32-bit display controls
-DDEML.DLL: DDE messaging
-D3D*.DLL DirectX/Direct3D drawing libraries
-DDRAW.DLL: DirectX drawing libraries
-DINPUT.DLL: DirectX input libraries
-DISPLAY.DLL: Display libraries
-DPLAY.DLL, DPLAYX.DLL: DirectX playback libraries
-DSOUND.DLL: DirectX audio libraries
-GDI.DLL: 16-bit graphics driver interface
-GDI32.DLL: 32-bit graphics driver interface
-IMAGEHLP.DLL: 32-bit IMM API helper libraries (for PE-executables)
-IMM32.DLL: 32-bit IMM API
-IMGUTIL.DLL:
-KERNEL32.DLL 32-bit kernel DLL
-KEYBOARD.DLL: Keyboard drivers
-LZ32.DLL: 32-bit Lempel-Ziv or LZ file compression
- used by the installshield installers (???).
-LZEXPAND.DLL: LZ file expansion; needed for Windows Setup
-MMSYSTEM.DLL: Core of the Windows multimedia system
-MOUSE.DLL: Mouse drivers
-MPR.DLL: 32-bit Windows network interface
-MSACM.DLL: Core of the Addressed Call Mode or ACM system
-MSACM32.DLL: Core of the 32-bit ACM system
- Audio Compression Manager ???
-MSNET32.DLL 32-bit network APIs
-MSVFW32.DLL: 32-bit Windows video system
-MSVIDEO.DLL: 16-bit Windows video system
-OLE2.DLL: OLE 2.0 libraries
-OLE32.DLL: 32-bit OLE 2.0 components
-OLE2CONV.DLL: Import filter for graphics files
-OLE2DISP.DLL, OLE2NLS.DLL: OLE 2.1 16- and 32-bit interoperability
-OLE2PROX.DLL: Proxy server for OLE 2.0
-OLE2THK.DLL: Thunking for OLE 2.0
-OLEAUT32.DLL 32-bit OLE 2.0 automation
-OLECLI.DLL: 16-bit OLE client
-OLECLI32.DLL: 32-bit OLE client
-OLEDLG.DLL: OLE 2.0 user interface support
-OLESVR.DLL: 16-bit OLE server libraries
-OLESVR32.DLL: 32-bit OLE server libraries
-PSAPI.DLL: Proces Status API libraries
-RASAPI16.DLL: 16-bit Remote Access Services libraries
-RASAPI32.DLL: 32-bit Remote Access Services libraries
-SHELL.DLL: 16-bit Windows shell used by Setup
-SHELL32.DLL: 32-bit Windows shell (COM object?)
-TAPI/TAPI32/TAPIADDR: Telephone API (for Modems)
-W32SKRNL: Win32s Kernel ? (not in use for Win95 and up!)
-WIN32S16.DLL: Application compatibility for Win32s
-WIN87EM.DLL: 80387 math-emulation libraries
-WINASPI.DLL: Advanced SCSI Peripheral Interface or ASPI libraries
-WINDEBUG.DLL Windows debugger
-WINMM.DLL: Libraries for multimedia thunking
-WING.DLL: Libraries required to "draw" graphics
-WINSOCK.DLL: Sockets APIs
-WINSPOOL.DLL: Print spooler libraries
-WNASPI32.DLL: 32-bit ASPI libraries
-WSOCK32.DLL: 32-bit sockets APIs
- </screen>
- </sect2>
- </sect1>
</chapter>
- <chapter id="initialization">
- <title> The Wine initialization process </title>
-
- <para>
- Wine has a rather complex startup procedure, so unlike many programs the best place to begin
- exploring the code-base is <emphasis>not</emphasis> 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.
- </para>
-
- <sect1>
- <title> First Steps </title>
-
- <para>
- 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
- <filename>loader/glibc.c</filename>. The result of this check is an exec of either
- wine-pthread or wine-kthread, potentially (on Linux) via
- the <emphasis>preloader</emphasis>. 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.
- </para>
-
- <para>
- The Wine preloader is found in <filename>loader/preloader.c</filename>, 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 <function>__libc_start_main</function> which
- initializes glibc before passing control to the main function as defined by the programmer.
- </para>
-
- <para>
- 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).
- </para>
-
- <para>
- 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.
- </para>
-
- <para>
- 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.
- </para>
-
- </sect1>
-
- <sect1>
- <title> Starting the emulator </title>
-
- <para>
- 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.
- </para>
-
- <para>
- Both the wine-pthread and wine-kthread binaries share a common <function>main</function>
- function, defined in <filename>loader/main.c</filename>, 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 <filename>libs/wine/loader.c</filename>. This is where the emulation really starts:
- <function>wine_init</function> can, with the correct preparation,
- be called from programs other than the wine loader itself.
- </para>
-
- <para>
- <function>wine_init</function> 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 <function>__wine_process_init</function> function defined
- in <filename>dlls/ntdll/loader.c</filename>
- </para>
-
- <para>
- 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.
- </para>
-
- <para>
- Finally, it loads and jumps to <function>__wine_kernel_init</function> in kernel32.dll: this
- is defined in <filename>dlls/kernel32/process.c</filename>. 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 <function>CreateProcess</function> specifying various things like how the first
- window should be displayed: this is sent to the new process via the wineserver.
- </para>
-
- <para>
- 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
- <function>__wine_kernel_init</function>. This function ends with the new process stack being
- initialized, and start_process being called on the new stack. Nearly there!
- </para>
-
- <para>
- The final element of initializing Wine is starting the newly loaded program
- itself. <function>start_process</function> sets up the SEH backstop handler, calls
- <function>LdrInitializeThunk</function> 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:
- </para>
-
- <programlisting>
- ExitProcess( entry( peb ) );
- </programlisting>
-
- <para>
- ... 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 <function>ExitProcess</function> API will be used to initialize a graceful shutdown.
- </para>
-
- </sect1>
- </chapter>
<!-- Keep this comment at the end of the file
Local variables:
diff --git a/documentation/consoles.sgml b/documentation/consoles.sgml
deleted file mode 100644
index fa420f0..0000000
--- a/documentation/consoles.sgml
+++ /dev/null
@@ -1,174 +0,0 @@
- <chapter id="consoles">
- <title>Consoles in Wine</title>
-
- <para>
- As described in the Wine User Guide's CUI section, Wine
- manipulates three kinds of "consoles" in order to support
- properly the Win32 CUI API.
- </para>
- <para>
- The following table describes the main implementation
- differences between the three approaches.
-
- <table>
- <title>Function consoles implementation comparison</title>
- <tgroup cols="4" align="left">
- <thead>
- <row>
- <entry>Function</entry>
- <entry>Bare streams</entry>
- <entry>Wineconsole & user backend</entry>
- <entry>Wineconsole & curses backend</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- Console as a Win32 Object (and associated
- handles)
- </entry>
- <entry>
- No specific Win32 object is used in this case. The
- handles manipulated for the standard Win32 streams
- are in fact "bare handles" to their corresponding
- Unix streams. The mode manipulation functions
- (<function>GetConsoleMode</function> /
- <function>SetConsoleMode</function>) are not
- supported.
- </entry>
- <entry>
- Implemented in server, and a specific Winelib
- program (wineconsole) is in charge of the
- rendering and user input. The mode manipulation
- functions behave as expected.
- </entry>
- <entry>
- Implemented in server, and a specific Winelib
- program (wineconsole) is in charge of the
- rendering and user input. The mode manipulation
- functions behave as expected.
- </entry>
- </row>
- <row>
- <entry>
- Inheritance (including handling in
- <function>CreateProcess</function> of
- <constant>CREATE_DETACHED</constant>,
- <constant>CREATE_NEW_CONSOLE</constant> flags).
- </entry>
- <entry>
- Not supported. Every process child of a process
- will inherit the Unix streams, so will also
- inherit the Win32 standard streams.
- </entry>
- <entry>
- Fully supported (each new console creation will be
- handled by the creation of a new USER32 window)
- </entry>
- <entry>
- Fully supported, except for the creation of a new
- console, which will be rendered on the same Unix
- terminal as the previous one, leading to
- unpredictable results.
- </entry>
- </row>
- <row>
- <entry><function>ReadFile</function> / <function>WriteFile</function> operations</entry>
- <entry>Fully supported</entry>
- <entry>Fully supported</entry>
- <entry>Fully supported</entry>
- </row>
- <row>
- <entry>
- Screen-buffer manipulation (creation, deletion, resizing...)
- </entry>
- <entry>Not supported</entry>
- <entry>Fully supported</entry>
- <entry>
- Partly supported (this won't work too well as we
- don't control (so far) the size of underlying Unix
- terminal
- </entry>
- </row>
- <row>
- <entry>
- APIs for reading/writing screen-buffer content,
- cursor position
- </entry>
- <entry>Not supported</entry>
- <entry>Fully supported</entry>
- <entry>Fully supported</entry>
- </row>
- <row>
- <entry>
- APIs for manipulating the rendering window size
- </entry>
- <entry>Not supported</entry>
- <entry>Fully supported</entry>
- <entry>
- Partly supported (this won't work too well as we
- don't control (so far) the size of underlying Unix
- terminal
- </entry>
- </row>
- <row>
- <entry>
- Signaling (in particular, Ctrl-C handling)
- </entry>
- <entry>
- Nothing is done, which means that Ctrl-C will
- generate (as usual) a <constant>SIGINT</constant>
- which will terminate the program.
- </entry>
- <entry>
- Partly supported (Ctrl-C behaves as expected,
- however the other Win32 CUI signaling isn't
- properly implemented).
- </entry>
- <entry>
- Partly supported (Ctrl-C behaves as expected,
- however the other Win32 CUI signaling isn't
- properly implemented).
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </para>
-
- <para>
- The Win32 objects behind a console can be created in several occasions:
- <itemizedlist>
- <listitem>
- <para>
- When the program is started from wineconsole, a new
- console object is created and will be used (inherited)
- by the process launched from wineconsole.
- </para>
- </listitem>
- <listitem>
- <para>
- When a program, which isn't attached to a console, calls
- <function>AllocConsole</function>, Wine then launches
- wineconsole, and attaches the current program to this
- console. In this mode, the USER32 mode is always
- selected as Wine cannot tell the current state of the
- Unix console.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Please also note, that starting a child process with the
- <constant>CREATE_NEW_CONSOLE</constant> flag, will end-up
- calling <function>AllocConsole</function> in the child
- process, hence creating a wineconsole with the USER32 backend.
- </para>
- </chapter>
-
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: sgml
-sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
-End:
--->
diff --git a/documentation/cvs-regression.sgml b/documentation/cvs-regression.sgml
deleted file mode 100644
index a0dbd97..0000000
--- a/documentation/cvs-regression.sgml
+++ /dev/null
@@ -1,142 +0,0 @@
- <chapter id="cvs-regression">
- <title>How to do regression testing using CVS</title>
-
- <para>
- A problem that can happen sometimes is 'it used to work
- before, now it doesn't anymore...'. Here is a step by step
- procedure to try to pinpoint when the problem occurred. This is
- <emphasis>NOT</emphasis> for casual users.
- </para>
-
- <orderedlist>
- <listitem>
- <para>
- Get the <quote>full CVS</quote> archive from winehq. This archive is
- the CVS tree but with the tags controlling the versioning
- system. It's a big file (> 40 meg) with a name like
- full-cvs-<last update date> (it's more than 100mb
- when uncompressed, you can't very well do this with
- small, old computers or slow Internet connections).
- </para>
- </listitem>
- <listitem>
- <para>
- untar it into a repository directory:
- <screen>
-cd /home/gerard
-tar -zxf full-cvs-2003-08-18.tar.gz
-mv wine repository
- </screen>
- </para>
- </listitem>
- <listitem>
- <para>
- extract a new destination directory. This directory must
- not be in a subdirectory of the repository else
- <command>cvs</command> will think it's part of the
- repository and deny you an extraction in the repository:
- <screen>
-cd /home/gerard
-mv wine wine_current (-> this protects your current wine sandbox, if any)
-export CVSROOT=/home/gerard/repository
-cvs -d $CVSROOT checkout wine
- </screen>
- </para>
- <para>
- Note that it's not possible to do a checkout at a given
- date; you always do the checkout for the last date where
- the full-cvs-xxx snapshot was generated.
- </para>
- <para>
- Note also that it is possible to do all this with a direct
- CVS connection, of course. The full CVS file method is less
- painful for the WineHQ CVS server and probably a bit faster
- if you don't have a very good net connection.
- </para>
- </listitem>
- <listitem>
- <para>
- you will have now in the <filename>~/wine</filename>
- directory an image of the CVS tree, on the client side.
- Now update this image to the date you want:
- <screen>
-cd /home/gerard/wine
-cvs update -PAd -D "2004-08-23 CDT"
- </screen>
- </para>
- <para>
- The date format is <literal>YYYY-MM-DD HH:MM:SS</literal>.
- Using the CST date format ensure that you will be able to
- extract patches in a way that will be compatible with the
- wine-cvs archive
- <ulink url="http://www.winehq.org/hypermail/wine-cvs">
- http://www.winehq.org/hypermail/wine-cvs</ulink>
- </para>
- <para>
- Many messages will inform you that more recent files have
- been deleted to set back the client cvs tree to the date
- you asked, for example:
- <screen>
-cvs update: tsx11/ts_xf86dga2.c is no longer in the repository
- </screen>
- </para>
- <para>
- <command>cvs update</command> is not limited to upgrade to
- a <emphasis>newer</emphasis> version as I have believed for
- far too long :-(
- </para>
- </listitem>
- <listitem>
- <para>
- Now proceed as for a normal update:
- </para>
- <screen>
-./configure
-make depend && make
- </screen>
- <para>
- If any non-programmer reads this, the fastest method to get
- at the point where the problem occurred is to use a binary
- search, that is, if the problem occurred in 1999, start at
- mid-year, then is the problem is already here, back to 1st
- April, if not, to 1st October, and so on.
- </para>
- <para>
- If you have lot of hard disk free space (a full compile currently
- takes 400 Mb), copy the oldest known working version before
- updating it, it will save time if you need to go back. (it's
- better to <command>make distclean</command> before going back in
- time, so you have to make everything if you don't backup the older
- version)
- </para>
- <para>
- When you have found the day where the problem happened, continue
- the search using the wine-cvs archive (sorted by date) and a
- more precise cvs update including hour, minute, second :
- <screen>
-cvs update -PAd -D "2004-08-23 15:17:25 CDT"
- </screen>
- This will allow you to find easily the exact patch that did it.
- </para>
- </listitem>
- <listitem>
- <para>
- If you find the patch that is the cause of the problem, you have
- almost won; report about it to
- <ulink url="http://bugs.winehq.org/">Wine Bugzilla</ulink>
- or subscribe to wine-devel and post it there. There is a chance
- that the author
- will jump in to suggest a fix; or there is always the possibility
- to look hard at the patch until it is coerced to reveal where is
- the bug :-)
- </para>
- </listitem>
- </orderedlist>
- </chapter>
-
- <!-- Keep this comment at the end of the file
- Local variables:
- mode: sgml
- sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
- End:
- -->
diff --git a/documentation/i18n.sgml b/documentation/i18n.sgml
deleted file mode 100644
index b2498d3..0000000
--- a/documentation/i18n.sgml
+++ /dev/null
@@ -1,66 +0,0 @@
- <chapter id="i18n">
- <title>Internationalization</title>
-
- <sect1 id="adding-languages">
- <title>Adding New Languages</title>
-
- <para>
- This file documents the necessary procedure for adding a new
- language to the list of languages that Wine can display system
- menus and forms in. Adding new translations is not hard as
- it requires no programming knowledge or special skills.
- </para>
-
- <para>
- Language dependent resources reside in files
- named <filename>somefile_Xx.rc</filename> or
- <filename>Xx.rc</filename>, where <literal>Xx</literal>
- is your language abbreviation (look for it in
- <filename>include/winnls.h</filename>). These are included
- in a master file named <filename>somefile.rc</filename> or
- <filename>rsrc.rc</filename>, located in the same
- directory as the language files.
- </para>
-
- <para>
- To add a new language to one of these resources you
- need to make a copy of the English resource (located
- in the <filename>somefile_En.rc</filename> file) over to
- your <filename>somefile_Xx.rc</filename> file, include this
- file in the master <filename>somefile.rc</filename> file,
- and edit the new file to translate the English text.
- You may also need to rearrange some of the controls
- to better fit the newly translated strings. Test your changes
- to make sure they properly layout on the screen.
- </para>
-
- <para>
- In menus, the character "&" means that the next
- character will be highlighted and that pressing that
- letter will select the item. You should place these
- "&" characters suitably for your language, not just
- copy the positions from English. In particular,
- items within one menu should have different highlighted
- letters.
- </para>
-
- <para>
- To get a list of the files that need translating,
- run the following command in the root of your Wine tree:
- <command>find -name "*En.rc"</command>.
- </para>
-
- <para>
- When adding a new language, also make sure the parameters
- defined in <filename>./dlls/kernel/nls/*.nls</filename>
- fit your local habits and language.
- </para>
- </sect1>
- </chapter>
-
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: sgml
-sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
-End:
--->
diff --git a/documentation/implementation.sgml b/documentation/implementation.sgml
deleted file mode 100644
index e190f53..0000000
--- a/documentation/implementation.sgml
+++ /dev/null
@@ -1,608 +0,0 @@
- <chapter id="implementation">
- <title>Low-level Implementation</title>
- <para>Details of Wine's Low-level Implementation...</para>
-
-<sect1 id="config-keyboard">
-<title>Keyboard</title>
-
-<para>
-Wine now needs to know about your keyboard layout. This
-requirement comes from a need from many apps to have the
-correct scancodes available, since they read these directly,
-instead of just taking the characters returned by the X
-server. This means that Wine now needs to have a mapping from
-X keys to the scancodes these programs expect.
-</para>
-<para>
-On startup, Wine will try to recognize the active X layout by
-seeing if it matches any of the defined tables. If it does,
-everything is alright. If not, you need to define it.
-</para>
-<para>
-To do this, open the file
-<filename>dlls/x11drv/keyboard.c</filename> and take a look
-at the existing tables. Make a backup copy of it, especially
-if you don't use CVS.
-</para>
-<para>
-What you really would need to do, is find out which scancode
-each key needs to generate. Find it in the
-<function>main_key_scan</function> table, which looks like
-this:
-</para>
-<programlisting>
-static const int main_key_scan[MAIN_LEN] =
-{
-/* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
-0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
-0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
-0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
-0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
-0x56 /* the 102nd key (actually to the right of l-shift) */
-};
-</programlisting>
-<para>
-Next, assign each scancode the characters imprinted on the
-keycaps. This was done (sort of) for the US 101-key keyboard,
-which you can find near the top in
-<filename>keyboard.c</filename>. It also shows that if there
-is no 102nd key, you can skip that.
-</para>
-<para>
-However, for most international 102-key keyboards, we have
-done it easy for you. The scancode layout for these already
-pretty much matches the physical layout in the
-<function>main_key_scan</function>, so all you need to do is
-to go through all the keys that generate characters on your
-main keyboard (except spacebar), and stuff those into an
-appropriate table. The only exception is that the 102nd key,
-which is usually to the left of the first key of the last line
-(usually <keycap>Z</keycap>), must be placed on a separate
-line after the last line.
-</para>
-<para>
-For example, my Norwegian keyboard looks like this
-</para>
-<screen>
-§ ! " # ¤ % & / ( ) = ? ` Back-
-| 1 2@ 3£ 4$ 5 6 7{ 8[ 9] 0} + \´ space
-
-Tab Q W E R T Y U I O P Å ^
- ¨~
- Enter
-Caps A S D F G H J K L Ø Æ *
-Lock '
-
-Sh- > Z X C V B N M ; : _ Shift
-ift < , . -
-
-Ctrl Alt Spacebar AltGr Ctrl
-</screen>
-<para>
-Note the 102nd key, which is the <keycap><></keycap> key, to
-the left of <keycap>Z</keycap>. The character to the right of
-the main character is the character generated by
-<keycap>AltGr</keycap>.
-</para>
-<para>
-This keyboard is defined as follows:
-</para>
-<programlisting>
-static const char main_key_NO[MAIN_LEN][4] =
-{
-"|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\´",
-"qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
-"aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
-"zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
-"<>"
-};
-</programlisting>
-<para>
-Except that " and \ needs to be quoted with a backslash, and
-that the 102nd key is on a separate line, it's pretty
-straightforward.
-</para>
-<para>
-After you have written such a table, you need to add it to the
-<function>main_key_tab[]</function> layout index table. This
-will look like this:
-</para>
-<programlisting>
-static struct {
-WORD lang, ansi_codepage, oem_codepage;
-const char (*key)[MAIN_LEN][4];
-} main_key_tab[]={
-...
-...
-{MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT), 1252, 865, &main_key_NO},
-...
-</programlisting>
-<para>
-After you have added your table, recompile Wine and test that
-it works. If it fails to detect your table, try running
-</para>
-<screen>
-WINEDEBUG=+key,+keyboard wine > key.log 2>&1
- </screen>
- <para>
- and look in the resulting <filename>key.log</filename> file to
- find the error messages it gives for your layout.
- </para>
- <para>
- Note that the <constant>LANG_*</constant> and
- <constant>SUBLANG_*</constant> definitions are in
- <filename>include/winnls.h</filename>, which you might need to
- know to find out which numbers your language is assigned, and
- find it in the WINEDEBUG output. The numbers will be
- <literal>(SUBLANG * 0x400 + LANG)</literal>, so, for example
- the combination <literal>LANG_NORWEGIAN (0x14)</literal> and
- <literal>SUBLANG_DEFAULT (0x1)</literal> will be (in hex)
- <literal>14 + 1*400 = 414</literal>, so since I'm Norwegian, I
- could look for <literal>0414</literal> in the WINEDEBUG output
- to find out why my keyboard won't detect.
- </para>
- <para>
- Once it works, submit it to the Wine project. If you use CVS,
- you will just have to do
- </para>
- <screen>
-cvs -z3 diff -u dlls/x11drv/keyboard.c > layout.diff
- </screen>
- <para>
- from your main Wine directory, then submit
- <filename>layout.diff</filename> to
- <email>wine-patches@winehq.org</email> along with a brief note
- of what it is.
- </para>
- <para>
- If you don't use CVS, you need to do
- </para>
- <screen>
-diff -u the_backup_file_you_made dlls/x11drv/keyboard.c > layout.diff
- </screen>
- <para>
- and submit it as explained above.
- </para>
- <para>
- If you did it right, it will be included in the next Wine
- release, and all the troublesome programs (especially
- remote-control programs) and games that use scancodes will
- be happily using your keyboard layout, and you won't get those
- annoying fixme messages either.
- </para>
- </sect1>
-
-
- <sect1 id="undoc-func">
- <title>Undocumented APIs</title>
-
- <para>
- Some background: On the i386 class of machines, stack entries are
- usually dword (4 bytes) in size, little-endian. The stack grows
- downward in memory. The stack pointer, maintained in the
- <literal>esp</literal> register, points to the last valid entry;
- thus, the operation of pushing a value onto the stack involves
- decrementing <literal>esp</literal> and then moving the value into
- the memory pointed to by <literal>esp</literal>
- (i.e., <literal>push p</literal> in assembly resembles
- <literal>*(--esp) = p;</literal> in C). Removing (popping)
- values off the stack is the reverse (i.e., <literal>pop p</literal>
- corresponds to <literal>p = *(esp++);</literal> in C).
- </para>
-
- <para>
- In the <literal>stdcall</literal> calling convention, arguments are
- pushed onto the stack right-to-left. For example, the C call
- <function>myfunction(40, 20, 70, 30);</function> is expressed in
- Intel assembly as:
- <screen>
- push 30
- push 70
- push 20
- push 40
- call myfunction
- </screen>
- The called function is responsible for removing the arguments
- off the stack. Thus, before the call to myfunction, the
- stack would look like:
- <screen>
- [local variable or temporary]
- [local variable or temporary]
- 30
- 70
- 20
- esp -> 40
- </screen>
- After the call returns, it should look like:
- <screen>
- [local variable or temporary]
- esp -> [local variable or temporary]
- </screen>
- </para>
-
- <para>
- To restore the stack to this state, the called function must know how
- many arguments to remove (which is the number of arguments it takes).
- This is a problem if the function is undocumented.
- </para>
-
- <para>
- One way to attempt to document the number of arguments each function
- takes is to create a wrapper around that function that detects the
- stack offset. Essentially, each wrapper assumes that the function will
- take a large number of arguments. The wrapper copies each of these
- arguments into its stack, calls the actual function, and then calculates
- the number of arguments by checking esp before and after the call.
- </para>
-
- <para>
- The main problem with this scheme is that the function must actually
- be called from another program. Many of these functions are seldom
- used. An attempt was made to aggressively query each function in a
- given library (<filename>ntdll.dll</filename>) by passing 64 arguments,
- all 0, to each function. Unfortunately, Windows NT quickly goes to a
- blue screen of death, even if the program is run from a
- non-administrator account.
- </para>
-
- <para>
- Another method that has been much more successful is to attempt to
- figure out how many arguments each function is removing from the
- stack. This instruction, <literal>ret hhll</literal> (where
- <symbol>hhll</symbol> is the number of bytes to remove, i.e. the
- number of arguments times 4), contains the bytes
- <literal>0xc2 ll hh</literal> in memory. It is a reasonable
- assumption that few, if any, functions take more than 16 arguments;
- therefore, simply searching for
- <literal>hh == 0 && ll < 0x40</literal> starting from the
- address of a function yields the correct number of arguments most
- of the time.
- </para>
-
- <para>
- Of course, this is not without errors. <literal>ret 00ll</literal>
- is not the only instruction that can have the byte sequence
- <literal>0xc2 ll 0x0</literal>; for example,
- <literal>push 0x000040c2</literal> has the byte sequence
- <literal>0x68 0xc2 0x40 0x0 0x0</literal>, which matches
- the above. Properly, the utility should look for this sequence
- only on an instruction boundary; unfortunately, finding
- instruction boundaries on an i386 requires implementing a full
- disassembler -- quite a daunting task. Besides, the probability
- of having such a byte sequence that is not the actual return
- instruction is fairly low.
- </para>
-
- <para>
- Much more troublesome is the non-linear flow of a function. For
- example, consider the following two functions:
- <screen>
- somefunction1:
- jmp somefunction1_impl
-
- somefunction2:
- ret 0004
-
- somefunction1_impl:
- ret 0008
- </screen>
- In this case, we would incorrectly detect both
- <function>somefunction1</function> and
- <function>somefunction2</function> as taking only a single
- argument, whereas <function>somefunction1</function> really
- takes two arguments.
- </para>
-
- <para>
- With these limitations in mind, it is possible to implement more stubs
- in Wine and, eventually, the functions themselves.
- </para>
- </sect1>
-
- <sect1 id="accel-impl">
- <title>Accelerators</title>
-
- <para>
- There are <emphasis>three</emphasis> differently sized
- accelerator structures exposed to the user:
- </para>
- <orderedlist>
- <listitem>
- <para>
- Accelerators in NE resources. This is also the internal
- layout of the global handle <type>HACCEL</type> (16 and
- 32) in Windows 95 and Wine. Exposed to the user as Win16
- global handles <type>HACCEL16</type> and
- <type>HACCEL32</type> by the Win16/Win32 API.
- These are 5 bytes long, with no padding:
- <programlisting>
-BYTE fVirt;
-WORD key;
-WORD cmd;
- </programlisting>
- </para>
- </listitem>
- <listitem>
- <para>
- Accelerators in PE resources. They are exposed to the user
- only by direct accessing PE resources.
- These have a size of 8 bytes:
- </para>
- <programlisting>
-BYTE fVirt;
-BYTE pad0;
-WORD key;
-WORD cmd;
-WORD pad1;
- </programlisting>
- </listitem>
- <listitem>
- <para>
- Accelerators in the Win32 API. These are exposed to the
- user by the <function>CopyAcceleratorTable</function>
- and <function>CreateAcceleratorTable</function> functions
- in the Win32 API.
- These have a size of 6 bytes:
- </para>
- <programlisting>
-BYTE fVirt;
-BYTE pad0;
-WORD key;
-WORD cmd;
- </programlisting>
- </listitem>
- </orderedlist>
-
- <para>
- Why two types of accelerators in the Win32 API? We can only
- guess, but my best bet is that the Win32 resource compiler
- can/does not handle struct packing. Win32 <type>ACCEL</type>
- is defined using <function>#pragma(2)</function> for the
- compiler but without any packing for RC, so it will assume
- <function>#pragma(4)</function>.
- </para>
-
- </sect1>
-
- <sect1 id="hardware-trace">
- <title>Doing A Hardware Trace</title>
-
- <para>
- The primary reason to do this is to reverse engineer a
- hardware device for which you don't have documentation, but
- can get to work under Wine.
- </para>
- <para>
- This lot is aimed at parallel port devices, and in particular
- parallel port scanners which are now so cheap they are
- virtually being given away. The problem is that few
- manufactures will release any programming information which
- prevents drivers being written for Sane, and the traditional
- technique of using DOSemu to produce the traces does not work
- as the scanners invariably only have drivers for Windows.
- </para>
- <para>
- Presuming that you have compiled and installed wine the first
- thing to do is is to enable direct hardware access to your
- parallel port. To do this edit <filename>config</filename>
- (usually in <filename>~/.wine/</filename>) and in the
- ports section add the following two lines
- </para>
- <programlisting>
-read=0x378,0x379,0x37a,0x37c,0x77a
-write=0x378,x379,0x37a,0x37c,0x77a
- </programlisting>
- <para>
- This adds the necessary access required for SPP/PS2/EPP/ECP
- parallel port on LPT1. You will need to adjust these number
- accordingly if your parallel port is on LPT2 or LPT0.
- </para>
- <para>
- When starting wine use the following command line, where
- <literal>XXXX</literal> is the program you need to run in
- order to access your scanner, and <literal>YYYY</literal> is
- the file your trace will be stored in:
- </para>
- <programlisting>
-WINEDEBUG=+io wine XXXX 2> >(sed 's/^[^:]*:io:[^ ]* //' > YYYY)
- </programlisting>
- <para>
- You will need large amounts of hard disk space (read hundreds
- of megabytes if you do a full page scan), and for reasonable
- performance a really fast processor and lots of RAM.
- </para>
- <para>
- You will need to postprocess the output into a more manageable
- format, using the <command>shrink</command> program. First
- you need to compile the source (which is located at the end of
- this section):
- <programlisting>
-cc shrink.c -o shrink
- </programlisting>
- </para>
- <para>
- Use the <command>shrink</command> program to reduce the
- physical size of the raw log as follows:
- </para>
- <programlisting>
-cat log | shrink > log2
- </programlisting>
- <para>
- The trace has the basic form of
- </para>
- <programlisting>
-XXXX > YY @ ZZZZ:ZZZZ
- </programlisting>
- <para>
- where <literal>XXXX</literal> is the port in hexadecimal being
- accessed, <literal>YY</literal> is the data written (or read)
- from the port, and <literal>ZZZZ:ZZZZ</literal> is the address
- in memory of the instruction that accessed the port. The
- direction of the arrow indicates whether the data was written
- or read from the port.
- </para>
- <programlisting>
-> data was written to the port
-< data was read from the port
- </programlisting>
- <para>
- My basic tip for interpreting these logs is to pay close
- attention to the addresses of the IO instructions. Their
- grouping and sometimes proximity should reveal the presence of
- subroutines in the driver. By studying the different versions
- you should be able to work them out. For example consider the
- following section of trace from my UMAX Astra 600P
- </para>
- <programlisting>
-0x378 > 55 @ 0297:01ec
-0x37a > 05 @ 0297:01f5
-0x379 < 8f @ 0297:01fa
-0x37a > 04 @ 0297:0211
-0x378 > aa @ 0297:01ec
-0x37a > 05 @ 0297:01f5
-0x379 < 8f @ 0297:01fa
-0x37a > 04 @ 0297:0211
-0x378 > 00 @ 0297:01ec
-0x37a > 05 @ 0297:01f5
-0x379 < 8f @ 0297:01fa
-0x37a > 04 @ 0297:0211
-0x378 > 00 @ 0297:01ec
-0x37a > 05 @ 0297:01f5
-0x379 < 8f @ 0297:01fa
-0x37a > 04 @ 0297:0211
-0x378 > 00 @ 0297:01ec
-0x37a > 05 @ 0297:01f5
-0x379 < 8f @ 0297:01fa
-0x37a > 04 @ 0297:0211
-0x378 > 00 @ 0297:01ec
-0x37a > 05 @ 0297:01f5
-0x379 < 8f @ 0297:01fa
-0x37a > 04 @ 0297:0211
- </programlisting>
- <para>
- As you can see there is a repeating structure starting at
- address <literal>0297:01ec</literal> that consists of four io
- accesses on the parallel port. Looking at it the first io
- access writes a changing byte to the data port the second
- always writes the byte <literal>0x05</literal> to the control
- port, then a value which always seems to
- <literal>0x8f</literal> is read from the status port at which
- point a byte <literal>0x04</literal> is written to the control
- port. By studying this and other sections of the trace we can
- write a C routine that emulates this, shown below with some
- macros to make reading/writing on the parallel port easier to
- read.
- </para>
- <programlisting>
-#define r_dtr(x) inb(x)
-#define r_str(x) inb(x+1)
-#define r_ctr(x) inb(x+2)
-#define w_dtr(x,y) outb(y, x)
-#define w_str(x,y) outb(y, x+1)
-#define w_ctr(x,y) outb(y, x+2)
-
-/* Seems to be sending a command byte to the scanner */
-int udpp_put(int udpp_base, unsigned char command)
-{
- int loop, value;
-
- w_dtr(udpp_base, command);
- w_ctr(udpp_base, 0x05);
-
- for (loop=0; loop < 10; loop++)
- if ((value = r_str(udpp_base)) & 0x80)
- {
- w_ctr(udpp_base, 0x04);
- return value & 0xf8;
- }
-
- return (value & 0xf8) | 0x01;
-}
- </programlisting>
- <para>
- For the UMAX Astra 600P only seven such routines exist (well
- 14 really, seven for SPP and seven for EPP). Whether you
- choose to disassemble the driver at this point to verify the
- routines is your own choice. If you do, the address from the
- trace should help in locating them in the disassembly.
- </para>
- <para>
- You will probably then find it useful to write a script/perl/C
- program to analyse the logfile and decode them futher as this
- can reveal higher level grouping of the low level routines.
- For example from the logs from my UMAX Astra 600P when decoded
- further reveal (this is a small snippet)
- </para>
- <programlisting>
-start:
-put: 55 8f
-put: aa 8f
-put: 00 8f
-put: 00 8f
-put: 00 8f
-put: c2 8f
-wait: ff
-get: af,87
-wait: ff
-get: af,87
-end: cc
-start:
-put: 55 8f
-put: aa 8f
-put: 00 8f
-put: 03 8f
-put: 05 8f
-put: 84 8f
-wait: ff
- </programlisting>
- <para>
- From this it is easy to see that <varname>put</varname>
- routine is often grouped together in five successive calls
- sending information to the scanner. Once these are understood
- it should be possible to process the logs further to show the
- higher level routines in an easy to see format. Once the
- highest level format that you can derive from this process is
- understood, you then need to produce a series of scans varying
- only one parameter between them, so you can discover how to
- set the various parameters for the scanner.
- </para>
-
- <para>
- The following is the <filename>shrink.c</filename> program:
- <programlisting>
-/* Copyright David Campbell <campbell@torque.net> */
-#include <stdio.h>
-#include <string.h>
-
-int main (void)
-{
- char buff[256], lastline[256] = "";
- int count = 0;
-
- while (!feof (stdin))
- {
- fgets (buff, sizeof (buff), stdin);
- if (strcmp (buff, lastline))
- {
- if (count > 1)
- printf ("# Last line repeated %i times #\n", count);
- printf ("%s", buff);
- strcpy (lastline, buff);
- count = 1;
- }
- else count++;
- }
- return 0;
-}
- </programlisting>
- </para>
- </sect1>
-
- </chapter>
-
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: sgml
-sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
-End:
--->
diff --git a/documentation/porting.sgml b/documentation/porting.sgml
deleted file mode 100644
index a732670..0000000
--- a/documentation/porting.sgml
+++ /dev/null
@@ -1,219 +0,0 @@
- <chapter id="porting">
- <title>Porting Wine to new Platforms</title>
- <para>
- This document provides a few tips on porting Wine to your
- favorite (UNIX-based) operating system.
- </para>
-
- <sect1 id="wine-porting">
- <title>Porting Wine to new Platforms</title>
- <sect2>
- <title>Why <symbol>#ifdef MyOS</symbol> is probably a mistake.</title>
-
- <para>
- Operating systems change. Maybe yours doesn't have the
- <filename>foo.h</filename> header, but maybe a future
- version will have it. If you want to <symbol>#include
- <foo.h></symbol>, it doesn't matter what operating
- system you are using; it only matters whether
- <filename>foo.h</filename> is there.
- </para>
- <para>
- Furthermore, operating systems change names or "fork" into
- several ones. An <symbol>#ifdef MyOs</symbol> will break
- over time.
- </para>
- <para>
- If you use the feature of <command>autoconf</command> -- the
- Gnu auto-configuration utility -- wisely, you will help
- future porters automatically because your changes will test
- for <emphasis>features</emphasis>, not names of operating
- systems. A feature can be many things:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- existence of a header file
- </para>
- </listitem>
- <listitem>
- <para>
- existence of a library function
- </para>
- </listitem>
- <listitem>
- <para>
- existence of libraries
- </para>
- </listitem>
- <listitem>
- <para>
- bugs in header files, library functions, the compiler, ...
- </para>
- </listitem>
- </itemizedlist>
- <para>
- You will need Gnu Autoconf, which you can get from your
- friendly Gnu mirror. This program takes Wine's
- <filename>configure.ac</filename> file and produces a
- <filename>configure</filename> shell script that users use
- to configure Wine to their system.
- </para>
- <para>
- There <emphasis>are</emphasis> exceptions to the "avoid
- <symbol>#ifdef MyOS</symbol>" rule. Wine, for example, needs
- the internals of the signal stack -- that cannot easily be
- described in terms of features. Moreover, you can not use
- <filename>autoconf</filename>'s <symbol>HAVE_*</symbol>
- symbols in Wine's headers, as these may be used by Winelib
- users who may not be using a <filename>configure</filename>
- script.
- </para>
- <para>
- Let's now turn to specific porting problems and how to solve
- them.
- </para>
- </sect2>
-
- <sect2>
- <title>MyOS doesn't have the <filename>foo.h</filename> header!</title>
-
- <para>
- This first step is to make <command>autoconf</command> check
- for this header. In <filename>configure.in</filename> you
- add a segment like this in the section that checks for
- header files (search for "header files"):
- </para>
- <programlisting>
-AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
- </programlisting>
- <para>
- If your operating system supports a header file with the
- same contents but a different name, say
- <filename>bar.h</filename>, add a check for that also.
- </para>
- <para>
- Now you can change
- </para>
- <programlisting>
-#include <foo.h>
- </programlisting>
- <para>
- to
- </para>
- <programlisting>
-#ifdef HAVE_FOO_H
-#include <foo.h>
-#elif defined (HAVE_BAR_H)
-#include <bar.h>
-#endif
- </programlisting>
- <para>
- If your system doesn't have a corresponding header file even
- though it has the library functions being used, you might
- have to add an <symbol>#else</symbol> section to the
- conditional. Avoid this if you can.
- </para>
- <para>
- You will also need to add <symbol>#undef HAVE_FOO_H</symbol>
- (etc.) to <filename>include/config.h.in</filename>
- </para>
- <para>
- Finish up with <command>make configure</command> and
- <command>./configure</command>.
- </para>
- </sect2>
-
- <sect2>
- <title>MyOS doesn't have the <function>bar</function> function!</title>
-
- <para>
- A typical example of this is the
- <function>memmove</function> function. To solve this
- problem you would add <function>memmove</function> to the
- list of functions that <command>autoconf</command> checks
- for. In <filename>configure.in</filename> you search for
- <function>AC_CHECK_FUNCS</function> and add
- <function>memmove</function>. (You will notice that someone
- already did this for this particular function.)
- </para>
- <para>
- Secondly, you will also need to add <symbol>#undef
- HAVE_BAR</symbol> to
- <filename>include/config.h.in</filename>
- </para>
- <para>
- The next step depends on the nature of the missing function.
- </para>
-
- <variablelist>
- <varlistentry>
- <term>Case 1:</term>
- <listitem>
- <para>
- It's easy to write a complete implementation of the
- function. (<function>memmove</function> belongs to
- this case.)
- </para>
- <para>
- You add your implementation in
- <filename>misc/port.c</filename> surrounded by
- <symbol>#ifndef HAVE_MEMMOVE</symbol> and
- <symbol>#endif</symbol>.
- </para>
- <para>
- You might have to add a prototype for your function.
- If so, <filename>include/miscemu.h</filename> might be the place. Don't
- forget to protect that definition by <symbol>#ifndef
- HAVE_MEMMOVE</symbol> and <symbol>#endif</symbol> also!
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Case 2:</term>
- <listitem>
- <para>
- A general implementation is hard, but Wine is only
- using a special case.
- </para>
- <para>
- An example is the various <function>wait</function>
- calls used in <function>SIGNAL_child</function> from
- <filename>loader/signal.c</filename>. Here we have a
- multi-branch case on features:
- </para>
- <programlisting>
-#ifdef HAVE_THIS
-...
-#elif defined (HAVE_THAT)
-...
-#elif defined (HAVE_SOMETHING_ELSE)
-...
-#endif
- </programlisting>
- <para>
- Note that this is very different from testing on
- operating systems. If a new version of your operating
- systems comes out and adds a new function, this code
- will magically start using it.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- Finish up with <command>make configure</command> and
- <command>./configure</command>.
- </para>
-
- </sect2>
- </sect1>
-
- </chapter>
-
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: sgml
-sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
-End:
--->
diff --git a/documentation/wine-devel.sgml b/documentation/wine-devel.sgml
index 8217b98..c8243a87 100644
--- a/documentation/wine-devel.sgml
+++ b/documentation/wine-devel.sgml
@@ -1,24 +1,20 @@
<!doctype book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
<!entity debugger SYSTEM "debugger.sgml">
-<!entity documentation SYSTEM "documentation.sgml">
-<!entity patches SYSTEM "patches.sgml">
+<!entity debugging SYSTEM "debugging.sgml">
+<!entity otherdebug SYSTEM "winedev-otherdebug.sgml">
+<!entity codingpractice SYSTEM "winedev-coding.sgml">
<!entity testing SYSTEM "testing.sgml">
-<!entity i18n SYSTEM "i18n.sgml">
+<!entity documentation SYSTEM "documentation.sgml">
<!entity architecture SYSTEM "architecture.sgml">
-<!entity debugging SYSTEM "debugging.sgml">
+<!entity kernel SYSTEM "winedev-kernel.sgml">
+<!entity graphical SYSTEM "winedev-graphical.sgml">
+<!entity windowing SYSTEM "winedev-windowing.sgml">
<!entity ole SYSTEM "ole.sgml">
<!entity opengl SYSTEM "opengl.sgml">
<!entity ddraw SYSTEM "ddraw.sgml">
<!entity multimedia SYSTEM "multimedia.sgml">
-<!entity threading SYSTEM "threading.sgml">
-<!entity address-space SYSTEM "address-space.sgml">
-
-<!entity implementation SYSTEM "implementation.sgml">
-<!entity porting SYSTEM "porting.sgml">
-<!entity consoles SYSTEM "consoles.sgml">
-<!entity cvs-regression SYSTEM "cvs-regression.sgml">
]>
@@ -114,31 +110,23 @@
<title>Developing Wine</title>
&debugger;
- &documentation;
- &patches;
+ &debugging;
+ &otherdebug;
+ &codingpractice;
&testing;
- &i18n;
+ &documentation;
</part>
<part id="part-two">
<title>Wine Architecture</title>
&architecture;
- &debugging;
+ &kernel;
+ &graphical;
+ &windowing;
&ole;
&opengl;
&ddraw;
&multimedia;
- &threading;
</part>
-
- <part id="part-three">
- <title>Advanced Topics</title>
- &implementation;
- &porting;
- &consoles;
- &address-space;
- &cvs-regression;
- </part>
-
</book>
diff --git a/documentation/winedev-coding.sgml b/documentation/winedev-coding.sgml
new file mode 100644
index 0000000..e8f80cd
--- /dev/null
+++ b/documentation/winedev-coding.sgml
@@ -0,0 +1,514 @@
+ <chapter id="codingpractice">
+ <title>Coding Practice</title>
+
+ <para>
+ This chapter describes the relevant coding practices in Wine,
+ that you should be aware of before doing any serious development
+ in Wine.
+ </para>
+ <sect1 id="patch-format">
+ <title>Patch Format</title>
+
+ <para>
+ Patches are submitted via email to the Wine patches mailing
+ list, <email>wine-patches@winehq.org</email>. Your patch
+ should include:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ A meaningful subject (very short description of patch)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A long (paragraph) description of what was wrong and what
+ is now better. (recommended)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A change log entry (short description of what was
+ changed).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The patch in <command>diff -u</command> format
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para></para>
+
+ <para>
+ <command>cvs diff -u</command> works great for the common case
+ where a file is edited. However, if you add or remove a file
+ <command>cvs diff</command> will not report that correctly so
+ make sure you explicitly take care of this rare case.
+ </para>
+ <para>
+ For additions simply include them by appending the
+ <command>diff -u /dev/null /my/new/file</command> output of
+ them to any <command>cvs diff -u</command> output you may
+ have. Alternatively, use <command>diff -Nu olddir/
+ newdir/</command> in case of multiple new files to add.
+ </para>
+ <para>
+ For removals, clearly list the files in the description of the
+ patch.
+ </para>
+ <para>
+ Since wine is constantly changing due to development it is
+ strongly recommended that you use cvs for patches, if you
+ cannot use cvs for some reason, you can submit patches against
+ the latest tarball. To do this make a copy of the files that
+ you will be modifying and <command>diff -u</command> against
+ the old file. I.E.
+ </para>
+ <screen>
+diff -u file.old file.c > file.txt
+ </screen>
+ </sect1>
+
+ <sect1 id="Style-notes">
+ <title>Some notes about style</title>
+
+ <para>
+ There are a few conventions that about coding style that have
+ been adopted over the years of development. The rational for
+ these <quote>rules</quote> is explained for each one.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ No HTML mail, since patches should be in-lined and HTML
+ turns the patch into garbage. Also it is considered bad
+ etiquette as it uglifies the message, and is not viewable
+ by many of the subscribers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Only one change set per patch. Patches should address only
+ one bug/problem at a time. If a lot of changes need to be
+ made then it is preferred to break it into a series of
+ patches. This makes it easier to find regressions.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Tabs are not forbidden but discouraged. A tab is defined
+ as 8 characters and the usual amount of indentation is 4
+ characters.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ C++ style comments are discouraged since some compilers
+ choke on them.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Commenting out a block of code is usually done by
+ enclosing it in <command>#if 0 ... #endif</command>
+ Statements. For example.
+ </para>
+ <screen>
+/* note about reason for commenting block */
+#if 0
+code
+code /* comments */
+code
+#endif
+ </screen>
+ <para>
+ The reason for using this method is that it does not
+ require that you edit comments that may be inside the
+ block of code.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Patches should be in-lined (if you can configure your
+ email client to not wrap lines), or attached as plain text
+ attachments so they can be read inline. This may mean some
+ more work for you. However it allows others to review your
+ patch easily and decreases the chances of it being
+ overlooked or forgotten.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Code is usually limited to 80 columns. This helps prevent
+ mailers mangling patches by line wrap. Also it generally
+ makes code easier to read.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the patch fixes a bug in Bugzilla please provide a link
+ to the bug in the comments of the patch. This will make it
+ easier for the maintainers of Bugzilla.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <sect2 id="Inline-Attachments-with-OE">
+ <title>Inline attachments with Outlook Express</title>
+ <para>
+ Outlook Express is notorious for mangling
+ attachments. Giving the patch a <filename>.txt</filename>
+ extension and attaching will solve the problem for most
+ mailers including Outlook. Also, there is a way to enable
+ Outlook Express send <filename>.diff</filename>
+ attachments.
+ </para>
+ <para>
+ You need following two things to make it work.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Make sure that <filename>.diff</filename> files have
+ \r\n line ends, because if OE detects that there is no
+ \r\n line endings it switches to quoted-printable format
+ attachments.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Using regedit add key "Content Type"
+ with value "text/plain" to the
+ <filename>.diff</filename> extension under
+ HKEY_CLASSES_ROOT (same as for <filename>.txt</filename>
+ extension). This tells OE to use
+ Content-Type: text/plain instead of
+ application/octet-stream.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Item #1 is important. After you hit "Send" button, go to
+ "Outbox" and using "Properties" verify the message source to
+ make sure that the mail has correct format. You might want
+ to send several test emails to yourself too.
+ </para>
+ </sect2>
+ <sect2 id="Alexandre-Bottom-Line">
+ <title>Alexandre's Bottom Line</title>
+ <para>
+ <quote>The basic rules are: no attachments, no MIME crap, no
+ line wrapping, a single patch per mail. Basically if I can't
+ do <command>"cat raw_mail | patch -p0"</command> it's in the
+ wrong format.</quote>
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="patch-quality">
+ <title>Quality Assurance</title>
+
+ <para>
+ (Or, "How do I get Alexandre to apply my patch quickly so I
+ can build on it and it will not go stale?")
+ </para>
+ <para>
+ Make sure your patch applies to the current CVS head
+ revisions. If a bunch of patches are committed to CVS that may
+ affect whether your patch will apply cleanly then verify that
+ your patch does apply! <command>cvs update</command> is your
+ friend!
+ </para>
+ <para>
+ Save yourself some embarrassment and run your patched code
+ against more than just your current test example. Experience
+ will tell you how much effort to apply here. If there are
+ any conformance tests for the code you're working on, run them
+ and make sure they still pass after your patch is applied. Running
+ tests can be done by running <command>make test</command>. You may
+ need to run <command>make testclean</command> to undo the results
+ of a previous test run. See the <quote>testing</quote> guide for
+ more details on Wine's conformance tests.
+ </para>
+
+ </sect1>
+ <sect1 id="porting">
+ <title>Porting Wine to new Platforms</title>
+ <para>
+ This document provides a few tips on porting Wine to your
+ favorite (UNIX-based) operating system.
+ </para>
+
+ <sect2>
+ <title>
+ Why <symbol>#ifdef MyOS</symbol> is probably a mistake.
+ </title>
+
+ <para>
+ Operating systems change. Maybe yours doesn't have the
+ <filename>foo.h</filename> header, but maybe a future
+ version will have it. If you want to <symbol>#include
+ <foo.h></symbol>, it doesn't matter what operating
+ system you are using; it only matters whether
+ <filename>foo.h</filename> is there.
+ </para>
+ <para>
+ Furthermore, operating systems change names or "fork" into
+ several ones. An <symbol>#ifdef MyOs</symbol> will break
+ over time.
+ </para>
+ <para>
+ If you use the feature of <command>autoconf</command> -- the
+ Gnu auto-configuration utility -- wisely, you will help
+ future porters automatically because your changes will test
+ for <emphasis>features</emphasis>, not names of operating
+ systems. A feature can be many things:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ existence of a header file
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ existence of a library function
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ existence of libraries
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ bugs in header files, library functions, the compiler, ...
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ You will need Gnu Autoconf, which you can get from your
+ friendly Gnu mirror. This program takes Wine's
+ <filename>configure.ac</filename> file and produces a
+ <filename>configure</filename> shell script that users use
+ to configure Wine to their system.
+ </para>
+ <para>
+ There <emphasis>are</emphasis> exceptions to the "avoid
+ <symbol>#ifdef MyOS</symbol>" rule. Wine, for example, needs
+ the internals of the signal stack -- that cannot easily be
+ described in terms of features. Moreover, you can not use
+ <filename>autoconf</filename>'s <symbol>HAVE_*</symbol>
+ symbols in Wine's headers, as these may be used by Winelib
+ users who may not be using a <filename>configure</filename>
+ script.
+ </para>
+ <para>
+ Let's now turn to specific porting problems and how to solve
+ them.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>
+ MyOS doesn't have the <filename>foo.h</filename> header!
+ </title>
+
+ <para>
+ This first step is to make <command>autoconf</command> check
+ for this header. In <filename>configure.in</filename> you
+ add a segment like this in the section that checks for
+ header files (search for "header files"):
+ </para>
+ <programlisting>
+AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
+ </programlisting>
+ <para>
+ If your operating system supports a header file with the
+ same contents but a different name, say
+ <filename>bar.h</filename>, add a check for that also.
+ </para>
+ <para>
+ Now you can change
+ </para>
+ <programlisting>
+#include <foo.h>
+ </programlisting>
+ <para>
+ to
+ </para>
+ <programlisting>
+#ifdef HAVE_FOO_H
+#include <foo.h>
+#elif defined (HAVE_BAR_H)
+#include <bar.h>
+#endif
+ </programlisting>
+ <para>
+ If your system doesn't have a corresponding header file even
+ though it has the library functions being used, you might
+ have to add an <symbol>#else</symbol> section to the
+ conditional. Avoid this if you can.
+ </para>
+ <para>
+ You will also need to add <symbol>#undef HAVE_FOO_H</symbol>
+ (etc.) to <filename>include/config.h.in</filename>
+ </para>
+ <para>
+ Finish up with <command>make configure</command> and
+ <command>./configure</command>.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>
+ MyOS doesn't have the <function>bar</function> function!
+ </title>
+
+ <para>
+ A typical example of this is the <function>memmove</function>
+ function. To solve this problem you would add
+ <function>memmove</function> to the list of functions that
+ <command>autoconf</command> checks for. In
+ <filename>configure.in</filename> you search for
+ <function>AC_CHECK_FUNCS</function> and add
+ <function>memmove</function>. (You will notice that someone
+ already did this for this particular function.)
+ </para>
+ <para>
+ Secondly, you will also need to add
+ <symbol>#undef HAVE_BAR</symbol> to
+ <filename>include/config.h.in</filename>
+ </para>
+ <para>
+ The next step depends on the nature of the missing function.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Case 1:</term>
+ <listitem>
+ <para>
+ It's easy to write a complete implementation of the
+ function. (<function>memmove</function> belongs to
+ this case.)
+ </para>
+ <para>
+ You add your implementation in
+ <filename>misc/port.c</filename> surrounded by
+ <symbol>#ifndef HAVE_MEMMOVE</symbol> and
+ <symbol>#endif</symbol>.
+ </para>
+ <para>
+ You might have to add a prototype for your function.
+ If so, <filename>include/miscemu.h</filename> might be
+ the place. Don't forget to protect that definition by
+ <symbol>#ifndef HAVE_MEMMOVE</symbol> and
+ <symbol>#endif</symbol> also!
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 2:</term>
+ <listitem>
+ <para>
+ A general implementation is hard, but Wine is only
+ using a special case.
+ </para>
+ <para>
+ An example is the various <function>wait</function>
+ calls used in <function>SIGNAL_child</function> from
+ <filename>loader/signal.c</filename>. Here we have a
+ multi-branch case on features:
+ </para>
+ <programlisting>
+#ifdef HAVE_THIS
+...
+#elif defined (HAVE_THAT)
+...
+#elif defined (HAVE_SOMETHING_ELSE)
+...
+#endif
+ </programlisting>
+ <para>
+ Note that this is very different from testing on
+ operating systems. If a new version of your operating
+ systems comes out and adds a new function, this code
+ will magically start using it.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ Finish up with <command>make configure</command> and
+ <command>./configure</command>.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="adding-languages">
+ <title>Adding New Languages</title>
+
+ <para>
+ This file documents the necessary procedure for adding a new
+ language to the list of languages that Wine can display system
+ menus and forms in. Adding new translations is not hard as it
+ requires no programming knowledge or special skills.
+ </para>
+
+ <para>
+ Language dependent resources reside in files
+ named <filename>somefile_Xx.rc</filename> or
+ <filename>Xx.rc</filename>, where <literal>Xx</literal>
+ is your language abbreviation (look for it in
+ <filename>include/winnls.h</filename>). These are included
+ in a master file named <filename>somefile.rc</filename> or
+ <filename>rsrc.rc</filename>, located in the same
+ directory as the language files.
+ </para>
+
+ <para>
+ To add a new language to one of these resources you
+ need to make a copy of the English resource (located
+ in the <filename>somefile_En.rc</filename> file) over to
+ your <filename>somefile_Xx.rc</filename> file, include this
+ file in the master <filename>somefile.rc</filename> file,
+ and edit the new file to translate the English text.
+ You may also need to rearrange some of the controls
+ to better fit the newly translated strings. Test your changes
+ to make sure they properly layout on the screen.
+ </para>
+
+ <para>
+ In menus, the character "&" means that the next
+ character will be highlighted and that pressing that
+ letter will select the item. You should place these
+ "&" characters suitably for your language, not just
+ copy the positions from English. In particular,
+ items within one menu should have different highlighted
+ letters.
+ </para>
+
+ <para>
+ To get a list of the files that need translating,
+ run the following command in the root of your Wine tree:
+ <command>find -name "*En.rc"</command>.
+ </para>
+
+ <para>
+ When adding a new language, also make sure the parameters
+ defined in <filename>./dlls/kernel/nls/*.nls</filename>
+ fit your local habits and language.
+ </para>
+ </sect1>
+</chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
+End:
+-->
diff --git a/documentation/winedev-graphical.sgml b/documentation/winedev-graphical.sgml
new file mode 100644
index 0000000..72c3a04
--- /dev/null
+++ b/documentation/winedev-graphical.sgml
@@ -0,0 +1,40 @@
+ <chapter>
+ <title>Graphical modules</title>
+ <sect1>
+ <title>GDI Module</title>
+
+ <sect2>
+ <title>X Windows System interface</title>
+
+ <para>
+ The X libraries used to implement X clients (such as Wine)
+ do not work properly if multiple threads access the same
+ display concurrently. It is possible to compile the X
+ libraries to perform their own synchronization (initiated
+ by calling <function>XInitThreads()</function>). However,
+ Wine does not use this approach. Instead Wine performs its
+ own synchronization using the
+ <function>wine_tsx11_lock()</function> / <function>wine_tsx11_unlock()</function>
+ functions. This locking protects library access
+ with a critical section, and also arranges things so that
+ X libraries compiled without <option>-D_REENTRANT</option>
+ (eg. with global <varname>errno</varname> variable) will
+ work with Wine.
+ </para>
+ <para>
+ In the past, all calls to X used to go through a wrapper called
+ <function>TSX...()</function> (for "Thread Safe X ...").
+ While it is still being used in the code, it's inefficient
+ as the lock is potentially aquired and released unnecessarily.
+ New code should explicitly aquire the lock.
+ </para>
+ </sect2>
+ </sect1>
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
+End:
+-->
diff --git a/documentation/winedev-kernel.sgml b/documentation/winedev-kernel.sgml
new file mode 100644
index 0000000..700835f
--- /dev/null
+++ b/documentation/winedev-kernel.sgml
@@ -0,0 +1,823 @@
+ <chapter>
+ <title>Kernel modules</title>
+ <para>
+ This section cover the kernel modules. As already stated, Wine
+ implements the NT architecture, hence provides NTDLL for the
+ core kernel functions, and KERNEL32, which is the
+ implementation of the basis of the Win32 subsystem, on top of
+ NTDLL.
+ </para>
+ <sect1 id="ntdll">
+ <title>NTDLL</title>
+ <para>
+ NTDLL provides most of the services you'd expect from a
+ kernel.
+ </para>
+ <para>
+ Process and thread management are part of them (even if
+ process management is still mainly done in KERNEL32, unlike
+ NT). A Windows process runs as a Unix process, and a Windows
+ thread runs as a Unix thread.
+ </para>
+ <para>
+ Wine also provide fibers (which is the Windows name of
+ co-routines).
+ </para>
+ <para>
+ Most of the Windows memory handling (Heap, Global and Local
+ functions, virtual memory...) are easily mapped upon their
+ Unix equivalents. Note the NTDLL doesn't know about 16 bit
+ memory, which is only handled in KERNEL32/KRNL386.EXE (and
+ also the DOS routines).
+ </para>
+
+ <sect2>
+ <title>File management</title>
+ <para>
+ Wine uses some configuration in order to map Windows
+ filenames (either defined with drive letters, or as UNC
+ names) to the unix filenames. Wine also uses some
+ incantation so that most of file related APIs can also
+ take full unix names. This is handy when passing filenames
+ on the command line.
+ </para>
+ <para>
+ File handles can be waitable objects, as Windows define
+ them.
+ </para>
+ <para>
+ Asynchronous I/O is implemented on file handles by
+ queueing pseudo APC. They are not real APC in the sense
+ that they have the same priority as the threads in the
+ considered process (while APCs on NT have normally a
+ higher priority). These APCs get called when invoking
+ Wine server (which should lead to correct behavior when the
+ program ends up waiting on some object - waiting always
+ implies calling Wine server).
+ </para>
+ <para>
+ FIXME: this should be enhanced and updated to latest work
+ on FS.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Synchronization</title>
+ <para>
+ Most of the synchronization (between threads or processes)
+ is done in Wine server, which handles both the waiting
+ operation (on a single object or a set of objects) and the
+ signaling of objects.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Module (DLL) loading</title>
+ <para>
+ Wine is able to load any NE and PE module. In all cases,
+ the module's binary code is directly executed by the
+ processor.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Device management</title>
+ <para>
+ Wine allows usage a wide variety of devices:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Communication ports are mapped to Unix
+ communication ports (if they have sufficient
+ permissions).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Parallel ports are mapped to Unix parallel ports (if
+ they have sufficient permissions).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ CDROM: the Windows device I/O control calls are
+ mapped onto Unix <function>ioctl()</function>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Some Win9x VxDs are supported, by rewriting some of
+ their internal behavior. But this support is
+ limited. Portable programs to Windows NT shouldn't
+ need them.
+ </para>
+ <para>
+ Wine will not support native VxD.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ <sect2 id="threading">
+ <title>Multi-threading in Wine</title>
+
+ <para>
+ This section will assume you understand the basics of
+ multithreading. If not there are plenty of good tutorials
+ available on the net to get you started.
+ </para>
+
+ <para>
+ Threading in Wine is somewhat complex due to several
+ factors. The first is the advanced level of multithreading
+ support provided by Windows - there are far more threading
+ related constructs available in Win32 than the Linux
+ equivalent (pthreads). The second is the need to be able to
+ map Win32 threads to native Linux threads which provides us
+ with benefits like having the kernel schedule them without
+ our intervention. While it's possible to implement threading
+ entirely without kernel support, doing so is not desirable
+ on most platforms that Wine runs on.
+ </para>
+
+ <sect3>
+ <title> Threading support in Win32 </title>
+
+ <para>
+ Win32 is an unusually thread friendly API. Not only is it
+ entirely thread safe, but it provides many different
+ facilities for working with threads. These range from the
+ basics such as starting and stopping threads, to the
+ extremely complex such as injecting threads into other
+ processes and COM inter-thread marshalling.
+ </para>
+
+ <para>
+ One of the primary challenges of writing Wine code
+ therefore is ensuring that all our DLLs are thread safe,
+ free of race conditions and so on. This isn't simple -
+ don't be afraid to ask if you aren't sure whether a piece
+ of code is thread safe or not!
+ </para>
+
+ <para>
+ Win32 provides many different ways you can make your code
+ thread safe however the most common are <emphasis>critical
+ section</emphasis> and the <emphasis>interlocked
+ functions</emphasis>. Critical sections are a type of
+ mutex designed to protect a geographic area of code. If
+ you don't want multiple threads running in a piece of code
+ at once, you can protect them with calls to
+ <function>EnterCriticalSection</function> and
+ <function>LeaveCriticalSection</function>. The first call
+ to <function>EnterCriticalSection</function> by a thread
+ will lock the section and continue without stopping. If
+ another thread calls it then it will block until the
+ original thread calls
+ <function>LeaveCriticalSection</function> again.
+ </para>
+
+ <para>
+ It is therefore vitally important that if you use critical
+ sections to make some code thread-safe, that you check
+ every possible codepath out of the code to ensure that any
+ held sections are left. Code like this:
+ </para>
+
+ <programlisting>
+if (res != ERROR_SUCCESS) return res;
+ </programlisting>
+
+ <para>
+ is extremely suspect in a function that also contains a
+ call to <function>EnterCriticalSection</function>. Be
+ careful.
+ </para>
+
+ <para>
+ If a thread blocks while waiting for another thread to
+ leave a critical section, you will see an error from the
+ <function>RtlpWaitForCriticalSection</function> function,
+ along with a note of which thread is holding the
+ lock. This only appears after a certain timeout, normally
+ a few seconds. It's possible the thread holding the lock
+ is just being really slow which is why Wine won't
+ terminate the app like a non-checked build of Windows
+ would, but the most common cause is that for some reason a
+ thread forgot to call
+ <function>LeaveCriticalSection</function>, or died while
+ holding the lock (perhaps because it was in turn waiting
+ for another lock). This doesn't just happen in Wine code:
+ a deadlock while waiting for a critical section could be
+ due to a bug in the app triggered by a slight difference
+ in the emulation.
+ </para>
+
+ <para>
+ Another popular mechanism available is the use of
+ functions like <function>InterlockedIncrement</function>
+ and <function>InterlockedExchange</function>. These make
+ use of native CPU abilities to execute a single
+ instruction while ensuring any other processors on the
+ system cannot access memory, and allow you to do common
+ operations like add/remove/check a variable in thread-safe
+ code without holding a mutex. These are useful for
+ reference counting especially in free-threaded (thread
+ safe) COM objects.
+ </para>
+
+ <para>
+ Finally, the usage of TLS slots are also popular. TLS
+ stands for thread-local storage, and is a set of slots
+ scoped local to a thread which you can store pointers
+ in. Look on MSDN for the <function>TlsAlloc</function>
+ function to learn more about the Win32 implementation of
+ this. Essentially, the contents of a given slot will be
+ different in each thread, so you can use this to store
+ data that is only meaningful in the context of a single
+ thread. On recent versions of Linux the __thread keyword
+ provides a convenient interface to this functionality - a
+ more portable API is exposed in the pthread
+ library. However, these facilities is not used by Wine,
+ rather, we implement Win32 TLS entirely ourselves.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title> SysLevels </title>
+
+ <para>
+ SysLevels are an undocumented Windows-internal
+ thread-safety system. They are basically critical sections
+ which must be taken in a particular order. The mechanism
+ is generic but there are always three syslevels: level 1
+ is the Win16 mutex, level 2 is the USER mutex and level 3
+ is the GDI mutex.
+ </para>
+
+ <para>
+ When entering a syslevel, the code (in
+ <filename>dlls/kernel/syslevel.c</filename>) will check
+ that a higher syslevel is not already held and produce an
+ error if so. This is because it's not legal to enter level
+ 2 while holding level 3 - first, you must leave level 3.
+ </para>
+
+ <para>
+ Throughout the code you may see calls to
+ <function>_ConfirmSysLevel()</function> and
+ <function>_CheckNotSysLevel()</function>. These functions
+ are essentially assertions about the syslevel states and
+ can be used to check that the rules have not been
+ accidentally violated. In particular,
+ <function>_CheckNotSysLevel()</function> will break
+ (probably into the debugger) if the check fails. If this
+ happens the solution is to get a backtrace and find out,
+ by reading the source of the wine functions called along
+ the way, how Wine got into the invalid state.
+ </para>
+
+ </sect3>
+
+ <sect3>
+ <title> POSIX threading vs kernel threading </title>
+
+ <para>
+ Wine runs in one of two modes: either pthreads (posix
+ threading) or kthreads (kernel threading). This section
+ explains the differences between them. The one that is
+ used is automatically selected on startup by a small test
+ program which then execs the correct binary, either
+ wine-kthread or wine-pthread. On NPTL-enabled systems
+ pthreads will be used, and on older non-NPTL systems
+ kthreads is selected.
+ </para>
+
+ <para>
+ Let's start with a bit of history. Back in the dark ages
+ when Wines threading support was first implemented a
+ problem was faced - Windows had much more capable
+ threading APIs than Linux did. This presented a problem -
+ Wine works either by reimplementing an API entirely or by
+ mapping it onto the underlying systems equivalent. How
+ could Win32 threading be implemented using a library which
+ did not have all the neeed features? The answer, of
+ course, was that it couldn't be.
+ </para>
+
+ <para>
+ On Linux the pthreads interface is used to start, stop and
+ control threads. The pthreads library in turn is based on
+ top of so-called "kernel threads" which are created using
+ the <function>clone(2)</function> syscall. Pthreads
+ provides a nicer (more portable) interface to this
+ functionality and also provides APIs for controlling
+ mutexes. There is a <ulink
+ url="http://www.llnl.gov/computing/tutorials/pthreads/">
+ good tutorial on pthreads </ulink> available if you want
+ to learn more.
+ </para>
+
+ <para>
+ As pthreads did not provide the necessary semantics to
+ implement Win32 threading, the decision was made to
+ implement Win32 threading on top of the underlying kernel
+ threads by using syscalls like <function>clone</function>
+ directly. This provided maximum flexibility and allowed a
+ correct implementation but caused some bad side
+ effects. Most notably, all the userland Linux APIs assumed
+ that the user was utilising the pthreads library. Some
+ only enabled thread safety when they detected that
+ pthreads was in use - this is true of glibc, for
+ instance. Worse, pthreads and pure kernel threads had
+ strange interactions when run in the same process yet some
+ libraries used by Wine used pthreads internally. Throw in
+ source code porting using WineLib - where you have both
+ UNIX and Win32 code in the same process - and chaos was
+ the result.
+ </para>
+
+ <para>
+ The solution was simple yet ingenius: Wine would provide
+ its own implementation of the pthread library
+ <emphasis>inside</emphasis> its own binary. Due to the
+ semantics of ELF symbol scoping, this would cause Wines
+ own implementations to override any implementation loaded
+ later on (like the real libpthread.so). Therefore, any
+ calls to the pthread APIs in external libraries would be
+ linked to Wines instead of the systems pthreads library,
+ and Wine implemented pthreads by using the standard
+ Windows threading APIs it in turn implemented itself.
+ </para>
+
+ <para>
+ As a result, libraries that only became thread-safe in the
+ presence of a loaded pthreads implementation would now do
+ so, and any external code that used pthreads would
+ actually end up creating Win32 threads that Wine was aware
+ of and controlled. This worked quite nicely for a long
+ time, even though it required doing some extremely
+ un-kosher things like overriding internal libc structures
+ and functions. That is, it worked until NPTL was developed
+ at which point the underlying thread implementation on
+ Linux changed dramatically.
+ </para>
+
+ <para>
+ The fake pthread implementation can be found in
+ <filename>loader/kthread.c</filename>, which is used to
+ produce to wine-kthread binary. In contrast,
+ loader/pthread.c produces the wine-pthread binary which is
+ used on newer NPTL systems.
+ </para>
+
+ <para>
+ NPTL is a new threading subsystem for Linux that hugely
+ improves its performance and flexibility. By allowing
+ threads to become much more scalable and adding new
+ pthread APIs, NPTL made Linux competitive with Windows in
+ the multi-threaded world. Unfortunately it also broke many
+ assumptions made by Wine (as well as other applications
+ such as the Sun JVM and RealPlayer) in the process.
+ </para>
+
+ <para>
+ There was, however, some good news. NPTL made Linux
+ threading powerful enough that Win32 threads could now be
+ implemented on top of pthreads like any other normal
+ application. There would no longer be problems with mixing
+ win32-kthreads and pthreads created by external libraries,
+ and no need to override glibc internals. As you can see
+ from the relative sizes of the
+ <filename>loader/kthread.c</filename> and
+ <filename>loader/pthread.c</filename> files, the
+ difference in code complexity is considerable. NPTL also
+ made several other semantic changes to things such as
+ signal delivery so changes were required in many different
+ places in Wine.
+ </para>
+
+ <para>
+ On non-Linux systems the threading interface is typically
+ not powerful enough to replicate the semantics Win32
+ applications expect and so kthreads with the pthread
+ overrides are used.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title> The Win32 thread environment </title>
+
+ <para>
+ All Win32 code, whether from a native EXE/DLL or in Wine
+ itself, expects certain constructs to be present in its
+ environment. This section explores what those constructs
+ are and how Wine sets them up. The lack of this
+ environment is one thing that makes it hard to use Wine
+ code directly from standard Linux applications - in order
+ to interact with Win32 code a thread must first be
+ "adopted" by Wine.
+ </para>
+
+ <para>
+ The first thing Win32 code requires is the
+ <emphasis>TEB</emphasis> or "Thread Environment
+ Block". This is an internal (undocumented) Windows
+ structure associated with every thread which stores a
+ variety of things such as TLS slots, a pointer to the
+ threads message queue, the last error code and so on. You
+ can see the definition of the TEB in
+ <filename>include/thread.h</filename>, or at least what we
+ know of it so far. Being internal and subject to change,
+ the layout of the TEB has had to be reverse engineered
+ from scratch.
+ </para>
+
+ <para>
+ A pointer to the TEB is stored in the %fs register and can
+ be accessed using <function>NtCurrentTeb()</function> from
+ within Wine code. %fs actually stores a selector, and
+ setting it therefore requires modifying the processes
+ local descriptor table (LDT) - the code to do this is in
+ <filename>lib/wine/ldt.c</filename>.
+ </para>
+
+ <para>
+ The TEB is required by nearly all Win32 code run in the
+ Wine environment, as any wineserver RPC will use it, which
+ in turn implies that any code which could possibly block
+ (for instance by using a critical section) needs it. The
+ TEB also holds the SEH exception handler chain as the
+ first element, so if when disassembling you see code like
+ this:
+ </para>
+
+ <programlisting> movl %esp, %fs:0 </programlisting>
+
+ <para>
+ ... then you are seeing the program set up an SEH handler
+ frame. All threads must have at least one SEH entry, which
+ normally points to the backstop handler which is
+ ultimately responsible for popping up the all-too-familiar
+ "This program has performed an illegal operation and will
+ be terminated" message. On Wine we just drop straight into
+ the debugger. A full description of SEH is out of the
+ scope of this section, however there are some good
+ articles in MSJ if you are interested.
+ </para>
+
+ <para>
+ All Win32-aware threads must have a wineserver
+ connection. Many different APIs require the ability to
+ communicate with the wineserver. In turn, the wineserver
+ must be aware of Win32 threads in order to be able to
+ accurately report information to other parts of the program
+ and do things like route inter-thread messages, dispatch
+ APCs (asynchronous procedure calls) and so on. Therefore a
+ part of thread initialization is initializing the thread
+ serverside. The result is not only correct information in
+ the server, but a set of file descriptors the thread can use
+ to communicate with the server - the request fd, reply fd
+ and wait fd (used for blocking).
+ </para>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>KERNEL Module</title>
+
+ <para>
+ FIXME: Needs some content...
+ </para>
+ <sect2 id="consoles">
+ <title>Consoles in Wine</title>
+ <para>
+ As described in the Wine User Guide's CUI section, Wine
+ manipulates three kinds of "consoles" in order to support
+ properly the Win32 CUI API.
+ </para>
+ <para>
+ The following table describes the main implementation
+ differences between the three approaches.
+ <table>
+ <title>Function consoles implementation comparison</title>
+ <tgroup cols="4" align="left">
+ <thead>
+ <row>
+ <entry>Function</entry>
+ <entry>Bare streams</entry>
+ <entry>Wineconsole & user backend</entry>
+ <entry>Wineconsole & curses backend</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Console as a Win32 Object (and associated
+ handles)
+ </entry>
+ <entry>
+ No specific Win32 object is used in this
+ case. The handles manipulated for the standard
+ Win32 streams are in fact "bare handles" to
+ their corresponding Unix streams. The mode
+ manipulation functions
+ (<function>GetConsoleMode</function> /
+ <function>SetConsoleMode</function>) are not
+ supported.
+ </entry>
+ <entry>
+ Implemented in server, and a specific Winelib
+ program (wineconsole) is in charge of the
+ rendering and user input. The mode manipulation
+ functions behave as expected.
+ </entry>
+ <entry>
+ Implemented in server, and a specific Winelib
+ program (wineconsole) is in charge of the
+ rendering and user input. The mode manipulation
+ functions behave as expected.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ Inheritance (including handling in
+ <function>CreateProcess</function> of
+ <constant>CREATE_DETACHED</constant>,
+ <constant>CREATE_NEW_CONSOLE</constant> flags).
+ </entry>
+ <entry>
+ Not supported. Every process child of a process
+ will inherit the Unix streams, so will also
+ inherit the Win32 standard streams.
+ </entry>
+ <entry>
+ Fully supported (each new console creation will
+ be handled by the creation of a new USER32
+ window)
+ </entry>
+ <entry>
+ Fully supported, except for the creation of a
+ new console, which will be rendered on the same
+ Unix terminal as the previous one, leading to
+ unpredictable results.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <function>ReadFile</function> /
+ <function>WriteFile</function>
+ operations
+ </entry>
+ <entry>Fully supported</entry>
+ <entry>Fully supported</entry>
+ <entry>Fully supported</entry>
+ </row>
+ <row>
+ <entry>
+ Screen-buffer manipulation (creation, deletion,
+ resizing...)
+ </entry>
+ <entry>Not supported</entry>
+ <entry>Fully supported</entry>
+ <entry>
+ Partly supported (this won't work too well as we
+ don't control (so far) the size of underlying
+ Unix terminal
+ </entry>
+ </row>
+ <row>
+ <entry>
+ APIs for reading/writing screen-buffer content,
+ cursor position
+ </entry>
+ <entry>Not supported</entry>
+ <entry>Fully supported</entry>
+ <entry>Fully supported</entry>
+ </row>
+ <row>
+ <entry>
+ APIs for manipulating the rendering window size
+ </entry>
+ <entry>Not supported</entry>
+ <entry>Fully supported</entry>
+ <entry>
+ Partly supported (this won't work too well as we
+ don't control (so far) the size of underlying
+ Unix terminal
+ </entry>
+ </row>
+ <row>
+ <entry>
+ Signaling (in particular, Ctrl-C handling)
+ </entry>
+ <entry>
+ Nothing is done, which means that Ctrl-C will
+ generate (as usual) a
+ <constant>SIGINT</constant> which will terminate
+ the program.
+ </entry>
+ <entry>
+ Partly supported (Ctrl-C behaves as expected,
+ however the other Win32 CUI signaling isn't
+ properly implemented).
+ </entry>
+ <entry>
+ Partly supported (Ctrl-C behaves as expected,
+ however the other Win32 CUI signaling isn't
+ properly implemented).
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ <para>
+ The Win32 objects behind a console can be created in
+ several occasions:
+ <itemizedlist>
+ <listitem>
+ <para>
+ When the program is started from wineconsole, a new
+ console object is created and will be used
+ (inherited) by the process launched from
+ wineconsole.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ When a program, which isn't attached to a console,
+ calls <function>AllocConsole</function>, Wine then
+ launches wineconsole, and attaches the current
+ program to this console. In this mode, the USER32
+ mode is always selected as Wine cannot tell the
+ current state of the Unix console.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Please also note, that starting a child process with the
+ <constant>CREATE_NEW_CONSOLE</constant> flag, will end-up
+ calling <function>AllocConsole</function> in the child
+ process, hence creating a wineconsole with the USER32
+ backend.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="initialization">
+
+ <title> The Wine initialization process </title>
+
+ <para>
+ Wine has a rather complex startup procedure, so unlike many
+ programs the best place to begin exploring the code-base is
+ <emphasis>not</emphasis> in fact at the
+ <function>main()</function> 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.
+ </para>
+
+ <sect2>
+ <title> First Steps </title>
+
+ <para>
+ 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
+ <filename>loader/glibc.c</filename>. The result of this check is an exec of either
+ wine-pthread or wine-kthread, potentially (on Linux) via
+ the <emphasis>preloader</emphasis>. 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.
+ </para>
+
+ <para>
+ The Wine preloader is found in <filename>loader/preloader.c</filename>, 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 <function>__libc_start_main</function> which
+ initializes glibc before passing control to the main function as defined by the programmer.
+ </para>
+
+ <para>
+ 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).
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ </sect2>
+
+ <sect2>
+ <title> Starting the emulator </title>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ Both the wine-pthread and wine-kthread binaries share a common <function>main</function>
+ function, defined in <filename>loader/main.c</filename>, 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 <filename>libs/wine/loader.c</filename>. This is where the emulation really starts:
+ <function>wine_init</function> can, with the correct preparation,
+ be called from programs other than the wine loader itself.
+ </para>
+
+ <para>
+ <function>wine_init</function> 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 <function>__wine_process_init</function> function defined
+ in <filename>dlls/ntdll/loader.c</filename>
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ Finally, it loads and jumps to <function>__wine_kernel_init</function> in kernel32.dll: this
+ is defined in <filename>dlls/kernel32/process.c</filename>. 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 <function>CreateProcess</function> specifying various things like how the first
+ window should be displayed: this is sent to the new process via the wineserver.
+ </para>
+
+ <para>
+ 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
+ <function>__wine_kernel_init</function>. This function ends with the new process stack being
+ initialized, and start_process being called on the new stack. Nearly there!
+ </para>
+
+ <para>
+ The final element of initializing Wine is starting the newly loaded program
+ itself. <function>start_process</function> sets up the SEH backstop handler, calls
+ <function>LdrInitializeThunk</function> 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:
+ </para>
+
+ <programlisting>
+ExitProcess( entry( peb ) );
+ </programlisting>
+
+ <para>
+ ... 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 <function>ExitProcess</function> API will be used to initialize a graceful shutdown.
+ </para>
+ </sect2>
+ </sect1>
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
+End:
+-->
diff --git a/documentation/winedev-otherdebug.sgml b/documentation/winedev-otherdebug.sgml
new file mode 100644
index 0000000..da501c4
--- /dev/null
+++ b/documentation/winedev-otherdebug.sgml
@@ -0,0 +1,508 @@
+ <chapter id="otherdebug">
+ <title>Other debugging techniques</title>
+ <sect1 id="hardware-trace">
+ <title>Doing A Hardware Trace</title>
+
+ <para>
+ The primary reason to do this is to reverse engineer a
+ hardware device for which you don't have documentation, but
+ can get to work under Wine.
+ </para>
+ <para>
+ This lot is aimed at parallel port devices, and in particular
+ parallel port scanners which are now so cheap they are
+ virtually being given away. The problem is that few
+ manufactures will release any programming information which
+ prevents drivers being written for Sane, and the traditional
+ technique of using DOSemu to produce the traces does not work
+ as the scanners invariably only have drivers for Windows.
+ </para>
+ <para>
+ Presuming that you have compiled and installed wine the first
+ thing to do is is to enable direct hardware access to your
+ parallel port. To do this edit <filename>config</filename>
+ (usually in <filename>~/.wine/</filename>) and in the
+ ports section add the following two lines
+ </para>
+ <programlisting>
+read=0x378,0x379,0x37a,0x37c,0x77a
+write=0x378,x379,0x37a,0x37c,0x77a
+ </programlisting>
+ <para>
+ This adds the necessary access required for SPP/PS2/EPP/ECP
+ parallel port on LPT1. You will need to adjust these number
+ accordingly if your parallel port is on LPT2 or LPT0.
+ </para>
+ <para>
+ When starting wine use the following command line, where
+ <literal>XXXX</literal> is the program you need to run in
+ order to access your scanner, and <literal>YYYY</literal> is
+ the file your trace will be stored in:
+ </para>
+ <programlisting>
+WINEDEBUG=+io wine XXXX 2> >(sed 's/^[^:]*:io:[^ ]* //' > YYYY)
+ </programlisting>
+ <para>
+ You will need large amounts of hard disk space (read hundreds
+ of megabytes if you do a full page scan), and for reasonable
+ performance a really fast processor and lots of RAM.
+ </para>
+ <para>
+ You will need to postprocess the output into a more manageable
+ format, using the <command>shrink</command> program. First
+ you need to compile the source (which is located at the end of
+ this section):
+ <programlisting>
+cc shrink.c -o shrink
+ </programlisting>
+ </para>
+ <para>
+ Use the <command>shrink</command> program to reduce the
+ physical size of the raw log as follows:
+ </para>
+ <programlisting>
+cat log | shrink > log2
+ </programlisting>
+ <para>
+ The trace has the basic form of
+ </para>
+ <programlisting>
+XXXX > YY @ ZZZZ:ZZZZ
+ </programlisting>
+ <para>
+ where <literal>XXXX</literal> is the port in hexadecimal being
+ accessed, <literal>YY</literal> is the data written (or read)
+ from the port, and <literal>ZZZZ:ZZZZ</literal> is the address
+ in memory of the instruction that accessed the port. The
+ direction of the arrow indicates whether the data was written
+ or read from the port.
+ </para>
+ <programlisting>
+> data was written to the port
+< data was read from the port
+ </programlisting>
+ <para>
+ My basic tip for interpreting these logs is to pay close
+ attention to the addresses of the IO instructions. Their
+ grouping and sometimes proximity should reveal the presence of
+ subroutines in the driver. By studying the different versions
+ you should be able to work them out. For example consider the
+ following section of trace from my UMAX Astra 600P
+ </para>
+ <programlisting>
+0x378 > 55 @ 0297:01ec
+0x37a > 05 @ 0297:01f5
+0x379 < 8f @ 0297:01fa
+0x37a > 04 @ 0297:0211
+0x378 > aa @ 0297:01ec
+0x37a > 05 @ 0297:01f5
+0x379 < 8f @ 0297:01fa
+0x37a > 04 @ 0297:0211
+0x378 > 00 @ 0297:01ec
+0x37a > 05 @ 0297:01f5
+0x379 < 8f @ 0297:01fa
+0x37a > 04 @ 0297:0211
+0x378 > 00 @ 0297:01ec
+0x37a > 05 @ 0297:01f5
+0x379 < 8f @ 0297:01fa
+0x37a > 04 @ 0297:0211
+0x378 > 00 @ 0297:01ec
+0x37a > 05 @ 0297:01f5
+0x379 < 8f @ 0297:01fa
+0x37a > 04 @ 0297:0211
+0x378 > 00 @ 0297:01ec
+0x37a > 05 @ 0297:01f5
+0x379 < 8f @ 0297:01fa
+0x37a > 04 @ 0297:0211
+ </programlisting>
+ <para>
+ As you can see there is a repeating structure starting at
+ address <literal>0297:01ec</literal> that consists of four io
+ accesses on the parallel port. Looking at it the first io
+ access writes a changing byte to the data port the second
+ always writes the byte <literal>0x05</literal> to the control
+ port, then a value which always seems to
+ <literal>0x8f</literal> is read from the status port at which
+ point a byte <literal>0x04</literal> is written to the control
+ port. By studying this and other sections of the trace we can
+ write a C routine that emulates this, shown below with some
+ macros to make reading/writing on the parallel port easier to
+ read.
+ </para>
+ <programlisting>
+#define r_dtr(x) inb(x)
+#define r_str(x) inb(x+1)
+#define r_ctr(x) inb(x+2)
+#define w_dtr(x,y) outb(y, x)
+#define w_str(x,y) outb(y, x+1)
+#define w_ctr(x,y) outb(y, x+2)
+
+/* Seems to be sending a command byte to the scanner */
+int udpp_put(int udpp_base, unsigned char command)
+{
+ int loop, value;
+
+ w_dtr(udpp_base, command);
+ w_ctr(udpp_base, 0x05);
+
+ for (loop=0; loop < 10; loop++)
+ if ((value = r_str(udpp_base)) & 0x80)
+ {
+ w_ctr(udpp_base, 0x04);
+ return value & 0xf8;
+ }
+
+ return (value & 0xf8) | 0x01;
+}
+ </programlisting>
+ <para>
+ For the UMAX Astra 600P only seven such routines exist (well
+ 14 really, seven for SPP and seven for EPP). Whether you
+ choose to disassemble the driver at this point to verify the
+ routines is your own choice. If you do, the address from the
+ trace should help in locating them in the disassembly.
+ </para>
+ <para>
+ You will probably then find it useful to write a script/perl/C
+ program to analyse the logfile and decode them futher as this
+ can reveal higher level grouping of the low level routines.
+ For example from the logs from my UMAX Astra 600P when decoded
+ further reveal (this is a small snippet)
+ </para>
+ <programlisting>
+start:
+put: 55 8f
+put: aa 8f
+put: 00 8f
+put: 00 8f
+put: 00 8f
+put: c2 8f
+wait: ff
+get: af,87
+wait: ff
+get: af,87
+end: cc
+start:
+put: 55 8f
+put: aa 8f
+put: 00 8f
+put: 03 8f
+put: 05 8f
+put: 84 8f
+wait: ff
+ </programlisting>
+ <para>
+ From this it is easy to see that <varname>put</varname>
+ routine is often grouped together in five successive calls
+ sending information to the scanner. Once these are understood
+ it should be possible to process the logs further to show the
+ higher level routines in an easy to see format. Once the
+ highest level format that you can derive from this process is
+ understood, you then need to produce a series of scans varying
+ only one parameter between them, so you can discover how to
+ set the various parameters for the scanner.
+ </para>
+
+ <para>
+ The following is the <filename>shrink.c</filename> program:
+ <programlisting>
+/* Copyright David Campbell <campbell@torque.net> */
+#include <stdio.h>
+#include <string.h>
+
+int main (void)
+{
+ char buff[256], lastline[256] = "";
+ int count = 0;
+
+ while (!feof (stdin))
+ {
+ fgets (buff, sizeof (buff), stdin);
+ if (strcmp (buff, lastline))
+ {
+ if (count > 1)
+ printf ("# Last line repeated %i times #\n", count);
+ printf ("%s", buff);
+ strcpy (lastline, buff);
+ count = 1;
+ }
+ else count++;
+ }
+ return 0;
+}
+ </programlisting>
+ </para>
+ </sect1>
+
+ <sect1 id="undoc-func">
+ <title>Understanding undocumented APIs</title>
+
+ <para>
+ Some background: On the i386 class of machines, stack entries are
+ usually dword (4 bytes) in size, little-endian. The stack grows
+ downward in memory. The stack pointer, maintained in the
+ <literal>esp</literal> register, points to the last valid entry;
+ thus, the operation of pushing a value onto the stack involves
+ decrementing <literal>esp</literal> and then moving the value into
+ the memory pointed to by <literal>esp</literal>
+ (i.e., <literal>push p</literal> in assembly resembles
+ <literal>*(--esp) = p;</literal> in C). Removing (popping)
+ values off the stack is the reverse (i.e., <literal>pop p</literal>
+ corresponds to <literal>p = *(esp++);</literal> in C).
+ </para>
+
+ <para>
+ In the <literal>stdcall</literal> calling convention, arguments are
+ pushed onto the stack right-to-left. For example, the C call
+ <function>myfunction(40, 20, 70, 30);</function> is expressed in
+ Intel assembly as:
+ <screen>
+ push 30
+ push 70
+ push 20
+ push 40
+ call myfunction
+ </screen>
+ The called function is responsible for removing the arguments
+ off the stack. Thus, before the call to myfunction, the
+ stack would look like:
+ <screen>
+ [local variable or temporary]
+ [local variable or temporary]
+ 30
+ 70
+ 20
+ esp -> 40
+ </screen>
+ After the call returns, it should look like:
+ <screen>
+ [local variable or temporary]
+ esp -> [local variable or temporary]
+ </screen>
+ </para>
+
+ <para>
+ To restore the stack to this state, the called function must know how
+ many arguments to remove (which is the number of arguments it takes).
+ This is a problem if the function is undocumented.
+ </para>
+
+ <para>
+ One way to attempt to document the number of arguments each function
+ takes is to create a wrapper around that function that detects the
+ stack offset. Essentially, each wrapper assumes that the function will
+ take a large number of arguments. The wrapper copies each of these
+ arguments into its stack, calls the actual function, and then calculates
+ the number of arguments by checking esp before and after the call.
+ </para>
+
+ <para>
+ The main problem with this scheme is that the function must actually
+ be called from another program. Many of these functions are seldom
+ used. An attempt was made to aggressively query each function in a
+ given library (<filename>ntdll.dll</filename>) by passing 64 arguments,
+ all 0, to each function. Unfortunately, Windows NT quickly goes to a
+ blue screen of death, even if the program is run from a
+ non-administrator account.
+ </para>
+
+ <para>
+ Another method that has been much more successful is to attempt to
+ figure out how many arguments each function is removing from the
+ stack. This instruction, <literal>ret hhll</literal> (where
+ <symbol>hhll</symbol> is the number of bytes to remove, i.e. the
+ number of arguments times 4), contains the bytes
+ <literal>0xc2 ll hh</literal> in memory. It is a reasonable
+ assumption that few, if any, functions take more than 16 arguments;
+ therefore, simply searching for
+ <literal>hh == 0 && ll < 0x40</literal> starting from the
+ address of a function yields the correct number of arguments most
+ of the time.
+ </para>
+
+ <para>
+ Of course, this is not without errors. <literal>ret 00ll</literal>
+ is not the only instruction that can have the byte sequence
+ <literal>0xc2 ll 0x0</literal>; for example,
+ <literal>push 0x000040c2</literal> has the byte sequence
+ <literal>0x68 0xc2 0x40 0x0 0x0</literal>, which matches
+ the above. Properly, the utility should look for this sequence
+ only on an instruction boundary; unfortunately, finding
+ instruction boundaries on an i386 requires implementing a full
+ disassembler -- quite a daunting task. Besides, the probability
+ of having such a byte sequence that is not the actual return
+ instruction is fairly low.
+ </para>
+
+ <para>
+ Much more troublesome is the non-linear flow of a function. For
+ example, consider the following two functions:
+ <screen>
+ somefunction1:
+ jmp somefunction1_impl
+
+ somefunction2:
+ ret 0004
+
+ somefunction1_impl:
+ ret 0008
+ </screen>
+ In this case, we would incorrectly detect both
+ <function>somefunction1</function> and
+ <function>somefunction2</function> as taking only a single
+ argument, whereas <function>somefunction1</function> really
+ takes two arguments.
+ </para>
+
+ <para>
+ With these limitations in mind, it is possible to implement
+ more stubs
+ in Wine and, eventually, the functions themselves.
+ </para>
+ </sect1>
+ <sect1>
+ <title>How to do regression testing using CVS</title>
+
+ <para>
+ A problem that can happen sometimes is 'it used to work
+ before, now it doesn't anymore...'. Here is a step by step
+ procedure to try to pinpoint when the problem occurred. This
+ is <emphasis>NOT</emphasis> for casual users.
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <para>
+ Get the <quote>full CVS</quote> archive from winehq. This
+ archive is the CVS tree but with the tags controlling the
+ versioning system. It's a big file (> 40 meg) with a name
+ like full-cvs-<last update date> (it's more than 100mb
+ when uncompressed, you can't very well do this with
+ small, old computers or slow Internet connections).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ untar it into a repository directory:
+ <screen>
+cd /home/gerard
+tar -zxf full-cvs-2003-08-18.tar.gz
+mv wine repository
+ </screen>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ extract a new destination directory. This directory must
+ not be in a subdirectory of the repository else
+ <command>cvs</command> will think it's part of the
+ repository and deny you an extraction in the repository:
+ <screen>
+cd /home/gerard
+mv wine wine_current (-> this protects your current wine sandbox, if any)
+export CVSROOT=/home/gerard/repository
+cvs -d $CVSROOT checkout wine
+ </screen>
+ </para>
+ <para>
+ Note that it's not possible to do a checkout at a given
+ date; you always do the checkout for the last date where
+ the full-cvs-xxx snapshot was generated.
+ </para>
+ <para>
+ Note also that it is possible to do all this with a direct
+ CVS connection, of course. The full CVS file method is less
+ painful for the WineHQ CVS server and probably a bit faster
+ if you don't have a very good net connection.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you will have now in the <filename>~/wine</filename>
+ directory an image of the CVS tree, on the client side.
+ Now update this image to the date you want:
+ <screen>
+cd /home/gerard/wine
+cvs update -PAd -D "2004-08-23 CDT"
+ </screen>
+ </para>
+ <para>
+ The date format is <literal>YYYY-MM-DD HH:MM:SS</literal>.
+ Using the CST date format ensure that you will be able to
+ extract patches in a way that will be compatible with the
+ wine-cvs archive
+ <ulink url="http://www.winehq.org/hypermail/wine-cvs">
+ http://www.winehq.org/hypermail/wine-cvs</ulink>
+ </para>
+ <para>
+ Many messages will inform you that more recent files have
+ been deleted to set back the client cvs tree to the date
+ you asked, for example:
+ <screen>
+cvs update: tsx11/ts_xf86dga2.c is no longer in the repository
+ </screen>
+ </para>
+ <para>
+ <command>cvs update</command> is not limited to upgrade to
+ a <emphasis>newer</emphasis> version as I have believed for
+ far too long :-(
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Now proceed as for a normal update:
+ </para>
+ <screen>
+./configure
+make depend && make
+ </screen>
+ <para>
+ If any non-programmer reads this, the fastest method to
+ get at the point where the problem occurred is to use a
+ binary search, that is, if the problem occurred in 1999,
+ start at mid-year, then is the problem is already here,
+ back to 1st April, if not, to 1st October, and so on.
+ </para>
+ <para>
+ If you have lot of hard disk free space (a full compile
+ currently takes 400 Mb), copy the oldest known working
+ version before updating it, it will save time if you need
+ to go back. (it's better to <command>make
+ distclean</command> before going back in time, so you
+ have to make everything if you don't backup the older
+ version)
+ </para>
+ <para>
+ When you have found the day where the problem happened,
+ continue the search using the wine-cvs archive (sorted by
+ date) and a more precise cvs update including hour,
+ minute, second:
+ <screen>
+cvs update -PAd -D "2004-08-23 15:17:25 CDT"
+ </screen>
+ This will allow you to find easily the exact patch that
+ did it.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If you find the patch that is the cause of the problem,
+ you have almost won; report about it to
+ <ulink url="http://bugs.winehq.org/">Wine Bugzilla</ulink>
+ or subscribe to wine-devel and post it there. There is a
+ chance that the author will jump in to suggest a fix; or
+ there is always the possibility to look hard at the patch
+ until it is coerced to reveal where is the bug :-)
+ </para>
+ </listitem>
+ </orderedlist>
+ </sect1>
+
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
+End:
+-->
diff --git a/documentation/winedev-windowing.sgml b/documentation/winedev-windowing.sgml
new file mode 100644
index 0000000..8d8cccc
--- /dev/null
+++ b/documentation/winedev-windowing.sgml
@@ -0,0 +1,673 @@
+ <chapter>
+ <title>Windowing system</title>
+ <sect1>
+ <title>USER Module</title>
+
+ <para>
+ USER implements windowing and messaging subsystems. It also
+ contains code for common controls and for other
+ miscellaneous stuff (rectangles, clipboard, WNet, etc).
+ Wine USER code is located in <filename>windows/</filename>,
+ <filename>controls/</filename>, and
+ <filename>misc/</filename> directories.
+ </para>
+
+ <sect2>
+ <title>Windowing subsystem</title>
+
+ <para><filename>windows/win.c</filename></para>
+ <para><filename>windows/winpos.c</filename></para>
+ <para>
+ Windows are arranged into parent/child hierarchy with one
+ common ancestor for all windows (desktop window). Each
+ window structure contains a pointer to the immediate
+ ancestor (parent window if <constant>WS_CHILD</constant>
+ style bit is set), a pointer to the sibling (returned by
+ <function>GetWindow(..., GW_NEXT)</function>), a pointer
+ to the owner window (set only for popup window if it was
+ created with valid <varname>hwndParent</varname>
+ parameter), and a pointer to the first child window
+ (<function>GetWindow(.., GW_CHILD)</function>). All popup
+ and non-child windows are therefore placed in the first
+ level of this hierarchy and their ancestor link
+ (<varname>wnd->parent</varname>) points to the desktop
+ window.
+ </para>
+ <screen>
+ Desktop window - root window
+ | \ `-.
+ | \ `-.
+ popup -> wnd1 -> wnd2 - top level windows
+ | \ `-. `-.
+ | \ `-. `-.
+ child1 child2 -> child3 child4 - child windows
+ </screen>
+ <para>
+ Horizontal arrows denote sibling relationship, vertical
+ lines - ancestor/child. To summarize, all windows with the
+ same immediate ancestor are sibling windows, all windows
+ which do not have desktop as their immediate ancestor are
+ child windows. Popup windows behave as topmost top-level
+ windows unless they are owned. In this case the only
+ requirement is that they must precede their owners in the
+ top-level sibling list (they are not topmost). Child
+ windows are confined to the client area of their parent
+ windows (client area is where window gets to do its own
+ drawing, non-client area consists of caption, menu,
+ borders, intrinsic scrollbars, and
+ minimize/maximize/close/help buttons).
+ </para>
+ <para>
+ Another fairly important concept is
+ <firstterm>z-order</firstterm>. It is derived from the
+ ancestor/child hierarchy and is used to determine
+ "above/below" relationship. For instance, in the example
+ above, z-order is
+ </para>
+ <screen>
+child1->popup->child2->child3->wnd1->child4->wnd2->desktop.
+ </screen>
+ <para>
+ Current active window ("foreground window" in Win32) is
+ moved to the front of z-order unless its top-level
+ ancestor owns popup windows.
+ </para>
+ <para>
+ All these issues are dealt with (or supposed to be) in
+ <filename>windows/winpos.c</filename> with
+ <function>SetWindowPos()</function> being the primary
+ interface to the window manager.
+ </para>
+ <para>
+ Wine specifics: in default and managed mode each top-level
+ window gets its own X counterpart with desktop window
+ being basically a fake stub. In desktop mode, however,
+ only desktop window has an X window associated with it.
+ Also, <function>SetWindowPos()</function> should
+ eventually be implemented via
+ <function>Begin/End/DeferWindowPos()</function> calls and
+ not the other way around.
+ </para>
+
+ <sect3>
+ <title>Visible region, clipping region and update region</title>
+
+ <para><filename>windows/dce.c</filename></para>
+ <para><filename>windows/winpos.c</filename></para>
+ <para><filename>windows/painting.c</filename></para>
+
+ <screen>
+ ________________________
+ |_________ | A and B are child windows of C
+ | A |______ |
+ | | | |
+ |---------' | |
+ | | B | |
+ | | | |
+ | `------------' |
+ | C |
+ `------------------------'
+ </screen>
+ <para>
+ Visible region determines which part of the window is
+ not obscured by other windows. If a window has the
+ <constant>WS_CLIPCHILDREN</constant> style then all
+ areas below its children are considered invisible.
+ Similarly, if the <constant>WS_CLIPSIBLINGS</constant>
+ bit is in effect then all areas obscured by its siblings
+ are invisible. Child windows are always clipped by the
+ boundaries of their parent windows.
+ </para>
+ <para>
+ B has a <constant>WS_CLIPSIBLINGS</constant> style:
+ </para>
+ <screen>
+ . ______
+ : | |
+ | ,-----' |
+ | | B | - visible region of B
+ | | |
+ : `------------'
+ </screen>
+ <para>
+ When the program requests a <firstterm>display
+ context</firstterm> (DC) for a window it can specify
+ an optional clipping region that further restricts the
+ area where the graphics output can appear. This area is
+ calculated as an intersection of the visible region and
+ a clipping region.
+ </para>
+ <para>
+ Program asked for a DC with a clipping region:
+ </para>
+ <screen>
+ ______
+ ,--|--. | . ,--.
+ ,--+--' | | : _: |
+ | | B | | => | | | - DC region where the painting will
+ | | | | | | | be visible
+ `--|-----|---' : `----'
+ `-----'
+ </screen>
+ <para>
+ When the window manager detects that some part of the window
+ became visible it adds this area to the update region of this
+ window and then generates <constant>WM_ERASEBKGND</constant> and
+ <constant>WM_PAINT</constant> messages. In addition,
+ <constant>WM_NCPAINT</constant> message is sent when the
+ uncovered area intersects a nonclient part of the window.
+ Application must reply to the <constant>WM_PAINT</constant>
+ message by calling the
+ <function>BeginPaint()</function>/<function>EndPaint()</function>
+ pair of functions. <function>BeginPaint()</function> returns a DC
+ that uses accumulated update region as a clipping region. This
+ operation cleans up invalidated area and the window will not
+ receive another <constant>WM_PAINT</constant> until the window
+ manager creates a new update region.
+ </para>
+ <para>
+ A was moved to the left:
+ </para>
+ <screen>
+ ________________________ ... / C update region
+ |______ | : .___ /
+ | A |_________ | => | ...|___|..
+ | | | | | : | |
+ |------' | | | : '---'
+ | | B | | | : \
+ | | | | : \
+ | `------------' | B update region
+ | C |
+ `------------------------'
+ </screen>
+ <para>
+ Windows maintains a display context cache consisting of
+ entries that include the DC itself, the window to which
+ it belongs, and an optional clipping region (visible
+ region is stored in the DC itself). When an API call
+ changes the state of the window tree, window manager has
+ to go through the DC cache to recalculate visible
+ regions for entries whose windows were involved in the
+ operation. DC entries (DCE) can be either private to the
+ window, or private to the window class, or shared
+ between all windows (Windows 3.1 limits the number of
+ shared DCEs to 5).
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Messaging subsystem</title>
+
+ <para><filename>windows/queue.c</filename></para>
+ <para><filename>windows/message.c</filename></para>
+
+ <para>
+ Each Windows task/thread has its own message queue - this
+ is where it gets messages from. Messages can be:
+ <orderedlist>
+ <listitem>
+ <para>
+ generated on the fly (<constant>WM_PAINT</constant>,
+ <constant>WM_NCPAINT</constant>,
+ <constant>WM_TIMER</constant>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ created by the system (hardware messages)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ posted by other tasks/threads (<function>PostMessage</function>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ sent by other tasks/threads (<function>SendMessage</function>)
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+ <para>
+ Message priority:
+ </para>
+ <para>
+ First the system looks for sent messages, then for posted
+ messages, then for hardware messages, then it checks if
+ the queue has the "dirty window" bit set, and, finally, it
+ checks for expired timers. See
+ <filename>windows/message.c</filename>.
+ </para>
+ <para>
+ From all these different types of messages, only posted
+ messages go directly into the private message queue.
+ System messages (even in Win95) are first collected in the
+ system message queue and then they either sit there until
+ <function>Get/PeekMessage</function> gets to process them
+ or, as in Win95, if system queue is getting clobbered, a
+ special thread ("raw input thread") assigns them to the
+ private queues. Sent messages are queued separately and
+ the sender sleeps until it gets a reply. Special messages
+ are generated on the fly depending on the window/queue
+ state. If the window update region is not empty, the
+ system sets the <constant>QS_PAINT</constant> bit in the
+ owning queue and eventually this window receives a
+ <constant>WM_PAINT</constant> message
+ (<constant>WM_NCPAINT</constant> too if the update region
+ intersects with the non-client area). A timer event is
+ raised when one of the queue timers expire. Depending on
+ the timer parameters <function>DispatchMessage</function>
+ either calls the callback function or the window
+ procedure. If there are no messages pending the
+ task/thread sleeps until messages appear.
+ </para>
+ <para>
+ There are several tricky moments (open for discussion) -
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ System message order has to be honored and messages
+ should be processed within correct task/thread
+ context. Therefore when <function>Get/PeekMessage</function> encounters
+ unassigned system message and this message appears not
+ to be for the current task/thread it should either
+ skip it (or get rid of it by moving it into the
+ private message queue of the target task/thread -
+ Win95, AFAIK) and look further or roll back and then
+ yield until this message gets processed when system
+ switches to the correct context (Win16). In the first
+ case we lose correct message ordering, in the second
+ case we have the infamous synchronous system message
+ queue. Here is a post to one of the OS/2 newsgroup I
+ found to be relevant:
+ </para>
+ <blockquote>
+ <attribution>by David Charlap</attribution>
+ <para>
+ " Here's the problem in a nutshell, and there is no
+ good solution. Every possible solution creates a
+ different problem.
+ </para>
+ <para>
+ With a windowing system, events can go to many
+ different windows. Most are sent by applications or
+ by the OS when things relating to that window happen
+ (like repainting, timers, etc.)
+ </para>
+ <para>
+ Mouse input events go to the window you click on
+ (unless some window captures the mouse).
+ </para>
+ <para>
+ So far, no problem. Whenever an event happens, you
+ put a message on the target window's message queue.
+ Every process has a message queue. If the process
+ queue fills up, the messages back up onto the system
+ queue.
+ </para>
+ <para>
+ This is the first cause of apps hanging the GUI. If
+ an app doesn't handle messages and they back up into
+ the system queue, other apps can't get any more
+ messages. The reason is that the next message in
+ line can't go anywhere, and the system won't skip
+ over it.
+ </para>
+ <para>
+ This can be fixed by making apps have bigger private
+ message queues. The SIQ fix does this. PMQSIZE does
+ this for systems without the SIQ fix. Applications
+ can also request large queues on their own.
+ </para>
+ <para>
+ Another source of the problem, however, happens when
+ you include keyboard events. When you press a key,
+ there's no easy way to know what window the
+ keystroke message should be delivered to.
+ </para>
+ <para>
+ Most windowing systems use a concept known as
+ "focus". The window with focus gets all incoming
+ keyboard messages. Focus can be changed from window
+ to window by apps or by users clicking on windows.
+ </para>
+ <para>
+ This is the second source of the problem. Suppose
+ window A has focus. You click on window B and start
+ typing before the window gets focus. Where should
+ the keystrokes go? On the one hand, they should go
+ to A until the focus actually changes to B. On the
+ other hand, you probably want the keystrokes to go
+ to B, since you clicked there first.
+ </para>
+ <para>
+ OS/2's solution is that when a focus-changing event
+ happens (like clicking on a window), OS/2 holds all
+ messages in the system queue until the focus change
+ actually happens. This way, subsequent keystrokes
+ go to the window you clicked on, even if it takes a
+ while for that window to get focus.
+ </para>
+ <para>
+ The downside is that if the window takes a real long
+ time to get focus (maybe it's not handling events,
+ or maybe the window losing focus isn't handling
+ events), everything backs up in the system queue and
+ the system appears hung.
+ </para>
+ <para>
+ There are a few solutions to this problem.
+ </para>
+ <para>
+ One is to make focus policy asynchronous. That is,
+ focus changing has absolutely nothing to do with the
+ keyboard. If you click on a window and start typing
+ before the focus actually changes, the keystrokes go
+ to the first window until focus changes, then they
+ go to the second. This is what X-windows does.
+ </para>
+ <para>
+ Another is what NT does. When focus changes,
+ keyboard events are held in the system message
+ queue, but other events are allowed through. This is
+ "asynchronous" because the messages in the system
+ queue are delivered to the application queues in a
+ different order from that with which they were
+ posted. If a bad app won't handle the "lose focus"
+ message, it's of no consequence - the app receiving
+ focus will get its "gain focus" message, and the
+ keystrokes will go to it.
+ </para>
+ <para>
+ The NT solution also takes care of the application
+ queue filling up problem. Since the system delivers
+ messages asynchronously, messages waiting in the
+ system queue will just sit there and the rest of the
+ messages will be delivered to their apps.
+ </para>
+ <para>
+ The OS/2 SIQ solution is this: When a
+ focus-changing event happens, in addition to
+ blocking further messages from the application
+ queues, a timer is started. When the timer goes
+ off, if the focus change has not yet happened, the
+ bad app has its focus taken away and all messages
+ targeted at that window are skipped. When the bad
+ app finally handles the focus change message, OS/2
+ will detect this and stop skipping its messages.
+ </para>
+
+ <para>
+ As for the pros and cons:
+ </para>
+ <para>
+ The X-windows solution is probably the easiest. The
+ problem is that users generally don't like having to
+ wait for the focus to change before they start
+ typing. On many occasions, you can type and the
+ characters end up in the wrong window because
+ something (usually heavy system load) is preventing
+ the focus change from happening in a timely manner.
+ </para>
+ <para>
+ The NT solution seems pretty nice, but making the
+ system message queue asynchronous can cause similar
+ problems to the X-windows problem. Since messages
+ can be delivered out of order, programs must not
+ assume that two messages posted in a particular
+ order will be delivered in that same order. This
+ can break legacy apps, but since Win32 always had an
+ asynchronous queue, it is fair to simply tell app
+ designers "don't do that". It's harder to tell app
+ designers something like that on OS/2 - they'll
+ complain "you changed the rules and our apps are
+ breaking."
+ </para>
+ <para>
+ The OS/2 solution's problem is that nothing happens
+ until you try to change window focus, and then wait
+ for the timeout. Until then, the bad app is not
+ detected and nothing is done."
+ </para>
+ </blockquote>
+ </listitem>
+
+ <listitem>
+ <para>
+ Intertask/interthread
+ <function>SendMessage</function>. The system has to
+ inform the target queue about the forthcoming message,
+ then it has to carry out the context switch and wait
+ until the result is available. Win16 stores necessary
+ parameters in the queue structure and then calls
+ <function>DirectedYield()</function> function.
+ However, in Win32 there could be several messages
+ pending sent by preemptively executing threads, and in
+ this case <function>SendMessage</function> has to
+ build some sort of message queue for sent messages.
+ Another issue is what to do with messages sent to the
+ sender when it is blocked inside its own
+ <function>SendMessage</function>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ <sect2 id="accel-impl">
+ <title>Accelerators</title>
+
+ <para>
+ There are <emphasis>three</emphasis> differently sized
+ accelerator structures exposed to the user:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Accelerators in NE resources. This is also the internal
+ layout of the global handle <type>HACCEL</type> (16 and
+ 32) in Windows 95 and Wine. Exposed to the user as Win16
+ global handles <type>HACCEL16</type> and
+ <type>HACCEL32</type> by the Win16/Win32 API.
+ These are 5 bytes long, with no padding:
+ <programlisting>
+BYTE fVirt;
+WORD key;
+WORD cmd;
+ </programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Accelerators in PE resources. They are exposed to the
+ user only by direct accessing PE resources. These have a
+ size of 8 bytes:
+ </para>
+ <programlisting>
+BYTE fVirt;
+BYTE pad0;
+WORD key;
+WORD cmd;
+WORD pad1;
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Accelerators in the Win32 API. These are exposed to the
+ user by the <function>CopyAcceleratorTable</function>
+ and <function>CreateAcceleratorTable</function> functions
+ in the Win32 API.
+ These have a size of 6 bytes:
+ </para>
+ <programlisting>
+BYTE fVirt;
+BYTE pad0;
+WORD key;
+WORD cmd;
+ </programlisting>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ Why two types of accelerators in the Win32 API? We can only
+ guess, but my best bet is that the Win32 resource compiler
+ can/does not handle struct packing. Win32 <type>ACCEL</type>
+ is defined using <function>#pragma(2)</function> for the
+ compiler but without any packing for RC, so it will assume
+ <function>#pragma(4)</function>.
+ </para>
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>X Windows System interface</title>
+ <para></para>
+ <sect2>
+ <title>Keyboard mapping</title>
+ <para>
+ Wine now needs to know about your keyboard layout. This
+ requirement comes from a need from many apps to have the
+ correct scancodes available, since they read these directly,
+ instead of just taking the characters returned by the X
+ server. This means that Wine now needs to have a mapping
+ from X keys to the scancodes these programs expect.
+ </para>
+ <para>
+ On startup, Wine will try to recognize the active X layout
+ by seeing if it matches any of the defined tables. If it
+ does, everything is alright. If not, you need to define it.
+ </para>
+ <para>
+ To do this, open the file
+ <filename>dlls/x11drv/keyboard.c</filename> and take a look
+ at the existing tables. Make a backup copy of it, especially
+ if you don't use CVS.
+ </para>
+ <para>
+ What you really would need to do, is find out which scancode
+ each key needs to generate. Find it in the
+ <function>main_key_scan</function> table, which looks like
+ this:
+ </para>
+ <programlisting>
+static const int main_key_scan[MAIN_LEN] =
+{
+/* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
+0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
+0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
+0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
+0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
+0x56 /* the 102nd key (actually to the right of l-shift) */
+};
+ </programlisting>
+ <para>
+ Next, assign each scancode the characters imprinted on the
+ keycaps. This was done (sort of) for the US 101-key keyboard,
+ which you can find near the top in
+ <filename>keyboard.c</filename>. It also shows that if there
+ is no 102nd key, you can skip that.
+ </para>
+ <para>
+ However, for most international 102-key keyboards, we have
+ done it easy for you. The scancode layout for these already
+ pretty much matches the physical layout in the
+ <function>main_key_scan</function>, so all you need to do is
+ to go through all the keys that generate characters on your
+ main keyboard (except spacebar), and stuff those into an
+ appropriate table. The only exception is that the 102nd key,
+ which is usually to the left of the first key of the last
+ line (usually <keycap>Z</keycap>), must be placed on a
+ separate line after the last line.
+ </para>
+ <para>
+ For example, my Norwegian keyboard looks like this
+ </para>
+ <screen>
+§ ! " # ¤ % & / ( ) = ? ` Back-
+| 1 2@ 3£ 4$ 5 6 7{ 8[ 9] 0} + \´ space
+
+Tab Q W E R T Y U I O P Å ^
+ ¨~
+ Enter
+Caps A S D F G H J K L Ø Æ *
+Lock '
+
+Sh- > Z X C V B N M ; : _ Shift
+ift < , . -
+
+Ctrl Alt Spacebar AltGr Ctrl
+ </screen>
+ <para>
+ Note the 102nd key, which is the <keycap><></keycap> key, to
+ the left of <keycap>Z</keycap>. The character to the right of
+ the main character is the character generated by
+ <keycap>AltGr</keycap>.
+ </para>
+ <para>
+ This keyboard is defined as follows:
+ </para>
+ <programlisting>
+static const char main_key_NO[MAIN_LEN][4] =
+{
+"|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\´",
+"qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
+"aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
+"zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
+"<>"
+};
+ </programlisting>
+ <para>
+ Except that " and \ needs to be quoted with a backslash, and
+ that the 102nd key is on a separate line, it's pretty
+ straightforward.
+ </para>
+ <para>
+ After you have written such a table, you need to add it to the
+ <function>main_key_tab[]</function> layout index table. This
+ will look like this:
+ </para>
+ <programlisting>
+static struct {
+WORD lang, ansi_codepage, oem_codepage;
+const char (*key)[MAIN_LEN][4];
+} main_key_tab[]={
+...
+...
+{MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT), 1252, 865, &main_key_NO},
+...
+ </programlisting>
+ <para>
+ After you have added your table, recompile Wine and test that
+ it works. If it fails to detect your table, try running
+ </para>
+ <screen>
+WINEDEBUG=+key,+keyboard wine > key.log 2>&1
+ </screen>
+ <para>
+ and look in the resulting <filename>key.log</filename> file to
+ find the error messages it gives for your layout.
+ </para>
+ <para>
+ Note that the <constant>LANG_*</constant> and
+ <constant>SUBLANG_*</constant> definitions are in
+ <filename>include/winnls.h</filename>, which you might need
+ to know to find out which numbers your language is assigned,
+ and find it in the WINEDEBUG output. The numbers will be
+ <literal>(SUBLANG * 0x400 + LANG)</literal>, so, for example
+ the combination <literal>LANG_NORWEGIAN (0x14)</literal> and
+ <literal>SUBLANG_DEFAULT (0x1)</literal> will be (in hex)
+ <literal>14 + 1*400 = 414</literal>, so since I'm Norwegian,
+ I could look for <literal>0414</literal> in the WINEDEBUG
+ output to find out why my keyboard won't detect.
+ </para>
+ </sect2>
+ </sect1>
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
+End:
+-->