Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / Remoting / StackBuilderSink.cs / 2 / StackBuilderSink.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** File: StackBuilderSink.cs ** ** ** Purpose: Terminating sink which will build a stack and ** make a method call on an object ** ** ===========================================================*/ namespace System.Runtime.Remoting.Messaging { using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Metadata; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Principal; /* Assembly Access */ using System; using System.Globalization; [Serializable] internal class StackBuilderSink : IMessageSink { //+=========================================================== // // Method: Constructor, public // // Synopsis: Store server object // // History: 06-May-1999MattSmit Created //-=========================================================== public StackBuilderSink(MarshalByRefObject server) { _server = server; } public StackBuilderSink(Object server) { _server = server; if (_server==null) { _bStatic = true; } } public virtual IMessage SyncProcessMessage(IMessage msg) { return SyncProcessMessage(msg, 0, false); } internal virtual IMessage SyncProcessMessage(IMessage msg, int methodPtr, bool fExecuteInContext) { // Validate message here IMessage errMsg = InternalSink.ValidateMessage(msg); if (errMsg != null) { return errMsg; } IMethodCallMessage mcMsg = msg as IMethodCallMessage; IMessage retMessage; LogicalCallContext oldCallCtx = null; LogicalCallContext lcc = CallContext.GetLogicalCallContext(); object xADCall = lcc.GetData(CrossAppDomainSink.LCC_DATA_KEY); bool isCallContextSet = false; try { Object server = _server; BCLDebug.Assert((server!=null) == (!_bStatic), "Invalid state in stackbuilder sink?"); // validate the method base if necessary VerifyIsOkToCallMethod(server, mcMsg); // install call context onto the thread, holding onto // the one that is currently on the thread LogicalCallContext messageCallContext = null; if (mcMsg != null) { messageCallContext = mcMsg.LogicalCallContext; } else { messageCallContext = (LogicalCallContext)msg.Properties["__CallContext"]; } oldCallCtx = CallContext.SetLogicalCallContext(messageCallContext); isCallContextSet = true; messageCallContext.PropagateIncomingHeadersToCallContext(msg); PreserveThreadPrincipalIfNecessary(messageCallContext, oldCallCtx); // NOTE: target for dispatch will be NULL when the StackBuilderSink // is used for async delegates on static methods. // *** NOTE *** // Although we always pass _server to these calls in the EE, // when we execute using Message::Dispatch we are using TP as // the this-ptr ... (what the call site thinks is the this-ptr) // when we execute using StackBuilderSink::PrivatePM we use // _server as the this-ptr (which could be different if there // is interception for strictly MBR types in the same AD). // ************ if (IsOKToStackBlt(mcMsg, server) && ((Message)mcMsg).Dispatch(server, fExecuteInContext)) { //retMessage = StackBasedReturnMessage.GetObjectFromPool((Message)mcMsg); retMessage = new StackBasedReturnMessage(); ((StackBasedReturnMessage)retMessage).InitFields((Message)mcMsg); // call context could be different then the one from before the call. LogicalCallContext latestCallContext = CallContext.GetLogicalCallContext(); // retrieve outgoing response headers latestCallContext.PropagateOutgoingHeadersToMessage(retMessage); // Install call context back into Message (from the thread) ((StackBasedReturnMessage)retMessage).SetLogicalCallContext(latestCallContext); } else { MethodBase mb = GetMethodBase(mcMsg); Object[] outArgs = null; Object ret = null; RemotingMethodCachedData methodCache = InternalRemotingServices.GetReflectionCachedData(mb); Message.DebugOut("StackBuilderSink::Calling PrivateProcessMessage\n"); Object[] args = Message.CoerceArgs(mcMsg, methodCache.Parameters); ret = PrivateProcessMessage( mb.MethodHandle, args, server, methodPtr, fExecuteInContext, out outArgs); CopyNonByrefOutArgsFromOriginalArgs(methodCache, args, ref outArgs); // call context could be different then the one from before the call. LogicalCallContext latestCallContext = CallContext.GetLogicalCallContext(); if (xADCall != null && ((bool)xADCall) == true && latestCallContext != null) { // Special case Principal since if might not be serializable before returning // ReturnMessage latestCallContext.RemovePrincipalIfNotSerializable(); } retMessage = new ReturnMessage( ret, outArgs, (outArgs == null ? 0 : outArgs.Length), latestCallContext, mcMsg); // retrieve outgoing response headers latestCallContext.PropagateOutgoingHeadersToMessage(retMessage); // restore the call context on the thread CallContext.SetLogicalCallContext(oldCallCtx); } } catch (Exception e) { Message.DebugOut( "StackBuilderSink::The server object probably threw an exception " + e.Message + e.StackTrace + "\n" ); retMessage = new ReturnMessage(e, mcMsg); ((ReturnMessage)retMessage).SetLogicalCallContext(mcMsg.LogicalCallContext); if (isCallContextSet) CallContext.SetLogicalCallContext(oldCallCtx); } return retMessage; } public virtual IMessageCtrl AsyncProcessMessage( IMessage msg, IMessageSink replySink) { IMethodCallMessage mcMsg = (IMethodCallMessage)msg; IMessageCtrl retCtrl = null; IMessage retMessage = null; LogicalCallContext oldCallCtx = null; bool isCallContextSet = false; try{ try { LogicalCallContext callCtx = (LogicalCallContext) mcMsg.Properties[Message.CallContextKey]; Object server = _server; // validate the method base if necessary VerifyIsOkToCallMethod(server, mcMsg); // install call context onto the thread, holding onto // the one that is currently on the thread oldCallCtx = CallContext.SetLogicalCallContext(callCtx); isCallContextSet = true; // retrieve incoming headers callCtx.PropagateIncomingHeadersToCallContext(msg); PreserveThreadPrincipalIfNecessary(callCtx, oldCallCtx); // see if this is a server message that was dispatched asynchronously ServerChannelSinkStack sinkStack = msg.Properties["__SinkStack"] as ServerChannelSinkStack; if (sinkStack != null) sinkStack.ServerObject = server; BCLDebug.Assert((server!=null)==(!_bStatic), "Invalid state in stackbuilder sink?"); MethodBase mb = GetMethodBase(mcMsg); Object[] outArgs = null; Object ret = null; RemotingMethodCachedData methodCache = InternalRemotingServices.GetReflectionCachedData(mb); Object[] args = Message.CoerceArgs(mcMsg, methodCache.Parameters); ret = PrivateProcessMessage(mb.MethodHandle, args, server, 0, false, out outArgs); CopyNonByrefOutArgsFromOriginalArgs(methodCache, args, ref outArgs); if(replySink != null) { // call context could be different then the one from before the call. LogicalCallContext latestCallContext = CallContext.GetLogicalCallContext(); if (latestCallContext != null) { // Special case Principal since if might not be serializable before returning // ReturnMessage latestCallContext.RemovePrincipalIfNotSerializable(); } retMessage = new ReturnMessage( ret, outArgs, (outArgs == null ? 0 : outArgs.Length), latestCallContext, mcMsg); // retrieve outgoing response headers latestCallContext.PropagateOutgoingHeadersToMessage(retMessage); } } catch (Exception e) { if(replySink != null) { retMessage = new ReturnMessage(e, mcMsg); ((ReturnMessage)retMessage).SetLogicalCallContext( (LogicalCallContext) mcMsg.Properties[Message.CallContextKey]); } } finally { if (replySink != null) { // Call the reply sink without catching the exceptions // in it. In v2.0 any exceptions in the callback for example // would probably bring down the process replySink.SyncProcessMessage(retMessage); } } } finally { // restore the call context on the thread if (isCallContextSet) CallContext.SetLogicalCallContext(oldCallCtx); } return retCtrl; } // AsyncProcessMessage public IMessageSink NextSink { get { // there is no nextSink for the StackBuilderSink return null; } } // This check if the call-site on the TP is in our own AD // It also handles the special case where the TP is on // a well-known object and we cannot do stack-blting internal bool IsOKToStackBlt(IMethodMessage mcMsg, Object server) { bool bOK = false; Message msg = mcMsg as Message; if(null != msg) { IInternalMessage iiMsg = (IInternalMessage) msg; // If there is a frame in the message we can always // Blt it (provided it is not a proxy to a well-known // object in our own appDomain)! // The GetThisPtr == server test allows for people to wrap // our proxy with their own interception .. in that case // we should not blt the stack. if (msg.GetFramePtr() != IntPtr.Zero && msg.GetThisPtr() == server && ( iiMsg.IdentityObject == null || ( iiMsg.IdentityObject != null && iiMsg.IdentityObject == iiMsg.ServerIdentityObject ) ) ) { bOK = true; } } return bOK; } private static MethodBase GetMethodBase(IMethodMessage msg) { MethodBase mb = msg.MethodBase; if(null == mb) { BCLDebug.Trace("REMOTE", "Method missing w/name ", msg.MethodName); throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Message_MethodMissing"), msg.MethodName, msg.TypeName)); } return mb; } private static void VerifyIsOkToCallMethod(Object server, IMethodMessage msg) { bool bTypeChecked = false; MarshalByRefObject mbr = server as MarshalByRefObject; if (mbr != null) { bool fServer; Identity id = MarshalByRefObject.GetIdentity(mbr, out fServer); if (id != null) { ServerIdentity srvId = id as ServerIdentity; if ((srvId != null) && srvId.MarshaledAsSpecificType) { Type srvType = srvId.ServerType; if (srvType != null) { MethodBase mb = GetMethodBase(msg); Type declaringType = mb.DeclaringType; // make sure that srvType is not more restrictive than method base // (i.e. someone marshaled with a specific type or interface exposed) if ((declaringType != srvType) && !declaringType.IsAssignableFrom(srvType)) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_InvalidCallingType"), mb.DeclaringType.FullName, srvType.FullName)); } // Set flag so we don't repeat this work below. if (declaringType.IsInterface) { VerifyNotIRemoteDispatch(declaringType); } bTypeChecked = true; } } } // We must always verify that the type corresponding to // the method being invoked is compatible with the real server // type. if (!bTypeChecked) { MethodBase mb = GetMethodBase(msg); Type reflectedType = mb.ReflectedType; if (!reflectedType.IsInterface) { if (!reflectedType.IsInstanceOfType(mbr)) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_InvalidCallingType"), reflectedType.FullName, mbr.GetType().FullName)); } } // This code prohibits calls made to System.EnterpriseServices.IRemoteDispatch // so that remote call cannot bypass lowFilterLevel logic in the serializers. // This special casing should be removed in the future else { VerifyNotIRemoteDispatch(reflectedType); } } } } // VerifyIsOkToCallMethod // This code prohibits calls made to System.EnterpriseServices.IRemoteDispatch // so that remote call cannot bypass lowFilterLevel logic in the serializers. // This special casing should be removed in the future // Check whether we are calling IRemoteDispatch private static void VerifyNotIRemoteDispatch(Type reflectedType) { if(reflectedType.FullName.Equals(sIRemoteDispatch) && reflectedType.Module.Assembly.nGetSimpleName().Equals(sIRemoteDispatchAssembly)) { throw new RemotingException( Environment.GetResourceString("Remoting_CantInvokeIRemoteDispatch")); } } // copies references of non-byref [In, Out] args from the input args to // the output args array. internal void CopyNonByrefOutArgsFromOriginalArgs(RemotingMethodCachedData methodCache, Object[] args, ref Object[] marshalResponseArgs) { int[] map = methodCache.NonRefOutArgMap; if (map.Length > 0) { if (marshalResponseArgs == null) marshalResponseArgs = new Object[methodCache.Parameters.Length]; foreach (int pos in map) { marshalResponseArgs[pos] = args[pos]; } } } // For the incoming call, we sometimes need to preserve the thread principal from // the executing thread, instead of blindly bashing it with the one from the message. // For instance, in cross process calls, the principal will always be null // in the incoming message. However, when we are hosted in ASP.Net, ASP.Net will handle // authentication and set up the thread principal. We should dispatch the call // using the identity that it set up. internal static void PreserveThreadPrincipalIfNecessary( LogicalCallContext messageCallContext, LogicalCallContext threadCallContext) { BCLDebug.Assert(messageCallContext != null, "message should always have a call context"); if (threadCallContext != null) { if (messageCallContext.Principal == null) { IPrincipal currentPrincipal = threadCallContext.Principal; if (currentPrincipal != null) { messageCallContext.Principal = currentPrincipal; } } } } // PreserveThreadPrincipalIfNecessary internal Object ServerObject { get { return _server; } } //+=========================================================== // // Method: PrivateProcessMessage, public // // Synopsis: does the actual work of building the stack, // finding the correct code address and calling it. // // History: 06-May-1999MattSmit Created //-============================================================ [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Object _PrivateProcessMessage( IntPtr md, Object[] args, Object server, int methodPtr, bool fExecuteInContext, out Object[] outArgs); public Object PrivateProcessMessage( RuntimeMethodHandle md, Object[] args, Object server, int methodPtr, bool fExecuteInContext, out Object[] outArgs) { return _PrivateProcessMessage(md.Value, args, server, methodPtr, fExecuteInContext, out outArgs); } private Object _server; // target object private static string sIRemoteDispatch = "System.EnterpriseServices.IRemoteDispatch"; private static string sIRemoteDispatchAssembly = "System.EnterpriseServices"; bool _bStatic; } }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MsmqIntegrationSecurityMode.cs
- LabelLiteral.cs
- BitmapEffectInputConnector.cs
- StatusStrip.cs
- WorkflowApplicationException.cs
- WebEvents.cs
- FloaterParaClient.cs
- PassportIdentity.cs
- OracleSqlParser.cs
- Scene3D.cs
- ControlDesigner.cs
- recordstatefactory.cs
- HyperLink.cs
- ZoneLinkButton.cs
- Helpers.cs
- TdsParserSessionPool.cs
- SweepDirectionValidation.cs
- DescendantOverDescendantQuery.cs
- TemplateField.cs
- TimeEnumHelper.cs
- BooleanStorage.cs
- AccessDataSourceView.cs
- TextBounds.cs
- XmlCharCheckingWriter.cs
- WorkflowServiceAttributes.cs
- DataGridViewColumnHeaderCell.cs
- TaskFormBase.cs
- StagingAreaInputItem.cs
- UnionCodeGroup.cs
- CustomSignedXml.cs
- ObservableCollectionDefaultValueFactory.cs
- AlphabeticalEnumConverter.cs
- BooleanSwitch.cs
- StyleModeStack.cs
- ConfigurationValue.cs
- ScrollBar.cs
- DataGridTableCollection.cs
- VirtualizedContainerService.cs
- Exception.cs
- PerformanceCounterLib.cs
- TripleDESCryptoServiceProvider.cs
- BStrWrapper.cs
- DependencyProperty.cs
- ProtectedConfiguration.cs
- SymLanguageType.cs
- XamlReaderConstants.cs
- TreeView.cs
- HuffModule.cs
- CodeSnippetCompileUnit.cs
- DataSpaceManager.cs
- ByteConverter.cs
- CornerRadiusConverter.cs
- ContextProperty.cs
- IISMapPath.cs
- XmlAnyElementAttributes.cs
- SQLMoneyStorage.cs
- ObjectSerializerFactory.cs
- SqlUtils.cs
- ActivityExecutorOperation.cs
- ColorTransform.cs
- SafeRightsManagementEnvironmentHandle.cs
- filewebresponse.cs
- HostedBindingBehavior.cs
- ListControl.cs
- XamlPointCollectionSerializer.cs
- DPTypeDescriptorContext.cs
- EnvelopedPkcs7.cs
- __ComObject.cs
- ObjectDataProvider.cs
- ConfigurationManagerInternal.cs
- ConsumerConnectionPointCollection.cs
- ScriptRegistrationManager.cs
- ToolStripItemGlyph.cs
- TargetConverter.cs
- DataGridAddNewRow.cs
- CodeThrowExceptionStatement.cs
- LoginName.cs
- CTreeGenerator.cs
- WizardStepCollectionEditor.cs
- DataContractSerializerSection.cs
- Panel.cs
- BStrWrapper.cs
- CodeVariableDeclarationStatement.cs
- MaskedTextBoxDesignerActionList.cs
- Int32EqualityComparer.cs
- VsPropertyGrid.cs
- Types.cs
- PreservationFileWriter.cs
- ServiceDescriptionSerializer.cs
- ToolbarAUtomationPeer.cs
- OdbcReferenceCollection.cs
- EventDescriptorCollection.cs
- XmlSchemaCompilationSettings.cs
- ClipboardProcessor.cs
- datacache.cs
- ParserStreamGeometryContext.cs
- TdsValueSetter.cs
- MenuItemStyle.cs
- TypeUsage.cs
- StylusShape.cs