📄 transact.c
字号:
/*++
Copyright (c) 1987 - 1999 Microsoft Corporation
Module Name:
transact.c
Abstract:
This file conatins the implementation of the transact exchange.
--*/
#include "precomp.h"
#pragma hdrstop
#pragma warning(error:4100) // Unreferenced formal parameter
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SmbCeInitializeTransactionParameters)
#pragma alloc_text(PAGE, SmbCeUninitializeTransactionParameters)
#pragma alloc_text(PAGE, SmbCeDiscardTransactExchange)
#pragma alloc_text(PAGE, SmbCeSubmitTransactionRequest)
#pragma alloc_text(PAGE, _SmbCeTransact)
#pragma alloc_text(PAGE, SmbTransactBuildHeader)
#pragma alloc_text(PAGE, SmbTransactExchangeStart)
#pragma alloc_text(PAGE, SmbTransactExchangeAbort)
#pragma alloc_text(PAGE, SmbTransactExchangeErrorHandler)
#pragma alloc_text(PAGE, SmbTransactExchangeSendCallbackHandler)
#pragma alloc_text(PAGE, SmbCeInitializeTransactExchange)
#pragma alloc_text(PAGE, SendSecondaryRequests)
#endif
//#define SET_DONTSUBSUME_PARAMS
#ifdef SET_DONTSUBSUME_PARAMS
ULONG MRxSmbDontSubsumeParams = 1;
#else
ULONG MRxSmbDontSubsumeParams = 0;
#endif
#if DBG
#define DONTSUBSUME_PARAMS MRxSmbDontSubsumeParams
#else
#define DONTSUBSUME_PARAMS FALSE
#endif
SMB_TRANSACTION_OPTIONS RxDefaultTransactionOptions = DEFAULT_TRANSACTION_OPTIONS;
RXDT_DefineCategory(TRANSACT);
#define Dbg (DEBUG_TRACE_TRANSACT)
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define SMB_TRANSACT_MAXIMUM_PARAMETER_SIZE (0xffff)
#define SMB_TRANSACT_MAXIMUM_DATA_SIZE (0xffff)
typedef struct _SMB_TRANSACT_RESP_FORMAT_DESCRIPTION {
ULONG WordCount;
ULONG TotalParameterCount;
ULONG TotalDataCount;
ULONG ParameterCount;
ULONG ParameterOffset;
ULONG ParameterDisplacement;
ULONG DataCount;
ULONG DataOffset;
ULONG DataDisplacement;
ULONG ByteCount;
ULONG ApparentMsgLength;
} SMB_TRANSACT_RESP_FORMAT_DESCRIPTION, *PSMB_TRANSACT_RESP_FORMAT_DESCRIPTION;
NTSTATUS
SmbTransactAccrueAndValidateFormatData(
IN struct _SMB_TRANSACT_EXCHANGE *pTransactExchange, // The exchange instance
IN PSMB_HEADER pSmbHeader,
IN ULONG BytesIndicated,
OUT PSMB_TRANSACT_RESP_FORMAT_DESCRIPTION Format
);
extern NTSTATUS
SmbTransactExchangeFinalize(
PSMB_EXCHANGE pExchange,
BOOLEAN *pPostFinalize);
extern NTSTATUS
ParseTransactResponse(
IN struct _SMB_TRANSACT_EXCHANGE *pTransactExchange, // The exchange instance
IN PSMB_TRANSACT_RESP_FORMAT_DESCRIPTION Format,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *pBytesTaken,
IN PSMB_HEADER pSmbHeader,
OUT PMDL *pCopyRequestMdlPointer,
OUT PULONG pCopyRequestSize);
extern NTSTATUS
SendSecondaryRequests(PVOID pContext);
extern NTSTATUS
SmbCeInitializeTransactExchange(
PSMB_TRANSACT_EXCHANGE pTransactExchange,
PRX_CONTEXT RxContext,
PSMB_TRANSACTION_OPTIONS pOptions,
PSMB_TRANSACTION_SEND_PARAMETERS pSendParameters,
PSMB_TRANSACTION_RECEIVE_PARAMETERS pReceiveParameters,
PSMB_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext);
NTSTATUS
SmbCeInitializeTransactionParameters(
PVOID pSetup,
USHORT SetupLength,
PVOID pParam,
ULONG ParamLength,
PVOID pData,
ULONG DataLength,
PSMB_TRANSACTION_PARAMETERS pTransactionParameters
)
/*++
Routine Description:
This routine initializes the transaction parameters
Arguments:
pSetup - the setup buffer
SetupLength - the setup buffer length
pParam - the param buffer
ParamLength - the param buffer length
pData - the data buffer
DataLength - the data buffer length
pTransactionParameters - the transaction parameters instance
Return Value:
RXSTATUS - The return status for the operation
Notes:
The TRANSACTION parameters come in two flavours -- the send parameters for the data
that is to be sent to the server and the receive parameters for receiving the data
from the server. There is one subtle difference in the way in which the parameters are
stored and referenced in these two cases. In the send case the Setup buffer is stored
as a pointer itself while in the receive case it is stored in the form of a MDL.
This is because the SMB protocol requires that the Header + setup information for a
transaction request cannot be greated then the maximum SMB buffer size, i.e., setup
information cannot spill to a secondary request. The buffer that is allocated for the
header is made sufficiently large enough to hold the setup data as well. On the other
hand the receives are handled in a two phase manner, -- the indication at the DPC
level followed by a copy data request if required. In order to avoid having to transition
between DPC level and a worker thread the MDL's for the buffers are eagerly evaluated.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PMDL pSetupMdl = NULL;
PMDL pParamMdl = NULL;
PMDL pDataMdl = NULL;
PAGED_CODE();
if (pTransactionParameters->Flags & TRANSACTION_RECEIVE_PARAMETERS_FLAG) {
if (pSetup != NULL) {
pSetupMdl = RxAllocateMdl(pSetup,SetupLength);
if (pSetupMdl == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
RxProbeAndLockPages(pSetupMdl,KernelMode,IoModifyAccess,Status);
if (Status != STATUS_SUCCESS) {
IoFreeMdl(pSetupMdl);
pSetupMdl = NULL;
} else {
if (MmGetSystemAddressForMdlSafe(pSetupMdl,LowPagePriority) == NULL) { //this maps the Mdl
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
}
if ((Status == STATUS_SUCCESS) && (pParam != NULL)) {
pParamMdl = RxAllocateMdl(pParam,ParamLength);
if (pParamMdl == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
RxProbeAndLockPages(pParamMdl,KernelMode,IoModifyAccess,Status);
if ((Status != STATUS_SUCCESS)) {
IoFreeMdl(pParamMdl);
pParamMdl = NULL;
} else {
if (MmGetSystemAddressForMdlSafe(pParamMdl,LowPagePriority) == NULL) { //this maps the Mdl
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
}
pTransactionParameters->SetupLength = SetupLength;
pTransactionParameters->ParamLength = ParamLength;
pTransactionParameters->pParamMdl = pParamMdl;
pTransactionParameters->pSetupMdl = pSetupMdl;
} else {
pTransactionParameters->SetupLength = SetupLength;
pTransactionParameters->pSetup = pSetup;
pTransactionParameters->ParamLength = ParamLength;
pTransactionParameters->pParam = pParam;
pTransactionParameters->pParamMdl = NULL;
}
ASSERT( !((pData == NULL)&&(DataLength!=0)) );
if ((Status == STATUS_SUCCESS) && (pData != NULL) && (DataLength > 0)) {
pDataMdl = RxAllocateMdl(pData,DataLength);
if (pDataMdl == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
RxProbeAndLockPages(pDataMdl,KernelMode,IoModifyAccess,Status);
if ((Status != STATUS_SUCCESS)) {
IoFreeMdl(pDataMdl);
pDataMdl = NULL;
} else {
if (MmGetSystemAddressForMdlSafe(pDataMdl,LowPagePriority) == NULL) { //this maps the Mdl
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
}
pTransactionParameters->pDataMdl = pDataMdl;
pTransactionParameters->DataLength = DataLength;
ASSERT((Status != STATUS_SUCCESS) || (DataLength == 0) || (pDataMdl != NULL));
if ((Status != STATUS_SUCCESS)) {
if (pTransactionParameters->Flags & TRANSACTION_RECEIVE_PARAMETERS_FLAG) {
if (pSetupMdl != NULL) {
MmUnlockPages(pSetupMdl); //this unmaps as well
IoFreeMdl(pSetupMdl);
}
if (pParamMdl != NULL) {
MmUnlockPages(pParamMdl);
IoFreeMdl(pParamMdl);
}
}
if (pDataMdl != NULL) {
MmUnlockPages(pDataMdl);
IoFreeMdl(pDataMdl);
}
}
return Status;
}
VOID
SmbCeUninitializeTransactionParameters(
PSMB_TRANSACTION_PARAMETERS pTransactionParameters
)
/*++
Routine Description:
This routine uninitializes the transaction parameters, i.e., free the associated MDL's
Arguments:
pTransactionParameters - the parameter instance for uninitialization
--*/
{
PAGED_CODE();
if (pTransactionParameters->Flags & TRANSACTION_RECEIVE_PARAMETERS_FLAG) {
if (pTransactionParameters->pSetupMdl != NULL) {
MmUnlockPages(pTransactionParameters->pSetupMdl);
IoFreeMdl(pTransactionParameters->pSetupMdl);
}
}
if (pTransactionParameters->pParamMdl != NULL) {
MmUnlockPages(pTransactionParameters->pParamMdl);
IoFreeMdl(pTransactionParameters->pParamMdl);
}
if (pTransactionParameters->pDataMdl != NULL
&& !BooleanFlagOn(pTransactionParameters->Flags,SMB_XACT_FLAGS_CALLERS_SENDDATAMDL)) {
MmUnlockPages(pTransactionParameters->pDataMdl);
IoFreeMdl(pTransactionParameters->pDataMdl);
}
}
VOID
SmbCeDiscardTransactExchange(PSMB_TRANSACT_EXCHANGE pTransactExchange)
/*++
Routine Description:
This routine discards a transact exchange
Arguments:
pExchange - the exchange instance
--*/
{
PSMB_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext;
PAGED_CODE();
// Deallocate any transact exchange specfic allocations ...
if (pTransactExchange->pActualPrimaryRequestSmbHeader != NULL) {
RxFreePool(pTransactExchange->pActualPrimaryRequestSmbHeader);
}
if (pTransactExchange->pReceiveSetupMdl != NULL) {
MmUnlockPages(pTransactExchange->pReceiveSetupMdl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -