📄 transact.c
字号:
IoFreeMdl(pTransactExchange->pReceiveSetupMdl);
}
if (pTransactExchange->pReceiveParamMdl != NULL) {
MmUnlockPages(pTransactExchange->pReceiveParamMdl);
IoFreeMdl(pTransactExchange->pReceiveParamMdl);
}
if (pTransactExchange->pReceiveDataMdl != NULL) {
MmUnlockPages(pTransactExchange->pReceiveDataMdl);
IoFreeMdl(pTransactExchange->pReceiveDataMdl);
}
if (pTransactExchange->pSendSetupMdl != NULL) {
MmUnlockPages(pTransactExchange->pSendSetupMdl);
IoFreeMdl(pTransactExchange->pSendSetupMdl);
}
if ((pTransactExchange->pSendDataMdl != NULL) &&
!BooleanFlagOn(pTransactExchange->Flags,SMB_XACT_FLAGS_CALLERS_SENDDATAMDL)) {
MmUnlockPages(pTransactExchange->pSendDataMdl);
IoFreeMdl(pTransactExchange->pSendDataMdl);
}
if (pTransactExchange->pSendParamMdl != NULL) {
MmUnlockPages(pTransactExchange->pSendParamMdl);
IoFreeMdl(pTransactExchange->pSendParamMdl);
}
if ((pResumptionContext = pTransactExchange->pResumptionContext) != NULL) {
NTSTATUS FinalStatus;
PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry((PSMB_EXCHANGE)pTransactExchange);
RxDbgTrace(0, Dbg,
("SmbCeTransactExchangeFinalize: everythings is good! parambytes (%ld) databytes (%ld)\n",
pTransactExchange->ParamBytesReceived, pTransactExchange->DataBytesReceived
));
FinalStatus = pTransactExchange->Status;
if (pServerEntry->ServerStatus != STATUS_SUCCESS) {
// If the server entry is in error state, the transact cannot receive a response from server.
// In this case, we return the server status.
pResumptionContext->FinalStatusFromServer = pServerEntry->ServerStatus;
} else {
// If the server entry is in good or disconnected state, we return the smb status.
pResumptionContext->FinalStatusFromServer = pTransactExchange->SmbStatus;
}
if ((FinalStatus == STATUS_SUCCESS)||
(FinalStatus == STATUS_MORE_PROCESSING_REQUIRED)) {
FinalStatus = pResumptionContext->FinalStatusFromServer;
}
pResumptionContext->SmbCeResumptionContext.Status = FinalStatus;
pResumptionContext->SetupBytesReceived = pTransactExchange->SetupBytesReceived;
pResumptionContext->DataBytesReceived = pTransactExchange->DataBytesReceived;
pResumptionContext->ParameterBytesReceived = pTransactExchange->ParamBytesReceived;
pResumptionContext->ServerVersion = pTransactExchange->ServerVersion;
SmbCeResume(&pResumptionContext->SmbCeResumptionContext);
}
SmbCeDereferenceAndDiscardExchange((PSMB_EXCHANGE)pTransactExchange);
}
NTSTATUS
SmbCeSubmitTransactionRequest(
PRX_CONTEXT RxContext,
PSMB_TRANSACTION_OPTIONS pOptions,
PSMB_TRANSACTION_PARAMETERS pSendParameters,
PSMB_TRANSACTION_PARAMETERS pReceiveParameters,
PSMB_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext )
/*++
Routine Description:
This routine submits a transaction request, i.e., allocates/initializes a transaction
exchange, sets up the completion information and initiates it
Arguments:
pNetRoot - the netroot for which the transaction request is intended
pOptions - the transaction options
pSendParameters - the transaction parameters to be sent to the server
pReceiveParameters - the transaction results from the server
pResumptionContext - the context for resuming the local activity on completion of the
transaction
Return Value:
RXSTATUS - The return status for the operation
STATUS_PENDING -- if the transcation was initiated successfully
Other error codes if the request could not be submitted successfully
Notes:
Whenever a status of STATUS_PENDING is returned it implies that the transact
exchange has assumed ownership of the MDLs passed in as receive and send
parameters. They will be released on completion of the exchange.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RxCaptureFcb;
RxCaptureFobx;
PMRX_V_NET_ROOT pVNetRoot = NULL;
PSMB_TRANSACT_EXCHANGE pTransactExchange;
PSMB_EXCHANGE pExchange = NULL;
PAGED_CODE();
if (capFobx == NULL) {
if (RxContext->MajorFunction == IRP_MJ_CREATE) {
pVNetRoot = RxContext->Create.pVNetRoot;
}
} else {
// These are the root objects which are associated with the device FCB. In
// such cases
pVNetRoot = (PMRX_V_NET_ROOT)capFobx;
if (NodeType(pVNetRoot) != RDBSS_NTC_V_NETROOT) {
pVNetRoot = capFobx->pSrvOpen->pVNetRoot;
}
}
if (pVNetRoot == NULL) {
PSMBCEDB_SERVER_ENTRY pServerEntry;
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
// Allocate and initialize an exchange for the given net root.
Status = SmbCeInitializeExchange2(
&pExchange,
RxContext,
pServerEntry,
TRANSACT_EXCHANGE,
&TransactExchangeDispatch);
} else {
// Allocate and initialize an exchange for the given net root.
Status = SmbCeInitializeExchange(
&pExchange,
RxContext,
pVNetRoot,
TRANSACT_EXCHANGE,
&TransactExchangeDispatch);
}
if (Status == STATUS_SUCCESS) {
// Initialize the transact exchange
pTransactExchange = (PSMB_TRANSACT_EXCHANGE)pExchange;
Status = SmbCeInitializeTransactExchange(
pTransactExchange,
RxContext,
pOptions,
pSendParameters,
pReceiveParameters,
pResumptionContext);
if (Status == STATUS_SUCCESS) {
// The transact exchange can be either asynchronous or synchronous. In
// the asynchronous case an additional reference is taken which is
// passed onto the caller alongwith the exchange squirelled away in the
// RX_CONTEXT if STATUS_PENDING is being returned. This enables the
// caller to control when the exchange is discarded. This works
// especially well in dealing with cancellation of asynchronous
// exchanges.
// This reference will be accounted for by the finalization routine
// of the transact exchange.
SmbCeReferenceExchange((PSMB_EXCHANGE)pTransactExchange);
if (BooleanFlagOn(pOptions->Flags,SMB_XACT_FLAGS_ASYNCHRONOUS)) {
// The corresponding dereference is the callers responsibility
SmbCeReferenceExchange((PSMB_EXCHANGE)pTransactExchange);
}
pResumptionContext->pTransactExchange = pTransactExchange;
pResumptionContext->SmbCeResumptionContext.Status = STATUS_SUCCESS;
SmbCeIncrementPendingLocalOperations(pExchange);
// Initiate the exchange
Status = SmbCeInitiateExchange(pExchange);
if (Status != STATUS_PENDING) {
pExchange->Status = Status;
if (pExchange->SmbStatus == STATUS_SUCCESS) {
pExchange->SmbStatus = Status;
}
if (BooleanFlagOn(pOptions->Flags,SMB_XACT_FLAGS_ASYNCHRONOUS)) {
PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
pMRxSmbContext->pExchange = NULL;
// Since the exchange has already been completed there is no
// point in returning the additional reference to the caller
SmbCeDereferenceExchange((PSMB_EXCHANGE)pTransactExchange);
}
}
SmbCeDecrementPendingLocalOperationsAndFinalize(pExchange);
// Map the status to STATUS_PENDING so that continuation routines
// do not attempt to finalize.
Status = STATUS_PENDING;
} else {
PMRXSMB_RX_CONTEXT MRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
ASSERT(MRxSmbContext->pExchange == pExchange);
MRxSmbContext->pExchange = NULL;
SmbCeDiscardExchange(pExchange);
}
}
return Status;
}
NTSTATUS
_SmbCeTransact(
PRX_CONTEXT RxContext,
PSMB_TRANSACTION_OPTIONS pOptions,
PVOID pInputSetupBuffer,
ULONG InputSetupBufferLength,
PVOID pOutputSetupBuffer,
ULONG OutputSetupBufferLength,
PVOID pInputParamBuffer,
ULONG InputParamBufferLength,
PVOID pOutputParamBuffer,
ULONG OutputParamBufferLength,
PVOID pInputDataBuffer,
ULONG InputDataBufferLength,
PVOID pOutputDataBuffer,
ULONG OutputDataBufferLength,
PSMB_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext)
/*++
Routine Description:
This routine implements a standardized mechanism of submitting transaction requests,
and synchronizing with their completion. This does not provide the smae amount of control
that SmbCeSubmitTransactRequest provides. Nevertheless, this implements a common mechanism
that should satisfy most needs
Arguments:
RxContext - the context for the transaction
pOptions - the transaction options
pSetupBuffer - the transaction setup buffer
SetupBufferlength - the setup buffer length
pInputParamBuffer - the Input param buffer
InputParamBufferLength - the input param buffer length
pOutputParamBuffer - the output param buffer
OutputParamBufferlength - the output param buffer length
pInputDataBuffer - the Input data buffer
InputDataBufferLength - the input data buffer length
pOutputDataBuffer - the output data buffer
OutputDataBufferlength - the output data buffer length
pResumptionContext - the transaction resumption context
Return Value:
RXSTATUS - The return status for the operation
STATUS_SUCCESS if successfull.
Other error codes if the request could not be submitted successfully
Notes:
In the case of asynchronous exchanges if STATUS_PENDING is returned the
Exchange instance is squirelled away in the minirdr context associated with
the given RX_CONTEXT instance. This exchange will not be discarded without
the callers intervention. It is the callers responsibility to invoke
SmbCeDereferenceAndDiscardExchange to discard the exchange
--*/
{
NTSTATUS Status;
SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
BOOLEAN fAsynchronous;
PAGED_CODE();
fAsynchronous = BooleanFlagOn(pOptions->Flags,SMB_XACT_FLAGS_ASYNCHRONOUS);
Status = SmbCeInitializeTransactionSendParameters(
pInputSetupBuffer,
(USHORT)InputSetupBufferLength,
pInputParamBuffer,
InputParamBufferLength,
pInputDataBuffer,
InputDataBufferLength,
&SendParameters);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -