⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transact.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
            SmbPutUlong( &pNtTransactRequest->ParameterOffset, ParamOffset);
            SmbPutUlong( &pNtTransactRequest->DataCount, DataBytesToBeSent);
            SmbPutUlong( &pNtTransactRequest->DataOffset, DataOffset);
        }
        break;

    default:
        ASSERT(!"Valid Smb Command for initiating Transaction");
        return STATUS_INVALID_PARAMETER;
    }

    // Update the Bcc field in the SMB and compute the SMB length
    SmbPutUshort(
        pBcc,
        (USHORT)((ParamOffset - BccOffset - sizeof(USHORT)) +
                 ParamBytesToBeSent +
                 PaddingLength +
                 DataBytesToBeSent)
        );

    SmbLength = ParamOffset +
                ParamBytesToBeSent +
                PaddingLength +
                DataBytesToBeSent;

    // The primary request buffer should be locked down for transmission. In order to
    // preclude race conditions while freeing this routine assumes ownership of the buffer.
    // There are two reasons why this model has to be adopted ...
    // 1) Inititaiting a transaction request can possibly involve a reconnection attempt
    // which will involve network traffic. Consequently the transmission of the primary
    // request can potentially occur in a worker thread which is different from the one
    // initializing the exchange. This problem can be worked around by carrying all the
    // possible context around and actually constructing the header as part of this routine.
    // But this would imply that those requests which could have been filtered out easily
    // because of error conditions etc. will be handled very late.

    pTransactExchange->pActualPrimaryRequestSmbHeader = NULL;
    pTransactExchange->pPrimaryRequestSmbHeader = NULL;

    // Ensure that the MDL's have been probed & locked. The new MDL's have been allocated.
    // The partial MDL's are allocated to be large enough to span the maximum buffer
    // length possible.

    MdlLength = ParamOffset;
    if (pTransactExchange->fParamsSubsumedInPrimaryRequest) {
        MdlLength += ParamBytesToBeSent + PaddingLength;
    }

    RxAllocateHeaderMdl(
        pPrimaryRequestSmbHeader,
        MdlLength,
        pPrimaryRequestSmbMdl
        );

    if (pPrimaryRequestSmbMdl != NULL) {
        Status = STATUS_SUCCESS;
    } else {
        RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: Insuffcient resources for MDL's\n"));
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    if ((DataBytesToBeSent > 0) &&
       (Status == STATUS_SUCCESS)) {
        pPartialDataMdl = RxAllocateMdl(
                              0,
                              (MIN(pTransactExchange->SendDataBufferSize,MaximumSmbBufferSize) +
                               PAGE_SIZE - 1)
                              );

        if (pPartialDataMdl != NULL) {
            Status = STATUS_SUCCESS;
        } else {
            RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: Insuffcient resources for MDL's\n"));
            Status = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    if ((ParamBytesToBeSent > 0) &&
        !pTransactExchange->fParamsSubsumedInPrimaryRequest &&
        (Status == STATUS_SUCCESS)) {

        pPartialParamMdl = RxAllocateMdl(
                               pTransactExchange->pSendParamBuffer,
                               ParamBytesToBeSent);

        if (PaddingLength!= 0) {
            pPaddingMdl = RxAllocateMdl(0,(sizeof(DWORD) + PAGE_SIZE - 1));
        } else {
            pPaddingMdl = NULL;
        }

        if ((pPartialParamMdl != NULL) &&
            ((pPaddingMdl != NULL)||(PaddingLength==0))) {
            Status = STATUS_SUCCESS;
        } else {
            RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: no param/pad MDLs %08lx %08lx\n",
               pPartialParamMdl,pPaddingMdl));
            Status = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    // At this point the validity of all the parameters will have been ascertained. The trivial
    // cases have been filtered out. Start the transact exchange.

    // Implementation Note: The Transact exchange implementation relies upon chaining the
    // MDL's together to build the relevant request buffers that need be sent. This ensures
    // that redundant copying of data is avoided altogether. Depending upon the parameters
    // specified the composite MDL that is sent is composed of the following MDL's.
    // TRANSACT2 and NT TRANSACT exchanges ...
    //          The composite buffer is made up off atmost four MDL's that are chained together. These
    //           are the header buffer, the setup buffer, parameter buffer and the data buffer.
    //          All the secondary requests are made up off atmost three MDL's that are chained together.
    //          These are the header buffer, the parameter buffer and the data buffer.
    // TRANSACT exchanges ....
    //          The composite buffer is made up off atmost three MDL's that are chained together. These are
    //          the header buffer ( includes the name and the setup information) , the parameter buffer
    //          and the data buffer.
    // All the secondary requests are made up off atmost three MDL's that are chained together.
    // These are the header buffer, the parameter buffer and the data buffer.
    // In all of these cases the number of MDL's can go up by 1 if a padding MDL is required
    // between the parameter buffer and the data buffer to ensure that all alignment requirements
    // are satisfied.

    if ((Status == STATUS_SUCCESS)) {

        RxProbeAndLockHeaderPages(pPrimaryRequestSmbMdl,KernelMode,IoModifyAccess,Status);
        if (Status != STATUS_SUCCESS) {  //do this now. the code below will try to unlock
            IoFreeMdl(pPrimaryRequestSmbMdl);
            pPrimaryRequestSmbMdl = NULL;
        } else {
            if (MmGetSystemAddressForMdlSafe(pPrimaryRequestSmbMdl,LowPagePriority) == NULL) { //map it
                Status = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
    }

    if ((Status == STATUS_SUCCESS)) {
        pLastMdlInChain = pPrimaryRequestSmbMdl;

        if (ParamBytesToBeSent > 0) {
            RxDbgTrace(
                0,
                Dbg,
                ("SmbCeTransactExchangeStart: Sending Param bytes %ld at offset %ld\n",
                 ParamBytesToBeSent,
                 ParamOffset)
                );
            pTransactExchange->ParamBytesSent = ParamBytesToBeSent;

            if (!pTransactExchange->fParamsSubsumedInPrimaryRequest) {
                IoBuildPartialMdl(
                    pTransactExchange->pSendParamMdl,
                    pPartialParamMdl,
                    (PBYTE)MmGetMdlVirtualAddress(pTransactExchange->pSendParamMdl),
                    ParamBytesToBeSent);

                // Chain the MDL's together
                pLastMdlInChain->Next = pPartialParamMdl;
                pLastMdlInChain       = pPartialParamMdl;
            }
        }

        // Link the data buffer or portions of it if the size constraints are satisfied
        // If padding is required between the parameter and data portions in the
        // primary request include the padding MDL, otherwise chain the data MDL
        // directly.
        if (DataBytesToBeSent > 0) {
            if (!pTransactExchange->fParamsSubsumedInPrimaryRequest &&
                (PaddingLength > 0)) {
                RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: Padding Length %ld\n",PaddingLength));

                RxBuildPaddingPartialMdl(pPaddingMdl,PaddingLength);
                pLastMdlInChain->Next = pPaddingMdl;
                pLastMdlInChain = pPaddingMdl;
            }

            RxDbgTrace( 0, Dbg,("SmbCeTransactExchangeStart: Sending Data bytes %ld at offset %ld\n",
                 DataBytesToBeSent, DataOffset) );

            pTransactExchange->DataBytesSent = DataBytesToBeSent;

            IoBuildPartialMdl(
                pTransactExchange->pSendDataMdl,
                pPartialDataMdl,
                (PBYTE)MmGetMdlVirtualAddress(pTransactExchange->pSendDataMdl),
                DataBytesToBeSent);

            pLastMdlInChain->Next = pPartialDataMdl;
            pLastMdlInChain       = pPartialDataMdl;
        }

        if ((Status == STATUS_SUCCESS)) {
            // There are cases in which the transaction exchange can be completed by merely sending
            // the primary request SMB. This should be distinguished from those cases in which either
            // a response is expected or a number of secondary requests need to be issued based upon
            // the parameter buffer length, data buffer length and the flags specified.
            if ((pTransactExchange->Flags & SMB_TRANSACTION_NO_RESPONSE ) &&
                (pTransactExchange->SendDataBufferSize == DataBytesToBeSent) &&
                (pTransactExchange->SendParamBufferSize == ParamBytesToBeSent)) {
                // No response is expected in this case. Therefore Send should suffice instead of
                // Tranceive

                // since we don't expect to do any more here, set the exchange status to success
                pExchange->Status = STATUS_SUCCESS;
                pTransactExchange->pResumptionContext->FinalStatusFromServer = STATUS_SUCCESS;

                RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: SmbCeSend(No Response expected)\n"));
                Status = SmbCeSend(
                             pExchange,
                             RXCE_SEND_SYNCHRONOUS,
                             pPrimaryRequestSmbMdl,
                             SmbLength);

                if ((Status != STATUS_SUCCESS)) {
                    RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: SmbCeSend returned %lx\n",Status));
                }
            } else {
                // This transaction involves ttansmit/receive of multiple SMB's. A tranceive is in
                // order.

                if ((pTransactExchange->SendDataBufferSize == DataBytesToBeSent) &&
                    (pTransactExchange->SendParamBufferSize == ParamBytesToBeSent)) {
                    RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: No Secondary Requests\n"));
                    pTransactExchange->State = TRANSACT_EXCHANGE_TRANSMITTED_SECONDARY_REQUESTS;
                } else {
                    pTransactExchange->State = TRANSACT_EXCHANGE_TRANSMITTED_PRIMARY_REQUEST;
                }

                RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: SmbCeTranceive(Response expected)\n"));
                Status = SmbCeTranceive(
                             pExchange,
                             RXCE_SEND_SYNCHRONOUS,
                             pPrimaryRequestSmbMdl,
                             SmbLength);

                if ((Status != STATUS_SUCCESS)) {
                    RxDbgTrace( 0, Dbg, ("SmbCeTransactExchangeStart: SmbCeTranceive returned %lx\n",Status));
                }
            }
        }
    }

    if (pPartialParamMdl != NULL) {
        IoFreeMdl(pPartialParamMdl);
    }

    if (pPartialDataMdl != NULL) {
        IoFreeMdl(pPartialDataMdl);
    }

    if (pPaddingMdl != NULL) {
        IoFreeMdl(pPaddingMdl);
    }

    if (pPrimaryRequestSmbMdl != NULL) {
        RxUnlockHeaderPages(pPrimaryRequestSmbMdl);
        IoFreeMdl(pPrimaryRequestSmbMdl);
    }

    RxFreePool(pActualPrimaryRequestSmbHeader);

    if (Status != STATUS_PENDING) {
        pExchange->Status = Status;
    }

    return Status;
}

NTSTATUS
SmbTransactExchangeReceive(
    IN struct _SMB_EXCHANGE *pExchange,    // The exchange instance
    IN ULONG          BytesIndicated,
    IN ULONG          BytesAvailable,
    OUT ULONG        *pBytesTaken,
    IN  PSMB_HEADER   pSmbHeader,
    OUT PMDL *pDataBufferPointer,
    OUT PULONG        pDataSize,
    IN ULONG          ReceiveFlags)
/*++

Routine Description:

    This is the recieve indication handling routine for transact exchanges

Arguments:

    pExchange - the exchange instance

    BytesIndicated - the number of bytes indicated

    Bytes Available - the number of bytes available

    pBytesTaken     - the number of bytes consumed

    pSmbHeader      - the byte buffer

    pDataBufferPointer - the buffer into which the remaining data is to be copied.

    pDataSize       - the buffer size.

Return Value:

    RXSTATUS - The return status for the operation

Notes:

    This routine is called at DPC level.

--*/
{
    NTSTATUS Status;
    PNTSTATUS pFinalSmbStatus;

    BOOLEAN fError = FALSE;
    BOOLEAN fIndicationNotSufficient = FALSE;
    BOOLEAN fMoreParsingRequired     = FALSE;
    BOOLEAN fDoErrorProcessing       = FALSE;

    SMB_TRANSACT_RESP_FORMAT_DESCRIPTION Format;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -