WineHQ
WineHQ

6.2. Writing Wine API Documentation

6.2.1. Introduction to API Documentation

Wine includes a large amount of documentation on the API functions it implements. There are several reasons to want to document the Win32 API:

  • To allow Wine developers to know what each function should do, should they need to update or fix it.

  • To allow Winelib users to understand the functions that are available to their applications.

  • To provide an alternative source of free documentation on the Win32 API.

  • To provide more accurate documentation where the existing documentation is accidentally or deliberately vague or misleading.

To this end, a semi formalized way of producing documentation from the Wine source code has evolved. Since the primary users of API documentation are Wine developers themselves, documentation is usually inserted into the source code in the form of comments and notes. Good things to include in the documentation of a function include:

  • The purpose of the function.

  • The parameters of the function and their purpose.

  • The return value of the function, in success as well as failure cases.

  • Additional notes such as interaction with other parts of the system, differences between Wine and Win32 implementations, errors in MSDN documentation, undocumented cases and bugs that Wine corrects or is compatible with.

Good documentation helps developers be aware of the effects of making changes. It also allows good tests to be written which cover all of the documented cases.

Note that you do not need to be a programmer to update the documentation in Wine. If you would like to contribute to the project, patches that improve the API documentation are welcome. The following describes how to format any documentation that you write so that the Wine documentation generator can extract it and make it available to other developers and users.

In general, if you did not write the function in question, you should be wary of adding comments to other peoples code. It is quite possible you may misunderstand or misrepresent what the original author intended! Adding API documentation on the other hand can be done by anybody, since in most cases there is plenty of information about what a function is supposed to do (if it isn't obvious) available in books and articles on the internet.

A final warning concerns copyright and must be noted. If you read MSDN or any publication in order to find out what an API call does, you must be aware that the text you are reading is copyrighted and in most cases cannot legally be reproduced without the authors permission. If you copy verbatim any information from such sources and submit it for inclusion into Wine, you open yourself up to potential legal liability. You must ensure that anything you submit is your own work, although it can be based on your understanding gleaned from reading other peoples work.

6.2.2. Basic API Documentation

The general form of an API comment in Wine is a block comment immediately before a function is implemented in the source code. General comments within a function body or at the top of an implementation file are ignored by the API documentation generator. Such comments are for the benefit of developers only, for example to explain what the source code is doing or to describe something that may not be obvious to the person reading the source code.

The following text uses the function PathRelativePathToA() from SHLWAPI.DLL as an example. You can find this function in the Wine source code tree in the file dlls/shlwapi/path.c.

The first line of the comment gives the name of the function, the DLL that the function is exported from, and its export ordinal number. This is the simplest (and most common type of) comment:

/*************************************************************************
 * PathRelativePathToW   [SHLWAPI.@]
 */

The functions name and the DLL name are obvious. The ordinal number takes one of two forms: Either @ as in the above, or a number if the export is exported by ordinal. You can see which to use by looking at the DLL .spec file. If the line on which the function is listed begins with a number, use it, otherwise use the @ symbol, which indicates that this function is imported only by name.

Note also that round or square brackets can be used, and whitespace between the name and the DLL/ordinal is free form. Thus the following is equally valid:

/*************************************************************************
 *		PathRelativePathToW	(SHLWAPI.@)
 */

This basic comment will not get processed into documentation, since it contains no information. In order to produce documentation for the function, We must add some of the information listed above.

First we add a description of the function. This can be as long as you like, but typically contains only a brief description of what the function is meant to do in general terms. It is free form text:

/*************************************************************************
 * PathRelativePathToW   [SHLWAPI.@]
 *
 * Create a relative path from one path to another.
 */

To be truly useful however we must document the parameters to the function. There are two methods for doing this: In the comment, or in the function prototype.

Parameters documented in the comment should be formatted as follows:

/*************************************************************************
 * PathRelativePathToW   [SHLWAPI.@]
 *
 * Create a relative path from one path to another.
 *
 * PARAMS
 *  lpszPath   [O] Destination for relative path
 *  lpszFrom   [I] Source path
 *  dwAttrFrom [I] File attribute of source path
 *  lpszTo     [I] Destination path
 *  dwAttrTo   [I] File attributes of destination path
 *
 */

The parameters section starts with PARAMS on its own line. Each parameter is listed in the order they appear in the functions prototype, first with the parameters name, followed by its input/output status, followed by a free form text description of the comment.

The input/output status tells the programmer whether the value will be modified by the function (an output parameter), or only read (an input parameter). The status must be enclosed in square brackets to be recognized, otherwise, or if it is absent, anything following the parameter name is treated as the parameter description. This field is case insensitive and can be any of the following: [I], [In], [O], [Out], [I/O], [In/Out].

Following the description and parameters come a number of optional sections, all in the same format. A section is defined as the section name, which is an all upper case section name on its own line, followed by free form text. You can create any sections you like, however for consistency it is recommended you use the following section names:

  1. NOTES. Anything that needs to be noted about the function such as special cases and the effects of input arguments.

  2. BUGS. Any bugs in the function that exist "by design", i.e. those that will not be fixed or exist for compatibility with Windows.

  3. TODO. Any unhandled cases or missing functionality in the Wine implementation of the function.

  4. FIXME. Things that should be updated or addressed in the implementation of the function at some future date (perhaps dependent on other parts of Wine). Note that if this information is only relevant to Wine developers then it should probably be placed in the relevant code section instead.

Following or before the optional sections comes the RETURNS section which describes the return value of the function. This is free form text but should include what is returned on success as well as possible error return codes. Note that this section must be present for documentation to be generated for your comment.

Our final documentation looks like the following:

/*************************************************************************
 * PathRelativePathToW   [SHLWAPI.@]
 *
 * Create a relative path from one path to another.
 *
 * PARAMS
 *  lpszPath   [O] Destination for relative path
 *  lpszFrom   [I] Source path
 *  dwAttrFrom [I] File attribute of source path
 *  lpszTo     [I] Destination path
 *  dwAttrTo   [I] File attributes of destination path
 *
 * RETURNS
 *  TRUE  If a relative path can be formed. lpszPath contains the new path
 *  FALSE If the paths are not relative or any parameters are invalid
 *
 * NOTES
 *  lpszTo should be at least MAX_PATH in length.
 *  Calling this function with relative paths for lpszFrom or lpszTo may
 *  give erroneous results.
 *
 *  The Win32 version of this function contains a bug where the lpszTo string
 *  may be referenced 1 byte beyond the end of the string. As a result random
 *  garbage may be written to the output path, depending on what lies beyond
 *  the last byte of the string. This bug occurs because of the behaviour of
 *  PathCommonPrefix() (see notes for that function), and no workaround seems
 *  possible with Win32.
 *  This bug has been fixed here, so for example the relative path from "\\"
 *  to "\\" is correctly determined as "." in this implementation.
 */

6.2.3. Advanced API Documentation

There is no markup language for formatting API comments, since they should be easily readable by any developer working on the source file. A number of constructs are treated specially however, and are noted here. You can use these constructs to enhance the usefulness of the generated documentation by making it easier to read and referencing related documents.

Any valid C identifier that ends with () is taken to be an API function and is formatted accordingly. When generating documentation, this text will become a link to that API call, if the output type supports hyperlinks or their equivalent.

Similarly, any interface name starting with a 'I' and followed by the words reference or object becomes a link to the documentation of that object.

Where an Ascii and Unicode version of a function are available, it is recommended that you document only the Unicode version and have the Ascii version refer to the Unicode one, as follows:

/*************************************************************************
 * PathRelativePathToA   [SHLWAPI.@]
 *
 * See PathRelativePathToW.
 */

Alternately you may use the following form:

/*************************************************************************
 * PathRelativePathToA   [SHLWAPI.@]
 *
 * Unicode version of PathRelativePathToW.
 */

You may also use this construct in any other section, such as NOTES.

Any numbers and text in quotes ("") are highlighted.

Words in all uppercase are assumed to be API constants and are highlighted. If you want to emphasize something in the documentation, put it in a section by itself rather than making it upper case.

Blank lines in a section cause a new paragraph to be started. Blank lines at the start and end of sections are ignored.

Any comment line starting with '*' or '|' is treated as raw text and is not pre-processed before being output. This should be used for code listings, tables and any text that should remain unformatted.

Any line starting with a single word followed by a colon (':') is assumed to be case listing and is emphasized and put in its own paragraph. This is most often used for return values, as in the example section below.

 * RETURNS
 *  Success: TRUE. Something happens that is documented here.
 *  Failure: FALSE. The reasons why this call can fail are listed here.

Any line starting with a '-' is put into a paragraph by itself. This allows lists to avoid being run together.

If you are in doubt as to how your comment will look, try generating the API documentation and checking the output.

6.2.4. Extra API Documentation

Simply documenting the API calls available provides a great deal of information to developers working with the Win32 API. However additional documentation is needed before the API Guide can be considered truly useful or comprehensive. For example, COM objects that are available for developers use should be documented, along with the interfaces that those objects export. Also, it would be helpful to document each DLL, to provide some structure to the documentation.

To facilitate providing extra documentation, you can create comments that provide extra documentation on functions, or on keywords such as the name of a COM interface or a type definition.

These items are generated using the same formatting rules as described earlier. The only difference is the first line of the comment, which indicates to the generator that the documentation is supplemental and does not describe an export from the DLL being processed.

Let's assume you have implemented a COM interface that you want to document; we'll use the name IExample as an example here. Your comment would look like the following (assuming you are exporting this object from EXAMPLE.DLL):

/*************************************************************************
 * IExample   {EXAMPLE}
 *
 * The IExample object provides lots of interesting functionality.
 * ...
 */

Format this documentation exactly as you would a standard export. The only difference is the use of curly brackets to mark this documentation as supplemental. The generator will output this documentation using the name given before the DLL name, and will link to it from the main DLL page. In addition, if you have referred to the comment name in other documentation using "IExample interface", "IExample object", or "IExample()", those references will point to this documentation.

If you document you COM interfaces this way then all following extra comments that follow in the same source file that begin with the same document title will be added as references to this comment before it is output. For an example of this see dlls/oleaut32/safearray.c. This uses an extra comment to document The SafeArray functions and link them together under one heading.

As a special case, if you use the DLL name as the comment name, the comment will be treated as documentation on the DLL itself. When the documentation for the DLL is processed, the contents of the comment will be placed before the generated statistics, exports and other information that makes up a DLL documentation page.

6.2.5. Generating API Documentation

Having edited or added new API documentation to a source code file, you should generate the documentation to ensure that the result is what you expected. Wine includes a tool (slightly misleadingly) called c2man.pl in the tools/ directory which is used to generate the documentation from the source code.

You can run c2man.pl manually for testing purposes; it is a fairly simple perl script which parses .c files to create output in several formats. If you wish to try this you may want to run it with no arguments, which will cause it to print usage information.

An easier way is to use Wine build system. To create man pages for a given DLL, just type make man from within the dlls directory or type make manpages in the root directory of the Wine source tree. You can then check that a man page was generated for your function, it should be present in the documentation/man3w directory with the same name as the function.

Once you have generated the man pages from the source code, running make install will install them for you. By default they are installed in section 3w of the manual, so they don't conflict with any existing man page names. So, to read the man page you should use man -S 3w name. Alternately you can edit /etc/man.config and add 3w to the list of search paths given in the MANSECT variable.

You can also generate HTML output for the API documentation, in this case the make command is make htmlpages in the dll directory, or from the root. The output will be placed by default under documentation/html. Similarly you can create SGML/XML Docbook source code to produce the Wine API Guide with the command make sgmlpages/make xmlpages respectively.