Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

353 lines
8.4 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
devfcb.c
Abstract:
This module implements all the passthru stuff from the wrapper. currently there is only one such
functions:
statistics
Revision History:
Balan Sethu Raman [SethuR] 16-July-1995
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
#include "fsctlbuf.h"
//
// The local trace mask for this part of the module
//
#define Dbg (DEBUG_TRACE_DEVFCB)
typedef enum _MRXPROXY_STATE_ {
MRXPROXY_STARTABLE,
MRXPROXY_START_IN_PROGRESS,
MRXPROXY_STARTED
} MRXPROXY_STATE,*PMRXPROXY_STATE;
MRXPROXY_STATE MRxProxyState = MRXPROXY_STARTABLE;
NTSTATUS
MRxProxyTestDevIoctl(
IN PRX_CONTEXT RxContext
);
NTSTATUS
MRxProxyExternalStart (
IN PRX_CONTEXT RxContext
);
NTSTATUS
MRxProxySetupClaimedServerList(
IN PRX_CONTEXT RxContext
);
VOID
MRxProxyDereferenceClaimedServers(void);
NTSTATUS
MRxProxyDevFcbXXXControlFile (
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine handles all the device FCB related FSCTL's in the mini rdr
Arguments:
RxContext - Describes the Fsctl and Context.
Return Value:
RxStatus(SUCCESS) -- the Startup sequence was successfully completed.
any other value indicates the appropriate error in the startup sequence.
Notes:
--*/
{
NTSTATUS Status;
RxCaptureFobx;
UCHAR MajorFunctionCode = RxContext->MajorFunction;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
ULONG ControlCode = LowIoContext->ParamsFor.FsCtl.FsControlCode;
RxDbgTrace(+1, Dbg, ("MRxProxyDevFcb\n"));
switch (MajorFunctionCode) {
case IRP_MJ_FILE_SYSTEM_CONTROL: {
switch (LowIoContext->ParamsFor.FsCtl.MinorFunction) {
case IRP_MN_USER_FS_REQUEST:
switch (ControlCode) {
case FSCTL_PROXY_START:
ASSERT (!capFobx);
Status = MRxProxyExternalStart( RxContext );
break;
case FSCTL_PROXY_STOP:
ASSERT (!capFobx);
MRxProxyDereferenceClaimedServers();
Status = RxStopMinirdr( RxContext, &RxContext->PostRequest );
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
break;
default : //minor function != IRP_MN_USER_FS_REQUEST
Status = STATUS_INVALID_DEVICE_REQUEST;
} // end of switch
} // end of FSCTL case
break;
case IRP_MJ_DEVICE_CONTROL:
case IRP_MJ_INTERNAL_DEVICE_CONTROL: {
switch (ControlCode) {
#if DBG
case IOCTL_LMMR_TEST:
Status = MRxProxyTestDevIoctl(RxContext);
break;
#endif //if DBG
default :
Status = STATUS_INVALID_DEVICE_REQUEST;
} // end of switch
} //end of IOCTL cases
break;
default:
ASSERT(!"unimplemented major function");
Status = STATUS_INVALID_DEVICE_REQUEST;
}
RxDbgTrace(-1, Dbg, ("MRxProxyDevFcb st,info=%08lx,%08lx\n",
Status,RxContext->InformationToReturn));
return(Status);
}
#if DBG
NTSTATUS
MRxProxyTestDevIoctl(
IN PRX_CONTEXT RxContext
)
{
NTSTATUS Status = STATUS_SUCCESS;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
PSZ InputString = LowIoContext->ParamsFor.FsCtl.pInputBuffer;
PSZ OutputString = LowIoContext->ParamsFor.FsCtl.pOutputBuffer;
ULONG OutputBufferLength = LowIoContext->ParamsFor.FsCtl.OutputBufferLength;
ULONG InputBufferLength = LowIoContext->ParamsFor.FsCtl.InputBufferLength;
ULONG i;
//BUGBUG because this is a method neither, the buffers have not been probed. since this is debug
//only i am foregoing that currently. when we do more here...we'll have to probe.
RxDbgTrace(0, Dbg,("MRxProxyTestDevIoctl %s, obl = %08lx\n",InputString, OutputBufferLength));
RxContext->InformationToReturn = (InputBufferLength-1)*(InputBufferLength-1);
for (i=0;i<InputBufferLength;i++) {
UCHAR c = InputString[i];
if (c==0) { break; }
OutputString[i] = c;
if ((i&3)==2) {
OutputString[i] = '@';
}
}
OutputString[i] = 0;
return(Status);
}
#endif //if DBG
NTSTATUS
MRxProxyExternalStart (
IN PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine starts up the proxy minirdr if it hasn't been started already.
Arguments:
RxContext - Describes the Fsctl and Context.
Return Value:
STATUS_SUCCESS -- the Startup sequence was successfully completed.
any other value indicates the appropriate error in the startup sequence.
--*/
{
NTSTATUS Status;
BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
PAGED_CODE();
//DbgBreakPoint();
RxDbgTrace(0, Dbg, ("MRxProxyExternalStart [Start] -> %08lx\n", 0));
Status = RxStartMinirdr( RxContext, &RxContext->PostRequest );
if (Status == STATUS_SUCCESS) {
MRXPROXY_STATE State;
MRxProxySetupClaimedServerList(RxContext);
State = (MRXPROXY_STATE)InterlockedCompareExchange(
(PVOID *)&MRxProxyState,
(PVOID)MRXPROXY_STARTED,
(PVOID)MRXPROXY_START_IN_PROGRESS);
if (State != MRXPROXY_START_IN_PROGRESS) {
Status = STATUS_REDIRECTOR_STARTED;
}
}
return Status;
}
//CODE.IMPROVEMENT we should get this from the registry........
struct {
PWCHAR ServerName;
PSRV_CALL SrvCall;
ULONG Flags;
} MRxProxyClaimedServerList[] =
{
{MRXPROXY_CLAIMED_SERVERNAME_U,NULL,0},
NULL
};
NTSTATUS
MRxProxySetupClaimedServerList(
IN PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine claims servers for this module.
Arguments:
none
Return Value:
RXSTATUS - could return an error if an allocation fails or something
--*/
{
ULONG i;
PAGED_CODE();
RxAcquirePrefixTableLockExclusive( &RxNetNameTable, TRUE);
try {
for (i=0;MRxProxyClaimedServerList[i].ServerName!=NULL;i++) {
PWCHAR ServerNameText = MRxProxyClaimedServerList[i].ServerName;
ULONG Flags = MRxProxyClaimedServerList[i].Flags;
UNICODE_STRING SrvCallName,UnmatchedName;
PVOID Container = NULL;
PSRV_CALL SrvCall;
RtlInitUnicodeString(&SrvCallName,ServerNameText);
DbgPrint("CLAIMEDSERVER %wZ %08lx\n",&SrvCallName,Flags);
Container = RxPrefixTableLookupName( &RxNetNameTable, &SrvCallName, &UnmatchedName );
if (Container!=NULL) {
ASSERT ( NodeType(Container) == RDBSS_NTC_SRVCALL);
SrvCall = (PSRV_CALL)Container;
//this leaves a reference!
} else {
//here we have to create the srvcall
SrvCall = RxCreateSrvCall(RxContext,&SrvCallName,NULL);
if (SrvCall == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
RxReferenceSrvCall(SrvCall);
//leave this reference
}
SrvCall->Flags |= Flags;
SrvCall->RxDeviceObject = &MRxProxyDeviceObject->RxDeviceObject;
if (FlagOn(SrvCall->Flags,SRVCALL_FLAG_NO_CONNECTION_ALLOWED)) {
SrvCall->Condition = Condition_Bad;
} else {
SrvCall->Condition = Condition_Good;
}
MRxProxyClaimedServerList[i].SrvCall = SrvCall; //remember this for later
}
} finally {
RxReleasePrefixTableLock( &RxNetNameTable );
}
return(STATUS_SUCCESS);
}
VOID
MRxProxyDereferenceClaimedServers(
void
)
/*++
Routine Description:
This routine tears down the list of claimed servers.
it does this by just removing a reference; this will make the servers
eligible for finalization in finalizenettable.
Arguments:
none
Return Value:
none
--*/
{
ULONG i;
LOCK_HOLDING_STATE LockHoldingState = LHS_LockNotHeld;
PAGED_CODE();
for (i=0;MRxProxyClaimedServerList[i].ServerName!=NULL;i++) {
PSRV_CALL SrvCall = MRxProxyClaimedServerList[i].SrvCall;
if (SrvCall != NULL) {
DbgPrint("Claimed Srvcall deref %wZ\n",&SrvCall->PrefixEntry.Prefix);
MRxProxyClaimedServerList[i].SrvCall = NULL;
RxDereferenceSrvCall(SrvCall,LockHoldingState);
}
}
}