Code:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
//using Microsoft.DirectX.Direct3D;
namespace Onyx.WoW.Native
{
// ReSharper disable InconsistentNaming
internal static class DirectX
{
#region Actual Useful Funcs
//public static unsafe IntPtr GetDevicePointerManaged(uint funcIndex)
//{
// var window = new Form();
// var device = new Device(0, (DeviceType) 1, window,
// CreateFlags.SoftwareVertexProcessing,
// new PresentParameters
// {
// Windowed = true,
// SwapEffect = SwapEffect.Discard,
// BackBufferFormat = Format.Unknown,
// });
// // This func requires an unsafe context due to the COM pointer
// var devicePtr = (IntPtr) device.UnmanagedComPointer;
// IntPtr ret = funcIndex < 0 ? devicePtr : Reader.GetVFunc(devicePtr, funcIndex);
// device.Dispose();
// window.Dispose();
// return ret;
//}
/// <summary>
/// Returns a function pointer for the current DirectX device.
/// </summary>
/// <param name="funcIndex">The index to the function you want to retrieve.</param>
/// <returns></returns>
public static IntPtr GetDevicePointer(uint funcIndex)
{
// Create a new 'window'
var window = new Form();
// Grabbed from d3d9.h
const uint D3D_SDK_VERSION = 32;
// Create the IDirect3D* object.
IntPtr direct3D = Direct3DCreate9(D3D_SDK_VERSION);
// Make sure it's valid. (Should always be valid....)
if (direct3D == IntPtr.Zero)
throw new Exception("Failed to create D3D.");
// Setup some present params...
var d3dpp = new D3DPRESENT_PARAMETERS {Windowed = true, SwapEffect = 1, BackBufferFormat = 0};
IntPtr device;
// CreateDevice is a vfunc of IDirect3D. Hence; why this entire thing only works in process! (Unless you
// know of some way to hook funcs from out of process...)
// It's the 16th vfunc btw.
// Check d3d9.h
var createDevice = Utilities.RegisterDelegate<IDirect3D9_CreateDevice>(Reader.GetVFunc(direct3D, 16));
// Pass it some vals. You can check d3d9.h for what these actually are....
if (createDevice(direct3D, 0, 1, window.Handle, 0x20, ref d3dpp, out device) < 0)
throw new Exception("Failed to create device.");
// If we passed anything lower than 0, just return the device pointer. Otherwise,
// grab the vfunc pointer. (Useful for EndScene/Reset/etc)
IntPtr ret = funcIndex < 0 ? device : Reader.GetVFunc(device, funcIndex);
// We now have a valid pointer to the device. We can release the shit we don't need now. :)
// Again, the Release() funcs are virtual. Part of the IUnknown interface for COM.
// They're the 3rd vfunc. (2nd index)
var deviceRelease = Utilities.RegisterDelegate<D3DVirtVoid>(Reader.GetVFunc(device, 2));
var d3dRelease = Utilities.RegisterDelegate<D3DVirtVoid>(Reader.GetVFunc(direct3D, 2));
// And finally, release the device and d3d object.
deviceRelease(device);
d3dRelease(direct3D);
// Destroy the window...
window.Dispose();
// Tell the CLR to finalize the object asap.
// And we can FINALLY return the pointer to the device or func.
return ret;
}
public static IntPtr GetEndScenePointer()
{
return GetDevicePointer(42);
}
//public static IntPtr GetEndScenePointerManaged()
//{
// return GetDevicePointerManaged(42);
//}
public static IntPtr GetResetPointer()
{
return GetDevicePointer(16);
}
//public static IntPtr GetResetPointerManaged()
//{
// return GetDevicePointerManaged(16);
//}
#endregion
#region DllImports
[DllImport("d3d9.dll")]
private static extern IntPtr Direct3DCreate9(uint sdkVersion);
#region Nested type: D3DVirtVoid
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void D3DVirtVoid(IntPtr instance);
#endregion
#region Nested type: IDirect3D9_CreateDevice
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int IDirect3D9_CreateDevice(IntPtr instance, uint adapter, uint deviceType,
IntPtr focusWindow,
uint behaviorFlags,
[In] ref D3DPRESENT_PARAMETERS presentationParameters,
[Out] out IntPtr returnedDeviceInterface);
#endregion
#endregion
#region Structs n Shit
[StructLayout(LayoutKind.Sequential)]
private struct D3DPRESENT_PARAMETERS
{
public readonly uint BackBufferWidth;
public readonly uint BackBufferHeight;
public uint BackBufferFormat;
public readonly uint BackBufferCount;
public readonly uint MultiSampleType;
public readonly uint MultiSampleQuality;
public uint SwapEffect;
public readonly IntPtr hDeviceWindow;
[MarshalAs(UnmanagedType.Bool)] public bool Windowed;
[MarshalAs(UnmanagedType.Bool)] public readonly bool EnableAutoDepthStencil;
public readonly uint AutoDepthStencilFormat;
public readonly uint Flags;
public readonly uint FullScreen_RefreshRateInHz;
public readonly uint PresentationInterval;
}
#endregion
}
}