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

📄 netroot.c

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

Copyright (c) 1989 - 1999  Microsoft Corporation

Module Name:

    netroot.c

Abstract:

    This module implements the routines for creating the SMB net root.

--*/

#include "precomp.h"
#pragma hdrstop

//
//  The Bug check file id for this module
//

#define BugCheckFileId  (RDBSS_BUG_CHECK_SMB_NETROOT)

//
//  The local debug trace level
//

#define Dbg (DEBUG_TRACE_DISPATCH)

#ifdef  ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxSmbUpdateNetRootState)
#pragma alloc_text(PAGE, MRxSmbGetDialectFlagsFromSrvCall)
#pragma alloc_text(PAGE, MRxSmbCreateVNetRoot)
#pragma alloc_text(PAGE, MRxSmbFinalizeNetRoot)
#pragma alloc_text(PAGE, SmbCeReconnect)
#pragma alloc_text(PAGE, SmbCeEstablishConnection)
#pragma alloc_text(PAGE, SmbConstructNetRootExchangeStart)
#pragma alloc_text(PAGE, MRxSmbExtractNetRootName)
#endif

//
// Forward declarations ...
//

extern NTSTATUS
SmbCeParseConstructNetRootResponse(
   PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange,
   PSMB_HEADER                     pSmbHeader,
   ULONG                           BytesAvailable,
   ULONG                           BytesIndicated,
   ULONG                           *pBytesTaken);

extern NTSTATUS
SmbConstructNetRootExchangeFinalize(
         PSMB_EXCHANGE  pExchange,
         BOOLEAN        *pPostFinalize);

typedef struct _SMBCE_NETROOT_CONSTRUCTION_CONTEXT {
    NTSTATUS                      Status;

    PMRX_CREATENETROOT_CONTEXT    pCreateNetRootContext;
    PMRX_V_NET_ROOT               pVNetRoot;

    RX_WORK_QUEUE_ITEM            WorkQueueItem;
} SMBCE_NETROOT_CONSTRUCTION_CONTEXT,
  *PSMBCE_NETROOT_CONSTRUCTION_CONTEXT;

NTSTATUS
MRxSmbUpdateNetRootState(
    IN OUT PMRX_NET_ROOT pNetRoot)
/*++

Routine Description:

   This routine update the mini redirector state associated with a net root.

Arguments:

    pNetRoot - the net root instance.

Return Value:

    RXSTATUS - The return status for the operation

Notes:

    By diffrentiating the mini redirewctor state from the net rot condition it is possible
    to permit a variety of reconnect strategies. It is conceivable that the RDBSS considers
    a net root to be good while the underlying mini redirector might mark it as invalid
    and reconnect on the fly.

--*/
{
    if (pNetRoot->MRxNetRootState == MRX_NET_ROOT_STATE_GOOD) {
        if (pNetRoot->Context == NULL) {
            pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
        } else {
            PSMBCEDB_SERVER_ENTRY   pServerEntry;

            pServerEntry = SmbCeReferenceAssociatedServerEntry(pNetRoot->pSrvCall);
            if (pServerEntry != NULL) {
                switch (pServerEntry->Header.State) {
                case SMBCEDB_ACTIVE:
                     pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
                     break;
                case SMBCEDB_INVALID:
                     pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_DISCONNECTED;
                     break;
                case SMBCEDB_CONSTRUCTION_IN_PROGRESS:
                     pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_RECONN;
                     break;
                default:
                     pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
                     break;
                }

                SmbCeDereferenceServerEntry(pServerEntry);
            } else {
                pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
            }
        }
    }

    return STATUS_SUCCESS;
}

ULONG
MRxSmbGetDialectFlagsFromSrvCall(
    PMRX_SRV_CALL SrvCall
    )
{
   ULONG DialectFlags;
   PSMBCEDB_SERVER_ENTRY pServerEntry;

   PAGED_CODE();

   pServerEntry = SmbCeReferenceAssociatedServerEntry(SrvCall);
   ASSERT(pServerEntry != NULL);
   DialectFlags = pServerEntry->Server.DialectFlags;
   SmbCeDereferenceServerEntry(pServerEntry);
   return(DialectFlags);
}


NTSTATUS
MRxSmbCreateVNetRoot(
    IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext
    )
/*++

Routine Description:

   This routine patches the RDBSS created net root instance with the information required
   by the mini redirector.

   In case the connection cannot be established, the mini redirector tries to transition
   the VNetRoot into disconnected mode and establishes the connection off-line. If the
   connection failes to establish in the synchronouse way, this routine will do the transition;
   Otherwise, SmbConstructNetRootExchangeFinalize routine will try the transition. In both
   cases, MRxSmbCreateVNetRoot will be called again to establish the connection in disconnected
   mode.

Arguments:

    pVNetRoot - the virtual net root instance.

    pCreateNetRootContext - the net root context for calling back

Return Value:

    RXSTATUS - The return status for the operation

--*/
{
    NTSTATUS  Status = STATUS_MORE_PROCESSING_REQUIRED;
    PRX_CONTEXT pRxContext = pCreateNetRootContext->RxContext;
    PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;

    PMRX_SRV_CALL pSrvCall;
    PMRX_NET_ROOT pNetRoot;

    PSMBCEDB_SERVER_ENTRY pServerEntry;

    PUNICODE_STRING pNetRootName,pSrvCallName;

    BOOLEAN  fInitializeNetRoot;
    BOOLEAN  fDeferNetworkInitialization;
    BOOLEAN  CallBack = FALSE;
    extern DWORD   hShareReint;

    PAGED_CODE();

    pNetRoot = pVNetRoot->pNetRoot;
    pSrvCall = pNetRoot->pSrvCall;

    pServerEntry = SmbCeGetAssociatedServerEntry(pSrvCall);

    if (pRxContext->Create.ThisIsATreeConnectOpen){
        InterlockedIncrement(&MRxSmbStatistics.UseCount);
    }

    SmbCeLog(("Vnetroot %wZ \n", pNetRoot->pNetRootName));

    fInitializeNetRoot = (pNetRoot->Context == NULL);
    fDeferNetworkInitialization = pRxContext->Create.TreeConnectOpenDeferred;

    ASSERT((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) &&
           (NodeType(pNetRoot->pSrvCall) == RDBSS_NTC_SRVCALL));

    if (pNetRoot->Type == NET_ROOT_MAILSLOT) {
        pVNetRoot->Context = NULL;
        Status = STATUS_NOT_SUPPORTED;
        RxDbgTrace( 0, Dbg, ("Mailslot open\n"));
    } else if (pNetRoot->Type == NET_ROOT_PIPE) {
        pVNetRoot->Context = NULL;
        Status = STATUS_NOT_SUPPORTED;
        RxDbgTrace( 0, Dbg, ("pipe open to core server\n"));
    }

    if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
        Status = SmbCeFindOrConstructVNetRootContext(
                     pVNetRoot,
                     fDeferNetworkInitialization);
    }

    if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
        // Update the flags on the VNetRootContext to indicate if this is a
        // agent open

        Status = SmbCeEstablishConnection(
                     pVNetRoot,
                     pCreateNetRootContext,
                     fInitializeNetRoot);
    }

    if (Status != STATUS_PENDING) {
        if (!NT_SUCCESS(Status)) {
            if (fInitializeNetRoot &&
                (pNetRoot->Context != NULL)) {
                PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;

                SmbCeAcquireResource();

                pNetRootEntry = SmbCeGetAssociatedNetRootEntry(pNetRoot);

                if (pNetRootEntry != NULL) {
                    pNetRootEntry->pRdbssNetRoot = NULL;
                    SmbCeDereferenceNetRootEntry(pNetRootEntry);
                }

                pNetRoot->Context = NULL;

                SmbCeReleaseResource();
            }

            SmbCeDestroyAssociatedVNetRootContext(pVNetRoot);

            if (pRxContext->Create.ThisIsATreeConnectOpen){
                InterlockedIncrement(&MRxSmbStatistics.FailedUseCount);
            }
        }

        pCreateNetRootContext->VirtualNetRootStatus = Status;

        if (fInitializeNetRoot) {
            pCreateNetRootContext->NetRootStatus = Status;
        } else {
            pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
        }

        CallBack = TRUE;

        // Map the error code to STATUS_PENDING since this triggers the synchronization
        // mechanism in the RDBSS.
        Status = STATUS_PENDING;
    }

    if (CallBack) {
        // Callback the RDBSS for resumption.
        pCreateNetRootContext->Callback(pCreateNetRootContext);
    }

    return Status;
}

NTSTATUS
MRxSmbFinalizeVNetRoot(
    IN PMRX_V_NET_ROOT pVNetRoot,
    IN PBOOLEAN        ForceDisconnect)
/*++

Routine Description:


Arguments:

    pVNetRoot - the virtual net root

    ForceDisconnect - disconnect is forced

Return Value:

    RXSTATUS - The return status for the operation

--*/
{
    PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
    PSMBCEDB_SESSION_ENTRY pDefaultSessionEntry;

    // This cannot be paged code since we meed to protect the default session list with the lock

    RxDbgTrace( 0, Dbg, ("MRxSmbFinalizeVNetRoot %lx\n",pVNetRoot));

    if (pVNetRoot->Context != NULL) {
        SmbCeDestroyAssociatedVNetRootContext(pVNetRoot);
    }

    return STATUS_SUCCESS;
}


NTSTATUS
MRxSmbFinalizeNetRoot(
    IN PMRX_NET_ROOT   pNetRoot,
    IN PBOOLEAN        ForceDisconnect)
/*++

Routine Description:


Arguments:

    pVirtualNetRoot - the virtual net root

    ForceDisconnect - disconnect is forced

Return Value:

    RXSTATUS - The return status for the operation

--*/
{
    PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;

    PAGED_CODE();

    RxDbgTrace( 0, Dbg, ("MRxSmbFinalizeNetRoot %lx\n",pNetRoot));

    if (pNetRoot->Context != NULL) {
        SmbCeAcquireResource();

        pNetRootEntry = SmbCeGetAssociatedNetRootEntry(pNetRoot);

        InterlockedCompareExchangePointer(
            &pNetRootEntry->pRdbssNetRoot,
            NULL,
            pNetRoot);

        SmbCeDereferenceNetRootEntry(pNetRootEntry);

        ASSERT(!FlagOn(pNetRoot->Flags,NETROOT_FLAG_FINALIZE_INVOKED));
        SetFlag(pNetRoot->Flags,NETROOT_FLAG_FINALIZE_INVOKED);

        SmbCeReleaseResource();
    }

    return STATUS_SUCCESS;
}

VOID
SmbCeReconnectCallback(
   PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
/*++

Routine Description:

⌨️ 快捷键说明

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