|
|
/*++
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_
|