windows-nt/Source/XPSP1/NT/net/sockets/winsock2/wsp/afdsys/afdstr.h
2020-09-26 16:20:57 +08:00

1626 lines
57 KiB
C

/*++
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_
//
// 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 MAX_REFERENCE 64
typedef union _AFD_REFERENCE_DEBUG {
struct {
ULONGLONG NewCount:4;
ULONGLONG LocationId:12;
ULONGLONG TickCount:16;
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) { \
PAFD_REFERENCE_DEBUG _s; \
LONG _n; \
LARGE_INTEGER _t; \
_n = InterlockedIncrement( &(_rd)->CurrentReferenceSlot ); \
_s = &(_rd)->ReferenceDebug[_n % MAX_REFERENCE]; \
_s->NewCount = _r; \
_s->LocationId = _l; \
_s->Param = _p; \
KeQueryTickCount (&_t); \
_s->TickCount = _t.QuadPart; \
}
#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.
//
struct _AFD_ENDPOINT;
struct _AFD_CONNECTION;
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 {
SINGLE_LIST_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
#define AfdBlockTypeDatagram 0xAFD1
#define AfdBlockTypeVcConnecting 0xAFD2
#define AfdBlockTypeVcListening 0xAFD4
#define AfdBlockTypeVcBoth 0xAFD6
#define AfdBlockTypeConnection 0xAFD8
#define AfdBlockTypeHelper 0xAAFD
#define AfdBlockTypeInvalidConnection 0xEAFD
#define AfdBlockTypeInvalidEndpoint 0xCAFD
#define AfdBlockTypeSanHelper 0x0AFD
#define AfdBlockTypeSanEndpoint 0x1AFD
#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
#define AfdConnectionStateFree 0
#define AfdConnectionStateUnaccepted 1
#define AfdConnectionStateReturned 2
#define AfdConnectionStateConnected 3
#define AfdConnectionStateClosing 4
//
// 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)
AbortIndicated:1,
:3,
DisconnectIndicated:1,
:3,
ConnectedReferenceAdded:1,
:3,
SpecialCondition:1,
:3,
CleanupBegun:1,
:3,
ClosePendedTransmit:1,
:3,
OnLRList:1,
SanConnection:1,
:2;
};
LOGICAL ConnectionStateFlags;
};
} AFD_CONNECTION_STATE_FLAGS;
C_ASSERT (sizeof (AFD_CONNECTION_STATE_FLAGS)==sizeof (LOGICAL));
typedef struct _AFD_CONNECTION {
// *** Frequently used, mostly read-only fields (state/type/flag changes are rare).
USHORT Type;
USHORT State;
AFD_CONNECTION_STATE_FLAGS ;
struct _AFD_ENDPOINT *Endpoint;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PEPROCESS OwningProcess;
union {
LONGLONG ConnectTime;
PIRP AcceptIrp;
PIRP ListenIrp;
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;
CLONG BufferredReceiveBytes;
CLONG BufferredExpeditedBytes;
USHORT BufferredReceiveCount;
USHORT BufferredExpeditedCount;
CLONG ReceiveBytesInTransport;
LIST_ENTRY SendIrpListHead;
CLONG BufferredSendBytes;
CLONG BufferredSendCount;
PIRP DisconnectIrp;
LONG ReceiveIrpsInTransport; // debug only.
} NonBufferring;
} Common;
CLONG MaxBufferredReceiveBytes;
CLONG MaxBufferredSendBytes;
PTRANSPORT_ADDRESS RemoteAddress;
ULONG RemoteAddressLength;
LONG Sequence;
HANDLE Handle;
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
SINGLE_LIST_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 CurrentReferenceSlot;
AFD_REFERENCE_DEBUG ReferenceDebug[MAX_REFERENCE];
#endif
#ifdef _AFD_VERIFY_DATA_
ULONGLONG VerifySequenceNumber;
#endif // _AFD_VERIFY_DATA_
} AFD_CONNECTION, *PAFD_CONNECTION;
#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 struct _AFD_TRANSPORT_INFO {
LIST_ENTRY TransportInfoListEntry;
volatile LONG ReferenceCount;
BOOLEAN InfoValid;
UNICODE_STRING TransportDeviceName;
TDI_PROVIDER_INFO ProviderInfo;
//WCHAR TransportDeviceNameStructure;
} AFD_TRANSPORT_INFO, *PAFD_TRANSPORT_INFO;
//
// Endpoint state definitions (can't be zero or state change
// macros won't work correctly).
//
#define AfdEndpointStateOpen 1
#define AfdEndpointStateBound 2
#define AfdEndpointStateConnected 3
#define AfdEndpointStateCleanup 4
#define AfdEndpointStateClosing 5
#define AfdEndpointStateTransmitClosing 6
#define AfdEndpointStateInvalid 7
//
// 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));
typedef 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 ;
PFILE_OBJECT AddressFileObject;
PDEVICE_OBJECT AddressDeviceObject;
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;
CLONG BufferredReceiveBytes;
CLONG BufferredReceiveCount;
CLONG MaxBufferredReceiveBytes;
CLONG BufferredSendBytes;
CLONG 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
} 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;
CLONG ContextLength;
ULONG LocalAddressLength;
PTRANSPORT_ADDRESS LocalAddress;
CLONG DisconnectMode;
CLONG 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 CurrentReferenceSlot;
AFD_REFERENCE_DEBUG ReferenceDebug[MAX_REFERENCE];
#endif
#if DBG
LIST_ENTRY OutstandingIrpListHead;
LONG ObReferenceBias;
#endif
} AFD_ENDPOINT, *PAFD_ENDPOINT;
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 \
: 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 { \
CLONG DataOffset; /* offset in buffer to start of unread data*/\
union { \
ULONG DatagramFlags; /* flags for datagrams with control info */\
CLONG 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*/ \
CLONG DataLength; /* actual data in the buffer */ \
CLONG 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;
typedef DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) 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
} AFD_BUFFER, *PAFD_BUFFER;
//
// 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.
//
#define AFD_PLACEMENT_HDR 0
#define AFD_PLACEMENT_IRP 1
#define AFD_PLACEMENT_MDL 2
#define AFD_PLACEMENT_BUFFER 3
#define AFD_PLACEMENT_HDR_IRP (AFD_PLACEMENT_HDR|(AFD_PLACEMENT_IRP<<2))
#define AFD_PLACEMENT_HDR_MDL (AFD_PLACEMENT_HDR|(AFD_PLACEMENT_MDL<<2))
#define AFD_PLACEMENT_IRP_MDL (AFD_PLACEMENT_IRP|(AFD_PLACEMENT_MDL<<2))
#define 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.
//
typedef 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 PUINT_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
//
typedef struct _AFD_TPACKETS_INFO_INTERNAL AFD_TPACKETS_INFO_INTERNAL, *PAFD_TPACKETS_INFO_INTERNAL;
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 CurrentReferenceSlot;
AFD_REFERENCE_DEBUG ReferenceDebug[MAX_REFERENCE];
#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 {
LIST_ENTRY EndpQueueEntry;
volatile LONG ReferenceCount;
volatile LONG StateFlags;
} AFD_TPACKETS_IRP_CTX, *PAFD_TPACKETS_IRP_CTX;
#define AFD_TP_ABORT_PENDING 0x00000001 // Request is being aborted
#define AFD_TP_WORKER_SCHEDULED 0x00000010 // Worker is scheduled or active
#ifdef TDI_SERVICE_SEND_AND_DISCONNECT
#define AFD_TP_SEND_AND_DISCONNECT 0x00000100 // 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)
#define AFD_GET_TPIC(_i) ((PAFD_TPACKETS_IRP_CTX)&(_i)->Tail.Overlay.DriverContext)
//
// 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;
CHAR * 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;
VOID * POINTER_32 Head;
ULONG HeadLength;
VOID * 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 {
WSABUF32 * 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
VOID * POINTER_32 UserData; // pointer to user data buffer
LONG OptionsLength; // length of follwoing buffer
VOID * POINTER_32 Options; // pointer to buffer containing options
LONG RemoteAddressLength; // length of following buffer
VOID * 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;
TDI_CONNECTION_INFORMATION32 * 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 {
WSABUF32 * 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 {
WSABUF32 * 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 {
WSABUF32 * POINTER_32 BufferArray;
ULONG BufferCount;
ULONG AfdFlags;
ULONG TdiFlags;
VOID * POINTER_32 Address;
ULONG * 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;
VOID * 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;
};
VOID * 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 {
TRANSMIT_PACKETS_ELEMENT * 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;
VOID * POINTER_32 ControlBuffer;
ULONG * POINTER_32 ControlLength;
ULONG * 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_SWITCH_CONTEXT * 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_SWITCH_CONTEXT * 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_SWITCH_CONTEXT * 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_SWITCH_CONTEXT * POINTER_32 SwitchContext;
VOID * 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_SWITCH_CONTEXT * POINTER_32 SwitchContext;
VOID * 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_SWITCH_CONTEXT * POINTER_32 SwitchContext;
VOID * POINTER_32 RequestContext;
VOID * POINTER_32 SocketCtxBuf;
ULONG SocketCtxBufSize;
WSABUF * 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_