📄 netroot.c
字号:
/*++
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 + -