Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2314 lines
82 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
nbftypes.h
Abstract:
This module defines private data structures and types for the NT
NBF transport provider.
Author:
David Beaver (dbeaver) 1 July 1991
Revision History:
--*/
#ifndef _NBFTYPES_
#define _NBFTYPES_
//
// This structure defines a NETBIOS name as a character array for use when
// passing preformatted NETBIOS names between internal routines. It is
// not a part of the external interface to the transport provider.
//
#define NETBIOS_NAME_SIZE 16
typedef struct _NBF_NETBIOS_ADDRESS {
UCHAR NetbiosName[NETBIOS_NAME_SIZE];
USHORT NetbiosNameType;
} NBF_NETBIOS_ADDRESS, *PNBF_NETBIOS_ADDRESS;
typedef UCHAR NAME;
typedef NAME UNALIGNED *PNAME;
//
// This structure defines things associated with a TP_REQUEST, or outstanding
// TDI request, maintained on a queue somewhere in the transport. All
// requests other than open/close require that a TP_REQUEST block be built.
//
#if DBG
#define REQUEST_HISTORY_LENGTH 20
extern KSPIN_LOCK NbfGlobalInterlock;
#endif
//
// To log packets that are sent/recd by NBF
//
#if PKT_LOG
#define PKT_QUE_SIZE 8
#define PKT_LOG_SIZE 58
typedef struct _PKT_LOG_ELM {
USHORT TimeLogged;
USHORT BytesTotal;
USHORT BytesSaved;
UCHAR PacketData[PKT_LOG_SIZE];
} PKT_LOG_ELM;
typedef struct _PKT_LOG_QUE {
ULONG PktNext;
PKT_LOG_ELM PktQue[PKT_QUE_SIZE];
} PKT_LOG_QUE;
#define PKT_IND_SIZE 32
typedef struct _PKT_IND_ELM {
USHORT TimeLogged;
USHORT BytesTotal;
USHORT BytesIndic;
USHORT BytesTaken;
ULONG IndcnStatus;
UCHAR PacketData[PKT_IND_SIZE];
} PKT_IND_ELM;
typedef struct _PKT_IND_QUE {
ULONG PktNext;
PKT_IND_ELM PktQue[PKT_QUE_SIZE];
} PKT_IND_QUE;
#endif // PKT_LOG
//
// the types of potential owners of requests
//
typedef enum _REQUEST_OWNER {
ConnectionType,
AddressType,
DeviceContextType
} REQUEST_OWNER;
//typedef
//NTSTATUS
//(*PTDI_TIMEOUT_ACTION)(
// IN PTP_REQUEST Request
// );
//
// The request itself
//
#if DBG
#define RREF_CREATION 0
#define RREF_PACKET 1
#define RREF_TIMER 2
#define RREF_RECEIVE 3
#define RREF_FIND_NAME 4
#define RREF_STATUS 5
#define NUMBER_OF_RREFS 8
#endif
typedef struct _TP_REQUEST {
CSHORT Type; // type of this structure
USHORT Size; // size of this structure
LIST_ENTRY Linkage; // used by ExInterlocked routines.
KSPIN_LOCK SpinLock; // spinlock for other fields.
// (used in KeAcquireSpinLock calls)
#if DBG
LONG RefTypes[NUMBER_OF_RREFS];
#endif
LONG ReferenceCount; // reasons why we can't destroy this req.
struct _DEVICE_CONTEXT *Provider; // pointer to the device context.
PKSPIN_LOCK ProviderInterlock; // &Provider->Interlock.
PIRP IoRequestPacket; // pointer to IRP for this request.
//
// The following two fields are used to quickly reference the basic
// components of the requests without worming through the IRP's stack.
//
PVOID Buffer2; // second buffer in the request.
ULONG Buffer2Length; // length of the second buffer.
//
// The following two fields (Flags and Context) are used to clean up
// queued requests which must be canceled or abnormally completed.
// The Flags field contains bitflags indicating the state of the request,
// and the specific queue type that the request is located on. The
// Context field contains a pointer to the owning structure (TP_CONNECTION
// or TP_ADDRESS) so that the cleanup routines can perform post-cleanup
// operations on the owning structure, such as dereferencing, etc.
//
ULONG Flags; // disposition of this request.
PVOID Context; // context of this request.
REQUEST_OWNER Owner; // what type of owner this request has.
#if DBG
LARGE_INTEGER Time; // time when request created
#endif
KTIMER Timer; // kernel timer for this request.
KDPC Dpc; // DPC object for timeouts.
//
// These fields are used for FIND.NAME and STATUS.QUERY requests.
//
ULONG Retries; // timeouts remaining.
USHORT BytesWritten; // usage varies.
USHORT FrameContext; // identifies request.
PVOID ResponseBuffer; // temp alloc to hold data.
#if DBG
LIST_ENTRY GlobalLinkage;
ULONG TotalReferences;
ULONG TotalDereferences;
ULONG NextRefLoc;
struct {
PVOID Caller;
PVOID CallersCaller;
} History[REQUEST_HISTORY_LENGTH];
BOOLEAN Completed;
BOOLEAN Destroyed;
#endif
} TP_REQUEST, *PTP_REQUEST;
//
// in nbfdrvr.c
//
extern UNICODE_STRING NbfRegistryPath;
//
// We need the driver object to create device context structures.
//
extern PDRIVER_OBJECT NbfDriverObject;
//
// This is a list of all the device contexts that NBF owns,
// used while unloading.
//
extern LIST_ENTRY NbfDeviceList;
//
// And a lock that protects the global list of NBF devices
//
extern FAST_MUTEX NbfDevicesLock;
#define INITIALIZE_DEVICES_LIST_LOCK() \
ExInitializeFastMutex(&NbfDevicesLock)
#define ACQUIRE_DEVICES_LIST_LOCK() \
ACQUIRE_FAST_MUTEX_UNSAFE(&NbfDevicesLock)
#define RELEASE_DEVICES_LIST_LOCK() \
RELEASE_FAST_MUTEX_UNSAFE(&NbfDevicesLock)
//
// A handle to be used in all provider notifications to TDI layer
//
extern HANDLE NbfProviderHandle;
//
// Global Configuration block for the driver ( no lock required )
//
extern PCONFIG_DATA NbfConfig;
#if DBG
extern KSPIN_LOCK NbfGlobalHistoryLock;
extern LIST_ENTRY NbfGlobalRequestList;
#define StoreRequestHistory(_req,_ref) { \
KIRQL oldIrql; \
KeAcquireSpinLock (&NbfGlobalHistoryLock, &oldIrql); \
if ((_req)->Destroyed) { \
DbgPrint ("request touched after being destroyed 0x%lx\n", \
(_req)); \
DbgBreakPoint(); \
} \
RtlGetCallersAddress( \
&(_req)->History[(_req)->NextRefLoc].Caller, \
&(_req)->History[(_req)->NextRefLoc].CallersCaller \
); \
if ((_ref)) { \
(_req)->TotalReferences++; \
} else { \
(_req)->TotalDereferences++; \
(_req)->History[(_req)->NextRefLoc].Caller = \
(PVOID)((ULONG_PTR)(_req)->History[(_req)->NextRefLoc].Caller | 1); \
} \
if (++(_req)->NextRefLoc == REQUEST_HISTORY_LENGTH) { \
(_req)->NextRefLoc = 0; \
} \
KeReleaseSpinLock (&NbfGlobalHistoryLock, oldIrql); \
}
#endif
#define NBF_ALLOCATION_TYPE_REQUEST 1
#define REQUEST_FLAGS_TIMER 0x0001 // a timer is active for this request.
#define REQUEST_FLAGS_TIMED_OUT 0x0002 // a timer expiration occured on this request.
#define REQUEST_FLAGS_ADDRESS 0x0004 // request is attached to a TP_ADDRESS.
#define REQUEST_FLAGS_CONNECTION 0x0008 // request is attached to a TP_CONNECTION.
#define REQUEST_FLAGS_STOPPING 0x0010 // request is being killed.
#define REQUEST_FLAGS_EOR 0x0020 // TdiSend request has END_OF_RECORD mark.
#define REQUEST_FLAGS_PIGGYBACK 0x0040 // TdiSend that can be piggyback ack'ed.
#define REQUEST_FLAGS_DC 0x0080 // request is attached to a TP_DEVICE_CONTEXT
//
// This defines the TP_SEND_IRP_PARAMETERS, which is masked onto the
// Parameters section of a send IRP's stack location.
//
typedef struct _TP_SEND_IRP_PARAMETERS {
TDI_REQUEST_KERNEL_SEND Request;
LONG ReferenceCount;
PVOID Irp;
} TP_SEND_IRP_PARAMETERS, *PTP_SEND_IRP_PARAMETERS;
#define IRP_SEND_LENGTH(_IrpSp) \
(((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.SendLength)
#define IRP_SEND_FLAGS(_IrpSp) \
(((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.SendFlags)
#define IRP_SEND_REFCOUNT(_IrpSp) \
(((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->ReferenceCount)
#define IRP_SEND_IRP(_IrpSp) \
(((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Irp)
#define IRP_SEND_CONNECTION(_IrpSp) \
((PTP_CONNECTION)((_IrpSp)->FileObject->FsContext))
#define IRP_DEVICE_CONTEXT(_IrpSp) \
((PDEVICE_CONTEXT)((_IrpSp)->DeviceObject))
//
// This defines the TP_RECEIVE_IRP_PARAMETERS, which is masked onto the
// Parameters section of a receive IRP's stack location.
//
typedef struct _TP_RECEIVE_IRP_PARAMETERS {
TDI_REQUEST_KERNEL_RECEIVE Request;
LONG ReferenceCount;
PIRP Irp;
} TP_RECEIVE_IRP_PARAMETERS, *PTP_RECEIVE_IRP_PARAMETERS;
#define IRP_RECEIVE_LENGTH(_IrpSp) \
(((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.ReceiveLength)
#define IRP_RECEIVE_FLAGS(_IrpSp) \
(((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.ReceiveFlags)
#define IRP_RECEIVE_REFCOUNT(_IrpSp) \
(((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->ReferenceCount)
#define IRP_RECEIVE_IRP(_IrpSp) \
(((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Irp)
#define IRP_RECEIVE_CONNECTION(_IrpSp) \
((PTP_CONNECTION)((_IrpSp)->FileObject->FsContext))
//
// This structure defines a TP_UI_FRAME, or connectionless frame header,
// that is manipulated by the FRAME.C routines.
//
typedef struct _TP_UI_FRAME {
PNDIS_PACKET NdisPacket;
LIST_ENTRY Linkage; // used by ExInterLocked routines.
PVOID DataBuffer; // for transport-created data.
UCHAR Header[1]; // the header in the frame (MAC + DLC + NBF)
} TP_UI_FRAME, *PTP_UI_FRAME;
//
// This structure defines a TP_VARIABLE, or network managable variable,
// maintained in a linked list on the device context.
//
typedef struct _TP_VARIABLE {
struct _TP_VARIABLE *Fwdlink; // next variable in provider's chain.
ULONG VariableSerialNumber; // identifier for this variable.
ULONG VariableType; // type of this variable (see TDI.H).
STRING VariableName; // allocated variable name.
union {
ULONG LongValue;
HARDWARE_ADDRESS HardwareAddressValue;
STRING StringValue; // allocated string value, if of that type.
} Value;
} TP_VARIABLE, *PTP_VARIABLE;
//
// This structure defines a TP_CONNECTION, or active transport connection,
// maintained on a transport address.
//
#if DBG
#define CONNECTION_HISTORY_LENGTH 50
#define CREF_SPECIAL_CREATION 0
#define CREF_SPECIAL_TEMP 1
#define CREF_COMPLETE_SEND 2
#define CREF_SEND_IRP 3
#define CREF_ADM_SESS 4
#define CREF_TRANSFER_DATA 5
#define CREF_FRAME_SEND 6
#define CREF_TIMER 7
#define CREF_BY_ID 8
#define CREF_LINK 9
#define CREF_SESSION_END 10
#define CREF_LISTENING 11
#define CREF_P_LINK 12
#define CREF_P_CONNECT 13
#define CREF_PACKETIZE 14
#define CREF_RECEIVE_IRP 15
#define CREF_PROCESS_DATA 16
#define CREF_REQUEST 17
#define CREF_TEMP 18
#define CREF_DATA_ACK_QUEUE 19
#define CREF_ASSOCIATE 20
#define CREF_STOP_ADDRESS 21
#define CREF_PACKETIZE_QUEUE 22
#define CREF_STALLED 23
#define NUMBER_OF_CREFS 24
#endif
//
// This structure holds our "complex send pointer" indicating
// where we are in the packetization of a send.
//
typedef struct _TP_SEND_POINTER {
ULONG MessageBytesSent; // up count, bytes sent/this msg.
PIRP CurrentSendIrp; // ptr, current send request in chain.
PMDL CurrentSendMdl; // ptr, current MDL in send chain.
ULONG SendByteOffset; // current byte offset in current MDL.
} TP_SEND_POINTER, *PTP_SEND_POINTER;
typedef struct _TP_CONNECTION {
#if DBG
ULONG RefTypes[NUMBER_OF_CREFS];
#endif
#if DBG
ULONG LockAcquired;
UCHAR LastAcquireFile[8];
ULONG LastAcquireLine;
ULONG Padding;
UCHAR LastReleaseFile[8];
ULONG LastReleaseLine;
#endif
CSHORT Type;
USHORT Size;
LIST_ENTRY LinkList; // used for link thread or for free
// resource list
KSPIN_LOCK SpinLock; // spinlock for connection protection.
PKSPIN_LOCK LinkSpinLock; // pointer to link's spinlock
LONG ReferenceCount; // number of references to this object.
LONG SpecialRefCount; // controls freeing of connection.
//
// The following lists are used to associate this connection with a
// particular address.
//
LIST_ENTRY AddressList; // list of connections for given address
LIST_ENTRY AddressFileList; // list for connections bound to a
// given address reference
//
// The following field is used as linkage in the device context's
// PacketizeQueue
//
LIST_ENTRY PacketizeLinkage;
//
// The following field is used as linkage in the device context's
// PacketWaitQueue.
//
LIST_ENTRY PacketWaitLinkage;
//
// The following field points to the TP_LINK object that describes the
// (active) data link connection for this transport connection. To be
// valid, this field is non-NULL.
//
struct _TP_LINK *Link; // pointer to transport link object.
struct _TP_ADDRESS_FILE *AddressFile; // pointer to owning Address.
struct _DEVICE_CONTEXT *Provider; // device context to which we are attached.
PKSPIN_LOCK ProviderInterlock; // &Provider->Interlock
PFILE_OBJECT FileObject; // easy backlink to file object.
//
// The following field contains the actual ID we expose to the TDI client
// to represent this connection. A unique one is created from the address.
//
USHORT ConnectionId; // unique identifier.
UCHAR SessionNumber; // the session number used in the packet header
//
// This field is used to keep the reason for the connection disconnect
// around until connection deletion time.
//
BOOLEAN RemoteDisconnect; // was this connection remotely disonnected?
//
// The following field is specified by the user at connection open time.
// It is the context that the user associates with the connection so that
// indications to and from the client can be associated with a particular
// connection.
//
CONNECTION_CONTEXT Context; // client-specified value.
//
// The following two queues are used to associate TdiSend and TdiReceive
// IRPs with this connection. New arrivals are placed at the end of
// the queues (really a linked list) and IRPs are processed at the
// front of the queues. The first TdiSend IRP on the SendQueue is
// the current TdiSend being processed, and the first TdiReceive IRP
// on the ReceiveQueue is the first TdiReceive being processed, PROVIDED
// the CONNECTION_FLAGS_ACTIVE_RECEIVE flag is set. If this flag is not
// set, then the first TdiReceive IRP on the ReceiveQueue is not active.
// These queues are managed by the EXECUTIVE interlocked list manipuation
// routines.
//
LIST_ENTRY SendQueue; // FIFO of outstanding TdiSends.
LIST_ENTRY ReceiveQueue; // FIFO of outstanding TdiReceives.
//
// The following fields are used to maintain state for the current receive.
//
ULONG MessageBytesReceived; // up count, bytes recd/this msg.
ULONG MessageBytesAcked; // bytes acked (NR or RO) this msg.
ULONG MessageInitAccepted; // bytes accepted during indication.
//
// These fields are only valid if the CONNECTION_FLAGS_ACTIVE_RECEIVE
// flag is set.
//
PIRP SpecialReceiveIrp; // a "no-request" receive IRP exists.
PIRP CurrentReceiveIrp; // ptr, current receive IRP.
PMDL CurrentReceiveMdl; // ptr, current MDL in receive chain.
ULONG ReceiveByteOffset; // current byte offset in current MDL.
ULONG ReceiveLength; // current receive length, in bytes (total)
ULONG ReceiveBytesUnaccepted; // by client...only indicate when == 0
//
// The following fields are used to maintain state for the active send.
// They only have meaning if the connection's SendState is not IDLE.
// Because the TDI client may submit multiple TdiSend requests to comprise
// a full message, we have to keep a complex pointer to the first byte of
// unACKed data (hence the first three fields). We also have a complex
// pointer to the first byte of unsent data (hence the last three fields).
//
ULONG SendState; // send state machine variable.
PIRP FirstSendIrp; // ptr, 1st TdiSend's IRP.
PMDL FirstSendMdl; // ptr, 1st unacked MDL in chain/this msg.
ULONG FirstSendByteOffset; // pre-acked bytes in that MDL.
TP_SEND_POINTER sp; // current send loc, defined above.
ULONG CurrentSendLength; // how long is this send (total)
ULONG StallCount; // times in a row we looked stalled.
ULONG StallBytesSent; // bytes sent last time we checked.
//
// This is TRUE if we need don't need to reference the current
// receive IRP during transfers (because it is a special
// receive or the driver doesn't pend transfers).
//
BOOLEAN CurrentReceiveSynchronous;
//
// This field will be TRUE if the last DOL received allowed
// piggyback acks.
//
BOOLEAN CurrentReceiveAckQueueable;
//
//
// This field will be TRUE if the last DOL received was
// sent NO.ACK.
//
BOOLEAN CurrentReceiveNoAck;
//
// These fields handle asynchronous TransferData calls.
//
ULONG TransferBytesPending; // bytes pending in current transfers
ULONG TotalTransferBytesPending; // bytes since TransferBytesPending was 0;
// how much we back off if a transfer fails
PMDL SavedCurrentReceiveMdl; // used to back off by TotalTransferPending bytes
ULONG SavedReceiveByteOffset; // used to back off by TotalTransferPending bytes
//
// This field will be TRUE if we are in the middle of
// processing a receive indication on this connection and
// we are not yet in a state where another indication
// can be handled.
//
// It is stored as a INT since access to it is guarded
// by the connection's link spinlock, unlike the variables
// around it
//
UINT IndicationInProgress;
//
// The following field is used as a linkage when on the device
// context's DataAckQueue.
//
LIST_ENTRY DataAckLinkage;
//
// TRUE if the connection is on the data ack queue.
// Also an INT so access can be non-guarded.
//
UINT OnDataAckQueue;
//
// These keep track of the number of consecutive sends or
// receives on this connection. This is used in determining when
// to queue a data ack.
//
ULONG ConsecutiveSends;
ULONG ConsecutiveReceives;
//
// The following list head is used as a pointer to a TdiListen/TdiConnect
// request which is in progress. Although manipulated
// with queue instructions, there will only be one request in the queue.
// This is done for consistency with respect to TpCreateRequest, which
// does a great job of creating a request and associating it atomically
// with a supervisory object.
//
LIST_ENTRY InProgressRequest; // TdiListen/TdiConnect
//
// If the connection is being disconnected as a result of
// a TdiDisconnect call (RemoteDisconnect is FALSE) then this
// will hold the IRP passed to TdiDisconnect. It is needed
// when the TdiDisconnect request is completed.
//
PIRP DisconnectIrp;
//
// If the connection is being closed, this will hold
// the IRP passed to TdiCloseConnection. It is needed
// when the request is completed.
//
PIRP CloseIrp;
//
// These fields are used for deferred operations on connections; the only
// deferred operation currently supported is piggyback ACK
//
ULONG DeferredFlags;
#if DBG
ULONG DeferredPasses;
#endif
LIST_ENTRY DeferredQueue;
//
// The following fields are used for connection housekeeping.
//
ULONG Flags; // attributes guarded by LinkSpinLock
ULONG Flags2; // attributes guarded by SpinLock
UINT OnPacketWaitQueue; // TRUE if on PacketWaitQueue
UCHAR Lsn; // local session number (1-254).
UCHAR Rsn; // remote session number (1-254).
USHORT Retries; // retry limit for NAME_QUERY shipments.
KTIMER Timer; // kernel timer for timeouts on NQ/NR.
LARGE_INTEGER ConnectStartTime; // when we sent the committed NQ.
KDPC Dpc; // DPC object for timeouts.
NTSTATUS Status; // status code for connection rundown.
ULONG LastPacketsSent; // The value that was in Link->XXX the
ULONG LastPacketsResent; // last time we calculated the throughput.
NBF_NETBIOS_ADDRESS CalledAddress; // TdiConnect request's T.A.
USHORT MaximumDataSize; // maximum I-frame data size for NBF.
NBF_HDR_CONNECTION NetbiosHeader; // pre-built Netbios header; we store
// the current send and reply correlators
// in the appropriate spots in this.
//
// These are for CONNECTION_INFO queries.
//
ULONG TransmittedTsdus; // TSDUs sent on this connection.
ULONG ReceivedTsdus; // TSDUs received on this connection.
ULONG TransmissionErrors; // TSDUs transmitted in error/this connection.
ULONG ReceiveErrors; // TSDUs received in error/this connection.
//
// The following structure contains statistics counters for use
// by TdiQueryInformation and TdiSetInformation. They should not
// be used for maintenance of internal data structures.
//
// TDI_CONNECTION_INFO Information; // information about this connection.
#if DBG
LIST_ENTRY GlobalLinkage;
ULONG TotalReferences;
ULONG TotalDereferences;
ULONG NextRefLoc;
struct {
PVOID Caller;
PVOID CallersCaller;
} History[CONNECTION_HISTORY_LENGTH];
BOOLEAN Destroyed;
#endif
CHAR RemoteName[16];
#if PKT_LOG
PKT_LOG_QUE LastNRecvs;
PKT_LOG_QUE LastNSends;
PKT_IND_QUE LastNIndcs;
#endif // PKT_LOG
} TP_CONNECTION, *PTP_CONNECTION;
#if DBG
extern KSPIN_LOCK NbfGlobalHistoryLock;
extern LIST_ENTRY NbfGlobalConnectionList;
#define StoreConnectionHistory(_conn,_ref) { \
KIRQL oldIrql; \
KeAcquireSpinLock (&NbfGlobalHistoryLock, &oldIrql); \
if ((_conn)->Destroyed) { \
DbgPrint ("connection touched after being destroyed 0x%lx\n", \
(_conn)); \
DbgBreakPoint(); \
} \
RtlGetCallersAddress( \
&(_conn)->History[(_conn)->NextRefLoc].Caller, \
&(_conn)->History[(_conn)->NextRefLoc].CallersCaller \
); \
if ((_ref)) { \
(_conn)->TotalReferences++; \
} else { \
(_conn)->TotalDereferences++; \
(_conn)->History[(_conn)->NextRefLoc].Caller = \
(PVOID)((ULONG_PTR)(_conn)->History[(_conn)->NextRefLoc].Caller | 1); \
} \
if (++(_conn)->NextRefLoc == CONNECTION_HISTORY_LENGTH) { \
(_conn)->NextRefLoc = 0; \
} \
KeReleaseSpinLock (&NbfGlobalHistoryLock, oldIrql); \
}
#endif
#define CONNECTION_FLAGS_VERSION2 0x00000001 // remote netbios is version 2.0.
#define CONNECTION_FLAGS_RECEIVE_WAKEUP 0x00000002 // send a RECEIVE_OUTSTANDING when a receive arrives.
#define CONNECTION_FLAGS_ACTIVE_RECEIVE 0x00000004 // a receive is active.
#define CONNECTION_FLAGS_WAIT_SI 0x00000020 // waiting for a SESSION_INITIALIZE.
#define CONNECTION_FLAGS_WAIT_SC 0x00000040 // waiting for a SESSION_CONFIRM.
#define CONNECTION_FLAGS_WAIT_LINK_UP 0x00000080 // waiting for DDI to est. connection.
#define CONNECTION_FLAGS_READY 0x00000200 // sends/rcvs/discons valid.
#define CONNECTION_FLAGS_RC_PENDING 0x00001000 // a receive is pending completion
#define CONNECTION_FLAGS_W_PACKETIZE 0x00002000 // w/for a packet to packetize.
#define CONNECTION_FLAGS_PACKETIZE 0x00004000 // we're on the PacketizeQueue.
#define CONNECTION_FLAGS_W_RESYNCH 0x00008000 // waiting for resynch indicator. (receive)
#define CONNECTION_FLAGS_SEND_SI 0x00010000 // w/for a packet to send SI.
#define CONNECTION_FLAGS_SEND_SC 0x00020000 // w/for a packet to send SC.
#define CONNECTION_FLAGS_SEND_DA 0x00040000 // w/for a packet to send DA.
#define CONNECTION_FLAGS_SEND_RO 0x00080000 // w/for a packet to send RO.
#define CONNECTION_FLAGS_SEND_RC 0x00100000 // w/for a packet to send RC.
#define CONNECTION_FLAGS_SEND_SE 0x00200000 // w/for a packet to send SE.
#define CONNECTION_FLAGS_SEND_NR 0x00400000 // w/for a packet to send NR.
#define CONNECTION_FLAGS_NO_INDICATE 0x00800000 // don't take packets at indication time
#define CONNECTION_FLAGS_FAILING_TO_EOR 0x01000000 // wait for an EOF in an incoming request before sending
#define CONNECTION_FLAGS_RESYNCHING 0x02000000 // engaged send side resynch
#define CONNECTION_FLAGS_RCV_CANCELLED 0x10000000 // current receive was cancelled
#define CONNECTION_FLAGS_PEND_INDICATE 0x20000000 // new data received during RC_PENDING
#define CONNECTION_FLAGS_TRANSFER_FAIL 0x40000000 // a transfer data call failed
#define CONNECTION_FLAGS2_STOPPING 0x00000001 // connection is running down.
#define CONNECTION_FLAGS2_WAIT_NR 0x00000002 // waiting for NAME_RECOGNIZED.
#define CONNECTION_FLAGS2_WAIT_NQ 0x00000004 // waiting for NAME_QUERY.
#define CONNECTION_FLAGS2_WAIT_NR_FN 0x00000008 // waiting for FIND NAME response.
#define CONNECTION_FLAGS2_CLOSING 0x00000010 // connection is closing
#define CONNECTION_FLAGS2_ASSOCIATED 0x00000020 // associated with address
#define CONNECTION_FLAGS2_DISCONNECT 0x00000040 // disconnect done on connection
#define CONNECTION_FLAGS2_ACCEPTED 0x00000080 // accept done on connection
#define CONNECTION_FLAGS2_REQ_COMPLETED 0x00000100 // Listen/Connect request completed.
#define CONNECTION_FLAGS2_DISASSOCIATED 0x00000200 // associate CRef has been removed
#define CONNECTION_FLAGS2_DISCONNECTED 0x00000400 // disconnect has been indicated
#define CONNECTION_FLAGS2_NO_LISTEN 0x00000800 // no_listen received during setup
#define CONNECTION_FLAGS2_REMOTE_VALID 0x00001000 // Connection->RemoteName is valid
#define CONNECTION_FLAGS2_GROUP_LSN 0x00002000 // connection LSN is globally assigned
#define CONNECTION_FLAGS2_W_ADDRESS 0x00004000 // waiting for address reregistration.
#define CONNECTION_FLAGS2_PRE_ACCEPT 0x00008000 // no TdiAccept after listen completes
#define CONNECTION_FLAGS2_ABORT 0x00010000 // abort this connection.
#define CONNECTION_FLAGS2_ORDREL 0x00020000 // we're in orderly release.
#define CONNECTION_FLAGS2_DESTROY 0x00040000 // destroy this connection.
#define CONNECTION_FLAGS2_LISTENER 0x00100000 // we were the passive listener.
#define CONNECTION_FLAGS2_CONNECTOR 0x00200000 // we were the active connector.
#define CONNECTION_FLAGS2_WAITING_SC 0x00400000 // the connection is waiting for
// and accept to send the
// session confirm
#define CONNECTION_FLAGS2_INDICATING 0x00800000 // connection was manipulated while
// indication was in progress
#define CONNECTION_FLAGS2_LDISC 0x01000000 // Local disconnect req.
#ifdef RASAUTODIAL
#define CONNECTION_FLAGS2_AUTOCONNECTING 0x02000000 // RAS autodial in progress
#define CONNECTION_FLAGS2_AUTOCONNECTED 0x04000000 // RAS autodial done
#endif // RASAUTODIAL
#define CONNECTION_FLAGS_STARVED ( \
CONNECTION_FLAGS_SEND_SI | \
CONNECTION_FLAGS_SEND_SC | \
CONNECTION_FLAGS_SEND_DA | \
CONNECTION_FLAGS_SEND_RO | \
CONNECTION_FLAGS_SEND_RC | \
CONNECTION_FLAGS_SEND_NR | \
CONNECTION_FLAGS_SEND_SE \
)
#define CONNECTION_FLAGS_DEFERRED_ACK 0x00000001 // send piggyback ack first opportunity
#define CONNECTION_FLAGS_DEFERRED_ACK_2 0x00000002 // deferred ack wasn't sent
#define CONNECTION_FLAGS_DEFERRED_NOT_Q 0x00000004 // DEFERRED_ACK set, but not on DataAckQueue
#define CONNECTION_FLAGS_DEFERRED_SENDS 0x80000000 // print completed sends
#define CONNECTION_SENDSTATE_IDLE 0 // no sends being processed.
#define CONNECTION_SENDSTATE_PACKETIZE 1 // send being packetized.
#define CONNECTION_SENDSTATE_W_PACKET 2 // waiting for free packet.
#define CONNECTION_SENDSTATE_W_LINK 3 // waiting for good link conditions.
#define CONNECTION_SENDSTATE_W_EOR 4 // waiting for TdiSend(EOR).
#define CONNECTION_SENDSTATE_W_ACK 5 // waiting for DATA_ACK.
#define CONNECTION_SENDSTATE_W_RCVCONT 6 // waiting for RECEIVE_CONTINUE.
//
// This structure is pointed to by the FsContext field in the FILE_OBJECT
// for this Address. This structure is the base for all activities on
// the open file object within the transport provider. All active connections
// on the address point to this structure, although no queues exist here to do
// work from. This structure also maintains a reference to a TP_ADDRESS
// structure, which describes the address that it is bound to. Thus, a
// connection will point to this structure, which describes the address the
// connection was associated with. When the address file closes, all connections
// opened on this address file get closed, too. Note that this may leave an
// address hanging around, with other references.
//
typedef struct _TP_ADDRESS_FILE {
CSHORT Type;
CSHORT Size;
LIST_ENTRY Linkage; // next address file on this address.
// also used for linkage in the
// look-aside list
LONG ReferenceCount; // number of references to this object.
//
// This structure is edited after taking the Address spinlock for the
// owning address. This ensures that the address and this structure
// will never get out of syncronization with each other.
//
//
// The following field points to a list of TP_CONNECTION structures,
// one per connection open on this address. This list of connections
// is used to help the cleanup process if a process closes an address
// before disassociating all connections on it. By design, connections
// will stay around until they are explicitly
// closed; we use this database to ensure that we clean up properly.
//
LIST_ENTRY ConnectionDatabase; // list of defined transport connections.
//
// the current state of the address file structure; this is either open or
// closing
//
UCHAR State;
//
// The following fields are kept for housekeeping purposes.
//
PIRP Irp; // the irp used for open or close
struct _TP_ADDRESS *Address; // address to which we are bound.
PFILE_OBJECT FileObject; // easy backlink to file object.
struct _DEVICE_CONTEXT *Provider; // device context to which we are attached.
//
// The following queue is used to queue receive datagram requests
// on this address file. Send datagram requests are queued on the
// address itself. These queues are managed by the EXECUTIVE interlocked
// list management routines. The actual objects which get queued to this
// structure are request control blocks (RCBs).
//
LIST_ENTRY ReceiveDatagramQueue; // FIFO of outstanding TdiReceiveDatagrams.
//
// This holds the Irp used to close this address file,
// for pended completion.
//
PIRP CloseIrp;
//
// is this address file currently indicating a connection request? if yes, we
// need to mark connections that are manipulated during this time.
//
BOOLEAN ConnectIndicationInProgress;
//
// handler for kernel event actions. First we have a set of booleans that
// indicate whether or not this address has an event handler of the given
// type registered.
//
BOOLEAN RegisteredConnectionHandler;
BOOLEAN RegisteredDisconnectHandler;
BOOLEAN RegisteredReceiveHandler;
BOOLEAN RegisteredReceiveDatagramHandler;
BOOLEAN RegisteredExpeditedDataHandler;
BOOLEAN RegisteredErrorHandler;
//
// This function pointer points to a connection indication handler for this
// Address. Any time a connect request is received on the address, this
// routine is invoked.
//
//
PTDI_IND_CONNECT ConnectionHandler;
PVOID ConnectionHandlerContext;
//
// The following function pointer always points to a TDI_IND_DISCONNECT
// handler for the address. If the NULL handler is specified in a
// TdiSetEventHandler, this this points to an internal routine which
// simply returns successfully.
//
PTDI_IND_DISCONNECT DisconnectHandler;
PVOID DisconnectHandlerContext;
//
// The following function pointer always points to a TDI_IND_RECEIVE
// event handler for connections on this address. If the NULL handler
// is specified in a TdiSetEventHandler, then this points to an internal
// routine which does not accept the incoming data.
//
PTDI_IND_RECEIVE ReceiveHandler;
PVOID ReceiveHandlerContext;
//
// The following function pointer always points to a TDI_IND_RECEIVE_DATAGRAM
// event handler for the address. If the NULL handler is specified in a
// TdiSetEventHandler, this this points to an internal routine which does
// not accept the incoming data.
//
PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler;
PVOID ReceiveDatagramHandlerContext;
//
// An expedited data handler. This handler is used if expedited data is
// expected; it never is in NBF, thus this handler should always point to
// the default handler.
//
PTDI_IND_RECEIVE_EXPEDITED ExpeditedDataHandler;
PVOID ExpeditedDataHandlerContext;
//
// The following function pointer always points to a TDI_IND_ERROR
// handler for the address. If the NULL handler is specified in a
// TdiSetEventHandler, this this points to an internal routine which
// simply returns successfully.
//
PTDI_IND_ERROR ErrorHandler;
PVOID ErrorHandlerContext;
PVOID ErrorHandlerOwner;
} TP_ADDRESS_FILE, *PTP_ADDRESS_FILE;
#define ADDRESSFILE_STATE_OPENING 0x00 // not yet open for business
#define ADDRESSFILE_STATE_OPEN 0x01 // open for business
#define ADDRESSFILE_STATE_CLOSING 0x02 // closing
//
// This structure defines a TP_ADDRESS, or active transport address,
// maintained by the transport provider. It contains all the visible
// components of the address (such as the TSAP and network name components),
// and it also contains other maintenance parts, such as a reference count,
// ACL, and so on. All outstanding connection-oriented and connectionless
// data transfer requests are queued here.
//
#if DBG
#define AREF_TIMER 0
#define AREF_TEMP_CREATE 1
#define AREF_OPEN 2
#define AREF_VERIFY 3
#define AREF_LOOKUP 4
#define AREF_FRAME_SEND 5
#define AREF_CONNECTION 6
#define AREF_TEMP_STOP 7
#define AREF_REQUEST 8
#define AREF_PROCESS_UI 9
#define AREF_PROCESS_DATAGRAM 10
#define AREF_TIMER_SCAN 11
#define NUMBER_OF_AREFS 12
#endif
typedef struct _TP_ADDRESS {
#if DBG
ULONG RefTypes[NUMBER_OF_AREFS];
#endif
USHORT Size;
CSHORT Type;
LIST_ENTRY Linkage; // next address/this device object.
LONG ReferenceCount; // number of references to this object.
//
// The following spin lock is acquired to edit this TP_ADDRESS structure
// or to scan down or edit the list of address files.
//
KSPIN_LOCK SpinLock; // lock to manipulate this structure.
//
// The following fields comprise the actual address itself.
//
PIRP Irp; // pointer to address creation IRP.
PNBF_NETBIOS_ADDRESS NetworkName; // this address
//
// The following fields are used to maintain state about this address.
//
ULONG Flags; // attributes of the address.
ULONG SendFlags; // State of the datagram current send
struct _DEVICE_CONTEXT *Provider; // device context to which we are attached.
//
// The following queues is used to hold send datagrams for this
// address. Receive datagrams are queued to the address file. Requests are
// processed in a first-in, first-out manner, so that the very next request
// to be serviced is always at the head of its respective queue. These
// queues are managed by the EXECUTIVE interlocked list management routines.
// The actual objects which get queued to this structure are request control
// blocks (RCBs).
//
LIST_ENTRY SendDatagramQueue; // FIFO of outstanding TdiSendDatagrams.
//
// The following field points to a list of TP_CONNECTION structures,
// one per active, connecting, or disconnecting connections on this
// address. By definition, if a connection is on this list, then
// it is visible to the client in terms of receiving events and being
// able to post requests by naming the ConnectionId. If the connection
// is not on this list, then it is not valid, and it is guaranteed that
// no indications to the client will be made with reference to it, and
// no requests specifying its ConnectionId will be accepted by the transport.
//
LIST_ENTRY ConnectionDatabase; // list of defined transport connections.
LIST_ENTRY AddressFileDatabase; // list of defined address file objects
//
// The packet pool of size 1 that holds the UI frame, and the
// frame that is allocated out of it.
//
NDIS_HANDLE UIFramePoolHandle;
PTP_UI_FRAME UIFrame; // DLC-UI/NBF header for datagram sends.
//
// The following fields are used to register this address on the network.
//
ULONG Retries; // retries of ADD_NAME_QUERY left to go.
KTIMER Timer; // kernel timer for timeouts on ANQ/ANR.
KDPC Dpc; // DPC object for timeout.
//
// These two can be a union because they are not used
// concurrently.
//
union {
//
// This structure is used for checking share access.
//
SHARE_ACCESS ShareAccess;
//
// Used for delaying NbfDestroyAddress to a thread so
// we can access the security descriptor.
//
WORK_QUEUE_ITEM DestroyAddressQueueItem;
} u;
//
// This structure is used to hold ACLs on the address.
PSECURITY_DESCRIPTOR SecurityDescriptor;
//
// If we get an ADD_NAME_RESPONSE frame, this holds the address
// of the remote we got it from (used to check for duplicate names).
//
UCHAR UniqueResponseAddress[6];
//
// Set to TRUE once we send a name in conflict frame, so that
// we don't flood the network with them on every response.
//
BOOLEAN NameInConflictSent;
} TP_ADDRESS, *PTP_ADDRESS;
#define ADDRESS_FLAGS_GROUP 0x00000001 // set if group, otherwise unique.
#define ADDRESS_FLAGS_CONFLICT 0x00000002 // address in conflict detected.
#define ADDRESS_FLAGS_REGISTERING 0x00000004 // registration in progress.
#define ADDRESS_FLAGS_DEREGISTERING 0x00000008 // deregistration in progress.
#define ADDRESS_FLAGS_DUPLICATE_NAME 0x00000010 // duplicate name was found on net.
#define ADDRESS_FLAGS_NEEDS_REG 0x00000020 // address must be registered.
#define ADDRESS_FLAGS_STOPPING 0x00000040 // TpStopAddress is in progress.
#define ADDRESS_FLAGS_BAD_ADDRESS 0x00000080 // name in conflict on associated address.
#define ADDRESS_FLAGS_SEND_IN_PROGRESS 0x00000100 // send datagram process active.
#define ADDRESS_FLAGS_CLOSED 0x00000200 // address has been closed;
// existing activity can
// complete, nothing new can start
#define ADDRESS_FLAGS_NEED_REREGISTER 0x00000400 // quick-reregister on next connect.
#define ADDRESS_FLAGS_QUICK_REREGISTER 0x00000800 // address is quick-reregistering.
#ifndef NO_STRESS_BUG
#define ADDRESS_FLAGS_SENT_TO_NDIS 0x00010000 // Packet sent to the NDIS layer
#define ADDRESS_FLAGS_RETD_BY_NDIS 0x00020000 // Packet returned by the NDIS layer
#endif
//
// This structure defines a TP_LINK, or established data link object,
// maintained by the transport provider. Each data link connection with
// a remote machine is represented by this object. Zero, one, or several
// transport connections can be multiplexed over the same data link connection.
// This object is managed by routines in LINK.C.
//
#if DBG
#define LREF_SPECIAL_CONN 0
#define LREF_SPECIAL_TEMP 1
#define LREF_CONNECTION 2
#define LREF_STOPPING 3
#define LREF_START_T1 4
#define LREF_TREE 5
#define LREF_NOT_ADM 6
#define LREF_NDIS_SEND 7
#define NUMBER_OF_LREFS 8
#endif
#if DBG
#define LINK_HISTORY_LENGTH 20
#endif
typedef struct _TP_LINK {
RTL_SPLAY_LINKS SplayLinks; // for the link splay tree
CSHORT Type; // type of this structure
USHORT Size; // size of this structure
#if DBG
ULONG RefTypes[NUMBER_OF_LREFS];
#endif
LIST_ENTRY Linkage; // for list of free links or deferred
// operation queue
KSPIN_LOCK SpinLock; // lock to manipulate this structure.
LONG ReferenceCount; // number of references to this object.
LONG SpecialRefCount; // controls freeing of the link.
//
// information about the remote hardware this link is talking to.
//
BOOLEAN Loopback; // TRUE if this is a loopback link.
UCHAR LoopbackDestinationIndex; // if Loopback, the index.
HARDWARE_ADDRESS HardwareAddress; // hardware address of remote.
ULARGE_INTEGER MagicAddress; // numerical representation of the
// hardware address used for quick
// comparisons
UCHAR Header[MAX_MAC_HEADER_LENGTH]; // a place to stick a prebuilt packet
// header.
ULONG HeaderLength; // length of Header for this link
//
// Vital conditions surrounding the data link connnection.
//
ULONG MaxFrameSize; // maximum size of NetBIOS frame, MAC
// dependent.
//
// Connections associated with this link. We keep a simple list of
// connections because it's unlikely we'll get more than a few connections
// on a given link (we're assuming that the server or redir will be the
// biggest user of the net in the vast majority of environments). We've
// made the link lookup be via a splay tree, which vastly speeds the
// process of getting to the proper link; as long as there are only a few
// connections, the connection lookup will be fast. If this becomes a
// problem down the road, we can make this connection list be a splay tree
// also.
//
LIST_ENTRY ConnectionDatabase;
ULONG ActiveConnectionCount; // # connections in above list.
//
// The following fields are used to maintain state about this link.
// One other field is implicit-- the address of this object is the
// ConnectionContext value as described in the PDI spec.
//
ULONG Flags; // attributes of the link.
ULONG DeferredFlags; // when on the deferred queue.
ULONG State; // link state variable.
//
// Send-side state.
//
ULONG PacketsSent; // number of packets sent.
ULONG PacketsResent; // number of packets resent.
UCHAR SendState; // send-side state variable.
UCHAR NextSend; // next N(S) we should send.
UCHAR LastAckReceived; // last N(R) we received.
UCHAR SendWindowSize; // current send window size.
UCHAR PrevWindowSize; // size last time we dropped a frame.
UCHAR WindowsUntilIncrease; // how many windows until size increases.
UCHAR SendRetries; // number of retries left/this checkpoint.
UCHAR ConsecutiveLastPacketLost; // consecutive windows with last packet dropped.
ULONG NdisSendsInProgress; // >0 if sends queued to NdisSendQueue.
LIST_ENTRY NdisSendQueue; // queue of sends to pass to NdisSend.
LIST_ENTRY WackQ; // sent packets waiting LLC acks.
BOOLEAN OnDeferredRrQueue;
LIST_ENTRY DeferredRrLinkage;
//
// Receive-side state.
//
ULONG PacketsReceived; // number of packets received.
UCHAR ReceiveState; // receive-side state variable.
UCHAR NextReceive; // next expected N(S) we should receive.
UCHAR LastAckSent; // last N(R) we sent.
UCHAR ReceiveWindowSize; // current receive window size.
BOOLEAN RespondToPoll; // remote guy is polling-- we must final.
BOOLEAN ResendingPackets; // ResendLlcPackets in progress
BOOLEAN LinkBusy; // received RNR (really send-side state).
//
// Timer, used to determine delay and throughput.
//
ULONG Delay; // an NT time, but only LowPart is saved.
LARGE_INTEGER Throughput;
//
// These are counters needed by ADAPTER_STATUS queries.
//
USHORT FrmrsReceived;
USHORT FrmrsTransmitted;
USHORT ErrorIFramesReceived;
USHORT ErrorIFramesTransmitted;
USHORT AbortedTransmissions;
USHORT BuffersNotAvailable;
ULONG SuccessfulTransmits;
ULONG SuccessfulReceives;
USHORT T1Expirations;
USHORT TiExpirations;
//
// Timeout state. There is one kernel timer for this transport that is set
// to go off at regular intervals. This timer increments the current time,
// which is then used to compare against the timer queues. The timer queues
// are ordered, so whenever the first element is not expired, the rest of
// the queue is not expired. This allows us to have hundreds of timers
// running with very little system overhead.
// A value of 0 indicates that the timer is not active.
//
ULONG T1; // retry timer.
ULONG T2; // delayed ack timer.
ULONG Ti; // inactivity timer.
BOOLEAN OnShortList; // TRUE if link is in ShortList
BOOLEAN OnLongList; // TRUE if link is in LongList
LIST_ENTRY ShortList; // list of links waiting t1 or t2
LIST_ENTRY LongList; // list of links waiting ti
LIST_ENTRY PurgeList;
//
// This counter is used to keep track of whether there are
// any "connectors" (connections initiated by this side) on
// this link. If there are none, and we are on an easily
// disconnected link, then we handle the inactivity timeout
// differently.
//
LONG NumberOfConnectors;
//
// BaseT1Timeout is the current T1 timeout computed based on
// the response to previous poll frames. T1Timeout is the
// value to be used for the next T1, and will generally be
// based on BaseT1Timeout but may be more if T1 is backing
// off. T2Timeout and TiTimeout are independent of these.
//
ULONG BaseT1Timeout; // Timeout value for T1, << 16.
ULONG CurrentT1Timeout; // Current backed-off T1 timeout.
ULONG MinimumBaseT1Timeout; // Minimum value, based on link speed.
ULONG BaseT1RecalcThreshhold; // Only recalc BaseT1 on frames > this.
ULONG CurrentPollRetransmits; // Current retransmits waiting for final.
BOOLEAN ThroughputAccurate; // Is the throughput on this link accurate?
BOOLEAN CurrentT1Backoff; // the last poll frame had retransmits
BOOLEAN CurrentPollOutstanding; // Check that we have a poll outstanding.
LARGE_INTEGER CurrentTimerStart; // Time that current timing was begun.
ULONG CurrentPollSize; // Size of current poll packet.
ULONG T2Timeout; // Timeout value for T2.
ULONG TiTimeout; // Timeout value for Ti.
ULONG LlcRetries; // total retry count for this link.
ULONG MaxWindowSize; // maximum send window size.
ULONG TiStartPacketsReceived; // PacketsReceived when Ti was started.
//
// Adaptive window algorithm state.
//
ULONG WindowErrors; // # retransmissions/this adaptive run.
UCHAR BestWindowSize; // our best window from experience.
UCHAR WorstWindowSize; // our worst window from experience.
//
// Keep track of remotes that never poll so we can send
// an RR every two frames.
//
BOOLEAN RemoteNoPoll; // We think remote doesn't poll
UCHAR ConsecutiveIFrames; // number received since polling
#if DBG
UCHAR CreatePacketFailures; // consecutive failures
#endif
LIST_ENTRY DeferredList; // for threading on deferred list
struct _DEVICE_CONTEXT *Provider;
PKSPIN_LOCK ProviderInterlock; // &Provider->Interlock
#if DBG
LIST_ENTRY GlobalLinkage;
ULONG TotalReferences;
ULONG TotalDereferences;
ULONG NextRefLoc;
struct {
PVOID Caller;
PVOID CallersCaller;
} History[LINK_HISTORY_LENGTH];
BOOLEAN Destroyed;
#endif
#if PKT_LOG
PKT_LOG_QUE LastNRecvs;
PKT_LOG_QUE LastNSends;
#endif // PKT_LOG
} TP_LINK, *PTP_LINK;
#if DBG
extern KSPIN_LOCK NbfGlobalHistoryLock;
extern LIST_ENTRY NbfGlobalLinkList;
#define StoreLinkHistory(_link,_ref) { \
KIRQL oldIrql; \
KeAcquireSpinLock (&NbfGlobalHistoryLock, &oldIrql); \
if ((_link)->Destroyed) { \
DbgPrint ("link touched after being destroyed 0x%lx\n", (_link)); \
DbgBreakPoint(); \
} \
RtlGetCallersAddress( \
&(_link)->History[(_link)->NextRefLoc].Caller, \
&(_link)->History[(_link)->NextRefLoc].CallersCaller \
); \
if ((_ref)) { \
(_link)->TotalReferences++; \
} else { \
(_link)->TotalDereferences++; \
(_link)->History[(_link)->NextRefLoc].Caller = \
(PVOID)((ULONG_PTR)(_link)->History[(_link)->NextRefLoc].Caller | 1);\
} \
if (++(_link)->NextRefLoc == LINK_HISTORY_LENGTH) { \
(_link)->NextRefLoc = 0; \
} \
KeReleaseSpinLock (&NbfGlobalHistoryLock, oldIrql); \
}
#endif
#define LINK_FLAGS_JUMP_START 0x00000040 // run adaptive alg/every sent window.
#define LINK_FLAGS_LOCAL_DISC 0x00000080 // link was stopped locally.
//
// deferred flags, used for processing at timer tick if needed
//
#define LINK_FLAGS_DEFERRED_DELETE 0x00010000 // delete at next opportunity
#define LINK_FLAGS_DEFERRED_ADD 0x00020000 // add to splay tree, next opportunity
#define LINK_FLAGS_DEFERRED_MASK 0x00030000 // (LINK_FLAGS_DEFERRED_DELETE | LINK_FLAGS_DEFERRED_ADD)
#define LINK_STATE_ADM 1 // asynchronous disconnected mode.
#define LINK_STATE_READY 2 // asynchronous balanced mode extended.
#define LINK_STATE_BUSY 3 // all link buffers are busy, sent RNR
#define LINK_STATE_CONNECTING 4 // waiting SABME response (UA-r/f).
#define LINK_STATE_W_POLL 5 // waiting initial checkpoint.
#define LINK_STATE_W_FINAL 6 // waiting final from initial checkpoint.
#define LINK_STATE_W_DISC_RSP 7 // waiting disconnect response.
#define SEND_STATE_DOWN 0 // asynchronous disconnected mode.
#define SEND_STATE_READY 1 // completely ready to send.
#define SEND_STATE_REJECTING 2 // other guy is rejecting.
#define SEND_STATE_CHECKPOINTING 3 // we're checkpointing (can't send data).
#define RECEIVE_STATE_DOWN 0 // asynchronous disconnected mode.
#define RECEIVE_STATE_READY 1 // we're ready to receive.
#define RECEIVE_STATE_REJECTING 2 // we're rejecting.
//
// This structure defines the DEVICE_OBJECT and its extension allocated at
// the time the transport provider creates its device object.
//
#if DBG
#define DCREF_CREATION 0
#define DCREF_ADDRESS 1
#define DCREF_CONNECTION 2
#define DCREF_LINK 3
#define DCREF_QUERY_INFO 4
#define DCREF_SCAN_TIMER 5
#define DCREF_REQUEST 6
#define DCREF_TEMP_USE 7
#define NUMBER_OF_DCREFS 8
#endif
typedef struct _NBF_POOL_LIST_DESC {
NDIS_HANDLE PoolHandle;
USHORT NumElements;
USHORT TotalElements;
struct _NBF_POOL_LIST_DESC *Next;
} NBF_POOL_LIST_DESC, *PNBF_POOL_LIST_DESC;
typedef struct _DEVICE_CONTEXT {
DEVICE_OBJECT DeviceObject; // the I/O system's device object.
#if DBG
ULONG RefTypes[NUMBER_OF_DCREFS];
#endif
CSHORT Type; // type of this structure
USHORT Size; // size of this structure
LIST_ENTRY Linkage; // links them on NbfDeviceList;
KSPIN_LOCK Interlock; // GLOBAL spinlock for reference count.
// (used in ExInterlockedXxx calls)
LONG ReferenceCount; // activity count/this provider.
LONG CreateRefRemoved; // has unload or unbind been called ?
//
// This protects the LoopbackQueue.
//
KSPIN_LOCK LoopbackSpinLock;
//
// The queue of packets waiting to be looped back.
//
LIST_ENTRY LoopbackQueue;
//
// These two links are used for loopback.
//
PTP_LINK LoopbackLinks[2];
//
// This buffer is used for loopback indications; a
// contiguous piece is copied into it. It is allocated
// (of size NBF_MAX_LOOPBACK_LOOKAHEAD) when one of
// the LoopbackLinks become non-NULL.
//
PUCHAR LookaheadContiguous;
//
// This holds the length of the header in the currently
// indicating loopback packet.
//
ULONG LoopbackHeaderLength;
//
// Used for processing the loopback queue.
//
KDPC LoopbackDpc;
//
// Determines if a LoopbackDpc is in progress.
//
BOOLEAN LoopbackInProgress;
//
// Determines if a WanDelayedDpc is in progress.
//
BOOLEAN WanThreadQueued;
//
// Used for momentarily delaying WAN packetizing to
// allow RR's to be received.
//
WORK_QUEUE_ITEM WanDelayedQueueItem;
//
// The queue of FIND.NAME requests waiting to be processed.
//
LIST_ENTRY FindNameQueue;
//
// The queue of STATUS.QUERY requests waiting to be processed.
//
LIST_ENTRY StatusQueryQueue;
//
// The queue of QUERY.INDICATION requests waiting to be completed.
//
LIST_ENTRY QueryIndicationQueue;
//
// The queue of DATAGRAM.INDICATION requests waiting to be completed.
//
LIST_ENTRY DatagramIndicationQueue;
//
// The queue of (currently receive only) IRPs waiting to complete.
//
LIST_ENTRY IrpCompletionQueue;
//
// This boolean is TRUE if either of the above two have ever
// had anything on them.
//
BOOLEAN IndicationQueuesInUse;
//
// Following are protected by Global Device Context SpinLock
//
KSPIN_LOCK SpinLock; // lock to manipulate this object.
// (used in KeAcquireSpinLock calls)
//
// the device context state, among open, closing
//
UCHAR State;
//
// Used when processing a STATUS_CLOSING indication.
//
WORK_QUEUE_ITEM StatusClosingQueueItem;
//
// The following queue holds free TP_LINK objects available for allocation.
//
LIST_ENTRY LinkPool;
//
// These counters keep track of resources uses by TP_LINK objects.
//
ULONG LinkAllocated;
ULONG LinkInitAllocated;
ULONG LinkMaxAllocated;
ULONG LinkInUse;
ULONG LinkMaxInUse;
ULONG LinkExhausted;
ULONG LinkTotal;
ULONG LinkSamples;
//
// The following queue holds free TP_ADDRESS objects available for allocation.
//
LIST_ENTRY AddressPool;
//
// These counters keep track of resources uses by TP_ADDRESS objects.
//
ULONG AddressAllocated;
ULONG AddressInitAllocated;
ULONG AddressMaxAllocated;
ULONG AddressInUse;
ULONG AddressMaxInUse;
ULONG AddressExhausted;
ULONG AddressTotal;
ULONG AddressSamples;
//
// The following queue holds free TP_ADDRESS_FILE objects available for allocation.
//
LIST_ENTRY AddressFilePool;
//
// These counters keep track of resources uses by TP_ADDRESS_FILE objects.
//
ULONG AddressFileAllocated;
ULONG AddressFileInitAllocated;
ULONG AddressFileMaxAllocated;
ULONG AddressFileInUse;
ULONG AddressFileMaxInUse;
ULONG AddressFileExhausted;
ULONG AddressFileTotal;
ULONG AddressFileSamples;
//
// The following queue holds free TP_CONNECTION objects available for allocation.
//
LIST_ENTRY ConnectionPool;
//
// These counters keep track of resources uses by TP_CONNECTION objects.
//
ULONG ConnectionAllocated;
ULONG ConnectionInitAllocated;
ULONG ConnectionMaxAllocated;
ULONG ConnectionInUse;
ULONG ConnectionMaxInUse;
ULONG ConnectionExhausted;
ULONG ConnectionTotal;
ULONG ConnectionSamples;
//
// The following is a free list of TP_REQUEST blocks which have been
// previously allocated and are available for use.
//
LIST_ENTRY RequestPool; // free request block pool.
//
// These counters keep track of resources uses by TP_REQUEST objects.
//
ULONG RequestAllocated;
ULONG RequestInitAllocated;
ULONG RequestMaxAllocated;
ULONG RequestInUse;
ULONG RequestMaxInUse;
ULONG RequestExhausted;
ULONG RequestTotal;
ULONG RequestSamples;
//
// The following list comprises a pool of UI NetBIOS frame headers
// that are manipulated by the routines in FRAMESND.C.
//
LIST_ENTRY UIFramePool; // free UI frames (TP_UI_FRAME objects).
//
// These counters keep track of resources uses by TP_UI_FRAME objects.
//
ULONG UIFrameLength;
ULONG UIFrameHeaderLength;
ULONG UIFrameAllocated;
ULONG UIFrameInitAllocated;
ULONG UIFrameExhausted;
//
// The following queue holds I-frame Send packets managed by PACKET.C.
//
SINGLE_LIST_ENTRY PacketPool;
//
// These counters keep track of resources uses by TP_PACKET objects.
//
ULONG PacketLength;
ULONG PacketHeaderLength;
ULONG PacketAllocated;
ULONG PacketInitAllocated;
ULONG PacketExhausted;
//
// The following queue holds RR-frame Send packets managed by PACKET.C.
//
SINGLE_LIST_ENTRY RrPacketPool;
//
// The following queue contains Receive packets
//
SINGLE_LIST_ENTRY ReceivePacketPool;
//
// These counters keep track of resources uses by NDIS_PACKET objects.
//
ULONG ReceivePacketAllocated;
ULONG ReceivePacketInitAllocated;
ULONG ReceivePacketExhausted;
//
// This queue contains pre-allocated receive buffers
//
SINGLE_LIST_ENTRY ReceiveBufferPool;
//
// These counters keep track of resources uses by TP_PACKET objects.
//
ULONG ReceiveBufferLength;
ULONG ReceiveBufferAllocated;
ULONG ReceiveBufferInitAllocated;
ULONG ReceiveBufferExhausted;
//
// This holds the total memory allocated for the above structures.
//
ULONG MemoryUsage;
ULONG MemoryLimit;
//
// The following field is a head of a list of TP_ADDRESS objects that
// are defined for this transport provider. To edit the list, you must
// hold the spinlock of the device context object.
//
LIST_ENTRY AddressDatabase; // list of defined transport addresses.
//
// The following field is the pointer to the root of the splay tree of
// links that are associated with this Device Context. You must hold the
// LinkSpinLock to modify this list. You must set the LinkTreeSemaphore
// to traverse this list without modifying it. Note that all modify
// operations are deferred to timer(DPC)-time operations.
//
KSPIN_LOCK LinkSpinLock; // protects these values
PTP_LINK LastLink; // the last link found in the tree.
PRTL_SPLAY_LINKS LinkTreeRoot; // pointer to root of the tree.
ULONG LinkTreeElements; // how many elements in the tree
LIST_ENTRY LinkDeferred; // Deferred operations on links.
ULONG DeferredNotSatisfied; // how many times we've come to the
// deferred well and not gotten it clear.
//
// The following queue holds connections which are waiting on available
// packets. As each new packet becomes available, a connection is removed
// from this queue and placed on the PacketizeQueue.
//
LIST_ENTRY PacketWaitQueue; // queue of packet-starved connections.
LIST_ENTRY PacketizeQueue; // queue of ready-to-packetize connections.
//
// The following queue holds connections which are waiting to send
// a piggyback ack. In that case the CONNECTION_FLAGS_DEFERRED_ACK
// bit in DeferredFlags will be set.
//
LIST_ENTRY DataAckQueue;
//
// The following queue holds links which are waiting to send an
// RR frame because the remote they are talking to never polls.
//
LIST_ENTRY DeferredRrQueue;
//
// Used to track when the queue has changed.
//
BOOLEAN DataAckQueueChanged;
//
// When this hits thirty seconds we checked for stalled connections.
//
USHORT StalledConnectionCount;
//
// This queue contains receives that are in progress
//
LIST_ENTRY ReceiveInProgress;
//
// NDIS fields
//
//
// following is used to keep adapter information.
//
NDIS_HANDLE NdisBindingHandle;
//
// The following fields are used for talking to NDIS. They keep information
// for the NDIS wrapper to use when determining what pool to use for
// allocating storage.
//
KSPIN_LOCK SendPoolListLock; // protects these values
PNBF_POOL_LIST_DESC SendPacketPoolDesc;
KSPIN_LOCK RcvPoolListLock; // protects these values
PNBF_POOL_LIST_DESC ReceivePacketPoolDesc;
NDIS_HANDLE NdisBufferPool;
//
// These are kept around for error logging.
//
ULONG SendPacketPoolSize;
ULONG ReceivePacketPoolSize;
ULONG MaxRequests;
ULONG MaxLinks;
ULONG MaxConnections;
ULONG MaxAddressFiles;
ULONG MaxAddresses;
PWCHAR DeviceName;
ULONG DeviceNameLength;
//
// This is the Mac type we must build the packet header for and know the
// offsets for.
//
NBF_NDIS_IDENTIFICATION MacInfo; // MAC type and other info
ULONG MaxReceivePacketSize; // does not include the MAC header
ULONG MaxSendPacketSize; // includes the MAC header
ULONG CurSendPacketSize; // may be smaller for async
USHORT RecommendedSendWindow; // used for Async lines
BOOLEAN EasilyDisconnected; // TRUE over wireless nets.
//
// some MAC addresses we use in the transport
//
HARDWARE_ADDRESS LocalAddress; // our local hardware address.
HARDWARE_ADDRESS NetBIOSAddress; // NetBIOS functional address, used for TR
//
// The reserved Netbios address; consists of 10 zeroes
// followed by LocalAddress;
//
UCHAR ReservedNetBIOSAddress[NETBIOS_NAME_LENGTH];
HANDLE TdiDeviceHandle;
HANDLE ReservedAddressHandle;
//
// These are used while initializing the MAC driver.
//
KEVENT NdisRequestEvent; // used for pended requests.
NDIS_STATUS NdisRequestStatus; // records request status.
//
// This next field maintains a unique number which can next be assigned
// as a connection identifier. It is incremented by one each time a
// value is allocated.
//
USHORT UniqueIdentifier; // starts at 0, wraps around 2^16-1.
//
// This contains the next unique indentified to use as
// the FsContext in the file object associated with an
// open of the control channel.
//
USHORT ControlChannelIdentifier;
//
// The following fields are used to implement the lightweight timer
// system in the protocol provider. Each TP_LINK object in the device
// context's LinkDatabase contains three lightweight timers that are
// serviced by a DPC routine, which receives control by kernel functions.
// There is one kernel timer for this transport that is set
// to go off at regular intervals. This timer increments the Absolute time,
// which is then used to compare against the timer queues. The timer queues
// are ordered, so whenever the first element is not expired, the rest of
// the queue is not expired. This allows us to have hundreds of timers
// running with very low system overhead.
// A value of -1 indicates that the timer is not active.
//
ULONG TimerState; // See the timer Macros in nbfprocs.h
LARGE_INTEGER ShortTimerStart; // when the short timer was set.
KDPC ShortTimerSystemDpc; // kernel DPC object, short timer.
KTIMER ShortSystemTimer; // kernel timer object, short timer.
ULONG ShortAbsoluteTime; // up-count timer ticks, short timer.
ULONG AdaptivePurge; // absolute time of next purge (short timer).
KDPC LongTimerSystemDpc; // kernel DPC object, long timer.
KTIMER LongSystemTimer; // kernel timer object, long timer.
ULONG LongAbsoluteTime; // up-count timer ticks, long timer.
union _DC_ACTIVE {
struct _DC_INDIVIDUAL {
BOOLEAN ShortListActive; // ShortList is not empty.
BOOLEAN DataAckQueueActive; // DataAckQueue is not empty.
BOOLEAN LinkDeferredActive; // LinkDeferred is not empty.
} i;
ULONG AnyActive; // used to check all four at once.
} a;
BOOLEAN ProcessingShortTimer; // TRUE if we are in ScanShortTimer.
KSPIN_LOCK TimerSpinLock; // lock for following timer queues
LIST_ENTRY ShortList; // list of links waiting T1 or T2
LIST_ENTRY LongList; // list of links waiting Ti expire
LIST_ENTRY PurgeList; // list of links waiting LAT expire
//
// These fields are used on "easily disconnected" adapters.
// Every time the long timer expires, it notes if there has
// been any multicast traffic received. If there has not been,
// it increments LongTimeoutsWithoutMulticast. Activity is
// recorded by incrementing MulticastPacket when MC
// packets are received, and zeroing it when the long timer
// expires.
//
ULONG LongTimeoutsWithoutMulticast; // LongTimer timeouts since traffic.
ULONG MulticastPacketCount; // How many MC packets rcved, this timeout.
//
// This information is used to keep track of the speed of
// the underlying medium.
//
ULONG MediumSpeed; // in units of 100 bytes/sec
BOOLEAN MediumSpeedAccurate; // if FALSE, can't use the link.
//
// This is TRUE if we are on a UP system.
//
BOOLEAN UniProcessor;
//
// Configuration information on how soon we should send
// an unasked for RR with a non-polling remote.
//
UCHAR MaxConsecutiveIFrames;
//
// This is configuration information controlling the default
// value of timers and retry counts.
//
ULONG DefaultT1Timeout;
ULONG MinimumT1Timeout;
ULONG DefaultT2Timeout;
ULONG DefaultTiTimeout;
ULONG LlcRetries;
ULONG LlcMaxWindowSize;
ULONG NameQueryRetries;
ULONG NameQueryTimeout;
ULONG AddNameQueryRetries;
ULONG AddNameQueryTimeout;
ULONG GeneralRetries;
ULONG GeneralTimeout;
ULONG MinimumSendWindowLimit; // how low we can lock a connection's window
//
// Counters for most of the statistics that NBF maintains;
// some of these are kept elsewhere. Including the structure
// itself wastes a little space but ensures that the alignment
// inside the structure is correct.
//
TDI_PROVIDER_STATISTICS Statistics;
//
// These are "temporary" versions of the other counters.
// During normal operations we update these, then during
// the short timer expiration we update the real ones.
//
ULONG TempIFrameBytesSent;
ULONG TempIFramesSent;
ULONG TempIFrameBytesReceived;
ULONG TempIFramesReceived;
//
// Some counters needed for Netbios adapter status.
//
ULONG TiExpirations;
ULONG FrmrReceived;
ULONG FrmrTransmitted;
//
// These are used to compute AverageSendWindow.
//
ULONG SendWindowTotal;
ULONG SendWindowSamples;
//
// Counters for "active" time.
//
LARGE_INTEGER NbfStartTime;
//
// This resource guards access to the ShareAccess
// and SecurityDescriptor fields in addresses.
//
ERESOURCE AddressResource;
//
// This array is used to keep track of which LSNs are
// available for use by Netbios sessions. LSNs can be
// re-used for sessions to unique names if they are on
// different links, but must be committed beforehand
// for group names. The maximum value that can fit in
// an array element is defined by LSN_TABLE_MAX.
//
UCHAR LsnTable[NETBIOS_SESSION_LIMIT+1];
//
// This is where we start looking in LsnTable for an
// unused LSN. We cycle from 0-63 to prevent quick
// down-and-up connections from getting funny data.
//
ULONG NextLsnStart;
//
// This array is used to quickly dismiss UI frames that
// are not destined for us. The count is the number
// of addresses with that first letter that are registered
// on this device.
//
UCHAR AddressCounts[256];
//
// This is to hold the underlying PDO of the device so
// that we can answer DEVICE_RELATION IRPs from above
//
PVOID PnPContext;
//
// The following structure contains statistics counters for use
// by TdiQueryInformation and TdiSetInformation. They should not
// be used for maintenance of internal data structures.
//
TDI_PROVIDER_INFO Information; // information about this provider.
PTP_VARIABLE NetmanVariables; // list of network managable variables.
//
// The magic bullet is a packet that is sent under certain debugging
// conditions. This allows the transport to signal packet capture devices
// that a particular condiion has been met. This packet has the current
// devicecontext as the source, and 0x04 in every other byte of the packet.
//
UCHAR MagicBullet[32]; //
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
//
// device context state definitions
//
#define DEVICECONTEXT_STATE_OPENING 0x00
#define DEVICECONTEXT_STATE_OPEN 0x01
#define DEVICECONTEXT_STATE_DOWN 0x02
#define DEVICECONTEXT_STATE_STOPPING 0x03
//
// device context PnP Flags
//
// #define DEVICECONTEXT_FLAGS_REMOVING 0x01
// #define DEVICECONTEXT_FLAGS_POWERING_OFF 0x02
// #define DEVICECONTEXT_FLAGS_POWERED_DOWN 0x04
//
// This is the maximum value that can go in an element
// of LsnTable (should be 0xff if they are UCHARs,
// 0xffff for USHORTs, etc.).
//
#define LSN_TABLE_MAX 0xff
#define MAGIC_BULLET_FOOD 0x04
//
// These are constants for the LoopbackLinks elements.
// The distinctions are arbitrary; the listener link
// is the one established from ProcessNameQuery, and
// the connector link is the one established from
// ProcessNameRecognized.
//
#define LISTENER_LINK 0
#define CONNECTOR_LINK 1
//
// This structure defines the packet object, used to represent a DLC I-frame
// in some portion of its lifetime. The PACKET.C module contains routines
// to manage this object.
//
typedef struct _TP_PACKET {
CSHORT Type; // type of this structure
USHORT Size; // size of this structure
PNDIS_PACKET NdisPacket; // ptr to owning Ndis Packet
ULONG NdisIFrameLength; // Length of NdisPacket
LIST_ENTRY Linkage; // used to chain packets together.
LONG ReferenceCount; // activity count/this packet.
BOOLEAN PacketSent; // packet completed by NDIS.
BOOLEAN PacketNoNdisBuffer; // chain on this packet was not allocated.
UCHAR Action; // what to do when we're acked.
BOOLEAN PacketizeConnection; // restart packetizing when completed.
PVOID Owner; // ptr to owning connection or IrpSp.
PTP_LINK Link; // ptr to link it was sent on.
PDEVICE_CONTEXT Provider; // The owner of this packet.
PKSPIN_LOCK ProviderInterlock; // &Provider->Interlock.
UCHAR Header[1]; // the MAC, DLC, and NBF headers
} TP_PACKET, *PTP_PACKET;
//
// The following values are placed in the Action field in the TP_PACKET
// object to indicate what action, if any, should be taken when the packet
// is destroyed.
//
#define PACKET_ACTION_NULL 0 // no special action should be taken.
#define PACKET_ACTION_IRP_SP 1 // Owner is an IRP_SP, deref when done.
#define PACKET_ACTION_CONNECTION 2 // Owner is a TP_CONNECTION, deref when done.
#define PACKET_ACTION_END 3 // shutdown session (sent SESSION_END).
#define PACKET_ACTION_RR 5 // packet is an RR, put back in RR pool.
//
// Types used to hold information in the send and receive NDIS packets
//
typedef struct _SEND_PACKET_TAG {
LIST_ENTRY Linkage; // used for threading on loopback queue
BOOLEAN OnLoopbackQueue; // TRUE if the packet is on a loopback queue
UCHAR LoopbackLinkIndex; // index of other link for loopback packets
USHORT Type; // identifier for packet type
PVOID Frame; // backpointer to owning NBF structure
PVOID Owner; // backpointer for owning nbf construct
// (like address, devicecontext, etc)
} SEND_PACKET_TAG, *PSEND_PACKET_TAG;
//
// Packet types used in send completion
//
#define TYPE_I_FRAME 1
#define TYPE_UI_FRAME 2
#define TYPE_ADDRESS_FRAME 3
//
// LoopbackLinkIndex values.
//
#define LOOPBACK_TO_LISTENER 0
#define LOOPBACK_TO_CONNECTOR 1
#define LOOPBACK_UI_FRAME 2
//
// receive packet used to hold information about this receive
//
typedef struct _RECEIVE_PACKET_TAG {
SINGLE_LIST_ENTRY Linkage; // used for threading in pool
PTP_CONNECTION Connection; // connection this receive is occuring on
ULONG BytesToTransfer; // for I-frame, bytes in this transfer
UCHAR PacketType; // the type of packet we're processing
BOOLEAN AllocatedNdisBuffer; // did we allocate our own NDIS_BUFFERs
BOOLEAN EndOfMessage; // does this receive complete the message
BOOLEAN CompleteReceive; // complete the receive after TransferData?
BOOLEAN TransferDataPended; // TRUE if TransferData returned PENDING
} RECEIVE_PACKET_TAG, *PRECEIVE_PACKET_TAG;
#define TYPE_AT_INDICATE 1
#define TYPE_AT_COMPLETE 2
#define TYPE_STATUS_RESPONSE 3
//
// receive buffer descriptor (built in memory at the beginning of the buffer)
//
typedef struct _BUFFER_TAG {
LIST_ENTRY Linkage; // thread in pool and on receive queue
NDIS_STATUS NdisStatus; // completion status for send
PTP_ADDRESS Address; // the address this datagram is for.
PNDIS_BUFFER NdisBuffer; // describes the rest of the buffer
ULONG Length; // the length of the buffer
UCHAR Buffer[1]; // the actual storage (accessed through the NDIS_BUFFER)
} BUFFER_TAG, *PBUFFER_TAG;
//
// Structure used to interpret the TransportReserved part in the NET_PNP_EVENT
//
typedef struct _NET_PNP_EVENT_RESERVED {
PWORK_QUEUE_ITEM PnPWorkItem;
PDEVICE_CONTEXT DeviceContext;
} NET_PNP_EVENT_RESERVED, *PNET_PNP_EVENT_RESERVED;
#endif // def _NBFTYPES_