87 lines
2.6 KiB
C++
87 lines
2.6 KiB
C++
// Copyright 2020-2023 The Mumble Developers. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file at the root of the
|
|
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
#ifndef MUMBLE_MUMBLE_PLUGIN_SE_COMMON_
|
|
#define MUMBLE_MUMBLE_PLUGIN_SE_COMMON_
|
|
|
|
typedef std::map< std::string, procptr_t > Interfaces;
|
|
|
|
struct InterfaceReg {
|
|
uint32_t createFunction;
|
|
uint32_t name;
|
|
uint32_t next;
|
|
};
|
|
|
|
static Interfaces getInterfaces(const procptr_t module) {
|
|
Interfaces interfaces;
|
|
|
|
// s_pInterfaceRegs is exported on Linux
|
|
auto s_pInterfaceRegs = proc->exportedSymbol("s_pInterfaceRegs", module);
|
|
if (!s_pInterfaceRegs) {
|
|
const auto CreateInterface = proc->exportedSymbol("CreateInterface", module);
|
|
if (CreateInterface == 0) {
|
|
return interfaces;
|
|
}
|
|
|
|
bool jmpOnly;
|
|
|
|
if (proc->peek< uint8_t >(CreateInterface) == 0xE9) {
|
|
// Left 4 Dead:
|
|
// E9 ?? ?? ?? ?? jmp CreateInterface_0
|
|
jmpOnly = true;
|
|
} else {
|
|
// Other games:
|
|
// 55 push ebp
|
|
// 8B EC mov ebp, esp
|
|
// 5D pop ebp
|
|
// E9 ?? ?? ?? ?? jmp CreateInterfaceInternal
|
|
jmpOnly = false;
|
|
}
|
|
|
|
const auto jmpTarget = proc->peek< int32_t >(CreateInterface + (jmpOnly ? 1 : 5));
|
|
const auto jmpInstructionEnd = CreateInterface + (jmpOnly ? 5 : 9);
|
|
const auto CreateInterfaceInternal = jmpInstructionEnd + jmpTarget;
|
|
|
|
// Left 4 Dead:
|
|
// 56 push esi
|
|
// 8B 35 ?? ?? ?? ?? mov esi, s_pInterfaceRegs
|
|
// 85 F6 test esi, esi
|
|
// 57 push edi
|
|
//
|
|
// Other games:
|
|
// 55 push ebp
|
|
// 8B EC mov ebp, esp
|
|
// 56 push esi
|
|
// 8B 35 ?? ?? ?? ?? mov esi, s_pInterfaceRegs
|
|
if (proc->peek< uint16_t >(CreateInterfaceInternal + (jmpOnly ? 1 : 4)) != 0x358B) {
|
|
return interfaces;
|
|
}
|
|
|
|
s_pInterfaceRegs = proc->peek< uint32_t >(CreateInterfaceInternal + (jmpOnly ? 3 : 6));
|
|
}
|
|
|
|
auto iface = proc->peek< InterfaceReg >(proc->peekPtr(s_pInterfaceRegs));
|
|
|
|
do {
|
|
const auto name = proc->peekString(iface.name);
|
|
const auto address = proc->peek< uint32_t >(iface.createFunction + (isWin32 ? 1 : 2));
|
|
|
|
interfaces.insert(Interfaces::value_type(name, address));
|
|
} while (iface.next && proc->peek(iface.next, iface));
|
|
|
|
return interfaces;
|
|
}
|
|
|
|
static procptr_t getInterfaceAddress(const std::string &name, const Interfaces &interfaces) {
|
|
const auto iface = interfaces.find(name);
|
|
if (iface == interfaces.end()) {
|
|
return 0;
|
|
}
|
|
|
|
return iface->second;
|
|
}
|
|
|
|
#endif
|