Fixed some issues found by winapi_check.
[wine] / DEVELOPERS-HINTS
index 96e1713..1dd695e 100644 (file)
@@ -1,7 +1,321 @@
-This is intended to be a document to help new developers get started.
-Existing developers should feel free to add their comments.
+This document should help new developers get started. Like all of Wine, it
+is a work in progress.
 
-MEMORY AND SEGMENTS:
+
+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 libraries
+               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
+                       winearts/ - ARTS audio driver
+                       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 neither ./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
@@ -11,7 +325,8 @@ 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's three ways to obtain a segmented pointer:
+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
@@ -41,7 +356,117 @@ 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.
 
-API ENTRY POINTS:
+
+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
@@ -49,64 +474,64 @@ 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 dll_*.s and dll_tab_*.c.  The dll_*.s
-files contain the entry point code for each API call, and the dll_tab_*.s
-files contain tables used by relay.c to translate arguments and transfer
-control to the proper handler.  The format of the *.spec files is
+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".
 
-REGISTER FUNCTIONS:
 
-Some functions are defined as type "register" in the DLL specification files.
-In order to return values in the registers to the WIN16 program, the handler
-function must exit by calling ReturnFromRegisterFunc().  Look at the function
-DOS3Call() for an example of how this works.
-
-DEBUG MESSAGES:
+DEBUG MESSAGES
+==============
 
 To display a message only during debugging, you normally write something
 like this:
 
-#ifdef DEBUG_WIN
-       printf("abc...");
-#endif
-
-You can write this shorter (and better) in this way:
-
-       dprintf_win(stddeb,"abc...");
-
-All symbols of the form dprintf_xxxx are macros 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/stddebug.h . These macros
-test for the symbol DEBUG_XXXX (e.g. dprintf_win refers to DEBUG_WIN) being 
-defined and thus decided whether to actually display the text. If you want
-to enable specific types of messages, simply put the corresponding
-#define DEBUG_XXXX in include/stddebug.h . If you want to enable or disable
-a specific type of message in just one c-source-file, put the corresponding 
-#define DEBUG_XXXX or #undefine DEBUG_XXXX between #include<stddebug.h> and
-#include <debug.h> in that specific file. 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 debugging_XXX as well. These are true when XXX is enabled, either
-permanent or in the command line. So instead of writing
-
-#ifdef DEBUG_WIN
-       DumpSomeStructure(&str);
-#endif
-
-write
-       if(debugging_win)DumpSomeStructure(&str);
+        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 (thus debugging_win is 0 at compile time), the compiler will 
+disabled (that is TRACE_ON(win) is 0 at compile time), the compiler will 
 eliminate the dead code.
 
-The file handle "stddeb" is intended for displaying standard informational
-messages, whereas "stdnimp" is intended for displaying messages concerning
-not yet implemented functions.
-
 You have to start tools/make_debug only if you introduced a new macro,
-e.g.  dprintf_win32s - not if you just changed one of the #define
-DEBUG_XXX's in include/stddebug.h or in a specific file.
+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 :-)
+