Move CWD hacks to own class

This commit is contained in:
YoshiRulz 2020-02-28 13:15:37 +10:00
parent 4e5849030b
commit 848eaabf46
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
3 changed files with 35 additions and 40 deletions

View File

@ -6,7 +6,7 @@ using NLua;
// TODO - evaluate for re-entrancy problems
namespace BizHawk.Client.Common
{
public unsafe class LuaSandbox
public class LuaSandbox
{
private static readonly ConditionalWeakTable<Lua, LuaSandbox> SandboxForThread = new ConditionalWeakTable<Lua, LuaSandbox>();
@ -21,45 +21,18 @@ namespace BizHawk.Client.Common
private bool CoolSetCurrentDirectory(string path, string currDirSpeedHack = null)
{
static string CoolGetCurrentDirectory()
{
if (OSTailoredCode.IsUnixHost) return Environment.CurrentDirectory;
//HACK to bypass Windows security checks triggered by *getting* the current directory (why), which only slow us down
var buf = new byte[32768];
fixed (byte* pBuf = &buf[0])
return System.Text.Encoding.Unicode.GetString(buf, 0, 2 * (int) Win32Imports.GetCurrentDirectoryW(32767, pBuf));
}
string target = $"{_currentDirectory}\\";
// first we'll bypass it with a general hack: don't do any setting if the value's already there (even at the OS level, setting the directory can be slow)
// yeah I know, not the smoothest move to compare strings here, in case path normalization is happening at some point
// but you got any better ideas?
if (currDirSpeedHack == null)
{
currDirSpeedHack = CoolGetCurrentDirectory();
}
currDirSpeedHack ??= OSTailoredCode.IsUnixHost ? Environment.CurrentDirectory : CWDHacks.Get();
if (currDirSpeedHack == path) return true;
if (currDirSpeedHack == path)
{
return true;
}
if (OSTailoredCode.IsUnixHost)
{
if (System.IO.Directory.Exists(_currentDirectory)) //TODO is this necessary with Mono? extra TODO: is this necessary with .NET Core on Windows?
{
Environment.CurrentDirectory = _currentDirectory;
return true;
}
return false;
}
//HACK to bypass Windows security checks triggered by setting the current directory, which only slow us down
fixed (byte* pstr = &System.Text.Encoding.Unicode.GetBytes($"{target}\0")[0])
return Win32Imports.SetCurrentDirectoryW(pstr);
if (!OSTailoredCode.IsUnixHost) return CWDHacks.Set(target);
if (!System.IO.Directory.Exists(_currentDirectory)) return false; //TODO is this necessary with Mono? Linux is fine with the CWD being nonexistent. also, is this necessary with .NET Core on Windows? --yoshi
Environment.CurrentDirectory = _currentDirectory;
return true;
}
private void Sandbox(Action callback, Action exceptionCallback)

View File

@ -0,0 +1,28 @@
using System;
using System.Runtime.InteropServices;
namespace BizHawk.Common
{
/// <summary>Gets/Sets the current working directory while bypassing the security checks triggered by the public API (<see cref="Environment.CurrentDirectory"/>).</summary>
public static unsafe class CWDHacks
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint GetCurrentDirectoryW(uint nBufferLength, byte* pBuffer);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetCurrentDirectoryW(byte* lpPathName);
public static bool Set(string newCWD)
{
fixed (byte* pstr = &System.Text.Encoding.Unicode.GetBytes($"{newCWD}\0")[0])
return SetCurrentDirectoryW(pstr);
}
public static string Get()
{
var buf = new byte[32768];
fixed (byte* pBuf = &buf[0])
return System.Text.Encoding.Unicode.GetString(buf, 0, 2 * (int) GetCurrentDirectoryW(32767, pBuf));
}
}
}

View File

@ -105,9 +105,6 @@ namespace BizHawk.Common
[DllImport("user32.dll")]
public static extern IntPtr GetActiveWindow();
[DllImport("kernel32.dll", SetLastError=true)]
public static extern unsafe uint GetCurrentDirectoryW(uint nBufferLength, byte* pBuffer);
[DllImport("kernel32", SetLastError = true, EntryPoint = "GetProcAddress")]
public static extern IntPtr GetProcAddressOrdinal(IntPtr hModule, IntPtr procName);
@ -142,9 +139,6 @@ namespace BizHawk.Common
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern unsafe bool SetCurrentDirectoryW(byte* lpPathName);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO bi);