netroot.c

来自「winddk src目录下的文件系统驱动源码压缩!」· C语言 代码 · 共 1,128 行 · 第 1/3 页

C
1,128
字号

                    IoFreeMdl(pSmbRequestMdl);
                }

                RxFreePool(pSmbActualBuffer);
            }
        } else {

            RxFreePool(pSmbActualBuffer);
        }
    } else {
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return Status;
}

NTSTATUS
SmbConstructNetRootExchangeReceive(
    IN struct _SMB_EXCHANGE *pExchange,
    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 net root construction 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:

    NTSTATUS - The return status for the operation

Notes:

    This routine is called at DPC level.

--*/
{
    NTSTATUS Status;

    PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;

    pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;

    RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesIndicated/Available %ld %ld\n",BytesIndicated,BytesAvailable));

    if (BytesAvailable > BytesIndicated ||
        !FlagOn(ReceiveFlags,TDI_RECEIVE_ENTIRE_MESSAGE)) {
        // The SMB response was not completely returned. Post a copy data request to
        // get the remainder of the response. If the response is greater than the original
        // buffer size, abort this connection request and consume the bytes available.

        if (BytesAvailable > CONSTRUCT_NETROOT_BUFFER_SIZE) {
            ASSERT(!"not enough bytes in parsesmbheader.....sigh.............."); // To be removed soon ...
            pExchange->Status = STATUS_NOT_IMPLEMENTED;
            *pBytesTaken = BytesAvailable;
            Status       = STATUS_SUCCESS;
        } else {
            *pBytesTaken        = 0;
            *pDataBufferPointer = pNetRootExchange->pSmbResponseMdl;
            *pDataSize          = CONSTRUCT_NETROOT_BUFFER_SIZE;
            Status              = STATUS_MORE_PROCESSING_REQUIRED;
        }
    } else {
        // The SMB exchange completed without an error.
        pExchange->Status = SmbCeParseConstructNetRootResponse(
                                 pNetRootExchange,
                                 pSmbHeader,
                                 BytesAvailable,
                                 BytesIndicated,
                                 pBytesTaken);

        RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesTaken %ld\n",*pBytesTaken));
        RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader Return Status %lx\n",pExchange->Status));
        Status = STATUS_SUCCESS;
    }

    return Status;
}

NTSTATUS
SmbConstructNetRootExchangeCopyDataHandler(
    IN PSMB_EXCHANGE    pExchange,
    IN PMDL       pCopyDataBuffer,
    IN ULONG            DataSize)
/*++

Routine Description:

    This is the copy data handling routine for net root construction exchanges

Arguments:

    pExchange - the exchange instance

Return Value:

    NTSTATUS - The return status for the operation

--*/
{
    PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;

    PSMB_HEADER pSmbHeader;
    ULONG       ResponseSize = DataSize;
    ULONG       ResponseBytesConsumed = 0;
    NTSTATUS    Status = STATUS_SUCCESS;

    pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
    ASSERT(pCopyDataBuffer == pNetRootExchange->pSmbResponseMdl);

    pSmbHeader = (PSMB_HEADER)MmGetSystemAddressForMdlSafe(pNetRootExchange->pSmbResponseMdl,LowPagePriority);

    if (pSmbHeader != NULL) {
        pExchange->Status = SmbCeParseConstructNetRootResponse(
                               pNetRootExchange,
                               pSmbHeader,
                               ResponseSize,
                               ResponseSize,
                               &ResponseBytesConsumed);
    } else {
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesTaken %ld\n",ResponseBytesConsumed));

    return Status;
}

NTSTATUS
SmbCeParseConstructNetRootResponse(
    PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange,
    PSMB_HEADER                     pSmbHeader,
    ULONG                           BytesAvailable,
    ULONG                           BytesIndicated,
    ULONG                           *pBytesTaken)
{
    NTSTATUS     Status,SmbResponseStatus;
    GENERIC_ANDX CommandToProcess;

    RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesIndicated %ld\n",BytesIndicated));
    Status = SmbCeParseSmbHeader(
                 (PSMB_EXCHANGE)pNetRootExchange,
                 pSmbHeader,
                 &CommandToProcess,
                 &SmbResponseStatus,
                 BytesAvailable,
                 BytesIndicated,
                 pBytesTaken);

    if (Status == STATUS_SUCCESS) {
        *pBytesTaken = BytesIndicated;
    }

    return Status;
}


NTSTATUS
SmbConstructNetRootExchangeFinalize(
    PSMB_EXCHANGE pExchange,
    BOOLEAN       *pPostFinalize)
/*++

Routine Description:

    This routine finalizes the construct net root exchange. It resumes the RDBSS by invoking
    the call back and discards the exchange

Arguments:

    pExchange - the exchange instance

    CurrentIrql - the current interrupt request level

    pPostFinalize - a pointer to a BOOLEAN if the request should be posted

Return Value:

    RXSTATUS - The return status for the operation

--*/
{
    PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
    PMRX_CREATENETROOT_CONTEXT      pCreateNetRootContext;
    PMRX_NETROOT_CALLBACK           pNetRootCallback;

    PMRX_V_NET_ROOT pVNetRoot;
    PMRX_NET_ROOT   pNetRoot;
    PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);

    PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
    NTSTATUS Status = pExchange->Status;

    if (RxShouldPostCompletion()) {
        *pPostFinalize = TRUE;
        return STATUS_SUCCESS;
    } else {
        *pPostFinalize = FALSE;
    }

    pVNetRoot = SmbCeGetExchangeVNetRoot(pExchange);
    pNetRoot  = pVNetRoot->pNetRoot;

    pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot);

    ASSERT((pVNetRoot == NULL) || (pVNetRoot->pNetRoot == pNetRoot));
    pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
    pNetRootCallback = pNetRootExchange->NetRootCallback;

    ASSERT(pNetRootExchange->Type == CONSTRUCT_NETROOT_EXCHANGE);

    pCreateNetRootContext = pNetRootExchange->pCreateNetRootContext;

    pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
    pCreateNetRootContext->NetRootStatus        = STATUS_SUCCESS;

    RxDbgTrace(0,Dbg,("SmbConstructNetRootExchangeFinalize: Net Root Exchange Status %lx\n", pExchange->Status));
    if (!NT_SUCCESS(pExchange->Status)) {
        if (pCreateNetRootContext->RxContext &&
            pCreateNetRootContext->RxContext->Create.ThisIsATreeConnectOpen){
            InterlockedIncrement(&MRxSmbStatistics.FailedUseCount);
        }

        pCreateNetRootContext->VirtualNetRootStatus = Status;

        if (pCreateNetRootContext->VirtualNetRootStatus == STATUS_INVALID_HANDLE) {
            pCreateNetRootContext->VirtualNetRootStatus = STATUS_UNEXPECTED_NETWORK_ERROR;
        }

        if (pNetRootExchange->fInitializeNetRoot) {
            pCreateNetRootContext->NetRootStatus = Status;

            if (pCreateNetRootContext->NetRootStatus == STATUS_INVALID_HANDLE) {
                pCreateNetRootContext->NetRootStatus = STATUS_UNEXPECTED_NETWORK_ERROR;
            }
        }

        SmbCeUpdateVNetRootContextState(
            pVNetRootContext,
            SMBCEDB_MARKED_FOR_DELETION);
    } else {
        PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;

        pNetRootEntry = SmbCeGetExchangeNetRootEntry(pExchange);

        // Update the associated wrapper data structures.
        SmbCeUpdateNetRoot(pNetRootEntry,pNetRoot);
    }

    SmbCeReferenceVNetRootContext(pVNetRootContext);
    SmbCeCompleteVNetRootContextInitialization(pVNetRootContext);
    pExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_NETROOT_CONSTRUCTOR;

    ASSERT((pCreateNetRootContext->VirtualNetRootStatus != STATUS_SUCCESS) || (pVNetRoot->Context != NULL));

    if ((pCreateNetRootContext->NetRootStatus == STATUS_CONNECTION_RESET)||(pCreateNetRootContext->NetRootStatus == STATUS_IO_TIMEOUT))
    {
        SmbCeLog(("!!Remote Reset Status=%x\n", pCreateNetRootContext->NetRootStatus));
    }

    if (pNetRootExchange->pSmbResponseMdl != NULL) {
        MmUnlockPages(pNetRootExchange->pSmbResponseMdl);
        IoFreeMdl(pNetRootExchange->pSmbResponseMdl);
    }

    if (pNetRootExchange->pSmbRequestMdl != NULL) {
        RxUnlockHeaderPages(pNetRootExchange->pSmbRequestMdl);
        IoFreeMdl(pNetRootExchange->pSmbRequestMdl);
    }

    if (pNetRootExchange->pSmbActualBuffer != NULL) {

        RxFreePool(pNetRootExchange->pSmbActualBuffer);
    }

    // Tear down the exchange instance ...
    SmbCeDiscardExchange(pExchange);

    // Callback the RDBSS for resumption
    pNetRootCallback(pCreateNetRootContext);

    return STATUS_SUCCESS;
}




SMB_EXCHANGE_DISPATCH_VECTOR
ConstructNetRootExchangeDispatch = {
                                       SmbConstructNetRootExchangeStart,
                                       SmbConstructNetRootExchangeReceive,
                                       SmbConstructNetRootExchangeCopyDataHandler,
                                       NULL,  // No SendCompletionHandler
                                       SmbConstructNetRootExchangeFinalize,
                                       NULL
                                   };


VOID
MRxSmbExtractNetRootName(
    IN PUNICODE_STRING FilePathName,
    IN PMRX_SRV_CALL   SrvCall,
    OUT PUNICODE_STRING NetRootName,
    OUT PUNICODE_STRING RestOfName OPTIONAL
    )
/*++

Routine Description:

    This routine parses the input name into srv, netroot, and the
    rest.

Arguments:


--*/
{
    UNICODE_STRING xRestOfName;

    ULONG length = FilePathName->Length;
    PWCH w = FilePathName->Buffer;
    PWCH wlimit = (PWCH)(((PCHAR)w)+length);
    PWCH wlow;

    PAGED_CODE();

    w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
    NetRootName->Buffer = wlow = w;
    for (;;) {
        if (w>=wlimit) break;
        if ( (*w == OBJ_NAME_PATH_SEPARATOR) && (w!=wlow) ){
            break;
        }
        w++;
    }
    NetRootName->Length = NetRootName->MaximumLength
                = (USHORT)((PCHAR)w - (PCHAR)wlow);

    if (!RestOfName) RestOfName = &xRestOfName;
    RestOfName->Buffer = w;
    RestOfName->Length = RestOfName->MaximumLength
                       = (USHORT)((PCHAR)wlimit - (PCHAR)w);

    RxDbgTrace( 0,Dbg,("  MRxSmbExtractNetRootName FilePath=%wZ\n",FilePathName));
    RxDbgTrace(0,Dbg,("         Srv=%wZ,Root=%wZ,Rest=%wZ\n",
                        SrvCall->pSrvCallName,NetRootName,RestOfName));

    return;
}




⌨️ 快捷键说明

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