mireado

starting commit

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
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
This diff is collapsed. Click to expand it.
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
This diff is collapsed. Click to expand it.
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
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 +)
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
This diff is collapsed. Click to expand it.
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
This diff is collapsed. Click to expand it.
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
1 +# host.pri
2 +# 8/9/2011 jichi
3 +
4 +DEFINES += WITH_LIB_ITH_HOST
5 +
6 +DEPENDPATH += $$PWD
7 +
8 +LIBS += -lvnrhost
9 +
10 +HEADERS += \
11 + $$PWD/avl_p.h \
12 + $$PWD/hookman.h \
13 + $$PWD/settings.h \
14 + $$PWD/srv.h \
15 + $$PWD/textthread.h \
16 + $$PWD/textthread_p.h
17 +
18 +# EOF
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
This diff is collapsed. Click to expand it.
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
1 +#pragma once
2 +
3 +// settings.h
4 +// 8/24/2013 jichi
5 +
6 +struct Settings {
7 + //bool debug; // whether output debug messages using pipes
8 + int splittingInterval;// time to split text into sentences
9 +
10 + Settings() : splittingInterval(200) {}
11 +
12 +};
13 +
14 +// EOF
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
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
This diff is collapsed. Click to expand it.
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
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 +*/
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
1 +# mono.pri
2 +# 12/26/2014 jichi
3 +
4 +DEPENDPATH += $$PWD
5 +
6 +HEADERS += \
7 + $$PWD/funcinfo.h \
8 + $$PWD/types.h
9 +
10 +# EOF
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
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