diff --git a/UIX/Microsoft/Iris/OS/ClrDllResource.cs b/UIX/Microsoft/Iris/OS/ClrDllResource.cs new file mode 100644 index 0000000..4664aa5 --- /dev/null +++ b/UIX/Microsoft/Iris/OS/ClrDllResource.cs @@ -0,0 +1,58 @@ +using Microsoft.Iris.Data; +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Microsoft.Iris.OS +{ + internal class ClrDllResource : Resource + { + private Assembly _assembly; + private string _identifier; + private GCHandle _handle; + private IntPtr _buffer; + private uint _length; + + internal ClrDllResource(string uri, Assembly assembly, string identifier) + : base(uri, true) + { + _assembly = assembly; + _identifier = identifier; + } + + public override string Identifier => _identifier; + + protected override void StartAcquisition(bool forceSynchronous) + { + string errorDetails = null; + if (_buffer == IntPtr.Zero) + { + try + { + var resName = _assembly.GetManifestResourceNames() + .First(s => s.EndsWith("." + _identifier, StringComparison.OrdinalIgnoreCase)); + + using System.IO.Stream fs = _assembly.GetManifestResourceStream(resName); + var data = new byte[fs.Length]; + fs.Read(data, 0, (int)fs.Length); + + _handle = GCHandle.Alloc(data, GCHandleType.Pinned); + _buffer = _handle.AddrOfPinnedObject(); + _length = (uint)data.LongLength; + } + catch + { + errorDetails = $"Resource not found: {ClrDllResources.Scheme}://{_assembly.Location}!{_identifier}"; + } + } + NotifyAcquisitionComplete(_buffer, _length, false, errorDetails); + } + + protected override void CancelAcquisition() + { + } + + public override string ToString() => _assembly.GetName().Name + "|" + _identifier.ToLowerInvariant(); + } +} diff --git a/UIX/Microsoft/Iris/OS/ClrDllResources.cs b/UIX/Microsoft/Iris/OS/ClrDllResources.cs new file mode 100644 index 0000000..3d08769 --- /dev/null +++ b/UIX/Microsoft/Iris/OS/ClrDllResources.cs @@ -0,0 +1,62 @@ +using Microsoft.Iris.Data; +using Microsoft.Iris.Library; +using Microsoft.Iris.Markup; +using Microsoft.Iris.Session; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Microsoft.Iris.OS +{ + internal class ClrDllResources : IResourceProvider + { + public const string Scheme = "clr-res"; + + private static ClrDllResources s_instance = new ClrDllResources(); + private Dictionary _shortNameToAssembly; + + private ClrDllResources() => _shortNameToAssembly = new Dictionary(InvariantString.OrdinalIgnoreCaseComparer); + + public static ClrDllResources Instance => s_instance; + + public Resource GetResource(string hierarchicalPart, string uri, bool forceSynchronous) + { + Resource resource = null; + DllResources.ParseResource(hierarchicalPart, out string host, out string identifier); + if (host != null) + { + Assembly assembly = GetAssembly(host); + if (assembly != null) + resource = new ClrDllResource(uri, assembly, identifier); + } + if (resource == null) + ErrorManager.ReportError($"Invalid resource uri: '{uri}'"); + return resource; + } + + public Assembly GetAssembly(string moduleName) + { + if (!_shortNameToAssembly.TryGetValue(moduleName, out Assembly a)) + { + AssemblyName name = null; + try + { + name = new AssemblyName(moduleName); + } + catch (COMException) + { + } + catch (IOException) + { + } + + if (name != null) + a = AssemblyLoadResult.FindAssembly(name, out _); + _shortNameToAssembly[moduleName] = a; + } + return a; + } + } +}