diff --git a/documentation/Makefile.in b/documentation/Makefile.in
index f80417e7b2..bbabb82b1b 100644
--- a/documentation/Makefile.in
+++ b/documentation/Makefile.in
@@ -26,20 +26,20 @@ WINE_USER_SRCS = \
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 66afd02199..62f9f89426 100644
--- a/documentation/architecture.sgml
+++ b/documentation/architecture.sgml
@@ -659,6 +659,125 @@
shared library.
+
+ Wine/Windows DLLs
+
+
+ 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.
+
+
+
+ Pros of Native DLLs
+
+
+ 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.
+
+
+ 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.
+
+
+
+
+ Cons of Native DLLs
+
+
+ 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.
+
+
+ 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.
+
+
+
+
+ Deciding Between Native and Built-In DLLs
+
+
+ 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.
+
+
+
+
+ Load Order for DLLs
+
+
+ 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.
+
+
+ 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.
+
+
+ The DefaultLoadOrder from the
+ [DllDefaults] section specifies for all DLLs which version
+ to try first. See manpage for explanation of the arguments.
+
+
+ The [DllOverrides] section deals with DLLs, which need a
+ different-from-default treatment.
+
+
+ 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.
+
+
+ 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
+ dlls/ subdirectory using the 32-bit
+ name.
+
+
+
+
Memory management
@@ -828,7 +947,116 @@
Wine is using, the glibc malloc arena and so on.
+
+
+ Laying out the address space
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
Processes
@@ -1124,971 +1352,8 @@
-
-
-
- Module Overview
-
- NTDLL Module
-
- NTDLL provides most of the services you'd expect from a
- kernel.
-
-
- 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.
-
-
- Wine also provide fibers (which is the Windows name of
- co-routines).
-
-
- 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).
-
-
-
- File management
-
- 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.
-
-
- File handles can be waitable objects, as Windows define
- them.
-
-
- 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).
-
-
- FIXME: this should be enhanced and updated to latest work
- on FS.
-
-
-
-
- Synchronization
-
- 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.
-
-
-
-
- Module (DLL) loading
-
- Wine is able to load any NE and PE module. In all cases,
- the module's binary code is directly executed by the
- processor.
-
-
-
-
- Device management
-
- Wine allows usage a wide variety of devices:
-
-
-
- Communication ports are mapped to Unix
- communication ports (if they have sufficient
- permissions).
-
-
-
-
- Parallel ports are mapped to Unix parallel ports (if
- they have sufficient permissions).
-
-
-
-
- CDROM: the Windows device I/O control calls are
- mapped onto Unix ioctl().
-
-
-
-
- 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.
-
-
- Wine will not support native VxD.
-
-
-
-
-
-
-
-
- KERNEL Module
-
-
- FIXME: Needs some content...
-
-
-
-
- GDI Module
-
-
- X Windows System interface
-
-
- 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 XInitThreads()). However,
- Wine does not use this approach. Instead Wine performs its
- own synchronization using the
- wine_tsx11_lock() / wine_tsx11_unlock()
- functions. This locking protects library access
- with a critical section, and also arranges things so that
- X libraries compiled without
- (eg. with global errno variable) will
- work with Wine.
-
-
- In the past, all calls to X used to go through a wrapper called
- TSX...() (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.
-
-
-
-
-
- USER Module
-
-
- 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 windows/,
- controls/, and
- misc/ directories.
-
-
-
- Windowing subsystem
-
- windows/win.c
- windows/winpos.c
-
- 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 WS_CHILD
- style bit is set), a pointer to the sibling (returned by
- GetWindow(..., GW_NEXT)), a pointer
- to the owner window (set only for popup window if it was
- created with valid hwndParent
- parameter), and a pointer to the first child window
- (GetWindow(.., GW_CHILD)). All popup
- and non-child windows are therefore placed in the first
- level of this hierarchy and their ancestor link
- (wnd->parent) points to the desktop
- window.
-
-
- Desktop window - root window
- | \ `-.
- | \ `-.
- popup -> wnd1 -> wnd2 - top level windows
- | \ `-. `-.
- | \ `-. `-.
- child1 child2 -> child3 child4 - child windows
-
-
- 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).
-
-
- Another fairly important concept is
- z-order. 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
-
-
-child1->popup->child2->child3->wnd1->child4->wnd2->desktop.
-
-
- Current active window ("foreground window" in Win32) is
- moved to the front of z-order unless its top-level
- ancestor owns popup windows.
-
-
- All these issues are dealt with (or supposed to be) in
- windows/winpos.c with
- SetWindowPos() being the primary
- interface to the window manager.
-
-
- 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, SetWindowPos() should
- eventually be implemented via
- Begin/End/DeferWindowPos() calls and
- not the other way around.
-
-
-
- Visible region, clipping region and update region
-
- windows/dce.c
- windows/winpos.c
- windows/painting.c
-
-
- ________________________
- |_________ | A and B are child windows of C
- | A |______ |
- | | | |
- |---------' | |
- | | B | |
- | | | |
- | `------------' |
- | C |
- `------------------------'
-
-
- Visible region determines which part of the window is
- not obscured by other windows. If a window has the
- WS_CLIPCHILDREN style then all
- areas below its children are considered invisible.
- Similarly, if the WS_CLIPSIBLINGS
- 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.
-
-
- B has a WS_CLIPSIBLINGS style:
-
-
- . ______
- : | |
- | ,-----' |
- | | B | - visible region of B
- | | |
- : `------------'
-
-
- When the program requests a display
- context (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.
-
-
- Program asked for a DC with a clipping region:
-
-
- ______
- ,--|--. | . ,--.
- ,--+--' | | : _: |
- | | B | | => | | | - DC region where the painting will
- | | | | | | | be visible
- `--|-----|---' : `----'
- `-----'
-
-
- 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 WM_ERASEBKGND and
- WM_PAINT messages. In addition,
- WM_NCPAINT message is sent when the
- uncovered area intersects a nonclient part of the window.
- Application must reply to the WM_PAINT
- message by calling the
- BeginPaint()/EndPaint()
- pair of functions. BeginPaint() 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 WM_PAINT until the window
- manager creates a new update region.
-
-
- A was moved to the left:
-
-
- ________________________ ... / C update region
- |______ | : .___ /
- | A |_________ | => | ...|___|..
- | | | | | : | |
- |------' | | | : '---'
- | | B | | | : \
- | | | | : \
- | `------------' | B update region
- | C |
- `------------------------'
-
-
- 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).
-
-
-
-
-
- Messaging subsystem
-
- windows/queue.c
- windows/message.c
-
-
- Each Windows task/thread has its own message queue - this
- is where it gets messages from. Messages can be:
-
-
-
- generated on the fly (WM_PAINT,
- WM_NCPAINT,
- WM_TIMER)
-
-
-
-
- created by the system (hardware messages)
-
-
-
-
- posted by other tasks/threads (PostMessage)
-
-
-
-
- sent by other tasks/threads (SendMessage)
-
-
-
-
-
- Message priority:
-
-
- 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
- windows/message.c.
-
-
- 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
- Get/PeekMessage 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 QS_PAINT bit in the
- owning queue and eventually this window receives a
- WM_PAINT message
- (WM_NCPAINT 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 DispatchMessage
- either calls the callback function or the window
- procedure. If there are no messages pending the
- task/thread sleeps until messages appear.
-
-
- There are several tricky moments (open for discussion) -
-
-
-
-
-
- System message order has to be honored and messages
- should be processed within correct task/thread
- context. Therefore when Get/PeekMessage 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:
-
-
- by David Charlap
-
- " Here's the problem in a nutshell, and there is no
- good solution. Every possible solution creates a
- different problem.
-
-
- 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.)
-
-
- Mouse input events go to the window you click on
- (unless some window captures the mouse).
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- There are a few solutions to this problem.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
- 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.
-
-
-
- As for the pros and cons:
-
-
- 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.
-
-
- 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."
-
-
- 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."
-
-
-
-
-
-
- Intertask/interthread
- SendMessage. 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
- DirectedYield() function.
- However, in Win32 there could be several messages
- pending sent by preemptively executing threads, and in
- this case SendMessage 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
- SendMessage.
-
-
-
-
-
-
-
-
- Wine/Windows DLLs
-
-
- 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.
-
-
-
- Pros of Native DLLs
-
-
- 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.
-
-
- 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.
-
-
-
-
- Cons of Native DLLs
-
-
- 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.
-
-
- 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.
-
-
-
-
- Deciding Between Native and Built-In DLLs
-
-
- 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.
-
-
-
-
-
- Load Order for DLLs
-
-
- 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.
-
-
- 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.
-
-
- The DefaultLoadOrder from the
- [DllDefaults] section specifies for all DLLs which version
- to try first. See manpage for explanation of the arguments.
-
-
- The [DllOverrides] section deals with DLLs, which need a
- different-from-default treatment.
-
-
- 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.
-
-
- 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
- dlls/ subdirectory using the 32-bit
- name.
-
-
-
-
- Understanding What DLLs Do
-
-
- 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.
-
-
- (See also ./DEVELOPER-HINTS or the
- dlls/ subdirectory to see which DLLs
- are currently being rewritten for Wine)
-
-
-
-
-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
-
-
-
-
- The Wine initialization process
-
-
- Wine has a rather complex startup procedure, so unlike many programs the best place to begin
- exploring the code-base is not in fact at the main() function but instead
- at some of the more straightforward DLLs that exist on the periphery such as MSI, the widget
- library (in USER and COMCTL32) etc. The purpose of this section is to document and explain how
- Wine starts up from the moment the user runs "wine myprogram.exe" to the point at which
- myprogram gets control.
-
-
-
- First Steps
-
-
- The actual wine binary that the user runs does not do very much, in fact it is only
- responsible for checking the threading model in use (NPTL vs LinuxThreads) and then invoking
- a new binary which performs the next stage in the startup sequence. See the threading chapter
- for more information on this check and why it's necessary. You can find this code in
- loader/glibc.c. The result of this check is an exec of either
- wine-pthread or wine-kthread, potentially (on Linux) via
- the preloader. We need to use separate binaries here because overriding
- the native pthreads library requires us to exploit a property of ELF symbol fixup semantics:
- it's not possible to do this without starting a new process.
-
-
-
- The Wine preloader is found in loader/preloader.c, and is required in
- order to impose a Win32 style address space layout upon the newly created Win32 process. The
- details of what this does is covered in the address space layout chapter. The preloader is a
- statically linked ELF binary which is passed the name of the actual Wine binary to run (either
- wine-kthread or wine-pthread) along with the arguments the user passed in from the command
- line. The preloader is an unusual program: it does not have a main() function. In standard ELF
- applications, the entry point is actually at a symbol named _start: this is provided by the
- standard gcc infrastructure and normally jumps to __libc_start_main which
- initializes glibc before passing control to the main function as defined by the programmer.
-
-
-
- The preloader takes control direct from the entry point for a few reasons. Firstly, it is
- required that glibc is not initialized twice: the result of such behaviour is undefined and
- subject to change without notice. Secondly, it's possible that as part of initializing glibc,
- the address space layout could be changed - for instance, any call to malloc will initialize a
- heap arena which modifies the VM mappings. Finally, glibc does not return to _start at any
- point, so by reusing it we avoid the need to recreate the ELF bootstrap stack (env, argv,
- auxiliary array etc).
-
-
-
- The preloader is responsible for two things: protecting important regions of the address
- space so the dynamic linker does not map shared libraries into them, and once that is done
- loading the real Wine binary off disk, linking it and starting it up. Normally all this is
- done automatically by glibc and the kernel but as we intercepted this process by using a
- static binary it's up to us to restart the process. The bulk of the code in the preloader is
- about loading wine-[pk]thread and ld-linux.so.2 off disk, linking them together, then
- starting the dynamic linking process.
-
-
-
- One of the last things the preloader does before jumping into the dynamic linker is scan the
- symbol table of the loaded Wine binary and set the value of a global variable directly: this
- is a more efficient way of passing information to the main Wine program than flattening the
- data structures into an environment variable or command line parameter then unpacking it on
- the other side, but it achieves pretty much the same thing. The global variable set points to
- the preload descriptor table, which contains the VMA regions protected by the preloader. This
- allows Wine to unmap them once the dynamic linker has been run, so leaving gaps we can
- initialize properly later on.
-
-
-
-
-
- Starting the emulator
-
-
- The process of starting up the emulator itself is mostly one of chaining through various
- initializer functions defined in the core libraries and DLLs: libwine, then NTDLL, then kernel32.
-
-
-
- Both the wine-pthread and wine-kthread binaries share a common main
- function, defined in loader/main.c, so no matter which binary is selected
- after the preloader has run we start here. This passes the information provided by the
- preloader into libwine and then calls wine_init, defined
- in libs/wine/loader.c. This is where the emulation really starts:
- wine_init can, with the correct preparation,
- be called from programs other than the wine loader itself.
-
-
-
- wine_init does some very basic setup tasks such as initializing the
- debugging infrastructure, yet more address space manipulation (see the information on the
- 4G/4G VM split in the address space chapter), before loading NTDLL - the core of both Wine and
- the Windows NT series - and jumping to the __wine_process_init function defined
- in dlls/ntdll/loader.c
-
-
-
- This function is responsible for initializing the primary Win32 environment. In thread_init(),
- it sets up the TEB, the wineserver connection for the main thread and the process heap. See
- the threading chapter for more information on this.
-
-
-
- Finally, it loads and jumps to __wine_kernel_init in kernel32.dll: this
- is defined in dlls/kernel32/process.c. This is where the bulk of the work
- is done. The kernel32 initialization code retrieves the startup info for the process from the
- server, initializes the registry, sets up the drive mapping system and locale data, then
- begins loading the requested application itself. Each process has a STARTUPINFO block that can
- be passed into CreateProcess specifying various things like how the first
- window should be displayed: this is sent to the new process via the wineserver.
-
-
-
- After determining the type of file given to Wine by the user (a Win32 EXE file, a Win16 EXE, a
- Winelib app etc), the program is loaded into memory (which may involve loading and
- initializing other DLLs, the bulk of Wines startup code), before control reaches the end of
- __wine_kernel_init. This function ends with the new process stack being
- initialized, and start_process being called on the new stack. Nearly there!
-
-
-
- The final element of initializing Wine is starting the newly loaded program
- itself. start_process sets up the SEH backstop handler, calls
- LdrInitializeThunk which performs the last part of the process
- initialization (such as performing relocations and calling the DllMains with PROCESS_ATTACH),
- grabs the entry point of the executable and then on this line:
-
-
-
- ExitProcess( entry( peb ) );
-
-
-
- ... jumps to the entry point of the program. At this point the users program is running and
- the API provided by Wine is ready to be used. When entry returns,
- the ExitProcess API will be used to initialize a graceful shutdown.
-
-
-
-
diff --git a/documentation/cvs-regression.sgml b/documentation/cvs-regression.sgml
deleted file mode 100644
index a0dbd9782c..0000000000
--- a/documentation/cvs-regression.sgml
+++ /dev/null
@@ -1,142 +0,0 @@
-
- How to do regression testing using CVS
-
-
- 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
- NOT for casual users.
-
-
-
-
-
- Get the full CVS 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).
-
-
-
-
- untar it into a repository directory:
-
-cd /home/gerard
-tar -zxf full-cvs-2003-08-18.tar.gz
-mv wine repository
-
-
-
-
-
- extract a new destination directory. This directory must
- not be in a subdirectory of the repository else
- cvs will think it's part of the
- repository and deny you an extraction in the repository:
-
-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
-
-
-
- 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.
-
-
- 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.
-
-
-
-
- you will have now in the ~/wine
- directory an image of the CVS tree, on the client side.
- Now update this image to the date you want:
-
-cd /home/gerard/wine
-cvs update -PAd -D "2004-08-23 CDT"
-
-
-
- The date format is YYYY-MM-DD HH:MM:SS.
- 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
-
- http://www.winehq.org/hypermail/wine-cvs
-
-
- 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:
-
-cvs update: tsx11/ts_xf86dga2.c is no longer in the repository
-
-
-
- cvs update is not limited to upgrade to
- a newer version as I have believed for
- far too long :-(
-
-
-
-
- Now proceed as for a normal update:
-
-
-./configure
-make depend && make
-
-
- 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.
-
-
- 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 make distclean before going back in
- time, so you have to make everything if you don't backup the older
- version)
-
-
- 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 :
-
-cvs update -PAd -D "2004-08-23 15:17:25 CDT"
-
- This will allow you to find easily the exact patch that did it.
-
-
-
-
- If you find the patch that is the cause of the problem, you have
- almost won; report about it to
- Wine Bugzilla
- 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 :-)
-
-
-
-
-
-
diff --git a/documentation/i18n.sgml b/documentation/i18n.sgml
deleted file mode 100644
index b2498d3a1a..0000000000
--- a/documentation/i18n.sgml
+++ /dev/null
@@ -1,66 +0,0 @@
-
- Internationalization
-
-
- Adding New Languages
-
-
- 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.
-
-
-
- Language dependent resources reside in files
- named somefile_Xx.rc or
- Xx.rc, where Xx
- is your language abbreviation (look for it in
- include/winnls.h). These are included
- in a master file named somefile.rc or
- rsrc.rc, located in the same
- directory as the language files.
-
-
-
- To add a new language to one of these resources you
- need to make a copy of the English resource (located
- in the somefile_En.rc file) over to
- your somefile_Xx.rc file, include this
- file in the master somefile.rc 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.
-
-
-
- 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.
-
-
-
- To get a list of the files that need translating,
- run the following command in the root of your Wine tree:
- find -name "*En.rc".
-
-
-
- When adding a new language, also make sure the parameters
- defined in ./dlls/kernel/nls/*.nls
- fit your local habits and language.
-
-
-
-
-
diff --git a/documentation/implementation.sgml b/documentation/implementation.sgml
deleted file mode 100644
index e190f53b80..0000000000
--- a/documentation/implementation.sgml
+++ /dev/null
@@ -1,608 +0,0 @@
-
- Low-level Implementation
- Details of Wine's Low-level Implementation...
-
-
-Keyboard
-
-
-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.
-
-
-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.
-
-
-To do this, open the file
-dlls/x11drv/keyboard.c and take a look
-at the existing tables. Make a backup copy of it, especially
-if you don't use CVS.
-
-
-What you really would need to do, is find out which scancode
-each key needs to generate. Find it in the
-main_key_scan table, which looks like
-this:
-
-
-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) */
-};
-
-
-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
-keyboard.c. It also shows that if there
-is no 102nd key, you can skip that.
-
-
-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
-main_key_scan, 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 Z), must be placed on a separate
-line after the last line.
-
-
-For example, my Norwegian keyboard looks like this
-
-
-§ ! " # ¤ % & / ( ) = ? ` 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
-
-
-Note the 102nd key, which is the <> key, to
-the left of Z. The character to the right of
-the main character is the character generated by
-AltGr.
-
-
-This keyboard is defined as follows:
-
-
-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",",;",".:","-_",
-"<>"
-};
-
-
-Except that " and \ needs to be quoted with a backslash, and
-that the 102nd key is on a separate line, it's pretty
-straightforward.
-
-
-After you have written such a table, you need to add it to the
-main_key_tab[] layout index table. This
-will look like this:
-
-
-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},
-...
-
-
-After you have added your table, recompile Wine and test that
-it works. If it fails to detect your table, try running
-
-
-WINEDEBUG=+key,+keyboard wine > key.log 2>&1
-
-
- and look in the resulting key.log file to
- find the error messages it gives for your layout.
-
-
- Note that the LANG_* and
- SUBLANG_* definitions are in
- include/winnls.h, 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
- (SUBLANG * 0x400 + LANG), so, for example
- the combination LANG_NORWEGIAN (0x14) and
- SUBLANG_DEFAULT (0x1) will be (in hex)
- 14 + 1*400 = 414, so since I'm Norwegian, I
- could look for 0414 in the WINEDEBUG output
- to find out why my keyboard won't detect.
-
-
- Once it works, submit it to the Wine project. If you use CVS,
- you will just have to do
-
-
-cvs -z3 diff -u dlls/x11drv/keyboard.c > layout.diff
-
-
- from your main Wine directory, then submit
- layout.diff to
- wine-patches@winehq.org along with a brief note
- of what it is.
-
-
- If you don't use CVS, you need to do
-
-
-diff -u the_backup_file_you_made dlls/x11drv/keyboard.c > layout.diff
-
-
- and submit it as explained above.
-
-
- 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.
-
-
-
-
-
- Undocumented APIs
-
-
- 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
- esp register, points to the last valid entry;
- thus, the operation of pushing a value onto the stack involves
- decrementing esp and then moving the value into
- the memory pointed to by esp
- (i.e., push p in assembly resembles
- *(--esp) = p; in C). Removing (popping)
- values off the stack is the reverse (i.e., pop p
- corresponds to p = *(esp++); in C).
-
-
-
- In the stdcall calling convention, arguments are
- pushed onto the stack right-to-left. For example, the C call
- myfunction(40, 20, 70, 30); is expressed in
- Intel assembly as:
-
- push 30
- push 70
- push 20
- push 40
- call myfunction
-
- The called function is responsible for removing the arguments
- off the stack. Thus, before the call to myfunction, the
- stack would look like:
-
- [local variable or temporary]
- [local variable or temporary]
- 30
- 70
- 20
- esp -> 40
-
- After the call returns, it should look like:
-
- [local variable or temporary]
- esp -> [local variable or temporary]
-
-
-
-
- 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.
-
-
-
- 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.
-
-
-
- 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 (ntdll.dll) 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.
-
-
-
- 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, ret hhll (where
- hhll is the number of bytes to remove, i.e. the
- number of arguments times 4), contains the bytes
- 0xc2 ll hh in memory. It is a reasonable
- assumption that few, if any, functions take more than 16 arguments;
- therefore, simply searching for
- hh == 0 && ll < 0x40 starting from the
- address of a function yields the correct number of arguments most
- of the time.
-
-
-
- Of course, this is not without errors. ret 00ll
- is not the only instruction that can have the byte sequence
- 0xc2 ll 0x0; for example,
- push 0x000040c2 has the byte sequence
- 0x68 0xc2 0x40 0x0 0x0, 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.
-
-
-
- Much more troublesome is the non-linear flow of a function. For
- example, consider the following two functions:
-
- somefunction1:
- jmp somefunction1_impl
-
- somefunction2:
- ret 0004
-
- somefunction1_impl:
- ret 0008
-
- In this case, we would incorrectly detect both
- somefunction1 and
- somefunction2 as taking only a single
- argument, whereas somefunction1 really
- takes two arguments.
-
-
-
- With these limitations in mind, it is possible to implement more stubs
- in Wine and, eventually, the functions themselves.
-
-
-
-
- Accelerators
-
-
- There are three differently sized
- accelerator structures exposed to the user:
-
-
-
-
- Accelerators in NE resources. This is also the internal
- layout of the global handle HACCEL (16 and
- 32) in Windows 95 and Wine. Exposed to the user as Win16
- global handles HACCEL16 and
- HACCEL32 by the Win16/Win32 API.
- These are 5 bytes long, with no padding:
-
-BYTE fVirt;
-WORD key;
-WORD cmd;
-
-
-
-
-
- Accelerators in PE resources. They are exposed to the user
- only by direct accessing PE resources.
- These have a size of 8 bytes:
-
-
-BYTE fVirt;
-BYTE pad0;
-WORD key;
-WORD cmd;
-WORD pad1;
-
-
-
-
- Accelerators in the Win32 API. These are exposed to the
- user by the CopyAcceleratorTable
- and CreateAcceleratorTable functions
- in the Win32 API.
- These have a size of 6 bytes:
-
-
-BYTE fVirt;
-BYTE pad0;
-WORD key;
-WORD cmd;
-
-
-
-
-
- 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 ACCEL
- is defined using #pragma(2) for the
- compiler but without any packing for RC, so it will assume
- #pragma(4).
-
-
-
-
-
- Doing A Hardware Trace
-
-
- 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.
-
-
- 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.
-
-
- 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 config
- (usually in ~/.wine/) and in the
- ports section add the following two lines
-
-
-read=0x378,0x379,0x37a,0x37c,0x77a
-write=0x378,x379,0x37a,0x37c,0x77a
-
-
- 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.
-
-
- When starting wine use the following command line, where
- XXXX is the program you need to run in
- order to access your scanner, and YYYY is
- the file your trace will be stored in:
-
-
-WINEDEBUG=+io wine XXXX 2> >(sed 's/^[^:]*:io:[^ ]* //' > YYYY)
-
-
- 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.
-
-
- You will need to postprocess the output into a more manageable
- format, using the shrink program. First
- you need to compile the source (which is located at the end of
- this section):
-
-cc shrink.c -o shrink
-
-
-
- Use the shrink program to reduce the
- physical size of the raw log as follows:
-
-
-cat log | shrink > log2
-
-
- The trace has the basic form of
-
-
-XXXX > YY @ ZZZZ:ZZZZ
-
-
- where XXXX is the port in hexadecimal being
- accessed, YY is the data written (or read)
- from the port, and ZZZZ:ZZZZ 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.
-
-
-> data was written to the port
-< data was read from the port
-
-
- 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
-
-
-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
-
-
- As you can see there is a repeating structure starting at
- address 0297:01ec 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 0x05 to the control
- port, then a value which always seems to
- 0x8f is read from the status port at which
- point a byte 0x04 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.
-
-
-#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;
-}
-
-
- 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.
-
-
- 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)
-
-
-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
-
-
- From this it is easy to see that put
- 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.
-
-
-
- The following is the shrink.c program:
-
-/* 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;
-}
-
-
-
-
-
-
-
diff --git a/documentation/porting.sgml b/documentation/porting.sgml
deleted file mode 100644
index a7326702e5..0000000000
--- a/documentation/porting.sgml
+++ /dev/null
@@ -1,219 +0,0 @@
-
- Porting Wine to new Platforms
-
- This document provides a few tips on porting Wine to your
- favorite (UNIX-based) operating system.
-
-
-
- Porting Wine to new Platforms
-
- Why #ifdef MyOS is probably a mistake.
-
-
- Operating systems change. Maybe yours doesn't have the
- foo.h header, but maybe a future
- version will have it. If you want to #include
- <foo.h>, it doesn't matter what operating
- system you are using; it only matters whether
- foo.h is there.
-
-
- Furthermore, operating systems change names or "fork" into
- several ones. An #ifdef MyOs will break
- over time.
-
-
- If you use the feature of autoconf -- the
- Gnu auto-configuration utility -- wisely, you will help
- future porters automatically because your changes will test
- for features, not names of operating
- systems. A feature can be many things:
-
-
-
-
-
- existence of a header file
-
-
-
-
- existence of a library function
-
-
-
-
- existence of libraries
-
-
-
-
- bugs in header files, library functions, the compiler, ...
-
-
-
-
- You will need Gnu Autoconf, which you can get from your
- friendly Gnu mirror. This program takes Wine's
- configure.ac file and produces a
- configure shell script that users use
- to configure Wine to their system.
-
-
- There are exceptions to the "avoid
- #ifdef MyOS" 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
- autoconf's HAVE_*
- symbols in Wine's headers, as these may be used by Winelib
- users who may not be using a configure
- script.
-
-
- Let's now turn to specific porting problems and how to solve
- them.
-
-
-
-
- MyOS doesn't have the foo.h header!
-
-
- This first step is to make autoconf check
- for this header. In configure.in you
- add a segment like this in the section that checks for
- header files (search for "header files"):
-
-
-AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
-
-
- If your operating system supports a header file with the
- same contents but a different name, say
- bar.h, add a check for that also.
-
-
- Now you can change
-
-
-#include <foo.h>
-
-
- to
-
-
-#ifdef HAVE_FOO_H
-#include <foo.h>
-#elif defined (HAVE_BAR_H)
-#include <bar.h>
-#endif
-
-
- 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 #else section to the
- conditional. Avoid this if you can.
-
-
- You will also need to add #undef HAVE_FOO_H
- (etc.) to include/config.h.in
-
-
- Finish up with make configure and
- ./configure.
-
-
-
-
- MyOS doesn't have the bar function!
-
-
- A typical example of this is the
- memmove function. To solve this
- problem you would add memmove to the
- list of functions that autoconf checks
- for. In configure.in you search for
- AC_CHECK_FUNCS and add
- memmove. (You will notice that someone
- already did this for this particular function.)
-
-
- Secondly, you will also need to add #undef
- HAVE_BAR to
- include/config.h.in
-
-
- The next step depends on the nature of the missing function.
-
-
-
-
- Case 1:
-
-
- It's easy to write a complete implementation of the
- function. (memmove belongs to
- this case.)
-
-
- You add your implementation in
- misc/port.c surrounded by
- #ifndef HAVE_MEMMOVE and
- #endif.
-
-
- You might have to add a prototype for your function.
- If so, include/miscemu.h might be the place. Don't
- forget to protect that definition by #ifndef
- HAVE_MEMMOVE and #endif also!
-
-
-
-
- Case 2:
-
-
- A general implementation is hard, but Wine is only
- using a special case.
-
-
- An example is the various wait
- calls used in SIGNAL_child from
- loader/signal.c. Here we have a
- multi-branch case on features:
-
-
-#ifdef HAVE_THIS
-...
-#elif defined (HAVE_THAT)
-...
-#elif defined (HAVE_SOMETHING_ELSE)
-...
-#endif
-
-
- 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.
-
-
-
-
-
- Finish up with make configure and
- ./configure.
-
-
-
-
-
-
-
-
diff --git a/documentation/wine-devel.sgml b/documentation/wine-devel.sgml
index 8217b98d6b..c8243a8762 100644
--- a/documentation/wine-devel.sgml
+++ b/documentation/wine-devel.sgml
@@ -1,24 +1,20 @@
-
-
+
+
+
-
+
-
+
+
+
-
-
-
-
-
-
-
]>
@@ -114,31 +110,23 @@
Developing Wine
&debugger;
- &documentation;
- &patches;
+ &debugging;
+ &otherdebug;
+ &codingpractice;
&testing;
- &i18n;
+ &documentation;
Wine Architecture
&architecture;
- &debugging;
+ &kernel;
+ &graphical;
+ &windowing;
&ole;
&opengl;
&ddraw;
&multimedia;
- &threading;
-
-
- Advanced Topics
- &implementation;
- &porting;
- &consoles;
- &address-space;
- &cvs-regression;
-
-
diff --git a/documentation/winedev-coding.sgml b/documentation/winedev-coding.sgml
new file mode 100644
index 0000000000..e8f80cd2cc
--- /dev/null
+++ b/documentation/winedev-coding.sgml
@@ -0,0 +1,514 @@
+
+ Coding Practice
+
+
+ This chapter describes the relevant coding practices in Wine,
+ that you should be aware of before doing any serious development
+ in Wine.
+
+
+ Patch Format
+
+
+ Patches are submitted via email to the Wine patches mailing
+ list, wine-patches@winehq.org. Your patch
+ should include:
+
+
+
+
+
+ A meaningful subject (very short description of patch)
+
+
+
+
+ A long (paragraph) description of what was wrong and what
+ is now better. (recommended)
+
+
+
+
+ A change log entry (short description of what was
+ changed).
+
+
+
+
+ The patch in diff -u format
+
+
+
+
+
+
+
+ cvs diff -u works great for the common case
+ where a file is edited. However, if you add or remove a file
+ cvs diff will not report that correctly so
+ make sure you explicitly take care of this rare case.
+
+
+ For additions simply include them by appending the
+ diff -u /dev/null /my/new/file output of
+ them to any cvs diff -u output you may
+ have. Alternatively, use diff -Nu olddir/
+ newdir/ in case of multiple new files to add.
+
+
+ For removals, clearly list the files in the description of the
+ patch.
+
+
+ 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 diff -u against
+ the old file. I.E.
+
+
+diff -u file.old file.c > file.txt
+
+
+
+
+ Some notes about style
+
+
+ There are a few conventions that about coding style that have
+ been adopted over the years of development. The rational for
+ these rules is explained for each one.
+
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+
+ Tabs are not forbidden but discouraged. A tab is defined
+ as 8 characters and the usual amount of indentation is 4
+ characters.
+
+
+
+
+ C++ style comments are discouraged since some compilers
+ choke on them.
+
+
+
+
+ Commenting out a block of code is usually done by
+ enclosing it in #if 0 ... #endif
+ Statements. For example.
+
+
+/* note about reason for commenting block */
+#if 0
+code
+code /* comments */
+code
+#endif
+
+
+ The reason for using this method is that it does not
+ require that you edit comments that may be inside the
+ block of code.
+
+
+
+
+ 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.
+
+
+
+
+ Code is usually limited to 80 columns. This helps prevent
+ mailers mangling patches by line wrap. Also it generally
+ makes code easier to read.
+
+
+
+
+ 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.
+
+
+
+
+ Inline attachments with Outlook Express
+
+ Outlook Express is notorious for mangling
+ attachments. Giving the patch a .txt
+ extension and attaching will solve the problem for most
+ mailers including Outlook. Also, there is a way to enable
+ Outlook Express send .diff
+ attachments.
+
+
+ You need following two things to make it work.
+
+
+
+
+ Make sure that .diff 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.
+
+
+
+
+ Using regedit add key "Content Type"
+ with value "text/plain" to the
+ .diff extension under
+ HKEY_CLASSES_ROOT (same as for .txt
+ extension). This tells OE to use
+ Content-Type: text/plain instead of
+ application/octet-stream.
+
+
+
+
+ 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.
+
+
+
+ Alexandre's Bottom Line
+
+ The basic rules are: no attachments, no MIME crap, no
+ line wrapping, a single patch per mail. Basically if I can't
+ do "cat raw_mail | patch -p0" it's in the
+ wrong format.
+
+
+
+
+
+ Quality Assurance
+
+
+ (Or, "How do I get Alexandre to apply my patch quickly so I
+ can build on it and it will not go stale?")
+
+
+ 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! cvs update is your
+ friend!
+
+
+ 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 make test. You may
+ need to run make testclean to undo the results
+ of a previous test run. See the testing guide for
+ more details on Wine's conformance tests.
+
+
+
+
+ Porting Wine to new Platforms
+
+ This document provides a few tips on porting Wine to your
+ favorite (UNIX-based) operating system.
+
+
+
+
+ Why #ifdef MyOS is probably a mistake.
+
+
+
+ Operating systems change. Maybe yours doesn't have the
+ foo.h header, but maybe a future
+ version will have it. If you want to #include
+ <foo.h>, it doesn't matter what operating
+ system you are using; it only matters whether
+ foo.h is there.
+
+
+ Furthermore, operating systems change names or "fork" into
+ several ones. An #ifdef MyOs will break
+ over time.
+
+
+ If you use the feature of autoconf -- the
+ Gnu auto-configuration utility -- wisely, you will help
+ future porters automatically because your changes will test
+ for features, not names of operating
+ systems. A feature can be many things:
+
+
+
+
+
+ existence of a header file
+
+
+
+
+ existence of a library function
+
+
+
+
+ existence of libraries
+
+
+
+
+ bugs in header files, library functions, the compiler, ...
+
+
+
+
+ You will need Gnu Autoconf, which you can get from your
+ friendly Gnu mirror. This program takes Wine's
+ configure.ac file and produces a
+ configure shell script that users use
+ to configure Wine to their system.
+
+
+ There are exceptions to the "avoid
+ #ifdef MyOS" 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
+ autoconf's HAVE_*
+ symbols in Wine's headers, as these may be used by Winelib
+ users who may not be using a configure
+ script.
+
+
+ Let's now turn to specific porting problems and how to solve
+ them.
+
+
+
+
+
+ MyOS doesn't have the foo.h header!
+
+
+
+ This first step is to make autoconf check
+ for this header. In configure.in you
+ add a segment like this in the section that checks for
+ header files (search for "header files"):
+
+
+AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
+
+
+ If your operating system supports a header file with the
+ same contents but a different name, say
+ bar.h, add a check for that also.
+
+
+ Now you can change
+
+
+#include <foo.h>
+
+
+ to
+
+
+#ifdef HAVE_FOO_H
+#include <foo.h>
+#elif defined (HAVE_BAR_H)
+#include <bar.h>
+#endif
+
+
+ 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 #else section to the
+ conditional. Avoid this if you can.
+
+
+ You will also need to add #undef HAVE_FOO_H
+ (etc.) to include/config.h.in
+
+
+ Finish up with make configure and
+ ./configure.
+
+
+
+
+
+ MyOS doesn't have the bar function!
+
+
+
+ A typical example of this is the memmove
+ function. To solve this problem you would add
+ memmove to the list of functions that
+ autoconf checks for. In
+ configure.in you search for
+ AC_CHECK_FUNCS and add
+ memmove. (You will notice that someone
+ already did this for this particular function.)
+
+
+ Secondly, you will also need to add
+ #undef HAVE_BAR to
+ include/config.h.in
+
+
+ The next step depends on the nature of the missing function.
+
+
+
+
+ Case 1:
+
+
+ It's easy to write a complete implementation of the
+ function. (memmove belongs to
+ this case.)
+
+
+ You add your implementation in
+ misc/port.c surrounded by
+ #ifndef HAVE_MEMMOVE and
+ #endif.
+
+
+ You might have to add a prototype for your function.
+ If so, include/miscemu.h might be
+ the place. Don't forget to protect that definition by
+ #ifndef HAVE_MEMMOVE and
+ #endif also!
+
+
+
+
+ Case 2:
+
+
+ A general implementation is hard, but Wine is only
+ using a special case.
+
+
+ An example is the various wait
+ calls used in SIGNAL_child from
+ loader/signal.c. Here we have a
+ multi-branch case on features:
+
+
+#ifdef HAVE_THIS
+...
+#elif defined (HAVE_THAT)
+...
+#elif defined (HAVE_SOMETHING_ELSE)
+...
+#endif
+
+
+ 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.
+
+
+
+
+
+ Finish up with make configure and
+ ./configure.
+
+
+
+
+
+ Adding New Languages
+
+
+ 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.
+
+
+
+ Language dependent resources reside in files
+ named somefile_Xx.rc or
+ Xx.rc, where Xx
+ is your language abbreviation (look for it in
+ include/winnls.h). These are included
+ in a master file named somefile.rc or
+ rsrc.rc, located in the same
+ directory as the language files.
+
+
+
+ To add a new language to one of these resources you
+ need to make a copy of the English resource (located
+ in the somefile_En.rc file) over to
+ your somefile_Xx.rc file, include this
+ file in the master somefile.rc 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.
+
+
+
+ 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.
+
+
+
+ To get a list of the files that need translating,
+ run the following command in the root of your Wine tree:
+ find -name "*En.rc".
+
+
+
+ When adding a new language, also make sure the parameters
+ defined in ./dlls/kernel/nls/*.nls
+ fit your local habits and language.
+
+
+
+
+
diff --git a/documentation/winedev-graphical.sgml b/documentation/winedev-graphical.sgml
new file mode 100644
index 0000000000..72c3a04ebb
--- /dev/null
+++ b/documentation/winedev-graphical.sgml
@@ -0,0 +1,40 @@
+
+ Graphical modules
+
+ GDI Module
+
+
+ X Windows System interface
+
+
+ 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 XInitThreads()). However,
+ Wine does not use this approach. Instead Wine performs its
+ own synchronization using the
+ wine_tsx11_lock() / wine_tsx11_unlock()
+ functions. This locking protects library access
+ with a critical section, and also arranges things so that
+ X libraries compiled without
+ (eg. with global errno variable) will
+ work with Wine.
+
+
+ In the past, all calls to X used to go through a wrapper called
+ TSX...() (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.
+
+
+
+
+
+
diff --git a/documentation/winedev-kernel.sgml b/documentation/winedev-kernel.sgml
new file mode 100644
index 0000000000..700835f97f
--- /dev/null
+++ b/documentation/winedev-kernel.sgml
@@ -0,0 +1,823 @@
+
+ Kernel modules
+
+ 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.
+
+
+ NTDLL
+
+ NTDLL provides most of the services you'd expect from a
+ kernel.
+
+
+ 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.
+
+
+ Wine also provide fibers (which is the Windows name of
+ co-routines).
+
+
+ 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).
+
+
+
+ File management
+
+ 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.
+
+
+ File handles can be waitable objects, as Windows define
+ them.
+
+
+ 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).
+
+
+ FIXME: this should be enhanced and updated to latest work
+ on FS.
+
+
+
+
+ Synchronization
+
+ 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.
+
+
+
+
+ Module (DLL) loading
+
+ Wine is able to load any NE and PE module. In all cases,
+ the module's binary code is directly executed by the
+ processor.
+
+
+
+
+ Device management
+
+ Wine allows usage a wide variety of devices:
+
+
+
+ Communication ports are mapped to Unix
+ communication ports (if they have sufficient
+ permissions).
+
+
+
+
+ Parallel ports are mapped to Unix parallel ports (if
+ they have sufficient permissions).
+
+
+
+
+ CDROM: the Windows device I/O control calls are
+ mapped onto Unix ioctl().
+
+
+
+
+ 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.
+
+
+ Wine will not support native VxD.
+
+
+
+
+
+
+ Multi-threading in Wine
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ Threading support in Win32
+
+
+ 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.
+
+
+
+ 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!
+
+
+
+ Win32 provides many different ways you can make your code
+ thread safe however the most common are critical
+ section and the interlocked
+ functions. 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
+ EnterCriticalSection and
+ LeaveCriticalSection. The first call
+ to EnterCriticalSection 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
+ LeaveCriticalSection again.
+
+
+
+ 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:
+
+
+
+if (res != ERROR_SUCCESS) return res;
+
+
+
+ is extremely suspect in a function that also contains a
+ call to EnterCriticalSection. Be
+ careful.
+
+
+
+ If a thread blocks while waiting for another thread to
+ leave a critical section, you will see an error from the
+ RtlpWaitForCriticalSection 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
+ LeaveCriticalSection, 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.
+
+
+
+ Another popular mechanism available is the use of
+ functions like InterlockedIncrement
+ and InterlockedExchange. 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.
+
+
+
+ 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 TlsAlloc
+ 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.
+
+
+
+
+ SysLevels
+
+
+ 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.
+
+
+
+ When entering a syslevel, the code (in
+ dlls/kernel/syslevel.c) 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.
+
+
+
+ Throughout the code you may see calls to
+ _ConfirmSysLevel() and
+ _CheckNotSysLevel(). 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,
+ _CheckNotSysLevel() 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.
+
+
+
+
+
+ POSIX threading vs kernel threading
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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 clone(2) syscall. Pthreads
+ provides a nicer (more portable) interface to this
+ functionality and also provides APIs for controlling
+ mutexes. There is a
+ good tutorial on pthreads available if you want
+ to learn more.
+
+
+
+ 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 clone
+ 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.
+
+
+
+ The solution was simple yet ingenius: Wine would provide
+ its own implementation of the pthread library
+ inside 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.
+
+
+
+ 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.
+
+
+
+ The fake pthread implementation can be found in
+ loader/kthread.c, 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.
+
+
+
+ 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.
+
+
+
+ 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
+ loader/kthread.c and
+ loader/pthread.c 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.
+
+
+
+ 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.
+
+
+
+
+ The Win32 thread environment
+
+
+ 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.
+
+
+
+ The first thing Win32 code requires is the
+ TEB 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
+ include/thread.h, 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.
+
+
+
+ A pointer to the TEB is stored in the %fs register and can
+ be accessed using NtCurrentTeb() 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
+ lib/wine/ldt.c.
+
+
+
+ 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:
+
+
+ movl %esp, %fs:0
+
+
+ ... 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.
+
+
+
+ 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).
+
+
+
+
+
+
+ KERNEL Module
+
+
+ FIXME: Needs some content...
+
+
+ Consoles in Wine
+
+ 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.
+
+
+ The following table describes the main implementation
+ differences between the three approaches.
+
+ Function consoles implementation comparison
+
+
+
+ Function
+ Bare streams
+ Wineconsole & user backend
+ Wineconsole & curses backend
+
+
+
+
+
+ Console as a Win32 Object (and associated
+ handles)
+
+
+ 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
+ (GetConsoleMode /
+ SetConsoleMode) are not
+ supported.
+
+
+ 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.
+
+
+ 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.
+
+
+
+
+ Inheritance (including handling in
+ CreateProcess of
+ CREATE_DETACHED,
+ CREATE_NEW_CONSOLE flags).
+
+
+ Not supported. Every process child of a process
+ will inherit the Unix streams, so will also
+ inherit the Win32 standard streams.
+
+
+ Fully supported (each new console creation will
+ be handled by the creation of a new USER32
+ window)
+
+
+ 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.
+
+
+
+
+ ReadFile /
+ WriteFile
+ operations
+
+ Fully supported
+ Fully supported
+ Fully supported
+
+
+
+ Screen-buffer manipulation (creation, deletion,
+ resizing...)
+
+ Not supported
+ Fully supported
+
+ Partly supported (this won't work too well as we
+ don't control (so far) the size of underlying
+ Unix terminal
+
+
+
+
+ APIs for reading/writing screen-buffer content,
+ cursor position
+
+ Not supported
+ Fully supported
+ Fully supported
+
+
+
+ APIs for manipulating the rendering window size
+
+ Not supported
+ Fully supported
+
+ Partly supported (this won't work too well as we
+ don't control (so far) the size of underlying
+ Unix terminal
+
+
+
+
+ Signaling (in particular, Ctrl-C handling)
+
+
+ Nothing is done, which means that Ctrl-C will
+ generate (as usual) a
+ SIGINT which will terminate
+ the program.
+
+
+ Partly supported (Ctrl-C behaves as expected,
+ however the other Win32 CUI signaling isn't
+ properly implemented).
+
+
+ Partly supported (Ctrl-C behaves as expected,
+ however the other Win32 CUI signaling isn't
+ properly implemented).
+
+
+
+
+
+
+
+
+ The Win32 objects behind a console can be created in
+ several occasions:
+
+
+
+ When the program is started from wineconsole, a new
+ console object is created and will be used
+ (inherited) by the process launched from
+ wineconsole.
+
+
+
+
+ When a program, which isn't attached to a console,
+ calls AllocConsole, 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.
+
+
+
+
+
+ Please also note, that starting a child process with the
+ CREATE_NEW_CONSOLE flag, will end-up
+ calling AllocConsole in the child
+ process, hence creating a wineconsole with the USER32
+ backend.
+
+
+
+
+
+
+ The Wine initialization process
+
+
+ Wine has a rather complex startup procedure, so unlike many
+ programs the best place to begin exploring the code-base is
+ not in fact at the
+ main() function but instead at some of the
+ more straightforward DLLs that exist on the periphery such as
+ MSI, the widget library (in USER and COMCTL32) etc. The purpose
+ of this section is to document and explain how Wine starts up
+ from the moment the user runs "wine myprogram.exe" to the point
+ at which myprogram gets control.
+
+
+
+ First Steps
+
+
+ The actual wine binary that the user runs does not do very much, in fact it is only
+ responsible for checking the threading model in use (NPTL vs LinuxThreads) and then invoking
+ a new binary which performs the next stage in the startup sequence. See the threading chapter
+ for more information on this check and why it's necessary. You can find this code in
+ loader/glibc.c. The result of this check is an exec of either
+ wine-pthread or wine-kthread, potentially (on Linux) via
+ the preloader. We need to use separate binaries here because overriding
+ the native pthreads library requires us to exploit a property of ELF symbol fixup semantics:
+ it's not possible to do this without starting a new process.
+
+
+
+ The Wine preloader is found in loader/preloader.c, and is required in
+ order to impose a Win32 style address space layout upon the newly created Win32 process. The
+ details of what this does is covered in the address space layout chapter. The preloader is a
+ statically linked ELF binary which is passed the name of the actual Wine binary to run (either
+ wine-kthread or wine-pthread) along with the arguments the user passed in from the command
+ line. The preloader is an unusual program: it does not have a main() function. In standard ELF
+ applications, the entry point is actually at a symbol named _start: this is provided by the
+ standard gcc infrastructure and normally jumps to __libc_start_main which
+ initializes glibc before passing control to the main function as defined by the programmer.
+
+
+
+ The preloader takes control direct from the entry point for a few reasons. Firstly, it is
+ required that glibc is not initialized twice: the result of such behaviour is undefined and
+ subject to change without notice. Secondly, it's possible that as part of initializing glibc,
+ the address space layout could be changed - for instance, any call to malloc will initialize a
+ heap arena which modifies the VM mappings. Finally, glibc does not return to _start at any
+ point, so by reusing it we avoid the need to recreate the ELF bootstrap stack (env, argv,
+ auxiliary array etc).
+
+
+
+ The preloader is responsible for two things: protecting important regions of the address
+ space so the dynamic linker does not map shared libraries into them, and once that is done
+ loading the real Wine binary off disk, linking it and starting it up. Normally all this is
+ done automatically by glibc and the kernel but as we intercepted this process by using a
+ static binary it's up to us to restart the process. The bulk of the code in the preloader is
+ about loading wine-[pk]thread and ld-linux.so.2 off disk, linking them together, then
+ starting the dynamic linking process.
+
+
+
+ One of the last things the preloader does before jumping into the dynamic linker is scan the
+ symbol table of the loaded Wine binary and set the value of a global variable directly: this
+ is a more efficient way of passing information to the main Wine program than flattening the
+ data structures into an environment variable or command line parameter then unpacking it on
+ the other side, but it achieves pretty much the same thing. The global variable set points to
+ the preload descriptor table, which contains the VMA regions protected by the preloader. This
+ allows Wine to unmap them once the dynamic linker has been run, so leaving gaps we can
+ initialize properly later on.
+
+
+
+
+
+ Starting the emulator
+
+
+ The process of starting up the emulator itself is mostly one of chaining through various
+ initializer functions defined in the core libraries and DLLs: libwine, then NTDLL, then kernel32.
+
+
+
+ Both the wine-pthread and wine-kthread binaries share a common main
+ function, defined in loader/main.c, so no matter which binary is selected
+ after the preloader has run we start here. This passes the information provided by the
+ preloader into libwine and then calls wine_init, defined
+ in libs/wine/loader.c. This is where the emulation really starts:
+ wine_init can, with the correct preparation,
+ be called from programs other than the wine loader itself.
+
+
+
+ wine_init does some very basic setup tasks such as initializing the
+ debugging infrastructure, yet more address space manipulation (see the information on the
+ 4G/4G VM split in the address space chapter), before loading NTDLL - the core of both Wine and
+ the Windows NT series - and jumping to the __wine_process_init function defined
+ in dlls/ntdll/loader.c
+
+
+
+ This function is responsible for initializing the primary Win32 environment. In thread_init(),
+ it sets up the TEB, the wineserver connection for the main thread and the process heap. See
+ the threading chapter for more information on this.
+
+
+
+ Finally, it loads and jumps to __wine_kernel_init in kernel32.dll: this
+ is defined in dlls/kernel32/process.c. This is where the bulk of the work
+ is done. The kernel32 initialization code retrieves the startup info for the process from the
+ server, initializes the registry, sets up the drive mapping system and locale data, then
+ begins loading the requested application itself. Each process has a STARTUPINFO block that can
+ be passed into CreateProcess specifying various things like how the first
+ window should be displayed: this is sent to the new process via the wineserver.
+
+
+
+ After determining the type of file given to Wine by the user (a Win32 EXE file, a Win16 EXE, a
+ Winelib app etc), the program is loaded into memory (which may involve loading and
+ initializing other DLLs, the bulk of Wines startup code), before control reaches the end of
+ __wine_kernel_init. This function ends with the new process stack being
+ initialized, and start_process being called on the new stack. Nearly there!
+
+
+
+ The final element of initializing Wine is starting the newly loaded program
+ itself. start_process sets up the SEH backstop handler, calls
+ LdrInitializeThunk which performs the last part of the process
+ initialization (such as performing relocations and calling the DllMains with PROCESS_ATTACH),
+ grabs the entry point of the executable and then on this line:
+
+
+
+ExitProcess( entry( peb ) );
+
+
+
+ ... jumps to the entry point of the program. At this point the users program is running and
+ the API provided by Wine is ready to be used. When entry returns,
+ the ExitProcess API will be used to initialize a graceful shutdown.
+
+
+
+
+
+
diff --git a/documentation/winedev-otherdebug.sgml b/documentation/winedev-otherdebug.sgml
new file mode 100644
index 0000000000..da501c4eb1
--- /dev/null
+++ b/documentation/winedev-otherdebug.sgml
@@ -0,0 +1,508 @@
+
+ Other debugging techniques
+
+ Doing A Hardware Trace
+
+
+ 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.
+
+
+ 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.
+
+
+ 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 config
+ (usually in ~/.wine/) and in the
+ ports section add the following two lines
+
+
+read=0x378,0x379,0x37a,0x37c,0x77a
+write=0x378,x379,0x37a,0x37c,0x77a
+
+
+ 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.
+
+
+ When starting wine use the following command line, where
+ XXXX is the program you need to run in
+ order to access your scanner, and YYYY is
+ the file your trace will be stored in:
+
+
+WINEDEBUG=+io wine XXXX 2> >(sed 's/^[^:]*:io:[^ ]* //' > YYYY)
+
+
+ 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.
+
+
+ You will need to postprocess the output into a more manageable
+ format, using the shrink program. First
+ you need to compile the source (which is located at the end of
+ this section):
+
+cc shrink.c -o shrink
+
+
+
+ Use the shrink program to reduce the
+ physical size of the raw log as follows:
+
+
+cat log | shrink > log2
+
+
+ The trace has the basic form of
+
+
+XXXX > YY @ ZZZZ:ZZZZ
+
+
+ where XXXX is the port in hexadecimal being
+ accessed, YY is the data written (or read)
+ from the port, and ZZZZ:ZZZZ 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.
+
+
+> data was written to the port
+< data was read from the port
+
+
+ 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
+
+
+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
+
+
+ As you can see there is a repeating structure starting at
+ address 0297:01ec 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 0x05 to the control
+ port, then a value which always seems to
+ 0x8f is read from the status port at which
+ point a byte 0x04 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.
+
+
+#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;
+}
+
+
+ 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.
+
+
+ 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)
+
+
+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
+
+
+ From this it is easy to see that put
+ 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.
+
+
+
+ The following is the shrink.c program:
+
+/* 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;
+}
+
+
+
+
+
+ Understanding undocumented APIs
+
+
+ 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
+ esp register, points to the last valid entry;
+ thus, the operation of pushing a value onto the stack involves
+ decrementing esp and then moving the value into
+ the memory pointed to by esp
+ (i.e., push p in assembly resembles
+ *(--esp) = p; in C). Removing (popping)
+ values off the stack is the reverse (i.e., pop p
+ corresponds to p = *(esp++); in C).
+
+
+
+ In the stdcall calling convention, arguments are
+ pushed onto the stack right-to-left. For example, the C call
+ myfunction(40, 20, 70, 30); is expressed in
+ Intel assembly as:
+
+ push 30
+ push 70
+ push 20
+ push 40
+ call myfunction
+
+ The called function is responsible for removing the arguments
+ off the stack. Thus, before the call to myfunction, the
+ stack would look like:
+
+ [local variable or temporary]
+ [local variable or temporary]
+ 30
+ 70
+ 20
+ esp -> 40
+
+ After the call returns, it should look like:
+
+ [local variable or temporary]
+ esp -> [local variable or temporary]
+
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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 (ntdll.dll) 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.
+
+
+
+ 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, ret hhll (where
+ hhll is the number of bytes to remove, i.e. the
+ number of arguments times 4), contains the bytes
+ 0xc2 ll hh in memory. It is a reasonable
+ assumption that few, if any, functions take more than 16 arguments;
+ therefore, simply searching for
+ hh == 0 && ll < 0x40 starting from the
+ address of a function yields the correct number of arguments most
+ of the time.
+
+
+
+ Of course, this is not without errors. ret 00ll
+ is not the only instruction that can have the byte sequence
+ 0xc2 ll 0x0; for example,
+ push 0x000040c2 has the byte sequence
+ 0x68 0xc2 0x40 0x0 0x0, 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.
+
+
+
+ Much more troublesome is the non-linear flow of a function. For
+ example, consider the following two functions:
+
+ somefunction1:
+ jmp somefunction1_impl
+
+ somefunction2:
+ ret 0004
+
+ somefunction1_impl:
+ ret 0008
+
+ In this case, we would incorrectly detect both
+ somefunction1 and
+ somefunction2 as taking only a single
+ argument, whereas somefunction1 really
+ takes two arguments.
+
+
+
+ With these limitations in mind, it is possible to implement
+ more stubs
+ in Wine and, eventually, the functions themselves.
+
+
+
+ How to do regression testing using CVS
+
+
+ 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 NOT for casual users.
+
+
+
+
+
+ Get the full CVS 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).
+
+
+
+
+ untar it into a repository directory:
+
+cd /home/gerard
+tar -zxf full-cvs-2003-08-18.tar.gz
+mv wine repository
+
+
+
+
+
+ extract a new destination directory. This directory must
+ not be in a subdirectory of the repository else
+ cvs will think it's part of the
+ repository and deny you an extraction in the repository:
+
+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
+
+
+
+ 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.
+
+
+ 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.
+
+
+
+
+ you will have now in the ~/wine
+ directory an image of the CVS tree, on the client side.
+ Now update this image to the date you want:
+
+cd /home/gerard/wine
+cvs update -PAd -D "2004-08-23 CDT"
+
+
+
+ The date format is YYYY-MM-DD HH:MM:SS.
+ 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
+
+ http://www.winehq.org/hypermail/wine-cvs
+
+
+ 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:
+
+cvs update: tsx11/ts_xf86dga2.c is no longer in the repository
+
+
+
+ cvs update is not limited to upgrade to
+ a newer version as I have believed for
+ far too long :-(
+
+
+
+
+ Now proceed as for a normal update:
+
+
+./configure
+make depend && make
+
+
+ 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.
+
+
+ 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 make
+ distclean before going back in time, so you
+ have to make everything if you don't backup the older
+ version)
+
+
+ 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:
+
+cvs update -PAd -D "2004-08-23 15:17:25 CDT"
+
+ This will allow you to find easily the exact patch that
+ did it.
+
+
+
+
+ If you find the patch that is the cause of the problem,
+ you have almost won; report about it to
+ Wine Bugzilla
+ 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 :-)
+
+
+
+
+
+
+
+
diff --git a/documentation/winedev-windowing.sgml b/documentation/winedev-windowing.sgml
new file mode 100644
index 0000000000..8d8cccc8d2
--- /dev/null
+++ b/documentation/winedev-windowing.sgml
@@ -0,0 +1,673 @@
+
+ Windowing system
+
+ USER Module
+
+
+ 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 windows/,
+ controls/, and
+ misc/ directories.
+
+
+
+ Windowing subsystem
+
+ windows/win.c
+ windows/winpos.c
+
+ 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 WS_CHILD
+ style bit is set), a pointer to the sibling (returned by
+ GetWindow(..., GW_NEXT)), a pointer
+ to the owner window (set only for popup window if it was
+ created with valid hwndParent
+ parameter), and a pointer to the first child window
+ (GetWindow(.., GW_CHILD)). All popup
+ and non-child windows are therefore placed in the first
+ level of this hierarchy and their ancestor link
+ (wnd->parent) points to the desktop
+ window.
+
+
+ Desktop window - root window
+ | \ `-.
+ | \ `-.
+ popup -> wnd1 -> wnd2 - top level windows
+ | \ `-. `-.
+ | \ `-. `-.
+ child1 child2 -> child3 child4 - child windows
+
+
+ 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).
+
+
+ Another fairly important concept is
+ z-order. 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
+
+
+child1->popup->child2->child3->wnd1->child4->wnd2->desktop.
+
+
+ Current active window ("foreground window" in Win32) is
+ moved to the front of z-order unless its top-level
+ ancestor owns popup windows.
+
+
+ All these issues are dealt with (or supposed to be) in
+ windows/winpos.c with
+ SetWindowPos() being the primary
+ interface to the window manager.
+
+
+ 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, SetWindowPos() should
+ eventually be implemented via
+ Begin/End/DeferWindowPos() calls and
+ not the other way around.
+
+
+
+ Visible region, clipping region and update region
+
+ windows/dce.c
+ windows/winpos.c
+ windows/painting.c
+
+
+ ________________________
+ |_________ | A and B are child windows of C
+ | A |______ |
+ | | | |
+ |---------' | |
+ | | B | |
+ | | | |
+ | `------------' |
+ | C |
+ `------------------------'
+
+
+ Visible region determines which part of the window is
+ not obscured by other windows. If a window has the
+ WS_CLIPCHILDREN style then all
+ areas below its children are considered invisible.
+ Similarly, if the WS_CLIPSIBLINGS
+ 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.
+
+
+ B has a WS_CLIPSIBLINGS style:
+
+
+ . ______
+ : | |
+ | ,-----' |
+ | | B | - visible region of B
+ | | |
+ : `------------'
+
+
+ When the program requests a display
+ context (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.
+
+
+ Program asked for a DC with a clipping region:
+
+
+ ______
+ ,--|--. | . ,--.
+ ,--+--' | | : _: |
+ | | B | | => | | | - DC region where the painting will
+ | | | | | | | be visible
+ `--|-----|---' : `----'
+ `-----'
+
+
+ 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 WM_ERASEBKGND and
+ WM_PAINT messages. In addition,
+ WM_NCPAINT message is sent when the
+ uncovered area intersects a nonclient part of the window.
+ Application must reply to the WM_PAINT
+ message by calling the
+ BeginPaint()/EndPaint()
+ pair of functions. BeginPaint() 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 WM_PAINT until the window
+ manager creates a new update region.
+
+
+ A was moved to the left:
+
+
+ ________________________ ... / C update region
+ |______ | : .___ /
+ | A |_________ | => | ...|___|..
+ | | | | | : | |
+ |------' | | | : '---'
+ | | B | | | : \
+ | | | | : \
+ | `------------' | B update region
+ | C |
+ `------------------------'
+
+
+ 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).
+
+
+
+
+
+ Messaging subsystem
+
+ windows/queue.c
+ windows/message.c
+
+
+ Each Windows task/thread has its own message queue - this
+ is where it gets messages from. Messages can be:
+
+
+
+ generated on the fly (WM_PAINT,
+ WM_NCPAINT,
+ WM_TIMER)
+
+
+
+
+ created by the system (hardware messages)
+
+
+
+
+ posted by other tasks/threads (PostMessage)
+
+
+
+
+ sent by other tasks/threads (SendMessage)
+
+
+
+
+
+ Message priority:
+
+
+ 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
+ windows/message.c.
+
+
+ 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
+ Get/PeekMessage 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 QS_PAINT bit in the
+ owning queue and eventually this window receives a
+ WM_PAINT message
+ (WM_NCPAINT 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 DispatchMessage
+ either calls the callback function or the window
+ procedure. If there are no messages pending the
+ task/thread sleeps until messages appear.
+
+
+ There are several tricky moments (open for discussion) -
+
+
+
+
+
+ System message order has to be honored and messages
+ should be processed within correct task/thread
+ context. Therefore when Get/PeekMessage 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:
+
+
+ by David Charlap
+
+ " Here's the problem in a nutshell, and there is no
+ good solution. Every possible solution creates a
+ different problem.
+
+
+ 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.)
+
+
+ Mouse input events go to the window you click on
+ (unless some window captures the mouse).
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ There are a few solutions to this problem.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+
+ As for the pros and cons:
+
+
+ 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.
+
+
+ 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."
+
+
+ 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."
+
+
+
+
+
+
+ Intertask/interthread
+ SendMessage. 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
+ DirectedYield() function.
+ However, in Win32 there could be several messages
+ pending sent by preemptively executing threads, and in
+ this case SendMessage 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
+ SendMessage.
+
+
+
+
+
+ Accelerators
+
+
+ There are three differently sized
+ accelerator structures exposed to the user:
+
+
+
+
+ Accelerators in NE resources. This is also the internal
+ layout of the global handle HACCEL (16 and
+ 32) in Windows 95 and Wine. Exposed to the user as Win16
+ global handles HACCEL16 and
+ HACCEL32 by the Win16/Win32 API.
+ These are 5 bytes long, with no padding:
+
+BYTE fVirt;
+WORD key;
+WORD cmd;
+
+
+
+
+
+ Accelerators in PE resources. They are exposed to the
+ user only by direct accessing PE resources. These have a
+ size of 8 bytes:
+
+
+BYTE fVirt;
+BYTE pad0;
+WORD key;
+WORD cmd;
+WORD pad1;
+
+
+
+
+ Accelerators in the Win32 API. These are exposed to the
+ user by the CopyAcceleratorTable
+ and CreateAcceleratorTable functions
+ in the Win32 API.
+ These have a size of 6 bytes:
+
+
+BYTE fVirt;
+BYTE pad0;
+WORD key;
+WORD cmd;
+
+
+
+
+
+ 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 ACCEL
+ is defined using #pragma(2) for the
+ compiler but without any packing for RC, so it will assume
+ #pragma(4).
+
+
+
+
+ X Windows System interface
+
+
+ Keyboard mapping
+
+ 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.
+
+
+ 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.
+
+
+ To do this, open the file
+ dlls/x11drv/keyboard.c and take a look
+ at the existing tables. Make a backup copy of it, especially
+ if you don't use CVS.
+
+
+ What you really would need to do, is find out which scancode
+ each key needs to generate. Find it in the
+ main_key_scan table, which looks like
+ this:
+
+
+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) */
+};
+
+
+ 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
+ keyboard.c. It also shows that if there
+ is no 102nd key, you can skip that.
+
+
+ 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
+ main_key_scan, 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 Z), must be placed on a
+ separate line after the last line.
+
+
+ For example, my Norwegian keyboard looks like this
+
+
+§ ! " # ¤ % & / ( ) = ? ` 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
+
+
+ Note the 102nd key, which is the <> key, to
+ the left of Z. The character to the right of
+ the main character is the character generated by
+ AltGr.
+
+
+ This keyboard is defined as follows:
+
+
+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",",;",".:","-_",
+"<>"
+};
+
+
+ Except that " and \ needs to be quoted with a backslash, and
+ that the 102nd key is on a separate line, it's pretty
+ straightforward.
+
+
+ After you have written such a table, you need to add it to the
+ main_key_tab[] layout index table. This
+ will look like this:
+
+
+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},
+...
+
+
+ After you have added your table, recompile Wine and test that
+ it works. If it fails to detect your table, try running
+
+
+WINEDEBUG=+key,+keyboard wine > key.log 2>&1
+
+
+ and look in the resulting key.log file to
+ find the error messages it gives for your layout.
+
+
+ Note that the LANG_* and
+ SUBLANG_* definitions are in
+ include/winnls.h, 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
+ (SUBLANG * 0x400 + LANG), so, for example
+ the combination LANG_NORWEGIAN (0x14) and
+ SUBLANG_DEFAULT (0x1) will be (in hex)
+ 14 + 1*400 = 414, so since I'm Norwegian,
+ I could look for 0414 in the WINEDEBUG
+ output to find out why my keyboard won't detect.
+
+
+
+
+
+