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

📄 transact.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
    GENERIC_ANDX  CommandToProcess;

    ULONG TransactResponseSize       = 0;
    ULONG SetupBytesOffsetInResponse = 0;
    ULONG SetupBytesInResponse       = 0;
    ULONG CopyDataSize               = 0;

    PMDL  pSetupMdl       = NULL;
    PMDL  pCopyRequestMdl = NULL;

    PSMB_TRANSACT_EXCHANGE pTransactExchange = (PSMB_TRANSACT_EXCHANGE)pExchange;

    RxDbgTrace( 0, Dbg,
               ("SmbTransactExchangeReceive: Entering w/ Bytes Available (%ld) Bytes Indicated (%ld) State (%ld)\n",
                BytesAvailable,
                BytesIndicated,
                pTransactExchange->State
               ));
    RxDbgTrace( 0, Dbg,
               ("SmbTransactExchangeReceive: Buffer %08lx Consumed (%ld) MDL (%08lx)\n",
                pSmbHeader,
                *pBytesTaken,
                *pDataBufferPointer
               ));

    pFinalSmbStatus = &pTransactExchange->SmbStatus;
    Status = SmbCeParseSmbHeader(
                 pExchange,
                 pSmbHeader,
                 &CommandToProcess,
                 pFinalSmbStatus,
                 BytesAvailable,
                 BytesIndicated,
                 pBytesTaken);

    if (Status != STATUS_SUCCESS) {
        Status = STATUS_INVALID_NETWORK_RESPONSE;
        goto FINALLY;
    }

    //this need some explanation. parseheader is written so as to take some extra smbs off the from
    //of the packet...specifically, stuff like sessionsetup&X and TC&X. since no transact is a valid followon
    //it would not make since if (a) not enough were indicated or (b) an early command had an error. so
    //we must have success.

    if (*((PBYTE)(pSmbHeader+1)) == 0 && (pTransactExchange->State!=TRANSACT_EXCHANGE_TRANSMITTED_PRIMARY_REQUEST)) {
        RxDbgTrace(0,Dbg,("SmbTransactExchangeReceive: FinalSmbStatus = %lx\n", *pFinalSmbStatus));

        if (NT_SUCCESS(*pFinalSmbStatus)) {
            Status = STATUS_INVALID_NETWORK_RESPONSE;
            goto FINALLY;
        }
    }

    //we know that status is SUCCESS from the assert above. but we will still continue to check so as
    //to be more resilient when we don't have msg boundaries. we have the following cases depending on the
    //characteristics of the smbresponse
    //
    //   non-error:   get the data and then return the stored responsestatus. the process of getting the data
    //                causes us to update the param and data counts so that we know when we have reached the
    //                end of the data. the parse routine re-ups the receive if needed.
    //   error:       there are main cases:
    //                    a) the server has sent no data. here we discard the packet and we can just get out. the
    //                       finalize routine will pickup the status correctly.
    //                    b) here, we have to discard the packet AND update the byte counts AND re-up the receive
    //                       if necessary. to discard the packet, we must either compute the apparent msg length from
    //                       the WC and BC parameters (best) OR use our maximum buffer size

    fMoreParsingRequired = FALSE;

    if (Status == STATUS_SUCCESS) {
        if (TRUE) { //maybe sometimes we wont copy!
            if (CommandToProcess.WordCount > 0) {
                
                TransactResponseSize = 0;

                // Ensure that at the very least enough bytes have been indicated to determine
                // the length of the setup, parameters and data for the transaction.

                switch (CommandToProcess.AndXCommand) {
                case SMB_COM_NT_TRANSACT:
                case SMB_COM_NT_TRANSACT_SECONDARY:
                    TransactResponseSize = FIELD_OFFSET(RESP_NT_TRANSACTION,Buffer);
                    break;

                case SMB_COM_TRANSACTION:
                case SMB_COM_TRANSACTION2:
                case SMB_COM_TRANSACTION_SECONDARY:
                case SMB_COM_TRANSACTION2_SECONDARY:
                    TransactResponseSize = FIELD_OFFSET(RESP_TRANSACTION,Buffer);
                    break;

                default:
                    TransactResponseSize = 0xffffffff;
                    Status = STATUS_INVALID_NETWORK_RESPONSE;
                    break;
                }

                if (BytesIndicated >= (sizeof(SMB_HEADER) + TransactResponseSize)) {
                    fMoreParsingRequired = TRUE;
                } else {
                    fIndicationNotSufficient = TRUE;
                    *pFinalSmbStatus = STATUS_INVALID_NETWORK_RESPONSE;
                }
            } else {
                // allow a response with wordcount==0 to go thru if we're the right state
                fMoreParsingRequired = (pTransactExchange->State==TRANSACT_EXCHANGE_TRANSMITTED_PRIMARY_REQUEST);
            }
        }
    }

    if (fMoreParsingRequired) {
        // The header was successfully parsed and the SMB response did not contain any errors
        // The stage is set for processing the transaction response.

        switch (pTransactExchange->State) {
        case TRANSACT_EXCHANGE_TRANSMITTED_PRIMARY_REQUEST:
            {
                // The primary request for the transaction has been sent and there are
                // secondary requests to be sent.
                // The only response expected at this time is an interim response. Any
                // other response will be treated as an error.
                PRESP_TRANSACTION_INTERIM pInterimResponse;

                RxDbgTrace(0,Dbg,("SmbCeTransactExchangeReceive: Processing interim response\n"));

                if ((*pBytesTaken + FIELD_OFFSET(RESP_TRANSACTION_INTERIM,Buffer)) <= BytesIndicated) {
                    pInterimResponse = (PRESP_TRANSACTION_INTERIM)((PBYTE)pSmbHeader + *pBytesTaken);
                    if ((pSmbHeader->Command == pTransactExchange->SmbCommand) &&
                        (SmbGetUshort(&pInterimResponse->WordCount) == 0) &&
                        (SmbGetUshort(&pInterimResponse->ByteCount) == 0)) {

                        // The interim response was valid. Transition the state of the exchange
                        // and transmit the secondary requests.
                        *pBytesTaken += FIELD_OFFSET(RESP_TRANSACTION_INTERIM,Buffer);
                        pTransactExchange->State = TRANSACT_EXCHANGE_RECEIVED_INTERIM_RESPONSE;

                        // Determine if any secondary transaction requests need to be sent. if none are
                        // required then modify the state
                        ASSERT((pTransactExchange->ParamBytesSent < pTransactExchange->SendParamBufferSize) ||
                               (pTransactExchange->DataBytesSent < pTransactExchange->SendDataBufferSize));
                        ASSERT((pTransactExchange->ParamBytesSent <= pTransactExchange->SendParamBufferSize) &&
                               (pTransactExchange->DataBytesSent <= pTransactExchange->SendDataBufferSize));

                        if (!(pTransactExchange->Flags & SMB_TRANSACTION_NO_RESPONSE )) {
                            Status = SmbCeReceive(pExchange);
                        }

                        if (Status != STATUS_SUCCESS) {
                            pExchange->Status = Status;
                        } else {
                            Status = STATUS_SUCCESS;
                            SmbCeIncrementPendingLocalOperations(pExchange);
                            RxPostToWorkerThread(
                                MRxSmbDeviceObject,
                                CriticalWorkQueue,
                                &pExchange->WorkQueueItem,
                                SendSecondaryRequests,
                                pExchange);
                        }
                    } else {
                        RxDbgTrace(0,Dbg,("SmbCeTransactExchangeReceive: Invalid interim response\n"));
                        Status = STATUS_INVALID_NETWORK_RESPONSE;
                    }
                } else {
                    fIndicationNotSufficient = TRUE;
                    Status = STATUS_MORE_PROCESSING_REQUIRED;
                }
            }
            break;

        case TRANSACT_EXCHANGE_RECEIVED_INTERIM_RESPONSE:
            RxDbgTrace(0,Dbg,("SmbCeTransactExchangeReceive: received again while in interim response\n"));
          //no break: this is okay
        case TRANSACT_EXCHANGE_TRANSMITTED_SECONDARY_REQUESTS:
        case TRANSACT_EXCHANGE_RECEIVED_PRIMARY_RESPONSE:
            {
                BOOLEAN fPrimaryResponse = FALSE;
                PRESP_TRANSACTION    pTransactResponse;
                PRESP_NT_TRANSACTION pNtTransactResponse;
                ULONG TotalParamBytesInResponse;
                ULONG TotalDataBytesInResponse;

                RxDbgTrace(0,Dbg,("SmbCeTransactExchangeReceive: Processing Primary/Secondary response\n"));

                //do this here so there's only one copy if the code
                pTransactResponse = (PRESP_TRANSACTION)((PBYTE)pSmbHeader +
                                              SmbGetUshort(&CommandToProcess.AndXOffset));

                // All the requests ( both primary and secondary have been sent ). The
                // only responses expected in this state are (1) a primary response and (2) a
                // secondary response. Any other response is an error.
                if (pSmbHeader->Command == pTransactExchange->SmbCommand) {
                    switch (pSmbHeader->Command) {
                    case SMB_COM_TRANSACTION:
                    case SMB_COM_TRANSACTION2:
                        //pTransactResponse = (PRESP_TRANSACTION)((PBYTE)pSmbHeader +
                        //                                        SmbGetUshort(&CommandToProcess.AndXOffset));
                        fPrimaryResponse = TRUE;
                        SetupBytesOffsetInResponse = FIELD_OFFSET(RESP_TRANSACTION,Buffer);
                        SetupBytesInResponse = sizeof(USHORT) * pTransactResponse->SetupCount;

                        // Initialize the total count of data and param bytes that will be received from
                        // the server during the course ofthe transaction response.
                        TotalParamBytesInResponse = SmbGetUshort(&pTransactResponse->TotalParameterCount);
                        TotalDataBytesInResponse  = SmbGetUshort(&pTransactResponse->TotalDataCount);

                    // fall through
                    case SMB_COM_TRANSACTION_SECONDARY:
                    case SMB_COM_TRANSACTION2_SECONDARY:
                        TransactResponseSize = FIELD_OFFSET(RESP_TRANSACTION,Buffer);
                        break;
                    case SMB_COM_NT_TRANSACT:
                        //pNtTransactResponse = (PRESP_NT_TRANSACTION)((PBYTE)pSmbHeader +
                        //                                        SmbGetUshort(&CommandToProcess.AndXOffset));
                        pNtTransactResponse = (PRESP_NT_TRANSACTION)pTransactResponse;
                        fPrimaryResponse = TRUE;
                        SetupBytesOffsetInResponse = FIELD_OFFSET(RESP_NT_TRANSACTION,Buffer);
                        SetupBytesInResponse = sizeof(USHORT) * pNtTransactResponse->SetupCount;

                        // Initialize the total count of data and param bytes that will be received from
                        // the server during the course ofthe transaction response.
                        TotalParamBytesInResponse = SmbGetUshort(&pNtTransactResponse->TotalParameterCount);
                        TotalDataBytesInResponse  = SmbGetUshort(&pNtTransactResponse->TotalDataCount);

                        // fall through ..
                    case SMB_COM_NT_TRANSACT_SECONDARY:
                        TransactResponseSize = FIELD_OFFSET(RESP_NT_TRANSACTION,Buffer);
                        break;

                    default:
                        // Abort the exchange. An unexpected response was received during the
                        // course of the transaction.
                        ASSERT(!"Valid network response");
                        Status = STATUS_INVALID_NETWORK_RESPONSE;
                    }

                    if (Status == STATUS_SUCCESS) {
                        if (fPrimaryResponse) {
                            RxDbgTrace( 0,
                                 Dbg,
                                 ("SmbTransactExchangeReceive: Primary Response Setup Bytes(%ld) Param Bytes (%ld) Data Bytes (%ld)\n",
                                  SetupBytesInResponse,
                                  TotalParamBytesInResponse,
                                  TotalDataBytesInResponse
                                 )
                               );

                            if ((TotalParamBytesInResponse > pTransactExchange->ReceiveParamBufferSize) ||
                                (TotalDataBytesInResponse > pTransactExchange->ReceiveDataBufferSize)) {
                                Status = STATUS_INVALID_NETWORK_RESPONSE;
                                goto FINALLY;
                            } else {
                                pTransactExchange->ReceiveParamBufferSize = TotalParamBytesInResponse;
                                pTransactExchange->ReceiveDataBufferSize  = TotalDataBytesInResponse;
                            }
                        }

                        if (Status == STATUS_SUCCESS &&
                            TransactResponseSize + *pBytesTaken <= BytesIndicated) {
                            if (fPrimaryResponse &&
                                (SetupBytesInResponse > 0)) {

                                PBYTE pSetupStartAddress;
                                ULONG SetupBytesIndicated = MIN(SetupBytesInResponse,
                                                            BytesIndicated - SetupBytesOffsetInResponse);

                                if( pTransactExchange->pReceiveSetupMdl ) {
                                    pSetupStartAddress = (PBYTE)MmGetSystemAddressForMdlSafe(
                                                                pTransactExchange->pReceiveSetupMdl,
                                                                LowPagePriority
                                                                );

                                    if( pSetupStartAddress == NULL ) {
                                        Status = STATUS_INSUFFICIENT_RESOURCES;
                                    } else {
                                        if (SetupBytesInResponse == SetupBytesIndicated) {
                                            RtlCopyMemory(
                                                pSetupStartAddress,
                                                ((PBYTE)pSmbHeader + SetupBytesOffsetInResponse),
                                                SetupBytesIndicated);

                                            pSetupStartAddress += SetupBytesIndicated;
                                            SetupBytesInResponse -= SetupBytesIndicated;
                                            SetupBytesOffsetInResponse += SetupBytesIndicated;
                                            pTransactExchange->SetupBytesReceived = SetupBytesInResponse;
                                        } else {
                                            ASSERT(!"this code doesn't work");
                                            RxDbgTrace(0,Dbg,("SmbTransactExchangeReceive: Setup Bytes Partially Indicated\n"));
                                            // Some setup bytes have not been indicated. An MDL needs to be
                                            // created for copying the data. This MDL should also include the padding
                                            // MDL for copying the padding bytes ...
                                            pSetupMdl = RxAllocateMdl(pSetupStartAddress,SetupBytesInResponse);

                                            if ( pSetupMdl != NULL ) {
                                                IoBuildPartialMdl(
                                                     pTransactExchange->pReceiveSetupMdl,
                                                     pSetupMdl,
                                                     pSetupStartAddress,
                                                     SetupBytesInResponse);
                                            } else {
                                                Status = STATUS_INSUFFICIENT_RESOURCES;
                                            }
                                        }
                                    }
                                }

                                RxDbgTrace(0,Dbg,("SmbTransactExchangeReceive: Setup Bytes Indicated (%ld)\n",SetupBytesIndicated));
                            }

                            if (Status == STATUS_SUCCESS) {
                                // from here, we cannot go back and redo the header....so we have to change state so
                                //that the copy routine doesn't try to reparse
                                pTransactExchange->State = TRANSACT_EXCHANGE_RECEIVED_PRIMARY_RESPONSE;

                                Status = SmbTransactAccrueAndValidateFormatData(
                                             pTransactExchange,
                                             pSmbHeader,
                                             BytesIndicated,
                         

⌨️ 快捷键说明

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