From ReactOS Wiki
Revision as of 13:25, 13 April 2013 by Zehnvor (talk | contribs)
Jump to: navigation, search

Native Development Kit Guidelines

This document serves as a brief introduction to the NDK, what should go in it, what shouldn't, and how the information is organized at the file level, as well as how the syntax and formatting is done at the source level.

What is the NDK?

The NDK, or Native Development Kit, is the brainchild of Alex Ionescu, allowing Windows and ReactOS developers alike to have access to a wealth of undocumented kernel and native structures and function prototypes.

Without the NDK, Windows developers are forced to define their own "undoct.h" headers in which they copy/paste information found online, which may or may not be valid and updated. For native types, this is even harder, as sometimes the information is present in the DDK or IFS, but cannot be used in a user-mode application, nor can it be copy-pasted. The developer must re-write all the definitions he needs.

Without the NDK, ReactOS developers are forced to use a system of up to 3 kinds of duplicated headers (sometimes four) containing identical, similar, or worse, different information. Differences between these headers create compile-time problems, and fixing one header set without updating the other usually causes brekage in applications compiled with "W32API" headers versus applications compiled with "ddk" headers vesus applications compiled with "ntos" headers.

The NDK provides a unified header set for development of:

  • User mode applications which use native functions (include windows.h and the user-mode NDK)
  • Native applications (include the user-mode NDK)
  • Kernel-mode drivers which use undocumented kernel functions (include ddk and/or ifs and kernel-mode NDK)

What goes in the NDK?

Because the NDK is a triple-mode header set, care must be taken to avoid collisions. The following information should go in the NDK:

  • Kernel-Mode API Function Prototypes or Types which are undocumented in the DDK or IFS. If the information is documented in the IFS but not the DDK, a file called ifssupp.h will automatically be inserted to provide the few types which are missing. Next year, then the Longhorn WDK is publically released, the IFS will be free and part of it, so everyone should then have access to it. For Types which vary according to version information, always include the most recent version. If older versions are needed, use a compile-time macro to read the build environment (target version) and choose the correct structure.
  • Native (RTL, DBG, PFX, NT/ZW) API Function Prototypes or Types which are undocumented in the DDK, IFS or Windows Headers.
    • If the Type is documented in the DDK or IFS, make sure that it's actually accessible from user mode. If that is the case, locate the proper header where it should go (ex: pstypes.h), and add it, making sure to surround it by #ifdef NTOS_MODE_USER/#endif. This will protect it from the DDK/IFS.
    • In the rare case that you will find types defined in Windows headers but not in DDK/IFS, you must add the definition to a special protected block (ex:#ifndef NTOS_MODE_USER) so that it will be skipped by user-mode applications.

What should not go in the NDK?

  • Do not add documented information in the NDK unless it must be accessible from user-mode (which cannot include DDK or IFS), see above guidelines.
  • Do not add Native ReactOS Specific information anywhere.
  • Do not add Private ReactOS function or types.
  • Do not add User-Mode undocumented functions (like shell32, etc).
    • However, if the function is inside ntdll, you must add it to "umfuncs.h"

How is the NDK organized?

  • The NDK is organized in a main folder (include/ndk) with arch-specific subfolders (ex: include/ndk/i386).
  • The NDK is structured by NT Subsystem Component (ex: ex, ps, rtl, etc).
  • The NDK can either be included on-demand (#include <ndk/xxxxx.h>) or globally (#include <ndk/ntndk.h>). The former is recommended to reduce compile time.
  • The NDK is structured by function and type. Every Subsystem Component has an associated "xxfuncs.h" and "xxtypes.h" header, where "xx" is the Subsystem (ex: iofuncs.h, iotypes.h)
  • The NDK has a special file called "umtypes.h" which exports to User-Mode or Native-Mode Applications the basic NT types which are present in ntdef.h. This file cannot be included since it would conflict with winnt.h and/or windef.h. Thus, umtypes.h provides the missing types. This file is automatically included in a User-Mode NDK project.
  • The NDK also includes a file called "umfuncs.h" which exports to User-Mode or Native-Mode Applications undocumented functions which can only be accessed from ntdll.dll.
  • The NDK has another special file called "ifssupp.h", which exports to Kernel-Mode drivers a few types which are only documented in the IFS kit, and are part of some native definitions. It will be deprecated next year with the release of the WDK.

What is the formatting syntax in the NDK?

Types must be defined as follows:

typedef struct _TYPENAME
    PMEMBER_TYPE Member1;
    MEMBER_TYPE1 Member2;
    struct _TYPENAME *SelfMember;
            UCHAR Member3:4;
            UCHAR Member4:4;
        UCHAR Member5;
    MEMBER_TYPE2 Member6;

Prototypes as follows:

    PARAM_TYPE Param1,
    PARAM_TYPE Param2

Similalry, function types:

    PARAM_TYPE Param1,
    PARAM_TYPE Param2

How is the NDK Licensed?

A file called readme.txt at the root of the NDK directory describes the NDK's license. For Open-Source Projects, either the LGPL or the GPL can be used, depending on which is easiest for the project to implement. However, for closed-source projects, a special license (the "NDK License) is enforced:

  • The right to use the NDK in any commercial project without limits others then the ones below.
    • The right to make any number of derivatives of the NDK
      • However, you may not call these derivatives "NDK" anymore and must dissociate the author from them except for copyright (see below)
        • Nevertheless, any derivative or modified version must reference the original work and author. (ie: You cannot call your derivative work 'NDK Headers 2.0, by Alex Ionescu'. They could be called, for example 'Windows Native Headers 2.0, by John Smith' and must contain a clause similar to "Based on NDK Headers 1.0, by Alex Ionescu". The same principle applies for the copyright text.
      • Additionally, it is appreciated, but not required to send any modifications back to the author. This will assure that the derivative version might re-convert into an official version.
      • It is however required that you notify the author of any publically released application which uses the NDK, and/or of any public release of the NDK that your will make. This information will not be made public at your request.
        • You understand that by not submitting your changes, your derivative work will become 'out of sync', at which point other developers/testers will be forced to use your distribution if your application requires it. You understand that, at any time, the official NDK distribution could be manually updated to contain your changes, or might contain changes which are incompatible with yours, and that, at said point, your NDK distribution might become incompatible.
      • You must keep the same rights that this license grants, and you may not add any further limitations to it (in other words, the unchanged readme.txt file must be present along with your distribution). This implies that you may not prohibit the author from merging your changes in the official NDK, even if you do not submit them.
    • The right to re-distribute the NDK, or any derivative version of it, using any medium, technology and distribution method, including commercial.
      • However, the author retains the original copyright.
      • You must keep the same rights that this license grants, and you may not add any further limitations to it (in other words, the unchanged readme.txt file must be present along with your distribution).
    • There is no guarantee, warranty or support offerred for using the NDK. The author is not responsible for any losses or damages.
    • The author retains all copyright to the NDK.

How do I use the NDK?

  • User Mode Application requiring Native Types:
 #define WIN32_NO_STATUS   /* Tell Windows headers you'll use ntstatus.s from NDK */
 #include <windows.h>      /* Declare Windows Headers like you normally would */
 #include <ntndk.h>        /* Declare the NDK Headers */
  • Native Mode Application:
 #include <windows.h>      /* Declare Windows Headers for basic types. NEEDED UNTIL NDK 1.5 */
 #include <ntndk.h>        /* Declare the NDK Headers */
  • Kernel Mode Driver:
 #include <ntddk.h>       /* Declare DDK Headers like you normally would */
 #include <ntndk.h>       /* Declare the NDK Headers */

You may also include only the files you need:

 #define WIN32_NO_STATUS   /* Tell Windows headers you'll use ntstatus.s from NDK */
 #include <windows.h>      /* Declare Windows Headers like you normally would */
 #include <rtlfuncs.h>     /* Declare the Rtl* Functions */

Some caveats

  • winternl.h: This header, part of the PSDK, was released by Microsoft as part of one of the government lawsuits against it, and documents a certain (minimal) part of the Native API and/or types. Unforunately, Microsoft decided to hack the Native Types and to define them incorrectly, replacing real members by "reserved" ones. As such, you 'cannot include winternl.h in any project that uses the NDK. Note however, that the NDK fully replaces it and retains compatibility with any project that used it.
  • Native programs: Native programs must include "windows.h" until the next release of the NDK (1.5). The upcoming version will automatically detect the lack of missing types and include them. Note however that you will still need to have the PSDK installed.