Showing
26 changed files
with
1761 additions
and
0 deletions
vnr/ith/hook/hook.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// hook.h | ||
4 | +// 8/23/2013 jichi | ||
5 | +// Branch: ITH/IHF_DLL.h, rev 66 | ||
6 | + | ||
7 | +#include "ith/common/const.h" | ||
8 | +#include "ith/common/types.h" | ||
9 | + | ||
10 | +//#ifdef IHF | ||
11 | +//# define IHFAPI __declspec(dllexport) __stdcall | ||
12 | +//#else | ||
13 | +//# define IHFAPI __declspec(dllimport) __stdcall | ||
14 | +//#endif // IHF | ||
15 | +#define IHFAPI // 9/19/2014 jichi: dummy | ||
16 | + | ||
17 | +//extern "C" { | ||
18 | +//DWORD IHFAPI OutputConsole(LPCWSTR text); | ||
19 | +void IHFAPI ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text | ||
20 | +//DWORD IHFAPI OutputDWORD(DWORD d); | ||
21 | +//DWORD IHFAPI OutputRegister(DWORD *base); | ||
22 | +DWORD IHFAPI NotifyHookInsert(DWORD addr); | ||
23 | +DWORD IHFAPI NewHook(const HookParam &hp, LPCWSTR name, DWORD flag = HOOK_ENGINE); | ||
24 | +DWORD IHFAPI RemoveHook(DWORD addr); | ||
25 | +DWORD IHFAPI SwitchTrigger(DWORD on); | ||
26 | +DWORD IHFAPI GetFunctionAddr(const char *name, DWORD *addr, DWORD *base, DWORD *size, LPWSTR *base_name); | ||
27 | +//DWORD IHFAPI RegisterEngineModule(DWORD idEngine, DWORD dnHook); | ||
28 | +//} // extern "C" | ||
29 | + | ||
30 | +// 10/21/2014 jichi: TODO: Get rid of this global variable | ||
31 | +// Defined in pipe.cc | ||
32 | +extern bool engine_registered; | ||
33 | + | ||
34 | + | ||
35 | +// 10/14/2014 jichi: disable GDI hooks | ||
36 | +void DisableGDIHooks(); | ||
37 | + | ||
38 | +// EOF |
vnr/ith/hook/hook.pro
0 → 100644
1 | +# hook.pro | ||
2 | +# 8/9/2013 jichi | ||
3 | +# Build vnrhook.dll for Windows 7+ | ||
4 | + | ||
5 | +CONFIG += eh eha # exception handler to catch all exceptions | ||
6 | +#CONFIG += noeh # msvcrt on Windows XP does not has exception handler | ||
7 | +include(../dllconfig.pri) | ||
8 | +include(../sys/sys.pri) | ||
9 | +include($$LIBDIR/disasm/disasm.pri) | ||
10 | +include($$LIBDIR/memdbg/memdbg.pri) | ||
11 | +include($$LIBDIR/ntinspect/ntinspect.pri) | ||
12 | +#include($$LIBDIR/winseh/winseh_safe.pri) | ||
13 | +include($$LIBDIR/winversion/winversion.pri) | ||
14 | + | ||
15 | +# 9/27/2013: disable ITH this game engine, only for debugging purpose | ||
16 | +#DEFINES += ITH_DISABLE_ENGINE | ||
17 | + | ||
18 | +# jichi 9/22/2013: When ITH is on wine, mutex is needed to protect NtWriteFile | ||
19 | +#DEFINES += ITH_WINE | ||
20 | +#DEFINES += ITH_SYNC_PIPE | ||
21 | + | ||
22 | +## Libraries | ||
23 | + | ||
24 | +LIBS += -lkernel32 -luser32 -lgdi32 | ||
25 | + | ||
26 | +## Sources | ||
27 | + | ||
28 | +TEMPLATE = lib | ||
29 | +TARGET = vnrhook | ||
30 | + | ||
31 | +#CONFIG += staticlib | ||
32 | + | ||
33 | +HEADERS += \ | ||
34 | + config.h \ | ||
35 | + cli.h \ | ||
36 | + hook.h \ | ||
37 | + engine/engine.h \ | ||
38 | + engine/hookdefs.h \ | ||
39 | + engine/match.h \ | ||
40 | + engine/pchooks.h \ | ||
41 | + engine/util.h \ | ||
42 | + tree/avl.h | ||
43 | + | ||
44 | +SOURCES += \ | ||
45 | + main.cc \ | ||
46 | + rpc/pipe.cc \ | ||
47 | + hijack/texthook.cc \ | ||
48 | + engine/engine.cc \ | ||
49 | + engine/match.cc \ | ||
50 | + engine/pchooks.cc \ | ||
51 | + engine/util.cc | ||
52 | + | ||
53 | +#RC_FILE += vnrhook.rc | ||
54 | +#OTHER_FILES += vnrhook.rc | ||
55 | + | ||
56 | +# EOF |
vnr/ith/hook/main.cc
0 → 100644
This diff is collapsed. Click to expand it.
vnr/ith/hook/rpc/pipe.cc
0 → 100644
1 | +// pipe.cc | ||
2 | +// 8/24/2013 jichi | ||
3 | +// Branch: ITH_DLL/pipe.cpp, rev 66 | ||
4 | +// 8/24/2013 TODO: Clean up this file | ||
5 | + | ||
6 | +#ifdef _MSC_VER | ||
7 | +# pragma warning (disable:4100) // C4100: unreference formal parameter | ||
8 | +#endif // _MSC_VER | ||
9 | + | ||
10 | +#include "cli.h" | ||
11 | +#include "engine/match.h" | ||
12 | +#include "ith/common/defs.h" | ||
13 | +//#include "ith/common/growl.h" | ||
14 | +#include "ith/sys/sys.h" | ||
15 | +#include "ccutil/ccmacro.h" | ||
16 | + | ||
17 | +//#include <ITH\AVL.h> | ||
18 | +//#include <ITH\ntdll.h> | ||
19 | +WCHAR mutex[] = ITH_GRANTPIPE_MUTEX; | ||
20 | +WCHAR exist[] = ITH_PIPEEXISTS_EVENT; | ||
21 | +WCHAR detach_mutex[0x20]; | ||
22 | +//WCHAR write_event[0x20]; | ||
23 | +//WCHAR engine_event[0x20]; | ||
24 | + | ||
25 | +//WCHAR recv_pipe[] = L"\\??\\pipe\\ITH_PIPE"; | ||
26 | +//WCHAR command[] = L"\\??\\pipe\\ITH_COMMAND"; | ||
27 | +wchar_t recv_pipe[] = ITH_TEXT_PIPE; | ||
28 | +wchar_t command[] = ITH_COMMAND_PIPE; | ||
29 | + | ||
30 | +LARGE_INTEGER wait_time = {-100*10000, -1}; | ||
31 | +LARGE_INTEGER sleep_time = {-20*10000, -1}; | ||
32 | + | ||
33 | +DWORD engine_type; | ||
34 | +DWORD module_base; | ||
35 | + | ||
36 | +//DWORD engine_base; | ||
37 | +bool engine_registered; // 10/19/2014 jichi: disable engine dll | ||
38 | + | ||
39 | +HANDLE hPipe, | ||
40 | + hCommand, | ||
41 | + hDetach; //,hLose; | ||
42 | +//InsertHookFun InsertHook; | ||
43 | +//IdentifyEngineFun IdentifyEngine; | ||
44 | +//InsertDynamicHookFun InsertDynamicHook; | ||
45 | + | ||
46 | +bool hook_inserted = false; | ||
47 | + | ||
48 | +// jichi 9/28/2013: protect pipe on wine | ||
49 | +// Put the definition in this file so that it might be inlined | ||
50 | +void CliUnlockPipe() | ||
51 | +{ | ||
52 | + if (IthIsWine()) | ||
53 | + IthReleaseMutex(::hmMutex); | ||
54 | +} | ||
55 | + | ||
56 | +void CliLockPipe() | ||
57 | +{ | ||
58 | + if (IthIsWine()) { | ||
59 | + const LONGLONG timeout = -50000000; // in nanoseconds = 5 seconds | ||
60 | + NtWaitForSingleObject(hmMutex, 0, (PLARGE_INTEGER)&timeout); | ||
61 | + } | ||
62 | +} | ||
63 | + | ||
64 | +HANDLE IthOpenPipe(LPWSTR name, ACCESS_MASK direction) | ||
65 | +{ | ||
66 | + UNICODE_STRING us; | ||
67 | + RtlInitUnicodeString(&us,name); | ||
68 | + SECURITY_DESCRIPTOR sd = {1}; | ||
69 | + OBJECT_ATTRIBUTES oa = {sizeof(oa), 0, &us, OBJ_CASE_INSENSITIVE, &sd, 0}; | ||
70 | + HANDLE hFile; | ||
71 | + IO_STATUS_BLOCK isb; | ||
72 | + if (NT_SUCCESS(NtCreateFile(&hFile, direction, &oa, &isb, 0, 0, FILE_SHARE_READ, FILE_OPEN, 0, 0, 0))) | ||
73 | + return hFile; | ||
74 | + else | ||
75 | + return INVALID_HANDLE_VALUE; | ||
76 | +} | ||
77 | + | ||
78 | +DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter) // Dynamically detect ITH main module status. | ||
79 | +{ | ||
80 | + CC_UNUSED(lpThreadParameter); | ||
81 | + int i; | ||
82 | + TextHook *man; | ||
83 | + struct { | ||
84 | + DWORD pid; | ||
85 | + TextHook *man; | ||
86 | + DWORD module; | ||
87 | + //DWORD engine; | ||
88 | + } u; | ||
89 | + HANDLE hMutex, | ||
90 | + hPipeExist; | ||
91 | + //swprintf(engine_event,L"ITH_ENGINE_%d",current_process_id); | ||
92 | + swprintf(detach_mutex, ITH_DETACH_MUTEX_ L"%d", current_process_id); | ||
93 | + //swprintf(lose_event,L"ITH_LOSEPIPE_%d",current_process_id); | ||
94 | + //hEngine=IthCreateEvent(engine_event); | ||
95 | + //NtWaitForSingleObject(hEngine,0,0); | ||
96 | + //NtClose(hEngine); | ||
97 | + while (!engine_registered) | ||
98 | + NtDelayExecution(0, &wait_time); | ||
99 | + //LoadEngine(L"ITH_Engine.dll"); | ||
100 | + u.module = module_base; | ||
101 | + u.pid = current_process_id; | ||
102 | + u.man = hookman; | ||
103 | + //u.engine = engine_base; // jichi 10/19/2014: disable the second dll | ||
104 | + hPipeExist = IthOpenEvent(exist); | ||
105 | + IO_STATUS_BLOCK ios; | ||
106 | + //hLose=IthCreateEvent(lose_event,0,0); | ||
107 | + if (hPipeExist != INVALID_HANDLE_VALUE) | ||
108 | + while (running) { | ||
109 | + hPipe = INVALID_HANDLE_VALUE; | ||
110 | + hCommand = INVALID_HANDLE_VALUE; | ||
111 | + while (NtWaitForSingleObject(hPipeExist,0,&wait_time) == WAIT_TIMEOUT) | ||
112 | + if (!running) | ||
113 | + goto _release; | ||
114 | + hMutex = IthCreateMutex(mutex,0); | ||
115 | + NtWaitForSingleObject(hMutex,0,0); | ||
116 | + while (hPipe == INVALID_HANDLE_VALUE|| | ||
117 | + hCommand == INVALID_HANDLE_VALUE) { | ||
118 | + NtDelayExecution(0, &sleep_time); | ||
119 | + if (hPipe == INVALID_HANDLE_VALUE) | ||
120 | + hPipe = IthOpenPipe(recv_pipe, GENERIC_WRITE); | ||
121 | + if (hCommand == INVALID_HANDLE_VALUE) | ||
122 | + hCommand = IthOpenPipe(command, GENERIC_READ); | ||
123 | + } | ||
124 | + //NtClearEvent(hLose); | ||
125 | + CliLockPipe(); | ||
126 | + NtWriteFile(hPipe, 0, 0, 0, &ios, &u, sizeof(u), 0, 0); | ||
127 | + CliUnlockPipe(); | ||
128 | + live = true; | ||
129 | + for (man = hookman, i = 0; i < current_hook; man++) | ||
130 | + if (man->RecoverHook()) // jichi 9/27/2013: This is the place where built-in hooks like TextOutA are inserted | ||
131 | + i++; | ||
132 | + //ConsoleOutput(dll_name); | ||
133 | + ConsoleOutput("vnrcli:WaitForPipe: pipe connected"); | ||
134 | + //OutputDWORD(tree->Count()); | ||
135 | + NtReleaseMutant(hMutex,0); | ||
136 | + NtClose(hMutex); | ||
137 | + if (!hook_inserted && engine_registered) { | ||
138 | + hook_inserted = true; | ||
139 | + Engine::IdentifyEngine(); | ||
140 | + } | ||
141 | + hDetach = IthCreateMutex(detach_mutex,1); | ||
142 | + while (running && NtWaitForSingleObject(hPipeExist, 0, &sleep_time) == WAIT_OBJECT_0) | ||
143 | + NtDelayExecution(0, &sleep_time); | ||
144 | + live = false; | ||
145 | + for (man = hookman, i = 0; i < current_hook; man++) | ||
146 | + if (man->RemoveHook()) | ||
147 | + i++; | ||
148 | + if (!running) { | ||
149 | + IthCoolDown(); // jichi 9/28/2013: Use cooldown instead of lock pipe to prevent from hanging on exit | ||
150 | + //CliLockPipe(); | ||
151 | + NtWriteFile(hPipe, 0, 0, 0, &ios, man, 4, 0, 0); | ||
152 | + //CliUnlockPipe(); | ||
153 | + IthReleaseMutex(hDetach); | ||
154 | + } | ||
155 | + NtClose(hDetach); | ||
156 | + NtClose(hPipe); | ||
157 | + } | ||
158 | +_release: | ||
159 | + //NtClose(hLose); | ||
160 | + NtClose(hPipeExist); | ||
161 | + return 0; | ||
162 | +} | ||
163 | +DWORD WINAPI CommandPipe(LPVOID lpThreadParameter) | ||
164 | +{ | ||
165 | + CC_UNUSED(lpThreadParameter); | ||
166 | + DWORD command; | ||
167 | + BYTE buff[0x400] = {}; | ||
168 | + HANDLE hPipeExist; | ||
169 | + hPipeExist = IthOpenEvent(exist); | ||
170 | + IO_STATUS_BLOCK ios={}; | ||
171 | + if (hPipeExist!=INVALID_HANDLE_VALUE) | ||
172 | + while (running) { | ||
173 | + while (!live) { | ||
174 | + if (!running) | ||
175 | + goto _detach; | ||
176 | + NtDelayExecution(0, &sleep_time); | ||
177 | + } | ||
178 | + // jichi 9/27/2013: Why 0x200 not 0x400? wchar_t? | ||
179 | + switch (NtReadFile(hCommand, 0, 0, 0, &ios, buff, 0x200, 0, 0)) { | ||
180 | + case STATUS_PIPE_BROKEN: | ||
181 | + case STATUS_PIPE_DISCONNECTED: | ||
182 | + NtClearEvent(hPipeExist); | ||
183 | + continue; | ||
184 | + case STATUS_PENDING: | ||
185 | + NtWaitForSingleObject(hCommand, 0, 0); | ||
186 | + switch (ios.Status) { | ||
187 | + case STATUS_PIPE_BROKEN: | ||
188 | + case STATUS_PIPE_DISCONNECTED: | ||
189 | + NtClearEvent(hPipeExist); | ||
190 | + continue; | ||
191 | + case 0: break; | ||
192 | + default: | ||
193 | + if (NtWaitForSingleObject(hDetach, 0, &wait_time) == WAIT_OBJECT_0) | ||
194 | + goto _detach; | ||
195 | + } | ||
196 | + } | ||
197 | + if (ios.uInformation && live) { | ||
198 | + command = *(DWORD *)buff; | ||
199 | + switch(command) { | ||
200 | + case IHF_COMMAND_NEW_HOOK: | ||
201 | + //IthBreak(); | ||
202 | + buff[ios.uInformation] = 0; | ||
203 | + buff[ios.uInformation + 1] = 0; | ||
204 | + NewHook(*(HookParam *)(buff + 4), (LPWSTR)(buff + 4 + sizeof(HookParam)), 0); | ||
205 | + break; | ||
206 | + case IHF_COMMAND_REMOVE_HOOK: | ||
207 | + { | ||
208 | + DWORD rm_addr = *(DWORD *)(buff+4); | ||
209 | + HANDLE hRemoved = IthOpenEvent(ITH_REMOVEHOOK_EVENT); | ||
210 | + | ||
211 | + TextHook *in = hookman; | ||
212 | + for (int i = 0; i < current_hook; in++) { | ||
213 | + if (in->Address()) i++; | ||
214 | + if (in->Address() == rm_addr) break; | ||
215 | + } | ||
216 | + if (in->Address()) | ||
217 | + in->ClearHook(); | ||
218 | + IthSetEvent(hRemoved); | ||
219 | + NtClose(hRemoved); | ||
220 | + } break; | ||
221 | + case IHF_COMMAND_MODIFY_HOOK: | ||
222 | + { | ||
223 | + DWORD rm_addr = *(DWORD *)(buff + 4); | ||
224 | + HANDLE hModify = IthOpenEvent(ITH_MODIFYHOOK_EVENT); | ||
225 | + TextHook *in = hookman; | ||
226 | + for (int i = 0; i < current_hook; in++) { | ||
227 | + if (in->Address()) | ||
228 | + i++; | ||
229 | + if (in->Address() == rm_addr) | ||
230 | + break; | ||
231 | + } | ||
232 | + if (in->Address()) | ||
233 | + in->ModifyHook(*(HookParam *)(buff + 4)); | ||
234 | + IthSetEvent(hModify); | ||
235 | + NtClose(hModify); | ||
236 | + } break; | ||
237 | + case IHF_COMMAND_DETACH: | ||
238 | + running = false; | ||
239 | + live = false; | ||
240 | + goto _detach; | ||
241 | + default: ; | ||
242 | + } | ||
243 | + } | ||
244 | + } | ||
245 | +_detach: | ||
246 | + NtClose(hPipeExist); | ||
247 | + NtClose(hCommand); | ||
248 | + return 0; | ||
249 | +} | ||
250 | +//extern "C" { | ||
251 | +void IHFAPI ConsoleOutput(LPCSTR text) | ||
252 | +{ // jichi 12/25/2013: Rewrite the implementation | ||
253 | + if (!live || !text) | ||
254 | + return; | ||
255 | + enum { buf_size = 0x50 }; | ||
256 | + BYTE buf[buf_size]; // buffer is needed to append the message header | ||
257 | + size_t text_size = strlen(text) + 1; | ||
258 | + size_t data_size = text_size + 8; | ||
259 | + | ||
260 | + BYTE *data = (data_size <= buf_size) ? buf : new BYTE[data_size]; | ||
261 | + *(DWORD *)data = IHF_NOTIFICATION; //cmd | ||
262 | + *(DWORD *)(data + 4) = IHF_NOTIFICATION_TEXT; //console | ||
263 | + memcpy(data + 8, text, text_size); | ||
264 | + | ||
265 | + IO_STATUS_BLOCK ios; | ||
266 | + NtWriteFile(hPipe, 0, 0, 0, &ios, data, data_size, 0, 0); | ||
267 | + if (data != buf) | ||
268 | + delete[] data; | ||
269 | +} | ||
270 | + //if (str) { | ||
271 | + // int t, len, sum; | ||
272 | + // BYTE buffer[0x80]; | ||
273 | + // BYTE *buff; | ||
274 | + // len = wcslen(str) << 1; | ||
275 | + // t = swprintf((LPWSTR)(buffer + 8),L"%d: ",current_process_id) << 1; | ||
276 | + // sum = len + t + 8; | ||
277 | + // if (sum > 0x80) { | ||
278 | + // buff = new BYTE[sum]; | ||
279 | + // memset(buff, 0, sum); // jichi 9/25/2013: zero memory | ||
280 | + // memcpy(buff + 8, buffer + 8, t); | ||
281 | + // } | ||
282 | + // else | ||
283 | + // buff = buffer; | ||
284 | + // *(DWORD *)buff = IHF_NOTIFICATION; //cmd | ||
285 | + // *(DWORD *)(buff + 4) = IHF_NOTIFICATION_TEXT; //console | ||
286 | + // memcpy(buff + t + 8, str, len); | ||
287 | + // IO_STATUS_BLOCK ios; | ||
288 | + // NtWriteFile(hPipe,0,0,0,&ios,buff,sum,0,0); | ||
289 | + // if (buff != buffer) | ||
290 | + // delete[] buff; | ||
291 | + // return len; | ||
292 | + //} | ||
293 | + | ||
294 | +//DWORD IHFAPI OutputDWORD(DWORD d) | ||
295 | +//{ | ||
296 | +// WCHAR str[0x10]; | ||
297 | +// swprintf(str,L"%.8X",d); | ||
298 | +// ConsoleOutput(str); | ||
299 | +// return 0; | ||
300 | +//} | ||
301 | +//DWORD IHFAPI OutputRegister(DWORD *base) | ||
302 | +//{ | ||
303 | +// WCHAR str[0x40]; | ||
304 | +// swprintf(str,L"EAX:%.8X",base[0]); | ||
305 | +// ConsoleOutput(str); | ||
306 | +// swprintf(str,L"ECX:%.8X",base[-1]); | ||
307 | +// ConsoleOutput(str); | ||
308 | +// swprintf(str,L"EDX:%.8X",base[-2]); | ||
309 | +// ConsoleOutput(str); | ||
310 | +// swprintf(str,L"EBX:%.8X",base[-3]); | ||
311 | +// ConsoleOutput(str); | ||
312 | +// swprintf(str,L"ESP:%.8X",base[-4]); | ||
313 | +// ConsoleOutput(str); | ||
314 | +// swprintf(str,L"EBP:%.8X",base[-5]); | ||
315 | +// ConsoleOutput(str); | ||
316 | +// swprintf(str,L"ESI:%.8X",base[-6]); | ||
317 | +// ConsoleOutput(str); | ||
318 | +// swprintf(str,L"EDI:%.8X",base[-7]); | ||
319 | +// ConsoleOutput(str); | ||
320 | +// return 0; | ||
321 | +//} | ||
322 | +//DWORD IHFAPI RegisterEngineModule(DWORD idEngine, DWORD dnHook) | ||
323 | +//{ | ||
324 | +// ::IdentifyEngine = (IdentifyEngineFun)idEngine; | ||
325 | +// ::InsertDynamicHook = (InsertDynamicHookFun)dnHook; | ||
326 | +// ::engine_registered = true; | ||
327 | +// return 0; | ||
328 | +//} | ||
329 | +DWORD IHFAPI NotifyHookInsert(DWORD addr) | ||
330 | +{ | ||
331 | + if (live) { | ||
332 | + BYTE buffer[0x10]; | ||
333 | + *(DWORD *)buffer = IHF_NOTIFICATION; | ||
334 | + *(DWORD *)(buffer + 4) = IHF_NOTIFICATION_NEWHOOK; | ||
335 | + *(DWORD *)(buffer + 8) = addr; | ||
336 | + *(DWORD *)(buffer + 0xc) = 0; | ||
337 | + IO_STATUS_BLOCK ios; | ||
338 | + CliLockPipe(); | ||
339 | + NtWriteFile(hPipe,0,0,0,&ios,buffer,0x10,0,0); | ||
340 | + CliUnlockPipe(); | ||
341 | + } | ||
342 | + return 0; | ||
343 | +} | ||
344 | +//} // extern "C" | ||
345 | + | ||
346 | +// EOF |
vnr/ith/hook/tree/avl.h
0 → 100644
This diff is collapsed. Click to expand it.
vnr/ith/hookxp/hookxp.pro
0 → 100644
1 | +# hookxp.pro | ||
2 | +# 8/9/2013 jichi | ||
3 | +# Build vnrhookxp.dll for Windows XP | ||
4 | + | ||
5 | +CONFIG += noeh # msvcrt on Windows XP does not has exception handler | ||
6 | +include(../dllconfig.pri) | ||
7 | +include(../sys/sys.pri) | ||
8 | +include($$LIBDIR/disasm/disasm.pri) | ||
9 | +include($$LIBDIR/memdbg/memdbg.pri) | ||
10 | +include($$LIBDIR/ntinspect/ntinspect.pri) | ||
11 | +include($$LIBDIR/winseh/winseh_safe.pri) | ||
12 | +include($$LIBDIR/winversion/winversion.pri) | ||
13 | + | ||
14 | +VPATH += ../hook | ||
15 | +INCLUDEPATH += ../hook | ||
16 | + | ||
17 | +# 9/27/2013: disable ITH this game engine, only for debugging purpose | ||
18 | +#DEFINES += ITH_DISABLE_ENGINE | ||
19 | + | ||
20 | + | ||
21 | +# jichi 9/22/2013: When ITH is on wine, mutex is needed to protect NtWriteFile | ||
22 | +#DEFINES += ITH_WINE | ||
23 | +#DEFINES += ITH_SYNC_PIPE | ||
24 | + | ||
25 | +## Libraries | ||
26 | + | ||
27 | +LIBS += -lkernel32 -luser32 -lgdi32 | ||
28 | + | ||
29 | +## Sources | ||
30 | + | ||
31 | +TEMPLATE = lib | ||
32 | +TARGET = vnrhookxp | ||
33 | + | ||
34 | +#CONFIG += staticlib | ||
35 | + | ||
36 | +HEADERS += \ | ||
37 | + config.h \ | ||
38 | + cli.h \ | ||
39 | + hook.h \ | ||
40 | + engine/engine.h \ | ||
41 | + engine/hookdefs.h \ | ||
42 | + engine/match.h \ | ||
43 | + engine/pchooks.h \ | ||
44 | + engine/util.h \ | ||
45 | + tree/avl.h | ||
46 | + | ||
47 | +SOURCES += \ | ||
48 | + main.cc \ | ||
49 | + rpc/pipe.cc \ | ||
50 | + hijack/texthook.cc \ | ||
51 | + engine/engine.cc \ | ||
52 | + engine/match.cc \ | ||
53 | + engine/pchooks.cc \ | ||
54 | + engine/util.cc | ||
55 | + | ||
56 | +#RC_FILE += vnrhook.rc | ||
57 | +#OTHER_FILES += vnrhook.rc | ||
58 | + | ||
59 | +# EOF |
vnr/ith/host/CMakeLists.txt
0 → 100644
1 | +# host.pro | ||
2 | +# #CONFIG += eha # 3/1/2014: catchlng all exceptions will break pytexthook on Windows XP | ||
3 | +# CONFIG += noeh # Needed by pytexthook ONLY on windows xp orz | ||
4 | +# include(../dllconfig.pri) | ||
5 | +# include(../sys/sys.pri) | ||
6 | +# include($$LIBDIR/winmaker/winmaker.pri) | ||
7 | +# include($$LIBDIR/winmutex/winmutex.pri) | ||
8 | + | ||
9 | +# config.pri | ||
10 | +# CONFIG(noeh) { # No Exception handler | ||
11 | +# message(CONFIG noeh) | ||
12 | +# QMAKE_CXXFLAGS += /GR- | ||
13 | +# QMAKE_CXXFLAGS_RTTI_ON -= /GR | ||
14 | +# QMAKE_CXXFLAGS_STL_ON -= /EHsc | ||
15 | +# QMAKE_CXXFLAGS_EXCEPTIONS_ON -= /EHsc | ||
16 | +# CONFIG(dll) { | ||
17 | +# QMAKE_LFLAGS += /ENTRY:"DllMain" | ||
18 | +# } | ||
19 | +# } | ||
20 | + | ||
21 | +set(vnrhost_src | ||
22 | + avl_p.h | ||
23 | + config.h | ||
24 | + hookman.h | ||
25 | + settings.h | ||
26 | + srv.h | ||
27 | + srv_p.h | ||
28 | + textthread.h | ||
29 | + textthread_p.h | ||
30 | + SettingManager.h | ||
31 | + hookman.cc | ||
32 | + main.cc | ||
33 | + pipe.cc | ||
34 | + textthread.cc | ||
35 | + ${PROJECT_SOURCE_DIR}/winmaker/winmaker.h | ||
36 | + ${PROJECT_SOURCE_DIR}/winmaker/winmaker.cc | ||
37 | + ${PROJECT_SOURCE_DIR}/winmutex/winmutex.h | ||
38 | + ${common_src} | ||
39 | +) | ||
40 | + | ||
41 | +source_group("common" FILES ${common_src}) | ||
42 | + | ||
43 | +add_library(vnrhost SHARED ${vnrhost_src}) | ||
44 | + | ||
45 | +set_target_properties(vnrhost PROPERTIES LINK_FLAGS /SUBSYSTEM:WINDOWS) | ||
46 | + | ||
47 | +target_compile_options(vnrhost PRIVATE | ||
48 | + /GR- | ||
49 | + $<$<CONFIG:Release>:> | ||
50 | + $<$<CONFIG:Debug>:> | ||
51 | +) | ||
52 | + | ||
53 | +STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) | ||
54 | + | ||
55 | +target_link_libraries(vnrhost | ||
56 | + vnrsys | ||
57 | + ${WDK_HOME}/lib/wxp/i386/ntdll.lib | ||
58 | +) | ||
59 | + | ||
60 | +target_compile_definitions(vnrhost PRIVATE | ||
61 | +) | ||
62 | + | ||
63 | +install(TARGETS vnrhost RUNTIME | ||
64 | + DESTINATION . | ||
65 | + CONFIGURATIONS Release | ||
66 | +) |
vnr/ith/host/SettingManager.h
0 → 100644
1 | +/* Copyright (C) 2010-2012 kaosu (qiupf2000@gmail.com) | ||
2 | + * This file is part of the Interactive Text Hooker. | ||
3 | + | ||
4 | + * Interactive Text Hooker is free software: you can redistribute it and/or | ||
5 | + * modify it under the terms of the GNU General Public License as published | ||
6 | + * by the Free Software Foundation, either version 3 of the License, or | ||
7 | + * (at your option) any later version. | ||
8 | + | ||
9 | + * This program is distributed in the hope that it will be useful, | ||
10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | + * GNU General Public License for more details. | ||
13 | + | ||
14 | + * You should have received a copy of the GNU General Public License | ||
15 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | + */ | ||
17 | + | ||
18 | +#pragma once | ||
19 | +#include "config.h" | ||
20 | +#include <intrin.h> | ||
21 | +#define SETTING_SPLIT_TIME 0 | ||
22 | +#define SETTING_CYCLIC_REMOVE 1 | ||
23 | +#define SETTING_REPEAT_COUNT 2 | ||
24 | +#define SETTING_CLIPFLAG 3 | ||
25 | +#define SETTING_MAX_INDEX 4 | ||
26 | +class IHFSERVICE SettingManager | ||
27 | +{ | ||
28 | +public: | ||
29 | + SettingManager() {memset(setting_int,0,sizeof(setting_int));} | ||
30 | + ~SettingManager(){} | ||
31 | + unsigned int SetValue(unsigned int index, unsigned int value) | ||
32 | + { | ||
33 | + if (index < SETTING_MAX_INDEX) | ||
34 | + return (unsigned int)_InterlockedExchange((long*)setting_int+index,(long)value); | ||
35 | + else return 0; | ||
36 | + } | ||
37 | + unsigned int GetValue(unsigned int index) | ||
38 | + { | ||
39 | + if (index < SETTING_MAX_INDEX) | ||
40 | + return setting_int[index]; | ||
41 | + else return 0; | ||
42 | + } | ||
43 | +private: | ||
44 | + unsigned int setting_int[SETTING_MAX_INDEX]; | ||
45 | + | ||
46 | +}; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
vnr/ith/host/avl_p.h
0 → 100644
This diff is collapsed. Click to expand it.
vnr/ith/host/config.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// config.h | ||
4 | +// 8/23/2013 jichi | ||
5 | +// The first header file that are included by all source files. | ||
6 | + | ||
7 | +#define IHF // for dll import | ||
8 | +#include "ith/dllconfig.h" | ||
9 | +#define IHFAPI __stdcall | ||
10 | +#ifdef IHF | ||
11 | +# define IHFSERVICE __declspec(dllexport) | ||
12 | +#else | ||
13 | +# define IHFSERVICE __declspec(dllimport) | ||
14 | +#endif | ||
15 | + | ||
16 | +// EOF |
vnr/ith/host/hookman.cc
0 → 100644
This diff is collapsed. Click to expand it.
vnr/ith/host/hookman.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// hookman.h | ||
4 | +// 8/23/2013 jichi | ||
5 | +// Branch: ITH/HookManager.h, rev 133 | ||
6 | + | ||
7 | +#include "ith/host/avl_p.h" | ||
8 | +#include "ith/host/textthread.h" | ||
9 | +#include "winmutex/winmutex.h" | ||
10 | + | ||
11 | +enum { MAX_REGISTER = 0xf }; | ||
12 | +enum { MAX_PREV_REPEAT_LENGTH = 0x20 }; | ||
13 | + | ||
14 | +struct ProcessRecord { | ||
15 | + DWORD pid_register; | ||
16 | + DWORD hookman_register; | ||
17 | + DWORD module_register; | ||
18 | + //DWORD engine_register; // jichi 10/19/2014: removed | ||
19 | + HANDLE process_handle; | ||
20 | + HANDLE hookman_mutex; | ||
21 | + HANDLE hookman_section; | ||
22 | + LPVOID hookman_map; | ||
23 | +}; | ||
24 | + | ||
25 | +class ThreadTable : public MyVector<TextThread *, 0x40> | ||
26 | +{ | ||
27 | +public: | ||
28 | + virtual void SetThread(DWORD number, TextThread *ptr); | ||
29 | + virtual TextThread *FindThread(DWORD number); | ||
30 | +}; | ||
31 | + | ||
32 | +struct TCmp { char operator()(const ThreadParameter *t1,const ThreadParameter *t2); }; | ||
33 | +struct TCpy { void operator()(ThreadParameter *t1,const ThreadParameter *t2); }; | ||
34 | +struct TLen { int operator()(const ThreadParameter *t); }; | ||
35 | + | ||
36 | +typedef DWORD (*ProcessEventCallback)(DWORD pid); | ||
37 | + | ||
38 | +class IHFSERVICE HookManager : public AVLTree<ThreadParameter, DWORD, TCmp, TCpy, TLen> | ||
39 | +{ | ||
40 | +public: | ||
41 | + HookManager(); | ||
42 | + ~HookManager(); | ||
43 | + // jichi 12/26/2013: remove virtual modifiers | ||
44 | + TextThread *FindSingle(DWORD pid, DWORD hook, DWORD retn, DWORD split); | ||
45 | + TextThread *FindSingle(DWORD number); | ||
46 | + ProcessRecord *GetProcessRecord(DWORD pid); | ||
47 | + DWORD GetProcessIDByPath(LPCWSTR str); | ||
48 | + void RemoveSingleThread(DWORD number); | ||
49 | + void LockHookman(); | ||
50 | + void UnlockHookman(); | ||
51 | + void ResetRepeatStatus(); | ||
52 | + void ClearCurrent(); | ||
53 | + void AddLink(WORD from, WORD to); | ||
54 | + void UnLink(WORD from); | ||
55 | + void UnLinkAll(WORD from); | ||
56 | + void SelectCurrent(DWORD num); | ||
57 | + void DetachProcess(DWORD pid); | ||
58 | + void SetCurrent(TextThread *it); | ||
59 | + void AddConsoleOutput(LPCWSTR text); | ||
60 | + | ||
61 | + // jichi 10/27/2013: Add const; add space. | ||
62 | + void DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD retn, DWORD split, int len, bool space); | ||
63 | + | ||
64 | + void ClearText(DWORD pid, DWORD hook, DWORD retn, DWORD split); | ||
65 | + void RemoveProcessContext(DWORD pid); | ||
66 | + void RemoveSingleHook(DWORD pid, DWORD addr); | ||
67 | + void RegisterThread(TextThread*, DWORD); | ||
68 | + void RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread); | ||
69 | + void RegisterProcess(DWORD pid, DWORD hookman, DWORD module); | ||
70 | + void UnRegisterProcess(DWORD pid); | ||
71 | + //void SetName(DWORD); | ||
72 | + | ||
73 | + DWORD GetCurrentPID(); | ||
74 | + HANDLE GetCmdHandleByPID(DWORD pid); | ||
75 | + | ||
76 | + ConsoleCallback RegisterConsoleCallback(ConsoleCallback cf) | ||
77 | + { return (ConsoleCallback)_InterlockedExchange((long*)&console,(long)cf); } | ||
78 | + | ||
79 | + ConsoleWCallback RegisterConsoleWCallback(ConsoleWCallback cf) | ||
80 | + { return (ConsoleWCallback)_InterlockedExchange((long*)&wconsole,(long)cf); } | ||
81 | + | ||
82 | + ThreadEventCallback RegisterThreadCreateCallback(ThreadEventCallback cf) | ||
83 | + { return (ThreadEventCallback)_InterlockedExchange((long*)&create,(long)cf); } | ||
84 | + | ||
85 | + ThreadEventCallback RegisterThreadRemoveCallback(ThreadEventCallback cf) | ||
86 | + { return (ThreadEventCallback)_InterlockedExchange((long*)&remove,(long)cf); } | ||
87 | + | ||
88 | + ThreadEventCallback RegisterThreadResetCallback(ThreadEventCallback cf) | ||
89 | + { return (ThreadEventCallback)_InterlockedExchange((long*)&reset,(long)cf); } | ||
90 | + | ||
91 | + ThreadEventCallback RegisterAddRemoveLinkCallback(ThreadEventCallback cf) | ||
92 | + { return (ThreadEventCallback)_InterlockedExchange((long*)&addRemoveLink, (long)cf); } | ||
93 | + | ||
94 | + ProcessEventCallback RegisterProcessAttachCallback(ProcessEventCallback cf) | ||
95 | + { return (ProcessEventCallback)_InterlockedExchange((long*)&attach,(long)cf); } | ||
96 | + | ||
97 | + ProcessEventCallback RegisterProcessDetachCallback(ProcessEventCallback cf) | ||
98 | + { return (ProcessEventCallback)_InterlockedExchange((long*)&detach,(long)cf); } | ||
99 | + | ||
100 | + ProcessEventCallback RegisterProcessNewHookCallback(ProcessEventCallback cf) | ||
101 | + { return (ProcessEventCallback)_InterlockedExchange((long*)&hook,(long)cf); } | ||
102 | + | ||
103 | + ProcessEventCallback ProcessNewHook() { return hook; } | ||
104 | + TextThread *GetCurrentThread() { return current; } | ||
105 | + ProcessRecord *Records() { return record; } | ||
106 | + ThreadTable *Table() { return thread_table; } | ||
107 | + | ||
108 | + //DWORD& SplitTime() { return split_time; } | ||
109 | + //DWORD& RepeatCount() { return repeat_count; } | ||
110 | + //DWORD& CyclicRemove() { return cyclic_remove; } | ||
111 | + //DWORD& GlobalFilter() { return global_filter; } | ||
112 | + void ConsoleOutput(LPCSTR text) { if (console) console(text); } // not thread safe | ||
113 | + void ConsoleOutputW(LPCWSTR text) { if (wconsole) wconsole(text); } // not thread safe | ||
114 | + | ||
115 | +private: | ||
116 | + typedef win_mutex<CRITICAL_SECTION> mutex_type; | ||
117 | + mutex_type hmcs; | ||
118 | + | ||
119 | + TextThread *current; | ||
120 | + ConsoleCallback console; // jichi 12/25/2013: add console output callback | ||
121 | + ConsoleWCallback wconsole; | ||
122 | + ThreadEventCallback create, | ||
123 | + remove, | ||
124 | + reset, | ||
125 | + addRemoveLink; | ||
126 | + ProcessEventCallback attach, | ||
127 | + detach, | ||
128 | + hook; | ||
129 | + DWORD current_pid; | ||
130 | + ThreadTable *thread_table; | ||
131 | + HANDLE destroy_event; | ||
132 | + ProcessRecord record[MAX_REGISTER + 1]; | ||
133 | + HANDLE text_pipes[MAX_REGISTER + 1], | ||
134 | + cmd_pipes[MAX_REGISTER + 1], | ||
135 | + recv_threads[MAX_REGISTER + 1]; | ||
136 | + WORD register_count, | ||
137 | + new_thread_number; | ||
138 | + | ||
139 | + // jichi 1/16/2014: Stop adding new threads when full | ||
140 | + bool IsFull() const; // { return new_thread_number >= MAX_HOOK; } | ||
141 | + bool IsEmpty() const { return !new_thread_number; } | ||
142 | +}; | ||
143 | + | ||
144 | +// EOF |
vnr/ith/host/host.pri
0 → 100644
vnr/ith/host/host.pro
0 → 100644
1 | +# host.pro | ||
2 | +# 8/9/2013 jichi | ||
3 | +# Build vnrhost | ||
4 | + | ||
5 | +#CONFIG += eha # 3/1/2014: catchlng all exceptions will break pytexthook on Windows XP | ||
6 | +CONFIG += noeh # Needed by pytexthook ONLY on windows xp orz | ||
7 | +include(../dllconfig.pri) | ||
8 | +include(../sys/sys.pri) | ||
9 | +include($$LIBDIR/winmaker/winmaker.pri) | ||
10 | +include($$LIBDIR/winmutex/winmutex.pri) | ||
11 | + | ||
12 | +# 9/22/2013: When ITH is on wine, certain NT functions are replaced | ||
13 | +#DEFINES += ITH_WINE | ||
14 | + | ||
15 | +# 9/27/2013: Only for debugging purpose | ||
16 | +#DEFINES += ITH_DISABLE_REPEAT # disable repetition elimination | ||
17 | +#DEFINES += ITH_DISABLE_FILTER # disable space filter in pipe | ||
18 | + | ||
19 | +## Libraries | ||
20 | + | ||
21 | +LIBS += -lkernel32 -luser32 #-lcomctl32 | ||
22 | + | ||
23 | +## Sources | ||
24 | + | ||
25 | +TEMPLATE = lib | ||
26 | +#TARGET = IHF # compatible with ITHv3 | ||
27 | +TARGET = vnrhost | ||
28 | + | ||
29 | +#CONFIG += staticlib | ||
30 | + | ||
31 | +HEADERS += \ | ||
32 | + avl_p.h \ | ||
33 | + config.h \ | ||
34 | + hookman.h \ | ||
35 | + settings.h \ | ||
36 | + srv.h \ | ||
37 | + srv_p.h \ | ||
38 | + textthread.h \ | ||
39 | + textthread_p.h | ||
40 | + #util.h | ||
41 | + | ||
42 | +SOURCES += \ | ||
43 | + hookman.cc \ | ||
44 | + main.cc \ | ||
45 | + pipe.cc \ | ||
46 | + textthread.cc | ||
47 | + #util.cc | ||
48 | + | ||
49 | +#RC_FILE += engine.rc | ||
50 | +#OTHER_FILES += engine.rc | ||
51 | + | ||
52 | +OTHER_FILES += host.pri | ||
53 | + | ||
54 | +# EOF |
vnr/ith/host/main.cc
0 → 100644
This diff is collapsed. Click to expand it.
vnr/ith/host/pipe.cc
0 → 100644
1 | +// pipe.cc | ||
2 | +// 8/24/2013 jichi | ||
3 | +// Branch IHF/pipe.cpp, rev 93 | ||
4 | +// 8/24/2013 TODO: Clean up this file | ||
5 | + | ||
6 | +#include "srv_p.h" | ||
7 | +#include "hookman.h" | ||
8 | +#include "ith/common/defs.h" | ||
9 | +#include "ith/common/const.h" | ||
10 | +//#include "ith/common/growl.h" | ||
11 | +#include "ith/sys/sys.h" | ||
12 | +//#include "CommandQueue.h" | ||
13 | + | ||
14 | +//DWORD WINAPI UpdateWindows(LPVOID lpThreadParameter); | ||
15 | + | ||
16 | +namespace { // unnamed | ||
17 | +enum NamedPipeCommand { | ||
18 | + NAMED_PIPE_DISCONNECT = 1 | ||
19 | + , NAMED_PIPE_CONNECT = 2 | ||
20 | +}; | ||
21 | + | ||
22 | +bool newline = false; | ||
23 | +bool detach = false; | ||
24 | + | ||
25 | +// jichi 10/27/2013 | ||
26 | +// Check if text has leading space | ||
27 | +enum { _filter_limit = 0x20 }; // The same as the orignal ITH filter. So, I don't have to check \u3000 | ||
28 | +//enum { _filter_limit = 0x19 }; | ||
29 | +inline bool has_leading_space(const BYTE *text, int len) | ||
30 | +{ | ||
31 | + return len == 1 ? *text <= _filter_limit : // 1 byte | ||
32 | + *reinterpret_cast<const WORD *>(text) <= _filter_limit; // 2 bytes | ||
33 | +} | ||
34 | + | ||
35 | +// jichi 9/28/2013: Skip leading garbage | ||
36 | +// Note: | ||
37 | +// - Modifying limit will break manual translation. The orignal one is 0x20 | ||
38 | +// - Eliminating 0x20 will break English-translated games | ||
39 | +const BYTE *Filter(const BYTE *str, int len) | ||
40 | +{ | ||
41 | +#ifdef ITH_DISABLE_FILTER // jichi 9/28/2013: only for debugging purpose | ||
42 | + return str; | ||
43 | +#endif // ITH_DISABLE_FILTER | ||
44 | +// if (len && *str == 0x10) // jichi 9/28/2013: garbage on wine, data link escape, or ^P | ||
45 | +// return nullptr; | ||
46 | + //enum { limit = 0x19 }; | ||
47 | + while (true) | ||
48 | + if (len >= 2) { | ||
49 | + if (*(const WORD *)str <= _filter_limit) { // jichi 10/27/2013: two bytes | ||
50 | + str += 2; | ||
51 | + len -= 2; | ||
52 | + } else | ||
53 | + break; | ||
54 | + } else if (*str <= _filter_limit) { // jichi 10/27/2013: 1 byte | ||
55 | + str++; | ||
56 | + len--; | ||
57 | + } else | ||
58 | + break; | ||
59 | + return str; | ||
60 | +} | ||
61 | +} // unnamed namespace | ||
62 | + | ||
63 | +//WCHAR recv_pipe[] = L"\\??\\pipe\\ITH_PIPE"; | ||
64 | +//WCHAR command_pipe[] = L"\\??\\pipe\\ITH_COMMAND"; | ||
65 | +wchar_t recv_pipe[] = ITH_TEXT_PIPE; | ||
66 | +wchar_t command_pipe[] = ITH_COMMAND_PIPE; | ||
67 | + | ||
68 | +CRITICAL_SECTION detach_cs; // jichi 9/27/2013: also used in main | ||
69 | +//HANDLE hDetachEvent; | ||
70 | +extern HANDLE hPipeExist; | ||
71 | + | ||
72 | +void CreateNewPipe() | ||
73 | +{ | ||
74 | + static DWORD acl[7] = { | ||
75 | + 0x1C0002, | ||
76 | + 1, | ||
77 | + 0x140000, | ||
78 | + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, | ||
79 | + 0x101, | ||
80 | + 0x1000000, | ||
81 | + 0}; | ||
82 | + static SECURITY_DESCRIPTOR sd = {1, 0, 4, 0, 0, 0, (PACL)acl}; | ||
83 | + | ||
84 | + HANDLE hTextPipe, hCmdPipe, hThread; | ||
85 | + IO_STATUS_BLOCK ios; | ||
86 | + UNICODE_STRING us; | ||
87 | + | ||
88 | + OBJECT_ATTRIBUTES oa = {sizeof(oa), 0, &us, OBJ_CASE_INSENSITIVE, &sd, 0}; | ||
89 | + LARGE_INTEGER time = {-500000, -1}; | ||
90 | + | ||
91 | + RtlInitUnicodeString(&us, recv_pipe); | ||
92 | + if (!NT_SUCCESS(NtCreateNamedPipeFile( | ||
93 | + &hTextPipe, | ||
94 | + GENERIC_READ | SYNCHRONIZE, | ||
95 | + &oa, | ||
96 | + &ios, | ||
97 | + FILE_SHARE_WRITE, | ||
98 | + FILE_OPEN_IF, | ||
99 | + FILE_SYNCHRONOUS_IO_NONALERT, | ||
100 | + 1, 1, 0, -1, | ||
101 | + 0x1000, | ||
102 | + 0x1000, | ||
103 | + &time))) { | ||
104 | + //ConsoleOutput(ErrorCreatePipe); | ||
105 | + ConsoleOutput("vnrhost:CreateNewPipe: failed to create recv pipe"); | ||
106 | + return; | ||
107 | + } | ||
108 | + | ||
109 | + RtlInitUnicodeString(&us, command_pipe); | ||
110 | + if (!NT_SUCCESS(NtCreateNamedPipeFile( | ||
111 | + &hCmdPipe, | ||
112 | + GENERIC_WRITE | SYNCHRONIZE, | ||
113 | + &oa, | ||
114 | + &ios, | ||
115 | + FILE_SHARE_READ, | ||
116 | + FILE_OPEN_IF, | ||
117 | + FILE_SYNCHRONOUS_IO_NONALERT, | ||
118 | + 1, 1, 0, -1, | ||
119 | + 0x1000, | ||
120 | + 0x1000, | ||
121 | + &time))) { | ||
122 | + //ConsoleOutput(ErrorCreatePipe); | ||
123 | + ConsoleOutput("vnrhost:CreateNewPipe: failed to create cmd pipe"); | ||
124 | + return; | ||
125 | + } | ||
126 | + | ||
127 | + hThread = IthCreateThread(RecvThread, (DWORD)hTextPipe); | ||
128 | + man->RegisterPipe(hTextPipe, hCmdPipe, hThread); | ||
129 | +} | ||
130 | + | ||
131 | +void DetachFromProcess(DWORD pid) | ||
132 | +{ | ||
133 | + HANDLE hMutex = INVALID_HANDLE_VALUE, | ||
134 | + hEvent = INVALID_HANDLE_VALUE; | ||
135 | + //try { | ||
136 | + IO_STATUS_BLOCK ios; | ||
137 | + ProcessRecord *pr = man->GetProcessRecord(pid); | ||
138 | + if (!pr) | ||
139 | + return; | ||
140 | + //IthBreak(); | ||
141 | + hEvent = IthCreateEvent(nullptr); | ||
142 | + if (STATUS_PENDING == NtFsControlFile( | ||
143 | + man->GetCmdHandleByPID(pid), | ||
144 | + hEvent, | ||
145 | + 0,0, | ||
146 | + &ios, | ||
147 | + CTL_CODE(FILE_DEVICE_NAMED_PIPE, NAMED_PIPE_DISCONNECT, 0, 0), | ||
148 | + 0,0,0,0)) | ||
149 | + NtWaitForSingleObject(hEvent, 0, 0); | ||
150 | + NtClose(hEvent); | ||
151 | + //hEvent = INVALID_HANDLE_VALUE; | ||
152 | + | ||
153 | + WCHAR mutex[0x20]; | ||
154 | + swprintf(mutex, ITH_DETACH_MUTEX_ L"%d", pid); | ||
155 | + hMutex = IthOpenMutex(mutex); | ||
156 | + if (hMutex != INVALID_HANDLE_VALUE) { | ||
157 | + NtWaitForSingleObject(hMutex, 0, 0); | ||
158 | + NtReleaseMutant(hMutex, 0); | ||
159 | + NtClose(hMutex); | ||
160 | + //hMutex = INVALID_HANDLE_VALUE; | ||
161 | + } | ||
162 | + | ||
163 | + //} catch (...) { | ||
164 | + // if (hEvent != INVALID_HANDLE_VALUE) | ||
165 | + // NtClose(hEvent); | ||
166 | + // else if (hMutex != INVALID_HANDLE_VALUE) { | ||
167 | + // NtWaitForSingleObject(hMutex, 0, 0); | ||
168 | + // NtReleaseMutant(hMutex, 0); | ||
169 | + // NtClose(hMutex); | ||
170 | + // } | ||
171 | + //} | ||
172 | + | ||
173 | + //NtSetEvent(hDetachEvent, 0); | ||
174 | + if (::running) | ||
175 | + NtSetEvent(hPipeExist, 0); | ||
176 | +} | ||
177 | + | ||
178 | +// jichi 9/27/2013: I don't need this | ||
179 | +//void OutputDWORD(DWORD d) | ||
180 | +//{ | ||
181 | +// WCHAR str[0x20]; | ||
182 | +// swprintf(str, L"%.8X", d); | ||
183 | +// ConsoleOutput(str); | ||
184 | +//} | ||
185 | + | ||
186 | +DWORD WINAPI RecvThread(LPVOID lpThreadParameter) | ||
187 | +{ | ||
188 | + HANDLE hTextPipe = (HANDLE)lpThreadParameter; | ||
189 | + | ||
190 | + IO_STATUS_BLOCK ios; | ||
191 | + NtFsControlFile(hTextPipe, | ||
192 | + 0, 0, 0, | ||
193 | + &ios, | ||
194 | + CTL_CODE(FILE_DEVICE_NAMED_PIPE, NAMED_PIPE_CONNECT, 0, 0), | ||
195 | + 0, 0, 0, 0); | ||
196 | + if (!::running) { | ||
197 | + NtClose(hTextPipe); | ||
198 | + return 0; | ||
199 | + } | ||
200 | + | ||
201 | + BYTE *buff; | ||
202 | + | ||
203 | + enum { PipeBufferSize = 0x1000 }; | ||
204 | + buff = new BYTE[PipeBufferSize]; | ||
205 | + ITH_MEMSET_HEAP(buff, 0, PipeBufferSize); // jichi 8/27/2013: zero memory, or it will crash wine on start up | ||
206 | + | ||
207 | + // 10/19/2014 jichi: there are totally three words received | ||
208 | + // See: hook/rpc/pipe.cc | ||
209 | + // struct { | ||
210 | + // DWORD pid; | ||
211 | + // TextHook *man; | ||
212 | + // DWORD module; | ||
213 | + // //DWORD engine; | ||
214 | + // } u; | ||
215 | + enum { module_struct_size = 12 }; | ||
216 | + NtReadFile(hTextPipe, 0, 0, 0, &ios, buff, module_struct_size, 0, 0); | ||
217 | + | ||
218 | + DWORD pid = *(DWORD *)buff, | ||
219 | + hookman = *(DWORD *)(buff + 0x4), | ||
220 | + module = *(DWORD *)(buff + 0x8); | ||
221 | + //engine = *(DWORD *)(buff + 0xc); | ||
222 | + man->RegisterProcess(pid, hookman, module); | ||
223 | + | ||
224 | + // jichi 9/27/2013: why recursion? | ||
225 | + CreateNewPipe(); | ||
226 | + | ||
227 | + //NtClose(IthCreateThread(UpdateWindows,0)); | ||
228 | + while (::running) { | ||
229 | + if (!NT_SUCCESS(NtReadFile(hTextPipe, | ||
230 | + 0, 0, 0, | ||
231 | + &ios, | ||
232 | + buff, | ||
233 | + 0xf80, | ||
234 | + 0, 0))) | ||
235 | + break; | ||
236 | + | ||
237 | + enum { data_offset = 0xc }; // jichi 10/27/2013: Seem to be the data offset in the pipe | ||
238 | + | ||
239 | + DWORD RecvLen = ios.uInformation; | ||
240 | + if (RecvLen < data_offset) | ||
241 | + break; | ||
242 | + DWORD hook = *(DWORD *)buff; | ||
243 | + | ||
244 | + union { DWORD retn; DWORD cmd_type; }; | ||
245 | + union { DWORD split; DWORD new_engine_type; }; | ||
246 | + | ||
247 | + retn = *(DWORD *)(buff + 4); | ||
248 | + split = *(DWORD *)(buff + 8); | ||
249 | + | ||
250 | + buff[RecvLen] = 0; | ||
251 | + buff[RecvLen + 1] = 0; | ||
252 | + | ||
253 | + if (hook == IHF_NOTIFICATION) { | ||
254 | + switch (cmd_type) { | ||
255 | + case IHF_NOTIFICATION_NEWHOOK: | ||
256 | + { | ||
257 | + static long lock; | ||
258 | + while (InterlockedExchange(&lock, 1) == 1); | ||
259 | + ProcessEventCallback new_hook = man->ProcessNewHook(); | ||
260 | + if (new_hook) | ||
261 | + new_hook(pid); | ||
262 | + lock = 0; | ||
263 | + } break; | ||
264 | + case IHF_NOTIFICATION_TEXT: | ||
265 | + ConsoleOutput((LPCSTR)(buff + 8)); | ||
266 | + break; | ||
267 | + } | ||
268 | + } else { | ||
269 | + // jichi 9/28/2013: Debug raw data | ||
270 | + //ITH_DEBUG_DWORD9(RecvLen - 0xc, | ||
271 | + // buff[0xc], buff[0xd], buff[0xe], buff[0xf], | ||
272 | + // buff[0x10], buff[0x11], buff[0x12], buff[0x13]); | ||
273 | + | ||
274 | + const BYTE *data = buff + data_offset; // th | ||
275 | + int len = RecvLen - data_offset; | ||
276 | + bool space = ::has_leading_space(data, len); | ||
277 | + if (space) { | ||
278 | + const BYTE *it = ::Filter(data, len); | ||
279 | + len -= it - data; | ||
280 | + data = it; | ||
281 | + } | ||
282 | + if (len >> 31) // jichi 10/27/2013: len is too large, which seldom happens | ||
283 | + len = 0; | ||
284 | + //man->DispatchText(pid, len ? data : nullptr, hook, retn, split, len, space); | ||
285 | + man->DispatchText(pid, data, hook, retn, split, len, space); | ||
286 | + } | ||
287 | + } | ||
288 | + | ||
289 | + EnterCriticalSection(&detach_cs); | ||
290 | + | ||
291 | + HANDLE hDisconnect = IthCreateEvent(nullptr); | ||
292 | + | ||
293 | + if (STATUS_PENDING == NtFsControlFile( | ||
294 | + hTextPipe, | ||
295 | + hDisconnect, | ||
296 | + 0, 0, | ||
297 | + &ios, | ||
298 | + CTL_CODE(FILE_DEVICE_NAMED_PIPE, NAMED_PIPE_DISCONNECT, 0, 0), | ||
299 | + 0, 0, 0, 0)) | ||
300 | + NtWaitForSingleObject(hDisconnect, 0, 0); | ||
301 | + | ||
302 | + NtClose(hDisconnect); | ||
303 | + DetachFromProcess(pid); | ||
304 | + man->UnRegisterProcess(pid); | ||
305 | + | ||
306 | + //NtClearEvent(hDetachEvent); | ||
307 | + | ||
308 | + LeaveCriticalSection(&detach_cs); | ||
309 | + delete[] buff; | ||
310 | + | ||
311 | + if (::running) | ||
312 | + ConsoleOutput("vnrhost:DetachFromProcess: detached"); | ||
313 | + | ||
314 | + //if (::running) { | ||
315 | + // swprintf((LPWSTR)buff, FormatDetach, pid); | ||
316 | + // ConsoleOutput((LPWSTR)buff); | ||
317 | + // NtClose(IthCreateThread(UpdateWindows, 0)); | ||
318 | + //} | ||
319 | + return 0; | ||
320 | +} | ||
321 | + | ||
322 | +// EOF |
vnr/ith/host/settings.h
0 → 100644
vnr/ith/host/srv.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// srv.h | ||
4 | +// 8/23/2013 jichi | ||
5 | +// Branch: ITH/IHF.h, rev 105 | ||
6 | + | ||
7 | +#include "config.h" | ||
8 | +//#include "ith/host/settings.h" | ||
9 | +#include "ith/host/hookman.h" | ||
10 | +#include "ith/host/SettingManager.h" | ||
11 | + | ||
12 | +struct Settings; | ||
13 | +struct HookParam; | ||
14 | + | ||
15 | +// jichi 8/24/2013: Why extern "C"? Any specific reason to use C instead of C++ naming? | ||
16 | +extern "C" { | ||
17 | +IHFSERVICE DWORD IHFAPI IHF_Init(); | ||
18 | +IHFSERVICE DWORD IHFAPI IHF_Start(); | ||
19 | +IHFSERVICE DWORD IHFAPI IHF_Cleanup(); | ||
20 | +IHFSERVICE DWORD IHFAPI IHF_GetPIDByName(LPCWSTR pwcTarget); | ||
21 | +IHFSERVICE DWORD IHFAPI IHF_InjectByPID(DWORD pid); | ||
22 | +IHFSERVICE DWORD IHFAPI IHF_ActiveDetachProcess(DWORD pid); | ||
23 | +IHFSERVICE DWORD IHFAPI IHF_GetHookManager(HookManager **hookman); | ||
24 | +IHFSERVICE DWORD IHFAPI IHF_GetSettingManager(SettingManager** set_man); | ||
25 | +IHFSERVICE DWORD IHFAPI IHF_GetSettings(Settings **settings); | ||
26 | +IHFSERVICE DWORD IHFAPI IHF_InsertHook(DWORD pid, HookParam *hp, LPCWSTR name = 0); | ||
27 | +IHFSERVICE DWORD IHFAPI IHF_ModifyHook(DWORD pid, HookParam *hp); | ||
28 | +IHFSERVICE DWORD IHFAPI IHF_RemoveHook(DWORD pid, DWORD addr); | ||
29 | +IHFSERVICE DWORD IHFAPI IHF_IsAdmin(); | ||
30 | +//IHFSERVICE DWORD IHFAPI IHF_GetFilters(PVOID *mb_filter, PVOID *uni_filter); | ||
31 | +IHFSERVICE DWORD IHFAPI IHF_AddLink(DWORD from, DWORD to); | ||
32 | +IHFSERVICE DWORD IHFAPI IHF_UnLink(DWORD from); | ||
33 | +IHFSERVICE DWORD IHFAPI IHF_UnLinkAll(DWORD from); | ||
34 | +} // extern "C" | ||
35 | + | ||
36 | +// EOF |
vnr/ith/host/srv_p.h
0 → 100644
1 | +#pragma once | ||
2 | +// srv_p.h | ||
3 | +// 8/24/2013 jichi | ||
4 | +// Branch IHF/main.h, rev 111 | ||
5 | +#include "config.h" | ||
6 | + | ||
7 | +#define GLOBAL extern | ||
8 | +#define SHIFT_JIS 0x3A4 | ||
9 | +class HookManager; | ||
10 | +//class CommandQueue; | ||
11 | +class SettingManager; | ||
12 | +class TextHook; | ||
13 | +//class BitMap; | ||
14 | +//class CustomFilterMultiByte; | ||
15 | +//class CustomFilterUnicode; | ||
16 | +//#define TextHook Hook | ||
17 | +GLOBAL BOOL running; | ||
18 | +//GLOBAL BitMap *pid_map; | ||
19 | +//GLOBAL CustomFilterMultiByte *mb_filter; | ||
20 | +//GLOBAL CustomFilterUnicode *uni_filter; | ||
21 | +GLOBAL HookManager *man; | ||
22 | +//GLOBAL CommandQueue *cmdq; | ||
23 | +GLOBAL SettingManager *setman; | ||
24 | +GLOBAL WCHAR recv_pipe[]; | ||
25 | +GLOBAL WCHAR command[]; | ||
26 | +GLOBAL HANDLE hPipeExist; | ||
27 | +GLOBAL DWORD split_time, | ||
28 | + cyclic_remove, | ||
29 | + clipboard_flag, | ||
30 | + global_filter; | ||
31 | +GLOBAL CRITICAL_SECTION detach_cs; | ||
32 | + | ||
33 | +DWORD WINAPI RecvThread(LPVOID lpThreadParameter); | ||
34 | +DWORD WINAPI CmdThread(LPVOID lpThreadParameter); | ||
35 | + | ||
36 | +void ConsoleOutput(LPCSTR text); | ||
37 | +void ConsoleOutputW(LPCWSTR text); | ||
38 | +DWORD GetCurrentPID(); | ||
39 | +//DWORD GetProcessIDByPath(LPWSTR str); | ||
40 | +HANDLE GetCmdHandleByPID(DWORD pid); | ||
41 | +//DWORD Inject(HANDLE hProc); | ||
42 | +//DWORD InjectByPID(DWORD pid); | ||
43 | +//DWORD PIDByName(LPWSTR target); | ||
44 | +//DWORD Hash(LPCWSTR module, int length=-1); | ||
45 | + | ||
46 | +// EOF |
vnr/ith/host/textthread.cc
0 → 100644
This diff is collapsed. Click to expand it.
vnr/ith/host/textthread.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// textthread.h | ||
4 | +// 8/23/2013 jichi | ||
5 | +// Branch: ITH/TextThread.h, rev 120 | ||
6 | + | ||
7 | +#include "ith/host/textthread_p.h" | ||
8 | +#include <intrin.h> // require _InterlockedExchange | ||
9 | + | ||
10 | +struct RepeatCountNode { | ||
11 | + short repeat; | ||
12 | + short count; | ||
13 | + RepeatCountNode *next; | ||
14 | + | ||
15 | + //RepeatCountNode() : repeat(0), count(0), next(nullptr) {} | ||
16 | +}; | ||
17 | + | ||
18 | +struct ThreadParameter { | ||
19 | + DWORD pid; // jichi: 5/11/2014: The process ID | ||
20 | + DWORD hook; | ||
21 | + DWORD retn; // jichi 5/11/2014: The return address of the hook | ||
22 | + DWORD spl; // jichi 5/11/2014: the processed split value of the hook parameter | ||
23 | +}; | ||
24 | + | ||
25 | +#define CURRENT_SELECT 0x1000 | ||
26 | +#define REPEAT_NUMBER_DECIDED 0x2000 | ||
27 | +#define BUFF_NEWLINE 0x4000 | ||
28 | +#define CYCLIC_REPEAT 0x8000 | ||
29 | +#define COUNT_PER_FOWARD 0x200 | ||
30 | +#define REPEAT_DETECT 0x10000 | ||
31 | +#define REPEAT_SUPPRESS 0x20000 | ||
32 | +#define REPEAT_NEWLINE 0x40000 | ||
33 | + | ||
34 | +class TextThread; | ||
35 | +typedef void (* ConsoleCallback)(LPCSTR text); | ||
36 | +typedef void (* ConsoleWCallback)(LPCWSTR text); | ||
37 | +typedef DWORD (* ThreadOutputFilterCallback)(TextThread *, BYTE *, DWORD, DWORD, PVOID, bool space); // jichi 10/27/2013: Add space | ||
38 | +typedef DWORD (* ThreadEventCallback)(TextThread *); | ||
39 | + | ||
40 | +//extern DWORD split_time,repeat_count,global_filter,cyclic_remove; | ||
41 | + | ||
42 | +class TextThread : public MyVector<BYTE, 0x200> | ||
43 | +{ | ||
44 | +public: | ||
45 | + TextThread(DWORD pid, DWORD hook, DWORD retn, DWORD spl, WORD num); | ||
46 | + ~TextThread(); | ||
47 | + //virtual void CopyLastSentence(LPWSTR str); | ||
48 | + //virtual void SetComment(LPWSTR); | ||
49 | + //virtual void ExportTextToFile(LPWSTR filename); | ||
50 | + | ||
51 | + virtual bool CheckCycle(TextThread *start); | ||
52 | + virtual DWORD GetThreadString(LPWSTR str, DWORD max); | ||
53 | + virtual DWORD GetEntryString(LPWSTR str, DWORD max = 0x200); | ||
54 | + | ||
55 | + void Reset(); | ||
56 | + void AddText(const BYTE *con,int len, bool new_line, bool space); // jichi 10/27/2013: add const; remove console; add space | ||
57 | + void RemoveSingleRepeatAuto(const BYTE *con, int &len); // jichi 10/27/2013: add const | ||
58 | + void RemoveSingleRepeatForce(BYTE *con, int &len); | ||
59 | + void RemoveCyclicRepeat(BYTE *&con, int &len); | ||
60 | + void ResetRepeatStatus(); | ||
61 | + void AddLineBreak(); | ||
62 | + //void ResetEditText(); | ||
63 | + void ComboSelectCurrent(); | ||
64 | + void UnLinkAll(); | ||
65 | + void CopyLastToClipboard(); | ||
66 | + | ||
67 | + //void AdjustPrevRepeat(DWORD len); | ||
68 | + //void PrevRepeatLength(DWORD &len); | ||
69 | + | ||
70 | + //bool AddToCombo(); | ||
71 | + bool RemoveFromCombo(); | ||
72 | + | ||
73 | + void SetNewLineFlag(); | ||
74 | + void SetNewLineTimer(); | ||
75 | + | ||
76 | + BYTE *GetStore(DWORD *len) { if (len) *len = used; return storage; } | ||
77 | + DWORD LastSentenceLen() { return used - last_sentence; } | ||
78 | + DWORD PID() const { return tp.pid; } | ||
79 | + DWORD Addr() const {return tp.hook; } | ||
80 | + DWORD &Status() { return status; } | ||
81 | + WORD Number() const { return thread_number; } | ||
82 | + WORD &Last() { return last; } | ||
83 | + WORD &LinkNumber() { return link_number; } | ||
84 | + UINT_PTR &Timer() { return timer; } | ||
85 | + ThreadParameter *GetThreadParameter() { return &tp; } | ||
86 | + TextThread *&Link() { return link; } | ||
87 | + //LPCWSTR GetComment() { return comment; } | ||
88 | + | ||
89 | + ThreadOutputFilterCallback RegisterOutputCallBack(ThreadOutputFilterCallback cb, PVOID data) | ||
90 | + { | ||
91 | + app_data = data; | ||
92 | + return (ThreadOutputFilterCallback)_InterlockedExchange((long*)&output,(long)cb); | ||
93 | + } | ||
94 | + | ||
95 | + ThreadOutputFilterCallback RegisterFilterCallBack(ThreadOutputFilterCallback cb, PVOID data) | ||
96 | + { | ||
97 | + app_data = data; | ||
98 | + return (ThreadOutputFilterCallback)_InterlockedExchange((long*)&filter,(long)cb); | ||
99 | + } | ||
100 | + | ||
101 | + void SetRepeatFlag() { status |= CYCLIC_REPEAT; } | ||
102 | + void ClearNewLineFlag() { status &= ~BUFF_NEWLINE; } | ||
103 | + void ClearRepeatFlag() { status &= ~CYCLIC_REPEAT; } | ||
104 | + | ||
105 | +protected: | ||
106 | + void AddTextDirect(const BYTE *con, int len, bool space); // jichi 10/27/2013: add const; add space; change to protected | ||
107 | + | ||
108 | +private: | ||
109 | + ThreadParameter tp; | ||
110 | + | ||
111 | + WORD thread_number, | ||
112 | + link_number; | ||
113 | + WORD last, | ||
114 | + align_space; | ||
115 | + WORD repeat_single; | ||
116 | + WORD repeat_single_current; | ||
117 | + WORD repeat_single_count; | ||
118 | + WORD repeat_detect_count; | ||
119 | + RepeatCountNode *head; | ||
120 | + | ||
121 | + TextThread *link; | ||
122 | + ThreadOutputFilterCallback filter; // jichi 10/27/2013: Remove filter | ||
123 | + ThreadOutputFilterCallback output; | ||
124 | + PVOID app_data; | ||
125 | + //LPWSTR comment, | ||
126 | + LPWSTR thread_string; | ||
127 | + UINT_PTR timer; | ||
128 | + DWORD status,repeat_detect_limit; | ||
129 | + DWORD last_sentence, | ||
130 | + prev_sentence, | ||
131 | + sentence_length, | ||
132 | + repeat_index, | ||
133 | + last_time; | ||
134 | +}; | ||
135 | + | ||
136 | +// EOF |
vnr/ith/host/textthread_p.h
0 → 100644
1 | +#pragma once | ||
2 | +// textthread_p.h | ||
3 | +// 8/14/2013 jichi | ||
4 | +// Branch: ITH/main_template.h, rev 66 | ||
5 | + | ||
6 | +#include "config.h" | ||
7 | + | ||
8 | +template <typename T> | ||
9 | +void Release(const T &p) { delete p; } | ||
10 | + | ||
11 | +// Prevent memory release. | ||
12 | +// Used when T is basic types and will be automatically released (on stack). | ||
13 | +#define MK_BASIC_TYPE(T) \ | ||
14 | + template<> \ | ||
15 | + void Release<T>(const T &p) {} | ||
16 | + | ||
17 | +template<class T> | ||
18 | +struct BinaryEqual { | ||
19 | + bool operator ()(const T &a, const T &b, DWORD) { return a == b; } | ||
20 | +}; | ||
21 | + | ||
22 | +template<class T, int default_size, class fComp=BinaryEqual<T> > | ||
23 | +class MyVector | ||
24 | +{ | ||
25 | +public: | ||
26 | + MyVector() : size(default_size), used(0) | ||
27 | + { | ||
28 | + InitializeCriticalSection(&cs_store); | ||
29 | + storage = new T[size]; | ||
30 | + // jichi 9/21/2013: zero memory | ||
31 | + // This would cause trouble if T is not an atomic type | ||
32 | + ITH_MEMSET_HEAP(storage, 0, sizeof(T) * size); | ||
33 | + } | ||
34 | + | ||
35 | + virtual ~MyVector() | ||
36 | + { | ||
37 | + if (storage) | ||
38 | + delete[] storage; | ||
39 | + DeleteCriticalSection(&cs_store); | ||
40 | + storage = 0; | ||
41 | + } | ||
42 | + | ||
43 | + void Reset() | ||
44 | + { | ||
45 | + EnterCriticalSection(&cs_store); | ||
46 | + for (int i = 0; i < used; i++) { | ||
47 | + Release<T>(storage[i]); | ||
48 | + storage[i] = T(); | ||
49 | + } | ||
50 | + used = 0; | ||
51 | + LeaveCriticalSection(&cs_store); | ||
52 | + } | ||
53 | + void Remove(int index) | ||
54 | + { | ||
55 | + if (index>=used) | ||
56 | + return; | ||
57 | + Release<T>(storage[index]); | ||
58 | + for (int i = index; i < used; i++) | ||
59 | + storage[i] = storage[i+1]; | ||
60 | + used--; | ||
61 | + } | ||
62 | + void ClearMemory(int offset, int clear_size) | ||
63 | + { | ||
64 | + if (clear_size < 0) | ||
65 | + return; | ||
66 | + EnterCriticalSection(&cs_store); | ||
67 | + if (offset+clear_size <= size) | ||
68 | + memset(storage+offset, 0, clear_size * sizeof(T)); // jichi 11/30/2013: This is the original code of ITH | ||
69 | + LeaveCriticalSection(&cs_store); | ||
70 | + //else __asm int 3 | ||
71 | + } | ||
72 | + int AddToStore(T *con,int amount) | ||
73 | + { | ||
74 | + if (amount <= 0 || con == 0) | ||
75 | + return 0; | ||
76 | + int status = 0; | ||
77 | + EnterCriticalSection(&cs_store); | ||
78 | + if (amount + used + 2 >= size) { | ||
79 | + while (amount + used + 2 >= size) | ||
80 | + size<<=1; | ||
81 | + T *temp; | ||
82 | + if (size * sizeof(T) < 0x1000000) { | ||
83 | + temp = new T[size]; | ||
84 | + if (size > used) | ||
85 | + ITH_MEMSET_HEAP(temp, 0, (size - used) * sizeof(T)); // jichi 9/25/2013: zero memory | ||
86 | + memcpy(temp, storage, used * sizeof(T)); | ||
87 | + } else { | ||
88 | + size = default_size; | ||
89 | + temp = new T[size]; | ||
90 | + ITH_MEMSET_HEAP(temp, 0, sizeof(T) * size); // jichi 9/25/2013: zero memory | ||
91 | + used = 0; | ||
92 | + status = 1; | ||
93 | + } | ||
94 | + delete[] storage; | ||
95 | + storage = temp; | ||
96 | + } | ||
97 | + memcpy(storage+used, con, amount * sizeof(T)); | ||
98 | + used += amount; | ||
99 | + LeaveCriticalSection(&cs_store); | ||
100 | + return status; | ||
101 | + } | ||
102 | + int Find(const T &item, int start = 0, DWORD control = 0) | ||
103 | + { | ||
104 | + int c = -1; | ||
105 | + for (int i=start; i < used; i++) | ||
106 | + if (fCmp(storage[i],item,control)) { | ||
107 | + c=i; | ||
108 | + break; | ||
109 | + } | ||
110 | + //if (storage[i]==item) {c=i;break;} | ||
111 | + return c; | ||
112 | + } | ||
113 | + int Used() const { return used; } | ||
114 | + T *Storage() const { return storage; } | ||
115 | + void LockVector() { EnterCriticalSection(&cs_store); } | ||
116 | + void UnlockVector() { LeaveCriticalSection(&cs_store); } | ||
117 | +protected: | ||
118 | + CRITICAL_SECTION cs_store; | ||
119 | + int size, | ||
120 | + used; | ||
121 | + T *storage; | ||
122 | + fComp fCmp; | ||
123 | +}; | ||
124 | + | ||
125 | +// EOF | ||
126 | + | ||
127 | +/* | ||
128 | +#ifndef ITH_STACK | ||
129 | +#define ITH_STACK | ||
130 | +template<class T, int default_size> | ||
131 | +class MyStack | ||
132 | +{ | ||
133 | +public: | ||
134 | + MyStack(): index(0) {} | ||
135 | + void push_back(const T& e) | ||
136 | + { | ||
137 | + if (index<default_size) | ||
138 | + s[index++]=e; | ||
139 | + } | ||
140 | + void pop_back() | ||
141 | + { | ||
142 | + index--; | ||
143 | + } | ||
144 | + T& back() | ||
145 | + { | ||
146 | + return s[index-1]; | ||
147 | + } | ||
148 | + T& operator[](int i) {return s[i];} | ||
149 | + int size() {return index;} | ||
150 | +private: | ||
151 | + int index; | ||
152 | + T s[default_size]; | ||
153 | +}; | ||
154 | +#endif | ||
155 | +*/ |
vnr/ith/import/mono/funcinfo.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// mono/funcinfo.h | ||
4 | +// 12/26/2014 | ||
5 | +// https://github.com/mono/mono/blob/master/mono/metadata/object.h | ||
6 | +// http://api.xamarin.com/index.aspx?link=xhtml%3Adeploy%2Fmono-api-string.html | ||
7 | + | ||
8 | +//#include "ith/import/mono/types.h" | ||
9 | + | ||
10 | +// MonoString* mono_string_new (MonoDomain *domain, | ||
11 | +// const char *text); | ||
12 | +// MonoString* mono_string_new_len (MonoDomain *domain, | ||
13 | +// const char *text, | ||
14 | +// guint length); | ||
15 | +// MonoString* mono_string_new_size (MonoDomain *domain, | ||
16 | +// gint32 len); | ||
17 | +// MonoString* mono_string_new_utf16 (MonoDomain *domain, | ||
18 | +// const guint16 *text, | ||
19 | +// gint32 len); | ||
20 | +// MonoString* mono_string_from_utf16 (gunichar2 *data); | ||
21 | +// mono_unichar2* mono_string_to_utf16 (MonoString *s); | ||
22 | +// char* mono_string_to_utf8 (MonoString *s); | ||
23 | +// gboolean mono_string_equal (MonoString *s1, | ||
24 | +// MonoString *s2); | ||
25 | +// guint mono_string_hash (MonoString *s); | ||
26 | +// MonoString* mono_string_intern (MonoString *str); | ||
27 | +// MonoString* mono_string_is_interned (MonoString *o); | ||
28 | +// MonoString* mono_string_new_wrapper (const char *text); | ||
29 | +// gunichar2* mono_string_chars (MonoString *s); | ||
30 | +// int mono_string_length (MonoString *s); | ||
31 | +// gunichar2* mono_unicode_from_external (const gchar *in, gsize *bytes); | ||
32 | +// gchar* mono_unicode_to_external (const gunichar2 *uni); | ||
33 | +// gchar* mono_utf8_from_external (const gchar *in); | ||
34 | + | ||
35 | +struct MonoFunction { | ||
36 | + const wchar_t *hookName; | ||
37 | + const char *functionName; | ||
38 | + size_t textIndex; // argument index, starting from 0 | ||
39 | + size_t lengthIndex; // argument index, start from 0 | ||
40 | + unsigned long hookType; // HookParam type | ||
41 | + void *text_fun; // HookParam::text_fun_t | ||
42 | +}; | ||
43 | + | ||
44 | +#define MONO_FUNCTIONS_INITIALIZER \ | ||
45 | + { L"mono_string_to_utf8", "mono_string_to_utf8", 0, 0, USING_UNICODE, SpecialHookMonoString } \ | ||
46 | + , { L"mono_string_to_utf16", "mono_string_to_utf16", 0, 0, USING_UNICODE, SpecialHookMonoString } \ | ||
47 | + , { L"mono_utf8_from_external", "mono_utf8_from_external", 1, 0, USING_STRING|USING_UTF8, nullptr } \ | ||
48 | + , { L"mono_string_from_utf16", "mono_string_from_utf16", 1, 0, USING_UNICODE, nullptr } \ | ||
49 | + , { L"mono_unicode_from_external", "mono_unicode_from_external", 1, 2, USING_UNICODE, nullptr } \ | ||
50 | + , { L"mono_unicode_to_external", "mono_unicode_to_external", 1, 0, USING_UNICODE, nullptr } | ||
51 | + | ||
52 | +// EOF |
vnr/ith/import/mono/mono.pri
0 → 100644
vnr/ith/import/mono/types.h
0 → 100644
1 | +#pragma once | ||
2 | + | ||
3 | +// mono/types.h | ||
4 | +// 12/26/2014 | ||
5 | +// https://github.com/mono/mono/blob/master/mono/metadata/object.h | ||
6 | +// http://api.xamarin.com/index.aspx?link=xhtml%3Adeploy%2Fmono-api-string.html | ||
7 | + | ||
8 | +#include <cstdint> | ||
9 | + | ||
10 | +// mono/io-layer/uglify.h | ||
11 | +typedef int8_t gint8; | ||
12 | +typedef int32_t gint32; | ||
13 | +typedef wchar_t gunichar2; // either char or wchar_t, depending on how mono is compiled | ||
14 | + | ||
15 | +typedef gint8 mono_byte; | ||
16 | +typedef gunichar2 mono_unichar2; | ||
17 | + | ||
18 | +// mono/metadata/object.h | ||
19 | + | ||
20 | +typedef mono_byte MonoBoolean; | ||
21 | + | ||
22 | +struct MonoArray; | ||
23 | +struct MonoDelegate; | ||
24 | +struct MonoException; | ||
25 | +struct MonoString; | ||
26 | +struct MonoThreadsSync; | ||
27 | +struct MonoThread; | ||
28 | +struct MonoVTable; | ||
29 | + | ||
30 | +struct MonoObject { | ||
31 | + MonoVTable *vtable; | ||
32 | + MonoThreadsSync *synchronisation; | ||
33 | +}; | ||
34 | + | ||
35 | +struct MonoString { | ||
36 | + MonoObject object; | ||
37 | + gint32 length; | ||
38 | + gunichar2 chars[0]; | ||
39 | +}; | ||
40 | + | ||
41 | +// EOF |
vnr/ith/import/ppsspp/funcinfo.h
0 → 100644
1 | +#pragma once | ||
2 | +//#include "ith/common/const.h" | ||
3 | + | ||
4 | +// ppsspp/funcinfo.h | ||
5 | +// 12/26/2014 | ||
6 | +// See: https://github.com/hrydgard/ppsspp | ||
7 | + | ||
8 | +// Core/HLE (High Level Emulator) | ||
9 | +// - sceCcc | ||
10 | +// #void sceCccSetTable(u32 jis2ucs, u32 ucs2jis) | ||
11 | +// int sceCccUTF8toUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr) | ||
12 | +// int sceCccUTF8toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr) | ||
13 | +// int sceCccUTF16toUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr) | ||
14 | +// int sceCccUTF16toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr) | ||
15 | +// int sceCccSJIStoUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr) | ||
16 | +// int sceCccSJIStoUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr) | ||
17 | +// int sceCccStrlenUTF8(u32 strAddr) | ||
18 | +// int sceCccStrlenUTF16(u32 strAddr) | ||
19 | +// int sceCccStrlenSJIS(u32 strAddr) | ||
20 | +// u32 sceCccEncodeUTF8(u32 dstAddrAddr, u32 ucs) | ||
21 | +// void sceCccEncodeUTF16(u32 dstAddrAddr, u32 ucs) | ||
22 | +// u32 sceCccEncodeSJIS(u32 dstAddrAddr, u32 jis) | ||
23 | +// u32 sceCccDecodeUTF8(u32 dstAddrAddr) | ||
24 | +// u32 sceCccDecodeUTF16(u32 dstAddrAddr) | ||
25 | +// u32 sceCccDecodeSJIS(u32 dstAddrAddr) | ||
26 | +// int sceCccIsValidUTF8(u32 c) | ||
27 | +// int sceCccIsValidUTF16(u32 c) | ||
28 | +// int sceCccIsValidSJIS(u32 c) | ||
29 | +// int sceCccIsValidUCS2(u32 c) | ||
30 | +// int sceCccIsValidUCS4(u32 c) | ||
31 | +// int sceCccIsValidJIS(u32 c) | ||
32 | +// int sceCccIsValidUnicode(u32 c) | ||
33 | +// #u32 sceCccSetErrorCharUTF8(u32 c) | ||
34 | +// #u32 sceCccSetErrorCharUTF16(u32 c) | ||
35 | +// #u32 sceCccSetErrorCharSJIS(u32 c) | ||
36 | +// u32 sceCccUCStoJIS(u32 c, u32 alt) | ||
37 | +// u32 sceCccJIStoUCS(u32 c, u32 alt) | ||
38 | +// - sceFont: search charCode | ||
39 | +// int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) | ||
40 | +// int sceFontGetShadowInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) | ||
41 | +// int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) | ||
42 | +// int sceFontGetShadowImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) | ||
43 | +// int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) | ||
44 | +// int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) | ||
45 | +// #int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode) | ||
46 | +// int sceFontGetShadowGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) | ||
47 | +// int sceFontGetShadowGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) | ||
48 | +// - sceKernelInterrupt | ||
49 | +// u32 sysclib_strcat(u32 dst, u32 src) | ||
50 | +// int sysclib_strcmp(u32 dst, u32 src) | ||
51 | +// u32 sysclib_strcpy(u32 dst, u32 src) | ||
52 | +// u32 sysclib_strlen(u32 src) | ||
53 | +// | ||
54 | +// Sample debug string: | ||
55 | +// 006EFD8E PUSH PPSSPPWi.00832188 ASCII "sceCccEncodeSJIS(%08x, U+%04x)" | ||
56 | +// Corresponding source code in sceCcc: | ||
57 | +// ERROR_LOG(HLE, "sceCccEncodeSJIS(%08x, U+%04x): invalid pointer", dstAddrAddr, jis); | ||
58 | + | ||
59 | +struct PPSSPPFunction | ||
60 | +{ | ||
61 | + const wchar_t *hookName; // hook name | ||
62 | + size_t argIndex; // argument index | ||
63 | + unsigned long hookType; // hook parameter type | ||
64 | + unsigned long hookSplit; // hook parameter split, positive: stack, negative: registers | ||
65 | + const char *pattern; // debug string used within the function | ||
66 | +}; | ||
67 | + | ||
68 | +// jichi 7/14/2014: UTF-8 is treated as STRING | ||
69 | +// http://867258173.diandian.com/post/2014-06-26/40062099618 | ||
70 | +// sceFontGetCharGlyphImage_Clip | ||
71 | +// Sample game: [KID] Monochrome: sceFontGetCharInfo, sceFontGetCharGlyphImage_Clip | ||
72 | +// | ||
73 | +// Example: { L"sceFontGetCharInfo", 2, USING_UNICODE, 4, "sceFontGetCharInfo(" } | ||
74 | +// Text is at arg2, using arg1 as split | ||
75 | +#define PPSSPP_FUNCTIONS_INITIALIZER \ | ||
76 | + { L"sceCccStrlenSJIS", 1, USING_STRING, 0, "sceCccStrlenSJIS(" } \ | ||
77 | + , { L"sceCccStrlenUTF8", 1, USING_UTF8, 0, "sceCccStrlenUTF8(" } \ | ||
78 | + , { L"sceCccStrlenUTF16", 1, USING_UNICODE, 0, "sceCccStrlenUTF16(" } \ | ||
79 | +\ | ||
80 | + , { L"sceCccSJIStoUTF8", 3, USING_UTF8, 0, "sceCccSJIStoUTF8(" } \ | ||
81 | + , { L"sceCccSJIStoUTF16", 3, USING_STRING, 0, "sceCccSJIStoUTF16(" } \ | ||
82 | + , { L"sceCccUTF8toSJIS", 3, USING_UTF8, 0, "sceCccUTF8toSJIS(" } \ | ||
83 | + , { L"sceCccUTF8toUTF16", 3, USING_UTF8, 0, "sceCccUTF8toUTF16(" } \ | ||
84 | + , { L"sceCccUTF16toSJIS", 3, USING_UNICODE, 0, "sceCccUTF16toSJIS(" } \ | ||
85 | + , { L"sceCccUTF16toUTF8", 3, USING_UNICODE, 0, "sceCccUTF16toUTF8(" } \ | ||
86 | +\ | ||
87 | + , { L"sceFontGetCharInfo", 2, USING_UNICODE, 4, "sceFontGetCharInfo(" } \ | ||
88 | + , { L"sceFontGetShadowInfo", 2, USING_UNICODE, 4, "sceFontGetShadowInfo("} \ | ||
89 | + , { L"sceFontGetCharImageRect", 2, USING_UNICODE, 4, "sceFontGetCharImageRect(" } \ | ||
90 | + , { L"sceFontGetShadowImageRect", 2, USING_UNICODE, 4, "sceFontGetShadowImageRect(" } \ | ||
91 | + , { L"sceFontGetCharGlyphImage", 2, USING_UNICODE, 4, "sceFontGetCharGlyphImage(" } \ | ||
92 | + , { L"sceFontGetCharGlyphImage_Clip", 2, USING_UNICODE, 4, "sceFontGetCharGlyphImage_Clip(" } \ | ||
93 | + , { L"sceFontGetShadowGlyphImage", 2, USING_UNICODE, 4, "sceFontGetShadowGlyphImage(" } \ | ||
94 | + , { L"sceFontGetShadowGlyphImage_Clip", 2, USING_UNICODE, 4, "sceFontGetShadowGlyphImage_Clip(" } \ | ||
95 | +\ | ||
96 | + , { L"sysclib_strcat", 2, USING_STRING, 0, "Untested sysclib_strcat(" } \ | ||
97 | + , { L"sysclib_strcpy", 2, USING_STRING, 0, "Untested sysclib_strcpy(" } \ | ||
98 | + , { L"sysclib_strlen", 1, USING_STRING, 0, "Untested sysclib_strlen(" } | ||
99 | + | ||
100 | + // Disabled as I am not sure how to deal with the source string | ||
101 | + //, { L"sceCccEncodeSJIS", 2, USING_STRING, 0, "sceCccEncodeSJIS(" } | ||
102 | + //, { L"sceCccEncodeUTF8", 2, USING_UTF8, 0, "sceCccEncodeUTF8(" } | ||
103 | + //, { L"sceCccEncodeUTF16", 2, USING_UNICODE, 0, "sceCccEncodeUTF16(" } | ||
104 | + //, { L"sysclib_strcmp", 2, USING_STRING, 0, "Untested sysclib_strcmp(" } | ||
105 | + | ||
106 | +// EOF |
-
Please register or login to post a comment