DllImpl::DllImpl(const std::wstring& installationDir) { auto dllPath(installationDir + L"temple.dll"); // Does it even exist? if (!PathFileExists(dllPath.c_str())) { auto msg(fmt::format("Temple.dll does not exist: {}", ucs2_to_utf8(dllPath))); throw TempleException(msg); } SetCurrentDirectory(installationDir.c_str()); // Try to load it mDllHandle = LoadLibrary(dllPath.c_str()); if (!mDllHandle) { throw TempleException("Unable to load temple.dll from {}: {}", ucs2_to_utf8(dllPath), GetLastWin32Error()); } // calculate the offset from the default 0x10000000 base address auto baseAddr = reinterpret_cast<uint32_t>(mDllHandle); mDeltaFromVanilla = baseAddr - defaultBaseAddr; logger->info("The temple.dll base address delta is: {}", mDeltaFromVanilla); auto status = MH_Initialize(); if (status != MH_OK) { FreeLibrary(mDllHandle); auto msg(fmt::format("Unable to initialize MinHook: {}", MH_StatusToString(status))); throw TempleException(msg); } }
// EnsureMinHookInitialized ensures that the MinHook // library is initialized. If MinHook is already // initialized, calling this function is a no-op. static void EnsureMinHookInitialized() { // Ensure MH_Initialize is only called once. if (InterlockedCompareExchange(&minhook_init_once, 1, 0) == 0) { MH_STATUS status = MH_Initialize(); if (status != MH_OK && status != MH_ERROR_ALREADY_INITIALIZED) { fods("HardHook: Failed to initialize minhook; MH_Initialize returned %s", MH_StatusToString(status)); } } }
/** * @brief Makes sure the given replacement function is run once func is called. * * Uses MinHook to put the hook in place. * * @param func Pointer to function to redirect. * @param replacement Pointer to code to redirect to. */ void HardHook::setup(voidFunc func, voidFunc replacement) { m_func = func; m_replacement = replacement; MH_STATUS status = MH_CreateHook((LPVOID) func, (LPVOID)replacement, (LPVOID *)&call); if (status != MH_OK) { fods("HardHook: setup failed, MH_CreateHook returned %s", MH_StatusToString(status)); } inject(true); }
vr::EVRInitError ServerDriver::Init(vr::IVRDriverContext *pDriverContext) { LOG(TRACE) << "CServerDriver::Init()"; // Initialize Hooking InterfaceHooks::setServerDriver(this); auto mhError = MH_Initialize(); if (mhError == MH_OK) { _driverContextHooks = InterfaceHooks::hookInterface(pDriverContext, "IVRDriverContext"); } else { LOG(ERROR) << "Error while initialising minHook: " << MH_StatusToString(mhError); } LOG(DEBUG) << "Initialize driver context."; VR_INIT_SERVER_DRIVER_CONTEXT(pDriverContext); // Read installation directory vr::ETrackedPropertyError tpeError; installDir = vr::VRProperties()->GetStringProperty(pDriverContext->GetDriverHandle(), vr::Prop_InstallPath_String, &tpeError); if (tpeError == vr::TrackedProp_Success) { LOG(INFO) << "Install Dir:" << installDir; } else { LOG(INFO) << "Could not get Install Dir: " << vr::VRPropertiesRaw()->GetPropErrorNameFromEnum(tpeError); } // Read vrsettings char buffer[vr::k_unMaxPropertyStringSize]; vr::EVRSettingsError peError; vr::VRSettings()->GetString(vrsettings_SectionName, vrsettings_overrideHmdManufacturer_string, buffer, vr::k_unMaxPropertyStringSize, &peError); if (peError == vr::VRSettingsError_None) { _propertiesOverrideHmdManufacturer = buffer; LOG(INFO) << vrsettings_SectionName << "::" << vrsettings_overrideHmdManufacturer_string << " = " << _propertiesOverrideHmdManufacturer; } vr::VRSettings()->GetString(vrsettings_SectionName, vrsettings_overrideHmdModel_string, buffer, vr::k_unMaxPropertyStringSize, &peError); if (peError == vr::VRSettingsError_None) { _propertiesOverrideHmdModel = buffer; LOG(INFO) << vrsettings_SectionName << "::" << vrsettings_overrideHmdModel_string << " = " << _propertiesOverrideHmdModel; } vr::VRSettings()->GetString(vrsettings_SectionName, vrsettings_overrideHmdTrackingSystem_string, buffer, vr::k_unMaxPropertyStringSize, &peError); if (peError == vr::VRSettingsError_None) { _propertiesOverrideHmdTrackingSystem = buffer; LOG(INFO) << vrsettings_SectionName << "::" << vrsettings_overrideHmdTrackingSystem_string << " = " << _propertiesOverrideHmdTrackingSystem; } auto boolVal = vr::VRSettings()->GetBool(vrsettings_SectionName, vrsettings_genericTrackerFakeController_bool, &peError); if (peError == vr::VRSettingsError_None) { _propertiesOverrideGenericTrackerFakeController = boolVal; LOG(INFO) << vrsettings_SectionName << "::" << vrsettings_genericTrackerFakeController_bool << " = " << boolVal; } // Start IPC thread shmCommunicator.init(this); return vr::VRInitError_None; }
/** * @brief Injects redirection code into the target function. * * @param force No-op in the MinHook-based HardHook implementation. */ void HardHook::inject(bool force) { if (!force) { // MinHook guarantees the presence of a trampoline, so // inject() and restore() are no-ops unless force is // set to true. return; } MH_STATUS status = MH_EnableHook((LPVOID)m_func); if (status != MH_OK) { fods("HardHook: inject() failed: MH_EnableHook returned %s", MH_StatusToString(status)); } }
DllImpl::~DllImpl() { auto status = MH_Uninitialize(); if (status != MH_OK) { logger->error("Unable to shutdown MinHook: {}", MH_StatusToString(status)); } if (mDllHandle) { if (!FreeLibrary(mDllHandle)) { logger->error("Unable to free the temple.dll library handle: {}", GetLastWin32Error()); } } }