NDK

From ReactOS Wiki
Revision as of 06:12, 17 August 2005 by Alex Ionescu (talk | contribs) (How is the NDK organized?)
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 latter is recommended.
  • 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.
  • 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;
    union
    {
        struct
        {
            UCHAR Member3:4;
            UCHAR Member4:4;
        };
        UCHAR Member5;
    }
    MEMVER_TYPE2 Member6;
} TYPENAME, *PTYPENAME;

Prototypes as follows:

RETURNTYPE
CALLING_CONVENTION
FunctionName(
    PARAM_TYPE Param1,
    PARAM_TYPE Param2
);

Similalry, function types:

typedef RETURNTYPE 
(CALLING_CONVENTION *PFUNCTION_TYPE(
    PARAM_TYPE Param1,
    PARAM_TYPE Param2
);

How is the NDK Licensed?

  • A file called COPYING at the root of the NDK directory will describe the NDK's license. This license will be OSI-Approved and will either be the w32api license, the libzlib/libpng license, the LGPL license or the BSD 2.0 License. Nevertheless, the following licensing requirements will probably be part of any license chosen:
    • 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.
        • 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 COPYRIGHT 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 COPYRIGHT 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:
 #include <windows.h>      /* Declare Windows Headers like you normally would */
 #DEFINE NTOS_MODE_USER    /* Tell the NDK that you are User Mode */
 #include <ndk/ntndk.h>    /* Declare the NDK Headers */
  • Native Mode Application:
 #DEFINE NTOS_MODE_USER    /* Tell the NDK that you are User Mode */
 #include <ndk/ntndk.h>    /* Declare the NDK Headers */
  • Kernel Mode Driver:
 #include <ddk/ntddk.h>    /* Declare DDK Headers like you normally would */
 #include <ndk/ntndk.h>    /* Declare the NDK Headers */

Some caveats

  • FIXMEs: There are still a large number of FIXMEs inside the NDK until it is ready for a 1.0 release. These have been documented into a file called FIXME at the root directory of the NDK. The goal is for all priority 1-4 bugs to be fixed before 0.3.0 in order for NDK 1.0 to be released publically.
  • winternl.h: This header, part of the PSDK, was released by Microsoft as part of one of the government lawsuits against it, and documentes 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.
  • pstypes.h: This header is a "dual-mode" header, meaning that it needs to be accessible from User-Mode, yet exports Kernel-Mode types as well; this is because it must define structures like the TEB or PEB as well as ETHREAD and EPROCESS. As such, the file is split in two and protected by the NTOS_MODE_USER definition. Please keep this in mind when adding a new Proces Manager type.
  • DDK/IFS Compatibility: Although one of its main goals, the NDK has not yet been targetted and/or tested with the official Microsoft Headers. However, a lot of work has been done to support this, and it should be a possibility soon after 1.0