487 lines
13 KiB
C
487 lines
13 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
|