|  | This document should help new developers get started. Like all of Wine, it | 
|  | is a work in progress. | 
|  |  | 
|  |  | 
|  | SOURCE TREE STRUCTURE | 
|  | ===================== | 
|  |  | 
|  | The Wine source tree is loosely based on the original Windows modules. | 
|  | Most of the source is concerned with implementing the Wine API, although | 
|  | there are also various tools, documentation, sample Winelib code, and | 
|  | code specific to the binary loader.  Note that several of the libraries | 
|  | listed here are "stubbed out", meaning they still need to be implemented. | 
|  |  | 
|  | DLLs: | 
|  | ----- | 
|  | dlls/			- All the DLLs implemented by Wine | 
|  |  | 
|  | advapi32/	- Crypto, systeminfo, security, eventlogging | 
|  | avicap32/	- AVI capture window class | 
|  | avifil32/	- COM object to play AVI files | 
|  | cabinet/	- Cabinet file interface | 
|  | comcat/		- Component category manager | 
|  | comctl32/	- Common controls | 
|  | commdlg/	- Common dialog boxes (both 16 & 32 bit) | 
|  | crtdll/		- Old C runtime library | 
|  | crypt32/	- Cryptography | 
|  | d3d8/		- Direct3D (3D graphics) | 
|  | d3dx8/		- Direct3D (3D graphics) | 
|  | dciman32/	- DCI Manager (graphics) | 
|  | ddraw/		- DirectDraw (graphics) | 
|  | devenum/	- Device enumeration | 
|  | dinput/		- DirectInput (device input) | 
|  | dinput8/	- DirectInput (device input) | 
|  | dplay/		- DirectPlay (networking) | 
|  | dplayx/		- DirectPlay (networking) | 
|  | dsound/		- DirectSound (audio) | 
|  | gdi/		- GDI (graphics) | 
|  | enhmetafiledrv/	- Enhanced metafile driver | 
|  | metafiledrv/	- Metafile driver | 
|  | win16drv/	- Support for Win16 printer drivers | 
|  | glu32/		- OpenGL Utility library (graphics) | 
|  | icmp/		- ICMP protocol (networking) | 
|  | imagehlp/	- PE (Portable Executable) Image Helper lib | 
|  | imm32/		- Input Method Manager | 
|  | kernel/		- The Windows kernel | 
|  | lzexpand/	- Lempel-Ziv compression/decompression | 
|  | mapi32/		- Mail interface | 
|  | mpr/		- Multi-Protocol Router (networking) | 
|  | msacm/		- Audio Compression Manager (multimedia) | 
|  | msdmo/		- DirectX Media Objects | 
|  | msimg32/	- Gradient and transparency (graphics) | 
|  | msisys/		- System information | 
|  | msnet32/	- Network interface | 
|  | msrle32/	- Run length encoder | 
|  | msvcrt/		- 16 bit C runtime library | 
|  | msvcrt20/	- 32 bit C runtime library | 
|  | msvideo/	- 16 bit video manager | 
|  | netapi32/	- Network interface | 
|  | ntdll/		- NT implementation of kernel calls | 
|  | odbc32/		- Open DataBase Connectivity driver manager | 
|  | ole32/		- 32 bit OLE 2.0 libraries | 
|  | oleaut32/	- 32 bit OLE 2.0 automation | 
|  | olecli/		- 16 bit OLE client | 
|  | oledlg/		- OLE 2.0 user interface support | 
|  | olepro32/	- 32 bit OLE 2.0 automation | 
|  | olesvr/		- 16 bit OLE server | 
|  | opengl32/	- OpenGL implementation (graphics) | 
|  | psapi/		- Process Status interface | 
|  | qcap/		- DirectShow runtime | 
|  | quartz/		- DirectShow runtime | 
|  | rasapi32/	- Remote Access Server interface | 
|  | richedit/	- Rich text formatting | 
|  | rpcrt4/		- Remote Procedure Call runtime | 
|  | serialui/	- Serial port property pages | 
|  | setupapi/	- Setup interface | 
|  | shdocvw/	- Shell document object and control | 
|  | shfolder/	- Shell folder service | 
|  | shell32/	- COM object implementing shell views | 
|  | shlwapi/	- Shell Light-Weight interface | 
|  | snmpapi/	- SNMP protocol interface (networking) | 
|  | sti/		- Still Image service | 
|  | tapi32/		- Telephone interface | 
|  | ttydrv/		- TTY display driver (Wine specific) | 
|  | twain/		- TWAIN Imaging device communications | 
|  | url/		- Internet shortcut shell extension | 
|  | urlmon/		- URL Moniker allows binding to a URL | 
|  | user/		- Window management, standard controls, etc. | 
|  | version/	- File installation library | 
|  | win32s/		- 32-bit function access for 16-bit systems | 
|  | winaspi/	- 16 bit Advanced SCSI Peripheral Interface | 
|  | winedos/	- DOS features and BIOS calls (interrupts) | 
|  | wineps/		- Postscript driver (Wine specific) | 
|  | wininet/	- Internet extensions | 
|  | winmm/		- Multimedia (16 & 32 bit) | 
|  | mciXXX/   - Various MCI drivers | 
|  | midimap/  - MIDI mapper | 
|  | wavemap/  - Audio mapper | 
|  | winealsa/ - ALSA audio driver | 
|  | winearts/ - aRts audio driver | 
|  | winejack/ - JACK audio server driver | 
|  | wineoss/  - OSS audio driver | 
|  | winnls/		- National Language Support | 
|  | winsock/	- Sockets 2.0 (networking) | 
|  | wsock32/	- Sockets 1.1 (networking) | 
|  | wintab32/	- Tablet device interface | 
|  | winspool/	- Printing & Print Spooler | 
|  | wintrust/	- Trust verification interface | 
|  | wow32/		- WOW subsystem | 
|  | x11drv/		- X11 display driver (Wine specific) | 
|  |  | 
|  | Winelib programs: | 
|  | ----------------- | 
|  |  | 
|  | programs/		- All the Winelib programs | 
|  |  | 
|  | avitools/	- AVI information viewer and player | 
|  | clock/		- Graphical clock | 
|  | cmdlgtst/	- Common dialog tests | 
|  | control/	- Control panel | 
|  | expand/		- Decompress Lempel-Ziv compressed archive | 
|  | notepad/	- Notepad with RichEdit functionality | 
|  | osversioncheck/	- Check version of Windows being indicated | 
|  | progman/	- Program manager | 
|  | regapi/		- Command line Registry implementation | 
|  | regedit/	- Registry editor | 
|  | regsvr32/	- Register COM server | 
|  | regtest/	- Registry testing program | 
|  | rpcss/		- RPC services | 
|  | rundll32/	- Execute DLL functions directly | 
|  | uninstaller/	- Remove installed programs | 
|  | view/		- Metafile viewer | 
|  | wcmd/		- Command line interface | 
|  | wineconsole/	- Console | 
|  | winedbg/	- Debugger | 
|  | winefile/	- File manager | 
|  | winemine/	- Mine game | 
|  | winepath/	- Translate between Wine and Unix paths | 
|  | winhelp/	- Help viewer | 
|  | winver/		- Windows Version Program | 
|  |  | 
|  |  | 
|  | Support programs, libraries, etc: | 
|  | --------------------------------- | 
|  |  | 
|  | documentation/		- some documentation | 
|  | include/		- Windows standard includes | 
|  | library/		- the Wine portability library | 
|  | miscemu/		- the main Wine program | 
|  | ole/			- global UUIDs static library | 
|  | server/			- the Wine server | 
|  | tools/			- relay code builder, new rc, bugreport | 
|  | generator, wineconfigurator, etc. | 
|  | unicode/		- Unicode support shared | 
|  |  | 
|  |  | 
|  | Miscellaneous: | 
|  | -------------- | 
|  |  | 
|  | Note: these directories will ultimately get moved into their | 
|  | respective dlls. | 
|  |  | 
|  | files/			- KERNEL file I/O | 
|  | if1632/			- KERNEL relay code | 
|  | loader/			- KERNEL loader code | 
|  | memory/			- KERNEL memory management | 
|  | misc/			- KERNEL shell, registry, winsock, etc. | 
|  | msdos/			- KERNEL DOS support | 
|  | relay32/		- KERNEL 32-bit relay code | 
|  | scheduler/		- KERNEL process and thread management | 
|  | win32/			- KERNEL misc Win32 functions | 
|  |  | 
|  | graphics/		- GDI graphics drivers | 
|  | objects/		- GDI logical objects | 
|  |  | 
|  | controls/		- USER built-in widgets | 
|  | windows/		- USER window management | 
|  |  | 
|  |  | 
|  |  | 
|  | IMPLEMENTING NEW API CALLS | 
|  | ========================== | 
|  |  | 
|  | This is the simple version, and covers only Win32. Win16 is slightly | 
|  | uglier, because of the Pascal heritage and the segmented memory model. | 
|  |  | 
|  | All of the Win32 APIs known to Wine are listed in the .spec file of | 
|  | their corresponding dll. An unimplemented call will look like (from | 
|  | gdi32.spec) | 
|  | 269 stub PolyBezierTo | 
|  | To implement this call, you need to do the following four things. | 
|  |  | 
|  | 1. Find the appropriate parameters for the call, and add a prototype to | 
|  | the correct header file. In this case, that means [include/wingdi.h], | 
|  | and it might look like | 
|  | BOOL WINAPI PolyBezierTo(HDC, LPCVOID, DWORD); | 
|  | If the function has both an ASCII and a Unicode version, you need to | 
|  | define both and add a #define WINELIB_NAME_AW declaration. See below | 
|  | for discussion of function naming conventions. | 
|  |  | 
|  | 2. Modify the .spec file to tell Wine that the function has an | 
|  | implementation, what the parameters look like and what Wine function | 
|  | to use for the implementation. In Win32, things are simple--everything | 
|  | is 32-bits. However, the relay code handles pointers and pointers to | 
|  | strings slightly differently, so you should use 'str' and 'wstr' for | 
|  | strings, 'ptr' for other pointer types, and 'long' for everything else. | 
|  | 269 stdcall PolyBezierTo(long ptr long) PolyBezierTo | 
|  | The 'PolyBezierTo' at the end of the line is which Wine function to use | 
|  | for the implementation. | 
|  |  | 
|  | 3. Implement the function as a stub. Once you add the function to the .spec | 
|  | file, you must add the function to the Wine source before it will link. | 
|  | Add a function called 'PolyBezierTo' somewhere. Good things to put | 
|  | into a stub: | 
|  | o a correct prototype, including the WINAPI | 
|  | o header comments, including full documentation for the function and | 
|  | arguments (see documentation/README.documentation) | 
|  | o A FIXME message and an appropriate return value are good things to | 
|  | put in a stub. | 
|  |  | 
|  | /************************************************************ | 
|  | *                    PolyBezierTo   (GDI32.269) | 
|  | * | 
|  | * Draw many Bezier curves | 
|  | * | 
|  | * RETURNS | 
|  | *   nonzero on success or zero on faillure | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI PolyBezierTo(HDC hdc,     /* handle to device context */ | 
|  | LPCVOID p,   /* ptr to array of Point structs */ | 
|  | DWORD count  /* nr of points in array */ | 
|  | ) | 
|  | { | 
|  | /* tell the user they've got a substandard implementation */ | 
|  | FIXME(gdi, ":(%x,%p,%d): stub\n", hdc, p, count); | 
|  |  | 
|  | /* some programs may be able to compensate, | 
|  | * if they know what happened | 
|  | */ | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE;    /* error value */ | 
|  | } | 
|  |  | 
|  | 4. Implement and test the rest of the function. | 
|  |  | 
|  |  | 
|  | IMPLEMENTING A NEW DLL | 
|  | ====================== | 
|  |  | 
|  | Generic directions | 
|  | ------------------ | 
|  |  | 
|  | Apart from writing the set of needed .c files, you also need to do the | 
|  | following: | 
|  |  | 
|  | 1.  Create a directory <MyDll> where to store the implementation of | 
|  | the DLL. This directory has to be put under the dlls/ directory. | 
|  | If the DLL exists under Windows as both 16 and 32 bit DLL, you | 
|  | should have a single directory with both implementations. | 
|  |  | 
|  | 2.  Create the Makefile.in in the ./dlls/<MyDll>/ directory. You can | 
|  | copy an existing Makefile.in from another ./dlls/ subdirectory. | 
|  | You need at least to change the MODULE and C_SRCS macros. | 
|  |  | 
|  | 3.  Add the directory in ./configure.ac (in AC_OUTPUT macro at the end | 
|  | of the file to trigger the Makefile generation) | 
|  |  | 
|  | 4.  Run ./make_dlls in the dlls directory to update Makefile.in in | 
|  | that directory. | 
|  |  | 
|  | 5.  You can now regenerate ./configure file (with 'make configure') | 
|  | and the various Makefiles (with 'configure; make depend') (run | 
|  | from the top of Wine's tree). | 
|  | You should now have a Makefile file in ./dlls/<MyDll>/ | 
|  |  | 
|  | 6.  Create the .spec file for the DLL exported functions in your | 
|  | directory. Refer to 'Implementation of new API calls' earlier in | 
|  | this document for more information on this part. | 
|  |  | 
|  | 7.  You can now start adding .c files. For the .h files, if they are | 
|  | standard Windows one, put them in include/. If they are linked to | 
|  | *your* implementation of the dll, put them in your newly created | 
|  | directory. | 
|  |  | 
|  | Debug channels | 
|  | -------------- | 
|  |  | 
|  | If you need to create a new debug channel, just add the | 
|  | WINE_DEFAULT_DEBUG_CHANNEL to your .c file(s), and use them. | 
|  | All the housekeeping will happen automatically. | 
|  |  | 
|  | Resources | 
|  | --------- | 
|  |  | 
|  | If you also need to add resources to your DLL, then create the .rc | 
|  | file. Add to your ./dlls/<MyDll>/Makefile.in, in the RC_SRCS macro, | 
|  | the list of .rc files to add to the DLL. See dlls/comctl32/ for an | 
|  | example of this. | 
|  |  | 
|  | Thunking | 
|  | -------- | 
|  |  | 
|  | If you're building a 16 & 32 bit DLLs pair, then from the 32 bit code | 
|  | you might need to call 16 bit routine. The way to do it to add in the | 
|  | code, fragments like: | 
|  | /* ### Start build ### */ | 
|  | extern WORD CALLBACK <PREFIX>_CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG); | 
|  | /* ### stop build ### */ | 
|  | Where <PREFIX>_ is an internal prefix for your module. The first | 
|  | parameter is always of type FARPROC16. Then, you can get the regular | 
|  | list of parameters. The _word_wwlll indicates the type of return (long | 
|  | or word) and the size of the parameters (here l=>long, w=>word; which | 
|  | maps to WORD,WORD,LONG,LONG,LONG. | 
|  | You can put several functions between the Start/Stop build pair. | 
|  |  | 
|  | You can also read the winebuild manpage for more details on this. | 
|  |  | 
|  | Then, add to ./dlls/<MyDll>/Makefile.in a line like: | 
|  |  | 
|  | EXTRA_OBJS = $(MODULE).glue.o | 
|  |  | 
|  | See dlls/winmm/ for an example of this. | 
|  |  | 
|  | MEMORY AND SEGMENTS | 
|  | =================== | 
|  |  | 
|  | NE (Win16) executables consist of multiple segments.  The Wine loader | 
|  | loads each segment into a unique location in the Wine processes memory | 
|  | and assigns a selector to that segment.  Because of this, it's not | 
|  | possible to exchange addresses freely between 16-bit and 32-bit code. | 
|  | Addresses used by 16-bit code are segmented addresses (16:16), formed | 
|  | by a 16-bit selector and a 16-bit offset.  Those used by the Wine code | 
|  | are regular 32-bit linear addresses. | 
|  |  | 
|  | There are four ways to obtain a segmented pointer: | 
|  | - Using the MapLS function (recommended). | 
|  | - Allocate a block of memory from the global heap and use | 
|  | WIN16_GlobalLock to get its segmented address. | 
|  | - Declare the argument as 'segptr' instead of 'ptr' in the spec file | 
|  | for a given API function. | 
|  |  | 
|  | Once you have a segmented pointer, it must be converted to a linear | 
|  | pointer before you can use it from 32-bit code.  This can be done with | 
|  | the MapSL function.  The linear pointer can then be used freely with | 
|  | standard Unix functions like memcpy() etc. without worrying about 64k | 
|  | boundaries.  Note: there's no easy way to convert back from a linear | 
|  | to a segmented address. | 
|  |  | 
|  | In most cases, you don't need to worry about segmented address, as the | 
|  | conversion is made automatically by the callback code and the API | 
|  | functions only see linear addresses. However, in some cases it is | 
|  | necessary to manipulate segmented addresses; the most frequent cases | 
|  | are: | 
|  | - API functions that return a pointer | 
|  | - lParam of Windows messages that point to a structure | 
|  | - Pointers contained inside structures accessed by 16-bit code. | 
|  |  | 
|  | It is usually a good practice to used the type 'SEGPTR' for segmented | 
|  | pointers, instead of something like 'LPSTR' or 'char *'.  As SEGPTR is | 
|  | defined as a DWORD, you'll get a compilation warning if you mistakenly | 
|  | use it as a regular 32-bit pointer. | 
|  |  | 
|  |  | 
|  | STRUCTURE PACKING | 
|  | ================= | 
|  |  | 
|  | Under Windows, data structures are tightly packed, i.e. there is no | 
|  | padding between structure members. On the other hand, by default gcc | 
|  | aligns structure members (e.g. WORDs are on a WORD boundary, etc.). | 
|  | This means that a structure like | 
|  |  | 
|  | struct { BYTE x; WORD y; }; | 
|  |  | 
|  | will take 3 bytes under Windows, but 4 with gcc, because gcc will add a | 
|  | dummy byte between x and y. To have the correct layout for structures | 
|  | used by Windows code, you need to embed the struct within two special | 
|  | #include's which will take care of the packing for you: | 
|  |  | 
|  | #include "pshpack1.h" | 
|  | struct { BYTE x; WORD y; }; | 
|  | #include "poppack1.h" | 
|  |  | 
|  | For alignment on a 2-byte boundary, there is a "pshpack2.h", etc. | 
|  |  | 
|  | The use of the WINE_PACKED attribute is obsolete. Please remove these | 
|  | in favour of the above solution. | 
|  | Using WINE_PACKED, you would declare the above structure like this: | 
|  |  | 
|  | struct { BYTE x; WORD y WINE_PACKED; }; | 
|  |  | 
|  | You had to do this every time a structure member is not aligned | 
|  | correctly under Windows (i.e. a WORD not on an even address, or a | 
|  | DWORD on a address that was not a multiple of 4). | 
|  |  | 
|  |  | 
|  | NAMING CONVENTIONS FOR API FUNCTIONS AND TYPES | 
|  | ============================================== | 
|  |  | 
|  | In order to support both Win16 and Win32 APIs within the same source | 
|  | code, the following convention must be used in naming all API | 
|  | functions and types. If the Windows API uses the name 'xxx', the Wine | 
|  | code must use: | 
|  |  | 
|  | - 'xxx16' for the Win16 version, | 
|  | - 'xxx'   for the Win32 version when no ASCII/Unicode strings are | 
|  | involved, | 
|  | - 'xxxA'  for the Win32 version with ASCII strings, | 
|  | - 'xxxW'  for the Win32 version with Unicode strings. | 
|  |  | 
|  | If the function has both ASCII and Unicode version, you should then | 
|  | use the macros WINELIB_NAME_AW(xxx) or DECL_WINELIB_TYPE_AW(xxx) | 
|  | (defined in include/windef.h) to define the correct 'xxx' function | 
|  | or type for Winelib. When compiling Wine itself, 'xxx' is _not_ | 
|  | defined, meaning that code inside of Wine must always specify | 
|  | explicitly the ASCII or Unicode version. | 
|  |  | 
|  | If 'xxx' is the same in Win16 and Win32, you can simply use the same | 
|  | name as Windows, i.e. just 'xxx'.  If 'xxx' is Win16 only, you could | 
|  | use the name as is, but it's preferable to use 'xxx16' to make it | 
|  | clear it is a Win16 function. | 
|  |  | 
|  | Examples: | 
|  |  | 
|  | typedef struct { /* Win32 ASCII data structure */ } WNDCLASSA; | 
|  | typedef struct { /* Win32 Unicode data structure */ } WNDCLASSW; | 
|  | typedef struct { /* Win16 data structure */ } WNDCLASS16; | 
|  | DECL_WINELIB_TYPE_AW(WNDCLASS); | 
|  |  | 
|  | ATOM RegisterClass16( WNDCLASS16 * ); | 
|  | ATOM RegisterClassA( WNDCLASSA * ); | 
|  | ATOM RegisterClassW( WNDCLASSW * ); | 
|  | #define RegisterClass WINELIB_NAME_AW(RegisterClass) | 
|  |  | 
|  | The Winelib user can then say: | 
|  |  | 
|  | WNDCLASS wc = { ... }; | 
|  | RegisterClass( &wc ); | 
|  |  | 
|  | and this will use the correct declaration depending on the definition | 
|  | of the UNICODE symbol. | 
|  |  | 
|  |  | 
|  | NAMING CONVENTIONS FOR NON-API FUNCTIONS AND TYPES | 
|  | ================================================== | 
|  |  | 
|  | Functions and data which are internal to your code (or at least shouldn't be | 
|  | visible to any Winelib or Windows program) should be preceded by | 
|  | an identifier to the module: | 
|  |  | 
|  | Examples: | 
|  |  | 
|  | ENUMPRINTERS_GetDWORDFromRegistryA()    (in dlls/winspool/info.c) | 
|  | IAVIFile_fnRelease()                    (in dlls/avifil32/avifile.c) | 
|  | X11DRV_CreateDC()                       (in graphics/x11drv/init.c) | 
|  |  | 
|  | if you need prototypes for these, there are a few possibilities: | 
|  | - within same source file only: | 
|  | put the prototypes at the top of your file and mark them as prototypes. | 
|  | - within the same module: | 
|  | create a header file within the subdirectory where that module resides, | 
|  | e.g.  graphics/ddraw_private.h | 
|  | - from a totally different module, or for use in winelib: | 
|  | you should never do that. Only exported APIs can be called across | 
|  | module boundaries. | 
|  |  | 
|  |  | 
|  | DEBUG MESSAGES | 
|  | ============== | 
|  |  | 
|  | To display a message only during debugging, you normally write something | 
|  | like this: | 
|  |  | 
|  | TRACE("abc...");  or | 
|  | FIXME("abc...");  or | 
|  | WARN("abc...");   or | 
|  | ERR("abc..."); | 
|  |  | 
|  | depending on the seriousness of the problem. (documentation/degug-msgs | 
|  | explains when it is appropriate to use each of them). You need to declare | 
|  | the debug channel name at the top of the file (after the includes) using | 
|  | the WINE_DEFAULT_DEBUG_CHANNEL macro, like so: | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(win); | 
|  |  | 
|  | If your debugging code is more complex than just printf, you can use | 
|  | the macros: | 
|  |  | 
|  | TRACE_ON(xxx), WARN_ON(xxx), ERR_ON(xxx) and FIXME_ON(xxx) | 
|  |  | 
|  | to test if the given channel is enabled. Thus, you can write: | 
|  |  | 
|  | if (TRACE_ON(win)) DumpSomeStructure(&str); | 
|  |  | 
|  | Don't worry about the inefficiency of the test. If it is permanently | 
|  | disabled (that is TRACE_ON(win) is 0 at compile time), the compiler will | 
|  | eliminate the dead code. | 
|  |  | 
|  | For more info about debugging messages, read: | 
|  |  | 
|  | documentation/debug-msgs | 
|  |  | 
|  |  | 
|  | MORE INFO | 
|  | ========= | 
|  |  | 
|  | 1. There is a FREE online version of the MSDN library (including | 
|  | documentation for the Win32 API) on http://msdn.microsoft.com/ | 
|  |  | 
|  | 2. http://www.sonic.net/~undoc/bookstore.html | 
|  |  | 
|  | 3. In 1993 Dr. Dobbs Journal published a column called "Undocumented Corner". | 
|  |  | 
|  | 4. You might want to check out BYTE from December 1983 as well :-) |