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-1999 MattSmit 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-1999 MattSmit 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
- LowerCaseStringConverter.cs
- DataGridSortCommandEventArgs.cs
- DockingAttribute.cs
- ColumnMapVisitor.cs
- BinHexDecoder.cs
- TraceSource.cs
- EventMap.cs
- SafeLocalAllocation.cs
- SingleAnimationBase.cs
- RadioButtonFlatAdapter.cs
- _ProxyChain.cs
- TreePrinter.cs
- HandlerBase.cs
- PointAnimationClockResource.cs
- TypeUtil.cs
- GlyphCollection.cs
- Debug.cs
- WindowsComboBox.cs
- LockCookie.cs
- OverrideMode.cs
- CodeAssignStatement.cs
- _HeaderInfo.cs
- CompiledQuery.cs
- TreeViewAutomationPeer.cs
- ReverseInheritProperty.cs
- PerformanceCounterManager.cs
- Function.cs
- BooleanSwitch.cs
- ByteStack.cs
- DBDataPermissionAttribute.cs
- CallContext.cs
- CustomPopupPlacement.cs
- ToolCreatedEventArgs.cs
- PathParser.cs
- FontUnit.cs
- XmlBinaryReader.cs
- UnsafeNativeMethodsCLR.cs
- AttachedPropertyMethodSelector.cs
- ProcessThread.cs
- WebCategoryAttribute.cs
- PartialArray.cs
- WindowsFormsHost.cs
- FixedSOMFixedBlock.cs
- JsonReaderWriterFactory.cs
- XmlElementAttribute.cs
- ConfigXmlSignificantWhitespace.cs
- PriorityQueue.cs
- WindowsListViewSubItem.cs
- dbdatarecord.cs
- HelpKeywordAttribute.cs
- DoubleCollectionConverter.cs
- UserControl.cs
- DataGridGeneralPage.cs
- CounterCreationData.cs
- SQLGuidStorage.cs
- HtmlTernaryTree.cs
- EmptyQuery.cs
- QueryOutputWriter.cs
- FeatureSupport.cs
- CustomWebEventKey.cs
- DbMetaDataCollectionNames.cs
- DataGridViewRowEventArgs.cs
- CapabilitiesRule.cs
- GuidConverter.cs
- DataGridBoundColumn.cs
- BooleanExpr.cs
- SuppressMessageAttribute.cs
- LOSFormatter.cs
- ListMarkerSourceInfo.cs
- CharacterBufferReference.cs
- newinstructionaction.cs
- CheckBoxRenderer.cs
- ConnectionProviderAttribute.cs
- ThreadInterruptedException.cs
- WebRequest.cs
- ChooseAction.cs
- QueryResult.cs
- EncodingTable.cs
- Attribute.cs
- StylusPointProperty.cs
- AspNetHostingPermission.cs
- SystemFonts.cs
- CollectionViewSource.cs
- WebEventCodes.cs
- TableLayoutPanelDesigner.cs
- Geometry.cs
- ConfigurationErrorsException.cs
- TabPanel.cs
- NameValuePair.cs
- SymmetricSecurityBindingElement.cs
- ManagementBaseObject.cs
- PipeSecurity.cs
- FixedFindEngine.cs
- DesignerCommandAdapter.cs
- XmlChoiceIdentifierAttribute.cs
- PieceDirectory.cs
- TextBox.cs
- RootBrowserWindow.cs
- ValidationError.cs
- ExpanderAutomationPeer.cs