Merge remote-tracking branch 'origin/develop' into 191-dedicated-server-optimization

This commit is contained in:
sr0 2017-02-23 21:37:22 +01:00
commit 3d2e8446f2
20 changed files with 229 additions and 109 deletions

2
.gitmodules vendored
View File

@ -34,7 +34,7 @@
[submodule "deps/protobuf"] [submodule "deps/protobuf"]
path = deps/protobuf path = deps/protobuf
url = https://github.com/google/protobuf.git url = https://github.com/google/protobuf.git
branch = 3.2.x branch = master
[submodule "deps/WinToast"] [submodule "deps/WinToast"]
path = deps/WinToast path = deps/WinToast
url = https://github.com/mohabouje/WinToast.git url = https://github.com/mohabouje/WinToast.git

2
deps/libtomcrypt vendored

@ -1 +1 @@
Subproject commit ef023f3329c44ec8afca29b9a56bae684daa88d9 Subproject commit c39390dba1dc519988fe8f6b1af6fdec24f86fc5

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit fa925b98937bafee6b5d7244cce5c1ad39bf9d36 Subproject commit 17174b54ddd040a326dec6db75d1bfb5e5b3caa9

View File

@ -26,7 +26,7 @@ namespace Components
char** Console::GetAutoCompleteFileList(const char *path, const char *extension, Game::FsListBehavior_e behavior, int *numfiles, int allocTrackType) char** Console::GetAutoCompleteFileList(const char *path, const char *extension, Game::FsListBehavior_e behavior, int *numfiles, int allocTrackType)
{ {
if (path == reinterpret_cast<char*>(0xBAADF00D) || path == reinterpret_cast<char*>(0xCDCDCDCD) || IsBadReadPtr(path, 1)) return nullptr; if (path == reinterpret_cast<char*>(0xBAADF00D) || path == reinterpret_cast<char*>(0xCDCDCDCD) || ::Utils::Memory::IsBadReadPtr(path)) return nullptr;
return Game::FS_GetFileList(path, extension, behavior, numfiles, allocTrackType); return Game::FS_GetFileList(path, extension, behavior, numfiles, allocTrackType);
} }

View File

@ -569,6 +569,8 @@ namespace Components
HRESULT D3D9Ex::D3D9Device::SetPixelShaderConstantF(UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) HRESULT D3D9Ex::D3D9Device::SetPixelShaderConstantF(UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount)
{ {
// Use real bad readptr check here, cause the query takes too long
// TODO: Fix the actual error!
if (IsBadReadPtr(pConstantData, Vector4fCount * 16)) if (IsBadReadPtr(pConstantData, Vector4fCount * 16))
{ {
//Logger::Print("Invalid shader constant array!\n"); //Logger::Print("Invalid shader constant array!\n");

View File

@ -251,7 +251,14 @@ namespace Components
int FileSystem::ExecIsFSStub(const char* execFilename) int FileSystem::ExecIsFSStub(const char* execFilename)
{ {
return !File(execFilename).exists(); bool result = !File(execFilename).exists();
if(execFilename =="mp/stats_init.cfg"s)
{
OutputDebugStringA("");
}
return result;
} }
void FileSystem::FsStartupSync(const char* a1) void FileSystem::FsStartupSync(const char* a1)
@ -290,6 +297,9 @@ namespace Components
// Filesystem config checks // Filesystem config checks
Utils::Hook(0x6098FD, FileSystem::ExecIsFSStub, HOOK_CALL).install()->quick(); Utils::Hook(0x6098FD, FileSystem::ExecIsFSStub, HOOK_CALL).install()->quick();
// Don't strip the folders from the config name (otherwise our ExecIsFSStub fails)
Utils::Hook::Nop(0x6098F2, 5);
// Register additional folders // Register additional folders
Utils::Hook(0x482647, FileSystem::StartupStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x482647, FileSystem::StartupStub, HOOK_JUMP).install()->quick();

View File

@ -260,6 +260,25 @@ namespace Components
Utils::Hook(0x4CE5EE, Localization::SetStringStub, HOOK_CALL).install()->quick(); Utils::Hook(0x4CE5EE, Localization::SetStringStub, HOOK_CALL).install()->quick();
Localization::UseLocalization = Dvar::Register<bool>("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings"); Localization::UseLocalization = Dvar::Register<bool>("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings");
// Generate localized entries for custom classes above 10
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, std::string name, bool* /*restrict*/)
{
if (type != Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY) return;
if(name == "CLASS_SLOT1"s)
{
for(int i = 11; i <= NUM_CUSTOM_CLASSES; ++i)
{
std::string key = Utils::String::VA("CLASS_SLOT%i", i);
std::string value = asset.localize->value;
Utils::String::Replace(value, "1", Utils::String::VA("%i", i)); // Pretty ugly, but it should work
Localization::Set(key, value);
}
}
});
} }
Localization::~Localization() Localization::~Localization()

View File

@ -276,7 +276,17 @@ namespace Components
{ {
for (auto menu : Menus::CustomMenus) for (auto menu : Menus::CustomMenus)
{ {
Utils::Merge(&menus, Menus::LoadMenu(menu)); bool hasMenu = false;
for(auto &loadedMenu : menus)
{
if(loadedMenu->window.name == menu)
{
hasMenu = true;
break;
}
}
if(!hasMenu) Utils::Merge(&menus, Menus::LoadMenu(menu));
} }
} }
@ -710,6 +720,7 @@ namespace Components
Menus::Add("ui_mp/startup_messages.menu"); Menus::Add("ui_mp/startup_messages.menu");
Menus::Add("ui_mp/pc_store.menu"); Menus::Add("ui_mp/pc_store.menu");
Menus::Add("ui_mp/iw4x_credits.menu"); Menus::Add("ui_mp/iw4x_credits.menu");
Menus::Add("ui_mp/resetclass.menu");
} }
Menus::~Menus() Menus::~Menus()

View File

@ -17,6 +17,7 @@ namespace Components
Utils::Hook(0x59A6F8, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x59A6F8, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
Utils::Hook(0x57F1E6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x57F1E6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
Utils::Hook(0x57ED36, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x57ED36, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
//Utils::Hook(0x609832, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
// remove fs_game check for moddable rawfiles - allows non-fs_game to modify rawfiles // remove fs_game check for moddable rawfiles - allows non-fs_game to modify rawfiles
Utils::Hook::Nop(0x61AB76, 2); Utils::Hook::Nop(0x61AB76, 2);

View File

@ -116,9 +116,41 @@ namespace Components
} }
} }
bool StructuredData::UpdateVersionOffsets(Game::StructuredDataDefSet *set, Game::StructuredDataBuffer *buffer, Game::StructuredDataDef *whatever)
{
Game::StructuredDataDef* newDef = &set->defs[0];
Game::StructuredDataDef* oldDef = &set->defs[0];
for(unsigned int i = 0; i < set->defCount; ++i)
{
if(newDef->version < set->defs[i].version)
{
newDef = &set->defs[i];
}
if(set->defs[i].version == *reinterpret_cast<int*>(buffer->data))
{
oldDef = &set->defs[i];
}
}
if (newDef->version >= 159 && oldDef->version <= 158)
{
// this should move the data 320 bytes infront
std::memmove(&buffer->data[3963], &buffer->data[3643], oldDef->size - 3643);
}
// StructuredData_UpdateVersion
return Utils::Hook::Call<bool(void*, void*, void*)>(0x456830)(set, buffer, whatever);
}
StructuredData::StructuredData() StructuredData::StructuredData()
{ {
Utils::Hook::Set<BYTE>(0x60A2FE, 15); // 15 custom classes // Correctly upgrade stats
Utils::Hook(0x42F088, StructuredData::UpdateVersionOffsets, HOOK_CALL).install()->quick();
// 15 or more custom classes
Utils::Hook::Set<BYTE>(0x60A2FE, NUM_CUSTOM_CLASSES);
// Only execute this when building zones // Only execute this when building zones
if (!ZoneBuilder::IsEnabled()) return; if (!ZoneBuilder::IsEnabled()) return;
@ -126,7 +158,7 @@ namespace Components
AssetHandler::OnLoad([] (Game::XAssetType type, Game::XAssetHeader asset, std::string filename, bool* /*restrict*/) AssetHandler::OnLoad([] (Game::XAssetType type, Game::XAssetHeader asset, std::string filename, bool* /*restrict*/)
{ {
// Only intercept playerdatadef loading // Only intercept playerdatadef loading
if (filename != "mp/playerdata.def" || type != Game::XAssetType::ASSET_TYPE_STRUCTUREDDATADEF) return; if (type != Game::XAssetType::ASSET_TYPE_STRUCTUREDDATADEF || filename != "mp/playerdata.def") return;
// Store asset // Store asset
Game::StructuredDataDefSet* data = asset.structuredData; Game::StructuredDataDefSet* data = asset.structuredData;

View File

@ -31,6 +31,8 @@ namespace Components
#endif #endif
private: private:
static bool UpdateVersionOffsets(Game::StructuredDataDefSet *set, Game::StructuredDataBuffer *buffer, Game::StructuredDataDef *oldDef);
static void PatchPlayerDataEnum(Game::StructuredDataDef* data, PlayerDataType type, std::vector<std::string>& entries); static void PatchPlayerDataEnum(Game::StructuredDataDef* data, PlayerDataType type, std::vector<std::string>& entries);
static void PatchAdditionalData(Game::StructuredDataDef* data, std::unordered_map<std::string, std::string>& patches); static void PatchAdditionalData(Game::StructuredDataDef* data, std::unordered_map<std::string, std::string>& patches);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#define PROTOCOL 0x93 #define PROTOCOL 0x93
#define NUM_CUSTOM_CLASSES 15
// This allows us to compile our structures in IDA, for easier reversing :3 // This allows us to compile our structures in IDA, for easier reversing :3
#ifdef __cplusplus #ifdef __cplusplus
@ -1553,6 +1554,12 @@ namespace Game
StructuredDataDef *defs; StructuredDataDef *defs;
}; };
struct StructuredDataBuffer
{
char *data;
size_t size; // 8188
};
typedef struct typedef struct
{ {
StructuredDataDef* data; StructuredDataDef* data;

View File

@ -67,6 +67,10 @@ AssertSize(std::uint8_t, 1);
// Ensure pointers are 4 bytes in size (32-bit) // Ensure pointers are 4 bytes in size (32-bit)
static_assert(sizeof(intptr_t) == 4 && sizeof(void*) == 4 && sizeof(size_t) == 4, "This doesn't seem to be a 32-bit environment!"); static_assert(sizeof(intptr_t) == 4 && sizeof(void*) == 4 && sizeof(size_t) == 4, "This doesn't seem to be a 32-bit environment!");
#if !defined(_M_IX86)
#error "Invalid processor achritecture!"
#endif
extern "C" extern "C"
{ {
// Disable telemetry data logging // Disable telemetry data logging

View File

@ -49,6 +49,7 @@ template <size_t S> class Sizer { };
#pragma warning(disable: 4005) #pragma warning(disable: 4005)
#pragma warning(disable: 4091) #pragma warning(disable: 4091)
#pragma warning(disable: 4100) #pragma warning(disable: 4100)
#pragma warning(disable: 4244)
#pragma warning(disable: 4389) #pragma warning(disable: 4389)
#pragma warning(disable: 4702) #pragma warning(disable: 4702)
#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS #pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS

View File

@ -28,63 +28,87 @@ namespace Steam
std::function<Proxy::SteamFreeLastCallbackFn> Proxy::SteamFreeLastCallback; std::function<Proxy::SteamFreeLastCallbackFn> Proxy::SteamFreeLastCallback;
std::function<Proxy::SteamGetAPICallResultFn> Proxy::SteamGetAPICallResult; std::function<Proxy::SteamGetAPICallResultFn> Proxy::SteamGetAPICallResult;
void* Interface::getMethod(std::string method) std::pair<void*, uint16_t> Interface::getMethod(std::string method)
{ {
if(this->methodCache.find(method) != this->methodCache.end()) if(this->methodCache.find(method) != this->methodCache.end())
{ {
return this->methodCache[method]; return this->methodCache[method];
} }
void* methodPtr = Interface::lookupMethod(method); auto methodData = Interface::lookupMethod(method);
this->methodCache[method] = methodPtr; this->methodCache[method] = methodData;
return methodPtr; return methodData;
} }
void* Interface::lookupMethod(std::string method) std::pair<void*, uint16_t> Interface::lookupMethod(std::string method)
{
if (!::Utils::Memory::IsBadReadPtr(this->interfacePtr))
{ {
if (IsBadReadPtr(this->interfacePtr, 4)) return nullptr;
unsigned char** vftbl = *static_cast<unsigned char***>(this->interfacePtr); unsigned char** vftbl = *static_cast<unsigned char***>(this->interfacePtr);
while (!IsBadReadPtr(vftbl, 4) && !IsBadCodePtr((FARPROC(*vftbl)))) while (!::Utils::Memory::IsBadReadPtr(vftbl) && !::Utils::Memory::IsBadCodePtr((FARPROC(*vftbl))))
{ {
if(this->getMethodName(*vftbl) == method) return *vftbl; std::string name;
uint16_t params;
if (this->getMethodData(*vftbl, &name, &params) && name == method)
{
return{ *vftbl, params };
}
++vftbl; ++vftbl;
} }
return nullptr;
} }
size_t Interface::getMethodParamSize(void* method) return { nullptr, 0 };
{
unsigned char* methodPtr = static_cast<unsigned char*>(method);
for (; !IsBadReadPtr(methodPtr, 3); ++methodPtr)
{
if (methodPtr[0] == 0xC2 && methodPtr[2] == 0) // __stdcall return
{
return (static_cast<size_t>(methodPtr[1])/* / sizeof(void*)*/);
}
} }
return 0; bool Interface::getMethodData(unsigned char* methodPtr, std::string* name, uint16_t* params)
{
name->clear();
*params = 0;
if (::Utils::Memory::IsBadCodePtr(methodPtr)) return false;
ud_t ud;
ud_init(&ud);
ud_set_mode(&ud, 32);
ud_set_pc(&ud, reinterpret_cast<uint64_t>(methodPtr));
ud_set_input_buffer(&ud, reinterpret_cast<uint8_t*>(methodPtr), INT32_MAX);
while (true)
{
ud_disassemble(&ud);
if (ud_insn_mnemonic(&ud) == UD_Iret)
{
const ud_operand* operand = ud_insn_opr(&ud, 0);
if (!operand) break;
if (operand->type == UD_OP_IMM && operand->size == 16)
{
*params = operand->lval.uword;
return true;
} }
std::string Interface::getMethodName(unsigned char* methodPtr)
{
for(;!IsBadReadPtr(methodPtr, 3); ++methodPtr)
{
if(methodPtr[0] == 0x68) // Push
{
char* name = *reinterpret_cast<char**>(&methodPtr[1]);
if(!IsBadReadPtr(name, 1)) return name;
}
else if(methodPtr[0] == 0xC2 && methodPtr[2] == 0) // __stdcall return
{
break; break;
} }
if (ud_insn_mnemonic(&ud) == UD_Ipush && name->empty())
{
auto operand = ud_insn_opr(&ud, 0);
if (operand->type == UD_OP_IMM && operand->size == 32)
{
char* operandPtr = reinterpret_cast<char*>(operand->lval.udword);
if (!::Utils::Memory::IsBadReadPtr(operandPtr))
{
name->clear();
name->append(operandPtr);
}
}
}
} }
return ""; return false;
} }
void Proxy::SetGame(uint32_t appId) void Proxy::SetGame(uint32_t appId)
@ -123,23 +147,6 @@ namespace Steam
char* modId = "IW4x"; char* modId = "IW4x";
gameID.modID = *reinterpret_cast<unsigned int*>(modId) | 0x80000000; gameID.modID = *reinterpret_cast<unsigned int*>(modId) | 0x80000000;
// Interface clientApps(Proxy::ClientEngine->GetIClientApps(Proxy::SteamUser, Proxy::SteamPipe, "CLIENTAPPS_INTERFACE_VERSION001"));
// Interface clientShortcuts(Proxy::ClientEngine->GetIClientShortcuts(Proxy::SteamUser, Proxy::SteamPipe, "CLIENTSHORTCUTS_INTERFACE_VERSION001"));
// if (!clientApps || !clientShortcuts) return;
//
// KeyValuesBuilder builder;
// builder.packString("name", mod.data());
// builder.packUint64("gameid", gameID.bits);
// builder.packString("installed", "1");
// builder.packString("gamedir", "IW4x");
// builder.packString("serverbrowsername", "IW4x");
// builder.packEnd();
//
// std::string str = builder.getString();
// uint32_t uniqueId = clientShortcuts.invoke<uint32_t>("GetUniqueLocalAppId");
// if (clientApps.invoke<bool>("SetLocalAppConfig", uniqueId, str.data(), static_cast<uint32_t>(str.size())))
{
Interface clientUtils(Proxy::ClientEngine->GetIClientUtils(Proxy::SteamPipe, "CLIENTUTILS_INTERFACE_VERSION001")); Interface clientUtils(Proxy::ClientEngine->GetIClientUtils(Proxy::SteamPipe, "CLIENTUTILS_INTERFACE_VERSION001"));
clientUtils.invoke<void>("SetAppIDForCurrentPipe", Proxy::AppId, false); clientUtils.invoke<void>("SetAppIDForCurrentPipe", Proxy::AppId, false);
@ -156,18 +163,17 @@ namespace Steam
// Therefore we have to check how many bytes the method expects as arguments // Therefore we have to check how many bytes the method expects as arguments
// and adapt our call accordingly! // and adapt our call accordingly!
size_t expectedParams = Proxy::ClientUser.paramSize("SpawnProcess"); size_t expectedParams = Proxy::ClientUser.paramSize("SpawnProcess");
if(expectedParams == 40) // Release if (expectedParams == 40) // Release
{ {
Proxy::ClientUser.invoke<bool>("SpawnProcess", ourPath, cmdline.data(), 0, ourDirectory, gameID.bits, Proxy::AppId, mod.data(), 0, 0); Proxy::ClientUser.invoke<bool>("SpawnProcess", ourPath, cmdline.data(), 0, ourDirectory, gameID.bits, Proxy::AppId, mod.data(), 0, 0);
} }
else if(expectedParams == 36) // Beta else if (expectedParams == 36) // Beta
{ {
Proxy::ClientUser.invoke<bool>("SpawnProcess", ourPath, cmdline.data(), 0, ourDirectory, gameID.bits, mod.data(), 0, 0); Proxy::ClientUser.invoke<bool>("SpawnProcess", ourPath, cmdline.data(), 0, ourDirectory, gameID.bits, mod.data(), 0, 0);
} }
else if (expectedParams == 48) // Legacy, expects VAC blob else if (expectedParams == 48) // Legacy, expects VAC blob
{ {
char blob[8] = { 0 }; char blob[8] = { 0 };
Proxy::ClientUser.invoke<bool>("SpawnProcess", blob, 0, ourPath, cmdline.data(), 0, ourDirectory, gameID.bits, Proxy::AppId, mod.data(), 0, 0); Proxy::ClientUser.invoke<bool>("SpawnProcess", blob, 0, ourPath, cmdline.data(), 0, ourDirectory, gameID.bits, Proxy::AppId, mod.data(), 0, 0);
} }
else else
@ -175,7 +181,6 @@ namespace Steam
OutputDebugStringA("Steam proxy was unable to match the arguments for SpawnProcess!\n"); OutputDebugStringA("Steam proxy was unable to match the arguments for SpawnProcess!\n");
} }
} }
}
void Proxy::RunMod() void Proxy::RunMod()
{ {
@ -322,11 +327,7 @@ namespace Steam
void Proxy::StartSteamIfNecessary() void Proxy::StartSteamIfNecessary()
{ {
if (Proxy::GetSteamDirectory().empty() if (Proxy::GetSteamDirectory().empty() || !Steam::Enabled()) return;
#ifndef DEBUG
|| !Steam::Enabled()
#endif
) return;
HKEY hRegKey; HKEY hRegKey;
DWORD pid = 0; DWORD pid = 0;

View File

@ -146,14 +146,14 @@ namespace Steam
return T(); return T();
} }
void* method = this->getMethod(methodName); auto method = this->getMethod(methodName);
if (!method) if (!method.first)
{ {
OutputDebugStringA(::Utils::String::VA("Steam interface method %s not found!\n", methodName.data())); OutputDebugStringA(::Utils::String::VA("Steam interface method %s not found!\n", methodName.data()));
return T(); return T();
} }
size_t argc = this->getMethodParamSize(method); size_t argc = method.second;
constexpr size_t passedArgc = Interface::AddSizes<sizeof(Args)...>::value; constexpr size_t passedArgc = Interface::AddSizes<sizeof(Args)...>::value;
if(passedArgc != argc) if(passedArgc != argc)
{ {
@ -161,7 +161,7 @@ namespace Steam
return T(); return T();
} }
return reinterpret_cast<T(__thiscall*)(void*, Args ...)>(method)(this->interfacePtr, args...); return reinterpret_cast<T(__thiscall*)(void*, Args ...)>(method.first)(this->interfacePtr, args...);
} }
explicit operator bool() const explicit operator bool() const
@ -171,14 +171,12 @@ namespace Steam
size_t paramSize(std::string methodName) size_t paramSize(std::string methodName)
{ {
void* method = this->getMethod(methodName); auto method = this->getMethod(methodName);
if (method) return this->getMethodParamSize(method); return method.second;
return 0;
} }
private: private:
// TODO: Use fold expressions in C++17 once available // TODO: Use fold expressions once available (C++17)
template<std::size_t ...> template<std::size_t ...>
struct AddSizes : std::integral_constant<std::size_t, 0> {}; struct AddSizes : std::integral_constant<std::size_t, 0> {};
@ -187,11 +185,10 @@ namespace Steam
struct AddSizes<X, Xs...> : std::integral_constant<std::size_t, X + ((AddSizes<Xs...>::value + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1))> {}; struct AddSizes<X, Xs...> : std::integral_constant<std::size_t, X + ((AddSizes<Xs...>::value + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1))> {};
void* interfacePtr; void* interfacePtr;
std::unordered_map<std::string, void*> methodCache; std::unordered_map<std::string, std::pair<void*, uint16_t>> methodCache;
void* getMethod(std::string method); std::pair<void*, uint16_t> getMethod(std::string method);
void* lookupMethod(std::string method); std::pair<void*, uint16_t> lookupMethod(std::string method);
size_t getMethodParamSize(void* method); bool getMethodData(unsigned char* methodPtr, std::string* name, uint16_t* params);
std::string getMethodName(unsigned char* methodPtr);
}; };
class KeyValuesBuilder class KeyValuesBuilder

View File

@ -64,4 +64,34 @@ namespace Utils
return true; return true;
} }
bool Memory::IsBadReadPtr(const void* ptr)
{
MEMORY_BASIC_INFORMATION mbi = { nullptr };
if (VirtualQuery(ptr, &mbi, sizeof(mbi)))
{
DWORD mask = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
bool b = !(mbi.Protect & mask);
// check the page is not a guard page
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true;
return b;
}
return true;
}
bool Memory::IsBadCodePtr(const void* ptr)
{
MEMORY_BASIC_INFORMATION mbi = { nullptr };
if (VirtualQuery(ptr, &mbi, sizeof(mbi)))
{
DWORD mask = (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
bool b = !(mbi.Protect & mask);
// check the page is not a guard page
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true;
return b;
}
return true;
}
} }

View File

@ -130,5 +130,8 @@ namespace Utils
static void FreeAlign(const void* data); static void FreeAlign(const void* data);
static bool IsSet(void* mem, char chr, size_t length); static bool IsSet(void* mem, char chr, size_t length);
static bool IsBadReadPtr(const void* ptr);
static bool IsBadCodePtr(const void* ptr);
}; };
} }

Binary file not shown.

Binary file not shown.