File: system\runtime\designerservices\windowsruntimedesignercontext.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
using System;
using System.Collections.Generic;
using System.Security;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Diagnostics.Contracts;
using StackCrawlMark = System.Threading.StackCrawlMark;
 
namespace System.Runtime.DesignerServices
{
#if !FEATURE_CORECLR
    // -------------------------
    // IMPORTANT!
    // The shared and designer context binders are ONLY to be used in tool
    // scenarios. There are known issues where use of these binders will
    // cause application crashes, and undefined behaviors.
    // -------------------------
    public sealed class WindowsRuntimeDesignerContext
    {
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SecurityCritical]
        [ResourceExposure(ResourceScope.AppDomain)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr CreateDesignerContext([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] paths, int count, bool shared);
 
        [SecurityCritical]
        internal static IntPtr CreateDesignerContext(IEnumerable<string> paths, [MarshalAs(UnmanagedType.Bool)] bool shared)
        {
            List<string> pathList = new List<string>(paths);
            string[] pathArray = pathList.ToArray();
            foreach (string path in pathArray)
            {
                // Each path has to be absolute path - check it
                if (path == null)
                {
                    throw new ArgumentNullException(Environment.GetResourceString("ArgumentNull_Path"));
                }
                if (System.IO.Path.IsRelative(path))
                {
                    throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"));
                }
            }
            return CreateDesignerContext(pathArray, pathArray.Length, shared);
        }
 
        // isDesignerContext = !shared
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SecurityCritical]
        [ResourceExposure(ResourceScope.AppDomain)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void SetCurrentContext([MarshalAs(UnmanagedType.Bool)] bool isDesignerContext, IntPtr context);
 
        private static object s_lock = new object();
        private static IntPtr s_sharedContext;
 
        private IntPtr m_contextObject;
        private string m_name;
 
        // This private constructor is called either by the public constructor or by the debugger via FuncEval.
        [SecurityCritical]
        private WindowsRuntimeDesignerContext(IEnumerable<string> paths, string name, bool designModeRequired)
        {
            if (name == null)
                throw new ArgumentNullException("name");
 
            if (paths == null)
                throw new ArgumentNullException("paths");
 
            // WindowsRuntimeDesignerContext is only supported in the default domain.
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
                throw new NotSupportedException();
 
            // WindowsRuntimeDesignerContext is only supported when running in AppX.
            if (!AppDomain.IsAppXModel())
                throw new NotSupportedException();
 
            // WindowsRuntimeDesignerContext is only supported when running in Designer Mode on in the debugger when called via funceval.
            // This is true when called via the public constructor,
            // but likely false when called directly by the debugger via FuncEval.
            if (designModeRequired && !AppDomain.IsAppXDesignMode())
                throw new NotSupportedException();
 
            m_name = name;
 
            lock (s_lock)
            {
                if (s_sharedContext == IntPtr.Zero)
                    InitializeSharedContext(new string[] {});
            }
 
            m_contextObject = CreateDesignerContext(paths, false);
        }
 
        // This is the public constructor that may be used when running in a process in DesignMode.
        [SecurityCritical]
        public WindowsRuntimeDesignerContext(IEnumerable<string> paths, string name)
            : this(paths, name, true)
        {}
 
        [SecurityCritical]
        public static void InitializeSharedContext(IEnumerable<string> paths)
        {
            // WindowsRuntimeDesignerContext is only supported in the default domain.
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
                throw new NotSupportedException();
 
            if (paths == null)
                throw new ArgumentNullException("paths");
 
            lock (s_lock)
            {
                if (s_sharedContext != IntPtr.Zero)
                    throw new NotSupportedException();
 
                IntPtr sharedContext = CreateDesignerContext(paths, true);
                SetCurrentContext(false, sharedContext);
                s_sharedContext = sharedContext;
            }
        }
 
        [SecurityCritical]
        public static void SetIterationContext(WindowsRuntimeDesignerContext context)
        {
            // WindowsRuntimeDesignerContext is only supported in the default domain.
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
                throw new NotSupportedException();
 
            if (context == null)
                throw new ArgumentNullException("context");
 
            lock (s_lock)
            {
                SetCurrentContext(true, context.m_contextObject);
            }
        }
 
        // Locate an assembly by the long form of the assembly name. 
        // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890"
        [SecurityCritical]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public Assembly GetAssembly(String assemblyName)
        {
            Contract.Ensures(Contract.Result<Assembly>() != null);
            Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RuntimeAssembly.InternalLoad(assemblyName, null, ref stackMark, m_contextObject, false /*forIntrospection*/);
        }
 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        [SecurityCritical]
        public Type GetType(String typeName)
        {
            if (typeName == null)
                throw new ArgumentNullException("typeName");
            Contract.EndContractBlock();
 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
 
            return RuntimeTypeHandle.GetTypeByName(
                typeName, false /*throwOnError*/, false /*ignoreCase*/, false /*reflectionOnly*/, ref stackMark, m_contextObject, false /*loadTypeFromPartialName*/);
        }
 
        public string Name
        {
            get
            {
                return m_name;
            }
        }
    }
#endif
}