/*++ BUILD Version: 0003    // Increment this if a change has global effects

Copyright (c) 1989  Microsoft Corporation

Module Name:

    ntosdef.h

Abstract:

    Common type definitions for the NTOS component that are private to
    NTOS, but shared between NTOS sub-components.

Author:

    Steve Wood (stevewo) 08-May-1989

Revision History:

--*/

#ifndef _NTOSDEF_
#define _NTOSDEF_

//
// Define alignment macros to align structure sizes up and down.
//

#define ALIGN_DOWN(address, type) ((ULONG)(address) & ~(sizeof( type ) - 1))

#define ALIGN_UP(address, type) (ALIGN_DOWN( (address + sizeof( type ) - 1), \
                                             type ))

// begin_ntddk begin_nthal begin_ntifs

#define POOL_TAGGING 1

#ifndef DBG
#define DBG 0
#endif

#if DBG
#define IF_DEBUG if (TRUE)
#else
#define IF_DEBUG if (FALSE)
#endif

#if DEVL
//
// Global flag set by NtPartyByNumber(6) controls behaviour of
// NT.  See \nt\sdk\inc\ntexapi.h for flag definitions
//

extern ULONG NtGlobalFlag;

#define IF_NTOS_DEBUG( FlagName ) \
    if (NtGlobalFlag & (FLG_ ## FlagName))

#else
#define IF_NTOS_DEBUG( FlagName ) if (FALSE)
#endif

//
// Kernel definitions that need to be here for forward reference purposes
//

// begin_ntndis
//
// Processor modes.
//

typedef CCHAR KPROCESSOR_MODE;

typedef enum _MODE {
    KernelMode,
    UserMode,
    MaximumMode
} MODE;

// end_ntndis
//
// APC function types
//

//
// Put in an empty definition for the KAPC so that the
// routines can reference it before it is declared.
//

struct _KAPC;

typedef
VOID
(*PKNORMAL_ROUTINE) (
    IN PVOID NormalContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    );

typedef
VOID
(*PKKERNEL_ROUTINE) (
    IN struct _KAPC *Apc,
    IN OUT PKNORMAL_ROUTINE *NormalRoutine,
    IN OUT PVOID *NormalContext,
    IN OUT PVOID *SystemArgument1,
    IN OUT PVOID *SystemArgument2
    );

typedef
VOID
(*PKRUNDOWN_ROUTINE) (
    IN struct _KAPC *Apc
    );

typedef
BOOLEAN
(*PKSYNCHRONIZE_ROUTINE) (
    IN PVOID SynchronizeContext
    );

typedef
BOOLEAN
(*PKTRANSFER_ROUTINE) (
    VOID
    );

//
//
// Asynchronous Procedure Call (APC) object
//

typedef struct _KAPC {
    CSHORT Type;
    CSHORT Size;
    ULONG Spare0;
    struct _KTHREAD *Thread;
    LIST_ENTRY ApcListEntry;
    PKKERNEL_ROUTINE KernelRoutine;
    PKRUNDOWN_ROUTINE RundownRoutine;
    PKNORMAL_ROUTINE NormalRoutine;
    PVOID NormalContext;

    //
    // N.B. The following two members MUST be together.
    //

    PVOID SystemArgument1;
    PVOID SystemArgument2;
    CCHAR ApcStateIndex;
    KPROCESSOR_MODE ApcMode;
    BOOLEAN Inserted;
} KAPC;

typedef KAPC *PKAPC;

// begin_ntndis
//
// DPC routine
//

struct _KDPC;

typedef
VOID
(*PKDEFERRED_ROUTINE) (
    IN struct _KDPC *Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    );

//
// Deferred Procedure Call (DPC) object
//

typedef struct _KDPC {
    CSHORT Type;
    CSHORT Size;
    LIST_ENTRY DpcListEntry;
    PKDEFERRED_ROUTINE DeferredRoutine;
    PVOID DeferredContext;
    PVOID SystemArgument1;
    PVOID SystemArgument2;
    PULONG Lock;
} KDPC, *PKDPC;

//
// I/O system definitions.
//
// Define a Memory Descriptor List (MDL)
//
// An MDL describes pages in a virtual buffer in terms of physical pages.  The
// pages associated with the buffer are described in an array that is allocated
// just after the MDL header structure itself.  In a future compiler this will
// be placed at:
//
//      ULONG Pages[];
//
// Until this declaration is permitted, however, one simply calculates the
// base of the array by adding one to the base MDL pointer:
//
//      Pages = (PULONG) (Mdl + 1);
//
// Notice that while in the context of the subject thread, the base virtual
// address of a buffer mapped by an MDL may be referenced using the following:
//
//      Mdl->StartVa | Mdl->ByteOffset
//

typedef struct _MDL {
    struct _MDL *Next;
    CSHORT Size;
    CSHORT MdlFlags;
    struct _EPROCESS *Process;
    PVOID MappedSystemVa;
    PVOID StartVa;
    ULONG ByteCount;
    ULONG ByteOffset;
} MDL, *PMDL;

#define MDL_MAPPED_TO_SYSTEM_VA     0x0001
#define MDL_PAGES_LOCKED            0x0002
#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
#define MDL_ALLOCATED_FROM_ZONE     0x0008
#define MDL_PARTIAL                 0x0010
#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
#define MDL_IO_PAGE_READ            0x0040
#define MDL_WRITE_OPERATION         0x0080
#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
#define MDL_LOCK_HELD               0x0200

#define MDL_MAPPING_FLAGS (MDL_MAPPED_TO_SYSTEM_VA |     \
                           MDL_PAGES_LOCKED |            \
                           MDL_SOURCE_IS_NONPAGED_POOL | \
                           MDL_PARTIAL_HAS_BEEN_MAPPED | \
                           MDL_PARENT_MAPPED_SYSTEM_VA | \
                           MDL_LOCK_HELD )

// end_ntndis
//
// switch to DBG when appropriate
//

#if DBG
#define PAGED_CODE() \
    if (KeGetCurrentIrql() > APC_LEVEL) { \
	KdPrint(( "EX: Pageable code called at IRQL %d\n", KeGetCurrentIrql() )); \
        ASSERT(FALSE); \
        }
#else
#define PAGED_CODE()
#endif

// end_ntddk end_nthal end_ntifs


// begin_ntifs
//
// Data structure used to represent client security context for a thread.
// This data structure is used to support impersonation.
//
//  THE FIELDS OF THIS DATA STRUCTURE SHOULD BE CONSIDERED OPAQUE
//  BY ALL EXCEPT THE SECURITY ROUTINES.
//

typedef struct _SECURITY_CLIENT_CONTEXT {
    SECURITY_QUALITY_OF_SERVICE SecurityQos;
    PACCESS_TOKEN ClientToken;
    BOOLEAN DirectlyAccessClientToken;
    BOOLEAN DirectAccessEffectiveOnly;
    BOOLEAN ServerIsRemote;
    TOKEN_CONTROL ClientTokenControl;
    } SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT;

// end_ntifs

//
// where
//
//    SecurityQos - is the security quality of service information in effect
//        for this client.  This information is used when directly accessing
//        the client's token.  In this case, the information here over-rides
//        the information in the client's token.  If a copy of the client's
//        token is requested, it must be generated using this information,
//        not the information in the client's token.  In all cases, this
//        information may not provide greater access than the information
//        in the client's token.  In particular, if the client's token is
//        an impersonation token with an impersonation level of
//        "SecurityDelegation", but the information in this field indicates
//        an impersonation level of "SecurityIdentification", then
//        the server may only get a copy of the token with an Identification
//        level of impersonation.
//
//    ClientToken - If the DirectlyAccessClientToken field is FALSE,
//        then this field contains a pointer to a duplicate of the
//        client's token.  Otherwise, this field points directly to
//        the client's token.
//
//    DirectlyAccessClientToken - This boolean flag indicates whether the
//        token pointed to by ClientToken is a copy of the client's token
//        or is a direct reference to the client's token.  A value of TRUE
//        indicates the client's token is directly accessed, FALSE indicates
//        a copy has been made.
//
//    DirectAccessEffectiveOnly - This boolean flag indicates whether the
//        the disabled portions of the token that is currently directly
//        referenced may be enabled.  This field is only valid if the
//        DirectlyAccessClientToken field is TRUE.  In that case, this
//        value supersedes the EffectiveOnly value in the SecurityQos
//        FOR THE CURRENT TOKEN ONLY!  If the client changes to impersonate
//        another client, this value may change.  This value is always
//        minimized by the EffectiveOnly flag in the SecurityQos field.
//
//    ServerIsRemote - If TRUE indicates that the server of the client's
//        request is remote.  This is used for determining the legitimacy
//        of certain levels of impersonation and to determine how to
//        track context.
//
//    ClientTokenControl - If the ServerIsRemote flag is TRUE, and the
//        tracking mode is DYNAMIC, then this field contains a copy of
//        the TOKEN_SOURCE from the client's token to assist in deciding
//        whether the information at the remote server needs to be
//        updated to match the current state of the client's security
//        context.
//
//
//    NOTE: At some point, we may find it worthwhile to keep an array of
//          elements in this data structure, where each element of the
//          array contains {ClientToken, ClientTokenControl} fields.
//          This would allow efficient handling of the case where a client
//          thread was constantly switching between a couple different
//          contexts - presumably impersonating client's of its own.
//

#endif // _NTOSDEF_
