459 lines
13 KiB
C
459 lines
13 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
NetName.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the local minirdr routines for initializing the dispatch vector
|
||
and delaing with netnames.
|
||
|
||
Author:
|
||
|
||
Joe Linn [JoeLinn] 4-dec-1994
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include "fsctlbuf.h"
|
||
#include "NtDdNfs2.h"
|
||
#include "stdio.h"
|
||
|
||
//
|
||
// The Bug check file id for this module
|
||
//
|
||
|
||
#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_NETNAME)
|
||
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_DISPATCH)
|
||
|
||
BOOLEAN //this is just a copy of the routine from string.c
|
||
RxCreateUnicodeStringFromAsciiz(
|
||
OUT PUNICODE_STRING DestinationString,
|
||
IN PCSZ SourceString
|
||
)
|
||
{
|
||
ANSI_STRING AnsiString;
|
||
RXSTATUS Status;
|
||
|
||
RtlInitAnsiString( &AnsiString, SourceString );
|
||
Status = RtlAnsiStringToUnicodeString( DestinationString, &AnsiString, TRUE );
|
||
if (NT_SUCCESS( Status )) {
|
||
return( TRUE );
|
||
}
|
||
else {
|
||
return( FALSE );
|
||
}
|
||
}
|
||
|
||
PSRV_CALL MrxLocalSrvCall;
|
||
RXSTATUS MRxLocalStart(
|
||
PRX_CONTEXT RxContext,
|
||
PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets up some initial (debug) netroots
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the Irp that was used to startup the rdbss and may contain a startup
|
||
linkage description
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
RXSTATUS Status;
|
||
RxCaptureRequestPacket;
|
||
RxCaptureParamBlock;
|
||
UNICODE_STRING MrxLocalSrvCallName,MyNetRootName,MyInnerPrefix;
|
||
PNET_ROOT DosDevicesNetRoot,MyNetRoot;
|
||
char c;
|
||
|
||
#ifdef RDBSSDBG
|
||
ULONG SaveFCBSTRUCTSLevel;
|
||
ULONG SavePREFIXLevel;
|
||
#endif // RDBSSDBG
|
||
|
||
//local minirdr UNC stuff
|
||
|
||
RxAcquirePrefixTableLockExclusive( &RxNetNameTable, TRUE );
|
||
|
||
|
||
#ifdef RDBSSTRACE
|
||
SaveFCBSTRUCTSLevel = RxDbgTraceFindControlPoint((DEBUG_TRACE_FCBSTRUCTS))->PrintLevel;
|
||
SavePREFIXLevel = RxDbgTraceFindControlPoint((DEBUG_TRACE_PREFIX))->PrintLevel;
|
||
RxDbgTraceFindControlPoint((DEBUG_TRACE_FCBSTRUCTS))->PrintLevel = 0;
|
||
RxDbgTraceFindControlPoint((DEBUG_TRACE_PREFIX))->PrintLevel = 0;
|
||
#endif // RDBSSTRACE
|
||
|
||
//joejoe we should be allocating our initial srvcall adn netroot together
|
||
RtlInitUnicodeString(&MrxLocalSrvCallName,L"\\RX$$");
|
||
MrxLocalSrvCall = RxCreateSrvCall(&MrxLocalSrvCallName,&MRxLocalDispatch,FALSE,
|
||
NULL,NULL,sizeof(FCB),sizeof(MRX_LOCAL_SRV_OPEN),sizeof(FOBX),0
|
||
);
|
||
MrxLocalSrvCall->Condition = Condition_Good;
|
||
|
||
|
||
#ifdef RDBSSTRACE
|
||
RxDbgTraceFindControlPoint((DEBUG_TRACE_FCBSTRUCTS))->PrintLevel = SaveFCBSTRUCTSLevel;
|
||
RxDbgTraceFindControlPoint((DEBUG_TRACE_PREFIX))->PrintLevel = SavePREFIXLevel;
|
||
#endif // RDBSSTRACE
|
||
|
||
RxReleasePrefixTableLock( &RxNetNameTable );
|
||
|
||
return(RxStatus(SUCCESS));
|
||
}
|
||
|
||
RXSTATUS
|
||
MRxLocalMinirdrControl(
|
||
IN PRX_CONTEXT RxContext,
|
||
IN PVOID Context,
|
||
IN OUT PUCHAR InputBuffer,
|
||
IN OUT PUCHAR OutputBuffer,
|
||
IN ULONG InputBufferLength,
|
||
IN ULONG OutputBufferLength,
|
||
OUT PULONG CopyBackLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does nothing.
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the Irp that was used to startup the rdbss and may contain a startup
|
||
linkage description
|
||
|
||
Return Value:
|
||
|
||
RxStatus(SUCCESS)
|
||
|
||
--*/
|
||
{
|
||
RXSTATUS Status = RxStatus(SUCCESS);
|
||
RxCaptureRequestPacket;
|
||
RxCaptureParamBlock;
|
||
|
||
PAGED_CODE();
|
||
|
||
RxDbgTrace(0, (DEBUG_TRACE_ALWAYS), ("MRxLocalMinirdrControl %-4.4s %-4.4s <%s>\n",
|
||
InputBuffer, InputBuffer+4,
|
||
((OutputBuffer)?OutputBuffer:"")
|
||
));
|
||
|
||
return(RxStatus(SUCCESS));
|
||
}
|
||
|
||
RXSTATUS MRxLocalStop(
|
||
PRX_CONTEXT RxContext,
|
||
PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does nothing.
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the Irp that was used to startup the rdbss and may contain a startup
|
||
linkage description
|
||
|
||
Return Value:
|
||
|
||
RxStatus(SUCCESS)
|
||
|
||
--*/
|
||
{
|
||
//RXSTATUS Status;
|
||
|
||
return(RxStatus(SUCCESS));
|
||
}
|
||
|
||
RXSTATUS MRxLocalInitializeCalldownTable(
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does two things sets up the minirdr dispatch table for the local minirdr.
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation, alayws success
|
||
|
||
--*/
|
||
{
|
||
RXSTATUS Status;
|
||
|
||
//local minirdr dispatch table init
|
||
ZeroAndInitializeNodeType( &MRxLocalDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
|
||
MRxLocalDispatch.MRxStart = MRxLocalStart;
|
||
MRxLocalDispatch.MRxStop = MRxLocalStop;
|
||
MRxLocalDispatch.MRxMinirdrControl = MRxLocalMinirdrControl;
|
||
MRxLocalDispatch.MRxCreate = MRxLocalCreate;
|
||
MRxLocalDispatch.MRxFlush = MRxLocalFlush;
|
||
MRxLocalDispatch.MRxQueryDirectory = MRxLocalQueryDirectory;
|
||
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = MRxLocalRead;
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = MRxLocalWrite;
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = MRxLocalLocks;
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = MRxLocalLocks;
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = MRxLocalLocks;
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCKALL] = MRxLocalLocks;
|
||
MRxLocalDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCKALLBYKEY] = MRxLocalLocks;
|
||
|
||
MRxLocalDispatch.MRxExtendForCache = MRxLocalExtendForCache;
|
||
MRxLocalDispatch.MRxCleanup = MRxLocalCleanup;
|
||
MRxLocalDispatch.MRxClose = MRxLocalClose;
|
||
MRxLocalDispatch.MRxForceClosed = MRxLocalForceClosed;
|
||
|
||
MRxLocalDispatch.MRxQueryVolumeInfo = MRxLocalQueryVolumeInformation;
|
||
//MRxLocalDispatch.MRxSetVolumeInfo = MRxLocalSetVolumeInformation;
|
||
MRxLocalDispatch.MRxQueryFileInfo = MRxLocalQueryFileInformation;
|
||
MRxLocalDispatch.MRxSetFileInfo = MRxLocalSetFileInformation;
|
||
MRxLocalDispatch.MRxSetFileInfoAtCleanup = MRxLocalSetFileInfoAtCleanup;
|
||
|
||
MRxLocalDispatch.MRxAssertBufferedFileLocks = MRxLocalAssertBufferedFileLocks;
|
||
|
||
MRxLocalDispatch.MRxCreateNetRoot = MRxLocalCreateNetRoot;
|
||
MRxLocalDispatch.MRxCreateSrvCall = MRxLocalCreateSrvCall;
|
||
MRxLocalDispatch.MRxSrvCallWinnerNotify = MRxLocalSrvCallWinnerNotify;
|
||
|
||
MRxLocalDispatch.MRxTransportUpdateHandler = NULL;
|
||
|
||
return(RxStatus(SUCCESS));
|
||
}
|
||
|
||
|
||
////
|
||
//// The local debug trace level
|
||
////
|
||
//
|
||
//#undef Dbg
|
||
//#define Dbg (DEBUG_TRACE_CREATE)
|
||
|
||
RXSTATUS MRxLocalCreateNetRoot(
|
||
IN PRX_CONTEXT RxContext,
|
||
IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine looks for a device that it can setup as a local netroot.
|
||
we can touch any field except the condition. any name that is not exactly
|
||
one character long will fail.
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the context of the original create/ioctl
|
||
|
||
CallBack - a routine that we call when we're finished. if we returned
|
||
pending, we would have to get to a thread to call. of course,
|
||
we would have had to mark pending as well.
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
RXSTATUS Status;
|
||
PNET_ROOT NetRoot = RxContext->Create.NetRoot;
|
||
RxCaptureRequestPacket;
|
||
RxCaptureParamBlock;
|
||
UNICODE_STRING MyInnerPrefix;
|
||
PUNICODE_STRING NetRootName,SrvCallName;
|
||
WCHAR c;
|
||
ULONG Length,PoolAllocSize;
|
||
|
||
ASSERT( NodeType(NetRoot) == RDBSS_NTC_NETROOT );
|
||
ASSERT( NodeType(NetRoot->SrvCall) == RDBSS_NTC_SRVCALL );
|
||
|
||
NetRootName = &NetRoot->PrefixEntry.Prefix;
|
||
SrvCallName = &NetRoot->SrvCall->PrefixEntry.Prefix;
|
||
|
||
Length = NetRootName->Length - SrvCallName->Length;
|
||
c = NetRootName->Buffer[(NetRootName->Length/sizeof(WCHAR))-1];
|
||
|
||
RxDbgTrace(0, Dbg, ("MRxLocalCreateNetRoot %wZ, length,c=%08lx<%02x>\n", NetRootName, Length, c));
|
||
|
||
PoolAllocSize = sizeof(L"\\dosdevices\\d:")-sizeof(WCHAR);
|
||
|
||
if ( (Length == 4) &&
|
||
(MyInnerPrefix.Buffer = RxAllocatePoolWithTag(NonPagedPool,PoolAllocSize,'pixR'))
|
||
) {
|
||
MyInnerPrefix.Length = 0;
|
||
MyInnerPrefix.MaximumLength = (USHORT)PoolAllocSize;
|
||
RtlAppendUnicodeToString(&MyInnerPrefix,L"\\dosdevices\\d:");
|
||
MyInnerPrefix.Buffer[(MyInnerPrefix.Length/sizeof(WCHAR))-2] = (WCHAR)c;
|
||
RxDbgTrace(0, Dbg, ("MRxLocalCreateNetRoot InnerPrefix=%wZ,buf=%08lx\n", &MyInnerPrefix, MyInnerPrefix.Buffer));
|
||
RxFinishNetRootInitialization(NetRoot,&MRxLocalDispatch,
|
||
&MyInnerPrefix,
|
||
sizeof(FCB),sizeof(MRX_LOCAL_SRV_OPEN),sizeof(FOBX),
|
||
NETROOT_FLAG_DEVICE_NETROOT|NETROOT_FLAG_EXTERNAL_INNERNAMEPREFIX
|
||
);
|
||
NetRoot->DeviceType = RxDeviceType(DISK);
|
||
pCreateNetRootContext->Condition = Condition_Good;
|
||
pCreateNetRootContext->Callback(RxContext,pCreateNetRootContext);
|
||
} else {
|
||
pCreateNetRootContext->Condition = Condition_Bad;
|
||
pCreateNetRootContext->Callback(RxContext,pCreateNetRootContext);
|
||
}
|
||
|
||
return STATUS_PENDING;
|
||
}
|
||
|
||
RXSTATUS
|
||
MRxLocalCreateSrvCall(
|
||
IN PRX_CONTEXT RxContext,
|
||
IN OUT PMRX_SRVCALL_CALLBACK_CONTEXT SrvCallCallBackContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine looks for at the srvcall and determines if it can make a srvcall.
|
||
of course, for the local case we can always have a call; so, we just look to see
|
||
if the name is of the form \rx$$<z> for some Z. if it is, then we return success;
|
||
otherwise failure.
|
||
|
||
the rxcontext could refer either to a IoCtl (from the MUP) or an Open
|
||
|
||
A real rdr could look for a netroot as well......
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the context of the original create/ioctl
|
||
|
||
CallBack - a routine that we call when we're finished. if we returned
|
||
pending, we would have to get to a thread to call. of course,
|
||
we would have had to mark pending as well.
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
RXSTATUS Status;
|
||
PSRV_CALL SrvCall = RxContext->Create.SrvCall;
|
||
PNET_ROOT NetRoot = RxContext->Create.NetRoot;
|
||
RxCaptureRequestPacket;
|
||
RxCaptureParamBlock;
|
||
//UNICODE_STRING MyInnerPrefix;
|
||
PUNICODE_STRING NetRootName,SrvCallName;
|
||
ULONG Length;
|
||
PWCH Buffer;
|
||
PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = SrvCallCallBackContext;
|
||
PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(SCCBC->SrvCalldownStructure);
|
||
KIRQL SavedIrql;
|
||
|
||
if (SrvCall != NULL) {
|
||
ASSERT( NodeType(SrvCall) == RDBSS_NTC_SRVCALL );
|
||
ASSERT( !NetRoot || NodeType(NetRoot) == RDBSS_NTC_NETROOT );
|
||
|
||
SrvCallName = &SrvCall->PrefixEntry.Prefix;
|
||
|
||
Length = SrvCallName->Length;
|
||
Buffer = SrvCallName->Buffer;
|
||
|
||
RxDbgTrace(0, Dbg, ("MrxLocalCreateSrvCall %wZ, length=%08lx\n", SrvCallName, Length));
|
||
|
||
if ( (Length >= 5)
|
||
&& ( (Buffer[1] == L'R') || (Buffer[1] == L'r') )
|
||
&& ( (Buffer[2] == L'X') || (Buffer[2] == L'x') )
|
||
&& ( (Buffer[3] == L'$') )
|
||
&& ( (Buffer[4] == L'$') )
|
||
) {
|
||
SCCBC->Status = RxStatus(SUCCESS);
|
||
} else {
|
||
SCCBC->Status = RxStatus(BAD_NETWORK_PATH);
|
||
}
|
||
} else {
|
||
SCCBC->Status = RxStatus(BAD_NETWORK_PATH);
|
||
}
|
||
|
||
KeAcquireSpinLock( SrvCalldownStructure->SpinLock, &SavedIrql );
|
||
SrvCalldownStructure->CallBack(SCCBC);
|
||
KeReleaseSpinLock( SrvCalldownStructure->SpinLock, SavedIrql );
|
||
return SCCBC->Status; //actually the return value is ignored
|
||
}
|
||
|
||
|
||
|
||
RXSTATUS
|
||
MRxLocalSrvCallWinnerNotify(
|
||
IN PRX_CONTEXT RxContext,
|
||
IN BOOLEAN ThisMinirdrIsTheWinner,
|
||
IN OUT PVOID DisconnectAfterLosingContext,
|
||
IN PVOID MinirdrContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the context of the original create/ioctl
|
||
|
||
CallBack - a routine that we call when we're finished. if we returned
|
||
pending, we would have to get to a thread to call. of course,
|
||
we would have had to mark pending as well.
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
RXSTATUS Status;
|
||
PSRV_CALL SrvCall = RxContext->Create.SrvCall;
|
||
PNET_ROOT NetRoot = RxContext->Create.NetRoot;
|
||
//RxCaptureRequestPacket;
|
||
//RxCaptureParamBlock;
|
||
//UNICODE_STRING MyInnerPrefix;
|
||
PUNICODE_STRING SrvCallName;
|
||
//ULONG Length,PoolAllocSize;
|
||
|
||
ASSERT( NodeType(NetRoot->SrvCall) == RDBSS_NTC_SRVCALL );
|
||
ASSERT( !NetRoot || NodeType(NetRoot) == RDBSS_NTC_NETROOT );
|
||
|
||
SrvCallName = &SrvCall->PrefixEntry.Prefix;
|
||
|
||
RxDbgTrace(0, Dbg, (" MRxLocalSrvCallWinnerNotify localmini wins %wZ\n", SrvCallName));
|
||
|
||
SrvCall->Dispatch = &MRxLocalDispatch;
|
||
|
||
// transition only the srvcall.....it'll come back for the netroot
|
||
if (NetRoot) RxTransitionNetRoot(NetRoot,Condition_Bad);
|
||
RxTransitionSrvCall(SrvCall,Condition_Good);
|
||
|
||
return(RxStatus(SUCCESS));
|
||
}
|
||
|
||
|
||
|
||
|