summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/nbf/nbftypes.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/tdi/nbf/nbftypes.h2202
1 files changed, 2202 insertions, 0 deletions
diff --git a/private/ntos/tdi/nbf/nbftypes.h b/private/ntos/tdi/nbf/nbftypes.h
new file mode 100644
index 000000000..a72e9fe1b
--- /dev/null
+++ b/private/ntos/tdi/nbf/nbftypes.h
@@ -0,0 +1,2202 @@
+/*++
+
+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
+
+//
+// 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;
+
+#ifdef _PNP_POWER
+//
+// in nbfdrvr.c
+//
+
+extern UNICODE_STRING NbfRegistryPath;
+
+//
+// We need the driver object to create device context structures.
+//
+
+extern PDRIVER_OBJECT NbfDriverObject;
+
+#endif // _PNP_POWER
+#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)(_req)->History[(_req)->NextRefLoc].Caller & \
+ ~0x80000000); \
+ } \
+ 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 (BUGBUG: What about Alpha?)
+ //
+
+ 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];
+
+} 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)(_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.
+ 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.
+
+
+//
+// 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
+
+} 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)(_link)->History[(_link)->NextRefLoc].Caller & \
+ ~0x80000000); \
+ } \
+ 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 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.
+
+
+ //
+ // 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];
+#ifdef _PNP_POWER
+ HANDLE TdiDeviceHandle;
+ HANDLE ReservedAddressHandle;
+#endif
+
+ //
+ // 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.
+ //
+
+ 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 TimersInitialized; // has the timer system been initialized.
+ 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];
+
+ //
+ // 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
+
+//
+// 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;
+
+#endif // def _NBFTYPES_
+