windows-nt/Source/XPSP1/NT/base/fs/rdr2/rdbss/proxy.mrx/netroot.c
2020-09-26 16:20:57 +08:00

487 lines
13 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
netroot.c
Abstract:
This module implements the routines for creating the PROXY net root.
Author:
Balan Sethu Raman [SethuR] 7-March-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// The Bug check file id for this module
//
#define BugCheckFileId (RDBSS_BUG_CHECK_PROXY_NETROOT)
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_DISPATCH)
//
// Forward declarations ...
//
NTSTATUS
MRxProxyUpdateNetRootState(
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:
--*/
{
if (pNetRoot->Context == NULL) {
pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
} else {
pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
}
return STATUS_SUCCESS;
}
NTSTATUS
MRxProxyCreateVNetRoot(
IN OUT PMRX_V_NET_ROOT pVNetRoot,
IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext
)
/*++
Routine Description:
This routine patches the RDBSS created net root instance with the information required
by the mini redirector.
Arguments:
pVNetRoot - the virtual net root instance.
pCreateNetRootContext - the net root context for calling back
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
//NTSTATUS Status;
PRX_CONTEXT pRxContext = pCreateNetRootContext->RxContext;
PMRXPROXY_DEVICE_OBJECT MRxProxyDeviceObject = (PMRXPROXY_DEVICE_OBJECT)(pRxContext->RxDeviceObject);
PMRX_SRV_CALL pSrvCall;
PMRX_NET_ROOT pNetRoot;
RxDbgTrace( 0, Dbg, ("MRxProxyCreateVNetRoot %lx\n",pVNetRoot));
pNetRoot = pVNetRoot->pNetRoot;
pSrvCall = pNetRoot->pSrvCall;
ASSERT((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) &&
(NodeType(pSrvCall) == RDBSS_NTC_SRVCALL));
pNetRoot->InnerNamePrefix = MRxProxyDeviceObject->InnerPrefixForOpens;
pNetRoot->DiskParameters.RenameInfoOverallocationSize = MRxProxyDeviceObject->PrefixForRename.Length;
pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
// Callback the RDBSS for resumption.
pCreateNetRootContext->Callback(pCreateNetRootContext);
// Map the error code to STATUS_PENDING since this triggers the synchronization
// mechanism in the RDBSS.
return STATUS_PENDING;
}
NTSTATUS
MRxProxyFinalizeVNetRoot(
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
--*/
{
RxDbgTrace( 0, Dbg, ("MRxProxyFinalizeVNetRoot %lx\n",pVNetRoot));
//return STATUS_SUCCESS;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
MRxProxyFinalizeNetRoot(
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
--*/
{
RxDbgTrace( 0, Dbg, ("MRxProxyFinalizeNetRoot %lx\n",pNetRoot));
//return STATUS_SUCCESS;
return STATUS_NOT_IMPLEMENTED;
}
VOID
ProxyCeReconnectCallback(
PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
/*++
Routine Description:
This routine signals the completion of a reconnect attempt
Arguments:
pCreateNetRootContext - the net root context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
KeSetEvent(&pCreateNetRootContext->FinishEvent, IO_NETWORK_INCREMENT, FALSE );
}
NTSTATUS
ProxyCeReconnect(
IN PMRX_V_NET_ROOT pVNetRoot)
/*++
Routine Description:
This routine reconnects, i.e, establishes a new session and tree connect to a previously
connected serverb share
Arguments:
pVNetRoot - the virtual net root instance.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext;
pCreateNetRootContext = (PMRX_CREATENETROOT_CONTEXT)
RxAllocatePoolWithTag(
NonPagedPool,
sizeof(MRX_CREATENETROOT_CONTEXT),
MRXPROXY_NETROOT_POOLTAG);
if (pCreateNetRootContext != NULL) {
pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->Callback = ProxyCeReconnectCallback;
pCreateNetRootContext->RxContext = NULL;
KeInitializeEvent( &pCreateNetRootContext->FinishEvent, SynchronizationEvent, FALSE );
// Since this is a reconnect instance the net root initialization is not required
#if 0
Status = ProxyCeEstablishConnection(
pVNetRoot,
pCreateNetRootContext,
FALSE);
#endif
Status = STATUS_SUCCESS;
if (Status == STATUS_PENDING) {
// Wait for the construction to be completed.
KeWaitForSingleObject(&pCreateNetRootContext->FinishEvent, Executive, KernelMode, FALSE, NULL);
Status = pCreateNetRootContext->VirtualNetRootStatus;
}
RxFreePool(pCreateNetRootContext);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}
NTSTATUS
ProxyCeEstablishConnection(
IN OUT PMRX_V_NET_ROOT pVNetRoot,
IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext,
IN BOOLEAN fInitializeNetRoot
)
/*++
Routine Description:
This routine triggers off the connection attempt for initial establishment of a
connection as well as subsequent reconnect attempts.
Arguments:
pVNetRoot - the virtual net root instance.
pCreateNetRootContext - the net root context for calling back
Return Value:
RXSTATUS - The return status for the operation
Notes:
CODE.IMPROVEMENT -- The net root create context must supply the open mode in order
to enable the mini redirector to implement a wide variety of reconnect strategies.
--*/
{
NTSTATUS Status;
#if 0
PPROXYCEDB_SERVER_ENTRY pServerEntry;
PPROXYCEDB_SESSION_ENTRY pSessionEntry;
PPROXYCEDB_NET_ROOT_ENTRY pNetRootEntry;
PPROXYCE_V_NET_ROOT_CONTEXT pVNetRootContext;
pVNetRootContext = ProxyCeGetAssociatedVNetRootContext(pVNetRoot);
if (pVNetRootContext == NULL) {
Status = STATUS_BAD_NETWORK_PATH;
} else {
pServerEntry = pVNetRootContext->pServerEntry;
pSessionEntry = pVNetRootContext->pSessionEntry;
pNetRootEntry = pVNetRootContext->pNetRootEntry;
Status = STATUS_SUCCESS;
}
if (Status != STATUS_SUCCESS) {
return Status;
}
if ((pServerEntry->Server.DialectFlags & DF_EXTENDED_SECURITY) &&
(pSessionEntry->Header.State != PROXYCEDB_ACTIVE)) {
PPROXY_EXCHANGE pSessionSetupExchange;
pSessionSetupExchange = ProxyMmAllocateExchange(EXTENDED_SESSION_SETUP_EXCHANGE,NULL);
if (pSessionSetupExchange != NULL) {
Status = ProxyCeInitializeExtendedSessionSetupExchange(
&pSessionSetupExchange,
pVNetRoot);
if (Status == STATUS_SUCCESS) {
PROXYCE_RESUMPTION_CONTEXT ExchangeResumptionContext;
// Attempt to reconnect( In this case it amounts to establishing the
// connection/session)
pSessionSetupExchange->ProxyCeFlags |= PROXYCE_EXCHANGE_ATTEMPT_RECONNECTS;
ProxyCeInitializeResumptionContext(&ExchangeResumptionContext);
((PPROXY_EXTENDED_SESSION_SETUP_EXCHANGE)pSessionSetupExchange)->pResumptionContext
= &ExchangeResumptionContext;
Status = ProxyCeInitiateExchange(pSessionSetupExchange);
if (Status == STATUS_PENDING) {
ProxyCeSuspend(
&ExchangeResumptionContext);
Status = ExchangeResumptionContext.Status;
} else {
ProxyCeDiscardExtendedSessionSetupExchange(
(PPROXY_EXTENDED_SESSION_SETUP_EXCHANGE)pSessionSetupExchange);
}
} else {
ProxyMmFreeExchange(pSessionSetupExchange);
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (Status == STATUS_SUCCESS) {
//
// The following code initializes the NetRootEntry, VNetRootContext and
// the session entry under certain cases.
//
// The session entry to a doenlevel server needs to be initialized. This
// is not handled by the previous code since the session entry and the
// net root entry initialization can be combined into one exchange.
//
// The net root entry has not been initialized, i.e., this corresponds to
// the construction of the first PROXYCE_V_NET_ROOT_CONTEXT instance for a
// given NetRootEntry.
//
// Subsequent PROXYCE_V_NET_ROOT context constructions. In these cases the
// construction of each context must obtain a new TID
//
BOOLEAN fNetRootExchangeRequired;
fNetRootExchangeRequired = (
((pSessionEntry->Header.State != PROXYCEDB_ACTIVE) &&
!(pServerEntry->Server.DialectFlags & DF_EXTENDED_SECURITY))
||
!BooleanFlagOn(
pVNetRootContext->Flags,
PROXYCE_V_NET_ROOT_CONTEXT_FLAG_VALID_TID)
);
if (fNetRootExchangeRequired) {
// This is a tree connect open which needs to be triggered immediately.
PPROXY_EXCHANGE pProxyExchange;
PPROXY_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
pProxyExchange = ProxyMmAllocateExchange(CONSTRUCT_NETROOT_EXCHANGE,NULL);
if (pProxyExchange != NULL) {
Status = ProxyCeInitializeExchange(
&pProxyExchange,
pVNetRoot,
CONSTRUCT_NETROOT_EXCHANGE,
&ConstructNetRootExchangeDispatch);
if (Status == RX_MAP_STATUS(SUCCESS)) {
pNetRootExchange = (PPROXY_CONSTRUCT_NETROOT_EXCHANGE)pProxyExchange;
// Attempt to reconnect( In this case it amounts to establishing the
// connection/session)
pNetRootExchange->ProxyCeFlags |= PROXYCE_EXCHANGE_ATTEMPT_RECONNECTS;
// Initialize the continuation for resumption upon completion of the
// tree connetcion.
pNetRootExchange->NetRootCallback = pCreateNetRootContext->Callback;
pNetRootExchange->pCreateNetRootContext = pCreateNetRootContext;
pNetRootExchange->fInitializeNetRoot = fInitializeNetRoot;
// Initiate the exchange.
Status = ProxyCeInitiateExchange(pProxyExchange);
if (Status != STATUS_PENDING) {
ProxyCeDiscardExchange(pProxyExchange);
}
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
#endif
Status = STATUS_SUCCESS;
return Status;
}
VOID
MRxProxyExtractNetRootName(
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;
w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
NetRootName->Buffer = wlow = w;
for (;;) {
if (w>=wlimit) break;
if ( (*w == OBJ_NAME_PATH_SEPARATOR) && (w!=wlow) ){
#if ZZZ_MODE
if (*(w-1) == L'z') {
w++;
continue;
}
#endif //if ZZZ_MODE
break;
}
w++;
}
NetRootName->Length = NetRootName->MaximumLength
= (PCHAR)w - (PCHAR)wlow;
if (!RestOfName) RestOfName = &xRestOfName;
RestOfName->Buffer = w;
RestOfName->Length = RestOfName->MaximumLength
= (PCHAR)wlimit - (PCHAR)w;
RxDbgTrace( 0,Dbg,(" MRxProxyExtractNetRootName FilePath=%wZ\n",FilePathName));
RxDbgTrace(0,Dbg,(" Srv=%wZ,Root=%wZ,Rest=%wZ\n",
SrvCall->pSrvCallName,NetRootName,RestOfName));
return;
}