#![allow(clippy::missing_safety_doc)]
mod com;
mod cost;
mod crash;
mod d3d11;
mod d3d12;
mod dump;
mod dxgi;
mod log;
mod passthrough;
mod settings;
mod system;
mod values;
mod vtables;
use core::ffi::c_void;
use std::sync::Once;
use windows::Win32::Foundation::{E_NOTIMPL, E_POINTER, HMODULE};
use windows::Win32::Graphics::Direct3D::{D3D_DRIVER_TYPE, D3D_FEATURE_LEVEL};
use windows::Win32::Graphics::Direct3D11::{D3D11_CREATE_DEVICE_FLAG, ID3D11Device};
use windows::Win32::Graphics::Dxgi::DXGI_SWAP_CHAIN_DESC;
use windows::core::{GUID, HRESULT, IUnknown, Interface};
use crate::d3d11::device::Device;
use crate::dxgi::{Adapter, Factory, SwapChain};
use crate::log::log;
use crate::system::{caller_of_caller, export, is_system_caller, module_of, module_path, system};
use crate::vtables::device::DeviceMethods;
fn hello() {
static ONCE: Once = Once::new();
ONCE.call_once(|| {
let exe = std::env::current_exe()
.map(|p| p.display().to_string())
.unwrap_or_default();
log!(
"locum {} in {exe} (pid {})",
env!("CARGO_PKG_VERSION"),
std::process::id()
);
crate::crash::install();
crate::values::start();
});
}
fn caller_name(address: *const c_void) -> String {
module_of(address)
.map(|m| module_path(m).display().to_string())
.unwrap_or_else(|| format!("{address:p}"))
}
type CreateDeviceFn = unsafe extern "system" fn(
*mut c_void,
D3D_DRIVER_TYPE,
HMODULE,
D3D11_CREATE_DEVICE_FLAG,
*const D3D_FEATURE_LEVEL,
u32,
u32,
*mut *mut c_void,
*mut D3D_FEATURE_LEVEL,
*mut *mut c_void,
) -> HRESULT;
type CreateDeviceAndSwapChainFn = unsafe extern "system" fn(
*mut c_void,
D3D_DRIVER_TYPE,
HMODULE,
D3D11_CREATE_DEVICE_FLAG,
*const D3D_FEATURE_LEVEL,
u32,
u32,
*const DXGI_SWAP_CHAIN_DESC,
*mut *mut c_void,
*mut *mut c_void,
*mut D3D_FEATURE_LEVEL,
*mut *mut c_void,
) -> HRESULT;
unsafe fn give_device(device: *mut c_void, device_out: *mut *mut c_void, context_out: *mut *mut c_void) {
let real = unsafe { ID3D11Device::from_raw(device) };
let wrapped = Device::wrap(real);
if wrapped.is_ok() {
d3d11::overrides::reload();
}
match wrapped {
Ok(wrapper) => unsafe {
let w = &*wrapper;
if !context_out.is_null() {
w.AddRef();
*context_out = w.immediate_raw();
}
if device_out.is_null() {
w.Release();
} else {
*device_out = wrapper.cast();
}
},
Err(real) => unsafe {
if !context_out.is_null() {
*context_out = real
.GetImmediateContext()
.map_or(core::ptr::null_mut(), |c| c.into_raw());
}
if !device_out.is_null() {
*device_out = real.into_raw();
}
},
}
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn D3D11CreateDevice(
adapter: *mut c_void,
driver_type: D3D_DRIVER_TYPE,
software: HMODULE,
flags: D3D11_CREATE_DEVICE_FLAG,
levels: *const D3D_FEATURE_LEVEL,
level_count: u32,
sdk_version: u32,
device_out: *mut *mut c_void,
level_out: *mut D3D_FEATURE_LEVEL,
context_out: *mut *mut c_void,
) -> HRESULT {
hello();
let caller = caller_of_caller();
let Some(real) = (unsafe { export::<CreateDeviceFn>(system().d3d11, c"D3D11CreateDevice") }) else {
return E_NOTIMPL;
};
let adapter = Adapter::unwrap_raw(adapter);
if is_system_caller(caller) {
let hr = unsafe {
real(
adapter,
driver_type,
software,
flags,
levels,
level_count,
sdk_version,
device_out,
level_out,
context_out,
)
};
log!(
"D3D11CreateDevice from {} flags {:#x} -> {hr:?} (real device)",
caller_name(caller),
flags.0
);
return hr;
}
let mut device = core::ptr::null_mut();
let wants = !device_out.is_null() || !context_out.is_null();
let hr = unsafe {
real(
adapter,
driver_type,
software,
flags,
levels,
level_count,
sdk_version,
if wants { &mut device } else { core::ptr::null_mut() },
level_out,
core::ptr::null_mut(),
)
};
log!(
"D3D11CreateDevice from {} flags {:#x} -> {hr:?}",
caller_name(caller),
flags.0
);
if hr.is_ok() && !device.is_null() {
unsafe { give_device(device, device_out, context_out) };
}
hr
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn D3D11CreateDeviceAndSwapChain(
adapter: *mut c_void,
driver_type: D3D_DRIVER_TYPE,
software: HMODULE,
flags: D3D11_CREATE_DEVICE_FLAG,
levels: *const D3D_FEATURE_LEVEL,
level_count: u32,
sdk_version: u32,
swapchain_desc: *const DXGI_SWAP_CHAIN_DESC,
swapchain_out: *mut *mut c_void,
device_out: *mut *mut c_void,
level_out: *mut D3D_FEATURE_LEVEL,
context_out: *mut *mut c_void,
) -> HRESULT {
hello();
let caller = caller_of_caller();
let Some(real) =
(unsafe { export::<CreateDeviceAndSwapChainFn>(system().d3d11, c"D3D11CreateDeviceAndSwapChain") })
else {
return E_NOTIMPL;
};
let adapter = Adapter::unwrap_raw(adapter);
let mut device = core::ptr::null_mut();
let mut swapchain = core::ptr::null_mut();
let hr = unsafe {
real(
adapter,
driver_type,
software,
flags,
levels,
level_count,
sdk_version,
swapchain_desc,
if swapchain_out.is_null() {
core::ptr::null_mut()
} else {
&mut swapchain
},
&mut device,
level_out,
core::ptr::null_mut(),
)
};
log!(
"D3D11CreateDeviceAndSwapChain from {} flags {:#x} -> {hr:?}",
caller_name(caller),
flags.0
);
if hr.is_err() || device.is_null() {
return hr;
}
let mut ours = core::ptr::null_mut();
unsafe { give_device(device, &mut ours, context_out) };
if !swapchain.is_null() {
let real = unsafe { IUnknown::from_raw(swapchain) };
let wrapped = match SwapChain::wrap(real, Device::from_raw(ours), None) {
Ok(w) => w.cast(),
Err(real) => real.into_raw(),
};
unsafe { *swapchain_out = wrapped };
}
unsafe {
if device_out.is_null() {
match Device::from_raw(ours) {
Some(d) => {
d.Release();
}
None => {
IUnknown::from_raw(ours);
}
}
} else {
*device_out = ours;
}
}
hr
}
type CreateFactoryFn = unsafe extern "system" fn(*const GUID, *mut *mut c_void) -> HRESULT;
type CreateFactory2Fn = unsafe extern "system" fn(u32, *const GUID, *mut *mut c_void) -> HRESULT;
unsafe fn give_factory(name: &str, caller: *const c_void, hr: HRESULT, out: *mut *mut c_void) -> HRESULT {
let system_caller = is_system_caller(caller);
log!(
"{name} from {} -> {hr:?}{}",
caller_name(caller),
if system_caller { " (real factory)" } else { "" }
);
if hr.is_err() || out.is_null() || unsafe { (*out).is_null() } || system_caller {
return hr;
}
let real = unsafe { IUnknown::from_raw(*out) };
match Factory::wrap(real) {
Ok(w) => unsafe { *out = w.cast() },
Err(real) => unsafe { *out = real.into_raw() },
}
hr
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn CreateDXGIFactory(iid: *const GUID, out: *mut *mut c_void) -> HRESULT {
hello();
let caller = caller_of_caller();
if out.is_null() {
return E_POINTER;
}
let Some(real) = (unsafe { export::<CreateFactoryFn>(system().dxgi, c"CreateDXGIFactory") }) else {
return E_NOTIMPL;
};
let hr = unsafe { real(iid, out) };
unsafe { give_factory("CreateDXGIFactory", caller, hr, out) }
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn CreateDXGIFactory1(iid: *const GUID, out: *mut *mut c_void) -> HRESULT {
hello();
let caller = caller_of_caller();
if out.is_null() {
return E_POINTER;
}
let Some(real) = (unsafe { export::<CreateFactoryFn>(system().dxgi, c"CreateDXGIFactory1") }) else {
return E_NOTIMPL;
};
let hr = unsafe { real(iid, out) };
unsafe { give_factory("CreateDXGIFactory1", caller, hr, out) }
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn CreateDXGIFactory2(
flags: u32,
iid: *const GUID,
out: *mut *mut c_void,
) -> HRESULT {
hello();
let caller = caller_of_caller();
if out.is_null() {
return E_POINTER;
}
let Some(real) = (unsafe { export::<CreateFactory2Fn>(system().dxgi, c"CreateDXGIFactory2") }) else {
return E_NOTIMPL;
};
let hr = unsafe { real(flags, iid, out) };
unsafe { give_factory("CreateDXGIFactory2", caller, hr, out) }
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn DXGIDeclareAdapterRemovalSupport() -> HRESULT {
hello();
type F = unsafe extern "system" fn() -> HRESULT;
match unsafe { export::<F>(system().dxgi, c"DXGIDeclareAdapterRemovalSupport") } {
Some(real) => unsafe { real() },
None => E_NOTIMPL,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn DXGIGetDebugInterface1(
flags: u32,
iid: *const GUID,
out: *mut *mut c_void,
) -> HRESULT {
hello();
match unsafe { export::<CreateFactory2Fn>(system().dxgi, c"DXGIGetDebugInterface1") } {
Some(real) => unsafe { real(flags, iid, out) },
None => E_NOTIMPL,
}
}