Skip to content

Commit

Permalink
Integrated Mithos DLL Injection
Browse files Browse the repository at this point in the history
  • Loading branch information
TulioAdriano committed Aug 26, 2015
1 parent 16d1763 commit 80357b2
Show file tree
Hide file tree
Showing 16 changed files with 1,165 additions and 54 deletions.
171 changes: 171 additions & 0 deletions Mithos/Direct3D8.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
This file is part of Mithos
Copyright (C) 2013 Lawrence Sebald
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Runtime.InteropServices;
using Yggdrasill;

/* For some unknown reason, I can't seem to get DirectX and DirectInput to
* hook the same way. At some point, I'd like to clean up the Direct3D hook
* code here to look more like the DirectInput one, but for now this will
* have to do. */
namespace Sylverant
{
public unsafe class IDirect3D8 : IDisposable
{
#region Variables

// A pointer to the native IDirect3D8 object that we are providing overrides for.
public D3D8.IDirect3D8* Context
{
get;
private set;
}

// A pointer to the original array of virtual functions. We keep this around so we can call the originals.
private IntPtr* vtable = null;

// Our link back to the launcher
private YggdrasillInterface Interface;

private DCreateDevice del_cd;

#endregion

#region Constructors

// For the case where we already have a native IDirect3D8 object and we want to override some of it's functions.
public unsafe IDirect3D8(D3D8.IDirect3D8* InContext, YggdrasillInterface iface)
{
Context = InContext;
Interface = iface;

// Override the functions in the vtable of the context with our own.
OverrideFunctions();
}

// For the case where we don't have a native IDirect3D object so we want one created for us.
public IDirect3D8(uint SdkVersion, YggdrasillInterface iface)
{
// Create the real IDirect3D8 object.
Context = D3D8.Direct3DCreate8(SdkVersion);
Interface = iface;

// Override the functions in the vtable of the context with our own.
OverrideFunctions();
}

#endregion

#region Destructors/Disposal methods

~IDirect3D8()
{
Dispose(true);
}

public void Dispose()
{
Dispose(false);
}

// Cleanup resources. Destructing == true means we are getting garbage collected so don't reference any managed resources.
private void Dispose(bool Destructing)
{
if (vtable != null)
{
Kernel32.HeapFree(Kernel32.GetProcessHeap(), 0, *vtable);
vtable = null;
}
}

#endregion

#region Vtable Management

// Backup the original native vtable and overwrite the pointer to it with our own (which is a copy of the original).
private void InitVtable()
{
// If we don't have a real IDirect3D8 object yet then do nothing.
if (Context == null) return;

// Save off the original vtable (only if it really is the original).
if (vtable == null) vtable = Context->vtable;

// IDirect3D8 has 17 members.
UInt32 vtblen = 17;
// Allocate space for our new vtable.
IntPtr* nvtable = (IntPtr*)Kernel32.HeapAlloc(Kernel32.GetProcessHeap(), 0, (UIntPtr)(vtblen * sizeof(IntPtr)));

// Copy all of the original function pointers into our new vtable.
for (int i = 0; i < vtblen; i++)
{
nvtable[i] = vtable[i];
}

// Set the Real IDirect3D8 implementation's vtable to point at our custom one.
Context->vtable = nvtable;
}

private void OverrideFunctions()
{
InitVtable();

// 0: STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
// 1: STDMETHOD_(ULONG,AddRef)(THIS) PURE;
// 2: STDMETHOD_(ULONG,Release)(THIS) PURE;
// 3: STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
// 4: STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
// 5: STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER8* pIdentifier) PURE;
// 6: STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter) PURE;
// 7: STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
// 8: STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE;
// 9: STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL Windowed) PURE;
// 10: STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE;
// 11: STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType) PURE;
// 12: STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;
// 13: STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS8* pCaps) PURE;
// 14: STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
// 15: STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface) PURE;

del_cd = new DCreateDevice(CreateDevice);
IntPtr ptr = Marshal.GetFunctionPointerForDelegate(del_cd);
Context->vtable[15] = ptr;
}

#endregion

#region IDirect3D8 Interface Function Implementations

public unsafe delegate int DCreateDevice(D3D8.IDirect3D8* This, uint Adapter, uint DeviceType, IntPtr hFocusWindow,
UInt32 BehaviorFlags, D3D8.D3DPRESENT_PARAMETERS* pPresentationParameters, IntPtr ppReturnedDeviceInterface);

public unsafe int CreateDevice(D3D8.IDirect3D8* This, uint Adapter, uint DeviceType, IntPtr hFocusWindow,
UInt32 BehaviorFlags, D3D8.D3DPRESENT_PARAMETERS* pPresentationParameters, IntPtr ppReturnedDeviceInterface)
{
DCreateDevice del = (DCreateDevice)Marshal.GetDelegateForFunctionPointer(vtable[15], typeof(DCreateDevice));

/* I want windowed mode, damn you! */
pPresentationParameters->hDeviceWindow = (IntPtr)1;
pPresentationParameters->FullScreen_RefreshRateInHz = 0;

return del(This, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
}

#endregion
}
}
117 changes: 117 additions & 0 deletions Mithos/DirectInput8.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
This file is part of Mithos
Copyright (C) 2013 Lawrence Sebald
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Yggdrasill;

namespace Sylverant
{
public unsafe class IDirectInput8
{
#region Variables

// A pointer to the native IDirectInput8 object that we are providing overrides for.
public DirectInput8.IDirectInput8* Context
{
get;
private set;
}

// Our link back to the launcher
private YggdrasillInterface Interface;

// Pointers to any of the old functions we override.
private IntPtr oldCreate;

private DCreateDevice del_cd;

private List<IDirectInputDevice8> devices = new List<IDirectInputDevice8>();

#endregion

#region Constructors

// For the case where we already have a native IDirectInput8 object and we want to override some of it's functions.
public unsafe IDirectInput8(DirectInput8.IDirectInput8* InNativeIDirectInput8, YggdrasillInterface iface)
{
Context = InNativeIDirectInput8;
Interface = iface;

/* Hook up any functions we care about */
OverrideFunctions();
}

// For the case where we don't have a native IDirectInput8 object so we want one created for us.
public unsafe IDirectInput8(IntPtr hInst, UInt32 dwVersion, IntPtr riidltf,
DirectInput8.IDirectInput8** ppvOut, IntPtr punkOuter, YggdrasillInterface iface, out int rv)
{
// Create the real IDirectInput8 object.
rv = DirectInput8.DirectInput8Create(hInst, dwVersion, riidltf, ppvOut, punkOuter);
Context = *ppvOut;
Interface = iface;

/* Hook up any functions we care about */
OverrideFunctions();
}

private void OverrideFunctions()
{
// List of functions in the IDirectInput8 interface:
// 0: STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
// 1: STDMETHOD_(ULONG,AddRef)(THIS) PURE;
// 2: STDMETHOD_(ULONG,Release)(THIS) PURE;
// 3: STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8A *,LPUNKNOWN) PURE;
// 4: STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
// 5: STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
// 6: STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
// 7: STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
// 8: STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE;
// 9: STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR,LPDIACTIONFORMATA,LPDIENUMDEVICESBYSEMANTICSCBA,LPVOID,DWORD) PURE;
// 10: STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSA,DWORD,LPVOID) PURE;

oldCreate = Context->vtable[3];
del_cd = new DCreateDevice(CreateDevice);
IntPtr ptr = Marshal.GetFunctionPointerForDelegate(del_cd);
Context->vtable[3] = ptr;
}

#endregion

#region IDirectInput8 Interface Function Implementations

[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)]
public unsafe delegate int DCreateDevice(DirectInput8.IDirectInput8* This, DirectInput8.GUID* rguid,
IntPtr *lplpDirectInputDevice, IntPtr pUnkOuter);

public unsafe int CreateDevice(DirectInput8.IDirectInput8* This, DirectInput8.GUID* rguid,
IntPtr *lplpDirectInputDevice, IntPtr pUnkOuter)
{
DCreateDevice del = (DCreateDevice)Marshal.GetDelegateForFunctionPointer(oldCreate, typeof(DCreateDevice));
int rv = del(This, rguid, lplpDirectInputDevice, pUnkOuter);

IDirectInputDevice8 dev = new IDirectInputDevice8((DirectInput8.IDirectInputDevice8*)*lplpDirectInputDevice, Interface);

devices.Add(dev);

return rv;
}

#endregion
}
}
Loading

0 comments on commit 80357b2

Please sign in to comment.