Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
fatalis committed May 3, 2014
0 parents commit 70cf317
Show file tree
Hide file tree
Showing 17 changed files with 1,872 additions and 0 deletions.
56 changes: 56 additions & 0 deletions LiveSplit.MirrorsEdge.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveSplit.MirrorsEdgeNoLoads", "LiveSplit.MirrorsEdge\LiveSplit.MirrorsEdgeNoLoads.csproj", "{6F40899A-6B45-4827-A3E7-1344DA09C4B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveSplit32BitPatcher", "LiveSplit32BitPatcher\LiveSplit32BitPatcher.csproj", "{25B82856-5429-4646-8E21-0E30A00D2AE1}"
EndProject
Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "menl_hooks", "menl_hooks\menl_hooks.visualdproj", "{0595D913-5F62-4D51-928C-8742CDE2F243}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Debug|Win32.ActiveCfg = Debug|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Release|Any CPU.Build.0 = Release|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{6F40899A-6B45-4827-A3E7-1344DA09C4B8}.Release|Win32.ActiveCfg = Release|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Debug|Win32.ActiveCfg = Debug|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Release|Any CPU.Build.0 = Release|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{25B82856-5429-4646-8E21-0E30A00D2AE1}.Release|Win32.ActiveCfg = Release|Any CPU
{0595D913-5F62-4D51-928C-8742CDE2F243}.Debug|Any CPU.ActiveCfg = Debug|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Debug|Win32.ActiveCfg = Debug|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Debug|Win32.Build.0 = Debug|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Release|Any CPU.ActiveCfg = Release|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Release|Mixed Platforms.Build.0 = Release|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Release|Win32.ActiveCfg = Release|Win32
{0595D913-5F62-4D51-928C-8742CDE2F243}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
161 changes: 161 additions & 0 deletions LiveSplit.MirrorsEdge/GameProcess.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
using System;
using System.ComponentModel;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace LiveSplit.MirrorsEdge
{
class GameProcess
{
public event EventHandler OnPause;
public event EventHandler OnUnpause;

private Task _thread;
private CancellationTokenSource _cancelSource;
private const string GAMEDLL = "menl_hooks.dll";
private const string PIPE_NAME = "LiveSplit.MirrorsEdge";

public void Run()
{
if (_thread != null && _thread.Status == TaskStatus.Running)
throw new InvalidOperationException();

_cancelSource = new CancellationTokenSource();
_thread = Task.Factory.StartNew(NamedPipeThread);
}

public void Stop()
{
if (_cancelSource == null || _thread == null)
throw new InvalidOperationException();

if (_thread.Status != TaskStatus.Running)
return;

_cancelSource.Cancel();
_thread.Wait();
}

void NamedPipeThread()
{
while (!_cancelSource.IsCancellationRequested)
{
try
{
Process gameProcess;
while ((gameProcess = GetGameProcess()) == null)
{
Thread.Sleep(250);
if (_cancelSource.IsCancellationRequested)
return;
}

Debug.WriteLine("got process");

if (!ProcessHasModule(gameProcess, GAMEDLL))
InjectDLL(gameProcess, GetGameDLLPath());

Debug.WriteLine("dll injected");

using (var pipe = new NamedPipeClientStream(".", PIPE_NAME, PipeDirection.In))
using (var sr = new StreamReader(pipe))
{
while (!gameProcess.HasExited)
{
try
{
pipe.Connect(250);
break;
}
catch (TimeoutException) { }
catch (IOException) { }
}
if (gameProcess.HasExited || !pipe.IsConnected)
continue;

Debug.WriteLine("pipe connected");

string line;
// TODO: readline blocks so when cancellation is supported in 1.4, go async
while ((line = sr.ReadLine()) != null)
{
if (line == "pause" && this.OnPause != null)
this.OnPause(this, EventArgs.Empty);
else if (line == "unpause")
this.OnUnpause(this, EventArgs.Empty);
}

Debug.WriteLine("pipe disconnected");
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
Thread.Sleep(1000);
}
}
}

static Process GetGameProcess()
{
return Process.GetProcesses()
.FirstOrDefault(p => p.ProcessName.ToLower() == "mirrorsedge" && !p.HasExited);
}

static string GetGameDLLPath()
{
string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? String.Empty;
return Path.Combine(dir, GAMEDLL);
}

static bool ProcessHasModule(Process process, string module)
{
return process.Modules.Cast<ProcessModule>().Any(m => Path.GetFileName(m.FileName).ToLower() == module);
}

static void InjectDLL(Process process, string path)
{
IntPtr loadLibraryAddr = SafeNativeMethods.GetProcAddress(SafeNativeMethods.GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (loadLibraryAddr == IntPtr.Zero)
throw new Exception("Couldn't locate LoadLibraryA");

IntPtr mem = IntPtr.Zero;
IntPtr hThread = IntPtr.Zero;
uint len = 0;

try
{
if ((mem = SafeNativeMethods.VirtualAllocEx(process.Handle, IntPtr.Zero, (uint)path.Length,
SafeNativeMethods.AllocationType.Commit | SafeNativeMethods.AllocationType.Reserve,
SafeNativeMethods.MemoryProtection.ReadWrite)) == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());

byte[] bytes = Encoding.ASCII.GetBytes(path + "\0");
len = (uint)bytes.Length;
uint written;
if (!SafeNativeMethods.WriteProcessMemory(process.Handle, mem, bytes, len, out written))
throw new Win32Exception(Marshal.GetLastWin32Error());

if ((hThread = SafeNativeMethods.CreateRemoteThread(process.Handle, IntPtr.Zero, 0, loadLibraryAddr, mem, 0, IntPtr.Zero))
== IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());

SafeNativeMethods.WaitForSingleObject(hThread, 0xFFFFFFFF); // INFINITE
}
finally
{
if (mem != IntPtr.Zero && len > 0)
SafeNativeMethods.VirtualFreeEx(process.Handle, mem, len, SafeNativeMethods.FreeType.Release);
if (hThread != IntPtr.Zero)
SafeNativeMethods.CloseHandle(hThread);
}
}
}
}
63 changes: 63 additions & 0 deletions LiveSplit.MirrorsEdge/LiveSplit.MirrorsEdgeNoLoads.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6F40899A-6B45-4827-A3E7-1344DA09C4B8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LiveSplit.MirrorsEdge</RootNamespace>
<AssemblyName>LiveSplit.MirrorsEdgeNoLoads</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="LiveSplit.Core">
<HintPath>C:\Files\Apps\Gaming\LiveSplit 1.3\LiveSplit.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="UpdateManager">
<HintPath>C:\Files\Apps\Gaming\LiveSplit 1.3\UpdateManager.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="GameProcess.cs" />
<Compile Include="MirrorsEdgeComponent.cs" />
<Compile Include="MirrorsEdgeFactory.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SafeNativeMethods.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Loading

0 comments on commit 70cf317

Please sign in to comment.