MegaBites-AI/Windows-powershell
0372
1using System;2using System.Collections.Generic;3using System.IO;4using System.Linq;5using System.Reflection;6using System.Runtime.InteropServices;7using System.Runtime.Loader;8using System.Management.Automation;9using Xunit;10 11using Microsoft.CodeAnalysis;12using Microsoft.CodeAnalysis.CSharp;13using Microsoft.CodeAnalysis.Emit;14using Microsoft.CodeAnalysis.Text;15 16namespace PSTests.Sequential17{18 public static class NativeInterop19 {20 [Fact]21 public static void TestLoadNativeInMemoryAssembly()22 {23 string tempDir = Path.Combine(Path.GetTempPath(), "TestLoadNativeInMemoryAssembly");24 string testDll = Path.Combine(tempDir, "test.dll");25 26 if (!File.Exists(testDll))27 {28 Directory.CreateDirectory(tempDir);29 bool result = CreateTestDll(testDll);30 Assert.True(result, "The call to 'CreateTestDll' should be successful and return true.");31 Assert.True(File.Exists(testDll), "The test assembly should be created.");32 }33 34 var asmName = AssemblyName.GetAssemblyName(testDll);35 string asmFullName = SearchAssembly(asmName.Name);36 Assert.Null(asmFullName);37 38 unsafe39 {40 int ret = LoadAssemblyTest(testDll);41 Assert.Equal(0, ret);42 }43 44 asmFullName = SearchAssembly(asmName.Name);45 Assert.Equal(asmName.FullName, asmFullName);46 }47 48 private static unsafe int LoadAssemblyTest(string assemblyPath)49 {50 // The 'LoadAssemblyFromNativeMemory' method is annotated with 'UnmanagedCallersOnly' attribute,51 // so we have to use the 'unmanaged' function pointer to invoke it.52 delegate* unmanaged<IntPtr, int, int> funcPtr = &PowerShellUnsafeAssemblyLoad.LoadAssemblyFromNativeMemory;53 54 int length = 0;55 IntPtr nativeMem = IntPtr.Zero;56 57 try58 {59 using (var fileStream = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read))60 {61 length = (int)fileStream.Length;62 nativeMem = Marshal.AllocHGlobal(length);63 64 using var unmanagedStream = new UnmanagedMemoryStream((byte*)nativeMem, length, length, FileAccess.Write);65 fileStream.CopyTo(unmanagedStream);66 }67 68 // Call the function pointer.69 return funcPtr(nativeMem, length);70 }71 finally72 {73 // Free the native memory74 Marshal.FreeHGlobal(nativeMem);75 }76 }77 78 private static string SearchAssembly(string assemblyName)79 {80 Assembly asm = AssemblyLoadContext.Default.Assemblies.FirstOrDefault(81 assembly => assembly.FullName.StartsWith(assemblyName, StringComparison.OrdinalIgnoreCase));82 83 return asm?.FullName;84 }85 86 private static bool CreateTestDll(string dllPath)87 {88 var parseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest);89 var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);90 91 List<SyntaxTree> syntaxTrees = new();92 SourceText sourceText = SourceText.From("public class Utt { }");93 syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText, parseOptions));94 95 var refs = new List<PortableExecutableReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) };96 Compilation compilation = CSharpCompilation.Create(97 Path.GetRandomFileName(),98 syntaxTrees: syntaxTrees,99 references: refs,100 options: compilationOptions);101 102 using var fs = new FileStream(dllPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);103 EmitResult emitResult = compilation.Emit(peStream: fs, options: null);104 return emitResult.Success;105 }106 }107}108 