90 lines
2.9 KiB
C#
90 lines
2.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace BizHawk.Common
|
|
{
|
|
public class InstanceDll : IDisposable, IImportResolver
|
|
{
|
|
[DllImport("kernel32.dll")]
|
|
public static extern UInt32 GetLastError();
|
|
|
|
public InstanceDll(string dllPath)
|
|
{
|
|
// copy the dll to a temp directory
|
|
var path = TempFileCleaner.GetTempFilename(string.Format("{0}", Path.GetFileNameWithoutExtension(dllPath)),".dll",false);
|
|
using (var stream = new FileStream(path, FileMode.Create, System.Security.AccessControl.FileSystemRights.FullControl, FileShare.ReadWrite | FileShare.Delete, 4 * 1024, FileOptions.None))
|
|
using (var sdll = File.OpenRead(dllPath))
|
|
sdll.CopyTo(stream);
|
|
|
|
// try to locate dlls in the current directory (for libretro cores)
|
|
// this isnt foolproof but its a little better than nothing
|
|
// setting PWD temporarily doesnt work. that'd be ideal since it supposedly gets searched early on,
|
|
// but i guess not with SetDllDirectory in effect
|
|
var envpath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
|
|
try
|
|
{
|
|
string envpath_new = Path.GetDirectoryName(path) + ";" + envpath;
|
|
Environment.SetEnvironmentVariable("PATH", envpath_new, EnvironmentVariableTarget.Process);
|
|
_hModule = LoadLibrary(path); //consider using LoadLibraryEx instead of shenanigans?
|
|
if (_hModule == IntPtr.Zero)
|
|
{
|
|
var lastError = GetLastError();
|
|
throw new InvalidOperationException($"Failed to load plugin {path}, error code: 0x{lastError:X}");
|
|
}
|
|
var newfname = TempFileCleaner.RenameTempFilenameForDelete(path);
|
|
File.Move(path, newfname);
|
|
}
|
|
finally
|
|
{
|
|
Environment.SetEnvironmentVariable("PATH", envpath, EnvironmentVariableTarget.Process);
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
enum LoadLibraryFlags : uint
|
|
{
|
|
DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
|
|
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
|
|
LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
|
|
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
|
|
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
|
|
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
|
|
}
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr LoadLibrary(string dllToLoad);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
static extern bool FreeLibrary(IntPtr hModule);
|
|
|
|
public IntPtr GetProcAddress(string procName)
|
|
{
|
|
return GetProcAddress(_hModule, procName);
|
|
}
|
|
|
|
public IntPtr HModule { get { return _hModule; } }
|
|
|
|
IntPtr IImportResolver.Resolve(string entryPoint)
|
|
{
|
|
return GetProcAddress(entryPoint);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_hModule != IntPtr.Zero)
|
|
{
|
|
FreeLibrary(_hModule);
|
|
_hModule = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
private IntPtr _hModule;
|
|
}
|
|
} |