Exemple #1
0
        private static void LoadInMemoryAssemblyInContextImpl(IntPtr moduleHandle, IntPtr assemblyPath, AssemblyLoadContext?alc = null)
        {
            string?assemblyPathString = Marshal.PtrToStringUni(assemblyPath);

            if (assemblyPathString == null)
            {
                throw new ArgumentOutOfRangeException(nameof(assemblyPath));
            }

            // We don't cache the ALCs or resolvers here since each IJW assembly will call this method at most once
            // (the load process rewrites the stubs that call here to call the actual methods they're supposed to)
            if (alc is null)
            {
                alc = new IsolatedComponentLoadContext(assemblyPathString);
            }
            else if (alc == AssemblyLoadContext.Default)
            {
                var resolver = new AssemblyDependencyResolver(assemblyPathString);
                AssemblyLoadContext.Default.Resolving +=
                    [RequiresUnreferencedCode("C++/CLI is not trim-compatible", Url = "https://aka.ms/dotnet-illink/nativehost")]
                        (context, assemblyName) =>
                {
                    string?assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
                    return(assemblyPath != null
                            ? context.LoadFromAssemblyPath(assemblyPath)
                            : null);
                };
            }

            alc.LoadFromInMemoryModule(moduleHandle);
        }
        /// <summary>
        /// Loads into an isolated AssemblyLoadContext an assembly that has already been loaded into memory by the OS loader as a native module.
        /// </summary>
        /// <param name="moduleHandle">The native module handle for the assembly.</param>
        /// <param name="assemblyPath">The path to the assembly (as a pointer to a UTF-16 C string).</param>
        public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath)
        {
            // We don't cache the ALCs here since each IJW assembly will call this method at most once
            // (the load process rewrites the stubs that call here to call the actual methods they're supposed to)
            AssemblyLoadContext context = new IsolatedComponentLoadContext(Marshal.PtrToStringUni(assemblyPath));

            context.LoadFromInMemoryModule(moduleHandle);
        }
Exemple #3
0
        private static IsolatedComponentLoadContext GetIsolatedComponentLoadContext(string assemblyPath)
        {
            IsolatedComponentLoadContext?alc;

            lock (s_assemblyLoadContexts)
            {
                if (!s_assemblyLoadContexts.TryGetValue(assemblyPath, out alc))
                {
                    alc = new IsolatedComponentLoadContext(assemblyPath);
                    s_assemblyLoadContexts.Add(assemblyPath, alc);
                }
            }

            return(alc);
        }
Exemple #4
0
        public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath)
        {
            string?assemblyPathString = Marshal.PtrToStringUni(assemblyPath);

            if (assemblyPathString == null)
            {
                throw new ArgumentOutOfRangeException(nameof(assemblyPath));
            }

            // We don't cache the ALCs here since each IJW assembly will call this method at most once
            // (the load process rewrites the stubs that call here to call the actual methods they're supposed to)
            AssemblyLoadContext context = new IsolatedComponentLoadContext(assemblyPathString);

            context.LoadFromInMemoryModule(moduleHandle);
        }
Exemple #5
0
        private static Delegate CreateDelegate(string assemblyPath, string typeName, string methodName, string delegateTypeName)
        {
            // Throws
            IsolatedComponentLoadContext alc = GetIsolatedComponentLoadContext(assemblyPath);

            Func <AssemblyName, Assembly> resolver = name => alc.LoadFromAssemblyName(name);

            // Throws
            Type type = Type.GetType(typeName, resolver, null, throwOnError: true) !;

            // Throws
            Type delegateType = Type.GetType(delegateTypeName, resolver, null, throwOnError: true) !;

            // Throws
            return(Delegate.CreateDelegate(delegateType, type, methodName) !);
        }
        /// <summary>
        /// Loads into an isolated AssemblyLoadContext an assembly that has already been loaded into memory by the OS loader as a native module.
        /// </summary>
        /// <param name="moduleHandle">The native module handle for the assembly.</param>
        /// <param name="assemblyPath">The path to the assembly (as a pointer to a UTF-16 C string).</param>
        public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath)
        {
#if TARGET_WINDOWS
            if (!IsSupported)
            {
                throw new NotSupportedException("This API is not enabled in trimmed scenarios. see https://aka.ms/dotnet-illink/nativehost for more details");
            }

            string?assemblyPathString = Marshal.PtrToStringUni(assemblyPath);
            if (assemblyPathString == null)
            {
                throw new ArgumentOutOfRangeException(nameof(assemblyPath));
            }

            // We don't cache the ALCs here since each IJW assembly will call this method at most once
            // (the load process rewrites the stubs that call here to call the actual methods they're supposed to)
            AssemblyLoadContext context = new IsolatedComponentLoadContext(assemblyPathString);
            context.LoadFromInMemoryModule(moduleHandle);
#else
            throw new PlatformNotSupportedException();
#endif
        }
Exemple #7
0
        public static unsafe int LoadAssemblyAndGetFunctionPointer(IntPtr assemblyPathNative,
                                                                   IntPtr typeNameNative,
                                                                   IntPtr methodNameNative,
                                                                   IntPtr delegateTypeNative,
                                                                   IntPtr reserved,
                                                                   IntPtr functionHandle)
        {
            try
            {
                // Load the assembly and create a resolver callback for types.
                string assemblyPath = MarshalToString(assemblyPathNative, nameof(assemblyPathNative));
                IsolatedComponentLoadContext  alc      = GetIsolatedComponentLoadContext(assemblyPath);
                Func <AssemblyName, Assembly> resolver = name => alc.LoadFromAssemblyName(name);

                // Get the requested type.
                string typeName = MarshalToString(typeNameNative, nameof(typeNameNative));
                Type   type     = Type.GetType(typeName, resolver, null, throwOnError: true) !;

                // Get the method name on the type.
                string methodName = MarshalToString(methodNameNative, nameof(methodNameNative));

                // Determine the signature of the type. There are 3 possibilities:
                //  * No delegate type was supplied - use the default (i.e. ComponentEntryPoint).
                //  * A sentinel value was supplied - the function is marked UnmanagedCallersOnly. This means
                //      a function pointer can be returned without creating a delegate.
                //  * A delegate type was supplied - Load the type and create a delegate for that method.
                Type?delegateType;
                if (delegateTypeNative == IntPtr.Zero)
                {
                    delegateType = typeof(ComponentEntryPoint);
                }
                else if (delegateTypeNative == (IntPtr)(-1))
                {
                    delegateType = null;
                }
                else
                {
                    string delegateTypeName = MarshalToString(delegateTypeNative, nameof(delegateTypeNative));
                    delegateType = Type.GetType(delegateTypeName, resolver, null, throwOnError: true) !;
                }

                if (reserved != IntPtr.Zero)
                {
                    throw new ArgumentOutOfRangeException(nameof(reserved));
                }

                if (functionHandle == IntPtr.Zero)
                {
                    throw new ArgumentNullException(nameof(functionHandle));
                }

                IntPtr functionPtr;
                if (delegateType == null)
                {
                    // Match search semantics of the CreateDelegate() function below.
                    BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
                    MethodInfo?  methodInfo   = type.GetMethod(methodName, bindingFlags);
                    if (methodInfo == null)
                    {
                        throw new MissingMethodException(typeName, methodName);
                    }

                    // Verify the function is properly marked.
                    if (null == methodInfo.GetCustomAttribute <UnmanagedCallersOnlyAttribute>())
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_FunctionMissingUnmanagedCallersOnly);
                    }

                    functionPtr = methodInfo.MethodHandle.GetFunctionPointer();
                }
                else
                {
                    Delegate d = Delegate.CreateDelegate(delegateType, type, methodName) !;

                    functionPtr = Marshal.GetFunctionPointerForDelegate(d);

                    lock (s_delegates)
                    {
                        // Keep a reference to the delegate to prevent it from being garbage collected
                        s_delegates[functionPtr] = d;
                    }
                }

                *(IntPtr *)functionHandle = functionPtr;
            }
            catch (Exception e)
            {
                return(e.HResult);
            }

            return(0);
        }