📄 smbxchng.h
字号:
/*++
Copyright (c) 1987-1999 Microsoft Corporation
Module Name:
smbcxchng.h
Abstract:
This is the include file that defines all constants and types for
SMB exchange implementation.
Notes:
An exchange is the core abstarction on which the SMB connection engine and
the mini RDR are implemented. It encapsulates the notion of sending an SMB to
the server and receiving the associated response, i.e, exchanging an SMB and
hence the name.
The exchange of an SMB with the server involves the following steps ....
1) Submitting the formatted SMB buffer for transmission.
2) Processing a send complete indication which ensures that at the
transport level the SMB has been sent to the server.
3) Processing the receive indication which contains all/part of the
response sent by the server.
4) Copying additional data not indicated by the transport
There are a number of variations on this theme. For example there are certain
SMB's for which no response is expected, e.g., certain SMB's which are
inherently multi part in nature, TRANSACT smb's.
In addition the steps outlined above will not always happen in that order. The
precise sequence of events is dictated by the underlying transport chosen and
the network conditions. It is this dependency that makes the implementation
of exchanges challenging.
The two primary goals that the current implementation was designed for are (1)
performance and (2) encapsulation of transport dependencies. Goal(1) is
important because this constitutes an integral part of the code path for
exchanging any packet with the server. Goal (2) is important to ensure
customization of the Rdr for different transports. This encapsulation provides
a convenient vehicle for isolating SMB protocol level decisions from transport
level decisons as much as possible.
In addition the following goals were used to guide the implementation process ...
1) The exchange implementation must be able to handle asynchronous
operations and synchronous operations well. The trade offs were made in
favour of asynchronous operations as and when required.
2) Sufficient infrastructure support must be provided so as to ease the
implementation of different flavours of exchanges.
The SMB_EXCHANGE consists of a dispatch vector with the following functions
1) Start -- to initiate the exchange
2) Receive -- to handle response indications from the server
3) CopyDataHandler -- to handle portions of the response not indicated
4) SendCompletionHandler -- to handle send complete indications from the transport.
5) QuiescentStateHandler -- to handle transitions to a quiescent state, i.e., no
SMB connection engine operations are outstanding.
Most kinds of exchange use the QuiescentStateHandler to finalize the
operation and discard the exchange. However, certain kinds of exchanges
which implement the notion of a macro exchange, i.e., exchange multiple
SMB's use this to delineate different phases of the multiple exchange,
e.g., ORDINARY_EXCHANGE which implements most file io operations.
In addition to the dispatch vector the vanilla exchange consists of state
information to record the current state of the exchange, sufficient context
for resumption and context for handling SMB protocol related operations. The
SMB protocol requires that each SMB sent to the server be stamped with a MID
( multiplex id. ) in order to distinguish between concurrent SMB exchanges.
The connection engine provides this service.
The exchange also encapsulates a SMBCE_EXCHANGE_CONTEXT instance which
encapsulates all the information required for building a SMB_HEADER.
--*/
#ifndef _SMBXCHNG_H_
#define _SMBXCHNG_H_
typedef enum _SMBCE_STATE_ {
SMBCE_START_IN_PROGRESS,
SMBCE_STARTED,
SMBCE_STOP_IN_PROGRESS,
SMBCE_STOPPED
} SMBCE_STATE, *PSMBCE_STATE;
typedef struct _SMBCE_STARTSTOP_CONTEXT_ {
SMBCE_STATE State;
LONG ActiveExchanges;
KEVENT StopEvent;
PKEVENT pServerEntryTearDownEvent;
LIST_ENTRY SessionSetupRequests;
} SMBCE_STARTSTOP_CONTEXT, *PSMBCE_STARTSTOP_CONTEXT;
extern SMBCE_STARTSTOP_CONTEXT SmbCeStartStopContext;
//
// SMB_PROTOCOL_EXCHANGE dispatch vector function prototypes ..
//
// the initiator or the start routine
typedef
NTSTATUS
(*PSMB_EXCHANGE_START)(
IN struct _SMB_EXCHANGE *pExchange);
// The SMB receive handler
typedef
NTSTATUS
(*PSMB_EXCHANGE_IND_RECEIVE)(
IN struct _SMB_EXCHANGE *pExchange, // The exchange instance
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PSMB_HEADER pSmbHeader,
OUT PMDL *pDataBufferPointer, // buffer to copy unindicated data
OUT PULONG pDataSize, // buffer size
IN ULONG ReceiveFlags
);
// the SMB xmit callback
typedef
NTSTATUS
(*PSMB_EXCHANGE_IND_SEND_CALLBACK)(
IN struct _SMB_EXCHANGE *pExchange, // The exchange instance
IN PMDL pDataBuffer,
IN NTSTATUS SendCompletionStatus
);
// the copy data callback for fetching large data
typedef
NTSTATUS
(*PSMB_EXCHANGE_IND_COPY_DATA_CALLBACK)(
IN struct _SMB_EXCHANGE *pExchange, // the exchange instance
IN PMDL pCopyDataBuffer, // the buffer
IN ULONG CopyDataSize // amount of data copied
);
// the finalization routine
// This particular routine has a signature that is NT specific the IRQL
// parameter that is passed in and the notion of posting. This helps consolidate
// the NT transport driver model of indications at DPC level in SmbCeFinalizeExchange.
// On WIN95 the lease restrictive value of IRQL can be passed in.
typedef
NTSTATUS
(*PSMB_EXCHANGE_FINALIZE)(
IN OUT struct _SMB_EXCHANGE *pExchange,
OUT BOOLEAN *pPostRequest);
typedef
NTSTATUS
(*PSMB_EXCHANGE_IND_ASSOCIATED_EXCHANGES_COMPLETION)(
IN OUT struct _SMB_EXCHANGE *pExchange,
OUT BOOLEAN *pPostRequest);
// The Exchange dispatch vector definition
typedef struct _SMB_EXCHANGE_DISPATCH_VECTOR_ {
PSMB_EXCHANGE_START Start;
PSMB_EXCHANGE_IND_RECEIVE Receive;
PSMB_EXCHANGE_IND_COPY_DATA_CALLBACK CopyDataHandler;
PSMB_EXCHANGE_IND_SEND_CALLBACK SendCompletionHandler;
PSMB_EXCHANGE_FINALIZE Finalize;
PSMB_EXCHANGE_IND_ASSOCIATED_EXCHANGES_COMPLETION AssociatedExchangesCompletionHandler;
} SMB_EXCHANGE_DISPATCH_VECTOR, *PSMB_EXCHANGE_DISPATCH_VECTOR;
// An enumerated type listing the type of exchanges
typedef enum _SMB_EXCHANGE_TYPE_ {
CONSTRUCT_NETROOT_EXCHANGE,
ORDINARY_EXCHANGE,
TRANSACT_EXCHANGE,
ADMIN_EXCHANGE,
SENTINEL_EXCHANGE
} SMB_EXCHANGE_TYPE, *PSMB_EXCHANGE_TYPE;
// known exchange type dispatch vectors
extern SMB_EXCHANGE_DISPATCH_VECTOR ConstructNetRootExchangeDispatch;
extern SMB_EXCHANGE_DISPATCH_VECTOR OrdinaryExchangeDispatch;
extern SMB_EXCHANGE_DISPATCH_VECTOR TransactExchangeDispatch;
// The various states of the exchange. Each exchange transitions from
// the SMBCE_EXCHANGE_INITIALIZATION_START to SMBCE_EXCHANGE_INITIATED or
// SMBCE_EXCHANGE_ABORTED state.
typedef enum _SMBCE_EXCHANGE_STATE_ {
SMBCE_EXCHANGE_INITIALIZATION_START,
SMBCE_EXCHANGE_SERVER_INITIALIZED,
SMBCE_EXCHANGE_SESSION_INITIALIZED,
SMBCE_EXCHANGE_NETROOT_INITIALIZED,
SMBCE_EXCHANGE_INITIATED,
SMBCE_EXCHANGE_ABORTED
} SMBCE_EXCHANGE_STATE, *PSMBCE_EXCHANGE_STATE;
// The exchange encapsulates the transport information from the clients. The
// Exchange engine is sandwiched between the protocol selection engine in the
// mini redirector on one side and the various transports on the other side.
// The transport information encapsulates the various categories of transport
// the exchange engine understands.
typedef struct SMBCE_EXCHANGE_TRANSPORT_INFORMATION {
union {
struct {
struct _SMBCE_VC *pVc;
} Vcs;
struct {
ULONG Dummy;
} Datagrams;
struct {
ULONG Dummy;
} Hybrid;
};
} SMBCE_EXCHANGE_TRANSPORT_CONTEXT,
*PSMBCE_EXCHANGE_TRANSPORT_CONTEXT;
typedef struct _SMBCE_EXCHANGE_CONTEXT_ {
PMRX_V_NET_ROOT pVNetRoot;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
SMBCE_EXCHANGE_TRANSPORT_CONTEXT TransportContext;
} SMBCE_EXCHANGE_CONTEXT,*PSMBCE_EXCHANGE_CONTEXT;
//
// Similar to the subclassing of SMB net roots the SMB_EXCHANGE will be subclassed
// further to deal with various types of SMB exchanges. SMB exchanges can be roughly
// classified into the following types based on the interactions involved ...
//
// The SMB's that need to be exchanged need to be augmented with some admin SMB's which
// are required for the maintenance of SMB's in the connection engine.
#define SMBCE_EXCHANGE_MID_VALID (0x1)
#define SMBCE_EXCHANGE_REUSE_MID (0x2)
#define SMBCE_EXCHANGE_RETAIN_MID (SMBCE_EXCHANGE_REUSE_MID)
#define SMBCE_EXCHANGE_MULTIPLE_SENDS_POSSIBLE (0x4)
#define SMBCE_EXCHANGE_FINALIZED (0x8)
#define SMBCE_EXCHANGE_ATTEMPT_RECONNECTS (0x10)
#define SMBCE_EXCHANGE_INDEFINITE_DELAY_IN_RESPONSE (0x20)
#define SMBCE_EXCHANGE_MAILSLOT_OPERATION (0x40)
#define SMBCE_EXCHANGE_SESSION_CONSTRUCTOR (0x100)
#define SMBCE_EXCHANGE_NETROOT_CONSTRUCTOR (0x200)
#define SMBCE_EXCHANGE_NOT_FROM_POOL (0x800)
#define SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION (0x1000)
#define SMBCE_EXCHANGE_TIMEDOUT (0x2000)
#define SMBCE_EXCHANGE_FULL_PROCESSID_SPECIFIED (0x4000)
#define SMBCE_EXCHANGE_SMBCE_STOPPED (0x8000)
#define SMBCE_ASSOCIATED_EXCHANGE (0x80000000)
#define SMBCE_ASSOCIATED_EXCHANGES_COMPLETION_HANDLER_ACTIVATED (0x40000000)
#define SMBCE_EXCHANGE_FLAGS_TO_PRESERVE (SMBCE_EXCHANGE_NOT_FROM_POOL)
#define SMBCE_OPLOCK_RESPONSE_MID (0xffff)
#define SMBCE_MAILSLOT_OPERATION_MID (0xffff)
#define SMBCE_ECHO_PROBE_MID (0xfffe)
//
// The cancellation status is defined as a PVOID instead of a BOOLEAN to allow
// us the use of Interlocked manipulation instructions
// There are only two states SMBCE_EXCHANGE_CANCELLED, SMBCE_EXCHANGE_ACTIVE
//
#define SMBCE_EXCHANGE_CANCELLED (0xcccccccc)
#define SMBCE_EXCHANGE_NOT_CANCELLED (0xaaaaaaaa)
// The Exchange definition
typedef struct _SMB_EXCHANGE {
union {
UCHAR Type;
struct {
NODE_TYPE_CODE NodeTypeCode; // node type.
NODE_BYTE_SIZE NodeByteSize; // node size.
LONG ReferenceCount;
};
};
LIST_ENTRY SmbMmInUseListEntry;
PRX_CONTEXT RxContext; //use of these two fields is advisory
PVOID LastExecutingThread; //OE and Xact will use them
union {
NTSTATUS SmbStatus;
PMRX_SMB_SRV_OPEN SmbSrvOpen;
};
NTSTATUS Status;
ULONG ServerVersion;
SMB_EXCHANGE_ID Id;
USHORT SmbCeState;
USHORT MidCookie;
SMB_MPX_ID Mid;
LONG CancellationStatus;
ULONG SmbCeFlags;
SMBCE_EXCHANGE_CONTEXT SmbCeContext;
LONG SendCompletePendingOperations;
LONG CopyDataPendingOperations;
LONG ReceivePendingOperations;
LONG LocalPendingOperations;
PKEVENT pSmbCeSynchronizationEvent;
LIST_ENTRY ExchangeList;
LARGE_INTEGER ExpiryTime;
PSMB_EXCHANGE_DISPATCH_VECTOR pDispatchVector;
union {
struct {
struct _SMB_EXCHANGE *pMasterExchange;
SINGLE_LIST_ENTRY NextAssociatedExchange;
} Associated;
struct {
SINGLE_LIST_ENTRY AssociatedExchangesToBeFinalized;
LONG PendingAssociatedExchanges;
} Master;
};
RX_WORK_QUEUE_ITEM WorkQueueItem;
ULONG ExchangeTransportInitialized;
NTSTATUS SessionSetupStatus;
} SMB_EXCHANGE, *PSMB_EXCHANGE;
INLINE PSMBCEDB_SERVER_ENTRY
SmbCeGetExchangeServerEntry(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
ASSERT(pSmbExchange->SmbCeContext.pServerEntry != NULL);
return pSmbExchange->SmbCeContext.pServerEntry;
}
INLINE PSMBCE_SERVER
SmbCeGetExchangeServer(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
return &(pSmbExchange->SmbCeContext.pServerEntry->Server);
}
INLINE PSMBCEDB_SESSION_ENTRY
SmbCeGetExchangeSessionEntry(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
if (pSmbExchange->SmbCeContext.pVNetRootContext != NULL) {
return pSmbExchange->SmbCeContext.pVNetRootContext->pSessionEntry;
} else {
return NULL;
}
}
INLINE PSMBCE_SESSION
SmbCeGetExchangeSession(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
if (pSmbExchange->SmbCeContext.pVNetRootContext != NULL) {
return &(pSmbExchange->SmbCeContext.pVNetRootContext->pSessionEntry->Session);
} else {
return NULL;
}
}
INLINE PSMBCEDB_NET_ROOT_ENTRY
SmbCeGetExchangeNetRootEntry(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
if (pSmbExchange->SmbCeContext.pVNetRootContext != NULL) {
return pSmbExchange->SmbCeContext.pVNetRootContext->pNetRootEntry;
} else {
return NULL;
}
}
INLINE PSMBCE_NET_ROOT
SmbCeGetExchangeNetRoot(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
if (pSmbExchange->SmbCeContext.pVNetRootContext != NULL) {
return &(pSmbExchange->SmbCeContext.pVNetRootContext->pNetRootEntry->NetRoot);
} else {
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -