* add svn ignore
[ezgdi.git] / ezgdi / hook.cpp
blob975d88a7859b930c86609ced4e2baf3a0e19000f
1 #include "stdafx.h"
3 #include "override.h"
4 #include "ft.h"
5 #include "fteng.h"
7 #include <locale.h>
9 #ifdef USE_DETOURS
10 #include <detours.h>
12 /* define ORIG_* WIN32 API prototype */
13 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
14 rettype (WINAPI * ORIG_##name) argtype;
15 #include "hooklist.h"
16 #undef HOOK_DEFINE
18 /* initialize ORIG_* with proc address */
19 static void hook_initinternal()
21 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
22 ORIG_##name = name;
23 #include "hooklist.h"
24 #undef HOOK_DEFINE
27 /* install IMPL_* hooks to replace ORIG_* */
28 static void hook_init()
30 DetourRestoreAfterWith();
32 DetourTransactionBegin();
33 DetourUpdateThread(GetCurrentThread());
35 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
36 DetourAttach(&(PVOID&)ORIG_##name, IMPL_##name);
37 #include "hooklist.h"
38 #undef HOOK_DEFINE
40 LONG error = DetourTransactionCommit();
42 if (error != NOERROR) {
43 TRACE(_T("hook_init error: %#x\n"), error);
47 static void hook_term()
49 DetourTransactionBegin();
50 DetourUpdateThread(GetCurrentThread());
52 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
53 DetourDetach(&(PVOID&)ORIG_##name, IMPL_##name);
54 #include "hooklist.h"
55 #undef HOOK_DEFINE
57 LONG error = DetourTransactionCommit();
59 if (error != NOERROR) {
60 TRACE(_T("hook_term error: %#x\n"), error);
64 #else /* EASYHOOK */
66 #include <easyhook.h>
68 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
69 HOOK_TRACE_INFO HOOK_##name; \
70 rettype (WINAPI * FUNC_##name) argtype = NULL; \
71 rettype (WINAPI * ORIG_##name) argtype = NULL; \
72 rettype WINAPI OLD_##name argtype { \
73 ULONG ACLEntries[] = {0}; \
74 LhSetExclusiveACL(ACLEntries, 1, &HOOK_##name); \
75 rettype retval = ##name arglist; \
76 LhSetExclusiveACL(ACLEntries, 0, &HOOK_##name); \
77 return retval; \
79 #include "hooklist.h"
80 #undef HOOK_DEFINE
82 static FARPROC GetProcAddressInDll(LPCTSTR lpczDllName, LPCSTR lpczProcName)
84 HMODULE hDLL = LoadLibrary(lpczDllName);
85 if (hDLL == NULL)
86 return NULL;
87 FARPROC lpProc = GetProcAddress(hDLL, lpczProcName);
88 FreeLibrary(hDLL);
89 return lpProc;
92 static void hook_initinternal()
94 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
95 FUNC_##name = (rettype (WINAPI *) argtype) GetProcAddressInDll(_T(#modname) _T(".dll"), #name); \
96 ORIG_##name = OLD_##name;
97 #include "hooklist.h"
98 #undef HOOK_DEFINE
101 #define FORCE(expr) {if(!SUCCEEDED(NtStatus = (expr))) goto ERROR_ABORT;}
103 static void hook_init()
105 ULONG ACLEntries[1] = {0};
106 NTSTATUS NtStatus;
108 #define HOOK_DEFINE(modname, name, rettype, argtype, arglist) \
109 FORCE(LhInstallHook(FUNC_##name, IMPL_##name, (PVOID)0, &HOOK_##name));\
110 FORCE(LhSetExclusiveACL(ACLEntries, 0, &HOOK_##name));
111 #include "hooklist.h"
112 #undef HOOK_DEFINE
114 FORCE(LhSetGlobalExclusiveACL(ACLEntries, 0));
115 return;
117 ERROR_ABORT:
118 TRACE(_T("hook_init error: %#x\n"), NtStatus);
122 static void hook_term()
124 LhUninstallAllHooks();
125 LhWaitForPendingRemovals();
128 #endif /* DETOURS and EASYHOOK */
130 HINSTANCE g_hinstDLL;
131 LONG g_bHookEnabled;
132 CTlsData<CThreadLocalInfo> g_TLInfo;
134 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID /*lp*/)
136 CGdippSettings* pSettings;
138 switch(reason) {
139 case DLL_PROCESS_ATTACH:
140 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
141 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW);
142 setlocale(LC_ALL, "");
143 g_hinstDLL = instance;
144 hook_initinternal();
146 CCriticalSectionLock::Init();
147 if (!g_TLInfo.ProcessInit()) {
148 return FALSE;
151 pSettings = CGdippSettings::CreateInstance();
152 if (!pSettings || !pSettings->LoadSettings(instance)) {
153 CGdippSettings::DestroyInstance();
154 return FALSE;
157 if (!IsProcessExcluded()) {
158 if (!FontLInit())
159 return FALSE;
160 if ( !(g_pFTEngine = new FreeTypeFontEngine) )
161 return FALSE;
163 InterlockedExchange(&g_bHookEnabled, TRUE);
164 hook_init();
167 break;
168 case DLL_THREAD_ATTACH:
169 break;
170 case DLL_THREAD_DETACH:
171 g_TLInfo.ThreadTerm();
172 break;
173 case DLL_PROCESS_DETACH:
174 if (InterlockedExchange(&g_bHookEnabled, FALSE))
175 hook_term();
176 if (g_pFTEngine)
177 delete g_pFTEngine;
179 FontLFree();
180 CGdippSettings::DestroyInstance();
181 g_TLInfo.ProcessTerm();
182 CCriticalSectionLock::Term();
183 break;
185 return TRUE;