Properly fix lib loading (builds upon 77bbc4128)

Also cleaned up OSTailoredCode.cs and fixed qualifiers in Program.cs
This commit is contained in:
YoshiRulz 2019-10-13 15:23:14 +10:00
parent 9b8db26086
commit 7df71f2c86
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
5 changed files with 77 additions and 57 deletions

View File

@ -152,16 +152,16 @@ namespace SevenZip
//{
// throw new SevenZipLibraryException("DLL file does not exist.");
//}
if ((_modulePtr = libLoader.LoadPlatformSpecific(_libraryFileName)) == IntPtr.Zero)
if ((_modulePtr = libLoader.LoadOrNull(_libraryFileName).Value) == IntPtr.Zero)
{
//try a different directory
string alternateFilename = Path.Combine(Path.Combine(Path.GetDirectoryName(_libraryFileName),"dll"),"7z.dll");
if ((_modulePtr = libLoader.LoadPlatformSpecific(alternateFilename)) == IntPtr.Zero)
if ((_modulePtr = libLoader.LoadOrNull(_libraryFileName).Value) == IntPtr.Zero)
throw new SevenZipLibraryException("failed to load library.");
}
if (libLoader.GetProcAddr(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
{
libLoader.FreePlatformSpecific(_modulePtr);
libLoader.FreeByPtr(_modulePtr);
throw new SevenZipLibraryException("library is invalid.");
}
}
@ -435,7 +435,7 @@ namespace SevenZip
if (_totalUsers == 0)
{
#if !WINCE && !MONO
libLoader.FreePlatformSpecific(_modulePtr);
libLoader.FreeByPtr(_modulePtr);
#endif
_modulePtr = IntPtr.Zero;

View File

@ -30,36 +30,33 @@ namespace BizHawk.Client.EmuHawk
//try loading libraries we know we'll need
//something in the winforms, etc. code below will cause .net to popup a missing msvcr100.dll in case that one's missing
//but oddly it lets us proceed and we'll then catch it here
var d3dx9 = libLoader.LoadPlatformSpecific("d3dx9_43.dll");
var vc2015 = libLoader.LoadPlatformSpecific("vcruntime140.dll");
var vc2012 = libLoader.LoadPlatformSpecific("msvcr120.dll"); //TODO - check version?
var vc2010 = libLoader.LoadPlatformSpecific("msvcr100.dll"); //TODO - check version?
var vc2010p = libLoader.LoadPlatformSpecific("msvcp100.dll");
var fail = vc2015 == IntPtr.Zero || vc2010 == IntPtr.Zero || vc2012 == IntPtr.Zero || vc2010p == IntPtr.Zero;
var warn = d3dx9 == IntPtr.Zero;
if (fail || warn)
var d3dx9 = libLoader.LoadOrNull("d3dx9_43.dll");
var vc2015 = libLoader.LoadOrNull("vcruntime140.dll");
var vc2012 = libLoader.LoadOrNull("msvcr120.dll"); //TODO - check version?
var vc2010 = libLoader.LoadOrNull("msvcr100.dll"); //TODO - check version?
var vc2010p = libLoader.LoadOrNull("msvcp100.dll");
var reqPresent = vc2015.HasValue && vc2010.HasValue && vc2012.HasValue && vc2010p.HasValue;
var optPresent = d3dx9.HasValue;
if (!reqPresent || !optPresent)
{
var alertLines = new[]
{
"[ OK ] .NET CLR (You wouldn't even get here without it)",
$"[{(d3dx9 == IntPtr.Zero ? "WARN" : " OK ")}] Direct3d 9",
$"[{(vc2010 == IntPtr.Zero || vc2010p == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2010 SP1 Runtime",
$"[{(vc2012 == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2012 Runtime",
$"[{(vc2015 == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2015 Runtime"
$"[{(d3dx9.HasValue ? " OK " : "WARN")}] Direct3d 9",
$"[{(vc2010.HasValue && vc2010p.HasValue ? " OK " : "FAIL")}] Visual C++ 2010 SP1 Runtime",
$"[{(vc2012.HasValue ? " OK " : "FAIL")}] Visual C++ 2012 Runtime",
$"[{(vc2015.HasValue ? " OK " : "FAIL")}] Visual C++ 2015 Runtime"
};
var box = new BizHawk.Client.EmuHawk.CustomControls.PrereqsAlert(!fail)
var box = new CustomControls.PrereqsAlert(reqPresent)
{
textBox1 = { Text = string.Join(Environment.NewLine, alertLines) }
};
box.ShowDialog();
if (fail) System.Diagnostics.Process.GetCurrentProcess().Kill();
if (!reqPresent) Process.GetCurrentProcess().Kill();
}
libLoader.FreePlatformSpecific(d3dx9);
libLoader.FreePlatformSpecific(vc2015);
libLoader.FreePlatformSpecific(vc2012);
libLoader.FreePlatformSpecific(vc2010);
libLoader.FreePlatformSpecific(vc2010p);
foreach (var p in new[] { d3dx9, vc2015, vc2012, vc2010, vc2010p })
if (p.HasValue) libLoader.FreeByPtr(p.Value);
// this will look in subdirectory "dll" to load pinvoked stuff
var dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll");
@ -110,7 +107,7 @@ namespace BizHawk.Client.EmuHawk
}
}
BizHawk.Common.TempFileManager.Start();
TempFileManager.Start();
HawkFile.ArchiveHandlerFactory = new SevenZipSharpArchiveHandler();
@ -129,8 +126,8 @@ namespace BizHawk.Client.EmuHawk
Global.Config.ResolveDefaults();
BizHawk.Client.Common.StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk;
BizHawk.Client.Common.StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE;
StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk;
StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE;
// super hacky! this needs to be done first. still not worth the trouble to make this system fully proper
if (Array.Exists(args, arg => arg.StartsWith("--gdi", StringComparison.InvariantCultureIgnoreCase)))

View File

@ -5,15 +5,15 @@ using BizHawk.Common;
namespace BizHawk.Common.BizInvoke
{
/// TODO move this and all in IImportResolver.cs to OSTailoredCode.cs and refactor
public class DynamicLibraryImportResolver : IImportResolver, IDisposable
{
private IntPtr _p;
private readonly OSTailoredCode.ILinkedLibManager libLoader = OSTailoredCode.LinkedLibManager;
private readonly OSTailoredCode.ILinkedLibManager libLoader = OSTailoredCode.LinkedLibManager; //TODO inline?
public DynamicLibraryImportResolver(string dllName)
{
_p = libLoader.LoadPlatformSpecific(dllName);
if (_p == IntPtr.Zero) throw new InvalidOperationException($"null pointer returned by {nameof(libLoader.LoadPlatformSpecific)}");
_p = libLoader.LoadOrThrow(dllName);
}
public IntPtr Resolve(string entryPoint)
@ -23,8 +23,8 @@ namespace BizHawk.Common.BizInvoke
private void Free()
{
if (_p == IntPtr.Zero) return;
libLoader.FreePlatformSpecific(_p);
if (_p == IntPtr.Zero) return; // already freed
libLoader.FreeByPtr(_p);
_p = IntPtr.Zero;
}

View File

@ -31,11 +31,13 @@ namespace BizHawk.Common
public static ILinkedLibManager LinkedLibManager => _LinkedLibManager.Value;
/// <remarks>this interface's inheritors hide OS-specific implementation details</remarks>
public interface ILinkedLibManager
{
IntPtr LoadPlatformSpecific(string dllToLoad);
IntPtr GetProcAddr(IntPtr hModule, string procName);
int FreePlatformSpecific(IntPtr hModule);
IntPtr? LoadOrNull(string dllToLoad);
IntPtr LoadOrThrow(string dllToLoad);
IntPtr GetProcAddr(IntPtr hModule, string procName); //TODO also split into nullable and throwing?
int FreeByPtr(IntPtr hModule);
}
/// <remarks>This class is copied from a tutorial, so don't git blame and then email me expecting insight.</remarks>
@ -43,41 +45,67 @@ namespace BizHawk.Common
{
private const int RTLD_NOW = 2;
[DllImport("libdl.so.2")]
private static extern IntPtr dlopen(string fileName, int flags);
private static extern int dlclose(IntPtr handle);
[DllImport("libdl.so.2")]
private static extern IntPtr dlerror();
[DllImport("libdl.so.2")]
private static extern IntPtr dlsym(IntPtr handle, string symbol);
private static extern IntPtr dlopen(string fileName, int flags);
[DllImport("libdl.so.2")]
private static extern int dlclose(IntPtr handle);
private static extern IntPtr dlsym(IntPtr handle, string symbol);
public IntPtr LoadPlatformSpecific(string dllToLoad) => dlopen(dllToLoad, RTLD_NOW);
public IntPtr GetProcAddr(IntPtr hModule, string procName)
{
dlerror();
var res = dlsym(hModule, procName);
var errPtr = dlerror();
if (errPtr != IntPtr.Zero) throw new InvalidOperationException($"error in dlsym: {Marshal.PtrToStringAnsi(errPtr)}");
if (errPtr != IntPtr.Zero) throw new InvalidOperationException($"error in {nameof(dlsym)}: {Marshal.PtrToStringAnsi(errPtr)}");
return res;
}
public int FreePlatformSpecific(IntPtr hModule) => dlclose(hModule);
public int FreeByPtr(IntPtr hModule) => dlclose(hModule);
public IntPtr? LoadOrNull(string dllToLoad)
{
var p = dlopen(dllToLoad, RTLD_NOW);
return p == IntPtr.Zero ? default(IntPtr?) : p;
}
public IntPtr LoadOrThrow(string dllToLoad)
{
var p = LoadOrNull(dllToLoad);
if (!p.HasValue) throw new InvalidOperationException($"got null pointer from {nameof(dlopen)}, error: {Marshal.PtrToStringAnsi(dlerror())}");
return p.Value;
}
}
private class WindowsLLManager : ILinkedLibManager
{
// comments reference extern functions removed from SevenZip.NativeMethods
[DllImport("kernel32.dll")]
private static extern bool FreeLibrary(IntPtr hModule); // return type was annotated MarshalAs(UnmanagedType.Bool)
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
[DllImport("kernel32.dll")] // had BestFitMapping = false, ThrowOnUnmappableChar = true
private static extern IntPtr LoadLibrary(string dllToLoad); // param dllToLoad was annotated `[MarshalAs(UnmanagedType.LPStr)]`
[DllImport("kernel32.dll")] // had BestFitMapping = false, ThrowOnUnmappableChar = true
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); // param procName was annotated `[MarshalAs(UnmanagedType.LPStr)]`
[DllImport("kernel32.dll")]
private static extern bool FreeLibrary(IntPtr hModule); // return type was annotated MarshalAs(UnmanagedType.Bool)
[DllImport("kernel32.dll")] // had BestFitMapping = false, ThrowOnUnmappableChar = true
private static extern IntPtr LoadLibrary(string dllToLoad); // param dllToLoad was annotated `[MarshalAs(UnmanagedType.LPStr)]`
public IntPtr LoadPlatformSpecific(string dllToLoad) => LoadLibrary(dllToLoad);
public IntPtr GetProcAddr(IntPtr hModule, string procName) => GetProcAddress(hModule, procName);
public int FreePlatformSpecific(IntPtr hModule) => FreeLibrary(hModule) ? 1 : 0;
public int FreeByPtr(IntPtr hModule) => FreeLibrary(hModule) ? 1 : 0;
public IntPtr? LoadOrNull(string dllToLoad)
{
var p = LoadLibrary(dllToLoad);
return p == IntPtr.Zero ? default(IntPtr?) : p;
}
public IntPtr LoadOrThrow(string dllToLoad)
{
var p = LoadOrNull(dllToLoad);
if (!p.HasValue) throw new InvalidOperationException($"got null pointer from {nameof(LoadLibrary)}, error code: {GetLastError()}");
return p.Value;
}
}
public enum DistinctOS : byte
@ -91,7 +119,7 @@ namespace BizHawk.Common
/// <param name="args">POSIX <c>$*</c> (space-delimited)</param>
/// <param name="checkStdout">stdout is discarded if false</param>
/// <param name="checkStderr">stderr is discarded if false</param>
/// <remarks>OS is implicit and needs to be checked at callsite, returned <see cref="Process"/> has not been started</remarks>
/// <remarks>OS is implicit and needs to be checked at callsite. Returned <see cref="Process"/> has not been started.</remarks>
public static Process ConstructSubshell(string cmd, string args, bool checkStdout = true, bool checkStderr = false) =>
new Process {
StartInfo = new ProcessStartInfo {

View File

@ -484,9 +484,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
}
this.bizhawkCore = bizhawkCore;
CoreDll = libLoader.LoadPlatformSpecific("mupen64plus");
if (CoreDll == IntPtr.Zero)
throw new InvalidOperationException("Failed to load mupen64plus.dll");
CoreDll = libLoader.LoadOrThrow("mupen64plus");
connectFunctionPointers();
@ -914,7 +912,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
m64pCoreDoCommandPtr(m64p_command.M64CMD_ROM_CLOSE, 0, IntPtr.Zero);
m64pCoreShutdown();
libLoader.FreePlatformSpecific(CoreDll);
libLoader.FreeByPtr(CoreDll);
disposed = true;
}
@ -934,10 +932,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
DetachPlugin(type);
AttachedPlugin plugin;
plugin.dllHandle = libLoader.LoadPlatformSpecific(PluginName);
if (plugin.dllHandle == IntPtr.Zero)
throw new InvalidOperationException($"Failed to load plugin {PluginName}");
plugin.dllHandle = libLoader.LoadOrThrow(PluginName);
plugin.dllStartup = (PluginStartup)Marshal.GetDelegateForFunctionPointer(libLoader.GetProcAddr(plugin.dllHandle, "PluginStartup"), typeof(PluginStartup));
plugin.dllShutdown = (PluginShutdown)Marshal.GetDelegateForFunctionPointer(libLoader.GetProcAddr(plugin.dllHandle, "PluginShutdown"), typeof(PluginShutdown));
plugin.dllStartup(CoreDll, null, null);
@ -945,7 +940,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
m64p_error result = m64pCoreAttachPlugin(type, plugin.dllHandle);
if (result != m64p_error.M64ERR_SUCCESS)
{
libLoader.FreePlatformSpecific(plugin.dllHandle);
libLoader.FreeByPtr(plugin.dllHandle);
throw new InvalidOperationException($"Error during attaching plugin {PluginName}");
}
@ -961,7 +956,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
plugins.Remove(type);
m64pCoreDetachPlugin(type);
plugin.dllShutdown();
libLoader.FreePlatformSpecific(plugin.dllHandle);
libLoader.FreeByPtr(plugin.dllHandle);
}
}