/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    afdstr.h

Abstract:

    This module contains typedefs for structures used by AFD.

Author:

    David Treadwell (davidtr)    21-Feb-1992

Revision History:

--*/

#ifndef _AFDSTR_
#define _AFDSTR_

//
// This field defines the layout of a 32-bit pointer.
// This must be ULONG as wow64 support 4gb address on win64.
// You shouldn't POINTER_32 as this will sign-extend addresses when converting
// it to a 64-bit pointer and will end up having the wrong address.
//
typedef ULONG AFD_POINTER_32;

//
// Make sure that queued spinlocks are not used with
// regular spinlock functions by wrapping them into
// a different structure.
//
typedef struct _AFD_QSPIN_LOCK {
    KSPIN_LOCK  ActualSpinLock;
} AFD_QSPIN_LOCK, *PAFD_QSPIN_LOCK;

#if DBG

#ifndef REFERENCE_DEBUG
#define REFERENCE_DEBUG 1
#endif

#ifndef GLOBAL_REFERENCE_DEBUG
#define GLOBAL_REFERENCE_DEBUG 0
#endif

//
// Debug aid for queued spinlocks
// Allows us to verify that spinlock is released using
// the same handle as it was taken with.
//
typedef struct _AFD_LOCK_QUEUE_HANDLE {
    KLOCK_QUEUE_HANDLE  LockHandle;
    PAFD_QSPIN_LOCK     SpinLock;
} AFD_LOCK_QUEUE_HANDLE, *PAFD_LOCK_QUEUE_HANDLE;

#else

#ifndef REFERENCE_DEBUG
#define REFERENCE_DEBUG 0
#endif

#ifndef GLOBAL_REFERENCE_DEBUG
#define GLOBAL_REFERENCE_DEBUG 0
#endif

#define AFD_LOCK_QUEUE_HANDLE KLOCK_QUEUE_HANDLE
#define PAFD_LOCK_QUEUE_HANDLE PKLOCK_QUEUE_HANDLE

#endif // DBG

#if REFERENCE_DEBUG

#define AFD_REF_SHIFT       6
#define AFD_REF_MASK        ((1<<AFD_REF_SHIFT)-1)
#define AFD_MAX_REF         (1<<AFD_REF_SHIFT)
#define AFD_REF_TIME_BITS   16
#define AFD_MAX_REF_TIME    ((1<<AFD_REF_TIME_BITS)-1)
#define AFD_TIME_EXP_SHIFT  4
#define AFD_TIME_EXP_BITS   2
#define AFD_REF_CNT_BITS    4
#define AFD_REF_LOC_BITS    (32-AFD_REF_CNT_BITS-AFD_REF_TIME_BITS-AFD_TIME_EXP_BITS)

C_ASSERT (32-AFD_REF_SHIFT-AFD_REF_TIME_BITS <=
          AFD_TIME_EXP_SHIFT*((1<<AFD_TIME_EXP_BITS)-1));

typedef union _AFD_REFERENCE_DEBUG {
    struct {
        ULONGLONG   NewCount:AFD_REF_CNT_BITS;
        ULONGLONG   LocationId:AFD_REF_LOC_BITS;
        ULONGLONG   TimeExp:AFD_TIME_EXP_BITS;
        ULONGLONG   TimeDif:AFD_REF_TIME_BITS;
        ULONGLONG   Param:32;
    };
    ULONGLONG       QuadPart;
} AFD_REFERENCE_DEBUG, *PAFD_REFERENCE_DEBUG;
C_ASSERT (sizeof (AFD_REFERENCE_DEBUG)==sizeof (ULONGLONG));

typedef struct _AFD_REFERENCE_LOCATION {
    PCHAR       Format;
    PVOID       Address;
} AFD_REFERENCE_LOCATION, *PAFD_REFERENCE_LOCATION;

LONG
AfdFindReferenceLocation (
    IN  PCHAR   Format,
    OUT PLONG   LocationId
    );

#define AFD_GET_ARL(_s) (_arl ? _arl : AfdFindReferenceLocation((_s),&_arl))

#define AFD_UPDATE_REFERENCE_DEBUG(_rd,_r,_l,_p)                            \
        do {                                                                \
            LONG _n, _n1;                                                   \
            ULONGLONG _t = KeQueryInterruptTime ();                         \
            _n = (_rd)->CurrentReferenceSlot;                               \
            _n1 = (((LONG)(_t>>13))<<AFD_REF_SHIFT) + ((_n+1)&AFD_REF_MASK);\
            if (InterlockedCompareExchange (&(_rd)->CurrentReferenceSlot,   \
                                            _n1,_n)==_n) {                  \
                PAFD_REFERENCE_DEBUG _s;                                    \
                LONG    _d,_e=0;                                            \
                (_rd)->CurrentTimeHigh = (LONG)(_t>>(13+32-AFD_REF_SHIFT)); \
                _s = &(_rd)->ReferenceDebug[_n & AFD_REF_MASK];             \
                _s->NewCount = _r;                                          \
                _s->LocationId = _l;                                        \
                _s->Param = _p;                                             \
                _d = (_n1-1-_n) >> AFD_REF_SHIFT;                           \
                while (_d>=AFD_MAX_REF_TIME) {                              \
                    _e += 1;                                                \
                    _d >>= _e*AFD_TIME_EXP_SHIFT;                           \
                }                                                           \
                _s->TimeDif = _d;                                           \
                _s->TimeExp = _e;                                           \
                break;                                                      \
            }                                                               \
        } while (1)


#if GLOBAL_REFERENCE_DEBUG
#define MAX_GLOBAL_REFERENCE 4096

typedef struct _AFD_GLOBAL_REFERENCE_DEBUG {
    PVOID Info1;
    PVOID Info2;
    PVOID Connection;
    ULONG_PTR Action;
    LARGE_INTEGER TickCounter;
    ULONG NewCount;
    ULONG Dummy;
} AFD_GLOBAL_REFERENCE_DEBUG, *PAFD_GLOBAL_REFERENCE_DEBUG;
#endif

#endif

//
// A structure for maintaining work queue information in AFD.
//

typedef struct _AFD_WORK_ITEM {
    LIST_ENTRY WorkItemListEntry;
    PWORKER_THREAD_ROUTINE AfdWorkerRoutine;
    PVOID Context;
} AFD_WORK_ITEM, *PAFD_WORK_ITEM;

//
// Structures for holding connect data pointers and lengths.  This is
// kept separate from the normal structures to save space in those
// structures for transports that do not support and applications
// which do not use connect data.
//

typedef struct _AFD_CONNECT_DATA_INFO {
    PVOID Buffer;
    ULONG BufferLength;
} AFD_CONNECT_DATA_INFO, *PAFD_CONNECT_DATA_INFO;

typedef struct _AFD_CONNECT_DATA_BUFFERS {
    AFD_CONNECT_DATA_INFO SendConnectData;
    AFD_CONNECT_DATA_INFO SendConnectOptions;
    AFD_CONNECT_DATA_INFO ReceiveConnectData;
    AFD_CONNECT_DATA_INFO ReceiveConnectOptions;
    AFD_CONNECT_DATA_INFO SendDisconnectData;
    AFD_CONNECT_DATA_INFO SendDisconnectOptions;
    AFD_CONNECT_DATA_INFO ReceiveDisconnectData;
    AFD_CONNECT_DATA_INFO ReceiveDisconnectOptions;
    TDI_CONNECTION_INFORMATION RequestConnectionInfo;
    TDI_CONNECTION_INFORMATION ReturnConnectionInfo;
    ULONG Flags;
} AFD_CONNECT_DATA_BUFFERS, *PAFD_CONNECT_DATA_BUFFERS;

//
// Structure used for holding disconnect context information.
//

typedef struct _AFD_ENDPOINT AFD_ENDPOINT, *PAFD_ENDPOINT;
typedef struct _AFD_CONNECTION AFD_CONNECTION, *PAFD_CONNECTION;

typedef struct _AFD_TPACKETS_INFO_INTERNAL 
                AFD_TPACKETS_INFO_INTERNAL,
                *PAFD_TPACKETS_INFO_INTERNAL;

typedef DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)
             struct _AFD_BUFFER 
                    AFD_BUFFER, 
                    *PAFD_BUFFER;

typedef struct _AFD_DISCONNECT_CONTEXT {
    LARGE_INTEGER Timeout;
    PIRP          Irp;
} AFD_DISCONNECT_CONTEXT, *PAFD_DISCONNECT_CONTEXT;


typedef struct _AFD_LR_LIST_ITEM AFD_LR_LIST_ITEM, *PAFD_LR_LIST_ITEM;
typedef BOOLEAN (* PAFD_LR_LIST_ROUTINE) (PAFD_LR_LIST_ITEM Item);

struct _AFD_LR_LIST_ITEM {
    SLIST_ENTRY             SListLink;    // Link in the list
    PAFD_LR_LIST_ROUTINE    Routine;      // Processing routine;
};


//
// Endpoint and connection structures and related informaion.
//
//
// Block types that identify which fields are
// available in the strucutures.
//

#define AfdBlockTypeEndpoint            0xAFD0  // VC endpoint before connect/accept/listen
#define AfdBlockTypeDatagram            0xAFD1  // Datagram endpoint in any state
#define AfdBlockTypeVcConnecting        0xAFD2  // VC endpoint after connect/accept
#define AfdBlockTypeVcListening         0xAFD4  // VC endpoint after listen
#define AfdBlockTypeVcBoth              0xAFD6  // VC endpoint after connect+listen
                                                // (used in multipoint root cases)


#define AfdBlockTypeHelper              0xAAFD  // Regular helper endpoint
#define AfdBlockTypeSanHelper           0x0AFD  // SAN helper endpoint
#define AfdBlockTypeSanEndpoint         0x1AFD  // SAN endpoint

#define AfdBlockTypeInvalidEndpoint     0xCAFD  // Right before we call ExFreePool

#define AfdBlockTypeConnection          0xAFD8  // Connection object
#define AfdBlockTypeInvalidConnection   0xEAFD  // Right before we call ExFreePool


#if DBG
#define IS_AFD_ENDPOINT_TYPE( endpoint )                         \
            ( (endpoint)->Type == AfdBlockTypeEndpoint ||        \
              (endpoint)->Type == AfdBlockTypeDatagram ||        \
              (endpoint)->Type == AfdBlockTypeVcConnecting ||    \
              (endpoint)->Type == AfdBlockTypeVcListening ||     \
              (endpoint)->Type == AfdBlockTypeVcBoth ||          \
              (endpoint)->Type == AfdBlockTypeHelper ||          \
              (endpoint)->Type == AfdBlockTypeSanHelper ||       \
              (endpoint)->Type == AfdBlockTypeSanEndpoint )
#endif

enum {
    AfdConnectionStateFree          = 0,    // On free/AcceptEx/DelayedAccept list
    AfdConnectionStateUnaccepted    = 1,    // On unaccepted list
    AfdConnectionStateReturned      = 2,    // On returned list
    AfdConnectionStateConnected     = 3,    // Accepted or connected
    AfdConnectionStateClosing       = 4     // Not  used anymore
};

//
// Flags that further qualify the state of the connection
//
typedef struct AFD_CONNECTION_STATE_FLAGS {
    union {
        struct {
            LOGICAL TdiBufferring:1,    // (Does not really belon here)
                    :3,                 // This spacing makes strcutures
                                        // much more readable (hex) in the 
                                        // debugger and has no effect
                                        // on the generated code as long
                                        // as number of flags is less than
                                        // 8 (we still take up full 32 bits
                                        // because of aligment requiremens
                                        // of most other fields)
                    Aborted:1,
                    AbortIndicated:1,
                    AbortFailed:1,
                    :1,
                    DisconnectIndicated:1,
                    :3,
                    ConnectedReferenceAdded:1,
                    :3,
                    SpecialCondition:1,
                    :3,
                    CleanupBegun:1,
                    :3,
                    ClosePendedTransmit:1,
                    :3,
                    OnLRList:1,         // Low-resource list
                    SanConnection:1,
                    RcvInitiated:1,     // AFD initiated receive to transport.
                    :1;
        };
        LOGICAL     ConnectionStateFlags;
    };
} AFD_CONNECTION_STATE_FLAGS;
C_ASSERT (sizeof (AFD_CONNECTION_STATE_FLAGS)==sizeof (LOGICAL));

struct _AFD_CONNECTION {
    // *** Frequently used, mostly read-only fields (state/type/flag changes are rare).
    USHORT Type;
    USHORT State;
    AFD_CONNECTION_STATE_FLAGS
#ifdef __cplusplus
        StateFlags
#endif
        ;

    PAFD_ENDPOINT Endpoint;
    PFILE_OBJECT FileObject;
    PDEVICE_OBJECT DeviceObject;
    PEPROCESS   OwningProcess;


    union {
        LONGLONG ConnectTime;   // After connection is accepted.
        PIRP     AcceptIrp;     // For AcceptEx
        PIRP     ListenIrp;     // For delayed accept
        PIRP     ConnectIrp;    // for SAN
    };

    // *** Frequently used volatile fields.
    volatile LONG ReferenceCount;

    union {

        struct {
            LARGE_INTEGER ReceiveBytesIndicated;
            LARGE_INTEGER ReceiveBytesTaken;
            LARGE_INTEGER ReceiveBytesOutstanding;

            LARGE_INTEGER ReceiveExpeditedBytesIndicated;
            LARGE_INTEGER ReceiveExpeditedBytesTaken;
            LARGE_INTEGER ReceiveExpeditedBytesOutstanding;
            BOOLEAN NonBlockingSendPossible;
            BOOLEAN ZeroByteReceiveIndicated;
        } Bufferring;

        struct {
            LIST_ENTRY ReceiveIrpListHead;
            LIST_ENTRY ReceiveBufferListHead;

            ULONG BufferredReceiveBytes;
            ULONG BufferredExpeditedBytes;

            USHORT BufferredReceiveCount;
            USHORT BufferredExpeditedCount;
            ULONG ReceiveBytesInTransport;

            LIST_ENTRY SendIrpListHead;
            
            ULONG BufferredSendBytes;
            ULONG BufferredSendCount;

            PIRP DisconnectIrp;

            LONG  ReceiveIrpsInTransport;   // debug only.
        } NonBufferring;

    } Common;


    ULONG MaxBufferredReceiveBytes;
    ULONG MaxBufferredSendBytes;

    PTRANSPORT_ADDRESS RemoteAddress;
    ULONG RemoteAddressLength;
    LONG    Sequence;

    HANDLE Handle;                          // Ref count protection



    union {
        AFD_WORK_ITEM           WorkItem;   // Work item to free the connection
                                            // Connection has to be at ref 0 to be
                                            // on the work queue, so it cannot be
                                            // on the lists below or being disconnected
                                            // because when on any of these lists the
                                            // ref count is above 0.
        struct {
            union {
                AFD_DISCONNECT_CONTEXT  DisconnectContext;
                                            // Disconnect operation context, we cannot be
                                            // on the listening endpoint list
                SLIST_ENTRY             SListEntry;
                                            // Links for listening endpoint lists
                LIST_ENTRY              ListEntry;
            };
            AFD_LR_LIST_ITEM    LRListItem; // Link for low resource list. When on this
                                            // list connection is referenced, but it can
                                            // also be on the listening endpoint list or
                                            // in the process of disconnecting.
        };
    };

    PAFD_CONNECT_DATA_BUFFERS ConnectDataBuffers;

#if REFERENCE_DEBUG
    LONG CurrentTimeHigh;
    volatile LONG CurrentReferenceSlot;
    AFD_REFERENCE_DEBUG ReferenceDebug[AFD_MAX_REF];
#endif

#ifdef _AFD_VERIFY_DATA_
    ULONGLONG VerifySequenceNumber;
#endif // _AFD_VERIFY_DATA_
};
// Fields of the AFD_CONNECTION are protected by the endpoint
// spinlock, except:
//  Type, FileObject, DeviceObject, OwningProcess, Handle which are
//      only set once and cleared when reference count goes to 0
// Endpoint field itself (and thus the spinlock) can change though.
//  - it is NULL when connection is on listening endpoint backlog
//      and connection cannot be referenced outside of listening endpoint.
//  - when it is assigned to listening endpoint it cannot change outside 
//      of listening endpoint spinlock
//  - when it is assigned to connecting/accepting endpoint, it cannot
//      change at all until reference count drops to 0 and
//      connection is again placed on listening endpoint backlog or
//      destroyed.
//  ReferenceCount only updated via interlocked operations.
//

#ifdef _AFD_VERIFY_DATA_
VOID
AfdVerifyBuffer (
    PAFD_CONNECTION Connection,
    PVOID           Buffer,
    ULONG           Length
    );
VOID
AfdVerifyMdl (
    PAFD_CONNECTION Connection,
    PMDL            Mdl,
    ULONG           Offset,
    ULONG           Length
    );
VOID
AfdVerifyAddress (
    PAFD_CONNECTION Connection,
    PTRANSPORT_ADDRESS Address
    );

#define AFD_VERIFY_BUFFER(_connection,_buffer,_length) \
            AfdVerifyBuffer(_connection,_buffer,_length)
#define AFD_VERIFY_MDL(_connection,_mdl,_offset,_length) \
            AfdVerifyMdl(_connection,_mdl,_offset,_length)
#define AFD_VERIFY_ADDRESS(_connection,_address) \
            AfdVerifyAddress(_connection,_address)
#else
#define AFD_VERIFY_BUFFER(_connection,_buffer,_length)
#define AFD_VERIFY_MDL(_connection,_mdl,_offset,_length)
#define AFD_VERIFY_ADDRESS(_connection,_address)
#endif // _AFD_VERIFY_DATA_

//
// Some macros that make code more readable.
//

#define VcNonBlockingSendPossible Common.Bufferring.NonBlockingSendPossible
#define VcZeroByteReceiveIndicated Common.Bufferring.ZeroByteReceiveIndicated

#define VcReceiveIrpListHead Common.NonBufferring.ReceiveIrpListHead
#define VcReceiveBufferListHead Common.NonBufferring.ReceiveBufferListHead
#define VcSendIrpListHead Common.NonBufferring.SendIrpListHead

#define VcBufferredReceiveBytes Common.NonBufferring.BufferredReceiveBytes
#define VcBufferredExpeditedBytes Common.NonBufferring.BufferredExpeditedBytes
#define VcBufferredReceiveCount Common.NonBufferring.BufferredReceiveCount
#define VcBufferredExpeditedCount Common.NonBufferring.BufferredExpeditedCount

#define VcReceiveBytesInTransport Common.NonBufferring.ReceiveBytesInTransport
#if DBG
#define VcReceiveIrpsInTransport Common.NonBufferring.ReceiveIrpsInTransport
#endif

#define VcBufferredSendBytes Common.NonBufferring.BufferredSendBytes
#define VcBufferredSendCount Common.NonBufferring.BufferredSendCount

#define VcDisconnectIrp Common.NonBufferring.DisconnectIrp

//
// Information stored about each transport device name for which there
// is an open endpoint.
//
typedef
NTSTATUS
(FASTCALL *PIO_CALL_DRIVER) (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

typedef
PAFD_BUFFER
(FASTCALL *PAFD_GET_BUFFER) (
    IN ULONG    BufferDataSize,
    IN ULONG  AddressSize,
    IN PEPROCESS Process
);

typedef
PAFD_TPACKETS_INFO_INTERNAL
(FASTCALL *PAFD_GET_TPINFO) (
    IN ULONG    ElementCount
);

typedef struct _AFD_TRANSPORT_INFO {
    LIST_ENTRY TransportInfoListEntry;
    volatile LONG ReferenceCount;
    BOOLEAN InfoValid;
#ifdef _AFD_VARIABLE_STACK_
    CCHAR   StackSize;
    PAFD_GET_BUFFER GetBuffer;
    PAFD_GET_TPINFO GetTpInfo;
    PIO_CALL_DRIVER CallDriver;
#endif // _AFD_VARIABLE_STACK_
    UNICODE_STRING TransportDeviceName;
    TDI_PROVIDER_INFO ProviderInfo;
    //WCHAR TransportDeviceNameStructure;
} AFD_TRANSPORT_INFO, *PAFD_TRANSPORT_INFO;

//
// Endpoint state definitions (can't be <=0 or state change
// macros won't work correctly).
//
enum {
    AfdEndpointStateOpen             =1,    // Socket created but no yet bound
    AfdEndpointStateBound            =2,
    AfdEndpointStateConnected        =3,
    AfdEndpointStateCleanup          =4,    // Not used anymore
    AfdEndpointStateClosing          =5,
    AfdEndpointStateTransmitClosing  =6,    // TransmitFile with reuse
    AfdEndpointStateInvalid          =7     // Helper endpoints
};

//
// Flags that further qualify the state of the endpoint
//
typedef struct AFD_ENDPOINT_STATE_FLAGS {
    union {
        struct {
            LOGICAL Listening:1,
                    DelayedAcceptance:1,
                    :2,                 // This spacing makes strcutures
                                        // much more readable (hex) in the 
                                        // debugger and has no effect
                                        // on the generated code as long
                                        // as number of flags is less than
                                        // 8 (we still take up full 32 bits
                                        // because of aligment requiremens
                                        // of most other fields)
                    NonBlocking:1,
                    :3,
                    InLine:1,
                    :3,
                    EndpointCleanedUp:1,
                    :3,
                    PollCalled:1,
                    :3,
                    RoutingQueryReferenced:1,
                    RoutingQueryIPv6:1,
                    :2,
                    DisableFastIoSend:1,
                    EnableSendEvent:1,
                    :2,
                    DisableFastIoRecv:1,
                    :3;
        };
        LOGICAL     EndpointStateFlags;
    };
} AFD_ENDPOINT_STATE_FLAGS;
C_ASSERT (sizeof (AFD_ENDPOINT_STATE_FLAGS)==sizeof (LOGICAL));

struct _AFD_ENDPOINT {
    // *** Frequently used, mostly read-only fields (state/type/flag changes are rare).
    USHORT  Type;
    UCHAR   State;
    BOOLEAN AdminAccessGranted;
    ULONG   TdiServiceFlags;        // Tdi transport flags cached for quick access.

    AFD_ENDPOINT_FLAGS __f;         // As requested by the application through the
                                    // Winsock2 provider flags and/or socket type
    AFD_ENDPOINT_STATE_FLAGS 
#ifdef __cplusplus
        StateFlags
#endif
        ;
    PFILE_OBJECT    AddressFileObject;
    union {
        PDEVICE_OBJECT  AddressDeviceObject;
        PSECURITY_DESCRIPTOR SecurityDescriptor; // Only
    };
    PEPROCESS       OwningProcess;

    // *** Frequently used volatile fields.
    AFD_QSPIN_LOCK  SpinLock;       // Pointer sized.
    volatile LONG ReferenceCount;
    ULONG EventsActive;

    //
    // Use a union to overlap the fields that are exclusive to datagram
    // connecting, or listening endpoints.  Since many fields are
    // relevant to only one type of socket, it makes no sense to
    // maintain the fields for all sockets--instead, save some nonpaged
    // pool by combining them.
    //

    union {
        //
        // Information for circuit-based endpoints
        //
        struct {
            union {
                struct {
                    // These members are valid for listening endpoints
                    // (AfdBlockTypeVcListening).
                    LIST_ENTRY UnacceptedConnectionListHead;
                    LIST_ENTRY ReturnedConnectionListHead;
                    LIST_ENTRY ListeningIrpListHead;

                    // The below lists have their own lock which gets
                    // used on the machines that do not support 64-bit
                    // interlocked compare and exchange.  On these machines
                    // using endpoint spinlock to synchronize causes all kinds
                    // of nasty deadlock conditions.
                    union {
                        LIST_ENTRY  ListenConnectionListHead; // Delayed accept
                        SLIST_HEADER FreeConnectionListHead;
                    };
                    SLIST_HEADER PreacceptedConnectionsListHead;

                    LONG FailedConnectionAdds;
                    LONG TdiAcceptPendingCount;

                    LONG Sequence;
                    BOOLEAN EnableDynamicBacklog;
                    BOOLEAN BacklogReplenishActive; // Worker is scheduled
                    USHORT  MaxExtraConnections;  // Extra connections we keep in the free queue
                                                  // based on maximum number of AcceptEx requests
                } Listening;
                struct {
                    KAPC    Apc;
                    USHORT  RemoteSocketAddressOffset;  // Offset inside of socket context
                                                        // pointing to remote address.
                    USHORT  RemoteSocketAddressLength;  // Length of the address.
#ifndef i386
                    BOOLEAN FixAddressAlignment;        // Fix address alignment in
                                                        // SuperAccept
#endif
                };
            };
            // These members are valid for all vc endpoints (but
            // can be NULL)
            PAFD_CONNECTION Connection;
            struct _AFD_ENDPOINT *ListenEndpoint;
            PAFD_CONNECT_DATA_BUFFERS ConnectDataBuffers;
        } VirtualCircuit;

#define VcConnecting    VirtualCircuit
#define VcListening     VirtualCircuit.Listening
#define VcConnection    VirtualCircuit.Connection
        //
        // Information for datagram endpoints.  Note that different
        // information is kept depending on whether the underlying
        // transport buffers internally.
        //

        struct {
            LIST_ENTRY ReceiveIrpListHead;
            LIST_ENTRY PeekIrpListHead;
            LIST_ENTRY ReceiveBufferListHead;

            ULONG BufferredReceiveBytes;
            ULONG BufferredReceiveCount;

            ULONG MaxBufferredReceiveBytes;
            ULONG BufferredSendBytes;
            ULONG MaxBufferredSendBytes;


            ULONG RemoteAddressLength;
            PTRANSPORT_ADDRESS RemoteAddress;

            union {
                struct {
                    LOGICAL CircularQueueing:1,
                        :3,
                        HalfConnect:1,
                        :3,
                        DisablePUError:1,
                        :3,
                        AddressDrop:1,
                        ResourceDrop:1,
                        BufferDrop:1,
                        ErrorDrop:1;
                };
                LOGICAL Flags;
            };
        } Datagram;

        struct {
            LIST_ENTRY SanListLink;
            PVOID   IoCompletionPort;
            PKEVENT IoCompletionEvent;
            LONG    Plsn;   // Provider list sequence number
            LONG    PendingRequests; // Number of pending requests to this process 
        } SanHlpr;

        struct {
            struct _AFD_ENDPOINT *SanHlpr;
            PFILE_OBJECT FileObject;
            union {
                //
                // We can only have either one of two at any given time.
                //
                PAFD_SWITCH_CONTEXT  SwitchContext;
                PVOID       SavedContext;
            };
            PAFD_SWITCH_CONTEXT  LocalContext;
            LIST_ENTRY  IrpList;
            ULONG       SavedContextLength;
            ULONG       RequestId;
            ULONG       SelectEventsActive;
            NTSTATUS    CtxTransferStatus;
            BOOLEAN     ImplicitDup; // Dup-ed into another process without
                                     // explicit request from the applicaiton
                                        
        } SanEndp;

    } Common;


    volatile PVOID Context;
    ULONG ContextLength;

    ULONG LocalAddressLength;
    PTRANSPORT_ADDRESS LocalAddress;

    ULONG DisconnectMode;
    LONG  OutstandingIrpCount;

    HANDLE  AddressHandle;      // TDI transport address object
    PAFD_TRANSPORT_INFO TransportInfo;

    LIST_ENTRY RoutingNotifications;  // For non-blocking sockets
    LIST_ENTRY RequestList;         // For misc requests

    LIST_ENTRY GlobalEndpointListEntry;
    AFD_WORK_ITEM   WorkItem;
    PIRP            Irp;        // AcceptEx or TransmitPackets IRP
    //
    // Non-zero when state change such as binding, accepting,
    // conntecting, and transmit file are in progress.
    LONG  StateChangeInProgress;

    //
    // EventSelect info.
    //

    ULONG EventsEnabled;
    NTSTATUS EventStatus[AFD_NUM_POLL_EVENTS]; // Currently 13 events
    PKEVENT EventObject;

    //
    // Socket grouping.
    //

    LONG GroupID;
    AFD_GROUP_TYPE GroupType;
    LIST_ENTRY ConstrainedEndpointListEntry;

    //
    // Debug stuff.
    //

#if REFERENCE_DEBUG
    LONG CurrentTimeHigh;
    LONG CurrentReferenceSlot;
    AFD_REFERENCE_DEBUG ReferenceDebug[AFD_MAX_REF];
#endif

#if DBG
    LIST_ENTRY OutstandingIrpListHead;
    LONG ObReferenceBias;
#endif
};
// Fields AFD_ENDPOINT structure are protected by the embedded
// spinlock, except:
// AdminAccessGranted, TdiServiceFlags, __f, OwningProcess, TransportInfo,
//  IoCompletionPort, IoCompletionEvent, AddressHandle which are
//  set once and are not touched until reference count goes to 0
// Type, State, LocalAddress, LocalAddressLength, AddressFileObject,
//  AddressDeviceObject, AddressHandle, TdiServiceFlags are protected by the 
//  StateChange interlocked mutex (AddressHandle and TdiServiceFlags can only be set
//  once under the mutex).
// AddressFileObject,AddressDeviceObject,LocalAddress, LocalAddressLength can only be 
//  reset to NULL under the endpoint spinlock in case of TransmitFile (REUSE) on
//  accepting endpoint (StateChange protection still applies).
// Counters: ReferenceCount, FailedConnectionAdds, TdiAcceptPendingCount,
//  Sequence, PendingRequests, SelectEventsActive are accessed with interlocked operations.
// Context, ContextLength, SwitchContext, SavedContext, LocalContext,
//  SavedContextLength, RemoveSocketAddressOffset, RemoteSocketAddressLength
//  are protected by the context lock (AfdLockContext).


typedef struct _AFD_POLL_ENDPOINT_INFO {
    PAFD_ENDPOINT Endpoint;
    PFILE_OBJECT FileObject;
    HANDLE Handle;
    ULONG PollEvents;
} AFD_POLL_ENDPOINT_INFO, *PAFD_POLL_ENDPOINT_INFO;

typedef struct _AFD_POLL_INFO_INTERNAL {
    LIST_ENTRY PollListEntry;
    ULONG NumberOfEndpoints;
    PIRP Irp;
    union {
        struct {
            KDPC Dpc;
            KTIMER Timer;
        };
        KAPC    Apc;            // for SAN
    };
    BOOLEAN Unique;
    BOOLEAN TimerStarted;
    BOOLEAN SanPoll;
    AFD_POLL_ENDPOINT_INFO EndpointInfo[1];
} AFD_POLL_INFO_INTERNAL, *PAFD_POLL_INFO_INTERNAL;

//
// A couple of useful manifests that make code more readable.
//

#define ReceiveDatagramIrpListHead Common.Datagram.ReceiveIrpListHead
#define PeekDatagramIrpListHead Common.Datagram.PeekIrpListHead
#define ReceiveDatagramBufferListHead Common.Datagram.ReceiveBufferListHead
#define DgBufferredReceiveCount Common.Datagram.BufferredReceiveCount
#define DgBufferredReceiveBytes Common.Datagram.BufferredReceiveBytes
#define DgBufferredSendBytes Common.Datagram.BufferredSendBytes

#define AFD_CONNECTION_FROM_ENDPOINT( endpoint ) (  \
        (((endpoint)->Type & AfdBlockTypeVcConnecting)==AfdBlockTypeVcConnecting) \
            ? (endpoint)->Common.VirtualCircuit.Connection                        \
            : (PAFD_CONNECTION)NULL                                               \
     )

//
// A structure which describes buffers used by AFD to perform bufferring
// for TDI providers which do not perform internal bufferring.
// It is also used in other code path as buffer descriptors.
//
typedef struct _AFD_BUFFER_HEADER AFD_BUFFER_HEADER, *PAFD_BUFFER_HEADER;

#define _AFD_BUFFER_HEADER_                                                    \
    union {                                                                    \
      TDI_CONNECTION_INFORMATION TdiInfo; /*holds info for TDI requests */     \
                                          /*with remote address */             \
      struct {                                                                 \
        union {           /* Links */                                          \
          struct {                                                             \
            union {                                                            \
              SINGLE_LIST_ENTRY SList; /* for buffer lookaside lists */        \
              PAFD_BUFFER_HEADER  Next; /* for transmit packet lists */        \
            };                                                                 \
            PFILE_OBJECT FileObject; /* for cached file in transmit file */    \
          };                                                                   \
          LIST_ENTRY BufferListEntry; /* for endpoint/connection lists */      \
        };                                                                     \
        union {                                                                \
          struct {                                                             \
            ULONG   DataOffset;   /* offset in buffer to start of unread data*/\
            union {                                                            \
              ULONG   DatagramFlags;/* flags for datagrams with control info */\
              LONG    RefCount; /* Permit partial copy outside the lock*/      \
            };                                                                 \
          };                                                                   \
          LARGE_INTEGER FileOffset;/* data offset from the start of the file */\
        };                                                                     \
        UCHAR       _Test; /* used to test relative field pos in the union */  \
      };                                                                       \
    };                                                                         \
    union {                                                                    \
      PVOID     Context; /* stores context info (endp/conn/etc)*/              \
      NTSTATUS  Status;/* stores status of completed operation */              \
    };                                                                         \
    PMDL        Mdl;             /* pointer to an MDL describing the buffer*/  \
    ULONG       DataLength;      /* actual data in the buffer */               \
    ULONG       BufferLength;    /* amount of space allocated for the buffer */\
    union {                                                                    \
      struct {                                                                 \
        /* Flags that describe data in the buffer */                           \
        UCHAR   ExpeditedData:1, /* The buffer contains expedited data*/       \
                :3,                                                            \
                PartialMessage:1,/* This is a partial message*/                \
                :3;                                                            \
        /* Flags that keep allocation information */                           \
        UCHAR   NdisPacket:1,    /* Context is a packet to return to NDIS/TDI*/\
                :3,                                                            \
                Placement:2,     /* Relative placement of the pieces */        \
                AlignmentAdjusted:1, /* MM block alignment was adjusted to */  \
                                 /* meet AFD buffer alignment requirement */   \
                Lookaside:1;     /* Poped from Slist (no quota charge)*/       \
      };                                                                       \
      USHORT    Flags;                                                         \
    };                                                                         \
    USHORT      AllocatedAddressLength/* length allocated for address */       \


struct _AFD_BUFFER_HEADER {
    _AFD_BUFFER_HEADER_ ;
};

//
// The buffer management code makes the following assumptions
// about the union at the top the buffer header so that list
// links and DataOffset field are not in conflict with
// RemoteAddress fields of the TDI_CONNECTION_INFORMATION.
//
C_ASSERT (FIELD_OFFSET (AFD_BUFFER_HEADER, TdiInfo.RemoteAddress) >=
                            FIELD_OFFSET (AFD_BUFFER_HEADER, _Test));
C_ASSERT (FIELD_OFFSET (AFD_BUFFER_HEADER, TdiInfo.RemoteAddressLength)>=
                            FIELD_OFFSET (AFD_BUFFER_HEADER, _Test));

C_ASSERT(FIELD_OFFSET (AFD_BUFFER_HEADER, AllocatedAddressLength)==
                FIELD_OFFSET(AFD_BUFFER_HEADER, Flags)+sizeof (USHORT));

typedef struct AFD_BUFFER_TAG {
    union {
        struct {
            _AFD_BUFFER_HEADER_;    // easy access to individual members
        };
        AFD_BUFFER_HEADER Header;   // access to the header as a whole
    };
#if DBG
    PVOID Caller;
    PVOID CallersCaller;
#endif
    // UCHAR Address[];            // address of datagram sender
} AFD_BUFFER_TAG, *PAFD_BUFFER_TAG;

struct _AFD_BUFFER {
    union {
        struct {
            _AFD_BUFFER_HEADER_;    // easy access to individual members
        };
        AFD_BUFFER_HEADER Header;   // access to the header as a whole
    };
    PIRP Irp;                      // pointer to the IRP associated w/the buffer
    PVOID Buffer;                  // a pointer to the actual data buffer

#if DBG
    LIST_ENTRY DebugListEntry;
    PVOID Caller;
    PVOID CallersCaller;
#endif
    // IRP Irp;                    // the IRP follows this structure
    // MDL Mdl;                    // the MDL follows the IRP
    // UCHAR Address[];            // address of datagram sender
    // UCHAR Buffer[BufferLength]; // the actual data buffer is last
} ;

//
// Placement of pieces that comprise the AFD_BUFFER.
// We have four pieces: header, IRP, MDL, data buffer
// and use 2 bits to encode each.
// We need to save the first piece so we know where the memory block
// starts when we need to return it to the memory manager.
//
enum {
    AFD_PLACEMENT_HDR      =0,
    AFD_PLACEMENT_IRP      =1,
    AFD_PLACEMENT_MDL      =2,
    AFD_PLACEMENT_BUFFER   =3,
    AFD_PLACEMENT_HDR_IRP  =(AFD_PLACEMENT_HDR|(AFD_PLACEMENT_IRP<<2)),
    AFD_PLACEMENT_HDR_MDL  =(AFD_PLACEMENT_HDR|(AFD_PLACEMENT_MDL<<2)),
    AFD_PLACEMENT_IRP_MDL  =(AFD_PLACEMENT_IRP|(AFD_PLACEMENT_MDL<<2)),
    AFD_PLACEMENT_HDR_IRP_MDL=(AFD_PLACEMENT_HDR|(AFD_PLACEMENT_IRP<<2)|(AFD_PLACEMENT_MDL<<4))
};


//
// ALIGN_DOWN_A aligns to given alignment requirement
// (as opposed to the type in the original ALIGN_DOWN macro)
//
#define ALIGN_DOWN_A(length,alignment)   \
    (((ULONG)(length)) & ~ ((alignment)-1))

//
// ALIGN_DOWN_A for pointers.
//
#define ALIGN_DOWN_A_POINTER(address,alignment)  \
    ((PVOID)(((ULONG_PTR)(address)) & ~ ((ULONG_PTR)(alignment)-1)))


//
// ALIGN_UP_A aligns to given alignment requirement
// (as opposed to the type in the original ALIGN_UP macro)
//
#define ALIGN_UP_A(length,alignment)   \
    ((((ULONG)(length)) + (alignment)-1) & ~ ((alignment)-1))

//
// ALIGN_UP_A for pointers.
//
#define ALIGN_UP_A_POINTER(address,alignment)  \
    ALIGN_DOWN_A_POINTER(((ULONG_PTR)(address) + alignment-1), alignment)

//
// ALIGN_UP_TO_TYPE aligns size to make sure it meets
// the type alignment requirement
//
#define ALIGN_UP_TO_TYPE(length,type)   \
    ALIGN_UP_A(length,TYPE_ALIGNMENT(type))

//
// ALIGN_UP_TO_TYPE for pointers.
//
#define ALIGN_UP_TO_TYPE_POINTER(address,type)   \
    ALIGN_UP_A_POINTER(address,TYPE_ALIGNMENT(type))

#if DBG

#define IS_VALID_AFD_BUFFER(b) (                                                                                                    \
    ((b)->Placement==AFD_PLACEMENT_HDR)                                                                                             \
        ? ((PUCHAR)b<(PUCHAR)(b)->Buffer && (PUCHAR)b<(PUCHAR)(b)->Mdl && (PUCHAR)b<(PUCHAR)(b)->Irp)                               \
        : (((b)->Placement==AFD_PLACEMENT_MDL)                                                                                      \
            ? ((PUCHAR)(b)->Mdl<(PUCHAR)(b)->Buffer && (PUCHAR)(b)->Mdl<(PUCHAR)b && (PUCHAR)(b)->Mdl<(PUCHAR)(b)->Irp)             \
            : ((b->Placement==AFD_PLACEMENT_IRP)                                                                                    \
                ? ((PUCHAR)(b)->Irp<(PUCHAR)(b)->Buffer && (PUCHAR)(b)->Irp<(PUCHAR)b && (PUCHAR)(b)->Irp<(PUCHAR)(b)->Mdl)         \
                : ((PUCHAR)(b)->Buffer<(PUCHAR)(b)->Irp && (PUCHAR)(b)->Buffer<(PUCHAR)b && (PUCHAR)(b)->Buffer<(PUCHAR)(b)->Mdl))  \
            )                                                                                                                       \
        )                                                                                                                           \

#endif


//
// Pointer to an IRP cleanup routine. This is used as a parameter to
// AfdCompleteIrpList().
//

typedef
BOOLEAN
(NTAPI * PAFD_IRP_CLEANUP_ROUTINE)(
    IN PIRP Irp
    );

//
// Debug statistics.
//

typedef struct _AFD_QUOTA_STATS {
    LARGE_INTEGER Charged;
    LARGE_INTEGER Returned;
} AFD_QUOTA_STATS;

typedef struct _AFD_HANDLE_STATS {
    LONG AddrOpened;
    LONG AddrClosed;
    LONG AddrRef;
    LONG AddrDeref;
    LONG ConnOpened;
    LONG ConnClosed;
    LONG ConnRef;
    LONG ConnDeref;
    LONG FileRef;
    LONG FileDeref;
} AFD_HANDLE_STATS;

typedef struct _AFD_QUEUE_STATS {
    LONG AfdWorkItemsQueued;
    LONG ExWorkItemsQueued;
    LONG WorkerEnter;
    LONG WorkerLeave;
    LONG AfdWorkItemsProcessed;
    PETHREAD AfdWorkerThread;
} AFD_QUEUE_STATS;

typedef struct _AFD_CONNECTION_STATS {
    LONG ConnectedReferencesAdded;
    LONG ConnectedReferencesDeleted;
    LONG GracefulDisconnectsInitiated;
    LONG GracefulDisconnectsCompleted;
    LONG GracefulDisconnectIndications;
    LONG AbortiveDisconnectsInitiated;
    LONG AbortiveDisconnectsCompleted;
    LONG AbortiveDisconnectIndications;
    LONG ConnectionIndications;
    LONG ConnectionsDropped;
    LONG ConnectionsAccepted;
    LONG ConnectionsPreaccepted;
    LONG ConnectionsReused;
    LONG EndpointsReused;
} AFD_CONNECTION_STATS;

//
// Global data. Resouces and lookaside list descriptors
// cannot be statically allocated, as they need to ALWAYS be nonpageable,
// even when the entire driver is paged out.
// Alignment table is variable-size and also cannot be statically allocated.
//

enum {
    AFD_LARGE_BUFFER_LIST=0,
    AFD_MEDIUM_BUFFER_LIST,
    AFD_SMALL_BUFFER_LIST,
    AFD_BUFFER_TAG_LIST,
    AFD_TP_INFO_LIST,
    AFD_REMOTE_ADDR_LIST,
    AFD_NUM_LOOKASIDE_LISTS
} AFD_LOOKASIDE_LISTS_INDEX;

typedef struct _AFD_GLOBAL_DATA {
    ERESOURCE               Resource;
    NPAGED_LOOKASIDE_LIST   List[AFD_NUM_LOOKASIDE_LISTS];
#define LargeBufferList     List[AFD_LARGE_BUFFER_LIST]
#define MediumBufferList    List[AFD_MEDIUM_BUFFER_LIST]
#define SmallBufferList     List[AFD_SMALL_BUFFER_LIST]
#define BufferTagList       List[AFD_BUFFER_TAG_LIST]
#define TpInfoList          List[AFD_TP_INFO_LIST]
#define RemoteAddrList      List[AFD_REMOTE_ADDR_LIST]
    LONG                    TrimFlags;
    KTIMER                  Timer;
    KDPC                    Dpc;
    UCHAR                   BufferAlignmentTable[ANYSIZE_ARRAY];
} AFD_GLOBAL_DATA, *PAFD_GLOBAL_DATA;

//
// Context structure for misc requests pended in AFD.
//
typedef struct _AFD_REQUEST_CONTEXT AFD_REQUEST_CONTEXT, *PAFD_REQUEST_CONTEXT;

//
// The routine is called after request is removed from endpoint list
// for cleanup purposes
//
typedef BOOLEAN (* PAFD_REQUEST_CLEANUP) (
                    PAFD_ENDPOINT           Endpoint,
                    PAFD_REQUEST_CONTEXT     NotifyCtx
                    );

//
// This structure has to no more 16 bytes long so we can
// reuse IrpSp->Parameters for it.
//
struct _AFD_REQUEST_CONTEXT {
    LIST_ENTRY              EndpointListLink;   // Link in endpoint list
    PAFD_REQUEST_CLEANUP    CleanupRoutine;     // Routine to call to cancel
    PVOID                   Context;            // Request dependent context
                                                // (PIRP)
};

//
// We use list entry fields to synchronize completion with cleanup/cancel
// routine assuming that as long as the entry is in the list
// both Flink and Blink fields cannot be NULL. (using these
// fields for synchronization allows us to cut down on
// cancel spinlock usage)
//

#define AfdEnqueueRequest(Endpoint,Request)                     \
    ExInterlockedInsertTailList(&(Endpoint)->RequestList,       \
                                &(Request)->EndpointListLink,   \
                                &(Endpoint)->SpinLock)


#define AfdIsRequestInQueue(Request)                           \
            ((Request)->EndpointListLink.Flink!=NULL)

#define AfdMarkRequestCompleted(Request)                       \
            (Request)->EndpointListLink.Blink = NULL

#define AfdIsRequestCompleted(Request)                         \
            ((Request)->EndpointListLink.Blink==NULL)


typedef struct _ROUTING_NOTIFY {
    LIST_ENTRY      NotifyListLink;
    PIRP            NotifyIrp;
    PVOID           NotifyContext;
} ROUTING_NOTIFY, *PROUTING_NOTIFY;

typedef struct _AFD_ADDRESS_ENTRY {
    LIST_ENTRY      AddressListLink;
    UNICODE_STRING  DeviceName;
    TA_ADDRESS      Address;
} AFD_ADDRESS_ENTRY, *PAFD_ADDRESS_ENTRY;

typedef struct _AFD_ADDRESS_CHANGE {
    LIST_ENTRY      ChangeListLink;
    union {
        PAFD_ENDPOINT   Endpoint;
        PIRP            Irp;
    };
    USHORT          AddressType;
    BOOLEAN         NonBlocking;
} AFD_ADDRESS_CHANGE, *PAFD_ADDRESS_CHANGE;


typedef 
NTSTATUS
(* PAFD_IMMEDIATE_CALL) (
    IN  PFILE_OBJECT        FileObject,
    IN  ULONG               IoctlCode,
    IN  KPROCESSOR_MODE     RequestorMode,
    IN  PVOID               InputBuffer,
    IN  ULONG               InputBufferLength,
    IN  PVOID               OutputBuffer,
    IN  ULONG               OutputBufferLength,
    OUT PULONG_PTR          Information
    );

typedef
NTSTATUS
(FASTCALL * PAFD_IRP_CALL) (
    IN  PIRP                Irp,
    IN  PIO_STACK_LOCATION  IrpSp
    );
    
typedef struct _AFD_TRANSMIT_PACKETS_ELEMENT {
#define TP_MDL      0x80000000
#define TP_COMBINE  0x40000000
    ULONG Flags;
    ULONG Length;
    union {
        struct {
            LARGE_INTEGER FileOffset;
            PFILE_OBJECT  FileObject;
        };
        struct {
            PVOID         Buffer;
            PMDL          Mdl;
        };
    };
} AFD_TRANSMIT_PACKETS_ELEMENT, *PAFD_TRANSMIT_PACKETS_ELEMENT;

//
// Structure to keep track of transmit packets request
//
struct _AFD_TPACKETS_INFO_INTERNAL {
    union {
        SINGLE_LIST_ENTRY   SListEntry;     // Link on S-List
        PFILE_OBJECT    TdiFileObject;      // Tdi objects (sending to)
    };

    PDEVICE_OBJECT  TdiDeviceObject;

    PMDL            HeadMdl;        // Ready to send chain
    PMDL            *TailMdl;
    
    PAFD_BUFFER_HEADER  HeadPd;     // Corresponding packet chain
    PAFD_BUFFER_HEADER  *TailPd;

    PIRP            ReadIrp;        // Irp used for file reads.
    PAFD_TRANSMIT_PACKETS_ELEMENT
                    ElementArray;   // Packet array
    
    ULONG           NextElement;    // Next element to send.
    ULONG           ElementCount;   // Total number of elements in the array
    
    ULONG           RemainingPkts;  // Number of packets remaining to be sent.
    USHORT          NumSendIrps;    // Actual number of send IRPs
    BOOLEAN         ArrayAllocated; // Element array is allocated (not built-in).
    BOOLEAN         PdNeedsPps;     // Packet descriptor being built needs post-
                                    // processing after completion.
    ULONG           PdLength;       // Currently accumulated send length
    ULONG           SendPacketLength; // Maximum length of the packet
                                    // APC/Work item for worker scheduling
    union {
        KAPC                Apc;
        WORK_QUEUE_ITEM     WorkItem;
    };

#if REFERENCE_DEBUG
    LONG CurrentTimeHigh;
    LONG CurrentReferenceSlot;
    AFD_REFERENCE_DEBUG ReferenceDebug[AFD_MAX_REF];
#endif
#if AFD_PERF_DBG
    LONG            WorkersExecuted;
#endif
#define AFD_TP_MIN_SEND_IRPS    2   // Need at least two to keep transport busy
#define AFD_TP_MAX_SEND_IRPS    8   // Max is based on current flags layout below
    PIRP            SendIrp[AFD_TP_MAX_SEND_IRPS];
    // ElementArray
    // SendIrp1
    // SendIrp2
};

//
// Structure maintained in driver context of the TPackets IRP
//
typedef struct _AFD_TPACKETS_IRP_CTX AFD_TPACKETS_IRP_CTX, *PAFD_TPACKETS_IRP_CTX;
#define AFD_GET_TPIC(_i) ((PAFD_TPACKETS_IRP_CTX)&(_i)->Tail.Overlay.DriverContext)
struct _AFD_TPACKETS_IRP_CTX {
    PAFD_TPACKETS_IRP_CTX       Next;           // Next TPackets IRP in the list
    LONG                        Flags;          // Application flags.
    volatile LONG               ReferenceCount; // IRP reference count
    volatile LONG               StateFlags;     // TPackets state flags
};

#define AFD_GET_TPIRP(_i) CONTAINING_RECORD(_i,IRP,Tail.Overlay.DriverContext)

#define AFD_TP_ABORT_PENDING         0x00000001  // Request is being aborted
#define AFD_TP_WORKER_SCHEDULED      0x00000002  // Worker is scheduled or active
#define AFD_TP_SENDS_POSTED          0x00000010  // All sends have been posted.
#define AFD_TP_QUEUED                0x00000020  // Irp is in the queue.
#define AFD_TP_SEND                  0x00000100  // This is a plain send in TP queue.
#define AFD_TP_AFD_SEND              0x00000200  // This is AFD send IRP.
#ifdef TDI_SERVICE_SEND_AND_DISCONNECT
#define AFD_TP_SEND_AND_DISCONNECT   0x00000400  // S&D is enabled
#endif // TDI_SERVICE_SEND_AND_DISCONNECT

#define AFD_TP_READ_CALL_PENDING     0x00001000  // MDL_READ call is imminent or in progress on ReadIrp
#define AFD_TP_READ_COMP_PENDING     0x00002000  // Read completion is expected on ReadIrp
#define AFD_TP_READ_BUSY (AFD_TP_READ_CALL_PENDING|AFD_TP_READ_COMP_PENDING)

    // TDI_SEND call is imminent or in progress on send Irp i
#define AFD_TP_SEND_CALL_PENDING(i) (0x00010000<<((i)*2))
    // Send completion is expected on send Irp i
#define AFD_TP_SEND_COMP_PENDING(i) (0x00020000<<((i)*2))
#define AFD_TP_SEND_BUSY(i)         (0x00030000<<((i)*2))
#define AFD_TP_SEND_MASK            (0x55550000)


#if DBG
//
// N.B. This structure MUST be alligned on memory allocation boundary
//

typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _AFD_POOL_HEADER {
    SIZE_T Size;
    PCHAR FileName;
    ULONG LineNumber;
    LONG  InUse;
} AFD_POOL_HEADER, *PAFD_POOL_HEADER;
#define AFD_POOL_OVERHEAD  (sizeof(AFD_POOL_HEADER))
#else
#define AFD_POOL_OVERHEAD   0
#endif

//
// This macro verifies that the 32-bit mapping of the structures in 64-bit
// compiler match original 32-bit structures.  Note, that the verification is
// performed when this file is compiled by 32 bit compiler, but
// the actual structures are used by 64 bit code.
//

#ifdef _WIN64
#define AFD_CHECK32on64(_str,_fld)
#define AFD_MAX_NATURAL_ALIGNMENT32  sizeof(ULONG)
#else
#define AFD_CHECK32on64(_str,_fld)    \
    C_ASSERT (FIELD_OFFSET (_str,_fld)==FIELD_OFFSET(_str##32,_fld))
#endif

//
// Structures for mapping IOCTL parameters for 32-bit clients on 64-bit
// platform.
//
typedef UNALIGNED struct _WSABUF32 {
    ULONG            len;
    AFD_POINTER_32   buf;
} WSABUF32, *LPWSABUF32;
AFD_CHECK32on64(WSABUF,len);
AFD_CHECK32on64(WSABUF,buf);

typedef UNALIGNED struct _QualityOfService32 {
    FLOWSPEC      SendingFlowspec;       /* the flow spec for data sending */
    FLOWSPEC      ReceivingFlowspec;     /* the flow spec for data receiving */
    WSABUF32      ProviderSpecific;      /* additional provider specific stuff */
} QOS32, * LPQOS32;
AFD_CHECK32on64(QOS,SendingFlowspec);
AFD_CHECK32on64(QOS,ReceivingFlowspec);
AFD_CHECK32on64(QOS,ProviderSpecific);

typedef UNALIGNED struct _AFD_ACCEPT_INFO32 {
    BOOLEAN     SanActive;
    LONG        Sequence;
    VOID * POINTER_32 AcceptHandle;
} AFD_ACCEPT_INFO32, *PAFD_ACCEPT_INFO32;
AFD_CHECK32on64(AFD_ACCEPT_INFO,SanActive);
AFD_CHECK32on64(AFD_ACCEPT_INFO,Sequence);
AFD_CHECK32on64(AFD_ACCEPT_INFO,AcceptHandle);

typedef UNALIGNED struct _AFD_SUPER_ACCEPT_INFO32 {
    BOOLEAN     SanActive;
    BOOLEAN     FixAddressAlignment;
    VOID * POINTER_32 AcceptHandle;
    ULONG ReceiveDataLength;
    ULONG LocalAddressLength;
    ULONG RemoteAddressLength;
} AFD_SUPER_ACCEPT_INFO32, *PAFD_SUPER_ACCEPT_INFO32;
AFD_CHECK32on64(AFD_SUPER_ACCEPT_INFO,SanActive);
AFD_CHECK32on64(AFD_SUPER_ACCEPT_INFO,FixAddressAlignment);
AFD_CHECK32on64(AFD_SUPER_ACCEPT_INFO,AcceptHandle);
AFD_CHECK32on64(AFD_SUPER_ACCEPT_INFO,ReceiveDataLength);
AFD_CHECK32on64(AFD_SUPER_ACCEPT_INFO,LocalAddressLength);
AFD_CHECK32on64(AFD_SUPER_ACCEPT_INFO,RemoteAddressLength);

typedef UNALIGNED struct _AFD_POLL_HANDLE_INFO32 {
    VOID * POINTER_32 Handle;
    ULONG             PollEvents;
    NTSTATUS          Status;
} AFD_POLL_HANDLE_INFO32, *PAFD_POLL_HANDLE_INFO32;
AFD_CHECK32on64(AFD_POLL_HANDLE_INFO,Handle);
AFD_CHECK32on64(AFD_POLL_HANDLE_INFO,PollEvents);
AFD_CHECK32on64(AFD_POLL_HANDLE_INFO,Status);

typedef UNALIGNED struct _AFD_POLL_INFO32 {
    LARGE_INTEGER Timeout;
    ULONG NumberOfHandles;
    BOOLEAN Unique;
    AFD_POLL_HANDLE_INFO32 Handles[1];
} AFD_POLL_INFO32, *PAFD_POLL_INFO32;
AFD_CHECK32on64(AFD_POLL_INFO,Timeout);
AFD_CHECK32on64(AFD_POLL_INFO,NumberOfHandles);
AFD_CHECK32on64(AFD_POLL_INFO,Unique);
AFD_CHECK32on64(AFD_POLL_INFO,Handles);

typedef UNALIGNED struct _AFD_HANDLE_INFO632 {
    VOID * POINTER_32 TdiAddressHandle;
    VOID * POINTER_32 TdiConnectionHandle;
} AFD_HANDLE_INFO32, *PAFD_HANDLE_INFO32;
AFD_CHECK32on64(AFD_HANDLE_INFO,TdiAddressHandle);
AFD_CHECK32on64(AFD_HANDLE_INFO,TdiConnectionHandle);

typedef UNALIGNED struct _AFD_TRANSMIT_FILE_INFO32 {
    LARGE_INTEGER Offset;
    LARGE_INTEGER WriteLength;
    ULONG SendPacketLength;
    VOID * POINTER_32 FileHandle;
    AFD_POINTER_32 Head;
    ULONG HeadLength;
    AFD_POINTER_32 Tail;
    ULONG TailLength;
    ULONG Flags;
} AFD_TRANSMIT_FILE_INFO32, *PAFD_TRANSMIT_FILE_INFO32;
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,Offset);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,WriteLength);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,SendPacketLength);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,FileHandle);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,Head);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,HeadLength);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,Tail);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,TailLength);
AFD_CHECK32on64(AFD_TRANSMIT_FILE_INFO,Flags);

typedef UNALIGNED struct _AFD_SEND_INFO32 {
    AFD_POINTER_32 BufferArray;
    ULONG BufferCount;
    ULONG AfdFlags;
    ULONG TdiFlags;
} AFD_SEND_INFO32, *PAFD_SEND_INFO32;
AFD_CHECK32on64(AFD_SEND_INFO,BufferArray);
AFD_CHECK32on64(AFD_SEND_INFO,BufferCount);
AFD_CHECK32on64(AFD_SEND_INFO,AfdFlags);
AFD_CHECK32on64(AFD_SEND_INFO,TdiFlags);

typedef UNALIGNED struct _TDI_REQUEST32 {
    union {
        VOID * POINTER_32 AddressHandle;
        VOID * POINTER_32 ConnectionContext;
        VOID * POINTER_32 ControlChannel;
    } Handle;

    VOID * POINTER_32 RequestNotifyObject;
    VOID * POINTER_32 RequestContext;
    TDI_STATUS TdiStatus;
} TDI_REQUEST32, *PTDI_REQUEST32;
AFD_CHECK32on64(TDI_REQUEST,Handle);
AFD_CHECK32on64(TDI_REQUEST,RequestNotifyObject);
AFD_CHECK32on64(TDI_REQUEST,RequestContext);
AFD_CHECK32on64(TDI_REQUEST,TdiStatus);

typedef UNALIGNED struct _TDI_CONNECTION_INFORMATION32 {
    LONG UserDataLength;            // length of user data buffer
    AFD_POINTER_32 UserData;        // pointer to user data buffer
    LONG OptionsLength;             // length of follwoing buffer
    AFD_POINTER_32 Options;         // pointer to buffer containing options
    LONG RemoteAddressLength;       // length of following buffer
    AFD_POINTER_32 RemoteAddress;   // buffer containing the remote address
} TDI_CONNECTION_INFORMATION32, *PTDI_CONNECTION_INFORMATION32;
AFD_CHECK32on64(TDI_CONNECTION_INFORMATION,UserDataLength);
AFD_CHECK32on64(TDI_CONNECTION_INFORMATION,UserData);
AFD_CHECK32on64(TDI_CONNECTION_INFORMATION,OptionsLength);
AFD_CHECK32on64(TDI_CONNECTION_INFORMATION,Options);
AFD_CHECK32on64(TDI_CONNECTION_INFORMATION,RemoteAddressLength);
AFD_CHECK32on64(TDI_CONNECTION_INFORMATION,RemoteAddress);

typedef UNALIGNED struct _TDI_REQUEST_SEND_DATAGRAM32 {
    TDI_REQUEST32 Request;
    AFD_POINTER_32 SendDatagramInformation;
} TDI_REQUEST_SEND_DATAGRAM32, *PTDI_REQUEST_SEND_DATAGRAM32;
AFD_CHECK32on64(TDI_REQUEST_SEND_DATAGRAM,Request);
AFD_CHECK32on64(TDI_REQUEST_SEND_DATAGRAM,SendDatagramInformation);


typedef UNALIGNED struct _AFD_SEND_DATAGRAM_INFO32 {
    AFD_POINTER_32 BufferArray;
    ULONG BufferCount;
    ULONG AfdFlags;
    TDI_REQUEST_SEND_DATAGRAM32 TdiRequest;
    TDI_CONNECTION_INFORMATION32 TdiConnInfo;
} AFD_SEND_DATAGRAM_INFO32, *PAFD_SEND_DATAGRAM_INFO32;
AFD_CHECK32on64(AFD_SEND_DATAGRAM_INFO,BufferArray);
AFD_CHECK32on64(AFD_SEND_DATAGRAM_INFO,BufferCount);
AFD_CHECK32on64(AFD_SEND_DATAGRAM_INFO,AfdFlags);
AFD_CHECK32on64(AFD_SEND_DATAGRAM_INFO,TdiRequest);
AFD_CHECK32on64(AFD_SEND_DATAGRAM_INFO,TdiConnInfo);

typedef UNALIGNED struct _AFD_RECV_INFO32 {
    AFD_POINTER_32 BufferArray;
    ULONG BufferCount;
    ULONG AfdFlags;
    ULONG TdiFlags;
} AFD_RECV_INFO32, *PAFD_RECV_INFO32;
AFD_CHECK32on64(AFD_RECV_INFO,BufferArray);
AFD_CHECK32on64(AFD_RECV_INFO,BufferCount);
AFD_CHECK32on64(AFD_RECV_INFO,AfdFlags);
AFD_CHECK32on64(AFD_RECV_INFO,TdiFlags);

typedef UNALIGNED struct _AFD_RECV_DATAGRAM_INFO32 {
    AFD_POINTER_32 BufferArray;
    ULONG BufferCount;
    ULONG AfdFlags;
    ULONG TdiFlags;
    AFD_POINTER_32 Address;
    AFD_POINTER_32 AddressLength;
} AFD_RECV_DATAGRAM_INFO32, *PAFD_RECV_DATAGRAM_INFO32;
AFD_CHECK32on64(AFD_RECV_DATAGRAM_INFO,BufferArray);
AFD_CHECK32on64(AFD_RECV_DATAGRAM_INFO,BufferCount);
AFD_CHECK32on64(AFD_RECV_DATAGRAM_INFO,AfdFlags);
AFD_CHECK32on64(AFD_RECV_DATAGRAM_INFO,TdiFlags);
AFD_CHECK32on64(AFD_RECV_DATAGRAM_INFO,Address);
AFD_CHECK32on64(AFD_RECV_DATAGRAM_INFO,AddressLength);

typedef UNALIGNED struct _AFD_CONNECT_JOIN_INFO32 {
    BOOLEAN     SanActive;
    VOID * POINTER_32   RootEndpoint;   // Root endpoint for joins
    VOID * POINTER_32   ConnectEndpoint;// Connect/leaf endpoint for async connects
    TRANSPORT_ADDRESS   RemoteAddress;  // Remote address
} AFD_CONNECT_JOIN_INFO32, *PAFD_CONNECT_JOIN_INFO32;
AFD_CHECK32on64(AFD_CONNECT_JOIN_INFO,SanActive);
AFD_CHECK32on64(AFD_CONNECT_JOIN_INFO,RootEndpoint);
AFD_CHECK32on64(AFD_CONNECT_JOIN_INFO,ConnectEndpoint);
AFD_CHECK32on64(AFD_CONNECT_JOIN_INFO,RemoteAddress);

typedef UNALIGNED struct _AFD_EVENT_SELECT_INFO32 {
    VOID * POINTER_32 Event;
    ULONG PollEvents;
} AFD_EVENT_SELECT_INFO32, *PAFD_EVENT_SELECT_INFO32;
AFD_CHECK32on64(AFD_EVENT_SELECT_INFO,Event);
AFD_CHECK32on64(AFD_EVENT_SELECT_INFO,PollEvents);

typedef UNALIGNED struct _AFD_QOS_INFO32 {
    QOS32 Qos;
    BOOLEAN GroupQos;
} AFD_QOS_INFO32, *PAFD_QOS_INFO32;
AFD_CHECK32on64(AFD_QOS_INFO,Qos);
AFD_CHECK32on64(AFD_QOS_INFO,GroupQos);

typedef UNALIGNED struct _AFD_TRANSPORT_IOCTL_INFO32 {
    VOID *  POINTER_32 Handle;
    AFD_POINTER_32 InputBuffer;
    ULONG   InputBufferLength;
    ULONG   IoControlCode;
    ULONG   AfdFlags;
    ULONG   PollEvent;
} AFD_TRANSPORT_IOCTL_INFO32, *PAFD_TRANSPORT_IOCTL_INFO32;
AFD_CHECK32on64(AFD_TRANSPORT_IOCTL_INFO,Handle);
AFD_CHECK32on64(AFD_TRANSPORT_IOCTL_INFO,InputBuffer);
AFD_CHECK32on64(AFD_TRANSPORT_IOCTL_INFO,InputBufferLength);
AFD_CHECK32on64(AFD_TRANSPORT_IOCTL_INFO,IoControlCode);
AFD_CHECK32on64(AFD_TRANSPORT_IOCTL_INFO,AfdFlags);
AFD_CHECK32on64(AFD_TRANSPORT_IOCTL_INFO,PollEvent);

typedef UNALIGNED struct _TRANSMIT_PACKETS_ELEMENT32 {
    ULONG dwElFlags;
#define TP_MEMORY   1
#define TP_FILE     2
#define TP_EOP      4
    ULONG cLength;
    union {
        struct {
            LARGE_INTEGER       nFileOffset;
            VOID *  POINTER_32  hFile;
        };
        AFD_POINTER_32          pBuffer;
    };
} TRANSMIT_PACKETS_ELEMENT32, *LPTRANSMIT_PACKETS_ELEMENT32;
AFD_CHECK32on64(TRANSMIT_PACKETS_ELEMENT,dwElFlags);
AFD_CHECK32on64(TRANSMIT_PACKETS_ELEMENT,nFileOffset);
AFD_CHECK32on64(TRANSMIT_PACKETS_ELEMENT,hFile);
AFD_CHECK32on64(TRANSMIT_PACKETS_ELEMENT,pBuffer);

typedef UNALIGNED struct _AFD_TPACKETS_INFO32 {
    AFD_POINTER_32              ElementArray;
    ULONG                       ElementCount;
    ULONG                       SendSize;
    ULONG                       Flags;
} AFD_TPACKETS_INFO32, *PAFD_TPACKETS_INFO32;
AFD_CHECK32on64(AFD_TPACKETS_INFO,ElementArray);
AFD_CHECK32on64(AFD_TPACKETS_INFO,ElementCount);
AFD_CHECK32on64(AFD_TPACKETS_INFO,SendSize);
AFD_CHECK32on64(AFD_TPACKETS_INFO,Flags);

typedef UNALIGNED struct _AFD_RECV_MESSAGE_INFO32 {
    AFD_RECV_DATAGRAM_INFO32    dgi;
    AFD_POINTER_32              ControlBuffer;
    AFD_POINTER_32              ControlLength;
    AFD_POINTER_32              MsgFlags;
} AFD_RECV_MESSAGE_INFO32, *PAFD_RECV_MESSAGE_INFO32;
AFD_CHECK32on64(AFD_RECV_MESSAGE_INFO,dgi);
AFD_CHECK32on64(AFD_RECV_MESSAGE_INFO,MsgFlags);
AFD_CHECK32on64(AFD_RECV_MESSAGE_INFO,ControlBuffer);
AFD_CHECK32on64(AFD_RECV_MESSAGE_INFO,ControlLength);


typedef UNALIGNED struct _AFD_SWITCH_OPEN_PACKET32 {
    VOID * POINTER_32   CompletionPort; 
    VOID * POINTER_32   CompletionEvent;
} AFD_SWITCH_OPEN_PACKET32, *PAFD_SWITCH_OPEN_PACKET32;
AFD_CHECK32on64(AFD_SWITCH_OPEN_PACKET,CompletionPort);
AFD_CHECK32on64(AFD_SWITCH_OPEN_PACKET,CompletionEvent);

typedef UNALIGNED struct _AFD_SWITCH_CONTEXT_INFO32 {
    VOID * POINTER_32               SocketHandle;
    AFD_POINTER_32                  SwitchContext;
} AFD_SWITCH_CONTEXT_INFO32, *PAFD_SWITCH_CONTEXT_INFO32;
AFD_CHECK32on64(AFD_SWITCH_CONTEXT_INFO,SocketHandle);
AFD_CHECK32on64(AFD_SWITCH_CONTEXT_INFO,SwitchContext);

typedef UNALIGNED struct _AFD_SWITCH_CONNECT_INFO32 {
    VOID * POINTER_32               ListenHandle;
    AFD_POINTER_32                  SwitchContext;
    TRANSPORT_ADDRESS               RemoteAddress;
} AFD_SWITCH_CONNECT_INFO32, *PAFD_SWITCH_CONNECT_INFO32;
AFD_CHECK32on64(AFD_SWITCH_CONNECT_INFO,ListenHandle);
AFD_CHECK32on64(AFD_SWITCH_CONNECT_INFO,SwitchContext);
AFD_CHECK32on64(AFD_SWITCH_CONNECT_INFO,RemoteAddress);

typedef UNALIGNED struct _AFD_SWITCH_ACCEPT_INFO32 {
    VOID * POINTER_32   AcceptHandle;
    ULONG               ReceiveLength;
} AFD_SWITCH_ACCEPT_INFO32, *PAFD_SWITCH_ACCEPT_INFO32;
AFD_CHECK32on64(AFD_SWITCH_ACCEPT_INFO,AcceptHandle);
AFD_CHECK32on64(AFD_SWITCH_ACCEPT_INFO,ReceiveLength);

typedef UNALIGNED struct _AFD_SWITCH_EVENT_INFO32 {
    VOID * POINTER_32   SocketHandle;
    AFD_POINTER_32      SwitchContext;
    ULONG               EventBit;
    NTSTATUS            Status;
} AFD_SWITCH_EVENT_INFO32, *PAFD_SWITCH_EVENT_INFO32;
AFD_CHECK32on64(AFD_SWITCH_EVENT_INFO,SocketHandle);
AFD_CHECK32on64(AFD_SWITCH_EVENT_INFO,SwitchContext);
AFD_CHECK32on64(AFD_SWITCH_EVENT_INFO,EventBit);
AFD_CHECK32on64(AFD_SWITCH_EVENT_INFO,Status);

typedef UNALIGNED struct _AFD_SWITCH_REQUEST_INFO32 {
    VOID * POINTER_32   SocketHandle;
    AFD_POINTER_32      SwitchContext;
    AFD_POINTER_32      RequestContext;
    NTSTATUS            RequestStatus;
    ULONG               DataOffset;
} AFD_SWITCH_REQUEST_INFO32, *PAFD_SWITCH_REQUEST_INFO32;
AFD_CHECK32on64(AFD_SWITCH_REQUEST_INFO,SocketHandle);
AFD_CHECK32on64(AFD_SWITCH_REQUEST_INFO,SwitchContext);
AFD_CHECK32on64(AFD_SWITCH_REQUEST_INFO,RequestContext);
AFD_CHECK32on64(AFD_SWITCH_REQUEST_INFO,RequestStatus);
AFD_CHECK32on64(AFD_SWITCH_REQUEST_INFO,DataOffset);

typedef UNALIGNED struct _AFD_SWITCH_ACQUIRE_CTX_INFO32 {
    VOID * POINTER_32   SocketHandle;
    AFD_POINTER_32      SwitchContext;
    AFD_POINTER_32      SocketCtxBuf;
    ULONG               SocketCtxBufSize;
} AFD_SWITCH_ACQUIRE_CTX_INFO32, *PAFD_SWITCH_ACQUIRE_CTX_INFO32;
AFD_CHECK32on64(AFD_SWITCH_ACQUIRE_CTX_INFO,SocketHandle);
AFD_CHECK32on64(AFD_SWITCH_ACQUIRE_CTX_INFO,SwitchContext);
AFD_CHECK32on64(AFD_SWITCH_ACQUIRE_CTX_INFO,SocketCtxBuf);
AFD_CHECK32on64(AFD_SWITCH_ACQUIRE_CTX_INFO,SocketCtxBufSize);

typedef UNALIGNED struct _AFD_SWITCH_TRANSFER_CTX_INFO32 {
    VOID * POINTER_32   SocketHandle;
    AFD_POINTER_32      SwitchContext;
    AFD_POINTER_32      RequestContext;
    AFD_POINTER_32      SocketCtxBuf;
    ULONG               SocketCtxBufSize;
    AFD_POINTER_32      RcvBufferArray;
    ULONG               RcvBufferCount;
    NTSTATUS            Status;
} AFD_SWITCH_TRANSFER_CTX_INFO32, *PAFD_SWITCH_TRANSFER_CTX_INFO32;
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,SocketHandle);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,SwitchContext);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,RequestContext);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,SocketCtxBuf);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,SocketCtxBufSize);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,RcvBufferArray);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,RcvBufferCount);
AFD_CHECK32on64(AFD_SWITCH_TRANSFER_CTX_INFO,Status);

typedef UNALIGNED struct _AFD_PARTIAL_DISCONNECT_INFO32 {
    ULONG DisconnectMode;
    LARGE_INTEGER Timeout;
} AFD_PARTIAL_DISCONNECT_INFO32, *PAFD_PARTIAL_DISCONNECT_INFO32;
AFD_CHECK32on64(AFD_PARTIAL_DISCONNECT_INFO,DisconnectMode);
AFD_CHECK32on64(AFD_PARTIAL_DISCONNECT_INFO,Timeout);

typedef UNALIGNED struct _AFD_SUPER_DISCONNECT_INFO32 {
    ULONG  Flags;
} AFD_SUPER_DISCONNECT_INFO32, *PAFD_SUPER_DISCONNECT_INFO32;
AFD_CHECK32on64(AFD_SUPER_DISCONNECT_INFO,Flags);

typedef UNALIGNED struct _AFD_INFORMATION32 {
    ULONG InformationType;
    union {
        BOOLEAN Boolean;
        ULONG Ulong;
        LARGE_INTEGER LargeInteger;
    } Information;
} AFD_INFORMATION32, *PAFD_INFORMATION32;
AFD_CHECK32on64(AFD_INFORMATION,InformationType);
AFD_CHECK32on64(AFD_INFORMATION,Information);
AFD_CHECK32on64(AFD_INFORMATION,Information.Boolean);
AFD_CHECK32on64(AFD_INFORMATION,Information.Ulong);
AFD_CHECK32on64(AFD_INFORMATION,Information.LargeInteger);


typedef UNALIGNED struct _TDI_CMSGHDR32 {
    ULONG       cmsg_len;
    LONG        cmsg_level;
    LONG        cmsg_type;
    /* followed by UCHAR cmsg_data[] */
} TDI_CMSGHDR32, *PTDI_CMSGHDR32;
AFD_CHECK32on64(TDI_CMSGHDR,cmsg_len);
AFD_CHECK32on64(TDI_CMSGHDR,cmsg_level);
AFD_CHECK32on64(TDI_CMSGHDR,cmsg_type);

#ifdef _WIN64
#define TDI_CMSGHDR_ALIGN32(length)                         \
            ( ((length) + TYPE_ALIGNMENT(TDI_CMSGHDR32)-1) &\
                (~(TYPE_ALIGNMENT(TDI_CMSGHDR32)-1)) )      \

#define TDI_CMSGDATA_ALIGN32(length)                        \
            ( ((length) + AFD_MAX_NATURAL_ALIGNMENT32-1) &  \
                (~(AFD_MAX_NATURAL_ALIGNMENT32-1)) )
#endif //_WIN64

#endif // ndef _AFDSTR_