| 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. |
| |
| Wine API directories: |
| --------------------- |
| |
| KERNEL: |
| |
| files/ - file I/O |
| loader/ - Win16-, Win32-binary loader |
| memory/ - memory management |
| msdos/ - DOS features and BIOS calls (interrupts) |
| scheduler/ - process and thread management |
| |
| GDI: |
| |
| graphics/ - graphics drivers |
| x11drv/ - X11 display driver |
| win16drv/ -> see below |
| ttydrv/ - tty display driver |
| psdrv/ - PostScript graphics driver |
| metafiledrv/ - metafile driver |
| enhmetafiledrv/ - enhanced metafile driver |
| objects/ - logical objects |
| |
| USER: |
| |
| controls/ - built-in widgets |
| resources/ - built-in menu and message box resources |
| windows/ - window management |
| |
| Other DLLs: |
| |
| dlls/ - Other system DLLs implemented by Wine |
| advapi32/ - crypto, systeminfo, security, eventlogging |
| avifil32/ - COM object to play AVI files |
| comctl32/ - common controls |
| commdlg/ - common dialog boxes (both 16 & 32 bit) |
| crtdll/ - Old C runtime library |
| dplayx/ - DirectX dplayx |
| dsound/ - DirectX dsound |
| imagehlp/ - PE (Portable Executable) Image Helper lib |
| imm32/ |
| lzexpand/ - Liv-Zempel compression/decompression |
| mpr/ - Multi-Protocol Router (interface to various |
| network transport protocols) |
| msacm/ - audio compression manager (multimedia) (16 bit) |
| msacm32/ - audio compression manager (multimedia) (32 bit) |
| msnet/ |
| msvcrt/ - C runtime library |
| msvideo/ - 16 bit video manager |
| ole32/ - 32 bit OLE 2.0 librairies |
| oleaut32/ - 32 bit OLE 2.0 automation |
| olecli/ - 16 bit OLE client |
| oledlg/ - OLE 2.0 user interface support |
| olesvr/ - 16 bit OLE server |
| ntdll/ - NT implementation of kernel calls |
| psapi/ - process status API |
| rasapi32/ - remote access server API |
| shell32/ - COM object implementing shell views |
| sound/ - Sound on loudspeaker (not sound card) |
| tapi32/ - telephone API |
| ver/ - File Installation Library (16 bit) |
| version/ - File Installation Library (32 bit) |
| win32s |
| win87em - 80387 math-emulation |
| winaspi/ - 16 bit Advanced SCSI Peripheral Interface |
| windebug/ - Windows debugger |
| wing/ - WinG (for games) internface |
| winmm/ - multimedia (16 & 32 bit) |
| mciXXX/ - various MCI drivers |
| wineoss/- MM driver for OSS systems |
| wavemap/- audio mapper |
| midimap/- midi mapper |
| winspool/ - Printing & Print Spooler |
| wnaspi32/ - 32 bit ASPI |
| |
| Miscellaneous: |
| |
| misc/ - shell, registry, winsock, etc. |
| ipc/ - SysV IPC based interprocess communication |
| win32/ - misc Win32 functions |
| ole/ - OLE code |
| nls/ - National Language Support |
| configuration files |
| |
| Tools: |
| ------ |
| |
| rc/ - old resource compiler |
| tools/ - relay code builder, new rc, bugreport |
| generator, wineconfigurator, etc. |
| documentation/ - some documentation |
| |
| |
| Binary loader specific directories: |
| ----------------------------------- |
| |
| debugger/ - built-in debugger |
| if1632/ - relay code |
| miscemu/ - hardware instruction emulation |
| graphics/win16drv/ - Win16 printer driver |
| server/ - the main, controlling thread of wine |
| tsx11/ - thread-safe X11 wrappers (auto generated) |
| |
| Winelib specific directories: |
| ----------------------------- |
| |
| library/ - Required code for programs using Winelib |
| libtest/ - Small samples and tests |
| programs/ - Extended samples / system utilities |
| |
| |
| 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 [relay32/*.spec]. 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. |
| |
| If the DLL exists under Windows as both 16 and 32 bit DLL, you can |
| either create one directory for each, or have a single directory |
| with both implementations. |
| |
| This (those) directory(ies) have to be put under the dlls/ |
| directory in Wine tree structure. |
| |
| 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, SPEC_SRCS, and C_SRCS |
| macros. |
| |
| 3. Add the directory (and the generated .o file for the module) in: |
| + ./configure.in (in AC_OUTPUT macro at the end of the file to |
| trigger the Makefile generation), |
| + ./Makefile.in (in LIBSUBDIRS and LIBOBJS macros) |
| + ./dlls/Makefile.in (in SUBDIRS macro) |
| |
| 4. 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 shall now have a Makefile file in ./dlls/<MyDll>/ |
| |
| 5. You now need to declare the DLL in the module lists. This is done |
| by adding the corresponding descriptor in ./if1632/builtin.c if |
| your DLL is 16 bit (resp. ./relay32/builtin.c for a 32 bit DLL) |
| (or both if your directory contains the dual 16/32 |
| implementations). |
| |
| Note: the name of the descriptor is based on the module name, not |
| on the file name (they are the same in most of the case, but for |
| some DLLs it's not the case). |
| |
| 6. You also need to define the loadorder for the created DLL |
| (./wine.ini and ./loader/loadorder.c). Usually, "native,builtin" |
| is ok. If you have written a paired 16/32 bit implementation, don't |
| forget to define it also in those files. |
| |
| 7. Create the .spec file for the DLL export points in your |
| directory. Refer to 'Implementation of new API calls' earlier in |
| this document for more information on this part. |
| |
| 8. Don't forget the .cvsignore file. The .cvsignore contain (on a per |
| directory basis) all the files generated by the compilation |
| process, why cvs shall ignore when processing the dir. |
| *.o is in there by default, but in Wine case you will find: |
| - Makefile (generated from Makefile.in) |
| - *.spec.c: those c files are generated by tools/build from the |
| .spec file |
| - when thunking down to 16 bit DLLs, you'll get some others (.glue.c) |
| - result of .y => .c translation (by yacc or bison) |
| - result of .rc compilation |
| - ... |
| For a simple DLL, listing in .cvsignore Makefile and |
| <MyDll>.spec.c will do. |
| |
| 9. You can now start adding .c files. |
| |
| 10. 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 |
| DECLARE_DEBUG_CHANNEL to your .c file(s) and rerun |
| tools/make_debug. When sending out your patch, you don't need to |
| provide nor ./configure nor the ./include/debugdefs.h diffs. Just |
| indicate that those files need to be regenerated. |
| |
| Resources |
| --------- |
| |
| If you also need to add resources to your DLL, the create the .rc |
| file. Since, the .rc file will be translated into a .s file, and then |
| compiled as a .o file, its basename must be different from the |
| basename of any .c file. |
| Add to your ./dlls/<MyDll>/Makefile.in, in the RC_SRCS macro, the list |
| of .rc files to add to the DLL. You may also have to add the following |
| directives |
| 1/ to tell gnumake to translate .rc into .s files, |
| $(RC_SRCS:.rc=.s): $(WRC) |
| 2/ to give some parameters to wrc for helping the translation. |
| WRCEXTRA = -s -p$(MODULE) |
| |
| 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 tools/build.txt for more details on this. |
| |
| Then, add to ./dlls/<MyDll>/Makefile.in to the macro GLUE the list of |
| .c files containing the /* ### Start build ### */ directives. |
| |
| 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: |
| - Use the SEGPTR_* macros in include/heap.h (recommended). |
| - Allocate a block of memory from the global heap and use |
| WIN16_GlobalLock to get its segmented address. |
| - Allocate a block of memory from a local heap, and build the |
| segmented address from the local heap selector (see the |
| USER_HEAP_* macros for an example of this). |
| - 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 PTR_SEG_TO_LIN() and PTR_SEG_OFF_TO_LIN() macros. 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) |
| TIMER_Init() (implemented in windows/timer.c, |
| used in loader/main.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: |
| put your header file entry in /include/wine/ |
| but be careful not to clutter this directory! |
| under no circumstances, you should add non-api calls to the standard |
| windoze include files. Unfortunately, this is often the case, e.g. |
| the above example of TIMER_Init is defined in include/message.h |
| |
| |
| API ENTRY POINTS |
| ================ |
| |
| Because Win16 programs use a 16-bit stack and because they can only |
| call 16:16 addressed functions, all API entry points must be at low |
| address offsets and must have the arguments translated and moved to |
| Wines 32-bit stack. This task is handled by the code in the "if1632" |
| directory. To define a new API entry point handler you must place a |
| new entry in the appropriate API specification file. These files are |
| named *.spec. For example, the API specification file for the USER |
| DLL is contained in the file user.spec. These entries are processed |
| by the "build" program to create an assembly file containing the entry |
| point code for each API call. The format of the *.spec files is |
| documented in the file "tools/build-spec.txt". |
| |
| |
| DEBUG MESSAGES |
| ============== |
| |
| To display a message only during debugging, you normally write something |
| like this: |
| |
| TRACE(win,"abc..."); or |
| FIXME(win,"abc..."); or |
| WARN(win,"abc..."); or |
| ERR(win,"abc..."); |
| |
| depending on the seriousness of the problem. (documentation/degug-msgs |
| explains when it is appropriate to use each of them) |
| |
| These macros are defined in include/debug.h. The macro-definitions are |
| generated by the shell-script tools/make_debug. It scans the source |
| code for symbols of this forms and puts the necessary macro |
| definitions in include/debug.h and include/debugdefs.h. These macros |
| test whether the debugging "channel" associated with the first |
| argument of these macros (win in the above example) is enabled and |
| thus decide whether to actually display the text. In addition you can |
| change the types of displayed messages by supplying the "-debugmsg" |
| option to Wine. If your debugging code is more complex than just |
| printf, you can use the symbols TRACE_ON(xxx), WARN_ON(xxx), |
| ERR_ON(xxx) and FIXME_ON(xxx) as well. These are true when channel xxx |
| is enabled, either permanent or in the command line. 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. |
| |
| You have to start tools/make_debug only if you introduced a new macro, |
| e.g. TRACE(win32). |
| |
| 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://www.microsoft.com/msdn/ |
| |
| 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 :-) |
| |