Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Runtime / Remoting / StackBuilderSink.cs / 3 / 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); // // *** 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 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 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 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; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SqlNotificationRequest.cs
- DataSourceGeneratorException.cs
- ThicknessAnimation.cs
- DrawingImage.cs
- BufferBuilder.cs
- QilStrConcatenator.cs
- RightsManagementEncryptionTransform.cs
- DiscoveryOperationContextExtension.cs
- ScrollChrome.cs
- StreamGeometryContext.cs
- SrgsOneOf.cs
- NumberFormatter.cs
- QueryNode.cs
- InvalidComObjectException.cs
- QuadraticBezierSegment.cs
- updatecommandorderer.cs
- BinarySerializer.cs
- BidirectionalDictionary.cs
- ToggleButton.cs
- ObjectConverter.cs
- TypeSystemHelpers.cs
- SplineKeyFrames.cs
- CompensationTokenData.cs
- Brush.cs
- TableCellCollection.cs
- SharedPerformanceCounter.cs
- ReflectionServiceProvider.cs
- IfAction.cs
- InternalTypeHelper.cs
- SqlRecordBuffer.cs
- PointLightBase.cs
- PanelStyle.cs
- EnumType.cs
- EntityDataSourceDesignerHelper.cs
- TextServicesHost.cs
- InternalControlCollection.cs
- ConfigurationStrings.cs
- DragEventArgs.cs
- MatrixStack.cs
- Rfc2898DeriveBytes.cs
- SqlCacheDependencySection.cs
- SafeHandle.cs
- TableItemProviderWrapper.cs
- ICollection.cs
- UrlAuthFailedErrorFormatter.cs
- ExtensionFile.cs
- StagingAreaInputItem.cs
- FieldNameLookup.cs
- UndirectedGraph.cs
- CultureInfo.cs
- SystemIcmpV4Statistics.cs
- JoinElimination.cs
- Vector3D.cs
- COM2PictureConverter.cs
- ConfigurationCollectionAttribute.cs
- Root.cs
- PaintValueEventArgs.cs
- NCryptSafeHandles.cs
- ParameterEditorUserControl.cs
- PageCopyCount.cs
- Cursors.cs
- PolyQuadraticBezierSegment.cs
- DateTimeConstantAttribute.cs
- MenuItemStyle.cs
- SoapFault.cs
- InfoCardBinaryReader.cs
- LogWriteRestartAreaAsyncResult.cs
- StatusBarItem.cs
- Thickness.cs
- LassoSelectionBehavior.cs
- DesignerProperties.cs
- SchemaComplexType.cs
- Pair.cs
- GPStream.cs
- CTreeGenerator.cs
- HtmlTernaryTree.cs
- altserialization.cs
- DataGridItem.cs
- X509SecurityTokenParameters.cs
- SynchronizationFilter.cs
- NamespaceCollection.cs
- LabelDesigner.cs
- DataPagerFieldCollection.cs
- HexParser.cs
- Matrix3DStack.cs
- DoubleAnimationUsingPath.cs
- SmiEventSink_DeferedProcessing.cs
- ListViewGroupConverter.cs
- DiscardableAttribute.cs
- PropertyKey.cs
- DesignBindingPropertyDescriptor.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- DataControlField.cs
- ValueProviderWrapper.cs
- BooleanKeyFrameCollection.cs
- ObjectItemNoOpAssemblyLoader.cs
- Speller.cs
- httpapplicationstate.cs
- X509Certificate2Collection.cs
- Compiler.cs