📄 smbxchng.h
字号:
}
INLINE PMRX_V_NET_ROOT
SmbCeGetExchangeVNetRoot(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
return pSmbExchange->SmbCeContext.pVNetRoot;
}
INLINE PSMBCE_V_NET_ROOT_CONTEXT
SmbCeGetExchangeVNetRootContext(PVOID pExchange)
{
PSMB_EXCHANGE pSmbExchange = (PSMB_EXCHANGE)pExchange;
return pSmbExchange->SmbCeContext.pVNetRootContext;
}
extern ULONG SmbCeTraceExchangeReferenceCount;
// The following functions ( inline, macros and otherwise ) are defined
// to manipulate the exchanges
// The reset exchange macro provides a mechanism for forcing the exchange
// instance to a well known start state. This is used by the protocol
// selection engine to transceive different SMB's. A note of caution --
// ensure that the conditions are O.K for initialization. There is no well
// known mechanism in the exchange engine to prevent overwriting an
// exchange instance while in use.
#define SmbCeResetExchange(pExchange) \
(pExchange)->SmbCeFlags &= ~SMBCE_EXCHANGE_FINALIZED; \
(pExchange)->ReceivePendingOperations = 0; \
(pExchange)->CopyDataPendingOperations = 0; \
(pExchange)->SendCompletePendingOperations = 0; \
(pExchange)->LocalPendingOperations = 0; \
(pExchange)->Status = STATUS_SUCCESS; \
(pExchange)->SmbStatus = STATUS_SUCCESS
// The following macros provide a mechanism for referencing and dereferencing
// the exchange. The reference count provides a mechanism for detecting
// when an exchange instance can be safely discarded. The reference count
// differs from the pending operations count maintained in the exchange
// which are used to detect when a quiescent state is reached.
#define SmbCeReferenceExchange(pExchange) \
InterlockedIncrement(&(pExchange)->ReferenceCount); \
if (SmbCeTraceExchangeReferenceCount) { \
DbgPrint("Reference Exchange %lx Type(%ld) %s %ld %ld\n", \
(pExchange), \
(pExchange)->Type, \
__FILE__, \
__LINE__, \
(pExchange)->ReferenceCount); \
}
#define SmbCeDereferenceExchange(pExchange) \
InterlockedDecrement(&(pExchange)->ReferenceCount); \
if (SmbCeTraceExchangeReferenceCount) { \
DbgPrint("Dereference Exchange %lx Type(%ld) %s %ld %ld\n", \
(pExchange), \
(pExchange)->Type, \
__FILE__, \
__LINE__, \
(pExchange)->ReferenceCount); \
}
#define SmbCeDereferenceAndDiscardExchange(pExchange) \
if (InterlockedDecrement(&(pExchange)->ReferenceCount) == 0) { \
SmbCeDiscardExchange(pExchange); \
} \
if (SmbCeTraceExchangeReferenceCount) { \
DbgPrint("Dereference Exchange %lx Type(%ld) %s %ld %ld\n", \
(pExchange), \
(pExchange)->Type, \
__FILE__, \
__LINE__, \
(pExchange)->ReferenceCount); \
}
// Macros to hide the syntactic details of dereferencing and calling a
// routine in a dispatch vector. These macros are purely intended for
// use in the connection engine only and is not meant for use by
// other modules.
#define SMB_EXCHANGE_DISPATCH(pExchange,Routine,Arguments) \
(*((pExchange)->pDispatchVector->Routine))##Arguments
#define SMB_EXCHANGE_POST(pExchange,Routine) \
RxPostToWorkerThread(&(pExchange)->WorkItem.WorkQueueItem, \
(pExchange)->pDispatchVector->Routine, \
(pExchange))
// The following enum type defines the result of invoking the finalization routine
// on an exchange instance.
typedef enum _SMBCE_EXCHANGE_STATUS_ {
SmbCeExchangeAlreadyFinalized,
SmbCeExchangeFinalized,
SmbCeExchangeNotFinalized
} SMBCE_EXCHANGE_STATUS, *PSMBCE_EXCHANGE_STATUS;
// The pending operations associated with an exchange are classified into four kinds
// Receive operations, Copy Data Operations, Send Complete and Local operations.
// These need to be incremented under the protection of a spinlock. However they
// are decremented in the absence of a spinlock ( with the respective assert ).
#define SMBCE_LOCAL_OPERATION 0x1
#define SMBCE_SEND_COMPLETE_OPERATION 0x2
#define SMBCE_COPY_DATA_OPERATION 0x4
#define SMBCE_RECEIVE_OPERATION 0x8
extern NTSTATUS
SmbCeIncrementPendingOperations(
PSMB_EXCHANGE pExchange,
ULONG PendingOperationsMask,
PVOID FileName,
ULONG FileLine);
extern NTSTATUS
SmbCeDecrementPendingOperations(
PSMB_EXCHANGE pExchange,
ULONG PendingOperationsMask,
PVOID FileName,
ULONG FileLine);
extern SMBCE_EXCHANGE_STATUS
SmbCeDecrementPendingOperationsAndFinalize(
PSMB_EXCHANGE pExchange,
ULONG PendingOperationsMask,
PVOID FileName,
ULONG FileLine);
// the pending operations increment routines
#define SmbCeIncrementPendingReceiveOperations(pExchange) \
SmbCeIncrementPendingOperations(pExchange,(SMBCE_RECEIVE_OPERATION),__FILE__,__LINE__)
#define SmbCeIncrementPendingSendCompleteOperations(pExchange) \
SmbCeIncrementPendingOperations(pExchange,(SMBCE_SEND_COMPLETE_OPERATION),__FILE__,__LINE__)
#define SmbCeIncrementPendingCopyDataOperations(pExchange) \
SmbCeIncrementPendingOperations(pExchange,(SMBCE_COPY_DATA_OPERATION),__FILE__,__LINE__)
#define SmbCeIncrementPendingLocalOperations(pExchange) \
SmbCeIncrementPendingOperations(pExchange,(SMBCE_LOCAL_OPERATION),__FILE__,__LINE__)
// The pending operations decrement routines
// Note the special casing of ReceivePendingOperations since it is the only one
// that can be forced by a disconnect indication. There are two variations in
// the decrement macros. The first flavour is to be used when it can be
// guaranteed that the decrement operation will not lead to the finalization
// of the exchange and the second is to be used when we cannot ensure the criterion
// for the first. The difference between the two is that it eliminates
// acquisition/release of a spinlock.
#define SmbCeDecrementPendingReceiveOperations(pExchange) \
SmbCeDecrementPendingOperations(pExchange,(SMBCE_RECEIVE_OPERATION),__FILE__,__LINE__)
#define SmbCeDecrementPendingSendCompleteOperations(pExchange) \
SmbCeDecrementPendingOperations(pExchange,(SMBCE_SEND_COMPLETE_OPERATION),__FILE__,__LINE__)
#define SmbCeDecrementPendingCopyDataOperations(pExchange) \
SmbCeDecrementPendingOperations(pExchange,(SMBCE_COPY_DATA_OPERATION),__FILE__,__LINE__)
#define SmbCeDecrementPendingLocalOperations(pExchange) \
SmbCeDecrementPendingOperations(pExchange,(SMBCE_LOCAL_OPERATION),__FILE__,__LINE__)
// The pending operations decrement routines
#define SmbCeDecrementPendingReceiveOperationsAndFinalize(pExchange) \
SmbCeDecrementPendingOperationsAndFinalize(pExchange,(SMBCE_RECEIVE_OPERATION),__FILE__,__LINE__)
#define SmbCeDecrementPendingSendCompleteOperationsAndFinalize(pExchange) \
SmbCeDecrementPendingOperationsAndFinalize(pExchange,(SMBCE_SEND_COMPLETE_OPERATION),__FILE__,__LINE__)
#define SmbCeDecrementPendingCopyDataOperationsAndFinalize(pExchange) \
SmbCeDecrementPendingOperationsAndFinalize(pExchange,(SMBCE_COPY_DATA_OPERATION),__FILE__,__LINE__)
#define SmbCeDecrementPendingLocalOperationsAndFinalize(pExchange) \
SmbCeDecrementPendingOperationsAndFinalize(pExchange,(SMBCE_LOCAL_OPERATION),__FILE__,__LINE__)
//
// This is the pid that will be used by the rdr; rdr1 used 0xcafe.
// only this pid is ever sent except for nt<-->nt creates. in these cases,
// we have to send the full 32bit process id for RPC.
//
#define MRXSMB_PROCESS_ID (0xfeff)
INLINE VOID
SmbCeSetFullProcessIdInHeader(
PSMB_EXCHANGE pExchange,
ULONG ProcessId,
PNT_SMB_HEADER pNtSmbHeader)
{
pExchange->SmbCeFlags |= SMBCE_EXCHANGE_FULL_PROCESSID_SPECIFIED;
SmbPutUshort(&pNtSmbHeader->Pid, (USHORT)((ProcessId) & 0xFFFF));
SmbPutUshort(&pNtSmbHeader->PidHigh, (USHORT)((ProcessId) >> 16));
}
// The exchange engine API, for creation and manipulation of exchange instances
// Initialization/Creation of an exchange instance
extern NTSTATUS
SmbCepInitializeExchange(
PSMB_EXCHANGE *pExchangePointer,
PRX_CONTEXT pRxContext,
PSMBCEDB_SERVER_ENTRY pServerEntry,
PMRX_V_NET_ROOT pVNetRoot,
SMB_EXCHANGE_TYPE ExchangeType,
PSMB_EXCHANGE_DISPATCH_VECTOR pDispatchVector);
INLINE NTSTATUS
SmbCeInitializeExchange(
PSMB_EXCHANGE *pExchangePointer,
PRX_CONTEXT pRxContext,
PMRX_V_NET_ROOT pVNetRoot,
SMB_EXCHANGE_TYPE ExchangeType,
PSMB_EXCHANGE_DISPATCH_VECTOR pDispatchVector)
{
return SmbCepInitializeExchange(
pExchangePointer,
pRxContext,
NULL,
pVNetRoot,
ExchangeType,
pDispatchVector);
}
INLINE NTSTATUS
SmbCeInitializeExchange2(
PSMB_EXCHANGE *pExchangePointer,
PRX_CONTEXT pRxContext,
PSMBCEDB_SERVER_ENTRY pServerEntry,
SMB_EXCHANGE_TYPE ExchangeType,
PSMB_EXCHANGE_DISPATCH_VECTOR pDispatchVector)
{
return SmbCepInitializeExchange(
pExchangePointer,
pRxContext,
pServerEntry,
NULL,
ExchangeType,
pDispatchVector);
}
extern NTSTATUS
SmbCeInitializeAssociatedExchange(
PSMB_EXCHANGE *pAssociatedExchangePointer,
PSMB_EXCHANGE pMasterExchange,
SMB_EXCHANGE_TYPE Type,
PSMB_EXCHANGE_DISPATCH_VECTOR pDispatchVector);
// converting one type of exchange to another
extern NTSTATUS
SmbCeTransformExchange(
PSMB_EXCHANGE pExchange,
SMB_EXCHANGE_TYPE NewType,
PSMB_EXCHANGE_DISPATCH_VECTOR pDispatchVector);
// Initiating an exchange
extern NTSTATUS
SmbCeInitiateExchange(PSMB_EXCHANGE pExchange);
extern NTSTATUS
SmbCeInitiateAssociatedExchange(
PSMB_EXCHANGE pAssociatedExchange,
BOOLEAN EnableCompletionHandlerInMasterExchange);
// Resuming an exchange
extern NTSTATUS
SmbCeResumeExchange(PSMB_EXCHANGE pExchange);
// aborting an initiated exchange
extern NTSTATUS
SmbCeAbortExchange(PSMB_EXCHANGE pExchange);
// discarding an exchnge instance
extern VOID
SmbCeDiscardExchange(PVOID pExchange);
// In addition to providing a flexible mechanism for exchanging packets with
// the server the exchange engine also provides a mechanism for building and
// parsing SMB_HEADER's. This functionality is built into the connection
// engine because the meta data in the headers is used to update the connection
// engine database.
// building SMB headers
extern NTSTATUS
SmbCeBuildSmbHeader(
IN OUT PSMB_EXCHANGE pExchange,
IN OUT PVOID pBuffer,
IN ULONG BufferLength,
OUT PULONG pRemainingBuffer,
OUT PUCHAR pLastCommandInHeader,
OUT PUCHAR *pNextCommand);
// parsing SMB headers.
extern NTSTATUS
SmbCeParseSmbHeader(
PSMB_EXCHANGE pExchange,
PSMB_HEADER pSmbHeader,
PGENERIC_ANDX pCommandToProcess,
NTSTATUS *pSmbResponseStatus,
ULONG BytesAvailable,
ULONG BytesIndicated,
PULONG pBytesConsumed);
// The following routines are intended for use in the connection engine only.
extern NTSTATUS
MRxSmbInitializeSmbCe();
extern NTSTATUS
MRxSmbTearDownSmbCe();
extern NTSTATUS
SmbCePrepareExchangeForReuse(PSMB_EXCHANGE pExchange);
extern PVOID
SmbCeMapSendBufferToCompletionContext(
PSMB_EXCHANGE pExchange,
PVOID pBuffer);
extern PVOID
SmbCeMapSendCompletionContextToBuffer(
PSMB_EXCHANGE pExchange,
PVOID pContext);
extern SMBCE_EXCHANGE_STATUS
SmbCeFinalizeExchange(PSMB_EXCHANGE pExchange);
extern VOID
SmbCeFinalizeExchangeOnDisconnect(
PSMB_EXCHANGE pExchange);
extern NTSTATUS
SmbCeReferenceServer(
PSMB_EXCHANGE pExchange);
extern NTSTATUS
SmbCeIncrementActiveExchangeCount();
extern VOID
SmbCeDecrementActiveExchangeCount();
extern VOID
SmbCeSetExpiryTime(
PSMB_EXCHANGE pExchange);
extern BOOLEAN
SmbCeDetectExpiredExchanges(
PSMBCEDB_SERVER_ENTRY pServerEntry);
extern VOID
SmbCepFinalizeAssociatedExchange(
PSMB_EXCHANGE pExchange);
extern NTSTATUS
SmbCeCancelExchange(
PRX_CONTEXT pRxContext);
typedef struct _SMB_CONSTRUCT_NETROOT_EXCHANGE_ {
union {
SMB_EXCHANGE;
SMB_EXCHANGE Exchange;
};
SMB_TREE_ID TreeId;
SMB_USER_ID UserId;
BOOLEAN fUpdateDefaultSessionEntry;
BOOLEAN fInitializeNetRoot;
PMRX_NETROOT_CALLBACK NetRootCallback;
PMDL pSmbRequestMdl;
PMDL pSmbResponseMdl;
PVOID pSmbActualBuffer; // Originally allocated buffer
PVOID pSmbBuffer; // Start of header
PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext;
} SMB_CONSTRUCT_NETROOT_EXCHANGE, *PSMB_CONSTRUCT_NETROOT_EXCHANGE;
extern
NTSTATUS
GetSmbResponseNtStatus(
IN PSMB_HEADER pSmbHeader,
IN PSMB_EXCHANGE pExchange
);
#endif // _SMBXCHNG_H_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -