/*++ 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;iFlags, 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); } } }