Skip to content

Commit

Permalink
メンバ関数ポインタ使う方式に変更
Browse files Browse the repository at this point in the history
  • Loading branch information
i-saint committed Oct 4, 2012
1 parent 8a223b3 commit 76c3766
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 53 deletions.
4 changes: 2 additions & 2 deletions ReloadClass/after.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define IMPLEMENT_MODULE
#include "module.h"

void MODULE_API Hoge::doSomething()
DEFINE_MODULE_MEMFUN(void, Hoge, doSomething, ())
{
printf("Hoge::doSomething() after: %d\n", m_data);
printf("Hoge::doSomethingImpl() after: %d\n", m_data);
}
4 changes: 2 additions & 2 deletions ReloadClass/before.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define IMPLEMENT_MODULE
#include "module.h"

void MODULE_API Hoge::doSomething()
DEFINE_MODULE_MEMFUN(void, Hoge, doSomething, ())
{
printf("Hoge::doSomething() before: %d\n", m_data);
printf("Hoge::doSomethingImpl() before: %d\n", m_data);
}
61 changes: 13 additions & 48 deletions ReloadClass/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,23 @@ Hoge::~Hoge()
{
}

DEFINE_MAIN_MEMFUN(void, Hoge, doSomething, ());


// write protect がかかったメモリ領域を強引に書き換える
template<class T>
inline void ForceWrite(T &dst, const T &src)


template<class To, class From>
To ForceCast(From from)
{
DWORD old_flag;
VirtualProtect(&dst, sizeof(T), PAGE_EXECUTE_READWRITE, &old_flag);
dst = src;
VirtualProtect(&dst, sizeof(T), old_flag, &old_flag);
union { From from; To to; } u;
u.from = from;
return u.to;
}

// dllname: 大文字小文字区別しません
// F: functor。引数は (const char *funcname, void *&imp_func)
template<class F>
bool EachImportFunction(HMODULE module, const char *dllname, const F &f)
template<class To, class From>
To ForceCast(From from, To /*型推測のためだけの引数*/)
{
if(module==0) { return false; }

size_t ImageBase = (size_t)module;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE) { return false; }
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)(ImageBase + pDosHeader->e_lfanew);

size_t RVAImports = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if(RVAImports==0) { return false; }

IMAGE_IMPORT_DESCRIPTOR *pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)(ImageBase + RVAImports);
while(pImportDesc->Name != 0) {
if(stricmp((const char*)(ImageBase+pImportDesc->Name), dllname)==0) {
IMAGE_IMPORT_BY_NAME **func_names = (IMAGE_IMPORT_BY_NAME**)(ImageBase+pImportDesc->Characteristics);
void **import_table = (void**)(ImageBase+pImportDesc->FirstThunk);
for(size_t i=0; ; ++i) {
if((size_t)func_names[i] == 0) { break;}
const char *funcname = (const char*)(ImageBase+(size_t)func_names[i]->Name);
f(funcname, import_table[i]);
}
}
++pImportDesc;
}
return true;
return ForceCast<To, From>(from);
}


Expand All @@ -63,21 +39,10 @@ int main()
hoge.doSomething();

{
const char mangled_func_name[] =
#ifdef _WIN64
"?doSomething@Hoge@@QEAAXXZ";
#else
"?doSomething@Hoge@@QAEXXZ";
#endif
HMODULE module_main = ::GetModuleHandle("main.exe");
HMODULE module_after = ::LoadLibrary("after.dll");
void *replacement = ::GetProcAddress(module_after, mangled_func_name);

EachImportFunction(module_main, "before.dll", [&](const char *funcname, void *&imp_func){
if(strcmp(funcname, mangled_func_name)==0) {
ForceWrite<void*>(imp_func, replacement);
}
});
printf("%s\n", g_Hoge_doSomething_Name);
g_Hoge_doSomething = *ForceCast(::GetProcAddress(module_after, g_Hoge_doSomething_Name), &g_Hoge_doSomething);
}

hoge.doSomething();
Expand Down
14 changes: 13 additions & 1 deletion ReloadClass/module.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
#define DECLARE_MODULE_MEMFUN(Ret, Class, Name, Args)\
Ret MODULE_API Name##Impl##Args;\
Ret Name##Args;

#ifdef IMPLEMENT_MODULE
# define MODULE_API __declspec(dllexport)
# define DEFINE_MODULE_MEMFUN(Ret, Class, Name, Args)\
extern "C" MODULE_API void (Class::*g_##Class##_##Name)() = &Class::Name##Impl;\
Ret Class::Name##Impl##Args
#else
# define MODULE_API __declspec(dllimport)
# define DEFINE_MAIN_MEMFUN(Ret, Class, Name, Args)\
Ret (Class::*g_##Class##_##Name)() = &Class::Name##Impl;\
const char g_##Class##_##Name##_Name[] = "g_" #Class "_" #Name;\
Ret Class::Name##Args { (this->*g_##Class##_##Name)(); }
#endif



class Hoge
{
public:
Hoge();
~Hoge();

void MODULE_API doSomething();
DECLARE_MODULE_MEMFUN(void, Hoge, doSomething, ());

private:
int m_data;
Expand Down

0 comments on commit 76c3766

Please sign in to comment.