Skip to content

Commit

Permalink
Fix HookManager and ComHook.
Browse files Browse the repository at this point in the history
  • Loading branch information
rhcad committed Nov 2, 2011
1 parent 71d7864 commit 3e3b8e6
Show file tree
Hide file tree
Showing 20 changed files with 214 additions and 100 deletions.
3 changes: 0 additions & 3 deletions code/pkg_AppUI/Interface/FrameApp/FrameAppImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ BOOL CFrameApp::InitInstance()
CWinApp::InitInstance();
VERIFY(AfxOleInit());

CoInitialize(NULL);
CoCreateInstance(IID_IUnknown, NULL, 0, IID_IUnknown, NULL); // for ComHook.plugin

return LoadPlugins()
&& CheckAppInstance()
&& CreateFrameWnd();
Expand Down
6 changes: 3 additions & 3 deletions code/pkg_Core/Interface/PluginManager/Ix_PluginLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class Ix_PluginLoader : public Ix_Object
//! Register a plugin (not load dll).
/*! It can used to static-link dll or main appliction module.
\param instance the module to register.
\return if register success.
\return true if register successful.
\note need to call InitializePlugins() after.
\see InitializePlugins
*/
Expand All @@ -82,7 +82,7 @@ class Ix_PluginLoader : public Ix_Object
//! Load a plugin.
/*! Use LoadLibraryEx() and RegisterPlugin() to load.
\param filename absolute file name or relative to the application.
\return if load success.
\return true if load successful.
\note need to call InitializePlugins() after.
\see InitializePlugins
*/
Expand All @@ -91,7 +91,7 @@ class Ix_PluginLoader : public Ix_Object
//! Unload a plugin.
/*! Automatic call plugin's x3CanUnloadPlugin() and x3UninitializePlugin() export functions.
\param name plugin filename regardless folder, such as 'MyData.plugin.dll'.
\return if unload success.
\return true if unload successful.
\see optional export function: OUTAPI void x3UninitializePlugin()
*/
virtual bool UnloadPlugin(const wchar_t* name) = 0;
Expand Down
15 changes: 12 additions & 3 deletions code/pkg_Core/Interface/UtilFunc/LoadDllHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class LoadDllHelper
\param assign a optional pointer to a variable that receives the library handle.
*/
LoadDllHelper(const wchar_t* filename = NULL, HMODULE* assign = NULL)
: m_hmod(NULL), m_assign(assign)
: m_hmod(NULL), m_assign(assign), m_loadnew(false)
{
if (filename)
{
Expand All @@ -39,7 +39,10 @@ class LoadDllHelper
{
if (m_hmod)
{
FreeLibrary(m_hmod);
if (m_loadnew)
{
FreeLibrary(m_hmod);
}
m_hmod = NULL;

if (m_assign)
Expand All @@ -54,7 +57,12 @@ class LoadDllHelper
{
Unload();

m_hmod = LoadLibraryW(filename);
m_hmod = GetModuleHandleW(filename);
m_loadnew = !m_hmod;
if (!m_hmod)
{
m_hmod = LoadLibraryW(filename);
}
if (m_assign)
{
*m_assign = m_hmod;
Expand All @@ -78,6 +86,7 @@ class LoadDllHelper
private:
HMODULE m_hmod;
HMODULE* m_assign;
bool m_loadnew;
};

#endif // UTILFUNC_LOADDLLHELPER_H_
3 changes: 1 addition & 2 deletions code/pkg_Example/Modules/SimpleApp/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ int main()

if (loader.LoadPluginManager(L"../plugins"))
{
loader.GetPluginLoader()->LoadPluginFiles(L"../plugins",
L"Win32DllTempl.plugin" PLNEXT);
loader.GetPluginLoader()->LoadPlugins(L"../plugins");
loader.GetPluginLoader()->InitializePlugins();

Test();
Expand Down
37 changes: 33 additions & 4 deletions code/pkg_Platform/Interface/Ix_HookManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,40 @@ class Ix_HookManager : public Ix_Object
public:
X3DEFINE_IID(Ix_HookManager)

virtual bool HookProc(PROC oldproc, PROC newproc) = 0;
virtual bool UnhookProc(PROC newproc) = 0;
//! Replace a API function in the import directory of all plugins.
/*! The functions and module are all in the current process.
\param dllname Valid name of the module imported by any plugin.
\param func Function name of the module of 'dllname'.
\param newproc A function to be used to replace.
\return how many plugins are replaced.
*/
virtual long HookPlugins(LPCWSTR dllname, LPCSTR func, PROC newproc) = 0;

virtual bool HookProc(LPCWSTR dllname, LPCSTR func, PROC newproc) = 0;
virtual bool UnhookProc(LPCWSTR dllname, LPCSTR funcname) = 0;
//! Restore a API function in the import directory of all plugins.
/*!
\param newproc A function which has been used to replace.
\return how many plugins are replaced.
*/
virtual long UnhookPlugins(PROC newproc) = 0;

//! Replace a API function in the import directory of the specified module.
/*! The functions and module are all in the current process.
\param oldproc A function to be replaced.
\param newproc A function to be used to replace.
\param hmod The specified module whose import directory will be replaced.
If hmod is null then use the main application module.
\return true if replaced successful.
*/
virtual bool HookProc(PROC oldproc, PROC newproc, HMODULE hmod = NULL) = 0;

//! Restore a API function in the import directory of the specified module.
/*!
\param newproc A function which has been used to replace.
\param hmod The specified module whose import directory will be replaced.
If hmod is null then use the main application module.
\return true if replaced successful.
*/
virtual bool UnhookProc(PROC newproc, HMODULE hmod = NULL) = 0;
};

#endif // X3_UTIL_IHOOKMANAGER_H_
7 changes: 0 additions & 7 deletions code/pkg_Platform/Modules/ComHook/ApiHook.h

This file was deleted.

18 changes: 11 additions & 7 deletions code/pkg_Platform/Modules/ComHook/ComCreator.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
#include <UtilFunc/PluginInc.h>
#include "ComCreator.h"
#include "ApiHook.h"
#include "ComFileMap.h"
#include "../Public/ApiHook.h"

static const PROC s_oldfunc = (PROC)CoCreateInstance;
static CComFileMap s_filemap;
static CComModules s_modules;

bool CComCreator::Init()
{
return HookModuleFunction("ole32.dll", s_oldfunc, (PROC)Hook_CoCreateInstance);
}

void CComCreator::Free()
{
HookModuleFunction("ole32.dll", (PROC)Hook_CoCreateInstance, s_oldfunc);
s_modules.Free();
s_filemap.Free();
}

bool CComCreator::Hook(HMODULE hmod)
{
return HookModuleFunction("ole32.dll", s_oldfunc, (PROC)Hook_CoCreateInstance, hmod);
}

bool CComCreator::Unhook(HMODULE hmod)
{
return HookModuleFunction("ole32.dll", (PROC)Hook_CoCreateInstance, s_oldfunc, hmod);
}

HRESULT WINAPI CComCreator::Hook_CoCreateInstance(
REFCLSID rclsid,
LPUNKNOWN pUnkOuter, DWORD context,
Expand Down
6 changes: 2 additions & 4 deletions code/pkg_Platform/Modules/ComHook/ComCreator.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
class CComCreator
{
public:
//! Replace API functions of the current process to hook CoCreateInstance.
static bool Init();

//! Restore API functions of the current process and unload COM modules.
static void Free();
static bool Hook(HMODULE hmod);
static bool Unhook(HMODULE hmod);

private:
static HRESULT WINAPI Hook_CoCreateInstance(REFCLSID rclsid,
Expand Down
31 changes: 30 additions & 1 deletion code/pkg_Platform/Modules/ComHook/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,45 @@
#include <Module/XModuleImpl.h>

#include "ComCreator.h"
#include <PluginManager/Ix_PluginLoader2.h>

XBEGIN_DEFINE_MODULE()
XEND_DEFINE_MODULE_DLL()

OUTAPI bool x3InitializePlugin()
{
return CComCreator::Init();
Cx_Interface<Ix_PluginLoader2> loader(x3GetObjectFactory());
HMODULE hmod;
std::wstring file;
int count = 0;

for (int i = 1; loader->GetPluginFileName(i, hmod, file); i++)
{
if (CComCreator::Hook(hmod))
{
count++;
}
}
if (CComCreator::Hook(NULL))
{
count++;
}

return true;
}

OUTAPI void x3UninitializePlugin()
{
Cx_Interface<Ix_PluginLoader2> loader(x3GetObjectFactory());
HMODULE hmod;
std::wstring file;
int count = 0;

for (int i = 0; loader->GetPluginFileName(i, hmod, file); i++)
{
count += CComCreator::Unhook(hmod) ? 1 : 0;
}
count += CComCreator::Unhook(NULL) ? 1 : 0;

CComCreator::Free();
}
94 changes: 56 additions & 38 deletions code/pkg_Platform/Modules/HookManager/Cx_HookManager.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// x3c - C++ PluginFramework
#include <UtilFunc/PluginInc.h>
#include "Cx_HookManager.h"
#include "../ComHook/ApiHook.cpp"
#include "../Public/ApiHook.h"
#include <UtilFunc/LoadDllHelper.h>
#include <PluginManager/Ix_PluginLoader2.h>
#include <Module/Ix_Module.h>

Ix_ObjectFactory* x3GetObjectFactory();

Cx_HookManager::Cx_HookManager()
{
Expand All @@ -11,72 +16,85 @@ Cx_HookManager::~Cx_HookManager()
{
while (!m_new2old.empty())
{
VERIFY(UnhookProc(m_new2old.begin()->first));
KEY k = m_new2old.begin()->first;
VERIFY(UnhookProc(k.first, k.second));
}
ASSERT(m_dlls.empty());
}

bool Cx_HookManager::HookProc(PROC oldproc, PROC newproc)
bool Cx_HookManager::HookProc(PROC oldproc, PROC newproc, HMODULE hmod)
{
ASSERT(oldproc && newproc && oldproc != newproc);

if (HookModuleFunction(NULL, oldproc, newproc))
if (HookModuleFunction(NULL, oldproc, newproc, hmod))
{
m_new2old[newproc] = oldproc;
m_new2old[KEY(newproc, hmod)] = oldproc;
return true;
}

return false;
}

bool Cx_HookManager::UnhookProc(PROC newproc)
bool Cx_HookManager::UnhookProc(PROC newproc, HMODULE hmod)
{
std::map<PROC, PROC>::iterator it = m_new2old.find(newproc);
std::map<KEY, PROC>::iterator it = m_new2old.find(KEY(newproc, hmod));
bool ret = false;

if (it != m_new2old.end())
{
VERIFY(HookModuleFunction(NULL, it->second, newproc));
ret = HookModuleFunction(NULL, newproc, it->second, hmod);
m_new2old.erase(it);

std::map<PROC, HMODULE>::iterator it2 = m_dlls.find(newproc);
if (it2 != m_dlls.end())
{
FreeLibrary(it2->second);
m_dlls.erase(it2);
}

return true;
}

return false;
return ret;
}

bool Cx_HookManager::HookProc(LPCWSTR dllname, LPCSTR func, PROC newproc)
long Cx_HookManager::HookPlugins(LPCWSTR dllname, LPCSTR func, PROC newproc)
{
HMODULE hdll = GetModuleHandleW(dllname);
bool add = false;
ASSERT(dllname && *dllname && newproc);
long count = 0;
LoadDllHelper dll(dllname);
PROC oldproc = dll.GetFunc(func);

if (NULL == hdll)
if (oldproc)
{
hdll = x3LoadLibrary(dllname);
add = !!hdll;
Cx_Interface<Ix_PluginLoader2> loader(x3GetObjectFactory());
HMODULE hmod;
std::wstring file;

for (int i = 0; loader->GetPluginFileName(i, hmod, file); i++)
{
if (HookProc(oldproc, newproc, hmod))
{
count++;
}
}
if (HookProc(oldproc, newproc, NULL))
{
count++;
}
}

bool ret = HookProc(GetProcAddress(hdll, func), newproc);
return count;
}

if (add)
long Cx_HookManager::UnhookPlugins(PROC newproc)
{
long count = 0;
Cx_Interface<Ix_PluginLoader2> loader(x3GetObjectFactory());
HMODULE hmod;
std::wstring file;

for (int i = 0; loader->GetPluginFileName(i, hmod, file); i++)
{
if (ret)
m_dlls[newproc] = hdll;
else
FreeLibrary(hdll);
if (UnhookProc(newproc, hmod))
{
count++;
}
}
if (UnhookProc(newproc, NULL))
{
count++;
}

return ret;
}

bool Cx_HookManager::UnhookProc(LPCWSTR dllname, LPCSTR funcname)
{
HMODULE hdll = GetModuleHandleW(dllname);
return UnhookProc(GetProcAddress(hdll, funcname));
return count;
}
12 changes: 6 additions & 6 deletions code/pkg_Platform/Modules/HookManager/Cx_HookManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class Cx_HookManager : public Ix_HookManager
~Cx_HookManager();

private:
virtual bool HookProc(PROC oldproc, PROC newproc);
virtual bool UnhookProc(PROC newproc);
virtual bool HookProc(LPCWSTR dllname, LPCSTR func, PROC newproc);
virtual bool UnhookProc(LPCWSTR dllname, LPCSTR funcname);
virtual long HookPlugins(LPCWSTR dllname, LPCSTR func, PROC newproc);
virtual long UnhookPlugins(PROC newproc);
virtual bool HookProc(PROC oldproc, PROC newproc, HMODULE hmod = NULL);
virtual bool UnhookProc(PROC newproc, HMODULE hmod = NULL);

private:
std::map<PROC, HMODULE> m_dlls;
std::map<PROC, PROC> m_new2old;
typedef std::pair<PROC, HMODULE> KEY;
std::map<KEY, PROC> m_new2old;
};

#endif // _X3_HOOKMANAGER_IMPL_H
Loading

0 comments on commit 3e3b8e6

Please sign in to comment.