Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Interop / InternalDispatchObject.cs / 1305600 / InternalDispatchObject.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // // Description: // InternalDispatchObject facilitates implementing a COM dispinterface using a non-public // corresponding managed interface definition (of type ComInterfaceType.InterfaceIsIDispatch). // (For example, we use this to implement DWebBrowserEvents2 without making it a public interface // type in the framework.) // // If a public managed interface definition is available, CLR's built-in implementation of // IDispatch suffices. It maps IDispatch calls to Reflection calls. But reflecting on non-public // members causes a demand for ReflectionPermission/MemberAccess against the caller of the // Reflection API. In a partial-trust AppDomain, and oddly only with some particular transitions // between managed-native-managed stack frames, this demand fails. Given that this occurs with // substantially equivalent callstacks in terms of CAS (Asserts) and managed<->native transitions, // there is probably an obscure CLR bug somewhere at the intersection of its IDispatch // implementation, Reflection and CAS. And there seems to be no explicit suggestion in // documentation that this scenario is supported in the first place. // // By implementing IReflect, any object can provide its own reflection implementation. And it // turns out CLR's IDispatch "front end" will happily use such an implementation. We don't need // to explicitly assert any ReflectionPermission in this arrangement as long as we are targeting // an internally visible interface type. (The built-in reflection system performs the equivalent // of a LinkDemand against the caller of the reflection API.) This, however, creates a potentially // dangerous security situation. // // CAUTION!!! Do not expose any InternalDispatchObject-derived object instance to untrusted code, // unless the implementation of the dispinterface is entirely safe. Such objects should be // passed only to native code, to be invoked via IDispatch. // // Because IReflect is a public interface and has no (link)demands on it and because // InternalDispatchObject's internal invocation of relection satisfies the reflection system's // ReflectionPermission demand, the implementaiton of the given dispinterface effectively // becomes publicly accessible. (Putting a LinkDemand on InternalDispatchObject.InvokeMember() // would have no effect because it can be called via IReflect, and LinkDemands are evaluated // based on static type info. And putting a full Demand would defeat the whole purpose of // InternalDispatchObject.) // // History // 04/30/08 - [....] - Created // //----------------------------------------------------------------------------- using System; using System.Security; using System.Reflection; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Globalization; namespace MS.Internal.Interop { ////// InternalDispatchObject-derived objects are potentially unsafe to expose to untrusted code. /// The IDispInterface implementation members should be treated as publicly accessible. /// internal abstract class InternalDispatchObject: IReflect { /// /// DISPID->MethodInfo map used by InvokeMember() /// private Dictionary_dispId2MethodMap; /// /// Critical - to help ensure whoever creates an instance of this class doesn't expose it. /// [SecurityCritical] protected InternalDispatchObject() { // Populate _dispId2MethodMap with the MethodInfos for the interface, keyed by DISPID. // There is no support for properties (yet). MethodInfo[] methods = typeof(IDispInterface).GetMethods(); _dispId2MethodMap = new Dictionary(methods.Length); foreach (MethodInfo method in methods) { int dispid = ((DispIdAttribute[])method.GetCustomAttributes(typeof(DispIdAttribute), false))[0].Value; _dispId2MethodMap[dispid] = method; } } FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) { return null; } MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) { throw new NotImplementedException(); } MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) { throw new NotImplementedException(); } MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) { // It doesn't help to return typeof(IDispInterface).GetMethods(), because the CLR's IDispatch layer // ignores non-visible MethodInfos (DispatchInfo::SynchWithManagedView(), in clr\src\VM\DispatchInfo.cpp). // For all "unknown" DISPIDs, IReflect.InvokeMember() is passed a method name like "[DISPID= ]", // which we parse. return null; } PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) { return null; } PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { throw new NotImplementedException(); } PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } /// /// Critical: Performs Reflection against a non-public type. /// NOT PublicOK! This method is intrinsically unsafe. Because it can be called via the public IReflect, /// instances of this class should not be exposed to untrusted code. (Full explanation above.) /// [SecurityCritical] object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) { // We never expect to get a real method name here--see the explanation in GetMethods(). if (name.StartsWith("[DISPID=", StringComparison.OrdinalIgnoreCase)) { int dispid = int.Parse(name.Substring(8, name.Length-9), CultureInfo.InvariantCulture); MethodInfo method; if (_dispId2MethodMap.TryGetValue(dispid, out method)) { return method.Invoke(this, invokeAttr, binder, args, culture); } } // This exception can be thrown if IDispInterface doesn't declare a method with a particular DISPID, // but the real COM interface has it and the event source is trying to invoke it. For a call coming via // the native IDispatch, such an error is usually ignorable. throw new MissingMethodException(GetType().Name, name); //return typeof(IDispInterface).InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters); } Type IReflect.UnderlyingSystemType { get { return typeof(IDispInterface); } } }; }//namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // // Description: // InternalDispatchObject facilitates implementing a COM dispinterface using a non-public // corresponding managed interface definition (of type ComInterfaceType.InterfaceIsIDispatch). // (For example, we use this to implement DWebBrowserEvents2 without making it a public interface // type in the framework.) // // If a public managed interface definition is available, CLR's built-in implementation of // IDispatch suffices. It maps IDispatch calls to Reflection calls. But reflecting on non-public // members causes a demand for ReflectionPermission/MemberAccess against the caller of the // Reflection API. In a partial-trust AppDomain, and oddly only with some particular transitions // between managed-native-managed stack frames, this demand fails. Given that this occurs with // substantially equivalent callstacks in terms of CAS (Asserts) and managed<->native transitions, // there is probably an obscure CLR bug somewhere at the intersection of its IDispatch // implementation, Reflection and CAS. And there seems to be no explicit suggestion in // documentation that this scenario is supported in the first place. // // By implementing IReflect, any object can provide its own reflection implementation. And it // turns out CLR's IDispatch "front end" will happily use such an implementation. We don't need // to explicitly assert any ReflectionPermission in this arrangement as long as we are targeting // an internally visible interface type. (The built-in reflection system performs the equivalent // of a LinkDemand against the caller of the reflection API.) This, however, creates a potentially // dangerous security situation. // // CAUTION!!! Do not expose any InternalDispatchObject-derived object instance to untrusted code, // unless the implementation of the dispinterface is entirely safe. Such objects should be // passed only to native code, to be invoked via IDispatch. // // Because IReflect is a public interface and has no (link)demands on it and because // InternalDispatchObject's internal invocation of relection satisfies the reflection system's // ReflectionPermission demand, the implementaiton of the given dispinterface effectively // becomes publicly accessible. (Putting a LinkDemand on InternalDispatchObject.InvokeMember() // would have no effect because it can be called via IReflect, and LinkDemands are evaluated // based on static type info. And putting a full Demand would defeat the whole purpose of // InternalDispatchObject.) // // History // 04/30/08 - [....] - Created // //----------------------------------------------------------------------------- using System; using System.Security; using System.Reflection; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Globalization; namespace MS.Internal.Interop { ////// InternalDispatchObject-derived objects are potentially unsafe to expose to untrusted code. /// The IDispInterface implementation members should be treated as publicly accessible. /// internal abstract class InternalDispatchObject: IReflect { /// /// DISPID->MethodInfo map used by InvokeMember() /// private Dictionary_dispId2MethodMap; /// /// Critical - to help ensure whoever creates an instance of this class doesn't expose it. /// [SecurityCritical] protected InternalDispatchObject() { // Populate _dispId2MethodMap with the MethodInfos for the interface, keyed by DISPID. // There is no support for properties (yet). MethodInfo[] methods = typeof(IDispInterface).GetMethods(); _dispId2MethodMap = new Dictionary(methods.Length); foreach (MethodInfo method in methods) { int dispid = ((DispIdAttribute[])method.GetCustomAttributes(typeof(DispIdAttribute), false))[0].Value; _dispId2MethodMap[dispid] = method; } } FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) { return null; } MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) { throw new NotImplementedException(); } MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) { throw new NotImplementedException(); } MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) { // It doesn't help to return typeof(IDispInterface).GetMethods(), because the CLR's IDispatch layer // ignores non-visible MethodInfos (DispatchInfo::SynchWithManagedView(), in clr\src\VM\DispatchInfo.cpp). // For all "unknown" DISPIDs, IReflect.InvokeMember() is passed a method name like "[DISPID= ]", // which we parse. return null; } PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) { return null; } PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { throw new NotImplementedException(); } PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } /// /// Critical: Performs Reflection against a non-public type. /// NOT PublicOK! This method is intrinsically unsafe. Because it can be called via the public IReflect, /// instances of this class should not be exposed to untrusted code. (Full explanation above.) /// [SecurityCritical] object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) { // We never expect to get a real method name here--see the explanation in GetMethods(). if (name.StartsWith("[DISPID=", StringComparison.OrdinalIgnoreCase)) { int dispid = int.Parse(name.Substring(8, name.Length-9), CultureInfo.InvariantCulture); MethodInfo method; if (_dispId2MethodMap.TryGetValue(dispid, out method)) { return method.Invoke(this, invokeAttr, binder, args, culture); } } // This exception can be thrown if IDispInterface doesn't declare a method with a particular DISPID, // but the real COM interface has it and the event source is trying to invoke it. For a call coming via // the native IDispatch, such an error is usually ignorable. throw new MissingMethodException(GetType().Name, name); //return typeof(IDispInterface).InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters); } Type IReflect.UnderlyingSystemType { get { return typeof(IDispInterface); } } }; }//namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConvertBinder.cs
- DbProviderFactories.cs
- RijndaelManaged.cs
- wgx_commands.cs
- RichTextBox.cs
- KeyFrames.cs
- AuthorizationSection.cs
- Table.cs
- ModelUIElement3D.cs
- ListMarkerSourceInfo.cs
- XmlQueryRuntime.cs
- ProviderConnectionPointCollection.cs
- assemblycache.cs
- XmlText.cs
- _LazyAsyncResult.cs
- NetNamedPipeBindingCollectionElement.cs
- XmlNodeChangedEventManager.cs
- IntegerValidatorAttribute.cs
- ArraySet.cs
- versioninfo.cs
- DurationConverter.cs
- FacetDescriptionElement.cs
- SymbolType.cs
- TypeUtil.cs
- X509RawDataKeyIdentifierClause.cs
- DataGridViewAutoSizeColumnModeEventArgs.cs
- LocalTransaction.cs
- DataPager.cs
- ConnectionStringSettings.cs
- XslAstAnalyzer.cs
- FileSecurity.cs
- SafeRightsManagementSessionHandle.cs
- GPStream.cs
- ChannelProtectionRequirements.cs
- Guid.cs
- ReadOnlyHierarchicalDataSourceView.cs
- InternalReceiveMessage.cs
- Point3DAnimation.cs
- HtmlEmptyTagControlBuilder.cs
- AssemblyBuilder.cs
- UniqueSet.cs
- EventLogWatcher.cs
- TextInfo.cs
- EndpointConfigContainer.cs
- ControlBindingsCollection.cs
- KeyboardInputProviderAcquireFocusEventArgs.cs
- MapPathBasedVirtualPathProvider.cs
- Roles.cs
- ISessionStateStore.cs
- UdpChannelFactory.cs
- AddInSegmentDirectoryNotFoundException.cs
- DateTimeUtil.cs
- AlternateViewCollection.cs
- WinFormsUtils.cs
- LowerCaseStringConverter.cs
- ToolboxItemCollection.cs
- HttpApplicationStateWrapper.cs
- CaretElement.cs
- TextTreeUndoUnit.cs
- TemplateBindingExtension.cs
- MultiTargetingUtil.cs
- PartialClassGenerationTask.cs
- TypeBuilderInstantiation.cs
- ToolStripControlHost.cs
- XmlUtf8RawTextWriter.cs
- ResolveCompletedEventArgs.cs
- DiagnosticStrings.cs
- WindowsNonControl.cs
- DisposableCollectionWrapper.cs
- RtfFormatStack.cs
- XmlSchemaImport.cs
- WindowsSysHeader.cs
- ProviderConnectionPoint.cs
- SecurityListenerSettingsLifetimeManager.cs
- DataViewManagerListItemTypeDescriptor.cs
- BatchServiceHost.cs
- EntryWrittenEventArgs.cs
- ToolStripSplitStackLayout.cs
- TableStyle.cs
- FontWeightConverter.cs
- PackageFilter.cs
- ResXResourceSet.cs
- Animatable.cs
- TextSpanModifier.cs
- Condition.cs
- DesignerToolboxInfo.cs
- DtdParser.cs
- TimersDescriptionAttribute.cs
- HtmlListAdapter.cs
- PipelineModuleStepContainer.cs
- ColorConvertedBitmapExtension.cs
- PolyQuadraticBezierSegment.cs
- Label.cs
- BlurBitmapEffect.cs
- Bezier.cs
- AddingNewEventArgs.cs
- Document.cs
- SqlDataAdapter.cs
- LogSwitch.cs
- categoryentry.cs